Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46712 Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/user32/tests/win.c | 71 +++++++++++++++++++++++++++++++++++++++++ dlls/user32/win.c | 38 +++++++++++++++++++++- 2 files changed, 108 insertions(+), 1 deletion(-)
diff --git a/dlls/user32/tests/win.c b/dlls/user32/tests/win.c index 3444abaf96..4fb9cc1a0c 100644 --- a/dlls/user32/tests/win.c +++ b/dlls/user32/tests/win.c @@ -6330,6 +6330,75 @@ static int check_error(DWORD actual, DWORD expected) return (!sets_last_error && (actual == 0xdeadbeef)) || (actual == expected); }
+static void test_set_window_long_size(void) +{ +#ifdef _WIN64 + WNDPROC old_window_procW, old_window_proc2W; + LONG_PTR retval; + HWND hwnd; + LONG ret; + + /* It's not allowed to set or get 64-bit pointer values using 32-bit functions. */ + hwnd = CreateWindowExA(0, "MainWindowClass", "Child window", WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_CHILD | + WS_MAXIMIZEBOX | WS_VISIBLE, 100, 100, 200, 200, hwndMain, 0, GetModuleHandleA(NULL), NULL); + ok(hwnd != NULL, "Failed to create test window.\n"); + + /* GWLP_WNDPROC */ + SetLastError(0xdeadbeef); + old_window_procW = (WNDPROC)(LONG_PTR)GetWindowLongA(hwnd, GWLP_WNDPROC); + ok(!old_window_procW && GetLastError() == ERROR_INVALID_INDEX, "Unexpected window proc.\n"); + + old_window_procW = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_WNDPROC); + ok(!!old_window_procW, "Unexpected window proc.\n"); + + SetLastError(0xdeadbeef); + old_window_proc2W = (WNDPROC)(LONG_PTR)SetWindowLongA(hwnd, GWLP_WNDPROC, 0xdeadbeef); + ok(!old_window_proc2W && GetLastError() == ERROR_INVALID_INDEX, "Unexpected window proc.\n"); + + old_window_proc2W = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_WNDPROC); + ok(old_window_proc2W == old_window_procW, "Unexpected window proc.\n"); + + /* GWLP_USERDATA */ + SetWindowLongPtrA(hwnd, GWLP_USERDATA, ((LONG_PTR)1 << 32) | 123); + ret = GetWindowLongA(hwnd, GWLP_USERDATA); + ok(ret == 123, "Unexpected user data %#x.\n", ret); + retval = GetWindowLongPtrA(hwnd, GWLP_USERDATA); + ok(retval > 123, "Unexpected user data.\n"); + + /* GWLP_ID */ + ret = SetWindowLongA(hwnd, GWLP_ID, 1); + ok(!ret, "Unexpected id %#x.\n", ret); + + ret = GetWindowLongA(hwnd, GWLP_ID); + ok(ret == 1, "Unexpected id %#x.\n", ret); + + SetWindowLongPtrA(hwnd, GWLP_ID, ((LONG_PTR)1 << 32) | 123); + ret = GetWindowLongA(hwnd, GWLP_ID); + ok(ret == 123, "Unexpected user data %#x.\n", ret); + retval = GetWindowLongPtrA(hwnd, GWLP_ID); + ok(retval > 123, "Unexpected user data.\n"); + + /* GWLP_HINSTANCE */ + retval = GetWindowLongPtrA(hwnd, GWLP_HINSTANCE); + ok(retval == (LONG_PTR)GetModuleHandleA(NULL), "Unexpected instance %#lx.\n", retval); + + SetLastError(0xdeadbeef); + ret = GetWindowLongA(hwnd, GWLP_HINSTANCE); + ok(!ret && GetLastError() == ERROR_INVALID_INDEX, "Unexpected instance %#x.\n", ret); + + SetLastError(0xdeadbeef); + ret = SetWindowLongA(hwnd, GWLP_HINSTANCE, 1); + ok(!ret && GetLastError() == ERROR_INVALID_INDEX, "Unexpected instance %#x.\n", ret); + + /* GWLP_HWNDPARENT */ + SetLastError(0xdeadbeef); + ret = GetWindowLongA(hwnd, GWLP_HWNDPARENT); + ok(!ret && GetLastError() == ERROR_INVALID_INDEX, "Unexpected parent window %#x.\n", ret); + + DestroyWindow(hwnd); +#endif +} + static void test_SetWindowLong(void) { LONG_PTR retval; @@ -6371,6 +6440,8 @@ static void test_SetWindowLong(void) /* set it back to ANSI */ SetWindowLongPtrA(hwndMain, GWLP_WNDPROC, 0); } + + test_set_window_long_size(); }
static LRESULT WINAPI check_style_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) diff --git a/dlls/user32/win.c b/dlls/user32/win.c index 24b2a2ffd5..d08fa67b11 100644 --- a/dlls/user32/win.c +++ b/dlls/user32/win.c @@ -2299,6 +2299,20 @@ UINT WINAPI GetDpiForWindow( HWND hwnd ) return ret; }
+static BOOL is_valid_window_value_size(INT offset, UINT size) +{ + switch (offset) + { +#ifdef _WIN64 + case GWLP_HWNDPARENT: + case GWLP_WNDPROC: + case GWLP_HINSTANCE: + return size == sizeof(LONG_PTR); +#endif + default: + return TRUE; + } +}
/********************************************************************** * WIN_GetWindowLong @@ -2312,7 +2326,15 @@ static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, UINT size, BOOL unicod
if (offset == GWLP_HWNDPARENT) { - HWND parent = GetAncestor( hwnd, GA_PARENT ); + HWND parent; + + if (!is_valid_window_value_size( offset, size )) + { + SetLastError( ERROR_INVALID_INDEX ); + return 0; + } + + parent = GetAncestor( hwnd, GA_PARENT ); if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER ); return (ULONG_PTR)parent; } @@ -2398,6 +2420,13 @@ static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, UINT size, BOOL unicod return retvalue; }
+ if (!is_valid_window_value_size( offset, size )) + { + SetLastError( ERROR_INVALID_INDEX ); + WIN_ReleasePtr( wndPtr ); + return 0; + } + switch(offset) { case GWLP_USERDATA: retvalue = wndPtr->userdata; break; @@ -2474,6 +2503,13 @@ LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, UINT size, LONG_PTR newval, B return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, MAKEWPARAM( offset, size ), newval ); }
+ if (!is_valid_window_value_size( offset, size )) + { + SetLastError( ERROR_INVALID_INDEX ); + WIN_ReleasePtr( wndPtr ); + return 0; + } + /* first some special cases */ switch( offset ) {