1 /*
2  *  ReactOS Task Manager
3  *
4  *  shutdown.c
5  *
6  *  Copyright (C) 1999 - 2001  Brian Palmer  <brianp@reactos.org>
7  *                2011         M�rio Kacm�r /Mario Kacmar/ aka Kario (kario@szm.sk)
8  *                2014         Robert Naumann  <gonzomdx@gmail.com>
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
23  */
24 
25 #include "precomp.h"
26 #include <ndk/exfuncs.h>
27 #include <ndk/pofuncs.h>
28 #include <ndk/rtlfuncs.h>
29 
30 // Uncomment when NtInitiatePowerAction() is implemented
31 // #define NT_INITIATE_POWERACTION_IMPLEMENTED
32 
33 static BOOL
34 EnablePrivilege(LPCWSTR lpszPrivilegeName, BOOL bEnablePrivilege)
35 {
36     BOOL   Success;
37     HANDLE hToken;
38     TOKEN_PRIVILEGES tp;
39 
40     Success = OpenProcessToken(GetCurrentProcess(),
41                                TOKEN_ADJUST_PRIVILEGES,
42                                &hToken);
43     if (!Success) return Success;
44 
45     Success = LookupPrivilegeValueW(NULL,
46                                     lpszPrivilegeName,
47                                     &tp.Privileges[0].Luid);
48     if (!Success) goto Quit;
49 
50     tp.PrivilegeCount = 1;
51     tp.Privileges[0].Attributes = (bEnablePrivilege ? SE_PRIVILEGE_ENABLED : 0);
52 
53     Success = AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL);
54 
55 Quit:
56     CloseHandle(hToken);
57     return Success;
58 }
59 
60 VOID
61 ShutDown_StandBy(VOID)
62 {
63     NTSTATUS Status;
64 
65     if (!EnablePrivilege(SE_SHUTDOWN_NAME, TRUE))
66     {
67         ShowWin32Error(GetLastError());
68         return;
69     }
70 
71 #ifdef NT_INITIATE_POWERACTION_IMPLEMENTED
72     Status = NtInitiatePowerAction(PowerActionSleep,
73                                    PowerSystemSleeping1,
74                                    0, FALSE);
75 #else
76     Status = NtSetSystemPowerState(PowerActionSleep,
77                                    PowerSystemSleeping1,
78                                    0);
79 #endif
80 
81     if (!NT_SUCCESS(Status))
82         ShowWin32Error(RtlNtStatusToDosError(Status));
83 
84     EnablePrivilege(SE_SHUTDOWN_NAME, FALSE);
85 }
86 
87 VOID
88 ShutDown_Hibernate(VOID)
89 {
90     NTSTATUS Status;
91 
92     if (!EnablePrivilege(SE_SHUTDOWN_NAME, TRUE))
93     {
94         ShowWin32Error(GetLastError());
95         return;
96     }
97 
98 #ifdef NT_INITIATE_POWERACTION_IMPLEMENTED
99     Status = NtInitiatePowerAction(PowerActionHibernate,
100                                    PowerSystemHibernate,
101                                    0, FALSE);
102 #else
103     Status = NtSetSystemPowerState(PowerActionHibernate,
104                                    PowerSystemHibernate,
105                                    0);
106 #endif
107 
108     if (!NT_SUCCESS(Status))
109         ShowWin32Error(RtlNtStatusToDosError(Status));
110 
111     EnablePrivilege(SE_SHUTDOWN_NAME, FALSE);
112 }
113 
114 VOID
115 ShutDown_PowerOff(VOID)
116 {
117     /* Trick: on Windows, pressing the CTRL key forces shutdown via NT API */
118     BOOL ForceShutdown = !!(GetKeyState(VK_CONTROL) & 0x8000);
119 
120     if (!EnablePrivilege(SE_SHUTDOWN_NAME, TRUE))
121     {
122         ShowWin32Error(GetLastError());
123         return;
124     }
125 
126     if (ForceShutdown)
127     {
128         NTSTATUS Status = NtShutdownSystem(ShutdownPowerOff);
129         if (!NT_SUCCESS(Status))
130             ShowWin32Error(RtlNtStatusToDosError(Status));
131     }
132     else
133     {
134         // The choice of EWX_SHUTDOWN or EWX_POWEROFF may be done with NtPowerInformation
135         if (!ExitWindowsEx(EWX_POWEROFF /* EWX_SHUTDOWN */, SHTDN_REASON_MAJOR_OTHER | SHTDN_REASON_MINOR_OTHER))
136             ShowWin32Error(GetLastError());
137     }
138 
139     EnablePrivilege(SE_SHUTDOWN_NAME, FALSE);
140 }
141 
142 VOID
143 ShutDown_Reboot(VOID)
144 {
145     /* Trick: on Windows, pressing the CTRL key forces reboot via NT API */
146     BOOL ForceReboot = !!(GetKeyState(VK_CONTROL) & 0x8000);
147 
148     if (!EnablePrivilege(SE_SHUTDOWN_NAME, TRUE))
149     {
150         ShowWin32Error(GetLastError());
151         return;
152     }
153 
154     if (ForceReboot)
155     {
156         NTSTATUS Status = NtShutdownSystem(ShutdownReboot);
157         if (!NT_SUCCESS(Status))
158             ShowWin32Error(RtlNtStatusToDosError(Status));
159     }
160     else
161     {
162         if (!ExitWindowsEx(EWX_REBOOT, SHTDN_REASON_MAJOR_OTHER | SHTDN_REASON_MINOR_OTHER))
163             ShowWin32Error(GetLastError());
164     }
165 
166     EnablePrivilege(SE_SHUTDOWN_NAME, FALSE);
167 }
168 
169 VOID
170 ShutDown_LogOffUser(VOID)
171 {
172     if (!ExitWindowsEx(EWX_LOGOFF, SHTDN_REASON_MAJOR_OTHER | SHTDN_REASON_MINOR_OTHER))
173         ShowWin32Error(GetLastError());
174 }
175 
176 VOID
177 ShutDown_SwitchUser(VOID)
178 {
179 }
180 
181 VOID
182 ShutDown_LockComputer(VOID)
183 {
184     if (!LockWorkStation())
185         ShowWin32Error(GetLastError());
186 }
187 
188 VOID
189 ShutDown_Disconnect(VOID)
190 {
191 }
192 
193 VOID
194 ShutDown_EjectComputer(VOID)
195 {
196 }
197