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
)
81 INT iSeconds
, iMinutes
, iHours
, iDays
;
83 if (!pShutdownParams
->bShuttingDown
)
85 /* Shutdown has been cancelled, close the dialog and bail out */
86 EndDialog(hwndDlg
, 0);
90 if (pShutdownParams
->dwTimeout
< SECONDS_PER_DAY
)
92 iSeconds
= (INT
)pShutdownParams
->dwTimeout
;
93 iHours
= iSeconds
/ 3600;
94 iSeconds
-= iHours
* 3600;
95 iMinutes
= iSeconds
/ 60;
96 iSeconds
-= iMinutes
* 60;
98 swprintf(szBuffer
, L
"%02d:%02d:%02d", iHours
, iMinutes
, iSeconds
);
102 iDays
= (INT
)(pShutdownParams
->dwTimeout
/ SECONDS_PER_DAY
);
103 swprintf(szBuffer
, L
"%d days", iDays
); // FIXME: Localize
106 SetDlgItemTextW(hwndDlg
, IDC_SYSSHUTDOWNTIMELEFT
, szBuffer
);
108 if (pShutdownParams
->dwTimeout
== 0)
110 /* Close the dialog and perform the system shutdown */
111 EndDialog(hwndDlg
, 0);
112 DoSystemShutdown(pShutdownParams
);
116 pShutdownParams
->dwTimeout
--;
129 PSYS_SHUTDOWN_PARAMS pShutdownParams
;
131 pShutdownParams
= (PSYS_SHUTDOWN_PARAMS
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
137 pShutdownParams
= (PSYS_SHUTDOWN_PARAMS
)lParam
;
138 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)pShutdownParams
);
140 if (pShutdownParams
->pszMessage
)
142 SetDlgItemTextW(hwndDlg
,
143 IDC_SYSSHUTDOWNMESSAGE
,
144 pShutdownParams
->pszMessage
);
147 DeleteMenu(GetSystemMenu(hwndDlg
, FALSE
), SC_CLOSE
, MF_BYCOMMAND
);
148 SetWindowPos(hwndDlg
, HWND_TOPMOST
, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
);
150 PostMessage(hwndDlg
, WM_TIMER
, 0, 0);
151 SetTimer(hwndDlg
, SHUTDOWN_TIMER_ID
, 1000, NULL
);
155 /* NOTE: Do not handle WM_CLOSE */
157 KillTimer(hwndDlg
, SHUTDOWN_TIMER_ID
);
161 OnTimer(hwndDlg
, pShutdownParams
);
175 InitiateSystemShutdownThread(
178 PSYS_SHUTDOWN_PARAMS pShutdownParams
;
181 pShutdownParams
= (PSYS_SHUTDOWN_PARAMS
)lpParameter
;
183 status
= DialogBoxParamW(hAppInstance
,
184 MAKEINTRESOURCEW(IDD_SYSSHUTDOWN
),
187 (LPARAM
)pShutdownParams
);
189 if (pShutdownParams
->pszMessage
)
191 HeapFree(GetProcessHeap(), 0, pShutdownParams
->pszMessage
);
192 pShutdownParams
->pszMessage
= NULL
;
196 return ERROR_SUCCESS
;
198 pShutdownParams
->bShuttingDown
= FALSE
;
199 return GetLastError();
204 TerminateSystemShutdown(VOID
)
206 if (_InterlockedCompareExchange8((volatile char*)&g_ShutdownParams
.bShuttingDown
, FALSE
, TRUE
) == FALSE
)
207 return ERROR_NO_SHUTDOWN_IN_PROGRESS
;
209 return ERROR_SUCCESS
;
215 PUNICODE_STRING lpMessage
,
217 BOOLEAN bForceAppsClosed
,
218 BOOLEAN bRebootAfterShutdown
,
223 /* Fail if the timeout is 10 years or more */
224 if (dwTimeout
>= SECONDS_PER_DECADE
)
225 return ERROR_INVALID_PARAMETER
;
227 if (_InterlockedCompareExchange8((volatile char*)&g_ShutdownParams
.bShuttingDown
, TRUE
, FALSE
) == TRUE
)
228 return ERROR_SHUTDOWN_IN_PROGRESS
;
230 if (lpMessage
&& lpMessage
->Length
&& lpMessage
->Buffer
)
232 g_ShutdownParams
.pszMessage
= HeapAlloc(GetProcessHeap(),
234 lpMessage
->Length
+ sizeof(UNICODE_NULL
));
235 if (g_ShutdownParams
.pszMessage
== NULL
)
237 g_ShutdownParams
.bShuttingDown
= FALSE
;
238 return GetLastError();
241 wcsncpy(g_ShutdownParams
.pszMessage
,
243 lpMessage
->Length
/ sizeof(WCHAR
));
247 g_ShutdownParams
.pszMessage
= NULL
;
250 g_ShutdownParams
.dwTimeout
= dwTimeout
;
251 g_ShutdownParams
.bForceAppsClosed
= bForceAppsClosed
;
252 g_ShutdownParams
.bRebootAfterShutdown
= bRebootAfterShutdown
;
253 g_ShutdownParams
.dwReason
= dwReason
;
255 /* If dwTimeout is zero perform an immediate system shutdown, otherwise display the countdown shutdown dialog */
256 if (g_ShutdownParams
.dwTimeout
== 0)
258 if (DoSystemShutdown(&g_ShutdownParams
))
259 return ERROR_SUCCESS
;
263 hThread
= CreateThread(NULL
, 0, InitiateSystemShutdownThread
, (PVOID
)&g_ShutdownParams
, 0, NULL
);
266 CloseHandle(hThread
);
267 return ERROR_SUCCESS
;
271 if (g_ShutdownParams
.pszMessage
)
273 HeapFree(GetProcessHeap(), 0, g_ShutdownParams
.pszMessage
);
274 g_ShutdownParams
.pszMessage
= NULL
;
277 g_ShutdownParams
.bShuttingDown
= FALSE
;
278 return GetLastError();