aboutsummaryrefslogtreecommitdiff
path: root/src/burn
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
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')
-rw-r--r--src/burn/engine/core.cpp24
-rw-r--r--src/burn/engine/core.h2
-rw-r--r--src/burn/engine/elevation.cpp15
-rw-r--r--src/burn/engine/elevation.h1
-rw-r--r--src/burn/engine/embedded.cpp4
-rw-r--r--src/burn/engine/engine.cpp264
-rw-r--r--src/burn/engine/pipe.cpp91
-rw-r--r--src/burn/engine/pipe.h10
-rw-r--r--src/burn/engine/uithread.cpp12
9 files changed, 325 insertions, 98 deletions
diff --git a/src/burn/engine/core.cpp b/src/burn/engine/core.cpp
index bfd979de..ed824411 100644
--- a/src/burn/engine/core.cpp
+++ b/src/burn/engine/core.cpp
@@ -69,6 +69,9 @@ static HRESULT DetectPackagePayloadsCached(
69static DWORD WINAPI CacheThreadProc( 69static DWORD WINAPI CacheThreadProc(
70 __in LPVOID lpThreadParameter 70 __in LPVOID lpThreadParameter
71 ); 71 );
72static DWORD WINAPI LoggingThreadProc(
73 __in LPVOID lpThreadParameter
74 );
72static void LogPackages( 75static void LogPackages(
73 __in_opt const BURN_PACKAGE* pUpgradeBundlePackage, 76 __in_opt const BURN_PACKAGE* pUpgradeBundlePackage,
74 __in_opt const BURN_PACKAGE* pForwardCompatibleBundlePackage, 77 __in_opt const BURN_PACKAGE* pForwardCompatibleBundlePackage,
@@ -615,6 +618,9 @@ extern "C" HRESULT CoreElevate(
615 618
616 hr = VariableSetNumeric(&pEngineState->variables, BURN_BUNDLE_ELEVATED, TRUE, TRUE); 619 hr = VariableSetNumeric(&pEngineState->variables, BURN_BUNDLE_ELEVATED, TRUE, TRUE);
617 ExitOnFailure(hr, "Failed to overwrite the %ls built-in variable.", BURN_BUNDLE_ELEVATED); 620 ExitOnFailure(hr, "Failed to overwrite the %ls built-in variable.", BURN_BUNDLE_ELEVATED);
621
622 pEngineState->hUnelevatedLoggingThread = ::CreateThread(NULL, 0, LoggingThreadProc, pEngineState, 0, NULL);
623 ExitOnNullWithLastError(pEngineState->hUnelevatedLoggingThread, hr, "Failed to create unelevated logging thread.");
618 } 624 }
619 625
620LExit: 626LExit:
@@ -2325,6 +2331,24 @@ LExit:
2325 return (DWORD)hr; 2331 return (DWORD)hr;
2326} 2332}
2327 2333
2334static DWORD WINAPI LoggingThreadProc(
2335 __in LPVOID lpThreadParameter
2336 )
2337{
2338 HRESULT hr = S_OK;
2339 BURN_ENGINE_STATE* pEngineState = reinterpret_cast<BURN_ENGINE_STATE*>(lpThreadParameter);
2340 BURN_PIPE_RESULT result = { };
2341
2342 hr = PipePumpMessages(pEngineState->companionConnection.hLoggingPipe, NULL, NULL, &result);
2343 ExitOnFailure(hr, "Failed to pump logging messages for elevated process.");
2344
2345 hr = (HRESULT)result.dwResult;
2346
2347LExit:
2348
2349 return (DWORD)hr;
2350}
2351
2328static void LogPackages( 2352static void LogPackages(
2329 __in_opt const BURN_PACKAGE* pUpgradeBundlePackage, 2353 __in_opt const BURN_PACKAGE* pUpgradeBundlePackage,
2330 __in_opt const BURN_PACKAGE* pForwardCompatibleBundlePackage, 2354 __in_opt const BURN_PACKAGE* pForwardCompatibleBundlePackage,
diff --git a/src/burn/engine/core.h b/src/burn/engine/core.h
index c75d42de..a2f1ab4c 100644
--- a/src/burn/engine/core.h
+++ b/src/burn/engine/core.h
@@ -152,7 +152,7 @@ typedef struct _BURN_ENGINE_STATE
152 152
153 BURN_PLAN plan; 153 BURN_PLAN plan;
154 154
155 DWORD dwElevatedLoggingTlsId; 155 HANDLE hUnelevatedLoggingThread;
156 156
157 LPWSTR sczBundleEngineWorkingPath; 157 LPWSTR sczBundleEngineWorkingPath;
158 BURN_PIPE_CONNECTION companionConnection; 158 BURN_PIPE_CONNECTION companionConnection;
diff --git a/src/burn/engine/elevation.cpp b/src/burn/engine/elevation.cpp
index e30a05bb..adc3aad9 100644
--- a/src/burn/engine/elevation.cpp
+++ b/src/burn/engine/elevation.cpp
@@ -91,7 +91,6 @@ typedef struct _BURN_ELEVATION_LAUNCH_APPROVED_EXE_MESSAGE_CONTEXT
91 91
92typedef struct _BURN_ELEVATION_CHILD_MESSAGE_CONTEXT 92typedef struct _BURN_ELEVATION_CHILD_MESSAGE_CONTEXT
93{ 93{
94 DWORD dwLoggingTlsId;
95 HANDLE hPipe; 94 HANDLE hPipe;
96 HANDLE* phLock; 95 HANDLE* phLock;
97 BOOL* pfDisabledAutomaticUpdates; 96 BOOL* pfDisabledAutomaticUpdates;
@@ -397,10 +396,10 @@ extern "C" HRESULT ElevationElevate(
397 Assert(!pEngineState->companionConnection.dwProcessId); 396 Assert(!pEngineState->companionConnection.dwProcessId);
398 Assert(INVALID_HANDLE_VALUE == pEngineState->companionConnection.hPipe); 397 Assert(INVALID_HANDLE_VALUE == pEngineState->companionConnection.hPipe);
399 Assert(INVALID_HANDLE_VALUE == pEngineState->companionConnection.hCachePipe); 398 Assert(INVALID_HANDLE_VALUE == pEngineState->companionConnection.hCachePipe);
399 Assert(INVALID_HANDLE_VALUE == pEngineState->companionConnection.hLoggingPipe);
400 400
401 HRESULT hr = S_OK; 401 HRESULT hr = S_OK;
402 int nResult = IDOK; 402 int nResult = IDOK;
403 HANDLE hPipesCreatedEvent = INVALID_HANDLE_VALUE;
404 403
405 hr = UserExperienceOnElevateBegin(&pEngineState->userExperience); 404 hr = UserExperienceOnElevateBegin(&pEngineState->userExperience);
406 ExitOnRootFailure(hr, "BA aborted elevation requirement."); 405 ExitOnRootFailure(hr, "BA aborted elevation requirement.");
@@ -408,7 +407,7 @@ extern "C" HRESULT ElevationElevate(
408 hr = PipeCreateNameAndSecret(&pEngineState->companionConnection.sczName, &pEngineState->companionConnection.sczSecret); 407 hr = PipeCreateNameAndSecret(&pEngineState->companionConnection.sczName, &pEngineState->companionConnection.sczSecret);
409 ExitOnFailure(hr, "Failed to create pipe name and client token."); 408 ExitOnFailure(hr, "Failed to create pipe name and client token.");
410 409
411 hr = PipeCreatePipes(&pEngineState->companionConnection, TRUE, &hPipesCreatedEvent); 410 hr = PipeCreatePipes(&pEngineState->companionConnection, TRUE);
412 ExitOnFailure(hr, "Failed to create pipe and cache pipe."); 411 ExitOnFailure(hr, "Failed to create pipe and cache pipe.");
413 412
414 LogId(REPORT_STANDARD, MSG_LAUNCH_ELEVATED_ENGINE_STARTING); 413 LogId(REPORT_STANDARD, MSG_LAUNCH_ELEVATED_ENGINE_STARTING);
@@ -442,8 +441,6 @@ extern "C" HRESULT ElevationElevate(
442 ExitOnFailure(hr, "Failed to elevate."); 441 ExitOnFailure(hr, "Failed to elevate.");
443 442
444LExit: 443LExit:
445 ReleaseHandle(hPipesCreatedEvent);
446
447 if (FAILED(hr)) 444 if (FAILED(hr))
448 { 445 {
449 PipeConnectionUninitialize(&pEngineState->companionConnection); 446 PipeConnectionUninitialize(&pEngineState->companionConnection);
@@ -1532,7 +1529,6 @@ LExit:
1532 1529
1533*******************************************************************/ 1530*******************************************************************/
1534extern "C" HRESULT ElevationChildPumpMessages( 1531extern "C" HRESULT ElevationChildPumpMessages(
1535 __in DWORD dwLoggingTlsId,
1536 __in HANDLE hPipe, 1532 __in HANDLE hPipe,
1537 __in HANDLE hCachePipe, 1533 __in HANDLE hCachePipe,
1538 __in BURN_APPROVED_EXES* pApprovedExes, 1534 __in BURN_APPROVED_EXES* pApprovedExes,
@@ -1556,7 +1552,6 @@ extern "C" HRESULT ElevationChildPumpMessages(
1556 BURN_PIPE_RESULT result = { }; 1552 BURN_PIPE_RESULT result = { };
1557 BOOL fDisabledAutomaticUpdates = FALSE; 1553 BOOL fDisabledAutomaticUpdates = FALSE;
1558 1554
1559 cacheContext.dwLoggingTlsId = dwLoggingTlsId;
1560 cacheContext.hPipe = hCachePipe; 1555 cacheContext.hPipe = hCachePipe;
1561 cacheContext.pCache = pCache; 1556 cacheContext.pCache = pCache;
1562 cacheContext.pContainers = pContainers; 1557 cacheContext.pContainers = pContainers;
@@ -1566,7 +1561,6 @@ extern "C" HRESULT ElevationChildPumpMessages(
1566 cacheContext.pRegistration = pRegistration; 1561 cacheContext.pRegistration = pRegistration;
1567 cacheContext.pUserExperience = pUserExperience; 1562 cacheContext.pUserExperience = pUserExperience;
1568 1563
1569 context.dwLoggingTlsId = dwLoggingTlsId;
1570 context.hPipe = hPipe; 1564 context.hPipe = hPipe;
1571 context.phLock = phLock; 1565 context.phLock = phLock;
1572 context.pfDisabledAutomaticUpdates = &fDisabledAutomaticUpdates; 1566 context.pfDisabledAutomaticUpdates = &fDisabledAutomaticUpdates;
@@ -1660,11 +1654,6 @@ static DWORD WINAPI ElevatedChildCacheThreadProc(
1660 BOOL fComInitialized = FALSE; 1654 BOOL fComInitialized = FALSE;
1661 BURN_PIPE_RESULT result = { }; 1655 BURN_PIPE_RESULT result = { };
1662 1656
1663 if (!::TlsSetValue(pContext->dwLoggingTlsId, pContext->hPipe))
1664 {
1665 ExitWithLastError(hr, "Failed to set elevated cache pipe into thread local storage for logging.");
1666 }
1667
1668 // initialize COM 1657 // initialize COM
1669 hr = ::CoInitializeEx(NULL, COINIT_MULTITHREADED); 1658 hr = ::CoInitializeEx(NULL, COINIT_MULTITHREADED);
1670 ExitOnFailure(hr, "Failed to initialize COM."); 1659 ExitOnFailure(hr, "Failed to initialize COM.");
diff --git a/src/burn/engine/elevation.h b/src/burn/engine/elevation.h
index bda0fdef..0d15b470 100644
--- a/src/burn/engine/elevation.h
+++ b/src/burn/engine/elevation.h
@@ -166,7 +166,6 @@ HRESULT ElevationLaunchApprovedExe(
166 166
167// Child (per-machine process) side functions. 167// Child (per-machine process) side functions.
168HRESULT ElevationChildPumpMessages( 168HRESULT ElevationChildPumpMessages(
169 __in DWORD dwLoggingTlsId,
170 __in HANDLE hPipe, 169 __in HANDLE hPipe,
171 __in HANDLE hCachePipe, 170 __in HANDLE hCachePipe,
172 __in BURN_APPROVED_EXES* pApprovedExes, 171 __in BURN_APPROVED_EXES* pApprovedExes,
diff --git a/src/burn/engine/embedded.cpp b/src/burn/engine/embedded.cpp
index ac4c76d0..b9335cdf 100644
--- a/src/burn/engine/embedded.cpp
+++ b/src/burn/engine/embedded.cpp
@@ -51,7 +51,6 @@ extern "C" HRESULT EmbeddedRunBundle(
51{ 51{
52 HRESULT hr = S_OK; 52 HRESULT hr = S_OK;
53 DWORD dwCurrentProcessId = ::GetCurrentProcessId(); 53 DWORD dwCurrentProcessId = ::GetCurrentProcessId();
54 HANDLE hCreatedPipesEvent = NULL;
55 LPWSTR sczCommand = NULL; 54 LPWSTR sczCommand = NULL;
56 PROCESS_INFORMATION pi = { }; 55 PROCESS_INFORMATION pi = { };
57 BURN_PIPE_RESULT result = { }; 56 BURN_PIPE_RESULT result = { };
@@ -65,7 +64,7 @@ extern "C" HRESULT EmbeddedRunBundle(
65 hr = PipeCreateNameAndSecret(&pConnection->sczName, &pConnection->sczSecret); 64 hr = PipeCreateNameAndSecret(&pConnection->sczName, &pConnection->sczSecret);
66 ExitOnFailure(hr, "Failed to create embedded pipe name and client token."); 65 ExitOnFailure(hr, "Failed to create embedded pipe name and client token.");
67 66
68 hr = PipeCreatePipes(pConnection, FALSE, &hCreatedPipesEvent); 67 hr = PipeCreatePipes(pConnection, FALSE);
69 ExitOnFailure(hr, "Failed to create embedded pipe."); 68 ExitOnFailure(hr, "Failed to create embedded pipe.");
70 69
71 hr = StrAllocFormatted(&sczCommand, L"%ls -%ls %ls %ls %u", sczBaseCommand, BURN_COMMANDLINE_SWITCH_EMBEDDED, pConnection->sczName, pConnection->sczSecret, dwCurrentProcessId); 70 hr = StrAllocFormatted(&sczCommand, L"%ls -%ls %ls %ls %u", sczBaseCommand, BURN_COMMANDLINE_SWITCH_EMBEDDED, pConnection->sczName, pConnection->sczSecret, dwCurrentProcessId);
@@ -100,7 +99,6 @@ LExit:
100 ReleaseHandle(pi.hProcess); 99 ReleaseHandle(pi.hProcess);
101 100
102 StrSecureZeroFreeString(sczCommand); 101 StrSecureZeroFreeString(sczCommand);
103 ReleaseHandle(hCreatedPipesEvent);
104 PipeConnectionUninitialize(pConnection); 102 PipeConnectionUninitialize(pConnection);
105 103
106 return hr; 104 return hr;
diff --git a/src/burn/engine/engine.cpp b/src/burn/engine/engine.cpp
index 323d2c3a..daaf51dc 100644
--- a/src/burn/engine/engine.cpp
+++ b/src/burn/engine/engine.cpp
@@ -3,6 +3,15 @@
3#include "precomp.h" 3#include "precomp.h"
4 4
5 5
6typedef struct _REDIRECTED_LOGGING_CONTEXT
7{
8 CRITICAL_SECTION csBuffer;
9 LPSTR sczBuffer;
10 HANDLE hPipe;
11 HANDLE hLogEvent;
12 HANDLE hFinishedEvent;
13} REDIRECTED_LOGGING_CONTEXT;
14
6// constants 15// constants
7 16
8const DWORD RESTART_RETRIES = 10; 17const DWORD RESTART_RETRIES = 10;
@@ -49,6 +58,20 @@ static HRESULT DAPI RedirectLoggingOverPipe(
49 __in_z LPCSTR szString, 58 __in_z LPCSTR szString,
50 __in_opt LPVOID pvContext 59 __in_opt LPVOID pvContext
51 ); 60 );
61static HRESULT LogStringOverPipe(
62 __in_z LPCSTR szString,
63 __in HANDLE hPipe
64 );
65static DWORD WINAPI ElevatedLoggingThreadProc(
66 __in LPVOID lpThreadParameter
67 );
68static HRESULT WaitForElevatedLoggingThread(
69 __in REDIRECTED_LOGGING_CONTEXT* pContext,
70 __in HANDLE hLoggingThread
71 );
72static HRESULT WaitForUnelevatedLoggingThread(
73 __in HANDLE hUnelevatedLoggingThread
74 );
52static HRESULT Restart(); 75static HRESULT Restart();
53static void CALLBACK BurnTraceError( 76static void CALLBACK BurnTraceError(
54 __in_z LPCSTR szFile, 77 __in_z LPCSTR szFile,
@@ -361,7 +384,6 @@ static HRESULT InitializeEngineState(
361 HANDLE hSourceEngineFile = INVALID_HANDLE_VALUE; 384 HANDLE hSourceEngineFile = INVALID_HANDLE_VALUE;
362 385
363 pEngineState->internalCommand.automaticUpdates = BURN_AU_PAUSE_ACTION_IFELEVATED; 386 pEngineState->internalCommand.automaticUpdates = BURN_AU_PAUSE_ACTION_IFELEVATED;
364 pEngineState->dwElevatedLoggingTlsId = TLS_OUT_OF_INDEXES;
365 ::InitializeCriticalSection(&pEngineState->userExperience.csEngineActive); 387 ::InitializeCriticalSection(&pEngineState->userExperience.csEngineActive);
366 PipeConnectionInitialize(&pEngineState->companionConnection); 388 PipeConnectionInitialize(&pEngineState->companionConnection);
367 PipeConnectionInitialize(&pEngineState->embeddedConnection); 389 PipeConnectionInitialize(&pEngineState->embeddedConnection);
@@ -434,11 +456,6 @@ static void UninitializeEngineState(
434 ReleaseStr(pEngineState->log.sczPath); 456 ReleaseStr(pEngineState->log.sczPath);
435 ReleaseStr(pEngineState->log.sczPathVariable); 457 ReleaseStr(pEngineState->log.sczPathVariable);
436 458
437 if (TLS_OUT_OF_INDEXES != pEngineState->dwElevatedLoggingTlsId)
438 {
439 ::TlsFree(pEngineState->dwElevatedLoggingTlsId);
440 }
441
442 // clear struct 459 // clear struct
443 memset(pEngineState, 0, sizeof(BURN_ENGINE_STATE)); 460 memset(pEngineState, 0, sizeof(BURN_ENGINE_STATE));
444} 461}
@@ -624,6 +641,8 @@ LExit:
624 if (INVALID_HANDLE_VALUE != pEngineState->companionConnection.hPipe) 641 if (INVALID_HANDLE_VALUE != pEngineState->companionConnection.hPipe)
625 { 642 {
626 PipeTerminateChildProcess(&pEngineState->companionConnection, pEngineState->userExperience.dwExitCode, FALSE); 643 PipeTerminateChildProcess(&pEngineState->companionConnection, pEngineState->userExperience.dwExitCode, FALSE);
644
645 WaitForUnelevatedLoggingThread(pEngineState->hUnelevatedLoggingThread);
627 } 646 }
628 647
629 // If the splash screen is still around, close it. 648 // If the splash screen is still around, close it.
@@ -646,6 +665,9 @@ static HRESULT RunElevated(
646{ 665{
647 HRESULT hr = S_OK; 666 HRESULT hr = S_OK;
648 HANDLE hLock = NULL; 667 HANDLE hLock = NULL;
668 HANDLE hLoggingThread = NULL;
669 REDIRECTED_LOGGING_CONTEXT loggingContext = { };
670 BOOL fDeleteLoggingCs = FALSE;
649 671
650 // Initialize logging. 672 // Initialize logging.
651 hr = LoggingOpen(&pEngineState->log, &pEngineState->internalCommand, &pEngineState->command, &pEngineState->variables, pEngineState->registration.sczDisplayName); 673 hr = LoggingOpen(&pEngineState->log, &pEngineState->internalCommand, &pEngineState->command, &pEngineState->variables, pEngineState->registration.sczDisplayName);
@@ -655,20 +677,23 @@ static HRESULT RunElevated(
655 hr = PipeChildConnect(&pEngineState->companionConnection, TRUE); 677 hr = PipeChildConnect(&pEngineState->companionConnection, TRUE);
656 ExitOnFailure(hr, "Failed to connect to unelevated process."); 678 ExitOnFailure(hr, "Failed to connect to unelevated process.");
657 679
658 // Set up the thread local storage to store the correct pipe to communicate logging then 680 // Set up the context for the logging thread then
659 // override logging to write over the pipe. 681 // override logging to write over the pipe.
660 pEngineState->dwElevatedLoggingTlsId = ::TlsAlloc(); 682 ::InitializeCriticalSection(&loggingContext.csBuffer);
661 if (TLS_OUT_OF_INDEXES == pEngineState->dwElevatedLoggingTlsId) 683 fDeleteLoggingCs = TRUE;
662 {
663 ExitWithLastError(hr, "Failed to allocate thread local storage for logging.");
664 }
665 684
666 if (!::TlsSetValue(pEngineState->dwElevatedLoggingTlsId, pEngineState->companionConnection.hPipe)) 685 loggingContext.hLogEvent = ::CreateEventW(NULL, TRUE, FALSE, NULL);
667 { 686 ExitOnNullWithLastError(loggingContext.hLogEvent, hr, "Failed to create log event for logging thread.");
668 ExitWithLastError(hr, "Failed to set elevated pipe into thread local storage for logging."); 687
669 } 688 loggingContext.hFinishedEvent = ::CreateEventW(NULL, TRUE, FALSE, NULL);
689 ExitOnNullWithLastError(loggingContext.hFinishedEvent, hr, "Failed to create finished event for logging thread.");
690
691 loggingContext.hPipe = pEngineState->companionConnection.hLoggingPipe;
692
693 hLoggingThread = ::CreateThread(NULL, 0, ElevatedLoggingThreadProc, &loggingContext, 0, NULL);
694 ExitOnNullWithLastError(hLoggingThread, hr, "Failed to create elevated logging thread.");
670 695
671 LogRedirect(RedirectLoggingOverPipe, pEngineState); 696 LogRedirect(RedirectLoggingOverPipe, &loggingContext);
672 697
673 // Create a top-level window to prevent shutting down the elevated process. 698 // Create a top-level window to prevent shutting down the elevated process.
674 hr = UiCreateMessageWindow(hInstance, pEngineState); 699 hr = UiCreateMessageWindow(hInstance, pEngineState);
@@ -677,16 +702,35 @@ static HRESULT RunElevated(
677 SrpInitialize(TRUE); 702 SrpInitialize(TRUE);
678 703
679 // Pump messages from parent process. 704 // Pump messages from parent process.
680 hr = ElevationChildPumpMessages(pEngineState->dwElevatedLoggingTlsId, pEngineState->companionConnection.hPipe, pEngineState->companionConnection.hCachePipe, &pEngineState->approvedExes, &pEngineState->cache, &pEngineState->containers, &pEngineState->packages, &pEngineState->payloads, &pEngineState->variables, &pEngineState->registration, &pEngineState->userExperience, &hLock, &pEngineState->userExperience.dwExitCode, &pEngineState->fRestart, &pEngineState->plan.fApplying); 705 hr = ElevationChildPumpMessages(pEngineState->companionConnection.hPipe, pEngineState->companionConnection.hCachePipe, &pEngineState->approvedExes, &pEngineState->cache, &pEngineState->containers, &pEngineState->packages, &pEngineState->payloads, &pEngineState->variables, &pEngineState->registration, &pEngineState->userExperience, &hLock, &pEngineState->userExperience.dwExitCode, &pEngineState->fRestart, &pEngineState->plan.fApplying);
681 LogRedirect(NULL, NULL); // reset logging so the next failure gets written to "log buffer" for the failure log.
682 ExitOnFailure(hr, "Failed to pump messages from parent process."); 706 ExitOnFailure(hr, "Failed to pump messages from parent process.");
683 707
708 WaitForElevatedLoggingThread(&loggingContext, hLoggingThread);
709
684LExit: 710LExit:
711 ReleaseHandle(hLoggingThread);
712
685 LogRedirect(NULL, NULL); // we're done talking to the child so always reset logging now. 713 LogRedirect(NULL, NULL); // we're done talking to the child so always reset logging now.
686 714
687 // If the message window is still around, close it. 715 // If the message window is still around, close it.
688 UiCloseMessageWindow(pEngineState); 716 UiCloseMessageWindow(pEngineState);
689 717
718 if (fDeleteLoggingCs)
719 {
720 ::DeleteCriticalSection(&loggingContext.csBuffer);
721 }
722
723 ReleaseHandle(loggingContext.hLogEvent);
724 ReleaseHandle(loggingContext.hFinishedEvent);
725
726 // If there was a log message left, try to log it locally.
727 if (loggingContext.sczBuffer)
728 {
729 LogStringWorkRaw(loggingContext.sczBuffer);
730
731 ReleaseStr(loggingContext.sczBuffer);
732 }
733
690 if (hLock) 734 if (hLock)
691 { 735 {
692 ::ReleaseMutex(hLock); 736 ::ReleaseMutex(hLock);
@@ -883,54 +927,180 @@ static HRESULT DAPI RedirectLoggingOverPipe(
883 __in_opt LPVOID pvContext 927 __in_opt LPVOID pvContext
884 ) 928 )
885{ 929{
886 static BOOL s_fCurrentlyLoggingToPipe = FALSE; 930 HRESULT hr = S_OK;
931 REDIRECTED_LOGGING_CONTEXT* pContext = static_cast<REDIRECTED_LOGGING_CONTEXT*>(pvContext);
932
933 ::EnterCriticalSection(&pContext->csBuffer);
934
935 hr = StrAnsiAllocConcat(&pContext->sczBuffer, szString, 0);
936
937 if (SUCCEEDED(hr) && !::SetEvent(pContext->hLogEvent))
938 {
939 HRESULT hrSet = HRESULT_FROM_WIN32(::GetLastError());
940 if (FAILED(hrSet))
941 {
942 TraceError(hrSet, "Failed to set log event.");
943 }
944 }
945
946 ::LeaveCriticalSection(&pContext->csBuffer);
887 947
948 return hr;
949}
950
951static HRESULT LogStringOverPipe(
952 __in_z LPCSTR szString,
953 __in HANDLE hPipe
954 )
955{
888 HRESULT hr = S_OK; 956 HRESULT hr = S_OK;
889 BURN_ENGINE_STATE* pEngineState = static_cast<BURN_ENGINE_STATE*>(pvContext);
890 BOOL fStartedLogging = FALSE;
891 HANDLE hPipe = INVALID_HANDLE_VALUE;
892 BYTE* pbData = NULL; 957 BYTE* pbData = NULL;
893 SIZE_T cbData = 0; 958 SIZE_T cbData = 0;
894 DWORD dwResult = 0; 959 DWORD dwResult = 0;
895 960
896 // Prevent this function from being called recursively. 961 hr = BuffWriteStringAnsi(&pbData, &cbData, szString);
897 if (s_fCurrentlyLoggingToPipe) 962 ExitOnFailure(hr, "Failed to prepare logging pipe message.");
898 { 963
899 ExitFunction(); 964 hr = PipeSendMessage(hPipe, static_cast<DWORD>(BURN_PIPE_MESSAGE_TYPE_LOG), pbData, cbData, NULL, NULL, &dwResult);
900 } 965 ExitOnFailure(hr, "Failed to send logging message over the pipe.");
966
967 hr = (HRESULT)dwResult;
968
969LExit:
970 ReleaseBuffer(pbData);
901 971
902 s_fCurrentlyLoggingToPipe = TRUE; 972 return hr;
903 fStartedLogging = TRUE; 973}
974
975static DWORD WINAPI ElevatedLoggingThreadProc(
976 __in LPVOID lpThreadParameter
977 )
978{
979 HRESULT hr = S_OK;
980 DWORD dwLastError = ERROR_SUCCESS;
981 REDIRECTED_LOGGING_CONTEXT* pContext = static_cast<REDIRECTED_LOGGING_CONTEXT*>(lpThreadParameter);
982 DWORD dwSignaledIndex = 0;
983 LPSTR sczBuffer = NULL;
984 BURN_PIPE_RESULT result = { };
985 HANDLE rghEvents[2] =
986 {
987 pContext->hLogEvent,
988 pContext->hFinishedEvent,
989 };
904 990
905 // Make sure the current thread set the pipe in TLS. 991 for (;;)
906 hPipe = ::TlsGetValue(pEngineState->dwElevatedLoggingTlsId);
907 if (!hPipe || INVALID_HANDLE_VALUE == hPipe)
908 { 992 {
909 hr = HRESULT_FROM_WIN32(ERROR_PIPE_NOT_CONNECTED); 993 hr = AppWaitForMultipleObjects(countof(rghEvents), rghEvents, FALSE, INFINITE, &dwSignaledIndex);
910 ExitFunction(); 994 if (FAILED(hr))
995 {
996 LogRedirect(NULL, NULL); // reset logging so the next failure gets written locally.
997 ExitOnFailure(hr, "Failed to wait for log thread events, signaled: %u.", dwSignaledIndex);
998 }
999
1000 if (1 == dwSignaledIndex)
1001 {
1002 LogRedirect(NULL, NULL); // No more messages will be logged over the pipe.
1003 }
1004
1005 dwLastError = ERROR_SUCCESS;
1006
1007 ::EnterCriticalSection(&pContext->csBuffer);
1008
1009 sczBuffer = pContext->sczBuffer;
1010 pContext->sczBuffer = NULL;
1011
1012 if (0 == dwSignaledIndex && !::ResetEvent(rghEvents[0]))
1013 {
1014 dwLastError = ::GetLastError();
1015 }
1016
1017 ::LeaveCriticalSection(&pContext->csBuffer);
1018
1019 if (ERROR_SUCCESS != dwLastError)
1020 {
1021 LogRedirect(NULL, NULL); // reset logging so the next failure gets written locally.
1022 ExitOnWin32Error(dwLastError, hr, "Failed to reset log event.");
1023 }
1024
1025 if (sczBuffer)
1026 {
1027 hr = LogStringOverPipe(sczBuffer, pContext->hPipe);
1028 if (FAILED(hr))
1029 {
1030 LogRedirect(NULL, NULL); // reset logging so the next failure gets written locally.
1031 ExitOnFailure(hr, "Failed to wait log message over pipe.");
1032 }
1033
1034 ReleaseStr(sczBuffer);
1035 }
1036
1037 if (1 == dwSignaledIndex)
1038 {
1039 break;
1040 }
911 } 1041 }
912 1042
913 // Do not log or use ExitOnFailure() macro here because they will be discarded 1043LExit:
914 // by the recursive block at the top of this function. 1044 LogRedirect(NULL, NULL); // No more messages will be logged over the pipe.
915 hr = BuffWriteStringAnsi(&pbData, &cbData, szString); 1045
916 if (SUCCEEDED(hr))
917 { 1046 {
918 hr = PipeSendMessage(hPipe, static_cast<DWORD>(BURN_PIPE_MESSAGE_TYPE_LOG), pbData, cbData, NULL, NULL, &dwResult); 1047 HRESULT hrTerminate = PipeTerminateLoggingPipe(pContext->hPipe, hr);
919 if (SUCCEEDED(hr)) 1048 if (FAILED(hrTerminate))
920 { 1049 {
921 hr = (HRESULT)dwResult; 1050 TraceError(hrTerminate, "Failed to terminate logging pipe.");
922 } 1051 }
923 } 1052 }
924 1053
925LExit: 1054 // Log the message locally if it failed to go over the pipe.
926 ReleaseBuffer(pbData); 1055 if (sczBuffer)
1056 {
1057 LogStringWorkRaw(sczBuffer);
1058
1059 ReleaseStr(sczBuffer);
1060 }
1061
1062 // Log any remaining message locally.
1063 if (pContext->sczBuffer)
1064 {
1065 AssertSz(FAILED(hr), "Exiting logging thread on success even though there was a leftover message");
1066 LogStringWorkRaw(pContext->sczBuffer);
1067
1068 ReleaseStr(pContext->sczBuffer);
1069 }
1070
1071 return (DWORD)hr;
1072}
1073
1074static HRESULT WaitForElevatedLoggingThread(
1075 __in REDIRECTED_LOGGING_CONTEXT* pContext,
1076 __in HANDLE hLoggingThread
1077 )
1078{
1079 HRESULT hr = S_OK;
927 1080
928 // We started logging so remember to say we are no longer logging. 1081 if (!::SetEvent(pContext->hFinishedEvent))
929 if (fStartedLogging)
930 { 1082 {
931 s_fCurrentlyLoggingToPipe = FALSE; 1083 ExitWithLastError(hr, "Failed to set log finished event.");
932 } 1084 }
933 1085
1086 hr = AppWaitForSingleObject(hLoggingThread, 5 * 60 * 1000); // TODO: is 5 minutes good?
1087 ExitOnFailure(hr, "Failed to wait for elevated logging thread.");
1088
1089LExit:
1090 return hr;
1091}
1092
1093static HRESULT WaitForUnelevatedLoggingThread(
1094 __in HANDLE hUnelevatedLoggingThread
1095 )
1096{
1097 HRESULT hr = S_OK;
1098
1099 // Give the thread 15 seconds to exit.
1100 hr = AppWaitForSingleObject(hUnelevatedLoggingThread, 15 * 1000);
1101 ExitOnFailure(hr, "Failed to wait for unelevated logging thread.");
1102
1103LExit:
934 return hr; 1104 return hr;
935} 1105}
936 1106
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);
diff --git a/src/burn/engine/pipe.h b/src/burn/engine/pipe.h
index f2d8070e..6571c0e2 100644
--- a/src/burn/engine/pipe.h
+++ b/src/burn/engine/pipe.h
@@ -15,6 +15,7 @@ typedef struct _BURN_PIPE_CONNECTION
15 HANDLE hProcess; 15 HANDLE hProcess;
16 HANDLE hPipe; 16 HANDLE hPipe;
17 HANDLE hCachePipe; 17 HANDLE hCachePipe;
18 HANDLE hLoggingPipe;
18} BURN_PIPE_CONNECTION; 19} BURN_PIPE_CONNECTION;
19 20
20typedef enum _BURN_PIPE_MESSAGE_TYPE : DWORD 21typedef enum _BURN_PIPE_MESSAGE_TYPE : DWORD
@@ -77,12 +78,15 @@ HRESULT PipeCreateNameAndSecret(
77 ); 78 );
78HRESULT PipeCreatePipes( 79HRESULT PipeCreatePipes(
79 __in BURN_PIPE_CONNECTION* pConnection, 80 __in BURN_PIPE_CONNECTION* pConnection,
80 __in BOOL fCreateCachePipe, 81 __in BOOL fCompanion
81 __out HANDLE* phEvent
82 ); 82 );
83HRESULT PipeWaitForChildConnect( 83HRESULT PipeWaitForChildConnect(
84 __in BURN_PIPE_CONNECTION* pConnection 84 __in BURN_PIPE_CONNECTION* pConnection
85 ); 85 );
86HRESULT PipeTerminateLoggingPipe(
87 __in HANDLE hLoggingPipe,
88 __in DWORD dwParentExitCode
89 );
86HRESULT PipeTerminateChildProcess( 90HRESULT PipeTerminateChildProcess(
87 __in BURN_PIPE_CONNECTION* pConnection, 91 __in BURN_PIPE_CONNECTION* pConnection,
88 __in DWORD dwParentExitCode, 92 __in DWORD dwParentExitCode,
@@ -92,7 +96,7 @@ HRESULT PipeTerminateChildProcess(
92// Child functions. 96// Child functions.
93HRESULT PipeChildConnect( 97HRESULT PipeChildConnect(
94 __in BURN_PIPE_CONNECTION* pConnection, 98 __in BURN_PIPE_CONNECTION* pConnection,
95 __in BOOL fConnectCachePipe 99 __in BOOL fCompanion
96 ); 100 );
97 101
98#ifdef __cplusplus 102#ifdef __cplusplus
diff --git a/src/burn/engine/uithread.cpp b/src/burn/engine/uithread.cpp
index fe1c21b8..26a9b723 100644
--- a/src/burn/engine/uithread.cpp
+++ b/src/burn/engine/uithread.cpp
@@ -107,18 +107,6 @@ static DWORD WINAPI ThreadProc(
107 BURN_ENGINE_STATE* pEngineState = pContext->pEngineState; 107 BURN_ENGINE_STATE* pEngineState = pContext->pEngineState;
108 BOOL fElevatedEngine = BURN_MODE_ELEVATED == pContext->pEngineState->internalCommand.mode; 108 BOOL fElevatedEngine = BURN_MODE_ELEVATED == pContext->pEngineState->internalCommand.mode;
109 109
110 // If elevated, set up the thread local storage to store the correct pipe to communicate logging.
111 if (fElevatedEngine)
112 {
113 Assert(TLS_OUT_OF_INDEXES != pEngineState->dwElevatedLoggingTlsId);
114
115 if (!::TlsSetValue(pEngineState->dwElevatedLoggingTlsId, pEngineState->companionConnection.hPipe))
116 {
117 // If the function failed we cannot write to the pipe so just terminate.
118 ExitFunction1(hr = E_INVALIDSTATE);
119 }
120 }
121
122 wc.lpfnWndProc = WndProc; 110 wc.lpfnWndProc = WndProc;
123 wc.hInstance = pContext->hInstance; 111 wc.hInstance = pContext->hInstance;
124 wc.lpszClassName = BURN_UITHREAD_CLASS_WINDOW; 112 wc.lpszClassName = BURN_UITHREAD_CLASS_WINDOW;