Author: hbelusca
Date: Sat Feb 7 15:26:42 2015
New Revision: 66192
URL:
http://svn.reactos.org/svn/reactos?rev=66192&view=rev
Log:
[WINLOGON][WIN32K]
Move the shutdown privilege check from winlogon to win32k (function
"UserInitiateShutdown") as it should be done.
[WIN32K]
- Introduce the pair of UserInitiateShutdown/UserEndShutdown calls that should be called
when WINSRV starts a shutdown (and when it finishes it). In particular it is in
UserInitiateShutdown that we need to check whether the caller has the rights to perform a
shutdown (it should also have a valid window station).
- Remove the ROS-specific TWOPARAM_ROUTINE_EXITREACTOS call that is traded for
Win2k3-compatible call to UserInitiateShutdown.
[WINSRV]
Hackfix our current ExitWindowsEx functionality (based on a patch by Alex made against
r46050 for win32csr) to make it "compatible" with the improvements in win32k:
impersonate the caller and call the UserInitiateShutdown win32k system call (instead of
the TWOPARAM_ROUTINE_EXITREACTOS). More will come later on.
[USER32]
Win32k can require performing shutdown in an asynchronous way (needed also on WINSRV side)
so we need to put all the code in a worker thread.
Part 8/X (part 6 was r65693 and part 7 was r66186).
CORE-8322 #comment Start to add Alex' win32csr shutdown patch in WINSRV; fixes for
winlogon and additions to win32k.
Modified:
trunk/reactos/base/system/winlogon/sas.c
trunk/reactos/win32ss/include/ntuser.h
trunk/reactos/win32ss/user/ntuser/ntstubs.c
trunk/reactos/win32ss/user/ntuser/shutdown.c
trunk/reactos/win32ss/user/ntuser/shutdown.h
trunk/reactos/win32ss/user/ntuser/simplecall.c
trunk/reactos/win32ss/user/user32/misc/exit.c
trunk/reactos/win32ss/user/winsrv/usersrv/shutdown.c
Modified: trunk/reactos/base/system/winlogon/sas.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/system/winlogon/sas.c…
==============================================================================
--- trunk/reactos/base/system/winlogon/sas.c [iso-8859-1] (original)
+++ trunk/reactos/base/system/winlogon/sas.c [iso-8859-1] Sat Feb 7 15:26:42 2015
@@ -1147,67 +1147,6 @@
return TRUE;
}
-
-#if 0
-static
-NTSTATUS
-CheckForShutdownPrivilege(
- IN DWORD RequestingProcessId)
-{
- HANDLE Process;
- HANDLE Token;
- BOOL CheckResult;
- PPRIVILEGE_SET PrivSet;
-
- TRACE("CheckForShutdownPrivilege()\n");
-
- Process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, RequestingProcessId);
- if (!Process)
- {
- WARN("OpenProcess() failed with error %lu\n", GetLastError());
- return STATUS_INVALID_HANDLE;
- }
- if (!OpenProcessToken(Process, TOKEN_QUERY, &Token))
- {
- WARN("OpenProcessToken() failed with error %lu\n", GetLastError());
- CloseHandle(Process);
- return STATUS_INVALID_HANDLE;
- }
- CloseHandle(Process);
- PrivSet = HeapAlloc(GetProcessHeap(), 0, sizeof(PRIVILEGE_SET) +
sizeof(LUID_AND_ATTRIBUTES));
- if (!PrivSet)
- {
- ERR("Failed to allocate mem for privilege set\n");
- CloseHandle(Token);
- return STATUS_NO_MEMORY;
- }
- PrivSet->PrivilegeCount = 1;
- PrivSet->Control = PRIVILEGE_SET_ALL_NECESSARY;
- if (!LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME,
&PrivSet->Privilege[0].Luid))
- {
- WARN("LookupPrivilegeValue() failed with error %lu\n",
GetLastError());
- HeapFree(GetProcessHeap(), 0, PrivSet);
- CloseHandle(Token);
- return STATUS_UNSUCCESSFUL;
- }
- if (!PrivilegeCheck(Token, PrivSet, &CheckResult))
- {
- WARN("PrivilegeCheck() failed with error %lu\n", GetLastError());
- HeapFree(GetProcessHeap(), 0, PrivSet);
- CloseHandle(Token);
- return STATUS_ACCESS_DENIED;
- }
- HeapFree(GetProcessHeap(), 0, PrivSet);
- CloseHandle(Token);
-
- if (!CheckResult)
- {
- WARN("SE_SHUTDOWN privilege not enabled\n");
- return STATUS_ACCESS_DENIED;
- }
- return STATUS_SUCCESS;
-}
-#endif
BOOL
WINAPI
@@ -1337,13 +1276,40 @@
UINT Action = Flags & EWX_ACTION_MASK;
DWORD wlxAction;
+ TRACE("\tFlags : 0x%lx\n", lParam);
+
+ /*
+ * Our caller (USERSRV) should have added the shutdown flag
+ * when setting also poweroff or reboot.
+ */
+ if (Action & (EWX_POWEROFF | EWX_REBOOT))
+ {
+ if ((Action & EWX_SHUTDOWN) == 0)
+ {
+ ERR("Missing EWX_SHUTDOWN flag for poweroff or reboot;
action 0x%x\n", Action);
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ /* Now we can locally remove it for performing checks */
+ Action &= ~EWX_SHUTDOWN;
+ }
+
/* Check parameters */
switch (Action)
{
- case EWX_LOGOFF: wlxAction = WLX_SAS_ACTION_LOGOFF; break;
- case EWX_SHUTDOWN: wlxAction = WLX_SAS_ACTION_SHUTDOWN; break;
- case EWX_REBOOT: wlxAction = WLX_SAS_ACTION_SHUTDOWN_REBOOT;
break;
- case EWX_POWEROFF: wlxAction = WLX_SAS_ACTION_SHUTDOWN_POWER_OFF;
break;
+ case EWX_LOGOFF:
+ wlxAction = WLX_SAS_ACTION_LOGOFF;
+ break;
+ case EWX_SHUTDOWN:
+ wlxAction = WLX_SAS_ACTION_SHUTDOWN;
+ break;
+ case EWX_REBOOT:
+ wlxAction = WLX_SAS_ACTION_SHUTDOWN_REBOOT;
+ break;
+ case EWX_POWEROFF:
+ wlxAction = WLX_SAS_ACTION_SHUTDOWN_POWER_OFF;
+ break;
+
default:
{
ERR("Invalid ExitWindows action 0x%x\n", Action);
@@ -1351,15 +1317,7 @@
}
}
-#if 0
- // FIXME: This check must be done by Win32k, not by us!
- if (WLX_SHUTTINGDOWN(wlxAction))
- {
- NTSTATUS Status = CheckForShutdownPrivilege(wParam);
- if (!NT_SUCCESS(Status))
- return Status;
- }
-#endif
+ /* Now do the shutdown action proper */
DoGenericAction(Session, wlxAction);
return 1;
}
Modified: trunk/reactos/win32ss/include/ntuser.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/include/ntuser.h?r…
==============================================================================
--- trunk/reactos/win32ss/include/ntuser.h [iso-8859-1] (original)
+++ trunk/reactos/win32ss/include/ntuser.h [iso-8859-1] Sat Feb 7 15:26:42 2015
@@ -3439,9 +3439,8 @@
#define ONEPARAM_ROUTINE_ENABLEPROCWNDGHSTING 0xfffe000d
#define ONEPARAM_ROUTINE_GETDESKTOPMAPPING 0xfffe000e
#define TWOPARAM_ROUTINE_SETMENUBARHEIGHT 0xfffd0050
-#define TWOPARAM_ROUTINE_EXITREACTOS 0xfffd0051
-#define TWOPARAM_ROUTINE_SETGUITHRDHANDLE 0xfffd0052
-#define HWNDLOCK_ROUTINE_SETFOREGROUNDWINDOWMOUSE 0xfffd0053
+#define TWOPARAM_ROUTINE_SETGUITHRDHANDLE 0xfffd0051
+#define HWNDLOCK_ROUTINE_SETFOREGROUNDWINDOWMOUSE 0xfffd0052
#define MSQ_STATE_CAPTURE 0x1
#define MSQ_STATE_ACTIVE 0x2
#define MSQ_STATE_FOCUS 0x3
Modified: trunk/reactos/win32ss/user/ntuser/ntstubs.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/ntstub…
==============================================================================
--- trunk/reactos/win32ss/user/ntuser/ntstubs.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/ntuser/ntstubs.c [iso-8859-1] Sat Feb 7 15:26:42 2015
@@ -412,7 +412,7 @@
{
NTSTATUS Status = STATUS_SUCCESS;
- /* Allow only Console Server to perform this operation (via CSRSS) */
+ /* Allow only the Console Server to perform this operation (via CSRSS) */
if (PsGetCurrentProcess() != gpepCSRSS)
return STATUS_ACCESS_DENIED;
@@ -770,7 +770,6 @@
{
NTSTATUS Status = STATUS_SUCCESS;
PETHREAD Thread;
- HANDLE CsrPortHandle;
/* Allow only CSRSS to perform this operation */
if (PsGetCurrentProcess() != gpepCSRSS)
@@ -792,24 +791,54 @@
case UserThreadInitiateShutdown:
{
ERR("Shutdown initiated\n");
- STUB;
- Status = STATUS_NOT_IMPLEMENTED;
+
+ if (ThreadInformationLength != sizeof(ULONG))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
+ Status = UserInitiateShutdown(Thread, (PULONG)ThreadInformation);
break;
}
case UserThreadEndShutdown:
{
+ NTSTATUS ShutdownStatus;
+
ERR("Shutdown ended\n");
- STUB;
- Status = STATUS_NOT_IMPLEMENTED;
+
+ if (ThreadInformationLength != sizeof(ShutdownStatus))
+ {
+ Status = STATUS_INFO_LENGTH_MISMATCH;
+ break;
+ }
+
+ Status = STATUS_SUCCESS;
+ _SEH2_TRY
+ {
+ ProbeForRead(ThreadInformation, sizeof(ShutdownStatus), sizeof(PVOID));
+ ShutdownStatus = *(NTSTATUS*)ThreadInformation;
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+
+ if (NT_SUCCESS(Status))
+ Status = UserEndShutdown(Thread, ShutdownStatus);
+
break;
}
case UserThreadCsrApiPort:
{
+ HANDLE CsrPortHandle;
+
ERR("Set CSR API Port for Win32k\n");
- if (ThreadInformationLength != sizeof(HANDLE))
+ if (ThreadInformationLength != sizeof(CsrPortHandle))
{
Status = STATUS_INFO_LENGTH_MISMATCH;
break;
@@ -818,7 +847,7 @@
Status = STATUS_SUCCESS;
_SEH2_TRY
{
- ProbeForRead(ThreadInformation, sizeof(HANDLE), sizeof(PVOID));
+ ProbeForRead(ThreadInformation, sizeof(CsrPortHandle), sizeof(PVOID));
CsrPortHandle = *(PHANDLE)ThreadInformation;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
@@ -828,9 +857,8 @@
_SEH2_END;
if (NT_SUCCESS(Status))
- {
Status = InitCsrApiPort(CsrPortHandle);
- }
+
break;
}
Modified: trunk/reactos/win32ss/user/ntuser/shutdown.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/shutdo…
==============================================================================
--- trunk/reactos/win32ss/user/ntuser/shutdown.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/ntuser/shutdown.c [iso-8859-1] Sat Feb 7 15:26:42 2015
@@ -7,7 +7,7 @@
*/
#include <win32k.h>
-// DBG_DEFAULT_CHANNEL(UserShutdown);
+DBG_DEFAULT_CHANNEL(UserShutdown);
/*
* Based on CSRSS and described in pages 1115 - 1118 "Windows Internals, Fifth
Edition".
@@ -85,4 +85,172 @@
return lResult;
}
+
+NTSTATUS
+GetProcessLuid(IN PETHREAD Thread OPTIONAL,
+ OUT PLUID Luid)
+{
+ NTSTATUS Status;
+ PACCESS_TOKEN Token;
+ SECURITY_IMPERSONATION_LEVEL ImpersonationLevel;
+ BOOLEAN CopyOnOpen, EffectiveOnly;
+
+ if (Thread == NULL)
+ Thread = PsGetCurrentThread();
+
+ /* Use a thread token */
+ Token = PsReferenceImpersonationToken(Thread,
+ &CopyOnOpen,
+ &EffectiveOnly,
+ &ImpersonationLevel);
+ if (Token == NULL)
+ {
+ /* We don't have a thread token, use a process token */
+ Token = PsReferencePrimaryToken(PsGetThreadProcess(Thread));
+
+ /* If no token, fail */
+ if (Token == NULL)
+ return STATUS_NO_TOKEN;
+ }
+
+ /* Query the LUID */
+ Status = SeQueryAuthenticationIdToken(Token, Luid);
+
+ /* Get rid of the token and return */
+ ObDereferenceObject(Token);
+ return Status;
+}
+
+BOOLEAN
+HasPrivilege(IN PPRIVILEGE_SET Privilege)
+{
+ BOOLEAN Result;
+ SECURITY_SUBJECT_CONTEXT SubjectContext;
+
+ /* Capture and lock the security subject context */
+ SeCaptureSubjectContext(&SubjectContext);
+ SeLockSubjectContext(&SubjectContext);
+
+ /* Do privilege check */
+ Result = SePrivilegeCheck(Privilege, &SubjectContext, UserMode);
+
+ /* Audit the privilege */
+#if 0
+ SePrivilegeObjectAuditAlarm(NULL,
+ &SubjectContext,
+ 0,
+ Privilege,
+ Result,
+ UserMode);
+#endif
+
+ /* Unlock and release the security subject context and return */
+ SeUnlockSubjectContext(&SubjectContext);
+ SeReleaseSubjectContext(&SubjectContext);
+ return Result;
+}
+
+NTSTATUS
+UserInitiateShutdown(IN PETHREAD Thread,
+ IN OUT PULONG pFlags)
+{
+ NTSTATUS Status;
+ ULONG Flags = *pFlags;
+ LUID CallerLuid;
+ // LUID SystemLuid = SYSTEM_LUID;
+ static PRIVILEGE_SET ShutdownPrivilege =
+ {
+ 1, PRIVILEGE_SET_ALL_NECESSARY,
+ { {{SE_SHUTDOWN_PRIVILEGE, 0}, 0} }
+ };
+
+ PPROCESSINFO ppi;
+
+ ERR("UserInitiateShutdown\n");
+
+ if(hwndSAS == NULL)
+ return STATUS_NOT_FOUND;
+
+ /* Get the caller's LUID */
+ Status = GetProcessLuid(Thread, &CallerLuid);
+ if (!NT_SUCCESS(Status))
+ {
+ ERR("GetProcessLuid failed\n");
+ return Status;
+ }
+
+ // FIXME: Check if this is the System LUID, and adjust flags if needed.
+ // if (RtlEqualLuid(&CallerLuid, &SystemLuid)) { Flags = ...; }
+ *pFlags = Flags;
+
+ /* Retrieve the Win32 process info */
+ ppi = PsGetProcessWin32Process(PsGetThreadProcess(Thread));
+ if (ppi == NULL)
+ return STATUS_INVALID_HANDLE;
+
+ /* If the caller is not Winlogon, do some security checks */
+ if (PsGetThreadProcessId(Thread) != gpidLogon)
+ {
+ // FIXME: Play again with flags...
+ *pFlags = Flags;
+
+ /* Check whether the current process is attached to a window station */
+ if (ppi->prpwinsta == NULL)
+ return STATUS_INVALID_HANDLE;
+
+ /* Check whether the window station of the current process can send exit requests
*/
+ if (!RtlAreAllAccessesGranted(ppi->amwinsta, WINSTA_EXITWINDOWS))
+ return STATUS_ACCESS_DENIED;
+
+ /*
+ * NOTE: USERSRV automatically adds the shutdown flag when we poweroff or
reboot.
+ *
+ * If the caller wants to shutdown / reboot / power-off...
+ */
+ if (Flags & EWX_SHUTDOWN)
+ {
+ /* ... check whether it has shutdown privilege */
+ if (!HasPrivilege(&ShutdownPrivilege))
+ return STATUS_PRIVILEGE_NOT_HELD;
+ }
+ else
+ {
+ /*
+ * ... but if it just wants to log-off, in case its
+ * window station is a non-IO one, fail the call.
+ */
+ if (ppi->prpwinsta->Flags & WSS_NOIO)
+ return STATUS_INVALID_DEVICE_REQUEST;
+ }
+ }
+
+ /* If the caller is not Winlogon, notify it to perform the real shutdown */
+ if (PsGetThreadProcessId(Thread) != gpidLogon)
+ {
+ // FIXME: HACK!! Do more checks!!
+ UserPostMessage(hwndSAS, WM_LOGONNOTIFY, LN_LOGOFF, (LPARAM)Flags);
+ return STATUS_PENDING;
+ }
+
+ // If we reach this point, that means it's Winlogon that triggered the shutdown.
+
+ /*
+ * FIXME:
+ * Update and save the shutdown flags globally for renotifying Winlogon
+ * if needed, when calling EndShutdown.
+ */
+ *pFlags = Flags;
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+UserEndShutdown(IN PETHREAD Thread,
+ IN NTSTATUS ShutdownStatus)
+{
+ ERR("UserEndShutdown\n");
+ STUB;
+ return STATUS_NOT_IMPLEMENTED;
+}
+
/* EOF */
Modified: trunk/reactos/win32ss/user/ntuser/shutdown.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/shutdo…
==============================================================================
--- trunk/reactos/win32ss/user/ntuser/shutdown.h [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/ntuser/shutdown.h [iso-8859-1] Sat Feb 7 15:26:42 2015
@@ -4,3 +4,11 @@
IntClientShutdown(IN PWND pWindow,
IN WPARAM wParam,
IN LPARAM lParam);
+
+NTSTATUS
+UserInitiateShutdown(IN PETHREAD Thread,
+ IN OUT PULONG pFlags);
+
+NTSTATUS
+UserEndShutdown(IN PETHREAD Thread,
+ IN NTSTATUS ShutdownStatus);
Modified: trunk/reactos/win32ss/user/ntuser/simplecall.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/simple…
==============================================================================
--- trunk/reactos/win32ss/user/ntuser/simplecall.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/ntuser/simplecall.c [iso-8859-1] Sat Feb 7 15:26:42 2015
@@ -7,8 +7,6 @@
*/
#include <win32k.h>
-
-#include <winlogon.h>
DBG_DEFAULT_CHANNEL(UserMisc);
@@ -449,18 +447,6 @@
case TWOPARAM_ROUTINE_UNHOOKWINDOWSHOOK:
RETURN( IntUnhookWindowsHook((int)Param1, (HOOKPROC)Param2));
-
- case TWOPARAM_ROUTINE_EXITREACTOS:
- {
- UNREFERENCED_PARAMETER(Param1 /* ProcessId */);
-
- if(hwndSAS == NULL)
- {
- ASSERT(hwndSAS);
- RETURN(STATUS_NOT_FOUND);
- }
- RETURN(co_IntSendMessage(hwndSAS, WM_LOGONNOTIFY, LN_LOGOFF, Param2 /* Flags
*/));
- }
}
ERR("Calling invalid routine number 0x%x in NtUserCallTwoParam(), Param1=0x%x
Parm2=0x%x\n",
Routine, Param1, Param2);
Modified: trunk/reactos/win32ss/user/user32/misc/exit.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/user32/misc/e…
==============================================================================
--- trunk/reactos/win32ss/user/user32/misc/exit.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/user32/misc/exit.c [iso-8859-1] Sat Feb 7 15:26:42 2015
@@ -9,6 +9,8 @@
#include <user32.h>
#include <wine/debug.h>
+
+WINE_DEFAULT_DEBUG_CHANNEL(user32);
/*
* Sequence of events:
@@ -61,6 +63,130 @@
* the kernel and executive shutdown by calling NtShutdownSystem.
*/
+typedef struct
+{
+ UINT uFlags;
+ DWORD dwReserved;
+} EXIT_REACTOS_DATA, *PEXIT_REACTOS_DATA;
+
+static BOOL
+ExitWindowsWorker(UINT uFlags,
+ DWORD dwReserved,
+ BOOL bCalledFromThread);
+
+static DWORD
+WINAPI
+ExitWindowsThread(LPVOID Param)
+{
+ DWORD dwExitCode;
+ PEXIT_REACTOS_DATA ExitData = (PEXIT_REACTOS_DATA)Param;
+
+ /* Do the exit asynchronously */
+ if (ExitWindowsWorker(ExitData->uFlags, ExitData->dwReserved, TRUE))
+ dwExitCode = ERROR_SUCCESS;
+ else
+ dwExitCode = GetLastError();
+
+ ExitThread(dwExitCode);
+ return ERROR_SUCCESS;
+}
+
+static BOOL
+ExitWindowsWorker(UINT uFlags,
+ DWORD dwReserved,
+ BOOL bCalledFromThread)
+{
+ EXIT_REACTOS_DATA ExitData;
+ HANDLE hExitThread;
+ DWORD ExitCode;
+ MSG msg;
+
+ USER_API_MESSAGE ApiMessage;
+ PUSER_EXIT_REACTOS ExitReactosRequest = &ApiMessage.Data.ExitReactosRequest;
+
+ /*
+ * 1- FIXME: Call NtUserCallOneParam(uFlags, ONEPARAM_ROUTINE_PREPAREFORLOGOFF);
+ * If success we can continue, otherwise we must fail.
+ */
+
+ /*
+ * 2- Send the Exit request to CSRSS (and to Win32k indirectly).
+ * We can shutdown synchronously or asynchronously.
+ */
+
+ // ExitReactosRequest->LastError = ERROR_SUCCESS;
+ ExitReactosRequest->Flags = uFlags;
+
+ CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
+ NULL,
+ CSR_CREATE_API_NUMBER(USERSRV_SERVERDLL_INDEX,
UserpExitWindowsEx),
+ sizeof(*ExitReactosRequest));
+
+ /* Set the last error accordingly */
+ if (NT_SUCCESS(ApiMessage.Status) || ApiMessage.Status == STATUS_CANT_WAIT)
+ {
+ if (ExitReactosRequest->LastError != ERROR_SUCCESS)
+ UserSetLastError(ExitReactosRequest->LastError);
+ }
+ else
+ {
+ UserSetLastNTError(ApiMessage.Status);
+ ExitReactosRequest->Success = FALSE;
+ }
+
+ /*
+ * In case CSR call succeeded and we did a synchronous exit
+ * (STATUS_CANT_WAIT is considered as a non-success status),
+ * return the real state of the operation now.
+ */
+ if (NT_SUCCESS(ApiMessage.Status))
+ return ExitReactosRequest->Success;
+
+ /*
+ * In case something failed: we have a non-success status and:
+ * - either we were doing a synchronous exit (Status != STATUS_CANT_WAIT), or
+ * - we were doing an asynchronous exit because we were called recursively via
+ * another thread but we failed to exit,
+ * then bail out immediately, otherwise we would enter an infinite loop of exit
requests.
+ *
+ * On the contrary if we need to do an asynchronous exit (Status == STATUS_CANT_WAIT
+ * and not called recursively via another thread), then continue and do the exit.
+ */
+ if (ApiMessage.Status != STATUS_CANT_WAIT || bCalledFromThread)
+ {
+ UserSetLastNTError(ApiMessage.Status);
+ return FALSE;
+ }
+
+ /*
+ * 3- Win32k wants us to perform an asynchronous exit. Run the request in a thread.
+ * (ApiMessage.Status == STATUS_CANT_WAIT and not already called from a thread)
+ */
+ ExitData.uFlags = uFlags;
+ ExitData.dwReserved = dwReserved;
+ hExitThread = CreateThread(NULL, 0, ExitWindowsThread, &ExitData, 0, NULL);
+ if (hExitThread == NULL)
+ return FALSE;
+
+ /* Pump and discard any input events sent to the app(s) */
+ while (MsgWaitForMultipleObjectsEx(1, &hExitThread, INFINITE, QS_ALLINPUT, 0))
+ {
+ while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
+ DispatchMessageW(&msg);
+ }
+
+ /* Finally, return to caller */
+ if (!GetExitCodeThread(hExitThread, &ExitCode))
+ ExitCode = GetLastError();
+
+ CloseHandle(hExitThread);
+
+ if (ExitCode != ERROR_SUCCESS)
+ UserSetLastError(ExitCode);
+
+ return (ExitCode == ERROR_SUCCESS);
+}
+
/*
* @implemented
*/
@@ -68,23 +194,17 @@
ExitWindowsEx(UINT uFlags,
DWORD dwReserved)
{
- NTSTATUS Status;
- USER_API_MESSAGE ApiMessage;
-
- ApiMessage.Data.ExitReactosRequest.Flags = uFlags;
- // ApiMessage.Data.ExitReactosRequest.Reserved = dwReserved;
-
- Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
- NULL,
- CSR_CREATE_API_NUMBER(USERSRV_SERVERDLL_INDEX,
UserpExitWindowsEx),
- sizeof(USER_EXIT_REACTOS));
- if (!NT_SUCCESS(Status))
- {
- UserSetLastNTError(Status);
- return FALSE;
- }
-
- return TRUE;
+ /*
+ * FIXME:
+ * 1- Calling the Exit worker must be done under certain conditions.
+ * We may also need to warn the user if there are other people logged
+ * on this computer (see
http://pve.proxmox.com/wiki/Windows_2003_guest_best_practices )
+ * 2- Call SrvRecordShutdownReason.
+ */
+
+ return ExitWindowsWorker(uFlags, dwReserved, FALSE);
+
+ /* FIXME: Call SrvRecordShutdownReason if we failed */
}
/*
Modified: trunk/reactos/win32ss/user/winsrv/usersrv/shutdown.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/winsrv/usersr…
==============================================================================
--- trunk/reactos/win32ss/user/winsrv/usersrv/shutdown.c [iso-8859-1] (original)
+++ trunk/reactos/win32ss/user/winsrv/usersrv/shutdown.c [iso-8859-1] Sat Feb 7 15:26:42
2015
@@ -778,6 +778,7 @@
return STATUS_ACCESS_DENIED;
}
+ // FIXME: HAAAAACK!!
DPRINT1("FIXME: Need to close all user processes!\n");
return STATUS_SUCCESS;
@@ -896,12 +897,34 @@
}
static NTSTATUS FASTCALL
-UserExitReactos(DWORD UserProcessId, UINT Flags)
+UserExitReactos(PCSR_THREAD CsrThread, UINT Flags)
{
NTSTATUS Status;
-
- /* FIXME Inside 2000 says we should impersonate the caller here */
- Status = NtUserCallTwoParam(UserProcessId, Flags, TWOPARAM_ROUTINE_EXITREACTOS);
+ LUID CallerLuid;
+
+ // FIXME: HACK!!
+
+ /*
+ * Retrieve the caller's LUID so that we can only shutdown
+ * processes in the caller's LUID.
+ */
+ if (!CsrImpersonateClient(NULL))
+ return STATUS_BAD_IMPERSONATION_LEVEL;
+
+ Status = CsrGetProcessLuid(NULL, &CallerLuid);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Unable to get caller LUID, Status = 0x%08x\n", Status);
+ goto Quit;
+ }
+
+ DPRINT1("Caller LUID is: %lx.%lx\n", CallerLuid.HighPart,
CallerLuid.LowPart);
+
+ /* Notify Win32k and potentially Winlogon of the shutdown */
+ Status = NtUserSetInformationThread(CsrThread->ThreadHandle,
+ UserThreadInitiateShutdown,
+ &Flags, sizeof(Flags));
+ DPRINT1("Win32k says: %lx\n", Status);
/* If the message isn't handled, the return value is 0, so 0 doesn't
indicate
success. Success is indicated by a 1 return value, if anything besides 0
@@ -915,6 +938,10 @@
Status = STATUS_NOT_IMPLEMENTED;
}
+ DPRINT1("SrvExitWindowsEx returned 0x%08x\n", Status);
+
+Quit:
+ CsrRevertToSelf();
return Status;
}
@@ -938,19 +965,42 @@
CSR_API(SrvExitWindowsEx)
{
+ NTSTATUS Status;
PUSER_EXIT_REACTOS ExitReactosRequest =
&((PUSER_API_MESSAGE)ApiMessage)->Data.ExitReactosRequest;
-
- if (0 == (ExitReactosRequest->Flags & EWX_INTERNAL_FLAG))
- {
- return UserExitReactos((DWORD_PTR) ApiMessage->Header.ClientId.UniqueProcess,
- ExitReactosRequest->Flags);
+ PCSR_THREAD CsrThread = CsrGetClientThread();
+ ULONG Flags = ExitReactosRequest->Flags;
+
+ /*
+ * Check for flags validity
+ */
+
+ DWORD ProcessId = HandleToUlong(CsrThread->ClientId.UniqueProcess);
+ DWORD ThreadId = HandleToUlong(CsrThread->ClientId.UniqueThread);
+
+ DPRINT1("SrvExitWindowsEx(ClientId: %lx.%lx, Flags: 0x%x)\n",
+ ProcessId, ThreadId, Flags);
+
+ /* Implicitely add the shutdown flag when we poweroff or reboot */
+ if (Flags & (EWX_POWEROFF | EWX_REBOOT))
+ Flags |= EWX_SHUTDOWN;
+
+
+ // FIXME: Everything else starting after this line is a HAAACK!!
+
+
+ if (0 == (Flags & EWX_INTERNAL_FLAG))
+ {
+ Status = UserExitReactos(CsrThread, Flags);
}
else
{
- return InternalExitReactos((DWORD_PTR)
ApiMessage->Header.ClientId.UniqueProcess,
- (DWORD_PTR)
ApiMessage->Header.ClientId.UniqueThread,
- ExitReactosRequest->Flags);
- }
+ // EWX_INTERNAL_FLAG --> For Winlogon only!!
+ // FIXME: This is just a big HAAAACK!!
+ Status = InternalExitReactos(ProcessId, ThreadId, Flags);
+ }
+
+ ExitReactosRequest->Success = NT_SUCCESS(Status);
+ return Status;
}
CSR_API(SrvEndTask)