From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/win32u/class.c | 19 +++++++++++-------- server/class.c | 16 ++++++++-------- server/protocol.def | 3 +-- 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/dlls/win32u/class.c b/dlls/win32u/class.c index adcbadcd119..06c9dcc4600 100644 --- a/dlls/win32u/class.c +++ b/dlls/win32u/class.c @@ -46,7 +46,6 @@ SYSTEM_BASIC_INFORMATION system_info; typedef struct tagCLASS { struct list entry; /* Entry in class list */ - BOOL local; /* Local class? */ struct dce *dce; /* Opaque pointer to class DCE */ HICON icon_internal; /* internal small icon, derived from hIcon */ const shared_object_t *shared; /* class object in session shared memory */ @@ -538,6 +537,12 @@ static BOOL class_name_matches( CLASS *class, UNICODE_STRING *name ) return name->Length == len && !wcsnicmp( class_name, name->Buffer, len / sizeof(WCHAR) ); } +static BOOL is_local_class( CLASS *class ) +{ + /* class local flag is safe to read without shared object locking as it is constant */ + return class->shared->shm.class.local; +} + static UINT_PTR get_class_instance( CLASS *class ) { struct object_lock lock = OBJECT_LOCK_INIT; @@ -563,7 +568,7 @@ static CLASS *find_class( HINSTANCE module, UNICODE_STRING *name ) UINT_PTR class_instance = get_class_instance( class ); if (!class_name_matches( class, name )) continue; is_win16 = !(class_instance >> 16); - if (!instance || !class->local || class_instance == instance || + if (!instance || !is_local_class( class ) || class_instance == instance || (!is_win16 && ((class_instance & ~0xffff) == (instance & ~0xffff)))) { TRACE( "%s %lx -> %p\n", debugstr_us(name), instance, class ); @@ -648,8 +653,6 @@ ATOM WINAPI NtUserRegisterClassExWOW( const WNDCLASSEXW *wc, UNICODE_STRING *nam if (!(class = calloc( 1, sizeof(*class) ))) return 0; - class->local = !fnid && !(wc->style & CS_GLOBALCLASS); - /* Other non-null values must be set by caller */ icon_internal = wc->hIconSm ? 0 : create_small_icon( wc->hIcon ); @@ -670,7 +673,6 @@ ATOM WINAPI NtUserRegisterClassExWOW( const WNDCLASSEXW *wc, UNICODE_STRING *nam .menu_name = wine_server_client_ptr( menu_name ), }; wine_server_add_data( req, &info, sizeof(info) ); - req->local = class->local; req->client_ptr = wine_server_client_ptr( class ); req->atom = wine_server_add_atom( req, name ); req->fnid = fnid; @@ -696,15 +698,16 @@ ATOM WINAPI NtUserRegisterClassExWOW( const WNDCLASSEXW *wc, UNICODE_STRING *nam goto failed; } - if (class->local) list_add_head( &class_list, &class->entry ); - else list_add_tail( &class_list, &class->entry ); - TRACE( "name=%s->%s atom=%04x wndproc=%p hinst=%p bg=%p style=%08x clsExt=%d winExt=%d class=%p\n", debugstr_w(wc->lpszClassName), debugstr_us(name), atom, wc->lpfnWndProc, instance, wc->hbrBackground, wc->style, wc->cbClsExtra, wc->cbWndExtra, class ); class->icon_internal = icon_internal; class->shared = shared; + + if (is_local_class( class )) list_add_head( &class_list, &class->entry ); + else list_add_tail( &class_list, &class->entry ); + release_class_ptr( class ); return atom; diff --git a/server/class.c b/server/class.c index a3e1b85bc80..28e263b0395 100644 --- a/server/class.c +++ b/server/class.c @@ -44,7 +44,6 @@ struct window_class struct winstation *winstation; /* winstation the class was created on */ struct process *process; /* process owning the class */ int count; /* reference count */ - int local; /* local class? */ atom_t atom; /* class atom for versioned class */ unsigned int fnid; /* builtin control FNID, or 0 */ client_ptr_t client_ptr; /* pointer to class in client address space */ @@ -61,7 +60,6 @@ static struct window_class *create_class( struct process *process, int local, in class->process = (struct process *)grab_object( process ); class->count = 0; - class->local = local; if (!(class->shared = alloc_shared_object( offsetof(class_shm_t, extra[cls_extra]) ))) goto failed; @@ -110,7 +108,7 @@ static struct window_class *find_class( struct process *process, atom_t atom, mo const class_shm_t *shared = class->shared; if (class->atom != atom) continue; is_win16 = !(shared->info.instance >> 16); - if (!instance || !class->local || shared->info.instance == instance || + if (!instance || !shared->local || shared->info.instance == instance || (!is_win16 && ((shared->info.instance & ~0xffff) == (instance & ~0xffff)))) return class; } return NULL; @@ -136,7 +134,7 @@ void release_class( struct window_class *class ) int is_desktop_class( struct window_class *class ) { - return (class->shared->info.atom == DESKTOP_ATOM && !class->local); + return class->shared->info.atom == DESKTOP_ATOM && !class->shared->local; } int is_message_class( struct window_class *class ) @@ -144,8 +142,7 @@ int is_message_class( struct window_class *class ) static const WCHAR messageW[] = {'M','e','s','s','a','g','e'}; static const struct unicode_str name = { messageW, sizeof(messageW) }; struct atom_table *table = get_user_atom_table(); - - return (!class->local && class->shared->info.atom == find_atom( table, &name )); + return !class->shared->local && class->shared->info.atom == find_atom( table, &name ); } int get_class_style( struct window_class *class ) @@ -199,6 +196,7 @@ DECL_HANDLER(create_class) atom_t atom = req->atom; struct class_info info; WCHAR buffer[16]; + bool local; if (name.len < sizeof(info)) return set_error( STATUS_INVALID_PARAMETER ); memcpy( &info, name.str, sizeof(info) ); @@ -227,8 +225,9 @@ DECL_HANDLER(create_class) info.atom = grab_atom( table, atom ); } + local = !req->fnid && !(info.style & CS_GLOBALCLASS); class = find_class( current->process, atom, info.instance ); - if (class && !class->local == !req->local) + if (class && !class->shared->local == !local) { set_win32_error( ERROR_CLASS_ALREADY_EXISTS ); release_atom( table, atom ); @@ -244,7 +243,7 @@ DECL_HANDLER(create_class) return; } - if (!(class = create_class( current->process, req->local, info.cls_extra ))) + if (!(class = create_class( current->process, local, info.cls_extra ))) { release_atom( table, atom ); release_atom( table, info.atom ); @@ -259,6 +258,7 @@ DECL_HANDLER(create_class) memcpy( (void *)shared->name, name.str, name.len ); shared->name_offset = name_offset; shared->name_len = name.len; + shared->local = local; memcpy( (void *)&shared->info, &info, sizeof(info) ); memset( (void *)shared->extra, 0, info.cls_extra ); } diff --git a/server/protocol.def b/server/protocol.def index e8fe6f1db58..3adb403e9c1 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1058,7 +1058,7 @@ typedef volatile struct data_size_t name_offset; /* offset in WCHAR of the unversioned class name, constant */ data_size_t name_len; /* len in bytes of the class name, constant */ WCHAR name[MAX_ATOM_LEN]; /* class name, constant */ - unsigned short __pad; + unsigned short local; /* class is local, constant */ struct class_info info; /* class info (GCLP_*) */ char extra[]; /* extra bytes storage */ } class_shm_t; @@ -3296,7 +3296,6 @@ enum caret_state /* Create a window class */ @REQ(create_class) - int local; /* is it a local class? */ atom_t atom; /* class atom */ unsigned int fnid; /* FNID for builtin classes, or 0 */ client_ptr_t client_ptr; /* pointer to class in client address space */ -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11123