diff options
Diffstat (limited to 'src/burn/engine/engine.cpp')
-rw-r--r-- | src/burn/engine/engine.cpp | 85 |
1 files changed, 62 insertions, 23 deletions
diff --git a/src/burn/engine/engine.cpp b/src/burn/engine/engine.cpp index 13d23ecd..9c8b6c1d 100644 --- a/src/burn/engine/engine.cpp +++ b/src/burn/engine/engine.cpp | |||
@@ -72,7 +72,9 @@ static HRESULT WaitForElevatedLoggingThread( | |||
72 | static HRESULT WaitForUnelevatedLoggingThread( | 72 | static HRESULT WaitForUnelevatedLoggingThread( |
73 | __in HANDLE hUnelevatedLoggingThread | 73 | __in HANDLE hUnelevatedLoggingThread |
74 | ); | 74 | ); |
75 | static HRESULT Restart(); | 75 | static HRESULT Restart( |
76 | __in BURN_ENGINE_STATE* pEngineState | ||
77 | ); | ||
76 | static void CALLBACK BurnTraceError( | 78 | static void CALLBACK BurnTraceError( |
77 | __in_z LPCSTR szFile, | 79 | __in_z LPCSTR szFile, |
78 | __in int iLine, | 80 | __in int iLine, |
@@ -131,7 +133,6 @@ extern "C" HRESULT EngineRun( | |||
131 | BOOL fRunNormal = FALSE; | 133 | BOOL fRunNormal = FALSE; |
132 | BOOL fRunElevated = FALSE; | 134 | BOOL fRunElevated = FALSE; |
133 | BOOL fRunRunOnce = FALSE; | 135 | BOOL fRunRunOnce = FALSE; |
134 | BOOL fRestart = FALSE; | ||
135 | 136 | ||
136 | BURN_ENGINE_STATE engineState = { }; | 137 | BURN_ENGINE_STATE engineState = { }; |
137 | engineState.command.cbSize = sizeof(BOOTSTRAPPER_COMMAND); | 138 | engineState.command.cbSize = sizeof(BOOTSTRAPPER_COMMAND); |
@@ -269,9 +270,7 @@ extern "C" HRESULT EngineRun( | |||
269 | ExitOnFailure(hr, "Invalid run mode."); | 270 | ExitOnFailure(hr, "Invalid run mode."); |
270 | } | 271 | } |
271 | 272 | ||
272 | // set exit code and remember if we are supposed to restart. | ||
273 | *pdwExitCode = engineState.userExperience.dwExitCode; | 273 | *pdwExitCode = engineState.userExperience.dwExitCode; |
274 | fRestart = engineState.fRestart; | ||
275 | 274 | ||
276 | LExit: | 275 | LExit: |
277 | ReleaseStr(sczExePath); | 276 | ReleaseStr(sczExePath); |
@@ -289,17 +288,17 @@ LExit: | |||
289 | CacheUninitialize(&engineState.cache); | 288 | CacheUninitialize(&engineState.cache); |
290 | 289 | ||
291 | // If this is a related bundle (but not an update) suppress restart and return the standard restart error code. | 290 | // If this is a related bundle (but not an update) suppress restart and return the standard restart error code. |
292 | if (fRestart && BOOTSTRAPPER_RELATION_NONE != engineState.command.relationType && BOOTSTRAPPER_RELATION_UPDATE != engineState.command.relationType) | 291 | if (engineState.fRestart && BOOTSTRAPPER_RELATION_NONE != engineState.command.relationType && BOOTSTRAPPER_RELATION_UPDATE != engineState.command.relationType) |
293 | { | 292 | { |
294 | LogId(REPORT_STANDARD, MSG_RESTART_ABORTED, LoggingRelationTypeToString(engineState.command.relationType)); | 293 | LogId(REPORT_STANDARD, MSG_RESTART_ABORTED, LoggingRelationTypeToString(engineState.command.relationType)); |
295 | 294 | ||
296 | fRestart = FALSE; | 295 | engineState.fRestart = FALSE; |
297 | hr = SUCCEEDED(hr) ? HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_REQUIRED) : HRESULT_FROM_WIN32(ERROR_FAIL_REBOOT_REQUIRED); | 296 | hr = SUCCEEDED(hr) ? HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_REQUIRED) : HRESULT_FROM_WIN32(ERROR_FAIL_REBOOT_REQUIRED); |
298 | } | 297 | } |
299 | 298 | ||
300 | if (fRunNormal) | 299 | if (fRunNormal) |
301 | { | 300 | { |
302 | LogId(REPORT_STANDARD, MSG_EXITING, FAILED(hr) ? (int)hr : *pdwExitCode, LoggingBoolToString(fRestart)); | 301 | LogId(REPORT_STANDARD, MSG_EXITING, FAILED(hr) ? (int)hr : *pdwExitCode, LoggingBoolToString(engineState.fRestart)); |
303 | } | 302 | } |
304 | else if (fRunUntrusted) | 303 | else if (fRunUntrusted) |
305 | { | 304 | { |
@@ -321,17 +320,20 @@ LExit: | |||
321 | LogFlush(); | 320 | LogFlush(); |
322 | } | 321 | } |
323 | 322 | ||
324 | if (fRestart) | 323 | if (engineState.fRestart) |
325 | { | 324 | { |
326 | LogId(REPORT_STANDARD, MSG_RESTARTING); | 325 | LogId(REPORT_STANDARD, MSG_RESTARTING); |
327 | 326 | ||
328 | HRESULT hrRestart = Restart(); | 327 | HRESULT hrRestart = Restart(&engineState); |
329 | if (FAILED(hrRestart)) | 328 | if (FAILED(hrRestart)) |
330 | { | 329 | { |
331 | LogErrorId(hrRestart, MSG_RESTART_FAILED); | 330 | LogErrorId(hrRestart, MSG_RESTART_FAILED); |
332 | } | 331 | } |
333 | } | 332 | } |
334 | 333 | ||
334 | // If the message window is still around, close it. | ||
335 | UiCloseMessageWindow(&engineState); | ||
336 | |||
335 | UninitializeEngineState(&engineState); | 337 | UninitializeEngineState(&engineState); |
336 | 338 | ||
337 | if (fXmlInitialized) | 339 | if (fXmlInitialized) |
@@ -385,6 +387,8 @@ static HRESULT InitializeEngineState( | |||
385 | HANDLE hSectionFile = hEngineFile; | 387 | HANDLE hSectionFile = hEngineFile; |
386 | HANDLE hSourceEngineFile = INVALID_HANDLE_VALUE; | 388 | HANDLE hSourceEngineFile = INVALID_HANDLE_VALUE; |
387 | 389 | ||
390 | ::InitializeCriticalSection(&pEngineState->csRestartState); | ||
391 | |||
388 | pEngineState->internalCommand.automaticUpdates = BURN_AU_PAUSE_ACTION_IFELEVATED; | 392 | pEngineState->internalCommand.automaticUpdates = BURN_AU_PAUSE_ACTION_IFELEVATED; |
389 | ::InitializeCriticalSection(&pEngineState->userExperience.csEngineActive); | 393 | ::InitializeCriticalSection(&pEngineState->userExperience.csEngineActive); |
390 | PipeConnectionInitialize(&pEngineState->companionConnection); | 394 | PipeConnectionInitialize(&pEngineState->companionConnection); |
@@ -459,6 +463,8 @@ static void UninitializeEngineState( | |||
459 | ReleaseStr(pEngineState->log.sczPath); | 463 | ReleaseStr(pEngineState->log.sczPath); |
460 | ReleaseStr(pEngineState->log.sczPathVariable); | 464 | ReleaseStr(pEngineState->log.sczPathVariable); |
461 | 465 | ||
466 | ::DeleteCriticalSection(&pEngineState->csRestartState); | ||
467 | |||
462 | // clear struct | 468 | // clear struct |
463 | memset(pEngineState, 0, sizeof(BURN_ENGINE_STATE)); | 469 | memset(pEngineState, 0, sizeof(BURN_ENGINE_STATE)); |
464 | } | 470 | } |
@@ -635,9 +641,6 @@ LExit: | |||
635 | 641 | ||
636 | BurnExtensionUnload(&pEngineState->extensions); | 642 | BurnExtensionUnload(&pEngineState->extensions); |
637 | 643 | ||
638 | // If the message window is still around, close it. | ||
639 | UiCloseMessageWindow(pEngineState); | ||
640 | |||
641 | VariablesDump(&pEngineState->variables); | 644 | VariablesDump(&pEngineState->variables); |
642 | 645 | ||
643 | // end per-machine process if running | 646 | // end per-machine process if running |
@@ -720,9 +723,6 @@ LExit: | |||
720 | 723 | ||
721 | LogRedirect(NULL, NULL); // we're done talking to the child so always reset logging now. | 724 | LogRedirect(NULL, NULL); // we're done talking to the child so always reset logging now. |
722 | 725 | ||
723 | // If the message window is still around, close it. | ||
724 | UiCloseMessageWindow(pEngineState); | ||
725 | |||
726 | if (fDeleteLoggingCs) | 726 | if (fDeleteLoggingCs) |
727 | { | 727 | { |
728 | ::DeleteCriticalSection(&loggingContext.csBuffer); | 728 | ::DeleteCriticalSection(&loggingContext.csBuffer); |
@@ -1112,7 +1112,9 @@ LExit: | |||
1112 | return hr; | 1112 | return hr; |
1113 | } | 1113 | } |
1114 | 1114 | ||
1115 | static HRESULT Restart() | 1115 | static HRESULT Restart( |
1116 | __in BURN_ENGINE_STATE* pEngineState | ||
1117 | ) | ||
1116 | { | 1118 | { |
1117 | HRESULT hr = S_OK; | 1119 | HRESULT hr = S_OK; |
1118 | HANDLE hProcessToken = NULL; | 1120 | HANDLE hProcessToken = NULL; |
@@ -1136,17 +1138,19 @@ static HRESULT Restart() | |||
1136 | ExitWithLastError(hr, "Failed to adjust token to add shutdown privileges."); | 1138 | ExitWithLastError(hr, "Failed to adjust token to add shutdown privileges."); |
1137 | } | 1139 | } |
1138 | 1140 | ||
1141 | pEngineState->fRestarting = TRUE; | ||
1142 | CoreUpdateRestartState(pEngineState, BURN_RESTART_STATE_REQUESTING); | ||
1143 | |||
1139 | do | 1144 | do |
1140 | { | 1145 | { |
1141 | hr = S_OK; | 1146 | hr = S_OK; |
1142 | 1147 | ||
1143 | // Wait a second to let the companion process (assuming we did an elevated install) to get to the | 1148 | if (dwRetries) |
1144 | // point where it too is thinking about restarting the computer. Only one will schedule the restart | 1149 | { |
1145 | // but both will have their log files closed and otherwise be ready to exit. | 1150 | // On retry, wait a second to let the OS try to get to a place where the restart can |
1146 | // | 1151 | // be initiated. |
1147 | // On retry, we'll also wait a second to let the OS try to get to a place where the restart can | 1152 | ::Sleep(1000); |
1148 | // be initiated. | 1153 | } |
1149 | ::Sleep(1000); | ||
1150 | 1154 | ||
1151 | if (!vpfnInitiateSystemShutdownExW(NULL, NULL, 0, FALSE, TRUE, SHTDN_REASON_MAJOR_APPLICATION | SHTDN_REASON_MINOR_INSTALLATION | SHTDN_REASON_FLAG_PLANNED)) | 1155 | if (!vpfnInitiateSystemShutdownExW(NULL, NULL, 0, FALSE, TRUE, SHTDN_REASON_MAJOR_APPLICATION | SHTDN_REASON_MINOR_INSTALLATION | SHTDN_REASON_FLAG_PLANNED)) |
1152 | { | 1156 | { |
@@ -1155,6 +1159,41 @@ static HRESULT Restart() | |||
1155 | } while (dwRetries++ < RESTART_RETRIES && (HRESULT_FROM_WIN32(ERROR_MACHINE_LOCKED) == hr || HRESULT_FROM_WIN32(ERROR_NOT_READY) == hr)); | 1159 | } while (dwRetries++ < RESTART_RETRIES && (HRESULT_FROM_WIN32(ERROR_MACHINE_LOCKED) == hr || HRESULT_FROM_WIN32(ERROR_NOT_READY) == hr)); |
1156 | ExitOnRootFailure(hr, "Failed to schedule restart."); | 1160 | ExitOnRootFailure(hr, "Failed to schedule restart."); |
1157 | 1161 | ||
1162 | CoreUpdateRestartState(pEngineState, BURN_RESTART_STATE_REQUESTED); | ||
1163 | |||
1164 | // Give the UI thread approximately 15 seconds to get the WM_QUERYENDSESSION message. | ||
1165 | for (DWORD i = 0; i < 60; ++i) | ||
1166 | { | ||
1167 | if (!::IsWindow(pEngineState->hMessageWindow)) | ||
1168 | { | ||
1169 | ExitFunction(); | ||
1170 | } | ||
1171 | |||
1172 | if (BURN_RESTART_STATE_REQUESTED < pEngineState->restartState) | ||
1173 | { | ||
1174 | break; | ||
1175 | } | ||
1176 | |||
1177 | ::Sleep(250); | ||
1178 | } | ||
1179 | |||
1180 | if (BURN_RESTART_STATE_INITIATING > pEngineState->restartState) | ||
1181 | { | ||
1182 | LogId(REPORT_WARNING, MSG_RESTART_BLOCKED); | ||
1183 | ExitFunction(); | ||
1184 | } | ||
1185 | |||
1186 | // Give the UI thread the chance to process the WM_ENDSESSION message. | ||
1187 | for (;;) | ||
1188 | { | ||
1189 | if (!::IsWindow(pEngineState->hMessageWindow) || BURN_RESTART_STATE_INITIATING < pEngineState->restartState) | ||
1190 | { | ||
1191 | break; | ||
1192 | } | ||
1193 | |||
1194 | ::Sleep(250); | ||
1195 | } | ||
1196 | |||
1158 | LExit: | 1197 | LExit: |
1159 | ReleaseHandle(hProcessToken); | 1198 | ReleaseHandle(hProcessToken); |
1160 | return hr; | 1199 | return hr; |