mirror of
https://github.com/reactos/reactos.git
synced 2024-06-29 01:12:06 +00:00
[NTUSER] Implement creating the system threads
- Add UserCreateSystemThread function that will signal csrss to create a new system thread. - NtUserCreateWindowStation: Create the raw input thread and the desktop thread when the IO window station gets created. - IntMakeHungWindowGhosted: Create the ghost system thread that will own all ghost windows. - Let the raw input thread manage the window station of csrss. [USERSRV] Remove system threads creating hack - Implement SrvCreateSystemThreads - Don't create the system threads in UserServerDllInitialization.
This commit is contained in:
parent
9924da34cc
commit
1a8d9f12d6
|
@ -14,6 +14,7 @@ DBG_DEFAULT_CHANNEL(UserCsr);
|
||||||
|
|
||||||
PEPROCESS gpepCSRSS = NULL;
|
PEPROCESS gpepCSRSS = NULL;
|
||||||
PVOID CsrApiPort = NULL;
|
PVOID CsrApiPort = NULL;
|
||||||
|
DWORD gdwPendingSystemThreads = 0;
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
InitCsrProcess(VOID /*IN PEPROCESS CsrProcess*/)
|
InitCsrProcess(VOID /*IN PEPROCESS CsrProcess*/)
|
||||||
|
@ -197,4 +198,83 @@ CsrClientCallServer(IN OUT PCSR_API_MESSAGE ApiMessage,
|
||||||
return ApiMessage->Status;
|
return ApiMessage->Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* UserSystemThreadProc
|
||||||
|
*
|
||||||
|
* Called form dedicated thread in CSRSS. RIT is started in context of this
|
||||||
|
* thread because it needs valid Win32 process with TEB initialized.
|
||||||
|
*/
|
||||||
|
DWORD UserSystemThreadProc(BOOL bRemoteProcess)
|
||||||
|
{
|
||||||
|
DWORD Type;
|
||||||
|
|
||||||
|
if (!gdwPendingSystemThreads)
|
||||||
|
{
|
||||||
|
ERR("gdwPendingSystemThreads is 0!\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Decide which thread this will be */
|
||||||
|
if (gdwPendingSystemThreads & ST_RIT)
|
||||||
|
Type = ST_RIT;
|
||||||
|
else if (gdwPendingSystemThreads & ST_DESKTOP_THREAD)
|
||||||
|
Type = ST_DESKTOP_THREAD;
|
||||||
|
else
|
||||||
|
Type = ST_GHOST_THREAD;
|
||||||
|
|
||||||
|
ASSERT(Type);
|
||||||
|
|
||||||
|
/* We will handle one of these threads right here so unmark it as pending */
|
||||||
|
gdwPendingSystemThreads &= ~Type;
|
||||||
|
|
||||||
|
UserLeave();
|
||||||
|
|
||||||
|
TRACE("UserSystemThreadProc: %d\n", Type);
|
||||||
|
|
||||||
|
switch (Type)
|
||||||
|
{
|
||||||
|
case ST_RIT: RawInputThreadMain(); break;
|
||||||
|
case ST_DESKTOP_THREAD: DesktopThreadMain(); break;
|
||||||
|
case ST_GHOST_THREAD: UserGhostThreadEntry(); break;
|
||||||
|
default: ERR("Wrong type: %x\n", Type);
|
||||||
|
}
|
||||||
|
|
||||||
|
UserEnterShared();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL UserCreateSystemThread(DWORD Type)
|
||||||
|
{
|
||||||
|
USER_API_MESSAGE ApiMessage;
|
||||||
|
PUSER_CREATE_SYSTEM_THREAD pCreateThreadRequest = &ApiMessage.Data.CreateSystemThreadRequest;
|
||||||
|
|
||||||
|
TRACE("UserCreateSystemThread: %d\n", Type);
|
||||||
|
|
||||||
|
ASSERT(UserIsEnteredExclusive());
|
||||||
|
|
||||||
|
if (gdwPendingSystemThreads & Type)
|
||||||
|
{
|
||||||
|
ERR("System thread 0x%x already pending for creation\n", Type);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We can't pass a parameter to the new thread so mark what the new thread needs to do */
|
||||||
|
gdwPendingSystemThreads |= Type;
|
||||||
|
|
||||||
|
/* Ask winsrv to create a new system thread. This new thread will enter win32k again calling UserSystemThreadProc */
|
||||||
|
pCreateThreadRequest->bRemote = FALSE;
|
||||||
|
CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage,
|
||||||
|
NULL,
|
||||||
|
CSR_CREATE_API_NUMBER(USERSRV_SERVERDLL_INDEX, UserpCreateSystemThreads),
|
||||||
|
sizeof(USER_CREATE_SYSTEM_THREAD));
|
||||||
|
if (!NT_SUCCESS(ApiMessage.Status))
|
||||||
|
{
|
||||||
|
ERR("Csr call failed!\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -32,4 +32,11 @@ CsrClientCallServer(IN OUT PCSR_API_MESSAGE ApiMessage,
|
||||||
IN CSR_API_NUMBER ApiNumber,
|
IN CSR_API_NUMBER ApiNumber,
|
||||||
IN ULONG DataLength);
|
IN ULONG DataLength);
|
||||||
|
|
||||||
|
#define ST_RIT (1<<0)
|
||||||
|
#define ST_DESKTOP_THREAD (1<<1)
|
||||||
|
#define ST_GHOST_THREAD (1<<2)
|
||||||
|
|
||||||
|
DWORD UserSystemThreadProc(BOOL bRemoteProcess);
|
||||||
|
BOOL UserCreateSystemThread(DWORD Type);
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -36,6 +36,7 @@ PDESKTOP gpdeskInputDesktop = NULL;
|
||||||
HDC ScreenDeviceContext = NULL;
|
HDC ScreenDeviceContext = NULL;
|
||||||
PTHREADINFO gptiDesktopThread = NULL;
|
PTHREADINFO gptiDesktopThread = NULL;
|
||||||
HCURSOR gDesktopCursor = NULL;
|
HCURSOR gDesktopCursor = NULL;
|
||||||
|
PKEVENT gpDesktopThreadStartedEvent = NULL;
|
||||||
|
|
||||||
/* OBJECT CALLBACKS **********************************************************/
|
/* OBJECT CALLBACKS **********************************************************/
|
||||||
|
|
||||||
|
@ -243,6 +244,22 @@ InitDesktopImpl(VOID)
|
||||||
ExDesktopObjectType->TypeInfo.DefaultNonPagedPoolCharge = sizeof(DESKTOP);
|
ExDesktopObjectType->TypeInfo.DefaultNonPagedPoolCharge = sizeof(DESKTOP);
|
||||||
ExDesktopObjectType->TypeInfo.GenericMapping = IntDesktopMapping;
|
ExDesktopObjectType->TypeInfo.GenericMapping = IntDesktopMapping;
|
||||||
ExDesktopObjectType->TypeInfo.ValidAccessMask = DESKTOP_ALL_ACCESS;
|
ExDesktopObjectType->TypeInfo.ValidAccessMask = DESKTOP_ALL_ACCESS;
|
||||||
|
|
||||||
|
/* Allocate memory for the event structure */
|
||||||
|
gpDesktopThreadStartedEvent = ExAllocatePoolWithTag(NonPagedPool,
|
||||||
|
sizeof(KEVENT),
|
||||||
|
USERTAG_EVENT);
|
||||||
|
if (!gpDesktopThreadStartedEvent)
|
||||||
|
{
|
||||||
|
ERR("Failed to allocate event!\n");
|
||||||
|
return STATUS_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize the kernel event */
|
||||||
|
KeInitializeEvent(gpDesktopThreadStartedEvent,
|
||||||
|
SynchronizationEvent,
|
||||||
|
FALSE);
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1501,6 +1518,8 @@ VOID NTAPI DesktopThreadMain(VOID)
|
||||||
classes will be allocated from the shared heap */
|
classes will be allocated from the shared heap */
|
||||||
UserRegisterSystemClasses();
|
UserRegisterSystemClasses();
|
||||||
|
|
||||||
|
KeSetEvent(gpDesktopThreadStartedEvent, IO_NO_INCREMENT, FALSE);
|
||||||
|
|
||||||
while (TRUE)
|
while (TRUE)
|
||||||
{
|
{
|
||||||
Ret = co_IntGetPeekMessage(&Msg, 0, 0, 0, PM_REMOVE, TRUE);
|
Ret = co_IntGetPeekMessage(&Msg, 0, 0, 0, PM_REMOVE, TRUE);
|
||||||
|
|
|
@ -86,6 +86,7 @@ extern PCLS DesktopWindowClass;
|
||||||
extern HDC ScreenDeviceContext;
|
extern HDC ScreenDeviceContext;
|
||||||
extern PTHREADINFO gptiForeground;
|
extern PTHREADINFO gptiForeground;
|
||||||
extern PTHREADINFO gptiDesktopThread;
|
extern PTHREADINFO gptiDesktopThread;
|
||||||
|
extern PKEVENT gpDesktopThreadStartedEvent;
|
||||||
|
|
||||||
typedef struct _SHELL_HOOK_WINDOW
|
typedef struct _SHELL_HOOK_WINDOW
|
||||||
{
|
{
|
||||||
|
|
|
@ -11,9 +11,34 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
|
DBG_DEFAULT_CHANNEL(UserInput);
|
||||||
|
|
||||||
static UNICODE_STRING GhostClass = RTL_CONSTANT_STRING(GHOSTCLASSNAME);
|
static UNICODE_STRING GhostClass = RTL_CONSTANT_STRING(GHOSTCLASSNAME);
|
||||||
static UNICODE_STRING GhostProp = RTL_CONSTANT_STRING(GHOST_PROP);
|
static UNICODE_STRING GhostProp = RTL_CONSTANT_STRING(GHOST_PROP);
|
||||||
|
|
||||||
|
PTHREADINFO gptiGhostThread = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GhostThreadMain
|
||||||
|
*
|
||||||
|
* Creates ghost windows and exits when no non-responsive window remains.
|
||||||
|
*/
|
||||||
|
VOID NTAPI
|
||||||
|
UserGhostThreadEntry(VOID)
|
||||||
|
{
|
||||||
|
TRACE("Ghost thread started\n");
|
||||||
|
|
||||||
|
UserEnterExclusive();
|
||||||
|
|
||||||
|
gptiGhostThread = PsGetCurrentThreadWin32Thread();
|
||||||
|
|
||||||
|
//TODO: Implement. This thread should handle all ghost windows and exit when no ghost window is needed.
|
||||||
|
|
||||||
|
gptiGhostThread = NULL;
|
||||||
|
|
||||||
|
UserLeave();
|
||||||
|
}
|
||||||
|
|
||||||
BOOL FASTCALL IntIsGhostWindow(PWND Window)
|
BOOL FASTCALL IntIsGhostWindow(PWND Window)
|
||||||
{
|
{
|
||||||
BOOLEAN Ret = FALSE;
|
BOOLEAN Ret = FALSE;
|
||||||
|
@ -161,18 +186,10 @@ BOOL FASTCALL IntMakeHungWindowGhosted(HWND hwndHung)
|
||||||
return FALSE; // already ghosting
|
return FALSE; // already ghosting
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO:
|
// TODO: Find a way to pass the hwnd of pHungWnd to the ghost thread as we can't pass parameters directly
|
||||||
// 1. Create a thread.
|
|
||||||
// 2. Create a ghost window in the thread.
|
|
||||||
// 3. Do message loop in the thread
|
|
||||||
{
|
|
||||||
static int bWarnedOnce = 0;
|
|
||||||
if (!bWarnedOnce)
|
|
||||||
{
|
|
||||||
bWarnedOnce++;
|
|
||||||
STUB;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return FALSE;
|
if (!gptiGhostThread)
|
||||||
|
UserCreateSystemThread(ST_GHOST_THREAD);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1,3 @@
|
||||||
BOOL FASTCALL IntMakeHungWindowGhosted(HWND hwndHung);
|
BOOL FASTCALL IntMakeHungWindowGhosted(HWND hwndHung);
|
||||||
|
VOID NTAPI UserGhostThreadEntry(VOID);
|
||||||
|
|
||||||
|
|
|
@ -138,6 +138,7 @@ RawInputThreadMain(VOID)
|
||||||
MOUSE_INPUT_DATA MouseInput;
|
MOUSE_INPUT_DATA MouseInput;
|
||||||
KEYBOARD_INPUT_DATA KeyInput;
|
KEYBOARD_INPUT_DATA KeyInput;
|
||||||
PVOID ShutdownEvent;
|
PVOID ShutdownEvent;
|
||||||
|
HWINSTA hWinSta;
|
||||||
|
|
||||||
ByteOffset.QuadPart = (LONGLONG)0;
|
ByteOffset.QuadPart = (LONGLONG)0;
|
||||||
//WaitTimeout.QuadPart = (LONGLONG)(-10000000);
|
//WaitTimeout.QuadPart = (LONGLONG)(-10000000);
|
||||||
|
@ -151,6 +152,23 @@ RawInputThreadMain(VOID)
|
||||||
KeSetPriorityThread(&PsGetCurrentThread()->Tcb,
|
KeSetPriorityThread(&PsGetCurrentThread()->Tcb,
|
||||||
LOW_REALTIME_PRIORITY + 3);
|
LOW_REALTIME_PRIORITY + 3);
|
||||||
|
|
||||||
|
Status = ObOpenObjectByPointer(InputWindowStation,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
MAXIMUM_ALLOWED,
|
||||||
|
ExWindowStationObjectType,
|
||||||
|
UserMode,
|
||||||
|
(PHANDLE)&hWinSta);
|
||||||
|
if (NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
UserSetProcessWindowStation(hWinSta);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ASSERT(FALSE);
|
||||||
|
/* Failed to open the interactive winsta! What now? */
|
||||||
|
}
|
||||||
|
|
||||||
UserEnterExclusive();
|
UserEnterExclusive();
|
||||||
StartTheTimers();
|
StartTheTimers();
|
||||||
UserLeave();
|
UserLeave();
|
||||||
|
@ -330,29 +348,6 @@ RawInputThreadMain(VOID)
|
||||||
ERR("Raw Input Thread Exit!\n");
|
ERR("Raw Input Thread Exit!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* CreateSystemThreads
|
|
||||||
*
|
|
||||||
* Called form dedicated thread in CSRSS. RIT is started in context of this
|
|
||||||
* thread because it needs valid Win32 process with TEB initialized.
|
|
||||||
*/
|
|
||||||
DWORD NTAPI
|
|
||||||
CreateSystemThreads(UINT Type)
|
|
||||||
{
|
|
||||||
UserLeave();
|
|
||||||
|
|
||||||
switch (Type)
|
|
||||||
{
|
|
||||||
case 0: RawInputThreadMain(); break;
|
|
||||||
case 1: DesktopThreadMain(); break;
|
|
||||||
default: ERR("Wrong type: %x\n", Type);
|
|
||||||
}
|
|
||||||
|
|
||||||
UserEnterShared();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* InitInputImpl
|
* InitInputImpl
|
||||||
*
|
*
|
||||||
|
|
|
@ -60,8 +60,8 @@ extern PATTACHINFO gpai;
|
||||||
|
|
||||||
/* General */
|
/* General */
|
||||||
INIT_FUNCTION NTSTATUS NTAPI InitInputImpl(VOID);
|
INIT_FUNCTION NTSTATUS NTAPI InitInputImpl(VOID);
|
||||||
|
VOID NTAPI RawInputThreadMain(VOID);
|
||||||
BOOL FASTCALL IntBlockInput(PTHREADINFO W32Thread, BOOL BlockIt);
|
BOOL FASTCALL IntBlockInput(PTHREADINFO W32Thread, BOOL BlockIt);
|
||||||
DWORD NTAPI CreateSystemThreads(UINT Type);
|
|
||||||
NTSTATUS FASTCALL UserAttachThreadInput(PTHREADINFO,PTHREADINFO,BOOL);
|
NTSTATUS FASTCALL UserAttachThreadInput(PTHREADINFO,PTHREADINFO,BOOL);
|
||||||
BOOL FASTCALL IsRemoveAttachThread(PTHREADINFO);
|
BOOL FASTCALL IsRemoveAttachThread(PTHREADINFO);
|
||||||
VOID FASTCALL DoTheScreenSaver(VOID);
|
VOID FASTCALL DoTheScreenSaver(VOID);
|
||||||
|
|
|
@ -392,7 +392,7 @@ NtUserCallOneParam(
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ONEPARAM_ROUTINE_CREATESYSTEMTHREADS:
|
case ONEPARAM_ROUTINE_CREATESYSTEMTHREADS:
|
||||||
Result = CreateSystemThreads(Param);
|
Result = UserSystemThreadProc(Param);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ONEPARAM_ROUTINE_LOCKFOREGNDWINDOW:
|
case ONEPARAM_ROUTINE_LOCKFOREGNDWINDOW:
|
||||||
|
|
|
@ -497,7 +497,20 @@ IntCreateWindowStation(
|
||||||
|
|
||||||
InputWindowStation = WindowStation;
|
InputWindowStation = WindowStation;
|
||||||
WindowStation->Flags &= ~WSS_NOIO;
|
WindowStation->Flags &= ~WSS_NOIO;
|
||||||
|
|
||||||
InitCursorImpl();
|
InitCursorImpl();
|
||||||
|
|
||||||
|
UserCreateSystemThread(ST_DESKTOP_THREAD);
|
||||||
|
UserCreateSystemThread(ST_RIT);
|
||||||
|
|
||||||
|
/* Desktop functions require the desktop thread running so wait for it to initialize */
|
||||||
|
UserLeaveCo();
|
||||||
|
KeWaitForSingleObject(gpDesktopThreadStartedEvent,
|
||||||
|
UserRequest,
|
||||||
|
UserMode,
|
||||||
|
FALSE,
|
||||||
|
NULL);
|
||||||
|
UserEnterCo();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -742,6 +755,8 @@ NtUserCreateWindowStation(
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UserEnterExclusive();
|
||||||
|
|
||||||
/* Create the window station */
|
/* Create the window station */
|
||||||
Status = IntCreateWindowStation(&hWinSta,
|
Status = IntCreateWindowStation(&hWinSta,
|
||||||
ObjectAttributes,
|
ObjectAttributes,
|
||||||
|
@ -753,6 +768,8 @@ NtUserCreateWindowStation(
|
||||||
Unknown4,
|
Unknown4,
|
||||||
Unknown5,
|
Unknown5,
|
||||||
Unknown6);
|
Unknown6);
|
||||||
|
UserLeave();
|
||||||
|
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
TRACE("NtUserCreateWindowStation created window station '%wZ' with handle 0x%p\n",
|
TRACE("NtUserCreateWindowStation created window station '%wZ' with handle 0x%p\n",
|
||||||
|
|
|
@ -121,8 +121,13 @@ CreateSystemThreads(PVOID pParam)
|
||||||
|
|
||||||
CSR_API(SrvCreateSystemThreads)
|
CSR_API(SrvCreateSystemThreads)
|
||||||
{
|
{
|
||||||
DPRINT1("%s not yet implemented\n", __FUNCTION__);
|
NTSTATUS Status = CsrExecServerThread(CreateSystemThreads, 0);
|
||||||
return STATUS_NOT_IMPLEMENTED;
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
DPRINT1("Cannot start system thread!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
CSR_API(SrvActivateDebugger)
|
CSR_API(SrvActivateDebugger)
|
||||||
|
@ -282,38 +287,6 @@ CSR_SERVER_DLL_INIT(UserServerDllInitialization)
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*** From win32csr... See r54125 ***/
|
|
||||||
{
|
|
||||||
HANDLE ServerThread;
|
|
||||||
CLIENT_ID ClientId;
|
|
||||||
UINT i;
|
|
||||||
|
|
||||||
/* Start the Raw Input Thread and the Desktop Thread */
|
|
||||||
for (i = 0; i < 2; ++i)
|
|
||||||
{
|
|
||||||
Status = RtlCreateUserThread(NtCurrentProcess(),
|
|
||||||
NULL,
|
|
||||||
TRUE,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
CreateSystemThreads,
|
|
||||||
UlongToPtr(i),
|
|
||||||
&ServerThread,
|
|
||||||
&ClientId);
|
|
||||||
if (NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
NtResumeThread(ServerThread, NULL);
|
|
||||||
NtClose(ServerThread);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DPRINT1("Cannot start Raw Input Thread!\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*** END - From win32csr... ***/
|
|
||||||
|
|
||||||
/* All done */
|
/* All done */
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue