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 | |
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')
-rw-r--r-- | src/burn/engine/core.cpp | 24 | ||||
-rw-r--r-- | src/burn/engine/core.h | 2 | ||||
-rw-r--r-- | src/burn/engine/elevation.cpp | 15 | ||||
-rw-r--r-- | src/burn/engine/elevation.h | 1 | ||||
-rw-r--r-- | src/burn/engine/embedded.cpp | 4 | ||||
-rw-r--r-- | src/burn/engine/engine.cpp | 264 | ||||
-rw-r--r-- | src/burn/engine/pipe.cpp | 91 | ||||
-rw-r--r-- | src/burn/engine/pipe.h | 10 | ||||
-rw-r--r-- | src/burn/engine/uithread.cpp | 12 |
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( | |||
69 | static DWORD WINAPI CacheThreadProc( | 69 | static DWORD WINAPI CacheThreadProc( |
70 | __in LPVOID lpThreadParameter | 70 | __in LPVOID lpThreadParameter |
71 | ); | 71 | ); |
72 | static DWORD WINAPI LoggingThreadProc( | ||
73 | __in LPVOID lpThreadParameter | ||
74 | ); | ||
72 | static void LogPackages( | 75 | static 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 | ||
620 | LExit: | 626 | LExit: |
@@ -2325,6 +2331,24 @@ LExit: | |||
2325 | return (DWORD)hr; | 2331 | return (DWORD)hr; |
2326 | } | 2332 | } |
2327 | 2333 | ||
2334 | static 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 | |||
2347 | LExit: | ||
2348 | |||
2349 | return (DWORD)hr; | ||
2350 | } | ||
2351 | |||
2328 | static void LogPackages( | 2352 | static 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 | ||
92 | typedef struct _BURN_ELEVATION_CHILD_MESSAGE_CONTEXT | 92 | typedef 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 | ||
444 | LExit: | 443 | LExit: |
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 | *******************************************************************/ |
1534 | extern "C" HRESULT ElevationChildPumpMessages( | 1531 | extern "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. |
168 | HRESULT ElevationChildPumpMessages( | 168 | HRESULT 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 | ||
6 | typedef 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 | ||
8 | const DWORD RESTART_RETRIES = 10; | 17 | const 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 | ); |
61 | static HRESULT LogStringOverPipe( | ||
62 | __in_z LPCSTR szString, | ||
63 | __in HANDLE hPipe | ||
64 | ); | ||
65 | static DWORD WINAPI ElevatedLoggingThreadProc( | ||
66 | __in LPVOID lpThreadParameter | ||
67 | ); | ||
68 | static HRESULT WaitForElevatedLoggingThread( | ||
69 | __in REDIRECTED_LOGGING_CONTEXT* pContext, | ||
70 | __in HANDLE hLoggingThread | ||
71 | ); | ||
72 | static HRESULT WaitForUnelevatedLoggingThread( | ||
73 | __in HANDLE hUnelevatedLoggingThread | ||
74 | ); | ||
52 | static HRESULT Restart(); | 75 | static HRESULT Restart(); |
53 | static void CALLBACK BurnTraceError( | 76 | static 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 | |||
684 | LExit: | 710 | LExit: |
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 | |||
951 | static 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 | |||
969 | LExit: | ||
970 | ReleaseBuffer(pbData); | ||
901 | 971 | ||
902 | s_fCurrentlyLoggingToPipe = TRUE; | 972 | return hr; |
903 | fStartedLogging = TRUE; | 973 | } |
974 | |||
975 | static 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 | 1043 | LExit: |
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 | ||
925 | LExit: | 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 | |||
1074 | static 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 | |||
1089 | LExit: | ||
1090 | return hr; | ||
1091 | } | ||
1092 | |||
1093 | static 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 | |||
1103 | LExit: | ||
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 | ||
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); |
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 | ||
20 | typedef enum _BURN_PIPE_MESSAGE_TYPE : DWORD | 21 | typedef enum _BURN_PIPE_MESSAGE_TYPE : DWORD |
@@ -77,12 +78,15 @@ HRESULT PipeCreateNameAndSecret( | |||
77 | ); | 78 | ); |
78 | HRESULT PipeCreatePipes( | 79 | HRESULT 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 | ); |
83 | HRESULT PipeWaitForChildConnect( | 83 | HRESULT PipeWaitForChildConnect( |
84 | __in BURN_PIPE_CONNECTION* pConnection | 84 | __in BURN_PIPE_CONNECTION* pConnection |
85 | ); | 85 | ); |
86 | HRESULT PipeTerminateLoggingPipe( | ||
87 | __in HANDLE hLoggingPipe, | ||
88 | __in DWORD dwParentExitCode | ||
89 | ); | ||
86 | HRESULT PipeTerminateChildProcess( | 90 | HRESULT 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. |
93 | HRESULT PipeChildConnect( | 97 | HRESULT 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; |