Sync to trunk revision 61757.
[reactos.git] / base / applications / shutdown / misc.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS shutdown/logoff utility
4 * FILE: base/applications/shutdown/misc.c
5 * PURPOSE: Misc. functions used for the shutdown utility
6 * PROGRAMMERS: Lee Schroeder
7 */
8
9 #include "precomp.h"
10
11 #include <stdio.h>
12
13 const DWORD defaultReason = SHTDN_REASON_MAJOR_OTHER | SHTDN_REASON_MINOR_OTHER;
14
15 REASON shutdownReason[] =
16 {
17 {L"U" , 0, 0, SHTDN_REASON_MAJOR_OTHER | SHTDN_REASON_MINOR_OTHER}, /* Other (Unplanned) */
18 {L"E" , 0, 0, SHTDN_REASON_MAJOR_OTHER | SHTDN_REASON_MINOR_OTHER}, /* Other (Unplanned) */
19 {L"EP", 0, 0, SHTDN_REASON_MAJOR_OTHER | SHTDN_REASON_MINOR_OTHER | SHTDN_REASON_FLAG_PLANNED}, /* Other (Planned) */
20 {L"U" , 0, 5, SHTDN_REASON_MAJOR_OTHER | SHTDN_REASON_MINOR_HUNG}, /* Other Failure: System Unresponsive */
21 {L"E" , 1, 1, SHTDN_REASON_MAJOR_HARDWARE | SHTDN_REASON_MINOR_MAINTENANCE}, /* Hardware: Maintenance (Unplanned) */
22 {L"EP", 1, 1, SHTDN_REASON_MAJOR_HARDWARE | SHTDN_REASON_MINOR_MAINTENANCE | SHTDN_REASON_FLAG_PLANNED}, /* Hardware: Maintenance (Planned) */
23 {L"E" , 1, 2, SHTDN_REASON_MAJOR_HARDWARE | SHTDN_REASON_MINOR_INSTALLATION}, /* Hardware: Installation (Unplanned) */
24 {L"EP", 1, 2, SHTDN_REASON_MAJOR_HARDWARE | SHTDN_REASON_MINOR_INSTALLATION | SHTDN_REASON_FLAG_PLANNED}, /* Hardware: Installation (Planned) */
25 {L"P" , 2, 3, SHTDN_REASON_MAJOR_OPERATINGSYSTEM | SHTDN_REASON_MINOR_UPGRADE | SHTDN_REASON_FLAG_PLANNED}, /* Operating System: Upgrade (Planned) */
26 {L"E" , 2, 4, SHTDN_REASON_MAJOR_OPERATINGSYSTEM | SHTDN_REASON_MINOR_RECONFIG}, /* Operating System: Reconfiguration (Unplanned) */
27 {L"EP", 2, 4, SHTDN_REASON_MAJOR_OPERATINGSYSTEM | SHTDN_REASON_MINOR_RECONFIG | SHTDN_REASON_FLAG_PLANNED}, /* Operating System: Reconfiguration (Planned) */
28 {L"P" , 2, 16, SHTDN_REASON_MAJOR_OPERATINGSYSTEM | SHTDN_REASON_MINOR_RECONFIG | SHTDN_REASON_FLAG_PLANNED}, /* Operating System: Service pack (Planned) */
29 {L"U" , 2, 17, SHTDN_REASON_MAJOR_OPERATINGSYSTEM | SHTDN_REASON_MINOR_HOTFIX}, /* Operating System: Hotfix (Unplanned) */
30 {L"P" , 2, 17, SHTDN_REASON_MAJOR_OPERATINGSYSTEM | SHTDN_REASON_MINOR_HOTFIX | SHTDN_REASON_FLAG_PLANNED}, /* Operating System: Hotfix (Planned) */
31 {L"U" , 2, 18, SHTDN_REASON_MAJOR_OPERATINGSYSTEM | SHTDN_REASON_MINOR_SECURITYFIX}, /* Operating System: Security fix (Unplanned) */
32 {L"P" , 2, 18, SHTDN_REASON_MAJOR_OPERATINGSYSTEM | SHTDN_REASON_MINOR_SECURITYFIX | SHTDN_REASON_FLAG_PLANNED}, /* Operating System: Security fix (Planned) */
33 {L"E" , 4, 1, SHTDN_REASON_MAJOR_APPLICATION | SHTDN_REASON_MINOR_MAINTENANCE}, /* Application: Maintenance (Unplanned) */
34 {L"EP", 4, 1, SHTDN_REASON_MAJOR_APPLICATION | SHTDN_REASON_MINOR_MAINTENANCE | SHTDN_REASON_FLAG_PLANNED}, /* Application: Maintenance (Planned) */
35 {L"EP", 4, 2, SHTDN_REASON_MAJOR_APPLICATION | SHTDN_REASON_MINOR_INSTALLATION | SHTDN_REASON_FLAG_PLANNED}, /* Application: Installation (Planned) */
36 {L"E" , 4, 5, SHTDN_REASON_MAJOR_APPLICATION | SHTDN_REASON_MINOR_HUNG}, /* Application: Unresponsive */
37 {L"E" , 4, 6, SHTDN_REASON_MAJOR_APPLICATION | SHTDN_REASON_MINOR_UNSTABLE}, /* Application: Unstable */
38 {L"U" , 5, 15, SHTDN_REASON_MAJOR_SYSTEM | SHTDN_REASON_MINOR_BLUESCREEN}, /* System Failure: Stop Error */
39 {L"E" , 5, 19, SHTDN_REASON_MAJOR_SYSTEM | SHTDN_REASON_MINOR_SECURITY}, /* Security Issue */
40 {L"U" , 5, 19, SHTDN_REASON_MAJOR_SYSTEM | SHTDN_REASON_MINOR_SECURITY}, /* Security Issue */
41 {L"EP", 5, 19, SHTDN_REASON_MAJOR_SYSTEM | SHTDN_REASON_MINOR_SECURITY | SHTDN_REASON_FLAG_PLANNED}, /* Security Issue (Planned) */
42 {L"E" , 5, 20, SHTDN_REASON_MAJOR_SYSTEM | SHTDN_REASON_MINOR_NETWORK_CONNECTIVITY}, /* Loss of Network Connectivity (Unplanned) */
43 {L"U" , 6, 11, SHTDN_REASON_MAJOR_POWER | SHTDN_REASON_MINOR_CORDUNPLUGGED}, /* Power Failure: Cord Unplugged */
44 {L"U" , 6, 12, SHTDN_REASON_MAJOR_POWER | SHTDN_REASON_MINOR_ENVIRONMENT}, /* Power Failure: Environment */
45 {L"P" , 7, 0, SHTDN_REASON_MAJOR_POWER | SHTDN_REASON_MINOR_ENVIRONMENT} /* Legacy API shutdown (Planned) */
46 };
47
48 /*
49 * This command helps to work around the fact that the shutdown utility has
50 * different upper limits for the comment flag since each version of Windows
51 * seems to have different upper limits.
52 */
53 BOOL CheckCommentLength(LPCWSTR comment)
54 {
55 DWORD finalLength = 0;
56 size_t strLength = 0;
57 DWORD osVersion = 0;
58 DWORD osMajorVersion = 0;
59 DWORD osMinorVersion = 0;
60
61 /* An empty string is always valid. */
62 if (!comment || *comment == 0)
63 return TRUE;
64
65 /* Grab the version of the current Operating System. */
66 osVersion = GetVersion();
67
68 osMajorVersion = (DWORD)(LOBYTE(LOWORD(osVersion)));
69 osMinorVersion = (DWORD)(HIBYTE(LOWORD(osVersion)));
70
71 /*
72 * Check to make sure that the proper length is being used
73 * based upon the version of Windows currently being used.
74 */
75 if (osMajorVersion == 5) /* Windows XP/2003 */
76 {
77 if ((osMinorVersion == 1) || (osMinorVersion == 2))
78 {
79 finalLength = 127;
80 }
81 }
82 else if (osMajorVersion == 6) /* Windows Vista/7/2008 */
83 {
84 if ((osMinorVersion == 0) || (osMinorVersion == 1))
85 {
86 finalLength = 512;
87 }
88 }
89
90 /* Grab the length of the comment string. */
91 strLength = wcslen(comment);
92
93 /*
94 * Compare the size of the string to make sure
95 * it fits with the current version of Windows,
96 * and return TRUE or FALSE accordingly.
97 */
98 return (strLength <= finalLength);
99 }
100
101 /*
102 * This function parses the reason code to a usable format that will specify
103 * why the user wants to shut the computer down. Although this is used for
104 * both client and server environments, use of a reason code is more important
105 * in a server environment since servers are supposed to be on all the time
106 * for easier access.
107 */
108 DWORD ParseReasonCode(LPCWSTR code)
109 {
110 PREASON reasonptr;
111 int majorCode = 0;
112 int minorCode = 0;
113 LPWSTR tmpPrefix = NULL;
114 size_t codeSize;
115
116 /* If no reason code is specified, use "Other (Unplanned)" as the default option */
117 if(code == NULL)
118 {
119 return defaultReason;
120 }
121 else
122 {
123 /* Store the size of the code so we can use it later */
124 codeSize = (size_t)wcslen(code);
125
126 /* A colon cannot be the first or last character in the reason code */
127 if ((code[0] == L':') || (code[codeSize] == L':'))
128 {
129 return defaultReason;
130 }
131
132 /* The minimum length that a reason code can be is 5-7 characters in length */
133 if ((codeSize < 5) || (codeSize > 7))
134 {
135 return defaultReason;
136 }
137
138 /* TODO: Add code for reason parsing here. */
139
140 /* Make sure that the major and minor codes are within size limits */
141 if ((majorCode > 7 ) || (majorCode < 0) ||
142 (minorCode > 20) || (minorCode < 0))
143 {
144 return defaultReason;
145 }
146
147 /* Figure out what flags to return */
148 for (reasonptr = shutdownReason ; reasonptr->prefix ; reasonptr++)
149 {
150 if ((majorCode == reasonptr->major) &&
151 (minorCode == reasonptr->minor) &&
152 (_wcsicmp(tmpPrefix, reasonptr->prefix) != 0))
153 {
154 return reasonptr->flag;
155 }
156 }
157 }
158
159 return defaultReason;
160 }
161
162 /* Writes the last error as both text and error code to the console */
163 VOID DisplayError(DWORD dwError)
164 {
165 LPWSTR lpMsgBuf = NULL;
166 DWORD errLength; /* Error message length */
167 LPSTR resMsg; /* For error message in OEM symbols */
168
169 /* Grabs the length of the error message */
170 errLength = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
171 NULL,
172 dwError,
173 LANG_USER_DEFAULT,
174 (LPWSTR)&lpMsgBuf,
175 0,
176 NULL) + 1;
177
178 /* Gets the error message ready for output */
179 resMsg = (LPSTR)LocalAlloc(LPTR, errLength * sizeof(WCHAR));
180 CharToOemBuffW(lpMsgBuf, resMsg, errLength);
181
182 /* Prints out the error message to the user */
183 fprintf(stderr, resMsg);
184 fwprintf(stderr, L"Error code: %lu\n", dwError);
185
186 LocalFree(lpMsgBuf);
187 LocalFree(resMsg);
188 }
189
190 /* EOF */