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>
9 /* INCLUDES ******************************************************************/
16 /* DEFINES *******************************************************************/
18 #define SHUTDOWN_TIMER_ID 2000
19 #define SECONDS_PER_DAY 86400
20 #define SECONDS_PER_DECADE 315360000
23 /* STRUCTS *******************************************************************/
25 typedef struct _SYS_SHUTDOWN_PARAMS
29 BOOLEAN bRebootAfterShutdown
;
30 BOOLEAN bForceAppsClosed
;
33 BOOLEAN bShuttingDown
;
34 } SYS_SHUTDOWN_PARAMS
, *PSYS_SHUTDOWN_PARAMS
;
37 /* GLOBALS *******************************************************************/
39 SYS_SHUTDOWN_PARAMS g_ShutdownParams
;
42 /* FUNCTIONS *****************************************************************/
47 IN PSYS_SHUTDOWN_PARAMS pShutdownParams
)
51 if (pShutdownParams
->pszMessage
)
53 HeapFree(GetProcessHeap(), 0, pShutdownParams
->pszMessage
);
54 pShutdownParams
->pszMessage
= NULL
;
57 /* If shutdown has been cancelled, bail out now */
58 if (!pShutdownParams
->bShuttingDown
)
61 Success
= ExitWindowsEx((pShutdownParams
->bRebootAfterShutdown
? EWX_REBOOT
: EWX_SHUTDOWN
) |
62 (pShutdownParams
->bForceAppsClosed
? EWX_FORCE
: 0),
63 pShutdownParams
->dwReason
);
66 /* Something went wrong, cancel shutdown */
67 pShutdownParams
->bShuttingDown
= FALSE
;
78 PSYS_SHUTDOWN_PARAMS pShutdownParams
)
80 WCHAR szFormatBuffer
[32];
82 INT iSeconds
, iMinutes
, iHours
, iDays
;
84 if (!pShutdownParams
->bShuttingDown
)
86 /* Shutdown has been cancelled, close the dialog and bail out */
87 EndDialog(hwndDlg
, 0);
91 if (pShutdownParams
->dwTimeout
< SECONDS_PER_DAY
)
93 iSeconds
= (INT
)pShutdownParams
->dwTimeout
;
94 iHours
= iSeconds
/ 3600;
95 iSeconds
-= iHours
* 3600;
96 iMinutes
= iSeconds
/ 60;
97 iSeconds
-= iMinutes
* 60;
99 LoadStringW(hAppInstance
, IDS_TIMEOUTSHORTFORMAT
, szFormatBuffer
, ARRAYSIZE(szFormatBuffer
));
100 swprintf(szBuffer
, szFormatBuffer
, iHours
, iMinutes
, iSeconds
);
104 iDays
= (INT
)(pShutdownParams
->dwTimeout
/ SECONDS_PER_DAY
);
106 LoadStringW(hAppInstance
, IDS_TIMEOUTLONGFORMAT
, szFormatBuffer
, ARRAYSIZE(szFormatBuffer
));
107 swprintf(szBuffer
, szFormatBuffer
, iDays
);
110 SetDlgItemTextW(hwndDlg
, IDC_SYSSHUTDOWNTIMELEFT
, szBuffer
);
112 if (pShutdownParams
->dwTimeout
== 0)
114 /* Close the dialog and perform the system shutdown */
115 EndDialog(hwndDlg
, 0);
116 DoSystemShutdown(pShutdownParams
);
120 pShutdownParams
->dwTimeout
--;
133 PSYS_SHUTDOWN_PARAMS pShutdownParams
;
135 pShutdownParams
= (PSYS_SHUTDOWN_PARAMS
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
141 pShutdownParams
= (PSYS_SHUTDOWN_PARAMS
)lParam
;
142 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)pShutdownParams
);
144 if (pShutdownParams
->pszMessage
)
146 SetDlgItemTextW(hwndDlg
,
147 IDC_SYSSHUTDOWNMESSAGE
,
148 pShutdownParams
->pszMessage
);
151 DeleteMenu(GetSystemMenu(hwndDlg
, FALSE
), SC_CLOSE
, MF_BYCOMMAND
);
152 SetWindowPos(hwndDlg
, HWND_TOPMOST
, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
);
154 PostMessage(hwndDlg
, WM_TIMER
, 0, 0);
155 SetTimer(hwndDlg
, SHUTDOWN_TIMER_ID
, 1000, NULL
);
159 /* NOTE: Do not handle WM_CLOSE */
161 KillTimer(hwndDlg
, SHUTDOWN_TIMER_ID
);
165 OnTimer(hwndDlg
, pShutdownParams
);
179 InitiateSystemShutdownThread(
182 PSYS_SHUTDOWN_PARAMS pShutdownParams
;
185 pShutdownParams
= (PSYS_SHUTDOWN_PARAMS
)lpParameter
;
187 status
= DialogBoxParamW(hAppInstance
,
188 MAKEINTRESOURCEW(IDD_SYSSHUTDOWN
),
191 (LPARAM
)pShutdownParams
);
193 if (pShutdownParams
->pszMessage
)
195 HeapFree(GetProcessHeap(), 0, pShutdownParams
->pszMessage
);
196 pShutdownParams
->pszMessage
= NULL
;
200 return ERROR_SUCCESS
;
202 pShutdownParams
->bShuttingDown
= FALSE
;
203 return GetLastError();
208 TerminateSystemShutdown(VOID
)
210 if (_InterlockedCompareExchange8((volatile char*)&g_ShutdownParams
.bShuttingDown
, FALSE
, TRUE
) == FALSE
)
211 return ERROR_NO_SHUTDOWN_IN_PROGRESS
;
213 return ERROR_SUCCESS
;
219 PUNICODE_STRING lpMessage
,
221 BOOLEAN bForceAppsClosed
,
222 BOOLEAN bRebootAfterShutdown
,
227 /* Fail if the timeout is 10 years or more */
228 if (dwTimeout
>= SECONDS_PER_DECADE
)
229 return ERROR_INVALID_PARAMETER
;
231 if (_InterlockedCompareExchange8((volatile char*)&g_ShutdownParams
.bShuttingDown
, TRUE
, FALSE
) == TRUE
)
232 return ERROR_SHUTDOWN_IN_PROGRESS
;
234 if (lpMessage
&& lpMessage
->Length
&& lpMessage
->Buffer
)
236 g_ShutdownParams
.pszMessage
= HeapAlloc(GetProcessHeap(),
238 lpMessage
->Length
+ sizeof(UNICODE_NULL
));
239 if (g_ShutdownParams
.pszMessage
== NULL
)
241 g_ShutdownParams
.bShuttingDown
= FALSE
;
242 return GetLastError();
245 wcsncpy(g_ShutdownParams
.pszMessage
,
247 lpMessage
->Length
/ sizeof(WCHAR
));
251 g_ShutdownParams
.pszMessage
= NULL
;
254 g_ShutdownParams
.dwTimeout
= dwTimeout
;
255 g_ShutdownParams
.bForceAppsClosed
= bForceAppsClosed
;
256 g_ShutdownParams
.bRebootAfterShutdown
= bRebootAfterShutdown
;
257 g_ShutdownParams
.dwReason
= dwReason
;
259 /* If dwTimeout is zero perform an immediate system shutdown, otherwise display the countdown shutdown dialog */
260 if (g_ShutdownParams
.dwTimeout
== 0)
262 if (DoSystemShutdown(&g_ShutdownParams
))
263 return ERROR_SUCCESS
;
267 hThread
= CreateThread(NULL
, 0, InitiateSystemShutdownThread
, (PVOID
)&g_ShutdownParams
, 0, NULL
);
270 CloseHandle(hThread
);
271 return ERROR_SUCCESS
;
275 if (g_ShutdownParams
.pszMessage
)
277 HeapFree(GetProcessHeap(), 0, g_ShutdownParams
.pszMessage
);
278 g_ShutdownParams
.pszMessage
= NULL
;
281 g_ShutdownParams
.bShuttingDown
= FALSE
;
282 return GetLastError();