2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS shutdown/logoff utility
4 * FILE: apps/utils/shutdown/shutdown.c
5 * PURPOSE: Initiate logoff, shutdown or reboot of the system
14 PrintUsage(LPCTSTR Cmd
)
16 _ftprintf(stderr
, _T("usage: %s [action] [flag]\n"), Cmd
);
17 _ftprintf(stderr
, _T(" action = \"logoff\", \"reboot\", \"shutdown\" or \"poweroff\"\n"));
18 _ftprintf(stderr
, _T(" flag = \"force\"\n"));
22 _tmain(int argc
, TCHAR
*argv
[])
32 { _T("logoff"), EWX_LOGOFF
, 0 },
33 { _T("logout"), EWX_LOGOFF
, 0 },
34 { _T("poweroff"), EWX_POWEROFF
, 0 },
35 { _T("powerdown"), EWX_POWEROFF
, 0 },
36 { _T("reboot"), EWX_REBOOT
, 0 },
37 { _T("restart"), EWX_REBOOT
, 0 },
38 { _T("shutdown"), EWX_SHUTDOWN
, 0 },
39 { _T("force"), 0, EWX_FORCE
},
40 { _T("forceifhung"), 0, EWX_FORCEIFHUNG
},
41 { _T("ifhung"), 0, EWX_FORCEIFHUNG
},
42 { _T("hung"), 0, EWX_FORCEIFHUNG
},
44 UINT ExitType
, ExitFlags
;
48 TCHAR BaseName
[_MAX_FNAME
];
50 BOOL HaveType
, Matched
;
56 _tsplitpath(argv
[0], NULL
, NULL
, BaseName
, NULL
);
58 /* Process optional arguments */
59 for (i
= 1; i
< (unsigned) argc
; i
++)
61 /* Allow e.g. "/s" or "-l" for shutdown resp. logoff */
63 if (_T('/') == *Arg
|| _T('-') == *Arg
)
68 /* Search known options */
70 for (j
= 0; j
< sizeof(Options
) / sizeof(Options
[0]) && ! Matched
; j
++)
72 /* Match if arg starts the same as the option name */
73 if (0 == _tcsnicmp(Options
[j
].Name
, Arg
, _tcslen(Arg
)))
75 if (0 == Options
[j
].ExitFlags
)
77 /* Can have only 1 type */
83 ExitType
= Options
[j
].ExitType
;
88 /* Can have only 1 flag */
94 ExitFlags
|= Options
[j
].ExitFlags
;
100 /* Was the argument processed? */
103 PrintUsage(BaseName
);
108 /* Check command name if user didn't explicitly specify action */
111 for (j
= 0; j
< sizeof(Options
) / sizeof(Options
[0]); j
++)
113 if (0 == _tcsicmp(Options
[j
].Name
, BaseName
) && 0 == Options
[j
].ExitFlags
)
115 ExitType
= Options
[j
].ExitType
;
121 /* Still not sure what to do? */
124 PrintUsage(BaseName
);
128 /* Everyone can logoff, for the other actions you need the appropriate privilege */
129 if (EWX_LOGOFF
!= ExitType
)
131 /* enable shutdown privilege for current process */
132 if (! OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES
, &hToken
))
134 _ftprintf(stderr
, _T("OpenProcessToken failed with error %d\n"), (int) GetLastError());
137 npr
.PrivilegeCount
= 1;
138 npr
.Privileges
[0].Attributes
= SE_PRIVILEGE_ENABLED
;
139 if (! LookupPrivilegeValue(NULL
, SE_SHUTDOWN_NAME
, &npr
.Privileges
[0].Luid
))
142 _ftprintf(stderr
, _T("LookupPrivilegeValue failed with error %d\n"), (int) GetLastError());
145 if (! AdjustTokenPrivileges(hToken
, FALSE
, &npr
, 0, 0, 0)
146 || ERROR_SUCCESS
!= GetLastError())
148 if (ERROR_NOT_ALL_ASSIGNED
== GetLastError())
150 _ftprintf(stderr
, _T("You are not authorized to shutdown the system\n"));
154 _ftprintf(stderr
, _T("AdjustTokenPrivileges failed with error %d\n"), (int) GetLastError());
163 if (! ExitWindowsEx(ExitType
| ExitFlags
, 0))
165 _ftprintf(stderr
, _T("ExitWindowsEx failed with error %d\n"), (int) GetLastError());