Keep track of the windows and hooks used by a thread to properly
refuse to change the thread desktop when it's in use.

diff --git a/server/winstation.c b/server/winstation.c
index d42ed66..ed61df9 100644
--- a/server/winstation.c
+++ b/server/winstation.c
@@ -175,6 +175,13 @@
     return full_name;
 }
 
+/* retrieve a pointer to a desktop object */
+inline static struct desktop *get_desktop_obj( struct process *process, obj_handle_t handle,
+                                               unsigned int access )
+{
+    return (struct desktop *)get_handle_obj( process, handle, access, &desktop_ops );
+}
+
 /* create a desktop object */
 static struct desktop *create_desktop( const WCHAR *name, size_t len, unsigned int flags,
                                        struct winstation *winstation )
@@ -426,14 +433,39 @@
 /* set the thread current desktop */
 DECL_HANDLER(set_thread_desktop)
 {
-    struct desktop *desktop;
+    struct desktop *old_desktop, *new_desktop;
+    struct winstation *winstation;
 
-    if ((desktop = (struct desktop *)get_handle_obj( current->process, req->handle, 0, &desktop_ops )))
+    if (!(winstation = get_process_winstation( current->process, 0 /* FIXME: access rights? */ )))
+        return;
+
+    if (!(new_desktop = get_desktop_obj( current->process, req->handle, 0 )))
     {
-        /* FIXME: should we close the old one? */
-        current->desktop = req->handle;
-        release_object( desktop );
+        release_object( winstation );
+        return;
     }
+    if (new_desktop->winstation != winstation)
+    {
+        set_error( STATUS_ACCESS_DENIED );
+        release_object( new_desktop );
+        release_object( winstation );
+        return;
+    }
+
+    /* check if we are changing to a new desktop */
+
+    if (!(old_desktop = get_desktop_obj( current->process, current->desktop, 0)))
+        clear_error();  /* ignore error */
+
+    /* when changing desktop, we can't have any users on the current one */
+    if (old_desktop != new_desktop && current->desktop_users > 0)
+        set_error( STATUS_DEVICE_BUSY );
+    else
+        current->desktop = req->handle;  /* FIXME: should we close the old one? */
+
+    if (old_desktop) release_object( old_desktop );
+    release_object( new_desktop );
+    release_object( winstation );
 }