diff options
| author | Sean Hall <r.sean.hall@gmail.com> | 2022-08-19 14:08:23 -0500 |
|---|---|---|
| committer | Sean Hall <r.sean.hall@gmail.com> | 2022-08-19 17:02:27 -0500 |
| commit | b72f58abdf6dd5d0020f174358027158cb52cb72 (patch) | |
| tree | 3070c1f1fa8a74125a2933f23a1be3c514ed1de7 /src/burn/engine/pipe.cpp | |
| parent | bbc36178172e4198351f2f84a91faf56c65e1475 (diff) | |
| download | wix-b72f58abdf6dd5d0020f174358027158cb52cb72.tar.gz wix-b72f58abdf6dd5d0020f174358027158cb52cb72.tar.bz2 wix-b72f58abdf6dd5d0020f174358027158cb52cb72.zip | |
Use a dedicated pipe for redirecting logging from the elevated process.
Fixes 6869
Diffstat (limited to 'src/burn/engine/pipe.cpp')
| -rw-r--r-- | src/burn/engine/pipe.cpp | 91 |
1 files changed, 73 insertions, 18 deletions
diff --git a/src/burn/engine/pipe.cpp b/src/burn/engine/pipe.cpp index 9529ef40..19bdcaa2 100644 --- a/src/burn/engine/pipe.cpp +++ b/src/burn/engine/pipe.cpp | |||
| @@ -8,6 +8,7 @@ static const DWORD PIPE_RETRY_FOR_CONNECTION = 1800; // for up to 3 minutes. | |||
| 8 | 8 | ||
| 9 | static const LPCWSTR PIPE_NAME_FORMAT_STRING = L"\\\\.\\pipe\\%ls"; | 9 | static const LPCWSTR PIPE_NAME_FORMAT_STRING = L"\\\\.\\pipe\\%ls"; |
| 10 | static const LPCWSTR CACHE_PIPE_NAME_FORMAT_STRING = L"\\\\.\\pipe\\%ls.Cache"; | 10 | static const LPCWSTR CACHE_PIPE_NAME_FORMAT_STRING = L"\\\\.\\pipe\\%ls.Cache"; |
| 11 | static const LPCWSTR LOGGING_PIPE_NAME_FORMAT_STRING = L"\\\\.\\pipe\\%ls.Log"; | ||
| 11 | 12 | ||
| 12 | static HRESULT AllocatePipeMessage( | 13 | static HRESULT AllocatePipeMessage( |
| 13 | __in DWORD dwMessage, | 14 | __in DWORD dwMessage, |
| @@ -48,6 +49,7 @@ void PipeConnectionInitialize( | |||
| 48 | memset(pConnection, 0, sizeof(BURN_PIPE_CONNECTION)); | 49 | memset(pConnection, 0, sizeof(BURN_PIPE_CONNECTION)); |
| 49 | pConnection->hPipe = INVALID_HANDLE_VALUE; | 50 | pConnection->hPipe = INVALID_HANDLE_VALUE; |
| 50 | pConnection->hCachePipe = INVALID_HANDLE_VALUE; | 51 | pConnection->hCachePipe = INVALID_HANDLE_VALUE; |
| 52 | pConnection->hLoggingPipe = INVALID_HANDLE_VALUE; | ||
| 51 | } | 53 | } |
| 52 | 54 | ||
| 53 | /******************************************************************* | 55 | /******************************************************************* |
| @@ -58,15 +60,14 @@ void PipeConnectionUninitialize( | |||
| 58 | __in BURN_PIPE_CONNECTION* pConnection | 60 | __in BURN_PIPE_CONNECTION* pConnection |
| 59 | ) | 61 | ) |
| 60 | { | 62 | { |
| 63 | ReleaseFileHandle(pConnection->hLoggingPipe); | ||
| 61 | ReleaseFileHandle(pConnection->hCachePipe); | 64 | ReleaseFileHandle(pConnection->hCachePipe); |
| 62 | ReleaseFileHandle(pConnection->hPipe); | 65 | ReleaseFileHandle(pConnection->hPipe); |
| 63 | ReleaseHandle(pConnection->hProcess); | 66 | ReleaseHandle(pConnection->hProcess); |
| 64 | ReleaseStr(pConnection->sczSecret); | 67 | ReleaseStr(pConnection->sczSecret); |
| 65 | ReleaseStr(pConnection->sczName); | 68 | ReleaseStr(pConnection->sczName); |
| 66 | 69 | ||
| 67 | memset(pConnection, 0, sizeof(BURN_PIPE_CONNECTION)); | 70 | PipeConnectionInitialize(pConnection); |
| 68 | pConnection->hPipe = INVALID_HANDLE_VALUE; | ||
| 69 | pConnection->hCachePipe = INVALID_HANDLE_VALUE; | ||
| 70 | } | 71 | } |
| 71 | 72 | ||
| 72 | /******************************************************************* | 73 | /******************************************************************* |
| @@ -235,13 +236,13 @@ LExit: | |||
| 235 | *******************************************************************/ | 236 | *******************************************************************/ |
| 236 | extern "C" HRESULT PipeCreatePipes( | 237 | extern "C" HRESULT PipeCreatePipes( |
| 237 | __in BURN_PIPE_CONNECTION* pConnection, | 238 | __in BURN_PIPE_CONNECTION* pConnection, |
| 238 | __in BOOL fCreateCachePipe, | 239 | __in BOOL fCompanion |
| 239 | __out HANDLE* phEvent | ||
| 240 | ) | 240 | ) |
| 241 | { | 241 | { |
| 242 | Assert(pConnection->sczName); | 242 | Assert(pConnection->sczName); |
| 243 | Assert(INVALID_HANDLE_VALUE == pConnection->hPipe); | 243 | Assert(INVALID_HANDLE_VALUE == pConnection->hPipe); |
| 244 | Assert(INVALID_HANDLE_VALUE == pConnection->hCachePipe); | 244 | Assert(INVALID_HANDLE_VALUE == pConnection->hCachePipe); |
| 245 | Assert(INVALID_HANDLE_VALUE == pConnection->hLoggingPipe); | ||
| 245 | 246 | ||
| 246 | HRESULT hr = S_OK; | 247 | HRESULT hr = S_OK; |
| 247 | PSECURITY_DESCRIPTOR psd = NULL; | 248 | PSECURITY_DESCRIPTOR psd = NULL; |
| @@ -249,10 +250,10 @@ extern "C" HRESULT PipeCreatePipes( | |||
| 249 | LPWSTR sczFullPipeName = NULL; | 250 | LPWSTR sczFullPipeName = NULL; |
| 250 | HANDLE hPipe = INVALID_HANDLE_VALUE; | 251 | HANDLE hPipe = INVALID_HANDLE_VALUE; |
| 251 | HANDLE hCachePipe = INVALID_HANDLE_VALUE; | 252 | HANDLE hCachePipe = INVALID_HANDLE_VALUE; |
| 253 | HANDLE hLoggingPipe = INVALID_HANDLE_VALUE; | ||
| 252 | 254 | ||
| 253 | // Only the grant special rights when the pipe is being used for "embedded" | 255 | // Only grant special rights when the pipe is being used for "embedded" scenarios. |
| 254 | // scenarios (aka: there is no cache pipe). | 256 | if (!fCompanion) |
| 255 | if (!fCreateCachePipe) | ||
| 256 | { | 257 | { |
| 257 | // Create the security descriptor that grants read/write/sync access to Everyone. | 258 | // Create the security descriptor that grants read/write/sync access to Everyone. |
| 258 | // TODO: consider locking down "WD" to LogonIds (logon session) | 259 | // TODO: consider locking down "WD" to LogonIds (logon session) |
| @@ -278,7 +279,7 @@ extern "C" HRESULT PipeCreatePipes( | |||
| 278 | ExitWithLastError(hr, "Failed to create pipe: %ls", sczFullPipeName); | 279 | ExitWithLastError(hr, "Failed to create pipe: %ls", sczFullPipeName); |
| 279 | } | 280 | } |
| 280 | 281 | ||
| 281 | if (fCreateCachePipe) | 282 | if (fCompanion) |
| 282 | { | 283 | { |
| 283 | // Create the cache pipe. | 284 | // Create the cache pipe. |
| 284 | hr = StrAllocFormatted(&sczFullPipeName, CACHE_PIPE_NAME_FORMAT_STRING, pConnection->sczName); | 285 | hr = StrAllocFormatted(&sczFullPipeName, CACHE_PIPE_NAME_FORMAT_STRING, pConnection->sczName); |
| @@ -287,20 +288,31 @@ extern "C" HRESULT PipeCreatePipes( | |||
| 287 | hCachePipe = ::CreateNamedPipeW(sczFullPipeName, PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, PIPE_64KB, PIPE_64KB, 1, NULL); | 288 | hCachePipe = ::CreateNamedPipeW(sczFullPipeName, PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, PIPE_64KB, PIPE_64KB, 1, NULL); |
| 288 | if (INVALID_HANDLE_VALUE == hCachePipe) | 289 | if (INVALID_HANDLE_VALUE == hCachePipe) |
| 289 | { | 290 | { |
| 290 | ExitWithLastError(hr, "Failed to create pipe: %ls", sczFullPipeName); | 291 | ExitWithLastError(hr, "Failed to create cache pipe: %ls", sczFullPipeName); |
| 292 | } | ||
| 293 | |||
| 294 | // Create the logging pipe. | ||
| 295 | hr = StrAllocFormatted(&sczFullPipeName, LOGGING_PIPE_NAME_FORMAT_STRING, pConnection->sczName); | ||
| 296 | ExitOnFailure(hr, "Failed to allocate full name of logging pipe: %ls", pConnection->sczName); | ||
| 297 | |||
| 298 | hLoggingPipe = ::CreateNamedPipeW(sczFullPipeName, PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, PIPE_64KB, PIPE_64KB, 1, NULL); | ||
| 299 | if (INVALID_HANDLE_VALUE == hLoggingPipe) | ||
| 300 | { | ||
| 301 | ExitWithLastError(hr, "Failed to create logging pipe: %ls", sczFullPipeName); | ||
| 291 | } | 302 | } |
| 292 | } | 303 | } |
| 293 | 304 | ||
| 305 | pConnection->hLoggingPipe = hLoggingPipe; | ||
| 306 | hLoggingPipe = INVALID_HANDLE_VALUE; | ||
| 307 | |||
| 294 | pConnection->hCachePipe = hCachePipe; | 308 | pConnection->hCachePipe = hCachePipe; |
| 295 | hCachePipe = INVALID_HANDLE_VALUE; | 309 | hCachePipe = INVALID_HANDLE_VALUE; |
| 296 | 310 | ||
| 297 | pConnection->hPipe = hPipe; | 311 | pConnection->hPipe = hPipe; |
| 298 | hPipe = INVALID_HANDLE_VALUE; | 312 | hPipe = INVALID_HANDLE_VALUE; |
| 299 | 313 | ||
| 300 | // TODO: remove the following | ||
| 301 | *phEvent = NULL; | ||
| 302 | |||
| 303 | LExit: | 314 | LExit: |
| 315 | ReleaseFileHandle(hLoggingPipe); | ||
| 304 | ReleaseFileHandle(hCachePipe); | 316 | ReleaseFileHandle(hCachePipe); |
| 305 | ReleaseFileHandle(hPipe); | 317 | ReleaseFileHandle(hPipe); |
| 306 | ReleaseStr(sczFullPipeName); | 318 | ReleaseStr(sczFullPipeName); |
| @@ -322,7 +334,7 @@ extern "C" HRESULT PipeWaitForChildConnect( | |||
| 322 | ) | 334 | ) |
| 323 | { | 335 | { |
| 324 | HRESULT hr = S_OK; | 336 | HRESULT hr = S_OK; |
| 325 | HANDLE hPipes[2] = { pConnection->hPipe, pConnection->hCachePipe}; | 337 | HANDLE hPipes[3] = { pConnection->hPipe, pConnection->hCachePipe, pConnection->hLoggingPipe}; |
| 326 | LPCWSTR wzSecret = pConnection->sczSecret; | 338 | LPCWSTR wzSecret = pConnection->sczSecret; |
| 327 | DWORD cbSecret = lstrlenW(wzSecret) * sizeof(WCHAR); | 339 | DWORD cbSecret = lstrlenW(wzSecret) * sizeof(WCHAR); |
| 328 | DWORD dwCurrentProcessId = ::GetCurrentProcessId(); | 340 | DWORD dwCurrentProcessId = ::GetCurrentProcessId(); |
| @@ -410,6 +422,32 @@ LExit: | |||
| 410 | } | 422 | } |
| 411 | 423 | ||
| 412 | /******************************************************************* | 424 | /******************************************************************* |
| 425 | PipeTerminateLoggingPipe - | ||
| 426 | |||
| 427 | *******************************************************************/ | ||
| 428 | extern "C" HRESULT PipeTerminateLoggingPipe( | ||
| 429 | __in HANDLE hLoggingPipe, | ||
| 430 | __in DWORD dwParentExitCode | ||
| 431 | ) | ||
| 432 | { | ||
| 433 | HRESULT hr = S_OK; | ||
| 434 | BYTE* pbData = NULL; | ||
| 435 | SIZE_T cbData = 0; | ||
| 436 | |||
| 437 | // Prepare the exit message. | ||
| 438 | hr = BuffWriteNumber(&pbData, &cbData, dwParentExitCode); | ||
| 439 | ExitOnFailure(hr, "Failed to write exit code to message buffer."); | ||
| 440 | |||
| 441 | hr = WritePipeMessage(hLoggingPipe, static_cast<DWORD>(BURN_PIPE_MESSAGE_TYPE_COMPLETE), pbData, cbData); | ||
| 442 | ExitOnFailure(hr, "Failed to post complete message to logging pipe."); | ||
| 443 | |||
| 444 | LExit: | ||
| 445 | ReleaseBuffer(pbData); | ||
| 446 | |||
| 447 | return hr; | ||
| 448 | } | ||
| 449 | |||
| 450 | /******************************************************************* | ||
| 413 | PipeTerminateChildProcess - | 451 | PipeTerminateChildProcess - |
| 414 | 452 | ||
| 415 | *******************************************************************/ | 453 | *******************************************************************/ |
| @@ -468,6 +506,8 @@ extern "C" HRESULT PipeTerminateChildProcess( | |||
| 468 | #endif | 506 | #endif |
| 469 | 507 | ||
| 470 | LExit: | 508 | LExit: |
| 509 | ReleaseBuffer(pbData); | ||
| 510 | |||
| 471 | return hr; | 511 | return hr; |
| 472 | } | 512 | } |
| 473 | 513 | ||
| @@ -478,7 +518,7 @@ LExit: | |||
| 478 | *******************************************************************/ | 518 | *******************************************************************/ |
| 479 | extern "C" HRESULT PipeChildConnect( | 519 | extern "C" HRESULT PipeChildConnect( |
| 480 | __in BURN_PIPE_CONNECTION* pConnection, | 520 | __in BURN_PIPE_CONNECTION* pConnection, |
| 481 | __in BOOL fConnectCachePipe | 521 | __in BOOL fCompanion |
| 482 | ) | 522 | ) |
| 483 | { | 523 | { |
| 484 | Assert(pConnection->sczName); | 524 | Assert(pConnection->sczName); |
| @@ -486,6 +526,7 @@ extern "C" HRESULT PipeChildConnect( | |||
| 486 | Assert(!pConnection->hProcess); | 526 | Assert(!pConnection->hProcess); |
| 487 | Assert(INVALID_HANDLE_VALUE == pConnection->hPipe); | 527 | Assert(INVALID_HANDLE_VALUE == pConnection->hPipe); |
| 488 | Assert(INVALID_HANDLE_VALUE == pConnection->hCachePipe); | 528 | Assert(INVALID_HANDLE_VALUE == pConnection->hCachePipe); |
| 529 | Assert(INVALID_HANDLE_VALUE == pConnection->hLoggingPipe); | ||
| 489 | 530 | ||
| 490 | HRESULT hr = S_OK; | 531 | HRESULT hr = S_OK; |
| 491 | LPWSTR sczPipeName = NULL; | 532 | LPWSTR sczPipeName = NULL; |
| @@ -519,7 +560,7 @@ extern "C" HRESULT PipeChildConnect( | |||
| 519 | hr = ChildPipeConnected(pConnection->hPipe, pConnection->sczSecret, &pConnection->dwProcessId); | 560 | hr = ChildPipeConnected(pConnection->hPipe, pConnection->sczSecret, &pConnection->dwProcessId); |
| 520 | ExitOnFailure(hr, "Failed to verify parent pipe: %ls", sczPipeName); | 561 | ExitOnFailure(hr, "Failed to verify parent pipe: %ls", sczPipeName); |
| 521 | 562 | ||
| 522 | if (fConnectCachePipe) | 563 | if (fCompanion) |
| 523 | { | 564 | { |
| 524 | // Connect to the parent for the cache pipe. | 565 | // Connect to the parent for the cache pipe. |
| 525 | hr = StrAllocFormatted(&sczPipeName, CACHE_PIPE_NAME_FORMAT_STRING, pConnection->sczName); | 566 | hr = StrAllocFormatted(&sczPipeName, CACHE_PIPE_NAME_FORMAT_STRING, pConnection->sczName); |
| @@ -528,12 +569,26 @@ extern "C" HRESULT PipeChildConnect( | |||
| 528 | pConnection->hCachePipe = ::CreateFileW(sczPipeName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); | 569 | pConnection->hCachePipe = ::CreateFileW(sczPipeName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); |
| 529 | if (INVALID_HANDLE_VALUE == pConnection->hCachePipe) | 570 | if (INVALID_HANDLE_VALUE == pConnection->hCachePipe) |
| 530 | { | 571 | { |
| 531 | ExitWithLastError(hr, "Failed to open parent pipe: %ls", sczPipeName) | 572 | ExitWithLastError(hr, "Failed to open parent cache pipe: %ls", sczPipeName) |
| 532 | } | 573 | } |
| 533 | 574 | ||
| 534 | // Verify the parent and notify it that the child connected. | 575 | // Verify the parent and notify it that the child connected. |
| 535 | hr = ChildPipeConnected(pConnection->hCachePipe, pConnection->sczSecret, &pConnection->dwProcessId); | 576 | hr = ChildPipeConnected(pConnection->hCachePipe, pConnection->sczSecret, &pConnection->dwProcessId); |
| 536 | ExitOnFailure(hr, "Failed to verify parent pipe: %ls", sczPipeName); | 577 | ExitOnFailure(hr, "Failed to verify parent cache pipe: %ls", sczPipeName); |
| 578 | |||
| 579 | // Connect to the parent for the logging pipe. | ||
| 580 | hr = StrAllocFormatted(&sczPipeName, LOGGING_PIPE_NAME_FORMAT_STRING, pConnection->sczName); | ||
| 581 | ExitOnFailure(hr, "Failed to allocate name of parent logging pipe."); | ||
| 582 | |||
| 583 | pConnection->hLoggingPipe = ::CreateFileW(sczPipeName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); | ||
| 584 | if (INVALID_HANDLE_VALUE == pConnection->hLoggingPipe) | ||
| 585 | { | ||
| 586 | ExitWithLastError(hr, "Failed to open parent logging pipe: %ls", sczPipeName) | ||
| 587 | } | ||
| 588 | |||
| 589 | // Verify the parent and notify it that the child connected. | ||
| 590 | hr = ChildPipeConnected(pConnection->hLoggingPipe, pConnection->sczSecret, &pConnection->dwProcessId); | ||
| 591 | ExitOnFailure(hr, "Failed to verify parent logging pipe: %ls", sczPipeName); | ||
| 537 | } | 592 | } |
| 538 | 593 | ||
| 539 | pConnection->hProcess = ::OpenProcess(SYNCHRONIZE, FALSE, pConnection->dwProcessId); | 594 | pConnection->hProcess = ::OpenProcess(SYNCHRONIZE, FALSE, pConnection->dwProcessId); |
