Always copying client class name to temporary buffer, to which version string also points to, in order to convert integral class names to string and unify the logic for versioning later on.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/user32/class.c | 71 ++++++++++++++++++++++----------------------- 1 file changed, 34 insertions(+), 37 deletions(-)
diff --git a/dlls/user32/class.c b/dlls/user32/class.c index 9c7bd3a5c6b..8c8be33dc46 100644 --- a/dlls/user32/class.c +++ b/dlls/user32/class.c @@ -194,7 +194,7 @@ static ULONG_PTR set_menu_nameA( HWND hwnd, INT offset, ULONG_PTR newval ) return 0; }
-static void get_versioned_name( const WCHAR *name, UNICODE_STRING *ret, UNICODE_STRING *version, HMODULE *reg_module ) +static void get_class_version( UNICODE_STRING *name, UNICODE_STRING *version, HMODULE *reg_module ) { ACTCTX_SECTION_KEYED_DATA data; struct wndclass_redirect_data @@ -207,30 +207,19 @@ static void get_versioned_name( const WCHAR *name, UNICODE_STRING *ret, UNICODE_ ULONG module_offset; } *wndclass; const WCHAR *module, *ptr; - UNICODE_STRING name_us; HMODULE hmod; UINT offset = 0;
if (reg_module) *reg_module = 0; if (version) version->Length = 0;
- if (IS_INTRESOURCE( name ) || is_comctl32_class( name ) || is_builtin_class( name )) - { - init_class_name( ret, name ); - return; - } + if (IS_INTRESOURCE( name->Buffer ) || is_comctl32_class( name->Buffer ) || is_builtin_class( name->Buffer )) return;
data.cbSize = sizeof(data); - RtlInitUnicodeString(&name_us, name); - if (RtlFindActivationContextSectionString( 0, NULL, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION, - &name_us, &data )) - { - init_class_name( ret, name ); - return; - } + if (RtlFindActivationContextSectionString( 0, NULL, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION, name, &data )) return;
wndclass = (struct wndclass_redirect_data *)data.lpData; - offset = wndclass->name_len / sizeof(WCHAR) - lstrlenW(name); + offset = (wndclass->name_len - name->Length) / sizeof(WCHAR);
module = (const WCHAR *)((BYTE *)data.lpSectionBase + wndclass->module_offset); if (!(hmod = GetModuleHandleW( module ))) @@ -243,13 +232,13 @@ static void get_versioned_name( const WCHAR *name, UNICODE_STRING *ret, UNICODE_ { WCHAR *combined = version->Buffer; memcpy( combined, ptr, offset * sizeof(WCHAR) ); - lstrcpyW( &combined[offset], name ); + lstrcpyW( &combined[offset], name->Buffer ); version->Length = offset * sizeof(WCHAR); ptr = combined; }
if (reg_module) *reg_module = hmod; - init_class_name( ret, ptr ); + init_class_name( name, ptr ); }
@@ -348,16 +337,13 @@ ATOM WINAPI RegisterClassExA( const WNDCLASSEXA* wc )
version.Buffer = combined; version.MaximumLength = sizeof(combined); - if (!IS_INTRESOURCE(wc->lpszClassName)) - { - if (!MultiByteToWideChar( CP_ACP, 0, wc->lpszClassName, -1, nameW, MAX_ATOM_LEN + 1 )) return 0; - get_versioned_name( nameW, &name, &version, FALSE ); - } + if (IS_INTRESOURCE( wc->lpszClassName )) init_class_name( &name, (const WCHAR *)wc->lpszClassName ); else { - init_class_name( &name, (const WCHAR *)wc->lpszClassName ); - version.Length = 0; + if (!MultiByteToWideChar( CP_ACP, 0, wc->lpszClassName, -1, nameW, MAX_ATOM_LEN + 1 )) return 0; + RtlInitUnicodeString( &name, nameW ); } + get_class_version( &name, &version, NULL );
if (!alloc_menu_nameA( &menu_name, wc->lpszMenuName )) return 0;
@@ -379,7 +365,8 @@ ATOM WINAPI RegisterClassExW( const WNDCLASSEXW* wc )
version.Buffer = combined; version.MaximumLength = sizeof(combined); - get_versioned_name( wc->lpszClassName, &name, &version, FALSE ); + init_class_name( &name, wc->lpszClassName ); + get_class_version( &name, &version, NULL );
if (!alloc_menu_nameW( &menu_name, wc->lpszMenuName )) return 0;
@@ -392,30 +379,39 @@ ATOM WINAPI RegisterClassExW( const WNDCLASSEXW* wc ) /*********************************************************************** * UnregisterClassA (USER32.@) */ -BOOL WINAPI UnregisterClassA( LPCSTR className, HINSTANCE hInstance ) +BOOL WINAPI UnregisterClassA( LPCSTR class_name, HINSTANCE instance ) { - if (!IS_INTRESOURCE(className)) - { - WCHAR name[MAX_ATOM_LEN + 1]; + struct client_menu_name menu_name; + WCHAR nameW[MAX_ATOM_LEN + 1]; + UNICODE_STRING name; + BOOL ret;
- if (!MultiByteToWideChar( CP_ACP, 0, className, -1, name, MAX_ATOM_LEN + 1 )) - return FALSE; - return UnregisterClassW( name, hInstance ); + if (IS_INTRESOURCE( class_name )) init_class_name( &name, (const WCHAR *)class_name ); + else + { + if (!MultiByteToWideChar( CP_ACP, 0, class_name, -1, nameW, MAX_ATOM_LEN + 1 )) return 0; + RtlInitUnicodeString( &name, nameW ); } - return UnregisterClassW( (LPCWSTR)className, hInstance ); + get_class_version( &name, NULL, NULL ); + + ret = NtUserUnregisterClass( &name, instance, &menu_name ); + if (ret) free_menu_name( &menu_name ); + return ret; }
/*********************************************************************** * UnregisterClassW (USER32.@) */ -BOOL WINAPI UnregisterClassW( LPCWSTR className, HINSTANCE hInstance ) +BOOL WINAPI UnregisterClassW( LPCWSTR class_name, HINSTANCE instance ) { struct client_menu_name menu_name; UNICODE_STRING name; BOOL ret;
- get_versioned_name( className, &name, NULL, FALSE ); - ret = NtUserUnregisterClass( &name, hInstance, &menu_name ); + init_class_name( &name, class_name ); + get_class_version( &name, NULL, NULL ); + + ret = NtUserUnregisterClass( &name, instance, &menu_name ); if (ret) free_menu_name( &menu_name ); return ret; } @@ -569,7 +565,8 @@ ATOM get_class_info( HINSTANCE instance, const WCHAR *class_name, WNDCLASSEXW *i HMODULE module; ATOM atom;
- get_versioned_name( class_name, &name, NULL, &module ); + init_class_name( &name, class_name ); + get_class_version( &name, NULL, &module );
if (!name_str && !instance) instance = user32_module;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/user32/class.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/dlls/user32/class.c b/dlls/user32/class.c index 8c8be33dc46..bd43618a4b9 100644 --- a/dlls/user32/class.c +++ b/dlls/user32/class.c @@ -568,8 +568,6 @@ ATOM get_class_info( HINSTANCE instance, const WCHAR *class_name, WNDCLASSEXW *i init_class_name( &name, class_name ); get_class_version( &name, NULL, &module );
- if (!name_str && !instance) instance = user32_module; - while (!(atom = NtUserGetClassInfoEx( instance, &name, info, NULL, ansi ))) { if (module) @@ -605,11 +603,11 @@ ATOM get_class_info( HINSTANCE instance, const WCHAR *class_name, WNDCLASSEXW *i /*********************************************************************** * GetClassInfoExA (USER32.@) */ -BOOL WINAPI GetClassInfoExA( HINSTANCE hInstance, LPCSTR name, WNDCLASSEXA *wc ) +BOOL WINAPI GetClassInfoExA( HINSTANCE instance, const char *class_name, WNDCLASSEXA *wc ) { ATOM atom;
- TRACE("%p %s %p\n", hInstance, debugstr_a(name), wc); + TRACE( "%p %s %p\n", instance, debugstr_a(class_name), wc );
if (!wc) { @@ -617,15 +615,16 @@ BOOL WINAPI GetClassInfoExA( HINSTANCE hInstance, LPCSTR name, WNDCLASSEXA *wc ) return FALSE; }
- if (!IS_INTRESOURCE(name)) + if (!instance) instance = user32_module; + if (!IS_INTRESOURCE(class_name)) { WCHAR nameW[MAX_ATOM_LEN + 1]; - if (!MultiByteToWideChar( CP_ACP, 0, name, -1, nameW, ARRAY_SIZE( nameW ))) + if (!MultiByteToWideChar( CP_ACP, 0, class_name, -1, nameW, ARRAY_SIZE( nameW ))) return FALSE; - atom = get_class_info( hInstance, nameW, (WNDCLASSEXW *)wc, NULL, TRUE ); + atom = get_class_info( instance, nameW, (WNDCLASSEXW *)wc, NULL, TRUE ); } - else atom = get_class_info( hInstance, (const WCHAR *)name, (WNDCLASSEXW *)wc, NULL, TRUE ); - if (atom) wc->lpszClassName = name; + else atom = get_class_info( instance, (const WCHAR *)class_name, (WNDCLASSEXW *)wc, NULL, TRUE ); + if (atom) wc->lpszClassName = class_name;
/* We must return the atom of the class here instead of just TRUE. */ return atom; @@ -635,11 +634,11 @@ BOOL WINAPI GetClassInfoExA( HINSTANCE hInstance, LPCSTR name, WNDCLASSEXA *wc ) /*********************************************************************** * GetClassInfoExW (USER32.@) */ -BOOL WINAPI GetClassInfoExW( HINSTANCE hInstance, LPCWSTR name, WNDCLASSEXW *wc ) +BOOL WINAPI GetClassInfoExW( HINSTANCE instance, const WCHAR *class_name, WNDCLASSEXW *wc ) { ATOM atom;
- TRACE("%p %s %p\n", hInstance, debugstr_w(name), wc); + TRACE( "%p %s %p\n", instance, debugstr_w(class_name), wc );
if (!wc) { @@ -647,8 +646,9 @@ BOOL WINAPI GetClassInfoExW( HINSTANCE hInstance, LPCWSTR name, WNDCLASSEXW *wc return FALSE; }
- atom = get_class_info( hInstance, name, wc, NULL, FALSE ); - if (atom) wc->lpszClassName = name; + if (!instance) instance = user32_module; + atom = get_class_info( instance, class_name, wc, NULL, FALSE ); + if (atom) wc->lpszClassName = class_name;
/* We must return the atom of the class here instead of just TRUE. */ return atom;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/user32/class.c | 120 ++++++++++++++++++++------------------------ 1 file changed, 55 insertions(+), 65 deletions(-)
diff --git a/dlls/user32/class.c b/dlls/user32/class.c index bd43618a4b9..c728b992138 100644 --- a/dlls/user32/class.c +++ b/dlls/user32/class.c @@ -194,51 +194,63 @@ static ULONG_PTR set_menu_nameA( HWND hwnd, INT offset, ULONG_PTR newval ) return 0; }
-static void get_class_version( UNICODE_STRING *name, UNICODE_STRING *version, HMODULE *reg_module ) +static void get_class_version( UNICODE_STRING *name, UNICODE_STRING *version, BOOL load ) { - ACTCTX_SECTION_KEYED_DATA data; - struct wndclass_redirect_data - { - ULONG size; - DWORD res; - ULONG name_len; - ULONG name_offset; - ULONG module_len; - ULONG module_offset; - } *wndclass; - const WCHAR *module, *ptr; - HMODULE hmod; - UINT offset = 0; - - if (reg_module) *reg_module = 0; - if (version) version->Length = 0; + ACTCTX_SECTION_KEYED_DATA data = {.cbSize = sizeof(data)}; + const WCHAR *class_name = name->Buffer; + HMODULE hmod = NULL;
- if (IS_INTRESOURCE( name->Buffer ) || is_comctl32_class( name->Buffer ) || is_builtin_class( name->Buffer )) return; + if (version) version->Length = 0;
- data.cbSize = sizeof(data); - if (RtlFindActivationContextSectionString( 0, NULL, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION, name, &data )) return; + if (IS_INTRESOURCE( name->Buffer ) || is_builtin_class( name->Buffer )) return;
- wndclass = (struct wndclass_redirect_data *)data.lpData; - offset = (wndclass->name_len - name->Length) / sizeof(WCHAR); + if (is_comctl32_class( name->Buffer )) + { + if (load && !(hmod = GetModuleHandleW( L"comctl32" ))) hmod = LoadLibraryW( L"comctl32" ); + } + else if (!RtlFindActivationContextSectionString( 0, NULL, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION, name, &data )) + { + struct wndclass_redirect_data + { + ULONG size; + DWORD res; + ULONG name_len; + ULONG name_offset; + ULONG module_len; + ULONG module_offset; + } *wndclass = (struct wndclass_redirect_data *)data.lpData; + const WCHAR *module, *ptr; + UINT offset; + + offset = (wndclass->name_len - name->Length) / sizeof(WCHAR); + + module = (const WCHAR *)((BYTE *)data.lpSectionBase + wndclass->module_offset); + if (load && !(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. */ + ptr = (const WCHAR *)((BYTE *)wndclass + wndclass->name_offset); + if (version) + { + WCHAR *combined = version->Buffer; + memcpy( combined, ptr, offset * sizeof(WCHAR) ); + lstrcpyW( &combined[offset], name->Buffer ); + version->Length = offset * sizeof(WCHAR); + ptr = combined; + }
- module = (const WCHAR *)((BYTE *)data.lpSectionBase + wndclass->module_offset); - if (!(hmod = GetModuleHandleW( module ))) - hmod = LoadLibraryW( module ); + init_class_name( name, ptr ); + }
- /* 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. */ - ptr = (const WCHAR *)((BYTE *)wndclass + wndclass->name_offset); - if (version) + if (load && hmod) { - WCHAR *combined = version->Buffer; - memcpy( combined, ptr, offset * sizeof(WCHAR) ); - lstrcpyW( &combined[offset], name->Buffer ); - version->Length = offset * sizeof(WCHAR); - ptr = combined; + BOOL (WINAPI *pRegisterClassNameW)( const WCHAR *class ); + if ((pRegisterClassNameW = (void *)GetProcAddress( hmod, "RegisterClassNameW" ))) + { + TRACE( "registering %s\n", debugstr_us(name) ); + pRegisterClassNameW( class_name ); + } } - - if (reg_module) *reg_module = hmod; - init_class_name( name, ptr ); }
@@ -343,7 +355,7 @@ ATOM WINAPI RegisterClassExA( const WNDCLASSEXA* wc ) if (!MultiByteToWideChar( CP_ACP, 0, wc->lpszClassName, -1, nameW, MAX_ATOM_LEN + 1 )) return 0; RtlInitUnicodeString( &name, nameW ); } - get_class_version( &name, &version, NULL ); + get_class_version( &name, &version, FALSE );
if (!alloc_menu_nameA( &menu_name, wc->lpszMenuName )) return 0;
@@ -366,7 +378,7 @@ ATOM WINAPI RegisterClassExW( const WNDCLASSEXW* wc ) version.Buffer = combined; version.MaximumLength = sizeof(combined); init_class_name( &name, wc->lpszClassName ); - get_class_version( &name, &version, NULL ); + get_class_version( &name, &version, FALSE );
if (!alloc_menu_nameW( &menu_name, wc->lpszMenuName )) return 0;
@@ -392,7 +404,7 @@ BOOL WINAPI UnregisterClassA( LPCSTR class_name, HINSTANCE instance ) if (!MultiByteToWideChar( CP_ACP, 0, class_name, -1, nameW, MAX_ATOM_LEN + 1 )) return 0; RtlInitUnicodeString( &name, nameW ); } - get_class_version( &name, NULL, NULL ); + get_class_version( &name, NULL, FALSE );
ret = NtUserUnregisterClass( &name, instance, &menu_name ); if (ret) free_menu_name( &menu_name ); @@ -409,7 +421,7 @@ BOOL WINAPI UnregisterClassW( LPCWSTR class_name, HINSTANCE instance ) BOOL ret;
init_class_name( &name, class_name ); - get_class_version( &name, NULL, NULL ); + get_class_version( &name, NULL, FALSE );
ret = NtUserUnregisterClass( &name, instance, &menu_name ); if (ret) free_menu_name( &menu_name ); @@ -562,34 +574,12 @@ ATOM get_class_info( HINSTANCE instance, const WCHAR *class_name, WNDCLASSEXW *i UNICODE_STRING *name_str, BOOL ansi ) { UNICODE_STRING name; - HMODULE module; ATOM atom;
init_class_name( &name, class_name ); - get_class_version( &name, NULL, &module ); - - while (!(atom = NtUserGetClassInfoEx( instance, &name, info, NULL, ansi ))) - { - if (module) - { - BOOL (WINAPI *pRegisterClassNameW)( const WCHAR *class ); - pRegisterClassNameW = (void *)GetProcAddress( module, "RegisterClassNameW" ); - module = NULL; - if (pRegisterClassNameW) - { - TRACE( "registering %s\n", debugstr_us(&name) ); - pRegisterClassNameW( class_name ); - continue; - } - } - if (IS_INTRESOURCE( class_name )) break; - if (!is_comctl32_class( class_name )) break; - if (GetModuleHandleW( L"comctl32.dll" )) break; - if (!LoadLibraryW( L"comctl32.dll" )) break; - TRACE( "%s retrying after loading comctl32\n", debugstr_w(class_name) ); - } + get_class_version( &name, NULL, TRUE );
- if (!atom) + if (!(atom = NtUserGetClassInfoEx( instance, &name, info, NULL, ansi ))) { TRACE( "%s %p -> not found\n", debugstr_w(class_name), instance ); SetLastError( ERROR_CLASS_DOES_NOT_EXIST );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/user32/class.c | 60 ++++++++++++++++++-------------------- dlls/user32/user_private.h | 4 +-- dlls/user32/win.c | 15 +++++++++- 3 files changed, 45 insertions(+), 34 deletions(-)
diff --git a/dlls/user32/class.c b/dlls/user32/class.c index c728b992138..156881fe253 100644 --- a/dlls/user32/class.c +++ b/dlls/user32/class.c @@ -121,7 +121,7 @@ static BOOL is_builtin_class( const WCHAR *name ) }
-static void init_class_name( UNICODE_STRING *str, const WCHAR *name ) +void init_class_name( UNICODE_STRING *str, const WCHAR *name ) { if (IS_INTRESOURCE( name )) { @@ -194,7 +194,7 @@ static ULONG_PTR set_menu_nameA( HWND hwnd, INT offset, ULONG_PTR newval ) return 0; }
-static void get_class_version( UNICODE_STRING *name, UNICODE_STRING *version, BOOL load ) +void get_class_version( UNICODE_STRING *name, UNICODE_STRING *version, BOOL load ) { ACTCTX_SECTION_KEYED_DATA data = {.cbSize = sizeof(data)}; const WCHAR *class_name = name->Buffer; @@ -570,31 +570,12 @@ BOOL WINAPI GetClassInfoW( HINSTANCE hInstance, LPCWSTR name, WNDCLASSW *wc ) return ret; }
-ATOM get_class_info( HINSTANCE instance, const WCHAR *class_name, WNDCLASSEXW *info, - UNICODE_STRING *name_str, BOOL ansi ) -{ - UNICODE_STRING name; - ATOM atom; - - init_class_name( &name, class_name ); - get_class_version( &name, NULL, TRUE ); - - if (!(atom = NtUserGetClassInfoEx( instance, &name, info, NULL, ansi ))) - { - TRACE( "%s %p -> not found\n", debugstr_w(class_name), instance ); - SetLastError( ERROR_CLASS_DOES_NOT_EXIST ); - return 0; - } - - if (name_str) *name_str = name; - return atom; -} - /*********************************************************************** * GetClassInfoExA (USER32.@) */ BOOL WINAPI GetClassInfoExA( HINSTANCE instance, const char *class_name, WNDCLASSEXA *wc ) { + UNICODE_STRING name; ATOM atom;
TRACE( "%p %s %p\n", instance, debugstr_a(class_name), wc ); @@ -605,17 +586,25 @@ BOOL WINAPI GetClassInfoExA( HINSTANCE instance, const char *class_name, WNDCLAS return FALSE; }
- if (!instance) instance = user32_module; - if (!IS_INTRESOURCE(class_name)) + if (IS_INTRESOURCE( class_name )) init_class_name( &name, (const WCHAR *)class_name ); + else { WCHAR nameW[MAX_ATOM_LEN + 1]; - if (!MultiByteToWideChar( CP_ACP, 0, class_name, -1, nameW, ARRAY_SIZE( nameW ))) - return FALSE; - atom = get_class_info( instance, nameW, (WNDCLASSEXW *)wc, NULL, TRUE ); + if (!MultiByteToWideChar( CP_ACP, 0, class_name, -1, nameW, ARRAY_SIZE( nameW ))) return FALSE; + RtlInitUnicodeString( &name, nameW ); + } + + get_class_version( &name, NULL, TRUE ); + + if (!instance) instance = user32_module; + if (!(atom = NtUserGetClassInfoEx( instance, &name, (WNDCLASSEXW *)wc, NULL, TRUE ))) + { + TRACE( "%s %p -> not found\n", debugstr_us(&name), instance ); + SetLastError( ERROR_CLASS_DOES_NOT_EXIST ); + return 0; } - else atom = get_class_info( instance, (const WCHAR *)class_name, (WNDCLASSEXW *)wc, NULL, TRUE ); - if (atom) wc->lpszClassName = class_name;
+ wc->lpszClassName = class_name; /* We must return the atom of the class here instead of just TRUE. */ return atom; } @@ -626,6 +615,7 @@ BOOL WINAPI GetClassInfoExA( HINSTANCE instance, const char *class_name, WNDCLAS */ BOOL WINAPI GetClassInfoExW( HINSTANCE instance, const WCHAR *class_name, WNDCLASSEXW *wc ) { + UNICODE_STRING name; ATOM atom;
TRACE( "%p %s %p\n", instance, debugstr_w(class_name), wc ); @@ -636,10 +626,18 @@ BOOL WINAPI GetClassInfoExW( HINSTANCE instance, const WCHAR *class_name, WNDCLA return FALSE; }
+ init_class_name( &name, class_name ); + get_class_version( &name, NULL, TRUE ); + if (!instance) instance = user32_module; - atom = get_class_info( instance, class_name, wc, NULL, FALSE ); - if (atom) wc->lpszClassName = class_name; + if (!(atom = NtUserGetClassInfoEx( instance, &name, wc, NULL, FALSE ))) + { + TRACE( "%s %p -> not found\n", debugstr_us(&name), instance ); + SetLastError( ERROR_CLASS_DOES_NOT_EXIST ); + return 0; + }
+ wc->lpszClassName = class_name; /* We must return the atom of the class here instead of just TRUE. */ return atom; } diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h index a324968400f..8eab66efe31 100644 --- a/dlls/user32/user_private.h +++ b/dlls/user32/user_private.h @@ -81,8 +81,8 @@ extern INT_PTR WINPROC_CallDlgProcW( HWND hwnd, UINT msg, WPARAM wParam, LPARAM extern void winproc_init(void); extern LRESULT dispatch_win_proc_params( struct win_proc_params *params );
-extern ATOM get_class_info( HINSTANCE instance, const WCHAR *name, WNDCLASSEXW *info, - UNICODE_STRING *name_str, BOOL ansi ); +extern void init_class_name( UNICODE_STRING *str, const WCHAR *name ); +extern void get_class_version( UNICODE_STRING *name, UNICODE_STRING *version, BOOL load );
/* kernel callbacks */
diff --git a/dlls/user32/win.c b/dlls/user32/win.c index 08371dd3e16..b1e8842b9e8 100644 --- a/dlls/user32/win.c +++ b/dlls/user32/win.c @@ -29,6 +29,11 @@
WINE_DEFAULT_DEBUG_CHANNEL(win);
+static const char *debugstr_us( const UNICODE_STRING *us ) +{ + if (!us) return "<null>"; + return debugstr_wn( us->Buffer, us->Length / sizeof(WCHAR) ); +}
#ifdef __i386__ /* Some apps pass a non-stdcall proc to EnumChildWindows, @@ -282,7 +287,15 @@ HWND WIN_CreateWindowEx( CREATESTRUCTW *cs, LPCWSTR className, HINSTANCE module, WCHAR name_buf[8]; HMENU menu;
- if (!get_class_info( module, className, &info, &class, FALSE )) return FALSE; + init_class_name( &class, className ); + get_class_version( &class, NULL, TRUE ); + + if (!NtUserGetClassInfoEx( module, &class, &info, NULL, FALSE )) + { + TRACE( "%s %p -> not found\n", debugstr_us(&class), module ); + SetLastError( ERROR_CLASS_DOES_NOT_EXIST ); + return FALSE; + }
TRACE("%s %s%s%s ex=%08lx style=%08lx %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n", unicode ? debugstr_w(cs->lpszName) : debugstr_a((LPCSTR)cs->lpszName),
From: Rémi Bernon rbernon@codeweavers.com
This shouldn't matter in theory but some tests check the case exactly and there's no good reason to use a different casing. --- dlls/comctl32/comctl32.manifest | 4 ++-- dlls/comctl32/tests/listbox.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/dlls/comctl32/comctl32.manifest b/dlls/comctl32/comctl32.manifest index 4c86137667e..8d37eeffc4d 100644 --- a/dlls/comctl32/comctl32.manifest +++ b/dlls/comctl32/comctl32.manifest @@ -6,9 +6,9 @@ <windowClass>ButtonListBox</windowClass> <windowClass>ComboBoxEx32</windowClass> <windowClass>ComboLBox</windowClass> - <windowClass>Combobox</windowClass> + <windowClass>ComboBox</windowClass> <windowClass>Edit</windowClass> - <windowClass>Listbox</windowClass> + <windowClass>ListBox</windowClass> <windowClass>NativeFontCtl</windowClass> <windowClass>ReBarWindow32</windowClass> <windowClass>ScrollBar</windowClass> diff --git a/dlls/comctl32/tests/listbox.c b/dlls/comctl32/tests/listbox.c index 4012811473c..8a9db99f386 100644 --- a/dlls/comctl32/tests/listbox.c +++ b/dlls/comctl32/tests/listbox.c @@ -56,7 +56,7 @@ static void CALLBACK msg_winevent_proc(HWINEVENTHOOK hevent,
/* ignore events not from a listbox control */ if (!GetClassNameA(hwnd, class_name, ARRAY_SIZE(class_name)) || - strcmp(class_name, WC_LISTBOXA) != 0) + stricmp(class_name, WC_LISTBOXA) != 0) return;
msg.message = event;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/user32/class.c | 99 +++++++++++++++++++++------------------------ dlls/user32/win.c | 7 +++- 2 files changed, 50 insertions(+), 56 deletions(-)
diff --git a/dlls/user32/class.c b/dlls/user32/class.c index 156881fe253..dedba766921 100644 --- a/dlls/user32/class.c +++ b/dlls/user32/class.c @@ -120,6 +120,19 @@ static BOOL is_builtin_class( const WCHAR *name ) return FALSE; }
+static void init_class_name_ansi( UNICODE_STRING *str, const char *name ) +{ + if (IS_INTRESOURCE( name )) + { + str->Buffer = (WCHAR *)name; + str->Length = str->MaximumLength = 0; + } + else + { + UINT len = MultiByteToWideChar( CP_ACP, 0, name, -1, str->Buffer, str->MaximumLength / sizeof(WCHAR) ); + str->Length = (len - 1) * sizeof(WCHAR); + } +}
void init_class_name( UNICODE_STRING *str, const WCHAR *name ) { @@ -128,7 +141,11 @@ void init_class_name( UNICODE_STRING *str, const WCHAR *name ) str->Buffer = (WCHAR *)name; str->Length = str->MaximumLength = 0; } - else RtlInitUnicodeString( str, name ); + else + { + str->Length = min( str->MaximumLength, wcslen( name ) * sizeof(WCHAR) ); + memcpy( str->Buffer, name, str->Length + sizeof(WCHAR) ); + } }
static BOOL alloc_menu_nameA( struct client_menu_name *ret, const char *menu_name ) @@ -200,7 +217,7 @@ void get_class_version( UNICODE_STRING *name, UNICODE_STRING *version, BOOL load const WCHAR *class_name = name->Buffer; HMODULE hmod = NULL;
- if (version) version->Length = 0; + memset( version, 0, sizeof(*version) );
if (IS_INTRESOURCE( name->Buffer ) || is_builtin_class( name->Buffer )) return;
@@ -220,26 +237,18 @@ void get_class_version( UNICODE_STRING *name, UNICODE_STRING *version, BOOL load ULONG module_offset; } *wndclass = (struct wndclass_redirect_data *)data.lpData; const WCHAR *module, *ptr; - UINT offset; - - offset = (wndclass->name_len - name->Length) / sizeof(WCHAR);
module = (const WCHAR *)((BYTE *)data.lpSectionBase + wndclass->module_offset); if (load && !(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. */ - ptr = (const WCHAR *)((BYTE *)wndclass + wndclass->name_offset); - if (version) - { - WCHAR *combined = version->Buffer; - memcpy( combined, ptr, offset * sizeof(WCHAR) ); - lstrcpyW( &combined[offset], name->Buffer ); - version->Length = offset * sizeof(WCHAR); - ptr = combined; - } + *version = *name; + version->Length = wndclass->name_len - name->Length; + class_name += version->Length / sizeof(WCHAR);
- init_class_name( name, ptr ); + ptr = (const WCHAR *)((BYTE *)wndclass + wndclass->name_offset); + memcpy( name->Buffer, ptr, wndclass->name_len ); + name->Length = wndclass->name_len; + name->Buffer[name->Length / sizeof(WCHAR)] = 0; }
if (load && hmod) @@ -247,7 +256,7 @@ void get_class_version( UNICODE_STRING *name, UNICODE_STRING *version, BOOL load BOOL (WINAPI *pRegisterClassNameW)( const WCHAR *class ); if ((pRegisterClassNameW = (void *)GetProcAddress( hmod, "RegisterClassNameW" ))) { - TRACE( "registering %s\n", debugstr_us(name) ); + TRACE( "registering %s version %s\n", debugstr_us(name), debugstr_us(version) ); pRegisterClassNameW( class_name ); } } @@ -342,19 +351,12 @@ ATOM WINAPI RegisterClassW( const WNDCLASSW* wc ) */ ATOM WINAPI RegisterClassExA( const WNDCLASSEXA* wc ) { - WCHAR nameW[MAX_ATOM_LEN + 1], combined[MAX_ATOM_LEN + 1]; struct client_menu_name menu_name; - UNICODE_STRING name, version; + WCHAR nameW[MAX_ATOM_LEN + 1]; + UNICODE_STRING name = RTL_CONSTANT_STRING(nameW), version; ATOM atom;
- version.Buffer = combined; - version.MaximumLength = sizeof(combined); - if (IS_INTRESOURCE( wc->lpszClassName )) init_class_name( &name, (const WCHAR *)wc->lpszClassName ); - else - { - if (!MultiByteToWideChar( CP_ACP, 0, wc->lpszClassName, -1, nameW, MAX_ATOM_LEN + 1 )) return 0; - RtlInitUnicodeString( &name, nameW ); - } + init_class_name_ansi( &name, wc->lpszClassName ); get_class_version( &name, &version, FALSE );
if (!alloc_menu_nameA( &menu_name, wc->lpszMenuName )) return 0; @@ -370,13 +372,11 @@ ATOM WINAPI RegisterClassExA( const WNDCLASSEXA* wc ) */ ATOM WINAPI RegisterClassExW( const WNDCLASSEXW* wc ) { - WCHAR combined[MAX_ATOM_LEN + 1]; struct client_menu_name menu_name; - UNICODE_STRING name, version; + WCHAR nameW[MAX_ATOM_LEN + 1]; + UNICODE_STRING name = RTL_CONSTANT_STRING(nameW), version; ATOM atom;
- version.Buffer = combined; - version.MaximumLength = sizeof(combined); init_class_name( &name, wc->lpszClassName ); get_class_version( &name, &version, FALSE );
@@ -395,16 +395,11 @@ BOOL WINAPI UnregisterClassA( LPCSTR class_name, HINSTANCE instance ) { struct client_menu_name menu_name; WCHAR nameW[MAX_ATOM_LEN + 1]; - UNICODE_STRING name; + UNICODE_STRING name = RTL_CONSTANT_STRING(nameW), version; BOOL ret;
- if (IS_INTRESOURCE( class_name )) init_class_name( &name, (const WCHAR *)class_name ); - else - { - if (!MultiByteToWideChar( CP_ACP, 0, class_name, -1, nameW, MAX_ATOM_LEN + 1 )) return 0; - RtlInitUnicodeString( &name, nameW ); - } - get_class_version( &name, NULL, FALSE ); + init_class_name_ansi( &name, class_name ); + get_class_version( &name, &version, FALSE );
ret = NtUserUnregisterClass( &name, instance, &menu_name ); if (ret) free_menu_name( &menu_name ); @@ -417,11 +412,12 @@ BOOL WINAPI UnregisterClassA( LPCSTR class_name, HINSTANCE instance ) BOOL WINAPI UnregisterClassW( LPCWSTR class_name, HINSTANCE instance ) { struct client_menu_name menu_name; - UNICODE_STRING name; + WCHAR nameW[MAX_ATOM_LEN + 1]; + UNICODE_STRING name = RTL_CONSTANT_STRING(nameW), version; BOOL ret;
init_class_name( &name, class_name ); - get_class_version( &name, NULL, FALSE ); + get_class_version( &name, &version, FALSE );
ret = NtUserUnregisterClass( &name, instance, &menu_name ); if (ret) free_menu_name( &menu_name ); @@ -575,7 +571,8 @@ BOOL WINAPI GetClassInfoW( HINSTANCE hInstance, LPCWSTR name, WNDCLASSW *wc ) */ BOOL WINAPI GetClassInfoExA( HINSTANCE instance, const char *class_name, WNDCLASSEXA *wc ) { - UNICODE_STRING name; + WCHAR nameW[MAX_ATOM_LEN + 1]; + UNICODE_STRING name = RTL_CONSTANT_STRING(nameW), version; ATOM atom;
TRACE( "%p %s %p\n", instance, debugstr_a(class_name), wc ); @@ -586,15 +583,8 @@ BOOL WINAPI GetClassInfoExA( HINSTANCE instance, const char *class_name, WNDCLAS return FALSE; }
- if (IS_INTRESOURCE( class_name )) init_class_name( &name, (const WCHAR *)class_name ); - else - { - WCHAR nameW[MAX_ATOM_LEN + 1]; - if (!MultiByteToWideChar( CP_ACP, 0, class_name, -1, nameW, ARRAY_SIZE( nameW ))) return FALSE; - RtlInitUnicodeString( &name, nameW ); - } - - get_class_version( &name, NULL, TRUE ); + init_class_name_ansi( &name, class_name ); + get_class_version( &name, &version, TRUE );
if (!instance) instance = user32_module; if (!(atom = NtUserGetClassInfoEx( instance, &name, (WNDCLASSEXW *)wc, NULL, TRUE ))) @@ -615,7 +605,8 @@ BOOL WINAPI GetClassInfoExA( HINSTANCE instance, const char *class_name, WNDCLAS */ BOOL WINAPI GetClassInfoExW( HINSTANCE instance, const WCHAR *class_name, WNDCLASSEXW *wc ) { - UNICODE_STRING name; + WCHAR nameW[MAX_ATOM_LEN + 1]; + UNICODE_STRING name = RTL_CONSTANT_STRING(nameW), version; ATOM atom;
TRACE( "%p %s %p\n", instance, debugstr_w(class_name), wc ); @@ -627,7 +618,7 @@ BOOL WINAPI GetClassInfoExW( HINSTANCE instance, const WCHAR *class_name, WNDCLA }
init_class_name( &name, class_name ); - get_class_version( &name, NULL, TRUE ); + get_class_version( &name, &version, TRUE );
if (!instance) instance = user32_module; if (!(atom = NtUserGetClassInfoEx( instance, &name, wc, NULL, FALSE ))) diff --git a/dlls/user32/win.c b/dlls/user32/win.c index b1e8842b9e8..18866ac694e 100644 --- a/dlls/user32/win.c +++ b/dlls/user32/win.c @@ -29,6 +29,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(win);
+#define MAX_ATOM_LEN 255 /* from dlls/kernel32/atom.c */ + static const char *debugstr_us( const UNICODE_STRING *us ) { if (!us) return "<null>"; @@ -280,7 +282,8 @@ static BOOL is_default_coord( int x ) */ HWND WIN_CreateWindowEx( CREATESTRUCTW *cs, LPCWSTR className, HINSTANCE module, BOOL unicode ) { - UNICODE_STRING class, window_name = {0}; + WCHAR nameW[MAX_ATOM_LEN + 1]; + UNICODE_STRING class = RTL_CONSTANT_STRING(nameW), version, window_name = {0}; HWND hwnd, top_child = 0; MDICREATESTRUCTW mdi_cs; WNDCLASSEXW info; @@ -288,7 +291,7 @@ HWND WIN_CreateWindowEx( CREATESTRUCTW *cs, LPCWSTR className, HINSTANCE module, HMENU menu;
init_class_name( &class, className ); - get_class_version( &class, NULL, TRUE ); + get_class_version( &class, &version, TRUE );
if (!NtUserGetClassInfoEx( module, &class, &info, NULL, FALSE )) {
Nikolay Sivov (@nsivov) commented about dlls/user32/class.c:
if (!MultiByteToWideChar( CP_ACP, 0, className, -1, name, MAX_ATOM_LEN + 1 ))
return FALSE;
return UnregisterClassW( name, hInstance );
- if (IS_INTRESOURCE( class_name )) init_class_name( &name, (const WCHAR *)class_name );
- else
- {
if (!MultiByteToWideChar( CP_ACP, 0, class_name, -1, nameW, MAX_ATOM_LEN + 1 )) return 0;
}RtlInitUnicodeString( &name, nameW );
- return UnregisterClassW( (LPCWSTR)className, hInstance );
- get_class_version( &name, NULL, NULL );
- ret = NtUserUnregisterClass( &name, instance, &menu_name );
- if (ret) free_menu_name( &menu_name );
- return ret;
Why is this better than calling the -W variant?
Nikolay Sivov (@nsivov) commented about dlls/user32/class.c:
/***********************************************************************
GetClassInfoExA (USER32.@)
*/ -BOOL WINAPI GetClassInfoExA( HINSTANCE hInstance, LPCSTR name, WNDCLASSEXA *wc ) +BOOL WINAPI GetClassInfoExA( HINSTANCE instance, const char *class_name, WNDCLASSEXA *wc ) {
I don't see a value in changing this.
On Wed Jun 18 19:55:46 2025 +0000, Nikolay Sivov wrote:
Why is this better than calling the -W variant?
With this MR every function use a similar pattern with a single init_class_name_ansi/init_class_name variation between the A/W versions.
I think it makes things overall more consistent than what it is now with some functions being able to convert to unicode and call W while other cannot.
On Wed Jun 18 19:55:46 2025 +0000, Nikolay Sivov wrote:
I don't see a value in changing this.
Same here, aiming at making the code consistent between the functions by keeping similarly named local variables, and taking the occasion to cleanup other parameters with legacy style.