Author: hbelusca Date: Tue Dec 23 21:17:24 2014 New Revision: 65817
URL: http://svn.reactos.org/svn/reactos?rev=65817&view=rev Log: [WIN32K] Reintroduce CSR support for kernel mode, based on code from Ge that was wiped out in revision 58770, and by ntdll CSR code. Is needed for kernel to user-mode CSR callbacks.
For readers, I remind you the big callback picture in the Win32 subsystem: - In Windows NT 3.1 and 3.51, USER and GDI was modeled against client/server model (USER32.DLL and WINSRV.DLL, and GDI32.DLL and GDISRV.DLL), all running in user mode (using the CSR API). - Starting Windows NT 4.0 (and up), some USER and GDI parts were moved into kernel mode (in the WIN32K.SYS driver) to speedup communication. We get: * GDI32.DLL as the client, doing win32k system calls (kernel-mode system calls to win32k), * and USER32.DLL, WINSRV.DLL and WIN32K.SYS working in tandem, USER32.DLL being the client and {WINSRV.DLL, WIN32K.SYS} being the server. USER32.DLL can do win32k system calls or CSR calls to WINSRV.DLL (client to server calls). For server-to-server calls, we have WINSRV.DLL doing win32k system calls, or WIN32K.SYS doing CSR calls back to WINSRV.DLL . Also, there is the possibility for WIN32K.SYS to make user-mode callbacks to USER32.DLL.
Modified: trunk/reactos/win32ss/CMakeLists.txt trunk/reactos/win32ss/user/ntuser/csr.c trunk/reactos/win32ss/user/ntuser/csr.h trunk/reactos/win32ss/user/ntuser/main.c trunk/reactos/win32ss/user/ntuser/ntstubs.c trunk/reactos/win32ss/user/ntuser/ntuser.c trunk/reactos/win32ss/user/ntuser/ntuser.h trunk/reactos/win32ss/win32kp.h
Modified: trunk/reactos/win32ss/CMakeLists.txt URL: http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/CMakeLists.txt?rev=... ============================================================================== --- trunk/reactos/win32ss/CMakeLists.txt [iso-8859-1] (original) +++ trunk/reactos/win32ss/CMakeLists.txt [iso-8859-1] Tue Dec 23 21:17:24 2014 @@ -105,6 +105,7 @@ 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
Modified: trunk/reactos/win32ss/user/ntuser/csr.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/csr.c?r... ============================================================================== --- trunk/reactos/win32ss/user/ntuser/csr.c [iso-8859-1] (original) +++ trunk/reactos/win32ss/user/ntuser/csr.c [iso-8859-1] Tue Dec 23 21:17:24 2014 @@ -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 <win32k.h>
-static HANDLE WindowsApiPort = NULL; -// See gpepCSRSS in ntuser/ntuser.c and its initialization into NtUserInitialize() -PEPROCESS CsrProcess = NULL; - -NTSTATUS FASTCALL -CsrInit(void) +DBG_DEFAULT_CHANNEL(UserCsr); + +PEPROCESS gpepCSRSS = NULL; +PVOID CsrApiPort = NULL; + +VOID +InitCsrProcess(VOID /*IN PEPROCESS CsrProcess*/) +{ + /* Save the EPROCESS of CSRSS */ + gpepCSRSS = PsGetCurrentProcess(); + // gpepCSRSS = CsrProcess; + ObReferenceObject(gpepCSRSS); +} + +VOID +ResetCsrProcess(VOID) +{ + if (gpepCSRSS) + ObDereferenceObject(gpepCSRSS); + + gpepCSRSS = NULL; +} + +NTSTATUS +InitCsrApiPort(IN HANDLE CsrPortHandle) { 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); + + Status = ObReferenceObjectByHandle(CsrPortHandle, + 0, + /* * */LpcPortObjectType, // or NULL, + UserMode, + &CsrApiPort, + NULL); if (!NT_SUCCESS(Status)) { - return Status; - } - - CsrProcess = PsGetCurrentProcess(); - - return STATUS_SUCCESS; -} - -NTSTATUS FASTCALL -co_CsrNotify(PCSR_API_MESSAGE Request) -{ - NTSTATUS Status; - PEPROCESS OldProcess; - - if (NULL == CsrProcess) - { - return STATUS_INVALID_PORT_HANDLE; - } - - 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); - - /* Switch to the process in which the WindowsApiPort handle is valid */ - OldProcess = PsGetCurrentProcess(); - if (CsrProcess != OldProcess) - { - KeAttachProcess(&CsrProcess->Pcb); - } - - UserLeaveCo(); - - Status = ZwRequestWaitReplyPort(WindowsApiPort, - &Request->Header, - &Request->Header); - - UserEnterCo(); - - if (CsrProcess != OldProcess) - { - KeDetachProcess(); - } - - if (NT_SUCCESS(Status)) - { - Status = Request->Status; - } - - return Status; + CsrApiPort = NULL; + ERR("Failed to set CSR API Port.\n"); + } + + return Status; +} + +VOID +ResetCsrApiPort(VOID) +{ + if (CsrApiPort) + ObDereferenceObject(CsrApiPort); + + CsrApiPort = NULL; +} + +/* + * 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 + + /* Do we have a connection to CSR yet? */ + if (!CsrApiPort) + return STATUS_INVALID_PORT_HANDLE; + + /* 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 */
Modified: trunk/reactos/win32ss/user/ntuser/csr.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/csr.h?r... ============================================================================== --- trunk/reactos/win32ss/user/ntuser/csr.h [iso-8859-1] (original) +++ trunk/reactos/win32ss/user/ntuser/csr.h [iso-8859-1] Tue Dec 23 21:17:24 2014 @@ -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 <ndk/lpcfuncs.h>
-NTSTATUS FASTCALL CsrInit(void); -NTSTATUS FASTCALL co_CsrNotify(PCSR_API_MESSAGE Request); +/* CSRSS Header */ +#include <csr/csr.h> +#include <win/winmsg.h> + +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 */
Modified: trunk/reactos/win32ss/user/ntuser/main.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/main.c?... ============================================================================== --- trunk/reactos/win32ss/user/ntuser/main.c [iso-8859-1] (original) +++ trunk/reactos/win32ss/user/ntuser/main.c [iso-8859-1] Tue Dec 23 21:17:24 2014 @@ -724,18 +724,30 @@ 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 @@ 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 @@ }
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;
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] Tue Dec 23 21:17:24 2014 @@ -939,9 +939,13 @@ 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; }
Modified: trunk/reactos/win32ss/user/ntuser/ntuser.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/ntuser.... ============================================================================== --- trunk/reactos/win32ss/user/ntuser/ntuser.c [iso-8859-1] (original) +++ trunk/reactos/win32ss/user/ntuser/ntuser.c [iso-8859-1] Tue Dec 23 21:17:24 2014 @@ -19,7 +19,6 @@ ATOM AtomFlashWndState; // Window Flash State atom. HINSTANCE hModClient = NULL; BOOL ClientPfnInit = FALSE; -PEPROCESS gpepCSRSS = NULL; ATOM gaGuiConsoleWndClass;
/* PRIVATE FUNCTIONS *********************************************************/ @@ -175,7 +174,7 @@ UserEnterExclusive();
/* Save the EPROCESS of CSRSS */ - gpepCSRSS = PsGetCurrentProcess(); + InitCsrProcess(/*PsGetCurrentProcess()*/);
// Initialize Power Request List (use hPowerRequestEvent). // Initialize Media Change (use hMediaRequestEvent).
Modified: trunk/reactos/win32ss/user/ntuser/ntuser.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/user/ntuser/ntuser.... ============================================================================== --- trunk/reactos/win32ss/user/ntuser/ntuser.h [iso-8859-1] (original) +++ trunk/reactos/win32ss/user/ntuser/ntuser.h [iso-8859-1] Tue Dec 23 21:17:24 2014 @@ -14,7 +14,6 @@ extern PPROCESSINFO gppiList; extern PPROCESSINFO ppiScrnSaver; extern PPROCESSINFO gppiInputProvider; -extern PEPROCESS gpepCSRSS; extern ATOM gaGuiConsoleWndClass;
INIT_FUNCTION NTSTATUS NTAPI InitUserImpl(VOID);
Modified: trunk/reactos/win32ss/win32kp.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/win32ss/win32kp.h?rev=65817... ============================================================================== --- trunk/reactos/win32ss/win32kp.h [iso-8859-1] (original) +++ trunk/reactos/win32ss/win32kp.h [iso-8859-1] Tue Dec 23 21:17:24 2014 @@ -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"