diff --git a/reactos/win32ss/CMakeLists.txt b/reactos/win32ss/CMakeLists.txt index 87260ae6f50..8ecccca4144 100644 --- a/reactos/win32ss/CMakeLists.txt +++ b/reactos/win32ss/CMakeLists.txt @@ -105,6 +105,7 @@ list(APPEND SOURCE user/ntuser/caret.c user/ntuser/class.c user/ntuser/clipboard.c + user/ntuser/csr.c user/ntuser/defwnd.c user/ntuser/desktop.c user/ntuser/display.c diff --git a/reactos/win32ss/user/ntuser/csr.c b/reactos/win32ss/user/ntuser/csr.c index 820db2a7edc..4c1c89ba902 100644 --- a/reactos/win32ss/user/ntuser/csr.c +++ b/reactos/win32ss/user/ntuser/csr.c @@ -1,91 +1,201 @@ /* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS Win32k subsystem - * PURPOSE: Interface to CSRSS / USERSRV + * PURPOSE: Interface between Win32k and USERSRV * FILE: subsystems/win32/win32k/ntuser/csr.c - * PROGRAMER: Ge van Geldorp (ge@gse.nl) + * PROGRAMER: Hermes Belusca-Maito (hermes.belusca@sfr.fr), based on + * the original code by Ge van Geldorp (ge@gse.nl) and by + * the CSR code in NTDLL. */ #include -static HANDLE WindowsApiPort = NULL; -// See gpepCSRSS in ntuser/ntuser.c and its initialization into NtUserInitialize() -PEPROCESS CsrProcess = NULL; +DBG_DEFAULT_CHANNEL(UserCsr); -NTSTATUS FASTCALL -CsrInit(void) +PEPROCESS gpepCSRSS = NULL; +PVOID CsrApiPort = NULL; + +VOID +InitCsrProcess(VOID /*IN PEPROCESS CsrProcess*/) { - NTSTATUS Status; - UNICODE_STRING PortName; - ULONG ConnectInfoLength; - SECURITY_QUALITY_OF_SERVICE Qos; - - RtlInitUnicodeString(&PortName, L"\\Windows\\ApiPort"); - ConnectInfoLength = 0; - Qos.Length = sizeof(Qos); - Qos.ImpersonationLevel = SecurityDelegation; - Qos.ContextTrackingMode = SECURITY_STATIC_TRACKING; - Qos.EffectiveOnly = FALSE; - - Status = ZwConnectPort(&WindowsApiPort, - &PortName, - &Qos, - NULL, - NULL, - NULL, - NULL, - &ConnectInfoLength); - if (!NT_SUCCESS(Status)) - { - return Status; - } - - CsrProcess = PsGetCurrentProcess(); - - return STATUS_SUCCESS; + /* Save the EPROCESS of CSRSS */ + gpepCSRSS = PsGetCurrentProcess(); + // gpepCSRSS = CsrProcess; + ObReferenceObject(gpepCSRSS); } -NTSTATUS FASTCALL -co_CsrNotify(PCSR_API_MESSAGE Request) +VOID +ResetCsrProcess(VOID) { - NTSTATUS Status; - PEPROCESS OldProcess; + if (gpepCSRSS) + ObDereferenceObject(gpepCSRSS); - if (NULL == CsrProcess) - { - return STATUS_INVALID_PORT_HANDLE; - } + gpepCSRSS = NULL; +} - Request->Header.u2.ZeroInit = 0; - Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE); - Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE); +NTSTATUS +InitCsrApiPort(IN HANDLE CsrPortHandle) +{ + NTSTATUS Status; - /* Switch to the process in which the WindowsApiPort handle is valid */ - OldProcess = PsGetCurrentProcess(); - if (CsrProcess != OldProcess) - { - KeAttachProcess(&CsrProcess->Pcb); - } + Status = ObReferenceObjectByHandle(CsrPortHandle, + 0, + /* * */LpcPortObjectType, // or NULL, + UserMode, + &CsrApiPort, + NULL); + if (!NT_SUCCESS(Status)) + { + CsrApiPort = NULL; + ERR("Failed to set CSR API Port.\n"); + } - UserLeaveCo(); + return Status; +} - Status = ZwRequestWaitReplyPort(WindowsApiPort, - &Request->Header, - &Request->Header); +VOID +ResetCsrApiPort(VOID) +{ + if (CsrApiPort) + ObDereferenceObject(CsrApiPort); - UserEnterCo(); + CsrApiPort = NULL; +} - if (CsrProcess != OldProcess) - { - KeDetachProcess(); - } +/* + * Function copied from ntdll/csr/connect.c::CsrClientCallServer + * and adapted for kernel-mode. + * + * NOTE: This is really a co_* function! + */ +NTSTATUS +NTAPI +CsrClientCallServer(IN OUT PCSR_API_MESSAGE ApiMessage, + IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer OPTIONAL, + IN CSR_API_NUMBER ApiNumber, + IN ULONG DataLength) +{ + NTSTATUS Status; +#if 0 + ULONG PointerCount; + PULONG_PTR OffsetPointer; +#endif - if (NT_SUCCESS(Status)) - { - Status = Request->Status; - } + /* Do we have a connection to CSR yet? */ + if (!CsrApiPort) + return STATUS_INVALID_PORT_HANDLE; - return Status; + /* Fill out the Port Message Header */ + ApiMessage->Header.u2.ZeroInit = 0; + ApiMessage->Header.u1.s1.TotalLength = DataLength + + sizeof(CSR_API_MESSAGE) - sizeof(ApiMessage->Data); // FIELD_OFFSET(CSR_API_MESSAGE, Data) + DataLength; + ApiMessage->Header.u1.s1.DataLength = DataLength + + FIELD_OFFSET(CSR_API_MESSAGE, Data) - sizeof(ApiMessage->Header); // ApiMessage->Header.u1.s1.TotalLength - sizeof(PORT_MESSAGE); + + /* Fill out the CSR Header */ + ApiMessage->ApiNumber = ApiNumber; + ApiMessage->CsrCaptureData = NULL; + + TRACE("API: %lx, u1.s1.DataLength: %x, u1.s1.TotalLength: %x\n", + ApiNumber, + ApiMessage->Header.u1.s1.DataLength, + ApiMessage->Header.u1.s1.TotalLength); + +#if 0 + /* Check if we got a Capture Buffer */ + if (CaptureBuffer) + { + /* + * We have to convert from our local (client) view + * to the remote (server) view. + */ + ApiMessage->CsrCaptureData = (PCSR_CAPTURE_BUFFER) + ((ULONG_PTR)CaptureBuffer + CsrPortMemoryDelta); + + /* Lock the buffer. */ + CaptureBuffer->BufferEnd = NULL; + + /* + * Each client pointer inside the CSR message is converted into + * a server pointer, and each pointer to these message pointers + * is converted into an offset. + */ + PointerCount = CaptureBuffer->PointerCount; + OffsetPointer = CaptureBuffer->PointerOffsetsArray; + while (PointerCount--) + { + if (*OffsetPointer != 0) + { + *(PULONG_PTR)*OffsetPointer += CsrPortMemoryDelta; + *OffsetPointer -= (ULONG_PTR)ApiMessage; + } + ++OffsetPointer; + } + } +#endif + + UserLeaveCo(); + + /* Send the LPC Message */ + + // The wait logic below is subject to change in the future. One can + // imagine adding an external parameter to CsrClientCallServer, or write + // two versions of CsrClientCallServer, synchronous and asynchronous. + if (PsGetCurrentProcess() == gpepCSRSS) + { + Status = LpcRequestPort(CsrApiPort, + &ApiMessage->Header); + } + else + { + Status = LpcRequestWaitReplyPort(CsrApiPort, + &ApiMessage->Header, + &ApiMessage->Header); + } + + UserEnterCo(); + +#if 0 + /* Check if we got a Capture Buffer */ + if (CaptureBuffer) + { + /* + * We have to convert back from the remote (server) view + * to our local (client) view. + */ + ApiMessage->CsrCaptureData = (PCSR_CAPTURE_BUFFER) + ((ULONG_PTR)ApiMessage->CsrCaptureData - CsrPortMemoryDelta); + + /* + * Convert back the offsets into pointers to CSR message + * pointers, and convert back these message server pointers + * into client pointers. + */ + PointerCount = CaptureBuffer->PointerCount; + OffsetPointer = CaptureBuffer->PointerOffsetsArray; + while (PointerCount--) + { + if (*OffsetPointer != 0) + { + *OffsetPointer += (ULONG_PTR)ApiMessage; + *(PULONG_PTR)*OffsetPointer -= CsrPortMemoryDelta; + } + ++OffsetPointer; + } + } +#endif + + /* Check for success */ + if (!NT_SUCCESS(Status)) + { + /* We failed. Overwrite the return value with the failure. */ + ERR("LPC Failed: %lx\n", Status); + ApiMessage->Status = Status; + } + + /* Return the CSR Result */ + TRACE("Got back: 0x%lx\n", ApiMessage->Status); + return ApiMessage->Status; } /* EOF */ diff --git a/reactos/win32ss/user/ntuser/csr.h b/reactos/win32ss/user/ntuser/csr.h index 94275cc7eb4..96d9fa31bca 100644 --- a/reactos/win32ss/user/ntuser/csr.h +++ b/reactos/win32ss/user/ntuser/csr.h @@ -1,16 +1,35 @@ /* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS Win32k subsystem - * PURPOSE: Interface to CSRSS / USERSRV + * PURPOSE: Interface between Win32k and USERSRV * FILE: subsystems/win32/win32k/ntuser/csr.h - * PROGRAMER: Ge van Geldorp (ge@gse.nl) + * PROGRAMER: Hermes Belusca-Maito (hermes.belusca@sfr.fr), based on + * the original code by Ge van Geldorp (ge@gse.nl) and by + * the CSR code in NTDLL. */ #pragma once -extern PEPROCESS CsrProcess; +/* NDK Headers */ +#include -NTSTATUS FASTCALL CsrInit(void); -NTSTATUS FASTCALL co_CsrNotify(PCSR_API_MESSAGE Request); +/* CSRSS Header */ +#include +#include + +extern PEPROCESS gpepCSRSS; +extern PVOID CsrApiPort; + +VOID InitCsrProcess(VOID /*IN PEPROCESS CsrProcess*/); +VOID ResetCsrProcess(VOID); +NTSTATUS InitCsrApiPort(IN HANDLE CsrPortHandle); +VOID ResetCsrApiPort(VOID); + +NTSTATUS +NTAPI +CsrClientCallServer(IN OUT PCSR_API_MESSAGE ApiMessage, + IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer OPTIONAL, + IN CSR_API_NUMBER ApiNumber, + IN ULONG DataLength); /* EOF */ diff --git a/reactos/win32ss/user/ntuser/main.c b/reactos/win32ss/user/ntuser/main.c index eeed3e613d7..cd47ad1eb17 100644 --- a/reactos/win32ss/user/ntuser/main.c +++ b/reactos/win32ss/user/ntuser/main.c @@ -724,18 +724,30 @@ Win32kThreadCallback(struct _ETHREAD *Thread, return Status; } + +VOID NTAPI +DriverUnload(IN PDRIVER_OBJECT DriverObject) +{ + // TODO: Do more cleanup! + + ResetCsrApiPort(); + ResetCsrProcess(); +} + #ifdef _M_IX86 C_ASSERT(sizeof(SERVERINFO) <= PAGE_SIZE); #endif // Return on failure #define NT_ROF(x) \ +{ \ Status = (x); \ if (!NT_SUCCESS(Status)) \ { \ DPRINT1("Failed '%s' (0x%lx)\n", #x, Status); \ return Status; \ - } + } \ +} /* * This definition doesn't work @@ -744,8 +756,8 @@ INIT_FUNCTION NTSTATUS APIENTRY DriverEntry( - IN PDRIVER_OBJECT DriverObject, - IN PUNICODE_STRING RegistryPath) + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath) { NTSTATUS Status; BOOLEAN Result; @@ -768,7 +780,9 @@ DriverEntry( } hModuleWin = MmPageEntireDriver(DriverEntry); - DPRINT("Win32k hInstance 0x%p!\n",hModuleWin); + DPRINT("Win32k hInstance 0x%p!\n", hModuleWin); + + DriverObject->DriverUnload = DriverUnload; /* Register Object Manager Callbacks */ CalloutData.ProcessCallout = Win32kProcessCallback; diff --git a/reactos/win32ss/user/ntuser/ntstubs.c b/reactos/win32ss/user/ntuser/ntstubs.c index 1493825721d..ae3ab4119c5 100644 --- a/reactos/win32ss/user/ntuser/ntstubs.c +++ b/reactos/win32ss/user/ntuser/ntstubs.c @@ -939,9 +939,13 @@ NtUserSetInformationThread(IN HANDLE ThreadHandle, case UserThreadCsrApiPort: { ERR("Set CSR API Port for Win32k\n"); - STUB; - // Return success to make usersrv happy. - Status = STATUS_SUCCESS; + + if (ThreadInformationLength != sizeof(HANDLE)) + { + Status = STATUS_INFO_LENGTH_MISMATCH; + break; + } + Status = InitCsrApiPort(*(PHANDLE)ThreadInformation); break; } diff --git a/reactos/win32ss/user/ntuser/ntuser.c b/reactos/win32ss/user/ntuser/ntuser.c index f67c4ab617a..efa2c493df1 100644 --- a/reactos/win32ss/user/ntuser/ntuser.c +++ b/reactos/win32ss/user/ntuser/ntuser.c @@ -19,7 +19,6 @@ ATOM AtomLayer; // Window Layer atom. ATOM AtomFlashWndState; // Window Flash State atom. HINSTANCE hModClient = NULL; BOOL ClientPfnInit = FALSE; -PEPROCESS gpepCSRSS = NULL; ATOM gaGuiConsoleWndClass; /* PRIVATE FUNCTIONS *********************************************************/ @@ -175,7 +174,7 @@ NtUserInitialize( UserEnterExclusive(); /* Save the EPROCESS of CSRSS */ - gpepCSRSS = PsGetCurrentProcess(); + InitCsrProcess(/*PsGetCurrentProcess()*/); // Initialize Power Request List (use hPowerRequestEvent). // Initialize Media Change (use hMediaRequestEvent). diff --git a/reactos/win32ss/user/ntuser/ntuser.h b/reactos/win32ss/user/ntuser/ntuser.h index 584091f7707..799318af50f 100644 --- a/reactos/win32ss/user/ntuser/ntuser.h +++ b/reactos/win32ss/user/ntuser/ntuser.h @@ -14,7 +14,6 @@ extern PTHREADINFO gptiCurrent; extern PPROCESSINFO gppiList; extern PPROCESSINFO ppiScrnSaver; extern PPROCESSINFO gppiInputProvider; -extern PEPROCESS gpepCSRSS; extern ATOM gaGuiConsoleWndClass; INIT_FUNCTION NTSTATUS NTAPI InitUserImpl(VOID); diff --git a/reactos/win32ss/win32kp.h b/reactos/win32ss/win32kp.h index 5e60855f84e..ce5e7ec3eea 100644 --- a/reactos/win32ss/win32kp.h +++ b/reactos/win32ss/win32kp.h @@ -26,7 +26,10 @@ #define DBG_ENABLE_EVENT_LOGGING 0 #define DBG_ENABLE_SERVICE_HOOKS 0 -/* Misc headers */ +/* CSRSS Interface */ +#include "user/ntuser/csr.h" + +/* Misc headers */ #include "user/ntuser/win32kdebug.h" #include "user/ntuser/mmcopy.h" #include "user/ntuser/tags.h"