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:
parent
d69ddb7ae7
commit
78a3e63377
|
@ -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) );
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 )))
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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() ));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue