From 19d16a7cb1af82f0515afb10033d56d8ec7856d7 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Mon, 29 Aug 2016 20:33:22 +0900 Subject: [PATCH] server: Add some validation of clipboard window handles. Signed-off-by: Alexandre Julliard --- dlls/user32/clipboard.c | 2 +- dlls/user32/tests/clipboard.c | 49 ++++++++++++++++++++++++++++++++++- server/clipboard.c | 27 +++++++++++++++---- server/trace.c | 1 + 4 files changed, 72 insertions(+), 7 deletions(-) diff --git a/dlls/user32/clipboard.c b/dlls/user32/clipboard.c index 6d62dfd5329..fb10d27c358 100644 --- a/dlls/user32/clipboard.c +++ b/dlls/user32/clipboard.c @@ -147,7 +147,7 @@ BOOL WINAPI OpenClipboard( HWND hwnd ) SERVER_START_REQ( open_clipboard ) { req->window = wine_server_user_handle( hwnd ); - if ((ret = !wine_server_call( req ))) + if ((ret = !wine_server_call_err( req ))) { if (!reply->owner) bCBHasChanged = FALSE; } diff --git a/dlls/user32/tests/clipboard.c b/dlls/user32/tests/clipboard.c index f01af3dadb2..b9b926d181a 100644 --- a/dlls/user32/tests/clipboard.c +++ b/dlls/user32/tests/clipboard.c @@ -26,6 +26,7 @@ #include "winuser.h" static BOOL (WINAPI *pAddClipboardFormatListener)(HWND hwnd); +static BOOL (WINAPI *pRemoveClipboardFormatListener)(HWND hwnd); static DWORD (WINAPI *pGetClipboardSequenceNumber)(void); static const BOOL is_win64 = sizeof(void *) > sizeof(int); @@ -565,7 +566,7 @@ static LRESULT CALLBACK clipboard_wnd_proc(HWND hwnd, UINT msg, WPARAM wp, LPARA static DWORD WINAPI clipboard_thread(void *param) { - HWND win = param; + HWND ret, win = param; BOOL r; HANDLE handle; UINT count, formats, old_seq = 0, seq; @@ -577,10 +578,36 @@ static DWORD WINAPI clipboard_thread(void *param) next_wnd = SetClipboardViewer(win); ok(GetLastError() == 0xdeadbeef, "GetLastError = %d\n", GetLastError()); LeaveCriticalSection(&clipboard_cs); + + SetLastError( 0xdeadbeef ); + ret = SetClipboardViewer( (HWND)0xdead ); + ok( !ret, "SetClipboardViewer succeeded\n" ); + ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() ); + SetLastError( 0xdeadbeef ); + r = ChangeClipboardChain( win, (HWND)0xdead ); + ok( !r, "ChangeClipboardChain succeeded\n" ); + ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() ); + SetLastError( 0xdeadbeef ); + r = ChangeClipboardChain( (HWND)0xdead, next_wnd ); + ok( !r, "ChangeClipboardChain succeeded\n" ); + ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() ); + if (pAddClipboardFormatListener) { r = pAddClipboardFormatListener(win); ok( r, "AddClipboardFormatListener failed err %d\n", GetLastError()); + SetLastError( 0xdeadbeef ); + r = pAddClipboardFormatListener( win ); + todo_wine ok( !r, "AddClipboardFormatListener succeeded\n" ); + todo_wine ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() ); + SetLastError( 0xdeadbeef ); + r = pAddClipboardFormatListener( (HWND)0xdead ); + todo_wine ok( !r, "AddClipboardFormatListener succeeded\n" ); + todo_wine ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() ); + r = pAddClipboardFormatListener( GetDesktopWindow() ); + ok( r, "AddClipboardFormatListener failed err %d\n", GetLastError()); + r = pRemoveClipboardFormatListener( GetDesktopWindow() ); + ok( r, "RemoveClipboardFormatListener failed err %d\n", GetLastError()); } if (pGetClipboardSequenceNumber) @@ -593,6 +620,11 @@ static DWORD WINAPI clipboard_thread(void *param) count = SendMessageA( win, WM_USER+2, 0, 0 ); ok( !count, "WM_CLIPBOARDUPDATE received\n" ); + SetLastError( 0xdeadbeef ); + r = OpenClipboard( (HWND)0xdead ); + ok( !r, "OpenClipboard succeeded\n" ); + ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() ); + r = OpenClipboard(win); ok(r, "OpenClipboard failed: %d\n", GetLastError()); @@ -887,6 +919,20 @@ static DWORD WINAPI clipboard_thread(void *param) r = PostMessageA(win, WM_USER, 0, 0); ok(r, "PostMessage failed: %d\n", GetLastError()); + + if (pRemoveClipboardFormatListener) + { + r = pRemoveClipboardFormatListener(win); + ok( r, "RemoveClipboardFormatListener failed err %d\n", GetLastError()); + SetLastError( 0xdeadbeef ); + r = pRemoveClipboardFormatListener(win); + todo_wine ok( !r, "RemoveClipboardFormatListener succeeded\n" ); + todo_wine ok( GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError() ); + SetLastError( 0xdeadbeef ); + r = pRemoveClipboardFormatListener( (HWND)0xdead ); + todo_wine ok( !r, "RemoveClipboardFormatListener succeeded\n" ); + todo_wine ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "wrong error %u\n", GetLastError() ); + } return 0; } @@ -1238,6 +1284,7 @@ START_TEST(clipboard) argv0 = argv[0]; pAddClipboardFormatListener = (void *)GetProcAddress( mod, "AddClipboardFormatListener" ); + pRemoveClipboardFormatListener = (void *)GetProcAddress( mod, "RemoveClipboardFormatListener" ); pGetClipboardSequenceNumber = (void *)GetProcAddress( mod, "GetClipboardSequenceNumber" ); if (argc == 4 && !strcmp( argv[2], "set_clipboard_data" )) diff --git a/server/clipboard.c b/server/clipboard.c index 98df23074e2..a1535b6e134 100644 --- a/server/clipboard.c +++ b/server/clipboard.c @@ -185,14 +185,18 @@ static int get_seqno( struct clipboard *clipboard ) DECL_HANDLER(open_clipboard) { struct clipboard *clipboard = get_process_clipboard(); - user_handle_t win; + user_handle_t win = req->window; if (!clipboard) return; - win = get_user_full_handle( req->window ); + if (win && !get_user_object_handle( &win, USER_WINDOW )) + { + set_win32_error( ERROR_INVALID_WINDOW_HANDLE ); + return; + } if (clipboard->open_thread && clipboard->open_win != win) { - set_error( STATUS_WAS_LOCKED ); + set_error( STATUS_INVALID_LOCK_SEQUENCE ); return; } clipboard->open_win = win; @@ -286,14 +290,27 @@ DECL_HANDLER(get_clipboard_info) DECL_HANDLER(set_clipboard_viewer) { struct clipboard *clipboard = get_process_clipboard(); + user_handle_t viewer = req->viewer; + user_handle_t previous = req->previous; if (!clipboard) return; + if (viewer && !get_user_object_handle( &viewer, USER_WINDOW )) + { + set_win32_error( ERROR_INVALID_WINDOW_HANDLE ); + return; + } + if (previous && !get_user_object_handle( &previous, USER_WINDOW )) + { + set_win32_error( ERROR_INVALID_WINDOW_HANDLE ); + return; + } + reply->old_viewer = clipboard->viewer; reply->owner = clipboard->owner_win; - if (!req->previous || clipboard->viewer == get_user_full_handle( req->previous )) - clipboard->viewer = get_user_full_handle( req->viewer ); + if (!previous || clipboard->viewer == previous) + clipboard->viewer = viewer; else set_error( STATUS_PENDING ); /* need to send message instead */ } diff --git a/server/trace.c b/server/trace.c index 6c9518eaaa3..0e8a9e847ba 100644 --- a/server/trace.c +++ b/server/trace.c @@ -5307,6 +5307,7 @@ static const struct { "INVALID_IMAGE_NOT_MZ", STATUS_INVALID_IMAGE_NOT_MZ }, { "INVALID_IMAGE_PROTECT", STATUS_INVALID_IMAGE_PROTECT }, { "INVALID_IMAGE_WIN_64", STATUS_INVALID_IMAGE_WIN_64 }, + { "INVALID_LOCK_SEQUENCE", STATUS_INVALID_LOCK_SEQUENCE }, { "INVALID_PARAMETER", STATUS_INVALID_PARAMETER }, { "INVALID_SECURITY_DESCR", STATUS_INVALID_SECURITY_DESCR }, { "IO_TIMEOUT", STATUS_IO_TIMEOUT },