mirror of
https://github.com/reactos/reactos.git
synced 2024-07-01 02:10:07 +00:00
[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. svn path=/trunk/; revision=65817
This commit is contained in:
parent
eacca6fe3e
commit
56347a8b98
|
@ -105,6 +105,7 @@ list(APPEND SOURCE
|
||||||
user/ntuser/caret.c
|
user/ntuser/caret.c
|
||||||
user/ntuser/class.c
|
user/ntuser/class.c
|
||||||
user/ntuser/clipboard.c
|
user/ntuser/clipboard.c
|
||||||
|
user/ntuser/csr.c
|
||||||
user/ntuser/defwnd.c
|
user/ntuser/defwnd.c
|
||||||
user/ntuser/desktop.c
|
user/ntuser/desktop.c
|
||||||
user/ntuser/display.c
|
user/ntuser/display.c
|
||||||
|
|
|
@ -1,91 +1,201 @@
|
||||||
/*
|
/*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS Win32k subsystem
|
* PROJECT: ReactOS Win32k subsystem
|
||||||
* PURPOSE: Interface to CSRSS / USERSRV
|
* PURPOSE: Interface between Win32k and USERSRV
|
||||||
* FILE: subsystems/win32/win32k/ntuser/csr.c
|
* 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>
|
#include <win32k.h>
|
||||||
|
|
||||||
static HANDLE WindowsApiPort = NULL;
|
DBG_DEFAULT_CHANNEL(UserCsr);
|
||||||
// See gpepCSRSS in ntuser/ntuser.c and its initialization into NtUserInitialize()
|
|
||||||
PEPROCESS CsrProcess = NULL;
|
|
||||||
|
|
||||||
NTSTATUS FASTCALL
|
PEPROCESS gpepCSRSS = NULL;
|
||||||
CsrInit(void)
|
PVOID CsrApiPort = NULL;
|
||||||
|
|
||||||
|
VOID
|
||||||
|
InitCsrProcess(VOID /*IN PEPROCESS CsrProcess*/)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
/* Save the EPROCESS of CSRSS */
|
||||||
UNICODE_STRING PortName;
|
gpepCSRSS = PsGetCurrentProcess();
|
||||||
ULONG ConnectInfoLength;
|
// gpepCSRSS = CsrProcess;
|
||||||
SECURITY_QUALITY_OF_SERVICE Qos;
|
ObReferenceObject(gpepCSRSS);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS FASTCALL
|
VOID
|
||||||
co_CsrNotify(PCSR_API_MESSAGE Request)
|
ResetCsrProcess(VOID)
|
||||||
|
{
|
||||||
|
if (gpepCSRSS)
|
||||||
|
ObDereferenceObject(gpepCSRSS);
|
||||||
|
|
||||||
|
gpepCSRSS = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
InitCsrApiPort(IN HANDLE CsrPortHandle)
|
||||||
{
|
{
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
PEPROCESS OldProcess;
|
|
||||||
|
|
||||||
if (NULL == CsrProcess)
|
Status = ObReferenceObjectByHandle(CsrPortHandle,
|
||||||
|
0,
|
||||||
|
/* * */LpcPortObjectType, // or NULL,
|
||||||
|
UserMode,
|
||||||
|
&CsrApiPort,
|
||||||
|
NULL);
|
||||||
|
if (!NT_SUCCESS(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;
|
return STATUS_INVALID_PORT_HANDLE;
|
||||||
}
|
|
||||||
|
|
||||||
Request->Header.u2.ZeroInit = 0;
|
/* Fill out the Port Message Header */
|
||||||
Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
|
ApiMessage->Header.u2.ZeroInit = 0;
|
||||||
Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
|
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);
|
||||||
|
|
||||||
/* Switch to the process in which the WindowsApiPort handle is valid */
|
/* Fill out the CSR Header */
|
||||||
OldProcess = PsGetCurrentProcess();
|
ApiMessage->ApiNumber = ApiNumber;
|
||||||
if (CsrProcess != OldProcess)
|
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)
|
||||||
{
|
{
|
||||||
KeAttachProcess(&CsrProcess->Pcb);
|
/*
|
||||||
|
* 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();
|
UserLeaveCo();
|
||||||
|
|
||||||
Status = ZwRequestWaitReplyPort(WindowsApiPort,
|
/* Send the LPC Message */
|
||||||
&Request->Header,
|
|
||||||
&Request->Header);
|
// 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();
|
UserEnterCo();
|
||||||
|
|
||||||
if (CsrProcess != OldProcess)
|
#if 0
|
||||||
|
/* Check if we got a Capture Buffer */
|
||||||
|
if (CaptureBuffer)
|
||||||
{
|
{
|
||||||
KeDetachProcess();
|
/*
|
||||||
|
* 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NT_SUCCESS(Status))
|
/* Return the CSR Result */
|
||||||
{
|
TRACE("Got back: 0x%lx\n", ApiMessage->Status);
|
||||||
Status = Request->Status;
|
return ApiMessage->Status;
|
||||||
}
|
|
||||||
|
|
||||||
return Status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -1,16 +1,35 @@
|
||||||
/*
|
/*
|
||||||
* COPYRIGHT: See COPYING in the top level directory
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS Win32k subsystem
|
* PROJECT: ReactOS Win32k subsystem
|
||||||
* PURPOSE: Interface to CSRSS / USERSRV
|
* PURPOSE: Interface between Win32k and USERSRV
|
||||||
* FILE: subsystems/win32/win32k/ntuser/csr.h
|
* 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
|
#pragma once
|
||||||
|
|
||||||
extern PEPROCESS CsrProcess;
|
/* NDK Headers */
|
||||||
|
#include <ndk/lpcfuncs.h>
|
||||||
|
|
||||||
NTSTATUS FASTCALL CsrInit(void);
|
/* CSRSS Header */
|
||||||
NTSTATUS FASTCALL co_CsrNotify(PCSR_API_MESSAGE Request);
|
#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 */
|
/* EOF */
|
||||||
|
|
|
@ -724,18 +724,30 @@ Win32kThreadCallback(struct _ETHREAD *Thread,
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VOID NTAPI
|
||||||
|
DriverUnload(IN PDRIVER_OBJECT DriverObject)
|
||||||
|
{
|
||||||
|
// TODO: Do more cleanup!
|
||||||
|
|
||||||
|
ResetCsrApiPort();
|
||||||
|
ResetCsrProcess();
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef _M_IX86
|
#ifdef _M_IX86
|
||||||
C_ASSERT(sizeof(SERVERINFO) <= PAGE_SIZE);
|
C_ASSERT(sizeof(SERVERINFO) <= PAGE_SIZE);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Return on failure
|
// Return on failure
|
||||||
#define NT_ROF(x) \
|
#define NT_ROF(x) \
|
||||||
|
{ \
|
||||||
Status = (x); \
|
Status = (x); \
|
||||||
if (!NT_SUCCESS(Status)) \
|
if (!NT_SUCCESS(Status)) \
|
||||||
{ \
|
{ \
|
||||||
DPRINT1("Failed '%s' (0x%lx)\n", #x, Status); \
|
DPRINT1("Failed '%s' (0x%lx)\n", #x, Status); \
|
||||||
return Status; \
|
return Status; \
|
||||||
}
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This definition doesn't work
|
* This definition doesn't work
|
||||||
|
@ -768,7 +780,9 @@ DriverEntry(
|
||||||
}
|
}
|
||||||
|
|
||||||
hModuleWin = MmPageEntireDriver(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 */
|
/* Register Object Manager Callbacks */
|
||||||
CalloutData.ProcessCallout = Win32kProcessCallback;
|
CalloutData.ProcessCallout = Win32kProcessCallback;
|
||||||
|
|
|
@ -939,9 +939,13 @@ NtUserSetInformationThread(IN HANDLE ThreadHandle,
|
||||||
case UserThreadCsrApiPort:
|
case UserThreadCsrApiPort:
|
||||||
{
|
{
|
||||||
ERR("Set CSR API Port for Win32k\n");
|
ERR("Set CSR API Port for Win32k\n");
|
||||||
STUB;
|
|
||||||
// Return success to make usersrv happy.
|
if (ThreadInformationLength != sizeof(HANDLE))
|
||||||
Status = STATUS_SUCCESS;
|
{
|
||||||
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Status = InitCsrApiPort(*(PHANDLE)ThreadInformation);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,6 @@ ATOM AtomLayer; // Window Layer atom.
|
||||||
ATOM AtomFlashWndState; // Window Flash State atom.
|
ATOM AtomFlashWndState; // Window Flash State atom.
|
||||||
HINSTANCE hModClient = NULL;
|
HINSTANCE hModClient = NULL;
|
||||||
BOOL ClientPfnInit = FALSE;
|
BOOL ClientPfnInit = FALSE;
|
||||||
PEPROCESS gpepCSRSS = NULL;
|
|
||||||
ATOM gaGuiConsoleWndClass;
|
ATOM gaGuiConsoleWndClass;
|
||||||
|
|
||||||
/* PRIVATE FUNCTIONS *********************************************************/
|
/* PRIVATE FUNCTIONS *********************************************************/
|
||||||
|
@ -175,7 +174,7 @@ NtUserInitialize(
|
||||||
UserEnterExclusive();
|
UserEnterExclusive();
|
||||||
|
|
||||||
/* Save the EPROCESS of CSRSS */
|
/* Save the EPROCESS of CSRSS */
|
||||||
gpepCSRSS = PsGetCurrentProcess();
|
InitCsrProcess(/*PsGetCurrentProcess()*/);
|
||||||
|
|
||||||
// Initialize Power Request List (use hPowerRequestEvent).
|
// Initialize Power Request List (use hPowerRequestEvent).
|
||||||
// Initialize Media Change (use hMediaRequestEvent).
|
// Initialize Media Change (use hMediaRequestEvent).
|
||||||
|
|
|
@ -14,7 +14,6 @@ extern PTHREADINFO gptiCurrent;
|
||||||
extern PPROCESSINFO gppiList;
|
extern PPROCESSINFO gppiList;
|
||||||
extern PPROCESSINFO ppiScrnSaver;
|
extern PPROCESSINFO ppiScrnSaver;
|
||||||
extern PPROCESSINFO gppiInputProvider;
|
extern PPROCESSINFO gppiInputProvider;
|
||||||
extern PEPROCESS gpepCSRSS;
|
|
||||||
extern ATOM gaGuiConsoleWndClass;
|
extern ATOM gaGuiConsoleWndClass;
|
||||||
|
|
||||||
INIT_FUNCTION NTSTATUS NTAPI InitUserImpl(VOID);
|
INIT_FUNCTION NTSTATUS NTAPI InitUserImpl(VOID);
|
||||||
|
|
|
@ -26,6 +26,9 @@
|
||||||
#define DBG_ENABLE_EVENT_LOGGING 0
|
#define DBG_ENABLE_EVENT_LOGGING 0
|
||||||
#define DBG_ENABLE_SERVICE_HOOKS 0
|
#define DBG_ENABLE_SERVICE_HOOKS 0
|
||||||
|
|
||||||
|
/* CSRSS Interface */
|
||||||
|
#include "user/ntuser/csr.h"
|
||||||
|
|
||||||
/* Misc headers */
|
/* Misc headers */
|
||||||
#include "user/ntuser/win32kdebug.h"
|
#include "user/ntuser/win32kdebug.h"
|
||||||
#include "user/ntuser/mmcopy.h"
|
#include "user/ntuser/mmcopy.h"
|
||||||
|
|
Loading…
Reference in a new issue