ReactOS  0.4.13-dev-99-g7e18b6d
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 
11 DBG_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  */
21 LRESULT
25 {
26  LPARAM lParams;
27  BOOL KillTimers;
28  INT i;
29  LRESULT lResult = MCSR_GOODFORSHUTDOWN;
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 
91 BOOLEAN
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 
120 BOOL
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");
154  UserPostMessage(hwndSAS, WM_LOGONNOTIFY, Notif, (LPARAM)Param);
155  return TRUE;
156  }
157  else
158  {
159  ERR("hwndSAS == NULL\n");
160  }
161 
162  return FALSE;
163 }
164 
165 NTSTATUS
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
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");
208  return STATUS_INVALID_HANDLE;
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  */
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");
226  return STATUS_INVALID_HANDLE;
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");
233  return STATUS_ACCESS_DENIED;
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 
289 NTSTATUS
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 */
VOID NTAPI SeCaptureSubjectContext(OUT PSECURITY_SUBJECT_CONTEXT SubjectContext)
Definition: access.c:301
#define MCSR_GOODFORSHUTDOWN
Definition: undocuser.h:106
#define IN
Definition: typedefs.h:38
BOOL FASTCALL UserPostMessage(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam)
Definition: message.c:1181
#define STATUS_PRIVILEGE_NOT_HELD
Definition: DriverTester.h:9
_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:2239
#define WINSTA_EXITWINDOWS
Definition: winuser.h:413
VOID NTAPI SeReleaseSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
Definition: access.c:360
#define MCSR_DONOTSHUTDOWN
Definition: undocuser.h:108
#define TRUE
Definition: types.h:120
BOOL NotifyLogon(IN HWND hWndSta, IN PLUID CallerLuid, IN ULONG Flags, IN NTSTATUS ShutdownStatus)
Definition: shutdown.c:121
#define LN_LOGOFF_CANCELED
Definition: undocuser.h:120
VOID NTAPI SeUnlockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
Definition: access.c:336
PVOID NTAPI PsGetProcessWin32Process(PEPROCESS Process)
Definition: process.c:1193
LONG NTSTATUS
Definition: precomp.h:26
NTSTATUS UserEndShutdown(IN PETHREAD Thread, IN NTSTATUS ShutdownStatus)
Definition: shutdown.c:290
#define WM_QUERYENDSESSION
Definition: winuser.h:1604
VOID NTAPI SeLockSubjectContext(IN PSECURITY_SUBJECT_CONTEXT SubjectContext)
Definition: access.c:314
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
UINT_PTR WPARAM
Definition: windef.h:207
struct _WINSTATION_OBJECT * prpwinsta
Definition: win32.h:257
DBG_DEFAULT_CHANNEL(UserShutdown)
int32_t INT
Definition: typedefs.h:56
WPARAM wParam
Definition: combotst.c:138
#define STATUS_INVALID_HANDLE
Definition: ntstatus.h:231
#define EWX_CALLER_WINLOGON
Definition: undocuser.h:127
BOOL FASTCALL DestroyTimersForWindow(PTHREADINFO pti, PWND Window)
Definition: timer.c:522
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
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 EWX_SHUTDOWN
Definition: winuser.h:634
unsigned int BOOL
Definition: ntddk_ex.h:94
#define RtlEqualLuid(Luid1, Luid2)
Definition: rtlfuncs.h:301
#define PRIVILEGE_SET_ALL_NECESSARY
Definition: setypes.h:83
#define EWX_CALLER_SYSTEM
Definition: undocuser.h:126
#define LN_LOGOFF
Definition: undocuser.h:113
PEPROCESS PsGetThreadProcess(_In_ PETHREAD Thread)
THRDESKHEAD head
Definition: ntuser.h:659
#define WSS_NOIO
Definition: winsta.h:9
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
_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
LONG_PTR LPARAM
Definition: windef.h:208
#define SE_SHUTDOWN_PRIVILEGE
Definition: security.c:673
PWND FASTCALL UserGetWindowObject(HWND hWnd)
Definition: window.c:103
HWND hwndSAS
Definition: winsta.c:24
#define EWX_SHUTDOWN_CANCELED
Definition: undocuser.h:125
#define TRACE(s)
Definition: solgame.cpp:4
LIST_ENTRY List
Definition: psmgr.c:57
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
HANDLE NTAPI PsGetThreadProcessId(IN PETHREAD Thread)
Definition: thread.c:745
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
BOOL Privilege(LPTSTR pszPrivilege, BOOL bEnable)
Definition: user_lib.cpp:531
#define WM_ENDSESSION
Definition: winuser.h:1609
LRESULT FASTCALL co_IntSendMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
Definition: message.c:1281
#define MCSR_SHUTDOWNFINISHED
Definition: undocuser.h:107
#define MCS_ENDSESSION
Definition: undocuser.h:103
HWND *FASTCALL IntWinListChildren(PWND Window)
Definition: window.c:255
#define EWX_NONOTIFY
Definition: undocuser.h:133
#define WM_LOGONNOTIFY
Definition: undocuser.h:37
static ULONG gdwShutdownFlags
Definition: shutdown.c:14
BOOLEAN NTAPI SePrivilegeCheck(PPRIVILEGE_SET Privileges, PSECURITY_SUBJECT_CONTEXT SubjectContext, KPROCESSOR_MODE PreviousMode)
Definition: priv.c:491
#define SYSTEM_LUID
Definition: setypes.h:672
BOOLEAN HasPrivilege(IN PPRIVILEGE_SET Privilege)
Definition: shutdown.c:92
Status
Definition: gdiplustypes.h:24
#define ERR(fmt,...)
Definition: debug.h:109
Definition: ntuser.h:657
NTSTATUS GetProcessLuid(IN PETHREAD Thread OPTIONAL, IN PEPROCESS Process OPTIONAL, OUT PLUID Luid)
Definition: misc.c:789
unsigned int * PULONG
Definition: retypes.h:1
NTSYSAPI BOOLEAN NTAPI RtlAreAllAccessesGranted(ACCESS_MASK GrantedAccess, ACCESS_MASK DesiredAccess)
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)
Definition: audit.c:845
#define OUT
Definition: typedefs.h:39
NTSTATUS UserInitiateShutdown(IN PETHREAD Thread, IN OUT PULONG pFlags)
Definition: shutdown.c:166
unsigned int ULONG
Definition: retypes.h:1
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
#define USERTAG_WINDOWLIST
Definition: tags.h:297
LONG_PTR LRESULT
Definition: windef.h:209
return STATUS_SUCCESS
Definition: btrfs.c:2725
ACCESS_MASK amwinsta
Definition: win32.h:259
LPARAM lParam
Definition: combotst.c:139
#define MCS_QUERYENDSESSION
Definition: undocuser.h:104
HANDLE gpidLogon
Definition: simplecall.c:15
LRESULT IntClientShutdown(IN PWND pWindow, IN WPARAM wParam, IN LPARAM lParam)
Definition: shutdown.c:22