diff options
Diffstat (limited to '')
| -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; |
