[PATCH 0/5] MR10999: win32u: Move private control info to the shared memory.
From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/user32/static.c | 29 ++++++++++++----------------- dlls/user32/user_private.h | 20 ++++++++++++++++++++ 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/dlls/user32/static.c b/dlls/user32/static.c index 042255c0d88..415a8033d74 100644 --- a/dlls/user32/static.c +++ b/dlls/user32/static.c @@ -49,10 +49,6 @@ static void STATIC_PaintEtchedfn( HWND hwnd, HDC hdc, HBRUSH hbrush, DWORD style static COLORREF color_3dshadow, color_3ddkshadow, color_3dhighlight; -/* offsets for GetWindowLong for static private information */ -#define HFONT_GWL_OFFSET 0 -#define HICON_GWL_OFFSET (sizeof(HFONT)) - typedef void (*pfPaint)( HWND hwnd, HDC hdc, HBRUSH hbrush, DWORD style ); static const pfPaint staticPaintFunc[SS_TYPEMASK+1] = @@ -94,7 +90,7 @@ static HICON STATIC_SetIcon( HWND hwnd, HICON hicon, DWORD style ) WARN("hicon != 0, but invalid\n"); return 0; } - prevIcon = (HICON)NtUserSetPrivateData( hwnd, HICON_GWL_OFFSET, sizeof(hicon), (LONG_PTR)hicon ); + prevIcon = set_control_icon( hwnd, hicon ); if (hicon && !(style & SS_CENTERIMAGE) && !(style & SS_REALSIZECONTROL)) { /* Windows currently doesn't implement SS_RIGHTJUST */ @@ -127,7 +123,7 @@ static HBITMAP STATIC_SetBitmap( HWND hwnd, HBITMAP hBitmap, DWORD style ) WARN("hBitmap != 0, but it's not a bitmap\n"); return 0; } - hOldBitmap = (HBITMAP)NtUserSetPrivateData( hwnd, HICON_GWL_OFFSET, sizeof(hBitmap), (LONG_PTR)hBitmap ); + hOldBitmap = set_control_icon( hwnd, hBitmap ); if (hBitmap && !(style & SS_CENTERIMAGE) && !(style & SS_REALSIZECONTROL)) { BITMAP bm; @@ -162,8 +158,7 @@ static HENHMETAFILE STATIC_SetEnhMetaFile( HWND hwnd, HENHMETAFILE hEnhMetaFile, WARN("hEnhMetaFile != 0, but it's not an enhanced metafile\n"); return 0; } - return (HENHMETAFILE)NtUserSetPrivateData( hwnd, HICON_GWL_OFFSET, sizeof(hEnhMetaFile), - (LONG_PTR)hEnhMetaFile ); + return set_control_icon( hwnd, hEnhMetaFile ); } /*********************************************************************** @@ -189,7 +184,7 @@ static HANDLE STATIC_GetImage( HWND hwnd, WPARAM wParam, DWORD style ) default: return NULL; } - return (HANDLE)NtUserGetPrivateData( hwnd, HICON_GWL_OFFSET, sizeof(HANDLE) ); + return get_control_icon( hwnd ); } /*********************************************************************** @@ -399,7 +394,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(0, sizeof(HFONT) + sizeof(HANDLE)) ); if (full_style & SS_SUNKEN || style == SS_ETCHEDHORZ || style == SS_ETCHEDVERT) SetWindowLongW( hwnd, GWL_EXSTYLE, @@ -487,7 +482,7 @@ LRESULT StaticWndProc_common( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam case WM_SETFONT: if (hasTextStyle( full_style )) { - NtUserSetPrivateData( hwnd, HFONT_GWL_OFFSET, sizeof(HFONT), wParam ); + set_control_font( hwnd, (HFONT)wParam ); if (LOWORD(lParam)) NtUserRedrawWindow( hwnd, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_ALLCHILDREN ); @@ -495,7 +490,7 @@ LRESULT StaticWndProc_common( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam break; case WM_GETFONT: - return NtUserGetPrivateData( hwnd, HFONT_GWL_OFFSET, sizeof(HFONT) ); + return (LRESULT)get_control_font( hwnd ); case WM_NCHITTEST: if (full_style & SS_NOTIFY) @@ -577,7 +572,7 @@ static void STATIC_PaintOwnerDrawfn( HWND hwnd, HDC hdc, HBRUSH hbrush, DWORD st dis.itemData = 0; GetClientRect( hwnd, &dis.rcItem ); - font = (HFONT)NtUserGetPrivateData( hwnd, HFONT_GWL_OFFSET, sizeof(HFONT) ); + font = get_control_font( hwnd ); if (font) oldFont = SelectObject( hdc, font ); SendMessageW( GetParent(hwnd), WM_DRAWITEM, id, (LPARAM)&dis ); if (font) SelectObject( hdc, oldFont ); @@ -639,7 +634,7 @@ static void STATIC_PaintTextfn( HWND hwnd, HDC hdc, HBRUSH hbrush, DWORD style ) format |= DT_SINGLELINE | DT_WORD_ELLIPSIS; } - if ((hFont = (HFONT)NtUserGetPrivateData( hwnd, HFONT_GWL_OFFSET, sizeof(HFONT) ))) + if ((hFont = get_control_font( hwnd ))) hOldFont = SelectObject( hdc, hFont ); if ((style & SS_TYPEMASK) != SS_SIMPLE) @@ -728,7 +723,7 @@ static void STATIC_PaintIconfn( HWND hwnd, HDC hdc, HBRUSH hbrush, DWORD style ) SIZE size; GetClientRect( hwnd, &rc ); - hIcon = (HICON)NtUserGetPrivateData( hwnd, HICON_GWL_OFFSET, sizeof(hIcon) ); + hIcon = get_control_icon( hwnd ); if (!hIcon || !get_icon_size( hIcon, &size )) { FillRect(hdc, &rc, hbrush); @@ -755,7 +750,7 @@ static void STATIC_PaintBitmapfn(HWND hwnd, HDC hdc, HBRUSH hbrush, DWORD style HDC hMemDC; HBITMAP hBitmap, oldbitmap; - if ((hBitmap = (HBITMAP)NtUserGetPrivateData( hwnd, HICON_GWL_OFFSET, sizeof(hBitmap) )) + if ((hBitmap = get_control_icon( hwnd )) && (GetObjectType(hBitmap) == OBJ_BITMAP) && (hMemDC = CreateCompatibleDC( hdc ))) { @@ -795,7 +790,7 @@ static void STATIC_PaintEnhMetafn(HWND hwnd, HDC hdc, HBRUSH hbrush, DWORD style GetClientRect(hwnd, &rc); FillRect(hdc, &rc, hbrush); - if ((hEnhMetaFile = (HENHMETAFILE)NtUserGetPrivateData( hwnd, HICON_GWL_OFFSET, sizeof(hEnhMetaFile) ))) + if ((hEnhMetaFile = get_control_icon( hwnd ))) { /* The control's current font is not selected into the device context! */ diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h index abb84b0e880..6b48c311a5a 100644 --- a/dlls/user32/user_private.h +++ b/dlls/user32/user_private.h @@ -188,4 +188,24 @@ static inline void mirror_rect( const RECT *window_rect, RECT *rect ) rect->right = width - tmp; } +static inline HANDLE get_control_icon( HWND hwnd ) +{ + return (HANDLE)NtUserGetPrivateData( hwnd, sizeof(HFONT), sizeof(HICON) ); +} + +static inline HANDLE set_control_icon( HWND hwnd, HANDLE icon ) +{ + return (HANDLE)NtUserSetPrivateData( hwnd, sizeof(HFONT), sizeof(icon), (LONG_PTR)icon ); +} + +static inline HFONT get_control_font( HWND hwnd ) +{ + return (HFONT)NtUserGetPrivateData( hwnd, 0, sizeof(HFONT) ); +} + +static inline HFONT set_control_font( HWND hwnd, HFONT font ) +{ + return (HFONT)NtUserSetPrivateData( hwnd, 0, sizeof(font), (LONG_PTR)font ); +} + #endif /* __WINE_USER_PRIVATE_H */ -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10999
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
From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/win32u/class.c | 13 +++++++------ server/class.c | 7 +++++++ server/protocol.def | 1 + server/user.h | 1 + server/window.c | 2 +- 5 files changed, 17 insertions(+), 7 deletions(-) diff --git a/dlls/win32u/class.c b/dlls/win32u/class.c index 453335617d3..d639f0f1cef 100644 --- a/dlls/win32u/class.c +++ b/dlls/win32u/class.c @@ -514,7 +514,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; @@ -525,10 +525,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; @@ -548,7 +548,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 ); @@ -573,6 +573,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; @@ -1103,8 +1104,8 @@ 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 (NtUserRegisterClassExWOW( &class, &name, &version, NULL, MAKE_FNID(descr->proc), 0, NULL )) return; + if (class.hCursor) NtUserDestroyCursor( class.hCursor, 0 ); } static void register_builtins(void) 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 7bc7c478fc8..d917a50fc33 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -3297,6 +3297,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 2a42e5333d3..e5a87c1bd6e 100644 --- a/server/window.c +++ b/server/window.c @@ -689,7 +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->control.fnid = 0; + shared->control.fnid = get_class_fnid( class ); shared->control.icon = 0; shared->control.font = 0; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10999
From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/user32/user_private.h | 8 ++++---- dlls/win32u/window.c | 35 +++++++++++++++++++---------------- include/ntuser.h | 23 ++++------------------- 3 files changed, 27 insertions(+), 39 deletions(-) diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h index 90b45d90fb0..1302d8decd9 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 UlongToHandle(NtUserGetPrivateData( hwnd, 8 )); + return (HANDLE)NtUserCallHwndParam( hwnd, 0, NtUserCallHwndParam_GetControlIcon ); } static inline HANDLE set_control_icon( HWND hwnd, HANDLE icon ) { - return UlongToHandle(NtUserSetPrivateData( hwnd, 8, (LONG_PTR)icon )); + return (HANDLE)NtUserCallHwndParam( hwnd, (LONG_PTR)icon, NtUserCallHwndParam_SetControlIcon ); } static inline HFONT get_control_font( HWND hwnd ) { - return UlongToHandle(NtUserGetPrivateData( hwnd, 4 )); + return (HFONT)NtUserCallHwndParam( hwnd, 0, NtUserCallHwndParam_GetControlFont ); } static inline HFONT set_control_font( HWND hwnd, HFONT font ) { - return UlongToHandle(NtUserSetPrivateData( hwnd, 4, (LONG_PTR)font )); + return (HFONT)NtUserCallHwndParam( hwnd, (LONG_PTR)font, NtUserCallHwndParam_SetControlFont ); } #endif /* __WINE_USER_PRIVATE_H */ diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 11ccd55b137..92b22da29c0 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -1163,23 +1163,15 @@ BOOL is_zoomed( HWND hwnd ) return (get_window_long( hwnd, GWL_STYLE ) & WS_MAXIMIZE) != 0; } -static UINT get_control_info( HWND hwnd, INT offset ) +static void get_control_info( HWND hwnd, struct control_info *info ) { 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; + *info = window_shm->control; + if (status || !info->fnid) memset( info, 0, sizeof(*info) ); } static LONG_PTR get_window_long_size( HWND hwnd, INT offset, UINT size, BOOL ansi ) @@ -6268,15 +6260,26 @@ ULONG_PTR WINAPI NtUserCallHwndParam( HWND hwnd, DWORD_PTR param, DWORD code ) return set_raw_window_pos( hwnd, params->rect, params->flags, params->internal ); } - case NtUserCallHwndParam_GetPrivateData: - return get_control_info( hwnd, param ); + case NtUserCallHwndParam_GetControlFont: + { + struct control_info info = {0}; + get_control_info( hwnd, &info ); + return info.font; + } - case NtUserCallHwndParam_SetPrivateData: + case NtUserCallHwndParam_SetControlFont: + return server_set_control_info( hwnd, offsetof(struct control_info, font), param ); + + case NtUserCallHwndParam_GetControlIcon: { - struct set_private_data_params *params = (void *)param; - return server_set_control_info( hwnd, params->offset, params->value ); + struct control_info info = {0}; + get_control_info( hwnd, &info ); + return info.icon; } + case NtUserCallHwndParam_SetControlIcon: + return server_set_control_info( hwnd, offsetof(struct control_info, icon), param ); + default: FIXME( "invalid code %u\n", code ); return 0; diff --git a/include/ntuser.h b/include/ntuser.h index bbd35a6711a..fa1c2a0339e 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -1417,8 +1417,10 @@ enum NtUserCallHwndParam_ExposeWindowSurface, NtUserCallHwndParam_GetWinMonitorDpi, NtUserCallHwndParam_SetRawWindowPos, - NtUserCallHwndParam_GetPrivateData, - NtUserCallHwndParam_SetPrivateData, + NtUserCallHwndParam_GetControlFont, + NtUserCallHwndParam_SetControlFont, + NtUserCallHwndParam_GetControlIcon, + NtUserCallHwndParam_SetControlIcon, }; struct get_window_rects_params @@ -1645,21 +1647,4 @@ static inline BOOL NtUserSetRawWindowPos( HWND hwnd, RECT rect, UINT flags, BOOL return NtUserCallHwndParam( hwnd, (UINT_PTR)¶ms, NtUserCallHwndParam_SetRawWindowPos ); } -static inline ULONG NtUserGetPrivateData( HWND hwnd, UINT offset ) -{ - return NtUserCallHwndParam( hwnd, offset, NtUserCallHwndParam_GetPrivateData ); -} - -struct set_private_data_params -{ - UINT offset; - ULONG value; -}; - -static inline ULONG NtUserSetPrivateData( HWND hwnd, UINT offset, ULONG value ) -{ - struct set_private_data_params params = { .offset = offset, .value = value }; - return NtUserCallHwndParam( hwnd, (UINT_PTR)¶ms, NtUserCallHwndParam_SetPrivateData ); -} - #endif /* _NTUSER_ */ -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10999
From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/user32/button.c | 104 ++++++++++++++----------------------- dlls/user32/user_private.h | 10 ++++ dlls/win32u/window.c | 10 ++++ include/ntuser.h | 2 + server/protocol.def | 1 + server/window.c | 1 + 6 files changed, 63 insertions(+), 65 deletions(-) diff --git a/dlls/user32/button.c b/dlls/user32/button.c index f4dbec7767c..0ffaa2d32db 100644 --- a/dlls/user32/button.c +++ b/dlls/user32/button.c @@ -45,12 +45,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(button); -/* GetWindowLong offsets for window extra information */ -#define STATE_GWL_OFFSET 0 -#define HFONT_GWL_OFFSET (sizeof(LONG)) -#define HIMAGE_GWL_OFFSET (HFONT_GWL_OFFSET+sizeof(HFONT)) -#define NB_EXTRA_BYTES (HIMAGE_GWL_OFFSET+sizeof(HANDLE)) - /* undocumented flags */ #define BUTTON_NSTATES 0x0F #define BUTTON_BTNPRESSED 0x40 @@ -109,27 +103,6 @@ static const pfPaint btnPaintFunc[MAX_BTN_TYPE] = OB_Paint /* BS_OWNERDRAW */ }; - -static inline LONG get_button_state( HWND hwnd ) -{ - return GetWindowLongW( hwnd, STATE_GWL_OFFSET ); -} - -static inline void set_button_state( HWND hwnd, LONG state ) -{ - SetWindowLongW( hwnd, STATE_GWL_OFFSET, state ); -} - -static inline HFONT get_button_font( HWND hwnd ) -{ - return (HFONT)GetWindowLongPtrW( hwnd, HFONT_GWL_OFFSET ); -} - -static inline void set_button_font( HWND hwnd, HFONT font ) -{ - SetWindowLongPtrW( hwnd, HFONT_GWL_OFFSET, (LONG_PTR)font ); -} - static inline UINT get_button_type( LONG window_style ) { return (window_style & BS_TYPEMASK); @@ -168,6 +141,7 @@ LRESULT ButtonWndProc_common(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, HANDLE oldHbitmap; if (!IsWindow( hWnd )) return 0; + if (uMsg == WM_NCCREATE) NtUserSetWindowFNID( hWnd, MAKE_FNID(NTUSER_WNDPROC_BUTTON) ); pt.x = (short)LOWORD(lParam); pt.y = (short)HIWORD(lParam); @@ -196,7 +170,7 @@ LRESULT ButtonWndProc_common(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, /* XP turns a BS_USERBUTTON into BS_PUSHBUTTON */ if (btn_type == BS_USERBUTTON ) NtUserAlterWindowStyle( hWnd, BS_TYPEMASK, BS_PUSHBUTTON ); - set_button_state( hWnd, BST_UNCHECKED ); + set_control_state( hWnd, BST_UNCHECKED ); return 0; case WM_ERASEBKGND: @@ -235,7 +209,7 @@ LRESULT ButtonWndProc_common(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, if (wParam == VK_SPACE) { SendMessageW( hWnd, BM_SETSTATE, TRUE, 0 ); - set_button_state( hWnd, get_button_state( hWnd ) | BUTTON_BTNPRESSED ); + set_control_state( hWnd, get_control_state( hWnd ) | BUTTON_BTNPRESSED ); NtUserSetCapture( hWnd ); } break; @@ -252,7 +226,7 @@ LRESULT ButtonWndProc_common(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, /* fall through */ case WM_LBUTTONDOWN: NtUserSetCapture( hWnd ); - set_button_state( hWnd, get_button_state( hWnd ) | BUTTON_BTNPRESSED ); + set_control_state( hWnd, get_control_state( hWnd ) | BUTTON_BTNPRESSED ); NtUserSetFocus( hWnd ); SendMessageW( hWnd, BM_SETSTATE, TRUE, 0 ); break; @@ -262,10 +236,10 @@ LRESULT ButtonWndProc_common(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, break; /* fall through */ case WM_LBUTTONUP: - state = get_button_state( hWnd ); + state = get_control_state( hWnd ); if (!(state & BUTTON_BTNPRESSED)) break; state &= BUTTON_NSTATES; - set_button_state( hWnd, state ); + set_control_state( hWnd, state ); if (!(state & BST_PUSHED)) { NtUserReleaseCapture(); @@ -275,7 +249,7 @@ LRESULT ButtonWndProc_common(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, GetClientRect( hWnd, &rect ); if (uMsg == WM_KEYUP || PtInRect( &rect, pt )) { - state = get_button_state( hWnd ); + state = get_control_state( hWnd ); switch(btn_type) { case BS_AUTOCHECKBOX: @@ -301,11 +275,11 @@ LRESULT ButtonWndProc_common(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, case WM_CAPTURECHANGED: TRACE("WM_CAPTURECHANGED %p\n", hWnd); if (hWnd == (HWND)lParam) break; - state = get_button_state( hWnd ); + state = get_control_state( hWnd ); if (state & BUTTON_BTNPRESSED) { state &= BUTTON_NSTATES; - set_button_state( hWnd, state ); + set_control_state( hWnd, state ); if (state & BST_PUSHED) SendMessageW( hWnd, BM_SETSTATE, FALSE, 0 ); } break; @@ -363,22 +337,22 @@ LRESULT ButtonWndProc_common(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, } case WM_SETFONT: - set_button_font( hWnd, (HFONT)wParam ); + set_control_font( hWnd, (HFONT)wParam ); if (lParam) NtUserInvalidateRect(hWnd, NULL, TRUE); break; case WM_GETFONT: - return (LRESULT)get_button_font( hWnd ); + return (LRESULT)get_control_font( hWnd ); case WM_SETFOCUS: TRACE("WM_SETFOCUS %p\n",hWnd); - set_button_state( hWnd, get_button_state(hWnd) | BST_FOCUS ); + set_control_state( hWnd, get_control_state(hWnd) | BST_FOCUS ); paint_button( hWnd, btn_type, ODA_FOCUS ); if (style & BS_NOTIFY) BUTTON_NOTIFY_PARENT(hWnd, BN_SETFOCUS); if (((btn_type == BS_RADIOBUTTON) || (btn_type == BS_AUTORADIOBUTTON)) && - !(get_button_state(hWnd) & (BST_CHECKED | BUTTON_BTNPRESSED))) + !(get_control_state(hWnd) & (BST_CHECKED | BUTTON_BTNPRESSED))) { BUTTON_NOTIFY_PARENT(hWnd, BN_CLICKED); } @@ -386,8 +360,8 @@ LRESULT ButtonWndProc_common(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, case WM_KILLFOCUS: TRACE("WM_KILLFOCUS %p\n",hWnd); - state = get_button_state( hWnd ); - set_button_state( hWnd, state & ~BST_FOCUS ); + state = get_control_state( hWnd ); + set_control_state( hWnd, state & ~BST_FOCUS ); paint_button( hWnd, btn_type, ODA_FOCUS ); if ((state & BUTTON_BTNPRESSED) && GetCapture() == hWnd) @@ -432,19 +406,19 @@ LRESULT ButtonWndProc_common(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, default: return 0; } - oldHbitmap = (HBITMAP)SetWindowLongPtrW( hWnd, HIMAGE_GWL_OFFSET, lParam ); + oldHbitmap = set_control_icon( hWnd, (HBITMAP)lParam ); NtUserInvalidateRect( hWnd, NULL, FALSE ); return (LRESULT)oldHbitmap; case BM_GETIMAGE: - return GetWindowLongPtrW( hWnd, HIMAGE_GWL_OFFSET ); + return (LRESULT)get_control_icon( hWnd ); case BM_GETCHECK: - return get_button_state( hWnd ) & 3; + return get_control_state( hWnd ) & 3; case BM_SETCHECK: if (wParam > maxCheckState[btn_type]) wParam = maxCheckState[btn_type]; - state = get_button_state( hWnd ); + state = get_control_state( hWnd ); if ((btn_type == BS_RADIOBUTTON) || (btn_type == BS_AUTORADIOBUTTON)) { if (wParam) NtUserAlterWindowStyle( hWnd, WS_TABSTOP, WS_TABSTOP ); @@ -452,7 +426,7 @@ LRESULT ButtonWndProc_common(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, } if ((state & 3) != wParam) { - set_button_state( hWnd, (state & ~3) | wParam ); + set_control_state( hWnd, (state & ~3) | wParam ); paint_button( hWnd, btn_type, ODA_SELECT ); NtUserNotifyWinEvent( EVENT_OBJECT_STATECHANGE, hWnd, OBJID_CLIENT, 0 ); @@ -460,14 +434,14 @@ LRESULT ButtonWndProc_common(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, break; case BM_GETSTATE: - return get_button_state( hWnd ); + return get_control_state( hWnd ); case BM_SETSTATE: - state = get_button_state( hWnd ); + state = get_control_state( hWnd ); if (wParam) - set_button_state( hWnd, state | BST_PUSHED ); + set_control_state( hWnd, state | BST_PUSHED ); else - set_button_state( hWnd, state & ~BST_PUSHED ); + set_control_state( hWnd, state & ~BST_PUSHED ); paint_button( hWnd, btn_type, ODA_SELECT ); @@ -568,7 +542,7 @@ static UINT BUTTON_CalcLabelRect(HWND hwnd, HDC hdc, RECT *rc) goto empty_rect; } - if ((hFont = get_button_font( hwnd ))) hPrevFont = SelectObject( hdc, hFont ); + if ((hFont = get_control_font( hwnd ))) hPrevFont = SelectObject( hdc, hFont ); DrawTextW(hdc, text, -1, &r, dtStyle | DT_CALCRECT); if (hPrevFont) SelectObject( hdc, hPrevFont ); HeapFree( GetProcessHeap(), 0, text ); @@ -576,7 +550,7 @@ static UINT BUTTON_CalcLabelRect(HWND hwnd, HDC hdc, RECT *rc) } case BS_ICON: - if (!GetIconInfo((HICON)GetWindowLongPtrW( hwnd, HIMAGE_GWL_OFFSET ), &iconInfo)) + if (!GetIconInfo(get_control_icon( hwnd ), &iconInfo)) goto empty_rect; GetObjectW (iconInfo.hbmColor, sizeof(BITMAP), &bm); @@ -589,7 +563,7 @@ static UINT BUTTON_CalcLabelRect(HWND hwnd, HDC hdc, RECT *rc) break; case BS_BITMAP: - if (!GetObjectW( (HANDLE)GetWindowLongPtrW( hwnd, HIMAGE_GWL_OFFSET ), sizeof(BITMAP), &bm)) + if (!GetObjectW( get_control_icon( hwnd ), sizeof(BITMAP), &bm)) goto empty_rect; r.right = r.left + bm.bmWidth; @@ -664,7 +638,7 @@ static void BUTTON_DrawLabel(HWND hwnd, HDC hdc, UINT dtFlags, const RECT *rc) WPARAM wp = 0; HBRUSH hbr = 0; UINT flags = IsWindowEnabled(hwnd) ? DSS_NORMAL : DSS_DISABLED; - LONG state = get_button_state( hwnd ); + LONG state = get_control_state( hwnd ); LONG style = GetWindowLongW( hwnd, GWL_STYLE ); WCHAR *text = NULL; @@ -691,12 +665,12 @@ static void BUTTON_DrawLabel(HWND hwnd, HDC hdc, UINT dtFlags, const RECT *rc) case BS_ICON: flags |= DST_ICON; - lp = GetWindowLongPtrW( hwnd, HIMAGE_GWL_OFFSET ); + lp = (LPARAM)get_control_icon( hwnd ); break; case BS_BITMAP: flags |= DST_BITMAP; - lp = GetWindowLongPtrW( hwnd, HIMAGE_GWL_OFFSET ); + lp = (LPARAM)get_control_icon( hwnd ); break; default: @@ -720,7 +694,7 @@ static void PB_Paint( HWND hwnd, HDC hDC, UINT action ) INT oldBkMode; COLORREF oldTxtColor; HFONT hFont; - LONG state = get_button_state( hwnd ); + LONG state = get_control_state( hwnd ); LONG style = GetWindowLongW( hwnd, GWL_STYLE ); BOOL pushedState = (state & BST_PUSHED); HWND parent; @@ -729,7 +703,7 @@ static void PB_Paint( HWND hwnd, HDC hDC, UINT action ) GetClientRect( hwnd, &rc ); /* Send WM_CTLCOLOR to allow changing the font (the colors are fixed) */ - if ((hFont = get_button_font( hwnd ))) SelectObject( hDC, hFont ); + if ((hFont = get_control_font( hwnd ))) SelectObject( hDC, hFont ); parent = GetParent(hwnd); if (!parent) parent = hwnd; SendMessageW( parent, WM_CTLCOLORBTN, (WPARAM)hDC, (LPARAM)hwnd ); @@ -809,7 +783,7 @@ static void CB_Paint( HWND hwnd, HDC hDC, UINT action ) int delta, text_offset, checkBoxWidth, checkBoxHeight; UINT dtFlags; HFONT hFont; - LONG state = get_button_state( hwnd ); + LONG state = get_control_state( hwnd ); LONG style = GetWindowLongW( hwnd, GWL_STYLE ); LONG ex_style = GetWindowLongW( hwnd, GWL_EXSTYLE ); HWND parent; @@ -827,7 +801,7 @@ static void CB_Paint( HWND hwnd, HDC hDC, UINT action ) checkBoxWidth = 12 * GetDpiForWindow( hwnd ) / 96 + 1; checkBoxHeight = 12 * GetDpiForWindow( hwnd ) / 96 + 1; - if ((hFont = get_button_font( hwnd ))) SelectObject( hDC, hFont ); + if ((hFont = get_control_font( hwnd ))) SelectObject( hDC, hFont ); GetCharWidthW( hDC, '0', '0', &text_offset ); text_offset /= 2; @@ -969,7 +943,7 @@ static void GB_Paint( HWND hwnd, HDC hDC, UINT action ) HWND parent; HRGN hrgn; - if ((hFont = get_button_font( hwnd ))) SelectObject( hDC, hFont ); + if ((hFont = get_control_font( hwnd ))) SelectObject( hDC, hFont ); /* GroupBox acts like static control, so it sends CTLCOLORSTATIC */ parent = GetParent(hwnd); if (!parent) parent = hwnd; @@ -1016,12 +990,12 @@ static void UB_Paint( HWND hwnd, HDC hDC, UINT action ) RECT rc; HBRUSH hBrush; HFONT hFont; - LONG state = get_button_state( hwnd ); + LONG state = get_control_state( hwnd ); HWND parent; GetClientRect( hwnd, &rc); - if ((hFont = get_button_font( hwnd ))) SelectObject( hDC, hFont ); + if ((hFont = get_control_font( hwnd ))) SelectObject( hDC, hFont ); parent = GetParent(hwnd); if (!parent) parent = hwnd; @@ -1057,7 +1031,7 @@ static void UB_Paint( HWND hwnd, HDC hDC, UINT action ) static void OB_Paint( HWND hwnd, HDC hDC, UINT action ) { - LONG state = get_button_state( hwnd ); + LONG state = get_control_state( hwnd ); DRAWITEMSTRUCT dis; LONG_PTR id = GetWindowLongPtrW( hwnd, GWLP_ID ); HWND parent; @@ -1076,7 +1050,7 @@ static void OB_Paint( HWND hwnd, HDC hDC, UINT action ) dis.itemData = 0; GetClientRect( hwnd, &dis.rcItem ); - if ((hFont = get_button_font( hwnd ))) SelectObject( hDC, hFont ); + if ((hFont = get_control_font( hwnd ))) SelectObject( hDC, hFont ); parent = GetParent(hwnd); if (!parent) parent = hwnd; SendMessageW( parent, WM_CTLCOLORBTN, (WPARAM)hDC, (LPARAM)hwnd ); diff --git a/dlls/user32/user_private.h b/dlls/user32/user_private.h index 1302d8decd9..c667a566df9 100644 --- a/dlls/user32/user_private.h +++ b/dlls/user32/user_private.h @@ -208,4 +208,14 @@ static inline HFONT set_control_font( HWND hwnd, HFONT font ) return (HFONT)NtUserCallHwndParam( hwnd, (LONG_PTR)font, NtUserCallHwndParam_SetControlFont ); } +static inline LONG get_control_state( HWND hwnd ) +{ + return NtUserCallHwndParam( hwnd, 0, NtUserCallHwndParam_GetControlState ); +} + +static inline LONG set_control_state( HWND hwnd, LONG state ) +{ + return NtUserCallHwndParam( hwnd, state, NtUserCallHwndParam_SetControlState ); +} + #endif /* __WINE_USER_PRIVATE_H */ diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 92b22da29c0..771d82eba05 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -6280,6 +6280,16 @@ ULONG_PTR WINAPI NtUserCallHwndParam( HWND hwnd, DWORD_PTR param, DWORD code ) case NtUserCallHwndParam_SetControlIcon: return server_set_control_info( hwnd, offsetof(struct control_info, icon), param ); + case NtUserCallHwndParam_GetControlState: + { + struct control_info info = {0}; + get_control_info( hwnd, &info ); + return info.state; + } + + case NtUserCallHwndParam_SetControlState: + return server_set_control_info( hwnd, offsetof(struct control_info, state), param ); + default: FIXME( "invalid code %u\n", code ); return 0; diff --git a/include/ntuser.h b/include/ntuser.h index fa1c2a0339e..5aa71c32dd6 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -1421,6 +1421,8 @@ enum NtUserCallHwndParam_SetControlFont, NtUserCallHwndParam_GetControlIcon, NtUserCallHwndParam_SetControlIcon, + NtUserCallHwndParam_GetControlState, + NtUserCallHwndParam_SetControlState, }; struct get_window_rects_params diff --git a/server/protocol.def b/server/protocol.def index d917a50fc33..75103c53ccc 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1068,6 +1068,7 @@ 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 */ + unsigned int state; /* control state */ }; typedef volatile struct diff --git a/server/window.c b/server/window.c index e5a87c1bd6e..61e8d30fdcd 100644 --- a/server/window.c +++ b/server/window.c @@ -692,6 +692,7 @@ static struct window *create_window( struct window *parent, struct window *owner shared->control.fnid = get_class_fnid( class ); shared->control.icon = 0; shared->control.font = 0; + shared->control.state = 0; } SHARED_WRITE_END; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10999
FNID will then be extended further to support real class name implementation. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10999#note_141324
participants (2)
-
Rémi Bernon -
Rémi Bernon (@rbernon)