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 c7a3b06c3a..7ba0b4c312 100644 --- a/dlls/user32/win.c +++ b/dlls/user32/win.c @@ -1344,7 +1344,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 ---
Extended to cover more redirected classes.
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..8a30ac575e 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, WS_VISIBLE, 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 );
Nikolay Sivov nsivov@codeweavers.com writes:
From: Fabian Maurer dark.shadow4@web.de
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com
Extended to cover more redirected classes.
dlls/comctl32/tests/misc.c | 9 +++++++++ 1 file changed, 9 insertions(+)
This fails here:
../../../tools/runtest -q -P wine -T ../../.. -M comctl32.dll -p comctl32_test.exe.so misc && touch misc.ok misc.c:364: Test failed: Failed to create window for class ComboBox. misc.c:366: Test failed: Unexpected class name Button, expected ComboBox. make: *** [Makefile:590: misc.ok] Error 2
On 08/24/2018 09:17 PM, Alexandre Julliard wrote:
Nikolay Sivov nsivov@codeweavers.com writes:
From: Fabian Maurer dark.shadow4@web.de
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com
Extended to cover more redirected classes.
dlls/comctl32/tests/misc.c | 9 +++++++++ 1 file changed, 9 insertions(+)
This fails here:
../../../tools/runtest -q -P wine -T ../../.. -M comctl32.dll -p comctl32_test.exe.so misc && touch misc.ok misc.c:364: Test failed: Failed to create window for class ComboBox. misc.c:366: Test failed: Unexpected class name Button, expected ComboBox. make: *** [Makefile:590: misc.ok] Error 2
Sorry about that, was almost sure I ran the test. Apparently you can't create WS_VISIBLE ComboBox without a parent window in Wine, and it works on Windows.
For consistency, wouldn't it be easier to always give a buffer and make it fill that with the versioned classname? Then we'd have the exact same versioned classname used everywhere, and could get rid of that NULL magic.
Regards, Fabian Maurer
On 08/24/2018 09:39 PM, Fabian Maurer wrote:
For consistency, wouldn't it be easier to always give a buffer and make it fill that with the versioned classname? Then we'd have the exact same versioned classname used everywhere, and could get rid of that NULL magic.
I want to avoid extra copy when it's not needed.
Regards,
Fabian Maurer
I want to avoid extra copy when it's not needed.
Is it only about the copy, or do you think it's cleaner? Because I don't think it should be a performance concern.
Regards,
Fabian Maurer