aboutsummaryrefslogtreecommitdiff
path: root/src/burn/engine/uithread.cpp
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2022-09-02 16:11:35 -0500
committerSean Hall <r.sean.hall@gmail.com>2022-09-03 15:29:26 -0500
commiteea6121f388197435529922b3cb13d3631afb9a8 (patch)
tree5740f0ff69f7e4aa9a7e8a92ff1f6fde0c1ae8d7 /src/burn/engine/uithread.cpp
parente263e6bca03d783ece2f2dc86345dcdfc4b9776d (diff)
downloadwix-eea6121f388197435529922b3cb13d3631afb9a8.tar.gz
wix-eea6121f388197435529922b3cb13d3631afb9a8.tar.bz2
wix-eea6121f388197435529922b3cb13d3631afb9a8.zip
Delay closing Burn's UI thread so that it can log the bundle's restart.
Diffstat (limited to '')
-rw-r--r--src/burn/engine/uithread.cpp62
1 files changed, 48 insertions, 14 deletions
diff --git a/src/burn/engine/uithread.cpp b/src/burn/engine/uithread.cpp
index 26a9b723..673111f8 100644
--- a/src/burn/engine/uithread.cpp
+++ b/src/burn/engine/uithread.cpp
@@ -46,6 +46,11 @@ HRESULT UiCreateMessageWindow(
46 HANDLE rgWaitHandles[2] = { }; 46 HANDLE rgWaitHandles[2] = { };
47 UITHREAD_CONTEXT context = { }; 47 UITHREAD_CONTEXT context = { };
48 48
49 // Try to make this process the first one to receive WM_QUERYENDSESSION.
50 // When blocking shutdown during Apply, this prevents other applications from being closed even though the restart will be blocked.
51 // When initiating a restart, this makes it reasonable to assume WM_QUERYENDSESSION will be received quickly because otherwise other applications could delay indefinitely.
52 ::SetProcessShutdownParameters(0x3FF, 0);
53
49 // Create event to signal after the UI thread / window is initialized. 54 // Create event to signal after the UI thread / window is initialized.
50 rgWaitHandles[0] = ::CreateEventW(NULL, TRUE, FALSE, NULL); 55 rgWaitHandles[0] = ::CreateEventW(NULL, TRUE, FALSE, NULL);
51 ExitOnNullWithLastError(rgWaitHandles[0], hr, "Failed to create initialization event."); 56 ExitOnNullWithLastError(rgWaitHandles[0], hr, "Failed to create initialization event.");
@@ -79,10 +84,6 @@ void UiCloseMessageWindow(
79 if (::IsWindow(pEngineState->hMessageWindow)) 84 if (::IsWindow(pEngineState->hMessageWindow))
80 { 85 {
81 ::PostMessageW(pEngineState->hMessageWindow, WM_CLOSE, 0, 0); 86 ::PostMessageW(pEngineState->hMessageWindow, WM_CLOSE, 0, 0);
82
83 // Give the window 15 seconds to close because if it stays open it can prevent
84 // the engine from starting a reboot (should a reboot actually be necessary).
85 ::WaitForSingleObject(pEngineState->hMessageWindowThread, 15 * 1000);
86 } 87 }
87} 88}
88 89
@@ -180,23 +181,56 @@ static LRESULT CALLBACK WndProc(
180 181
181 case WM_QUERYENDSESSION: 182 case WM_QUERYENDSESSION:
182 { 183 {
183 DWORD dwEndSession = static_cast<DWORD>(lParam); 184 BOOL fCritical = ENDSESSION_CRITICAL & lParam;
184 BOOL fCritical = ENDSESSION_CRITICAL & dwEndSession; 185 BOOL fAllowed = FALSE;
185 BOOL fCancel = FALSE;
186 BOOL fRet = FALSE;
187 186
188 // Always block shutdown during apply.
189 UITHREAD_INFO* pInfo = reinterpret_cast<UITHREAD_INFO*>(::GetWindowLongPtrW(hWnd, GWLP_USERDATA)); 187 UITHREAD_INFO* pInfo = reinterpret_cast<UITHREAD_INFO*>(::GetWindowLongPtrW(hWnd, GWLP_USERDATA));
190 if (pInfo->pEngineState->plan.fApplying) 188 if (!pInfo->pEngineState->plan.fApplying && // always block shutdown during apply.
189 !fCritical) // always block critical shutdowns to receive the WM_ENDSESSION message.
191 { 190 {
192 fCancel = TRUE; 191 fAllowed = TRUE;
193 } 192 }
194 193
194 CoreUpdateRestartState(pInfo->pEngineState, BURN_RESTART_STATE_INITIATING);
195 pInfo->pEngineState->fCriticalShutdownInitiated |= fCritical; 195 pInfo->pEngineState->fCriticalShutdownInitiated |= fCritical;
196 196
197 fRet = !fCancel; 197 LogId(REPORT_STANDARD, MSG_SYSTEM_SHUTDOWN_REQUEST, LoggingBoolToString(fAllowed), LoggingBoolToString(pInfo->fElevatedEngine), LoggingBoolToString(fCritical), LoggingBoolToString(lParam & ENDSESSION_LOGOFF), LoggingBoolToString(lParam & ENDSESSION_CLOSEAPP));
198 LogId(REPORT_STANDARD, MSG_SYSTEM_SHUTDOWN, LoggingBoolToString(fCritical), LoggingBoolToString(pInfo->fElevatedEngine), LoggingBoolToString(fRet)); 198 LogFlush();
199 return fRet; 199 return fAllowed;
200 }
201
202 case WM_ENDSESSION:
203 {
204 UITHREAD_INFO* pInfo = reinterpret_cast<UITHREAD_INFO*>(::GetWindowLongPtrW(hWnd, GWLP_USERDATA));
205 BOOL fAllowed = 0 != wParam;
206
207 LogId(REPORT_STANDARD, MSG_SYSTEM_SHUTDOWN_RESULT, LoggingBoolToString(fAllowed), LoggingBoolToString(pInfo->fElevatedEngine), LoggingBoolToString(lParam & ENDSESSION_CRITICAL), LoggingBoolToString(lParam & ENDSESSION_LOGOFF), LoggingBoolToString(lParam & ENDSESSION_CLOSEAPP));
208
209 if (fAllowed)
210 {
211 // Windows will shutdown the process as soon as we return from this message.
212 // https://docs.microsoft.com/en-us/previous-versions/windows/desktop/ms700677(v=vs.85)
213
214 // Give Apply approximately 20 seconds to complete.
215 for (DWORD i = 0; i < 80; ++i)
216 {
217 if (!pInfo->pEngineState->plan.fApplying)
218 {
219 break;
220 }
221
222 ::Sleep(250);
223 }
224
225 LogStringWorkRaw("=======================================\r\n");
226
227 // Close the log to try to make sure everything is flushed to disk.
228 LogClose(FALSE);
229 }
230
231 CoreUpdateRestartState(pInfo->pEngineState, fAllowed ? BURN_RESTART_STATE_INITIATED : BURN_RESTART_STATE_BLOCKED);
232
233 return 0;
200 } 234 }
201 235
202 case WM_DESTROY: 236 case WM_DESTROY: