aboutsummaryrefslogtreecommitdiff
path: root/src/burn/engine/pipe.cpp
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2022-08-19 14:08:23 -0500
committerSean Hall <r.sean.hall@gmail.com>2022-08-19 17:02:27 -0500
commitb72f58abdf6dd5d0020f174358027158cb52cb72 (patch)
tree3070c1f1fa8a74125a2933f23a1be3c514ed1de7 /src/burn/engine/pipe.cpp
parentbbc36178172e4198351f2f84a91faf56c65e1475 (diff)
downloadwix-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.cpp91
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
9static const LPCWSTR PIPE_NAME_FORMAT_STRING = L"\\\\.\\pipe\\%ls"; 9static const LPCWSTR PIPE_NAME_FORMAT_STRING = L"\\\\.\\pipe\\%ls";
10static const LPCWSTR CACHE_PIPE_NAME_FORMAT_STRING = L"\\\\.\\pipe\\%ls.Cache"; 10static const LPCWSTR CACHE_PIPE_NAME_FORMAT_STRING = L"\\\\.\\pipe\\%ls.Cache";
11static const LPCWSTR LOGGING_PIPE_NAME_FORMAT_STRING = L"\\\\.\\pipe\\%ls.Log";
11 12
12static HRESULT AllocatePipeMessage( 13static 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*******************************************************************/
236extern "C" HRESULT PipeCreatePipes( 237extern "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
303LExit: 314LExit:
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*******************************************************************/
428extern "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
444LExit:
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
470LExit: 508LExit:
509 ReleaseBuffer(pbData);
510
471 return hr; 511 return hr;
472} 512}
473 513
@@ -478,7 +518,7 @@ LExit:
478*******************************************************************/ 518*******************************************************************/
479extern "C" HRESULT PipeChildConnect( 519extern "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);