Skip to content

Commit 0b6cd57

Browse files
committed
[WIN32K]
- Add (yet another) shutdown.c file, and import trunk's shutdown code there. Key parts are turned off now. - Enable respective parts in the NtUserSetInformationThread. - Include undocuser.h svn path=/branches/arwinss/; revision=70343
1 parent ed047f5 commit 0b6cd57

File tree

5 files changed

+281
-5
lines changed

5 files changed

+281
-5
lines changed

arwinss/server/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ list(APPEND SOURCE
8888
main/kbdlayout.c
8989
main/keyboard.c
9090
main/misc.c
91+
main/shutdown.c
9192
swm/winman.c
9293
wine/atom.c
9394
wine/class.c

arwinss/server/include/shutdown.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#pragma once
2+
3+
NTSTATUS
4+
UserInitiateShutdown(IN PETHREAD Thread,
5+
IN OUT PULONG pFlags);
6+
7+
NTSTATUS
8+
UserEndShutdown(IN PETHREAD Thread,
9+
IN NTSTATUS ShutdownStatus);

arwinss/server/include/win32k.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ typedef struct _SECURITY_ATTRIBUTES SECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES;
5252
#include <ntgdihdl.h>
5353
#include <ntgdi.h>
5454

55+
/* Undocumented user definitions */
56+
#include <undocuser.h>
57+
5558
/* Internal Win32K Header */
5659
#include <win32kp.h>
5760

arwinss/server/main/misc.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
#include <debug.h>
1515

1616
#include <ntstatus.h>
17-
//#include <shutdown.h>
17+
#include <shutdown.h>
1818
#include <csr.h>
1919

2020
extern PEPROCESS CsrProcess;
@@ -72,8 +72,7 @@ NtUserSetInformationThread(IN HANDLE ThreadHandle,
7272
}
7373
_SEH2_END;
7474

75-
Status = STATUS_NOT_IMPLEMENTED; //UserInitiateShutdown(Thread, &CapturedFlags);
76-
UNIMPLEMENTED;
75+
Status = UserInitiateShutdown(Thread, &CapturedFlags);
7776

7877
/* Return the modified value to the caller */
7978
_SEH2_TRY
@@ -115,8 +114,7 @@ NtUserSetInformationThread(IN HANDLE ThreadHandle,
115114
}
116115
_SEH2_END;
117116

118-
Status = STATUS_NOT_IMPLEMENTED; //UserEndShutdown(Thread, ShutdownStatus);
119-
UNIMPLEMENTED;
117+
Status = UserEndShutdown(Thread, ShutdownStatus);
120118
break;
121119
}
122120

arwinss/server/main/shutdown.c

Lines changed: 265 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,265 @@
1+
/*
2+
* PROJECT: ReactOS Win32K
3+
* LICENSE: GPL - See COPYING in the top level directory
4+
* FILE: server/main/misc.c
5+
* PURPOSE: Shutdown code
6+
* PROGRAMMERS: Aleksey Bragin ([email protected])
7+
*/
8+
9+
/* INCLUDES ******************************************************************/
10+
11+
#include <win32k.h>
12+
13+
//#define NDEBUG
14+
#include <debug.h>
15+
16+
#include <ntstatus.h>
17+
18+
/* Our local copy of shutdown flags */
19+
static ULONG gdwShutdownFlags = 0;
20+
21+
HWND hwndSAS = NULL;
22+
23+
NTSTATUS
24+
GetProcessLuid(IN PETHREAD Thread OPTIONAL,
25+
OUT PLUID Luid)
26+
{
27+
NTSTATUS Status;
28+
PACCESS_TOKEN Token;
29+
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
30+
BOOLEAN CopyOnOpen, EffectiveOnly;
31+
32+
if (Thread == NULL)
33+
Thread = PsGetCurrentThread();
34+
35+
/* Use a thread token */
36+
Token = PsReferenceImpersonationToken(Thread,
37+
&CopyOnOpen,
38+
&EffectiveOnly,
39+
&ImpersonationLevel);
40+
if (Token == NULL)
41+
{
42+
/* We don't have a thread token, use a process token */
43+
Token = PsReferencePrimaryToken(PsGetThreadProcess(Thread));
44+
45+
/* If no token, fail */
46+
if (Token == NULL)
47+
return STATUS_NO_TOKEN;
48+
}
49+
50+
/* Query the LUID */
51+
Status = SeQueryAuthenticationIdToken(Token, Luid);
52+
53+
/* Get rid of the token and return */
54+
ObDereferenceObject(Token);
55+
return Status;
56+
}
57+
58+
BOOL
59+
NotifyLogon(IN HWND hWndSta,
60+
IN PLUID CallerLuid,
61+
IN ULONG Flags,
62+
IN NTSTATUS ShutdownStatus)
63+
{
64+
// LUID SystemLuid = SYSTEM_LUID;
65+
ULONG Notif, Param;
66+
67+
DPRINT("NotifyLogon(0x%lx, 0x%lx)\n", Flags, ShutdownStatus);
68+
69+
/* If no Winlogon notifications are needed, just return */
70+
if (Flags & EWX_NONOTIFY)
71+
return FALSE;
72+
73+
/* In case we cancelled the shutdown...*/
74+
if (Flags & EWX_SHUTDOWN_CANCELED)
75+
{
76+
/* ... send a LN_LOGOFF_CANCELED to Winlogon with the real cancel status... */
77+
Notif = LN_LOGOFF_CANCELED;
78+
Param = ShutdownStatus;
79+
}
80+
else
81+
{
82+
/* ... otherwise it's a real logoff. Send the shutdown flags in that case. */
83+
Notif = LN_LOGOFF;
84+
Param = Flags;
85+
}
86+
87+
// FIXME: At the moment, always send the notifications... In real world some checks are done.
88+
// if (hwndSAS && ( (Flags & EWX_SHUTDOWN) || RtlEqualLuid(CallerLuid, &SystemLuid)) )
89+
if (hwndSAS)
90+
{
91+
DPRINT("\tSending %s, Param 0x%x message to Winlogon\n", Notif == LN_LOGOFF ? "LN_LOGOFF" : "LN_LOGOFF_CANCELED", Param);
92+
//UserPostMessage(hwndSAS, WM_LOGONNOTIFY, Notif, (LPARAM)Param);
93+
UNIMPLEMENTED;
94+
return TRUE;
95+
}
96+
else
97+
{
98+
DPRINT1("hwndSAS == NULL\n");
99+
}
100+
101+
return FALSE;
102+
}
103+
104+
105+
NTSTATUS
106+
UserInitiateShutdown(IN PETHREAD Thread,
107+
IN OUT PULONG pFlags)
108+
{
109+
NTSTATUS Status;
110+
ULONG Flags = *pFlags;
111+
LUID CallerLuid;
112+
LUID SystemLuid = SYSTEM_LUID;
113+
/*static PRIVILEGE_SET ShutdownPrivilege =
114+
{
115+
1, PRIVILEGE_SET_ALL_NECESSARY,
116+
{ {{SE_SHUTDOWN_PRIVILEGE, 0}, 0} }
117+
};*/
118+
119+
PPROCESSINFO ppi;
120+
121+
DPRINT("UserInitiateShutdown\n");
122+
123+
/* Get the caller's LUID */
124+
Status = GetProcessLuid(Thread, &CallerLuid);
125+
if (!NT_SUCCESS(Status))
126+
{
127+
DPRINT1("GetProcessLuid failed\n");
128+
return Status;
129+
}
130+
131+
/*
132+
* Check if this is the System LUID, and adjust flags if needed.
133+
* In particular, be sure there is no EWX_CALLER_SYSTEM flag
134+
* spuriously set (could be the sign of malicous app!).
135+
*/
136+
if (RtlEqualLuid(&CallerLuid, &SystemLuid))
137+
Flags |= EWX_CALLER_SYSTEM;
138+
else
139+
Flags &= ~EWX_CALLER_SYSTEM;
140+
141+
*pFlags = Flags;
142+
143+
/* Retrieve the Win32 process info */
144+
ppi = PsGetProcessWin32Process(PsGetThreadProcess(Thread));
145+
if (ppi == NULL)
146+
return STATUS_INVALID_HANDLE;
147+
148+
#if 0
149+
/* If the caller is not Winlogon, do some security checks */
150+
if (PsGetThreadProcessId(Thread) != gpidLogon)
151+
{
152+
/*
153+
* Here also, be sure there is no EWX_CALLER_WINLOGON flag
154+
* spuriously set (could be the sign of malicous app!).
155+
*/
156+
Flags &= ~EWX_CALLER_WINLOGON;
157+
158+
*pFlags = Flags;
159+
160+
/* Check whether the current process is attached to a window station */
161+
if (ppi->prpwinsta == NULL)
162+
return STATUS_INVALID_HANDLE;
163+
164+
/* Check whether the window station of the current process can send exit requests */
165+
if (!RtlAreAllAccessesGranted(ppi->amwinsta, WINSTA_EXITWINDOWS))
166+
return STATUS_ACCESS_DENIED;
167+
168+
/*
169+
* NOTE: USERSRV automatically adds the shutdown flag when we poweroff or reboot.
170+
*
171+
* If the caller wants to shutdown / reboot / power-off...
172+
*/
173+
if (Flags & EWX_SHUTDOWN)
174+
{
175+
/* ... check whether it has shutdown privilege */
176+
if (!HasPrivilege(&ShutdownPrivilege))
177+
return STATUS_PRIVILEGE_NOT_HELD;
178+
}
179+
else
180+
{
181+
/*
182+
* ... but if it just wants to log-off, in case its
183+
* window station is a non-IO one, fail the call.
184+
*/
185+
if (ppi->prpwinsta->Flags & WSS_NOIO)
186+
return STATUS_INVALID_DEVICE_REQUEST;
187+
}
188+
}
189+
190+
/* If the caller is not Winlogon, possibly notify it to perform the real shutdown */
191+
if (PsGetThreadProcessId(Thread) != gpidLogon)
192+
{
193+
// FIXME: HACK!! Do more checks!!
194+
ERR("UserInitiateShutdown -- Notify Winlogon for shutdown\n");
195+
NotifyLogon(hwndSAS, &CallerLuid, Flags, STATUS_SUCCESS);
196+
return STATUS_PENDING;
197+
}
198+
199+
// If we reach this point, that means it's Winlogon that triggered the shutdown.
200+
ERR("UserInitiateShutdown -- Winlogon is doing a shutdown\n");
201+
202+
/*
203+
* Update and save the shutdown flags globally for renotifying
204+
* Winlogon if needed, when calling EndShutdown.
205+
*/
206+
Flags |= EWX_CALLER_WINLOGON; // Winlogon is doing a shutdown, be sure the internal flag is set.
207+
*pFlags = Flags;
208+
209+
/* Save the shutdown flags now */
210+
gdwShutdownFlags = Flags;
211+
#else
212+
UNIMPLEMENTED;
213+
#endif
214+
return STATUS_SUCCESS;
215+
}
216+
217+
NTSTATUS
218+
UserEndShutdown(IN PETHREAD Thread,
219+
IN NTSTATUS ShutdownStatus)
220+
{
221+
NTSTATUS Status;
222+
ULONG Flags;
223+
LUID CallerLuid;
224+
225+
DPRINT("UserEndShutdown\n");
226+
227+
/*
228+
* FIXME: Some cleanup should be done when shutdown succeeds,
229+
* and some reset should be done when shutdown is cancelled.
230+
*/
231+
Status = GetProcessLuid(Thread, &CallerLuid);
232+
if (!NT_SUCCESS(Status))
233+
{
234+
DPRINT1("GetProcessLuid failed\n");
235+
return Status;
236+
}
237+
238+
/* Copy the global flags because we're going to modify them for our purposes */
239+
Flags = gdwShutdownFlags;
240+
241+
if (NT_SUCCESS(ShutdownStatus))
242+
{
243+
/* Just report success, and keep the shutdown flags as they are */
244+
ShutdownStatus = STATUS_SUCCESS;
245+
}
246+
else
247+
{
248+
/* Report the status to Winlogon and say that we cancel the shutdown */
249+
Flags |= EWX_SHUTDOWN_CANCELED;
250+
// FIXME: Should we reset gdwShutdownFlags to 0 ??
251+
}
252+
253+
DPRINT("UserEndShutdown -- Notify Winlogon for end of shutdown\n");
254+
255+
#if 0
256+
NotifyLogon(hwndSAS, &CallerLuid, Flags, ShutdownStatus);
257+
#else
258+
UNIMPLEMENTED
259+
#endif
260+
261+
/* Always return success */
262+
return STATUS_SUCCESS;
263+
}
264+
265+
/* EOF */

0 commit comments

Comments
 (0)