server: Connect to the window station and desktop specified by startup info.

If window station and desktop aren't inherited from the parent, don't
connect to them from the server, but from the USER init code where we
can get the proper values from the startup info structure.
This commit is contained in:
Alexandre Julliard 2006-03-27 12:57:17 +02:00
parent 641e9e382f
commit 90af5a0d17
5 changed files with 112 additions and 55 deletions

View File

@ -31,10 +31,13 @@
#include "controls.h"
#include "user_private.h"
#include "win.h"
#include "wine/unicode.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(graphics);
#define DESKTOP_ALL_ACCESS 0x01ff
WORD USER_HeapSel = 0; /* USER heap selector */
HMODULE user32_module = 0;
@ -152,6 +155,48 @@ static void palette_init(void)
}
/***********************************************************************
* winstation_init
*
* Connect to the process window station and desktop.
*/
static void winstation_init(void)
{
static const WCHAR WinSta0[] = {'W','i','n','S','t','a','0',0};
static const WCHAR Default[] = {'D','e','f','a','u','l','t',0};
STARTUPINFOW info;
WCHAR *winstation = NULL, *desktop = NULL, *buffer = NULL;
HANDLE handle;
GetStartupInfoW( &info );
if (info.lpDesktop && *info.lpDesktop)
{
buffer = HeapAlloc( GetProcessHeap(), 0, (strlenW(info.lpDesktop) + 1) * sizeof(WCHAR) );
strcpyW( buffer, info.lpDesktop );
if ((desktop = strchrW( buffer, '\\' )))
{
*desktop++ = 0;
winstation = buffer;
}
else desktop = buffer;
}
/* set winstation if explicitly specified, or if we don't have one yet */
if (buffer || !GetProcessWindowStation())
{
handle = CreateWindowStationW( winstation ? winstation : WinSta0, 0, WINSTA_ALL_ACCESS, NULL );
if (handle) SetProcessWindowStation( handle );
}
if (buffer || !GetThreadDesktop( GetCurrentThreadId() ))
{
handle = CreateDesktopW( desktop ? desktop : Default, NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL );
if (handle) SetThreadDesktop( handle );
}
HeapFree( GetProcessHeap(), 0, buffer );
}
/***********************************************************************
* USER initialisation routine
*/
@ -170,6 +215,8 @@ static BOOL process_attach(void)
/* some Win9x dlls expect keyboard to be loaded */
if (GetVersion() & 0x80000000) LoadLibrary16( "keyboard.drv" );
winstation_init();
/* Initialize system colors and metrics */
SYSPARAMS_Init();

View File

@ -339,10 +339,8 @@ size_t init_process( struct thread *thread )
return 0;
}
/* connect to the window station and desktop */
connect_process_winstation( process, NULL );
connect_process_desktop( process, NULL );
thread->desktop = process->desktop;
/* connect to the window station */
connect_process_winstation( process, parent_thread );
if (!info) return 0;

View File

@ -152,8 +152,9 @@ extern void *get_class_client_ptr( struct window_class *class );
extern struct winstation *get_process_winstation( struct process *process, unsigned int access );
extern struct desktop *get_thread_desktop( struct thread *thread, unsigned int access );
extern void connect_process_winstation( struct process *process, const struct unicode_str *name );
extern void connect_process_desktop( struct process *process, const struct unicode_str *name );
extern void connect_process_winstation( struct process *process, struct thread *parent );
extern void set_process_default_desktop( struct process *process, struct desktop *desktop,
obj_handle_t handle );
extern void close_process_desktop( struct process *process );
extern void close_thread_desktop( struct thread *thread );

View File

@ -442,6 +442,7 @@ static struct window *create_window( struct window *parent, struct window *owner
list_init( &win->entry );
assert( !desktop->top_window );
desktop->top_window = win;
set_process_default_desktop( current->process, desktop, current->desktop );
}
current->desktop_users++;

View File

@ -41,7 +41,6 @@
static struct list winstation_list = LIST_INIT(winstation_list);
static struct winstation *interactive_winstation;
static struct namespace *winstation_namespace;
static void winstation_dump( struct object *obj, int verbose );
@ -135,7 +134,6 @@ static void winstation_destroy( struct object *obj )
{
struct winstation *winstation = (struct winstation *)obj;
if (winstation == interactive_winstation) interactive_winstation = NULL;
list_remove( &winstation->entry );
if (winstation->clipboard) release_object( winstation->clipboard );
if (winstation->atom_table) release_object( winstation->atom_table );
@ -247,67 +245,75 @@ struct desktop *get_thread_desktop( struct thread *thread, unsigned int access )
return get_desktop_obj( thread->process, thread->desktop, access );
}
/* connect a process to its window station */
void connect_process_winstation( struct process *process, const struct unicode_str *name )
/* set the process default desktop handle */
void set_process_default_desktop( struct process *process, struct desktop *desktop,
obj_handle_t handle )
{
struct winstation *winstation;
struct thread *thread;
struct desktop *old_desktop;
if (process->winstation) return; /* already has one */
if (process->desktop == handle) return; /* nothing to do */
/* check for an inherited winstation handle (don't ask...) */
if ((process->winstation = find_inherited_handle( process, &winstation_ops )) != 0) return;
if (!(old_desktop = get_desktop_obj( process, process->desktop, 0 ))) clear_error();
process->desktop = handle;
if (name)
/* set desktop for threads that don't have one yet */
LIST_FOR_EACH_ENTRY( thread, &process->thread_list, struct thread, proc_entry )
if (!thread->desktop) thread->desktop = handle;
desktop->users++;
if (desktop->close_timeout)
{
winstation = create_winstation( name, OBJ_CASE_INSENSITIVE | OBJ_OPENIF, 0 );
remove_timeout_user( desktop->close_timeout );
desktop->close_timeout = NULL;
}
else
if (old_desktop)
{
if (!interactive_winstation)
{
static const WCHAR winsta0W[] = {'W','i','n','S','t','a','0'};
static const struct unicode_str winsta0 = { winsta0W, sizeof(winsta0W) };
interactive_winstation = create_winstation( &winsta0, OBJ_CASE_INSENSITIVE | OBJ_OPENIF, 0 );
winstation = interactive_winstation;
}
else winstation = (struct winstation *)grab_object( interactive_winstation );
old_desktop->users--;
release_object( old_desktop );
}
if (winstation)
{
process->winstation = alloc_handle( process, winstation, WINSTA_ALL_ACCESS, 0 );
release_object( winstation );
}
clear_error(); /* ignore errors */
}
/* connect a process to its main desktop */
void connect_process_desktop( struct process *process, const struct unicode_str *name )
/* connect a process to its window station */
void connect_process_winstation( struct process *process, struct thread *parent )
{
struct desktop *desktop;
struct winstation *winstation;
struct winstation *winstation = NULL;
struct desktop *desktop = NULL;
obj_handle_t handle;
if (process->desktop) return; /* already has one */
if ((winstation = get_process_winstation( process, WINSTA_CREATEDESKTOP )))
/* check for an inherited winstation handle (don't ask...) */
if ((handle = find_inherited_handle( process, &winstation_ops )))
{
static const WCHAR defaultW[] = {'D','e','f','a','u','l','t'};
static const struct unicode_str default_str = { defaultW, sizeof(defaultW) };
if (!name) name = &default_str;
if ((desktop = create_desktop( name, OBJ_CASE_INSENSITIVE | OBJ_OPENIF, 0, winstation )))
{
process->desktop = alloc_handle( process, desktop, DESKTOP_ALL_ACCESS, 0 );
desktop->users++;
if (desktop->close_timeout)
{
remove_timeout_user( desktop->close_timeout );
desktop->close_timeout = NULL;
}
release_object( desktop );
}
release_object( winstation );
winstation = (struct winstation *)get_handle_obj( process, handle, 0, &winstation_ops );
}
clear_error(); /* ignore errors */
else if (parent && parent->process->winstation)
{
handle = duplicate_handle( parent->process, parent->process->winstation,
process, 0, 0, DUP_HANDLE_SAME_ACCESS );
winstation = (struct winstation *)get_handle_obj( process, handle, 0, &winstation_ops );
}
if (!winstation) goto done;
process->winstation = handle;
if ((handle = find_inherited_handle( process, &desktop_ops )))
{
desktop = get_desktop_obj( process, handle, 0 );
if (!desktop || desktop->winstation != winstation) goto done;
}
else if (parent && parent->desktop)
{
desktop = get_desktop_obj( parent->process, parent->desktop, 0 );
if (!desktop || desktop->winstation != winstation) goto done;
handle = duplicate_handle( parent->process, parent->desktop,
process, 0, 0, DUP_HANDLE_SAME_ACCESS );
}
if (handle) set_process_default_desktop( process, desktop, handle );
done:
if (desktop) release_object( desktop );
if (winstation) release_object( winstation );
clear_error();
}
static void close_desktop_timeout( void *private )
@ -334,6 +340,7 @@ void close_process_desktop( struct process *process )
struct timeval when;
gettimeofday( &when, NULL );
add_timeout( &when, 1000 );
assert( !desktop->close_timeout );
desktop->close_timeout = add_timeout_user( &when, close_desktop_timeout, desktop );
}
release_object( desktop );
@ -518,6 +525,9 @@ DECL_HANDLER(set_thread_desktop)
else
current->desktop = req->handle; /* FIXME: should we close the old one? */
if (!current->process->desktop)
set_process_default_desktop( current->process, new_desktop, req->handle );
if (old_desktop != new_desktop && current->queue) detach_thread_input( current );
if (old_desktop) release_object( old_desktop );