server: Don't allow orphaned windows in set_parent request.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2022-02-08 13:13:19 +01:00 committed by Alexandre Julliard
parent ce3abc225f
commit 82572350cd
3 changed files with 10 additions and 5 deletions

View File

@ -865,16 +865,13 @@ static void test_thread_exit_destroy(void)
SetLastError( 0xdeadbeef );
tmp = SetParent( child1, adopter );
ok( tmp == 0, "SetParent returned %p\n", tmp );
todo_wine
ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %u\n", GetLastError() );
SetLastError( 0xdeadbeef );
tmp = SetParent( child3, adopter );
ok( tmp == 0, "SetParent returned %p\n", tmp );
todo_wine
ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %u\n", GetLastError() );
SetLastError( 0xdeadbeef );
tmp = GetParent( child1 );
todo_wine
ok( tmp == params.hwnd, "GetParent returned %p, error %u\n", tmp, GetLastError() );
ok( GetLastError() == 0xdeadbeef, "GetWindowLongW error %u\n", GetLastError() );

View File

@ -3374,7 +3374,7 @@ HWND WINAPI SetParent( HWND hwnd, HWND parent )
{
req->handle = wine_server_user_handle( hwnd );
req->parent = wine_server_user_handle( parent );
if ((ret = !wine_server_call( req )))
if ((ret = !wine_server_call_err( req )))
{
old_parent = wine_server_ptr_handle( reply->old_parent );
wndPtr->parent = parent = wine_server_ptr_handle( reply->full_parent );

View File

@ -200,6 +200,14 @@ static inline int is_desktop_window( const struct window *win )
return !win->parent; /* only desktop windows have no parent */
}
/* check if window is orphaned */
static int is_orphan_window( struct window *win )
{
do if (!win->handle) return 1;
while ((win = win->parent));
return 0;
}
/* get next window in Z-order list */
static inline struct window *get_next_window( struct window *win )
{
@ -2066,7 +2074,7 @@ DECL_HANDLER(set_parent)
if (!(win = get_window( req->handle ))) return;
if (req->parent && !(parent = get_window( req->parent ))) return;
if (is_desktop_window(win))
if (is_desktop_window(win) || is_orphan_window( win ) || (parent && is_orphan_window( parent )))
{
set_error( STATUS_INVALID_PARAMETER );
return;