aboutsummaryrefslogtreecommitdiff
path: root/src/burn
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2022-09-02 16:12:26 -0500
committerSean Hall <r.sean.hall@gmail.com>2022-09-03 15:29:26 -0500
commit7728e34e48a4fdb710ecc92dd8dca833bff3993f (patch)
tree83d9a6a5068985670dc47121d400fc7c491c23ec /src/burn
parenteea6121f388197435529922b3cb13d3631afb9a8 (diff)
downloadwix-7728e34e48a4fdb710ecc92dd8dca833bff3993f.tar.gz
wix-7728e34e48a4fdb710ecc92dd8dca833bff3993f.tar.bz2
wix-7728e34e48a4fdb710ecc92dd8dca833bff3993f.zip
Use elevated engine to make the restart request when it is available.
Fixes 6145
Diffstat (limited to 'src/burn')
-rw-r--r--src/burn/engine/core.cpp42
-rw-r--r--src/burn/engine/core.h17
-rw-r--r--src/burn/engine/engine.cpp152
-rw-r--r--src/burn/engine/uithread.cpp10
4 files changed, 121 insertions, 100 deletions
diff --git a/src/burn/engine/core.cpp b/src/burn/engine/core.cpp
index 3c1ed117..c8dce17b 100644
--- a/src/burn/engine/core.cpp
+++ b/src/burn/engine/core.cpp
@@ -2028,6 +2028,48 @@ extern "C" HRESULT DAPI CoreWaitForProcCompletion(
2028 return vpfnProcWaitForCompletion(hProcess, dwTimeout, pdwReturnCode); 2028 return vpfnProcWaitForCompletion(hProcess, dwTimeout, pdwReturnCode);
2029} 2029}
2030 2030
2031extern "C" HRESULT DAPI CoreCloseElevatedLoggingThread(
2032 __in BURN_ENGINE_STATE* pEngineState
2033 )
2034{
2035 HRESULT hr = S_OK;
2036
2037 if (INVALID_HANDLE_VALUE == pEngineState->elevatedLoggingContext.hThread)
2038 {
2039 ExitFunction();
2040 }
2041
2042 if (!::SetEvent(pEngineState->elevatedLoggingContext.hFinishedEvent))
2043 {
2044 ExitWithLastError(hr, "Failed to set log finished event.");
2045 }
2046
2047 hr = AppWaitForSingleObject(pEngineState->elevatedLoggingContext.hThread, 5 * 60 * 1000); // TODO: is 5 minutes good?
2048 ExitOnFailure(hr, "Failed to wait for elevated logging thread.");
2049
2050LExit:
2051 return hr;
2052}
2053
2054extern "C" HRESULT DAPI CoreWaitForUnelevatedLoggingThread(
2055 __in HANDLE hUnelevatedLoggingThread
2056 )
2057{
2058 HRESULT hr = S_OK;
2059
2060 if (INVALID_HANDLE_VALUE == hUnelevatedLoggingThread)
2061 {
2062 ExitFunction();
2063 }
2064
2065 // Give the thread 15 seconds to exit.
2066 hr = AppWaitForSingleObject(hUnelevatedLoggingThread, 15 * 1000);
2067 ExitOnFailure(hr, "Failed to wait for unelevated logging thread.");
2068
2069LExit:
2070 return hr;
2071}
2072
2031// internal helper functions 2073// internal helper functions
2032 2074
2033static HRESULT AppendEscapedArgumentToCommandLine( 2075static HRESULT AppendEscapedArgumentToCommandLine(
diff --git a/src/burn/engine/core.h b/src/burn/engine/core.h
index 28b5ba5d..812b40b1 100644
--- a/src/burn/engine/core.h
+++ b/src/burn/engine/core.h
@@ -123,6 +123,16 @@ typedef struct _BURN_ENGINE_COMMAND
123 LPWSTR sczLogFile; 123 LPWSTR sczLogFile;
124} BURN_ENGINE_COMMAND; 124} BURN_ENGINE_COMMAND;
125 125
126typedef struct _BURN_REDIRECTED_LOGGING_CONTEXT
127{
128 CRITICAL_SECTION csBuffer;
129 LPSTR sczBuffer;
130 HANDLE hPipe;
131 HANDLE hLogEvent;
132 HANDLE hFinishedEvent;
133 HANDLE hThread;
134} BURN_REDIRECTED_LOGGING_CONTEXT;
135
126typedef struct _BURN_ENGINE_STATE 136typedef struct _BURN_ENGINE_STATE
127{ 137{
128 // UX flow control 138 // UX flow control
@@ -164,6 +174,7 @@ typedef struct _BURN_ENGINE_STATE
164 174
165 BURN_PLAN plan; 175 BURN_PLAN plan;
166 176
177 BURN_REDIRECTED_LOGGING_CONTEXT elevatedLoggingContext;
167 HANDLE hUnelevatedLoggingThread; 178 HANDLE hUnelevatedLoggingThread;
168 179
169 LPWSTR sczBundleEngineWorkingPath; 180 LPWSTR sczBundleEngineWorkingPath;
@@ -336,6 +347,12 @@ HRESULT DAPI CoreWaitForProcCompletion(
336 __in DWORD dwTimeout, 347 __in DWORD dwTimeout,
337 __out_opt DWORD* pdwReturnCode 348 __out_opt DWORD* pdwReturnCode
338 ); 349 );
350HRESULT DAPI CoreCloseElevatedLoggingThread(
351 __in BURN_ENGINE_STATE* pEngineState
352 );
353HRESULT DAPI CoreWaitForUnelevatedLoggingThread(
354 __in HANDLE hUnelevatedLoggingThread
355 );
339 356
340#if defined(__cplusplus) 357#if defined(__cplusplus)
341} 358}
diff --git a/src/burn/engine/engine.cpp b/src/burn/engine/engine.cpp
index 9c8b6c1d..89082a88 100644
--- a/src/burn/engine/engine.cpp
+++ b/src/burn/engine/engine.cpp
@@ -3,15 +3,6 @@
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
15// constants 6// constants
16 7
17const DWORD RESTART_RETRIES = 10; 8const DWORD RESTART_RETRIES = 10;
@@ -65,13 +56,6 @@ static HRESULT LogStringOverPipe(
65static DWORD WINAPI ElevatedLoggingThreadProc( 56static DWORD WINAPI ElevatedLoggingThreadProc(
66 __in LPVOID lpThreadParameter 57 __in LPVOID lpThreadParameter
67 ); 58 );
68static HRESULT WaitForElevatedLoggingThread(
69 __in REDIRECTED_LOGGING_CONTEXT* pContext,
70 __in HANDLE hLoggingThread
71 );
72static HRESULT WaitForUnelevatedLoggingThread(
73 __in HANDLE hUnelevatedLoggingThread
74 );
75static HRESULT Restart( 59static HRESULT Restart(
76 __in BURN_ENGINE_STATE* pEngineState 60 __in BURN_ENGINE_STATE* pEngineState
77 ); 61 );
@@ -308,10 +292,6 @@ LExit:
308 { 292 {
309 LogId(REPORT_STANDARD, MSG_EXITING_RUN_ONCE, FAILED(hr) ? (int)hr : *pdwExitCode); 293 LogId(REPORT_STANDARD, MSG_EXITING_RUN_ONCE, FAILED(hr) ? (int)hr : *pdwExitCode);
310 } 294 }
311 else if (fRunElevated)
312 {
313 LogId(REPORT_STANDARD, MSG_EXITING_ELEVATED, FAILED(hr) ? (int)hr : *pdwExitCode);
314 }
315 295
316 if (fLogInitialized) 296 if (fLogInitialized)
317 { 297 {
@@ -320,7 +300,12 @@ LExit:
320 LogFlush(); 300 LogFlush();
321 } 301 }
322 302
323 if (engineState.fRestart) 303 // end per-machine process if running
304 if (!fRunElevated && INVALID_HANDLE_VALUE != engineState.companionConnection.hPipe)
305 {
306 PipeTerminateChildProcess(&engineState.companionConnection, *pdwExitCode, engineState.fRestart);
307 }
308 else if (engineState.fRestart)
324 { 309 {
325 LogId(REPORT_STANDARD, MSG_RESTARTING); 310 LogId(REPORT_STANDARD, MSG_RESTARTING);
326 311
@@ -334,6 +319,30 @@ LExit:
334 // If the message window is still around, close it. 319 // If the message window is still around, close it.
335 UiCloseMessageWindow(&engineState); 320 UiCloseMessageWindow(&engineState);
336 321
322 // If the logging thread is still around, close it.
323 if (!fRunElevated)
324 {
325 CoreWaitForUnelevatedLoggingThread(engineState.hUnelevatedLoggingThread);
326 }
327 else if (fRunElevated)
328 {
329 CoreCloseElevatedLoggingThread(&engineState);
330
331 // We're done talking to the child so always reset logging now.
332 LogRedirect(NULL, NULL);
333
334 // If there was a log message left, try to log it locally.
335 if (engineState.elevatedLoggingContext.sczBuffer)
336 {
337 LogStringWorkRaw(engineState.elevatedLoggingContext.sczBuffer);
338
339 ReleaseStr(engineState.elevatedLoggingContext.sczBuffer);
340 }
341
342 // Log the exit code here to make sure it gets in the elevated log.
343 LogId(REPORT_STANDARD, MSG_EXITING_ELEVATED, FAILED(hr) ? (int)hr : *pdwExitCode);
344 }
345
337 UninitializeEngineState(&engineState); 346 UninitializeEngineState(&engineState);
338 347
339 if (fXmlInitialized) 348 if (fXmlInitialized)
@@ -387,7 +396,12 @@ static HRESULT InitializeEngineState(
387 HANDLE hSectionFile = hEngineFile; 396 HANDLE hSectionFile = hEngineFile;
388 HANDLE hSourceEngineFile = INVALID_HANDLE_VALUE; 397 HANDLE hSourceEngineFile = INVALID_HANDLE_VALUE;
389 398
399 pEngineState->hUnelevatedLoggingThread = INVALID_HANDLE_VALUE;
400 pEngineState->elevatedLoggingContext.hPipe = INVALID_HANDLE_VALUE;
401 pEngineState->elevatedLoggingContext.hThread = INVALID_HANDLE_VALUE;
402
390 ::InitializeCriticalSection(&pEngineState->csRestartState); 403 ::InitializeCriticalSection(&pEngineState->csRestartState);
404 ::InitializeCriticalSection(&pEngineState->elevatedLoggingContext.csBuffer);
391 405
392 pEngineState->internalCommand.automaticUpdates = BURN_AU_PAUSE_ACTION_IFELEVATED; 406 pEngineState->internalCommand.automaticUpdates = BURN_AU_PAUSE_ACTION_IFELEVATED;
393 ::InitializeCriticalSection(&pEngineState->userExperience.csEngineActive); 407 ::InitializeCriticalSection(&pEngineState->userExperience.csEngineActive);
@@ -423,6 +437,12 @@ static void UninitializeEngineState(
423 ReleaseMem(pEngineState->internalCommand.rgSecretArgs); 437 ReleaseMem(pEngineState->internalCommand.rgSecretArgs);
424 ReleaseMem(pEngineState->internalCommand.rgUnknownArgs); 438 ReleaseMem(pEngineState->internalCommand.rgUnknownArgs);
425 439
440 ReleaseFileHandle(pEngineState->hUnelevatedLoggingThread);
441 ReleaseFileHandle(pEngineState->elevatedLoggingContext.hThread);
442 ::DeleteCriticalSection(&pEngineState->elevatedLoggingContext.csBuffer);
443 ReleaseHandle(pEngineState->elevatedLoggingContext.hLogEvent);
444 ReleaseHandle(pEngineState->elevatedLoggingContext.hFinishedEvent);
445
426 PipeConnectionUninitialize(&pEngineState->embeddedConnection); 446 PipeConnectionUninitialize(&pEngineState->embeddedConnection);
427 PipeConnectionUninitialize(&pEngineState->companionConnection); 447 PipeConnectionUninitialize(&pEngineState->companionConnection);
428 ReleaseStr(pEngineState->sczBundleEngineWorkingPath) 448 ReleaseStr(pEngineState->sczBundleEngineWorkingPath)
@@ -643,14 +663,6 @@ LExit:
643 663
644 VariablesDump(&pEngineState->variables); 664 VariablesDump(&pEngineState->variables);
645 665
646 // end per-machine process if running
647 if (INVALID_HANDLE_VALUE != pEngineState->companionConnection.hPipe)
648 {
649 PipeTerminateChildProcess(&pEngineState->companionConnection, pEngineState->userExperience.dwExitCode, FALSE);
650
651 WaitForUnelevatedLoggingThread(pEngineState->hUnelevatedLoggingThread);
652 }
653
654 // If the splash screen is still around, close it. 666 // If the splash screen is still around, close it.
655 if (::IsWindow(pEngineState->command.hwndSplashScreen)) 667 if (::IsWindow(pEngineState->command.hwndSplashScreen))
656 { 668 {
@@ -671,9 +683,7 @@ static HRESULT RunElevated(
671{ 683{
672 HRESULT hr = S_OK; 684 HRESULT hr = S_OK;
673 HANDLE hLock = NULL; 685 HANDLE hLock = NULL;
674 HANDLE hLoggingThread = NULL; 686 BURN_REDIRECTED_LOGGING_CONTEXT* pLoggingContext = &pEngineState->elevatedLoggingContext;
675 REDIRECTED_LOGGING_CONTEXT loggingContext = { };
676 BOOL fDeleteLoggingCs = FALSE;
677 687
678 // Initialize logging. 688 // Initialize logging.
679 hr = LoggingOpen(&pEngineState->log, &pEngineState->internalCommand, &pEngineState->command, &pEngineState->variables, pEngineState->registration.sczDisplayName); 689 hr = LoggingOpen(&pEngineState->log, &pEngineState->internalCommand, &pEngineState->command, &pEngineState->variables, pEngineState->registration.sczDisplayName);
@@ -685,21 +695,18 @@ static HRESULT RunElevated(
685 695
686 // Set up the context for the logging thread then 696 // Set up the context for the logging thread then
687 // override logging to write over the pipe. 697 // override logging to write over the pipe.
688 ::InitializeCriticalSection(&loggingContext.csBuffer); 698 pLoggingContext->hLogEvent = ::CreateEventW(NULL, TRUE, FALSE, NULL);
689 fDeleteLoggingCs = TRUE; 699 ExitOnNullWithLastError(pLoggingContext->hLogEvent, hr, "Failed to create log event for logging thread.");
690
691 loggingContext.hLogEvent = ::CreateEventW(NULL, TRUE, FALSE, NULL);
692 ExitOnNullWithLastError(loggingContext.hLogEvent, hr, "Failed to create log event for logging thread.");
693 700
694 loggingContext.hFinishedEvent = ::CreateEventW(NULL, TRUE, FALSE, NULL); 701 pLoggingContext->hFinishedEvent = ::CreateEventW(NULL, TRUE, FALSE, NULL);
695 ExitOnNullWithLastError(loggingContext.hFinishedEvent, hr, "Failed to create finished event for logging thread."); 702 ExitOnNullWithLastError(pLoggingContext->hFinishedEvent, hr, "Failed to create finished event for logging thread.");
696 703
697 loggingContext.hPipe = pEngineState->companionConnection.hLoggingPipe; 704 pLoggingContext->hPipe = pEngineState->companionConnection.hLoggingPipe;
698 705
699 hLoggingThread = ::CreateThread(NULL, 0, ElevatedLoggingThreadProc, &loggingContext, 0, NULL); 706 pLoggingContext->hThread = ::CreateThread(NULL, 0, ElevatedLoggingThreadProc, pLoggingContext, 0, NULL);
700 ExitOnNullWithLastError(hLoggingThread, hr, "Failed to create elevated logging thread."); 707 ExitOnNullWithLastError(pLoggingContext->hThread, hr, "Failed to create elevated logging thread.");
701 708
702 LogRedirect(RedirectLoggingOverPipe, &loggingContext); 709 LogRedirect(RedirectLoggingOverPipe, pLoggingContext);
703 710
704 if (!pEngineState->internalCommand.fInitiallyElevated) 711 if (!pEngineState->internalCommand.fInitiallyElevated)
705 { 712 {
@@ -716,29 +723,7 @@ static HRESULT RunElevated(
716 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); 723 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);
717 ExitOnFailure(hr, "Failed to pump messages from parent process."); 724 ExitOnFailure(hr, "Failed to pump messages from parent process.");
718 725
719 WaitForElevatedLoggingThread(&loggingContext, hLoggingThread);
720
721LExit: 726LExit:
722 ReleaseHandle(hLoggingThread);
723
724 LogRedirect(NULL, NULL); // we're done talking to the child so always reset logging now.
725
726 if (fDeleteLoggingCs)
727 {
728 ::DeleteCriticalSection(&loggingContext.csBuffer);
729 }
730
731 ReleaseHandle(loggingContext.hLogEvent);
732 ReleaseHandle(loggingContext.hFinishedEvent);
733
734 // If there was a log message left, try to log it locally.
735 if (loggingContext.sczBuffer)
736 {
737 LogStringWorkRaw(loggingContext.sczBuffer);
738
739 ReleaseStr(loggingContext.sczBuffer);
740 }
741
742 if (hLock) 727 if (hLock)
743 { 728 {
744 ::ReleaseMutex(hLock); 729 ::ReleaseMutex(hLock);
@@ -936,7 +921,7 @@ static HRESULT DAPI RedirectLoggingOverPipe(
936 ) 921 )
937{ 922{
938 HRESULT hr = S_OK; 923 HRESULT hr = S_OK;
939 REDIRECTED_LOGGING_CONTEXT* pContext = static_cast<REDIRECTED_LOGGING_CONTEXT*>(pvContext); 924 BURN_REDIRECTED_LOGGING_CONTEXT* pContext = static_cast<BURN_REDIRECTED_LOGGING_CONTEXT*>(pvContext);
940 925
941 ::EnterCriticalSection(&pContext->csBuffer); 926 ::EnterCriticalSection(&pContext->csBuffer);
942 927
@@ -986,7 +971,7 @@ static DWORD WINAPI ElevatedLoggingThreadProc(
986{ 971{
987 HRESULT hr = S_OK; 972 HRESULT hr = S_OK;
988 DWORD dwLastError = ERROR_SUCCESS; 973 DWORD dwLastError = ERROR_SUCCESS;
989 REDIRECTED_LOGGING_CONTEXT* pContext = static_cast<REDIRECTED_LOGGING_CONTEXT*>(lpThreadParameter); 974 BURN_REDIRECTED_LOGGING_CONTEXT* pContext = static_cast<BURN_REDIRECTED_LOGGING_CONTEXT*>(lpThreadParameter);
990 DWORD dwSignaledIndex = 0; 975 DWORD dwSignaledIndex = 0;
991 LPSTR sczBuffer = NULL; 976 LPSTR sczBuffer = NULL;
992 BURN_PIPE_RESULT result = { }; 977 BURN_PIPE_RESULT result = { };
@@ -1079,39 +1064,6 @@ LExit:
1079 return (DWORD)hr; 1064 return (DWORD)hr;
1080} 1065}
1081 1066
1082static HRESULT WaitForElevatedLoggingThread(
1083 __in REDIRECTED_LOGGING_CONTEXT* pContext,
1084 __in HANDLE hLoggingThread
1085 )
1086{
1087 HRESULT hr = S_OK;
1088
1089 if (!::SetEvent(pContext->hFinishedEvent))
1090 {
1091 ExitWithLastError(hr, "Failed to set log finished event.");
1092 }
1093
1094 hr = AppWaitForSingleObject(hLoggingThread, 5 * 60 * 1000); // TODO: is 5 minutes good?
1095 ExitOnFailure(hr, "Failed to wait for elevated logging thread.");
1096
1097LExit:
1098 return hr;
1099}
1100
1101static HRESULT WaitForUnelevatedLoggingThread(
1102 __in HANDLE hUnelevatedLoggingThread
1103 )
1104{
1105 HRESULT hr = S_OK;
1106
1107 // Give the thread 15 seconds to exit.
1108 hr = AppWaitForSingleObject(hUnelevatedLoggingThread, 15 * 1000);
1109 ExitOnFailure(hr, "Failed to wait for unelevated logging thread.");
1110
1111LExit:
1112 return hr;
1113}
1114
1115static HRESULT Restart( 1067static HRESULT Restart(
1116 __in BURN_ENGINE_STATE* pEngineState 1068 __in BURN_ENGINE_STATE* pEngineState
1117 ) 1069 )
diff --git a/src/burn/engine/uithread.cpp b/src/burn/engine/uithread.cpp
index 673111f8..8ddd51bd 100644
--- a/src/burn/engine/uithread.cpp
+++ b/src/burn/engine/uithread.cpp
@@ -222,6 +222,16 @@ static LRESULT CALLBACK WndProc(
222 ::Sleep(250); 222 ::Sleep(250);
223 } 223 }
224 224
225 // If this is the per-machine process then close the logging pipe with the parent process.
226 if (pInfo->fElevatedEngine)
227 {
228 CoreCloseElevatedLoggingThread(pInfo->pEngineState);
229 }
230 else
231 {
232 CoreWaitForUnelevatedLoggingThread(pInfo->pEngineState->hUnelevatedLoggingThread);
233 }
234
225 LogStringWorkRaw("=======================================\r\n"); 235 LogStringWorkRaw("=======================================\r\n");
226 236
227 // Close the log to try to make sure everything is flushed to disk. 237 // Close the log to try to make sure everything is flushed to disk.