From: Piotr Caban <piotr@codeweavers.com> --- dlls/user32/static.c | 25 +++++----- dlls/user32/tests/static.c | 28 +++++------ dlls/win32u/main.c | 5 ++ dlls/win32u/ntuser_private.h | 2 + dlls/win32u/win32syscalls.h | 5 +- dlls/win32u/win32u.spec | 2 +- dlls/win32u/window.c | 92 ++++++++++++++++++++++++++++++++---- dlls/wow64win/user.c | 8 ++++ include/ntuser.h | 34 +++++++++++++ server/window.c | 14 +++++- 10 files changed, 177 insertions(+), 38 deletions(-) diff --git a/dlls/user32/static.c b/dlls/user32/static.c index f3953f7610a..042255c0d88 100644 --- a/dlls/user32/static.c +++ b/dlls/user32/static.c @@ -94,7 +94,7 @@ static HICON STATIC_SetIcon( HWND hwnd, HICON hicon, DWORD style ) WARN("hicon != 0, but invalid\n"); return 0; } - prevIcon = (HICON)SetWindowLongPtrW( hwnd, HICON_GWL_OFFSET, (LONG_PTR)hicon ); + prevIcon = (HICON)NtUserSetPrivateData( hwnd, HICON_GWL_OFFSET, sizeof(hicon), (LONG_PTR)hicon ); if (hicon && !(style & SS_CENTERIMAGE) && !(style & SS_REALSIZECONTROL)) { /* Windows currently doesn't implement SS_RIGHTJUST */ @@ -127,7 +127,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)SetWindowLongPtrW( hwnd, HICON_GWL_OFFSET, (LONG_PTR)hBitmap ); + hOldBitmap = (HBITMAP)NtUserSetPrivateData( hwnd, HICON_GWL_OFFSET, sizeof(hBitmap), (LONG_PTR)hBitmap ); if (hBitmap && !(style & SS_CENTERIMAGE) && !(style & SS_REALSIZECONTROL)) { BITMAP bm; @@ -162,7 +162,8 @@ static HENHMETAFILE STATIC_SetEnhMetaFile( HWND hwnd, HENHMETAFILE hEnhMetaFile, WARN("hEnhMetaFile != 0, but it's not an enhanced metafile\n"); return 0; } - return (HENHMETAFILE)SetWindowLongPtrW( hwnd, HICON_GWL_OFFSET, (LONG_PTR)hEnhMetaFile ); + return (HENHMETAFILE)NtUserSetPrivateData( hwnd, HICON_GWL_OFFSET, sizeof(hEnhMetaFile), + (LONG_PTR)hEnhMetaFile ); } /*********************************************************************** @@ -188,7 +189,7 @@ static HANDLE STATIC_GetImage( HWND hwnd, WPARAM wParam, DWORD style ) default: return NULL; } - return (HANDLE)GetWindowLongPtrW( hwnd, HICON_GWL_OFFSET ); + return (HANDLE)NtUserGetPrivateData( hwnd, HICON_GWL_OFFSET, sizeof(HANDLE) ); } /*********************************************************************** @@ -398,6 +399,8 @@ 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)) ); + if (full_style & SS_SUNKEN || style == SS_ETCHEDHORZ || style == SS_ETCHEDVERT) SetWindowLongW( hwnd, GWL_EXSTYLE, GetWindowLongW( hwnd, GWL_EXSTYLE ) | WS_EX_STATICEDGE ); @@ -484,7 +487,7 @@ LRESULT StaticWndProc_common( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam case WM_SETFONT: if (hasTextStyle( full_style )) { - SetWindowLongPtrW( hwnd, HFONT_GWL_OFFSET, wParam ); + NtUserSetPrivateData( hwnd, HFONT_GWL_OFFSET, sizeof(HFONT), wParam ); if (LOWORD(lParam)) NtUserRedrawWindow( hwnd, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_ALLCHILDREN ); @@ -492,7 +495,7 @@ LRESULT StaticWndProc_common( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam break; case WM_GETFONT: - return GetWindowLongPtrW( hwnd, HFONT_GWL_OFFSET ); + return NtUserGetPrivateData( hwnd, HFONT_GWL_OFFSET, sizeof(HFONT) ); case WM_NCHITTEST: if (full_style & SS_NOTIFY) @@ -574,7 +577,7 @@ static void STATIC_PaintOwnerDrawfn( HWND hwnd, HDC hdc, HBRUSH hbrush, DWORD st dis.itemData = 0; GetClientRect( hwnd, &dis.rcItem ); - font = (HFONT)GetWindowLongPtrW( hwnd, HFONT_GWL_OFFSET ); + font = (HFONT)NtUserGetPrivateData( hwnd, HFONT_GWL_OFFSET, sizeof(HFONT) ); if (font) oldFont = SelectObject( hdc, font ); SendMessageW( GetParent(hwnd), WM_DRAWITEM, id, (LPARAM)&dis ); if (font) SelectObject( hdc, oldFont ); @@ -636,7 +639,7 @@ static void STATIC_PaintTextfn( HWND hwnd, HDC hdc, HBRUSH hbrush, DWORD style ) format |= DT_SINGLELINE | DT_WORD_ELLIPSIS; } - if ((hFont = (HFONT)GetWindowLongPtrW( hwnd, HFONT_GWL_OFFSET ))) + if ((hFont = (HFONT)NtUserGetPrivateData( hwnd, HFONT_GWL_OFFSET, sizeof(HFONT) ))) hOldFont = SelectObject( hdc, hFont ); if ((style & SS_TYPEMASK) != SS_SIMPLE) @@ -725,7 +728,7 @@ static void STATIC_PaintIconfn( HWND hwnd, HDC hdc, HBRUSH hbrush, DWORD style ) SIZE size; GetClientRect( hwnd, &rc ); - hIcon = (HICON)GetWindowLongPtrW( hwnd, HICON_GWL_OFFSET ); + hIcon = (HICON)NtUserGetPrivateData( hwnd, HICON_GWL_OFFSET, sizeof(hIcon) ); if (!hIcon || !get_icon_size( hIcon, &size )) { FillRect(hdc, &rc, hbrush); @@ -752,7 +755,7 @@ static void STATIC_PaintBitmapfn(HWND hwnd, HDC hdc, HBRUSH hbrush, DWORD style HDC hMemDC; HBITMAP hBitmap, oldbitmap; - if ((hBitmap = (HBITMAP)GetWindowLongPtrW( hwnd, HICON_GWL_OFFSET )) + if ((hBitmap = (HBITMAP)NtUserGetPrivateData( hwnd, HICON_GWL_OFFSET, sizeof(hBitmap) )) && (GetObjectType(hBitmap) == OBJ_BITMAP) && (hMemDC = CreateCompatibleDC( hdc ))) { @@ -792,7 +795,7 @@ static void STATIC_PaintEnhMetafn(HWND hwnd, HDC hdc, HBRUSH hbrush, DWORD style GetClientRect(hwnd, &rc); FillRect(hdc, &rc, hbrush); - if ((hEnhMetaFile = (HENHMETAFILE)GetWindowLongPtrW( hwnd, HICON_GWL_OFFSET ))) + if ((hEnhMetaFile = (HENHMETAFILE)NtUserGetPrivateData( hwnd, HICON_GWL_OFFSET, sizeof(hEnhMetaFile) ))) { /* The control's current font is not selected into the device context! */ diff --git a/dlls/user32/tests/static.c b/dlls/user32/tests/static.c index 9a2cf1629b3..382895cc7d9 100644 --- a/dlls/user32/tests/static.c +++ b/dlls/user32/tests/static.c @@ -360,8 +360,8 @@ static LRESULT WINAPI static_wrapper_proc(HWND hwnd, UINT msg, WPARAM wparam, LP { SetLastError(0xdeadbeef); v = SetWindowLongA(hwnd, 0, 3); - todo_wine_if(msg != WM_NCCREATE) ok(!v, "got %lx\n", v); - todo_wine ok(GetLastError() == ERROR_INVALID_INDEX, "GetLastError() = %ld\n", GetLastError()); + ok(!v, "got %lx\n", v); + ok(GetLastError() == ERROR_INVALID_INDEX, "GetLastError() = %ld\n", GetLastError()); } v = SetWindowLongA(hwnd, test_data_off, 4); @@ -369,8 +369,8 @@ static LRESULT WINAPI static_wrapper_proc(HWND hwnd, UINT msg, WPARAM wparam, LP SetLastError(0xdeadbeef); v = GetWindowLongA(hwnd, 0); - todo_wine ok(!v, "got %lx\n", v); - todo_wine ok(GetLastError() == ERROR_INVALID_INDEX, "GetLastError() = %ld\n", GetLastError()); + ok(!v, "got %lx\n", v); + ok(GetLastError() == ERROR_INVALID_INDEX, "GetLastError() = %ld\n", GetLastError()); v = GetWindowLongA(hwnd, test_data_off); ok(v == 4, "got %lx\n", v); @@ -399,18 +399,18 @@ static void test_window_extra_data(char **argv) SetLastError(0xdeadbeef); v = GetWindowLongA(hwnd, 0); - todo_wine ok(!v, "got %lx\n", v); - todo_wine ok(GetLastError() == ERROR_INVALID_INDEX, "GetLastError() = %ld\n", GetLastError()); + ok(!v, "got %lx\n", v); + ok(GetLastError() == ERROR_INVALID_INDEX, "GetLastError() = %ld\n", GetLastError()); SetLastError(0xdeadbeef); v = SetWindowLongA(hwnd, 0, 1); - todo_wine ok(!v, "got %lx\n", v); - todo_wine ok(GetLastError() == ERROR_INVALID_INDEX, "GetLastError() = %ld\n", GetLastError()); + ok(!v, "got %lx\n", v); + ok(GetLastError() == ERROR_INVALID_INDEX, "GetLastError() = %ld\n", GetLastError()); SetLastError(0xdeadbeef); v = GetWindowLongW(hwnd, 0); - todo_wine ok(!v, "got %lx\n", v); - todo_wine ok(GetLastError() == ERROR_INVALID_INDEX, "GetLastError() = %ld\n", GetLastError()); + ok(!v, "got %lx\n", v); + ok(GetLastError() == ERROR_INVALID_INDEX, "GetLastError() = %ld\n", GetLastError()); si.cb = sizeof(si); sprintf(buffer, "\"%s\" %s window_extra_data %p", argv[0], argv[1], hwnd); @@ -446,16 +446,16 @@ static void test_window_extra_data_proc(char *arg) SetLastError(0xdeadbeef); v = GetWindowLongA(hwnd, 0); - todo_wine ok(!v, "v = %ld\n", v); - todo_wine ok(GetLastError() == ERROR_INVALID_INDEX, "GetLastError() = %ld\n", GetLastError()); + ok(!v, "v = %ld\n", v); + ok(GetLastError() == ERROR_INVALID_INDEX, "GetLastError() = %ld\n", GetLastError()); SetLastError(0xdeadbeef); v = SetWindowLongA(hwnd, 0, 1); - todo_wine ok(!v, "v = %ld\n", v); + ok(!v, "v = %ld\n", v); todo_wine ok(GetLastError() == 0xdeadbeef, "GetLastError() = %ld\n", GetLastError()); v = SetWindowLongA(hwnd, 0, 1); - todo_wine ok(!v, "v = %ld\n", v); + ok(!v, "v = %ld\n", v); todo_wine ok(GetLastError() == 0xdeadbeef, "GetLastError() = %ld\n", GetLastError()); PostMessageA(hwnd, WM_QUIT, 0, 0); diff --git a/dlls/win32u/main.c b/dlls/win32u/main.c index aa47111ba72..73a6ae32448 100644 --- a/dlls/win32u/main.c +++ b/dlls/win32u/main.c @@ -2347,6 +2347,11 @@ BOOL SYSCALL_API NtUserSetWindowContextHelpId( HWND hwnd, DWORD id ) SYSCALL_FUNC( NtUserSetWindowContextHelpId ); } +BOOL SYSCALL_API NtUserSetWindowFNID( HWND hwnd, WORD fnid ) +{ + SYSCALL_FUNC( NtUserSetWindowFNID ); +} + LONG SYSCALL_API NtUserSetWindowLong( HWND hwnd, INT offset, LONG newval, BOOL ansi ) { SYSCALL_FUNC( NtUserSetWindowLong ); diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index ec6cf02ffb1..2f9bc9c2ccc 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -76,6 +76,8 @@ 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/win32syscalls.h b/dlls/win32u/win32syscalls.h index 7826afd3fc3..aa0ceec4072 100644 --- a/dlls/win32u/win32syscalls.h +++ b/dlls/win32u/win32syscalls.h @@ -1441,7 +1441,7 @@ SYSCALL_ENTRY( 0x159d, NtUserSetWindowCompositionTransition, 0 ) \ SYSCALL_ENTRY( 0x159e, NtUserSetWindowContextHelpId, 8 ) \ SYSCALL_ENTRY( 0x159f, NtUserSetWindowDisplayAffinity, 0 ) \ - SYSCALL_ENTRY( 0x15a0, NtUserSetWindowFNID, 0 ) \ + SYSCALL_ENTRY( 0x15a0, NtUserSetWindowFNID, 8 ) \ SYSCALL_ENTRY( 0x15a1, NtUserSetWindowFeedbackSetting, 0 ) \ SYSCALL_ENTRY( 0x15a2, NtUserSetWindowGroup, 0 ) \ SYSCALL_ENTRY( 0x15a3, NtUserSetWindowLong, 16 ) \ @@ -2983,7 +2983,7 @@ SYSCALL_ENTRY( 0x159d, NtUserSetWindowCompositionTransition, 0 ) \ SYSCALL_ENTRY( 0x159e, NtUserSetWindowContextHelpId, 16 ) \ SYSCALL_ENTRY( 0x159f, NtUserSetWindowDisplayAffinity, 0 ) \ - SYSCALL_ENTRY( 0x15a0, NtUserSetWindowFNID, 0 ) \ + SYSCALL_ENTRY( 0x15a0, NtUserSetWindowFNID, 16 ) \ SYSCALL_ENTRY( 0x15a1, NtUserSetWindowFeedbackSetting, 0 ) \ SYSCALL_ENTRY( 0x15a2, NtUserSetWindowGroup, 0 ) \ SYSCALL_ENTRY( 0x15a3, NtUserSetWindowLong, 32 ) \ @@ -4086,7 +4086,6 @@ SYSCALL_STUB( NtUserSetWindowCompositionAttribute ) \ SYSCALL_STUB( NtUserSetWindowCompositionTransition ) \ SYSCALL_STUB( NtUserSetWindowDisplayAffinity ) \ - SYSCALL_STUB( NtUserSetWindowFNID ) \ SYSCALL_STUB( NtUserSetWindowFeedbackSetting ) \ SYSCALL_STUB( NtUserSetWindowGroup ) \ SYSCALL_STUB( NtUserSetWindowMessageCapability ) \ diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec index 66e8541d915..2f657aa854e 100644 --- a/dlls/win32u/win32u.spec +++ b/dlls/win32u/win32u.spec @@ -1439,7 +1439,7 @@ @ stub -syscall NtUserSetWindowCompositionTransition @ stdcall -syscall NtUserSetWindowContextHelpId(long long) @ stub -syscall NtUserSetWindowDisplayAffinity -@ stub -syscall NtUserSetWindowFNID +@ stdcall -syscall NtUserSetWindowFNID(long long) @ stub -syscall NtUserSetWindowFeedbackSetting @ stub -syscall NtUserSetWindowGroup @ stdcall -syscall NtUserSetWindowLong(long long long long) diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index adbbc77937c..fc129df0785 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -1164,7 +1164,12 @@ BOOL is_zoomed( HWND hwnd ) return (get_window_long( hwnd, GWL_STYLE ) & WS_MAXIMIZE) != 0; } -static LONG_PTR get_window_long_size( HWND hwnd, INT offset, UINT size, BOOL ansi ) +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; WND *win; @@ -1227,7 +1232,8 @@ static LONG_PTR get_window_long_size( HWND hwnd, INT offset, UINT size, BOOL ans if (offset >= 0) { - if (offset > (int)(win->cbWndExtra - size)) + if (offset > (int)(win->cbWndExtra - size) || + (!internal && in_private_data_range( win, offset, size ))) { WARN("Invalid offset %d\n", offset ); release_win_ptr( win ); @@ -1268,13 +1274,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 ); + return get_window_long_size( hwnd, offset, sizeof(LONG), FALSE, 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 ); + return get_window_long_size( hwnd, offset, sizeof(LONG_PTR), ansi, FALSE ); } /* see GetWindowWord */ @@ -1285,7 +1291,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 ); + return get_window_long_size( hwnd, offset, sizeof(WORD), TRUE, FALSE ); } UINT set_window_style_bits( HWND hwnd, UINT set_bits, UINT clear_bits ) @@ -1385,7 +1391,8 @@ static HWND set_window_owner( HWND hwnd, HWND owner ) } /* Helper function for SetWindowLong(). */ -LONG_PTR set_window_long( HWND hwnd, INT offset, UINT size, LONG_PTR newval, BOOL ansi ) +static LONG_PTR set_window_long_internal( HWND hwnd, INT offset, UINT size, + LONG_PTR newval, BOOL ansi, BOOL internal ) { BOOL ok, made_visible = FALSE, layered = FALSE; LONG_PTR retval = 0; @@ -1484,7 +1491,8 @@ LONG_PTR set_window_long( HWND hwnd, INT offset, UINT size, LONG_PTR newval, BOO case GWLP_USERDATA: break; default: - if (offset < 0 || offset > (int)(win->cbWndExtra - size)) + if (offset < 0 || offset > (int)(win->cbWndExtra - size) || + (!internal && in_private_data_range( win, offset, size ))) { WARN("Invalid offset %d\n", offset ); release_win_ptr( win ); @@ -1567,6 +1575,62 @@ LONG_PTR set_window_long( HWND hwnd, INT offset, UINT size, LONG_PTR newval, BOO 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.@) + * + * fnid parameter not compatible with Windows. + */ +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; +} + /********************************************************************** * NtUserSetWindowWord (win32u.@) */ @@ -6126,7 +6190,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 ); + return get_window_long_size( hwnd, param, sizeof(LONG), TRUE, FALSE ); case NtUserCallHwndParam_GetWindowLongW: return get_window_long( hwnd, param ); @@ -6211,6 +6275,18 @@ 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: + { + struct get_private_data_params *params = (void *)param; + return get_window_long_size( hwnd, params->offset, params->size, FALSE, TRUE ); + } + + 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 ); + } + default: FIXME( "invalid code %u\n", code ); return 0; diff --git a/dlls/wow64win/user.c b/dlls/wow64win/user.c index 6bbb1fba508..0a570d79ff7 100644 --- a/dlls/wow64win/user.c +++ b/dlls/wow64win/user.c @@ -4622,6 +4622,14 @@ NTSTATUS WINAPI wow64_NtUserSetWindowContextHelpId( UINT *args ) return NtUserSetWindowContextHelpId( hwnd, id ); } +NTSTATUS WINAPI wow64_NtUserSetWindowFNID( UINT *args ) +{ + HWND hwnd = get_handle( &args ); + WORD fnid = get_ulong( &args ); + + return NtUserSetWindowFNID( hwnd, fnid ); +} + NTSTATUS WINAPI wow64_NtUserSetWindowLong( UINT *args ) { HWND hwnd = get_handle( &args ); diff --git a/include/ntuser.h b/include/ntuser.h index ce1b18fdfd9..31674c76858 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -667,6 +667,12 @@ enum wine_internal_message #define IMN_WINE_SET_OPEN_STATUS 0x000f #define IMN_WINE_SET_COMP_STRING 0x0010 +/* 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) + /* builtin IME driver calls */ enum wine_ime_call { @@ -1017,6 +1023,7 @@ W32KAPI HWND WINAPI NtUserSetTaskmanWindow( HWND hwnd ); W32KAPI BOOL WINAPI NtUserSetThreadDesktop( HDESK handle ); W32KAPI UINT_PTR WINAPI NtUserSetTimer( HWND hwnd, UINT_PTR id, UINT timeout, TIMERPROC proc, ULONG tolerance ); W32KAPI BOOL WINAPI NtUserSetWindowContextHelpId( HWND hwnd, DWORD id ); +W32KAPI BOOL WINAPI NtUserSetWindowFNID( HWND hwnd, WORD fnid ); W32KAPI LONG WINAPI NtUserSetWindowLong( HWND hwnd, INT offset, LONG newval, BOOL ansi ); W32KAPI LONG_PTR WINAPI NtUserSetWindowLongPtr( HWND hwnd, INT offset, LONG_PTR newval, BOOL ansi ); W32KAPI BOOL WINAPI NtUserSetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *wpl ); @@ -1422,6 +1429,8 @@ enum NtUserCallHwndParam_ExposeWindowSurface, NtUserCallHwndParam_GetWinMonitorDpi, NtUserCallHwndParam_SetRawWindowPos, + NtUserCallHwndParam_GetPrivateData, + NtUserCallHwndParam_SetPrivateData, }; struct get_window_rects_params @@ -1648,4 +1657,29 @@ static inline BOOL NtUserSetRawWindowPos( HWND hwnd, RECT rect, UINT flags, BOOL return NtUserCallHwndParam( hwnd, (UINT_PTR)¶ms, NtUserCallHwndParam_SetRawWindowPos ); } +struct get_private_data_params +{ + 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 ); +} + +struct set_private_data_params +{ + UINT offset; + UINT size; + LONG_PTR value; +}; + +static inline LONG_PTR NtUserSetPrivateData( HWND hwnd, UINT offset, UINT size, LONG_PTR value ) +{ + struct set_private_data_params params = { .offset = offset, .size = size, .value = value }; + return NtUserCallHwndParam( hwnd, (UINT_PTR)¶ms, NtUserCallHwndParam_SetPrivateData ); +} + #endif /* _NTUSER_ */ diff --git a/server/window.c b/server/window.c index f4ce0dece3c..f222b5c2a59 100644 --- a/server/window.c +++ b/server/window.c @@ -92,6 +92,8 @@ 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 */ @@ -2273,6 +2275,11 @@ 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) @@ -2396,7 +2403,8 @@ 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) + req->offset > win->nb_extra_bytes - (int)req->size || + in_private_data_range( win, req->offset, req->size )) { set_win32_error( ERROR_INVALID_INDEX ); break; @@ -2463,6 +2471,10 @@ 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) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10277