diff options
author | Sean Hall <r.sean.hall@gmail.com> | 2022-09-02 16:11:35 -0500 |
---|---|---|
committer | Sean Hall <r.sean.hall@gmail.com> | 2022-09-03 15:29:26 -0500 |
commit | eea6121f388197435529922b3cb13d3631afb9a8 (patch) | |
tree | 5740f0ff69f7e4aa9a7e8a92ff1f6fde0c1ae8d7 /src/burn/engine/uithread.cpp | |
parent | e263e6bca03d783ece2f2dc86345dcdfc4b9776d (diff) | |
download | wix-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.cpp | 62 |
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: |