https://git.reactos.org/?p=reactos.git;a=commitdiff;h=1a8d9f12d63d9135eeb8a…
commit 1a8d9f12d63d9135eeb8af65e1093413cadcc9bb
Author: Giannis Adamopoulos <gadamopoulos(a)reactos.org>
AuthorDate: Sun Dec 16 13:16:29 2018 +0200
Commit: Giannis Adamopoulos <gadamopoulos(a)reactos.org>
CommitDate: Wed Dec 19 16:13:18 2018 +0200
[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.
---
win32ss/user/ntuser/csr.c | 80 ++++++++++++++++++++++++++++++++++++++
win32ss/user/ntuser/csr.h | 7 ++++
win32ss/user/ntuser/desktop.c | 19 +++++++++
win32ss/user/ntuser/desktop.h | 1 +
win32ss/user/ntuser/ghost.c | 43 +++++++++++++-------
win32ss/user/ntuser/ghost.h | 2 +
win32ss/user/ntuser/input.c | 41 +++++++++----------
win32ss/user/ntuser/input.h | 2 +-
win32ss/user/ntuser/simplecall.c | 2 +-
win32ss/user/ntuser/winsta.c | 17 ++++++++
win32ss/user/winsrv/usersrv/init.c | 41 ++++---------------
11 files changed, 183 insertions(+), 72 deletions(-)
diff --git a/win32ss/user/ntuser/csr.c b/win32ss/user/ntuser/csr.c
index 7893cb53c0..93fffc0e7e 100644
--- a/win32ss/user/ntuser/csr.c
+++ b/win32ss/user/ntuser/csr.c
@@ -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 */
diff --git a/win32ss/user/ntuser/csr.h b/win32ss/user/ntuser/csr.h
index 8359e733a2..ac1ef10bc9 100644
--- a/win32ss/user/ntuser/csr.h
+++ b/win32ss/user/ntuser/csr.h
@@ -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 */
diff --git a/win32ss/user/ntuser/desktop.c b/win32ss/user/ntuser/desktop.c
index 4cfdde9af7..e066198226 100644
--- a/win32ss/user/ntuser/desktop.c
+++ b/win32ss/user/ntuser/desktop.c
@@ -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);
diff --git a/win32ss/user/ntuser/desktop.h b/win32ss/user/ntuser/desktop.h
index 0e1950ff64..6f15bb12a3 100644
--- a/win32ss/user/ntuser/desktop.h
+++ b/win32ss/user/ntuser/desktop.h
@@ -86,6 +86,7 @@ extern PCLS DesktopWindowClass;
extern HDC ScreenDeviceContext;
extern PTHREADINFO gptiForeground;
extern PTHREADINFO gptiDesktopThread;
+extern PKEVENT gpDesktopThreadStartedEvent;
typedef struct _SHELL_HOOK_WINDOW
{
diff --git a/win32ss/user/ntuser/ghost.c b/win32ss/user/ntuser/ghost.c
index 3342fea155..fcb70a4c77 100644
--- a/win32ss/user/ntuser/ghost.c
+++ b/win32ss/user/ntuser/ghost.c
@@ -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
+
+ if (!gptiGhostThread)
+ UserCreateSystemThread(ST_GHOST_THREAD);
- return FALSE;
+ return TRUE;
}
diff --git a/win32ss/user/ntuser/ghost.h b/win32ss/user/ntuser/ghost.h
index cd7b45ce5c..9746658335 100644
--- a/win32ss/user/ntuser/ghost.h
+++ b/win32ss/user/ntuser/ghost.h
@@ -1 +1,3 @@
BOOL FASTCALL IntMakeHungWindowGhosted(HWND hwndHung);
+VOID NTAPI UserGhostThreadEntry(VOID);
+
diff --git a/win32ss/user/ntuser/input.c b/win32ss/user/ntuser/input.c
index 509fcda6e9..e4dbbabba0 100644
--- a/win32ss/user/ntuser/input.c
+++ b/win32ss/user/ntuser/input.c
@@ -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
*
diff --git a/win32ss/user/ntuser/input.h b/win32ss/user/ntuser/input.h
index 715a0b95ee..2c2e50c4ef 100644
--- a/win32ss/user/ntuser/input.h
+++ b/win32ss/user/ntuser/input.h
@@ -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);
diff --git a/win32ss/user/ntuser/simplecall.c b/win32ss/user/ntuser/simplecall.c
index 9356415c46..179d58bcde 100644
--- a/win32ss/user/ntuser/simplecall.c
+++ b/win32ss/user/ntuser/simplecall.c
@@ -392,7 +392,7 @@ NtUserCallOneParam(
break;
case ONEPARAM_ROUTINE_CREATESYSTEMTHREADS:
- Result = CreateSystemThreads(Param);
+ Result = UserSystemThreadProc(Param);
break;
case ONEPARAM_ROUTINE_LOCKFOREGNDWINDOW:
diff --git a/win32ss/user/ntuser/winsta.c b/win32ss/user/ntuser/winsta.c
index 12a1b90d3a..63325fe800 100644
--- a/win32ss/user/ntuser/winsta.c
+++ b/win32ss/user/ntuser/winsta.c
@@ -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",
diff --git a/win32ss/user/winsrv/usersrv/init.c b/win32ss/user/winsrv/usersrv/init.c
index d70209e688..2c38825bbe 100644
--- a/win32ss/user/winsrv/usersrv/init.c
+++ b/win32ss/user/winsrv/usersrv/init.c
@@ -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;
}