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=65817&r1=65816&r2=65817&view=diff
==============================================================================
--- 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?rev=65817&r1=65816&r2=65817&view=diff
==============================================================================
--- 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 ([email protected])
+ * PROGRAMER:        Hermes Belusca-Maito ([email protected]), based on
+ *                   the original code by Ge van Geldorp ([email protected]) 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?rev=65817&r1=65816&r2=65817&view=diff
==============================================================================
--- 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 ([email protected])
+ * PROGRAMER:        Hermes Belusca-Maito ([email protected]), based on
+ *                   the original code by Ge van Geldorp ([email protected]) 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?rev=65817&r1=65816&r2=65817&view=diff
==============================================================================
--- 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.c?rev=65817&r1=65816&r2=65817&view=diff
==============================================================================
--- 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.c?rev=65817&r1=65816&r2=65817&view=diff
==============================================================================
--- 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.h?rev=65817&r1=65816&r2=65817&view=diff
==============================================================================
--- 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&r1=65816&r2=65817&view=diff
==============================================================================
--- 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"


Reply via email to