[PATCH] user32: When registering redirected class use correct base class name

Fabian Maurer dark.shadow4 at web.de
Thu Aug 23 14:36:40 CDT 2018


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(-)

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 )
-- 
2.18.0




More information about the wine-devel mailing list