Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenshutdown.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS shutdown/logoff utility 00004 * FILE: base/application/shutdown/shutdown.c 00005 * PURPOSE: Initiate logoff, shutdown or reboot of the system 00006 */ 00007 00008 #include "precomp.h" 00009 00010 // Print information about which commandline arguments the program accepts. 00011 static void PrintUsage() { 00012 LPTSTR lpUsage = NULL; 00013 DWORD errLength; // error message length 00014 LPTSTR resMsg; // for error message in OEM symbols 00015 00016 if( AllocAndLoadString( &lpUsage, 00017 GetModuleHandle(NULL), 00018 IDS_USAGE ) ) 00019 { 00020 errLength = strlen(lpUsage) + 1; 00021 resMsg = (LPTSTR)LocalAlloc(LPTR, errLength * sizeof(TCHAR)); 00022 CharToOemBuff(lpUsage, resMsg, errLength); 00023 00024 _putts( resMsg ); 00025 00026 LocalFree(lpUsage); 00027 LocalFree(resMsg); 00028 } 00029 } 00030 00031 struct CommandLineOptions { 00032 BOOL abort; // Not used yet 00033 BOOL force; 00034 BOOL logoff; 00035 BOOL restart; 00036 BOOL shutdown; 00037 }; 00038 00039 struct ExitOptions { 00040 // This flag is used to distinguish between a user-initiated LOGOFF (which has value 0) 00041 // and an underdetermined situation because user didn't give an argument to start Exit. 00042 BOOL shouldExit; 00043 // flags is the type of shutdown to do - EWX_LOGOFF, EWX_REBOOT, EWX_POWEROFF, etc.. 00044 UINT flags; 00045 // reason is the System Shutdown Reason code. F.instance SHTDN_REASON_MAJOR_OTHER | SHTDN_REASON_MINOR_OTHER | SHTDN_REASON_FLAG_PLANNED. 00046 DWORD reason; 00047 }; 00048 00049 // Takes the commandline arguments, and creates a struct which matches the arguments supplied. 00050 static struct CommandLineOptions ParseArguments(int argc, TCHAR *argv[]) 00051 { 00052 struct CommandLineOptions opts; 00053 int i; 00054 00055 // Reset all flags in struct 00056 opts.abort = FALSE; 00057 opts.force = FALSE; 00058 opts.logoff = FALSE; 00059 opts.restart = FALSE; 00060 opts.shutdown = FALSE; 00061 00062 for (i = 1; i < argc; i++) 00063 { 00064 if (argv[i][0] == '-' || argv[i][0] == '/') 00065 { 00066 switch(argv[i][1]) { 00067 case '?': 00068 PrintUsage(); 00069 exit(0); 00070 case 'f': 00071 case 'F': 00072 opts.force = TRUE; 00073 break; 00074 case 'l': 00075 case 'L': 00076 opts.logoff = TRUE; 00077 break; 00078 case 'r': 00079 case 'R': 00080 opts.restart = TRUE; 00081 break; 00082 case 's': 00083 case 'S': 00084 opts.shutdown = TRUE; 00085 break; 00086 default: 00087 // Unknown arguments will exit program. 00088 PrintUsage(); 00089 exit(0); 00090 break; 00091 } 00092 } 00093 } 00094 00095 return opts; 00096 } 00097 00098 // Converts the commandline arguments to flags used to shutdown computer 00099 static struct ExitOptions ParseCommandLineOptionsToExitOptions(struct CommandLineOptions opts) 00100 { 00101 struct ExitOptions exitOpts; 00102 exitOpts.shouldExit = TRUE; 00103 00104 // Sets ONE of the exit type flags 00105 if (opts.logoff) 00106 exitOpts.flags = EWX_LOGOFF; 00107 else if (opts.restart) 00108 exitOpts.flags = EWX_REBOOT; 00109 else if(opts.shutdown) 00110 exitOpts.flags = EWX_POWEROFF; 00111 else 00112 { 00113 exitOpts.flags = 0; 00114 exitOpts.shouldExit = FALSE; 00115 } 00116 00117 // Sets additional flags 00118 if (opts.force) 00119 { 00120 exitOpts.flags = exitOpts.flags | EWX_FORCE; 00121 00122 // This makes sure that we log off, also if there is only the "-f" option specified. 00123 // The Windows shutdown utility does it the same way. 00124 exitOpts.shouldExit = TRUE; 00125 } 00126 00127 // Reason for shutdown 00128 // Hardcoded to "Other (Planned)" 00129 exitOpts.reason = SHTDN_REASON_MAJOR_OTHER | SHTDN_REASON_MINOR_OTHER | SHTDN_REASON_FLAG_PLANNED; 00130 00131 return exitOpts; 00132 } 00133 00134 // Writes the last error as both text and error code to the console. 00135 void DisplayLastError() 00136 { 00137 int errorCode = GetLastError(); 00138 LPTSTR lpMsgBuf = NULL; 00139 DWORD errLength; // error message length 00140 LPTSTR resMsg; // for error message in OEM symbols 00141 00142 // Display the error message to the user 00143 errLength = FormatMessage( 00144 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 00145 NULL, 00146 errorCode, 00147 LANG_USER_DEFAULT, 00148 (LPTSTR) &lpMsgBuf, 00149 0, 00150 NULL) + 1; 00151 00152 resMsg = (LPTSTR)LocalAlloc(LPTR, errLength * sizeof(TCHAR)); 00153 CharToOemBuff(lpMsgBuf, resMsg, errLength); 00154 00155 _ftprintf(stderr, resMsg); 00156 _ftprintf(stderr, _T("Error code: %d\n"), errorCode); 00157 00158 LocalFree(lpMsgBuf); 00159 LocalFree(resMsg); 00160 } 00161 00162 void EnableShutdownPrivileges() 00163 { 00164 HANDLE token; 00165 TOKEN_PRIVILEGES privs; 00166 00167 // Check to see if the choosen action is allowed by the user. Everyone can call LogOff, but only privilieged users can shutdown/restart etc. 00168 if (! OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token)) 00169 { 00170 DisplayLastError(); 00171 exit(1); 00172 } 00173 00174 // Get LUID (Locally Unique Identifier) for the privilege we need 00175 if (!LookupPrivilegeValue( 00176 NULL, // system - NULL is localsystem 00177 SE_SHUTDOWN_NAME, // name of the privilege 00178 &privs.Privileges[0].Luid) // output 00179 ) 00180 { 00181 DisplayLastError(); 00182 exit(1); 00183 } 00184 // and give our current process (i.e. shutdown.exe) the privilege to shutdown the machine. 00185 privs.PrivilegeCount = 1; 00186 privs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 00187 if (AdjustTokenPrivileges( 00188 token, 00189 FALSE, 00190 &privs, 00191 0, 00192 (PTOKEN_PRIVILEGES)NULL, // previous state. Set to NULL, we don't care about previous state. 00193 NULL 00194 ) == 0) // return value 0 means failure 00195 { 00196 DisplayLastError(); 00197 exit(1); 00198 } 00199 } 00200 00201 // Main entry for program 00202 int _tmain(int argc, TCHAR *argv[]) 00203 { 00204 struct CommandLineOptions opts; 00205 struct ExitOptions exitOpts; 00206 00207 if (argc == 1) // i.e. no commandline arguments given 00208 { 00209 PrintUsage(); 00210 exit(0); 00211 } 00212 00213 opts = ParseArguments(argc, argv); 00214 exitOpts = ParseCommandLineOptionsToExitOptions(opts); 00215 00216 // Perform the shutdown/restart etc. action 00217 if (exitOpts.shouldExit) 00218 { 00219 EnableShutdownPrivileges(); 00220 00221 if (!ExitWindowsEx(exitOpts.flags, exitOpts.reason)) 00222 { 00223 DisplayLastError(); 00224 exit(1); 00225 } 00226 } 00227 return 0; 00228 } 00229 00230 // EOF Generated on Sat May 26 2012 04:16:25 for ReactOS by
1.7.6.1
|