xref: /reactos/base/applications/shutdown/misc.c (revision 84ccccab)
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     ConMsgPuts(StdErr, FORMAT_MESSAGE_FROM_SYSTEM,
166                NULL, dwError, LANG_USER_DEFAULT);
167     ConPrintf(StdErr, L"Error code: %lu\n", dwError);
168 }
169 
170 /* EOF */
171