From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/win32u/class.c | 36 ++++++++++++++----------- server/class.c | 66 +++++++++++++++++++++++---------------------- server/protocol.def | 12 +++++---- server/trace.c | 11 ++++++++ tools/make_requests | 1 + 5 files changed, 73 insertions(+), 53 deletions(-) diff --git a/dlls/win32u/class.c b/dlls/win32u/class.c index 5140430c558..c0ed05834cb 100644 --- a/dlls/win32u/class.c +++ b/dlls/win32u/class.c @@ -452,7 +452,7 @@ static UINT_PTR get_class_instance( CLASS *class ) NTSTATUS status; while ((status = get_shared_class( class, &lock, &class_shm )) == STATUS_PENDING) - instance = class_shm->instance; + instance = class_shm->info.instance; if (status) return 0; return instance; } @@ -552,11 +552,15 @@ ATOM WINAPI NtUserRegisterClassExWOW( const WNDCLASSEXW *wc, UNICODE_STRING *nam user_lock(); SERVER_START_REQ( create_class ) { + struct class_info info = + { + .style = wc->style, + .instance = wine_server_client_ptr( instance ), + .cls_extra = wc->cbClsExtra, + .win_extra = wc->cbWndExtra, + }; + wine_server_add_data( req, &info, sizeof(info) ); req->local = class->local; - req->style = wc->style; - req->instance = wine_server_client_ptr( instance ); - req->cls_extra = wc->cbClsExtra; - req->win_extra = wc->cbWndExtra; req->client_ptr = wine_server_client_ptr( class ); req->atom = wine_server_add_atom( req, name ); req->name_offset = version->Length / sizeof(WCHAR); @@ -669,10 +673,10 @@ ATOM WINAPI NtUserGetClassInfoEx( HINSTANCE instance, UNICODE_STRING *name, WNDC { if (wc) { - wc->style = class_shm->style; + wc->style = class_shm->info.style; wc->lpfnWndProc = get_winproc( class->winproc, ansi ); - wc->cbClsExtra = class_shm->cls_extra; - wc->cbWndExtra = class_shm->win_extra; + wc->cbClsExtra = class_shm->info.cls_extra; + wc->cbWndExtra = class_shm->info.win_extra; wc->hInstance = (instance == user32_module) ? 0 : instance; wc->hIcon = class->hIcon; wc->hIconSm = class->hIconSm; @@ -681,9 +685,9 @@ ATOM WINAPI NtUserGetClassInfoEx( HINSTANCE instance, UNICODE_STRING *name, WNDC wc->lpszMenuName = (WCHAR *)class->menu_name; wc->lpszClassName = name->Buffer; } - atom = class_shm->atom; + atom = class_shm->info.atom; } - if (!wc->hIconSm) wc->hIconSm = class->icon_internal; + if (wc && !wc->hIconSm) wc->hIconSm = class->icon_internal; *menu_name = class->menu_name; release_class_ptr( class ); return status ? 0 : atom; @@ -918,13 +922,13 @@ static ULONG_PTR get_class_long_shm( HWND hwnd, INT offset, UINT size, BOOL ansi { switch (offset) { - case GCW_ATOM: ret = class_shm->atom; break; - case GCL_STYLE: ret = class_shm->style; break; - case GCL_CBCLSEXTRA: ret = class_shm->cls_extra; break; - case GCL_CBWNDEXTRA: ret = class_shm->win_extra; break; - case GCLP_HMODULE: ret = class_shm->instance; break; + case GCW_ATOM: ret = class_shm->info.atom; break; + case GCL_STYLE: ret = class_shm->info.style; break; + case GCL_CBCLSEXTRA: ret = class_shm->info.cls_extra; break; + case GCL_CBWNDEXTRA: ret = class_shm->info.win_extra; break; + case GCLP_HMODULE: ret = class_shm->info.instance; break; default: - valid = offset >= 0 && offset <= (INT)(class_shm->cls_extra - size); + valid = offset >= 0 && offset <= (INT)(class_shm->info.cls_extra - size); if (valid) memcpy( &ret, (char *)class_shm->extra + offset, size ); break; } diff --git a/server/class.c b/server/class.c index a71ee0a332a..a35b2904d76 100644 --- a/server/class.c +++ b/server/class.c @@ -81,7 +81,7 @@ static void destroy_class( struct window_class *class ) struct atom_table *table = get_user_atom_table(); release_atom( table, class->atom ); - release_atom( table, class->shared->atom ); + release_atom( table, class->shared->info.atom ); list_remove( &class->entry ); release_object( class->process ); if (class->shared) free_shared_object( class->shared ); @@ -108,9 +108,9 @@ 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->instance >> 16); - if (!instance || !class->local || shared->instance == instance || - (!is_win16 && ((shared->instance & ~0xffff) == (instance & ~0xffff)))) return class; + is_win16 = !(shared->info.instance >> 16); + if (!instance || !class->local || shared->info.instance == instance || + (!is_win16 && ((shared->info.instance & ~0xffff) == (instance & ~0xffff)))) return class; } return NULL; } @@ -122,7 +122,7 @@ struct window_class *grab_class( struct process *process, atom_t atom, mod_handl if (class) { class->count++; - *extra_bytes = class->shared->win_extra; + *extra_bytes = class->shared->info.win_extra; *locator = get_shared_object_locator( class->shared ); } else set_error( STATUS_INVALID_HANDLE ); @@ -137,7 +137,7 @@ void release_class( struct window_class *class ) int is_desktop_class( struct window_class *class ) { - return (class->shared->atom == DESKTOP_ATOM && !class->local); + return (class->shared->info.atom == DESKTOP_ATOM && !class->local); } int is_message_class( struct window_class *class ) @@ -146,17 +146,17 @@ int is_message_class( struct window_class *class ) static const struct unicode_str name = { messageW, sizeof(messageW) }; struct atom_table *table = get_user_atom_table(); - return (!class->local && class->shared->atom == find_atom( table, &name )); + return (!class->local && class->shared->info.atom == find_atom( table, &name )); } int get_class_style( struct window_class *class ) { - return class->shared->style; + return class->shared->info.style; } atom_t get_class_atom( struct window_class *class ) { - return class->shared->atom; + return class->shared->info.atom; } client_ptr_t get_class_client_ptr( struct window_class *class ) @@ -181,10 +181,16 @@ DECL_HANDLER(create_class) struct window_class *class; struct unicode_str name = get_req_unicode_str(); struct atom_table *table = get_user_atom_table(); - atom_t atom = req->atom, base_atom; unsigned int name_offset = 0; + atom_t atom = req->atom; + struct class_info info; WCHAR buffer[16]; + if (name.len < sizeof(info)) return set_error( STATUS_INVALID_PARAMETER ); + memcpy( &info, name.str, sizeof(info) ); + name.str += sizeof(info) / sizeof(WCHAR); + name.len -= sizeof(info); + if (atom && !name.len) name = integral_atom_name( buffer, atom ); if (!atom && !(atom = add_atom( table, &name ))) return; @@ -196,7 +202,7 @@ DECL_HANDLER(create_class) base.str += name_offset; base.len -= name_offset * sizeof(WCHAR); - if (!(base_atom = add_atom( table, &base ))) + if (!(info.atom = add_atom( table, &base ))) { release_atom( table, atom ); return; @@ -204,30 +210,30 @@ DECL_HANDLER(create_class) } else { - base_atom = grab_atom( table, atom ); + info.atom = grab_atom( table, atom ); } - class = find_class( current->process, atom, req->instance ); + class = find_class( current->process, atom, info.instance ); if (class && !class->local == !req->local) { set_win32_error( ERROR_CLASS_ALREADY_EXISTS ); release_atom( table, atom ); - release_atom( table, base_atom ); + release_atom( table, info.atom ); return; } - if (req->cls_extra < 0 || req->cls_extra > 4096 || req->win_extra < 0 || req->win_extra > 4096) + if (info.cls_extra > 4096 || info.win_extra > 4096) { /* don't allow stupid values here */ set_error( STATUS_INVALID_PARAMETER ); release_atom( table, atom ); - release_atom( table, base_atom ); + release_atom( table, info.atom ); return; } - if (!(class = create_class( current->process, req->local, req->cls_extra ))) + if (!(class = create_class( current->process, req->local, info.cls_extra ))) { release_atom( table, atom ); - release_atom( table, base_atom ); + release_atom( table, info.atom ); return; } class->atom = atom; @@ -238,17 +244,13 @@ DECL_HANDLER(create_class) memcpy( (void *)shared->name, name.str, name.len ); shared->name_offset = name_offset; shared->name_len = name.len; - shared->atom = base_atom; - shared->instance = req->instance; - shared->style = req->style; - shared->win_extra = req->win_extra; - shared->cls_extra = req->cls_extra; - memset( (void *)shared->extra, 0, req->cls_extra ); + memcpy( (void *)&shared->info, &info, sizeof(info) ); + memset( (void *)shared->extra, 0, info.cls_extra ); } SHARED_WRITE_END; reply->locator = get_shared_object_locator( class->shared ); - reply->atom = base_atom; + reply->atom = info.atom; } /* destroy a window class */ @@ -291,8 +293,8 @@ DECL_HANDLER(set_class_info) switch (req->offset) { case GCL_STYLE: - reply->old_info = shared->style; - shared->style = req->new_info; + reply->old_info = shared->info.style; + shared->info.style = req->new_info; break; case GCL_CBWNDEXTRA: if (req->new_info > 4096) @@ -300,19 +302,19 @@ DECL_HANDLER(set_class_info) set_error( STATUS_INVALID_PARAMETER ); return; } - reply->old_info = shared->win_extra; - shared->win_extra = req->new_info; + reply->old_info = shared->info.win_extra; + shared->info.win_extra = req->new_info; break; case GCL_CBCLSEXTRA: set_win32_error( ERROR_INVALID_INDEX ); break; case GCLP_HMODULE: - reply->old_info = shared->instance; - shared->instance = req->new_info; + reply->old_info = shared->info.instance; + shared->info.instance = req->new_info; break; default: if (req->size > sizeof(req->new_info) || req->offset < 0 || - req->offset > class->shared->cls_extra - (int)req->size) + req->offset > class->shared->info.cls_extra - (int)req->size) { set_win32_error( ERROR_INVALID_INDEX ); return; diff --git a/server/protocol.def b/server/protocol.def index 3ee3be605d4..ad14f20ba47 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1038,17 +1038,22 @@ typedef volatile struct unsigned __int64 keystate_serial; /* keystate update counter at last sync */ } input_shm_t; -typedef volatile struct +struct class_info { atom_t atom; /* class atom */ unsigned int style; /* class style */ unsigned int cls_extra; /* number of class extra bytes */ unsigned int win_extra; /* number of window extra bytes */ mod_handle_t instance; /* module instance */ +}; + +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; + struct class_info info; /* class info (GCLP_*) */ char extra[]; /* extra bytes storage */ } class_shm_t; @@ -3268,12 +3273,9 @@ enum caret_state @REQ(create_class) int local; /* is it a local class? */ atom_t atom; /* class atom */ - unsigned int style; /* class style */ - mod_handle_t instance; /* module instance */ client_ptr_t client_ptr; /* pointer to class in client address space */ - short int cls_extra; /* number of extra class bytes */ - short int win_extra; /* number of window extra bytes */ data_size_t name_offset; /* base class name offset for specified atom */ + VARARG(info,class_info); /* class info */ VARARG(name,unicode_str); /* class name */ @REPLY struct obj_locator locator; /* locator for the shared class object */ diff --git a/server/trace.c b/server/trace.c index c9812d818bd..9ed682156b1 100644 --- a/server/trace.c +++ b/server/trace.c @@ -1654,6 +1654,17 @@ static void dump_varargs_monitor_infos( const char *prefix, data_size_t size ) remove_data( size ); } +static void dump_varargs_class_info( const char *prefix, data_size_t size ) +{ + const struct class_info *info = cur_data; + + fprintf( stderr, "%s{atom=%#x,style=%#x,cls_extra=%u,win_extra=%u", + prefix, info->atom, info->style, info->cls_extra, info->win_extra ); + dump_uint64( ",instance=", &info->instance ); + fputc( '}', stderr ); + remove_data( sizeof(*info) ); +} + void trace_request(void) { enum request req = current->req.request_header.req; diff --git a/tools/make_requests b/tools/make_requests index 17e425537b5..b4849e5f605 100755 --- a/tools/make_requests +++ b/tools/make_requests @@ -68,6 +68,7 @@ my %formats = "struct thread_info" => [ 40, 8 ], "union udp_endpoint" => [ 32, 4 ], "struct user_apc" => [ 40, 8 ], + "struct class_info" => [ 24, 8 ], ); my $file_header = -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10959