user32: Introduce get_class_info.

And use it in WIN_CreateWindowEx to trigger class registration.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Huw Davies <huw@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2022-03-07 14:41:03 +01:00 committed by Alexandre Julliard
parent ea79e50f98
commit 5e75e5f66d
3 changed files with 46 additions and 28 deletions

View File

@ -211,6 +211,16 @@ static BOOL set_server_info( HWND hwnd, INT offset, LONG_PTR newval, UINT size )
}
static void init_class_name( UNICODE_STRING *str, const WCHAR *name )
{
if (IS_INTRESOURCE( name ))
{
str->Buffer = (WCHAR *)name;
str->Length = str->MaximumLength = 0;
}
else RtlInitUnicodeString( str, name );
}
/***********************************************************************
* CLASS_GetMenuNameA
*
@ -253,7 +263,6 @@ static void CLASS_SetMenuNameA( CLASS *classPtr, LPCSTR name )
else classPtr->menuName = (LPWSTR)name;
}
/***********************************************************************
* CLASS_SetMenuNameW
*
@ -313,7 +322,7 @@ static CLASS *find_class( HINSTANCE module, const WCHAR *name )
{
if (wcsicmp( class->name, name )) continue;
}
if (!class->local || (class->instance & ~0xffff) == instance)
if (!class->local || !module || (class->instance & ~0xffff) == instance)
{
TRACE("%s %Ix -> %p\n", debugstr_w(name), instance, class);
return class;
@ -323,7 +332,7 @@ static CLASS *find_class( HINSTANCE module, const WCHAR *name )
return NULL;
}
const WCHAR *CLASS_GetVersionedName( const WCHAR *name, UINT *basename_offset, WCHAR *combined, BOOL register_class )
static const WCHAR *CLASS_GetVersionedName( const WCHAR *name, UINT *basename_offset, WCHAR *combined, BOOL register_class )
{
ACTCTX_SECTION_KEYED_DATA data;
struct wndclass_redirect_data
@ -397,11 +406,12 @@ const WCHAR *CLASS_GetVersionedName( const WCHAR *name, UINT *basename_offset, W
*
* Return a pointer to the class.
*/
static CLASS *CLASS_FindClass( LPCWSTR name, HINSTANCE hinstance )
static CLASS *CLASS_FindClass( LPCWSTR name, HINSTANCE hinstance, UNICODE_STRING *name_str )
{
CLASS *class;
GetDesktopWindow(); /* create the desktop window to trigger builtin class registration */
if (name != (LPCWSTR)DESKTOP_CLASS_ATOM && (IS_INTRESOURCE(name) || wcsicmp( name, L"Message" )))
GetDesktopWindow(); /* create the desktop window to trigger builtin class registration */
if (!name) return NULL;
@ -417,6 +427,7 @@ static CLASS *CLASS_FindClass( LPCWSTR name, HINSTANCE hinstance )
}
if (!class) TRACE("%s %p -> not found\n", debugstr_w(name), hinstance);
else if (name_str) init_class_name( name_str, name );
return class;
}
@ -1253,6 +1264,21 @@ BOOL WINAPI GetClassInfoW( HINSTANCE hInstance, LPCWSTR name, WNDCLASSW *wc )
return ret;
}
ATOM get_class_info( HINSTANCE instance, const WCHAR *name, UNICODE_STRING *name_str )
{
CLASS *class;
ATOM atom;
if (!(class = CLASS_FindClass( name, instance, name_str )))
{
SetLastError( ERROR_CLASS_DOES_NOT_EXIST );
return FALSE;
}
atom = class->atomName;
release_class_ptr( class );
return atom;
}
/***********************************************************************
* GetClassInfoExA (USER32.@)
@ -1277,9 +1303,9 @@ BOOL WINAPI GetClassInfoExA( HINSTANCE hInstance, LPCSTR name, WNDCLASSEXA *wc )
WCHAR nameW[MAX_ATOM_LEN + 1];
if (!MultiByteToWideChar( CP_ACP, 0, name, -1, nameW, ARRAY_SIZE( nameW )))
return FALSE;
classPtr = CLASS_FindClass( nameW, hInstance );
classPtr = CLASS_FindClass( nameW, hInstance, NULL );
}
else classPtr = CLASS_FindClass( (LPCWSTR)name, hInstance );
else classPtr = CLASS_FindClass( (LPCWSTR)name, hInstance, NULL );
if (!classPtr)
{
@ -1323,7 +1349,7 @@ BOOL WINAPI GetClassInfoExW( HINSTANCE hInstance, LPCWSTR name, WNDCLASSEXW *wc
if (!hInstance) hInstance = user32_module;
if (!(classPtr = CLASS_FindClass( name, hInstance )))
if (!(classPtr = CLASS_FindClass( name, hInstance, NULL )))
{
SetLastError( ERROR_CLASS_DOES_NOT_EXIST );
return FALSE;

View File

@ -160,8 +160,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 void winproc_init(void) DECLSPEC_HIDDEN;
extern const WCHAR *CLASS_GetVersionedName(const WCHAR *classname, UINT *basename_offset,
WCHAR *combined, BOOL register_class) DECLSPEC_HIDDEN;
extern ATOM get_class_info( HINSTANCE instance, const WCHAR *name, UNICODE_STRING *name_str ) DECLSPEC_HIDDEN;
/* kernel callbacks */

View File

@ -126,7 +126,7 @@ void *free_user_handle( HANDLE handle, unsigned int type )
*
* Create a window handle with the server.
*/
static WND *create_window_handle( HWND parent, HWND owner, LPCWSTR name,
static WND *create_window_handle( HWND parent, HWND owner, UNICODE_STRING *name,
HINSTANCE instance, BOOL unicode,
DWORD style, DWORD ex_style )
{
@ -146,8 +146,8 @@ static WND *create_window_handle( HWND parent, HWND owner, LPCWSTR name,
req->awareness = awareness;
req->style = style;
req->ex_style = ex_style;
if (!(req->atom = get_int_atom_value( name )) && name)
wine_server_add_data( req, name, lstrlenW(name)*sizeof(WCHAR) );
if (!(req->atom = get_int_atom_value( name->Buffer )) && name->Length)
wine_server_add_data( req, name->Buffer, name->Length );
if (!wine_server_call_err( req ))
{
handle = wine_server_ptr_handle( reply->handle );
@ -184,7 +184,7 @@ static WND *create_window_handle( HWND parent, HWND owner, LPCWSTR name,
{
struct user_thread_info *thread_info = get_user_thread_info();
if (name == (LPCWSTR)DESKTOP_CLASS_ATOM)
if (name->Buffer == (LPCWSTR)DESKTOP_CLASS_ATOM)
{
if (!thread_info->top_window) thread_info->top_window = full_parent ? full_parent : handle;
else assert( full_parent == thread_info->top_window );
@ -1395,18 +1395,19 @@ HWND WIN_CreateWindowEx( CREATESTRUCTW *cs, LPCWSTR className, HINSTANCE module,
RECT rect;
WND *wndPtr;
HWND hwnd, parent, owner, top_child = 0;
const WCHAR *p = className;
UINT win_dpi, thread_dpi = get_thread_dpi();
DPI_AWARENESS_CONTEXT context;
MDICREATESTRUCTW mdi_cs;
UNICODE_STRING class;
CBT_CREATEWNDW cbtc;
CREATESTRUCTW cbcs;
className = CLASS_GetVersionedName(className, NULL, NULL, TRUE);
if (!get_class_info( module, className, &class )) return FALSE;
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),
debugstr_w(p), p != className ? "->" : "", p != className ? debugstr_w(className) : "",
debugstr_w(className), class.Buffer != className ? "->" : "",
class.Buffer != className ? debugstr_wn(class.Buffer, class.Length / sizeof(WCHAR)) : "",
cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
@ -1524,17 +1525,9 @@ HWND WIN_CreateWindowEx( CREATESTRUCTW *cs, LPCWSTR className, HINSTANCE module,
style = cs->style & ~WS_VISIBLE;
ex_style = cs->dwExStyle & ~WS_EX_LAYERED;
if (!(wndPtr = create_window_handle( parent, owner, className, module,
unicode, style, ex_style )))
{
WNDCLASSW wc;
/* if it's a comctl32 class, GetClassInfo will load it, then we can retry */
if (GetLastError() != ERROR_INVALID_HANDLE ||
!GetClassInfoW( 0, className, &wc ) ||
!(wndPtr = create_window_handle( parent, owner, className, module,
unicode, style, ex_style )))
return 0;
}
if (!(wndPtr = create_window_handle( parent, owner, &class, module,
unicode, style, ex_style )))
return 0;
hwnd = wndPtr->obj.handle;
/* Fill the window structure */