1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS Winlogon 4 * FILE: base/system/winlogon/shutdown.c 5 * PURPOSE: System shutdown dialog 6 * PROGRAMMERS: alpha5056 <alpha5056@users.noreply.github.com> 7 */ 8 9 /* INCLUDES ******************************************************************/ 10 11 #include "winlogon.h" 12 13 #include <rpc.h> 14 #include <winreg_s.h> 15 16 /* DEFINES *******************************************************************/ 17 18 #define SHUTDOWN_TIMER_ID 2000 19 #define SECONDS_PER_DAY 86400 20 #define SECONDS_PER_DECADE 315360000 21 22 23 /* STRUCTS *******************************************************************/ 24 25 typedef struct _SYS_SHUTDOWN_PARAMS 26 { 27 PWSTR pszMessage; 28 ULONG dwTimeout; 29 BOOLEAN bRebootAfterShutdown; 30 BOOLEAN bForceAppsClosed; 31 DWORD dwReason; 32 33 BOOLEAN bShuttingDown; 34 } SYS_SHUTDOWN_PARAMS, *PSYS_SHUTDOWN_PARAMS; 35 36 37 /* GLOBALS *******************************************************************/ 38 39 SYS_SHUTDOWN_PARAMS g_ShutdownParams; 40 41 42 /* FUNCTIONS *****************************************************************/ 43 44 static 45 BOOL 46 DoSystemShutdown( 47 IN PSYS_SHUTDOWN_PARAMS pShutdownParams) 48 { 49 BOOL Success; 50 51 if (pShutdownParams->pszMessage) 52 { 53 HeapFree(GetProcessHeap(), 0, pShutdownParams->pszMessage); 54 pShutdownParams->pszMessage = NULL; 55 } 56 57 /* If shutdown has been cancelled, bail out now */ 58 if (!pShutdownParams->bShuttingDown) 59 return TRUE; 60 61 Success = ExitWindowsEx((pShutdownParams->bRebootAfterShutdown ? EWX_REBOOT : EWX_SHUTDOWN) | 62 (pShutdownParams->bForceAppsClosed ? EWX_FORCE : 0), 63 pShutdownParams->dwReason); 64 if (!Success) 65 { 66 /* Something went wrong, cancel shutdown */ 67 pShutdownParams->bShuttingDown = FALSE; 68 } 69 70 return Success; 71 } 72 73 74 static 75 VOID 76 OnTimer( 77 HWND hwndDlg, 78 PSYS_SHUTDOWN_PARAMS pShutdownParams) 79 { 80 WCHAR szFormatBuffer[32]; 81 WCHAR szBuffer[32]; 82 INT iSeconds, iMinutes, iHours, iDays; 83 84 if (!pShutdownParams->bShuttingDown) 85 { 86 /* Shutdown has been cancelled, close the dialog and bail out */ 87 EndDialog(hwndDlg, 0); 88 return; 89 } 90 91 if (pShutdownParams->dwTimeout < SECONDS_PER_DAY) 92 { 93 iSeconds = (INT)pShutdownParams->dwTimeout; 94 iHours = iSeconds / 3600; 95 iSeconds -= iHours * 3600; 96 iMinutes = iSeconds / 60; 97 iSeconds -= iMinutes * 60; 98 99 LoadStringW(hAppInstance, IDS_TIMEOUTSHORTFORMAT, szFormatBuffer, ARRAYSIZE(szFormatBuffer)); 100 swprintf(szBuffer, szFormatBuffer, iHours, iMinutes, iSeconds); 101 } 102 else 103 { 104 iDays = (INT)(pShutdownParams->dwTimeout / SECONDS_PER_DAY); 105 106 LoadStringW(hAppInstance, IDS_TIMEOUTLONGFORMAT, szFormatBuffer, ARRAYSIZE(szFormatBuffer)); 107 swprintf(szBuffer, szFormatBuffer, iDays); 108 } 109 110 SetDlgItemTextW(hwndDlg, IDC_SYSSHUTDOWNTIMELEFT, szBuffer); 111 112 if (pShutdownParams->dwTimeout == 0) 113 { 114 /* Close the dialog and perform the system shutdown */ 115 EndDialog(hwndDlg, 0); 116 DoSystemShutdown(pShutdownParams); 117 return; 118 } 119 120 pShutdownParams->dwTimeout--; 121 } 122 123 124 static 125 INT_PTR 126 CALLBACK 127 ShutdownDialogProc( 128 HWND hwndDlg, 129 UINT uMsg, 130 WPARAM wParam, 131 LPARAM lParam) 132 { 133 PSYS_SHUTDOWN_PARAMS pShutdownParams; 134 135 pShutdownParams = (PSYS_SHUTDOWN_PARAMS)GetWindowLongPtr(hwndDlg, DWLP_USER); 136 137 switch (uMsg) 138 { 139 case WM_INITDIALOG: 140 { 141 pShutdownParams = (PSYS_SHUTDOWN_PARAMS)lParam; 142 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pShutdownParams); 143 144 if (pShutdownParams->pszMessage) 145 { 146 SetDlgItemTextW(hwndDlg, 147 IDC_SYSSHUTDOWNMESSAGE, 148 pShutdownParams->pszMessage); 149 } 150 151 DeleteMenu(GetSystemMenu(hwndDlg, FALSE), SC_CLOSE, MF_BYCOMMAND); 152 SetWindowPos(hwndDlg, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE); 153 154 PostMessage(hwndDlg, WM_TIMER, 0, 0); 155 SetTimer(hwndDlg, SHUTDOWN_TIMER_ID, 1000, NULL); 156 break; 157 } 158 159 /* NOTE: Do not handle WM_CLOSE */ 160 case WM_DESTROY: 161 KillTimer(hwndDlg, SHUTDOWN_TIMER_ID); 162 break; 163 164 case WM_TIMER: 165 OnTimer(hwndDlg, pShutdownParams); 166 break; 167 168 default: 169 return FALSE; 170 } 171 172 return TRUE; 173 } 174 175 176 static 177 DWORD 178 WINAPI 179 InitiateSystemShutdownThread( 180 LPVOID lpParameter) 181 { 182 PSYS_SHUTDOWN_PARAMS pShutdownParams; 183 INT_PTR status; 184 185 pShutdownParams = (PSYS_SHUTDOWN_PARAMS)lpParameter; 186 187 status = DialogBoxParamW(hAppInstance, 188 MAKEINTRESOURCEW(IDD_SYSSHUTDOWN), 189 NULL, 190 ShutdownDialogProc, 191 (LPARAM)pShutdownParams); 192 193 if (pShutdownParams->pszMessage) 194 { 195 HeapFree(GetProcessHeap(), 0, pShutdownParams->pszMessage); 196 pShutdownParams->pszMessage = NULL; 197 } 198 199 if (status >= 0) 200 return ERROR_SUCCESS; 201 202 pShutdownParams->bShuttingDown = FALSE; 203 return GetLastError(); 204 } 205 206 207 DWORD 208 TerminateSystemShutdown(VOID) 209 { 210 if (_InterlockedCompareExchange8((volatile char*)&g_ShutdownParams.bShuttingDown, FALSE, TRUE) == FALSE) 211 return ERROR_NO_SHUTDOWN_IN_PROGRESS; 212 213 return ERROR_SUCCESS; 214 } 215 216 217 DWORD 218 StartSystemShutdown( 219 PUNICODE_STRING lpMessage, 220 ULONG dwTimeout, 221 BOOLEAN bForceAppsClosed, 222 BOOLEAN bRebootAfterShutdown, 223 ULONG dwReason) 224 { 225 HANDLE hThread; 226 227 /* Fail if the timeout is 10 years or more */ 228 if (dwTimeout >= SECONDS_PER_DECADE) 229 return ERROR_INVALID_PARAMETER; 230 231 if (_InterlockedCompareExchange8((volatile char*)&g_ShutdownParams.bShuttingDown, TRUE, FALSE) == TRUE) 232 return ERROR_SHUTDOWN_IN_PROGRESS; 233 234 if (lpMessage && lpMessage->Length && lpMessage->Buffer) 235 { 236 g_ShutdownParams.pszMessage = HeapAlloc(GetProcessHeap(), 237 HEAP_ZERO_MEMORY, 238 lpMessage->Length + sizeof(UNICODE_NULL)); 239 if (g_ShutdownParams.pszMessage == NULL) 240 { 241 g_ShutdownParams.bShuttingDown = FALSE; 242 return GetLastError(); 243 } 244 245 wcsncpy(g_ShutdownParams.pszMessage, 246 lpMessage->Buffer, 247 lpMessage->Length / sizeof(WCHAR)); 248 } 249 else 250 { 251 g_ShutdownParams.pszMessage = NULL; 252 } 253 254 g_ShutdownParams.dwTimeout = dwTimeout; 255 g_ShutdownParams.bForceAppsClosed = bForceAppsClosed; 256 g_ShutdownParams.bRebootAfterShutdown = bRebootAfterShutdown; 257 g_ShutdownParams.dwReason = dwReason; 258 259 /* If dwTimeout is zero perform an immediate system shutdown, otherwise display the countdown shutdown dialog */ 260 if (g_ShutdownParams.dwTimeout == 0) 261 { 262 if (DoSystemShutdown(&g_ShutdownParams)) 263 return ERROR_SUCCESS; 264 } 265 else 266 { 267 hThread = CreateThread(NULL, 0, InitiateSystemShutdownThread, (PVOID)&g_ShutdownParams, 0, NULL); 268 if (hThread) 269 { 270 CloseHandle(hThread); 271 return ERROR_SUCCESS; 272 } 273 } 274 275 if (g_ShutdownParams.pszMessage) 276 { 277 HeapFree(GetProcessHeap(), 0, g_ShutdownParams.pszMessage); 278 g_ShutdownParams.pszMessage = NULL; 279 } 280 281 g_ShutdownParams.bShuttingDown = FALSE; 282 return GetLastError(); 283 } 284 285 /* EOF */ 286