Module: wine Branch: master Commit: 19d16a7cb1af82f0515afb10033d56d8ec7856d7 URL: http://source.winehq.org/git/wine.git/?a=commit;h=19d16a7cb1af82f0515afb1003...
Author: Alexandre Julliard julliard@winehq.org Date: Mon Aug 29 20:33:22 2016 +0900
server: Add some validation of clipboard window handles.
Signed-off-by: Alexandre Julliard julliard@winehq.org
---
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 6d62dfd..fb10d27 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 f01af3d..b9b926d 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 98df230..a1535b6 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 6c9518e..0e8a9e8 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 },