From 76adb1ff0d3eebd81cebee12ce71c29e8d16a6b9 Mon Sep 17 00:00:00 2001 From: Martin Fuchs Date: Tue, 18 Nov 2003 00:13:34 +0000 Subject: [PATCH] - Move shell window into the background. - Add tests for Get/SetShellWindow(). --- dlls/user/focus.c | 22 +++++--- dlls/user/tests/win.c | 124 +++++++++++++++++++++++++++++++++++++++++- server/window.c | 10 ++-- 3 files changed, 143 insertions(+), 13 deletions(-) diff --git a/dlls/user/focus.c b/dlls/user/focus.c index bea90194fb4..410fc563672 100644 --- a/dlls/user/focus.c +++ b/dlls/user/focus.c @@ -362,6 +362,21 @@ BOOL WINAPI SetShellWindowEx(HWND hwndShell, HWND hwndListView) { BOOL ret; + if (GetShellWindow()) + return FALSE; + + if (GetWindowLongW(hwndShell, GWL_EXSTYLE) & WS_EX_TOPMOST) + return FALSE; + + if (hwndListView != hwndShell) + if (GetWindowLongW(hwndListView, GWL_EXSTYLE) & WS_EX_TOPMOST) + return FALSE; + + if (hwndListView && hwndListView!=hwndShell) + SetWindowPos(hwndListView, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE); + + SetWindowPos(hwndShell, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE); + SERVER_START_REQ(set_global_windows) { req->flags = SET_GLOBAL_SHELL_WINDOWS; @@ -371,13 +386,6 @@ BOOL WINAPI SetShellWindowEx(HWND hwndShell, HWND hwndListView) } SERVER_END_REQ; - if (ret) - { - if (hwndListView && hwndListView!=hwndShell) - SetWindowPos(hwndListView, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE); - - SetWindowPos(hwndShell, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE); - } return ret; } diff --git a/dlls/user/tests/win.c b/dlls/user/tests/win.c index 1d675c595c4..170f8950722 100644 --- a/dlls/user/tests/win.c +++ b/dlls/user/tests/win.c @@ -563,6 +563,128 @@ static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam) return CallNextHookEx(hhook, nCode, wParam, lParam); } +static void test_shell_window() +{ + BOOL ret; + DWORD error; + HMODULE hinst, hUser32; + BOOL (WINAPI*SetShellWindow)(HWND); + BOOL (WINAPI*SetShellWindowEx)(HWND, HWND); + HWND hwnd1, hwnd2, hwnd3, hwnd4, hwnd5; + HWND shellWindow, nextWnd; + + shellWindow = GetShellWindow(); + hinst = GetModuleHandle(0); + hUser32 = GetModuleHandleA("user32"); + + SetShellWindow = (void *)GetProcAddress(hUser32, "SetShellWindow"); + SetShellWindowEx = (void *)GetProcAddress(hUser32, "SetShellWindowEx"); + + trace("previous shell window: %p\n", shellWindow); + + if (shellWindow) { + DWORD pid; + HANDLE hProcess; + + ret = DestroyWindow(shellWindow); + error = GetLastError(); + + ok(!ret, "DestroyWindow(shellWindow)\n"); + /* passes on Win XP, but not on Win98 + ok(error==ERROR_ACCESS_DENIED, "ERROR_ACCESS_DENIED after DestroyWindow(shellWindow)\n"); */ + + /* close old shell instance */ + GetWindowThreadProcessId(shellWindow, &pid); + hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); + ret = TerminateProcess(hProcess, 0); + ok(ret, "termination of previous shell process failed: GetLastError()=%ld", GetLastError()); + WaitForSingleObject(hProcess, INFINITE); /* wait for termination */ + CloseHandle(hProcess); + } + + hwnd1 = CreateWindowEx(0, TEXT("#32770"), TEXT("TEST1"), WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 100, 100, 300, 200, 0, 0, hinst, 0); + trace("created window 1: %p\n", hwnd1); + + ret = SetShellWindow(hwnd1); + ok(ret, "first call to SetShellWindow(hwnd1)\n"); + shellWindow = GetShellWindow(); + ok(shellWindow==hwnd1, "wrong shell window: %p", shellWindow); + + ret = SetShellWindow(hwnd1); + ok(!ret, "second call to SetShellWindow(hwnd1)\n"); + + ret = SetShellWindow(0); + error = GetLastError(); + /* passes on Win XP, but not on Win98 + ok(!ret, "reset shell window by SetShellWindow(0)\n"); + ok(error==ERROR_INVALID_WINDOW_HANDLE, "ERROR_INVALID_WINDOW_HANDLE after SetShellWindow(0)\n"); */ + + ret = SetShellWindow(hwnd1); + /* passes on Win XP, but not on Win98 + ok(!ret, "third call to SetShellWindow(hwnd1)\n"); */ + + todo_wine + { + SetWindowLong(hwnd1, GWL_EXSTYLE, GetWindowLong(hwnd1,GWL_EXSTYLE)|WS_EX_TOPMOST); + ret = GetWindowLong(hwnd1,GWL_EXSTYLE)&WS_EX_TOPMOST? TRUE: FALSE; + ok(!ret, "SetWindowExStyle(hwnd1, WS_EX_TOPMOST)\n"); + } + + ret = DestroyWindow(hwnd1); + ok(ret, "DestroyWindow(hwnd1)\n"); + + hwnd2 = CreateWindowEx(WS_EX_TOPMOST, TEXT("#32770"), TEXT("TEST2"), WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 150, 250, 300, 200, 0, 0, hinst, 0); + trace("created window 2: %p\n", hwnd2); + ret = SetShellWindow(hwnd2); + ok(!ret, "SetShellWindow(hwnd2) with WS_EX_TOPMOST"); + + hwnd3 = CreateWindowEx(0, TEXT("#32770"), TEXT("TEST3"), WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 200, 400, 300, 200, 0, 0, hinst, 0); + trace("created window 3: %p\n", hwnd3); + + hwnd4 = CreateWindowEx(0, TEXT("#32770"), TEXT("TEST4"), WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 250, 500, 300, 200, 0, 0, hinst, 0); + trace("created window 4: %p\n", hwnd4); + + nextWnd = GetWindow(hwnd4, GW_HWNDNEXT); + ok(nextWnd==hwnd3, "wrong next window for hwnd4: %p - expected hwnd3\n", nextWnd); + + ret = SetShellWindow(hwnd4); + ok(ret, "SetShellWindow(hwnd4)\n"); + shellWindow = GetShellWindow(); + ok(shellWindow==hwnd4, "wrong shell window: %p - expected hwnd4", shellWindow); + + nextWnd = GetWindow(hwnd4, GW_HWNDNEXT); + ok(nextWnd==0, "wrong next window for hwnd4: %p - expected 0\n", nextWnd); + + ret = SetWindowPos(hwnd4, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE); + ok(ret, "SetWindowPos(hwnd4, HWND_TOPMOST)\n"); + + ret = SetWindowPos(hwnd4, hwnd3, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE); + ok(ret, "SetWindowPos(hwnd4, hwnd3"); + + ret = SetShellWindow(hwnd3); + ok(!ret, "SetShellWindow(hwnd3)\n"); + shellWindow = GetShellWindow(); + ok(shellWindow==hwnd4, "wrong shell window: %p - expected hwnd4", shellWindow); + + hwnd5 = CreateWindowEx(0, TEXT("#32770"), TEXT("TEST5"), WS_OVERLAPPEDWINDOW/*|WS_VISIBLE*/, 300, 600, 300, 200, 0, 0, hinst, 0); + trace("created window 5: %p\n", hwnd5); + ret = SetWindowPos(hwnd4, hwnd5, 0, 0, 0, 0, SWP_NOSIZE|SWP_NOMOVE); + ok(ret, "SetWindowPos(hwnd4, hwnd5)\n"); + + todo_wine + { + nextWnd = GetWindow(hwnd4, GW_HWNDNEXT); + ok(nextWnd==0, "wrong next window for hwnd4 after SetWindowPos(): %p - expected 0\n", nextWnd); + } + + /* destroy test windows */ + DestroyWindow(hwnd2); + DestroyWindow(hwnd3); + DestroyWindow(hwnd4); + DestroyWindow(hwnd5); +} + + START_TEST(win) { pGetAncestor = (void *)GetProcAddress( GetModuleHandleA("user32.dll"), "GetAncestor" ); @@ -586,6 +708,6 @@ START_TEST(win) assert( hwndMain2 ); test_parent_owner(); - + test_shell_window(); UnhookWindowsHookEx(hhook); } diff --git a/server/window.c b/server/window.c index 7ce6ba83f1a..a13c7343c42 100644 --- a/server/window.c +++ b/server/window.c @@ -836,16 +836,16 @@ DECL_HANDLER(get_window_properties) /* helper for set_global_windows request */ static int get_new_global_window( struct window **win, user_handle_t handle ) { - if (*win && (*win)->thread != current) - { - set_error( STATUS_ACCESS_DENIED ); - return 0; - } if (!handle) { *win = NULL; return 1; } + else if (*win) + { + set_error( STATUS_ACCESS_DENIED ); + return 0; + } *win = get_window( handle ); return (*win != NULL); }