https://git.reactos.org/?p=reactos.git;a=commitdiff;h=cb20bf8c903f42b64bb39…
commit cb20bf8c903f42b64bb397477b857b5cf4e4eb71
Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
AuthorDate: Sat Apr 28 18:14:53 2018 +0200
Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)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();
}