From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/user32/static.c | 3 +-- dlls/user32/tests/class.c | 2 +- dlls/win32u/class.c | 9 +++++++++ dlls/win32u/tests/win32u.c | 4 ++-- dlls/win32u/win32u_private.h | 1 + dlls/win32u/window.c | 13 +++++++++++++ server/protocol.def | 2 ++ server/window.c | 6 ++++-- 8 files changed, 33 insertions(+), 7 deletions(-) diff --git a/dlls/user32/static.c b/dlls/user32/static.c index f36c35bcec4..7cb138c0fd3 100644 --- a/dlls/user32/static.c +++ b/dlls/user32/static.c @@ -325,6 +325,7 @@ LRESULT StaticWndProc_common( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam LONG style = full_style & SS_TYPEMASK; if (!IsWindow( hwnd )) return 0; + NtUserSetWindowFNID( hwnd, MAKE_FNID(NTUSER_WNDPROC_STATIC) ); switch (uMsg) { @@ -399,8 +400,6 @@ LRESULT StaticWndProc_common( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam { CREATESTRUCTW *cs = (CREATESTRUCTW *)lParam; - NtUserSetWindowFNID( hwnd, MAKE_FNID(NTUSER_WNDPROC_STATIC) ); - if (full_style & SS_SUNKEN || style == SS_ETCHEDHORZ || style == SS_ETCHEDVERT) SetWindowLongW( hwnd, GWL_EXSTYLE, GetWindowLongW( hwnd, GWL_EXSTYLE ) | WS_EX_STATICEDGE ); diff --git a/dlls/user32/tests/class.c b/dlls/user32/tests/class.c index 791a3e51a60..70a51178937 100644 --- a/dlls/user32/tests/class.c +++ b/dlls/user32/tests/class.c @@ -2525,7 +2525,7 @@ static const struct real_class_test class_tests[] = { "Edit", "Edit", FALSE, FALSE, TRUE, TRUE, TRUE }, { "ListBox", "ListBox", FALSE, TRUE, TRUE, TRUE, TRUE }, { "ScrollBar", "ScrollBar", FALSE, TRUE, FALSE, TRUE, TRUE }, - { "Static", "Static", TRUE, TRUE, TRUE, TRUE, TRUE }, + { "Static", "Static", TRUE, TRUE, TRUE, TRUE, FALSE }, { "ComboLBox", "ListBox", FALSE, TRUE, TRUE, TRUE, TRUE }, { "MDIClient", "MDIClient", TRUE, TRUE, TRUE, TRUE, TRUE }, { "#32768", "#32768", FALSE, FALSE, TRUE, TRUE, TRUE }, diff --git a/dlls/win32u/class.c b/dlls/win32u/class.c index 1bde8453ace..708e0f04f0c 100644 --- a/dlls/win32u/class.c +++ b/dlls/win32u/class.c @@ -889,6 +889,8 @@ INT WINAPI NtUserGetClassName( HWND hwnd, BOOL real, UNICODE_STRING *name ) WCHAR buffer[MAX_ATOM_LEN]; NTSTATUS status; UINT len = 0; + ATOM atom; + WORD fnid; int ret; TRACE( "%p %x %p\n", hwnd, real, name ); @@ -899,6 +901,13 @@ INT WINAPI NtUserGetClassName( HWND hwnd, BOOL real, UNICODE_STRING *name ) return 0; } + if (real && (fnid = get_window_fnid( hwnd )) && (fnid & 0x7fff) < ARRAY_SIZE(builtin_classes)) + { + get_desktop_window(); /* create the desktop window to trigger builtin class registration */ + atom = builtin_classes[fnid & 0x7fff].atom; + return NtUserGetAtomName( atom, name ); + } + while ((status = get_shared_window_class( hwnd, &lock, &class_shm )) == STATUS_PENDING) { len = class_shm->name_len - class_shm->name_offset * sizeof(WCHAR); diff --git a/dlls/win32u/tests/win32u.c b/dlls/win32u/tests/win32u.c index 59c2016347c..4481ffa1b32 100644 --- a/dlls/win32u/tests/win32u.c +++ b/dlls/win32u/tests/win32u.c @@ -448,10 +448,10 @@ static void test_class(void) name.Length = 0xdead; name.MaximumLength = sizeof(buf); ret = NtUserGetClassName( hwnd, TRUE, &name ); - todo_wine ok( ret == 6, "NtUserGetClassName returned %lu\n", ret ); + ok( ret == 6, "NtUserGetClassName returned %lu\n", ret ); ok( name.Length == 0xdead, "Length = %u\n", name.Length ); ok( name.MaximumLength == sizeof(buf), "MaximumLength = %u\n", name.MaximumLength ); - todo_wine ok( !wcscmp( buf, L"Static" ), "buf = %s\n", debugstr_w(buf) ); + ok( !wcscmp( buf, L"Static" ), "buf = %s\n", debugstr_w(buf) ); /* Get normal class instead of real class. */ memset( buf, 0xcc, sizeof(buf) ); diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index bf3e871ae96..be303ae4d13 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -292,6 +292,7 @@ extern BOOL is_zoomed( HWND hwnd ); extern BOOL set_window_pixel_format( HWND hwnd, int format, BOOL internal ); extern int get_window_pixel_format( HWND hwnd ); extern DWORD get_window_long( HWND hwnd, INT offset ); +extern UINT get_window_fnid( HWND hwnd ); extern ULONG_PTR get_window_long_ptr( HWND hwnd, INT offset, BOOL ansi ); extern BOOL get_window_rect( HWND hwnd, RECT *rect, UINT dpi ); enum coords_relative; diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 4d3cdd9fff4..4b53686dba1 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -1161,6 +1161,17 @@ BOOL is_zoomed( HWND hwnd ) return (get_window_long( hwnd, GWL_STYLE ) & WS_MAXIMIZE) != 0; } +UINT get_window_fnid( HWND hwnd ) +{ + struct object_lock lock = OBJECT_LOCK_INIT; + const window_shm_t *window_shm = NULL; + UINT status, fnid = 0; + + while ((status = get_shared_window( hwnd, &lock, &window_shm )) == STATUS_PENDING) + fnid = window_shm->fnid; + return status ? 0 : fnid; +} + static LONG_PTR get_window_long_size( HWND hwnd, INT offset, UINT size, BOOL ansi, BOOL internal ) { LONG_PTR retval = 0; @@ -1577,11 +1588,13 @@ BOOL WINAPI NtUserSetWindowFNID( HWND hwnd, WORD fnid ) RtlSetLastWin32Error( ERROR_INVALID_PARAMETER ); return FALSE; } + if (fnid == get_window_fnid( hwnd )) return TRUE; SERVER_START_REQ( set_window_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/protocol.def b/server/protocol.def index c24eb3d9e11..4f4f90c80e1 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 */ data_size_t private_size; /* length of private extra bytes range */ } window_shm_t; @@ -2698,6 +2699,7 @@ 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/window.c b/server/window.c index 9d0568130f8..3fa71fc3f1c 100644 --- a/server/window.c +++ b/server/window.c @@ -689,6 +689,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 = 0; shared->private_size = 0; } SHARED_WRITE_END; @@ -2285,12 +2286,13 @@ DECL_HANDLER(set_window_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->private_size) return set_error( STATUS_INVALID_PARAMETER ); + 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 ) { - shared->private_size = extra_bytes; + shared->fnid = req->fnid; + shared->private_size = extra_bytes; } SHARED_WRITE_END; release_class( class ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11012