https://git.reactos.org/?p=reactos.git;a=commitdiff;h=1a8d9f12d63d9135eeb8af65e1093413cadcc9bb

commit 1a8d9f12d63d9135eeb8af65e1093413cadcc9bb
Author:     Giannis Adamopoulos <[email protected]>
AuthorDate: Sun Dec 16 13:16:29 2018 +0200
Commit:     Giannis Adamopoulos <[email protected]>
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;
 }

Reply via email to