user32: Fix return value when passing a non-sibling preceding window to SetWindowPos.

David Hedberg dhedberg at codeweavers.com
Mon Mar 21 07:43:41 CDT 2011


This stops Acrobat Reader from crashing when opening the preference dialog.
---
 dlls/user32/tests/win.c |  161 ++++++++++++++++++++++++++++++++++-------------
 dlls/user32/winpos.c    |   20 ++++--
 2 files changed, 131 insertions(+), 50 deletions(-)

diff --git a/dlls/user32/tests/win.c b/dlls/user32/tests/win.c
index 603e93e..b854b6e 100644
--- a/dlls/user32/tests/win.c
+++ b/dlls/user32/tests/win.c
@@ -127,6 +127,34 @@ static void check_parents( HWND hwnd, HWND ga_parent, HWND gwl_parent, HWND get_
     }
 }
 
+#define check_wnd_state(a,b,c,d) check_wnd_state_(__FILE__,__LINE__,a,b,c,d)
+static void check_wnd_state_(const char *file, int line,
+                             HWND active, HWND foreground, HWND focus, HWND capture)
+{
+    ok_(file, line)(active == GetActiveWindow(), "GetActiveWindow() = %p\n", GetActiveWindow());
+    /* only check foreground if it belongs to the current thread */
+    /* foreground can be moved to a different app pretty much at any time */
+    if (foreground && GetForegroundWindow() &&
+        GetWindowThreadProcessId(GetForegroundWindow(), NULL) == GetCurrentThreadId())
+        ok_(file, line)(foreground == GetForegroundWindow(), "GetForegroundWindow() = %p\n", GetForegroundWindow());
+    ok_(file, line)(focus == GetFocus(), "GetFocus() = %p\n", GetFocus());
+    ok_(file, line)(capture == GetCapture(), "GetCapture() = %p\n", GetCapture());
+}
+
+/* same as above but without capture test */
+#define check_active_state(a,b,c) check_active_state_(__FILE__,__LINE__,a,b,c)
+static void check_active_state_(const char *file, int line,
+                                HWND active, HWND foreground, HWND focus)
+{
+    ok_(file, line)(active == GetActiveWindow(), "GetActiveWindow() = %p\n", GetActiveWindow());
+    /* only check foreground if it belongs to the current thread */
+    /* foreground can be moved to a different app pretty much at any time */
+    if (foreground && GetForegroundWindow() &&
+        GetWindowThreadProcessId(GetForegroundWindow(), NULL) == GetCurrentThreadId())
+        ok_(file, line)(foreground == GetForegroundWindow(), "GetForegroundWindow() = %p\n", GetForegroundWindow());
+    ok_(file, line)(focus == GetFocus(), "GetFocus() = %p\n", GetFocus());
+}
+
 static BOOL ignore_message( UINT message )
 {
     /* these are always ignored */
@@ -1941,10 +1969,13 @@ static LRESULT WINAPI nccalcsize_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM
     return DefWindowProc( hwnd, msg, wparam, lparam );
 }
 
-static void test_SetWindowPos(HWND hwnd)
+static void test_SetWindowPos(HWND hwnd, HWND hwnd2)
 {
     RECT orig_win_rc, rect;
     LONG_PTR old_proc;
+    HWND hwnd_desktop, hwnd_child, hwnd_grandchild;
+    RECT rc1, rc2;
+    BOOL ret;
 
     SetRect(&rect, 111, 222, 333, 444);
     ok(!GetWindowRect(0, &rect), "GetWindowRect succeeded\n");
@@ -1959,7 +1990,8 @@ static void test_SetWindowPos(HWND hwnd)
     GetWindowRect(hwnd, &orig_win_rc);
 
     old_proc = SetWindowLongPtr( hwnd, GWLP_WNDPROC, (ULONG_PTR)nccalcsize_proc );
-    SetWindowPos(hwnd, 0, 100, 100, 0, 0, SWP_NOZORDER|SWP_FRAMECHANGED);
+    ret = SetWindowPos(hwnd, 0, 100, 100, 0, 0, SWP_NOZORDER|SWP_FRAMECHANGED);
+    ok(ret, "Got %d\n", ret);
     GetWindowRect( hwnd, &rect );
     ok( rect.left == 100 && rect.top == 100 && rect.right == 100 && rect.bottom == 100,
         "invalid window rect %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
@@ -1968,7 +2000,8 @@ static void test_SetWindowPos(HWND hwnd)
     ok( rect.left == 90 && rect.top == 90 && rect.right == 110 && rect.bottom == 110,
         "invalid client rect %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
 
-    SetWindowPos(hwnd, 0, 200, 200, 0, 0, SWP_NOZORDER|SWP_FRAMECHANGED);
+    ret = SetWindowPos(hwnd, 0, 200, 200, 0, 0, SWP_NOZORDER|SWP_FRAMECHANGED);
+    ok(ret, "Got %d\n", ret);
     GetWindowRect( hwnd, &rect );
     ok( rect.left == 200 && rect.top == 200 && rect.right == 200 && rect.bottom == 200,
         "invalid window rect %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
@@ -1977,30 +2010,98 @@ static void test_SetWindowPos(HWND hwnd)
     ok( rect.left == 210 && rect.top == 210 && rect.right == 190 && rect.bottom == 190,
         "invalid client rect %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
 
-    SetWindowPos(hwnd, 0, orig_win_rc.left, orig_win_rc.top,
-                 orig_win_rc.right, orig_win_rc.bottom, 0);
+    ret = SetWindowPos(hwnd, 0, orig_win_rc.left, orig_win_rc.top,
+                      orig_win_rc.right, orig_win_rc.bottom, 0);
+    ok(ret, "Got %d\n", ret);
     SetWindowLongPtr( hwnd, GWLP_WNDPROC, old_proc );
 
     /* Win9x truncates coordinates to 16-bit irrespectively */
     if (!is_win9x)
     {
-        SetWindowPos(hwnd, 0, -32769, -40000, -32769, -90000, SWP_NOMOVE);
-        SetWindowPos(hwnd, 0, 32768, 40000, 32768, 40000, SWP_NOMOVE);
-
-        SetWindowPos(hwnd, 0, -32769, -40000, -32769, -90000, SWP_NOSIZE);
-        SetWindowPos(hwnd, 0, 32768, 40000, 32768, 40000, SWP_NOSIZE);
+        ret = SetWindowPos(hwnd, 0, -32769, -40000, -32769, -90000, SWP_NOMOVE);
+        ok(ret, "Got %d\n", ret);
+        ret = SetWindowPos(hwnd, 0, 32768, 40000, 32768, 40000, SWP_NOMOVE);
+        ok(ret, "Got %d\n", ret);
+
+        ret = SetWindowPos(hwnd, 0, -32769, -40000, -32769, -90000, SWP_NOSIZE);
+        ok(ret, "Got %d\n", ret);
+        ret = SetWindowPos(hwnd, 0, 32768, 40000, 32768, 40000, SWP_NOSIZE);
+        ok(ret, "Got %d\n", ret);
     }
 
-    SetWindowPos(hwnd, 0, orig_win_rc.left, orig_win_rc.top,
-                 orig_win_rc.right, orig_win_rc.bottom, 0);
+    ret = SetWindowPos(hwnd, 0, orig_win_rc.left, orig_win_rc.top,
+                       orig_win_rc.right, orig_win_rc.bottom, 0);
+    ok(ret, "Got %d\n", ret);
 
     ok(!(GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST), "WS_EX_TOPMOST should not be set\n");
-    SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
+    ret = SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
+    ok(ret, "Got %d\n", ret);
     ok(GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST, "WS_EX_TOPMOST should be set\n");
-    SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
+    ret = SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
+    ok(ret, "Got %d\n", ret);
     ok(GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST, "WS_EX_TOPMOST should be set\n");
-    SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
+    ret = SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE);
+    ok(ret, "Got %d\n", ret);
     ok(!(GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST), "WS_EX_TOPMOST should not be set\n");
+
+    hwnd_desktop = GetDesktopWindow();
+    ok(!!hwnd_desktop, "Failed to get hwnd_desktop window (%d).\n", GetLastError());
+    hwnd_child = create_tool_window(WS_VISIBLE|WS_CHILD, hwnd);
+    ok(!!hwnd_child, "Failed to create child window (%d)\n", GetLastError());
+    hwnd_grandchild = create_tool_window(WS_VISIBLE|WS_CHILD, hwnd);
+    ok(!!hwnd_grandchild, "Failed to create grandchild window (%d)\n", GetLastError());
+
+    ret = SetWindowPos(hwnd, hwnd2, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
+    ok(ret, "Got %d\n", ret);
+    check_active_state(hwnd, hwnd, hwnd);
+
+    ret = SetWindowPos(hwnd2, hwnd, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
+    ok(ret, "Got %d\n", ret);
+    check_active_state(hwnd2, hwnd2, hwnd2);
+
+    ret = SetWindowPos(hwnd_child, hwnd2, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
+    ok(ret, "Got %d\n", ret);
+    check_active_state(hwnd2, hwnd2, hwnd2);
+
+    ret = SetWindowPos(hwnd_grandchild, hwnd2, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
+    ok(ret, "Got %d\n", ret);
+    check_active_state(hwnd2, hwnd2, hwnd2);
+
+    GetWindowRect(hwnd_grandchild, &rc1);
+    ret = SetWindowPos(hwnd_grandchild, hwnd2, 0, 0, 0, 0, 0);
+    ok(ret, "Got %d\n", ret);
+    GetWindowRect(hwnd_grandchild, &rc2);
+    ok(rc1.top == rc2.top && rc1.left == rc2.left && rc1.bottom == rc2.bottom && rc1.right == rc2.right,
+       "Got (%d, %d, %d, %d) != (%d, %d, %d, %d)\n",
+       rc1.top, rc1.left, rc1.bottom, rc1.right, rc2.top, rc2.left, rc2.bottom, rc2.right);
+    check_active_state(hwnd2, hwnd2, hwnd2);
+
+    ret = SetWindowPos(hwnd_child, hwnd_desktop, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
+    ok(!ret, "Got %d\n", ret);
+    check_active_state(hwnd2, hwnd2, hwnd2);
+
+    GetWindowRect(hwnd_child, &rc1);
+    ret = SetWindowPos(hwnd_child, hwnd_desktop, 0, 0, 0, 0, 0);
+    GetWindowRect(hwnd_child, &rc2);
+    ok(rc1.top == rc2.top && rc1.left == rc2.left && rc1.bottom == rc2.bottom && rc1.right == rc2.right,
+       "Got (%d, %d, %d, %d) != (%d, %d, %d, %d)\n",
+       rc1.top, rc1.left, rc1.bottom, rc1.right, rc2.top, rc2.left, rc2.bottom, rc2.right);
+    check_active_state(hwnd2, hwnd2, hwnd2);
+
+    ret = SetWindowPos(hwnd_desktop, hwnd_child, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
+    ok(!ret, "Got %d\n", ret);
+    check_active_state(hwnd2, hwnd2, hwnd2);
+
+    ret = SetWindowPos(hwnd_desktop, hwnd, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
+    ok(!ret, "Got %d\n", ret);
+    check_active_state(hwnd2, hwnd2, hwnd2);
+
+    ret = SetWindowPos(hwnd, hwnd_desktop, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
+    todo_wine ok(!ret, "Got %d\n", ret);
+    todo_wine check_active_state(hwnd2, hwnd2, hwnd2);
+
+    DestroyWindow(hwnd_grandchild);
+    DestroyWindow(hwnd_child);
 }
 
 static void test_SetMenu(HWND parent)
@@ -2439,34 +2540,6 @@ todo_wine
     DestroyWindow( child );
 }
 
-#define check_wnd_state(a,b,c,d) check_wnd_state_(__FILE__,__LINE__,a,b,c,d)
-static void check_wnd_state_(const char *file, int line,
-                             HWND active, HWND foreground, HWND focus, HWND capture)
-{
-    ok_(file, line)(active == GetActiveWindow(), "GetActiveWindow() = %p\n", GetActiveWindow());
-    /* only check foreground if it belongs to the current thread */
-    /* foreground can be moved to a different app pretty much at any time */
-    if (foreground && GetForegroundWindow() &&
-        GetWindowThreadProcessId(GetForegroundWindow(), NULL) == GetCurrentThreadId())
-        ok_(file, line)(foreground == GetForegroundWindow(), "GetForegroundWindow() = %p\n", GetForegroundWindow());
-    ok_(file, line)(focus == GetFocus(), "GetFocus() = %p\n", GetFocus());
-    ok_(file, line)(capture == GetCapture(), "GetCapture() = %p\n", GetCapture());
-}
-
-/* same as above but without capture test */
-#define check_active_state(a,b,c) check_active_state_(__FILE__,__LINE__,a,b,c)
-static void check_active_state_(const char *file, int line,
-                                HWND active, HWND foreground, HWND focus)
-{
-    ok_(file, line)(active == GetActiveWindow(), "GetActiveWindow() = %p\n", GetActiveWindow());
-    /* only check foreground if it belongs to the current thread */
-    /* foreground can be moved to a different app pretty much at any time */
-    if (foreground && GetForegroundWindow() &&
-        GetWindowThreadProcessId(GetForegroundWindow(), NULL) == GetCurrentThreadId())
-        ok_(file, line)(foreground == GetForegroundWindow(), "GetForegroundWindow() = %p\n", GetForegroundWindow());
-    ok_(file, line)(focus == GetFocus(), "GetFocus() = %p\n", GetFocus());
-}
-
 static void test_SetActiveWindow(HWND hwnd)
 {
     HWND hwnd2;
@@ -6438,7 +6511,7 @@ START_TEST(win)
 
     test_mdi();
     test_icons();
-    test_SetWindowPos(hwndMain);
+    test_SetWindowPos(hwndMain, hwndMain2);
     test_SetMenu(hwndMain);
     test_SetFocus(hwndMain);
     test_SetActiveWindow(hwndMain);
diff --git a/dlls/user32/winpos.c b/dlls/user32/winpos.c
index 03c16c9..e14944e 100644
--- a/dlls/user32/winpos.c
+++ b/dlls/user32/winpos.c
@@ -1844,17 +1844,18 @@ static UINT SWP_DoNCCalcSize( WINDOWPOS* pWinpos, const RECT* pNewWindowRect, RE
 }
 
 /* fix redundant flags and values in the WINDOWPOS structure */
-static BOOL fixup_flags( WINDOWPOS *winpos )
+#define ERROR_ABORT_WITH_TRUE 30000
+static UINT fixup_flags( WINDOWPOS *winpos )
 {
     HWND parent;
     RECT window_rect;
     WND *wndPtr = WIN_GetPtr( winpos->hwnd );
-    BOOL ret = TRUE;
+    UINT ret = ERROR_SUCCESS;
 
     if (!wndPtr || wndPtr == WND_OTHER_PROCESS)
     {
         SetLastError( ERROR_INVALID_WINDOW_HANDLE );
-        return FALSE;
+        return ERROR_FUNCTION_FAILED;
     }
     winpos->hwnd = wndPtr->obj.handle;  /* make it a full handle */
 
@@ -1928,7 +1929,10 @@ static BOOL fixup_flags( WINDOWPOS *winpos )
     }
     else
     {
-        if (GetAncestor( winpos->hwndInsertAfter, GA_PARENT ) != parent) ret = FALSE;
+        HWND ia_parent = GetAncestor( winpos->hwndInsertAfter, GA_PARENT );
+
+        if (!ia_parent) ret = ERROR_FUNCTION_FAILED;
+        else if (ia_parent != parent) ret = ERROR_ABORT_WITH_TRUE;
         else
         {
             /* don't need to change the Zorder of hwnd if it's already inserted
@@ -2029,7 +2033,7 @@ BOOL set_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags,
 BOOL USER_SetWindowPos( WINDOWPOS * winpos )
 {
     RECT newWindowRect, newClientRect, valid_rects[2];
-    UINT orig_flags;
+    UINT orig_flags, ret;
     
     orig_flags = winpos->flags;
     
@@ -2052,7 +2056,11 @@ BOOL USER_SetWindowPos( WINDOWPOS * winpos )
     if (!SWP_DoWinPosChanging( winpos, &newWindowRect, &newClientRect )) return FALSE;
 
     /* Fix redundant flags */
-    if (!fixup_flags( winpos )) return FALSE;
+    ret = fixup_flags( winpos );
+    if(ret == ERROR_FUNCTION_FAILED)
+        return FALSE;
+    else if(ret == ERROR_ABORT_WITH_TRUE)
+        return TRUE;
 
     if((winpos->flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER)
     {
-- 
1.7.4.1




More information about the wine-patches mailing list