[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