Skip to content
Snippets Groups Projects
Commit 90af5a0d authored by Alexandre Julliard's avatar Alexandre Julliard
Browse files

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.
parent 641e9e38
No related branches found
No related tags found
No related merge requests found
......@@ -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();
......
......@@ -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;
......
......@@ -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 );
......
......@@ -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++;
......
......@@ -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)
{
winstation = create_winstation( name, OBJ_CASE_INSENSITIVE | OBJ_OPENIF, 0 );
}
else
/* 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)
{
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 );
remove_timeout_user( desktop->close_timeout );
desktop->close_timeout = NULL;
}
if (winstation)
if (old_desktop)
{
process->winstation = alloc_handle( process, winstation, WINSTA_ALL_ACCESS, 0 );
release_object( winstation );
old_desktop->users--;
release_object( old_desktop );
}
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 )))
{
winstation = (struct winstation *)get_handle_obj( process, handle, 0, &winstation_ops );
}
else if (parent && parent->process->winstation)
{
static const WCHAR defaultW[] = {'D','e','f','a','u','l','t'};
static const struct unicode_str default_str = { defaultW, sizeof(defaultW) };
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 (!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 );
if ((handle = find_inherited_handle( process, &desktop_ops )))
{
desktop = get_desktop_obj( process, handle, 0 );
if (!desktop || desktop->winstation != winstation) goto done;
}
clear_error(); /* ignore errors */
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 );
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment