https://git.reactos.org/?p=reactos.git;a=commitdiff;h=cb20bf8c903f42b64bb397...
commit cb20bf8c903f42b64bb397477b857b5cf4e4eb71 Author: Hermès Bélusca-Maïto hermes.belusca-maito@reactos.org AuthorDate: Sat Apr 28 18:14:53 2018 +0200 Commit: Hermès Bélusca-Maïto hermes.belusca-maito@reactos.org CommitDate: Sun Apr 29 01:02:05 2018 +0200
[WINLOGON] Usability enhancement for the RPC SystemShutdown functionality.
- Perform an immediate system shutdown if the timeout is zero, otherwise display the countdown shutdown dialog. - Cleanup pShutdownParams->pszMessage as soon as the dialog goes away. - It actually appears (tested on Windows 2000 and 2003) that sending WM_CLOSE messages from a user-mode app to the shutdown dialog really do nothing (and in particular does not cancel the shutdown!), so modify the code to take this fact into account. --- base/system/winlogon/shutdown.c | 98 +++++++++++++++++++++++++++-------------- 1 file changed, 65 insertions(+), 33 deletions(-)
diff --git a/base/system/winlogon/shutdown.c b/base/system/winlogon/shutdown.c index 42452ca067..d3b86aa140 100644 --- a/base/system/winlogon/shutdown.c +++ b/base/system/winlogon/shutdown.c @@ -30,7 +30,6 @@ typedef struct _SYS_SHUTDOWN_PARAMS BOOLEAN bForceAppsClosed; DWORD dwReason;
- HWND hShutdownDialog; BOOLEAN bShuttingDown; } SYS_SHUTDOWN_PARAMS, *PSYS_SHUTDOWN_PARAMS;
@@ -42,6 +41,36 @@ SYS_SHUTDOWN_PARAMS g_ShutdownParams;
/* FUNCTIONS *****************************************************************/
+static +BOOL +DoSystemShutdown( + IN PSYS_SHUTDOWN_PARAMS pShutdownParams) +{ + BOOL Success; + + if (pShutdownParams->pszMessage) + { + HeapFree(GetProcessHeap(), 0, pShutdownParams->pszMessage); + pShutdownParams->pszMessage = NULL; + } + + /* If shutdown has been cancelled, bail out now */ + if (!pShutdownParams->bShuttingDown) + return TRUE; + + Success = ExitWindowsEx((pShutdownParams->bRebootAfterShutdown ? EWX_REBOOT : EWX_SHUTDOWN) | + (pShutdownParams->bForceAppsClosed ? EWX_FORCE : 0), + pShutdownParams->dwReason); + if (!Success) + { + /* Something went wrong, cancel shutdown */ + pShutdownParams->bShuttingDown = FALSE; + } + + return Success; +} + + static VOID OnTimer( @@ -51,6 +80,13 @@ OnTimer( WCHAR szBuffer[12]; INT iSeconds, iMinutes, iHours, iDays;
+ if (!pShutdownParams->bShuttingDown) + { + /* Shutdown has been cancelled, close the dialog and bail out */ + EndDialog(hwndDlg, 0); + return; + } + if (pShutdownParams->dwTimeout < SECONDS_PER_DAY) { iSeconds = (INT)pShutdownParams->dwTimeout; @@ -64,17 +100,17 @@ OnTimer( else { iDays = (INT)(pShutdownParams->dwTimeout / SECONDS_PER_DAY); - swprintf(szBuffer, L"%d days", iDays); + swprintf(szBuffer, L"%d days", iDays); // FIXME: Localize }
SetDlgItemTextW(hwndDlg, IDC_SYSSHUTDOWNTIMELEFT, szBuffer);
if (pShutdownParams->dwTimeout == 0) { - PostMessage(hwndDlg, WM_CLOSE, 0, 0); - ExitWindowsEx((pShutdownParams->bRebootAfterShutdown ? EWX_REBOOT : EWX_SHUTDOWN) | - (pShutdownParams->bForceAppsClosed ? EWX_FORCE : 0), - pShutdownParams->dwReason); + /* Close the dialog and perform the system shutdown */ + EndDialog(hwndDlg, 0); + DoSystemShutdown(pShutdownParams); + return; }
pShutdownParams->dwTimeout--; @@ -97,11 +133,10 @@ ShutdownDialogProc( switch (uMsg) { case WM_INITDIALOG: + { pShutdownParams = (PSYS_SHUTDOWN_PARAMS)lParam; SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pShutdownParams);
- pShutdownParams->hShutdownDialog = hwndDlg; - if (pShutdownParams->pszMessage) { SetDlgItemTextW(hwndDlg, @@ -109,26 +144,17 @@ ShutdownDialogProc( pShutdownParams->pszMessage); }
- RemoveMenu(GetSystemMenu(hwndDlg, FALSE), SC_CLOSE, MF_BYCOMMAND); + DeleteMenu(GetSystemMenu(hwndDlg, FALSE), SC_CLOSE, MF_BYCOMMAND); SetWindowPos(hwndDlg, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
PostMessage(hwndDlg, WM_TIMER, 0, 0); SetTimer(hwndDlg, SHUTDOWN_TIMER_ID, 1000, NULL); break; + }
- case WM_CLOSE: - pShutdownParams->hShutdownDialog = NULL; - pShutdownParams->bShuttingDown = FALSE; - + /* NOTE: Do not handle WM_CLOSE */ + case WM_DESTROY: KillTimer(hwndDlg, SHUTDOWN_TIMER_ID); - - if (pShutdownParams->pszMessage) - { - HeapFree(GetProcessHeap(), 0, pShutdownParams->pszMessage); - pShutdownParams->pszMessage = NULL; - } - - EndDialog(hwndDlg, 0); break;
case WM_TIMER: @@ -159,10 +185,6 @@ InitiateSystemShutdownThread( NULL, ShutdownDialogProc, (LPARAM)pShutdownParams); - if (status >= 0) - { - return ERROR_SUCCESS; - }
if (pShutdownParams->pszMessage) { @@ -170,8 +192,10 @@ InitiateSystemShutdownThread( pShutdownParams->pszMessage = NULL; }
- pShutdownParams->bShuttingDown = FALSE; + if (status >= 0) + return ERROR_SUCCESS;
+ pShutdownParams->bShuttingDown = FALSE; return GetLastError(); }
@@ -179,10 +203,10 @@ InitiateSystemShutdownThread( DWORD TerminateSystemShutdown(VOID) { - if (g_ShutdownParams.bShuttingDown == FALSE) + if (_InterlockedCompareExchange8((volatile char*)&g_ShutdownParams.bShuttingDown, FALSE, TRUE) == FALSE) return ERROR_NO_SHUTDOWN_IN_PROGRESS;
- return PostMessage(g_ShutdownParams.hShutdownDialog, WM_CLOSE, 0, 0) ? ERROR_SUCCESS : GetLastError(); + return ERROR_SUCCESS; }
@@ -228,11 +252,20 @@ StartSystemShutdown( g_ShutdownParams.bRebootAfterShutdown = bRebootAfterShutdown; g_ShutdownParams.dwReason = dwReason;
- hThread = CreateThread(NULL, 0, InitiateSystemShutdownThread, (PVOID)&g_ShutdownParams, 0, NULL); - if (hThread) + /* If dwTimeout is zero perform an immediate system shutdown, otherwise display the countdown shutdown dialog */ + if (g_ShutdownParams.dwTimeout == 0) { - CloseHandle(hThread); - return ERROR_SUCCESS; + if (DoSystemShutdown(&g_ShutdownParams)) + return ERROR_SUCCESS; + } + else + { + hThread = CreateThread(NULL, 0, InitiateSystemShutdownThread, (PVOID)&g_ShutdownParams, 0, NULL); + if (hThread) + { + CloseHandle(hThread); + return ERROR_SUCCESS; + } }
if (g_ShutdownParams.pszMessage) @@ -242,7 +275,6 @@ StartSystemShutdown( }
g_ShutdownParams.bShuttingDown = FALSE; - return GetLastError(); }