ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

shutdown.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.