diff --git a/server/atom.c b/server/atom.c index 84814e29d8c..eb32bfab112 100644 --- a/server/atom.c +++ b/server/atom.c @@ -284,12 +284,9 @@ static atom_t find_atom( struct atom_table *table, const WCHAR *str, size_t len return 0; } -static struct atom_table *get_global_table( int create ) +static struct atom_table *get_global_table( struct winstation *winstation, int create ) { struct atom_table *global_table; - struct winstation *winstation = get_process_winstation( current->process, WINSTA_ACCESSGLOBALATOMS ); - - if (!winstation) return NULL; if (!(global_table = get_winstation_atom_table( winstation ))) { @@ -300,13 +297,12 @@ static struct atom_table *get_global_table( int create ) } else set_error( STATUS_OBJECT_NAME_NOT_FOUND ); } - release_object( winstation ); return global_table; } static struct atom_table *get_table( obj_handle_t h, int create ) { - struct atom_table *table; + struct atom_table *table = NULL; if (h) { @@ -314,24 +310,30 @@ static struct atom_table *get_table( obj_handle_t h, int create ) } else { - table = get_global_table( 1 ); - if (table) grab_object( table ); + struct winstation *winstation = get_process_winstation( current->process, + WINSTA_ACCESSGLOBALATOMS ); + if (winstation) + { + table = get_global_table( winstation, 1 ); + if (table) grab_object( table ); + release_object( winstation ); + } } return table; } /* add an atom in the global table; used for window properties */ -atom_t add_global_atom( const WCHAR *str, size_t len ) +atom_t add_global_atom( struct winstation *winstation, const WCHAR *str, size_t len ) { - struct atom_table *global_table = get_global_table( 1 ); + struct atom_table *global_table = get_global_table( winstation, 1 ); if (!global_table) return 0; return add_atom( global_table, str, len ); } /* find an atom in the global table; used for window properties */ -atom_t find_global_atom( const WCHAR *str, size_t len ) +atom_t find_global_atom( struct winstation *winstation, const WCHAR *str, size_t len ) { - struct atom_table *global_table = get_global_table( 0 ); + struct atom_table *global_table = get_global_table( winstation, 0 ); struct atom_entry *entry; if (!len || len > MAX_ATOM_LEN || !global_table) return 0; @@ -341,11 +343,11 @@ atom_t find_global_atom( const WCHAR *str, size_t len ) } /* increment the ref count of a global atom; used for window properties */ -int grab_global_atom( atom_t atom ) +int grab_global_atom( struct winstation *winstation, atom_t atom ) { if (atom >= MIN_STR_ATOM) { - struct atom_table *global_table = get_global_table( 0 ); + struct atom_table *global_table = get_global_table( winstation, 0 ); if (global_table) { struct atom_entry *entry = get_atom_entry( global_table, atom ); @@ -358,11 +360,11 @@ int grab_global_atom( atom_t atom ) } /* decrement the ref count of a global atom; used for window properties */ -void release_global_atom( atom_t atom ) +void release_global_atom( struct winstation *winstation, atom_t atom ) { if (atom >= MIN_STR_ATOM) { - struct atom_table *global_table = get_global_table( 0 ); + struct atom_table *global_table = get_global_table( winstation, 0 ); if (global_table) delete_atom( global_table, atom, 1 ); } } diff --git a/server/class.c b/server/class.c index 5f034d9b5b5..929e4ffd924 100644 --- a/server/class.c +++ b/server/class.c @@ -33,6 +33,7 @@ #include "object.h" #include "process.h" #include "user.h" +#include "winuser.h" struct window_class { @@ -156,6 +157,7 @@ void *get_class_client_ptr( struct window_class *class ) DECL_HANDLER(create_class) { struct window_class *class; + struct winstation *winstation; if (!req->local && req->atom == DESKTOP_ATOM) { @@ -175,11 +177,19 @@ DECL_HANDLER(create_class) set_error( STATUS_INVALID_PARAMETER ); return; } - if (!grab_global_atom( req->atom )) return; + if (!(winstation = get_process_winstation( current->process, WINSTA_ACCESSGLOBALATOMS ))) + return; + + if (!grab_global_atom( winstation, req->atom )) + { + release_object( winstation ); + return; + } if (!(class = create_class( current->process, req->extra, req->local ))) { - release_global_atom( req->atom ); + release_global_atom( winstation, req->atom ); + release_object( winstation ); return; } class->atom = req->atom; @@ -187,6 +197,7 @@ DECL_HANDLER(create_class) class->style = req->style; class->win_extra = req->win_extra; class->client_ptr = req->client_ptr; + release_object( winstation ); } /* destroy a window class */ @@ -249,9 +260,16 @@ DECL_HANDLER(set_class_info) if (req->flags & SET_CLASS_ATOM) { - if (!grab_global_atom( req->atom )) return; - release_global_atom( class->atom ); + struct winstation *winstation = get_process_winstation( current->process, + WINSTA_ACCESSGLOBALATOMS ); + if (!grab_global_atom( winstation, req->atom )) + { + release_object( winstation ); + return; + } + release_global_atom( winstation, class->atom ); class->atom = req->atom; + release_object( winstation ); } if (req->flags & SET_CLASS_STYLE) class->style = req->style; if (req->flags & SET_CLASS_WINEXTRA) class->win_extra = req->win_extra; diff --git a/server/object.h b/server/object.h index c7e29edcd97..dfccf98a2ea 100644 --- a/server/object.h +++ b/server/object.h @@ -43,6 +43,7 @@ struct file; struct wait_queue_entry; struct async; struct async_queue; +struct winstation; /* operations valid on all objects */ struct object_ops @@ -157,10 +158,10 @@ extern void close_signals(void); /* atom functions */ -extern atom_t add_global_atom( const WCHAR *str, size_t len ); -extern atom_t find_global_atom( const WCHAR *str, size_t len ); -extern int grab_global_atom( atom_t atom ); -extern void release_global_atom( atom_t atom ); +extern atom_t add_global_atom( struct winstation *winstation, const WCHAR *str, size_t len ); +extern atom_t find_global_atom( struct winstation *winstation, const WCHAR *str, size_t len ); +extern int grab_global_atom( struct winstation *winstation, atom_t atom ); +extern void release_global_atom( struct winstation *winstation, atom_t atom ); /* global variables */ diff --git a/server/window.c b/server/window.c index 0a4cdfafbda..d6c7240bee7 100644 --- a/server/window.c +++ b/server/window.c @@ -200,8 +200,8 @@ static int add_handle_to_array( struct user_handle_array *array, user_handle_t h } /* set a window property */ -static void set_property( struct window *win, atom_t atom, obj_handle_t handle, - enum property_type type ) +static void set_property( struct winstation *winstation, struct window *win, + atom_t atom, obj_handle_t handle, enum property_type type ) { int i, free = -1; struct property *new_props; @@ -223,7 +223,7 @@ static void set_property( struct window *win, atom_t atom, obj_handle_t handle, } /* need to add an entry */ - if (!grab_global_atom( atom )) return; + if (!grab_global_atom( winstation, atom )) return; if (free == -1) { /* no free entry */ @@ -234,7 +234,7 @@ static void set_property( struct window *win, atom_t atom, obj_handle_t handle, sizeof(*new_props) * (win->prop_alloc + 16) ))) { set_error( STATUS_NO_MEMORY ); - release_global_atom( atom ); + release_global_atom( winstation, atom ); return; } win->prop_alloc += 16; @@ -248,7 +248,7 @@ static void set_property( struct window *win, atom_t atom, obj_handle_t handle, } /* remove a window property */ -static obj_handle_t remove_property( struct window *win, atom_t atom ) +static obj_handle_t remove_property( struct winstation *winstation, struct window *win, atom_t atom ) { int i; @@ -257,7 +257,7 @@ static obj_handle_t remove_property( struct window *win, atom_t atom ) if (win->properties[i].type == PROP_TYPE_FREE) continue; if (win->properties[i].atom == atom) { - release_global_atom( atom ); + release_global_atom( winstation, atom ); win->properties[i].type = PROP_TYPE_FREE; return win->properties[i].handle; } @@ -283,15 +283,20 @@ static obj_handle_t get_property( struct window *win, atom_t atom ) /* destroy all properties of a window */ inline static void destroy_properties( struct window *win ) { + struct winstation *winstation; int i; if (!win->properties) return; + /* FIXME: winstation pointer should be taken from window */ + if (!(winstation = get_process_winstation( win->thread->process, WINSTA_ACCESSGLOBALATOMS ))) + return; for (i = 0; i < win->prop_inuse; i++) { if (win->properties[i].type == PROP_TYPE_FREE) continue; - release_global_atom( win->properties[i].atom ); + release_global_atom( winstation, win->properties[i].atom ); } free( win->properties ); + release_object( winstation ); } /* destroy a window */ @@ -1878,34 +1883,42 @@ DECL_HANDLER(redraw_window) /* set a window property */ DECL_HANDLER(set_window_property) { + struct winstation *winstation; struct window *win = get_window( req->window ); if (!win) return; + if (!(winstation = get_process_winstation( current->process, WINSTA_ACCESSGLOBALATOMS ))) return; if (get_req_data_size()) { - atom_t atom = add_global_atom( get_req_data(), get_req_data_size() / sizeof(WCHAR) ); + atom_t atom = add_global_atom( winstation, get_req_data(), get_req_data_size() / sizeof(WCHAR) ); if (atom) { - set_property( win, atom, req->handle, PROP_TYPE_STRING ); - release_global_atom( atom ); + set_property( winstation, win, atom, req->handle, PROP_TYPE_STRING ); + release_global_atom( winstation, atom ); } } - else set_property( win, req->atom, req->handle, PROP_TYPE_ATOM ); + else set_property( winstation, win, req->atom, req->handle, PROP_TYPE_ATOM ); + + release_object( winstation ); } /* remove a window property */ DECL_HANDLER(remove_window_property) { + struct winstation *winstation; struct window *win = get_window( req->window ); - reply->handle = 0; - if (win) + + if (!win) return; + + if ((winstation = get_process_winstation( current->process, WINSTA_ACCESSGLOBALATOMS ))) { atom_t atom = req->atom; - if (get_req_data_size()) atom = find_global_atom( get_req_data(), + if (get_req_data_size()) atom = find_global_atom( winstation, get_req_data(), get_req_data_size() / sizeof(WCHAR) ); - if (atom) reply->handle = remove_property( win, atom ); + if (atom) reply->handle = remove_property( winstation, win, atom ); + release_object( winstation ); } } @@ -1913,14 +1926,18 @@ DECL_HANDLER(remove_window_property) /* get a window property */ DECL_HANDLER(get_window_property) { + struct winstation *winstation; struct window *win = get_window( req->window ); - reply->handle = 0; - if (win) + + if (!win) return; + + if ((winstation = get_process_winstation( current->process, WINSTA_ACCESSGLOBALATOMS ))) { atom_t atom = req->atom; - if (get_req_data_size()) atom = find_global_atom( get_req_data(), + if (get_req_data_size()) atom = find_global_atom( winstation, get_req_data(), get_req_data_size() / sizeof(WCHAR) ); if (atom) reply->handle = get_property( win, atom ); + release_object( winstation ); } }