ReactOS 0.4.15-dev-5667-ged97270
shutdown.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Win32k subsystem
4 * PURPOSE: Shutdown routines
5 * FILE: win32ss/user/ntuser/shutdown.c
6 * PROGRAMER: Hermes Belusca
7 */
8
9#include <win32k.h>
10
11DBG_DEFAULT_CHANNEL(UserShutdown);
12
13/* Our local copy of shutdown flags */
15
16/*
17 * Based on CSRSS and described in pages 1115 - 1118 "Windows Internals, Fifth Edition".
18 * CSRSS sends WM_CLIENTSHUTDOWN messages to top-level windows, and it is our job
19 * to send WM_QUERYENDSESSION / WM_ENDSESSION messages in response.
20 */
25{
26 LPARAM lParams;
27 BOOL KillTimers;
28 INT i;
30 HWND *List;
31
32 KillTimers = wParam & MCS_ENDSESSION ? TRUE : FALSE;
33 lParams = lParam & (ENDSESSION_LOGOFF | ENDSESSION_CRITICAL | ENDSESSION_CLOSEAPP);
34
35 /* First, send end sessions to children */
36 List = IntWinListChildren(pWindow);
37
38 if (List)
39 {
40 for (i = 0; List[i]; i++)
41 {
42 PWND WndChild;
43
44 if (!(WndChild = UserGetWindowObject(List[i])))
45 continue;
46
48 {
49 if (!co_IntSendMessage(WndChild->head.h, WM_QUERYENDSESSION, 0, lParams))
50 {
51 lResult = MCSR_DONOTSHUTDOWN;
52 break;
53 }
54 }
55 else
56 {
57 co_IntSendMessage(WndChild->head.h, WM_ENDSESSION, KillTimers, lParams);
58 if (KillTimers)
59 {
60 DestroyTimersForWindow(WndChild->head.pti, WndChild);
61 }
62 lResult = MCSR_SHUTDOWNFINISHED;
63 }
64 }
66 if (lResult == MCSR_DONOTSHUTDOWN)
67 return lResult;
68 }
69
70 /* Send to the caller */
72 {
73 if (!co_IntSendMessage(pWindow->head.h, WM_QUERYENDSESSION, 0, lParams))
74 {
75 lResult = MCSR_DONOTSHUTDOWN;
76 }
77 }
78 else
79 {
80 co_IntSendMessage(pWindow->head.h, WM_ENDSESSION, KillTimers, lParams);
81 if (KillTimers)
82 {
83 DestroyTimersForWindow(pWindow->head.pti, pWindow);
84 }
85 lResult = MCSR_SHUTDOWNFINISHED;
86 }
87
88 return lResult;
89}
90
93{
96
97 /* Capture and lock the security subject context */
100
101 /* Do privilege check */
103
104 /* Audit the privilege */
105#if 0
108 0,
109 Privilege,
110 Result,
111 UserMode);
112#endif
113
114 /* Unlock and release the security subject context and return */
117 return Result;
118}
119
120BOOL
122 IN PLUID CallerLuid,
123 IN ULONG Flags,
124 IN NTSTATUS ShutdownStatus)
125{
126 // LUID SystemLuid = SYSTEM_LUID;
127 ULONG Notif, Param;
128
129 ERR("NotifyLogon(0x%lx, 0x%lx)\n", Flags, ShutdownStatus);
130
131 /* If no Winlogon notifications are needed, just return */
132 if (Flags & EWX_NONOTIFY)
133 return FALSE;
134
135 /* In case we cancelled the shutdown...*/
137 {
138 /* ... send a LN_LOGOFF_CANCELED to Winlogon with the real cancel status... */
139 Notif = LN_LOGOFF_CANCELED;
140 Param = ShutdownStatus;
141 }
142 else
143 {
144 /* ... otherwise it's a real logoff. Send the shutdown flags in that case. */
145 Notif = LN_LOGOFF;
146 Param = Flags;
147 }
148
149 // FIXME: At the moment, always send the notifications... In real world some checks are done.
150 // if (hwndSAS && ( (Flags & EWX_SHUTDOWN) || RtlEqualLuid(CallerLuid, &SystemLuid)) )
151 if (hwndSAS)
152 {
153 TRACE("\tSending %s message to Winlogon\n", Notif == LN_LOGOFF ? "LN_LOGOFF" : "LN_LOGOFF_CANCELED");
155 return TRUE;
156 }
157 else
158 {
159 ERR("hwndSAS == NULL\n");
160 }
161
162 return FALSE;
163}
164
167 IN OUT PULONG pFlags)
168{
170 ULONG Flags = *pFlags;
171 LUID CallerLuid;
172 LUID SystemLuid = SYSTEM_LUID;
173 static PRIVILEGE_SET ShutdownPrivilege =
174 {
176 { {{SE_SHUTDOWN_PRIVILEGE, 0}, 0} }
177 };
178
179 PPROCESSINFO ppi;
180
181 TRACE("UserInitiateShutdown\n");
182
183 /* Get the caller's LUID */
184 Status = GetProcessLuid(Thread, NULL, &CallerLuid);
185 if (!NT_SUCCESS(Status))
186 {
187 ERR("UserInitiateShutdown: GetProcessLuid failed\n");
188 return Status;
189 }
190
191 /*
192 * Check if this is the System LUID, and adjust flags if needed.
193 * In particular, be sure there is no EWX_CALLER_SYSTEM flag
194 * spuriously set (could be the sign of malicous app!).
195 */
196 if (RtlEqualLuid(&CallerLuid, &SystemLuid))
198 else
199 Flags &= ~EWX_CALLER_SYSTEM;
200
201 *pFlags = Flags;
202
203 /* Retrieve the Win32 process info */
205 if (ppi == NULL)
206 {
207 ERR("UserInitiateShutdown: Failed to get win32 thread!\n");
209 }
210
211 /* If the caller is not Winlogon, do some security checks */
213 {
214 /*
215 * Here also, be sure there is no EWX_CALLER_WINLOGON flag
216 * spuriously set (could be the sign of malicous app!).
217 */
218 Flags &= ~EWX_CALLER_WINLOGON;
219
220 *pFlags = Flags;
221
222 /* Check whether the current process is attached to a window station */
223 if (ppi->prpwinsta == NULL)
224 {
225 ERR("UserInitiateShutdown: Process is not attached to a desktop\n");
227 }
228
229 /* Check whether the window station of the current process can send exit requests */
231 {
232 ERR("UserInitiateShutdown: Caller doesn't have the rights to shutdown\n");
234 }
235
236 /*
237 * NOTE: USERSRV automatically adds the shutdown flag when we poweroff or reboot.
238 *
239 * If the caller wants to shutdown / reboot / power-off...
240 */
241 if (Flags & EWX_SHUTDOWN)
242 {
243 /* ... check whether it has shutdown privilege */
244 if (!HasPrivilege(&ShutdownPrivilege))
245 {
246 ERR("UserInitiateShutdown: Caller doesn't have the rights to shutdown\n");
248 }
249 }
250 else
251 {
252 /*
253 * ... but if it just wants to log-off, in case its
254 * window station is a non-IO one, fail the call.
255 */
256 if (ppi->prpwinsta->Flags & WSS_NOIO)
257 {
258 ERR("UserInitiateShutdown: Caller doesn't have the rights to logoff\n");
260 }
261 }
262 }
263
264 /* If the caller is not Winlogon, possibly notify it to perform the real shutdown */
266 {
267 // FIXME: HACK!! Do more checks!!
268 TRACE("UserInitiateShutdown: Notify Winlogon for shutdown\n");
269 NotifyLogon(hwndSAS, &CallerLuid, Flags, STATUS_SUCCESS);
270 return STATUS_PENDING;
271 }
272
273 // If we reach this point, that means it's Winlogon that triggered the shutdown.
274 TRACE("UserInitiateShutdown: Winlogon is doing a shutdown\n");
275
276 /*
277 * Update and save the shutdown flags globally for renotifying
278 * Winlogon if needed, when calling EndShutdown.
279 */
280 Flags |= EWX_CALLER_WINLOGON; // Winlogon is doing a shutdown, be sure the internal flag is set.
281 *pFlags = Flags;
282
283 /* Save the shutdown flags now */
285
286 return STATUS_SUCCESS;
287}
288
291 IN NTSTATUS ShutdownStatus)
292{
294 ULONG Flags;
295 LUID CallerLuid;
296
297 TRACE("UserEndShutdown called\n");
298
299 /*
300 * FIXME: Some cleanup should be done when shutdown succeeds,
301 * and some reset should be done when shutdown is cancelled.
302 */
303 //STUB;
304
305 Status = GetProcessLuid(Thread, NULL, &CallerLuid);
306 if (!NT_SUCCESS(Status))
307 {
308 ERR("UserEndShutdown: GetProcessLuid failed\n");
309 return Status;
310 }
311
312 /* Copy the global flags because we're going to modify them for our purposes */
314
315 if (NT_SUCCESS(ShutdownStatus))
316 {
317 /* Just report success, and keep the shutdown flags as they are */
318 ShutdownStatus = STATUS_SUCCESS;
319 }
320 else
321 {
322 /* Report the status to Winlogon and say that we cancel the shutdown */
324 // FIXME: Should we reset gdwShutdownFlags to 0 ??
325 }
326
327 TRACE("UserEndShutdown: Notify Winlogon for end of shutdown\n");
328 NotifyLogon(hwndSAS, &CallerLuid, Flags, ShutdownStatus);
329
330 /* Always return success */
331 return STATUS_SUCCESS;
332}
333
334/* EOF */
#define STATUS_PRIVILEGE_NOT_HELD
Definition: DriverTester.h:9
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
#define ERR(fmt,...)
Definition: debug.h:110
#define DBG_DEFAULT_CHANNEL(ch)
Definition: debug.h:103
PEPROCESS __stdcall PsGetThreadProcess(_In_ PETHREAD Thread)
WPARAM wParam
Definition: combotst.c:138
LPARAM lParam
Definition: combotst.c:139
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
unsigned int BOOL
Definition: ntddk_ex.h:94
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
_Inout_ PLIST_ENTRY _In_ PVOID _In_ PSTRING _In_ BOOLEAN _In_ BOOLEAN _In_ ULONG _In_ PFLT_CALLBACK_DATA _In_opt_ PCHECK_FOR_TRAVERSE_ACCESS _In_opt_ PSECURITY_SUBJECT_CONTEXT SubjectContext
Definition: fltkernel.h:2246
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
#define SE_SHUTDOWN_PRIVILEGE
Definition: security.c:673
#define UserMode
Definition: asm.h:35
NTSYSAPI BOOLEAN NTAPI RtlAreAllAccessesGranted(ACCESS_MASK GrantedAccess, ACCESS_MASK DesiredAccess)
PVOID NTAPI PsGetProcessWin32Process(PEPROCESS Process)
Definition: process.c:1193
HANDLE NTAPI PsGetThreadProcessId(IN PETHREAD Thread)
Definition: thread.c:745
VOID NTAPI SePrivilegeObjectAuditAlarm(_In_ HANDLE Handle, _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext, _In_ ACCESS_MASK DesiredAccess, _In_ PPRIVILEGE_SET Privileges, _In_ BOOLEAN AccessGranted, _In_ KPROCESSOR_MODE CurrentMode)
Raises an audit with alarm notification message when an object tries to acquire this privilege.
Definition: audit.c:1321
BOOLEAN NTAPI SePrivilegeCheck(_In_ PPRIVILEGE_SET Privileges, _In_ PSECURITY_SUBJECT_CONTEXT SubjectContext, _In_ KPROCESSOR_MODE PreviousMode)
Checks if a set of privileges exist and match within a security subject context.
Definition: priv.c:698
#define STATUS_INVALID_HANDLE
Definition: ntstatus.h:245
#define STATUS_PENDING
Definition: ntstatus.h:82
HWND hwndSAS
Definition: winsta.c:24
#define STATUS_SUCCESS
Definition: shellext.h:65
HANDLE gpidLogon
Definition: simplecall.c:15
#define TRACE(s)
Definition: solgame.cpp:4
ACCESS_MASK amwinsta
Definition: win32.h:268
struct _WINSTATION_OBJECT * prpwinsta
Definition: win32.h:266
Definition: ntuser.h:689
THRDESKHEAD head
Definition: ntuser.h:690
VOID NTAPI SeLockSubjectContext(_In_ PSECURITY_SUBJECT_CONTEXT SubjectContext)
Locks both the referenced primary and client access tokens of a security subject context.
Definition: subject.c:107
VOID NTAPI SeReleaseSubjectContext(_In_ PSECURITY_SUBJECT_CONTEXT SubjectContext)
Releases both the primary and client tokens of a security subject context.
Definition: subject.c:171
VOID NTAPI SeUnlockSubjectContext(_In_ PSECURITY_SUBJECT_CONTEXT SubjectContext)
Unlocks both the referenced primary and client access tokens of a security subject context.
Definition: subject.c:138
VOID NTAPI SeCaptureSubjectContext(_Out_ PSECURITY_SUBJECT_CONTEXT SubjectContext)
Captures the security subject context of the calling thread and calling process.
Definition: subject.c:85
uint32_t * PULONG
Definition: typedefs.h:59
int32_t INT
Definition: typedefs.h:58
#define IN
Definition: typedefs.h:39
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
#define EWX_SHUTDOWN_CANCELED
Definition: undocuser.h:127
#define MCSR_GOODFORSHUTDOWN
Definition: undocuser.h:108
#define EWX_CALLER_SYSTEM
Definition: undocuser.h:128
#define EWX_NONOTIFY
Definition: undocuser.h:135
#define MCS_QUERYENDSESSION
Definition: undocuser.h:106
#define MCSR_SHUTDOWNFINISHED
Definition: undocuser.h:109
#define MCS_ENDSESSION
Definition: undocuser.h:105
#define WM_LOGONNOTIFY
Definition: undocuser.h:37
#define EWX_CALLER_WINLOGON
Definition: undocuser.h:129
#define LN_LOGOFF
Definition: undocuser.h:115
#define MCSR_DONOTSHUTDOWN
Definition: undocuser.h:110
#define LN_LOGOFF_CANCELED
Definition: undocuser.h:122
BOOL Privilege(LPTSTR pszPrivilege, BOOL bEnable)
Definition: user_lib.cpp:531
PWND FASTCALL UserGetWindowObject(HWND hWnd)
Definition: window.c:134
_Must_inspect_result_ _In_ WDFCMRESLIST List
Definition: wdfresource.h:550
BOOL FASTCALL UserPostMessage(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam)
Definition: message.c:1346
LRESULT FASTCALL co_IntSendMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
Definition: message.c:1446
NTSTATUS GetProcessLuid(IN PETHREAD Thread OPTIONAL, IN PEPROCESS Process OPTIONAL, OUT PLUID Luid)
Definition: misc.c:809
static ULONG gdwShutdownFlags
Definition: shutdown.c:14
NTSTATUS UserEndShutdown(IN PETHREAD Thread, IN NTSTATUS ShutdownStatus)
Definition: shutdown.c:290
BOOLEAN HasPrivilege(IN PPRIVILEGE_SET Privilege)
Definition: shutdown.c:92
NTSTATUS UserInitiateShutdown(IN PETHREAD Thread, IN OUT PULONG pFlags)
Definition: shutdown.c:166
BOOL NotifyLogon(IN HWND hWndSta, IN PLUID CallerLuid, IN ULONG Flags, IN NTSTATUS ShutdownStatus)
Definition: shutdown.c:121
LRESULT IntClientShutdown(IN PWND pWindow, IN WPARAM wParam, IN LPARAM lParam)
Definition: shutdown.c:22
#define USERTAG_WINDOWLIST
Definition: tags.h:298
BOOL FASTCALL DestroyTimersForWindow(PTHREADINFO pti, PWND Window)
Definition: timer.c:522
HWND *FASTCALL IntWinListChildren(PWND Window)
Definition: window.c:286
#define WSS_NOIO
Definition: winsta.h:9
LONG_PTR LPARAM
Definition: windef.h:208
LONG_PTR LRESULT
Definition: windef.h:209
UINT_PTR WPARAM
Definition: windef.h:207
#define EWX_SHUTDOWN
Definition: winuser.h:634
#define WINSTA_EXITWINDOWS
Definition: winuser.h:413
#define WM_QUERYENDSESSION
Definition: winuser.h:1612
#define WM_ENDSESSION
Definition: winuser.h:1617
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define RtlEqualLuid(Luid1, Luid2)
Definition: rtlfuncs.h:301
#define SYSTEM_LUID
Definition: setypes.h:700
#define PRIVILEGE_SET_ALL_NECESSARY
Definition: setypes.h:83