3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS shutdown/logoff utility
5 * FILE: apps/utils/shutdown/shutdown.c
6 * PURPOSE: Initiate logoff, shutdown or reboot of the system
15 PrintUsage(LPCTSTR Cmd
)
17 _ftprintf(stderr
, _T("usage: %s [action] [flag]\n"), Cmd
);
18 _ftprintf(stderr
, _T(" action = \"logoff\", \"reboot\", \"shutdown\" or \"poweroff\"\n"));
19 _ftprintf(stderr
, _T(" flag = \"force\"\n"));
23 _tmain(int argc
, TCHAR
*argv
[])
33 { _T("logoff"), EWX_LOGOFF
, 0 },
34 { _T("logout"), EWX_LOGOFF
, 0 },
35 { _T("poweroff"), EWX_POWEROFF
, 0 },
36 { _T("powerdown"), EWX_POWEROFF
, 0 },
37 { _T("reboot"), EWX_REBOOT
, 0 },
38 { _T("restart"), EWX_REBOOT
, 0 },
39 { _T("shutdown"), EWX_SHUTDOWN
, 0 },
40 { _T("force"), 0, EWX_FORCE
},
41 { _T("forceifhung"), 0, EWX_FORCEIFHUNG
},
42 { _T("ifhung"), 0, EWX_FORCEIFHUNG
},
43 { _T("hung"), 0, EWX_FORCEIFHUNG
},
45 UINT ExitType
, ExitFlags
;
49 TCHAR BaseName
[_MAX_FNAME
];
51 BOOL HaveType
, Matched
;
57 _tsplitpath(argv
[0], NULL
, NULL
, BaseName
, NULL
);
59 /* Process optional arguments */
60 for (i
= 1; i
< (unsigned) argc
; i
++)
62 /* Allow e.g. "/s" or "-l" for shutdown resp. logoff */
64 if (_T('/') == *Arg
|| _T('-') == *Arg
)
69 /* Search known options */
71 for (j
= 0; j
< sizeof(Options
) / sizeof(Options
[0]) && ! Matched
; j
++)
73 /* Match if arg starts the same as the option name */
74 if (0 == _tcsnicmp(Options
[j
].Name
, Arg
, _tcslen(Arg
)))
76 if (0 == Options
[j
].ExitFlags
)
78 /* Can have only 1 type */
84 ExitType
= Options
[j
].ExitType
;
89 /* Can have only 1 flag */
95 ExitFlags
|= Options
[j
].ExitFlags
;
101 /* Was the argument processed? */
104 PrintUsage(BaseName
);
109 /* Check command name if user didn't explicitly specify action */
112 for (j
= 0; j
< sizeof(Options
) / sizeof(Options
[0]); j
++)
114 if (0 == _tcsicmp(Options
[j
].Name
, BaseName
) && 0 == Options
[j
].ExitFlags
)
116 ExitType
= Options
[j
].ExitType
;
122 /* Still not sure what to do? */
125 PrintUsage(BaseName
);
129 /* Everyone can logoff, for the other actions you need the appropriate privilege */
130 if (EWX_LOGOFF
!= ExitType
)
132 /* enable shutdown privilege for current process */
133 if (! OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES
, &hToken
))
135 _ftprintf(stderr
, _T("OpenProcessToken failed with error %d\n"), (int) GetLastError());
138 npr
.PrivilegeCount
= 1;
139 npr
.Privileges
[0].Attributes
= SE_PRIVILEGE_ENABLED
;
140 if (! LookupPrivilegeValue(NULL
, SE_SHUTDOWN_NAME
, &npr
.Privileges
[0].Luid
))
143 _ftprintf(stderr
, _T("LookupPrivilegeValue failed with error %d\n"), (int) GetLastError());
146 if (! AdjustTokenPrivileges(hToken
, FALSE
, &npr
, 0, 0, 0)
147 || ERROR_SUCCESS
!= GetLastError())
149 if (ERROR_NOT_ALL_ASSIGNED
== GetLastError())
151 _ftprintf(stderr
, _T("You are not authorized to shutdown the system\n"));
155 _ftprintf(stderr
, _T("AdjustTokenPrivileges failed with error %d\n"), (int) GetLastError());
164 if (! ExitWindowsEx(ExitType
| ExitFlags
, 0))
166 _ftprintf(stderr
, _T("ExitWindowsEx failed with error %d\n"), (int) GetLastError());