[PATCH v2 0/5] MR10999: Draft: win32u: Move private control info to the shared memory.
-- v2: win32u: Move window info private len to window shared memory. win32u: Pass builtin class FNID to create_window. win32u: Get rid of unnecessary private_off window field. win32u: Create FNID from the ntuser_client_procs enum. win32u: Keep track of the registered builtin class atoms. https://gitlab.winehq.org/wine/wine/-/merge_requests/10999
From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/win32u/class.c | 235 +++++++++++++++++++++----------------------- 1 file changed, 113 insertions(+), 122 deletions(-) diff --git a/dlls/win32u/class.c b/dlls/win32u/class.c index 453335617d3..ac9771e8cc3 100644 --- a/dlls/win32u/class.c +++ b/dlls/win32u/class.c @@ -60,9 +60,109 @@ struct builtin_class_descr INT extra; /* window extra bytes */ ULONG_PTR cursor; /* cursor id */ HBRUSH brush; /* brush or system color */ - enum ntuser_client_procs proc; + ATOM atom; /* class atom */ }; +static struct builtin_class_descr builtin_classes[] = +{ + [NTUSER_WNDPROC_SCROLLBAR] = + { + .name = "ScrollBar", + .style = CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW | CS_PARENTDC, + .extra = sizeof(struct scroll_bar_win_data), + .cursor = IDC_ARROW, + }, + [NTUSER_WNDPROC_MESSAGE] = + { + .name = "Message", + }, + [NTUSER_WNDPROC_MENU] = + { + .name = "#32768", /* POPUPMENU_CLASS_ATOM */ + .style = CS_DROPSHADOW | CS_SAVEBITS | CS_DBLCLKS, + .extra = sizeof(HMENU), + .cursor = IDC_ARROW, + .brush = (HBRUSH)(COLOR_MENU + 1), + }, + [NTUSER_WNDPROC_DESKTOP] = + { + .name = "#32769", /* DESKTOP_CLASS_ATOM */ + .style = CS_DBLCLKS, + .brush = (HBRUSH)(COLOR_BACKGROUND + 1), + }, + [NTUSER_WNDPROC_DEFWND] = {0}, + [NTUSER_WNDPROC_ICONTITLE] = + { + .name = "#32772", /* ICONTITLE_CLASS_ATOM */ + .cursor = IDC_ARROW, + }, + [NTUSER_WNDPROC_UNKNOWN] = {0}, + [NTUSER_WNDPROC_BUTTON] = + { + .name = "Button", + .style = CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW | CS_PARENTDC, + .extra = sizeof(UINT) + 2 * sizeof(HANDLE), + .cursor = IDC_ARROW, + }, + [NTUSER_WNDPROC_COMBO] = + { + .name = "ComboBox", + .style = CS_PARENTDC | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW, + .extra = sizeof(void *), + .cursor = IDC_ARROW, + }, + [NTUSER_WNDPROC_COMBOLBOX] = + { + .name = "ComboLBox", + .style = CS_DBLCLKS | CS_SAVEBITS, + .extra = sizeof(void *), + .cursor = IDC_ARROW, + }, + [NTUSER_WNDPROC_DIALOG] = + { + .name = "#32770", /* DIALOG_CLASS_ATOM */ + .style = CS_SAVEBITS | CS_DBLCLKS, + .extra = DLGWINDOWEXTRA, + .cursor = IDC_ARROW, + }, + [NTUSER_WNDPROC_EDIT] = + { + .name = "Edit", + .style = CS_DBLCLKS | CS_PARENTDC, + .extra = sizeof(UINT64), + .cursor = IDC_IBEAM, + }, + [NTUSER_WNDPROC_LISTBOX] = + { + .name = "ListBox", + .style = CS_DBLCLKS, + .extra = sizeof(void *), + .cursor = IDC_ARROW, + }, + [NTUSER_WNDPROC_MDICLIENT] = + { + .name = "MDIClient", + .extra = 2 * sizeof(void *), + .cursor = IDC_ARROW, + .brush = (HBRUSH)(COLOR_APPWORKSPACE + 1), + }, + [NTUSER_WNDPROC_STATIC] = + { + .name = "Static", + .style = CS_DBLCLKS | CS_PARENTDC, + .extra = 2 * sizeof(HANDLE), + .cursor = IDC_ARROW, + }, + [NTUSER_WNDPROC_IME] = + { + .name = "IME", + .extra = 2 * sizeof(LONG_PTR), + .cursor = IDC_ARROW, + }, + [NTUSER_WNDPROC_GHOST] = {0}, +}; +C_ASSERT( ARRAY_SIZE(builtin_classes) == NTUSER_NB_PROCS ); + typedef struct tagWINDOWPROC { WNDPROC procA; /* ANSI window proc */ @@ -973,127 +1073,25 @@ WORD get_class_word( HWND hwnd, INT offset ) return get_class_long_size( hwnd, offset, sizeof(WORD), TRUE ); } -static const struct builtin_class_descr desktop_builtin_class = -{ - .name = "#32769", /* DESKTOP_CLASS_ATOM */ - .style = CS_DBLCLKS, - .proc = NTUSER_WNDPROC_DESKTOP, - .brush = (HBRUSH)(COLOR_BACKGROUND + 1), -}; - -static const struct builtin_class_descr message_builtin_class = -{ - .name = "Message", - .proc = NTUSER_WNDPROC_MESSAGE, -}; - -static const struct builtin_class_descr builtin_classes[] = -{ - /* button */ - { - .name = "Button", - .style = CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW | CS_PARENTDC, - .proc = NTUSER_WNDPROC_BUTTON, - .extra = sizeof(UINT) + 2 * sizeof(HANDLE), - .cursor = IDC_ARROW, - }, - /* combo */ - { - .name = "ComboBox", - .style = CS_PARENTDC | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW, - .proc = NTUSER_WNDPROC_COMBO, - .extra = sizeof(void *), - .cursor = IDC_ARROW, - }, - /* combolbox */ - { - .name = "ComboLBox", - .style = CS_DBLCLKS | CS_SAVEBITS, - .proc = NTUSER_WNDPROC_COMBOLBOX, - .extra = sizeof(void *), - .cursor = IDC_ARROW, - }, - /* dialog */ - { - .name = "#32770", /* DIALOG_CLASS_ATOM */ - .style = CS_SAVEBITS | CS_DBLCLKS, - .proc = NTUSER_WNDPROC_DIALOG, - .extra = DLGWINDOWEXTRA, - .cursor = IDC_ARROW, - }, - /* icon title */ - { - .name = "#32772", /* ICONTITLE_CLASS_ATOM */ - .proc = NTUSER_WNDPROC_ICONTITLE, - .cursor = IDC_ARROW, - }, - /* IME */ - { - .name = "IME", - .proc = NTUSER_WNDPROC_IME, - .extra = 2 * sizeof(LONG_PTR), - .cursor = IDC_ARROW, - }, - /* listbox */ - { - .name = "ListBox", - .style = CS_DBLCLKS, - .proc = NTUSER_WNDPROC_LISTBOX, - .extra = sizeof(void *), - .cursor = IDC_ARROW, - }, - /* menu */ - { - .name = "#32768", /* POPUPMENU_CLASS_ATOM */ - .style = CS_DROPSHADOW | CS_SAVEBITS | CS_DBLCLKS, - .proc = NTUSER_WNDPROC_MENU, - .extra = sizeof(HMENU), - .cursor = IDC_ARROW, - .brush = (HBRUSH)(COLOR_MENU + 1), - }, - /* MDIClient */ - { - .name = "MDIClient", - .proc = NTUSER_WNDPROC_MDICLIENT, - .extra = 2 * sizeof(void *), - .cursor = IDC_ARROW, - .brush = (HBRUSH)(COLOR_APPWORKSPACE + 1), - }, - /* scrollbar */ - { - .name = "ScrollBar", - .style = CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW | CS_PARENTDC, - .proc = NTUSER_WNDPROC_SCROLLBAR, - .extra = sizeof(struct scroll_bar_win_data), - .cursor = IDC_ARROW, - }, - /* static */ - { - .name = "Static", - .style = CS_DBLCLKS | CS_PARENTDC, - .proc = NTUSER_WNDPROC_STATIC, - .extra = 2 * sizeof(HANDLE), - .cursor = IDC_ARROW, - }, -}; - /*********************************************************************** * register_builtin * * Register a builtin control class. * This allows having both ANSI and Unicode winprocs for the same class. */ -static void register_builtin( const struct builtin_class_descr *descr ) +static void register_builtin( enum ntuser_client_procs proc ) { + struct builtin_class_descr *descr = builtin_classes + proc; UNICODE_STRING name, version = { .Length = 0 }; WCHAR nameW[64]; - WNDCLASSEXW class = { + WNDCLASSEXW class = + { .cbSize = sizeof(class), .hInstance = user32_module, .style = descr->style, .cbWndExtra = descr->extra, .hbrBackground = descr->brush, - .lpfnWndProc = BUILTIN_WINPROC( descr->proc ), + .lpfnWndProc = BUILTIN_WINPROC( proc ), }; if (descr->cursor) @@ -1103,28 +1101,21 @@ static void register_builtin( const struct builtin_class_descr *descr ) asciiz_to_unicode( nameW, descr->name ); RtlInitUnicodeString( &name, nameW ); - if (!NtUserRegisterClassExWOW( &class, &name, &version, NULL, 1, 0, NULL ) && class.hCursor) - NtUserDestroyCursor( class.hCursor, 0 ); + if ((descr->atom = NtUserRegisterClassExWOW( &class, &name, &version, NULL, 1, 0, NULL ))) return; + if (class.hCursor) NtUserDestroyCursor( class.hCursor, 0 ); } static void register_builtins(void) { + struct builtin_class_descr *edit_class = builtin_classes + NTUSER_WNDPROC_EDIT; ULONG ret_len, i; void *ret_ptr; /* 64-bit Windows use sizeof(UINT64) for all processes, while 32-bit Windows use 6 for extra * bytes size. Civilization II depends on the size being 6, so we use that even in wow64. */ - const struct builtin_class_descr edit_class = - { - .name = "Edit", - .style = CS_DBLCLKS | CS_PARENTDC, - .proc = NTUSER_WNDPROC_EDIT, - .extra = sizeof(void *) == 4 || NtCurrentTeb()->WowTebOffset ? 6 : sizeof(UINT64), - .cursor = IDC_IBEAM, - }; + if (sizeof(void *) == 4 || NtCurrentTeb()->WowTebOffset) edit_class->extra = 6; - for (i = 0; i < ARRAYSIZE(builtin_classes); i++) register_builtin( &builtin_classes[i] ); - register_builtin( &edit_class ); + for (i = 0; i < ARRAY_SIZE(builtin_classes); i++) if (builtin_classes[i].name) register_builtin( i ); KeUserModeCallback( NtUserInitBuiltinClasses, NULL, 0, &ret_ptr, &ret_len ); } @@ -1142,6 +1133,6 @@ void register_builtin_classes(void) */ void register_desktop_class(void) { - register_builtin( &desktop_builtin_class ); - register_builtin( &message_builtin_class ); + register_builtin( NTUSER_WNDPROC_DESKTOP ); + register_builtin( NTUSER_WNDPROC_MESSAGE ); } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10999
From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/user32/static.c | 2 +- dlls/win32u/class.c | 6 ++++++ dlls/win32u/ntuser_private.h | 1 + dlls/win32u/window.c | 9 ++++----- include/ntuser.h | 4 +--- server/window.c | 6 ++++-- 6 files changed, 17 insertions(+), 11 deletions(-) diff --git a/dlls/user32/static.c b/dlls/user32/static.c index 042255c0d88..f36c35bcec4 100644 --- a/dlls/user32/static.c +++ b/dlls/user32/static.c @@ -399,7 +399,7 @@ LRESULT StaticWndProc_common( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam { CREATESTRUCTW *cs = (CREATESTRUCTW *)lParam; - NtUserSetWindowFNID( hwnd, MAKE_FNID(0, HICON_GWL_OFFSET + sizeof(HANDLE)) ); + NtUserSetWindowFNID( hwnd, MAKE_FNID(NTUSER_WNDPROC_STATIC) ); if (full_style & SS_SUNKEN || style == SS_ETCHEDHORZ || style == SS_ETCHEDVERT) SetWindowLongW( hwnd, GWL_EXSTYLE, diff --git a/dlls/win32u/class.c b/dlls/win32u/class.c index ac9771e8cc3..f65da58658c 100644 --- a/dlls/win32u/class.c +++ b/dlls/win32u/class.c @@ -1073,6 +1073,12 @@ WORD get_class_word( HWND hwnd, INT offset ) return get_class_long_size( hwnd, offset, sizeof(WORD), TRUE ); } +DWORD get_builtin_class_extra( enum ntuser_client_procs proc ) +{ + get_desktop_window(); /* create the desktop window to trigger builtin class registration */ + return builtin_classes[proc].extra; +} + /*********************************************************************** * register_builtin * diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index 713d0e20524..13cbbfff3c3 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -199,6 +199,7 @@ struct dce *set_class_dce( struct tagCLASS *class, struct dce *dce ); extern atom_t wine_server_add_atom( void *req, UNICODE_STRING *str ); extern BOOL is_desktop_class( UNICODE_STRING *name ); extern BOOL is_message_class( UNICODE_STRING *name ); +extern DWORD get_builtin_class_extra( enum ntuser_client_procs proc ); extern void register_builtin_classes(void); extern void register_desktop_class(void); diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 8681a6ec128..5315644060b 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -1587,8 +1587,7 @@ LONG_PTR set_window_long( HWND hwnd, INT offset, UINT size, LONG_PTR newval, BOO */ BOOL WINAPI NtUserSetWindowFNID( HWND hwnd, WORD fnid ) { - int off = FNID_OFF(fnid); - int len = FNID_LEN(fnid); + DWORD len = get_builtin_class_extra( fnid & 0x7fff ); WND *win; BOOL ret; @@ -1608,7 +1607,7 @@ BOOL WINAPI NtUserSetWindowFNID( HWND hwnd, WORD fnid ) if (win->private_len) { - ret = win->private_off == off && win->private_len == len; + ret = win->private_off == 0 && win->private_len == len; release_win_ptr( win ); if (!ret) RtlSetLastWin32Error( ERROR_INVALID_PARAMETER ); @@ -1619,10 +1618,10 @@ BOOL WINAPI NtUserSetWindowFNID( HWND hwnd, WORD fnid ) { req->handle = wine_server_user_handle( hwnd ); req->offset = GWLP_FNID_INTERNAL; - req->new_info = fnid; + req->new_info = len; if ((ret = !wine_server_call_err( req ))) { - win->private_off = off; + win->private_off = 0; win->private_len = len; } } diff --git a/include/ntuser.h b/include/ntuser.h index ac998b2ab78..846f75b7975 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -659,9 +659,7 @@ enum wine_internal_message /* not compatible with Windows */ #define GWLP_FNID_INTERNAL (-1000) -#define MAKE_FNID(off, len) (((off) << 8) + len) -#define FNID_OFF(fnid) ((fnid) >> 8) -#define FNID_LEN(fnid) ((fnid) & 0xff) +#define MAKE_FNID(index) ((WORD)(0x8000 | (index))) /* builtin IME driver calls */ enum wine_ime_call diff --git a/server/window.c b/server/window.c index f222b5c2a59..0d5cf7d064f 100644 --- a/server/window.c +++ b/server/window.c @@ -679,6 +679,8 @@ static struct window *create_window( struct window *parent, struct window *owner win->prop_inuse = 0; win->prop_alloc = 0; win->properties = NULL; + win->private_off = 0; + win->private_len = 0; win->nb_extra_bytes = 0; win->extra_bytes = NULL; win->shared = NULL; @@ -2472,8 +2474,8 @@ DECL_HANDLER(set_window_info) win->user_data = req->new_info; break; case GWLP_FNID_INTERNAL: - win->private_off = FNID_OFF(req->new_info); - win->private_len = FNID_LEN(req->new_info); + win->private_off = 0; + win->private_len = req->new_info; break; default: if (req->size > sizeof(req->new_info) || req->offset < 0 || -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10999
From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/win32u/ntuser_private.h | 1 - dlls/win32u/window.c | 18 ++++-------------- server/window.c | 10 +--------- 3 files changed, 5 insertions(+), 24 deletions(-) diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index 13cbbfff3c3..eb612e31bc1 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -76,7 +76,6 @@ typedef struct tagWND int clip_clients; /* Has client surfaces that needs to be clipped out */ int cbWndExtra; /* class cbWndExtra at window creation */ DWORD_PTR userdata; /* User private data */ - int private_off; /* offset of private extra bytes range */ int private_len; /* length of private extra bytes range */ DWORD wExtra[1]; /* Window extra bytes */ } WND; diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 5315644060b..5832cc603f6 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -1164,11 +1164,6 @@ BOOL is_zoomed( HWND hwnd ) return (get_window_long( hwnd, GWL_STYLE ) & WS_MAXIMIZE) != 0; } -static BOOL in_private_data_range( const WND *win, INT offset, UINT size ) -{ - return offset < win->private_off + win->private_len && offset + size >= win->private_off; -} - static LONG_PTR get_window_long_size( HWND hwnd, INT offset, UINT size, BOOL ansi, BOOL internal ) { LONG_PTR retval = 0; @@ -1233,7 +1228,7 @@ static LONG_PTR get_window_long_size( HWND hwnd, INT offset, UINT size, BOOL ans if (offset >= 0) { if (offset > (int)(win->cbWndExtra - size) || - (!internal && in_private_data_range( win, offset, size ))) + (!internal && offset < win->private_len)) { WARN("Invalid offset %d\n", offset ); release_win_ptr( win ); @@ -1492,7 +1487,7 @@ static LONG_PTR set_window_long_internal( HWND hwnd, INT offset, UINT size, break; default: if (offset < 0 || offset > (int)(win->cbWndExtra - size) || - (!internal && in_private_data_range( win, offset, size ))) + (!internal && offset < win->private_len)) { WARN("Invalid offset %d\n", offset ); release_win_ptr( win ); @@ -1607,8 +1602,7 @@ BOOL WINAPI NtUserSetWindowFNID( HWND hwnd, WORD fnid ) if (win->private_len) { - ret = win->private_off == 0 && win->private_len == len; - + ret = win->private_len == len; release_win_ptr( win ); if (!ret) RtlSetLastWin32Error( ERROR_INVALID_PARAMETER ); return ret; @@ -1619,11 +1613,7 @@ BOOL WINAPI NtUserSetWindowFNID( HWND hwnd, WORD fnid ) req->handle = wine_server_user_handle( hwnd ); req->offset = GWLP_FNID_INTERNAL; req->new_info = len; - if ((ret = !wine_server_call_err( req ))) - { - win->private_off = 0; - win->private_len = len; - } + if ((ret = !wine_server_call_err( req ))) win->private_len = len; } SERVER_END_REQ; release_win_ptr( win ); diff --git a/server/window.c b/server/window.c index 0d5cf7d064f..5d2966453bf 100644 --- a/server/window.c +++ b/server/window.c @@ -92,7 +92,6 @@ struct window int prop_inuse; /* number of in-use window properties */ int prop_alloc; /* number of allocated window properties */ struct property *properties; /* window properties array */ - int private_off; /* offset of private extra bytes range */ int private_len; /* length of private extra bytes range */ int nb_extra_bytes; /* number of extra bytes */ char *extra_bytes; /* extra bytes storage */ @@ -679,7 +678,6 @@ static struct window *create_window( struct window *parent, struct window *owner win->prop_inuse = 0; win->prop_alloc = 0; win->properties = NULL; - win->private_off = 0; win->private_len = 0; win->nb_extra_bytes = 0; win->extra_bytes = NULL; @@ -2277,11 +2275,6 @@ DECL_HANDLER(create_window) reply->class_ptr = get_class_client_ptr( win->class ); } -static BOOL in_private_data_range( const struct window *win, int offset, int size ) -{ - return offset < win->private_off + win->private_len && offset + size >= win->private_off; -} - /* set the parent of a window */ DECL_HANDLER(set_parent) @@ -2406,7 +2399,7 @@ DECL_HANDLER(get_window_info) default: if (req->size > sizeof(reply->info) || req->offset < 0 || req->offset > win->nb_extra_bytes - (int)req->size || - in_private_data_range( win, req->offset, req->size )) + req->offset < win->private_len) { set_win32_error( ERROR_INVALID_INDEX ); break; @@ -2474,7 +2467,6 @@ DECL_HANDLER(set_window_info) win->user_data = req->new_info; break; case GWLP_FNID_INTERNAL: - win->private_off = 0; win->private_len = req->new_info; break; default: -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10999
From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/win32u/class.c | 11 ++++++----- server/class.c | 7 +++++++ server/protocol.def | 2 ++ server/user.h | 1 + server/window.c | 5 ++++- 5 files changed, 20 insertions(+), 6 deletions(-) diff --git a/dlls/win32u/class.c b/dlls/win32u/class.c index f65da58658c..43663797f4a 100644 --- a/dlls/win32u/class.c +++ b/dlls/win32u/class.c @@ -614,7 +614,7 @@ struct dce *set_class_dce( CLASS *class, struct dce *dce ) ATOM WINAPI NtUserRegisterClassExWOW( const WNDCLASSEXW *wc, UNICODE_STRING *name, UNICODE_STRING *version, struct client_menu_name *menu_name, DWORD fnid, DWORD flags, DWORD *wow ) { - const BOOL is_builtin = fnid, ansi = flags; + const BOOL ansi = flags; const shared_object_t *shared; struct obj_locator locator; HICON icon_internal; @@ -625,10 +625,10 @@ ATOM WINAPI NtUserRegisterClassExWOW( const WNDCLASSEXW *wc, UNICODE_STRING *nam BOOL ret; /* create the desktop window to trigger builtin class registration */ - if (!is_builtin) get_desktop_window(); + if (!fnid) get_desktop_window(); 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 */ + (!fnid && wc->hInstance == user32_module)) /* we can't register a class for user32 */ { RtlSetLastWin32Error( ERROR_INVALID_PARAMETER ); return 0; @@ -648,7 +648,7 @@ ATOM WINAPI NtUserRegisterClassExWOW( const WNDCLASSEXW *wc, UNICODE_STRING *nam if (!(class = calloc( 1, sizeof(*class) ))) return 0; - class->local = !is_builtin && !(wc->style & CS_GLOBALCLASS); + class->local = !fnid && !(wc->style & CS_GLOBALCLASS); /* Other non-null values must be set by caller */ icon_internal = wc->hIconSm ? 0 : create_small_icon( wc->hIcon ); @@ -673,6 +673,7 @@ ATOM WINAPI NtUserRegisterClassExWOW( const WNDCLASSEXW *wc, UNICODE_STRING *nam req->local = class->local; req->client_ptr = wine_server_client_ptr( class ); req->atom = wine_server_add_atom( req, name ); + req->fnid = fnid; req->name_offset = version->Length / sizeof(WCHAR); ret = !wine_server_call_err( req ); locator = reply->locator; @@ -1107,7 +1108,7 @@ static void register_builtin( enum ntuser_client_procs proc ) asciiz_to_unicode( nameW, descr->name ); RtlInitUnicodeString( &name, nameW ); - if ((descr->atom = NtUserRegisterClassExWOW( &class, &name, &version, NULL, 1, 0, NULL ))) return; + if ((descr->atom = NtUserRegisterClassExWOW( &class, &name, &version, NULL, MAKE_FNID(proc), 0, NULL ))) return; if (class.hCursor) NtUserDestroyCursor( class.hCursor, 0 ); } diff --git a/server/class.c b/server/class.c index 2ca94bca7be..fa84b363391 100644 --- a/server/class.c +++ b/server/class.c @@ -46,6 +46,7 @@ struct window_class int count; /* reference count */ int local; /* local class? */ atom_t atom; /* class atom for versioned class */ + unsigned int fnid; /* builtin control FNID, or 0 */ client_ptr_t client_ptr; /* pointer to class in client address space */ class_shm_t *shared; /* class in session shared memory */ }; @@ -159,6 +160,11 @@ atom_t get_class_atom( struct window_class *class ) return class->shared->info.atom; } +unsigned short get_class_fnid( struct window_class *class ) +{ + return class->fnid; +} + client_ptr_t get_class_client_ptr( struct window_class *class ) { return class->client_ptr; @@ -237,6 +243,7 @@ DECL_HANDLER(create_class) return; } class->atom = atom; + class->fnid = req->fnid; class->client_ptr = req->client_ptr; SHARED_WRITE_BEGIN( class->shared, class_shm_t ) diff --git a/server/protocol.def b/server/protocol.def index c2cfa64d86d..673383f7463 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1067,6 +1067,7 @@ typedef volatile struct { struct obj_locator class; /* object locator for the window class shared object */ unsigned int dpi_context; /* DPI awareness context */ + unsigned int fnid; /* builtin class FNID, or 0 */ } window_shm_t; typedef volatile union @@ -3279,6 +3280,7 @@ enum caret_state @REQ(create_class) int local; /* is it a local class? */ atom_t atom; /* class atom */ + unsigned int fnid; /* FNID for builtin classes, or 0 */ client_ptr_t client_ptr; /* pointer to class in client address space */ data_size_t name_offset; /* base class name offset for specified atom */ VARARG(info,class_info); /* class info */ diff --git a/server/user.h b/server/user.h index 060e54ec775..a985283c31b 100644 --- a/server/user.h +++ b/server/user.h @@ -196,6 +196,7 @@ extern int is_desktop_class( struct window_class *class ); extern int is_message_class( struct window_class *class ); extern int get_class_style( struct window_class *class ); extern atom_t get_class_atom( struct window_class *class ); +extern unsigned short get_class_fnid( struct window_class *class ); extern client_ptr_t get_class_client_ptr( struct window_class *class ); /* windows station functions */ diff --git a/server/window.c b/server/window.c index 5d2966453bf..f6a91466e98 100644 --- a/server/window.c +++ b/server/window.c @@ -622,6 +622,7 @@ static struct window *create_window( struct window *parent, struct window *owner struct desktop *desktop; struct window_class *class; struct obj_locator class_locator; + unsigned int fnid; if (!(desktop = get_thread_desktop( current, DESKTOP_CREATEWINDOW ))) return NULL; @@ -630,6 +631,7 @@ static struct window *create_window( struct window *parent, struct window *owner release_object( desktop ); return NULL; } + fnid = get_class_fnid( class ); if (!parent) /* null parent is only allowed for desktop or HWND_MESSAGE top window */ { @@ -678,7 +680,7 @@ static struct window *create_window( struct window *parent, struct window *owner win->prop_inuse = 0; win->prop_alloc = 0; win->properties = NULL; - win->private_len = 0; + win->private_len = fnid ? extra_bytes : 0; win->nb_extra_bytes = 0; win->extra_bytes = NULL; win->shared = NULL; @@ -691,6 +693,7 @@ static struct window *create_window( struct window *parent, struct window *owner { shared->class = class_locator; shared->dpi_context = NTUSER_DPI_PER_MONITOR_AWARE; + shared->fnid = fnid; } SHARED_WRITE_END; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10999
From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/win32u/class.c | 4 +- dlls/win32u/ntuser_private.h | 3 +- dlls/win32u/window.c | 78 +++++++++--------------------------- include/ntuser.h | 1 - server/protocol.def | 9 +++++ server/window.c | 40 +++++++++++++----- 6 files changed, 63 insertions(+), 72 deletions(-) diff --git a/dlls/win32u/class.c b/dlls/win32u/class.c index 43663797f4a..2159a6ad101 100644 --- a/dlls/win32u/class.c +++ b/dlls/win32u/class.c @@ -1074,10 +1074,10 @@ WORD get_class_word( HWND hwnd, INT offset ) return get_class_long_size( hwnd, offset, sizeof(WORD), TRUE ); } -DWORD get_builtin_class_extra( enum ntuser_client_procs proc ) +ATOM get_builtin_class_atom( enum ntuser_client_procs proc ) { get_desktop_window(); /* create the desktop window to trigger builtin class registration */ - return builtin_classes[proc].extra; + return builtin_classes[proc].atom; } /*********************************************************************** diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index eb612e31bc1..98ed3afd852 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -76,7 +76,6 @@ typedef struct tagWND int clip_clients; /* Has client surfaces that needs to be clipped out */ int cbWndExtra; /* class cbWndExtra at window creation */ DWORD_PTR userdata; /* User private data */ - int private_len; /* length of private extra bytes range */ DWORD wExtra[1]; /* Window extra bytes */ } WND; @@ -198,7 +197,7 @@ struct dce *set_class_dce( struct tagCLASS *class, struct dce *dce ); extern atom_t wine_server_add_atom( void *req, UNICODE_STRING *str ); extern BOOL is_desktop_class( UNICODE_STRING *name ); extern BOOL is_message_class( UNICODE_STRING *name ); -extern DWORD get_builtin_class_extra( enum ntuser_client_procs proc ); +extern ATOM get_builtin_class_atom( enum ntuser_client_procs proc ); extern void register_builtin_classes(void); extern void register_desktop_class(void); diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 5832cc603f6..79d2c7f168d 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -1113,26 +1113,22 @@ static HWND get_last_active_popup( HWND hwnd ) return retval; } -static LONG_PTR get_win_data( const void *ptr, UINT size ) +static BOOL get_window_extra( HWND hwnd, WND *win, INT offset, UINT size, LONG_PTR *ret, BOOL internal ) { - if (size == sizeof(WORD)) - { - WORD ret; - memcpy( &ret, ptr, sizeof(ret) ); - return ret; - } - else if (size == sizeof(DWORD)) - { - DWORD ret; - memcpy( &ret, ptr, sizeof(ret) ); - return ret; - } - else + struct object_lock lock = OBJECT_LOCK_INIT; + const window_shm_t *window_shm = NULL; + BOOL valid = FALSE; + UINT status; + + while ((status = get_shared_window( hwnd, &lock, &window_shm )) == STATUS_PENDING) { - LONG_PTR ret; - memcpy( &ret, ptr, sizeof(ret) ); - return ret; + valid = offset >= (internal ? 0 : window_shm->private_size) && offset <= (int)(win->cbWndExtra - size); + if (valid) memcpy( ret, (char *)win->wExtra + offset, size ); } + + if (status) RtlSetLastWin32Error( ERROR_INVALID_WINDOW_HANDLE ); + else if (!valid) RtlSetLastWin32Error( ERROR_INVALID_INDEX ); + return valid; } /* helper for set_window_long */ @@ -1227,15 +1223,7 @@ static LONG_PTR get_window_long_size( HWND hwnd, INT offset, UINT size, BOOL ans if (offset >= 0) { - if (offset > (int)(win->cbWndExtra - size) || - (!internal && offset < win->private_len)) - { - WARN("Invalid offset %d\n", offset ); - release_win_ptr( win ); - RtlSetLastWin32Error( ERROR_INVALID_INDEX ); - return 0; - } - retval = get_win_data( (char *)win->wExtra + offset, size ); + if (!get_window_extra( hwnd, win, offset, size, &retval, internal )) retval = 0; release_win_ptr( win ); return retval; } @@ -1486,15 +1474,12 @@ static LONG_PTR set_window_long_internal( HWND hwnd, INT offset, UINT size, case GWLP_USERDATA: break; default: - if (offset < 0 || offset > (int)(win->cbWndExtra - size) || - (!internal && offset < win->private_len)) + if (!get_window_extra( hwnd, win, offset, size, &retval, internal )) { - WARN("Invalid offset %d\n", offset ); release_win_ptr( win ); - RtlSetLastWin32Error( ERROR_INVALID_INDEX ); return 0; } - else if (get_win_data( (char *)win->wExtra + offset, size ) == newval) + if (retval == newval) { /* already set to the same value */ release_win_ptr( win ); @@ -1582,41 +1567,18 @@ LONG_PTR set_window_long( HWND hwnd, INT offset, UINT size, LONG_PTR newval, BOO */ BOOL WINAPI NtUserSetWindowFNID( HWND hwnd, WORD fnid ) { - DWORD len = get_builtin_class_extra( fnid & 0x7fff ); - WND *win; BOOL ret; TRACE( "%p %x\n", hwnd, fnid ); - if (!(win = get_win_ptr( hwnd ))) - { - RtlSetLastWin32Error( ERROR_INVALID_WINDOW_HANDLE ); - return FALSE; - } - - if (win == WND_DESKTOP || win == WND_OTHER_PROCESS) - { - RtlSetLastWin32Error( ERROR_ACCESS_DENIED ); - return FALSE; - } - - if (win->private_len) - { - ret = win->private_len == len; - release_win_ptr( win ); - if (!ret) RtlSetLastWin32Error( ERROR_INVALID_PARAMETER ); - return ret; - } - - SERVER_START_REQ( set_window_info ) + SERVER_START_REQ( set_window_fnid ) { req->handle = wine_server_user_handle( hwnd ); - req->offset = GWLP_FNID_INTERNAL; - req->new_info = len; - if ((ret = !wine_server_call_err( req ))) win->private_len = len; + req->fnid = fnid; + req->atom = get_builtin_class_atom( fnid & 0x7fff ); + ret = !wine_server_call_err( req ); } SERVER_END_REQ; - release_win_ptr( win ); return ret; } diff --git a/include/ntuser.h b/include/ntuser.h index 846f75b7975..2bbf77a4cf1 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -658,7 +658,6 @@ enum wine_internal_message #define IMN_WINE_SET_COMP_STRING 0x0010 /* not compatible with Windows */ -#define GWLP_FNID_INTERNAL (-1000) #define MAKE_FNID(index) ((WORD)(0x8000 | (index))) /* builtin IME driver calls */ diff --git a/server/protocol.def b/server/protocol.def index 673383f7463..8ccaacdd9d1 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1068,6 +1068,7 @@ typedef volatile struct struct obj_locator class; /* object locator for the window class shared object */ unsigned int dpi_context; /* DPI awareness context */ unsigned int fnid; /* builtin class FNID, or 0 */ + data_size_t private_size; /* length of private extra bytes range */ } window_shm_t; typedef volatile union @@ -2694,6 +2695,14 @@ enum message_type @END +/* Set the window builtin class FNID */ +@REQ(set_window_fnid) + user_handle_t handle; /* handle to the window */ + unsigned int fnid; /* builtin class FNID */ + atom_t atom; /* class atom */ +@END + + /* Set the parent of a window */ @REQ(set_parent) user_handle_t handle; /* handle to the window */ diff --git a/server/window.c b/server/window.c index f6a91466e98..b08b45daa30 100644 --- a/server/window.c +++ b/server/window.c @@ -92,7 +92,6 @@ struct window int prop_inuse; /* number of in-use window properties */ int prop_alloc; /* number of allocated window properties */ struct property *properties; /* window properties array */ - int private_len; /* length of private extra bytes range */ int nb_extra_bytes; /* number of extra bytes */ char *extra_bytes; /* extra bytes storage */ window_shm_t *shared; /* window in session shared memory */ @@ -680,7 +679,6 @@ static struct window *create_window( struct window *parent, struct window *owner win->prop_inuse = 0; win->prop_alloc = 0; win->properties = NULL; - win->private_len = fnid ? extra_bytes : 0; win->nb_extra_bytes = 0; win->extra_bytes = NULL; win->shared = NULL; @@ -691,9 +689,10 @@ static struct window *create_window( struct window *parent, struct window *owner if (!(win->shared = alloc_shared_object( sizeof(*win->shared) ))) goto failed; SHARED_WRITE_BEGIN( win->shared, window_shm_t ) { - shared->class = class_locator; - shared->dpi_context = NTUSER_DPI_PER_MONITOR_AWARE; - shared->fnid = fnid; + shared->class = class_locator; + shared->dpi_context = NTUSER_DPI_PER_MONITOR_AWARE; + shared->fnid = fnid; + shared->private_size = fnid ? extra_bytes : 0; } SHARED_WRITE_END; @@ -2279,6 +2278,32 @@ DECL_HANDLER(create_window) } +/* Set the window builtin class FNID */ +DECL_HANDLER(set_window_fnid) +{ + struct obj_locator class_locator; + struct window_class *class; + struct window *win; + int extra_bytes; + + if (!(win = get_window( req->handle ))) return; + if (is_desktop_window( win ) && win->thread != current) return set_error( STATUS_ACCESS_DENIED ); + if (win->shared->fnid && win->shared->fnid != req->fnid) return set_error( STATUS_INVALID_PARAMETER ); + if (!req->fnid) return set_error( STATUS_INVALID_PARAMETER ); + + if (!(class = grab_class( current->process, req->atom, 0, &extra_bytes, &class_locator ))) return; + + SHARED_WRITE_BEGIN( win->shared, window_shm_t ) + { + shared->fnid = req->fnid; + shared->private_size = extra_bytes; + } + SHARED_WRITE_END; + + release_class( class ); +} + + /* set the parent of a window */ DECL_HANDLER(set_parent) { @@ -2402,7 +2427,7 @@ DECL_HANDLER(get_window_info) default: if (req->size > sizeof(reply->info) || req->offset < 0 || req->offset > win->nb_extra_bytes - (int)req->size || - req->offset < win->private_len) + req->offset < win->shared->private_size) { set_win32_error( ERROR_INVALID_INDEX ); break; @@ -2469,9 +2494,6 @@ DECL_HANDLER(set_window_info) reply->old_info = win->user_data; win->user_data = req->new_info; break; - case GWLP_FNID_INTERNAL: - win->private_len = req->new_info; - break; default: if (req->size > sizeof(req->new_info) || req->offset < 0 || req->offset > win->nb_extra_bytes - (int)req->size) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10999
participants (2)
-
Rémi Bernon -
Rémi Bernon (@rbernon)