2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS shutdown/logoff utility
4 * FILE: base/application/shutdown/shutdown.c
5 * PURPOSE: Initiate logoff, shutdown or reboot of the system
10 // Print information about which commandline arguments the program accepts.
11 static void PrintUsage() {
12 LPTSTR lpUsage
= NULL
;
14 if( AllocAndLoadString( &lpUsage
,
15 GetModuleHandle(NULL
),
22 struct CommandLineOptions
{
23 BOOL abort
; // Not used yet
31 // This flag is used to distinguish between a user-initiated LOGOFF (which has value 0)
32 // and an underdetermined situation because user didn't give an argument to start Exit.
34 // flags is the type of shutdown to do - EWX_LOGOFF, EWX_REBOOT, EWX_POWEROFF, etc..
36 // reason is the System Shutdown Reason code. F.instance SHTDN_REASON_MAJOR_OTHER | SHTDN_REASON_MINOR_OTHER | SHTDN_REASON_FLAG_PLANNED.
40 // Takes the commandline arguments, and creates a struct which matches the arguments supplied.
41 static struct CommandLineOptions
ParseArguments(int argc
, TCHAR
*argv
[])
43 struct CommandLineOptions opts
;
46 // Reset all flags in struct
51 opts
.shutdown
= FALSE
;
53 for (i
= 1; i
< argc
; i
++)
55 if (argv
[i
][0] == '-' || argv
[i
][0] == '/')
78 // Unknown arguments will exit program.
89 // Converts the commandline arguments to flags used to shutdown computer
90 static struct ExitOptions
ParseCommandLineOptionsToExitOptions(struct CommandLineOptions opts
)
92 struct ExitOptions exitOpts
;
93 exitOpts
.shouldExit
= TRUE
;
95 // Sets ONE of the exit type flags
97 exitOpts
.flags
= EWX_LOGOFF
;
98 else if (opts
.restart
)
99 exitOpts
.flags
= EWX_REBOOT
;
100 else if(opts
.shutdown
)
101 exitOpts
.flags
= EWX_POWEROFF
;
105 exitOpts
.shouldExit
= FALSE
;
108 // Sets additional flags
111 exitOpts
.flags
= exitOpts
.flags
| EWX_FORCE
;
113 // This makes sure that we log off, also if there is only the "-f" option specified.
114 // The Windows shutdown utility does it the same way.
115 exitOpts
.shouldExit
= TRUE
;
118 // Reason for shutdown
119 // Hardcoded to "Other (Planned)"
120 exitOpts
.reason
= SHTDN_REASON_MAJOR_OTHER
| SHTDN_REASON_MINOR_OTHER
| SHTDN_REASON_FLAG_PLANNED
;
125 // Writes the last error as both text and error code to the console.
126 void DisplayLastError()
128 int errorCode
= GetLastError();
131 // Display the error message to the user
133 FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
,
141 _ftprintf(stderr
, lpMsgBuf
);
142 _ftprintf(stderr
, _T("Error code: %d\n"), errorCode
);
145 void EnableShutdownPrivileges()
148 TOKEN_PRIVILEGES privs
;
150 // Check to see if the choosen action is allowed by the user. Everyone can call LogOff, but only privilieged users can shutdown/restart etc.
151 if (! OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES
, &token
))
157 // Get LUID (Locally Unique Identifier) for the privilege we need
158 if (!LookupPrivilegeValue(
159 NULL
, // system - NULL is localsystem
160 SE_SHUTDOWN_NAME
, // name of the privilege
161 &privs
.Privileges
[0].Luid
) // output
167 // and give our current process (i.e. shutdown.exe) the privilege to shutdown the machine.
168 privs
.PrivilegeCount
= 1;
169 privs
.Privileges
[0].Attributes
= SE_PRIVILEGE_ENABLED
;
170 if (AdjustTokenPrivileges(
175 (PTOKEN_PRIVILEGES
)NULL
, // previous state. Set to NULL, we don't care about previous state.
177 ) == 0) // return value 0 means failure
184 // Main entry for program
185 int _tmain(int argc
, TCHAR
*argv
[])
187 struct CommandLineOptions opts
;
188 struct ExitOptions exitOpts
;
190 if (argc
== 1) // i.e. no commandline arguments given
196 opts
= ParseArguments(argc
, argv
);
197 exitOpts
= ParseCommandLineOptionsToExitOptions(opts
);
199 // Perform the shutdown/restart etc. action
200 if (exitOpts
.shouldExit
)
202 EnableShutdownPrivileges();
204 if (!ExitWindowsEx(exitOpts
.flags
, exitOpts
.reason
))