server: Add some validation of clipboard window handles.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2016-08-29 20:33:22 +09:00
parent 09f9986ea1
commit 19d16a7cb1
4 changed files with 72 additions and 7 deletions

View file

@ -147,7 +147,7 @@ BOOL WINAPI OpenClipboard( HWND hwnd )
SERVER_START_REQ( open_clipboard ) SERVER_START_REQ( open_clipboard )
{ {
req->window = wine_server_user_handle( hwnd ); 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; if (!reply->owner) bCBHasChanged = FALSE;
} }

View file

@ -26,6 +26,7 @@
#include "winuser.h" #include "winuser.h"
static BOOL (WINAPI *pAddClipboardFormatListener)(HWND hwnd); static BOOL (WINAPI *pAddClipboardFormatListener)(HWND hwnd);
static BOOL (WINAPI *pRemoveClipboardFormatListener)(HWND hwnd);
static DWORD (WINAPI *pGetClipboardSequenceNumber)(void); static DWORD (WINAPI *pGetClipboardSequenceNumber)(void);
static const BOOL is_win64 = sizeof(void *) > sizeof(int); 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) static DWORD WINAPI clipboard_thread(void *param)
{ {
HWND win = param; HWND ret, win = param;
BOOL r; BOOL r;
HANDLE handle; HANDLE handle;
UINT count, formats, old_seq = 0, seq; UINT count, formats, old_seq = 0, seq;
@ -577,10 +578,36 @@ static DWORD WINAPI clipboard_thread(void *param)
next_wnd = SetClipboardViewer(win); next_wnd = SetClipboardViewer(win);
ok(GetLastError() == 0xdeadbeef, "GetLastError = %d\n", GetLastError()); ok(GetLastError() == 0xdeadbeef, "GetLastError = %d\n", GetLastError());
LeaveCriticalSection(&clipboard_cs); 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) if (pAddClipboardFormatListener)
{ {
r = pAddClipboardFormatListener(win); r = pAddClipboardFormatListener(win);
ok( r, "AddClipboardFormatListener failed err %d\n", GetLastError()); 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) if (pGetClipboardSequenceNumber)
@ -593,6 +620,11 @@ static DWORD WINAPI clipboard_thread(void *param)
count = SendMessageA( win, WM_USER+2, 0, 0 ); count = SendMessageA( win, WM_USER+2, 0, 0 );
ok( !count, "WM_CLIPBOARDUPDATE received\n" ); 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); r = OpenClipboard(win);
ok(r, "OpenClipboard failed: %d\n", GetLastError()); 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); r = PostMessageA(win, WM_USER, 0, 0);
ok(r, "PostMessage failed: %d\n", GetLastError()); 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; return 0;
} }
@ -1238,6 +1284,7 @@ START_TEST(clipboard)
argv0 = argv[0]; argv0 = argv[0];
pAddClipboardFormatListener = (void *)GetProcAddress( mod, "AddClipboardFormatListener" ); pAddClipboardFormatListener = (void *)GetProcAddress( mod, "AddClipboardFormatListener" );
pRemoveClipboardFormatListener = (void *)GetProcAddress( mod, "RemoveClipboardFormatListener" );
pGetClipboardSequenceNumber = (void *)GetProcAddress( mod, "GetClipboardSequenceNumber" ); pGetClipboardSequenceNumber = (void *)GetProcAddress( mod, "GetClipboardSequenceNumber" );
if (argc == 4 && !strcmp( argv[2], "set_clipboard_data" )) if (argc == 4 && !strcmp( argv[2], "set_clipboard_data" ))

View file

@ -185,14 +185,18 @@ static int get_seqno( struct clipboard *clipboard )
DECL_HANDLER(open_clipboard) DECL_HANDLER(open_clipboard)
{ {
struct clipboard *clipboard = get_process_clipboard(); struct clipboard *clipboard = get_process_clipboard();
user_handle_t win; user_handle_t win = req->window;
if (!clipboard) return; 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) if (clipboard->open_thread && clipboard->open_win != win)
{ {
set_error( STATUS_WAS_LOCKED ); set_error( STATUS_INVALID_LOCK_SEQUENCE );
return; return;
} }
clipboard->open_win = win; clipboard->open_win = win;
@ -286,14 +290,27 @@ DECL_HANDLER(get_clipboard_info)
DECL_HANDLER(set_clipboard_viewer) DECL_HANDLER(set_clipboard_viewer)
{ {
struct clipboard *clipboard = get_process_clipboard(); struct clipboard *clipboard = get_process_clipboard();
user_handle_t viewer = req->viewer;
user_handle_t previous = req->previous;
if (!clipboard) return; 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->old_viewer = clipboard->viewer;
reply->owner = clipboard->owner_win; reply->owner = clipboard->owner_win;
if (!req->previous || clipboard->viewer == get_user_full_handle( req->previous )) if (!previous || clipboard->viewer == previous)
clipboard->viewer = get_user_full_handle( req->viewer ); clipboard->viewer = viewer;
else else
set_error( STATUS_PENDING ); /* need to send message instead */ set_error( STATUS_PENDING ); /* need to send message instead */
} }

View file

@ -5307,6 +5307,7 @@ static const struct
{ "INVALID_IMAGE_NOT_MZ", STATUS_INVALID_IMAGE_NOT_MZ }, { "INVALID_IMAGE_NOT_MZ", STATUS_INVALID_IMAGE_NOT_MZ },
{ "INVALID_IMAGE_PROTECT", STATUS_INVALID_IMAGE_PROTECT }, { "INVALID_IMAGE_PROTECT", STATUS_INVALID_IMAGE_PROTECT },
{ "INVALID_IMAGE_WIN_64", STATUS_INVALID_IMAGE_WIN_64 }, { "INVALID_IMAGE_WIN_64", STATUS_INVALID_IMAGE_WIN_64 },
{ "INVALID_LOCK_SEQUENCE", STATUS_INVALID_LOCK_SEQUENCE },
{ "INVALID_PARAMETER", STATUS_INVALID_PARAMETER }, { "INVALID_PARAMETER", STATUS_INVALID_PARAMETER },
{ "INVALID_SECURITY_DESCR", STATUS_INVALID_SECURITY_DESCR }, { "INVALID_SECURITY_DESCR", STATUS_INVALID_SECURITY_DESCR },
{ "IO_TIMEOUT", STATUS_IO_TIMEOUT }, { "IO_TIMEOUT", STATUS_IO_TIMEOUT },