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
;
13 DWORD errLength
; // error message length
14 LPTSTR resMsg
; // for error message in OEM symbols
16 if( AllocAndLoadString( &lpUsage
,
17 GetModuleHandle(NULL
),
20 errLength
= strlen(lpUsage
) + 1;
21 resMsg
= (LPTSTR
)LocalAlloc(LPTR
, errLength
* sizeof(TCHAR
));
22 CharToOemBuff(lpUsage
, resMsg
, errLength
);
31 struct CommandLineOptions
{
32 BOOL abort
; // Not used yet
40 // This flag is used to distinguish between a user-initiated LOGOFF (which has value 0)
41 // and an underdetermined situation because user didn't give an argument to start Exit.
43 // flags is the type of shutdown to do - EWX_LOGOFF, EWX_REBOOT, EWX_POWEROFF, etc..
45 // reason is the System Shutdown Reason code. F.instance SHTDN_REASON_MAJOR_OTHER | SHTDN_REASON_MINOR_OTHER | SHTDN_REASON_FLAG_PLANNED.
49 // Takes the commandline arguments, and creates a struct which matches the arguments supplied.
50 static struct CommandLineOptions
ParseArguments(int argc
, TCHAR
*argv
[])
52 struct CommandLineOptions opts
;
55 // Reset all flags in struct
60 opts
.shutdown
= FALSE
;
62 for (i
= 1; i
< argc
; i
++)
64 if (argv
[i
][0] == '-' || argv
[i
][0] == '/')
87 // Unknown arguments will exit program.
98 // Converts the commandline arguments to flags used to shutdown computer
99 static struct ExitOptions
ParseCommandLineOptionsToExitOptions(struct CommandLineOptions opts
)
101 struct ExitOptions exitOpts
;
102 exitOpts
.shouldExit
= TRUE
;
104 // Sets ONE of the exit type flags
106 exitOpts
.flags
= EWX_LOGOFF
;
107 else if (opts
.restart
)
108 exitOpts
.flags
= EWX_REBOOT
;
109 else if(opts
.shutdown
)
110 exitOpts
.flags
= EWX_POWEROFF
;
114 exitOpts
.shouldExit
= FALSE
;
117 // Sets additional flags
120 exitOpts
.flags
= exitOpts
.flags
| EWX_FORCE
;
122 // This makes sure that we log off, also if there is only the "-f" option specified.
123 // The Windows shutdown utility does it the same way.
124 exitOpts
.shouldExit
= TRUE
;
127 // Reason for shutdown
128 // Hardcoded to "Other (Planned)"
129 exitOpts
.reason
= SHTDN_REASON_MAJOR_OTHER
| SHTDN_REASON_MINOR_OTHER
| SHTDN_REASON_FLAG_PLANNED
;
134 // Writes the last error as both text and error code to the console.
135 void DisplayLastError()
137 int errorCode
= GetLastError();
138 LPTSTR lpMsgBuf
= NULL
;
139 DWORD errLength
; // error message length
140 LPTSTR resMsg
; // for error message in OEM symbols
142 // Display the error message to the user
143 errLength
= FormatMessage(
144 FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
,
152 resMsg
= (LPTSTR
)LocalAlloc(LPTR
, errLength
* sizeof(TCHAR
));
153 CharToOemBuff(lpMsgBuf
, resMsg
, errLength
);
155 _ftprintf(stderr
, resMsg
);
156 _ftprintf(stderr
, _T("Error code: %d\n"), errorCode
);
162 void EnableShutdownPrivileges()
165 TOKEN_PRIVILEGES privs
;
167 // Check to see if the choosen action is allowed by the user. Everyone can call LogOff, but only privilieged users can shutdown/restart etc.
168 if (! OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES
, &token
))
174 // Get LUID (Locally Unique Identifier) for the privilege we need
175 if (!LookupPrivilegeValue(
176 NULL
, // system - NULL is localsystem
177 SE_SHUTDOWN_NAME
, // name of the privilege
178 &privs
.Privileges
[0].Luid
) // output
184 // and give our current process (i.e. shutdown.exe) the privilege to shutdown the machine.
185 privs
.PrivilegeCount
= 1;
186 privs
.Privileges
[0].Attributes
= SE_PRIVILEGE_ENABLED
;
187 if (AdjustTokenPrivileges(
192 (PTOKEN_PRIVILEGES
)NULL
, // previous state. Set to NULL, we don't care about previous state.
194 ) == 0) // return value 0 means failure
201 // Main entry for program
202 int _tmain(int argc
, TCHAR
*argv
[])
204 struct CommandLineOptions opts
;
205 struct ExitOptions exitOpts
;
207 if (argc
== 1) // i.e. no commandline arguments given
213 opts
= ParseArguments(argc
, argv
);
214 exitOpts
= ParseCommandLineOptionsToExitOptions(opts
);
216 // Perform the shutdown/restart etc. action
217 if (exitOpts
.shouldExit
)
219 EnableShutdownPrivileges();
221 if (!ExitWindowsEx(exitOpts
.flags
, exitOpts
.reason
))