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); |