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?re... ============================================================================== --- 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/ntstubs... ============================================================================== --- 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/shutdow... ============================================================================== --- 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/shutdow... ============================================================================== --- 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/simplec... ============================================================================== --- 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/ex... ============================================================================== --- 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/usersrv... ============================================================================== --- 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)