1 /*
2 * PROJECT: ReactOS Task Manager
3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4 * PURPOSE: System Shutdown.
5 * COPYRIGHT: Copyright 1999-2001 Brian Palmer <brianp@reactos.org>
6 * Copyright 2011 Mário Kacmár /Mario Kacmar/ aka Kario <kario@szm.sk>
7 * Copyright 2014 Robert Naumann <gonzomdx@gmail.com>
8 */
9
10 #include "precomp.h"
11 #include <ndk/exfuncs.h>
12 #include <ndk/pofuncs.h>
13 #include <ndk/rtlfuncs.h>
14
15 // Uncomment when NtInitiatePowerAction() is implemented
16 // #define NT_INITIATE_POWERACTION_IMPLEMENTED
17
18 static BOOL
EnablePrivilege(LPCWSTR lpszPrivilegeName,BOOL bEnablePrivilege)19 EnablePrivilege(LPCWSTR lpszPrivilegeName, BOOL bEnablePrivilege)
20 {
21 BOOL Success;
22 HANDLE hToken;
23 TOKEN_PRIVILEGES tp;
24
25 Success = OpenProcessToken(GetCurrentProcess(),
26 TOKEN_ADJUST_PRIVILEGES,
27 &hToken);
28 if (!Success) return Success;
29
30 Success = LookupPrivilegeValueW(NULL,
31 lpszPrivilegeName,
32 &tp.Privileges[0].Luid);
33 if (!Success) goto Quit;
34
35 tp.PrivilegeCount = 1;
36 tp.Privileges[0].Attributes = (bEnablePrivilege ? SE_PRIVILEGE_ENABLED : 0);
37
38 Success = AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL);
39
40 Quit:
41 CloseHandle(hToken);
42 return Success;
43 }
44
45 VOID
ShutDown_StandBy(VOID)46 ShutDown_StandBy(VOID)
47 {
48 NTSTATUS Status;
49
50 if (!EnablePrivilege(SE_SHUTDOWN_NAME, TRUE))
51 {
52 ShowWin32Error(GetLastError());
53 return;
54 }
55
56 #ifdef NT_INITIATE_POWERACTION_IMPLEMENTED
57 Status = NtInitiatePowerAction(PowerActionSleep,
58 PowerSystemSleeping1,
59 0, FALSE);
60 #else
61 Status = NtSetSystemPowerState(PowerActionSleep,
62 PowerSystemSleeping1,
63 0);
64 #endif
65
66 if (!NT_SUCCESS(Status))
67 ShowWin32Error(RtlNtStatusToDosError(Status));
68
69 EnablePrivilege(SE_SHUTDOWN_NAME, FALSE);
70 }
71
72 VOID
ShutDown_Hibernate(VOID)73 ShutDown_Hibernate(VOID)
74 {
75 NTSTATUS Status;
76
77 if (!EnablePrivilege(SE_SHUTDOWN_NAME, TRUE))
78 {
79 ShowWin32Error(GetLastError());
80 return;
81 }
82
83 #ifdef NT_INITIATE_POWERACTION_IMPLEMENTED
84 Status = NtInitiatePowerAction(PowerActionHibernate,
85 PowerSystemHibernate,
86 0, FALSE);
87 #else
88 Status = NtSetSystemPowerState(PowerActionHibernate,
89 PowerSystemHibernate,
90 0);
91 #endif
92
93 if (!NT_SUCCESS(Status))
94 ShowWin32Error(RtlNtStatusToDosError(Status));
95
96 EnablePrivilege(SE_SHUTDOWN_NAME, FALSE);
97 }
98
99 VOID
ShutDown_PowerOff(VOID)100 ShutDown_PowerOff(VOID)
101 {
102 /* Trick: on Windows, pressing the CTRL key forces shutdown via NT API */
103 BOOL ForceShutdown = !!(GetKeyState(VK_CONTROL) & 0x8000);
104
105 if (!EnablePrivilege(SE_SHUTDOWN_NAME, TRUE))
106 {
107 ShowWin32Error(GetLastError());
108 return;
109 }
110
111 if (ForceShutdown)
112 {
113 NTSTATUS Status = NtShutdownSystem(ShutdownPowerOff);
114 if (!NT_SUCCESS(Status))
115 ShowWin32Error(RtlNtStatusToDosError(Status));
116 }
117 else
118 {
119 // The choice of EWX_SHUTDOWN or EWX_POWEROFF may be done with NtPowerInformation
120 if (!ExitWindowsEx(EWX_POWEROFF /* EWX_SHUTDOWN */, SHTDN_REASON_MAJOR_OTHER | SHTDN_REASON_MINOR_OTHER))
121 ShowWin32Error(GetLastError());
122 }
123
124 EnablePrivilege(SE_SHUTDOWN_NAME, FALSE);
125 }
126
127 VOID
ShutDown_Reboot(VOID)128 ShutDown_Reboot(VOID)
129 {
130 /* Trick: on Windows, pressing the CTRL key forces reboot via NT API */
131 BOOL ForceReboot = !!(GetKeyState(VK_CONTROL) & 0x8000);
132
133 if (!EnablePrivilege(SE_SHUTDOWN_NAME, TRUE))
134 {
135 ShowWin32Error(GetLastError());
136 return;
137 }
138
139 if (ForceReboot)
140 {
141 NTSTATUS Status = NtShutdownSystem(ShutdownReboot);
142 if (!NT_SUCCESS(Status))
143 ShowWin32Error(RtlNtStatusToDosError(Status));
144 }
145 else
146 {
147 if (!ExitWindowsEx(EWX_REBOOT, SHTDN_REASON_MAJOR_OTHER | SHTDN_REASON_MINOR_OTHER))
148 ShowWin32Error(GetLastError());
149 }
150
151 EnablePrivilege(SE_SHUTDOWN_NAME, FALSE);
152 }
153
154 VOID
ShutDown_LogOffUser(VOID)155 ShutDown_LogOffUser(VOID)
156 {
157 if (!ExitWindowsEx(EWX_LOGOFF, SHTDN_REASON_MAJOR_OTHER | SHTDN_REASON_MINOR_OTHER))
158 ShowWin32Error(GetLastError());
159 }
160
161 VOID
ShutDown_SwitchUser(VOID)162 ShutDown_SwitchUser(VOID)
163 {
164 }
165
166 VOID
ShutDown_LockComputer(VOID)167 ShutDown_LockComputer(VOID)
168 {
169 if (!LockWorkStation())
170 ShowWin32Error(GetLastError());
171 }
172
173 VOID
ShutDown_Disconnect(VOID)174 ShutDown_Disconnect(VOID)
175 {
176 }
177
178 VOID
ShutDown_EjectComputer(VOID)179 ShutDown_EjectComputer(VOID)
180 {
181 }
182