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
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
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
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
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
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
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
162 ShutDown_SwitchUser(VOID)
163 {
164 }
165 
166 VOID
167 ShutDown_LockComputer(VOID)
168 {
169     if (!LockWorkStation())
170         ShowWin32Error(GetLastError());
171 }
172 
173 VOID
174 ShutDown_Disconnect(VOID)
175 {
176 }
177 
178 VOID
179 ShutDown_EjectComputer(VOID)
180 {
181 }
182