[PATCH] user32: When registering redirected class use correct base class name
Nikolay Sivov
nsivov at codeweavers.com
Thu Aug 23 14:59:56 CDT 2018
On 08/23/2018 10:36 PM, Fabian Maurer wrote:
> Some applications are dependent on the correct spelling of
> "ComboBox", it can't be the "Combobox" from the comctl32
> manifest.
> We have to take it from the base class instead
> of the versioned class name.
>
> Supersedes 150043
>
> Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45689
> Signed-off-by: Fabian Maurer <dark.shadow4 at web.de>
> ---
> dlls/comctl32/tests/combo.c | 15 +++++++++++++
> dlls/user32/class.c | 41 ++++++++++++++++------------------
> dlls/user32/user_private.h | 3 +--
> dlls/user32/win.c | 2 +-
> include/wine/server_protocol.h | 9 ++++----
> server/class.c | 14 +++++++-----
> server/protocol.def | 6 +++--
> server/request.h | 3 ++-
> server/trace.c | 6 +++--
> 9 files changed, 59 insertions(+), 40 deletions(-)
That looks too complicated, I don't see why server changes are
necessary. It should be enough to fix up what CLASS_GetVersionedName()
returns.
>
> diff --git a/dlls/comctl32/tests/combo.c b/dlls/comctl32/tests/combo.c
> index 923d826b30..065ce1a620 100644
> --- a/dlls/comctl32/tests/combo.c
> +++ b/dlls/comctl32/tests/combo.c
> @@ -1254,6 +1254,20 @@ static void test_combo_dropdown_size(DWORD style)
> }
> }
>
> +static void test_combo(void)
> +{
> + HWND handle_combo;
> + char classname[10];
> +
> + handle_combo = create_combobox(CBS_DROPDOWNLIST);
> +
> + GetClassNameA(handle_combo, classname, sizeof(classname));
> +
> + ok(strcmp(classname, "ComboBox") == 0, "Got wrong classname: %s\n", classname);
> +
> + DestroyWindow(handle_combo);
> +}
> +
> START_TEST(combo)
> {
> ULONG_PTR ctx_cookie;
> @@ -1281,6 +1295,7 @@ START_TEST(combo)
> }
>
> /* ComboBox control tests. */
> + test_combo();
> test_combo_WS_VSCROLL();
> test_combo_setfont(CBS_DROPDOWN);
> test_combo_setfont(CBS_DROPDOWNLIST);
> diff --git a/dlls/user32/class.c b/dlls/user32/class.c
> index 07d36f05d7..3d4105d91b 100644
> --- a/dlls/user32/class.c
> +++ b/dlls/user32/class.c
> @@ -61,7 +61,7 @@ typedef struct tagCLASS
> HBRUSH hbrBackground; /* Default background */
> ATOM atomName; /* Name of the class */
> WCHAR name[MAX_ATOM_LEN + 1];
> - WCHAR *basename; /* Base name for redirected classes, pointer within 'name'. */
> + WCHAR basename[MAX_ATOM_LEN + 1]; /* Base name for redirected classes */
> } CLASS;
>
> static struct list class_list = LIST_INIT( class_list );
> @@ -320,7 +320,7 @@ static void CLASS_FreeClass( CLASS *classPtr )
> USER_Unlock();
> }
>
> -const WCHAR *CLASS_GetVersionedName( const WCHAR *name, UINT *basename_offset, BOOL register_class )
> +const WCHAR *CLASS_GetVersionedName( const WCHAR *name, BOOL register_class )
> {
> ACTCTX_SECTION_KEYED_DATA data;
> struct wndclass_redirect_data
> @@ -336,9 +336,6 @@ const WCHAR *CLASS_GetVersionedName( const WCHAR *name, UINT *basename_offset, B
> UNICODE_STRING name_us;
> HMODULE hmod;
>
> - if (basename_offset)
> - *basename_offset = 0;
> -
> if (IS_INTRESOURCE( name ))
> return name;
>
> @@ -352,8 +349,6 @@ const WCHAR *CLASS_GetVersionedName( const WCHAR *name, UINT *basename_offset, B
> return name;
>
> wndclass = (struct wndclass_redirect_data *)data.lpData;
> - if (basename_offset)
> - *basename_offset = wndclass->name_len / sizeof(WCHAR) - strlenW(name);
>
> module = (const WCHAR *)((BYTE *)data.lpSectionBase + wndclass->module_offset);
> if (!(hmod = GetModuleHandleW( module )))
> @@ -409,7 +404,7 @@ static CLASS *CLASS_FindClass( LPCWSTR name, HINSTANCE hinstance )
>
> if (!name) return NULL;
>
> - name = CLASS_GetVersionedName( name, NULL, TRUE );
> + name = CLASS_GetVersionedName( name, TRUE );
>
> for (;;)
> {
> @@ -450,11 +445,12 @@ static CLASS *CLASS_FindClass( LPCWSTR name, HINSTANCE hinstance )
> *
> * The real RegisterClass() functionality.
> */
> -static CLASS *CLASS_RegisterClass( LPCWSTR name, UINT basename_offset, HINSTANCE hInstance, BOOL local,
> +static CLASS *CLASS_RegisterClass( LPCWSTR name, LPCWSTR basename, HINSTANCE hInstance, BOOL local,
> DWORD style, INT classExtra, INT winExtra )
> {
> CLASS *classPtr;
> BOOL ret;
> + int name_len = 0, basename_len = 0;
>
> TRACE("name=%s hinst=%p style=0x%x clExtr=0x%x winExtr=0x%x\n",
> debugstr_w(name), hInstance, style, classExtra, winExtra );
> @@ -470,11 +466,12 @@ static CLASS *CLASS_RegisterClass( LPCWSTR name, UINT basename_offset, HINSTANCE
> if (!classPtr) return NULL;
>
> classPtr->atomName = get_int_atom_value( name );
> - classPtr->basename = classPtr->name;
> if (!classPtr->atomName && name)
> {
> strcpyW( classPtr->name, name );
> - classPtr->basename += basename_offset;
> + name_len = strlenW(name) * sizeof(WCHAR);
> + strcpyW( classPtr->basename, basename );
> + basename_len = strlenW(basename) * sizeof(WCHAR);
> }
> else GlobalGetAtomNameW( classPtr->atomName, classPtr->name, ARRAY_SIZE( classPtr->name ));
>
> @@ -487,8 +484,10 @@ static CLASS *CLASS_RegisterClass( LPCWSTR name, UINT basename_offset, HINSTANCE
> req->win_extra = winExtra;
> req->client_ptr = wine_server_client_ptr( classPtr );
> req->atom = classPtr->atomName;
> - req->name_offset = basename_offset;
> - if (!req->atom && name) wine_server_add_data( req, name, strlenW(name) * sizeof(WCHAR) );
> + req->name_len = name_len;
> + req->basename_len = basename_len;
> + if (name_len) wine_server_add_data( req, name, name_len);
> + if (basename_len) wine_server_add_data( req, basename, basename_len);
> ret = !wine_server_call_err( req );
> classPtr->atomName = reply->atom;
> }
> @@ -524,7 +523,7 @@ static void register_builtin( const struct builtin_class_descr *descr )
> {
> CLASS *classPtr;
>
> - if (!(classPtr = CLASS_RegisterClass( descr->name, 0, user32_module, FALSE,
> + if (!(classPtr = CLASS_RegisterClass( descr->name, descr->name, user32_module, FALSE,
> descr->style, 0, descr->extra ))) return;
>
> if (descr->cursor) classPtr->hCursor = LoadCursorA( 0, (LPSTR)descr->cursor );
> @@ -680,15 +679,14 @@ ATOM WINAPI RegisterClassExA( const WNDCLASSEXA* wc )
>
> if (!IS_INTRESOURCE(wc->lpszClassName))
> {
> - UINT basename_offset;
> if (!MultiByteToWideChar( CP_ACP, 0, wc->lpszClassName, -1, name, MAX_ATOM_LEN + 1 )) return 0;
> - classname = CLASS_GetVersionedName( name, &basename_offset, FALSE );
> - classPtr = CLASS_RegisterClass( classname, basename_offset, instance, !(wc->style & CS_GLOBALCLASS),
> + classname = CLASS_GetVersionedName( name, FALSE );
> + classPtr = CLASS_RegisterClass( classname, name, instance, !(wc->style & CS_GLOBALCLASS),
> wc->style, wc->cbClsExtra, wc->cbWndExtra );
> }
> else
> {
> - classPtr = CLASS_RegisterClass( (LPCWSTR)wc->lpszClassName, 0, instance,
> + classPtr = CLASS_RegisterClass( (LPCWSTR)wc->lpszClassName, (LPCWSTR)wc->lpszClassName, instance,
> !(wc->style & CS_GLOBALCLASS), wc->style,
> wc->cbClsExtra, wc->cbWndExtra );
> }
> @@ -721,7 +719,6 @@ ATOM WINAPI RegisterClassExA( const WNDCLASSEXA* wc )
> ATOM WINAPI RegisterClassExW( const WNDCLASSEXW* wc )
> {
> const WCHAR *classname;
> - UINT basename_offset;
> ATOM atom;
> CLASS *classPtr;
> HINSTANCE instance;
> @@ -736,8 +733,8 @@ ATOM WINAPI RegisterClassExW( const WNDCLASSEXW* wc )
> }
> if (!(instance = wc->hInstance)) instance = GetModuleHandleW( NULL );
>
> - classname = CLASS_GetVersionedName( wc->lpszClassName, &basename_offset, FALSE );
> - if (!(classPtr = CLASS_RegisterClass( classname, basename_offset, instance, !(wc->style & CS_GLOBALCLASS),
> + classname = CLASS_GetVersionedName( wc->lpszClassName, FALSE );
> + if (!(classPtr = CLASS_RegisterClass( classname, wc->lpszClassName, instance, !(wc->style & CS_GLOBALCLASS),
> wc->style, wc->cbClsExtra, wc->cbWndExtra )))
> return 0;
>
> @@ -789,7 +786,7 @@ BOOL WINAPI UnregisterClassW( LPCWSTR className, HINSTANCE hInstance )
>
> GetDesktopWindow(); /* create the desktop window to trigger builtin class registration */
>
> - className = CLASS_GetVersionedName( className, NULL, FALSE );
> + className = CLASS_GetVersionedName( className, FALSE );
> SERVER_START_REQ( destroy_class )
> {
> req->instance = wine_server_client_ptr( hInstance );
> diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h
> index 73a2badc7d..8051f15d30 100644
> --- a/dlls/user32/user_private.h
> +++ b/dlls/user32/user_private.h
> @@ -272,8 +272,7 @@ extern INT_PTR WINPROC_CallDlgProcW( DLGPROC func, HWND hwnd, UINT msg, WPARAM w
> extern BOOL WINPROC_call_window( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam,
> LRESULT *result, BOOL unicode, enum wm_char_mapping mapping ) DECLSPEC_HIDDEN;
>
> -extern const WCHAR *CLASS_GetVersionedName(const WCHAR *classname, UINT *basename_offset,
> - BOOL register_class) DECLSPEC_HIDDEN;
> +extern const WCHAR *CLASS_GetVersionedName(const WCHAR *classname, BOOL register_class) DECLSPEC_HIDDEN;
>
> /* message spy definitions */
>
> diff --git a/dlls/user32/win.c b/dlls/user32/win.c
> index cbfd8bb14a..48cf947b36 100644
> --- a/dlls/user32/win.c
> +++ b/dlls/user32/win.c
> @@ -1323,7 +1323,7 @@ HWND WIN_CreateWindowEx( CREATESTRUCTW *cs, LPCWSTR className, HINSTANCE module,
> CBT_CREATEWNDW cbtc;
> CREATESTRUCTW cbcs;
>
> - className = CLASS_GetVersionedName(className, NULL, TRUE);
> + className = CLASS_GetVersionedName(className, TRUE);
>
> TRACE("%s %s%s%s ex=%08x style=%08x %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
> unicode ? debugstr_w(cs->lpszName) : debugstr_a((LPCSTR)cs->lpszName),
> diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
> index c636bacb35..4f29006036 100644
> --- a/include/wine/server_protocol.h
> +++ b/include/wine/server_protocol.h
> @@ -4496,9 +4496,10 @@ struct create_class_request
> int extra;
> int win_extra;
> client_ptr_t client_ptr;
> - data_size_t name_offset;
> - /* VARARG(name,unicode_str); */
> - char __pad_52[4];
> + data_size_t name_len;
> + data_size_t basename_len;
> + /* VARARG(name,unicode_str,name_len); */
> + /* VARARG(name,unicode_str,basename_len); */
> };
> struct create_class_reply
> {
> @@ -6533,6 +6534,6 @@ union generic_reply
> struct terminate_job_reply terminate_job_reply;
> };
>
> -#define SERVER_PROTOCOL_VERSION 556
> +#define SERVER_PROTOCOL_VERSION 557
>
> #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
> diff --git a/server/class.c b/server/class.c
> index 6a7de7843e..da6191d6aa 100644
> --- a/server/class.c
> +++ b/server/class.c
> @@ -151,19 +151,21 @@ client_ptr_t get_class_client_ptr( struct window_class *class )
> DECL_HANDLER(create_class)
> {
> struct window_class *class;
> - struct unicode_str name = get_req_unicode_str();
> + struct unicode_str name, basename;
> atom_t atom, base_atom;
>
> + name.len = req->name_len;
> + name.str = get_req_data();
> + basename.len = req->basename_len;
> + basename.str = (WCHAR *)((char *)get_req_data() + req->name_len);
> +
> if (name.len)
> {
> atom = add_global_atom( NULL, &name );
> if (!atom) return;
> - if (req->name_offset && req->name_offset < name.len / sizeof(WCHAR))
> + if (basename.len)
> {
> - name.str += req->name_offset;
> - name.len -= req->name_offset * sizeof(WCHAR);
> -
> - base_atom = add_global_atom( NULL, &name );
> + base_atom = add_global_atom( NULL, &basename );
> if (!base_atom)
> {
> release_global_atom( NULL, atom );
> diff --git a/server/protocol.def b/server/protocol.def
> index c8bb3b1100..c55f888a6d 100644
> --- a/server/protocol.def
> +++ b/server/protocol.def
> @@ -3159,8 +3159,10 @@ enum caret_state
> int extra; /* number of extra class bytes */
> int win_extra; /* number of window extra bytes */
> client_ptr_t client_ptr; /* pointer to class in client address space */
> - data_size_t name_offset; /* base class name offset for specified atom */
> - VARARG(name,unicode_str); /* class name */
> + data_size_t name_len; /* class name length */
> + data_size_t basename_len; /* base class name length */
> + VARARG(name,unicode_str,name_len); /* class name */
> + VARARG(name,unicode_str,basename_len); /* base class name */
> @REPLY
> atom_t atom; /* resulting class atom */
> @END
> diff --git a/server/request.h b/server/request.h
> index d3028f0b1d..56562be81c 100644
> --- a/server/request.h
> +++ b/server/request.h
> @@ -2044,7 +2044,8 @@ C_ASSERT( FIELD_OFFSET(struct create_class_request, instance) == 24 );
> C_ASSERT( FIELD_OFFSET(struct create_class_request, extra) == 32 );
> C_ASSERT( FIELD_OFFSET(struct create_class_request, win_extra) == 36 );
> C_ASSERT( FIELD_OFFSET(struct create_class_request, client_ptr) == 40 );
> -C_ASSERT( FIELD_OFFSET(struct create_class_request, name_offset) == 48 );
> +C_ASSERT( FIELD_OFFSET(struct create_class_request, name_len) == 48 );
> +C_ASSERT( FIELD_OFFSET(struct create_class_request, basename_len) == 52 );
> C_ASSERT( sizeof(struct create_class_request) == 56 );
> C_ASSERT( FIELD_OFFSET(struct create_class_reply, atom) == 8 );
> C_ASSERT( sizeof(struct create_class_reply) == 16 );
> diff --git a/server/trace.c b/server/trace.c
> index 68e47d49b8..966022aaac 100644
> --- a/server/trace.c
> +++ b/server/trace.c
> @@ -3770,8 +3770,10 @@ static void dump_create_class_request( const struct create_class_request *req )
> fprintf( stderr, ", extra=%d", req->extra );
> fprintf( stderr, ", win_extra=%d", req->win_extra );
> dump_uint64( ", client_ptr=", &req->client_ptr );
> - fprintf( stderr, ", name_offset=%u", req->name_offset );
> - dump_varargs_unicode_str( ", name=", cur_size );
> + fprintf( stderr, ", name_len=%u", req->name_len );
> + fprintf( stderr, ", basename_len=%u", req->basename_len );
> + dump_varargs_unicode_str( ", name=", min(cur_size,req->name_len) );
> + dump_varargs_unicode_str( ", name=", min(cur_size,req->basename_len) );
> }
>
> static void dump_create_class_reply( const struct create_class_reply *req )
More information about the wine-devel
mailing list