summaryrefslogtreecommitdiff
path: root/src/burn/engine/engine.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/burn/engine/engine.cpp')
-rw-r--r--src/burn/engine/engine.cpp85
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(
72static HRESULT WaitForUnelevatedLoggingThread( 72static HRESULT WaitForUnelevatedLoggingThread(
73 __in HANDLE hUnelevatedLoggingThread 73 __in HANDLE hUnelevatedLoggingThread
74 ); 74 );
75static HRESULT Restart(); 75static HRESULT Restart(
76 __in BURN_ENGINE_STATE* pEngineState
77 );
76static void CALLBACK BurnTraceError( 78static 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
276LExit: 275LExit:
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
1115static HRESULT Restart() 1115static 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
1158LExit: 1197LExit:
1159 ReleaseHandle(hProcessToken); 1198 ReleaseHandle(hProcessToken);
1160 return hr; 1199 return hr;