- Don't call winsock initialiser for each seperate server thread
[reactos.git] / reactos / apps / utils / shutdown / shutdown.c
1 /* $Id$
2 *
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
7 */
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <windows.h>
12 #include <tchar.h>
13
14 static void
15 PrintUsage(LPCTSTR Cmd)
16 {
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"));
20 }
21
22 int
23 _tmain(int argc, TCHAR *argv[])
24 {
25 static struct
26 {
27 TCHAR *Name;
28 UINT ExitType;
29 UINT ExitFlags;
30 }
31 Options[] =
32 {
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 },
44 };
45 UINT ExitType, ExitFlags;
46 HANDLE hToken;
47 TOKEN_PRIVILEGES npr;
48 TCHAR *Arg;
49 TCHAR BaseName[_MAX_FNAME];
50 unsigned i, j;
51 BOOL HaveType, Matched;
52
53 ExitType = 0;
54 ExitFlags = 0;
55 HaveType = FALSE;
56
57 _tsplitpath(argv[0], NULL, NULL, BaseName, NULL);
58
59 /* Process optional arguments */
60 for (i = 1; i < (unsigned) argc; i++)
61 {
62 /* Allow e.g. "/s" or "-l" for shutdown resp. logoff */
63 Arg = argv[i];
64 if (_T('/') == *Arg || _T('-') == *Arg)
65 {
66 Arg++;
67 }
68
69 /* Search known options */
70 Matched = FALSE;
71 for (j = 0; j < sizeof(Options) / sizeof(Options[0]) && ! Matched; j++)
72 {
73 /* Match if arg starts the same as the option name */
74 if (0 == _tcsnicmp(Options[j].Name, Arg, _tcslen(Arg)))
75 {
76 if (0 == Options[j].ExitFlags)
77 {
78 /* Can have only 1 type */
79 if (HaveType)
80 {
81 PrintUsage(BaseName);
82 exit(1);
83 }
84 ExitType = Options[j].ExitType;
85 HaveType = TRUE;
86 }
87 else
88 {
89 /* Can have only 1 flag */
90 if (0 != ExitFlags)
91 {
92 PrintUsage(BaseName);
93 exit(1);
94 }
95 ExitFlags |= Options[j].ExitFlags;
96 }
97 Matched = TRUE;
98 }
99 }
100
101 /* Was the argument processed? */
102 if (! Matched)
103 {
104 PrintUsage(BaseName);
105 exit(1);
106 }
107 }
108
109 /* Check command name if user didn't explicitly specify action */
110 if (! HaveType)
111 {
112 for (j = 0; j < sizeof(Options) / sizeof(Options[0]); j++)
113 {
114 if (0 == _tcsicmp(Options[j].Name, BaseName) && 0 == Options[j].ExitFlags)
115 {
116 ExitType = Options[j].ExitType;
117 HaveType = TRUE;
118 }
119 }
120 }
121
122 /* Still not sure what to do? */
123 if (! HaveType)
124 {
125 PrintUsage(BaseName);
126 exit(1);
127 }
128
129 /* Everyone can logoff, for the other actions you need the appropriate privilege */
130 if (EWX_LOGOFF != ExitType)
131 {
132 /* enable shutdown privilege for current process */
133 if (! OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
134 {
135 _ftprintf(stderr, _T("OpenProcessToken failed with error %d\n"), (int) GetLastError());
136 exit(1);
137 }
138 npr.PrivilegeCount = 1;
139 npr.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
140 if (! LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &npr.Privileges[0].Luid))
141 {
142 CloseHandle(hToken);
143 _ftprintf(stderr, _T("LookupPrivilegeValue failed with error %d\n"), (int) GetLastError());
144 exit(1);
145 }
146 if (! AdjustTokenPrivileges(hToken, FALSE, &npr, 0, 0, 0)
147 || ERROR_SUCCESS != GetLastError())
148 {
149 if (ERROR_NOT_ALL_ASSIGNED == GetLastError())
150 {
151 _ftprintf(stderr, _T("You are not authorized to shutdown the system\n"));
152 }
153 else
154 {
155 _ftprintf(stderr, _T("AdjustTokenPrivileges failed with error %d\n"), (int) GetLastError());
156 }
157 CloseHandle(hToken);
158 exit(1);
159 }
160 CloseHandle(hToken);
161 }
162
163 /* Finally do it */
164 if (! ExitWindowsEx(ExitType | ExitFlags, 0))
165 {
166 _ftprintf(stderr, _T("ExitWindowsEx failed with error %d\n"), (int) GetLastError());
167 exit(1);
168 }
169
170 return 0;
171 }