- Update KTHREAD and KUSER_SHARED_DATA to latest versions. This should make 2K3 drive...
[reactos.git] / reactos / subsys / win32k / ntuser / desktop.c
index fa4019b..9c89b69 100644 (file)
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- *  $Id: desktop.c,v 1.18 2004/08/08 17:57:34 weiden Exp $
+ *  $Id$
  *
  *  COPYRIGHT:        See COPYING in the top level directory
  *  PROJECT:          ReactOS kernel
  */
 
 /* INCLUDES ******************************************************************/
+
 #include <w32k.h>
 
-#if 0
-/* not yet defined in w32api... */
-NTSTATUS STDCALL
-ObFindHandleForObject(IN PEPROCESS Process,
-                      IN PVOID Object,
-                      IN POBJECT_TYPE ObjectType,
-                      IN POBJECT_HANDLE_INFORMATION HandleInformation,
-                      OUT PHANDLE Handle);
-#else
-#define ObFindHandleForObject(Process, Object, ObjectType, HandleInformation, Handle) \
-  (STATUS_UNSUCCESSFUL)
-#endif
+#define NDEBUG
+#include <debug.h>
 
 /* GLOBALS *******************************************************************/
 
 /* Currently active desktop */
 PDESKTOP_OBJECT InputDesktop = NULL;
-HDESK InputDesktopHandle = NULL; 
+HDESK InputDesktopHandle = NULL;
 HDC ScreenDeviceContext = NULL;
 
+BOOL g_PaintDesktopVersion = FALSE;
+
 /* INITALIZATION FUNCTIONS ****************************************************/
 
+static GENERIC_MAPPING IntDesktopMapping =
+   {
+      STANDARD_RIGHTS_READ     | DESKTOP_ENUMERATE       | DESKTOP_READOBJECTS,
+      STANDARD_RIGHTS_WRITE    | DESKTOP_CREATEMENU      | DESKTOP_CREATEWINDOW    | DESKTOP_HOOKCONTROL   |
+      DESKTOP_JOURNALPLAYBACK | DESKTOP_JOURNALRECORD   | DESKTOP_WRITEOBJECTS,
+      STANDARD_RIGHTS_EXECUTE  | DESKTOP_SWITCHDESKTOP,
+      STANDARD_RIGHTS_REQUIRED | DESKTOP_CREATEMENU      | DESKTOP_CREATEWINDOW    | DESKTOP_ENUMERATE     |
+      DESKTOP_HOOKCONTROL     | DESKTOP_JOURNALPLAYBACK | DESKTOP_JOURNALRECORD |
+      DESKTOP_READOBJECTS     | DESKTOP_SWITCHDESKTOP   | DESKTOP_WRITEOBJECTS
+   };
+
 NTSTATUS FASTCALL
 InitDesktopImpl(VOID)
 {
-  return STATUS_SUCCESS;
+   /* Set Desktop Object Attributes */
+   ExDesktopObjectType->TypeInfo.DefaultNonPagedPoolCharge = sizeof(DESKTOP_OBJECT);
+   ExDesktopObjectType->TypeInfo.GenericMapping = IntDesktopMapping;
+
+   return STATUS_SUCCESS;
 }
 
 NTSTATUS FASTCALL
 CleanupDesktopImpl(VOID)
 {
-  return STATUS_SUCCESS;
+   return STATUS_SUCCESS;
+}
+
+/* OBJECT CALLBACKS **********************************************************/
+
+NTSTATUS STDCALL
+IntDesktopObjectCreate(PVOID ObjectBody,
+                       PVOID Parent,
+                       PWSTR RemainingPath,
+                       struct _OBJECT_ATTRIBUTES* ObjectAttributes)
+{
+   PDESKTOP_OBJECT Desktop = (PDESKTOP_OBJECT)ObjectBody;
+   UNICODE_STRING UnicodeString;
+
+   DPRINT("Creating desktop (0x%X)  Name (%S)\n", Desktop, RemainingPath);
+   if (RemainingPath == NULL)
+   {
+      return STATUS_SUCCESS;
+   }
+
+   if (wcschr((RemainingPath + 1), '\\') != NULL)
+   {
+      return STATUS_UNSUCCESSFUL;
+   }
+
+   RtlInitUnicodeString(&UnicodeString, (RemainingPath + 1));
+
+   InitializeListHead(&Desktop->ShellHookWindows);
+
+   Desktop->WindowStation = (PWINSTATION_OBJECT)Parent;
+
+   /* Put the desktop on the window station's list of associcated desktops */
+//   ExInterlocked
+   InsertTailList(
+      &Desktop->WindowStation->DesktopListHead,
+      &Desktop->ListEntry);//,
+//      &Desktop->WindowStation->Lock);
+
+   return RtlCreateUnicodeString(&Desktop->Name, UnicodeString.Buffer);
+}
+
+VOID STDCALL
+IntDesktopObjectDelete(PVOID DeletedObject)
+{
+   PDESKTOP_OBJECT Desktop = (PDESKTOP_OBJECT)DeletedObject;
+
+   DPRINT("Deleting desktop (0x%X)\n", Desktop);
+
+   /* Remove the desktop from the window station's list of associcated desktops */
+   RemoveEntryList(&Desktop->ListEntry);
+
+   RtlFreeUnicodeString(&Desktop->Name);
 }
 
 /* PRIVATE FUNCTIONS **********************************************************/
 
+static int GetSystemVersionString(LPWSTR buffer)
+{
+   RTL_OSVERSIONINFOEXW versionInfo;
+   int len;
+
+   versionInfo.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW);
+
+   if (!NT_SUCCESS(RtlGetVersion((PRTL_OSVERSIONINFOW)&versionInfo)))
+      return 0;
+
+   if (versionInfo.dwMajorVersion <= 4)
+      len = swprintf(buffer,
+                     L"ReactOS Version %d.%d %s Build %d",
+                     versionInfo.dwMajorVersion, versionInfo.dwMinorVersion,
+                     versionInfo.szCSDVersion, versionInfo.dwBuildNumber&0xFFFF);
+   else
+      len = swprintf(buffer,
+                     L"ReactOS %s (Build %d)",
+                     versionInfo.szCSDVersion, versionInfo.dwBuildNumber&0xFFFF);
+
+   return len;
+}
+
+
+NTSTATUS FASTCALL
+IntParseDesktopPath(PEPROCESS Process,
+                    PUNICODE_STRING DesktopPath,
+                    HWINSTA *hWinSta,
+                    HDESK *hDesktop)
+{
+   OBJECT_ATTRIBUTES ObjectAttributes;
+   UNICODE_STRING WinSta, Desktop, FullName;
+   BOOL DesktopPresent = FALSE;
+   BOOL WinStaPresent = FALSE;
+   NTSTATUS Status;
+
+   ASSERT(hWinSta);
+
+   *hWinSta = NULL;
+
+   if(hDesktop != NULL)
+   {
+      *hDesktop = NULL;
+   }
+
+   RtlInitUnicodeString(&WinSta, NULL);
+   RtlInitUnicodeString(&Desktop, NULL);
+
+   if(DesktopPath != NULL && DesktopPath->Buffer != NULL && DesktopPath->Length > sizeof(WCHAR))
+   {
+      PWCHAR c = DesktopPath->Buffer;
+      USHORT wl = 0;
+      USHORT l = DesktopPath->Length;
+
+      /*
+       * Parse the desktop path string which can be in the form "WinSta\Desktop"
+       * or just "Desktop". In latter case WinSta0 will be used.
+       */
+
+      while(l > 0)
+      {
+         if(*c == L'\\')
+         {
+            wl = (ULONG_PTR)c - (ULONG_PTR)DesktopPath->Buffer;
+            break;
+         }
+         l -= sizeof(WCHAR);
+         c++;
+      }
+
+      if(wl > 0)
+      {
+         WinSta.Length = wl;
+         WinSta.MaximumLength = wl + sizeof(WCHAR);
+         WinSta.Buffer = DesktopPath->Buffer;
+
+         WinStaPresent = TRUE;
+         c++;
+      }
+
+      Desktop.Length = DesktopPath->Length - wl;
+      if(wl > 0)
+      {
+         Desktop.Length -= sizeof(WCHAR);
+      }
+      if(Desktop.Length > 0)
+      {
+         Desktop.MaximumLength = Desktop.Length + sizeof(WCHAR);
+         Desktop.Buffer = ((wl > 0) ? c : DesktopPath->Buffer);
+         DesktopPresent = TRUE;
+      }
+   }
+
+   if(!WinStaPresent)
+   {
+      /* search the process handle table for (inherited) window station
+         handles, use a more appropriate one than WinSta0 if possible. */
+      Status = ObFindHandleForObject(Process,
+                                     NULL,
+                                     ExWindowStationObjectType,
+                                     NULL,
+                                     (PHANDLE)hWinSta);
+      if(!NT_SUCCESS(Status))
+      {
+         /* we had no luck searching for opened handles, use WinSta0 now */
+         RtlInitUnicodeString(&WinSta, L"WinSta0");
+      }
+   }
+
+   if(!DesktopPresent && hDesktop != NULL)
+   {
+      /* search the process handle table for (inherited) desktop
+         handles, use a more appropriate one than Default if possible. */
+      Status = ObFindHandleForObject(Process,
+                                     NULL,
+                                     ExDesktopObjectType,
+                                     NULL,
+                                     (PHANDLE)hDesktop);
+      if(!NT_SUCCESS(Status))
+      {
+         /* we had no luck searching for opened handles, use Desktop now */
+         RtlInitUnicodeString(&Desktop, L"Default");
+      }
+   }
+
+   if(*hWinSta == NULL)
+   {
+      if(!IntGetFullWindowStationName(&FullName, &WinSta, NULL))
+      {
+         return STATUS_INSUFFICIENT_RESOURCES;
+      }
+
+      /* open the window station */
+      InitializeObjectAttributes(&ObjectAttributes,
+                                 &FullName,
+                                 OBJ_CASE_INSENSITIVE,
+                                 NULL,
+                                 NULL);
+
+      Status = ObOpenObjectByName(&ObjectAttributes,
+                                  ExWindowStationObjectType,
+                                  NULL,
+                                  KernelMode,
+                                  0,
+                                  NULL,
+                                  (HANDLE*)hWinSta);
+
+      RtlFreeUnicodeString(&FullName);
+
+      if(!NT_SUCCESS(Status))
+      {
+         SetLastNtError(Status);
+         DPRINT("Failed to reference window station %wZ PID: %d!\n", &WinSta, PsGetCurrentProcessId());
+         return Status;
+      }
+   }
+
+   if(hDesktop != NULL && *hDesktop == NULL)
+   {
+      if(!IntGetFullWindowStationName(&FullName, &WinSta, &Desktop))
+      {
+         NtClose(*hWinSta);
+         *hWinSta = NULL;
+         return STATUS_INSUFFICIENT_RESOURCES;
+      }
+
+      /* open the desktop object */
+      InitializeObjectAttributes(&ObjectAttributes,
+                                 &FullName,
+                                 OBJ_CASE_INSENSITIVE,
+                                 NULL,
+                                 NULL);
+
+      Status = ObOpenObjectByName(&ObjectAttributes,
+                                  ExDesktopObjectType,
+                                  NULL,
+                                  KernelMode,
+                                  0,
+                                  NULL,
+                                  (HANDLE*)hDesktop);
+
+      RtlFreeUnicodeString(&FullName);
+
+      if(!NT_SUCCESS(Status))
+      {
+         *hDesktop = NULL;
+         NtClose(*hWinSta);
+         *hWinSta = NULL;
+         SetLastNtError(Status);
+         DPRINT("Failed to reference desktop %wZ PID: %d!\n", &Desktop, PsGetCurrentProcessId());
+         return Status;
+      }
+   }
+
+   return STATUS_SUCCESS;
+}
+
 /*
  * IntValidateDesktopHandle
  *
@@ -86,12 +342,12 @@ IntValidateDesktopHandle(
    NTSTATUS Status;
 
    Status = ObReferenceObjectByHandle(
-      Desktop,
-      DesiredAccess,
-      ExDesktopObjectType,
-      AccessMode,
-      (PVOID*)Object,
-      NULL);
+               Desktop,
+               DesiredAccess,
+               ExDesktopObjectType,
+               AccessMode,
+               (PVOID*)Object,
+               NULL);
 
    if (!NT_SUCCESS(Status))
       SetLastNtError(Status);
@@ -102,36 +358,37 @@ IntValidateDesktopHandle(
 VOID FASTCALL
 IntGetDesktopWorkArea(PDESKTOP_OBJECT Desktop, PRECT Rect)
 {
-  PRECT Ret;
-  
-  ASSERT(Desktop);
-  
-  Ret = &Desktop->WorkArea;
-  if((Ret->right == -1) && ScreenDeviceContext)
-  {
-    PDC dc;
-    BITMAPOBJ *BitmapObj;
-    dc = DC_LockDc(ScreenDeviceContext);
-    BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
-    if(BitmapObj)
-    {
-      Ret->right = BitmapObj->SurfObj.sizlBitmap.cx;
-      Ret->bottom = BitmapObj->SurfObj.sizlBitmap.cy;
-      BITMAPOBJ_UnlockBitmap(dc->w.hBitmap);
-    }
-    DC_UnlockDc(ScreenDeviceContext);
-  }
-  
-  if(Rect)
-  {
-    *Rect = *Ret;
-  }
+   PRECT Ret;
+
+   ASSERT(Desktop);
+
+   Ret = &Desktop->WorkArea;
+   if((Ret->right == -1) && ScreenDeviceContext)
+   {
+      PDC dc;
+      BITMAPOBJ *BitmapObj;
+      dc = DC_LockDc(ScreenDeviceContext);
+      /* FIXME - Handle dc == NULL!!!! */
+      BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
+      if(BitmapObj)
+      {
+         Ret->right = BitmapObj->SurfObj.sizlBitmap.cx;
+         Ret->bottom = BitmapObj->SurfObj.sizlBitmap.cy;
+         BITMAPOBJ_UnlockBitmap(BitmapObj);
+      }
+      DC_UnlockDc(dc);
+   }
+
+   if(Rect)
+   {
+      *Rect = *Ret;
+   }
 }
 
 PDESKTOP_OBJECT FASTCALL
 IntGetActiveDesktop(VOID)
 {
-  return InputDesktop;
+   return InputDesktop;
 }
 
 /*
@@ -140,35 +397,35 @@ IntGetActiveDesktop(VOID)
 HDESK FASTCALL
 IntGetDesktopObjectHandle(PDESKTOP_OBJECT DesktopObject)
 {
-  NTSTATUS Status;
-  HDESK Ret;
-  
-  ASSERT(DesktopObject);
-  
-  Status = ObFindHandleForObject(PsGetCurrentProcess(),
-                                 DesktopObject,
-                                 ExDesktopObjectType,
-                                 NULL,
-                                 (PHANDLE)&Ret);
-   
-  if(!NT_SUCCESS(Status))
-  {
-    Status = ObOpenObjectByPointer(DesktopObject,
-                                   0,
-                                   NULL,
-                                   0,
-                                   ExDesktopObjectType,
-                                   UserMode,
-                                   (PHANDLE)&Ret);
-    if(!NT_SUCCESS(Status))
-    {
-     /* unable to create a handle */
-     DPRINT1("Unable to create a desktop handle\n"); 
-     return NULL;
-    }
-  }
-  
-  return Ret;
+   NTSTATUS Status;
+   HDESK Ret;
+
+   ASSERT(DesktopObject);
+
+   Status = ObFindHandleForObject(PsGetCurrentProcess(),
+                                  DesktopObject,
+                                  ExDesktopObjectType,
+                                  NULL,
+                                  (PHANDLE)&Ret);
+
+   if(!NT_SUCCESS(Status))
+   {
+      Status = ObOpenObjectByPointer(DesktopObject,
+                                     0,
+                                     NULL,
+                                     0,
+                                     ExDesktopObjectType,
+                                     UserMode,
+                                     (PHANDLE)&Ret);
+      if(!NT_SUCCESS(Status))
+      {
+         /* unable to create a handle */
+         DPRINT1("Unable to create a desktop handle\n");
+         return NULL;
+      }
+   }
+
+   return Ret;
 }
 
 PUSER_MESSAGE_QUEUE FASTCALL
@@ -197,8 +454,8 @@ IntSetFocusMessageQueue(PUSER_MESSAGE_QUEUE NewQueue)
    {
       if(NewQueue->Desktop != NULL)
       {
-        DPRINT("Message Queue already attached to another desktop!\n");
-        return;
+         DPRINT("Message Queue already attached to another desktop!\n");
+         return;
       }
       IntReferenceMessageQueue(NewQueue);
       InterlockedExchange((LONG*)&NewQueue->Desktop, (LONG)pdo);
@@ -219,61 +476,259 @@ HWND FASTCALL IntGetDesktopWindow(VOID)
       DPRINT("No active desktop\n");
       return NULL;
    }
-  return pdo->DesktopWindow;
+   return pdo->DesktopWindow;
 }
 
+PWINDOW_OBJECT FASTCALL UserGetDesktopWindow(VOID)
+{
+   PDESKTOP_OBJECT pdo = IntGetActiveDesktop();
+
+   if (!pdo)
+   {
+      DPRINT("No active desktop\n");
+      return NULL;
+   }
+
+   return UserGetWindowObject(pdo->DesktopWindow);
+}
+
+
 HWND FASTCALL IntGetCurrentThreadDesktopWindow(VOID)
 {
-  PDESKTOP_OBJECT pdo = PsGetWin32Thread()->Desktop;
-  if (NULL == pdo)
-    {
+   PDESKTOP_OBJECT pdo = PsGetWin32Thread()->Desktop;
+   if (NULL == pdo)
+   {
       DPRINT1("Thread doesn't have a desktop\n");
       return NULL;
-    }
-  return pdo->DesktopWindow;
+   }
+   return pdo->DesktopWindow;
+}
+
+BOOL FASTCALL IntDesktopUpdatePerUserSettings(BOOL bEnable)
+{
+   if (bEnable)
+   {
+      RTL_QUERY_REGISTRY_TABLE QueryTable[2];
+      NTSTATUS Status;
+
+      RtlZeroMemory(QueryTable, sizeof(QueryTable));
+
+      QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
+      QueryTable[0].Name = L"PaintDesktopVersion";
+      QueryTable[0].EntryContext = &g_PaintDesktopVersion;
+
+      /* Query the "PaintDesktopVersion" flag in the "Control Panel\Desktop" key */
+      Status = RtlQueryRegistryValues(RTL_REGISTRY_USER,
+                                      L"Control Panel\\Desktop",
+                                      QueryTable, NULL, NULL);
+      if (!NT_SUCCESS(Status))
+      {
+         DPRINT1("RtlQueryRegistryValues failed for PaintDesktopVersion (%x)\n",
+                 Status);
+         g_PaintDesktopVersion = FALSE;
+         return FALSE;
+      }
+
+      DPRINT("PaintDesktopVersion = %d\n", g_PaintDesktopVersion);
+
+      return TRUE;
+   }
+   else
+   {
+      g_PaintDesktopVersion = FALSE;
+      return TRUE;
+   }
 }
 
 /* PUBLIC FUNCTIONS ***********************************************************/
 
 NTSTATUS FASTCALL
-IntShowDesktop(PDESKTOP_OBJECT Desktop, ULONG Width, ULONG Height)
+co_IntShowDesktop(PDESKTOP_OBJECT Desktop, ULONG Width, ULONG Height)
 {
-  CSRSS_API_REQUEST Request;
-  CSRSS_API_REPLY Reply;
+   CSR_API_MESSAGE Request;
 
-  Request.Type = CSRSS_SHOW_DESKTOP;
-  Request.Data.ShowDesktopRequest.DesktopWindow = Desktop->DesktopWindow;
-  Request.Data.ShowDesktopRequest.Width = Width;
-  Request.Data.ShowDesktopRequest.Height = Height;
+   Request.Type = MAKE_CSR_API(SHOW_DESKTOP, CSR_GUI);
+   Request.Data.ShowDesktopRequest.DesktopWindow = Desktop->DesktopWindow;
+   Request.Data.ShowDesktopRequest.Width = Width;
+   Request.Data.ShowDesktopRequest.Height = Height;
 
-  return CsrNotify(&Request, &Reply);
+   return co_CsrNotify(&Request);
 }
 
 NTSTATUS FASTCALL
 IntHideDesktop(PDESKTOP_OBJECT Desktop)
 {
 #if 0
-  CSRSS_API_REQUEST Request;
-  CSRSS_API_REPLY Reply;
+   CSRSS_API_REQUEST Request;
+   CSRSS_API_REPLY Reply;
 
-  Request.Type = CSRSS_HIDE_DESKTOP;
-  Request.Data.HideDesktopRequest.DesktopWindow = Desktop->DesktopWindow;
+   Request.Type = CSRSS_HIDE_DESKTOP;
+   Request.Data.HideDesktopRequest.DesktopWindow = Desktop->DesktopWindow;
 
-  return NotifyCsrss(&Request, &Reply);
+   return NotifyCsrss(&Request, &Reply);
 #else
-  PWINDOW_OBJECT DesktopWindow;
 
-  DesktopWindow = IntGetWindowObject(Desktop->DesktopWindow);
-  if (! DesktopWindow)
-    {
+   PWINDOW_OBJECT DesktopWindow;
+
+   DesktopWindow = IntGetWindowObject(Desktop->DesktopWindow);
+   if (! DesktopWindow)
+   {
       return ERROR_INVALID_WINDOW_HANDLE;
-    }
-  DesktopWindow->Style &= ~WS_VISIBLE;
+   }
+   DesktopWindow->Style &= ~WS_VISIBLE;
+
+   return STATUS_SUCCESS;
+#endif
+}
+
+
+
+
+static
+HWND* FASTCALL
+UserBuildShellHookHwndList(PDESKTOP_OBJECT Desktop)
+{
+   ULONG entries=0;
+   PSHELL_HOOK_WINDOW Current;
+   HWND* list;
+   
+   /* fixme: if we save nb elements in desktop, we dont have to loop to find nb entries */
+   LIST_FOR_EACH(Current, &Desktop->ShellHookWindows, SHELL_HOOK_WINDOW, ListEntry)
+      entries++;
+
+   if (!entries) return NULL;
+
+   list = ExAllocatePool(PagedPool, sizeof(HWND) * (entries + 1)); /* alloc one extra for nullterm */
+   if (list)
+   {
+      HWND* cursor = list;
+      
+      LIST_FOR_EACH(Current, &Desktop->ShellHookWindows, SHELL_HOOK_WINDOW, ListEntry)
+         *cursor++ = Current->hWnd;
+   
+      *cursor = NULL; /* nullterm list */
+   }
+
+   return list;
+}
+
+/*
+ * Send the Message to the windows registered for ShellHook
+ * notifications. The lParam contents depend on the Message. See
+ * MSDN for more details (RegisterShellHookWindow)
+ */
+VOID co_IntShellHookNotify(WPARAM Message, LPARAM lParam)
+{
+   PDESKTOP_OBJECT Desktop = IntGetActiveDesktop();
+   HWND* HwndList;
+
+   static UINT MsgType = 0;
 
-  return STATUS_SUCCESS;
+   if (!MsgType)
+   {
+
+      /* Too bad, this doesn't work.*/
+#if 0
+      UNICODE_STRING Str;
+      RtlInitUnicodeString(&Str, L"SHELLHOOK");
+      MsgType = UserRegisterWindowMessage(&Str);
 #endif
+
+      MsgType = IntAddAtom(L"SHELLHOOK");
+
+      DPRINT("MsgType = %x\n", MsgType);
+      if (!MsgType)
+         DPRINT1("LastError: %x\n", GetLastNtError());
+   }
+
+   if (!Desktop)
+   {
+      DPRINT1("IntShellHookNotify: No desktop!\n");
+      return;
+   }
+
+   HwndList = UserBuildShellHookHwndList(Desktop);
+   if (HwndList)
+   {
+      HWND* cursor = HwndList;
+      
+      for (; *cursor; cursor++)
+      {
+         DPRINT("Sending notify\n");
+         co_IntPostOrSendMessage(*cursor,
+                                 MsgType,
+                                 Message,
+                                 lParam);
+      }
+
+      ExFreePool(HwndList);
+   }
+   
 }
 
+/*
+ * Add the window to the ShellHookWindows list. The windows
+ * on that list get notifications that are important to shell
+ * type applications.
+ *
+ * TODO: Validate the window? I'm not sure if sending these messages to
+ * an unsuspecting application that is not your own is a nice thing to do.
+ */
+BOOL IntRegisterShellHookWindow(HWND hWnd)
+{
+   PDESKTOP_OBJECT Desktop = PsGetWin32Thread()->Desktop;
+   PSHELL_HOOK_WINDOW Entry;
+
+   DPRINT("IntRegisterShellHookWindow\n");
+
+   /* First deregister the window, so we can be sure it's never twice in the
+    * list.
+    */
+   IntDeRegisterShellHookWindow(hWnd);
+
+   Entry = ExAllocatePoolWithTag(PagedPool,
+                                 sizeof(SHELL_HOOK_WINDOW),
+                                 TAG_WINSTA);
+
+   if (!Entry)
+      return FALSE;
+
+   Entry->hWnd = hWnd;
+
+   InsertTailList(&Desktop->ShellHookWindows, &Entry->ListEntry);
+
+   return TRUE;
+}
+
+/*
+ * Remove the window from the ShellHookWindows list. The windows
+ * on that list get notifications that are important to shell
+ * type applications.
+ */
+BOOL IntDeRegisterShellHookWindow(HWND hWnd)
+{
+   PDESKTOP_OBJECT Desktop = PsGetWin32Thread()->Desktop;
+   PSHELL_HOOK_WINDOW Current;
+
+   LIST_FOR_EACH(Current, &Desktop->ShellHookWindows, SHELL_HOOK_WINDOW, ListEntry)
+   {
+      if (Current->hWnd == hWnd)
+      {
+         RemoveEntryList(&Current->ListEntry);
+         ExFreePool(Current);
+         return TRUE;
+      }
+   }
+
+   return FALSE;
+}
+
+
+
+
+/* SYSCALLS *******************************************************************/
+
+
 /*
  * NtUserCreateDesktop
  *
@@ -314,135 +769,154 @@ NtUserCreateDesktop(
    LPSECURITY_ATTRIBUTES lpSecurity,
    HWINSTA hWindowStation)
 {
-  OBJECT_ATTRIBUTES ObjectAttributes;
-  PWINSTATION_OBJECT WinStaObject;
-  PDESKTOP_OBJECT DesktopObject;
-  UNICODE_STRING DesktopName;
-  NTSTATUS Status;
-  HDESK Desktop;
-  CSRSS_API_REQUEST Request;
-  CSRSS_API_REPLY Reply;
-
-  Status = IntValidateWindowStationHandle(
-    hWindowStation,
-    KernelMode,
-    0,
-    &WinStaObject);
-
-  if (! NT_SUCCESS(Status))
-    {
-      DPRINT1("Failed validation of window station handle (0x%X)\n", 
-        hWindowStation);
+   OBJECT_ATTRIBUTES ObjectAttributes;
+   PWINSTATION_OBJECT WinStaObject;
+   PDESKTOP_OBJECT DesktopObject;
+   UNICODE_STRING DesktopName;
+   NTSTATUS Status;
+   HDESK Desktop;
+   CSR_API_MESSAGE Request;
+   DECLARE_RETURN(HDESK);
+
+   DPRINT("Enter NtUserCreateDesktop: %wZ\n", lpszDesktopName);
+   UserEnterExclusive();
+
+   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 (! IntGetFullWindowStationName(&DesktopName, &WinStaObject->Name,
-          lpszDesktopName))
-    {
+      RETURN( NULL);
+   }
+
+   if (! IntGetFullWindowStationName(&DesktopName, &WinStaObject->Name,
+                                     lpszDesktopName))
+   {
       SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
       ObDereferenceObject(WinStaObject);
-      return NULL;
-    }
-
-  ObDereferenceObject(WinStaObject);
-
-  /*
-   * Try to open already existing desktop
-   */
-
-  DPRINT("Trying to open desktop (%wZ)\n", &DesktopName);
-
-  /* Initialize ObjectAttributes for the desktop object */
-  InitializeObjectAttributes(
-    &ObjectAttributes,
-    &DesktopName,
-    0,
-    NULL,
-    NULL);
-
-  Status = ObOpenObjectByName(
-    &ObjectAttributes,
-    ExDesktopObjectType,
-    NULL,
-    UserMode,
-    dwDesiredAccess,
-    NULL,
-    (HANDLE*)&Desktop);
-
-  if (NT_SUCCESS(Status))
-    {
+      RETURN( NULL);
+   }
+
+   ObDereferenceObject(WinStaObject);
+
+   /*
+    * Try to open already existing desktop
+    */
+
+   DPRINT1("Trying to open desktop (%wZ)\n", &DesktopName);
+
+   /* Initialize ObjectAttributes for the desktop object */
+   InitializeObjectAttributes(
+      &ObjectAttributes,
+      &DesktopName,
+      0,
+      NULL,
+      NULL);
+
+   Status = ObOpenObjectByName(
+               &ObjectAttributes,
+               ExDesktopObjectType,
+               NULL,
+               KernelMode,
+               dwDesiredAccess,
+               NULL,
+               (HANDLE*)&Desktop);
+
+   if (NT_SUCCESS(Status))
+   {
       DPRINT("Successfully opened desktop (%wZ)\n", &DesktopName);
       ExFreePool(DesktopName.Buffer);
-      return Desktop;
-    }
-
-  /*
-   * No existing desktop found, try to create new one
-   */
-
-  Status = ObCreateObject(
-    ExGetPreviousMode(),
-    ExDesktopObjectType,
-    &ObjectAttributes,
-    ExGetPreviousMode(),
-    NULL,
-    sizeof(DESKTOP_OBJECT),
-    0,
-    0,
-    (PVOID*)&DesktopObject);
-
-  if (! NT_SUCCESS(Status))
-    {
+      RETURN( Desktop);
+   }
+
+   /*
+    * No existing desktop found, try to create new one
+    */
+
+   Status = ObCreateObject(
+               KernelMode,
+               ExDesktopObjectType,
+               &ObjectAttributes,
+               ExGetPreviousMode(),
+               NULL,
+               sizeof(DESKTOP_OBJECT),
+               0,
+               0,
+               (PVOID*)&DesktopObject);
+
+   if (! NT_SUCCESS(Status))
+   {
       DPRINT1("Failed creating desktop (%wZ)\n", &DesktopName);
       ExFreePool(DesktopName.Buffer);
       SetLastNtError(STATUS_UNSUCCESSFUL);
-      return NULL;
-    }
-  
-  // init desktop area
-  DesktopObject->WorkArea.left = 0;
-  DesktopObject->WorkArea.top = 0;
-  DesktopObject->WorkArea.right = -1;
-  DesktopObject->WorkArea.bottom = -1;
-  IntGetDesktopWorkArea(DesktopObject, NULL);
-
-  /* Initialize some local (to win32k) desktop state. */
-  DesktopObject->ActiveMessageQueue = NULL;
-
-  Status = ObInsertObject(
-    (PVOID)DesktopObject,
-    NULL,
-    STANDARD_RIGHTS_REQUIRED,
-    0,
-    NULL,
-    (HANDLE*)&Desktop);
-  
-  ObDereferenceObject(DesktopObject);
-  ExFreePool(DesktopName.Buffer);
-
-  if (! NT_SUCCESS(Status))
-    {
+      RETURN( NULL);
+   }
+
+   // init desktop area
+   DesktopObject->WorkArea.left = 0;
+   DesktopObject->WorkArea.top = 0;
+   DesktopObject->WorkArea.right = -1;
+   DesktopObject->WorkArea.bottom = -1;
+   IntGetDesktopWorkArea(DesktopObject, NULL);
+
+   /* Initialize some local (to win32k) desktop state. */
+   DesktopObject->ActiveMessageQueue = NULL;
+
+   Status = ObInsertObject(
+               (PVOID)DesktopObject,
+               NULL,
+               STANDARD_RIGHTS_REQUIRED,
+               0,
+               NULL,
+               (HANDLE*)&Desktop);
+
+   ObDereferenceObject(DesktopObject);
+   ExFreePool(DesktopName.Buffer);
+
+   if (! NT_SUCCESS(Status))
+   {
       DPRINT1("Failed to create desktop handle\n");
       SetLastNtError(Status);
-      return NULL;
-    }
+      RETURN( NULL);
+   }
 
-  Request.Type = CSRSS_CREATE_DESKTOP;
-  memcpy(Request.Data.CreateDesktopRequest.DesktopName, lpszDesktopName->Buffer,
-         lpszDesktopName->Length);
-  Request.Data.CreateDesktopRequest.DesktopName[lpszDesktopName->Length / sizeof(WCHAR)] = L'\0';
+   /*
+    * Create a handle for CSRSS and notify CSRSS
+    */
+   Request.Type = MAKE_CSR_API(CREATE_DESKTOP, CSR_GUI);
+   Status = CsrInsertObject(Desktop,
+                            GENERIC_ALL,
+                            (HANDLE*)&Request.Data.CreateDesktopRequest.DesktopHandle);
+   if (! NT_SUCCESS(Status))
+   {
+      DPRINT1("Failed to create desktop handle for CSRSS\n");
+      ZwClose(Desktop);
+      SetLastNtError(Status);
+      RETURN( NULL);
+   }
 
-  Status = CsrNotify(&Request, &Reply);
-  if (! NT_SUCCESS(Status))
-    {
+   Status = co_CsrNotify(&Request);
+   if (! NT_SUCCESS(Status))
+   {
+      CsrCloseHandle(Request.Data.CreateDesktopRequest.DesktopHandle);
       DPRINT1("Failed to notify CSRSS about new desktop\n");
       ZwClose(Desktop);
       SetLastNtError(Status);
-      return NULL;
-    }
+      RETURN( NULL);
+   }
 
-  return Desktop;
+   RETURN( Desktop);
+
+CLEANUP:
+   DPRINT("Leave NtUserCreateDesktop, ret=%i\n",_ret_);
+   UserLeave();
+   END_CLEANUP;
 }
 
 /*
@@ -478,6 +952,10 @@ NtUserOpenDesktop(
    UNICODE_STRING DesktopName;
    NTSTATUS Status;
    HDESK Desktop;
+   DECLARE_RETURN(HDESK);
+
+   DPRINT("Enter NtUserOpenDesktop: %wZ\n", lpszDesktopName);
+   UserEnterExclusive();
 
    /*
     * Validate the window station handle and compose the fully
@@ -485,30 +963,30 @@ NtUserOpenDesktop(
     */
 
    Status = IntValidateWindowStationHandle(
-      PROCESS_WINDOW_STATION(),
-      KernelMode,
-      0,
-      &WinStaObject);
+               PsGetCurrentProcess()->Win32WindowStation,
+               KernelMode,
+               0,
+               &WinStaObject);
 
    if (!NT_SUCCESS(Status))
    {
-      DPRINT("Failed validation of window station handle (0x%X)\n",
-         PROCESS_WINDOW_STATION());
+      DPRINT1("Failed validation of window station handle (0x%X)\n",
+              PsGetCurrentProcess()->Win32WindowStation);
       SetLastNtError(Status);
-      return 0;
+      RETURN( 0);
    }
 
    if (!IntGetFullWindowStationName(&DesktopName, &WinStaObject->Name,
-       lpszDesktopName))
+                                    lpszDesktopName))
    {
       SetLastNtError(STATUS_INSUFFICIENT_RESOURCES);
       ObDereferenceObject(WinStaObject);
-      return 0;
+      RETURN( 0);
    }
+
    ObDereferenceObject(WinStaObject);
 
-   DPRINT("Trying to open desktop station (%wZ)\n", &DesktopName);
+   DPRINT1("Trying to open desktop (%wZ)\n", &DesktopName);
 
    /* Initialize ObjectAttributes for the desktop object */
    InitializeObjectAttributes(
@@ -519,25 +997,30 @@ NtUserOpenDesktop(
       NULL);
 
    Status = ObOpenObjectByName(
-      &ObjectAttributes,
-      ExDesktopObjectType,
-      NULL,
-      UserMode,
-      dwDesiredAccess,
-      NULL,
-      (HANDLE*)&Desktop);
+               &ObjectAttributes,
+               ExDesktopObjectType,
+               NULL,
+               UserMode,
+               dwDesiredAccess,
+               NULL,
+               (HANDLE*)&Desktop);
 
    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;
+   RETURN( Desktop);
+
+CLEANUP:
+   DPRINT("Leave NtUserOpenDesktop, ret=%i\n",_ret_);
+   UserLeave();
+   END_CLEANUP;
 }
 
 /*
@@ -554,7 +1037,7 @@ NtUserOpenDesktop(
  *
  *    dwDesiredAccess
  *       Requested type of access.
- * 
+ *
  * Return Value
  *    Handle to the input desktop or zero on failure.
  *
@@ -571,44 +1054,53 @@ NtUserOpenInputDesktop(
    PDESKTOP_OBJECT Object;
    NTSTATUS Status;
    HDESK Desktop;
+   DECLARE_RETURN(HDESK);
+
+   DPRINT("Enter NtUserOpenInputDesktop\n");
+   UserEnterExclusive();
 
    DPRINT("About to open input desktop\n");
 
    /* Get a pointer to the desktop object */
 
    Status = IntValidateDesktopHandle(
-      InputDesktopHandle,
-      UserMode,
-      0,
-      &Object);
+               InputDesktopHandle,
+               UserMode,
+               0,
+               &Object);
 
    if (!NT_SUCCESS(Status))
    {
       DPRINT("Validation of input desktop handle (0x%X) failed\n", InputDesktop);
-      return (HDESK)0;
+      RETURN((HDESK)0);
    }
 
    /* Create a new handle to the object */
 
    Status = ObOpenObjectByPointer(
-      Object,
-      0,
-      NULL,
-      dwDesiredAccess,
-      ExDesktopObjectType,
-      UserMode,
-      (HANDLE*)&Desktop);
+               Object,
+               0,
+               NULL,
+               dwDesiredAccess,
+               ExDesktopObjectType,
+               UserMode,
+               (HANDLE*)&Desktop);
 
    ObDereferenceObject(Object);
 
    if (NT_SUCCESS(Status))
    {
       DPRINT("Successfully opened input desktop\n");
-      return (HDESK)Desktop;
+      RETURN((HDESK)Desktop);
    }
 
    SetLastNtError(Status);
-   return (HDESK)0;
+   RETURN((HDESK)0);
+   
+CLEANUP:
+   DPRINT("Leave NtUserOpenInputDesktop, ret=%i\n",_ret_);
+   UserLeave();
+   END_CLEANUP;   
 }
 
 /*
@@ -638,19 +1130,23 @@ NtUserCloseDesktop(HDESK hDesktop)
 {
    PDESKTOP_OBJECT Object;
    NTSTATUS Status;
+   DECLARE_RETURN(BOOL);
+
+   DPRINT("Enter NtUserCloseDesktop\n");
+   UserEnterExclusive();
 
    DPRINT("About to close desktop handle (0x%X)\n", hDesktop);
 
    Status = IntValidateDesktopHandle(
-      hDesktop,
-      UserMode,
-      0,
-      &Object);
+               hDesktop,
+               UserMode,
+               0,
+               &Object);
 
    if (!NT_SUCCESS(Status))
    {
       DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop);
-      return FALSE;
+      RETURN(FALSE);
    }
 
    ObDereferenceObject(Object);
@@ -661,12 +1157,20 @@ NtUserCloseDesktop(HDESK hDesktop)
    if (!NT_SUCCESS(Status))
    {
       SetLastNtError(Status);
-      return FALSE;
+      RETURN(FALSE);
    }
 
-   return TRUE;
+   RETURN(TRUE);
+
+CLEANUP:
+   DPRINT("Leave NtUserCloseDesktop, ret=%i\n",_ret_);
+   UserLeave();
+   END_CLEANUP;     
 }
 
+
+
+
 /*
  * NtUserPaintDesktop
  *
@@ -675,8 +1179,8 @@ NtUserCloseDesktop(HDESK hDesktop)
  * function is provided primarily for shell desktops.
  *
  * Parameters
- *    hdc 
- *       Handle to the device context. 
+ *    hDC
+ *       Handle to the device context.
  *
  * Status
  *    @implemented
@@ -685,26 +1189,123 @@ NtUserCloseDesktop(HDESK hDesktop)
 BOOL STDCALL
 NtUserPaintDesktop(HDC hDC)
 {
-  RECT Rect;
-  HBRUSH DesktopBrush, PreviousBrush;
-  HWND hWndDesktop;
+   RECT Rect;
+   HBRUSH DesktopBrush, PreviousBrush;
+   HWND hWndDesktop;
+   BOOL doPatBlt = TRUE;
+   PWINDOW_OBJECT WndDesktop;
+   int len;
+   DECLARE_RETURN(BOOL);
+   
+   UserEnterExclusive();
+   DPRINT("Enter NtUserPaintDesktop\n");
+
+   PWINSTATION_OBJECT WinSta = PsGetWin32Thread()->Desktop->WindowStation;
 
-  IntGdiGetClipBox(hDC, &Rect);
+   IntGdiGetClipBox(hDC, &Rect);
 
-  hWndDesktop = IntGetDesktopWindow();
-  DesktopBrush = (HBRUSH)NtUserGetClassLong(hWndDesktop, GCL_HBRBACKGROUND, FALSE);
+   hWndDesktop = IntGetDesktopWindow();
+   if (!(WndDesktop = UserGetWindowObject(hWndDesktop)))
+      RETURN(FALSE);
 
-  /*
-   * Paint desktop background
-   */
+   DesktopBrush = (HBRUSH)IntGetClassLong(WndDesktop, GCL_HBRBACKGROUND, FALSE); //fixme: verify retval
 
-  PreviousBrush = NtGdiSelectObject(hDC, DesktopBrush);
-  NtGdiPatBlt(hDC, Rect.left, Rect.top, Rect.right, Rect.bottom, PATCOPY);
-  NtGdiSelectObject(hDC, PreviousBrush);
 
-  return TRUE;
+   /*
+    * Paint desktop background
+    */
+
+   if(WinSta->hbmWallpaper != NULL)
+   {
+      PWINDOW_OBJECT DeskWin;
+
+      if((DeskWin = UserGetWindowObject(hWndDesktop)))
+      {
+         SIZE sz;
+         int x, y;
+         HDC hWallpaperDC;
+
+         sz.cx = DeskWin->WindowRect.right - DeskWin->WindowRect.left;
+         sz.cy = DeskWin->WindowRect.bottom - DeskWin->WindowRect.top;
+
+
+         x = (sz.cx / 2) - (WinSta->cxWallpaper / 2);
+         y = (sz.cy / 2) - (WinSta->cyWallpaper / 2);
+
+         hWallpaperDC = NtGdiCreateCompatibleDC(hDC);
+         if(hWallpaperDC != NULL)
+         {
+            HBITMAP hOldBitmap;
+
+            if(x > 0 || y > 0)
+            {
+               /* FIXME - clip out the bitmap */
+               PreviousBrush = NtGdiSelectObject(hDC, DesktopBrush);
+               NtGdiPatBlt(hDC, Rect.left, Rect.top, Rect.right, Rect.bottom, PATCOPY);
+               NtGdiSelectObject(hDC, PreviousBrush);
+            }
+            else
+               doPatBlt = FALSE;
+
+            hOldBitmap = NtGdiSelectObject(hWallpaperDC, WinSta->hbmWallpaper);
+            NtGdiBitBlt(hDC, x, y, WinSta->cxWallpaper, WinSta->cyWallpaper, hWallpaperDC, 0, 0, SRCCOPY);
+            NtGdiSelectObject(hWallpaperDC, hOldBitmap);
+
+            NtGdiDeleteDC(hWallpaperDC);
+         }
+      }
+   }
+
+   if (doPatBlt)
+   {
+      PreviousBrush = NtGdiSelectObject(hDC, DesktopBrush);
+      NtGdiPatBlt(hDC, Rect.left, Rect.top, Rect.right, Rect.bottom, PATCOPY);
+      NtGdiSelectObject(hDC, PreviousBrush);
+   }
+
+   /*
+    * Display system version on the desktop background
+    */
+
+   if (g_PaintDesktopVersion)
+   {
+      static WCHAR s_wszVersion[256] = {0};
+      RECT rect;
+
+      if (*s_wszVersion)
+         len = wcslen(s_wszVersion);
+      else
+         len = GetSystemVersionString(s_wszVersion);
+
+      if (len)
+      {
+         if (!UserSystemParametersInfo(SPI_GETWORKAREA, 0, &rect, 0))
+         {
+            rect.right = UserGetSystemMetrics(SM_CXSCREEN);
+            rect.bottom = UserGetSystemMetrics(SM_CYSCREEN);
+         }
+
+         COLORREF color_old = NtGdiSetTextColor(hDC, RGB(255,255,255));
+         UINT align_old = NtGdiSetTextAlign(hDC, TA_RIGHT);
+         int mode_old = NtGdiSetBkMode(hDC, TRANSPARENT);
+
+         NtGdiTextOut(hDC, rect.right-16, rect.bottom-48, s_wszVersion, len);
+
+         NtGdiSetBkMode(hDC, mode_old);
+         NtGdiSetTextAlign(hDC, align_old);
+         NtGdiSetTextColor(hDC, color_old);
+      }
+   }
+
+   RETURN(TRUE);
+   
+CLEANUP:
+   DPRINT("Leave NtUserPaintDesktop, ret=%i\n",_ret_);
+   UserLeave();
+   END_CLEANUP;   
 }
 
+
 /*
  * NtUserSwitchDesktop
  *
@@ -726,33 +1327,37 @@ NtUserSwitchDesktop(HDESK hDesktop)
 {
    PDESKTOP_OBJECT DesktopObject;
    NTSTATUS Status;
+   DECLARE_RETURN(BOOL);
+   
+   UserEnterExclusive();
+   DPRINT("Enter NtUserSwitchDesktop\n");
 
    DPRINT("About to switch desktop (0x%X)\n", hDesktop);
 
    Status = IntValidateDesktopHandle(
-      hDesktop,
-      UserMode,
-      0,
-      &DesktopObject);
+               hDesktop,
+               UserMode,
+               0,
+               &DesktopObject);
 
-   if (!NT_SUCCESS(Status)) 
+   if (!NT_SUCCESS(Status))
    {
       DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop);
-      return FALSE;
+      RETURN(FALSE);
    }
-   
+
    /*
     * Don't allow applications switch the desktop if it's locked, unless the caller
     * is the logon application itself
     */
    if((DesktopObject->WindowStation->Flags & WSS_LOCKED) &&
-      LogonProcess != NULL && LogonProcess != PsGetWin32Process())
+         LogonProcess != NULL && LogonProcess != PsGetWin32Process())
    {
       ObDereferenceObject(DesktopObject);
       DPRINT1("Switching desktop 0x%x denied because the work station is locked!\n", hDesktop);
-      return FALSE;
+      RETURN(FALSE);
    }
-   
+
    /* FIXME: Fail if the desktop belong to an invisible window station */
    /* FIXME: Fail if the process is associated with a secured
              desktop such as Winlogon or Screen-Saver */
@@ -768,7 +1373,12 @@ NtUserSwitchDesktop(HDESK hDesktop)
 
    ObDereferenceObject(DesktopObject);
 
-   return TRUE;
+   RETURN(TRUE);
+   
+CLEANUP:
+   DPRINT("Leave NtUserSwitchDesktop, ret=%i\n",_ret_);
+   UserLeave();
+   END_CLEANUP;   
 }
 
 /*
@@ -795,71 +1405,80 @@ NtUserResolveDesktopForWOW(DWORD Unknown0)
 HDESK STDCALL
 NtUserGetThreadDesktop(DWORD dwThreadId, DWORD Unknown1)
 {
-  NTSTATUS Status;
-  PETHREAD Thread;
-  PDESKTOP_OBJECT DesktopObject;
-  HDESK Ret, hThreadDesktop;
-  OBJECT_HANDLE_INFORMATION HandleInformation;
-  
-  if(!dwThreadId)
-  {
-    SetLastWin32Error(ERROR_INVALID_PARAMETER);
-    return 0;
-  }
-  
-  Status = PsLookupThreadByThreadId((PVOID)dwThreadId, &Thread);
-  if(!NT_SUCCESS(Status))
-  {
-    SetLastWin32Error(ERROR_INVALID_PARAMETER);
-    return 0;
-  }
-  
-  if(Thread->ThreadsProcess == PsGetCurrentProcess())
-  {
-    /* just return the handle, we queried the desktop handle of a thread running
-       in the same context */
-    Ret = Thread->Win32Thread->hDesktop;
-    ObDereferenceObject(Thread);
-    return Ret;
-  }
-  
-  /* get the desktop handle and the desktop of the thread */
-  if(!(hThreadDesktop = Thread->Win32Thread->hDesktop) ||
-     !(DesktopObject = Thread->Win32Thread->Desktop))
-  {
-    ObDereferenceObject(Thread);
-    DPRINT1("Desktop information of thread 0x%x broken!?\n", dwThreadId);
-    return NULL;
-  }
-  
-  /* we could just use DesktopObject instead of looking up the handle, but latter
-     may be a bit safer (e.g. when the desktop is being destroyed */
-  /* switch into the context of the thread we're trying to get the desktop from,
-     so we can use the handle */
-  KeAttachProcess(Thread->ThreadsProcess);
-  Status = ObReferenceObjectByHandle(hThreadDesktop,
-                                     GENERIC_ALL,
-                                    ExDesktopObjectType,
-                                    UserMode,
-                                    (PVOID*)&DesktopObject,
-                                    &HandleInformation);
-  KeDetachProcess();
-  
-  /* the handle couldn't be found, there's nothing to get... */
-  if(!NT_SUCCESS(Status))
-  {
-    ObDereferenceObject(Thread);
-    return NULL;                                               
-  }
-  
-  /* lookup our handle table if we can find a handle to the desktop object,
-     if not, create one */
-  Ret = IntGetDesktopObjectHandle(DesktopObject);
-  
-  /* all done, we got a valid handle to the desktop */
-  ObDereferenceObject(DesktopObject);
-  ObDereferenceObject(Thread);
-  return Ret;
+   NTSTATUS Status;
+   PETHREAD Thread;
+   PDESKTOP_OBJECT DesktopObject;
+   HDESK Ret, hThreadDesktop;
+   OBJECT_HANDLE_INFORMATION HandleInformation;
+   DECLARE_RETURN(HDESK);
+   
+   UserEnterExclusive();
+   DPRINT("Enter NtUserGetThreadDesktop\n");
+
+   if(!dwThreadId)
+   {
+      SetLastWin32Error(ERROR_INVALID_PARAMETER);
+      RETURN(0);
+   }
+
+   Status = PsLookupThreadByThreadId((HANDLE)dwThreadId, &Thread);
+   if(!NT_SUCCESS(Status))
+   {
+      SetLastWin32Error(ERROR_INVALID_PARAMETER);
+      RETURN(0);
+   }
+
+   if(Thread->ThreadsProcess == PsGetCurrentProcess())
+   {
+      /* just return the handle, we queried the desktop handle of a thread running
+         in the same context */
+      Ret = ((PW32THREAD)Thread->Tcb.Win32Thread)->hDesktop;
+      ObDereferenceObject(Thread);
+      RETURN(Ret);
+   }
+
+   /* get the desktop handle and the desktop of the thread */
+   if(!(hThreadDesktop = ((PW32THREAD)Thread->Tcb.Win32Thread)->hDesktop) ||
+         !(DesktopObject = ((PW32THREAD)Thread->Tcb.Win32Thread)->Desktop))
+   {
+      ObDereferenceObject(Thread);
+      DPRINT1("Desktop information of thread 0x%x broken!?\n", dwThreadId);
+      RETURN(NULL);
+   }
+
+   /* we could just use DesktopObject instead of looking up the handle, but latter
+      may be a bit safer (e.g. when the desktop is being destroyed */
+   /* switch into the context of the thread we're trying to get the desktop from,
+      so we can use the handle */
+   KeAttachProcess(&Thread->ThreadsProcess->Pcb);
+   Status = ObReferenceObjectByHandle(hThreadDesktop,
+                                      GENERIC_ALL,
+                                      ExDesktopObjectType,
+                                      UserMode,
+                                      (PVOID*)&DesktopObject,
+                                      &HandleInformation);
+   KeDetachProcess();
+
+   /* the handle couldn't be found, there's nothing to get... */
+   if(!NT_SUCCESS(Status))
+   {
+      ObDereferenceObject(Thread);
+      RETURN(NULL);
+   }
+
+   /* lookup our handle table if we can find a handle to the desktop object,
+      if not, create one */
+   Ret = IntGetDesktopObjectHandle(DesktopObject);
+
+   /* all done, we got a valid handle to the desktop */
+   ObDereferenceObject(DesktopObject);
+   ObDereferenceObject(Thread);
+   RETURN(Ret);
+   
+CLEANUP:
+   DPRINT("Leave NtUserGetThreadDesktop, ret=%i\n",_ret_);
+   UserLeave();
+   END_CLEANUP;
 }
 
 /*
@@ -875,28 +1494,25 @@ NtUserSetThreadDesktop(HDESK hDesktop)
    PW32THREAD W32Thread;
    PDESKTOP_OBJECT DesktopObject;
    NTSTATUS Status;
-
+   DECLARE_RETURN(BOOL);
+   
+   UserEnterExclusive();
+   DPRINT("Enter NtUserSetThreadDesktop\n");
+   
    /* Validate the new desktop. */
    Status = IntValidateDesktopHandle(
-      hDesktop,
-      UserMode,
-      0,
-      &DesktopObject);
+               hDesktop,
+               UserMode,
+               0,
+               &DesktopObject);
 
-   if (!NT_SUCCESS(Status)) 
+   if (!NT_SUCCESS(Status))
    {
       DPRINT("Validation of desktop handle (0x%X) failed\n", hDesktop);
-      return FALSE;
+      RETURN(FALSE);
    }
 
    W32Thread = PsGetWin32Thread();
-   /* Check for setting the same desktop as before. */
-   if (DesktopObject == W32Thread->Desktop)
-   {
-      W32Thread->hDesktop = hDesktop;
-      ObDereferenceObject(DesktopObject);
-      return TRUE;
-   }
 
    /* FIXME: Should check here to see if the thread has any windows. */
 
@@ -908,7 +1524,12 @@ NtUserSetThreadDesktop(HDESK hDesktop)
    W32Thread->Desktop = DesktopObject;
    W32Thread->hDesktop = hDesktop;
 
-   return TRUE;
+   RETURN(TRUE);
+   
+CLEANUP:
+   DPRINT("Leave NtUserSetThreadDesktop, ret=%i\n",_ret_);
+   UserLeave();
+   END_CLEANUP;
 }
 
 /* EOF */