[win32k]
[reactos.git] / reactos / subsystems / win32 / win32k / main / dllmain.c
index f78bf19..21b1802 100644 (file)
@@ -107,18 +107,27 @@ Win32kProcessCallback(struct _EPROCESS *Process,
         if(Process->Peb != NULL)
         {
             /* map the gdi handle table to user land */
-            Process->Peb->GdiSharedHandleTable = GDI_MapHandleTable(GdiTableSection, Process);
+            Process->Peb->GdiSharedHandleTable = GDI_MapHandleTable(Process);
             Process->Peb->GdiDCAttributeList = GDI_BATCH_LIMIT;
         }
 
         Win32Process->peProcess = Process;
         /* setup process flags */
         Win32Process->W32PF_flags = 0;
+
+        /* Create pools for GDI object attributes */
+        Win32Process->pPoolDcAttr = GdiPoolCreate(sizeof(DC_ATTR), 'acdG');
+        Win32Process->pPoolBrushAttr = GdiPoolCreate(sizeof(BRUSH_ATTR), 'arbG');
+        Win32Process->pPoolRgnAttr = GdiPoolCreate(sizeof(RGN_ATTR), 'agrG');
+        ASSERT(Win32Process->pPoolDcAttr);
+        ASSERT(Win32Process->pPoolBrushAttr);
+        ASSERT(Win32Process->pPoolRgnAttr);
     }
     else
     {
         DPRINT("Destroying W32 process PID:%d at IRQ level: %lu\n", Process->UniqueProcessId, KeGetCurrentIrql());
         Win32Process->W32PF_flags |= W32PF_TERMINATED;
+
         if (Win32Process->InputIdleEvent)
         {
            EngFreeMem((PVOID)Win32Process->InputIdleEvent);
@@ -144,6 +153,20 @@ Win32kProcessCallback(struct _EPROCESS *Process,
         {
             LogonProcess = NULL;
         }
+
+        /* Close the startup desktop */
+        ASSERT(Win32Process->rpdeskStartup);
+        ASSERT(Win32Process->hdeskStartup);
+        ObDereferenceObject(Win32Process->rpdeskStartup);
+        ZwClose(Win32Process->hdeskStartup);
+
+        /* Close the current window station */
+        UserSetProcessWindowStation(NULL);
+
+        /* Destroy GDI pools */
+        GdiPoolDestroy(Win32Process->pPoolDcAttr);
+        GdiPoolDestroy(Win32Process->pPoolBrushAttr);
+        GdiPoolDestroy(Win32Process->pPoolRgnAttr);
     }
 
     RETURN( STATUS_SUCCESS);
@@ -195,6 +218,7 @@ Win32kThreadCallback(struct _ETHREAD *Thread,
         HDESK hDesk = NULL;
         NTSTATUS Status;
         PUNICODE_STRING DesktopPath;
+        PDESKTOP pdesk;
         PRTL_USER_PROCESS_PARAMETERS ProcessParams = (Process->Peb ? Process->Peb->ProcessParameters : NULL);
 
         DPRINT("Creating W32 thread TID:%d at IRQ level: %lu\n", Thread->Cid.UniqueThread, KeGetCurrentIrql());
@@ -207,75 +231,70 @@ Win32kThreadCallback(struct _ETHREAD *Thread,
             InitializeListHead(&Win32Thread->aphkStart[i]);
         }
 
-        /*
-         * inherit the thread desktop and process window station (if not yet inherited) from the process startup
-         * info structure. See documentation of CreateProcess()
-         */
-        DesktopPath = (ProcessParams ? ((ProcessParams->DesktopInfo.Length > 0) ? &ProcessParams->DesktopInfo : NULL) : NULL);
-        Status = IntParseDesktopPath(Process,
-                                     DesktopPath,
-                                     &hWinSta,
-                                     &hDesk);
-        if(NT_SUCCESS(Status))
+        Win32Thread->TIF_flags &= ~TIF_INCLEANUP;
+        co_IntDestroyCaret(Win32Thread);
+        Win32Thread->ppi = PsGetCurrentProcessWin32Process();
+        Win32Thread->ptiSibling = Win32Thread->ppi->ptiList;
+        Win32Thread->ppi->ptiList = Win32Thread;
+        Win32Thread->ppi->cThreads++;
+        if (Win32Thread->rpdesk && !Win32Thread->pDeskInfo)
         {
-            if(hWinSta != NULL)
+           Win32Thread->pDeskInfo = Win32Thread->rpdesk->pDeskInfo;
+        }
+        Win32Thread->MessageQueue = MsqCreateMessageQueue(Thread);
+        Win32Thread->KeyboardLayout = W32kGetDefaultKeyLayout();
+
+        /* HAAAAAAAACK! This should go to Win32kProcessCallback */
+        if(Win32Thread->ppi->hdeskStartup == NULL)
+        {
+            /*
+             * inherit the thread desktop and process window station (if not yet inherited) from the process startup
+             * info structure. See documentation of CreateProcess()
+             */
+            DesktopPath = (ProcessParams ? ((ProcessParams->DesktopInfo.Length > 0) ? &ProcessParams->DesktopInfo : NULL) : NULL);
+            Status = IntParseDesktopPath(Process,
+                                         DesktopPath,
+                                         &hWinSta,
+                                         &hDesk);
+            if(NT_SUCCESS(Status))
             {
-                if(Process != CsrProcess)
+                if(hWinSta != NULL)
                 {
-                    HWINSTA hProcessWinSta = (HWINSTA)InterlockedCompareExchangePointer((PVOID)&Process->Win32WindowStation, (PVOID)hWinSta, NULL);
-                    if(hProcessWinSta != NULL)
+                    if(!UserSetProcessWindowStation(hWinSta))
                     {
-                        /* our process is already assigned to a different window station, we don't need the handle anymore */
-                        NtClose(hWinSta);
+                        DPRINT1("Failed to set process window station\n");
                     }
                 }
-                else
-                {
-                    NtClose(hWinSta);
-                }
-            }
 
-            if (hDesk != NULL)
-            {
-                PDESKTOP DesktopObject;
-                Win32Thread->rpdesk = NULL;
-                Status = ObReferenceObjectByHandle(hDesk,
-                                                   0,
-                                                   ExDesktopObjectType,
-                                                   KernelMode,
-                                                   (PVOID*)&DesktopObject,
-                                                   NULL);
-                NtClose(hDesk);
-                if(NT_SUCCESS(Status))
+                if (hDesk != NULL)
                 {
-                    if (!IntSetThreadDesktop(DesktopObject,
-                                             FALSE))
+                    /* Validate the new desktop. */
+                    Status = IntValidateDesktopHandle(hDesk,
+                                                      UserMode,
+                                                      0,
+                                                      &pdesk);
+
+                    if(NT_SUCCESS(Status))
                     {
-                        DPRINT1("Unable to set thread desktop\n");
+                        Win32Thread->ppi->hdeskStartup = hDesk;
+                        Win32Thread->ppi->rpdeskStartup = pdesk;
                     }
                 }
-                else
-                {
-                    DPRINT1("Unable to reference thread desktop handle 0x%x\n", hDesk);
-                }
+            }
+            else
+            {
+               DPRINT1("No Desktop handle for this Thread!\n");
             }
         }
-        else
-        {
-           DPRINT1("No Desktop handle for this Thread!\n");
-        }
-        Win32Thread->TIF_flags &= ~TIF_INCLEANUP;
-        co_IntDestroyCaret(Win32Thread);
-        Win32Thread->ppi = PsGetCurrentProcessWin32Process();
-        Win32Thread->ptiSibling = Win32Thread->ppi->ptiList;
-        Win32Thread->ppi->ptiList = Win32Thread;
-        Win32Thread->ppi->cThreads++;
-        if (Win32Thread->rpdesk && !Win32Thread->pDeskInfo)
+
+        if (Win32Thread->ppi->hdeskStartup != NULL)
         {
-           Win32Thread->pDeskInfo = Win32Thread->rpdesk->pDeskInfo;
+            if (!IntSetThreadDesktop(Win32Thread->ppi->hdeskStartup, FALSE))
+            {
+                DPRINT1("Unable to set thread desktop\n");
+            }
         }
-        Win32Thread->MessageQueue = MsqCreateMessageQueue(Thread);
-        Win32Thread->KeyboardLayout = W32kGetDefaultKeyLayout();
+
         pTeb = NtCurrentTeb();
         if (pTeb)
         { /* Attempt to startup client support which should have been initialized in IntSetThreadDesktop. */
@@ -286,7 +305,7 @@ Win32kThreadCallback(struct _ETHREAD *Thread,
            if (Win32Thread->KeyboardLayout) pci->hKL = Win32Thread->KeyboardLayout->hkl;
            pci->dwTIFlags = Win32Thread->TIF_flags;
            /* CI may not have been initialized. */
-           if (!pci->pDeskInfo && Win32Thread->pDeskInfo) 
+           if (!pci->pDeskInfo && Win32Thread->pDeskInfo)
            {
               if (!pci->ulClientDelta) pci->ulClientDelta = DesktopHeapGetUserDelta();
 
@@ -456,11 +475,13 @@ DriverEntry(
     CalloutData.ProcessCallout = Win32kProcessCallback;
     CalloutData.ThreadCallout = Win32kThreadCallback;
     CalloutData.BatchFlushRoutine = NtGdiFlushUserBatch;
+    CalloutData.DesktopOkToCloseProcedure = IntDesktopOkToClose;
+    CalloutData.WindowStationOkToCloseProcedure = IntWinstaOkToClose;
 
     /* Register our per-process and per-thread structures. */
     PsEstablishWin32Callouts((PWIN32_CALLOUTS_FPNS)&CalloutData);
 
-#if 0 // DBG
+#if DBG_ENABLE_SERVICE_HOOKS
     /* Register service hook callbacks */
     KdSystemDebugControl('CsoR', DbgPreServiceHook, ID_Win32PreServiceHook, 0, 0, 0, 0);
     KdSystemDebugControl('CsoR', DbgPostServiceHook, ID_Win32PostServiceHook, 0, 0, 0, 0);