Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45689 Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/user32/class.c | 31 +++++++++++++++++++++---------- dlls/user32/user_private.h | 2 +- dlls/user32/win.c | 2 +- 3 files changed, 23 insertions(+), 12 deletions(-)
diff --git a/dlls/user32/class.c b/dlls/user32/class.c index 07d36f05d7..5383b6771f 100644 --- a/dlls/user32/class.c +++ b/dlls/user32/class.c @@ -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, UINT *basename_offset, WCHAR *combined, BOOL register_class ) { ACTCTX_SECTION_KEYED_DATA data; struct wndclass_redirect_data @@ -335,9 +335,12 @@ const WCHAR *CLASS_GetVersionedName( const WCHAR *name, UINT *basename_offset, B const WCHAR *module, *ret; UNICODE_STRING name_us; HMODULE hmod; + UINT offset;
- if (basename_offset) - *basename_offset = 0; + if (!basename_offset) + basename_offset = &offset; + + *basename_offset = 0;
if (IS_INTRESOURCE( name )) return name; @@ -352,14 +355,21 @@ 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); + *basename_offset = wndclass->name_len / sizeof(WCHAR) - strlenW(name);
module = (const WCHAR *)((BYTE *)data.lpSectionBase + wndclass->module_offset); if (!(hmod = GetModuleHandleW( module ))) hmod = LoadLibraryW( module );
+ /* Combined name is used to register versioned class name. Base name part will match exactly + original class name and won't be reused from context data. */ ret = (const WCHAR *)((BYTE *)wndclass + wndclass->name_offset); + if (combined) + { + memcpy(combined, ret, *basename_offset * sizeof(WCHAR)); + strcpyW(&combined[*basename_offset], name); + ret = combined; + }
if (register_class && hmod) { @@ -409,7 +419,7 @@ static CLASS *CLASS_FindClass( LPCWSTR name, HINSTANCE hinstance )
if (!name) return NULL;
- name = CLASS_GetVersionedName( name, NULL, TRUE ); + name = CLASS_GetVersionedName( name, NULL, NULL, TRUE );
for (;;) { @@ -662,8 +672,8 @@ ATOM WINAPI RegisterClassW( const WNDCLASSW* wc ) */ ATOM WINAPI RegisterClassExA( const WNDCLASSEXA* wc ) { + WCHAR name[MAX_ATOM_LEN + 1], combined[MAX_ATOM_LEN + 1]; const WCHAR *classname = NULL; - WCHAR name[MAX_ATOM_LEN + 1]; ATOM atom; CLASS *classPtr; HINSTANCE instance; @@ -682,7 +692,7 @@ ATOM WINAPI RegisterClassExA( const WNDCLASSEXA* wc ) { 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 ); + classname = CLASS_GetVersionedName( name, &basename_offset, combined, FALSE ); classPtr = CLASS_RegisterClass( classname, basename_offset, instance, !(wc->style & CS_GLOBALCLASS), wc->style, wc->cbClsExtra, wc->cbWndExtra ); } @@ -720,6 +730,7 @@ ATOM WINAPI RegisterClassExA( const WNDCLASSEXA* wc ) */ ATOM WINAPI RegisterClassExW( const WNDCLASSEXW* wc ) { + WCHAR name[MAX_ATOM_LEN + 1]; const WCHAR *classname; UINT basename_offset; ATOM atom; @@ -736,7 +747,7 @@ ATOM WINAPI RegisterClassExW( const WNDCLASSEXW* wc ) } if (!(instance = wc->hInstance)) instance = GetModuleHandleW( NULL );
- classname = CLASS_GetVersionedName( wc->lpszClassName, &basename_offset, FALSE ); + classname = CLASS_GetVersionedName( wc->lpszClassName, &basename_offset, name, FALSE ); if (!(classPtr = CLASS_RegisterClass( classname, basename_offset, instance, !(wc->style & CS_GLOBALCLASS), wc->style, wc->cbClsExtra, wc->cbWndExtra ))) return 0; @@ -789,7 +800,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, NULL, NULL, 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..0ee7dbeece 100644 --- a/dlls/user32/user_private.h +++ b/dlls/user32/user_private.h @@ -273,7 +273,7 @@ extern BOOL WINPROC_call_window( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPar 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; + WCHAR *combined, BOOL register_class) DECLSPEC_HIDDEN;
/* message spy definitions */
diff --git a/dlls/user32/win.c b/dlls/user32/win.c index e7bbc4eb90..2a55ab4ce6 100644 --- a/dlls/user32/win.c +++ b/dlls/user32/win.c @@ -1349,7 +1349,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, NULL, NULL, 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),
From: Fabian Maurer dark.shadow4@web.de
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com ---
v2: fixed test failures
dlls/comctl32/tests/misc.c | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/dlls/comctl32/tests/misc.c b/dlls/comctl32/tests/misc.c index eca85d490b..85f339b1ff 100644 --- a/dlls/comctl32/tests/misc.c +++ b/dlls/comctl32/tests/misc.c @@ -345,6 +345,9 @@ static void check_class( const char *name, int must_exist, UINT style, UINT igno
if (GetClassInfoA( 0, name, &wc )) { + char buff[64]; + HWND hwnd; + todo_wine_if(strcmp(name, "Button") && strcmp(name, "ComboBox") && strcmp(name, "Edit") && @@ -356,6 +359,12 @@ todo_wine_if(strcmp(name, "Button") && ok( !(wc.style & ~style), "System class %s has extra bits %x (%08x/%08x)\n", name, wc.style & ~style, wc.style, style ); ok( !wc.hInstance, "System class %s has hInstance %p\n", name, wc.hInstance ); + + hwnd = CreateWindowA(name, 0, 0, 0, 0, 0, 0, 0, NULL, GetModuleHandleA(NULL), 0); + ok( hwnd != NULL, "Failed to create window for class %s.\n", name ); + GetClassNameA(hwnd, buff, ARRAY_SIZE(buff)); + ok( !strcmp(name, buff), "Unexpected class name %s, expected %s.\n", buff, name ); + DestroyWindow(hwnd); } else ok( !must_exist, "System class %s does not exist\n", name );