[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:
Giannis Adamopoulos 2018-12-16 13:16:29 +02:00
parent 9924da34cc
commit 1a8d9f12d6
11 changed files with 183 additions and 72 deletions

View file

@ -14,6 +14,7 @@ DBG_DEFAULT_CHANNEL(UserCsr);
PEPROCESS gpepCSRSS = NULL;
PVOID CsrApiPort = NULL;
DWORD gdwPendingSystemThreads = 0;
VOID
InitCsrProcess(VOID /*IN PEPROCESS CsrProcess*/)
@ -197,4 +198,83 @@ CsrClientCallServer(IN OUT PCSR_API_MESSAGE ApiMessage,
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 */

View file

@ -32,4 +32,11 @@ CsrClientCallServer(IN OUT PCSR_API_MESSAGE ApiMessage,
IN CSR_API_NUMBER ApiNumber,
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 */

View file

@ -36,6 +36,7 @@ PDESKTOP gpdeskInputDesktop = NULL;
HDC ScreenDeviceContext = NULL;
PTHREADINFO gptiDesktopThread = NULL;
HCURSOR gDesktopCursor = NULL;
PKEVENT gpDesktopThreadStartedEvent = NULL;
/* OBJECT CALLBACKS **********************************************************/
@ -243,6 +244,22 @@ InitDesktopImpl(VOID)
ExDesktopObjectType->TypeInfo.DefaultNonPagedPoolCharge = sizeof(DESKTOP);
ExDesktopObjectType->TypeInfo.GenericMapping = IntDesktopMapping;
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;
}
@ -1501,6 +1518,8 @@ VOID NTAPI DesktopThreadMain(VOID)
classes will be allocated from the shared heap */
UserRegisterSystemClasses();
KeSetEvent(gpDesktopThreadStartedEvent, IO_NO_INCREMENT, FALSE);
while (TRUE)
{
Ret = co_IntGetPeekMessage(&Msg, 0, 0, 0, PM_REMOVE, TRUE);

View file

@ -86,6 +86,7 @@ extern PCLS DesktopWindowClass;
extern HDC ScreenDeviceContext;
extern PTHREADINFO gptiForeground;
extern PTHREADINFO gptiDesktopThread;
extern PKEVENT gpDesktopThreadStartedEvent;
typedef struct _SHELL_HOOK_WINDOW
{

View file

@ -11,9 +11,34 @@
#define NDEBUG
#include <debug.h>
DBG_DEFAULT_CHANNEL(UserInput);
static UNICODE_STRING GhostClass = RTL_CONSTANT_STRING(GHOSTCLASSNAME);
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)
{
BOOLEAN Ret = FALSE;
@ -161,18 +186,10 @@ BOOL FASTCALL IntMakeHungWindowGhosted(HWND hwndHung)
return FALSE; // already ghosting
}
// TODO:
// 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;
}
}
// TODO: Find a way to pass the hwnd of pHungWnd to the ghost thread as we can't pass parameters directly
return FALSE;
if (!gptiGhostThread)
UserCreateSystemThread(ST_GHOST_THREAD);
return TRUE;
}

View file

@ -1 +1,3 @@
BOOL FASTCALL IntMakeHungWindowGhosted(HWND hwndHung);
VOID NTAPI UserGhostThreadEntry(VOID);

View file

@ -138,6 +138,7 @@ RawInputThreadMain(VOID)
MOUSE_INPUT_DATA MouseInput;
KEYBOARD_INPUT_DATA KeyInput;
PVOID ShutdownEvent;
HWINSTA hWinSta;
ByteOffset.QuadPart = (LONGLONG)0;
//WaitTimeout.QuadPart = (LONGLONG)(-10000000);
@ -151,6 +152,23 @@ RawInputThreadMain(VOID)
KeSetPriorityThread(&PsGetCurrentThread()->Tcb,
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();
StartTheTimers();
UserLeave();
@ -330,29 +348,6 @@ RawInputThreadMain(VOID)
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
*

View file

@ -60,8 +60,8 @@ extern PATTACHINFO gpai;
/* General */
INIT_FUNCTION NTSTATUS NTAPI InitInputImpl(VOID);
VOID NTAPI RawInputThreadMain(VOID);
BOOL FASTCALL IntBlockInput(PTHREADINFO W32Thread, BOOL BlockIt);
DWORD NTAPI CreateSystemThreads(UINT Type);
NTSTATUS FASTCALL UserAttachThreadInput(PTHREADINFO,PTHREADINFO,BOOL);
BOOL FASTCALL IsRemoveAttachThread(PTHREADINFO);
VOID FASTCALL DoTheScreenSaver(VOID);

View file

@ -392,7 +392,7 @@ NtUserCallOneParam(
break;
case ONEPARAM_ROUTINE_CREATESYSTEMTHREADS:
Result = CreateSystemThreads(Param);
Result = UserSystemThreadProc(Param);
break;
case ONEPARAM_ROUTINE_LOCKFOREGNDWINDOW:

View file

@ -497,7 +497,20 @@ IntCreateWindowStation(
InputWindowStation = WindowStation;
WindowStation->Flags &= ~WSS_NOIO;
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
{
@ -742,6 +755,8 @@ NtUserCreateWindowStation(
return NULL;
}
UserEnterExclusive();
/* Create the window station */
Status = IntCreateWindowStation(&hWinSta,
ObjectAttributes,
@ -753,6 +768,8 @@ NtUserCreateWindowStation(
Unknown4,
Unknown5,
Unknown6);
UserLeave();
if (NT_SUCCESS(Status))
{
TRACE("NtUserCreateWindowStation created window station '%wZ' with handle 0x%p\n",

View file

@ -121,8 +121,13 @@ CreateSystemThreads(PVOID pParam)
CSR_API(SrvCreateSystemThreads)
{
DPRINT1("%s not yet implemented\n", __FUNCTION__);
return STATUS_NOT_IMPLEMENTED;
NTSTATUS Status = CsrExecServerThread(CreateSystemThreads, 0);
if (!NT_SUCCESS(Status))
{
DPRINT1("Cannot start system thread!\n");
}
return Status;
}
CSR_API(SrvActivateDebugger)
@ -282,38 +287,6 @@ CSR_SERVER_DLL_INIT(UserServerDllInitialization)
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 */
return STATUS_SUCCESS;
}