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?…
==============================================================================
--- 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(a)gse.nl)
+ * PROGRAMER: Hermes Belusca-Maito (hermes.belusca(a)sfr.fr), based on
+ * the original code by Ge van Geldorp (ge(a)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?…
==============================================================================
--- 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(a)gse.nl)
+ * PROGRAMER: Hermes Belusca-Maito (hermes.belusca(a)sfr.fr), based on
+ * the original code by Ge van Geldorp (ge(a)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/ntstub…
==============================================================================
--- 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=6581…
==============================================================================
--- 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"