[CMAKE]
[reactos.git] / subsystems / win32 / win32k / ntuser / desktop.c
index 74da248..3dbfdcf 100644 (file)
@@ -168,6 +168,29 @@ IntDesktopObjectDelete(PWIN32_DELETEMETHOD_PARAMETERS Parameters)
    IntFreeDesktopHeap(Desktop);
 }
 
+NTSTATUS NTAPI
+IntDesktopOkToClose(PWIN32_OKAYTOCLOSEMETHOD_PARAMETERS Parameters)
+{
+    PTHREADINFO pti;
+
+    pti = PsGetCurrentThreadWin32Thread();
+
+    if( pti == NULL)
+    {
+        /* This happens when we leak desktop handles */
+        return TRUE;
+    }
+
+    /* Do not allow the current desktop or the initial desktop to be closed */
+    if( Parameters->Handle == pti->ppi->hdeskStartup ||
+        Parameters->Handle == pti->hdesk)
+    {
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
 /* PRIVATE FUNCTIONS **********************************************************/
 
 INIT_FUNCTION
@@ -616,15 +639,19 @@ VOID APIENTRY
 UserRedrawDesktop()
 {
     PWND Window = NULL;
+    HRGN hRgn;
 
     Window = UserGetDesktopWindow();
+    hRgn = IntSysCreateRectRgnIndirect(&Window->rcWindow);
 
     IntInvalidateWindows( Window,
-              Window->hrgnUpdate,
+                            hRgn,
                        RDW_FRAME |
                        RDW_ERASE |
                   RDW_INVALIDATE |
                  RDW_ALLCHILDREN);
+
+    GreDeleteObject(hRgn);
 }
 
 
@@ -738,7 +765,11 @@ VOID co_IntShellHookNotify(WPARAM Message, LPARAM lParam)
 
       for (; *cursor; cursor++)
       {
-         UserPostMessage(*cursor, gpsi->uiShellMsg, Message, lParam);
+         DPRINT("Sending notify\n");
+         co_IntPostOrSendMessage(*cursor,
+                                 gpsi->uiShellMsg,
+                                 Message,
+                                 lParam);
       }
 
       ExFreePool(HwndList);
@@ -851,15 +882,12 @@ IntFreeDesktopHeap(IN OUT PDESKTOP Desktop)
 
 HDESK APIENTRY
 NtUserCreateDesktop(
-   POBJECT_ATTRIBUTES poa,
+   POBJECT_ATTRIBUTES ObjectAttributes,
    PUNICODE_STRING lpszDesktopDevice,
    LPDEVMODEW lpdmw,
    DWORD dwFlags,
    ACCESS_MASK dwDesiredAccess)
 {
-   OBJECT_ATTRIBUTES ObjectAttributes;
-   PTHREADINFO W32Thread;
-   PWINSTATION_OBJECT WinStaObject;
    PDESKTOP DesktopObject;
    UNICODE_STRING DesktopName;
    NTSTATUS Status = STATUS_SUCCESS;
@@ -867,12 +895,9 @@ NtUserCreateDesktop(
    CSR_API_MESSAGE Request;
    PVOID DesktopHeapSystemBase = NULL;
    SIZE_T DesktopInfoSize;
-   UNICODE_STRING SafeDesktopName;
    ULONG DummyContext;
    ULONG_PTR HeapSize = 4 * 1024 * 1024; /* FIXME */
-   HWINSTA hWindowStation = NULL ;
-   PUNICODE_STRING lpszDesktopName = NULL;
-   UNICODE_STRING ClassName, MenuName;
+   UNICODE_STRING ClassName;
    LARGE_STRING WindowName;
    BOOL NoHooks = FALSE;
    PWND pWnd = NULL;
@@ -881,7 +906,7 @@ NtUserCreateDesktop(
    PTHREADINFO ptiCurrent;
    DECLARE_RETURN(HDESK);
 
-   DPRINT("Enter NtUserCreateDesktop: %wZ\n", lpszDesktopName);
+   DPRINT("Enter NtUserCreateDesktop\n");
    UserEnterExclusive();
 
    ptiCurrent = PsGetCurrentThreadWin32Thread();
@@ -891,68 +916,7 @@ NtUserCreateDesktop(
       NoHooks = (ptiCurrent->TIF_flags & TIF_DISABLEHOOKS);
       ptiCurrent->TIF_flags |= TIF_DISABLEHOOKS;
    }
-
-   _SEH2_TRY
-   {
-      ProbeForRead( poa,
-                    sizeof(OBJECT_ATTRIBUTES),
-                    1);
-
-      hWindowStation = poa->RootDirectory;
-      lpszDesktopName = poa->ObjectName;
-   }
-   _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-   {
-      Status =_SEH2_GetExceptionCode();
-   }
-   _SEH2_END
-
-   if (! NT_SUCCESS(Status))
-   {
-      DPRINT1("Failed reading Object Attributes from user space.\n");
-      SetLastNtError(Status);
-      RETURN( NULL);
-   }
-
-   Status = IntValidateWindowStationHandle(
-               hWindowStation,
-               KernelMode,
-               0, /* FIXME - WINSTA_CREATEDESKTOP */
-               &WinStaObject);
-
-   if (! NT_SUCCESS(Status))
-   {
-      DPRINT1("Failed validation of window station handle (0x%X), cannot create desktop %wZ\n",
-              hWindowStation, lpszDesktopName);
-      SetLastNtError(Status);
-      RETURN( NULL);
-   }
-   if(lpszDesktopName != NULL)
-   {
-      Status = IntSafeCopyUnicodeString(&SafeDesktopName, lpszDesktopName);
-      if(!NT_SUCCESS(Status))
-      {
-         SetLastNtError(Status);
-         RETURN( NULL);
-         }
-   }
-   else
-   {
-      RtlInitUnicodeString(&SafeDesktopName, NULL);
-   }
-
-   if (! IntGetFullWindowStationName(&DesktopName, &WinStaObject->Name,
-                                     &SafeDesktopName))
-   {
-      SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
-      ObDereferenceObject(WinStaObject);
-      if (lpszDesktopName)
-         ExFreePoolWithTag(SafeDesktopName.Buffer, TAG_STRING);
-      RETURN( NULL);
-   }
-   if (lpszDesktopName)
-      ExFreePoolWithTag(SafeDesktopName.Buffer, TAG_STRING);
-   ObDereferenceObject(WinStaObject);
+   DesktopName.Buffer = NULL;
 
    /*
     * Try to open already existing desktop
@@ -960,18 +924,10 @@ NtUserCreateDesktop(
 
    DPRINT("Trying to open desktop (%wZ)\n", &DesktopName);
 
-   /* Initialize ObjectAttributes for the desktop object */
-   InitializeObjectAttributes(
-      &ObjectAttributes,
-      &DesktopName,
-      0,
-      NULL,
-      NULL);
-
    Status = ObOpenObjectByName(
-               &ObjectAttributes,
+               ObjectAttributes,
                ExDesktopObjectType,
-               KernelMode,
+               UserMode,
                NULL,
                dwDesiredAccess,
                (PVOID)&DummyContext,
@@ -979,10 +935,29 @@ NtUserCreateDesktop(
    if (!NT_SUCCESS(Status)) RETURN(NULL);
    if (Status == STATUS_OBJECT_NAME_EXISTS)
    {
-      ExFreePoolWithTag(DesktopName.Buffer, TAG_STRING);
       RETURN( Desktop);
    }
 
+   /* Capture desktop name */
+   _SEH2_TRY
+   {
+      ProbeForRead( ObjectAttributes, sizeof(OBJECT_ATTRIBUTES),  1);
+
+      Status = IntSafeCopyUnicodeString(&DesktopName, ObjectAttributes->ObjectName);
+   }
+   _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+   {
+      Status = _SEH2_GetExceptionCode();
+   }
+   _SEH2_END
+
+   if (! NT_SUCCESS(Status))
+   {
+      DPRINT1("Failed reading Object Attributes from user space.\n");
+      SetLastNtError(Status);
+      RETURN( NULL);
+   }
+
    /* Reference the desktop */
    Status = ObReferenceObjectByHandle(Desktop,
                                       0,
@@ -1003,12 +978,11 @@ NtUserCreateDesktop(
        RETURN(NULL);
    }
 
-   DesktopInfoSize = FIELD_OFFSET(DESKTOPINFO,
-                                  szDesktopName[(lpszDesktopName->Length / sizeof(WCHAR)) + 1]);
+   DesktopInfoSize = sizeof(DESKTOPINFO) + DesktopName.Length;
 
    DesktopObject->pDeskInfo = RtlAllocateHeap(DesktopObject->pheapDesktop,
-                                                HEAP_NO_SERIALIZE,
-                                                DesktopInfoSize);
+                                              HEAP_NO_SERIALIZE,
+                                              DesktopInfoSize);
 
    if (DesktopObject->pDeskInfo == NULL)
    {
@@ -1023,8 +997,8 @@ NtUserCreateDesktop(
    DesktopObject->pDeskInfo->pvDesktopBase = DesktopHeapSystemBase;
    DesktopObject->pDeskInfo->pvDesktopLimit = (PVOID)((ULONG_PTR)DesktopHeapSystemBase + HeapSize);
    RtlCopyMemory(DesktopObject->pDeskInfo->szDesktopName,
-                 lpszDesktopName->Buffer,
-                 lpszDesktopName->Length);
+                 DesktopName.Buffer,
+                 DesktopName.Length);
 
    /* Initialize some local (to win32k) desktop state. */
    InitializeListHead(&DesktopObject->PtiList);
@@ -1034,7 +1008,6 @@ NtUserCreateDesktop(
    {
       InitializeListHead(&DesktopObject->pDeskInfo->aphkStart[i]);
    }
-   ExFreePoolWithTag(DesktopName.Buffer, TAG_STRING);
 
 //// why is this here?
 #if 0
@@ -1082,7 +1055,6 @@ NtUserCreateDesktop(
    //
    ClassName.Buffer = ((PWSTR)((ULONG_PTR)(WORD)(gpsi->atomSysClass[ICLS_DESKTOP])));
    ClassName.Length = 0;
-   RtlZeroMemory(&MenuName, sizeof(MenuName));
    RtlZeroMemory(&WindowName, sizeof(WindowName));
 
    RtlZeroMemory(&Cs, sizeof(Cs));
@@ -1105,9 +1077,8 @@ NtUserCreateDesktop(
       DesktopObject->pDeskInfo->spwnd = pWndDesktop;
    }
 #endif
-   W32Thread = PsGetCurrentThreadWin32Thread();
 
-   if (!W32Thread->rpdesk) IntSetThreadDesktop(DesktopObject,FALSE);
+   if (!ptiCurrent->rpdesk) IntSetThreadDesktop(Desktop,FALSE);
 
   /*
      Based on wine/server/window.c in get_desktop_window.
@@ -1115,7 +1086,6 @@ NtUserCreateDesktop(
 
    ClassName.Buffer = ((PWSTR)((ULONG_PTR)(WORD)(gpsi->atomSysClass[ICLS_HWNDMESSAGE])));
    ClassName.Length = 0;
-   RtlZeroMemory(&MenuName, sizeof(MenuName));
    RtlZeroMemory(&WindowName, sizeof(WindowName));
 
    RtlZeroMemory(&Cs, sizeof(Cs));
@@ -1146,6 +1116,10 @@ NtUserCreateDesktop(
    RETURN( Desktop);
 
 CLEANUP:
+   if(DesktopName.Buffer != NULL)
+   {
+       ExFreePoolWithTag(DesktopName.Buffer, TAG_STRING);
+   }
    if (!NoHooks && ptiCurrent) ptiCurrent->TIF_flags &= ~TIF_DISABLEHOOKS;
    DPRINT("Leave NtUserCreateDesktop, ret=%i\n",_ret_);
    UserLeave();
@@ -1176,85 +1150,17 @@ CLEANUP:
 
 HDESK APIENTRY
 NtUserOpenDesktop(
-   PUNICODE_STRING lpszDesktopName,
+   POBJECT_ATTRIBUTES ObjectAttributes,
    DWORD dwFlags,
    ACCESS_MASK dwDesiredAccess)
 {
-   OBJECT_ATTRIBUTES ObjectAttributes;
-   HWINSTA WinSta;
-   PWINSTATION_OBJECT WinStaObject;
-   UNICODE_STRING DesktopName;
-   UNICODE_STRING SafeDesktopName;
    NTSTATUS Status;
    HDESK Desktop;
-   BOOL Result;
-   DECLARE_RETURN(HDESK);
-
-   DPRINT("Enter NtUserOpenDesktop: %wZ\n", lpszDesktopName);
-   UserEnterExclusive();
-
-   /*
-    * Validate the window station handle and compose the fully
-    * qualified desktop name
-    */
-
-   WinSta = UserGetProcessWindowStation();
-   Status = IntValidateWindowStationHandle(
-               WinSta,
-               KernelMode,
-               0,
-               &WinStaObject);
-
-   if (!NT_SUCCESS(Status))
-   {
-      DPRINT1("Failed validation of window station handle (0x%X)\n", WinSta);
-      SetLastNtError(Status);
-      RETURN( 0);
-   }
-
-   if(lpszDesktopName != NULL)
-   {
-      Status = IntSafeCopyUnicodeString(&SafeDesktopName, lpszDesktopName);
-      if(!NT_SUCCESS(Status))
-      {
-         SetLastNtError(Status);
-         RETURN( NULL);
-         }
-   }
-   else
-   {
-      RtlInitUnicodeString(&SafeDesktopName, NULL);
-   }
-
-   Result = IntGetFullWindowStationName(&DesktopName, &WinStaObject->Name,
-                                        &SafeDesktopName);
-
-   if (lpszDesktopName)
-      ExFreePoolWithTag(SafeDesktopName.Buffer, TAG_STRING);
-   ObDereferenceObject(WinStaObject);
-
-
-   if (!Result)
-   {
-      SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
-      RETURN( 0);
-   }
-
-
-   DPRINT("Trying to open desktop (%wZ)\n", &DesktopName);
-
-   /* Initialize ObjectAttributes for the desktop object */
-   InitializeObjectAttributes(
-      &ObjectAttributes,
-      &DesktopName,
-      0,
-      NULL,
-      NULL);
 
    Status = ObOpenObjectByName(
-               &ObjectAttributes,
+               ObjectAttributes,
                ExDesktopObjectType,
-               KernelMode,
+               UserMode,
                NULL,
                dwDesiredAccess,
                NULL,
@@ -1263,19 +1169,10 @@ NtUserOpenDesktop(
    if (!NT_SUCCESS(Status))
    {
       SetLastNtError(Status);
-      ExFreePool(DesktopName.Buffer);
-      RETURN( 0);
+      return 0;
    }
 
-   DPRINT("Successfully opened desktop (%wZ)\n", &DesktopName);
-   ExFreePool(DesktopName.Buffer);
-
-   RETURN( Desktop);
-
-CLEANUP:
-   DPRINT("Leave NtUserOpenDesktop, ret=%i\n",_ret_);
-   UserLeave();
-   END_CLEANUP;
+   return Desktop;
 }
 
 /*
@@ -1921,105 +1818,135 @@ IntMapDesktopView(IN PDESKTOP DesktopObject)
 }
 
 BOOL
-IntSetThreadDesktop(IN PDESKTOP DesktopObject,
+IntSetThreadDesktop(IN HDESK hDesktop,
                     IN BOOL FreeOnFailure)
 {
-    PDESKTOP OldDesktop;
+    PDESKTOP DesktopObject = NULL, OldDesktop;
+    HDESK hOldDesktop;
     PTHREADINFO W32Thread;
     NTSTATUS Status;
     BOOL MapHeap;
     CLIENTTHREADINFO ctiSave;
 
-    DPRINT("IntSetThreadDesktop() DO=%p, FOF=%d\n", DesktopObject, FreeOnFailure);
+    DPRINT("IntSetThreadDesktop() , FOF=%d\n", FreeOnFailure);
     MapHeap = (PsGetCurrentProcess() != PsInitialSystemProcess);
     W32Thread = PsGetCurrentThreadWin32Thread();
 
-    if (W32Thread->rpdesk != DesktopObject)
+    if(hDesktop != NULL)
     {
-        OldDesktop = W32Thread->rpdesk;
-
-        if (!IsListEmpty(&W32Thread->WindowListHead))
+        /* Validate the new desktop. */
+        Status = IntValidateDesktopHandle(
+                    hDesktop,
+                    UserMode,
+                    0,
+                    &DesktopObject);
+
+        if (!NT_SUCCESS(Status))
         {
-            DPRINT1("Attempted to change thread desktop although the thread has windows!\n");
-            EngSetLastError(ERROR_BUSY);
+            DPRINT1("Validation of desktop handle (0x%X) failed\n", hDesktop);
             return FALSE;
         }
 
-        W32Thread->rpdesk = DesktopObject;
-
-        if (MapHeap && DesktopObject != NULL)
+        if (W32Thread->rpdesk == DesktopObject)
         {
-            Status = IntMapDesktopView(DesktopObject);
-            if (!NT_SUCCESS(Status))
-            {
-                SetLastNtError(Status);
-                return FALSE;
-            }
-            W32Thread->pDeskInfo = DesktopObject->pDeskInfo;
+            /* Nothing to do */
+            ObDereferenceObject(DesktopObject);
+            return TRUE;
         }
 
-        RtlZeroMemory(&ctiSave, sizeof(CLIENTTHREADINFO));
+    }
 
-        if (W32Thread->pcti && OldDesktop && NtCurrentTeb())
-        {
-           RtlCopyMemory(&ctiSave, W32Thread->pcti, sizeof(CLIENTTHREADINFO));
-           DPRINT("Free ClientThreadInfo\n");
-           DesktopHeapFree(OldDesktop, W32Thread->pcti);
-           W32Thread->pcti = NULL;
-        }
+    if (!IsListEmpty(&W32Thread->WindowListHead))
+    {
+        DPRINT1("Attempted to change thread desktop although the thread has windows!\n");
+        EngSetLastError(ERROR_BUSY);
+        return FALSE;
+    }
 
-        if (!W32Thread->pcti && DesktopObject && NtCurrentTeb())
+    OldDesktop = W32Thread->rpdesk;
+    hOldDesktop = W32Thread->hdesk;
+
+    W32Thread->rpdesk = DesktopObject;
+    W32Thread->hdesk = hDesktop;
+
+    if (MapHeap && DesktopObject != NULL)
+    {
+        Status = IntMapDesktopView(DesktopObject);
+        if (!NT_SUCCESS(Status))
         {
-           DPRINT("Allocate ClientThreadInfo\n");
-           W32Thread->pcti = DesktopHeapAlloc( DesktopObject,
-                                               sizeof(CLIENTTHREADINFO));
-           RtlCopyMemory(W32Thread->pcti, &ctiSave, sizeof(CLIENTTHREADINFO));
+            SetLastNtError(Status);
+            return FALSE;
         }
+        W32Thread->pDeskInfo = DesktopObject->pDeskInfo;
+    }
+
+    RtlZeroMemory(&ctiSave, sizeof(CLIENTTHREADINFO));
+
+    if (W32Thread->pcti && OldDesktop && NtCurrentTeb())
+    {
+        RtlCopyMemory(&ctiSave, W32Thread->pcti, sizeof(CLIENTTHREADINFO));
+        DPRINT("Free ClientThreadInfo\n");
+        DesktopHeapFree(OldDesktop, W32Thread->pcti);
+        W32Thread->pcti = NULL;
+    }
+
+    if (!W32Thread->pcti && DesktopObject && NtCurrentTeb())
+    {
+        DPRINT("Allocate ClientThreadInfo\n");
+        W32Thread->pcti = DesktopHeapAlloc( DesktopObject,
+                                            sizeof(CLIENTTHREADINFO));
+        RtlCopyMemory(W32Thread->pcti, &ctiSave, sizeof(CLIENTTHREADINFO));
+    }
 
-        if (NtCurrentTeb())
+    if (NtCurrentTeb())
+    {
+        PCLIENTINFO pci = GetWin32ClientInfo();
+        pci->ulClientDelta = DesktopHeapGetUserDelta();
+        if (DesktopObject)
         {
-            PCLIENTINFO pci = GetWin32ClientInfo();
-            pci->ulClientDelta = DesktopHeapGetUserDelta();
-            if (DesktopObject)
-            {
-                pci->pDeskInfo = (PVOID)((ULONG_PTR)DesktopObject->pDeskInfo - pci->ulClientDelta);
-                if (W32Thread->pcti) pci->pClientThreadInfo = (PVOID)((ULONG_PTR)W32Thread->pcti - pci->ulClientDelta);
-            }
+            pci->pDeskInfo = (PVOID)((ULONG_PTR)DesktopObject->pDeskInfo - pci->ulClientDelta);
+            if (W32Thread->pcti) pci->pClientThreadInfo = (PVOID)((ULONG_PTR)W32Thread->pcti - pci->ulClientDelta);
         }
+    }
 
-        if (OldDesktop != NULL &&
-            !IntCheckProcessDesktopClasses(OldDesktop,
-                                           FreeOnFailure))
-        {
-            DPRINT1("Failed to move process classes to shared heap!\n");
+    if (OldDesktop != NULL &&
+        !IntCheckProcessDesktopClasses(OldDesktop,
+                                        FreeOnFailure))
+    {
+        DPRINT1("Failed to move process classes to shared heap!\n");
 
-            /* failed to move desktop classes to the shared heap,
-               unmap the view and return the error */
-            if (MapHeap && DesktopObject != NULL)
-                IntUnmapDesktopView(DesktopObject);
+        /* failed to move desktop classes to the shared heap,
+            unmap the view and return the error */
+        if (MapHeap && DesktopObject != NULL)
+            IntUnmapDesktopView(DesktopObject);
 
-            return FALSE;
-        }
+        return FALSE;
+    }
 
-        /* Remove the thread from the old desktop's list */
-        RemoveEntryList(&W32Thread->PtiLink);
+    /* Remove the thread from the old desktop's list */
+    RemoveEntryList(&W32Thread->PtiLink);
 
-        if (DesktopObject != NULL)
+    if (DesktopObject != NULL)
+    {
+        ObReferenceObject(DesktopObject);
+        /* Insert into new desktop's list */
+        InsertTailList(&DesktopObject->PtiList, &W32Thread->PtiLink);
+    }
+
+    /* Close the old desktop */
+    if (OldDesktop != NULL)
+    {
+        if (MapHeap)
         {
-            ObReferenceObject(DesktopObject);
-            /* Insert into new desktop's list */
-            InsertTailList(&DesktopObject->PtiList, &W32Thread->PtiLink);
+            IntUnmapDesktopView(OldDesktop);
         }
 
-        if (OldDesktop != NULL)
-        {
-            if (MapHeap)
-            {
-                IntUnmapDesktopView(OldDesktop);
-            }
+        ObDereferenceObject(OldDesktop);
+    }
 
-            ObDereferenceObject(OldDesktop);
-        }
+    if (hOldDesktop != NULL)
+    {
+        ZwClose(hOldDesktop);
     }
 
     return TRUE;
@@ -2035,40 +1962,15 @@ IntSetThreadDesktop(IN PDESKTOP DesktopObject,
 BOOL APIENTRY
 NtUserSetThreadDesktop(HDESK hDesktop)
 {
-   PDESKTOP DesktopObject;
-   NTSTATUS Status;
-   DECLARE_RETURN(BOOL);
+   BOOL ret;
 
    UserEnterExclusive();
-   DPRINT("Enter NtUserSetThreadDesktop\n");
-
-   /* Validate the new desktop. */
-   Status = IntValidateDesktopHandle(
-               hDesktop,
-               UserMode,
-               0,
-               &DesktopObject);
-
-   if (!NT_SUCCESS(Status))
-   {
-      DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop);
-      RETURN(FALSE);
-   }
 
-   /* FIXME: Should check here to see if the thread has any windows. */
-
-   if (!IntSetThreadDesktop(DesktopObject,
-                            FALSE))
-   {
-       RETURN(FALSE);
-   }
+   ret = IntSetThreadDesktop(hDesktop, FALSE);
 
-   RETURN(TRUE);
-
-CLEANUP:
-   DPRINT("Leave NtUserSetThreadDesktop, ret=%i\n",_ret_);
    UserLeave();
-   END_CLEANUP;
+
+   return ret;
 }
 
 /* EOF */