ReactOS 0.4.16-dev-297-gc569aee
shutdown.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS shutdown/logoff utility
4 * FILE: base/applications/shutdown/shutdown.c
5 * PURPOSE: Initiate logoff, shutdown or reboot of the system
6 */
7
8#include "precomp.h"
9
10#include <stdlib.h>
11#include <tchar.h>
12#include <powrprof.h>
13
14/*
15 * Takes the commandline arguments, and creates a
16 * struct which matches the arguments supplied.
17 */
18static DWORD
20{
21 int index;
22
23 if (!pOpts)
25
26 /* Reset all flags in struct */
27 pOpts->abort = FALSE;
28 pOpts->force = FALSE;
29 pOpts->logoff = FALSE;
30 pOpts->restart = FALSE;
31 pOpts->shutdown = FALSE;
32 pOpts->document_reason = FALSE;
33 pOpts->hibernate = FALSE;
34 pOpts->shutdown_delay = 30;
35 pOpts->remote_system = NULL;
36 pOpts->reason = ParseReasonCode(NULL); /* NOTE: NEVER use 0 here since it can delay the shutdown. */
37 pOpts->message = NULL;
38 pOpts->show_gui = FALSE;
39
40 /*
41 * Determine which flags the user has specified
42 * to the program so we can use them later.
43 */
44 for (index = 1; index < argc; index++)
45 {
46 if (argv[index][0] == L'-' || argv[index][0] == L'/')
47 {
48 switch (towlower(argv[index][1]))
49 {
50 case L'?': /* Help */
52 return ERROR_SUCCESS;
53
54 case L'a': /* Cancel delayed shutdown */
55 pOpts->abort = TRUE;
56 break;
57
58 case L'c': /* Comment on reason for shutdown */
59 if (index+1 >= argc)
60 return ERROR_INVALID_DATA;
61 if (!argv[index+1] || wcslen(argv[index+1]) <= 512)
62 {
63 pOpts->message = argv[index+1];
64 index++;
65 }
66 else
67 {
69 return ERROR_BAD_LENGTH;
70 }
71 break;
72
73 case L'd': /* Reason code [p|u:]xx:yy */
74 if (index+1 >= argc)
75 return ERROR_INVALID_DATA;
76 pOpts->reason = ParseReasonCode(argv[index+1]);
77 index++;
78 break;
79
80 case L'e': /* Documents reason for shutdown */
81 /* TODO: Determine what this flag does exactly. */
82 pOpts->document_reason = TRUE;
83 break;
84
85 case L'f': /* Force shutdown without warning */
86 pOpts->force = TRUE;
87 break;
88
89 case L'h': /* Hibernate the local computer */
90 pOpts->hibernate = TRUE;
91 break;
92
93 case L'i': /* Shows GUI version of the tool */
94 pOpts->show_gui = TRUE;
95 break;
96
97 case L'l': /* Logoff the current user */
98 pOpts->logoff = TRUE;
99 break;
100
101 case L'm': /* Target remote systems (UNC name/IP address) */
102 if (index+1 >= argc)
103 return ERROR_INVALID_DATA;
104 pOpts->remote_system = argv[index+1];
105 index++;
106 break;
107
108 case L'p': /* Turn off local computer with no warning/time-out */
109 pOpts->force = TRUE;
110 pOpts->shutdown_delay = 0;
111 break;
112
113 case L'r': /* Restart computer */
114 pOpts->restart = TRUE;
115 break;
116
117 case L's': /* Shutdown */
118 pOpts->shutdown = TRUE;
119 break;
120
121 case L't': /* Shutdown delay */
122 if (index+1 >= argc)
123 return ERROR_INVALID_DATA;
124 pOpts->shutdown_delay = _wtoi(argv[index+1]);
125 if (pOpts->shutdown_delay > 0)
126 pOpts->force = TRUE;
127 index++;
128 break;
129
130 default:
131 /* Unknown arguments will exit the program. */
133 return ERROR_SUCCESS;
134 }
135 }
136 }
137
138 return ERROR_SUCCESS;
139}
140
141static DWORD
142EnablePrivilege(LPCWSTR lpszPrivilegeName, BOOL bEnablePrivilege)
143{
144 DWORD dwRet = ERROR_SUCCESS;
145 HANDLE hToken = NULL;
146
149 &hToken))
150 {
152
153 tp.PrivilegeCount = 1;
154 tp.Privileges[0].Attributes = (bEnablePrivilege ? SE_PRIVILEGE_ENABLED : 0);
155
157 lpszPrivilegeName,
158 &tp.Privileges[0].Luid))
159 {
160 if (AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL))
161 {
164 }
165 else
166 {
167 dwRet = GetLastError();
168 }
169 }
170 else
171 {
172 dwRet = GetLastError();
173 }
174
175 CloseHandle(hToken);
176 }
177 else
178 {
179 dwRet = GetLastError();
180 }
181
182 /* Display the error description if any */
183 if (dwRet != ERROR_SUCCESS) DisplayError(dwRet);
184
185 return dwRet;
186}
187
188/* Main entry for program */
189int wmain(int argc, WCHAR *argv[])
190{
192 struct CommandLineOptions opts;
193
194 /* Initialize the Console Standard Streams */
196
197 if (argc == 1) /* i.e. no commandline arguments given */
198 {
200 return EXIT_SUCCESS;
201 }
202
203 error = ParseArguments(&opts, argc, argv);
204 if (error != ERROR_SUCCESS)
205 {
207 return EXIT_FAILURE;
208 }
209
210 /* If the user wants to abort a shutdown */
211 if (opts.abort)
212 {
213 /* First, the program has to determine if the shutdown/restart is local
214 or remote. This is done since each one requires separate privileges. */
215 if (opts.remote_system == NULL)
217 else
219
220 /* Abort the delayed system shutdown specified. */
222 {
225 return EXIT_FAILURE;
226 }
227 else
228 {
229 return EXIT_SUCCESS;
230 }
231 }
232
233 /*
234 * If the user wants to hibernate the computer. Assume
235 * that the user wants to wake the computer up from
236 * hibernation and it should not force it on the system.
237 */
238 if (opts.hibernate)
239 {
241 {
243
244 /* The shutdown utility cannot hibernate remote systems */
245 if (opts.remote_system != NULL)
246 {
247 return EXIT_FAILURE;
248 }
249
251 {
254 return EXIT_FAILURE;
255 }
256 else
257 {
259 return EXIT_SUCCESS;
260 }
261 }
262 else
263 {
264 return EXIT_FAILURE;
265 }
266 }
267
268 /* Both shutdown and restart flags cannot both be true */
269 if (opts.shutdown && opts.restart)
270 {
272 return EXIT_FAILURE;
273 }
274
275 /* Ensure that the timeout amount is not too high or a negative number */
277 {
279 return EXIT_FAILURE;
280 }
281
282 /* If the user wants a GUI environment */
283 if (opts.show_gui)
284 {
285 if (ShutdownGuiMain(opts))
286 return EXIT_SUCCESS;
287 else
288 return EXIT_FAILURE;
289 }
290
291 if (opts.logoff && (opts.remote_system == NULL))
292 {
293 /*
294 * NOTE: Sometimes, shutdown and logoff are used together. If the logoff
295 * flag is used by itself, then simply logoff. But if used with shutdown,
296 * then skip logging off of the computer and eventually go to the action
297 * for shutdown.
298 */
299 if (!opts.shutdown && !opts.restart)
300 {
302
304 {
305 return EXIT_SUCCESS;
306 }
307 else
308 {
311 return EXIT_FAILURE;
312 }
313 }
314 }
315
316 /*
317 * Since both shutting down the system and restarting calls the exact same
318 * function, all we need to know is if we wanted to restart or shutdown.
319 */
320 if (opts.shutdown || opts.restart)
321 {
322 /*
323 * First, the program has to determine if the shutdown/restart is local
324 * or remote. This is done since each one requires separate privileges.
325 */
326 if (opts.remote_system == NULL)
327 {
329 }
330 else
331 {
332 /* TODO: Remote shutdown is not supported yet */
333 // EnablePrivilege(SE_REMOTE_SHUTDOWN_NAME, TRUE);
334 return EXIT_SUCCESS;
335 }
336
337 /* Initiate the shutdown */
339 opts.message,
340 opts.shutdown_delay,
341 opts.force,
342 opts.restart,
343 opts.reason))
344 {
345 /*
346 * If there is an error, give the proper output depending
347 * on whether the user wanted to shutdown or restart.
348 */
349 if (opts.restart)
351 else
353
355 return EXIT_FAILURE;
356 }
357 else
358 {
359 return EXIT_SUCCESS;
360 }
361 }
362
363 return EXIT_SUCCESS;
364}
365
366/* EOF */
static int argc
Definition: ServiceArgs.c:12
#define IDS_USAGE
Definition: resource.h:3
#define ConInitStdStreams()
Definition: fc.c:13
#define StdOut
Definition: fc.c:14
void ConResPrintf(FILE *fp, UINT nID,...)
Definition: fc.c:33
#define StdErr
Definition: fc.c:15
void ConResPuts(FILE *fp, UINT nID)
Definition: fc.c:27
#define index(s, c)
Definition: various.h:29
BOOL ShutdownGuiMain(struct CommandLineOptions opts)
Definition: gui.c:45
DWORD ParseReasonCode(LPCWSTR code)
Definition: misc.c:55
#define IDS_ERROR_SHUTDOWN_REBOOT
Definition: resource.h:6
#define IDS_ERROR_MAX_COMMENT_LENGTH
Definition: resource.h:12
#define IDS_ERROR_ABORT
Definition: resource.h:8
#define IDS_ERROR_HIBERNATE_ENABLED
Definition: resource.h:15
#define IDS_ERROR_LOGOFF
Definition: resource.h:9
#define IDS_ERROR_HIBERNATE
Definition: resource.h:13
#define IDS_ERROR_SHUTDOWN
Definition: resource.h:11
#define IDS_ERROR_RESTART
Definition: resource.h:10
#define IDS_ERROR_TIMEOUT
Definition: resource.h:7
static DWORD EnablePrivilege(LPCWSTR lpszPrivilegeName, BOOL bEnablePrivilege)
Definition: shutdown.c:142
static DWORD ParseArguments(struct CommandLineOptions *pOpts, int argc, WCHAR *argv[])
Definition: shutdown.c:19
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
BOOL WINAPI AbortSystemShutdownW(LPCWSTR lpMachineName)
Definition: shutdown.c:48
BOOL WINAPI InitiateSystemShutdownExW(LPWSTR lpMachineName, LPWSTR lpMessage, DWORD dwTimeout, BOOL bForceAppsClosed, BOOL bRebootAfterShutdown, DWORD dwReason)
Definition: shutdown.c:254
BOOL WINAPI LookupPrivilegeValueW(LPCWSTR lpSystemName, LPCWSTR lpPrivilegeName, PLUID lpLuid)
Definition: misc.c:782
BOOL WINAPI AdjustTokenPrivileges(HANDLE TokenHandle, BOOL DisableAllPrivileges, PTOKEN_PRIVILEGES NewState, DWORD BufferLength, PTOKEN_PRIVILEGES PreviousState, PDWORD ReturnLength)
Definition: security.c:374
BOOL WINAPI OpenProcessToken(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle)
Definition: security.c:294
#define CloseHandle
Definition: compat.h:739
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define GetCurrentProcess()
Definition: compat.h:759
_In_ uint64_t _In_ uint64_t _In_ uint64_t _In_opt_ traverse_ptr * tp
Definition: btrfs.c:2996
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint index
Definition: glext.h:6031
_Check_return_ _CRTIMP int __cdecl _wtoi(_In_z_ const wchar_t *_Str)
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define EXIT_FAILURE
Definition: jerror.c:33
VOID DisplayError(DWORD dwError)
Definition: logoff.c:33
#define error(str)
Definition: mkdosfs.c:1605
#define argv
Definition: mplay32.c:18
#define L(x)
Definition: ntvdm.h:50
BOOLEAN WINAPI IsPwrHibernateAllowed(VOID)
Definition: powrprof.c:450
BOOLEAN WINAPI SetSuspendState(BOOLEAN Hibernate, BOOLEAN ForceCritical, BOOLEAN DisableWakeEvent)
Definition: powrprof.c:681
int wmain()
#define EXIT_SUCCESS
Definition: rdjpgcom.c:55
LPWSTR remote_system
Definition: precomp.h:44
LPWSTR message
Definition: precomp.h:45
BOOL document_reason
Definition: precomp.h:41
DWORD shutdown_delay
Definition: precomp.h:43
#define towlower(c)
Definition: wctype.h:97
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define ERROR_BAD_LENGTH
Definition: winerror.h:127
#define ERROR_NOT_ALL_ASSIGNED
Definition: winerror.h:782
#define ERROR_INVALID_DATA
Definition: winerror.h:116
#define SE_REMOTE_SHUTDOWN_NAME
Definition: winnt_old.h:418
#define SE_SHUTDOWN_NAME
Definition: winnt_old.h:413
#define MAX_SHUTDOWN_TIMEOUT
Definition: winreg.h:53
#define EWX_LOGOFF
Definition: winuser.h:636
BOOL WINAPI ExitWindowsEx(_In_ UINT, _In_ DWORD)
#define TOKEN_ADJUST_PRIVILEGES
Definition: setypes.h:930
#define SE_PRIVILEGE_ENABLED
Definition: setypes.h:63
__wchar_t WCHAR
Definition: xmlstorage.h:180
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185