user32: Protect from setting as a window owner one of its successors.
diff --git a/dlls/user32/tests/win.c b/dlls/user32/tests/win.c index 632e382..3af8d75 100644 --- a/dlls/user32/tests/win.c +++ b/dlls/user32/tests/win.c
@@ -380,6 +380,15 @@ check_parents( test, desktop, 0, desktop, 0, test, desktop ); /* window is now child of desktop so GWLP_HWNDPARENT changes owner from now on */ + if (!is_win9x) + { + ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)test ); + ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret ); + check_parents( test, desktop, 0, desktop, 0, test, desktop ); + } + else + win_skip("Test creates circular window tree under Win9x/WinMe\n" ); + ret = (HWND)SetWindowLongPtrA( test, GWLP_HWNDPARENT, (LONG_PTR)child ); ok( ret == 0, "GWL_HWNDPARENT return value %p expected 0\n", ret ); check_parents( test, desktop, child, desktop, child, test, desktop );
diff --git a/server/window.c b/server/window.c index 3b912b0..5fdfd13 100644 --- a/server/window.c +++ b/server/window.c
@@ -1834,7 +1834,7 @@ DECL_HANDLER(set_window_owner) { struct window *win = get_window( req->handle ); - struct window *owner = NULL; + struct window *owner = NULL, *ptr; if (!win) return; if (req->owner && !(owner = get_window( req->owner ))) return; @@ -1843,6 +1843,17 @@ set_error( STATUS_ACCESS_DENIED ); return; } + + /* make sure owner is not a successor of window */ + for (ptr = owner; ptr; ptr = ptr->owner ? get_window( ptr->owner ) : NULL) + { + if (ptr == win) + { + set_error( STATUS_INVALID_PARAMETER ); + return; + } + } + reply->prev_owner = win->owner; reply->full_owner = win->owner = owner ? owner->handle : 0; }