Commit 92fec7b6 authored by Alexandre Julliard's avatar Alexandre Julliard

Keep track of the windows and hooks used by a thread to properly

refuse to change the thread desktop when it's in use.
parent 52736b47
...@@ -64,12 +64,9 @@ static DWORD CALLBACK thread( LPVOID arg ) ...@@ -64,12 +64,9 @@ static DWORD CALLBACK thread( LPVOID arg )
trace( "created desktop %p\n", d2 ); trace( "created desktop %p\n", d2 );
ok( d2 != 0, "CreateDesktop failed\n" ); ok( d2 != 0, "CreateDesktop failed\n" );
todo_wine SetLastError( 0xdeadbeef );
{ ok( !SetThreadDesktop( d2 ), "set thread desktop succeeded with existing window\n" );
SetLastError( 0xdeadbeef ); ok( GetLastError() == ERROR_BUSY, "bad last error %ld\n", GetLastError() );
ok( !SetThreadDesktop( d2 ), "set thread desktop succeeded with existing window\n" );
ok( GetLastError() == ERROR_BUSY, "bad last error %ld\n", GetLastError() );
}
DestroyWindow( hwnd ); DestroyWindow( hwnd );
ok( SetThreadDesktop( d2 ), "set thread desktop failed\n" ); ok( SetThreadDesktop( d2 ), "set thread desktop failed\n" );
......
...@@ -125,6 +125,7 @@ static struct hook *add_hook( struct thread *thread, int index, int global ) ...@@ -125,6 +125,7 @@ static struct hook *add_hook( struct thread *thread, int index, int global )
hook->thread = thread ? (struct thread *)grab_object( thread ) : NULL; hook->thread = thread ? (struct thread *)grab_object( thread ) : NULL;
hook->index = index; hook->index = index;
list_add_head( &table->hooks[index], &hook->chain ); list_add_head( &table->hooks[index], &hook->chain );
if (thread) thread->desktop_users++;
return hook; return hook;
} }
...@@ -133,7 +134,12 @@ static void free_hook( struct hook *hook ) ...@@ -133,7 +134,12 @@ static void free_hook( struct hook *hook )
{ {
free_user_handle( hook->handle ); free_user_handle( hook->handle );
if (hook->module) free( hook->module ); if (hook->module) free( hook->module );
if (hook->thread) release_object( hook->thread ); if (hook->thread)
{
assert( hook->thread->desktop_users > 0 );
hook->thread->desktop_users--;
release_object( hook->thread );
}
if (hook->process) release_object( hook->process ); if (hook->process) release_object( hook->process );
release_object( hook->owner ); release_object( hook->owner );
list_remove( &hook->chain ); list_remove( &hook->chain );
......
...@@ -140,6 +140,7 @@ inline static void init_thread_structure( struct thread *thread ) ...@@ -140,6 +140,7 @@ inline static void init_thread_structure( struct thread *thread )
thread->suspend = 0; thread->suspend = 0;
thread->creation_time = time(NULL); thread->creation_time = time(NULL);
thread->exit_time = 0; thread->exit_time = 0;
thread->desktop_users = 0;
list_init( &thread->mutex_list ); list_init( &thread->mutex_list );
list_init( &thread->system_apc ); list_init( &thread->system_apc );
......
...@@ -83,6 +83,7 @@ struct thread ...@@ -83,6 +83,7 @@ struct thread
int affinity; /* affinity mask */ int affinity; /* affinity mask */
int suspend; /* suspend count */ int suspend; /* suspend count */
obj_handle_t desktop; /* desktop handle */ obj_handle_t desktop; /* desktop handle */
int desktop_users; /* number of objects using the thread desktop */
time_t creation_time; /* Thread creation time */ time_t creation_time; /* Thread creation time */
time_t exit_time; /* Thread exit time */ time_t exit_time; /* Thread exit time */
struct token *token; /* security token associated with this thread */ struct token *token; /* security token associated with this thread */
......
...@@ -311,6 +311,8 @@ static void destroy_window( struct window *win ) ...@@ -311,6 +311,8 @@ static void destroy_window( struct window *win )
if (win == shell_listview) shell_listview = NULL; if (win == shell_listview) shell_listview = NULL;
if (win == progman_window) progman_window = NULL; if (win == progman_window) progman_window = NULL;
if (win == taskman_window) taskman_window = NULL; if (win == taskman_window) taskman_window = NULL;
assert( win->thread->desktop_users > 0 );
win->thread->desktop_users--;
free_user_handle( win->handle ); free_user_handle( win->handle );
destroy_properties( win ); destroy_properties( win );
list_remove( &win->entry ); list_remove( &win->entry );
...@@ -376,6 +378,7 @@ static struct window *create_window( struct window *parent, struct window *owner ...@@ -376,6 +378,7 @@ static struct window *create_window( struct window *parent, struct window *owner
/* put it on parent unlinked list */ /* put it on parent unlinked list */
if (parent) list_add_head( &parent->unlinked, &win->entry ); if (parent) list_add_head( &parent->unlinked, &win->entry );
current->desktop_users++;
return win; return win;
failed: failed:
...@@ -1303,6 +1306,7 @@ DECL_HANDLER(create_window) ...@@ -1303,6 +1306,7 @@ DECL_HANDLER(create_window)
if (!top_window) if (!top_window)
{ {
if (!(top_window = create_window( NULL, NULL, req->atom, req->instance ))) return; if (!(top_window = create_window( NULL, NULL, req->atom, req->instance ))) return;
current->desktop_users--;
top_window->thread = NULL; /* no thread owns the desktop */ top_window->thread = NULL; /* no thread owns the desktop */
top_window->style = WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; top_window->style = WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
} }
......
...@@ -175,6 +175,13 @@ static WCHAR *build_desktop_name( const WCHAR *name, size_t len, ...@@ -175,6 +175,13 @@ static WCHAR *build_desktop_name( const WCHAR *name, size_t len,
return full_name; 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 */ /* create a desktop object */
static struct desktop *create_desktop( const WCHAR *name, size_t len, unsigned int flags, static struct desktop *create_desktop( const WCHAR *name, size_t len, unsigned int flags,
struct winstation *winstation ) struct winstation *winstation )
...@@ -426,14 +433,39 @@ DECL_HANDLER(get_thread_desktop) ...@@ -426,14 +433,39 @@ DECL_HANDLER(get_thread_desktop)
/* set the thread current desktop */ /* set the thread current desktop */
DECL_HANDLER(set_thread_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? */ release_object( winstation );
current->desktop = req->handle; return;
release_object( desktop ); }
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 );
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment