The desktop of a new thread should be set from the process initial

desktop, not from the parent thread.
Fixed a couple of bugs in the desktop name handling.
This commit is contained in:
Alexandre Julliard 2005-06-09 12:07:12 +00:00
parent d69ddb7ae7
commit 78a3e63377
7 changed files with 32 additions and 28 deletions

View File

@ -42,6 +42,8 @@ static void print_object( HANDLE obj )
trace( "obj %p type '%s'\n", obj, buffer );
}
static HDESK initial_desktop;
static DWORD CALLBACK thread( LPVOID arg )
{
HDESK d1, d2;
@ -49,6 +51,7 @@ static DWORD CALLBACK thread( LPVOID arg )
ok( hwnd != 0, "CreateWindow failed\n" );
d1 = GetThreadDesktop(GetCurrentThreadId());
trace( "thread %p desktop: %p\n", arg, d1 );
ok( d1 == initial_desktop, "thread %p doesn't use initial desktop\n", arg );
if (0) /* FIXME: this should be todo_wine but it would break the rest of the test */
{
@ -150,6 +153,7 @@ static void test_handles(void)
/* desktops */
d1 = GetThreadDesktop(GetCurrentThreadId());
initial_desktop = d1;
ok( GetThreadDesktop(GetCurrentThreadId()) == d1,
"GetThreadDesktop returned different handles\n" );
@ -201,8 +205,8 @@ static void test_handles(void)
ok( d1 == d2, "got different handles after close\n" );
}
trace( "thread 1 desktop: %p\n", d2 );
print_object( d2 );
trace( "thread 1 desktop: %p\n", d1 );
print_object( d1 );
hthread = CreateThread( NULL, 0, thread, (LPVOID)2, 0, &id );
Sleep(1000);
trace( "get other thread desktop: %p\n", GetThreadDesktop(id) );

View File

@ -56,7 +56,7 @@ struct handle_table
static struct handle_table *global_table;
/* reserved handle access rights */
#define RESERVED_SHIFT 25
#define RESERVED_SHIFT 26
#define RESERVED_INHERIT (HANDLE_FLAG_INHERIT << RESERVED_SHIFT)
#define RESERVED_CLOSE_PROTECT (HANDLE_FLAG_PROTECT_FROM_CLOSE << RESERVED_SHIFT)
#define RESERVED_ALL (RESERVED_INHERIT | RESERVED_CLOSE_PROTECT)

View File

@ -281,6 +281,7 @@ struct thread *create_process( int fd )
process->peb = NULL;
process->ldt_copy = NULL;
process->winstation = 0;
process->desktop = 0;
process->exe.file = NULL;
process->exe.dbg_offset = 0;
process->exe.dbg_size = 0;
@ -379,7 +380,8 @@ static struct startup_info *init_process( struct init_process_reply *reply )
/* connect to the window station and desktop */
connect_process_winstation( process, NULL, 0 );
connect_thread_desktop( current, NULL, 0 );
connect_process_desktop( process, NULL, 0 );
current->desktop = process->desktop;
/* set the process console */
if (!set_process_console( process, parent_thread, info, reply )) return NULL;

View File

@ -73,6 +73,7 @@ struct process
struct event *idle_event; /* event for input idle */
struct msg_queue *queue; /* main message queue */
obj_handle_t winstation; /* main handle to process window station */
obj_handle_t desktop; /* handle to desktop to use for new threads */
struct token *token; /* security token associated with this process */
struct process_dll exe; /* main exe file */
struct list dlls; /* list of loaded dlls */

View File

@ -137,7 +137,6 @@ inline static void init_thread_structure( struct thread *thread )
thread->priority = THREAD_PRIORITY_NORMAL;
thread->affinity = 1;
thread->suspend = 0;
thread->desktop = 0;
thread->creation_time = time(NULL);
thread->exit_time = 0;
@ -159,6 +158,7 @@ struct thread *create_thread( int fd, struct process *process )
init_thread_structure( thread );
thread->process = (struct process *)grab_object( process );
thread->desktop = process->desktop;
if (!current) current = thread;
if (!booting_thread) /* first thread ever */
@ -834,7 +834,6 @@ DECL_HANDLER(new_thread)
if ((thread = create_thread( request_fd, current->process )))
{
if (req->suspend) thread->suspend++;
thread->desktop = current->desktop;
reply->tid = get_thread_id( thread );
if ((reply->handle = alloc_handle( current->process, thread,
THREAD_ALL_ACCESS, req->inherit )))

View File

@ -121,7 +121,7 @@ extern void *get_class_client_ptr( struct window_class *class );
/* windows station functions */
extern void connect_process_winstation( struct process *process, const WCHAR *name, size_t len );
extern void connect_thread_desktop( struct thread *thread, const WCHAR *name, size_t len );
extern void connect_process_desktop( struct process *process, const WCHAR *name, size_t len );
extern void close_thread_desktop( struct thread *thread );
#endif /* __WINE_SERVER_USER_H */

View File

@ -162,7 +162,7 @@ static WCHAR *build_desktop_name( const WCHAR *name, size_t len,
if (!(full_name = mem_alloc( *res_len ))) return NULL;
memcpy( full_name, winstation_name, winstation_len );
full_name[winstation_len / sizeof(WCHAR)] = '\\';
memcpy( full_name + (winstation_len + 1) / sizeof(WCHAR), name, len );
memcpy( full_name + winstation_len / sizeof(WCHAR) + 1, name, len );
return full_name;
}
@ -207,21 +207,17 @@ static void desktop_destroy( struct object *obj )
release_object( desktop->winstation );
}
/* close a desktop handle if allowed */
static void close_desktop_handle( struct process *process, obj_handle_t handle )
/* check if a desktop handle is currently used by the process */
static int is_desktop_in_use( struct process *process, obj_handle_t handle )
{
struct thread *thread;
/* make sure it's not in use by any thread in the process */
if (process->desktop == handle) return 1;
LIST_FOR_EACH_ENTRY( thread, &process->thread_list, struct thread, proc_entry )
{
if (thread->desktop == handle)
{
set_error( STATUS_DEVICE_BUSY );
return;
}
}
close_handle( process, handle, NULL );
if (thread->desktop == handle) return 1;
return 0;
}
/* connect a process to its window station */
@ -262,14 +258,13 @@ void connect_process_winstation( struct process *process, const WCHAR *name, siz
clear_error(); /* ignore errors */
}
/* connect a thread to its desktop */
void connect_thread_desktop( struct thread *thread, const WCHAR *name, size_t len )
/* connect a process to its main desktop */
void connect_process_desktop( struct process *process, const WCHAR *name, size_t len )
{
struct desktop *desktop;
struct winstation *winstation;
struct process *process = thread->process;
if (thread->desktop) return; /* already has one */
if (process->desktop) return; /* already has one */
if ((winstation = get_process_winstation( process, WINSTA_CREATEDESKTOP )))
{
@ -282,7 +277,7 @@ void connect_thread_desktop( struct thread *thread, const WCHAR *name, size_t le
}
if ((desktop = create_desktop( name, len, 0, winstation )))
{
thread->desktop = alloc_handle( process, desktop, DESKTOP_ALL_ACCESS, FALSE );
process->desktop = alloc_handle( process, desktop, DESKTOP_ALL_ACCESS, FALSE );
release_object( desktop );
}
release_object( winstation );
@ -296,8 +291,8 @@ void close_thread_desktop( struct thread *thread )
obj_handle_t handle = thread->desktop;
thread->desktop = 0;
if (handle) close_desktop_handle( thread->process, handle );
clear_error(); /* ignore errors */
if (handle && !is_desktop_in_use( thread->process, handle ))
close_handle( thread->process, handle, NULL );
}
@ -413,7 +408,10 @@ DECL_HANDLER(close_desktop)
if ((desktop = (struct desktop *)get_handle_obj( current->process, req->handle,
0, &desktop_ops )))
{
close_desktop_handle( current->process, req->handle );
if (!is_desktop_in_use( current->process, req->handle ))
close_handle( current->process, req->handle, NULL );
else
set_error( STATUS_DEVICE_BUSY );
release_object( desktop );
}
}
@ -479,8 +477,8 @@ DECL_HANDLER(set_user_object_info)
/* if there is a backslash return the part of the name after it */
if (name && (ptr = memchrW( name, '\\', len )))
{
len -= (ptr + 1 - name) * sizeof(WCHAR);
name = ptr + 1;
len -= (ptr - name) * sizeof(WCHAR);
}
if (name) set_reply_data( name, min( len, get_reply_max_size() ));
}