From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/user32/static.c | 2 +- dlls/user32/user_private.h | 8 +-- dlls/win32u/ntuser_private.h | 2 - dlls/win32u/window.c | 109 ++++++++++++++--------------------- include/ntuser.h | 22 ++----- server/protocol.def | 18 ++++++ server/window.c | 43 +++++++++----- 7 files changed, 101 insertions(+), 103 deletions(-) diff --git a/dlls/user32/static.c b/dlls/user32/static.c index 415a8033d74..09a227c1209 100644 --- a/dlls/user32/static.c +++ b/dlls/user32/static.c @@ -394,7 +394,7 @@ LRESULT StaticWndProc_common( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam { CREATESTRUCTW *cs = (CREATESTRUCTW *)lParam; - NtUserSetWindowFNID( hwnd, MAKE_FNID(0, sizeof(HFONT) + 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/user32/user_private.h b/dlls/user32/user_private.h index 6b48c311a5a..90b45d90fb0 100644 --- a/dlls/user32/user_private.h +++ b/dlls/user32/user_private.h @@ -190,22 +190,22 @@ static inline void mirror_rect( const RECT *window_rect, RECT *rect ) static inline HANDLE get_control_icon( HWND hwnd ) { - return (HANDLE)NtUserGetPrivateData( hwnd, sizeof(HFONT), sizeof(HICON) ); + return UlongToHandle(NtUserGetPrivateData( hwnd, 8 )); } static inline HANDLE set_control_icon( HWND hwnd, HANDLE icon ) { - return (HANDLE)NtUserSetPrivateData( hwnd, sizeof(HFONT), sizeof(icon), (LONG_PTR)icon ); + return UlongToHandle(NtUserSetPrivateData( hwnd, 8, (LONG_PTR)icon )); } static inline HFONT get_control_font( HWND hwnd ) { - return (HFONT)NtUserGetPrivateData( hwnd, 0, sizeof(HFONT) ); + return UlongToHandle(NtUserGetPrivateData( hwnd, 4 )); } static inline HFONT set_control_font( HWND hwnd, HFONT font ) { - return (HFONT)NtUserSetPrivateData( hwnd, 0, sizeof(font), (LONG_PTR)font ); + return UlongToHandle(NtUserSetPrivateData( hwnd, 4, (LONG_PTR)font )); } #endif /* __WINE_USER_PRIVATE_H */ diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index 713d0e20524..2478da71ae6 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -76,8 +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 8681a6ec128..11ccd55b137 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -29,7 +29,6 @@ #include "ntgdi_private.h" #include "ntuser_private.h" #include "wine/opengl_driver.h" -#include "wine/server.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(win); @@ -1164,12 +1163,26 @@ 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 ) +static UINT get_control_info( HWND hwnd, INT offset ) { - return offset < win->private_off + win->private_len && offset + size >= win->private_off; + struct object_lock lock = OBJECT_LOCK_INIT; + const window_shm_t *window_shm = NULL; + NTSTATUS status; + WORD fnid = 0; + UINT ret = 0; + + if (offset > sizeof(struct control_info) - sizeof(ret)) return 0; + + while ((status = get_shared_window( hwnd, &lock, &window_shm )) == STATUS_PENDING) + { + memcpy( &ret, (char *)&window_shm->control + offset, sizeof(ret) ); + fnid = window_shm->control.fnid; + } + + return !status && fnid ? ret : 0; } -static LONG_PTR get_window_long_size( HWND hwnd, INT offset, UINT size, BOOL ansi, BOOL internal ) +static LONG_PTR get_window_long_size( HWND hwnd, INT offset, UINT size, BOOL ansi ) { LONG_PTR retval = 0; WND *win; @@ -1232,8 +1245,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 ))) + if (offset > (int)(win->cbWndExtra - size)) { WARN("Invalid offset %d\n", offset ); release_win_ptr( win ); @@ -1274,13 +1286,13 @@ static LONG_PTR get_window_long_size( HWND hwnd, INT offset, UINT size, BOOL ans /* see GetWindowLongW */ DWORD get_window_long( HWND hwnd, INT offset ) { - return get_window_long_size( hwnd, offset, sizeof(LONG), FALSE, FALSE ); + return get_window_long_size( hwnd, offset, sizeof(LONG), FALSE ); } /* see GetWindowLongPtr */ ULONG_PTR get_window_long_ptr( HWND hwnd, INT offset, BOOL ansi ) { - return get_window_long_size( hwnd, offset, sizeof(LONG_PTR), ansi, FALSE ); + return get_window_long_size( hwnd, offset, sizeof(LONG_PTR), ansi ); } /* see GetWindowWord */ @@ -1291,7 +1303,7 @@ static WORD get_window_word( HWND hwnd, INT offset ) RtlSetLastWin32Error( ERROR_INVALID_INDEX ); return 0; } - return get_window_long_size( hwnd, offset, sizeof(WORD), TRUE, FALSE ); + return get_window_long_size( hwnd, offset, sizeof(WORD), TRUE ); } UINT set_window_style_bits( HWND hwnd, UINT set_bits, UINT clear_bits ) @@ -1390,9 +1402,25 @@ static HWND set_window_owner( HWND hwnd, HWND owner ) return ret; } +static UINT server_set_control_info( HWND hwnd, UINT offset, UINT newval ) +{ + UINT ret; + + SERVER_START_REQ( set_control_info ) + { + req->handle = wine_server_user_handle( hwnd ); + req->offset = offset; + req->new_info = newval; + wine_server_call_err( req ); + ret = reply->old_info; + } + SERVER_END_REQ; + + return ret; +} + /* Helper function for SetWindowLong(). */ -static LONG_PTR set_window_long_internal( HWND hwnd, INT offset, UINT size, - LONG_PTR newval, BOOL ansi, BOOL internal ) +LONG_PTR set_window_long( HWND hwnd, INT offset, UINT size, LONG_PTR newval, BOOL ansi ) { BOOL ok, made_visible = FALSE, layered = FALSE; LONG_PTR retval = 0; @@ -1491,8 +1519,7 @@ 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 && in_private_data_range( win, offset, size ))) + if (offset < 0 || offset > (int)(win->cbWndExtra - size)) { WARN("Invalid offset %d\n", offset ); release_win_ptr( win ); @@ -1575,11 +1602,6 @@ static LONG_PTR set_window_long_internal( HWND hwnd, INT offset, UINT size, return retval; } -LONG_PTR set_window_long( HWND hwnd, INT offset, UINT size, LONG_PTR newval, BOOL ansi ) -{ - return set_window_long_internal( hwnd, offset, size, newval, ansi, FALSE ); -} - /********************************************************************** * NtUserSetWindowFNID (win32u.@) * @@ -1587,48 +1609,8 @@ 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); - 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_off == off && win->private_len == len; - - release_win_ptr( win ); - if (!ret) RtlSetLastWin32Error( ERROR_INVALID_PARAMETER ); - return ret; - } - - SERVER_START_REQ( set_window_info ) - { - req->handle = wine_server_user_handle( hwnd ); - req->offset = GWLP_FNID_INTERNAL; - req->new_info = fnid; - if ((ret = !wine_server_call_err( req ))) - { - win->private_off = off; - win->private_len = len; - } - } - SERVER_END_REQ; - release_win_ptr( win ); - return ret; + return server_set_control_info( hwnd, offsetof(struct control_info, fnid), fnid ); } /********************************************************************** @@ -6201,7 +6183,7 @@ ULONG_PTR WINAPI NtUserCallHwndParam( HWND hwnd, DWORD_PTR param, DWORD code ) return get_window_info( hwnd, (WINDOWINFO *)param ); case NtUserCallHwndParam_GetWindowLongA: - return get_window_long_size( hwnd, param, sizeof(LONG), TRUE, FALSE ); + return get_window_long_size( hwnd, param, sizeof(LONG), TRUE ); case NtUserCallHwndParam_GetWindowLongW: return get_window_long( hwnd, param ); @@ -6287,15 +6269,12 @@ ULONG_PTR WINAPI NtUserCallHwndParam( HWND hwnd, DWORD_PTR param, DWORD code ) } case NtUserCallHwndParam_GetPrivateData: - { - struct get_private_data_params *params = (void *)param; - return get_window_long_size( hwnd, params->offset, params->size, FALSE, TRUE ); - } + return get_control_info( hwnd, param ); case NtUserCallHwndParam_SetPrivateData: { struct set_private_data_params *params = (void *)param; - return set_window_long_internal( hwnd, params->offset, params->size, params->value, FALSE, TRUE ); + return server_set_control_info( hwnd, params->offset, params->value ); } default: diff --git a/include/ntuser.h b/include/ntuser.h index ac998b2ab78..bbd35a6711a 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 @@ -1647,28 +1645,20 @@ static inline BOOL NtUserSetRawWindowPos( HWND hwnd, RECT rect, UINT flags, BOOL return NtUserCallHwndParam( hwnd, (UINT_PTR)¶ms, NtUserCallHwndParam_SetRawWindowPos ); } -struct get_private_data_params +static inline ULONG NtUserGetPrivateData( HWND hwnd, UINT offset ) { - UINT offset; - UINT size; -}; - -static inline LONG_PTR NtUserGetPrivateData( HWND hwnd, UINT offset, UINT size ) -{ - struct get_private_data_params params = { .offset = offset, .size = size }; - return NtUserCallHwndParam( hwnd, (UINT_PTR)¶ms, NtUserCallHwndParam_GetPrivateData ); + return NtUserCallHwndParam( hwnd, offset, NtUserCallHwndParam_GetPrivateData ); } struct set_private_data_params { UINT offset; - UINT size; - LONG64 value; + ULONG value; }; -static inline LONG_PTR NtUserSetPrivateData( HWND hwnd, UINT offset, UINT size, LONG_PTR value ) +static inline ULONG NtUserSetPrivateData( HWND hwnd, UINT offset, ULONG value ) { - struct set_private_data_params params = { .offset = offset, .size = size, .value = value }; + struct set_private_data_params params = { .offset = offset, .value = value }; return NtUserCallHwndParam( hwnd, (UINT_PTR)¶ms, NtUserCallHwndParam_SetPrivateData ); } diff --git a/server/protocol.def b/server/protocol.def index c2cfa64d86d..7bc7c478fc8 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1063,10 +1063,18 @@ typedef volatile struct char extra[]; /* extra bytes storage */ } class_shm_t; +struct control_info +{ + unsigned int fnid; /* builtin control FNID, or 0 */ + user_handle_t font; /* control font handle */ + user_handle_t icon; /* control icon handle */ +}; + typedef volatile struct { struct obj_locator class; /* object locator for the window class shared object */ unsigned int dpi_context; /* DPI awareness context */ + struct control_info control; /* private control info */ } window_shm_t; typedef volatile union @@ -2693,6 +2701,16 @@ enum message_type @END +/* Set control window private info */ +@REQ(set_control_info) + user_handle_t handle; /* handle to the window */ + unsigned int offset; /* offset of the info */ + unsigned int new_info; /* new control info value */ +@REPLY + unsigned int old_info; /* old control info value */ +@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 f222b5c2a59..2a42e5333d3 100644 --- a/server/window.c +++ b/server/window.c @@ -92,8 +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 */ window_shm_t *shared; /* window in session shared memory */ @@ -689,8 +687,11 @@ 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->class = class_locator; + shared->dpi_context = NTUSER_DPI_PER_MONITOR_AWARE; + shared->control.fnid = 0; + shared->control.icon = 0; + shared->control.font = 0; } SHARED_WRITE_END; @@ -2275,11 +2276,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) @@ -2403,8 +2399,7 @@ DECL_HANDLER(get_window_info) case GWLP_USERDATA: reply->info = win->user_data; break; 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->nb_extra_bytes - (int)req->size) { set_win32_error( ERROR_INVALID_INDEX ); break; @@ -2471,10 +2466,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_off = FNID_OFF(req->new_info); - win->private_len = FNID_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) @@ -2489,6 +2480,28 @@ DECL_HANDLER(set_window_info) } +/* set control window private info */ +DECL_HANDLER(set_control_info) +{ + struct window *win; + unsigned int fnid; + + if (!(win = get_window( req->handle ))) return; + fnid = win->shared->control.fnid; + + if (is_desktop_window( win ) && win->thread != current) return set_error( STATUS_ACCESS_DENIED ); + if (req->offset > sizeof(struct control_info) - sizeof(req->new_info)) return set_error( STATUS_INVALID_PARAMETER ); + if (req->offset == offsetof(struct control_info, fnid) ? fnid : !fnid) return set_error( STATUS_INVALID_PARAMETER ); + + SHARED_WRITE_BEGIN( win->shared, window_shm_t ) + { + memcpy( &reply->old_info, (char *)&shared->control + req->offset, sizeof(reply->old_info) ); + memcpy( (char *)&shared->control + req->offset, &req->new_info, sizeof(req->new_info) ); + } + SHARED_WRITE_END; +} + + /* get a list of the window parents, up to the root of the tree */ DECL_HANDLER(get_window_parents) { -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10999