[PATCH 0/6] MR11044: Draft: win32u: Set builtin class FNID on window creation.
From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/win32u/class.c | 11 ++++++----- server/class.c | 2 ++ server/protocol.def | 1 + 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/dlls/win32u/class.c b/dlls/win32u/class.c index 708e0f04f0c..69e69c50b1d 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; @@ -1116,7 +1117,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..39a6ec6b818 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 */ }; @@ -237,6 +238,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 4f4f90c80e1..f8b3de0d604 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -3289,6 +3289,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 */ -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11044
From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/win32u/window.c | 1 - server/class.c | 14 +++++++++++--- server/protocol.def | 1 - server/user.h | 4 ++-- server/window.c | 20 ++++++++++++-------- 5 files changed, 25 insertions(+), 15 deletions(-) diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 4b53686dba1..3e47becca16 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -1594,7 +1594,6 @@ BOOL WINAPI NtUserSetWindowFNID( HWND hwnd, WORD fnid ) { req->handle = wine_server_user_handle( hwnd ); req->atom = get_builtin_class_atom( fnid & 0x7fff ); - req->fnid = fnid; ret = !wine_server_call_err( req ); } SERVER_END_REQ; diff --git a/server/class.c b/server/class.c index 39a6ec6b818..e505fa46e58 100644 --- a/server/class.c +++ b/server/class.c @@ -116,14 +116,12 @@ static struct window_class *find_class( struct process *process, atom_t atom, mo return NULL; } -struct window_class *grab_class( struct process *process, atom_t atom, mod_handle_t instance, - int *extra_bytes, struct obj_locator *locator ) +struct window_class *grab_class( struct process *process, atom_t atom, mod_handle_t instance, struct obj_locator *locator ) { struct window_class *class = find_class( process, atom, instance ); if (class) { class->count++; - *extra_bytes = class->shared->info.win_extra; *locator = get_shared_object_locator( class->shared ); } else set_error( STATUS_INVALID_HANDLE ); @@ -160,6 +158,16 @@ atom_t get_class_atom( struct window_class *class ) return class->shared->info.atom; } +unsigned int get_class_fnid( struct window_class *class, data_size_t *extra_size, data_size_t *private_size ) +{ + *extra_size = class->shared->info.win_extra; + + if ((class->fnid & ~0x7fff) != 0x8000) *private_size = 0; + else *private_size = *extra_size; + + return class->fnid; +} + client_ptr_t get_class_client_ptr( struct window_class *class ) { return class->client_ptr; diff --git a/server/protocol.def b/server/protocol.def index f8b3de0d604..e7d966613ac 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -2699,7 +2699,6 @@ enum message_type @REQ(set_window_fnid) user_handle_t handle; /* handle to the window */ atom_t atom; /* class atom */ - unsigned int fnid; /* builtin class FNID */ @END diff --git a/server/user.h b/server/user.h index 060e54ec775..844e31f0386 100644 --- a/server/user.h +++ b/server/user.h @@ -189,13 +189,13 @@ extern struct window_class *get_window_class( user_handle_t window ); /* window class functions */ extern void destroy_process_classes( struct process *process ); -extern struct window_class *grab_class( struct process *process, atom_t atom, mod_handle_t instance, - int *extra_bytes, struct obj_locator *locator ); +extern struct window_class *grab_class( struct process *process, atom_t atom, mod_handle_t instance, struct obj_locator *locator ); extern void release_class( struct window_class *class ); 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 int get_class_fnid( struct window_class *class, data_size_t *extra_size, data_size_t *private_size ); 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 3fa71fc3f1c..72637901a0c 100644 --- a/server/window.c +++ b/server/window.c @@ -616,7 +616,7 @@ void post_desktop_message( struct desktop *desktop, unsigned int message, static struct window *create_window( struct window *parent, struct window *owner, atom_t atom, mod_handle_t class_instance, mod_handle_t instance ) { - int extra_bytes; + data_size_t extra_bytes, private_size; struct window *win = NULL; struct desktop *desktop; struct window_class *class; @@ -624,11 +624,12 @@ static struct window *create_window( struct window *parent, struct window *owner if (!(desktop = get_thread_desktop( current, DESKTOP_CREATEWINDOW ))) return NULL; - if (!(class = grab_class( current->process, atom, class_instance, &extra_bytes, &class_locator ))) + if (!(class = grab_class( current->process, atom, class_instance, &class_locator ))) { release_object( desktop ); return NULL; } + get_class_fnid( class, &extra_bytes, &private_size ); if (!parent) /* null parent is only allowed for desktop or HWND_MESSAGE top window */ { @@ -2279,20 +2280,23 @@ DECL_HANDLER(create_window) /* Set the window builtin class FNID */ DECL_HANDLER(set_window_fnid) { + data_size_t extra_bytes, private_size; struct obj_locator class_locator; struct window_class *class; struct window *win; - int extra_bytes; + unsigned int fnid; 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 (!(class = grab_class( current->process, req->atom, 0, &extra_bytes, &class_locator ))) return; - SHARED_WRITE_BEGIN( win->shared, window_shm_t ) + if (!(class = grab_class( current->process, req->atom, 0, &class_locator ))) return; + fnid = get_class_fnid( class, &extra_bytes, &private_size ); + + if (win->shared->fnid && win->shared->fnid != fnid) set_error( STATUS_INVALID_PARAMETER ); + else SHARED_WRITE_BEGIN( win->shared, window_shm_t ) { - shared->fnid = req->fnid; - shared->private_size = extra_bytes; + shared->fnid = fnid; + shared->private_size = private_size; } SHARED_WRITE_END; release_class( class ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11044
From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/user32/menu.c | 2 ++ dlls/user32/tests/class.c | 2 +- dlls/win32u/menu.c | 31 ++++++++++++++++++++----------- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/dlls/user32/menu.c b/dlls/user32/menu.c index 00031f45730..318675428d3 100644 --- a/dlls/user32/menu.c +++ b/dlls/user32/menu.c @@ -198,6 +198,7 @@ LRESULT WINAPI PopupMenuWndProcA( HWND hwnd, UINT message, WPARAM wParam, LPARAM case WM_ERASEBKGND: case WM_SHOWWINDOW: case MN_GETHMENU: + case WM_NCCREATE: return NtUserMessageCall( hwnd, message, wParam, lParam, NULL, NtUserPopupMenuWndProc, TRUE ); @@ -223,6 +224,7 @@ LRESULT WINAPI PopupMenuWndProcW( HWND hwnd, UINT message, WPARAM wParam, LPARAM case WM_ERASEBKGND: case WM_SHOWWINDOW: case MN_GETHMENU: + case WM_NCCREATE: return NtUserMessageCall( hwnd, message, wParam, lParam, NULL, NtUserPopupMenuWndProc, FALSE ); diff --git a/dlls/user32/tests/class.c b/dlls/user32/tests/class.c index c7a99cc80d4..a41cfb1c9a5 100644 --- a/dlls/user32/tests/class.c +++ b/dlls/user32/tests/class.c @@ -2528,7 +2528,7 @@ static const struct real_class_test class_tests[] = { "Static", "Static", TRUE, TRUE, TRUE, TRUE, FALSE }, { "ComboLBox", "ListBox", FALSE, TRUE, TRUE, TRUE, FALSE }, { "MDIClient", "MDIClient", TRUE, TRUE, TRUE, TRUE, TRUE }, - { "#32768", "#32768", FALSE, FALSE, TRUE, TRUE, TRUE }, + { "#32768", "#32768", FALSE, FALSE, TRUE, TRUE, FALSE }, { "#32770", "#32770", TRUE, TRUE, TRUE, TRUE, TRUE }, /* Not all built-in classes set real window class. */ { "Message", NULL, FALSE, FALSE, FALSE, FALSE, FALSE }, diff --git a/dlls/win32u/menu.c b/dlls/win32u/menu.c index dda7d119ecc..a700f44af78 100644 --- a/dlls/win32u/menu.c +++ b/dlls/win32u/menu.c @@ -160,6 +160,16 @@ static BOOL exit_menu = FALSE; static SIZE menucharsize; static UINT od_item_height; /* default owner drawn item height */ +static HMENU get_control_menu( HWND hwnd ) +{ + return (HMENU)NtUserGetPrivateData( hwnd, 0, sizeof(HMENU) ); +} + +static HMENU set_control_menu( HWND hwnd, HMENU menu ) +{ + return (HMENU)NtUserSetPrivateData( hwnd, 0, sizeof(HMENU), (LONG_PTR)menu ); +} + /********************************************************************** * NtUserCopyAcceleratorTable (win32u.@) */ @@ -2909,7 +2919,7 @@ LRESULT popup_menu_window_proc( HWND hwnd, UINT message, WPARAM wparam, LPARAM l case WM_CREATE: { CREATESTRUCTW *cs = (CREATESTRUCTW *)lparam; - NtUserSetWindowLongPtr( hwnd, 0, (LONG_PTR)cs->lpCreateParams, FALSE ); + set_control_menu( hwnd, cs->lpCreateParams ); return 0; } @@ -2920,14 +2930,14 @@ LRESULT popup_menu_window_proc( HWND hwnd, UINT message, WPARAM wparam, LPARAM l { PAINTSTRUCT ps; NtUserBeginPaint( hwnd, &ps ); - draw_popup_menu( hwnd, ps.hdc, (HMENU)get_window_long_ptr( hwnd, 0, FALSE )); + draw_popup_menu( hwnd, ps.hdc, get_control_menu( hwnd ) ); NtUserEndPaint( hwnd, &ps ); return 0; } case WM_PRINTCLIENT: { - draw_popup_menu( hwnd, (HDC)wparam, (HMENU)get_window_long_ptr( hwnd, 0, FALSE )); + draw_popup_menu( hwnd, (HDC)wparam, get_control_menu( hwnd ) ); return 0; } @@ -2944,17 +2954,16 @@ LRESULT popup_menu_window_proc( HWND hwnd, UINT message, WPARAM wparam, LPARAM l break; case WM_SHOWWINDOW: - if (wparam) - { - if (!get_window_long_ptr( hwnd, 0, FALSE )) ERR( "no menu to display\n" ); - } - else - NtUserSetWindowLongPtr( hwnd, 0, 0, FALSE ); + if (!wparam) NtUserSetPrivateData( hwnd, 0, sizeof(LONG_PTR), 0 ); + else if (!get_control_menu( hwnd )) ERR( "no menu to display\n" ); break; case MN_GETHMENU: - return get_window_long_ptr( hwnd, 0, FALSE ); + return (LRESULT)get_control_menu( hwnd ); + case WM_NCCREATE: + NtUserSetWindowFNID( hwnd, MAKE_FNID(NTUSER_WNDPROC_MENU) ); + /* fallthrough */ default: return default_window_proc( hwnd, message, wparam, lparam, ansi ); } @@ -4599,7 +4608,7 @@ BOOL WINAPI NtUserGetMenuBarInfo( HWND hwnd, LONG id, LONG item, MENUBARINFO *in return FALSE; } - hmenu = (HMENU)get_window_long_ptr( hwnd, 0, FALSE ); + hmenu = get_control_menu( hwnd ); break; case OBJID_MENU: hmenu = get_menu( hwnd ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11044
From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/user32/mdi.c | 2 ++ dlls/user32/tests/class.c | 2 +- server/class.c | 6 +++++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/dlls/user32/mdi.c b/dlls/user32/mdi.c index d19990fbdb0..7e6a6054b18 100644 --- a/dlls/user32/mdi.c +++ b/dlls/user32/mdi.c @@ -993,6 +993,8 @@ LRESULT MDIClientWndProc_common( HWND hwnd, UINT message, WPARAM wParam, LPARAM TRACE("%p %04x (%s) %08Ix %08Ix\n", hwnd, message, SPY_GetMsgName(message, hwnd), wParam, lParam); + NtUserSetWindowFNID( hwnd, MAKE_FNID(NTUSER_WNDPROC_MDICLIENT) ); + if (!(ci = get_client_info( hwnd ))) { if (message == WM_NCCREATE) diff --git a/dlls/user32/tests/class.c b/dlls/user32/tests/class.c index a41cfb1c9a5..5588ab781e3 100644 --- a/dlls/user32/tests/class.c +++ b/dlls/user32/tests/class.c @@ -2527,7 +2527,7 @@ static const struct real_class_test class_tests[] = { "ScrollBar", "ScrollBar", FALSE, TRUE, FALSE, TRUE, TRUE }, { "Static", "Static", TRUE, TRUE, TRUE, TRUE, FALSE }, { "ComboLBox", "ListBox", FALSE, TRUE, TRUE, TRUE, FALSE }, - { "MDIClient", "MDIClient", TRUE, TRUE, TRUE, TRUE, TRUE }, + { "MDIClient", "MDIClient", TRUE, TRUE, TRUE, TRUE, FALSE }, { "#32768", "#32768", FALSE, FALSE, TRUE, TRUE, FALSE }, { "#32770", "#32770", TRUE, TRUE, TRUE, TRUE, TRUE }, /* Not all built-in classes set real window class. */ diff --git a/server/class.c b/server/class.c index e505fa46e58..95defe8b9ba 100644 --- a/server/class.c +++ b/server/class.c @@ -163,7 +163,11 @@ unsigned int get_class_fnid( struct window_class *class, data_size_t *extra_size *extra_size = class->shared->info.win_extra; if ((class->fnid & ~0x7fff) != 0x8000) *private_size = 0; - else *private_size = *extra_size; + else switch (class->fnid & 0x7fff) + { + case NTUSER_WNDPROC_MDICLIENT: *private_size = 0; break; + default: *private_size = *extra_size; break; + } return class->fnid; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11044
From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/user32/defdlg.c | 4 ++++ dlls/user32/tests/class.c | 2 +- server/class.c | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/dlls/user32/defdlg.c b/dlls/user32/defdlg.c index 1b50893c041..69c573c61c0 100644 --- a/dlls/user32/defdlg.c +++ b/dlls/user32/defdlg.c @@ -316,6 +316,8 @@ static LRESULT USER_DefDlgProcA( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPar DIALOGINFO *dlgInfo; LRESULT result; + NtUserSetWindowFNID( hwnd, MAKE_FNID(NTUSER_WNDPROC_DIALOG) ); + /* Perform DIALOGINFO initialization if not done */ if(!(dlgInfo = DIALOG_get_info( hwnd, TRUE ))) return 0; @@ -368,6 +370,8 @@ static LRESULT USER_DefDlgProcW( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPar DIALOGINFO *dlgInfo; LRESULT result; + NtUserSetWindowFNID( hwnd, MAKE_FNID(NTUSER_WNDPROC_DIALOG) ); + /* Perform DIALOGINFO initialization if not done */ if(!(dlgInfo = DIALOG_get_info( hwnd, TRUE ))) return 0; diff --git a/dlls/user32/tests/class.c b/dlls/user32/tests/class.c index 5588ab781e3..a554891f4a6 100644 --- a/dlls/user32/tests/class.c +++ b/dlls/user32/tests/class.c @@ -2529,7 +2529,7 @@ static const struct real_class_test class_tests[] = { "ComboLBox", "ListBox", FALSE, TRUE, TRUE, TRUE, FALSE }, { "MDIClient", "MDIClient", TRUE, TRUE, TRUE, TRUE, FALSE }, { "#32768", "#32768", FALSE, FALSE, TRUE, TRUE, FALSE }, - { "#32770", "#32770", TRUE, TRUE, TRUE, TRUE, TRUE }, + { "#32770", "#32770", TRUE, TRUE, TRUE, TRUE, FALSE }, /* Not all built-in classes set real window class. */ { "Message", NULL, FALSE, FALSE, FALSE, FALSE, FALSE }, }; diff --git a/server/class.c b/server/class.c index 95defe8b9ba..a3e1b85bc80 100644 --- a/server/class.c +++ b/server/class.c @@ -165,6 +165,7 @@ unsigned int get_class_fnid( struct window_class *class, data_size_t *extra_size if ((class->fnid & ~0x7fff) != 0x8000) *private_size = 0; else switch (class->fnid & 0x7fff) { + case NTUSER_WNDPROC_DIALOG: *private_size = 0; break; case NTUSER_WNDPROC_MDICLIENT: *private_size = 0; break; default: *private_size = *extra_size; break; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11044
From: Rémi Bernon <rbernon@codeweavers.com> --- server/window.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/server/window.c b/server/window.c index 72637901a0c..897034159a9 100644 --- a/server/window.c +++ b/server/window.c @@ -621,6 +621,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; @@ -629,7 +630,7 @@ static struct window *create_window( struct window *parent, struct window *owner release_object( desktop ); return NULL; } - get_class_fnid( class, &extra_bytes, &private_size ); + fnid = get_class_fnid( class, &extra_bytes, &private_size ); if (!parent) /* null parent is only allowed for desktop or HWND_MESSAGE top window */ { @@ -690,8 +691,8 @@ 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 = 0; - shared->private_size = 0; + shared->fnid = fnid; + shared->private_size = private_size; } SHARED_WRITE_END; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11044
This merge request was approved by Elizabeth Figura. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11044
participants (3)
-
Elizabeth Figura (@zfigura) -
Rémi Bernon -
Rémi Bernon (@rbernon)