[WIN32K]
[reactos.git] / reactos / win32ss / user / ntuser / main.c
index 75b46da..e6df046 100644 (file)
 
 #define NDEBUG
 #include <debug.h>
+#include <kdros.h>
 
 HANDLE hModuleWin;
 
-PGDI_HANDLE_TABLE NTAPI GDIOBJ_iAllocHandleTable(OUT PSECTION_OBJECT *SectionObject);
+PGDI_HANDLE_TABLE NTAPI GDIOBJ_iAllocHandleTable(OUT PVOID *SectionObject);
 BOOL NTAPI GDI_CleanupForProcess (struct _EPROCESS *Process);
 NTSTATUS NTAPI UserDestroyThreadInfo(struct _ETHREAD *Thread);
 
 HANDLE GlobalUserHeap = NULL;
-PSECTION_OBJECT GlobalUserHeapSection = NULL;
+PVOID GlobalUserHeapSection = NULL;
 
 PSERVERINFO gpsi = NULL; // Global User Server Information.
 
 SHORT gusLanguageID;
 PPROCESSINFO ppiScrnSaver;
+PPROCESSINFO gppiList = NULL;
 
 extern ULONG_PTR Win32kSSDT[];
 extern UCHAR Win32kSSPT[];
@@ -54,8 +56,8 @@ APIENTRY
 Win32kProcessCallback(struct _EPROCESS *Process,
                       BOOLEAN Create)
 {
-    PPROCESSINFO ppiCurrent;
-    DECLARE_RETURN(NTSTATUS);
+    PPROCESSINFO ppiCurrent, *pppi;
+    NTSTATUS Status;
 
     ASSERT(Process->Peb);
 
@@ -67,26 +69,37 @@ Win32kProcessCallback(struct _EPROCESS *Process,
         LARGE_INTEGER Offset;
         PVOID UserBase = NULL;
         PRTL_USER_PROCESS_PARAMETERS pParams = Process->Peb->ProcessParameters;
-        NTSTATUS Status;
 
-        ASSERT(PsGetProcessWin32Process(Process) == NULL);
+        /* We might be called with an already allocated win32 process */
+        ppiCurrent = PsGetProcessWin32Process(Process);
+        if (ppiCurrent != NULL)
+        {
+            /* There is no more to do for us (this is a success code!) */
+            Status = STATUS_ALREADY_WIN32;
+            goto Leave;
+        }
 
+        /* Allocate a new win32 process */
         ppiCurrent = ExAllocatePoolWithTag(NonPagedPool,
                                            sizeof(PROCESSINFO),
                                            USERTAG_PROCESSINFO);
-
         if (ppiCurrent == NULL)
         {
-            ERR_CH(UserProcess, "Failed to allocate ppi for PID:0x%lx\n", HandleToUlong(Process->UniqueProcessId));
-            RETURN( STATUS_NO_MEMORY);
+            ERR_CH(UserProcess, "Failed to allocate ppi for PID:0x%lx\n",
+                   HandleToUlong(Process->UniqueProcessId));
+            Status = STATUS_NO_MEMORY;
+            goto Leave;
         }
 
         RtlZeroMemory(ppiCurrent, sizeof(PROCESSINFO));
 
-        PsSetProcessWin32Process(Process, ppiCurrent);
+        PsSetProcessWin32Process(Process, ppiCurrent, NULL);
 
 #if DBG
         DbgInitDebugChannels();
+#if KDBG
+        KdRosRegisterCliCallback(DbgGdiKdbgCliCallback);
+#endif
 #endif
 
         TRACE_CH(UserProcess,"Allocated ppi 0x%p for PID:0x%lx\n", ppiCurrent, HandleToUlong(Process->UniqueProcessId));
@@ -106,7 +119,7 @@ Win32kProcessCallback(struct _EPROCESS *Process,
         if (!NT_SUCCESS(Status))
         {
             TRACE_CH(UserProcess,"Failed to map the global heap! 0x%x\n", Status);
-            RETURN(Status);
+            goto Leave;
         }
         ppiCurrent->HeapMappings.Next = NULL;
         ppiCurrent->HeapMappings.KernelMapping = (PVOID)GlobalUserHeap;
@@ -149,6 +162,9 @@ Win32kProcessCallback(struct _EPROCESS *Process,
            ppiCurrent->W32PF_flags |= W32PF_SCREENSAVER;
         }
 
+        // Fixme check if this process is allowed.
+        ppiCurrent->W32PF_flags |= W32PF_ALLOWFOREGROUNDACTIVATE; // Starting application it will get toggled off.
+
         /* Create pools for GDI object attributes */
         ppiCurrent->pPoolDcAttr = GdiPoolCreate(sizeof(DC_ATTR), 'acdG');
         ppiCurrent->pPoolBrushAttr = GdiPoolCreate(sizeof(BRUSH_ATTR), 'arbG');
@@ -156,6 +172,10 @@ Win32kProcessCallback(struct _EPROCESS *Process,
         ASSERT(ppiCurrent->pPoolDcAttr);
         ASSERT(ppiCurrent->pPoolBrushAttr);
         ASSERT(ppiCurrent->pPoolRgnAttr);
+
+        /* Add the process to the global list */
+        ppiCurrent->ppiNext = gppiList;
+        gppiList = ppiCurrent;
     }
     else
     {
@@ -208,18 +228,32 @@ Win32kProcessCallback(struct _EPROCESS *Process,
 
         if (gppiInputProvider == ppiCurrent) gppiInputProvider = NULL;
 
+        pppi = &gppiList;
+        while (*pppi != NULL && *pppi != ppiCurrent)
+            pppi = &(*pppi)->ppiNext;
+
+        ASSERT(*pppi == ppiCurrent);
+
+        *pppi = ppiCurrent->ppiNext;
+
         TRACE_CH(UserProcess,"Freeing ppi 0x%p\n", ppiCurrent);
+#if DBG
+        if (DBG_IS_CHANNEL_ENABLED(ppiCurrent, DbgChUserObj, WARN_LEVEL))
+        {
+            DbgUserDumpHandleTable();
+        }
+#endif
 
-        /* Ftee the PROCESSINFO */
-        PsSetProcessWin32Process(Process, NULL);
+        /* Free the PROCESSINFO */
+        PsSetProcessWin32Process(Process, NULL, ppiCurrent);
         ExFreePoolWithTag(ppiCurrent, USERTAG_PROCESSINFO);
     }
 
-    RETURN( STATUS_SUCCESS);
+    Status = STATUS_SUCCESS;
 
-CLEANUP:
+Leave:
     UserLeave();
-    END_CLEANUP;
+    return Status;
 }
 
 NTSTATUS NTAPI
@@ -231,6 +265,8 @@ UserCreateThreadInfo(struct _ETHREAD *Thread)
     int i;
     NTSTATUS Status = STATUS_SUCCESS;
     PTEB pTeb;
+    LARGE_INTEGER LargeTickCount;
+    OBJECT_ATTRIBUTES EventQueueObjAttr;
 
     Process = Thread->ThreadsProcess;
 
@@ -251,26 +287,54 @@ UserCreateThreadInfo(struct _ETHREAD *Thread)
 
     RtlZeroMemory(ptiCurrent, sizeof(THREADINFO));
 
-    PsSetThreadWin32Thread(Thread, ptiCurrent);
+    /* Initialize the THREADINFO */
+
+    PsSetThreadWin32Thread(Thread, ptiCurrent, NULL);
+    IntReferenceThreadInfo(ptiCurrent);
+    ptiCurrent->pEThread = Thread;
+    ptiCurrent->ppi = PsGetCurrentProcessWin32Process();
     pTeb->Win32ThreadInfo = ptiCurrent;
     ptiCurrent->pClientInfo = (PCLIENTINFO)pTeb->Win32ClientInfo;
 
     TRACE_CH(UserThread, "Allocated pti 0x%p for TID %p\n", ptiCurrent, Thread->Cid.UniqueThread);
 
-    /* Initialize the THREADINFO */
     InitializeListHead(&ptiCurrent->WindowListHead);
     InitializeListHead(&ptiCurrent->W32CallbackListHead);
+    InitializeListHead(&ptiCurrent->PostedMessagesListHead);
+    InitializeListHead(&ptiCurrent->SentMessagesListHead);
+    InitializeListHead(&ptiCurrent->DispatchingMessagesHead);
+    InitializeListHead(&ptiCurrent->LocalDispatchingMessagesHead);
     InitializeListHead(&ptiCurrent->PtiLink);
     for (i = 0; i < NB_HOOKS; i++)
     {
         InitializeListHead(&ptiCurrent->aphkStart[i]);
     }
-    ptiCurrent->pEThread = Thread;
-    ptiCurrent->ppi = PsGetCurrentProcessWin32Process();
     ptiCurrent->ptiSibling = ptiCurrent->ppi->ptiList;
     ptiCurrent->ppi->ptiList = ptiCurrent;
     ptiCurrent->ppi->cThreads++;
-    ptiCurrent->MessageQueue = MsqCreateMessageQueue(Thread);
+
+    ptiCurrent->hEventQueueClient = NULL;
+    InitializeObjectAttributes(&EventQueueObjAttr, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
+    Status = ZwCreateEvent(&ptiCurrent->hEventQueueClient, EVENT_ALL_ACCESS,
+                            NULL, SynchronizationEvent, FALSE);
+    if (!NT_SUCCESS(Status))
+    {
+       goto error;
+    }
+    Status = ObReferenceObjectByHandle(ptiCurrent->hEventQueueClient, 0,
+                                       *ExEventObjectType, KernelMode,
+                                       (PVOID*)&ptiCurrent->pEventQueueServer, NULL);
+    if (!NT_SUCCESS(Status))
+    {
+       ZwClose(ptiCurrent->hEventQueueClient);
+       ptiCurrent->hEventQueueClient = NULL;
+       goto error;
+    }
+
+    KeQueryTickCount(&LargeTickCount);
+    ptiCurrent->timeLast = LargeTickCount.u.LowPart;
+
+    ptiCurrent->MessageQueue = MsqCreateMessageQueue(ptiCurrent);
     if(ptiCurrent->MessageQueue == NULL)
     {
         ERR_CH(UserThread,"Failed to allocate message loop\n");
@@ -281,6 +345,9 @@ UserCreateThreadInfo(struct _ETHREAD *Thread)
     if (ptiCurrent->KeyboardLayout)
         UserReferenceObject(ptiCurrent->KeyboardLayout);
     ptiCurrent->TIF_flags &= ~TIF_INCLEANUP;
+    if (Process == gpepCSRSS) /* If this thread is owned by CSRSS, mark it as such */
+        ptiCurrent->TIF_flags |= TIF_CSRSSTHREAD;
+    ptiCurrent->pcti = &ptiCurrent->cti;
 
     /* Initialize the CLIENTINFO */
     pci = (PCLIENTINFO)pTeb->Win32ClientInfo;
@@ -366,8 +433,14 @@ UserCreateThreadInfo(struct _ETHREAD *Thread)
 
     /* mark the thread as fully initialized */
     ptiCurrent->TIF_flags |= TIF_GUITHREADINITIALIZED;
-    ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags;
 
+    if (!(ptiCurrent->ppi->W32PF_flags & (W32PF_ALLOWFOREGROUNDACTIVATE | W32PF_APPSTARTING)) &&
+         (gptiForeground && gptiForeground->ppi == ptiCurrent->ppi ))
+    {
+       ptiCurrent->TIF_flags |= TIF_ALLOWFOREGROUNDACTIVATE;
+    }
+    ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags;
+    TRACE_CH(UserThread,"UserCreateW32Thread pti 0x%p\n",ptiCurrent);
     return STATUS_SUCCESS;
 
 error:
@@ -376,6 +449,35 @@ error:
     return Status;
 }
 
+/*
+  Called from IntDereferenceThreadInfo.
+ */
+VOID
+FASTCALL
+UserDeleteW32Thread(PTHREADINFO pti)
+{
+    if (!pti->RefCount)
+    {
+       TRACE_CH(UserThread,"UserDeleteW32Thread pti 0x%p\n",pti);
+       if (pti->hEventQueueClient != NULL)
+          ZwClose(pti->hEventQueueClient);
+       pti->hEventQueueClient = NULL;
+
+       /* Free the message queue */
+       if (pti->MessageQueue)
+       {
+          MsqDestroyMessageQueue(pti);
+       }
+
+       MsqCleanupThreadMsgs(pti);
+
+       IntSetThreadDesktop(NULL, TRUE);
+
+       PsSetThreadWin32Thread(pti->pEThread, NULL, pti);
+       ExFreePoolWithTag(pti, USERTAG_THREADINFO);
+    }
+}
+
 NTSTATUS
 NTAPI
 UserDestroyThreadInfo(struct _ETHREAD *Thread)
@@ -401,6 +503,11 @@ UserDestroyThreadInfo(struct _ETHREAD *Thread)
     ppiCurrent = ptiCurrent->ppi;
     ASSERT(ppiCurrent);
 
+    IsRemoveAttachThread(ptiCurrent);
+
+    ptiCurrent->TIF_flags |= TIF_DONTATTACHQUEUE;
+    ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags;
+
     /* Decrement thread count and check if its 0 */
     ppiCurrent->cThreads--;
 
@@ -439,8 +546,8 @@ UserDestroyThreadInfo(struct _ETHREAD *Thread)
         HOOK_DestroyThreadHooks(Thread);
         EVENT_DestroyThreadEvents(Thread);
         DestroyTimersForThread(ptiCurrent);
-        KeSetEvent(ptiCurrent->MessageQueue->NewMessages, IO_NO_INCREMENT, FALSE);
-        UnregisterThreadHotKeys(Thread);
+        KeSetEvent(ptiCurrent->pEventQueueServer, IO_NO_INCREMENT, FALSE);
+        UnregisterThreadHotKeys(ptiCurrent);
 /*
         if (IsListEmpty(&ptiCurrent->WindowListHead))
         {
@@ -449,9 +556,10 @@ UserDestroyThreadInfo(struct _ETHREAD *Thread)
 */
         co_DestroyThreadWindows(Thread);
 
-        if (ppiCurrent && ppiCurrent->ptiList == ptiCurrent && !ptiCurrent->ptiSibling)
+        if (ppiCurrent && ppiCurrent->ptiList == ptiCurrent && !ptiCurrent->ptiSibling &&
+            ppiCurrent->W32PF_flags & W32PF_CLASSESREGISTERED)
         {
-           //ERR_CH(UserThread,"DestroyProcessClasses\n");
+           TRACE_CH(UserThread,"DestroyProcessClasses\n");
           /* no process windows should exist at this point, or the function will assert! */
            DestroyProcessClasses(ppiCurrent);
            ppiCurrent->W32PF_flags &= ~W32PF_CLASSESREGISTERED;
@@ -472,29 +580,6 @@ UserDestroyThreadInfo(struct _ETHREAD *Thread)
         }
     }
 
-    // ptiTo
-    if (IsThreadAttach(ptiCurrent))
-    {
-       PTHREADINFO ptiFrom = IsThreadAttach(ptiCurrent);
-       TRACE_CH(UserThread,"Attached Thread ptiTo is getting switched!\n");
-       UserAttachThreadInput(ptiFrom, ptiCurrent, FALSE);
-    }
-    
-    // ptiFrom
-    if (ptiCurrent->pqAttach && ptiCurrent->MessageQueue)
-    {
-       PTHREADINFO ptiTo;
-       ptiTo = PsGetThreadWin32Thread(ptiCurrent->MessageQueue->Thread);
-       TRACE_CH(UserThread,"Attached Thread ptiFrom is getting switched!\n");
-       UserAttachThreadInput( ptiCurrent, ptiTo, FALSE);
-    }
-
-    /* Free the message queue */
-    if(ptiCurrent->MessageQueue)
-    {
-       MsqDestroyMessageQueue(ptiCurrent->MessageQueue);
-    }
-
     /* Find the THREADINFO in the PROCESSINFO's list */
     ppti = &ppiCurrent->ptiList;
     while (*ppti != NULL && *ppti != ptiCurrent)
@@ -511,13 +596,28 @@ UserDestroyThreadInfo(struct _ETHREAD *Thread)
     if (ptiCurrent->KeyboardLayout)
         UserDereferenceObject(ptiCurrent->KeyboardLayout);
 
-    IntSetThreadDesktop(NULL, TRUE);
+    if (gptiForeground == ptiCurrent)
+    {
+//       IntNotifyWinEvent(EVENT_OBJECT_FOCUS, NULL, OBJID_CLIENT, CHILDID_SELF, 0);
+//       IntNotifyWinEvent(EVENT_SYSTEM_FOREGROUND, NULL, OBJID_WINDOW, CHILDID_SELF, 0);
 
+       gptiForeground = NULL;
+    }
+
+    // Fixes CORE-6384 & CORE-7030.
+/*    if (ptiLastInput == ptiCurrent)
+    {
+       if (!ppiCurrent->ptiList)
+          ptiLastInput = gptiForeground;
+       else
+          ptiLastInput = ppiCurrent->ptiList;
+       ERR_CH(UserThread,"DTI: ptiLastInput is Cleared!!\n");
+    }
+*/
     TRACE_CH(UserThread,"Freeing pti 0x%p\n", ptiCurrent);
 
     /* Free the THREADINFO */
-    PsSetThreadWin32Thread(Thread, NULL);
-    ExFreePoolWithTag(ptiCurrent, USERTAG_THREADINFO);
+    IntDereferenceThreadInfo(ptiCurrent);
 
     return STATUS_SUCCESS;
 }
@@ -596,14 +696,16 @@ DriverEntry(
     DPRINT("Win32k hInstance 0x%p!\n",hModuleWin);
 
     /* Register Object Manager Callbacks */
+    CalloutData.ProcessCallout = Win32kProcessCallback;
+    CalloutData.ThreadCallout = Win32kThreadCallback;
     CalloutData.WindowStationParseProcedure = IntWinStaObjectParse;
     CalloutData.WindowStationDeleteProcedure = IntWinStaObjectDelete;
+    CalloutData.WindowStationOkToCloseProcedure = IntWinstaOkToClose;
+    CalloutData.DesktopOkToCloseProcedure = IntDesktopOkToClose;
     CalloutData.DesktopDeleteProcedure = IntDesktopObjectDelete;
-    CalloutData.ProcessCallout = Win32kProcessCallback;
-    CalloutData.ThreadCallout = Win32kThreadCallback;
+    CalloutData.DesktopCloseProcedure = IntDesktopObjectClose;
+    CalloutData.DesktopOpenProcedure = IntDesktopObjectOpen;
     CalloutData.BatchFlushRoutine = NtGdiFlushUserBatch;
-    CalloutData.DesktopOkToCloseProcedure = IntDesktopOkToClose;
-    CalloutData.WindowStationOkToCloseProcedure = IntWinstaOkToClose;
 
     /* Register our per-process and per-thread structures. */
     PsEstablishWin32Callouts((PWIN32_CALLOUTS_FPNS)&CalloutData);