win32u: Move class management implementation from user32.

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:42:32 +01:00 committed by Alexandre Julliard
parent b1b0470083
commit 7c76aa05a9
12 changed files with 340 additions and 259 deletions

View file

@ -40,7 +40,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(class);
#define MAX_ATOM_LEN 255 /* from dlls/kernel32/atom.c */
static struct list class_list = LIST_INIT( class_list );
static INIT_ONCE init_once = INIT_ONCE_STATIC_INIT;
#define CLASS_OTHER_PROCESS ((CLASS *)1)
@ -301,54 +300,6 @@ static void CLASS_SetMenuNameW( CLASS *classPtr, LPCWSTR name )
}
/***********************************************************************
* CLASS_FreeClass
*
* Free a class structure.
*/
static void CLASS_FreeClass( CLASS *classPtr )
{
TRACE("%p\n", classPtr);
USER_Lock();
if (classPtr->dce) free_dce( classPtr->dce, 0 );
list_remove( &classPtr->entry );
if (classPtr->hbrBackground > (HBRUSH)(COLOR_GRADIENTINACTIVECAPTION + 1))
DeleteObject( classPtr->hbrBackground );
DestroyIcon( classPtr->hIconSmIntern );
free_menu_name( &classPtr->menu_name );
HeapFree( GetProcessHeap(), 0, classPtr );
USER_Unlock();
}
static CLASS *find_class( HINSTANCE module, UNICODE_STRING *name )
{
ATOM atom = get_int_atom_value( name );
UINT_PTR instance = (UINT_PTR)module & ~0xffff;
CLASS *class;
USER_Lock();
LIST_FOR_EACH_ENTRY( class, &class_list, CLASS, entry )
{
if (atom)
{
if (class->atomName != atom) continue;
}
else
{
if (wcsnicmp( class->name, name->Buffer, name->Length / sizeof(WCHAR) )) continue;
}
if (!class->local || !module || (class->instance & ~0xffff) == instance)
{
TRACE( "%s %Ix -> %p\n", debugstr_us(name), instance, class );
return class;
}
}
USER_Unlock();
return NULL;
}
static void get_versioned_name( const WCHAR *name, UNICODE_STRING *ret, UNICODE_STRING *version, HMODULE *reg_module )
{
ACTCTX_SECTION_KEYED_DATA data;
@ -407,75 +358,6 @@ static void get_versioned_name( const WCHAR *name, UNICODE_STRING *ret, UNICODE_
init_class_name( ret, ptr );
}
/***********************************************************************
* CLASS_RegisterClass
*
* The real RegisterClass() functionality.
*/
static CLASS *CLASS_RegisterClass( UNICODE_STRING *name, UINT basename_offset, HINSTANCE hInstance,
BOOL local, DWORD style, INT classExtra, INT winExtra )
{
CLASS *classPtr;
BOOL ret;
TRACE("name=%s hinst=%p style=0x%x clExtr=0x%x winExtr=0x%x\n",
debugstr_us(name), hInstance, style, classExtra, winExtra );
/* Fix the extra bytes value */
if (classExtra > 40) /* Extra bytes are limited to 40 in Win32 */
WARN("Class extra bytes %d is > 40\n", classExtra);
if (winExtra > 40) /* Extra bytes are limited to 40 in Win32 */
WARN("Win extra bytes %d is > 40\n", winExtra );
classPtr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CLASS) + classExtra );
if (!classPtr) return NULL;
classPtr->atomName = get_int_atom_value( name );
classPtr->basename = classPtr->name;
if (!classPtr->atomName && name)
{
memcpy( classPtr->name, name->Buffer, name->Length );
classPtr->name[name->Length / sizeof(WCHAR)] = 0;
classPtr->basename += basename_offset;
}
else GlobalGetAtomNameW( classPtr->atomName, classPtr->name, ARRAY_SIZE( classPtr->name ));
SERVER_START_REQ( create_class )
{
req->local = local;
req->style = style;
req->instance = wine_server_client_ptr( hInstance );
req->extra = classExtra;
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->Buffer, name->Length );
ret = !wine_server_call_err( req );
classPtr->atomName = reply->atom;
}
SERVER_END_REQ;
if (!ret)
{
HeapFree( GetProcessHeap(), 0, classPtr );
return NULL;
}
classPtr->style = style;
classPtr->local = local;
classPtr->cbWndExtra = winExtra;
classPtr->cbClsExtra = classExtra;
classPtr->instance = (UINT_PTR)hInstance;
/* Other non-null values must be set by caller */
USER_Lock();
if (local) list_add_head( &class_list, &classPtr->entry );
else list_add_tail( &class_list, &classPtr->entry );
return classPtr;
}
/***********************************************************************
* register_builtin
@ -485,24 +367,22 @@ static CLASS *CLASS_RegisterClass( UNICODE_STRING *name, UINT basename_offset, H
*/
static void register_builtin( const struct builtin_class_descr *descr )
{
UNICODE_STRING name;
CLASS *classPtr;
HCURSOR cursor = 0;
UNICODE_STRING name, version = { .Length = 0 };
struct client_menu_name menu_name = { 0 };
WNDCLASSEXW class = {
.cbSize = sizeof(class),
.hInstance = user32_module,
.style = descr->style,
.cbWndExtra = descr->extra,
.hbrBackground = descr->brush,
.lpfnWndProc = BUILTIN_WINPROC( descr->proc ),
};
if (descr->cursor) cursor = LoadCursorA( 0, (LPSTR)descr->cursor );
if (descr->cursor) class.hCursor = LoadCursorA( 0, (LPSTR)descr->cursor );
init_class_name( &name, descr->name );
if (!(classPtr = CLASS_RegisterClass( &name, 0, user32_module, FALSE,
descr->style, 0, descr->extra )))
{
if (cursor) DestroyCursor( cursor );
return;
}
classPtr->hCursor = cursor;
classPtr->hbrBackground = descr->brush;
classPtr->winproc = BUILTIN_WINPROC( descr->proc );
release_class_ptr( classPtr );
if (!NtUserRegisterClassExWOW( &class, &name, &version, &menu_name, 1, 0, NULL ) && class.hCursor)
DestroyCursor( class.hCursor );
}
static void load_uxtheme(void)
@ -654,18 +534,6 @@ ATOM WINAPI RegisterClassExA( const WNDCLASSEXA* wc )
struct client_menu_name menu_name;
UNICODE_STRING name, version;
ATOM atom;
CLASS *classPtr;
HINSTANCE instance;
GetDesktopWindow(); /* create the desktop window to trigger builtin class registration */
if (wc->cbSize != sizeof(*wc) || wc->cbClsExtra < 0 || wc->cbWndExtra < 0 ||
wc->hInstance == user32_module) /* we can't register a class for user32 */
{
SetLastError( ERROR_INVALID_PARAMETER );
return 0;
}
if (!(instance = wc->hInstance)) instance = GetModuleHandleW( NULL );
version.Buffer = combined;
version.MaximumLength = sizeof(combined);
@ -682,27 +550,8 @@ ATOM WINAPI RegisterClassExA( const WNDCLASSEXA* wc )
if (!alloc_menu_nameA( &menu_name, wc->lpszMenuName )) return 0;
classPtr = CLASS_RegisterClass( &name, version.Length / sizeof(WCHAR), instance, !(wc->style & CS_GLOBALCLASS),
wc->style, wc->cbClsExtra, wc->cbWndExtra );
if (!classPtr) return 0;
atom = classPtr->atomName;
TRACE( "name=%s->%s atom=%04x wndproc=%p hinst=%p bg=%p style=%08x clsExt=%d winExt=%d class=%p\n",
debugstr_a(wc->lpszClassName), debugstr_us(&name), atom, wc->lpfnWndProc,
instance, wc->hbrBackground, wc->style, wc->cbClsExtra, wc->cbWndExtra, classPtr );
classPtr->hIcon = wc->hIcon;
classPtr->hIconSm = wc->hIconSm;
classPtr->hIconSmIntern = wc->hIcon && !wc->hIconSm ?
CopyImage( wc->hIcon, IMAGE_ICON,
GetSystemMetrics( SM_CXSMICON ),
GetSystemMetrics( SM_CYSMICON ),
LR_COPYFROMRESOURCE ) : NULL;
classPtr->hCursor = wc->hCursor;
classPtr->hbrBackground = wc->hbrBackground;
classPtr->winproc = WINPROC_AllocProc( wc->lpfnWndProc, FALSE );
classPtr->menu_name = menu_name;
release_class_ptr( classPtr );
atom = NtUserRegisterClassExWOW( (WNDCLASSEXW *)wc, &name, &version, &menu_name, 0, 1, NULL );
if (!atom) free_menu_name( &menu_name );
return atom;
}
@ -716,50 +565,15 @@ ATOM WINAPI RegisterClassExW( const WNDCLASSEXW* wc )
struct client_menu_name menu_name;
UNICODE_STRING name, version;
ATOM atom;
CLASS *classPtr;
HINSTANCE instance;
GetDesktopWindow(); /* create the desktop window to trigger builtin class registration */
if (wc->cbSize != sizeof(*wc) || wc->cbClsExtra < 0 || wc->cbWndExtra < 0 ||
wc->hInstance == user32_module) /* we can't register a class for user32 */
{
SetLastError( ERROR_INVALID_PARAMETER );
return 0;
}
if (!(instance = wc->hInstance)) instance = GetModuleHandleW( NULL );
if (!alloc_menu_nameW( &menu_name, wc->lpszMenuName )) return 0;
version.Buffer = combined;
version.MaximumLength = sizeof(combined);
get_versioned_name( wc->lpszClassName, &name, &version, FALSE );
if (!(classPtr = CLASS_RegisterClass( &name, version.Length / sizeof(WCHAR), instance,
!(wc->style & CS_GLOBALCLASS),
wc->style, wc->cbClsExtra, wc->cbWndExtra )))
{
free_menu_name( &menu_name );
return 0;
}
atom = classPtr->atomName;
if (!alloc_menu_nameW( &menu_name, wc->lpszMenuName )) return 0;
TRACE( "name=%s->%s atom=%04x wndproc=%p hinst=%p bg=%p style=%08x clsExt=%d winExt=%d class=%p\n",
debugstr_w(wc->lpszClassName), debugstr_us(&name), atom, wc->lpfnWndProc, instance,
wc->hbrBackground, wc->style, wc->cbClsExtra, wc->cbWndExtra, classPtr );
classPtr->hIcon = wc->hIcon;
classPtr->hIconSm = wc->hIconSm;
classPtr->hIconSmIntern = wc->hIcon && !wc->hIconSm ?
CopyImage( wc->hIcon, IMAGE_ICON,
GetSystemMetrics( SM_CXSMICON ),
GetSystemMetrics( SM_CYSMICON ),
LR_COPYFROMRESOURCE ) : NULL;
classPtr->hCursor = wc->hCursor;
classPtr->hbrBackground = wc->hbrBackground;
classPtr->winproc = WINPROC_AllocProc( wc->lpfnWndProc, TRUE );
CLASS_SetMenuNameW( classPtr, wc->lpszMenuName );
release_class_ptr( classPtr );
atom = NtUserRegisterClassExWOW( wc, &name, &version, &menu_name, 0, 0, NULL );
if (!atom) free_menu_name( &menu_name );
return atom;
}
@ -785,23 +599,14 @@ BOOL WINAPI UnregisterClassA( LPCSTR className, HINSTANCE hInstance )
*/
BOOL WINAPI UnregisterClassW( LPCWSTR className, HINSTANCE hInstance )
{
CLASS *classPtr = NULL;
struct client_menu_name menu_name;
UNICODE_STRING name;
GetDesktopWindow(); /* create the desktop window to trigger builtin class registration */
BOOL ret;
get_versioned_name( className, &name, NULL, FALSE );
SERVER_START_REQ( destroy_class )
{
req->instance = wine_server_client_ptr( hInstance );
if (!(req->atom = get_int_atom_value(&name)) && name.Length)
wine_server_add_data( req, name.Buffer, name.Length );
if (!wine_server_call_err( req )) classPtr = wine_server_get_ptr( reply->client_ptr );
}
SERVER_END_REQ;
if (classPtr) CLASS_FreeClass( classPtr );
return (classPtr != NULL);
ret = NtUserUnregisterClass( &name, hInstance, &menu_name );
if (ret) free_menu_name( &menu_name );
return ret;
}
@ -1259,19 +1064,13 @@ ATOM get_class_info( HINSTANCE instance, const WCHAR *class_name, WNDCLASSEXW *i
{
UNICODE_STRING name;
HMODULE module;
CLASS *class;
ATOM atom;
get_versioned_name( class_name, &name, NULL, &module );
if (!name_str && !instance) instance = user32_module;
if (name.Buffer != (LPCWSTR)DESKTOP_CLASS_ATOM &&
(IS_INTRESOURCE(name.Buffer) || name.Length != sizeof(L"Message") ||
wcsnicmp( name.Buffer, L"Message", ARRAYSIZE(L"Message") )))
GetDesktopWindow(); /* create the desktop window to trigger builtin class registration */
while (class_name && !(class = find_class( instance, &name )))
while (!(atom = NtUserGetClassInfoEx( instance, &name, info, NULL, ansi )))
{
if (module)
{
@ -1292,31 +1091,14 @@ ATOM get_class_info( HINSTANCE instance, const WCHAR *class_name, WNDCLASSEXW *i
TRACE( "%s retrying after loading comctl32\n", debugstr_w(class_name) );
}
if (!class)
if (!atom)
{
TRACE("%s %p -> not found\n", debugstr_w(class_name), instance);
TRACE( "%s %p -> not found\n", debugstr_w(class_name), instance );
SetLastError( ERROR_CLASS_DOES_NOT_EXIST );
return 0;
}
if (info)
{
info->style = class->style;
info->lpfnWndProc = WINPROC_GetProc( class->winproc, !ansi );
info->cbClsExtra = class->cbClsExtra;
info->cbWndExtra = class->cbWndExtra;
info->hInstance = (instance == user32_module) ? 0 : instance;
info->hIcon = class->hIcon;
info->hIconSm = class->hIconSm ? class->hIconSm : class->hIconSmIntern;
info->hCursor = class->hCursor;
info->hbrBackground = class->hbrBackground;
info->lpszMenuName = ansi ? (const WCHAR *)class->menu_name.nameA : class->menu_name.nameW;
info->lpszClassName = class_name;
}
if (name_str) *name_str = name;
atom = class->atomName;
release_class_ptr( class );
return atom;
}
@ -1355,6 +1137,8 @@ BOOL WINAPI GetClassInfoExA( HINSTANCE hInstance, LPCSTR name, WNDCLASSEXA *wc )
*/
BOOL WINAPI GetClassInfoExW( HINSTANCE hInstance, LPCWSTR name, WNDCLASSEXW *wc )
{
ATOM atom;
TRACE("%p %s %p\n", hInstance, debugstr_w(name), wc);
if (!wc)
@ -1363,7 +1147,11 @@ BOOL WINAPI GetClassInfoExW( HINSTANCE hInstance, LPCWSTR name, WNDCLASSEXW *wc
return FALSE;
}
return get_class_info( hInstance, name, wc, NULL, FALSE );
atom = get_class_info( hInstance, name, wc, NULL, FALSE );
if (atom) wc->lpszClassName = name;
/* We must return the atom of the class here instead of just TRUE. */
return atom;
}

View file

@ -24,13 +24,6 @@
#include "winuser.h"
#include "../win32u/ntuser_private.h"
/* Built-in class names (see _Undocumented_Windows_ p.418) */
#define POPUPMENU_CLASS_ATOM MAKEINTATOM(32768) /* PopupMenu */
#define DESKTOP_CLASS_ATOM MAKEINTATOM(32769) /* Desktop */
#define DIALOG_CLASS_ATOM MAKEINTATOM(32770) /* Dialog */
#define WINSWITCH_CLASS_ATOM MAKEINTATOM(32771) /* WinSwitch */
#define ICONTITLE_CLASS_ATOM MAKEINTATOM(32772) /* IconTitle */
/* Built-in class descriptor */
struct builtin_class_descr
{

View file

@ -328,7 +328,7 @@ static struct dce *get_window_dce( HWND hwnd )
*
* Free a class or window DCE.
*/
void free_dce( struct dce *dce, HWND hwnd )
void WINAPI free_dce( struct dce *dce, HWND hwnd )
{
struct dce *dce_to_free = NULL;

View file

@ -135,12 +135,14 @@ static void dpiaware_init(void)
static const struct user_callbacks user_funcs =
{
CopyImage,
GetDesktopWindow,
GetWindowRect,
IsChild,
RedrawWindow,
SendMessageTimeoutW,
WindowFromDC,
free_dce,
MSG_SendInternalMessageTimeout,
};

View file

@ -113,7 +113,7 @@ extern void create_offscreen_window_surface( const RECT *visible_rect, struct wi
extern void CLIPBOARD_ReleaseOwner( HWND hwnd ) DECLSPEC_HIDDEN;
extern BOOL FOCUS_MouseActivate( HWND hwnd ) DECLSPEC_HIDDEN;
extern BOOL set_capture_window( HWND hwnd, UINT gui_flags, HWND *prev_ret ) DECLSPEC_HIDDEN;
extern void free_dce( struct dce *dce, HWND hwnd ) DECLSPEC_HIDDEN;
extern void WINAPI free_dce( struct dce *dce, HWND hwnd ) DECLSPEC_HIDDEN;
extern void invalidate_dce( struct tagWND *win, const RECT *rect ) DECLSPEC_HIDDEN;
extern HDC get_display_dc(void) DECLSPEC_HIDDEN;
extern void release_display_dc( HDC hdc ) DECLSPEC_HIDDEN;

View file

@ -42,6 +42,10 @@ static WINDOWPROC winproc_array[MAX_WINPROCS];
static UINT winproc_used = NB_BUILTIN_WINPROCS;
static pthread_mutex_t winproc_lock = PTHREAD_MUTEX_INITIALIZER;
static struct list class_list = LIST_INIT( class_list );
static HINSTANCE user32_module;
/* find an existing winproc for a given function and type */
/* FIXME: probably should do something more clever than a linear search */
static WINDOWPROC *find_winproc( WNDPROC func, BOOL ansi )
@ -129,6 +133,24 @@ WNDPROC alloc_winproc( WNDPROC func, BOOL ansi )
return proc_to_handle( proc );
}
/* Get a window procedure pointer that can be passed to the Windows program. */
static WNDPROC get_winproc( WNDPROC proc, BOOL ansi )
{
WINDOWPROC *ptr = get_winproc_ptr( proc );
if (!ptr || ptr == WINPROC_PROC16) return proc;
if (ansi)
{
if (ptr->procA) return ptr->procA;
return proc;
}
else
{
if (ptr->procW) return ptr->procW;
return proc;
}
}
/***********************************************************************
* NtUserInitializeClientPfnArrays (win32u.@)
*/
@ -165,9 +187,31 @@ NTSTATUS WINAPI NtUserInitializeClientPfnArrays( const struct user_client_procs
winproc_array[WINPROC_MESSAGE].procA = client_procsA->pMessageWndProc;
winproc_array[WINPROC_MESSAGE].procW = client_procsW->pMessageWndProc;
user32_module = user_module;
return STATUS_SUCCESS;
}
/***********************************************************************
* get_int_atom_value
*/
static ATOM get_int_atom_value( UNICODE_STRING *name )
{
const WCHAR *ptr = name->Buffer;
const WCHAR *end = ptr + name->Length / sizeof(WCHAR);
UINT ret = 0;
if (IS_INTRESOURCE(ptr)) return LOWORD(ptr);
if (*ptr++ != '#') return 0;
while (ptr < end)
{
if (*ptr < '0' || *ptr > '9') return 0;
ret = ret * 10 + *ptr++ - '0';
if (ret > 0xffff) return 0;
}
return ret;
}
/***********************************************************************
* get_class_ptr
*/
@ -191,15 +235,218 @@ static CLASS *get_class_ptr( HWND hwnd, BOOL write_access )
return NULL;
}
/***********************************************************************
* release_class_ptr
*/
static inline void release_class_ptr( CLASS *ptr )
static void release_class_ptr( CLASS *ptr )
{
user_unlock();
}
static CLASS *find_class( HINSTANCE module, UNICODE_STRING *name )
{
ATOM atom = get_int_atom_value( name );
ULONG_PTR instance = (UINT_PTR)module & ~0xffff;
CLASS *class;
user_lock();
LIST_FOR_EACH_ENTRY( class, &class_list, CLASS, entry )
{
if (atom)
{
if (class->atomName != atom) continue;
}
else
{
if (wcsnicmp( class->name, name->Buffer, name->Length / sizeof(WCHAR) )) continue;
}
if (!class->local || !module || (class->instance & ~0xffff) == instance)
{
TRACE( "%s %lx -> %p\n", debugstr_us(name), instance, class );
return class;
}
}
user_unlock();
return NULL;
}
/***********************************************************************
* NtUserRegisterClassExWOW (win32u.@)
*/
ATOM WINAPI NtUserRegisterClassExWOW( const WNDCLASSEXW *wc, UNICODE_STRING *name, UNICODE_STRING *version,
struct client_menu_name *client_menu_name, DWORD fnid,
DWORD flags, DWORD *wow )
{
const BOOL is_builtin = fnid, ansi = flags;
HINSTANCE instance;
CLASS *class;
ATOM atom;
BOOL ret;
/* create the desktop window to trigger builtin class registration */
if (!is_builtin && user_callbacks) user_callbacks->pGetDesktopWindow();
if (wc->cbSize != sizeof(*wc) || wc->cbClsExtra < 0 || wc->cbWndExtra < 0 ||
(!is_builtin && wc->hInstance == user32_module)) /* we can't register a class for user32 */
{
SetLastError( ERROR_INVALID_PARAMETER );
return 0;
}
if (!(instance = wc->hInstance)) instance = NtCurrentTeb()->Peb->ImageBaseAddress;
TRACE( "name=%s hinst=%p style=0x%x clExtr=0x%x winExtr=0x%x\n",
debugstr_us(name), instance, wc->style, wc->cbClsExtra, wc->cbWndExtra );
/* Fix the extra bytes value */
if (wc->cbClsExtra > 40) /* Extra bytes are limited to 40 in Win32 */
WARN( "Class extra bytes %d is > 40\n", wc->cbClsExtra);
if (wc->cbWndExtra > 40) /* Extra bytes are limited to 40 in Win32 */
WARN("Win extra bytes %d is > 40\n", wc->cbWndExtra );
if (!(class = calloc( 1, sizeof(CLASS) + wc->cbClsExtra ))) return 0;
class->atomName = get_int_atom_value( name );
class->basename = class->name;
if (!class->atomName && name)
{
memcpy( class->name, name->Buffer, name->Length );
class->name[name->Length / sizeof(WCHAR)] = 0;
class->basename += version->Length / sizeof(WCHAR);
}
else
{
UNICODE_STRING str = { .MaximumLength = sizeof(class->name), .Buffer = class->name };
NtUserGetAtomName( class->atomName, &str );
}
class->style = wc->style;
class->local = !is_builtin && !(wc->style & CS_GLOBALCLASS);
class->cbWndExtra = wc->cbWndExtra;
class->cbClsExtra = wc->cbClsExtra;
class->instance = (UINT_PTR)instance;
SERVER_START_REQ( create_class )
{
req->local = class->local;
req->style = class->style;
req->instance = class->instance;
req->extra = class->cbClsExtra;
req->win_extra = class->cbWndExtra;
req->client_ptr = wine_server_client_ptr( class );
req->atom = class->atomName;
req->name_offset = version->Length / sizeof(WCHAR);
if (!req->atom && name) wine_server_add_data( req, name->Buffer, name->Length );
ret = !wine_server_call_err( req );
class->atomName = reply->atom;
}
SERVER_END_REQ;
if (!ret)
{
free( class );
return 0;
}
/* Other non-null values must be set by caller */
user_lock();
if (class->local) list_add_head( &class_list, &class->entry );
else list_add_tail( &class_list, &class->entry );
atom = class->atomName;
TRACE( "name=%s->%s atom=%04x wndproc=%p hinst=%p bg=%p style=%08x clsExt=%d winExt=%d class=%p\n",
debugstr_w(wc->lpszClassName), debugstr_us(name), atom, wc->lpfnWndProc, instance,
wc->hbrBackground, wc->style, wc->cbClsExtra, wc->cbWndExtra, class );
class->hIcon = wc->hIcon;
class->hIconSm = wc->hIconSm;
class->hCursor = wc->hCursor;
class->hbrBackground = wc->hbrBackground;
class->winproc = alloc_winproc( wc->lpfnWndProc, ansi );
class->menu_name = *client_menu_name;
if (wc->hIcon && !wc->hIconSm && user_callbacks)
class->hIconSmIntern = user_callbacks->pCopyImage( wc->hIcon, IMAGE_ICON,
get_system_metrics( SM_CXSMICON ),
get_system_metrics( SM_CYSMICON ),
LR_COPYFROMRESOURCE );
release_class_ptr( class );
return atom;
}
/***********************************************************************
* NtUserUnregisterClass (win32u.@)
*/
BOOL WINAPI NtUserUnregisterClass( UNICODE_STRING *name, HINSTANCE instance,
struct client_menu_name *client_menu_name )
{
CLASS *class = NULL;
if (user_callbacks) /* create the desktop window to trigger builtin class registration */
user_callbacks->pGetDesktopWindow();
SERVER_START_REQ( destroy_class )
{
req->instance = wine_server_client_ptr( instance );
if (!(req->atom = get_int_atom_value( name )) && name->Length)
wine_server_add_data( req, name->Buffer, name->Length );
if (!wine_server_call_err( req )) class = wine_server_get_ptr( reply->client_ptr );
}
SERVER_END_REQ;
if (!class) return FALSE;
TRACE( "%p\n", class );
user_lock();
if (class->dce && user_callbacks) user_callbacks->free_dce( class->dce, 0 );
list_remove( &class->entry );
if (class->hbrBackground > (HBRUSH)(COLOR_GRADIENTINACTIVECAPTION + 1))
NtGdiDeleteObjectApp( class->hbrBackground );
NtUserDestroyCursor( class->hIconSmIntern, 0 );
free( class );
user_unlock();
return TRUE;
}
/***********************************************************************
* NtUserGetClassInfo (win32u.@)
*/
ATOM WINAPI NtUserGetClassInfoEx( HINSTANCE instance, UNICODE_STRING *name, WNDCLASSEXW *wc,
struct client_menu_name *menu_name, BOOL ansi )
{
static const WCHAR messageW[] = {'M','e','s','s','a','g','e'};
CLASS *class;
ATOM atom;
/* create the desktop window to trigger builtin class registration */
if (name->Buffer != (const WCHAR *)DESKTOP_CLASS_ATOM &&
(IS_INTRESOURCE(name->Buffer) || name->Length != sizeof(messageW) ||
wcsnicmp( name->Buffer, messageW, ARRAYSIZE(messageW) )))
user_callbacks->pGetDesktopWindow();
if (!(class = find_class( instance, name ))) return 0;
if (wc)
{
wc->style = class->style;
wc->lpfnWndProc = get_winproc( class->winproc, ansi );
wc->cbClsExtra = class->cbClsExtra;
wc->cbWndExtra = class->cbWndExtra;
wc->hInstance = (instance == user32_module) ? 0 : instance;
wc->hIcon = class->hIcon;
wc->hIconSm = class->hIconSm ? class->hIconSm : class->hIconSmIntern;
wc->hCursor = class->hCursor;
wc->hbrBackground = class->hbrBackground;
wc->lpszMenuName = ansi ? (const WCHAR *)class->menu_name.nameA : class->menu_name.nameW;
wc->lpszClassName = name->Buffer;
}
if (menu_name) *menu_name = class->menu_name;
atom = class->atomName;
release_class_ptr( class );
return atom;
}
/***********************************************************************
* NtUserGetAtomName (win32u.@)
*/

View file

@ -1165,6 +1165,7 @@ static struct unix_funcs unix_funcs =
NtUserEnumDisplayMonitors,
NtUserEnumDisplaySettings,
NtUserGetAsyncKeyState,
NtUserGetClassInfoEx,
NtUserGetCursorInfo,
NtUserGetDisplayConfigBufferSizes,
NtUserGetIconInfo,
@ -1175,6 +1176,7 @@ static struct unix_funcs unix_funcs =
NtUserGetUpdatedClipboardFormats,
NtUserIsClipboardFormatAvailable,
NtUserMapVirtualKeyEx,
NtUserRegisterClassExWOW,
NtUserRegisterHotKey,
NtUserScrollDC,
NtUserSelectPalette,
@ -1186,6 +1188,7 @@ static struct unix_funcs unix_funcs =
NtUserSystemParametersInfo,
NtUserSystemParametersInfoForDpi,
NtUserToUnicodeEx,
NtUserUnregisterClass,
NtUserUnregisterHotKey,
NtUserVkKeyScanEx,

View file

@ -25,14 +25,18 @@
#include "ntuser.h"
#include "wine/list.h"
struct dce;
struct user_callbacks
{
HANDLE (WINAPI *pCopyImage)( HANDLE, UINT, INT, INT, UINT );
HWND (WINAPI *pGetDesktopWindow)(void);
BOOL (WINAPI *pGetWindowRect)( HWND hwnd, LPRECT rect );
BOOL (WINAPI *pIsChild)( HWND, HWND );
BOOL (WINAPI *pRedrawWindow)( HWND, const RECT*, HRGN, UINT );
LRESULT (WINAPI *pSendMessageTimeoutW)( HWND, UINT, WPARAM, LPARAM, UINT, UINT, PDWORD_PTR );
HWND (WINAPI *pWindowFromDC)( HDC );
void (WINAPI *free_dce)( struct dce *dce, HWND hwnd );
LRESULT (WINAPI *send_ll_message)( DWORD, DWORD, UINT, WPARAM, LPARAM, UINT, UINT, PDWORD_PTR );
};
@ -169,6 +173,13 @@ typedef struct tagWINDOWPROC
#define MAX_ATOM_LEN 255
/* Built-in class names (see _Undocumented_Windows_ p.418) */
#define POPUPMENU_CLASS_ATOM MAKEINTATOM(32768) /* PopupMenu */
#define DESKTOP_CLASS_ATOM MAKEINTATOM(32769) /* Desktop */
#define DIALOG_CLASS_ATOM MAKEINTATOM(32770) /* Dialog */
#define WINSWITCH_CLASS_ATOM MAKEINTATOM(32771) /* WinSwitch */
#define ICONTITLE_CLASS_ATOM MAKEINTATOM(32772) /* IconTitle */
typedef struct tagCLASS
{
struct list entry; /* Entry in class list */

View file

@ -898,7 +898,7 @@
@ stub NtUserGetCPD
@ stub NtUserGetCaretBlinkTime
@ stub NtUserGetCaretPos
@ stub NtUserGetClassInfoEx
@ stdcall NtUserGetClassInfoEx(ptr ptr ptr ptr long)
@ stdcall -syscall NtUserGetClassName(long long ptr)
@ stub NtUserGetClipCursor
@ stub NtUserGetClipboardAccessToken
@ -1122,7 +1122,7 @@
@ stub NtUserRealWaitMessageEx
@ stub NtUserRedrawWindow
@ stub NtUserRegisterBSDRWindow
@ stub NtUserRegisterClassExWOW
@ stdcall NtUserRegisterClassExWOW(ptr ptr ptr ptr long long long)
@ stub NtUserRegisterDManipHook
@ stub NtUserRegisterEdgy
@ stub NtUserRegisterErrorReportingDialog
@ -1288,7 +1288,7 @@
@ stdcall -syscall NtUserUnhookWindowsHookEx(long)
@ stub NtUserUnloadKeyboardLayout
@ stub NtUserUnlockWindowStation
@ stub NtUserUnregisterClass
@ stdcall NtUserUnregisterClass(ptr ptr ptr)
@ stdcall NtUserUnregisterHotKey(long long)
@ stub NtUserUnregisterSessionPort
@ stub NtUserUnregisterUserApiHook

View file

@ -203,6 +203,8 @@ struct unix_funcs
BOOL (WINAPI *pNtUserEnumDisplaySettings)( UNICODE_STRING *device, DWORD mode,
DEVMODEW *dev_mode, DWORD flags );
SHORT (WINAPI *pNtUserGetAsyncKeyState)( INT key );
ATOM (WINAPI *pNtUserGetClassInfoEx)( HINSTANCE instance, UNICODE_STRING *name, WNDCLASSEXW *wc,
struct client_menu_name *menu_name, BOOL ansi );
BOOL (WINAPI *pNtUserGetCursorInfo)( CURSORINFO *info );
LONG (WINAPI *pNtUserGetDisplayConfigBufferSizes)( UINT32 flags, UINT32 *num_path_info,
UINT32 *num_mode_info );
@ -215,6 +217,10 @@ struct unix_funcs
BOOL (WINAPI *pNtUserGetUpdatedClipboardFormats)( UINT *formats, UINT size, UINT *out_size );
BOOL (WINAPI *pNtUserIsClipboardFormatAvailable)( UINT format );
UINT (WINAPI *pNtUserMapVirtualKeyEx)( UINT code, UINT type, HKL layout );
ATOM (WINAPI *pNtUserRegisterClassExWOW)( const WNDCLASSEXW *wc, UNICODE_STRING *name,
UNICODE_STRING *version,
struct client_menu_name *client_menu_name,
DWORD fnid, DWORD flags, DWORD *wow );
BOOL (WINAPI *pNtUserRegisterHotKey)( HWND hwnd, INT id, UINT modifiers, UINT vk );
BOOL (WINAPI *pNtUserScrollDC)( HDC hdc, INT dx, INT dy, const RECT *scroll, const RECT *clip,
HRGN ret_update_rgn, RECT *update_rect );
@ -230,6 +236,8 @@ struct unix_funcs
UINT winini, UINT dpi );
INT (WINAPI *pNtUserToUnicodeEx)( UINT virt, UINT scan, const BYTE *state,
WCHAR *str, int size, UINT flags, HKL layout );
BOOL (WINAPI *pNtUserUnregisterClass)( UNICODE_STRING *name, HINSTANCE instance,
struct client_menu_name *client_menu_name );
BOOL (WINAPI *pNtUserUnregisterHotKey)( HWND hwnd, INT id );
WORD (WINAPI *pNtUserVkKeyScanEx)( WCHAR chr, HKL layout );

View file

@ -795,6 +795,13 @@ SHORT WINAPI NtUserGetAsyncKeyState( INT key )
return unix_funcs->pNtUserGetAsyncKeyState( key );
}
ATOM WINAPI NtUserGetClassInfoEx( HINSTANCE instance, UNICODE_STRING *name, WNDCLASSEXW *wc,
struct client_menu_name *menu_name, BOOL ansi )
{
if (!unix_funcs) return FALSE;
return unix_funcs->pNtUserGetClassInfoEx( instance, name, wc, menu_name, ansi );
}
BOOL WINAPI NtUserGetCursorInfo( CURSORINFO *info )
{
if (!unix_funcs) return FALSE;
@ -857,6 +864,14 @@ UINT WINAPI NtUserMapVirtualKeyEx( UINT code, UINT type, HKL layout )
return unix_funcs->pNtUserMapVirtualKeyEx( code, type, layout );
}
ATOM WINAPI NtUserRegisterClassExWOW( const WNDCLASSEXW *wc, UNICODE_STRING *name, UNICODE_STRING *version,
struct client_menu_name *client_menu_name, DWORD fnid, DWORD flags,
DWORD *wow )
{
if (!unix_funcs) return 0;
return unix_funcs->pNtUserRegisterClassExWOW( wc, name, version, client_menu_name, fnid, flags, wow );
}
BOOL WINAPI NtUserRegisterHotKey( HWND hwnd, INT id, UINT modifiers, UINT vk )
{
if (!unix_funcs) return FALSE;
@ -926,6 +941,13 @@ INT WINAPI NtUserToUnicodeEx( UINT virt, UINT scan, const BYTE *state,
return unix_funcs->pNtUserToUnicodeEx( virt, scan, state, str, size, flags, layout );
}
BOOL WINAPI NtUserUnregisterClass( UNICODE_STRING *name, HINSTANCE instance,
struct client_menu_name *client_menu_name )
{
if (!unix_funcs) return FALSE;
return unix_funcs->pNtUserUnregisterClass( name, instance, client_menu_name );
}
BOOL WINAPI NtUserUnregisterHotKey( HWND hwnd, INT id )
{
if (!unix_funcs) return FALSE;

View file

@ -264,6 +264,8 @@ HICON WINAPI NtUserFindExistingCursorIcon( UNICODE_STRING *module, UNICODE_STR
void *desc );
SHORT WINAPI NtUserGetAsyncKeyState( INT key );
ULONG WINAPI NtUserGetAtomName( ATOM atom, UNICODE_STRING *name );
ATOM WINAPI NtUserGetClassInfoEx( HINSTANCE instance, UNICODE_STRING *name, WNDCLASSEXW *wc,
struct client_menu_name *menu_name, BOOL ansi );
INT WINAPI NtUserGetClassName( HWND hwnd, BOOL real, UNICODE_STRING *name );
INT WINAPI NtUserGetClipboardFormatName( UINT format, WCHAR *buffer, INT maxlen );
HWND WINAPI NtUserGetClipboardOwner(void);
@ -312,6 +314,9 @@ HWINSTA WINAPI NtUserOpenWindowStation( OBJECT_ATTRIBUTES *attr, ACCESS_MASK acc
BOOL WINAPI NtUserSetObjectInformation( HANDLE handle, INT index, void *info, DWORD len );
HDESK WINAPI NtUserOpenDesktop( OBJECT_ATTRIBUTES *attr, DWORD flags, ACCESS_MASK access );
HDESK WINAPI NtUserOpenInputDesktop( DWORD flags, BOOL inherit, ACCESS_MASK access );
ATOM WINAPI NtUserRegisterClassExWOW( const WNDCLASSEXW *wc, UNICODE_STRING *name, UNICODE_STRING *version,
struct client_menu_name *client_menu_name, DWORD fnid, DWORD flags,
DWORD *wow );
BOOL WINAPI NtUserRegisterHotKey( HWND hwnd, INT id, UINT modifiers, UINT vk );
BOOL WINAPI NtUserRemoveClipboardFormatListener( HWND hwnd );
HANDLE WINAPI NtUserRemoveProp( HWND hwnd, const WCHAR *str );
@ -340,6 +345,8 @@ INT WINAPI NtUserToUnicodeEx( UINT virt, UINT scan, const BYTE *state,
WCHAR *str, int size, UINT flags, HKL layout );
BOOL WINAPI NtUserUnhookWinEvent( HWINEVENTHOOK hEventHook );
BOOL WINAPI NtUserUnhookWindowsHookEx( HHOOK handle );
BOOL WINAPI NtUserUnregisterClass( UNICODE_STRING *name, HINSTANCE instance,
struct client_menu_name *client_menu_name );
BOOL WINAPI NtUserUnregisterHotKey( HWND hwnd, INT id );
WORD WINAPI NtUserVkKeyScanEx( WCHAR chr, HKL layout );