From 7c7c64313765a32a7e5adf808ab69eb49eebd7bf Mon Sep 17 00:00:00 2001 From: Thomas Faber Date: Sat, 3 Sep 2011 20:16:33 +0000 Subject: [PATCH] [KMTestSuite] - Sync with rostests r53563 svn path=/branches/GSoC_2011/KMTestSuite/; revision=53565 --- apitests/ntdll/NtFreeVirtualMemory.c | 50 +- apitests/user32/WndProc.c | 8 +- rosautotest/CMakeLists.txt | 3 +- winetests/CMakeLists.txt | 4 +- winetests/advapi32/service.c | 3 +- winetests/rpcrt4/CMakeLists.txt | 14 + winetests/rpcrt4/rpcrt4.rbuild | 2 + winetests/rpcrt4/server.c | 4 +- winetests/shell32/CMakeLists.txt | 3 +- winetests/shell32/shlfileop.c | 2 - winetests/shlwapi/CMakeLists.txt | 2 + winetests/user32/broadcast.c | 2 +- winetests/user32/class.c | 88 ++- winetests/user32/clipboard.c | 34 +- winetests/user32/combo.c | 14 +- winetests/user32/cursoricon.c | 794 ++++++++++++++++++- winetests/user32/dce.c | 93 ++- winetests/user32/dde.c | 46 +- winetests/user32/dialog.c | 44 +- winetests/user32/edit.c | 53 +- winetests/user32/generated.c | 6 +- winetests/user32/input.c | 45 +- winetests/user32/listbox.c | 11 +- winetests/user32/menu.c | 101 ++- winetests/user32/monitor.c | 8 + winetests/user32/msg.c | 1066 ++++++++++++++++++++++++-- winetests/user32/resource.c | 12 +- winetests/user32/scroll.c | 6 +- winetests/user32/static.c | 4 +- winetests/user32/sysparams.c | 4 +- winetests/user32/text.c | 11 +- winetests/user32/win.c | 749 ++++++++++++++++-- winetests/user32/wsprintf.c | 70 +- 33 files changed, 2970 insertions(+), 386 deletions(-) diff --git a/apitests/ntdll/NtFreeVirtualMemory.c b/apitests/ntdll/NtFreeVirtualMemory.c index 416e54b6e2d..075b4f41b00 100644 --- a/apitests/ntdll/NtFreeVirtualMemory.c +++ b/apitests/ntdll/NtFreeVirtualMemory.c @@ -15,15 +15,15 @@ static void Test_NtFreeVirtualMemory(void) &Length, MEM_RESERVE, PAGE_READWRITE); - ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed : 0x%08x\n", Status); - ok(Length == PAGE_SIZE, "Length mismatch : 0x08x\n", Length); + ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed : 0x%08lx\n", Status); + ok(Length == PAGE_SIZE, "Length mismatch : 0x%08lx\n", (ULONG)Length); ok(((ULONG_PTR)Buffer % PAGE_SIZE) == 0, "The buffer is not aligned to PAGE_SIZE.\n"); Status = NtFreeVirtualMemory(NtCurrentProcess(), &Buffer, &Length, MEM_DECOMMIT); - ok(Status == STATUS_SUCCESS, "NtFreeVirtualMemory failed : 0x%08x\n", Status); + ok(Status == STATUS_SUCCESS, "NtFreeVirtualMemory failed : 0x%08lx\n", Status); /* Now try to free more than we got */ Length++; @@ -31,13 +31,13 @@ static void Test_NtFreeVirtualMemory(void) &Buffer, &Length, MEM_DECOMMIT); - ok(Status == STATUS_UNABLE_TO_FREE_VM, "NtFreeVirtualMemory returned status : 0x%08x\n", Status); + ok(Status == STATUS_UNABLE_TO_FREE_VM, "NtFreeVirtualMemory returned status : 0x%08lx\n", Status); Status = NtFreeVirtualMemory(NtCurrentProcess(), &Buffer, &Length, MEM_RELEASE); - ok(Status == STATUS_UNABLE_TO_FREE_VM, "NtFreeVirtualMemory returned status : 0x%08x\n", Status); + ok(Status == STATUS_UNABLE_TO_FREE_VM, "NtFreeVirtualMemory returned status : 0x%08lx\n", Status); /* Free out of bounds from the wrong origin */ Length = PAGE_SIZE; @@ -47,7 +47,7 @@ static void Test_NtFreeVirtualMemory(void) &Buffer2, &Length, MEM_DECOMMIT); - ok(Status == STATUS_UNABLE_TO_FREE_VM, "NtFreeVirtualMemory returned status : 0x%08x\n", Status); + ok(Status == STATUS_UNABLE_TO_FREE_VM, "NtFreeVirtualMemory returned status : 0x%08lx\n", Status); Buffer2 = (PVOID)((ULONG_PTR)Buffer+1); Length = PAGE_SIZE; @@ -55,7 +55,7 @@ static void Test_NtFreeVirtualMemory(void) &Buffer2, &Length, MEM_RELEASE); - ok(Status == STATUS_UNABLE_TO_FREE_VM, "NtFreeVirtualMemory returned status : 0x%08x\n", Status); + ok(Status == STATUS_UNABLE_TO_FREE_VM, "NtFreeVirtualMemory returned status : 0x%08lx\n", Status); /* Same but in bounds */ Length = PAGE_SIZE - 1; @@ -65,7 +65,7 @@ static void Test_NtFreeVirtualMemory(void) &Buffer2, &Length, MEM_DECOMMIT); - ok(Status == STATUS_SUCCESS, "NtFreeVirtualMemory returned status : 0x%08x\n", Status); + ok(Status == STATUS_SUCCESS, "NtFreeVirtualMemory returned status : 0x%08lx\n", Status); ok(Buffer2 == Buffer, "NtFreeVirtualMemory set wrong buffer.\n"); ok(Length == PAGE_SIZE, "NtFreeVirtualMemory did not round Length to PAGE_SIZE.\n"); @@ -75,7 +75,7 @@ static void Test_NtFreeVirtualMemory(void) &Buffer2, &Length, MEM_RELEASE); - ok(Status == STATUS_SUCCESS, "NtFreeVirtualMemory returned status : 0x%08x\n", Status); + ok(Status == STATUS_SUCCESS, "NtFreeVirtualMemory returned status : 0x%08lx\n", Status); ok(Buffer2 == Buffer, "NtFreeVirtualMemory set wrong buffer.\n"); ok(Length == PAGE_SIZE, "NtFreeVirtualMemory did not round Length to PAGE_SIZE.\n"); @@ -87,8 +87,8 @@ static void Test_NtFreeVirtualMemory(void) &Length, MEM_RESERVE, PAGE_READWRITE); - ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed : 0x%08x\n", Status); - ok(Length == 2*PAGE_SIZE, "Length mismatch : 0x08x\n", Length); + ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed : 0x%08lx\n", Status); + ok(Length == 2*PAGE_SIZE, "Length mismatch : 0x%08lx\n", (ULONG)Length); ok(((ULONG_PTR)Buffer % PAGE_SIZE) == 0, "The buffer is not aligned to PAGE_SIZE.\n"); Buffer2 = Buffer; @@ -97,8 +97,8 @@ static void Test_NtFreeVirtualMemory(void) &Buffer2, &Length, MEM_RELEASE); - ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed : 0x%08x\n", Status); - ok(Length == PAGE_SIZE, "Length mismatch : 0x08x\n", Length); + ok(NT_SUCCESS(Status), "NtFreeVirtualMemory failed : 0x%08lx\n", Status); + ok(Length == PAGE_SIZE, "Length mismatch : 0x%08lx\n", (ULONG)Length); ok(Buffer2 == Buffer, "The buffer is not aligned to PAGE_SIZE.\n"); Buffer2 = (PVOID)((ULONG_PTR)Buffer+PAGE_SIZE); @@ -107,8 +107,8 @@ static void Test_NtFreeVirtualMemory(void) &Buffer2, &Length, MEM_RELEASE); - ok(NT_SUCCESS(Status), "NtFreeVirtualMemory failed : 0x%08x\n", Status); - ok(Length == PAGE_SIZE, "Length mismatch : 0x08x\n", Length); + ok(NT_SUCCESS(Status), "NtFreeVirtualMemory failed : 0x%08lx\n", Status); + ok(Length == PAGE_SIZE, "Length mismatch : 0x%08lx\n", (ULONG)Length); ok(Buffer2 == (PVOID)((ULONG_PTR)Buffer+PAGE_SIZE), "The buffer is not aligned to PAGE_SIZE.\n"); /* Same, but try to free the second page before the first one */ @@ -119,8 +119,8 @@ static void Test_NtFreeVirtualMemory(void) &Length, MEM_RESERVE, PAGE_READWRITE); - ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed : 0x%08x\n", Status); - ok(Length == 2*PAGE_SIZE, "Length mismatch : 0x08x\n", Length); + ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed : 0x%08lx\n", Status); + ok(Length == 2*PAGE_SIZE, "Length mismatch : 0x%08lx\n", (ULONG)Length); ok(((ULONG_PTR)Buffer % PAGE_SIZE) == 0, "The buffer is not aligned to PAGE_SIZE.\n"); Buffer2 = (PVOID)((ULONG_PTR)Buffer+PAGE_SIZE); @@ -129,8 +129,8 @@ static void Test_NtFreeVirtualMemory(void) &Buffer2, &Length, MEM_RELEASE); - ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed : 0x%08x\n", Status); - ok(Length == PAGE_SIZE, "Length mismatch : 0x08x\n", Length); + ok(NT_SUCCESS(Status), "NtFreeVirtualMemory failed : 0x%08lx\n", Status); + ok(Length == PAGE_SIZE, "Length mismatch : 0x%08lx\n", (ULONG)Length); ok(Buffer2 == (PVOID)((ULONG_PTR)Buffer+PAGE_SIZE), "The buffer is not aligned to PAGE_SIZE.\n"); Buffer2 = Buffer; @@ -139,8 +139,8 @@ static void Test_NtFreeVirtualMemory(void) &Buffer2, &Length, MEM_RELEASE); - ok(NT_SUCCESS(Status), "NtFreeVirtualMemory failed : 0x%08x\n", Status); - ok(Length == PAGE_SIZE, "Length mismatch : 0x08x\n", Length); + ok(NT_SUCCESS(Status), "NtFreeVirtualMemory failed : 0x%08lx\n", Status); + ok(Length == PAGE_SIZE, "Length mismatch : 0x%08lx\n", (ULONG)Length); ok(Buffer2 == Buffer, "The buffer is not aligned to PAGE_SIZE.\n"); /* Now allocate two pages and try to free them in the middle */ @@ -151,8 +151,8 @@ static void Test_NtFreeVirtualMemory(void) &Length, MEM_RESERVE, PAGE_READWRITE); - ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed : 0x%08x\n", Status); - ok(Length == 2*PAGE_SIZE, "Length mismatch : 0x08x\n", Length); + ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed : 0x%08lx\n", Status); + ok(Length == 2*PAGE_SIZE, "Length mismatch : 0x%08lx\n", (ULONG)Length); ok(((ULONG_PTR)Buffer % PAGE_SIZE) == 0, "The buffer is not aligned to PAGE_SIZE.\n"); Buffer2 = (PVOID)((ULONG_PTR)Buffer+1); @@ -161,8 +161,8 @@ static void Test_NtFreeVirtualMemory(void) &Buffer2, &Length, MEM_RELEASE); - ok(NT_SUCCESS(Status), "NtAllocateVirtualMemory failed : 0x%08x\n", Status); - ok(Length == 2*PAGE_SIZE, "Length mismatch : 0x08x\n", Length); + ok(NT_SUCCESS(Status), "NtFreeVirtualMemory failed : 0x%08lx\n", Status); + ok(Length == 2*PAGE_SIZE, "Length mismatch : 0x%08lx\n", (ULONG)Length); ok(Buffer2 == Buffer, "The buffer is not aligned to PAGE_SIZE.\n"); } diff --git a/apitests/user32/WndProc.c b/apitests/user32/WndProc.c index bc5437088fc..e9c70f1210a 100644 --- a/apitests/user32/WndProc.c +++ b/apitests/user32/WndProc.c @@ -32,7 +32,7 @@ static LRESULT WINAPI redraw_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LP { PAINTSTRUCT ps; BeginPaint(hwnd, &ps); - EndPaint(hwnd, &ps); + EndPaint(hwnd, &ps); return 1; } /* @@ -43,7 +43,7 @@ static LRESULT WINAPI redraw_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LP asm ("movl $0, %eax\n\t" "leave\n\t" "ret"); -#else +#elif defined(_M_IX86) //#ifdef _MSC_VER __asm { @@ -51,6 +51,8 @@ static LRESULT WINAPI redraw_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LP leave ret } +#else + trace("unimplemented\n"); #endif } return DefWindowProc(hwnd, msg, wparam, lparam); @@ -64,7 +66,7 @@ static void test_wndproc(void) cls.style = CS_DBLCLKS; cls.lpfnWndProc = (WNDPROC)redraw_window_procA; cls.cbClsExtra = 0; - cls.cbWndExtra = 0; + cls.cbWndExtra = 0; cls.hInstance = GetModuleHandleA(0); cls.hIcon = 0; cls.hCursor = LoadCursorA(0, IDC_ARROW); diff --git a/rosautotest/CMakeLists.txt b/rosautotest/CMakeLists.txt index a0a4795299e..e77ec8c744f 100644 --- a/rosautotest/CMakeLists.txt +++ b/rosautotest/CMakeLists.txt @@ -1,5 +1,4 @@ -set_unicode() set_cpp() list(APPEND SOURCE @@ -21,7 +20,7 @@ list(APPEND SOURCE add_executable(rosautotest ${SOURCE}) -set_module_type(rosautotest win32cui) +set_module_type(rosautotest win32cui UNICODE) add_importlibs(rosautotest advapi32 shell32 user32 wininet msvcrt kernel32 ntdll) add_pch(rosautotest precomp.h) diff --git a/winetests/CMakeLists.txt b/winetests/CMakeLists.txt index 40cffd8be17..4866549724f 100644 --- a/winetests/CMakeLists.txt +++ b/winetests/CMakeLists.txt @@ -75,9 +75,7 @@ add_subdirectory(quartz) add_subdirectory(rasapi32) add_subdirectory(riched20) add_subdirectory(riched32) -if(NOT MSVC) - add_subdirectory(rpcrt4) # FIXME: msvc build. -endif() +add_subdirectory(rpcrt4) add_subdirectory(rsabase) add_subdirectory(rsaenh) add_subdirectory(schannel) diff --git a/winetests/advapi32/service.c b/winetests/advapi32/service.c index aae8c6ea9b1..269ff6156af 100644 --- a/winetests/advapi32/service.c +++ b/winetests/advapi32/service.c @@ -32,7 +32,8 @@ #include "wine/test.h" -static const CHAR spooler[] = "Spooler"; /* Should be available on all platforms */ +//static const CHAR spooler[] = "Spooler"; /* Should be available on all platforms */ +static const CHAR spooler[] = "Eventlog"; /* All platform except reactos :-/ */ static BOOL (WINAPI *pChangeServiceConfig2A)(SC_HANDLE,DWORD,LPVOID); static BOOL (WINAPI *pEnumServicesStatusExA)(SC_HANDLE, SC_ENUM_TYPE, DWORD, diff --git a/winetests/rpcrt4/CMakeLists.txt b/winetests/rpcrt4/CMakeLists.txt index d28a9e1ea1b..75b418df0f9 100644 --- a/winetests/rpcrt4/CMakeLists.txt +++ b/winetests/rpcrt4/CMakeLists.txt @@ -6,8 +6,17 @@ add_definitions( -D__ROS_LONG64__ -D_DLL -D__USE_CRTIMP) +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +if(MSVC) + set(IDL_FLAGS ${IDL_FLAGS} /prefix server s_ /app_config) +else() + set(IDL_FLAGS ${IDL_FLAGS} --prefix-server=s_) +endif() + add_rpc_files(client server.idl) add_rpc_files(server server.idl) +unset(IDL_FLAGS) list(APPEND SOURCE cstub.c @@ -21,6 +30,11 @@ list(APPEND SOURCE ${CMAKE_CURRENT_BINARY_DIR}/server_c.c ${CMAKE_CURRENT_BINARY_DIR}/server_s.c) +if(MSVC) + # The nmake generator misses this dependency, so set it explicitly until this bug is fixed. + set_source_files_properties(server.c PROPERTIES OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/server_s.h) +endif() + add_executable(rpcrt4_winetest ${SOURCE}) target_link_libraries(rpcrt4_winetest uuid diff --git a/winetests/rpcrt4/rpcrt4.rbuild b/winetests/rpcrt4/rpcrt4.rbuild index fc366d0284e..dea00074b0e 100644 --- a/winetests/rpcrt4/rpcrt4.rbuild +++ b/winetests/rpcrt4/rpcrt4.rbuild @@ -12,6 +12,8 @@ . 0x0500 + + IServer_v0_0_s_ifspec wine pseh ole32 diff --git a/winetests/rpcrt4/server.c b/winetests/rpcrt4/server.c index 21b0cedf6ab..ccf995623ba 100644 --- a/winetests/rpcrt4/server.c +++ b/winetests/rpcrt4/server.c @@ -1542,12 +1542,12 @@ server(void) if (pRpcServerRegisterIfEx) { trace("Using RpcServerRegisterIfEx\n"); - status = pRpcServerRegisterIfEx(IServer_v0_0_s_ifspec, NULL, NULL, + status = pRpcServerRegisterIfEx(s_IServer_v0_0_s_ifspec, NULL, NULL, RPC_IF_ALLOW_CALLBACKS_WITH_NO_AUTH, RPC_C_LISTEN_MAX_CALLS_DEFAULT, NULL); } else - status = RpcServerRegisterIf(IServer_v0_0_s_ifspec, NULL, NULL); + status = RpcServerRegisterIf(s_IServer_v0_0_s_ifspec, NULL, NULL); ok(status == RPC_S_OK, "RpcServerRegisterIf failed with status %d\n", status); status = RpcServerListen(1, 20, TRUE); ok(status == RPC_S_OK, "RpcServerListen failed with status %d\n", status); diff --git a/winetests/shell32/CMakeLists.txt b/winetests/shell32/CMakeLists.txt index b2ab6170b1b..0433f2a7cdf 100644 --- a/winetests/shell32/CMakeLists.txt +++ b/winetests/shell32/CMakeLists.txt @@ -1,6 +1,5 @@ -remove_definitions(-D_WIN32_WINNT=0x502) -add_definitions(-D_WIN32_WINNT=0x501) +remove_definitions(-DWINVER=0x502 -D_WIN32_IE=0x600 -D_WIN32_WINNT=0x502) add_definitions( -D__ROS_LONG64__ diff --git a/winetests/shell32/shlfileop.c b/winetests/shell32/shlfileop.c index 08867c87d6c..3e9a2e49e14 100644 --- a/winetests/shell32/shlfileop.c +++ b/winetests/shell32/shlfileop.c @@ -2309,8 +2309,6 @@ static void test_unicode(void) ok(!file_existsW(UNICODE_PATH), "The directory should have been removed\n"); } -extern HRESULT WINAPI Shell_MergeMenus (HMENU hmDst, HMENU hmSrc, UINT uInsert, UINT uIDAdjust, UINT uIDAdjustMax, ULONG uFlags); - static void test_shlmenu(void) { HRESULT hres; diff --git a/winetests/shlwapi/CMakeLists.txt b/winetests/shlwapi/CMakeLists.txt index a2dfd8ba474..807f11a2eb8 100644 --- a/winetests/shlwapi/CMakeLists.txt +++ b/winetests/shlwapi/CMakeLists.txt @@ -3,6 +3,8 @@ add_definitions( -D__ROS_LONG64__ -D_DLL -D__USE_CRTIMP) +remove_definitions(-DWINVER=0x502 -D_WIN32_IE=0x600 -D_WIN32_WINNT=0x502) + list(APPEND SOURCE assoc.c clist.c diff --git a/winetests/user32/broadcast.c b/winetests/user32/broadcast.c index 48f1318a879..21d38e3cc40 100644 --- a/winetests/user32/broadcast.c +++ b/winetests/user32/broadcast.c @@ -18,7 +18,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#define _WIN32_WINNT 0x0501 +//#define _WIN32_WINNT 0x0501 #include #include diff --git a/winetests/user32/class.c b/winetests/user32/class.c index 7149163fbd3..f9d1aef8325 100755 --- a/winetests/user32/class.c +++ b/winetests/user32/class.c @@ -617,6 +617,7 @@ static void test_builtinproc(void) static const WCHAR classW[] = {'d','e','f','t','e','s','t',0}; WCHAR unistring[] = {0x142, 0x40e, 0x3b4, 0}; /* a string that would be destroyed by a W->A->W conversion */ WNDPROC pDefWindowProcA, pDefWindowProcW; + WNDPROC pNtdllDefWindowProcA, pNtdllDefWindowProcW; WNDPROC oldproc; WNDCLASSEXA cls; /* the memory layout of WNDCLASSEXA and WNDCLASSEXW is the same */ WCHAR buf[128]; @@ -626,45 +627,56 @@ static void test_builtinproc(void) pDefWindowProcA = (void *)GetProcAddress(GetModuleHandle("user32.dll"), "DefWindowProcA"); pDefWindowProcW = (void *)GetProcAddress(GetModuleHandle("user32.dll"), "DefWindowProcW"); + pNtdllDefWindowProcA = (void *)GetProcAddress(GetModuleHandle("ntdll.dll"), "NtdllDefWindowProc_A"); + pNtdllDefWindowProcW = (void *)GetProcAddress(GetModuleHandle("ntdll.dll"), "NtdllDefWindowProc_W"); - for (i = 0; i < 4; i++) + /* On Vista+, the user32.dll export DefWindowProcA/W is forwarded to */ + /* ntdll.NtdllDefWindowProc_A/W. However, the wndproc returned by */ + /* GetClassLong/GetWindowLong points to an unexported user32 function */ + if (pDefWindowProcA == pNtdllDefWindowProcA && + pDefWindowProcW == pNtdllDefWindowProcW) + skip("user32.DefWindowProcX forwarded to ntdll.NtdllDefWindowProc_X\n"); + else { - ZeroMemory(&cls, sizeof(cls)); - cls.cbSize = sizeof(cls); - cls.hInstance = GetModuleHandle(NULL); - cls.hbrBackground = GetStockObject (WHITE_BRUSH); - if (i & 1) - cls.lpfnWndProc = pDefWindowProcA; - else - cls.lpfnWndProc = pDefWindowProcW; - - if (i & 2) + for (i = 0; i < 4; i++) { - cls.lpszClassName = classA; - atom = RegisterClassExA(&cls); + ZeroMemory(&cls, sizeof(cls)); + cls.cbSize = sizeof(cls); + cls.hInstance = GetModuleHandle(NULL); + cls.hbrBackground = GetStockObject (WHITE_BRUSH); + if (i & 1) + cls.lpfnWndProc = pDefWindowProcA; + else + cls.lpfnWndProc = pDefWindowProcW; + + if (i & 2) + { + cls.lpszClassName = classA; + atom = RegisterClassExA(&cls); + } + else + { + cls.lpszClassName = (LPCSTR)classW; + atom = RegisterClassExW((WNDCLASSEXW *)&cls); + } + ok(atom != 0, "Couldn't register class, i=%d, %d\n", i, GetLastError()); + + hwnd = CreateWindowA(classA, NULL, 0, 0, 0, 100, 100, NULL, NULL, GetModuleHandle(NULL), NULL); + ok(hwnd != NULL, "Couldn't create window i=%d\n", i); + + ok(GetWindowLongPtrA(hwnd, GWLP_WNDPROC) == (LONG_PTR)pDefWindowProcA, "Wrong ANSI wndproc: %p vs %p\n", + (void *)GetWindowLongPtrA(hwnd, GWLP_WNDPROC), pDefWindowProcA); + ok(GetClassLongPtrA(hwnd, GCLP_WNDPROC) == (ULONG_PTR)pDefWindowProcA, "Wrong ANSI wndproc: %p vs %p\n", + (void *)GetClassLongPtrA(hwnd, GCLP_WNDPROC), pDefWindowProcA); + + ok(GetWindowLongPtrW(hwnd, GWLP_WNDPROC) == (LONG_PTR)pDefWindowProcW, "Wrong Unicode wndproc: %p vs %p\n", + (void *)GetWindowLongPtrW(hwnd, GWLP_WNDPROC), pDefWindowProcW); + ok(GetClassLongPtrW(hwnd, GCLP_WNDPROC) == (ULONG_PTR)pDefWindowProcW, "Wrong Unicode wndproc: %p vs %p\n", + (void *)GetClassLongPtrW(hwnd, GCLP_WNDPROC), pDefWindowProcW); + + DestroyWindow(hwnd); + UnregisterClass((LPSTR)(DWORD_PTR)atom, GetModuleHandle(NULL)); } - else - { - cls.lpszClassName = (LPCSTR)classW; - atom = RegisterClassExW((WNDCLASSEXW *)&cls); - } - ok(atom != 0, "Couldn't register class, i=%d, %d\n", i, GetLastError()); - - hwnd = CreateWindowA(classA, NULL, 0, 0, 0, 100, 100, NULL, NULL, GetModuleHandle(NULL), NULL); - ok(hwnd != NULL, "Couldn't create window i=%d\n", i); - - ok(GetWindowLongPtrA(hwnd, GWLP_WNDPROC) == (LONG_PTR)pDefWindowProcA, "Wrong ANSI wndproc: %p vs %p\n", - (void *)GetWindowLongPtrA(hwnd, GWLP_WNDPROC), pDefWindowProcA); - ok(GetClassLongPtrA(hwnd, GCLP_WNDPROC) == (ULONG_PTR)pDefWindowProcA, "Wrong ANSI wndproc: %p vs %p\n", - (void *)GetClassLongPtrA(hwnd, GCLP_WNDPROC), pDefWindowProcA); - - ok(GetWindowLongPtrW(hwnd, GWLP_WNDPROC) == (LONG_PTR)pDefWindowProcW, "Wrong Unicode wndproc: %p vs %p\n", - (void *)GetWindowLongPtrW(hwnd, GWLP_WNDPROC), pDefWindowProcW); - ok(GetClassLongPtrW(hwnd, GCLP_WNDPROC) == (ULONG_PTR)pDefWindowProcW, "Wrong Unicode wndproc: %p vs %p\n", - (void *)GetClassLongPtrW(hwnd, GCLP_WNDPROC), pDefWindowProcW); - - DestroyWindow(hwnd); - UnregisterClass((LPSTR)(DWORD_PTR)atom, GetModuleHandle(NULL)); } /* built-in winproc - window A/W type automatically detected */ @@ -942,22 +954,28 @@ if (0) { /* crashes under XP */ "expected ERROR_NOACCESS, got %d\n", GetLastError()); wcx.cbSize = 0; + wcx.lpfnWndProc = NULL; SetLastError(0xdeadbeef); ret = GetClassInfoExA(0, "static", &wcx); ok(ret, "GetClassInfoExA() error %d\n", GetLastError()); ok(wcx.cbSize == 0, "expected 0, got %u\n", wcx.cbSize); + ok(wcx.lpfnWndProc != NULL, "got null proc\n"); wcx.cbSize = sizeof(wcx) - 1; + wcx.lpfnWndProc = NULL; SetLastError(0xdeadbeef); ret = GetClassInfoExA(0, "static", &wcx); ok(ret, "GetClassInfoExA() error %d\n", GetLastError()); ok(wcx.cbSize == sizeof(wcx) - 1, "expected sizeof(wcx)-1, got %u\n", wcx.cbSize); + ok(wcx.lpfnWndProc != NULL, "got null proc\n"); wcx.cbSize = sizeof(wcx) + 1; + wcx.lpfnWndProc = NULL; SetLastError(0xdeadbeef); ret = GetClassInfoExA(0, "static", &wcx); ok(ret, "GetClassInfoExA() error %d\n", GetLastError()); ok(wcx.cbSize == sizeof(wcx) + 1, "expected sizeof(wcx)+1, got %u\n", wcx.cbSize); + ok(wcx.lpfnWndProc != NULL, "got null proc\n"); } START_TEST(class) diff --git a/winetests/user32/clipboard.c b/winetests/user32/clipboard.c index a0d0fe97745..266f629aa23 100755 --- a/winetests/user32/clipboard.c +++ b/winetests/user32/clipboard.c @@ -68,8 +68,8 @@ static void test_ClipboardOwner(void) ok(OpenClipboard(hWnd1), "OpenClipboard failed\n"); SetLastError(0xdeadbeef); - ok(!OpenClipboard(hWnd2) && - (GetLastError() == 0xdeadbeef || GetLastError() == ERROR_ACCESS_DENIED), + ret = OpenClipboard(hWnd2); + ok(!ret && (GetLastError() == 0xdeadbeef || GetLastError() == ERROR_ACCESS_DENIED), "OpenClipboard should fail without setting last error value, or with ERROR_ACCESS_DENIED, got error %d\n", GetLastError()); SetLastError(0xdeadbeef); @@ -79,9 +79,9 @@ static void test_ClipboardOwner(void) ok(GetClipboardOwner() == hWnd1, "clipboard should be owned by %p, not by %p\n", hWnd1, GetClipboardOwner()); SetLastError(0xdeadbeef); - ok(!OpenClipboard(hWnd2) && - (GetLastError() == 0xdeadbeef || GetLastError() == ERROR_ACCESS_DENIED), - "OpenClipboard should fail without setting last error valuei, or with ERROR_ACCESS_DENIED, got error %d\n", GetLastError()); + ret = OpenClipboard(hWnd2); + ok(!ret && (GetLastError() == 0xdeadbeef || GetLastError() == ERROR_ACCESS_DENIED), + "OpenClipboard should fail without setting last error value, or with ERROR_ACCESS_DENIED, got error %d\n", GetLastError()); ret = CloseClipboard(); ok( ret, "CloseClipboard error %d\n", GetLastError()); @@ -140,6 +140,7 @@ todo_wine atom_id = GlobalFindAtomA("my_cool_clipboard_format"); ok(atom_id == 0, "GlobalFindAtomA should fail\n"); test_last_error(ERROR_FILE_NOT_FOUND); + } for (format_id = 0; format_id < 0xffff; format_id++) { @@ -147,18 +148,9 @@ todo_wine len = GetClipboardFormatNameA(format_id, buf, 256); if (format_id < 0xc000) - { ok(!len, "GetClipboardFormatNameA should fail, but it returned %d (%s)\n", len, buf); - test_last_error(ERROR_INVALID_PARAMETER); - } else - { - if (len) - trace("%04x: %s\n", format_id, len ? buf : ""); - else - test_last_error(ERROR_INVALID_HANDLE); - } - } + if (len) trace("%04x: %s\n", format_id, len ? buf : ""); } ret = OpenClipboard(0); @@ -191,6 +183,9 @@ todo_wine ok(!EmptyClipboard(), "EmptyClipboard should fail if clipboard wasn't open\n"); ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN || broken(GetLastError() == 0xdeadbeef), /* wow64 */ "Wrong error %u\n", GetLastError()); + + format_id = RegisterClipboardFormatA("#1234"); + ok(format_id == 1234, "invalid clipboard format id %04x\n", format_id); } static HGLOBAL create_text(void) @@ -216,6 +211,7 @@ static void test_synthesized(void) HENHMETAFILE emf; BOOL r; UINT cf; + HANDLE data; htext = create_text(); emf = create_emf(); @@ -235,15 +231,21 @@ static void test_synthesized(void) ok(r, "gle %d\n", GetLastError()); cf = EnumClipboardFormats(0); ok(cf == CF_TEXT, "cf %08x\n", cf); + data = GetClipboardData(cf); + ok(data != NULL, "couldn't get data, cf %08x\n", cf); cf = EnumClipboardFormats(cf); ok(cf == CF_ENHMETAFILE, "cf %08x\n", cf); + data = GetClipboardData(cf); + ok(data != NULL, "couldn't get data, cf %08x\n", cf); cf = EnumClipboardFormats(cf); todo_wine ok(cf == CF_LOCALE, "cf %08x\n", cf); if(cf == CF_LOCALE) cf = EnumClipboardFormats(cf); ok(cf == CF_OEMTEXT, "cf %08x\n", cf); + data = GetClipboardData(cf); + ok(data != NULL, "couldn't get data, cf %08x\n", cf); cf = EnumClipboardFormats(cf); ok(cf == CF_UNICODETEXT || @@ -253,6 +255,8 @@ static void test_synthesized(void) if(cf == CF_UNICODETEXT) cf = EnumClipboardFormats(cf); ok(cf == CF_METAFILEPICT, "cf %08x\n", cf); + data = GetClipboardData(cf); + todo_wine ok(data != NULL, "couldn't get data, cf %08x\n", cf); cf = EnumClipboardFormats(cf); ok(cf == 0, "cf %08x\n", cf); diff --git a/winetests/user32/combo.c b/winetests/user32/combo.c index b7fa63f8e3d..fd852d13df7 100644 --- a/winetests/user32/combo.c +++ b/winetests/user32/combo.c @@ -77,7 +77,7 @@ static void test_setitemheight(DWORD style) trace("Style %x\n", style); GetClientRect(hCombo, &r); - expect_rect(r, 0, 0, 100, 24); + expect_rect(r, 0, 0, 100, font_height(GetStockObject(SYSTEM_FONT)) + 8); SendMessageA(hCombo, CB_GETDROPPEDCONTROLRECT, 0, (LPARAM)&r); MapWindowPoints(HWND_DESKTOP, hMainWnd, (LPPOINT)&r, 2); todo_wine expect_rect(r, 5, 5, 105, 105); @@ -112,11 +112,15 @@ static void test_setfont(DWORD style) hFont2 = CreateFont(8, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, SYMBOL_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH|FF_DONTCARE, "Marlett"); GetClientRect(hCombo, &r); - expect_rect(r, 0, 0, 100, 24); + expect_rect(r, 0, 0, 100, font_height(GetStockObject(SYSTEM_FONT)) + 8); SendMessageA(hCombo, CB_GETDROPPEDCONTROLRECT, 0, (LPARAM)&r); MapWindowPoints(HWND_DESKTOP, hMainWnd, (LPPOINT)&r, 2); todo_wine expect_rect(r, 5, 5, 105, 105); + /* The size of the dropped control is initially equal to the size + of the window when it was created. The size of the calculated + dropped area changes only by how much the selection area + changes, not by how much the list area changes. */ if (font_height(hFont1) == 10 && font_height(hFont2) == 8) { SendMessage(hCombo, WM_SETFONT, (WPARAM)hFont1, FALSE); @@ -124,21 +128,21 @@ static void test_setfont(DWORD style) expect_rect(r, 0, 0, 100, 18); SendMessageA(hCombo, CB_GETDROPPEDCONTROLRECT, 0, (LPARAM)&r); MapWindowPoints(HWND_DESKTOP, hMainWnd, (LPPOINT)&r, 2); - todo_wine expect_rect(r, 5, 5, 105, 99); + todo_wine expect_rect(r, 5, 5, 105, 105 - (font_height(GetStockObject(SYSTEM_FONT)) - font_height(hFont1))); SendMessage(hCombo, WM_SETFONT, (WPARAM)hFont2, FALSE); GetClientRect(hCombo, &r); expect_rect(r, 0, 0, 100, 16); SendMessageA(hCombo, CB_GETDROPPEDCONTROLRECT, 0, (LPARAM)&r); MapWindowPoints(HWND_DESKTOP, hMainWnd, (LPPOINT)&r, 2); - todo_wine expect_rect(r, 5, 5, 105, 97); + todo_wine expect_rect(r, 5, 5, 105, 105 - (font_height(GetStockObject(SYSTEM_FONT)) - font_height(hFont2))); SendMessage(hCombo, WM_SETFONT, (WPARAM)hFont1, FALSE); GetClientRect(hCombo, &r); expect_rect(r, 0, 0, 100, 18); SendMessageA(hCombo, CB_GETDROPPEDCONTROLRECT, 0, (LPARAM)&r); MapWindowPoints(HWND_DESKTOP, hMainWnd, (LPPOINT)&r, 2); - todo_wine expect_rect(r, 5, 5, 105, 99); + todo_wine expect_rect(r, 5, 5, 105, 105 - (font_height(GetStockObject(SYSTEM_FONT)) - font_height(hFont1))); } else { diff --git a/winetests/user32/cursoricon.c b/winetests/user32/cursoricon.c index b2e1d842aa3..2cfbc22f149 100644 --- a/winetests/user32/cursoricon.c +++ b/winetests/user32/cursoricon.c @@ -54,6 +54,243 @@ typedef struct CURSORICONFILEDIRENTRY idEntries[1]; } CURSORICONFILEDIR; +#define RIFF_FOURCC( c0, c1, c2, c3 ) \ + ( (DWORD)(BYTE)(c0) | ( (DWORD)(BYTE)(c1) << 8 ) | \ + ( (DWORD)(BYTE)(c2) << 16 ) | ( (DWORD)(BYTE)(c3) << 24 ) ) + +#define ANI_RIFF_ID RIFF_FOURCC('R', 'I', 'F', 'F') +#define ANI_LIST_ID RIFF_FOURCC('L', 'I', 'S', 'T') +#define ANI_ACON_ID RIFF_FOURCC('A', 'C', 'O', 'N') +#define ANI_anih_ID RIFF_FOURCC('a', 'n', 'i', 'h') +#define ANI_seq__ID RIFF_FOURCC('s', 'e', 'q', ' ') +#define ANI_fram_ID RIFF_FOURCC('f', 'r', 'a', 'm') +#define ANI_icon_ID RIFF_FOURCC('i', 'c', 'o', 'n') +#define ANI_rate_ID RIFF_FOURCC('r', 'a', 't', 'e') + +#define ANI_FLAG_ICON 0x1 +#define ANI_FLAG_SEQUENCE 0x2 + +typedef struct { + DWORD header_size; + DWORD num_frames; + DWORD num_steps; + DWORD width; + DWORD height; + DWORD bpp; + DWORD num_planes; + DWORD display_rate; + DWORD flags; +} ani_header; + +typedef struct { + BYTE data[32*32*4]; +} ani_data32x32x32; + +typedef struct { + CURSORICONFILEDIR icon_info; /* animated cursor frame information */ + BITMAPINFOHEADER bmi_header; /* animated cursor frame header */ + ani_data32x32x32 bmi_data; /* animated cursor frame DIB data */ +} ani_frame32x32x32; + +typedef struct { + DWORD chunk_id; /* ANI_anih_ID */ + DWORD chunk_size; /* actual size of data */ + ani_header header; /* animated cursor header */ +} riff_header_t; + +typedef struct { + DWORD chunk_id; /* ANI_LIST_ID */ + DWORD chunk_size; /* actual size of data */ + DWORD chunk_type; /* ANI_fram_ID */ +} riff_list_t; + +typedef struct { + DWORD chunk_id; /* ANI_icon_ID */ + DWORD chunk_size; /* actual size of data */ + ani_frame32x32x32 data; /* animated cursor frame */ +} riff_icon32x32x32_t; + +typedef struct { + DWORD chunk_id; /* ANI_RIFF_ID */ + DWORD chunk_size; /* actual size of data */ + DWORD chunk_type; /* ANI_ACON_ID */ + riff_header_t header; /* RIFF animated cursor header */ + riff_list_t frame_list; /* RIFF animated cursor frame list info */ + riff_icon32x32x32_t frames[1]; /* array of animated cursor frames */ +} riff_cursor1_t; + +typedef struct { + DWORD chunk_id; /* ANI_RIFF_ID */ + DWORD chunk_size; /* actual size of data */ + DWORD chunk_type; /* ANI_ACON_ID */ + riff_header_t header; /* RIFF animated cursor header */ + riff_list_t frame_list; /* RIFF animated cursor frame list info */ + riff_icon32x32x32_t frames[3]; /* array of three animated cursor frames */ +} riff_cursor3_t; + +typedef struct { + DWORD chunk_id; /* ANI_rate_ID */ + DWORD chunk_size; /* actual size of data */ + DWORD rate[3]; /* animated cursor rate data */ +} riff_rate3_t; + +typedef struct { + DWORD chunk_id; /* ANI_seq__ID */ + DWORD chunk_size; /* actual size of data */ + DWORD order[3]; /* animated cursor sequence data */ +} riff_seq3_t; + +typedef struct { + DWORD chunk_id; /* ANI_RIFF_ID */ + DWORD chunk_size; /* actual size of data */ + DWORD chunk_type; /* ANI_ACON_ID */ + riff_header_t header; /* RIFF animated cursor header */ + riff_seq3_t seq; /* sequence data for three cursor frames */ + riff_rate3_t rates; /* rate data for three cursor frames */ + riff_list_t frame_list; /* RIFF animated cursor frame list info */ + riff_icon32x32x32_t frames[3]; /* array of three animated cursor frames */ +} riff_cursor3_seq_t; + +#define EMPTY_ICON32 \ +{ \ + ANI_icon_ID, \ + sizeof(ani_frame32x32x32), \ + { \ + { \ + 0x0, /* reserved */ \ + 0, /* type: icon(1), cursor(2) */ \ + 1, /* count */ \ + { \ + { \ + 32, /* width */ \ + 32, /* height */ \ + 0, /* color count */ \ + 0x0, /* reserved */ \ + 16, /* x hotspot */ \ + 16, /* y hotspot */ \ + sizeof(ani_data32x32x32), /* DIB size */ \ + sizeof(CURSORICONFILEDIR) /* DIB offset */ \ + } \ + } \ + }, \ + { \ + sizeof(BITMAPINFOHEADER), /* structure for DIB-type data */ \ + 32, /* width */ \ + 32*2, /* actual height times two */ \ + 1, /* planes */ \ + 32, /* bpp */ \ + BI_RGB, /* compression */ \ + 0, /* image size */ \ + 0, /* biXPelsPerMeter */ \ + 0, /* biYPelsPerMeter */ \ + 0, /* biClrUsed */ \ + 0 /* biClrImportant */ \ + }, \ + /* DIB data: left uninitialized */ \ + } \ +} + +riff_cursor1_t empty_anicursor = { + ANI_RIFF_ID, + sizeof(empty_anicursor) - sizeof(DWORD)*2, + ANI_ACON_ID, + { + ANI_anih_ID, + sizeof(ani_header), + { + sizeof(ani_header), + 1, /* frames */ + 1, /* steps */ + 32, /* width */ + 32, /* height */ + 32, /* depth */ + 1, /* planes */ + 10, /* display rate in jiffies */ + ANI_FLAG_ICON /* flags */ + } + }, + { + ANI_LIST_ID, + sizeof(riff_icon32x32x32_t)*(1 /*frames*/) + sizeof(DWORD), + ANI_fram_ID, + }, + { + EMPTY_ICON32 + } +}; + +riff_cursor3_t empty_anicursor3 = { + ANI_RIFF_ID, + sizeof(empty_anicursor3) - sizeof(DWORD)*2, + ANI_ACON_ID, + { + ANI_anih_ID, + sizeof(ani_header), + { + sizeof(ani_header), + 3, /* frames */ + 3, /* steps */ + 32, /* width */ + 32, /* height */ + 32, /* depth */ + 1, /* planes */ + 0xbeef, /* display rate in jiffies */ + ANI_FLAG_ICON /* flags */ + } + }, + { + ANI_LIST_ID, + sizeof(riff_icon32x32x32_t)*(3 /*frames*/) + sizeof(DWORD), + ANI_fram_ID, + }, + { + EMPTY_ICON32, + EMPTY_ICON32, + EMPTY_ICON32 + } +}; + +riff_cursor3_seq_t empty_anicursor3_seq = { + ANI_RIFF_ID, + sizeof(empty_anicursor3_seq) - sizeof(DWORD)*2, + ANI_ACON_ID, + { + ANI_anih_ID, + sizeof(ani_header), + { + sizeof(ani_header), + 3, /* frames */ + 3, /* steps */ + 32, /* width */ + 32, /* height */ + 32, /* depth */ + 1, /* planes */ + 0xbeef, /* display rate in jiffies */ + ANI_FLAG_ICON|ANI_FLAG_SEQUENCE /* flags */ + } + }, + { + ANI_seq__ID, + sizeof(riff_seq3_t) - sizeof(DWORD)*2, + { 2, 0, 1} /* show frames in a uniquely identifiable order */ + }, + { + ANI_rate_ID, + sizeof(riff_rate3_t) - sizeof(DWORD)*2, + { 0xc0de, 0xcafe, 0xbabe} + }, + { + ANI_LIST_ID, + sizeof(riff_icon32x32x32_t)*(3 /*frames*/) + sizeof(DWORD), + ANI_fram_ID, + }, + { + EMPTY_ICON32, + EMPTY_ICON32, + EMPTY_ICON32 + } +}; + #include "poppack.h" static char **test_argv; @@ -65,6 +302,10 @@ static HANDLE child_process; #define PROC_INIT (WM_USER+1) static BOOL (WINAPI *pGetCursorInfo)(CURSORINFO *); +static BOOL (WINAPI *pGetIconInfoExA)(HICON,ICONINFOEXA *); +static BOOL (WINAPI *pGetIconInfoExW)(HICON,ICONINFOEXW *); + +static const int is_win64 = (sizeof(void *) > sizeof(int)); static LRESULT CALLBACK callback_child(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { @@ -78,7 +319,7 @@ static LRESULT CALLBACK callback_child(HWND hwnd, UINT msg, WPARAM wParam, LPARA SetLastError(0xdeadbeef); ret = DestroyCursor((HCURSOR) lParam); error = GetLastError(); - todo_wine ok(!ret || broken(ret) /* win9x */, "DestroyCursor on the active cursor succeeded.\n"); + ok(!ret || broken(ret) /* win9x */, "DestroyCursor on the active cursor succeeded.\n"); ok(error == ERROR_DESTROY_OBJECT_OF_OTHER_THREAD || error == 0xdeadbeef, /* vista */ "Last error: %u\n", error); @@ -504,6 +745,37 @@ static void test_icon_info_dbg(HICON hIcon, UINT exp_cx, UINT exp_cy, UINT exp_b ok_(__FILE__, line)(bmMask.bmWidth == exp_cx, "bmMask.bmWidth = %d\n", bmMask.bmWidth); ok_(__FILE__, line)(bmMask.bmHeight == exp_cy * 2, "bmMask.bmHeight = %d\n", bmMask.bmHeight); } + if (pGetIconInfoExA) + { + ICONINFOEXA infoex; + + memset( &infoex, 0xcc, sizeof(infoex) ); + SetLastError( 0xdeadbeef ); + infoex.cbSize = sizeof(infoex) - 1; + ret = pGetIconInfoExA( hIcon, &infoex ); + ok_(__FILE__, line)(!ret, "GetIconInfoEx succeeded\n"); + ok_(__FILE__, line)(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %d\n", GetLastError()); + + SetLastError( 0xdeadbeef ); + infoex.cbSize = sizeof(infoex) + 1; + ret = pGetIconInfoExA( hIcon, &infoex ); + ok_(__FILE__, line)(!ret, "GetIconInfoEx succeeded\n"); + ok_(__FILE__, line)(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %d\n", GetLastError()); + + SetLastError( 0xdeadbeef ); + infoex.cbSize = sizeof(infoex); + ret = pGetIconInfoExA( (HICON)0xdeadbabe, &infoex ); + ok_(__FILE__, line)(!ret, "GetIconInfoEx succeeded\n"); + ok_(__FILE__, line)(GetLastError() == ERROR_INVALID_CURSOR_HANDLE, + "wrong error %d\n", GetLastError()); + + infoex.cbSize = sizeof(infoex); + ret = pGetIconInfoExA( hIcon, &infoex ); + ok_(__FILE__, line)(ret, "GetIconInfoEx failed err %d\n", GetLastError()); + ok_(__FILE__, line)(infoex.wResID == 0, "GetIconInfoEx wrong resid %x\n", infoex.wResID); + ok_(__FILE__, line)(infoex.szModName[0] == 0, "GetIconInfoEx wrong module %s\n", infoex.szModName); + ok_(__FILE__, line)(infoex.szResName[0] == 0, "GetIconInfoEx wrong name %s\n", infoex.szResName); + } } #define test_icon_info(a,b,c,d) test_icon_info_dbg((a),(b),(c),(d),__LINE__) @@ -730,6 +1002,24 @@ static unsigned char gif4pixel[42] = { 0x02,0x00,0x00,0x02,0x03,0x14,0x16,0x05,0x00,0x3b }; +static const DWORD biSize_tests[] = { + 0, + sizeof(BITMAPCOREHEADER) - 1, + sizeof(BITMAPCOREHEADER) + 1, + sizeof(BITMAPINFOHEADER) - 1, + sizeof(BITMAPINFOHEADER) + 1, + sizeof(BITMAPV4HEADER) - 1, + sizeof(BITMAPV4HEADER) + 1, + sizeof(BITMAPV5HEADER) - 1, + sizeof(BITMAPV5HEADER) + 1, + (sizeof(BITMAPCOREHEADER) + sizeof(BITMAPINFOHEADER)) / 2, + (sizeof(BITMAPV4HEADER) + sizeof(BITMAPV5HEADER)) / 2, + 0xdeadbeef, + 0xffffffff +}; + +#define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0])) + static void test_LoadImageBitmap(const char * test_desc, HBITMAP hbm) { BITMAP bm; @@ -819,8 +1109,9 @@ static void test_LoadImage(void) DWORD error, bytes_written; CURSORICONFILEDIR *icon_data; CURSORICONFILEDIRENTRY *icon_entry; - BITMAPINFOHEADER *icon_header; + BITMAPINFOHEADER *icon_header, *bitmap_header; ICONINFO icon_info; + int i; #define ICON_WIDTH 32 #define ICON_HEIGHT 32 @@ -889,6 +1180,18 @@ static void test_LoadImage(void) ok(icon_info.hbmMask != NULL, "No hbmMask!\n"); } + if (pGetIconInfoExA) + { + ICONINFOEXA infoex; + infoex.cbSize = sizeof(infoex); + ret = pGetIconInfoExA( handle, &infoex ); + ok( ret, "GetIconInfoEx failed err %d\n", GetLastError() ); + ok( infoex.wResID == 0, "GetIconInfoEx wrong resid %x\n", infoex.wResID ); + ok( infoex.szModName[0] == 0, "GetIconInfoEx wrong module %s\n", infoex.szModName ); + ok( infoex.szResName[0] == 0, "GetIconInfoEx wrong name %s\n", infoex.szResName ); + } + else win_skip( "GetIconInfoEx not available\n" ); + /* Clean up. */ SetLastError(0xdeadbeef); ret = DestroyCursor(handle); @@ -899,21 +1202,62 @@ static void test_LoadImage(void) HeapFree(GetProcessHeap(), 0, icon_data); DeleteFileA("icon.ico"); + /* Test a system icon */ + handle = LoadIcon( 0, IDI_HAND ); + ok(handle != NULL, "LoadImage() failed.\n"); + if (pGetIconInfoExA) + { + ICONINFOEXA infoexA; + ICONINFOEXW infoexW; + infoexA.cbSize = sizeof(infoexA); + ret = pGetIconInfoExA( handle, &infoexA ); + ok( ret, "GetIconInfoEx failed err %d\n", GetLastError() ); + ok( infoexA.wResID == (UINT_PTR)IDI_HAND, "GetIconInfoEx wrong resid %x\n", infoexA.wResID ); + /* the A version is broken on 64-bit, it truncates the string after the first char */ + if (is_win64 && infoexA.szModName[0] && infoexA.szModName[1] == 0) + trace( "GetIconInfoExA broken on Win64\n" ); + else + ok( GetModuleHandleA(infoexA.szModName) == GetModuleHandleA("user32.dll"), + "GetIconInfoEx wrong module %s\n", infoexA.szModName ); + ok( infoexA.szResName[0] == 0, "GetIconInfoEx wrong name %s\n", infoexA.szResName ); + infoexW.cbSize = sizeof(infoexW); + ret = pGetIconInfoExW( handle, &infoexW ); + ok( ret, "GetIconInfoEx failed err %d\n", GetLastError() ); + ok( infoexW.wResID == (UINT_PTR)IDI_HAND, "GetIconInfoEx wrong resid %x\n", infoexW.wResID ); + ok( GetModuleHandleW(infoexW.szModName) == GetModuleHandleA("user32.dll"), + "GetIconInfoEx wrong module %s\n", wine_dbgstr_w(infoexW.szModName) ); + ok( infoexW.szResName[0] == 0, "GetIconInfoEx wrong name %s\n", wine_dbgstr_w(infoexW.szResName) ); + } + SetLastError(0xdeadbeef); + DestroyIcon(handle); + test_LoadImageFile("BMP", bmpimage, sizeof(bmpimage), "bmp", 1); test_LoadImageFile("BMP (coreinfo)", bmpcoreimage, sizeof(bmpcoreimage), "bmp", 1); test_LoadImageFile("GIF", gifimage, sizeof(gifimage), "gif", 0); test_LoadImageFile("GIF (2x2 pixel)", gif4pixel, sizeof(gif4pixel), "gif", 0); test_LoadImageFile("JPG", jpgimage, sizeof(jpgimage), "jpg", 0); test_LoadImageFile("PNG", pngimage, sizeof(pngimage), "png", 0); + /* Check failure for broken BMP images */ - bmpimage[0x14]++; /* biHeight > 65535 */ + bitmap_header = (BITMAPINFOHEADER *)(bmpimage + sizeof(BITMAPFILEHEADER)); + + bitmap_header->biHeight = 65536; test_LoadImageFile("BMP (too high)", bmpimage, sizeof(bmpimage), "bmp", 0); - bmpimage[0x14]--; - bmpimage[0x18]++; /* biWidth > 65535 */ + bitmap_header->biHeight = 1; + + bitmap_header->biWidth = 65536; test_LoadImageFile("BMP (too wide)", bmpimage, sizeof(bmpimage), "bmp", 0); - bmpimage[0x18]--; + bitmap_header->biWidth = 1; + + for (i = 0; i < ARRAY_SIZE(biSize_tests); i++) { + bitmap_header->biSize = biSize_tests[i]; + test_LoadImageFile("BMP (broken biSize)", bmpimage, sizeof(bmpimage), "bmp", 0); + } + bitmap_header->biSize = sizeof(BITMAPINFOHEADER); } +#undef ARRAY_SIZE + static void test_CreateIconFromResource(void) { HANDLE handle; @@ -968,6 +1312,17 @@ static void test_CreateIconFromResource(void) ok(icon_info.hbmMask != NULL, "No hbmMask!\n"); } + if (pGetIconInfoExA) + { + ICONINFOEXA infoex; + infoex.cbSize = sizeof(infoex); + ret = pGetIconInfoExA( handle, &infoex ); + ok( ret, "GetIconInfoEx failed err %d\n", GetLastError() ); + ok( infoex.wResID == 0, "GetIconInfoEx wrong resid %x\n", infoex.wResID ); + ok( infoex.szModName[0] == 0, "GetIconInfoEx wrong module %s\n", infoex.szModName ); + ok( infoex.szResName[0] == 0, "GetIconInfoEx wrong name %s\n", infoex.szResName ); + } + /* Clean up. */ SetLastError(0xdeadbeef); ret = DestroyCursor(handle); @@ -1005,7 +1360,331 @@ static void test_CreateIconFromResource(void) error = GetLastError(); ok(error == 0xdeadbeef, "Last error: %u\n", error); + /* Rejection of NULL pointer crashes at least on WNT4WSSP6, W2KPROSP4, WXPPROSP3 + * + * handle = CreateIconFromResource(NULL, ICON_RES_SIZE, TRUE, 0x00030000); + * ok(handle == NULL, "Invalid pointer accepted (%p)\n", handle); + */ HeapFree(GetProcessHeap(), 0, hotspot); + + /* Test creating an animated cursor. */ + empty_anicursor.frames[0].data.icon_info.idType = 2; /* type: cursor */ + empty_anicursor.frames[0].data.icon_info.idEntries[0].xHotspot = 3; + empty_anicursor.frames[0].data.icon_info.idEntries[0].yHotspot = 3; + handle = CreateIconFromResource((PBYTE) &empty_anicursor, sizeof(empty_anicursor), FALSE, 0x00030000); + ok(handle != NULL, "Create cursor failed.\n"); + + /* Test the animated cursor's information. */ + SetLastError(0xdeadbeef); + ret = GetIconInfo(handle, &icon_info); + ok(ret, "GetIconInfo() failed.\n"); + error = GetLastError(); + ok(error == 0xdeadbeef, "Last error: %u\n", error); + + if (ret) + { + ok(icon_info.fIcon == FALSE, "fIcon != FALSE.\n"); + ok(icon_info.xHotspot == 3, "xHotspot is %u.\n", icon_info.xHotspot); + ok(icon_info.yHotspot == 3, "yHotspot is %u.\n", icon_info.yHotspot); + ok(icon_info.hbmColor != NULL || broken(!icon_info.hbmColor) /* no color cursor support */, + "No hbmColor!\n"); + ok(icon_info.hbmMask != NULL, "No hbmMask!\n"); + } + + /* Clean up. */ + SetLastError(0xdeadbeef); + ret = DestroyCursor(handle); + ok(ret, "DestroyCursor() failed.\n"); + error = GetLastError(); + ok(error == 0xdeadbeef, "Last error: %u\n", error); +} + +static int check_cursor_data( HDC hdc, HCURSOR hCursor, void *data, int length) +{ + char *image = NULL; + BITMAPINFO *info; + ICONINFO iinfo; + DWORD ret; + + ret = GetIconInfo( hCursor, &iinfo ); + ok(ret, "GetIconInfo() failed\n"); + if (!ret) return 0; + ret = 0; + info = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET( BITMAPINFO, bmiColors[256] )); + ok(info != NULL, "HeapAlloc() failed\n"); + if (!info) return 0; + + info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + info->bmiHeader.biWidth = 32; + info->bmiHeader.biHeight = 32; + info->bmiHeader.biPlanes = 1; + info->bmiHeader.biBitCount = 32; + info->bmiHeader.biCompression = BI_RGB; + info->bmiHeader.biSizeImage = 32 * 32 * 4; + info->bmiHeader.biXPelsPerMeter = 0; + info->bmiHeader.biYPelsPerMeter = 0; + info->bmiHeader.biClrUsed = 0; + info->bmiHeader.biClrImportant = 0; + image = HeapAlloc( GetProcessHeap(), 0, info->bmiHeader.biSizeImage ); + ok(image != NULL, "HeapAlloc() failed\n"); + if (!image) goto cleanup; + ret = GetDIBits( hdc, iinfo.hbmColor, 0, 32, image, info, DIB_RGB_COLORS ); + ok(ret, "GetDIBits() failed\n"); + if (!ret) goto cleanup; + ret = (memcmp(image, data, length) == 0); + ok(ret, "Expected 0x%x, actually 0x%x (first 4 bytes only)\n", *(DWORD *)data, *(DWORD *)image); + +cleanup: + HeapFree( GetProcessHeap(), 0, image ); + HeapFree( GetProcessHeap(), 0, info ); + return ret; +} + +static HCURSOR (WINAPI *pGetCursorFrameInfo)(HCURSOR hCursor, DWORD unk1, DWORD istep, DWORD *rate, DWORD *steps); +static void test_GetCursorFrameInfo(void) +{ + DWORD frame_identifier[] = { 0x10Ad, 0xc001, 0x1c05 }; + HBITMAP bmp = NULL, bmpOld = NULL; + DWORD rate, steps; + BITMAPINFOHEADER *icon_header; + BITMAPINFO bitmapInfo; + HDC hdc = NULL; + void *bits = 0; + INT16 *hotspot; + HANDLE h1, h2; + BOOL ret; + int i; + + if (!pGetCursorFrameInfo) + { + win_skip( "GetCursorFrameInfo not supported, skipping tests.\n" ); + return; + } + + hdc = CreateCompatibleDC(0); + ok(hdc != 0, "CreateCompatibleDC(0) failed to return a valid DC\n"); + if (!hdc) + return; + + memset(&bitmapInfo, 0, sizeof(bitmapInfo)); + bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bitmapInfo.bmiHeader.biWidth = 3; + bitmapInfo.bmiHeader.biHeight = 3; + bitmapInfo.bmiHeader.biBitCount = 32; + bitmapInfo.bmiHeader.biPlanes = 1; + bitmapInfo.bmiHeader.biCompression = BI_RGB; + bitmapInfo.bmiHeader.biSizeImage = sizeof(UINT32); + bmp = CreateDIBSection(hdc, &bitmapInfo, DIB_RGB_COLORS, &bits, NULL, 0); + ok (bmp && bits, "CreateDIBSection failed to return a valid bitmap and buffer\n"); + if (!bmp || !bits) + goto cleanup; + bmpOld = SelectObject(hdc, bmp); + +#define ICON_RES_WIDTH 32 +#define ICON_RES_HEIGHT 32 +#define ICON_RES_AND_SIZE (ICON_WIDTH*ICON_HEIGHT/8) +#define ICON_RES_BPP 32 +#define ICON_RES_SIZE \ + (sizeof(BITMAPINFOHEADER) + ICON_AND_SIZE + ICON_AND_SIZE*ICON_BPP) +#define CRSR_RES_SIZE (2*sizeof(INT16) + ICON_RES_SIZE) + + /* Set icon data. */ + hotspot = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, CRSR_RES_SIZE); + + /* Cursor resources have an extra hotspot, icon resources not. */ + hotspot[0] = 3; + hotspot[1] = 3; + + icon_header = (BITMAPINFOHEADER *) (hotspot + 2); + icon_header->biSize = sizeof(BITMAPINFOHEADER); + icon_header->biWidth = ICON_WIDTH; + icon_header->biHeight = ICON_HEIGHT*2; + icon_header->biPlanes = 1; + icon_header->biBitCount = ICON_BPP; + icon_header->biSizeImage = 0; /* Uncompressed bitmap. */ + + /* Creating a static cursor. */ + SetLastError(0xdeadbeef); + h1 = CreateIconFromResource((PBYTE) hotspot, CRSR_RES_SIZE, FALSE, 0x00030000); + ok(h1 != NULL, "Create cursor failed (error = %d).\n", GetLastError()); + + /* Check GetCursorFrameInfo behavior on a static cursor */ + rate = steps = 0xdead; + h2 = pGetCursorFrameInfo(h1, 0xdead, 0xdead, &rate, &steps); + ok(h1 == h2, "GetCursorFrameInfo() failed: (%p != %p).\n", h1, h2); + ok(rate == 0, "GetCursorFrameInfo() unexpected param 4 value (0x%x != 0x0).\n", rate); + ok(steps == 1, "GetCursorFrameInfo() unexpected param 5 value (%d != 1).\n", steps); + + /* Clean up static cursor. */ + SetLastError(0xdeadbeef); + ret = DestroyCursor(h1); + ok(ret, "DestroyCursor() failed (error = %d).\n", GetLastError()); + + /* Creating a single-frame animated cursor. */ + empty_anicursor.frames[0].data.icon_info.idType = 2; /* type: cursor */ + empty_anicursor.frames[0].data.icon_info.idEntries[0].xHotspot = 3; + empty_anicursor.frames[0].data.icon_info.idEntries[0].yHotspot = 3; + memcpy( &empty_anicursor.frames[0].data.bmi_data.data[0], &frame_identifier[0], sizeof(DWORD) ); + SetLastError(0xdeadbeef); + h1 = CreateIconFromResource((PBYTE) &empty_anicursor, sizeof(empty_anicursor), FALSE, 0x00030000); + ok(h1 != NULL, "Create cursor failed (error = %d).\n", GetLastError()); + + /* Check GetCursorFrameInfo behavior on a single-frame animated cursor */ + rate = steps = 0xdead; + h2 = pGetCursorFrameInfo(h1, 0xdead, 0, &rate, &steps); + ok(h1 == h2, "GetCursorFrameInfo() failed: (%p != %p).\n", h1, h2); + ret = check_cursor_data( hdc, h2, &frame_identifier[0], sizeof(DWORD) ); + ok(ret, "GetCursorFrameInfo() returned wrong cursor data for frame 0.\n"); + ok(rate == 0x0, "GetCursorFrameInfo() unexpected param 4 value (0x%x != 0x0).\n", rate); + ok(steps == empty_anicursor.header.header.num_steps, + "GetCursorFrameInfo() unexpected param 5 value (%d != 1).\n", steps); + + /* Clean up single-frame animated cursor. */ + SetLastError(0xdeadbeef); + ret = DestroyCursor(h1); + ok(ret, "DestroyCursor() failed (error = %d).\n", GetLastError()); + + /* Creating a multi-frame animated cursor. */ + for (i=0; i= 3) @@ -1741,6 +2484,7 @@ START_TEST(cursoricon) test_CreateIcon(); test_LoadImage(); test_CreateIconFromResource(); + test_GetCursorFrameInfo(); test_DrawIcon(); test_DrawIconEx(); test_DrawState(); diff --git a/winetests/user32/dce.c b/winetests/user32/dce.c index cfa07e51408..4aacd64a593 100755 --- a/winetests/user32/dce.c +++ b/winetests/user32/dce.c @@ -66,10 +66,7 @@ static void test_dc_attributes(void) hdc = hdcs[i] = GetDCEx( hwnd_cache, 0, DCX_USESTYLE | DCX_NORESETATTRS ); if (!hdc) break; rop = GetROP2( hdc ); - if (hdc == old_hdc) - todo_wine ok( rop == def_rop, "wrong ROP2 %d after release %p/%p\n", rop, old_hdc, hdc ); - else - ok( rop == def_rop, "wrong ROP2 %d after release %p/%p\n", rop, old_hdc, hdc ); + ok( rop == def_rop, "wrong ROP2 %d after release %p/%p\n", rop, old_hdc, hdc ); if (hdc == old_hdc) { found_dc = 1; @@ -104,8 +101,8 @@ static void test_dc_attributes(void) rop = GetROP2( hdc ); if (hdc == old_hdc) { - todo_wine ok( rop == R2_WHITE || broken( rop == def_rop), - "wrong ROP2 %d after release %p/%p\n", rop, old_hdc, hdc ); + ok( rop == R2_WHITE || broken( rop == def_rop), + "wrong ROP2 %d after release %p/%p\n", rop, old_hdc, hdc ); SetROP2( old_hdc, def_rop ); } else @@ -226,7 +223,7 @@ static void test_dc_visrgn(void) SetRectEmpty( &rect ); GetClipBox( hdc, &rect ); ok( !(rect.left >= 10 && rect.top >= 10 && rect.right <= 20 && rect.bottom <= 20), - "clip box sould have been reset %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom ); + "clip box should have been reset %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom ); ReleaseDC( hwnd_cache, hdc ); /* window DC */ @@ -427,6 +424,87 @@ static void test_invisible_create(void) DestroyWindow(hwnd_owndc); } +static void test_dc_layout(void) +{ + DWORD (WINAPI *pSetLayout)(HDC hdc, DWORD layout); + DWORD (WINAPI *pGetLayout)(HDC hdc); + HWND hwnd_cache_rtl, hwnd_owndc_rtl, hwnd_classdc_rtl, hwnd_classdc2_rtl; + HDC hdc; + DWORD layout; + HMODULE mod = GetModuleHandleA("gdi32.dll"); + + pGetLayout = (void *)GetProcAddress( mod, "GetLayout" ); + pSetLayout = (void *)GetProcAddress( mod, "SetLayout" ); + if (!pGetLayout || !pSetLayout) + { + win_skip( "Don't have SetLayout\n" ); + return; + } + + hdc = GetDC( hwnd_cache ); + pSetLayout( hdc, LAYOUT_RTL ); + layout = pGetLayout( hdc ); + ReleaseDC( hwnd_cache, hdc ); + if (!layout) + { + win_skip( "SetLayout not supported\n" ); + return; + } + + hwnd_cache_rtl = CreateWindowExA(WS_EX_LAYOUTRTL, "cache_class", NULL, WS_OVERLAPPED | WS_VISIBLE, + 0, 0, 100, 100, 0, 0, GetModuleHandleA(0), NULL ); + hwnd_owndc_rtl = CreateWindowExA(WS_EX_LAYOUTRTL, "owndc_class", NULL, WS_OVERLAPPED | WS_VISIBLE, + 0, 200, 100, 100, 0, 0, GetModuleHandleA(0), NULL ); + hwnd_classdc_rtl = CreateWindowExA(WS_EX_LAYOUTRTL, "classdc_class", NULL, WS_OVERLAPPED | WS_VISIBLE, + 200, 0, 100, 100, 0, 0, GetModuleHandleA(0), NULL ); + hwnd_classdc2_rtl = CreateWindowExA(WS_EX_LAYOUTRTL, "classdc_class", NULL, WS_OVERLAPPED | WS_VISIBLE, + 200, 200, 100, 100, 0, 0, GetModuleHandleA(0), NULL ); + hdc = GetDC( hwnd_cache_rtl ); + layout = pGetLayout( hdc ); + + ok( layout == LAYOUT_RTL, "wrong layout %x\n", layout ); + pSetLayout( hdc, 0 ); + ReleaseDC( hwnd_cache_rtl, hdc ); + hdc = GetDC( hwnd_owndc_rtl ); + layout = pGetLayout( hdc ); + ok( layout == LAYOUT_RTL, "wrong layout %x\n", layout ); + ReleaseDC( hwnd_cache_rtl, hdc ); + + hdc = GetDC( hwnd_cache ); + layout = pGetLayout( hdc ); + ok( layout == 0, "wrong layout %x\n", layout ); + ReleaseDC( hwnd_cache, hdc ); + + hdc = GetDC( hwnd_owndc_rtl ); + layout = pGetLayout( hdc ); + ok( layout == LAYOUT_RTL, "wrong layout %x\n", layout ); + pSetLayout( hdc, 0 ); + ReleaseDC( hwnd_owndc_rtl, hdc ); + hdc = GetDC( hwnd_owndc_rtl ); + layout = pGetLayout( hdc ); + ok( layout == LAYOUT_RTL, "wrong layout %x\n", layout ); + ReleaseDC( hwnd_owndc_rtl, hdc ); + + hdc = GetDC( hwnd_classdc_rtl ); + layout = pGetLayout( hdc ); + ok( layout == LAYOUT_RTL, "wrong layout %x\n", layout ); + pSetLayout( hdc, 0 ); + ReleaseDC( hwnd_classdc_rtl, hdc ); + hdc = GetDC( hwnd_classdc2_rtl ); + layout = pGetLayout( hdc ); + ok( layout == LAYOUT_RTL, "wrong layout %x\n", layout ); + ReleaseDC( hwnd_classdc2_rtl, hdc ); + hdc = GetDC( hwnd_classdc ); + layout = pGetLayout( hdc ); + ok( layout == LAYOUT_RTL, "wrong layout %x\n", layout ); + ReleaseDC( hwnd_classdc_rtl, hdc ); + + DestroyWindow(hwnd_classdc2_rtl); + DestroyWindow(hwnd_classdc_rtl); + DestroyWindow(hwnd_owndc_rtl); + DestroyWindow(hwnd_cache_rtl); +} + static void test_destroyed_window(void) { HDC dc; @@ -483,6 +561,7 @@ START_TEST(dce) test_dc_visrgn(); test_begin_paint(); test_invisible_create(); + test_dc_layout(); DestroyWindow(hwnd_classdc2); DestroyWindow(hwnd_classdc); diff --git a/winetests/user32/dde.c b/winetests/user32/dde.c index 529c527f2e2..e273de21379 100755 --- a/winetests/user32/dde.c +++ b/winetests/user32/dde.c @@ -19,7 +19,6 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#include #include #include @@ -63,17 +62,19 @@ static void flush_events(void) static void create_dde_window(HWND *hwnd, LPCSTR name, WNDPROC wndproc) { WNDCLASSA wcA; + ATOM aclass; memset(&wcA, 0, sizeof(wcA)); wcA.lpfnWndProc = wndproc; wcA.lpszClassName = name; wcA.hInstance = GetModuleHandleA(0); - assert(RegisterClassA(&wcA)); + aclass = RegisterClassA(&wcA); + ok (aclass, "RegisterClass failed\n"); *hwnd = CreateWindowExA(0, name, NULL, WS_POPUP, 500, 500, CW_USEDEFAULT, CW_USEDEFAULT, GetDesktopWindow(), 0, GetModuleHandleA(0), NULL); - assert(*hwnd); + ok(*hwnd != NULL, "CreateWindowExA failed\n"); } static void destroy_dde_window(HWND *hwnd, LPCSTR name) @@ -1000,7 +1001,7 @@ static LRESULT WINAPI dde_msg_client_wndproc(HWND hwnd, UINT msg, WPARAM wparam, ok(data->fAckReq == 0, "Expected 0, got %d\n", data->fAckReq); ok(data->cfFormat == CF_TEXT, "Expected CF_TEXT, got %d\n", data->cfFormat); ok(!lstrcmpA((LPSTR)data->Value, "requested data\r\n"), - "Expeted 'requested data\\r\\n', got %s\n", data->Value); + "Expected 'requested data\\r\\n', got %s\n", data->Value); GlobalUnlock((HGLOBAL)lo); size = GlobalGetAtomNameA(hi, str, MAX_PATH); @@ -1295,7 +1296,7 @@ static LRESULT WINAPI dde_server_wndprocA(HWND hwnd, UINT msg, WPARAM wparam, LP if (!conv_unicode) ok( !lstrcmpA(cmd, exec_cmdA), "server A got wrong command '%s'\n", cmd ); else /* we get garbage as the A command was mapped W->A */ - ok( cmd[0] == '?', "server A got wrong command '%s'\n", cmd ); + ok( cmd[0] != exec_cmdA[0], "server A got wrong command '%s'\n", cmd ); break; case 2: /* ANSI command in Unicode format */ @@ -1316,7 +1317,7 @@ static LRESULT WINAPI dde_server_wndprocA(HWND hwnd, UINT msg, WPARAM wparam, LP if (!conv_unicode) ok( !lstrcmpA(cmd, exec_cmdWA), "server A got wrong command '%s'\n", cmd ); else /* we get garbage as the A command was mapped W->A */ - ok( cmd[0] == '?', "server A got wrong command '%s'\n", cmd ); + ok( cmd[0] != exec_cmdWA[0], "server A got wrong command '%s'\n", cmd ); break; } GlobalUnlock((HGLOBAL)hi); @@ -1430,7 +1431,7 @@ static LRESULT WINAPI dde_server_wndprocW(HWND hwnd, UINT msg, WPARAM wparam, LP case 1: /* ANSI command */ if (conv_unicode && !client_unicode) /* W->A mapping -> garbage */ - ok( cmd[0] == '?', "server W got wrong command '%s'\n", cmd ); + ok( cmd[0] != exec_cmdA[0], "server W got wrong command '%s'\n", cmd ); else if (!conv_unicode && client_unicode) /* A->W mapping */ ok( !lstrcmpW((LPCWSTR)cmd, exec_cmdAW), "server W got wrong command '%s'\n", cmd ); else @@ -1457,7 +1458,7 @@ static LRESULT WINAPI dde_server_wndprocW(HWND hwnd, UINT msg, WPARAM wparam, LP case 4: /* Unicode command in ANSI format */ if (conv_unicode && !client_unicode) /* W->A mapping -> garbage */ - ok( cmd[0] == '?', "server W got wrong command '%s'\n", cmd ); + ok( cmd[0] != exec_cmdWA[0], "server W got wrong command '%s'\n", cmd ); else if (!conv_unicode && client_unicode) /* A->W mapping */ ok( !lstrcmpW((LPCWSTR)cmd, exec_cmdW), "server W got wrong command '%s'\n", cmd ); else @@ -1571,6 +1572,7 @@ static void test_dde_aw_transaction( BOOL client_unicode, BOOL server_unicode ) CONVINFO info; HDDEDATA hdata; BOOL conv_unicode = client_unicode; + BOOL got; static char test_cmd[] = "test dde command"; if (!(hwnd_server = create_dde_server( server_unicode ))) return; @@ -1709,7 +1711,8 @@ todo_wine { ok(err == DMLERR_NOTPROCESSED, "DdeClientTransaction returned error %x\n", err); } - ok(DdeDisconnect(hconv), "DdeDisconnect error %x\n", DdeGetLastError(dde_inst)); + got = DdeDisconnect(hconv); + ok(got, "DdeDisconnect error %x\n", DdeGetLastError(dde_inst)); info.cb = sizeof(info); ret = DdeQueryConvInfo(hconv, QID_SYNC, &info); @@ -1719,7 +1722,8 @@ todo_wine { ok(err == DMLERR_INVALIDPARAMETER, "wrong dde error %x\n", err); } - ok(DdeFreeStringHandle(dde_inst, hsz_server), "DdeFreeStringHandle error %x\n", DdeGetLastError(dde_inst)); + got = DdeFreeStringHandle(dde_inst, hsz_server); + ok(got, "DdeFreeStringHandle error %x\n", DdeGetLastError(dde_inst)); /* This call hangs on win2k SP4 and XP SP1. DdeUninitialize(dde_inst);*/ @@ -1757,7 +1761,7 @@ static void test_initialisation(void) item = DdeCreateStringHandleA(client_pid, "request", CP_WINANSI); - /* There is no converstation so an invalild parameter results */ + /* There is no conversation so an invalid parameter results */ res = 0xdeadbeef; DdeGetLastError(client_pid); hdata = DdeClientTransaction(NULL, 0, conversation, item, CF_TEXT, XTYP_REQUEST, default_timeout, &res); @@ -2043,12 +2047,6 @@ static void test_DdeCreateStringHandle(void) dde_inst = 0xdeadbeef; SetLastError(0xdeadbeef); ret = DdeInitializeW(&dde_inst, client_ddeml_callback, APPCMD_CLIENTONLY, 0); - if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) - { - win_skip("DdeInitializeW is unimplemented\n"); - return; - } - ok(ret == DMLERR_INVALIDPARAMETER, "DdeInitializeW should fail, but got %04x instead\n", ret); ok(DdeGetLastError(dde_inst) == DMLERR_INVALIDPARAMETER, "expected DMLERR_INVALIDPARAMETER\n"); @@ -2493,8 +2491,6 @@ static HDDEDATA CALLBACK server_end_to_end_callback(UINT uType, UINT uFmt, HCONV else if (unicode_client) { /* ASCII string mapped W->A -> garbage */ - ok(size == size_a / sizeof(WCHAR) || size == size_a / sizeof(WCHAR) + 1, - "Wrong size %d, msg_index=%d\n", size, msg_index); } else { @@ -2536,7 +2532,8 @@ static HDDEDATA CALLBACK server_end_to_end_callback(UINT uType, UINT uFmt, HCONV DWORD nt_size = MultiByteToWideChar( CP_ACP, 0, (char *)cmd_w, size_w, test_cmd_a_to_w, sizeof(test_cmd_a_to_w)/sizeof(WCHAR) ) * sizeof(WCHAR); DWORD xp_size = MultiByteToWideChar( CP_ACP, 0, (char *)cmd_w, -1, NULL, 0 ) * sizeof(WCHAR); - ok(size == xp_size || broken(size == nt_size), + ok(size == xp_size || broken(size == nt_size) || + broken(str_index == 4 && IsDBCSLeadByte(cmd_w[0])) /* East Asian */, "Wrong size %d/%d, msg_index=%d\n", size, size_a_to_w, msg_index); ok(!lstrcmpW((WCHAR*)buffer, test_cmd_a_to_w), "Expected %s, msg_index=%d\n", wine_dbgstr_w(test_cmd_a_to_w), msg_index); @@ -2696,6 +2693,7 @@ START_TEST(dde) char buffer[MAX_PATH]; STARTUPINFO startup; PROCESS_INFORMATION proc; + DWORD dde_inst = 0xdeadbeef; argc = winetest_get_mainargs(&argv); if (argc == 3) @@ -2714,6 +2712,14 @@ START_TEST(dde) test_initialisation(); + SetLastError(0xdeadbeef); + DdeInitializeW(&dde_inst, client_ddeml_callback, APPCMD_CLIENTONLY, 0); + if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) + { + win_skip("Skipping tests on win9x because of brokenness\n"); + return; + } + ZeroMemory(&startup, sizeof(STARTUPINFO)); sprintf(buffer, "%s dde ddeml", argv[0]); startup.cb = sizeof(startup); diff --git a/winetests/user32/dialog.c b/winetests/user32/dialog.c index 736c99d784e..8e4ffb577de 100755 --- a/winetests/user32/dialog.c +++ b/winetests/user32/dialog.c @@ -50,7 +50,7 @@ static HWND g_hwndTestDlg, g_hwndTestDlgBut1, g_hwndTestDlgBut2, g_hwndTestDlgEd static HWND g_hwndInitialFocusT1, g_hwndInitialFocusT2, g_hwndInitialFocusGroupBox; static LONG g_styleInitialFocusT1, g_styleInitialFocusT2; -static BOOL g_bInitialFocusInitDlgResult; +static BOOL g_bInitialFocusInitDlgResult, g_bReceivedCommand; static int g_terminated; @@ -209,7 +209,7 @@ static BOOL CreateWindows (HINSTANCE hinst) /* Form the lParam of a WM_KEYDOWN message */ static DWORD KeyDownData (int repeat, int scancode, int extended, int wasdown) { - return ((repeat & 0x0000FFFF) | ((scancode & 0x00FF) >> 16) | + return ((repeat & 0x0000FFFF) | ((scancode & 0x00FF) << 16) | (extended ? 0x01000000 : 0) | (wasdown ? 0x40000000 : 0)); } @@ -539,6 +539,8 @@ static LRESULT CALLBACK testDlgWinProc (HWND hwnd, UINT uiMsg, WPARAM wParam, case WM_CREATE: return (OnTestDlgCreate (hwnd, (LPCREATESTRUCTA) lParam) ? 0 : (LRESULT) -1); + case WM_COMMAND: + if(LOWORD(wParam) == 300) g_bReceivedCommand = TRUE; } return DefDlgProcA (hwnd, uiMsg, wParam, lParam); @@ -576,6 +578,8 @@ static BOOL RegisterWindowClasses (void) static void test_WM_NEXTDLGCTL(void) { + HWND child1, child2, child3; + MSG msg; DWORD dwVal; g_hwndTestDlg = CreateWindowEx( WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR @@ -638,7 +642,7 @@ static void test_WM_NEXTDLGCTL(void) "Button1 style not set to BS_DEFPUSHBUTTON\n" ); ok ( !((GetWindowLong( g_hwndTestDlgBut2, GWL_STYLE)) & BS_DEFPUSHBUTTON), - "Button2's style not chaged to BS_PUSHBUTTON\n" ); + "Button2's style not changed to BS_PUSHBUTTON\n" ); } /* @@ -663,7 +667,7 @@ static void test_WM_NEXTDLGCTL(void) "Button2 style not set to BS_DEFPUSHBUTTON\n" ); ok ( !((GetWindowLong( g_hwndTestDlgBut1, GWL_STYLE)) & BS_DEFPUSHBUTTON), - "Button1's style not chaged to BS_PUSHBUTTON\n" ); + "Button1's style not changed to BS_PUSHBUTTON\n" ); } /* @@ -678,6 +682,38 @@ static void test_WM_NEXTDLGCTL(void) dwVal = DefDlgProcA(g_hwndTestDlg, DM_GETDEFID, 0, 0); ok ( IDCANCEL == (LOWORD(dwVal)), "WM_NEXTDLGCTL changed default button\n"); } + + /* test nested default buttons */ + + child1 = CreateWindowA("button", "child1", WS_VISIBLE|WS_CHILD, 0, 0, 50, 50, + g_hwndTestDlg, (HMENU)100, g_hinst, NULL); + ok(child1 != NULL, "failed to create first child\n"); + child2 = CreateWindowA("button", "child2", WS_VISIBLE|WS_CHILD, 60, 60, 30, 30, + g_hwndTestDlg, (HMENU)200, g_hinst, NULL); + ok(child2 != NULL, "failed to create second child\n"); + /* create nested child */ + child3 = CreateWindowA("button", "child3", WS_VISIBLE|WS_CHILD, 10, 10, 10, 10, + child1, (HMENU)300, g_hinst, NULL); + ok(child3 != NULL, "failed to create subchild\n"); + + DefDlgProcA( g_hwndTestDlg, DM_SETDEFID, 200, 0); + dwVal = DefDlgProcA( g_hwndTestDlg, DM_GETDEFID, 0, 0); + ok(LOWORD(dwVal) == 200, "expected 200, got %x\n", dwVal); + + DefDlgProcA( g_hwndTestDlg, DM_SETDEFID, 300, 0); + dwVal = DefDlgProcA( g_hwndTestDlg, DM_GETDEFID, 0, 0); + ok(LOWORD(dwVal) == 300, "expected 300, got %x\n", dwVal); + ok(SendMessageW( child3, WM_GETDLGCODE, 0, 0) != DLGC_DEFPUSHBUTTON, + "expected child3 not to be marked as DLGC_DEFPUSHBUTTON\n"); + + g_bReceivedCommand = FALSE; + FormEnterMsg (&msg, child3); + ok(IsDialogMessage (g_hwndTestDlg, &msg), "Did not handle the ENTER\n"); + ok(g_bReceivedCommand, "Did not trigger the default Button action\n"); + + DestroyWindow(child3); + DestroyWindow(child2); + DestroyWindow(child1); DestroyWindow(g_hwndTestDlg); } diff --git a/winetests/user32/edit.c b/winetests/user32/edit.c index fb74143ecd2..c6c815a369c 100755 --- a/winetests/user32/edit.c +++ b/winetests/user32/edit.c @@ -559,6 +559,7 @@ static HWND create_editcontrol (DWORD style, DWORD exstyle) style, 10, 10, 300, 300, NULL, NULL, hinst, NULL); + ok (handle != NULL, "CreateWindow EDIT Control failed\n"); assert (handle); if (winetest_interactive) ShowWindow (handle, SW_SHOW); @@ -570,12 +571,14 @@ static HWND create_child_editcontrol (DWORD style, DWORD exstyle) HWND parentWnd; HWND editWnd; RECT rect; + BOOL b; rect.left = 0; rect.top = 0; rect.right = 300; rect.bottom = 300; - assert(AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE)); + b = AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE); + ok(b, "AdjustWindowRect failed\n"); parentWnd = CreateWindowEx(0, szEditTextPositionClass, @@ -584,6 +587,7 @@ static HWND create_child_editcontrol (DWORD style, DWORD exstyle) CW_USEDEFAULT, CW_USEDEFAULT, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, hinst, NULL); + ok (parentWnd != NULL, "CreateWindow EDIT Test failed\n"); assert(parentWnd); editWnd = CreateWindowEx(exstyle, @@ -592,6 +596,7 @@ static HWND create_child_editcontrol (DWORD style, DWORD exstyle) WS_CHILD | style, 0, 0, 300, 300, parentWnd, NULL, hinst, NULL); + ok (editWnd != NULL, "CreateWindow EDIT Test Text failed\n"); assert(editWnd); if (winetest_interactive) ShowWindow (parentWnd, SW_SHOW); @@ -837,10 +842,15 @@ static void test_edit_control_3(void) { HWND hWnd; HWND hParent; - int len; + HDC hDC; + int len, dpi; static const char *str = "this is a long string."; static const char *str2 = "this is a long string.\r\nthis is a long string.\r\nthis is a long string.\r\nthis is a long string."; + hDC = GetDC(NULL); + dpi = GetDeviceCaps(hDC, LOGPIXELSY); + ReleaseDC(NULL, hDC); + trace("EDIT: Test notifications\n"); hParent = CreateWindowExA(0, @@ -947,7 +957,7 @@ static void test_edit_control_3(void) "EDIT", NULL, ES_MULTILINE, - 10, 10, 50, 50, + 10, 10, (50 * dpi) / 96, (50 * dpi) / 96, hParent, NULL, NULL, NULL); assert(hWnd); @@ -992,7 +1002,7 @@ static void test_edit_control_3(void) "EDIT", NULL, ES_MULTILINE | ES_AUTOHSCROLL, - 10, 10, 50, 50, + 10, 10, (50 * dpi) / 96, (50 * dpi) / 96, hParent, NULL, NULL, NULL); assert(hWnd); @@ -1308,9 +1318,7 @@ static void test_edit_control_limittext(void) ok(r == 30000, "Incorrect default text limit, expected 30000 got %u\n", r); SendMessage(hwEdit, EM_SETLIMITTEXT, 0, 0); r = SendMessage(hwEdit, EM_GETLIMITTEXT, 0, 0); - /* Win9x+ME: 32766; WinNT: 2147483646UL */ - ok( (r == 32766) || (r == 2147483646UL), - "got limit %u (expected 32766 or 2147483646)\n", r); + ok( r == 2147483646, "got limit %u (expected 2147483646)\n", r); DestroyWindow(hwEdit); /* Test default limit for multi-line control */ @@ -1320,9 +1328,7 @@ static void test_edit_control_limittext(void) ok(r == 30000, "Incorrect default text limit, expected 30000 got %u\n", r); SendMessage(hwEdit, EM_SETLIMITTEXT, 0, 0); r = SendMessage(hwEdit, EM_GETLIMITTEXT, 0, 0); - /* Win9x+ME: 65535; WinNT: 4294967295UL */ - ok( (r == 65535) || (r == 4294967295UL), - "got limit %u (expected 65535 or 4294967295)\n", r); + ok( r == 4294967295U, "got limit %u (expected 4294967295)\n", r); DestroyWindow(hwEdit); } @@ -1527,6 +1533,7 @@ static void test_margins_font_change(void) ok(HIWORD(margins) == HIWORD(font_margins), "got %d\n", HIWORD(margins)); SendMessageA(hwEdit, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(EC_USEFONTINFO,EC_USEFONTINFO)); + SendMessageA(hwEdit, WM_SETFONT, (WPARAM)hfont, 0); margins = SendMessage(hwEdit, EM_GETMARGINS, 0, 0); ok(LOWORD(margins) == LOWORD(font_margins), "got %d\n", LOWORD(margins)); ok(HIWORD(margins) == HIWORD(font_margins), "got %d\n", HIWORD(margins)); @@ -1566,7 +1573,7 @@ static void test_text_position_style(DWORD style) HDC dc; TEXTMETRIC metrics; INT b, bm, b2, b3; - BOOL single_line = !(style & ES_MULTILINE); + BOOL xb, single_line = !(style & ES_MULTILINE); b = GetSystemMetrics(SM_CYBORDER) + 1; b2 = 2 * b; @@ -1574,10 +1581,13 @@ static void test_text_position_style(DWORD style) bm = b2 - 1; /* Get a stock font for which we can determine the metrics */ - assert(font = GetStockObject(SYSTEM_FONT)); - assert(dc = GetDC(NULL)); + font = GetStockObject(SYSTEM_FONT); + ok (font != NULL, "GetStockObjcet SYSTEM_FONT failed\n"); + dc = GetDC(NULL); + ok (dc != NULL, "GetDC() failed\n"); oldFont = SelectObject(dc, font); - assert(GetTextMetrics(dc, &metrics)); + xb = GetTextMetrics(dc, &metrics); + ok (xb, "GetTextMetrics failed\n"); SelectObject(dc, oldFont); ReleaseDC(NULL, dc); @@ -2212,9 +2222,15 @@ static void test_fontsize(void) { HWND hwEdit; HFONT hfont; + HDC hDC; LOGFONT lf; LONG r; char szLocalString[MAXLEN]; + int dpi; + + hDC = GetDC(NULL); + dpi = GetDeviceCaps(hDC, LOGPIXELSY); + ReleaseDC(NULL, hDC); memset(&lf,0,sizeof(LOGFONTA)); strcpy(lf.lfFaceName,"Arial"); @@ -2224,7 +2240,8 @@ static void test_fontsize(void) trace("EDIT: Oversized font (Multi line)\n"); hwEdit= CreateWindow("EDIT", NULL, ES_MULTILINE|ES_AUTOHSCROLL, - 0, 0, 150, 50, NULL, NULL, hinst, NULL); + 0, 0, (150 * dpi) / 96, (50 * dpi) / 96, NULL, NULL, + hinst, NULL); SendMessage(hwEdit,WM_SETFONT,(WPARAM)hfont,0); @@ -2435,10 +2452,14 @@ static void test_dialogmode(void) START_TEST(edit) { + BOOL b; + init_function_pointers(); hinst = GetModuleHandleA(NULL); - assert(RegisterWindowClasses()); + b = RegisterWindowClasses(); + ok (b, "RegisterWindowClasses failed\n"); + if (!b) return; test_edit_control_1(); test_edit_control_2(); diff --git a/winetests/user32/generated.c b/winetests/user32/generated.c index e7c08cf9143..c8e8b5542be 100644 --- a/winetests/user32/generated.c +++ b/winetests/user32/generated.c @@ -5,9 +5,9 @@ * Unit tests for data structure packing */ -#define WINVER 0x0501 -#define _WIN32_IE 0x0501 -#define _WIN32_WINNT 0x0501 +//#define WINVER 0x0501 +//#define _WIN32_IE 0x0501 +//#define _WIN32_WINNT 0x0501 #define WINE_NOWINSOCK diff --git a/winetests/user32/input.c b/winetests/user32/input.c index d81240cb384..60904afa24d 100755 --- a/winetests/user32/input.c +++ b/winetests/user32/input.c @@ -43,10 +43,9 @@ * if it is a problem. * */ -#undef _WIN32_WINNT -#undef _WIN32_IE -#define _WIN32_IE 0x0500 -#define _WIN32_WINNT 0x500 + +//#define _WIN32_WINNT 0x401 +//#define _WIN32_IE 0x0500 #include #include @@ -234,14 +233,15 @@ static BOOL do_test( HWND hwnd, int seqnr, const KEV td[] ) ADDTOINPUTS(td[i]) strcat(buf, getdesc[td[i]]); if(td[i]) - expmsg[i].message = KbdMessage(td[i], &(expmsg[i].wParam), &(expmsg[i].lParam)); /* see queue_kbd_event() */ + expmsg[i].message = KbdMessage(td[i], &(expmsg[i].wParam), &(expmsg[i].lParam)); else expmsg[i].message = 0; } for( kmctr = 0; kmctr < MAXKEYEVENTS && expmsg[kmctr].message; kmctr++) ; - assert( evtctr <= MAXKEYEVENTS ); - assert( evtctr == pSendInput(evtctr, &inputs[0], sizeof(INPUT))); + ok( evtctr <= MAXKEYEVENTS, "evtctr is above MAXKEYEVENTS\n" ); + if( evtctr != pSendInput(evtctr, &inputs[0], sizeof(INPUT))) + ok (FALSE, "SendInput failed to send some events\n"); i = 0; if (winetest_debug > 1) trace("======== key stroke sequence #%d: %s =============\n", @@ -369,6 +369,16 @@ static void test_Input_whitebox(void) DestroyWindow(hWndTest); } +static inline BOOL is_keyboard_message( UINT message ) +{ + return (message >= WM_KEYFIRST && message <= WM_KEYLAST); +} + +static inline BOOL is_mouse_message( UINT message ) +{ + return (message >= WM_MOUSEFIRST && message <= WM_MOUSELAST); +} + /* try to make sure pending X events have been processed before continuing */ static void empty_message_queue(void) { @@ -382,6 +392,9 @@ static void empty_message_queue(void) if (MsgWaitForMultipleObjects(0, NULL, FALSE, min_timeout, QS_ALLINPUT) == WAIT_TIMEOUT) break; while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { + if (is_keyboard_message(msg.message) || is_mouse_message(msg.message)) + ok(msg.time != 0, "message %#x has time set to 0\n", msg.message); + TranslateMessage(&msg); DispatchMessage(&msg); } @@ -415,7 +428,7 @@ struct message { LPARAM lParam; /* expected value of lParam */ }; -struct sendinput_test_s { +static const struct sendinput_test_s { WORD wVk; DWORD dwFlags; BOOL _todo_wine; @@ -675,10 +688,10 @@ static struct message sent_messages[MAXKEYMESSAGES]; static UINT sent_messages_cnt; /* Verify that only specified key state transitions occur */ -static void compare_and_check(int id, BYTE *ks1, BYTE *ks2, struct sendinput_test_s *test) +static void compare_and_check(int id, BYTE *ks1, BYTE *ks2, const struct sendinput_test_s *test) { int i, failcount = 0; - struct transition_s *t = test->expected_transitions; + const struct transition_s *t = test->expected_transitions; UINT actual_cnt = 0; const struct message *expected = test->expected_messages; @@ -1140,6 +1153,8 @@ static void test_Input_unicode(void) WNDCLASSW wclass; HANDLE hInstance = GetModuleHandleW(NULL); HHOOK hook; + HMODULE hModuleImm32; + BOOL (WINAPI *pImmDisableIME)(DWORD); wclass.lpszClassName = classNameW; wclass.style = CS_HREDRAW | CS_VREDRAW; @@ -1155,6 +1170,16 @@ static void test_Input_unicode(void) win_skip("Unicode functions not supported\n"); return; } + + hModuleImm32 = LoadLibrary("imm32.dll"); + if (hModuleImm32) { + pImmDisableIME = (void *)GetProcAddress(hModuleImm32, "ImmDisableIME"); + if (pImmDisableIME) + pImmDisableIME(0); + } + pImmDisableIME = NULL; + FreeLibrary(hModuleImm32); + /* create the test window that will receive the keystrokes */ hWndTest = CreateWindowW(wclass.lpszClassName, windowNameW, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, 100, 100, diff --git a/winetests/user32/listbox.c b/winetests/user32/listbox.c index 06c41d41531..1d6e8a34ed8 100644 --- a/winetests/user32/listbox.c +++ b/winetests/user32/listbox.c @@ -291,7 +291,7 @@ static void test_ownerdraw(void) cls.hbrBackground = GetStockObject(WHITE_BRUSH); cls.lpszMenuName = NULL; cls.lpszClassName = "main_window_class"; - assert(RegisterClass(&cls)); + ok (RegisterClass(&cls), "RegisterClass failed\n"); parent = CreateWindowEx(0, "main_window_class", NULL, WS_POPUP | WS_VISIBLE, @@ -840,7 +840,6 @@ static void test_listbox_LB_DIR(void) memset(pathBuffer, 0, MAX_PATH); driveletter = '\0'; SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer); - p = pathBuffer + strlen(pathBuffer); if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) { ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter); } @@ -951,7 +950,6 @@ static void test_listbox_LB_DIR(void) memset(pathBuffer, 0, MAX_PATH); driveletter = '\0'; SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer); - p = pathBuffer + strlen(pathBuffer); if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) { ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter); } else { @@ -987,7 +985,6 @@ static void test_listbox_LB_DIR(void) memset(pathBuffer, 0, MAX_PATH); driveletter = '\0'; SendMessage(hList, LB_GETTEXT, i, (LPARAM)pathBuffer); - p = pathBuffer + strlen(pathBuffer); ok (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1, "Element %d (%s) does not fit [-X-]\n", i, pathBuffer); ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter); } @@ -996,8 +993,8 @@ static void test_listbox_LB_DIR(void) DeleteFileA( "wtest1.tmp.c" ); } -HWND g_listBox; -HWND g_label; +static HWND g_listBox; +static HWND g_label; #define ID_TEST_LABEL 1001 #define ID_TEST_LISTBOX 1002 @@ -1181,7 +1178,6 @@ static void test_listbox_dlgdir(void) for (i = 0; i < itemCount; i++) { memset(pathBuffer, 0, MAX_PATH); SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer); - p = pathBuffer + strlen(pathBuffer); ok( pathBuffer[0] == '[' && pathBuffer[strlen(pathBuffer)-1] == ']', "Element %d (%s) does not fit requested [...]\n", i, pathBuffer); } @@ -1321,7 +1317,6 @@ static void test_listbox_dlgdir(void) memset(pathBuffer, 0, MAX_PATH); driveletter = '\0'; SendMessage(g_listBox, LB_GETTEXT, i, (LPARAM)pathBuffer); - p = pathBuffer + strlen(pathBuffer); if (sscanf(pathBuffer, "[-%c-]", &driveletter) == 1) { ok( driveletter >= 'a' && driveletter <= 'z', "Drive letter not in range a..z, got ascii %d\n", driveletter); } else { diff --git a/winetests/user32/menu.c b/winetests/user32/menu.c index deecbe8dd03..2d308c48178 100755 --- a/winetests/user32/menu.c +++ b/winetests/user32/menu.c @@ -19,7 +19,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#define _WIN32_WINNT 0x0501 +//#define _WIN32_WINNT 0x0501 #include #include @@ -169,6 +169,8 @@ static LRESULT WINAPI menu_ownerdraw_wnd_proc(HWND hwnd, UINT msg, if( winetest_debug) trace("WM_MEASUREITEM received data %lx size %dx%d\n", pmis->itemData, pmis->itemWidth, pmis->itemHeight); + ok( !wparam, "wrong wparam %lx\n", wparam ); + ok( pmis->CtlType == ODT_MENU, "wrong type %x\n", pmis->CtlType ); MOD_odheight = pmis->itemHeight; pmis->itemWidth = MODsizes[pmis->itemData].cx; pmis->itemHeight = MODsizes[pmis->itemData].cy; @@ -197,6 +199,8 @@ static LRESULT WINAPI menu_ownerdraw_wnd_proc(HWND hwnd, UINT msg, pdis->rcItem.right,pdis->rcItem.bottom ); SelectObject( pdis->hDC, oldpen); } + ok( !wparam, "wrong wparam %lx\n", wparam ); + ok( pdis->CtlType == ODT_MENU, "wrong type %x\n", pdis->CtlType ); /* calculate widths of some menu texts */ if( ! MOD_txtsizes[0].size.cx) for(i = 0; MOD_txtsizes[i].text; i++) { @@ -217,7 +221,7 @@ static LRESULT WINAPI menu_ownerdraw_wnd_proc(HWND hwnd, UINT msg, } if( pdis->itemData > MOD_maxid) return TRUE; - /* store the rectangl */ + /* store the rectangle */ MOD_rc[pdis->itemData] = pdis->rcItem; /* calculate average character width */ GetTextExtentPoint( pdis->hDC, chrs, 52, &sz ); @@ -404,6 +408,7 @@ static void test_menu_ownerdraw(void) int i,j,k; BOOL ret; HMENU hmenu; + MENUITEMINFO mii; LONG leftcol; HWND hwnd = CreateWindowEx(0, MAKEINTATOM(atomMenuCheckClass), NULL, WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, 200, 200, @@ -425,7 +430,7 @@ static void test_menu_ownerdraw(void) MOD_maxid = k-1; assert( k <= sizeof(MOD_rc)/sizeof(RECT)); /* display the menu */ - ret = TrackPopupMenu( hmenu, TPM_RETURNCMD, 100,100, 0, hwnd, NULL); + TrackPopupMenu( hmenu, TPM_RETURNCMD, 100,100, 0, hwnd, NULL); /* columns have a 4 pixel gap between them */ ok( MOD_rc[0].right + 4 == MOD_rc[2].left, @@ -449,7 +454,7 @@ static void test_menu_ownerdraw(void) leftcol= MOD_rc[0].left; ModifyMenu( hmenu, 0, MF_BYCOMMAND| MF_OWNERDRAW| MF_SEPARATOR, 0, 0); /* display the menu */ - ret = TrackPopupMenu( hmenu, TPM_RETURNCMD, 100,100, 0, hwnd, NULL); + TrackPopupMenu( hmenu, TPM_RETURNCMD, 100,100, 0, hwnd, NULL); /* left should be 4 pixels less now */ ok( leftcol == MOD_rc[0].left + 4, "columns should be 4 pixels to the left (actual %d).\n", @@ -463,6 +468,18 @@ static void test_menu_ownerdraw(void) "Height is incorrect. Got %d expected %d\n", MOD_rc[0].bottom - MOD_rc[0].top, MOD_SIZE); + /* test owner-drawn callback bitmap */ + ModifyMenu( hmenu, 1, MF_BYPOSITION | MFT_BITMAP, 1, (LPCSTR)HBMMENU_CALLBACK ); + mii.cbSize = sizeof(mii); + mii.fMask = MIIM_BITMAP | MIIM_FTYPE | MIIM_ID; + if (GetMenuItemInfoA( hmenu, 1, TRUE, &mii )) + { + ok( mii.fType == MFT_BITMAP, "wrong type %x\n", mii.fType ); + ok( mii.wID == 1, "wrong id %x\n", mii.wID ); + ok( mii.hbmpItem == HBMMENU_CALLBACK, "wrong data %p\n", mii.hbmpItem ); + } + TrackPopupMenu( hmenu, TPM_RETURNCMD, 100,100, 0, hwnd, NULL); + /* test width/height of an ownerdraw menu bar as well */ ret = DestroyMenu(hmenu); ok(ret, "DestroyMenu failed with error %d\n", GetLastError()); @@ -562,13 +579,15 @@ static void test_mbs_help( int ispop, int hassub, int mnuopt, ReleaseDC( hwnd, hdc); } if(ispop) - ret = TrackPopupMenu( hmenu, TPM_RETURNCMD, 100,100, 0, hwnd, NULL); + TrackPopupMenu( hmenu, TPM_RETURNCMD, 100,100, 0, hwnd, NULL); else { ret = SetMenu( hwnd, hmenu); ok(ret, "SetMenu failed with error %d\n", GetLastError()); DrawMenuBar( hwnd); } ret = GetMenuItemRect( hwnd, hmenu, 0, &rc); + ok(ret, "GetMenuItemRect failed with error %d\n", GetLastError()); + if (0) /* comment out menu size checks, behavior is different in almost every Windows version */ /* the tests should however succeed on win2000, XP and Wine (at least up to 1.1.15) */ /* with a variety of dpis and desktop font sizes */ @@ -660,6 +679,7 @@ static void test_menu_bmp_and_string(void) MENUINFO mi= {sizeof(MENUINFO)}; MENUITEMINFOA mii= {sizeof(MENUITEMINFOA)}; int count, szidx, txtidx, bmpidx, hassub, mnuopt, ispop; + BOOL got; if( !pGetMenuInfo) { @@ -681,12 +701,14 @@ static void test_menu_bmp_and_string(void) ok( hsysmenu != NULL, "GetSystemMenu failed with error %d\n", GetLastError()); mi.fMask = MIM_STYLE; mi.dwStyle = 0; - ok( pGetMenuInfo( hsysmenu, &mi), "GetMenuInfo failed gle=%d\n", GetLastError()); + got = pGetMenuInfo( hsysmenu, &mi); + ok( got, "GetMenuInfo failed gle=%d\n", GetLastError()); ok( MNS_CHECKORBMP == mi.dwStyle, "System Menu Style is %08x, without the bit %08x\n", mi.dwStyle, MNS_CHECKORBMP); mii.fMask = MIIM_BITMAP; mii.hbmpItem = NULL; - ok( GetMenuItemInfoA( hsysmenu, SC_CLOSE, FALSE, &mii), "GetMenuItemInfoA failed gle=%d\n", GetLastError()); + got = GetMenuItemInfoA( hsysmenu, SC_CLOSE, FALSE, &mii); + ok( got, "GetMenuItemInfoA failed gle=%d\n", GetLastError()); ok( HBMMENU_POPUP_CLOSE == mii.hbmpItem, "Item info did not get the right hbitmap: got %p expected %p\n", mii.hbmpItem, HBMMENU_POPUP_CLOSE); @@ -954,7 +976,9 @@ static void check_menu_item_info( int line, HMENU hmenu, BOOL ansi, UINT mask, U "wrong bmpitem %p/%p\n", info.hbmpItem, item ); ok_(__FILE__, line)( info.dwTypeData == type_data || (ULONG_PTR)info.dwTypeData == LOWORD(type_data), "wrong type data %p/%p\n", info.dwTypeData, type_data ); - ok_(__FILE__, line)( info.cch == out_len, "wrong len %x/%x\n", info.cch, out_len ); + ok_(__FILE__, line)( info.cch == out_len || + broken(! ansi && info.cch == 2 * out_len) /* East-Asian */, + "wrong len %x/%x\n", info.cch, out_len ); if (expname) { if(ansi) @@ -1058,7 +1082,7 @@ static void test_menu_iteminfo( void ) void *txt, *init, *empty, *string; HBITMAP hbm = CreateBitmap(1,1,1,1,NULL); char stringA[0x80]; - HMENU hmenu, submenu=CreateMenu(); + HMENU hmenu, submenu; HBITMAP dummy_hbm = (HBITMAP)(ULONG_PTR)0xdeadbeef; do { @@ -2031,6 +2055,7 @@ static void test_menu_input(void) { HINSTANCE hInstance = GetModuleHandleA( NULL ); HANDLE hThread, hWnd; DWORD tid; + ATOM aclass; if (!pSendInput) { @@ -2048,11 +2073,14 @@ static void test_menu_input(void) { wclass.lpszMenuName = 0; wclass.cbClsExtra = 0; wclass.cbWndExtra = 0; - assert (RegisterClassA( &wclass )); - assert (hWnd = CreateWindowA( wclass.lpszClassName, "MenuTest", - WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, - 400, 200, NULL, NULL, hInstance, NULL) ); - + aclass = RegisterClassA( &wclass ); + ok (aclass, "MenuTest class not created\n"); + if (!aclass) return; + hWnd = CreateWindowA( wclass.lpszClassName, "MenuTest", + WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, + 400, 200, NULL, NULL, hInstance, NULL); + ok (hWnd != NULL, "MenuTest window not created\n"); + if (!hWnd) return; /* fixed menus */ hMenus[3] = CreatePopupMenu(); AppendMenu(hMenus[3], MF_STRING, 0, "&Enabled"); @@ -2118,6 +2146,7 @@ static void test_menu_hilitemenuitem( void ) HMENU hMenu, hPopupMenu; WNDCLASSA wclass; HWND hWnd; + ATOM aclass; wclass.lpszClassName = "HiliteMenuTestClass"; wclass.style = CS_HREDRAW | CS_VREDRAW; @@ -2129,10 +2158,14 @@ static void test_menu_hilitemenuitem( void ) wclass.lpszMenuName = 0; wclass.cbClsExtra = 0; wclass.cbWndExtra = 0; - assert (RegisterClassA( &wclass )); - assert (hWnd = CreateWindowA( wclass.lpszClassName, "HiliteMenuTest", - WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, - 400, 200, NULL, NULL, wclass.hInstance, NULL) ); + aclass = RegisterClassA( &wclass ); + ok (aclass, "HiliteMenuTest class could not be created\n"); + if (!aclass) return; + hWnd = CreateWindowA( wclass.lpszClassName, "HiliteMenuTest", + WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, + 400, 200, NULL, NULL, wclass.hInstance, NULL); + ok (hWnd != NULL, "HiliteMenuTest window could not be created\n"); + if (!hWnd) return; hMenu = CreateMenu(); hPopupMenu = CreatePopupMenu(); @@ -2884,7 +2917,8 @@ static void test_menu_trackpopupmenu(void) } /* display the menu */ /* start with an invalid menu handle */ - gle = 0xdeadbeef; + SetLastError(0xdeadbeef); + gflag_initmenupopup = gflag_entermenuloop = gflag_initmenu = 0; ret = MyTrackPopupMenu( Ex, NULL, TPM_RETURNCMD, 100,100, hwnd, NULL); gle = GetLastError(); @@ -2900,7 +2934,7 @@ static void test_menu_trackpopupmenu(void) gflag_entermenuloop ? "WM_INITMENULOOP ": "", gflag_initmenu ? "WM_INITMENU": ""); /* another one but not NULL */ - gle = 0xdeadbeef; + SetLastError(0xdeadbeef); gflag_initmenupopup = gflag_entermenuloop = gflag_initmenu = 0; ret = MyTrackPopupMenu( Ex, (HMENU)hwnd, TPM_RETURNCMD, 100,100, hwnd, NULL); gle = GetLastError(); @@ -2915,8 +2949,22 @@ static void test_menu_trackpopupmenu(void) gflag_initmenupopup ? " WM_INITMENUPOPUP ": " ", gflag_entermenuloop ? "WM_INITMENULOOP ": "", gflag_initmenu ? "WM_INITMENU": ""); + + /* invalid window */ + SetLastError(0xdeadbeef); + gflag_initmenupopup = gflag_entermenuloop = gflag_initmenu = 0; + ret = MyTrackPopupMenu( Ex, hmenu, TPM_RETURNCMD, 100,100, 0, NULL); + gle = GetLastError(); + ok( !ret, "TrackPopupMenu%s should have failed\n", Ex ? "Ex" : ""); + ok( gle == ERROR_INVALID_WINDOW_HANDLE, "TrackPopupMenu%s error got %u\n", Ex ? "Ex" : "", gle ); + ok( !(gflag_initmenupopup || gflag_entermenuloop || gflag_initmenu), + "got unexpected message(s)%s%s%s\n", + gflag_initmenupopup ? " WM_INITMENUPOPUP ": " ", + gflag_entermenuloop ? "WM_INITMENULOOP ": "", + gflag_initmenu ? "WM_INITMENU": ""); + /* now a somewhat successful call */ - gle = 0xdeadbeef; + SetLastError(0xdeadbeef); gflag_initmenupopup = gflag_entermenuloop = gflag_initmenu = 0; ret = MyTrackPopupMenu( Ex, hmenu, TPM_RETURNCMD, 100,100, hwnd, NULL); gle = GetLastError(); @@ -2934,7 +2982,7 @@ static void test_menu_trackpopupmenu(void) /* and another */ ret = AppendMenuA( hmenu, MF_STRING, 1, "winetest"); ok( ret, "AppendMenA has failed!\n"); - gle = 0xdeadbeef; + SetLastError(0xdeadbeef); gflag_initmenupopup = gflag_entermenuloop = gflag_initmenu = 0; ret = MyTrackPopupMenu( Ex, hmenu, TPM_RETURNCMD, 100,100, hwnd, NULL); gle = GetLastError(); @@ -3055,21 +3103,21 @@ static void test_menu_cancelmode(void) {MSG msg; while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessage(&msg);} /* test the effect of sending a WM_CANCELMODE message in the WM_INITMENULOOP * handler of the menu owner */ - /* test results is exctracted from variable g_got_enteridle. Possible values: + /* test results is extracted from variable g_got_enteridle. Possible values: * 0 : complete conformance. Sending WM_CANCELMODE cancels a menu initializing tracking * 1 : Sending WM_CANCELMODE cancels a menu that is in tracking state * 2 : Sending WM_CANCELMODE does not work */ /* menu owner is top level window */ g_hwndtosend = hwnd; - ret = TrackPopupMenu( menu, TPM_RETURNCMD, 100,100, 0, hwnd, NULL); + TrackPopupMenu( menu, TPM_RETURNCMD, 100,100, 0, hwnd, NULL); todo_wine { ok( g_got_enteridle == 0, "received %d WM_ENTERIDLE messages, none expected\n", g_got_enteridle); } ok( g_got_enteridle < 2, "received %d WM_ENTERIDLE messages, should be less than 2\n", g_got_enteridle); /* menu owner is child window */ g_hwndtosend = hwndchild; - ret = TrackPopupMenu( menu, TPM_RETURNCMD, 100,100, 0, hwndchild, NULL); + TrackPopupMenu( menu, TPM_RETURNCMD, 100,100, 0, hwndchild, NULL); todo_wine { ok(g_got_enteridle == 0, "received %d WM_ENTERIDLE messages, none expected\n", g_got_enteridle); } @@ -3077,7 +3125,7 @@ static void test_menu_cancelmode(void) /* now send the WM_CANCELMODE messages to the WRONG window */ /* those should fail ( to have any effect) */ g_hwndtosend = hwnd; - ret = TrackPopupMenu( menu, TPM_RETURNCMD, 100,100, 0, hwndchild, NULL); + TrackPopupMenu( menu, TPM_RETURNCMD, 100,100, 0, hwndchild, NULL); ok( g_got_enteridle == 2, "received %d WM_ENTERIDLE messages, should be 2\n", g_got_enteridle); /* cleanup */ DestroyMenu( menu); @@ -3177,6 +3225,7 @@ static void test_menualign(void) if( pGetMenuInfo) { mi.fMask = MIM_STYLE; ret = pGetMenuInfo( menu, &mi); + ok( ret, "GetMenuInfo failed: %d\n", GetLastError()); ok( menu != NULL, "GetMenuInfo() failed\n"); ok( 0 == mi.dwStyle, "menuinfo style is %x\n", mi.dwStyle); } diff --git a/winetests/user32/monitor.c b/winetests/user32/monitor.c index daa303585bd..e31019f6708 100644 --- a/winetests/user32/monitor.c +++ b/winetests/user32/monitor.c @@ -267,6 +267,14 @@ static void test_ChangeDisplaySettingsEx(void) ok(ClipCursor(&r1), "ClipCursor() failed\n"); ok(GetClipCursor(&r), "GetClipCursor() failed\n"); ok(EqualRect(&r, &r1), "Invalid clip rect: (%d %d) x (%d %d)\n", r.left, r.top, r.right, r.bottom); + SetRect(&r1, 10, 10, 10, 10); + ok(ClipCursor(&r1), "ClipCursor() failed\n"); + ok(GetClipCursor(&r), "GetClipCursor() failed\n"); + ok(EqualRect(&r, &r1), "Invalid clip rect: (%d %d) x (%d %d)\n", r.left, r.top, r.right, r.bottom); + SetRect(&r1, 10, 10, 10, 9); + ok(!ClipCursor(&r1), "ClipCursor() succeeded\n"); + /* Windows bug: further clipping fails once an empty rect is set, so we have to reset it */ + ClipCursor(NULL); SetRect(&r1, virt.left - 10, virt.top - 10, virt.right + 20, virt.bottom + 20); ok(ClipCursor(&r1), "ClipCursor() failed\n"); diff --git a/winetests/user32/msg.c b/winetests/user32/msg.c index e0494ef2a06..cdb8206e0f7 100755 --- a/winetests/user32/msg.c +++ b/winetests/user32/msg.c @@ -20,8 +20,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#define _WIN32_WINNT 0x0600 /* For WM_CHANGEUISTATE,QS_RAWINPUT,WM_DWMxxxx */ -#define WINVER 0x0600 /* for WM_GETTITLEBARINFOEX */ +//#define _WIN32_WINNT 0x0600 /* For WM_CHANGEUISTATE,QS_RAWINPUT,WM_DWMxxxx */ +//#define WINVER 0x0600 /* for WM_GETTITLEBARINFOEX */ #include #include @@ -79,6 +79,7 @@ typedef struct static BOOL test_DestroyWindow_flag; static HWINEVENTHOOK hEvent_hook; +static HHOOK hKBD_hook; static HHOOK hCBT_hook; static DWORD cbt_hook_thread_id; @@ -105,7 +106,8 @@ typedef enum { beginpaint=0x40, optional=0x80, hook=0x100, - winevent_hook=0x200 + winevent_hook=0x200, + kbd_hook=0x400 } msg_flags_t; struct message { @@ -293,7 +295,7 @@ static const struct message WmSwitchChild[] = { { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, /* in the 2nd MDI child */ { WM_MDIACTIVATE, sent|defwinproc }, /* in the 2nd MDI child */ { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, - /* Preparing for maximize and maximaze the 1st MDI child */ + /* Preparing for maximize and maximize the 1st MDI child */ { WM_GETMINMAXINFO, sent|defwinproc }, /* in the 1st MDI child */ { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_STATECHANGED }, /* in the 1st MDI child */ { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 }, /* in the 1st MDI child */ @@ -1717,6 +1719,8 @@ static BOOL (WINAPI *pSetMenuInfo)(HMENU,LPCMENUINFO); static HWINEVENTHOOK (WINAPI *pSetWinEventHook)(DWORD, DWORD, HMODULE, WINEVENTPROC, DWORD, DWORD, DWORD); static BOOL (WINAPI *pTrackMouseEvent)(TRACKMOUSEEVENT*); static BOOL (WINAPI *pUnhookWinEvent)(HWINEVENTHOOK); +static BOOL (WINAPI *pGetMonitorInfoA)(HMONITOR,LPMONITORINFO); +static HMONITOR (WINAPI *pMonitorFromPoint)(POINT,DWORD); /* kernel32 functions */ static BOOL (WINAPI *pGetCPInfoExA)(UINT, DWORD, LPCPINFOEXA); @@ -1738,6 +1742,8 @@ static void init_procs(void) GET_PROC(user32, SetWinEventHook) GET_PROC(user32, TrackMouseEvent) GET_PROC(user32, UnhookWinEvent) + GET_PROC(user32, GetMonitorInfoA) + GET_PROC(user32, MonitorFromPoint) GET_PROC(kernel32, GetCPInfoExA) @@ -1940,6 +1946,11 @@ static void dump_sequence(const struct message *expected, const char *context, c trace_(file, line)( " %u: expected: winevent %04x - actual: %s\n", count, expected->message, actual->output ); } + else if (expected->flags & kbd_hook) + { + trace_(file, line)( " %u: expected: kbd %04x - actual: %s\n", + count, expected->message, actual->output ); + } else { trace_(file, line)( " %u: expected: msg %04x - actual: %s\n", @@ -2014,7 +2025,8 @@ static void ok_sequence_(const struct message *expected_list, const char *contex while (expected->message && actual->message) { - if (expected->message == actual->message) + if (expected->message == actual->message && + !((expected->flags ^ actual->flags) & (hook|winevent_hook|kbd_hook))) { if (expected->flags & wparam) { @@ -2108,13 +2120,19 @@ static void ok_sequence_(const struct message *expected_list, const char *contex context, count, expected->message); if ((expected->flags & winevent_hook) != (actual->flags & winevent_hook)) dump++; + ok_( file, line) ((expected->flags & kbd_hook) == (actual->flags & kbd_hook), + "%s: %u: the msg 0x%04x should have been sent by a keyboard hook\n", + context, count, expected->message); + if ((expected->flags & kbd_hook) != (actual->flags & kbd_hook)) dump++; + expected++; actual++; } /* silently drop hook messages if there is no support for them */ else if ((expected->flags & optional) || ((expected->flags & hook) && !hCBT_hook) || - ((expected->flags & winevent_hook) && !hEvent_hook)) + ((expected->flags & winevent_hook) && !hEvent_hook) || + ((expected->flags & kbd_hook) && !hKBD_hook)) expected++; else if (todo) { @@ -3363,7 +3381,7 @@ static void test_mdi_messages(void) RECT rc; HMENU hMenu = CreateMenu(); - assert(mdi_RegisterWindowClasses()); + if (!mdi_RegisterWindowClasses()) assert(0); flush_sequence(); @@ -6157,6 +6175,16 @@ static void test_paint_messages(void) flush_events(); ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE ); + trace("testing UpdateWindow(NULL)\n"); + SetLastError(0xdeadbeef); + ok(!UpdateWindow(NULL), "UpdateWindow(NULL) should fail\n"); + ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || + broken( GetLastError() == 0xdeadbeef ) /* win9x */, + "wrong error code %d\n", GetLastError()); + check_update_rgn( hwnd, 0 ); + flush_events(); + ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE ); + /* now with frame */ SetRectRgn( hrgn, -5, -5, 20, 20 ); @@ -6701,7 +6729,7 @@ static void test_interthread_messages(void) CloseHandle(wnd_event.start_event); SetLastError(0xdeadbeef); - ok(!DestroyWindow(wnd_event.hwnd), "DestroyWindow succeded\n"); + ok(!DestroyWindow(wnd_event.hwnd), "DestroyWindow succeeded\n"); ok(GetLastError() == ERROR_ACCESS_DENIED || GetLastError() == 0xdeadbeef, "wrong error code %d\n", GetLastError()); @@ -6723,7 +6751,7 @@ static void test_interthread_messages(void) SetLastError(0xdeadbeef); len = DispatchMessageA(&msg); ok((!len && GetLastError() == ERROR_MESSAGE_SYNC_ONLY) || broken(len), /* nt4 */ - "DispatchMessageA(WM_GETTEXT) succeded on another thread window: ret %d, error %d\n", len, GetLastError()); + "DispatchMessageA(WM_GETTEXT) succeeded on another thread window: ret %d, error %d\n", len, GetLastError()); /* the following test causes an exception in user.exe under win9x */ msg.hwnd = wnd_event.hwnd; @@ -7686,6 +7714,49 @@ static LRESULT WINAPI PaintLoopProcA(HWND hWnd, UINT msg, WPARAM wParam, LPARAM return DefWindowProcA(hWnd,msg,wParam,lParam); } +static LRESULT WINAPI HotkeyMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + static LONG defwndproc_counter = 0; + LRESULT ret; + struct recvd_message msg; + DWORD queue_status; + + if (ignore_message( message )) return 0; + + if ((message >= WM_KEYFIRST && message <= WM_KEYLAST) || + message == WM_HOTKEY || message >= WM_APP) + { + msg.hwnd = hwnd; + msg.message = message; + msg.flags = sent|wparam|lparam; + if (defwndproc_counter) msg.flags |= defwinproc; + msg.wParam = wParam; + msg.lParam = lParam; + msg.descr = "HotkeyMsgCheckProcA"; + add_message(&msg); + } + + defwndproc_counter++; + ret = DefWindowProcA(hwnd, message, wParam, lParam); + defwndproc_counter--; + + if (message == WM_APP) + { + queue_status = GetQueueStatus(QS_HOTKEY); + ok((queue_status & (QS_HOTKEY << 16)) == QS_HOTKEY << 16, "expected QS_HOTKEY << 16 set, got %x\n", queue_status); + queue_status = GetQueueStatus(QS_POSTMESSAGE); + ok((queue_status & (QS_POSTMESSAGE << 16)) == QS_POSTMESSAGE << 16, "expected QS_POSTMESSAGE << 16 set, got %x\n", queue_status); + PostMessageA(hwnd, WM_APP+1, 0, 0); + } + else if (message == WM_APP+1) + { + queue_status = GetQueueStatus(QS_HOTKEY); + ok((queue_status & (QS_HOTKEY << 16)) == 0, "expected QS_HOTKEY << 16 cleared, got %x\n", queue_status); + } + + return ret; +} + static BOOL RegisterWindowClasses(void) { WNDCLASSA cls; @@ -7703,6 +7774,10 @@ static BOOL RegisterWindowClasses(void) cls.lpszClassName = "TestWindowClass"; if(!RegisterClassA(&cls)) return FALSE; + cls.lpfnWndProc = HotkeyMsgCheckProcA; + cls.lpszClassName = "HotkeyWindowClass"; + if(!RegisterClassA(&cls)) return FALSE; + cls.lpfnWndProc = ShowWindowProcA; cls.lpszClassName = "ShowWindowClass"; if(!RegisterClassA(&cls)) return FALSE; @@ -10012,6 +10087,50 @@ done: flush_events(); } +static INT_PTR CALLBACK wm_quit_dlg_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp) +{ + struct recvd_message msg; + + if (ignore_message( message )) return 0; + + msg.hwnd = hwnd; + msg.message = message; + msg.flags = sent|wparam|lparam; + msg.wParam = wp; + msg.lParam = lp; + msg.descr = "dialog"; + add_message(&msg); + + switch (message) + { + case WM_INITDIALOG: + PostMessage(hwnd, WM_QUIT, 0x1234, 0x5678); + PostMessage(hwnd, WM_USER, 0xdead, 0xbeef); + return 0; + + case WM_GETDLGCODE: + return 0; + + case WM_USER: + EndDialog(hwnd, 0); + break; + } + + return 1; +} + +static const struct message WmQuitDialogSeq[] = { + { HCBT_CREATEWND, hook }, + { WM_SETFONT, sent }, + { WM_INITDIALOG, sent }, + { WM_CHANGEUISTATE, sent|optional }, + { HCBT_DESTROYWND, hook }, + { 0x0090, sent|optional }, /* Vista */ + { WM_DESTROY, sent }, + { WM_NCDESTROY, sent }, + { 0 } +}; + static void test_quit_message(void) { MSG msg; @@ -10062,6 +10181,18 @@ static void test_quit_message(void) ret = GetMessage(&msg, NULL, 0, 0); ok(ret > 0, "GetMessage failed with error %d\n", GetLastError()); ok(msg.message == WM_USER, "Received message 0x%04x instead of WM_USER\n", msg.message); + + flush_events(); + flush_sequence(); + ret = DialogBoxParam(GetModuleHandle(0), "TEST_EMPTY_DIALOG", 0, wm_quit_dlg_proc, 0); + ok(ret == 1, "expected 1, got %d\n", ret); + ok_sequence(WmQuitDialogSeq, "WmQuitDialogSeq", FALSE); + memset(&msg, 0xab, sizeof(msg)); + ret = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE); + ok(ret, "PeekMessage failed\n"); + ok(msg.message == WM_QUIT, "Received message 0x%04x instead of WM_QUIT\n", msg.message); + ok(msg.wParam == 0x1234, "wParam was 0x%lx instead of 0x1234\n", msg.wParam); + ok(msg.lParam == 0, "lParam was 0x%lx instead of 0\n", msg.lParam); } static const struct message WmMouseHoverSeq[] = { @@ -10631,71 +10762,132 @@ static void test_ShowWindow(void) LPARAM ret; /* ShowWindow return value */ DWORD style; /* window style after the command */ const struct message *msg; /* message sequence the command produces */ + INT wp_cmd, wp_flags; /* window placement after the command */ + POINT wp_min, wp_max; /* window placement after the command */ BOOL todo_msg; /* message sequence doesn't match what Wine does */ } sw[] = { -/* 1 */ { SW_SHOWNORMAL, FALSE, WS_VISIBLE, WmShowNormal, FALSE }, -/* 2 */ { SW_SHOWNORMAL, TRUE, WS_VISIBLE, WmEmptySeq, FALSE }, -/* 3 */ { SW_HIDE, TRUE, 0, WmHide_1, FALSE }, -/* 4 */ { SW_HIDE, FALSE, 0, WmEmptySeq, FALSE }, -/* 5 */ { SW_SHOWMINIMIZED, FALSE, WS_VISIBLE|WS_MINIMIZE, WmShowMinimized_1, FALSE }, -/* 6 */ { SW_SHOWMINIMIZED, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinMax_1, FALSE }, -/* 7 */ { SW_HIDE, TRUE, WS_MINIMIZE, WmHide_1, FALSE }, -/* 8 */ { SW_HIDE, FALSE, WS_MINIMIZE, WmEmptySeq, FALSE }, -/* 9 */ { SW_SHOWMAXIMIZED, FALSE, WS_VISIBLE|WS_MAXIMIZE, WmShowMaximized_1, FALSE }, -/* 10 */ { SW_SHOWMAXIMIZED, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmMinMax_2, FALSE }, -/* 11 */ { SW_HIDE, TRUE, WS_MAXIMIZE, WmHide_1, FALSE }, -/* 12 */ { SW_HIDE, FALSE, WS_MAXIMIZE, WmEmptySeq, FALSE }, -/* 13 */ { SW_SHOWNOACTIVATE, FALSE, WS_VISIBLE, WmShowNoActivate_1, FALSE }, -/* 14 */ { SW_SHOWNOACTIVATE, TRUE, WS_VISIBLE, WmEmptySeq, FALSE }, -/* 15 */ { SW_HIDE, TRUE, 0, WmHide_2, FALSE }, -/* 16 */ { SW_HIDE, FALSE, 0, WmEmptySeq, FALSE }, -/* 17 */ { SW_SHOW, FALSE, WS_VISIBLE, WmShow, FALSE }, -/* 18 */ { SW_SHOW, TRUE, WS_VISIBLE, WmEmptySeq, FALSE }, -/* 19 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinimize_1, FALSE }, -/* 20 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinMax_3, FALSE }, -/* 21 */ { SW_HIDE, TRUE, WS_MINIMIZE, WmHide_2, FALSE }, -/* 22 */ { SW_SHOWMINNOACTIVE, FALSE, WS_VISIBLE|WS_MINIMIZE, WmShowMinNoActivate, TRUE }, -/* 23 */ { SW_SHOWMINNOACTIVE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinMax_4, FALSE }, -/* 24 */ { SW_HIDE, TRUE, WS_MINIMIZE, WmHide_2, FALSE }, -/* 25 */ { SW_HIDE, FALSE, WS_MINIMIZE, WmEmptySeq, FALSE }, -/* 26 */ { SW_SHOWNA, FALSE, WS_VISIBLE|WS_MINIMIZE, WmShowNA_1, FALSE }, -/* 27 */ { SW_SHOWNA, TRUE, WS_VISIBLE|WS_MINIMIZE, WmShowNA_2, FALSE }, -/* 28 */ { SW_HIDE, TRUE, WS_MINIMIZE, WmHide_2, FALSE }, -/* 29 */ { SW_HIDE, FALSE, WS_MINIMIZE, WmEmptySeq, FALSE }, -/* 30 */ { SW_RESTORE, FALSE, WS_VISIBLE, WmRestore_1, FALSE }, -/* 31 */ { SW_RESTORE, TRUE, WS_VISIBLE, WmEmptySeq, FALSE }, -/* 32 */ { SW_HIDE, TRUE, 0, WmHide_3, FALSE }, -/* 33 */ { SW_HIDE, FALSE, 0, WmEmptySeq, FALSE }, -/* 34 */ { SW_NORMALNA, FALSE, 0, WmEmptySeq, FALSE }, /* what does this mean?! */ -/* 35 */ { SW_NORMALNA, FALSE, 0, WmEmptySeq, FALSE }, -/* 36 */ { SW_HIDE, FALSE, 0, WmEmptySeq, FALSE }, -/* 37 */ { SW_RESTORE, FALSE, WS_VISIBLE, WmRestore_2, FALSE }, -/* 38 */ { SW_RESTORE, TRUE, WS_VISIBLE, WmEmptySeq, FALSE }, -/* 39 */ { SW_SHOWNOACTIVATE, TRUE, WS_VISIBLE, WmEmptySeq, FALSE }, -/* 40 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinimize_2, FALSE }, -/* 41 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinMax_3, FALSE }, -/* 42 */ { SW_SHOWMAXIMIZED, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmShowMaximized_2, FALSE }, -/* 43 */ { SW_SHOWMAXIMIZED, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmMinMax_2, FALSE }, -/* 44 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinimize_1, FALSE }, -/* 45 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinMax_3, FALSE }, -/* 46 */ { SW_RESTORE, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmRestore_3, FALSE }, -/* 47 */ { SW_RESTORE, TRUE, WS_VISIBLE, WmRestore_4, FALSE }, -/* 48 */ { SW_SHOWMAXIMIZED, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmShowMaximized_3, FALSE }, -/* 49 */ { SW_SHOW, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmEmptySeq, FALSE }, -/* 50 */ { SW_SHOWNORMAL, TRUE, WS_VISIBLE, WmRestore_5, FALSE }, -/* 51 */ { SW_SHOWNORMAL, TRUE, WS_VISIBLE, WmRestore_5, FALSE }, -/* 52 */ { SW_HIDE, TRUE, 0, WmHide_1, FALSE }, -/* 53 */ { SW_HIDE, FALSE, 0, WmEmptySeq, FALSE }, -/* 54 */ { SW_MINIMIZE, FALSE, WS_VISIBLE|WS_MINIMIZE, WmMinimize_3, FALSE }, -/* 55 */ { SW_HIDE, TRUE, WS_MINIMIZE, WmHide_2, FALSE }, -/* 56 */ { SW_SHOWNOACTIVATE, FALSE, WS_VISIBLE, WmShowNoActivate_2, FALSE }, -/* 57 */ { SW_SHOW, TRUE, WS_VISIBLE, WmEmptySeq, FALSE } +/* 1 */ { SW_SHOWNORMAL, FALSE, WS_VISIBLE, WmShowNormal, + SW_SHOWNORMAL, 0, {-1,-1}, {-1,-1}, FALSE }, +/* 2 */ { SW_SHOWNORMAL, TRUE, WS_VISIBLE, WmEmptySeq, + SW_SHOWNORMAL, 0, {-1,-1}, {-1,-1}, FALSE }, +/* 3 */ { SW_HIDE, TRUE, 0, WmHide_1, + SW_SHOWNORMAL, 0, {-1,-1}, {-1,-1}, FALSE }, +/* 4 */ { SW_HIDE, FALSE, 0, WmEmptySeq, + SW_SHOWNORMAL, 0, {-1,-1}, {-1,-1}, FALSE }, +/* 5 */ { SW_SHOWMINIMIZED, FALSE, WS_VISIBLE|WS_MINIMIZE, WmShowMinimized_1, + SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 6 */ { SW_SHOWMINIMIZED, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinMax_1, + SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 7 */ { SW_HIDE, TRUE, WS_MINIMIZE, WmHide_1, + SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 8 */ { SW_HIDE, FALSE, WS_MINIMIZE, WmEmptySeq, + SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 9 */ { SW_SHOWMAXIMIZED, FALSE, WS_VISIBLE|WS_MAXIMIZE, WmShowMaximized_1, + SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, +/* 10 */ { SW_SHOWMAXIMIZED, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmMinMax_2, + SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, +/* 11 */ { SW_HIDE, TRUE, WS_MAXIMIZE, WmHide_1, + SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, +/* 12 */ { SW_HIDE, FALSE, WS_MAXIMIZE, WmEmptySeq, + SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, +/* 13 */ { SW_SHOWNOACTIVATE, FALSE, WS_VISIBLE, WmShowNoActivate_1, + SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 14 */ { SW_SHOWNOACTIVATE, TRUE, WS_VISIBLE, WmEmptySeq, + SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 15 */ { SW_HIDE, TRUE, 0, WmHide_2, + SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 16 */ { SW_HIDE, FALSE, 0, WmEmptySeq, + SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 17 */ { SW_SHOW, FALSE, WS_VISIBLE, WmShow, + SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 18 */ { SW_SHOW, TRUE, WS_VISIBLE, WmEmptySeq, + SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 19 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinimize_1, + SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 20 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinMax_3, + SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 21 */ { SW_HIDE, TRUE, WS_MINIMIZE, WmHide_2, + SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 22 */ { SW_SHOWMINNOACTIVE, FALSE, WS_VISIBLE|WS_MINIMIZE, WmShowMinNoActivate, + SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, TRUE }, +/* 23 */ { SW_SHOWMINNOACTIVE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinMax_4, + SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 24 */ { SW_HIDE, TRUE, WS_MINIMIZE, WmHide_2, + SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 25 */ { SW_HIDE, FALSE, WS_MINIMIZE, WmEmptySeq, + SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 26 */ { SW_SHOWNA, FALSE, WS_VISIBLE|WS_MINIMIZE, WmShowNA_1, + SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 27 */ { SW_SHOWNA, TRUE, WS_VISIBLE|WS_MINIMIZE, WmShowNA_2, + SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 28 */ { SW_HIDE, TRUE, WS_MINIMIZE, WmHide_2, + SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 29 */ { SW_HIDE, FALSE, WS_MINIMIZE, WmEmptySeq, + SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 30 */ { SW_RESTORE, FALSE, WS_VISIBLE, WmRestore_1, + SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 31 */ { SW_RESTORE, TRUE, WS_VISIBLE, WmEmptySeq, + SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 32 */ { SW_HIDE, TRUE, 0, WmHide_3, + SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 33 */ { SW_HIDE, FALSE, 0, WmEmptySeq, + SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 34 */ { SW_NORMALNA, FALSE, 0, WmEmptySeq, /* what does this mean?! */ + SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 35 */ { SW_NORMALNA, FALSE, 0, WmEmptySeq, + SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 36 */ { SW_HIDE, FALSE, 0, WmEmptySeq, + SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 37 */ { SW_RESTORE, FALSE, WS_VISIBLE, WmRestore_2, + SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 38 */ { SW_RESTORE, TRUE, WS_VISIBLE, WmEmptySeq, + SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 39 */ { SW_SHOWNOACTIVATE, TRUE, WS_VISIBLE, WmEmptySeq, + SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 40 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinimize_2, + SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 41 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinMax_3, + SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 42 */ { SW_SHOWMAXIMIZED, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmShowMaximized_2, + SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, +/* 43 */ { SW_SHOWMAXIMIZED, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmMinMax_2, + SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, +/* 44 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinimize_1, + SW_SHOWMINIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, +/* 45 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinMax_3, + SW_SHOWMINIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, +/* 46 */ { SW_RESTORE, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmRestore_3, + SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, +/* 47 */ { SW_RESTORE, TRUE, WS_VISIBLE, WmRestore_4, + SW_SHOWNORMAL, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, +/* 48 */ { SW_SHOWMAXIMIZED, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmShowMaximized_3, + SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, +/* 49 */ { SW_SHOW, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmEmptySeq, + SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, +/* 50 */ { SW_SHOWNORMAL, TRUE, WS_VISIBLE, WmRestore_5, + SW_SHOWNORMAL, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, +/* 51 */ { SW_SHOWNORMAL, TRUE, WS_VISIBLE, WmRestore_5, + SW_SHOWNORMAL, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, +/* 52 */ { SW_HIDE, TRUE, 0, WmHide_1, + SW_SHOWNORMAL, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, +/* 53 */ { SW_HIDE, FALSE, 0, WmEmptySeq, + SW_SHOWNORMAL, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, +/* 54 */ { SW_MINIMIZE, FALSE, WS_VISIBLE|WS_MINIMIZE, WmMinimize_3, + SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 55 */ { SW_HIDE, TRUE, WS_MINIMIZE, WmHide_2, + SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 56 */ { SW_SHOWNOACTIVATE, FALSE, WS_VISIBLE, WmShowNoActivate_2, + SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 57 */ { SW_SHOW, TRUE, WS_VISIBLE, WmEmptySeq, + SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE } }; HWND hwnd; DWORD style; LPARAM ret; INT i; + WINDOWPLACEMENT wp; + RECT win_rc, work_rc = {0, 0, 0, 0}; #define WS_BASE (WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_POPUP|WS_CLIPSIBLINGS) hwnd = CreateWindowEx(0, "ShowWindowClass", NULL, WS_BASE, @@ -10709,6 +10901,52 @@ static void test_ShowWindow(void) flush_events(); flush_sequence(); + if (pGetMonitorInfoA && pMonitorFromPoint) + { + HMONITOR hmon; + MONITORINFO mi; + POINT pt = {0, 0}; + + SetLastError(0xdeadbeef); + hmon = pMonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY); + ok(hmon != 0, "MonitorFromPoint error %u\n", GetLastError()); + + mi.cbSize = sizeof(mi); + SetLastError(0xdeadbeef); + ret = pGetMonitorInfoA(hmon, &mi); + ok(ret, "GetMonitorInfo error %u\n", GetLastError()); + trace("monitor (%d,%d-%d,%d), work (%d,%d-%d,%d)\n", + mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom, + mi.rcWork.left, mi.rcWork.top, mi.rcWork.right, mi.rcWork.bottom); + work_rc = mi.rcWork; + } + + GetWindowRect(hwnd, &win_rc); + OffsetRect(&win_rc, -work_rc.left, -work_rc.top); + + wp.length = sizeof(wp); + SetLastError(0xdeadbeaf); + ret = GetWindowPlacement(hwnd, &wp); + ok(ret, "GetWindowPlacement error %u\n", GetLastError()); + ok(wp.flags == 0, "expected 0, got %#x\n", wp.flags); + ok(wp.showCmd == SW_SHOWNORMAL, "expected SW_SHOWNORMAL, got %d\n", wp.showCmd); + ok(wp.ptMinPosition.x == -1 && wp.ptMinPosition.y == -1, + "expected -1,-1 got %d,%d\n", wp.ptMinPosition.x, wp.ptMinPosition.y); + ok(wp.ptMaxPosition.x == -1 && wp.ptMaxPosition.y == -1, + "expected -1,-1 got %d,%d\n", wp.ptMaxPosition.x, wp.ptMaxPosition.y); + if (work_rc.left || work_rc.top) todo_wine /* FIXME: remove once Wine is fixed */ + ok(EqualRect(&win_rc, &wp.rcNormalPosition), + "expected %d,%d-%d,%d got %d,%d-%d,%d\n", + win_rc.left, win_rc.top, win_rc.right, win_rc.bottom, + wp.rcNormalPosition.left, wp.rcNormalPosition.top, + wp.rcNormalPosition.right, wp.rcNormalPosition.bottom); + else + ok(EqualRect(&win_rc, &wp.rcNormalPosition), + "expected %d,%d-%d,%d got %d,%d-%d,%d\n", + win_rc.left, win_rc.top, win_rc.right, win_rc.bottom, + wp.rcNormalPosition.left, wp.rcNormalPosition.top, + wp.rcNormalPosition.right, wp.rcNormalPosition.bottom); + for (i = 0; i < sizeof(sw)/sizeof(sw[0]); i++) { static const char * const sw_cmd_name[13] = @@ -10733,6 +10971,47 @@ static void test_ShowWindow(void) sprintf(comment, "%d: ShowWindow(%s)", i+1, sw_cmd_name[idx]); ok_sequence(sw[i].msg, comment, sw[i].todo_msg); + wp.length = sizeof(wp); + SetLastError(0xdeadbeaf); + ret = GetWindowPlacement(hwnd, &wp); + ok(ret, "GetWindowPlacement error %u\n", GetLastError()); + ok(wp.flags == sw[i].wp_flags, "expected %#x, got %#x\n", sw[i].wp_flags, wp.flags); + ok(wp.showCmd == sw[i].wp_cmd, "expected %d, got %d\n", sw[i].wp_cmd, wp.showCmd); + + /* NT moves the minimized window to -32000,-32000, win9x to 3000,3000 */ + if ((wp.ptMinPosition.x + work_rc.left == -32000 && wp.ptMinPosition.y + work_rc.top == -32000) || + (wp.ptMinPosition.x + work_rc.left == 3000 && wp.ptMinPosition.y + work_rc.top == 3000)) + { + ok((wp.ptMinPosition.x + work_rc.left == sw[i].wp_min.x && wp.ptMinPosition.y + work_rc.top == sw[i].wp_min.y) || + (wp.ptMinPosition.x + work_rc.left == 3000 && wp.ptMinPosition.y + work_rc.top == 3000), + "expected %d,%d got %d,%d\n", sw[i].wp_min.x, sw[i].wp_min.y, wp.ptMinPosition.x, wp.ptMinPosition.y); + } + else + { + if (wp.ptMinPosition.x != sw[i].wp_min.x || wp.ptMinPosition.y != sw[i].wp_min.y) + todo_wine + ok(wp.ptMinPosition.x == sw[i].wp_min.x && wp.ptMinPosition.y == sw[i].wp_min.y, + "expected %d,%d got %d,%d\n", sw[i].wp_min.x, sw[i].wp_min.y, wp.ptMinPosition.x, wp.ptMinPosition.y); + else + ok(wp.ptMinPosition.x == sw[i].wp_min.x && wp.ptMinPosition.y == sw[i].wp_min.y, + "expected %d,%d got %d,%d\n", sw[i].wp_min.x, sw[i].wp_min.y, wp.ptMinPosition.x, wp.ptMinPosition.y); + } + + if (wp.ptMaxPosition.x != sw[i].wp_max.x || wp.ptMaxPosition.y != sw[i].wp_max.y) + todo_wine + ok(wp.ptMaxPosition.x == sw[i].wp_max.x && wp.ptMaxPosition.y == sw[i].wp_max.y, + "expected %d,%d got %d,%d\n", sw[i].wp_max.x, sw[i].wp_max.y, wp.ptMaxPosition.x, wp.ptMaxPosition.y); + else + ok(wp.ptMaxPosition.x == sw[i].wp_max.x && wp.ptMaxPosition.y == sw[i].wp_max.y, + "expected %d,%d got %d,%d\n", sw[i].wp_max.x, sw[i].wp_max.y, wp.ptMaxPosition.x, wp.ptMaxPosition.y); + +if (0) /* FIXME: Wine behaves completely different here */ + ok(EqualRect(&win_rc, &wp.rcNormalPosition), + "expected %d,%d-%d,%d got %d,%d-%d,%d\n", + win_rc.left, win_rc.top, win_rc.right, win_rc.bottom, + wp.rcNormalPosition.left, wp.rcNormalPosition.top, + wp.rcNormalPosition.right, wp.rcNormalPosition.bottom); + flush_events(); flush_sequence(); } @@ -11419,6 +11698,7 @@ static void test_dbcs_wm_char(void) ok( !PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ), "got message %x\n", msg.message ); DestroyWindow(hwnd); + DestroyWindow(hwnd2); } #define ID_LISTBOX 0x000f @@ -11746,6 +12026,33 @@ static const struct message wm_popup_menu_3[] = { 0 } }; +static const struct message wm_single_menu_item[] = +{ + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, + { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'Q', 0x20000001 }, + { WM_SYSKEYDOWN, sent|wparam|lparam, 'Q', 0x20000001 }, + { WM_SYSCHAR, sent|wparam|lparam, 'q', 0x20000001 }, + { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_KEYMENU, 'q' }, + { WM_ENTERMENULOOP, sent|wparam|lparam, 0, 0 }, + { WM_INITMENU, sent|lparam, 0, 0 }, + { WM_MENUSELECT, sent|wparam|optional, MAKEWPARAM(300,MF_HILITE) }, + { WM_MENUSELECT, sent|wparam|lparam, MAKEWPARAM(0,0xffff), 0 }, + { WM_EXITMENULOOP, sent|wparam|lparam, 0, 0 }, + { WM_MENUCOMMAND, sent }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'Q', 0xe0000001 }, + { WM_SYSKEYUP, sent|wparam|lparam, 'Q', 0xe0000001 }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, + { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 }, + + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_ESCAPE, 1 }, + { WM_KEYDOWN, sent|wparam|lparam, VK_ESCAPE, 1 }, + { WM_CHAR, sent|wparam|lparam, VK_ESCAPE, 0x00000001 }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_ESCAPE, 0xc0000001 }, + { WM_KEYUP, sent|wparam|lparam, VK_ESCAPE, 0xc0000001 }, + { 0 } +}; + static LRESULT WINAPI parent_menu_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp) { if (message == WM_ENTERIDLE || @@ -11904,6 +12211,21 @@ static void test_menu_messages(void) } ok_sequence(wm_popup_menu_2, "submenu of a popup menu command", FALSE); + trace("testing single menu item command\n"); + flush_sequence(); + keybd_event(VK_MENU, 0, 0, 0); + keybd_event('Q', 0, 0, 0); + keybd_event('Q', 0, KEYEVENTF_KEYUP, 0); + keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); + keybd_event(VK_ESCAPE, 0, 0, 0); + keybd_event(VK_ESCAPE, 0, KEYEVENTF_KEYUP, 0); + while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + ok_sequence(wm_single_menu_item, "single menu item command", FALSE); + set_menu_style(hmenu, 0); style = get_menu_style(hmenu); ok(style == 0, "expected 0, got %u\n", style); @@ -12501,11 +12823,611 @@ static void test_WaitForInputIdle( char *argv0 ) CloseHandle( thread ); } +static const struct message WmSetParentSeq_1[] = { + { WM_SHOWWINDOW, sent|wparam, 0 }, + { EVENT_OBJECT_PARENTCHANGE, winevent_hook|wparam|lparam, 0, 0 }, + { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE }, + { WM_CHILDACTIVATE, sent }, + { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOREDRAW|SWP_NOCLIENTSIZE }, + { WM_MOVE, sent|defwinproc|wparam, 0 }, + { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, + { WM_SHOWWINDOW, sent|wparam, 1 }, + { 0 } +}; + +static const struct message WmSetParentSeq_2[] = { + { WM_SHOWWINDOW, sent|wparam, 0 }, + { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE }, + { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, + { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, + { HCBT_SETFOCUS, hook|optional }, + { WM_NCACTIVATE, sent|wparam|optional, 0 }, + { WM_ACTIVATE, sent|wparam|optional, 0 }, + { WM_ACTIVATEAPP, sent|wparam|optional, 0 }, + { WM_KILLFOCUS, sent|wparam, 0 }, + { EVENT_OBJECT_PARENTCHANGE, winevent_hook|wparam|lparam, 0, 0 }, + { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE }, + { HCBT_ACTIVATE, hook|optional }, + { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, + { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, + { WM_NCACTIVATE, sent|wparam|optional, 1 }, + { WM_ACTIVATE, sent|wparam|optional, 1 }, + { HCBT_SETFOCUS, hook|optional }, + { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, + { WM_SETFOCUS, sent|optional|defwinproc }, + { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOREDRAW|SWP_NOSIZE|SWP_NOCLIENTSIZE }, + { WM_MOVE, sent|defwinproc|wparam, 0 }, + { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, + { WM_SHOWWINDOW, sent|wparam, 1 }, + { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, + { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, + { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, + { 0 } +}; + + +static void test_SetParent(void) +{ + HWND parent1, parent2, child, popup; + RECT rc, rc_old; + + parent1 = CreateWindowEx(0, "TestParentClass", NULL, WS_OVERLAPPEDWINDOW, + 100, 100, 200, 200, 0, 0, 0, NULL); + ok(parent1 != 0, "Failed to create parent1 window\n"); + + parent2 = CreateWindowEx(0, "TestParentClass", NULL, WS_OVERLAPPEDWINDOW, + 400, 100, 200, 200, 0, 0, 0, NULL); + ok(parent2 != 0, "Failed to create parent2 window\n"); + + /* WS_CHILD window */ + child = CreateWindowEx(0, "TestWindowClass", NULL, WS_CHILD | WS_VISIBLE, + 10, 10, 150, 150, parent1, 0, 0, NULL); + ok(child != 0, "Failed to create child window\n"); + + GetWindowRect(parent1, &rc); + trace("parent1 (%d,%d)-(%d,%d)\n", rc.left, rc.top, rc.right, rc.bottom); + GetWindowRect(child, &rc_old); + MapWindowPoints(0, parent1, (POINT *)&rc_old, 2); + trace("child (%d,%d)-(%d,%d)\n", rc_old.left, rc_old.top, rc_old.right, rc_old.bottom); + + flush_sequence(); + + SetParent(child, parent2); + flush_events(); + ok_sequence(WmSetParentSeq_1, "SetParent() visible WS_CHILD", TRUE); + + ok(GetWindowLongA(child, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); + ok(!IsWindowVisible(child), "IsWindowVisible() should return FALSE\n"); + + GetWindowRect(parent2, &rc); + trace("parent2 (%d,%d)-(%d,%d)\n", rc.left, rc.top, rc.right, rc.bottom); + GetWindowRect(child, &rc); + MapWindowPoints(0, parent2, (POINT *)&rc, 2); + trace("child (%d,%d)-(%d,%d)\n", rc.left, rc.top, rc.right, rc.bottom); + + ok(EqualRect(&rc_old, &rc), "rects do not match (%d,%d-%d,%d) / (%d,%d-%d,%d)\n", + rc_old.left, rc_old.top, rc_old.right, rc_old.bottom, + rc.left, rc.top, rc.right, rc.bottom ); + + /* WS_POPUP window */ + popup = CreateWindowEx(0, "TestWindowClass", NULL, WS_POPUP | WS_VISIBLE, + 20, 20, 100, 100, 0, 0, 0, NULL); + ok(popup != 0, "Failed to create popup window\n"); + + GetWindowRect(popup, &rc_old); + trace("popup (%d,%d)-(%d,%d)\n", rc_old.left, rc_old.top, rc_old.right, rc_old.bottom); + + flush_sequence(); + + SetParent(popup, child); + flush_events(); + ok_sequence(WmSetParentSeq_2, "SetParent() visible WS_POPUP", TRUE); + + ok(GetWindowLongA(popup, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); + ok(!IsWindowVisible(popup), "IsWindowVisible() should return FALSE\n"); + + GetWindowRect(child, &rc); + trace("parent2 (%d,%d)-(%d,%d)\n", rc.left, rc.top, rc.right, rc.bottom); + GetWindowRect(popup, &rc); + MapWindowPoints(0, child, (POINT *)&rc, 2); + trace("popup (%d,%d)-(%d,%d)\n", rc.left, rc.top, rc.right, rc.bottom); + + ok(EqualRect(&rc_old, &rc), "rects do not match (%d,%d-%d,%d) / (%d,%d-%d,%d)\n", + rc_old.left, rc_old.top, rc_old.right, rc_old.bottom, + rc.left, rc.top, rc.right, rc.bottom ); + + DestroyWindow(popup); + DestroyWindow(child); + DestroyWindow(parent1); + DestroyWindow(parent2); + + flush_sequence(); +} + +static const struct message WmKeyReleaseOnly[] = { + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 0x41, 0x80000001 }, + { WM_KEYUP, sent|wparam|lparam, 0x41, 0x80000001 }, + { 0 } +}; +static const struct message WmKeyPressNormal[] = { + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 0x41, 0x1 }, + { WM_KEYDOWN, sent|wparam|lparam, 0x41, 0x1 }, + { 0 } +}; +static const struct message WmKeyPressRepeat[] = { + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 0x41, 0x40000001 }, + { WM_KEYDOWN, sent|wparam|lparam, 0x41, 0x40000001 }, + { 0 } +}; +static const struct message WmKeyReleaseNormal[] = { + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 0x41, 0xc0000001 }, + { WM_KEYUP, sent|wparam|lparam, 0x41, 0xc0000001 }, + { 0 } +}; + +static void test_keyflags(void) +{ + HWND test_window; + SHORT key_state; + BYTE keyboard_state[256]; + MSG msg; + + test_window = CreateWindowEx(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE, + 100, 100, 200, 200, 0, 0, 0, NULL); + + flush_sequence(); + + /* keyup without a keydown */ + keybd_event(0x41, 0, KEYEVENTF_KEYUP, 0); + while (PeekMessage(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) + DispatchMessage(&msg); + ok_sequence(WmKeyReleaseOnly, "key release only", TRUE); + + key_state = GetAsyncKeyState(0x41); + ok((key_state & 0x8000) == 0, "unexpected key state %x\n", key_state); + + key_state = GetKeyState(0x41); + ok((key_state & 0x8000) == 0, "unexpected key state %x\n", key_state); + + /* keydown */ + keybd_event(0x41, 0, 0, 0); + while (PeekMessage(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) + DispatchMessage(&msg); + ok_sequence(WmKeyPressNormal, "key press only", FALSE); + + key_state = GetAsyncKeyState(0x41); + ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state); + + key_state = GetKeyState(0x41); + ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state); + + /* keydown repeat */ + keybd_event(0x41, 0, 0, 0); + while (PeekMessage(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) + DispatchMessage(&msg); + ok_sequence(WmKeyPressRepeat, "key press repeat", FALSE); + + key_state = GetAsyncKeyState(0x41); + ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state); + + key_state = GetKeyState(0x41); + ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state); + + /* keyup */ + keybd_event(0x41, 0, KEYEVENTF_KEYUP, 0); + while (PeekMessage(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) + DispatchMessage(&msg); + ok_sequence(WmKeyReleaseNormal, "key release repeat", FALSE); + + key_state = GetAsyncKeyState(0x41); + ok((key_state & 0x8000) == 0, "unexpected key state %x\n", key_state); + + key_state = GetKeyState(0x41); + ok((key_state & 0x8000) == 0, "unexpected key state %x\n", key_state); + + /* set the key state in this thread */ + GetKeyboardState(keyboard_state); + keyboard_state[0x41] = 0x80; + SetKeyboardState(keyboard_state); + + key_state = GetAsyncKeyState(0x41); + ok((key_state & 0x8000) == 0, "unexpected key state %x\n", key_state); + + /* keydown */ + keybd_event(0x41, 0, 0, 0); + while (PeekMessage(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) + DispatchMessage(&msg); + ok_sequence(WmKeyPressRepeat, "key press after setkeyboardstate", TRUE); + + key_state = GetAsyncKeyState(0x41); + ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state); + + key_state = GetKeyState(0x41); + ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state); + + /* clear the key state in this thread */ + GetKeyboardState(keyboard_state); + keyboard_state[0x41] = 0; + SetKeyboardState(keyboard_state); + + key_state = GetAsyncKeyState(0x41); + ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state); + + /* keyup */ + keybd_event(0x41, 0, KEYEVENTF_KEYUP, 0); + while (PeekMessage(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) + DispatchMessage(&msg); + ok_sequence(WmKeyReleaseOnly, "key release after setkeyboardstate", TRUE); + + key_state = GetAsyncKeyState(0x41); + ok((key_state & 0x8000) == 0, "unexpected key state %x\n", key_state); + + key_state = GetKeyState(0x41); + ok((key_state & 0x8000) == 0, "unexpected key state %x\n", key_state); + + DestroyWindow(test_window); + flush_sequence(); +} + +static const struct message WmHotkeyPressLWIN[] = { + { WM_KEYDOWN, kbd_hook|wparam|lparam, VK_LWIN, LLKHF_INJECTED }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_LWIN, 1 }, + { WM_KEYDOWN, sent|wparam|lparam, VK_LWIN, 1 }, + { 0 } +}; +static const struct message WmHotkeyPress[] = { + { WM_KEYDOWN, kbd_hook|lparam, 0, LLKHF_INJECTED }, + { WM_HOTKEY, sent|wparam, 5 }, + { 0 } +}; +static const struct message WmHotkeyRelease[] = { + { WM_KEYUP, kbd_hook|lparam, 0, LLKHF_INJECTED|LLKHF_UP }, + { HCBT_KEYSKIPPED, hook|lparam|optional, 0, 0x80000001 }, + { WM_KEYUP, sent|lparam, 0, 0x80000001 }, + { 0 } +}; +static const struct message WmHotkeyReleaseLWIN[] = { + { WM_KEYUP, kbd_hook|wparam|lparam, VK_LWIN, LLKHF_INJECTED|LLKHF_UP }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_LWIN, 0xc0000001 }, + { WM_KEYUP, sent|wparam|lparam, VK_LWIN, 0xc0000001 }, + { 0 } +}; +static const struct message WmHotkeyCombined[] = { + { WM_KEYDOWN, kbd_hook|wparam|lparam, VK_LWIN, LLKHF_INJECTED }, + { WM_KEYDOWN, kbd_hook|lparam, 0, LLKHF_INJECTED }, + { WM_KEYUP, kbd_hook|lparam, 0, LLKHF_INJECTED|LLKHF_UP }, + { WM_KEYUP, kbd_hook|wparam|lparam, VK_LWIN, LLKHF_INJECTED|LLKHF_UP }, + { WM_APP, sent, 0, 0 }, + { WM_HOTKEY, sent|wparam, 5 }, + { WM_APP+1, sent, 0, 0 }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_LWIN, 1 }, + { WM_KEYDOWN, sent|wparam|lparam, VK_LWIN, 1 }, + { HCBT_KEYSKIPPED, hook|optional, 0, 0x80000001 }, + { WM_KEYUP, sent, 0, 0x80000001 }, /* lparam not checked so the sequence isn't a todo */ + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_LWIN, 0xc0000001 }, + { WM_KEYUP, sent|wparam|lparam, VK_LWIN, 0xc0000001 }, + { 0 } +}; +static const struct message WmHotkeyPrevious[] = { + { WM_KEYDOWN, kbd_hook|wparam|lparam, VK_LWIN, LLKHF_INJECTED }, + { WM_KEYDOWN, kbd_hook|lparam, 0, LLKHF_INJECTED }, + { WM_KEYUP, kbd_hook|lparam, 0, LLKHF_INJECTED|LLKHF_UP }, + { WM_KEYUP, kbd_hook|wparam|lparam, VK_LWIN, LLKHF_INJECTED|LLKHF_UP }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_LWIN, 1 }, + { WM_KEYDOWN, sent|wparam|lparam, VK_LWIN, 1 }, + { HCBT_KEYSKIPPED, hook|lparam|optional, 0, 1 }, + { WM_KEYDOWN, sent|lparam, 0, 1 }, + { HCBT_KEYSKIPPED, hook|optional|lparam, 0, 0xc0000001 }, + { WM_KEYUP, sent|lparam, 0, 0xc0000001 }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_LWIN, 0xc0000001 }, + { WM_KEYUP, sent|wparam|lparam, VK_LWIN, 0xc0000001 }, + { 0 } +}; +static const struct message WmHotkeyNew[] = { + { WM_KEYDOWN, kbd_hook|lparam, 0, LLKHF_INJECTED }, + { WM_KEYUP, kbd_hook|lparam, 0, LLKHF_INJECTED|LLKHF_UP }, + { WM_HOTKEY, sent|wparam, 5 }, + { HCBT_KEYSKIPPED, hook|optional, 0, 0x80000001 }, + { WM_KEYUP, sent, 0, 0x80000001 }, /* lparam not checked so the sequence isn't a todo */ + { 0 } +}; + +static int hotkey_letter; + +static LRESULT CALLBACK KeyboardHookProc(int nCode, WPARAM wParam, LPARAM lParam) +{ + struct recvd_message msg; + + if (nCode == HC_ACTION) + { + KBDLLHOOKSTRUCT *kdbhookstruct = (KBDLLHOOKSTRUCT*)lParam; + + msg.hwnd = 0; + msg.message = wParam; + msg.flags = kbd_hook|wparam|lparam; + msg.wParam = kdbhookstruct->vkCode; + msg.lParam = kdbhookstruct->flags; + msg.descr = "KeyboardHookProc"; + add_message(&msg); + + if (wParam == WM_KEYUP || wParam == WM_KEYDOWN) + { + ok(kdbhookstruct->vkCode == VK_LWIN || kdbhookstruct->vkCode == hotkey_letter, + "unexpected keycode %x\n", kdbhookstruct->vkCode); + } + } + + return CallNextHookEx(hKBD_hook, nCode, wParam, lParam); +} + +static void test_hotkey(void) +{ + HWND test_window, taskbar_window; + BOOL ret; + MSG msg; + DWORD queue_status; + SHORT key_state; + + SetLastError(0xdeadbeef); + ret = UnregisterHotKey(NULL, 0); + ok(ret == FALSE, "expected FALSE, got %i\n", ret); + ok(GetLastError() == ERROR_HOTKEY_NOT_REGISTERED || broken(GetLastError() == 0xdeadbeef), + "unexpected error %d\n", GetLastError()); + + if (ret == TRUE) + { + skip("hotkeys not supported\n"); + return; + } + + test_window = CreateWindowEx(0, "HotkeyWindowClass", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE, + 100, 100, 200, 200, 0, 0, 0, NULL); + + flush_sequence(); + + SetLastError(0xdeadbeef); + ret = UnregisterHotKey(test_window, 0); + ok(ret == FALSE, "expected FALSE, got %i\n", ret); + ok(GetLastError() == ERROR_HOTKEY_NOT_REGISTERED || broken(GetLastError() == 0xdeadbeef), + "unexpected error %d\n", GetLastError()); + + /* Search for a Windows Key + letter combination that hasn't been registered */ + for (hotkey_letter = 0x41; hotkey_letter <= 0x51; hotkey_letter ++) + { + SetLastError(0xdeadbeef); + ret = RegisterHotKey(test_window, 5, MOD_WIN, hotkey_letter); + + if (ret == TRUE) + { + break; + } + else + { + ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED || broken(GetLastError() == 0xdeadbeef), + "unexpected error %d\n", GetLastError()); + } + } + + if (hotkey_letter == 0x52) + { + ok(0, "Couldn't find any free Windows Key + letter combination\n"); + goto end; + } + + hKBD_hook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHookProc, GetModuleHandle(NULL), 0); + if (!hKBD_hook) win_skip("WH_KEYBOARD_LL is not supported\n"); + + /* Same key combination, different id */ + SetLastError(0xdeadbeef); + ret = RegisterHotKey(test_window, 4, MOD_WIN, hotkey_letter); + ok(ret == FALSE, "expected FALSE, got %i\n", ret); + ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED || broken(GetLastError() == 0xdeadbeef), + "unexpected error %d\n", GetLastError()); + + /* Same key combination, different window */ + SetLastError(0xdeadbeef); + ret = RegisterHotKey(NULL, 5, MOD_WIN, hotkey_letter); + ok(ret == FALSE, "expected FALSE, got %i\n", ret); + ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED || broken(GetLastError() == 0xdeadbeef), + "unexpected error %d\n", GetLastError()); + + /* Register the same hotkey twice */ + SetLastError(0xdeadbeef); + ret = RegisterHotKey(test_window, 5, MOD_WIN, hotkey_letter); + ok(ret == FALSE, "expected FALSE, got %i\n", ret); + ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED || broken(GetLastError() == 0xdeadbeef), + "unexpected error %d\n", GetLastError()); + + /* Window on another thread */ + taskbar_window = FindWindowA("Shell_TrayWnd", NULL); + if (!taskbar_window) + { + skip("no taskbar?\n"); + } + else + { + SetLastError(0xdeadbeef); + ret = RegisterHotKey(taskbar_window, 5, 0, hotkey_letter); + ok(ret == FALSE, "expected FALSE, got %i\n", ret); + ok(GetLastError() == ERROR_WINDOW_OF_OTHER_THREAD || broken(GetLastError() == 0xdeadbeef), + "unexpected error %d\n", GetLastError()); + } + + /* Inject the appropriate key sequence */ + keybd_event(VK_LWIN, 0, 0, 0); + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + DispatchMessage(&msg); + ok_sequence(WmHotkeyPressLWIN, "window hotkey press LWIN", FALSE); + + keybd_event(hotkey_letter, 0, 0, 0); + queue_status = GetQueueStatus(QS_HOTKEY); + ok((queue_status & (QS_HOTKEY << 16)) == QS_HOTKEY << 16, "expected QS_HOTKEY << 16 set, got %x\n", queue_status); + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + if (msg.message == WM_HOTKEY) + { + ok(msg.hwnd == test_window, "unexpected hwnd %p\n", msg.hwnd); + ok(msg.lParam == MAKELPARAM(MOD_WIN, hotkey_letter), "unexpected WM_HOTKEY lparam %lx\n", msg.lParam); + } + DispatchMessage(&msg); + } + ok_sequence(WmHotkeyPress, "window hotkey press", FALSE); + + queue_status = GetQueueStatus(QS_HOTKEY); + ok((queue_status & (QS_HOTKEY << 16)) == 0, "expected QS_HOTKEY << 16 cleared, got %x\n", queue_status); + + key_state = GetAsyncKeyState(hotkey_letter); + ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state); + + keybd_event(hotkey_letter, 0, KEYEVENTF_KEYUP, 0); + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + DispatchMessage(&msg); + ok_sequence(WmHotkeyRelease, "window hotkey release", TRUE); + + keybd_event(VK_LWIN, 0, KEYEVENTF_KEYUP, 0); + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + DispatchMessage(&msg); + ok_sequence(WmHotkeyReleaseLWIN, "window hotkey release LWIN", FALSE); + + /* normal posted WM_HOTKEY messages set QS_HOTKEY */ + PostMessage(test_window, WM_HOTKEY, 0, 0); + queue_status = GetQueueStatus(QS_HOTKEY); + ok((queue_status & (QS_HOTKEY << 16)) == QS_HOTKEY << 16, "expected QS_HOTKEY << 16 set, got %x\n", queue_status); + queue_status = GetQueueStatus(QS_POSTMESSAGE); + ok((queue_status & (QS_POSTMESSAGE << 16)) == QS_POSTMESSAGE << 16, "expected QS_POSTMESSAGE << 16 set, got %x\n", queue_status); + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + DispatchMessage(&msg); + flush_sequence(); + + /* Send and process all messages at once */ + PostMessage(test_window, WM_APP, 0, 0); + keybd_event(VK_LWIN, 0, 0, 0); + keybd_event(hotkey_letter, 0, 0, 0); + keybd_event(hotkey_letter, 0, KEYEVENTF_KEYUP, 0); + keybd_event(VK_LWIN, 0, KEYEVENTF_KEYUP, 0); + + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + if (msg.message == WM_HOTKEY) + { + ok(msg.hwnd == test_window, "unexpected hwnd %p\n", msg.hwnd); + ok(msg.lParam == MAKELPARAM(MOD_WIN, hotkey_letter), "unexpected WM_HOTKEY lparam %lx\n", msg.lParam); + } + DispatchMessage(&msg); + } + ok_sequence(WmHotkeyCombined, "window hotkey combined", FALSE); + + /* Register same hwnd/id with different key combination */ + ret = RegisterHotKey(test_window, 5, 0, hotkey_letter); + ok(ret == TRUE, "expected TRUE, got %i, err=%d\n", ret, GetLastError()); + + /* Previous key combination does not work */ + keybd_event(VK_LWIN, 0, 0, 0); + keybd_event(hotkey_letter, 0, 0, 0); + keybd_event(hotkey_letter, 0, KEYEVENTF_KEYUP, 0); + keybd_event(VK_LWIN, 0, KEYEVENTF_KEYUP, 0); + + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + DispatchMessage(&msg); + ok_sequence(WmHotkeyPrevious, "window hotkey previous", FALSE); + + /* New key combination works */ + keybd_event(hotkey_letter, 0, 0, 0); + keybd_event(hotkey_letter, 0, KEYEVENTF_KEYUP, 0); + + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + if (msg.message == WM_HOTKEY) + { + ok(msg.hwnd == test_window, "unexpected hwnd %p\n", msg.hwnd); + ok(msg.lParam == MAKELPARAM(0, hotkey_letter), "unexpected WM_HOTKEY lparam %lx\n", msg.lParam); + } + DispatchMessage(&msg); + } + ok_sequence(WmHotkeyNew, "window hotkey new", FALSE); + + /* Unregister hotkey properly */ + ret = UnregisterHotKey(test_window, 5); + ok(ret == TRUE, "expected TRUE, got %i, err=%d\n", ret, GetLastError()); + + /* Unregister hotkey again */ + SetLastError(0xdeadbeef); + ret = UnregisterHotKey(test_window, 5); + ok(ret == FALSE, "expected FALSE, got %i\n", ret); + ok(GetLastError() == ERROR_HOTKEY_NOT_REGISTERED || broken(GetLastError() == 0xdeadbeef), + "unexpected error %d\n", GetLastError()); + + /* Register thread hotkey */ + ret = RegisterHotKey(NULL, 5, MOD_WIN, hotkey_letter); + ok(ret == TRUE, "expected TRUE, got %i, err=%d\n", ret, GetLastError()); + + /* Inject the appropriate key sequence */ + keybd_event(VK_LWIN, 0, 0, 0); + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + ok(msg.hwnd != NULL, "unexpected thread message %x\n", msg.message); + DispatchMessage(&msg); + } + ok_sequence(WmHotkeyPressLWIN, "thread hotkey press LWIN", FALSE); + + keybd_event(hotkey_letter, 0, 0, 0); + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + if (msg.message == WM_HOTKEY) + { + struct recvd_message message; + ok(msg.hwnd == NULL, "unexpected hwnd %p\n", msg.hwnd); + ok(msg.lParam == MAKELPARAM(MOD_WIN, hotkey_letter), "unexpected WM_HOTKEY lparam %lx\n", msg.lParam); + message.message = msg.message; + message.flags = sent|wparam|lparam; + message.wParam = msg.wParam; + message.lParam = msg.lParam; + message.descr = "test_hotkey thread message"; + add_message(&message); + } + else + ok(msg.hwnd != NULL, "unexpected thread message %x\n", msg.message); + DispatchMessage(&msg); + } + ok_sequence(WmHotkeyPress, "thread hotkey press", FALSE); + + keybd_event(hotkey_letter, 0, KEYEVENTF_KEYUP, 0); + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + ok(msg.hwnd != NULL, "unexpected thread message %x\n", msg.message); + DispatchMessage(&msg); + } + ok_sequence(WmHotkeyRelease, "thread hotkey release", TRUE); + + keybd_event(VK_LWIN, 0, KEYEVENTF_KEYUP, 0); + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + ok(msg.hwnd != NULL, "unexpected thread message %x\n", msg.message); + DispatchMessage(&msg); + } + ok_sequence(WmHotkeyReleaseLWIN, "thread hotkey release LWIN", FALSE); + + /* Unregister thread hotkey */ + ret = UnregisterHotKey(NULL, 5); + ok(ret == TRUE, "expected TRUE, got %i, err=%d\n", ret, GetLastError()); + + if (hKBD_hook) UnhookWindowsHookEx(hKBD_hook); + hKBD_hook = NULL; + +end: + UnregisterHotKey(NULL, 5); + UnregisterHotKey(test_window, 5); + DestroyWindow(test_window); + flush_sequence(); +} + START_TEST(msg) { char **test_argv; BOOL ret; BOOL (WINAPI *pIsWinEventHookInstalled)(DWORD)= 0;/*GetProcAddress(user32, "IsWinEventHookInstalled");*/ + HMODULE hModuleImm32; + BOOL (WINAPI *pImmDisableIME)(DWORD); int argc = winetest_get_mainargs( &test_argv ); if (argc >= 3) @@ -12519,6 +13441,15 @@ START_TEST(msg) init_procs(); + hModuleImm32 = LoadLibrary("imm32.dll"); + if (hModuleImm32) { + pImmDisableIME = (void *)GetProcAddress(hModuleImm32, "ImmDisableIME"); + if (pImmDisableIME) + pImmDisableIME(0); + } + pImmDisableIME = NULL; + FreeLibrary(hModuleImm32); + if (!RegisterWindowClasses()) assert(0); if (pSetWinEventHook) @@ -12553,6 +13484,7 @@ START_TEST(msg) hEvent_hook = 0; #endif + test_SetParent(); test_PostMessage(); test_ShowWindow(); test_PeekMessage(); @@ -12597,6 +13529,8 @@ START_TEST(msg) test_paintingloop(); test_defwinproc(); test_clipboard_viewers(); + test_keyflags(); + test_hotkey(); /* keep it the last test, under Windows it tends to break the tests * which rely on active/foreground windows being correct. */ diff --git a/winetests/user32/resource.c b/winetests/user32/resource.c index c64aff0a60e..5bc2d7a34d0 100755 --- a/winetests/user32/resource.c +++ b/winetests/user32/resource.c @@ -180,12 +180,10 @@ static void test_accel1(void) ok( hAccel != NULL, "create accelerator table\n"); r = CopyAcceleratorTable( hAccel, NULL, 0 ); - ok( r == n || broken(r == 2), /* win9x */ - "two entries in table %u/%u\n", r, n); + ok( r == n, "two entries in table %u/%u\n", r, n); r = CopyAcceleratorTable( hAccel, &ac[0], n ); - ok( r == n || broken(r == 2), /* win9x */ - "still should be two entries in table %u/%u\n", r, n); + ok( r == n, "still should be two entries in table %u/%u\n", r, n); n=0; ok( ac[n].cmd == 1000, "cmd 0 not preserved got %x\n", ac[n].cmd); @@ -262,11 +260,11 @@ static void test_accel2(void) hac = CreateAcceleratorTable( &ac[0], 2); ok( hac != NULL , "fail\n"); res = CopyAcceleratorTable( hac, NULL, 100 ); - ok( res == 2 || broken(res == 0), /* win9x */ "copy null failed %d\n", res); + ok( res == 2, "copy null failed %d\n", res); res = CopyAcceleratorTable( hac, NULL, 0 ); ok( res == 2, "copy null failed %d\n", res); res = CopyAcceleratorTable( hac, NULL, 1 ); - ok( res == 2 || broken(res == 0), /* win9x */ "copy null failed %d\n", res); + ok( res == 2, "copy null failed %d\n", res); ok( 1 == CopyAcceleratorTable( hac, out, 1 ), "copy 1 failed\n"); ok( 2 == CopyAcceleratorTable( hac, out, 2 ), "copy 2 failed\n"); ok( DestroyAcceleratorTable( hac ), "destroy failed\n"); @@ -318,7 +316,7 @@ static void test_accel2(void) hac = CreateAcceleratorTable( &ac[0], 2); ok( hac != NULL , "fail\n"); res = CopyAcceleratorTable( hac, out, 2 ); - ok( res == 2 || broken(res == 1), /* win9x */ "copy 2 failed %d\n", res); + ok( res == 2, "copy 2 failed %d\n", res); /* ok( memcmp( ac, out, sizeof ac ), "tables not different\n"); */ ok( out[0].cmd == ac[0].cmd, "cmd modified\n"); ok( out[0].fVirt == (ac[0].fVirt&0x7f), "fVirt not modified\n"); diff --git a/winetests/user32/scroll.c b/winetests/user32/scroll.c index e3f6938129c..e4bfdb15de5 100644 --- a/winetests/user32/scroll.c +++ b/winetests/user32/scroll.c @@ -259,7 +259,7 @@ todo_wine "Scroll bar range is %d,%d. Expected 0,100. Style %08x\n", min, max, style); /* test GetScrollInfo, vist for vertical SB */ ret = GetScrollInfo( hwnd, SB_VERT, &si); - /* should fail if no H orV scroll bar styles are present. Succeed otherwise */ + /* should fail if no H or V scroll bar styles are present. Succeed otherwise */ if( !( style & ( WS_VSCROLL | WS_HSCROLL))) ok( !ret, "GetScrollInfo succeeded unexpectedly. Style is %08x\n", style); else @@ -269,7 +269,7 @@ todo_wine "GetScrollInfo failed unexpectedly. Style is %08x\n", style); /* Same for Horizontal SB */ ret = GetScrollInfo( hwnd, SB_HORZ, &si); - /* should fail if no H orV scroll bar styles are present. Succeed otherwise */ + /* should fail if no H or V scroll bar styles are present. Succeed otherwise */ if( !( style & ( WS_VSCROLL | WS_HSCROLL))) ok( !ret, "GetScrollInfo succeeded unexpectedly. Style is %08x\n", style); else @@ -316,7 +316,7 @@ todo_wine hwnd = CreateWindowExA( 0, "static", "", WS_POPUP | style, 0, 0, 10, 10, 0, 0, 0, NULL); assert( hwnd != 0); - /* Set Horizonta Scroll range to something that could be the default value it + /* Set Horizontal Scroll range to something that could be the default value it * already has */; ret = SetScrollRange( hwnd, SB_HORZ, 0, 100, FALSE); ok( ret, "SetScrollRange failed.\n"); diff --git a/winetests/user32/static.c b/winetests/user32/static.c index d04f725138a..b7613563104 100644 --- a/winetests/user32/static.c +++ b/winetests/user32/static.c @@ -95,9 +95,7 @@ static void test_updates(int style, int flags) if (flags & TODO_COUNT) todo_wine { expect_eq(g_nReceivedColorStatic, exp, int, "%d"); } else if ((style & SS_TYPEMASK) == SS_ICON || (style & SS_TYPEMASK) == SS_BITMAP) - ok( g_nReceivedColorStatic == exp || - broken(g_nReceivedColorStatic == 0), /* win9x */ - "expected %u got %u\n", exp, g_nReceivedColorStatic ); + ok( g_nReceivedColorStatic == exp, "expected %u got %u\n", exp, g_nReceivedColorStatic ); else expect_eq(g_nReceivedColorStatic, exp, int, "%d"); DestroyWindow(hStatic); diff --git a/winetests/user32/sysparams.c b/winetests/user32/sysparams.c index ba1c8026a89..1de3da0300f 100755 --- a/winetests/user32/sysparams.c +++ b/winetests/user32/sysparams.c @@ -24,7 +24,7 @@ #undef _WIN32_WINNT #define _WIN32_WINNT 0x0600 /* For SPI_GETMOUSEHOVERWIDTH and more */ -#define _WIN32_IE 0x0700 +//#define _WIN32_IE 0x0700 #include "wine/test.h" #include "windef.h" @@ -2463,7 +2463,7 @@ static DWORD WINAPI SysParamsThreadFunc( LPVOID lpParam ) * not all metrics are properly restored. Problems are * SM_CXMAXTRACK, SM_CYMAXTRACK * Fortunately setting the Non-Client metrics like in - * test_SPI_SETNONCLIENTMETRICS will corect this. That is why + * test_SPI_SETNONCLIENTMETRICS will correct this. That is why * we do the DISPLAY change now... */ test_WM_DISPLAYCHANGE(); test_SPI_SETNONCLIENTMETRICS(); /* 42 */ diff --git a/winetests/user32/text.c b/winetests/user32/text.c index 88ea6b566c0..1874b1572e0 100755 --- a/winetests/user32/text.c +++ b/winetests/user32/text.c @@ -114,13 +114,7 @@ static void test_DrawTextCalcRect(void) heightcheck = textheight = DrawTextExA(hdc, text, 0, &rect, DT_CALCRECT, NULL ); ok( !EMPTY(rect) && !MODIFIED(rect), "rectangle should NOT be empty got %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom ); - if (textheight != 0) /* Windows 98 */ - { - win_skip("XP conformity failed, skipping XP tests. Probably win9x\n"); - conform_xp = FALSE; - } - else - ok(textheight==0,"Got textheight from DrawTextExA\n"); + ok(textheight==0,"Got textheight from DrawTextExA\n"); SetRect( &rect, 10,10, 100, 100); textheight = DrawTextA(hdc, text, 0, &rect, DT_CALCRECT); @@ -617,6 +611,9 @@ static void test_TabbedText(void) ret = GetTextMetricsA( hdc, &tm); ok( ret, "GetTextMetrics error %u\n", GetLastError()); + extent = GetTabbedTextExtentA( hdc, "x", 0, 1, tabs); + ok( extent == 0, "GetTabbedTextExtentA returned non-zero on nCount == 0\n"); + extent = GetTabbedTextExtentA( hdc, "x", 1, 1, tabs); cx = LOWORD( extent); cy = HIWORD( extent); diff --git a/winetests/user32/win.c b/winetests/user32/win.c index 33c837bed0e..94f7c638612 100644 --- a/winetests/user32/win.c +++ b/winetests/user32/win.c @@ -21,7 +21,7 @@ */ /* To get ICON_SMALL2 with the MSVC headers */ -#define _WIN32_WINNT 0x0501 +//#define _WIN32_WINNT 0x0501 #include #include @@ -49,10 +49,17 @@ static BOOL (WINAPI *pGetWindowInfo)(HWND,WINDOWINFO*); static UINT (WINAPI *pGetWindowModuleFileNameA)(HWND,LPSTR,UINT); static BOOL (WINAPI *pGetLayeredWindowAttributes)(HWND,COLORREF*,BYTE*,DWORD*); static BOOL (WINAPI *pSetLayeredWindowAttributes)(HWND,COLORREF,BYTE,DWORD); +static BOOL (WINAPI *pUpdateLayeredWindow)(HWND,HDC,POINT*,SIZE*,HDC,POINT*,COLORREF,BLENDFUNCTION*,DWORD); static BOOL (WINAPI *pGetMonitorInfoA)(HMONITOR,LPMONITORINFO); static HMONITOR (WINAPI *pMonitorFromPoint)(POINT,DWORD); static int (WINAPI *pGetWindowRgnBox)(HWND,LPRECT); static BOOL (WINAPI *pGetGUIThreadInfo)(DWORD, GUITHREADINFO*); +static BOOL (WINAPI *pGetProcessDefaultLayout)( DWORD *layout ); +static BOOL (WINAPI *pSetProcessDefaultLayout)( DWORD layout ); +static BOOL (WINAPI *pFlashWindowEx)( PFLASHWINFO pfwi ); +static DWORD (WINAPI *pSetLayout)(HDC hdc, DWORD layout); +static DWORD (WINAPI *pGetLayout)(HDC hdc); +static BOOL (WINAPI *pMirrorRgn)(HWND hwnd, HRGN hrgn); static BOOL test_lbuttondown_flag; static HWND hwndMessage; @@ -121,6 +128,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 */ @@ -380,6 +415,15 @@ static void test_parent_owner(void) 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 ); @@ -596,6 +640,22 @@ static DWORD CALLBACK enum_thread( void *arg ) BOOL ret; MSG msg; + if (pGetGUIThreadInfo) + { + GUITHREADINFO info; + info.cbSize = sizeof(info); + ret = pGetGUIThreadInfo( GetCurrentThreadId(), &info ); + ok( ret || broken(!ret), /* win9x */ + "GetGUIThreadInfo failed without message queue\n" ); + SetLastError( 0xdeadbeef ); + info.cbSize = sizeof(info) + 1; + ret = pGetGUIThreadInfo( GetCurrentThreadId(), &info ); + ok( !ret, "GetGUIThreadInfo succeeded with wrong size\n" ); + ok( GetLastError() == ERROR_INVALID_PARAMETER || + broken(GetLastError() == 0xdeadbeef), /* win9x */ + "wrong error %u\n", GetLastError() ); + } + PeekMessage( &msg, 0, 0, 0, PM_NOREMOVE ); /* make sure we have a message queue */ count = 0; @@ -665,8 +725,12 @@ static LRESULT WINAPI main_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPAR /* Win9x does not fixup cx/xy for WM_WINDOWPOSCHANGING */ if (!(winpos->flags & SWP_NOSIZE) && !is_win9x) { - ok(winpos->cx >= 0 && winpos->cx <= 32767, "bad winpos->cx %d\n", winpos->cx); - ok(winpos->cy >= 0 && winpos->cy <= 32767, "bad winpos->cy %d\n", winpos->cy); + ok((winpos->cx >= 0 && winpos->cx <= 32767) || + winpos->cx == 32768, /* win7 doesn't truncate */ + "bad winpos->cx %d\n", winpos->cx); + ok((winpos->cy >= 0 && winpos->cy <= 32767) || + winpos->cy == 40000, /* win7 doesn't truncate */ + "bad winpos->cy %d\n", winpos->cy); } break; } @@ -680,8 +744,12 @@ static LRESULT WINAPI main_window_procA(HWND hwnd, UINT msg, WPARAM wparam, LPAR ok(winpos->x >= -32768 && winpos->x <= 32767, "bad winpos->x %d\n", winpos->x); ok(winpos->y >= -32768 && winpos->y <= 32767, "bad winpos->y %d\n", winpos->y); - ok(winpos->cx >= 0 && winpos->cx <= 32767, "bad winpos->cx %d\n", winpos->cx); - ok(winpos->cy >= 0 && winpos->cy <= 32767, "bad winpos->cy %d\n", winpos->cy); + ok((winpos->cx >= 0 && winpos->cx <= 32767) || + winpos->cx == 32768, /* win7 doesn't truncate */ + "bad winpos->cx %d\n", winpos->cx); + ok((winpos->cy >= 0 && winpos->cy <= 32767) || + winpos->cy == 40000, /* win7 doesn't truncate */ + "bad winpos->cy %d\n", winpos->cy); GetWindowRect(hwnd, &rc1); SetRect(&rc2, winpos->x, winpos->y, winpos->x + winpos->cx, winpos->y + winpos->cy); @@ -939,8 +1007,6 @@ static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam) RECT rc; LONG style; CBT_CREATEWNDA *createwnd = (CBT_CREATEWNDA *)lParam; - trace("HCBT_CREATEWND: hwnd %p, parent %p, style %08x\n", - hwnd, createwnd->lpcs->hwndParent, createwnd->lpcs->style); ok(createwnd->hwndInsertAfter == HWND_TOP, "hwndInsertAfter should be always HWND_TOP\n"); if (pGetWindowInfo) @@ -1009,7 +1075,6 @@ static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam) case HCBT_MOVESIZE: case HCBT_MINMAX: case HCBT_ACTIVATE: - case HCBT_SETFOCUS: if (pGetWindowInfo && IsWindow(hwnd)) { WINDOWINFO info; @@ -1023,9 +1088,9 @@ static LRESULT CALLBACK cbt_hook_proc(int nCode, WPARAM wParam, LPARAM lParam) verify_window_info(code_name, hwnd, &info); } break; - /* on HCBT_DESTROYWND window state is undefined */ + /* window state is undefined */ + case HCBT_SETFOCUS: case HCBT_DESTROYWND: - trace( "HCBT_DESTROYWND: hwnd %p\n", hwnd ); break; default: break; @@ -1905,10 +1970,14 @@ 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_grandchild, hwnd_child, hwnd_child2; + HWND hwnd_desktop; + RECT rc1, rc2; + BOOL ret; SetRect(&rect, 111, 222, 333, 444); ok(!GetWindowRect(0, &rect), "GetWindowRect succeeded\n"); @@ -1923,7 +1992,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 ); @@ -1932,7 +2002,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 ); @@ -1941,30 +2012,151 @@ 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); + 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); - 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_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_child); + ok(!!hwnd_child, "Failed to create child window (%d)\n", GetLastError()); + hwnd_child2 = create_tool_window(WS_VISIBLE|WS_CHILD, hwnd); + ok(!!hwnd_child2, "Failed to create second child 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); + + /* Returns TRUE also for windows that are not siblings */ + 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(hwnd2, hwnd_child, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); + ok(ret, "Got %d\n", ret); + check_active_state(hwnd2, hwnd2, hwnd2); + + /* Does not seem to do anything even without passing flags, still returns TRUE */ + GetWindowRect(hwnd_child, &rc1); + ret = SetWindowPos(hwnd_child, hwnd2 , 1, 2, 3, 4, 0); + ok(ret, "Got %d\n", ret); + GetWindowRect(hwnd_child, &rc2); + ok(rc1.left == rc2.left && rc1.top == rc2.top && + rc1.right == rc2.right && rc1.bottom == rc2.bottom, + "(%d, %d, %d, %d) != (%d, %d, %d, %d)\n", + rc1.left, rc1.top, rc1.right, rc1.bottom, rc2.left, rc2.top, rc2.right, rc2.bottom); + check_active_state(hwnd2, hwnd2, hwnd2); + + /* Same thing the other way around. */ + GetWindowRect(hwnd2, &rc1); + ret = SetWindowPos(hwnd2, hwnd_child, 1, 2, 3, 4, 0); + ok(ret, "Got %d\n", ret); + GetWindowRect(hwnd2, &rc2); + ok(rc1.left == rc2.left && rc1.top == rc2.top && + rc1.right == rc2.right && rc1.bottom == rc2.bottom, + "(%d, %d, %d, %d) != (%d, %d, %d, %d)\n", + rc1.left, rc1.top, rc1.right, rc1.bottom, rc2.left, rc2.top, rc2.right, rc2.bottom); + check_active_state(hwnd2, hwnd2, hwnd2); + + /* .. and with these windows. */ + GetWindowRect(hwnd_grandchild, &rc1); + ret = SetWindowPos(hwnd_grandchild, hwnd_child2, 1, 2, 3, 4, 0); + ok(ret, "Got %d\n", ret); + GetWindowRect(hwnd_grandchild, &rc2); + ok(rc1.left == rc2.left && rc1.top == rc2.top && + rc1.right == rc2.right && rc1.bottom == rc2.bottom, + "(%d, %d, %d, %d) != (%d, %d, %d, %d)\n", + rc1.left, rc1.top, rc1.right, rc1.bottom, rc2.left, rc2.top, rc2.right, rc2.bottom); + check_active_state(hwnd2, hwnd2, hwnd2); + + /* Add SWP_NOZORDER and it will be properly resized. */ + GetWindowRect(hwnd_grandchild, &rc1); + ret = SetWindowPos(hwnd_grandchild, hwnd_child2, 1, 2, 3, 4, SWP_NOZORDER); + ok(ret, "Got %d\n", ret); + GetWindowRect(hwnd_grandchild, &rc2); + ok((rc1.left+1) == rc2.left && (rc1.top+2) == rc2.top && + (rc1.left+4) == rc2.right && (rc1.top+6) == rc2.bottom, + "(%d, %d, %d, %d) != (%d, %d, %d, %d)\n", + rc1.left+1, rc1.top+2, rc1.left+4, rc1.top+6, rc2.left, rc2.top, rc2.right, rc2.bottom); + check_active_state(hwnd2, hwnd2, hwnd2); + + /* Given a sibling window, the window is properly resized. */ + GetWindowRect(hwnd_child, &rc1); + ret = SetWindowPos(hwnd_child, hwnd_child2, 1, 2, 3, 4, 0); + ok(ret, "Got %d\n", ret); + GetWindowRect(hwnd_child, &rc2); + ok((rc1.left+1) == rc2.left && (rc1.top+2) == rc2.top && + (rc1.left+4) == rc2.right && (rc1.top+6) == rc2.bottom, + "(%d, %d, %d, %d) != (%d, %d, %d, %d)\n", + rc1.left+1, rc1.top+2, rc1.left+4, rc1.top+6, rc2.left, rc2.top, rc2.right, rc2.bottom); + check_active_state(hwnd2, hwnd2, hwnd2); + + /* Involving the desktop window changes things. */ + 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); + ok(!ret, "Got %d\n", ret); + GetWindowRect(hwnd_child, &rc2); + ok(rc1.top == rc2.top && rc1.left == rc2.left && + rc1.bottom == rc2.bottom && rc1.right == rc2.right, + "(%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); + ok(!ret, "Got %d\n", ret); + check_active_state(hwnd2, hwnd2, hwnd2); + + DestroyWindow(hwnd_grandchild); + DestroyWindow(hwnd_child); + DestroyWindow(hwnd_child2); } static void test_SetMenu(HWND parent) @@ -2403,20 +2595,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()); -} - static void test_SetActiveWindow(HWND hwnd) { HWND hwnd2; @@ -2550,7 +2728,8 @@ static void test_SetForegroundWindow(HWND hwnd) hwnd2 = GetForegroundWindow(); ok(hwnd2 == hwnd, "Wrong foreground window %p\n", hwnd2); - ok(SetForegroundWindow( GetDesktopWindow() ), "SetForegroundWindow(desktop) error: %d\n", GetLastError()); + ret = SetForegroundWindow( GetDesktopWindow() ); + ok(ret, "SetForegroundWindow(desktop) error: %d\n", GetLastError()); hwnd2 = GetForegroundWindow(); ok(hwnd2 != hwnd, "Wrong foreground window %p\n", hwnd2); @@ -2669,10 +2848,7 @@ static LRESULT WINAPI button_hook_proc(HWND button, UINT msg, WPARAM wparam, LPA static void test_capture_1(void) { - HWND button, capture, oldFocus, oldActive; - - oldFocus = GetFocus(); - oldActive = GetActiveWindow(); + HWND button, capture; capture = GetCapture(); ok(capture == 0, "GetCapture() = %p\n", capture); @@ -2690,7 +2866,9 @@ static void test_capture_1(void) check_wnd_state(button, 0, button, button); DestroyWindow(button); - check_wnd_state(oldActive, 0, oldFocus, 0); + /* old active window test depends on previously executed window + * activation tests, and fails under NT4. + check_wnd_state(oldActive, 0, oldFocus, 0);*/ } static void test_capture_2(void) @@ -2847,6 +3025,7 @@ static void test_capture_4(void) HWND hwnd; WNDCLASSA wclass; HINSTANCE hInstance = GetModuleHandleA( NULL ); + ATOM aclass; if (!pGetGUIThreadInfo) { @@ -2863,10 +3042,11 @@ static void test_capture_4(void) wclass.lpszMenuName = 0; wclass.cbClsExtra = 0; wclass.cbWndExtra = 0; - assert (RegisterClassA( &wclass )); - assert (hwnd = CreateWindowA( wclass.lpszClassName, "MenuTest", - WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, - 400, 200, NULL, NULL, hInstance, NULL) ); + aclass = RegisterClassA( &wclass ); + ok( aclass, "RegisterClassA failed with error %d\n", GetLastError()); + hwnd = CreateWindowA( wclass.lpszClassName, "MenuTest", + WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, + 400, 200, NULL, NULL, hInstance, NULL); ok(hwnd != NULL, "CreateWindowEx failed with error %d\n", GetLastError()); if (!hwnd) return; hmenu = CreatePopupMenu(); @@ -3293,10 +3473,10 @@ static void test_nccalcscroll(HWND parent) static void test_SetParent(void) { - BOOL ret; HWND desktop = GetDesktopWindow(); HMENU hMenu; - HWND parent, child1, child2, child3, child4, sibling; + HWND ret, parent, child1, child2, child3, child4, sibling, popup; + BOOL bret; parent = CreateWindowExA(0, "static", NULL, WS_OVERLAPPEDWINDOW, 100, 100, 200, 200, 0, 0, 0, NULL); @@ -3341,8 +3521,6 @@ static void test_SetParent(void) if (!is_win9x) /* Win9x doesn't survive this test */ { - HWND ret; - ok(!SetParent(parent, child1), "SetParent should fail\n"); ok(!SetParent(child2, child3), "SetParent should fail\n"); ok(SetParent(child1, parent) != 0, "SetParent should not fail\n"); @@ -3388,8 +3566,7 @@ static void test_SetParent(void) ok(SetParent(sibling, parent) != 0, "SetParent should not fail\n"); ok(GetMenu(sibling) == hMenu, "SetParent should not remove menu\n"); - ret = DestroyWindow(parent); - ok( ret, "DestroyWindow() error %d\n", GetLastError()); + ok(DestroyWindow(parent), "DestroyWindow() failed\n"); ok(!IsWindow(parent), "parent still exists\n"); ok(!IsWindow(sibling), "sibling still exists\n"); @@ -3397,6 +3574,51 @@ static void test_SetParent(void) ok(!IsWindow(child2), "child2 still exists\n"); ok(!IsWindow(child3), "child3 still exists\n"); ok(!IsWindow(child4), "child4 still exists\n"); + + parent = CreateWindowExA(0, "static", NULL, WS_OVERLAPPEDWINDOW, + 100, 100, 200, 200, 0, 0, 0, NULL); + assert(parent != 0); + child1 = CreateWindowExA(0, "static", NULL, WS_CHILD, + 0, 0, 50, 50, parent, 0, 0, NULL); + assert(child1 != 0); + popup = CreateWindowExA(0, "static", NULL, WS_POPUP, + 0, 0, 50, 50, 0, 0, 0, NULL); + assert(popup != 0); + + trace("parent %p, child %p, popup %p\n", parent, child1, popup); + + check_parents(parent, desktop, 0, 0, 0, parent, parent); + check_parents(child1, parent, parent, parent, 0, parent, parent); + check_parents(popup, desktop, 0, 0, 0, popup, popup); + + SetActiveWindow(parent); + SetFocus(parent); + check_active_state(parent, 0, parent); + + ret = SetParent(popup, child1); + ok(ret == desktop, "expected %p, got %p\n", desktop, ret); + check_parents(popup, child1, child1, 0, 0, parent, popup); +todo_wine + check_active_state(popup, 0, popup); + + SetActiveWindow(parent); + SetFocus(parent); + check_active_state(parent, 0, parent); + + bret = SetForegroundWindow(popup); +todo_wine { + ok(bret || broken(!bret), "SetForegroundWindow() failed\n"); + if (!bret) + check_active_state(popup, 0, popup); + else + check_active_state(popup, popup, popup); + } + + ok(DestroyWindow(parent), "DestroyWindow() failed\n"); + + ok(!IsWindow(parent), "parent still exists\n"); + ok(!IsWindow(child1), "child1 still exists\n"); + ok(!IsWindow(popup), "popup still exists\n"); } static LRESULT WINAPI StyleCheckProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) @@ -3482,6 +3704,25 @@ static void check_window_style(DWORD dwStyleIn, DWORD dwExStyleIn, DWORD dwStyle "Style (0x%08x) should really be 0x%08x and/or Ex style (0x%08x) should really be 0x%08x\n", dwActualStyle, dwStyleOut, dwActualExStyle, dwExStyleOut); + /* try setting the styles explicitly */ + SetWindowLong( hwnd, GWL_EXSTYLE, dwExStyleIn ); + SetWindowLong( hwnd, GWL_STYLE, dwStyleIn ); + dwActualStyle = GetWindowLong(hwnd, GWL_STYLE); + dwActualExStyle = GetWindowLong(hwnd, GWL_EXSTYLE); + /* WS_CLIPSIBLINGS can't be reset on top-level windows */ + if (dwStyleIn & WS_CHILD) dwStyleOut = dwStyleIn; + else dwStyleOut = dwStyleIn | WS_CLIPSIBLINGS; + /* WS_EX_WINDOWEDGE can't always be changed */ + if ((dwExStyleIn & WS_EX_DLGMODALFRAME) || (dwStyleIn & WS_THICKFRAME)) + dwExStyleOut = dwExStyleIn | WS_EX_WINDOWEDGE; + else if (dwStyleIn & (WS_CHILD | WS_POPUP)) + dwExStyleOut = dwExStyleIn & ~WS_EX_WINDOWEDGE; + else + dwExStyleOut = dwExStyleIn; + ok((dwActualStyle == dwStyleOut) && (dwActualExStyle == dwExStyleOut), + "%08x/%08x: Style (0x%08x) should really be 0x%08x and/or Ex style (0x%08x) should really be 0x%08x\n", + dwStyleIn, dwExStyleIn, dwActualStyle, dwStyleOut, dwActualExStyle, dwExStyleOut); + DestroyWindow(hwnd); if (hwndParent) DestroyWindow(hwndParent); } @@ -3823,6 +4064,10 @@ static void test_params(void) HWND hwnd; INT rc; + ok(!IsWindow(0), "IsWindow(0)\n"); + ok(!IsWindow(HWND_BROADCAST), "IsWindow(HWND_BROADCAST)\n"); + ok(!IsWindow(HWND_TOPMOST), "IsWindow(HWND_TOPMOST)\n"); + /* Just a param check */ if (pGetMonitorInfoA) { @@ -4442,6 +4687,8 @@ static LRESULT CALLBACK winsizes_wnd_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM "wrong y size %d/%d\n", cs->cy, expected_cy ); ok( (rect.right - rect.left == expected_rect.right - expected_rect.left && rect.bottom - rect.top == expected_rect.bottom - expected_rect.top) || + (rect.right - rect.left == min( 65535, expected_rect.right - expected_rect.left ) && + rect.bottom - rect.top == min( 65535, expected_rect.bottom - expected_rect.top )) || broken( rect.right - rect.left == broken_rect.right - broken_rect.left && rect.bottom - rect.top == broken_rect.bottom - broken_rect.top) || broken( rect.right - rect.left == (short)broken_rect.right - (short)broken_rect.left && @@ -4472,10 +4719,12 @@ static void test_CreateWindow(void) HMENU hmenu; RECT rc, rc_minmax; MINMAXINFO minmax; + BOOL res; #define expect_menu(window, menu) \ SetLastError(0xdeadbeef); \ - ok(GetMenu(window) == (HMENU)menu, "GetMenu error %d\n", GetLastError()) + res = (GetMenu(window) == (HMENU)menu); \ + ok(res, "GetMenu error %d\n", GetLastError()) #define expect_style(window, style)\ ok((ULONG)GetWindowLong(window, GWL_STYLE) == (style), "expected style %x != %x\n", (LONG)(style), GetWindowLong(window, GWL_STYLE)) @@ -4494,7 +4743,8 @@ static void test_CreateWindow(void) assert(parent != 0); SetLastError(0xdeadbeef); - ok(IsMenu(hmenu), "IsMenu error %d\n", GetLastError()); + res = IsMenu(hmenu); + ok(res, "IsMenu error %d\n", GetLastError()); /* WS_CHILD */ SetLastError(0xdeadbeef); @@ -4743,8 +4993,10 @@ static void test_CreateWindow(void) hwnd = CreateWindowExA(0, "Sizes_WndClass", NULL, WS_CHILD, 300000, 300000, 200000, 200000, parent, 0, 0, NULL); ok( hwnd != 0, "creation failed err %u\n", GetLastError()); GetClientRect( hwnd, &rc ); - ok( rc.right == 200000 || broken(rc.right == (short)200000), "invalid rect right %u\n", rc.right ); - ok( rc.bottom == 200000 || broken(rc.bottom == (short)200000), "invalid rect bottom %u\n", rc.bottom ); + ok( rc.right == 200000 || rc.right == 65535 || broken(rc.right == (short)200000), + "invalid rect right %u\n", rc.right ); + ok( rc.bottom == 200000 || rc.bottom == 65535 || broken(rc.bottom == (short)200000), + "invalid rect bottom %u\n", rc.bottom ); DestroyWindow(hwnd); expected_cx = expected_cy = -10; @@ -4780,7 +5032,8 @@ static void test_CreateWindow(void) ok( hwnd != 0, "creation failed err %u\n", GetLastError()); GetClientRect( hwnd, &rc ); ok( rc.right == 100, "invalid rect right %u\n", rc.right ); - ok( rc.bottom == 0x7fffffff - 10 || broken(rc.bottom == 0), "invalid rect bottom %u\n", rc.bottom ); + ok( rc.bottom == 0x7fffffff - 10 || rc.bottom ==65535 || broken(rc.bottom == 0), + "invalid rect bottom %u\n", rc.bottom ); DestroyWindow(hwnd); expected_cx = 0x7fffffff; @@ -4790,8 +5043,10 @@ static void test_CreateWindow(void) hwnd = CreateWindowExA(0, "Sizes_WndClass", NULL, WS_CHILD, 20, 10, 0x7fffffff, 0x7fffffff, parent, 0, 0, NULL); ok( hwnd != 0, "creation failed err %u\n", GetLastError()); GetClientRect( hwnd, &rc ); - ok( rc.right == 0x7fffffff - 20 || broken(rc.right == 0), "invalid rect right %u\n", rc.right ); - ok( rc.bottom == 0x7fffffff - 10 || broken(rc.bottom == 0), "invalid rect bottom %u\n", rc.bottom ); + ok( rc.right == 0x7fffffff - 20 || rc.right == 65535 || broken(rc.right == 0), + "invalid rect right %u\n", rc.right ); + ok( rc.bottom == 0x7fffffff - 10 || rc.right == 65535 || broken(rc.bottom == 0), + "invalid rect bottom %u\n", rc.bottom ); DestroyWindow(hwnd); /* top level window */ @@ -4804,6 +5059,74 @@ static void test_CreateWindow(void) ok( rc.bottom <= expected_cy, "invalid rect bottom %u\n", rc.bottom ); DestroyWindow(hwnd); + if (pGetLayout && pSetLayout) + { + HDC hdc = GetDC( parent ); + pSetLayout( hdc, LAYOUT_RTL ); + if (pGetLayout( hdc )) + { + ReleaseDC( parent, hdc ); + DestroyWindow( parent ); + SetLastError( 0xdeadbeef ); + parent = CreateWindowEx(WS_EX_APPWINDOW | WS_EX_LAYOUTRTL, "static", NULL, WS_POPUP, + 0, 0, 100, 100, 0, 0, 0, NULL); + ok( parent != 0, "creation failed err %u\n", GetLastError()); + expect_ex_style( parent, WS_EX_APPWINDOW | WS_EX_LAYOUTRTL ); + hwnd = CreateWindowExA(0, "static", NULL, WS_CHILD, 0, 0, 20, 20, parent, 0, 0, NULL); + ok( hwnd != 0, "creation failed err %u\n", GetLastError()); + expect_ex_style( hwnd, WS_EX_LAYOUTRTL ); + DestroyWindow( hwnd ); + hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP, 0, 0, 20, 20, parent, 0, 0, NULL); + ok( hwnd != 0, "creation failed err %u\n", GetLastError()); + expect_ex_style( hwnd, 0 ); + DestroyWindow( hwnd ); + SetWindowLongW( parent, GWL_EXSTYLE, WS_EX_APPWINDOW | WS_EX_LAYOUTRTL | WS_EX_NOINHERITLAYOUT ); + hwnd = CreateWindowExA(0, "static", NULL, WS_CHILD, 0, 0, 20, 20, parent, 0, 0, NULL); + ok( hwnd != 0, "creation failed err %u\n", GetLastError()); + expect_ex_style( hwnd, 0 ); + DestroyWindow( hwnd ); + + if (pGetProcessDefaultLayout && pSetProcessDefaultLayout) + { + DWORD layout; + + SetLastError( 0xdeadbeef ); + ok( !pGetProcessDefaultLayout( NULL ), "GetProcessDefaultLayout succeeded\n" ); + ok( GetLastError() == ERROR_NOACCESS, "wrong error %u\n", GetLastError() ); + SetLastError( 0xdeadbeef ); + ok( pGetProcessDefaultLayout( &layout ), + "GetProcessDefaultLayout failed err %u\n", GetLastError ()); + ok( layout == 0, "GetProcessDefaultLayout wrong layout %x\n", layout ); + SetLastError( 0xdeadbeef ); + ok( pSetProcessDefaultLayout( 7 ), + "SetProcessDefaultLayout failed err %u\n", GetLastError ()); + ok( pGetProcessDefaultLayout( &layout ), + "GetProcessDefaultLayout failed err %u\n", GetLastError ()); + ok( layout == 7, "GetProcessDefaultLayout wrong layout %x\n", layout ); + SetLastError( 0xdeadbeef ); + ok( pSetProcessDefaultLayout( LAYOUT_RTL ), + "SetProcessDefaultLayout failed err %u\n", GetLastError ()); + ok( pGetProcessDefaultLayout( &layout ), + "GetProcessDefaultLayout failed err %u\n", GetLastError ()); + ok( layout == LAYOUT_RTL, "GetProcessDefaultLayout wrong layout %x\n", layout ); + hwnd = CreateWindowEx(WS_EX_APPWINDOW, "static", NULL, WS_POPUP, + 0, 0, 100, 100, 0, 0, 0, NULL); + ok( hwnd != 0, "creation failed err %u\n", GetLastError()); + expect_ex_style( hwnd, WS_EX_APPWINDOW | WS_EX_LAYOUTRTL ); + DestroyWindow( hwnd ); + hwnd = CreateWindowEx(WS_EX_APPWINDOW, "static", NULL, WS_POPUP, + 0, 0, 100, 100, parent, 0, 0, NULL); + ok( hwnd != 0, "creation failed err %u\n", GetLastError()); + expect_ex_style( hwnd, WS_EX_APPWINDOW ); + DestroyWindow( hwnd ); + pSetProcessDefaultLayout( 0 ); + } + else win_skip( "SetProcessDefaultLayout not supported\n" ); + } + else win_skip( "SetLayout not supported\n" ); + } + else win_skip( "SetLayout not available\n" ); + DestroyWindow(parent); UnregisterClass("MinMax_WndClass", GetModuleHandle(0)); @@ -4834,13 +5157,13 @@ static void test_SetWindowLong(void) retval = SetWindowLongPtr(NULL, GWLP_WNDPROC, 0); ok(!retval, "SetWindowLongPtr on invalid window handle should have returned 0 instead of 0x%lx\n", retval); ok(check_error(GetLastError(), ERROR_INVALID_WINDOW_HANDLE), - "SetWindowLongPtr should have set error to ERROR_INVALID_WINDOW_HANDLE instad of %d\n", GetLastError()); + "SetWindowLongPtr should have set error to ERROR_INVALID_WINDOW_HANDLE instead of %d\n", GetLastError()); SetLastError(0xdeadbeef); retval = SetWindowLongPtr(hwndMain, 0xdeadbeef, 0); ok(!retval, "SetWindowLongPtr on invalid index should have returned 0 instead of 0x%lx\n", retval); ok(check_error(GetLastError(), ERROR_INVALID_INDEX), - "SetWindowLongPtr should have set error to ERROR_INVALID_INDEX instad of %d\n", GetLastError()); + "SetWindowLongPtr should have set error to ERROR_INVALID_INDEX instead of %d\n", GetLastError()); SetLastError(0xdeadbeef); retval = SetWindowLongPtr(hwndMain, GWLP_WNDPROC, 0); @@ -4872,7 +5195,7 @@ static void test_ShowWindow(void) { HWND hwnd; DWORD style; - RECT rcMain, rc; + RECT rcMain, rc, rcMinimized; LPARAM ret; SetRect(&rcMain, 120, 120, 210, 210); @@ -4914,8 +5237,16 @@ static void test_ShowWindow(void) ok(style & WS_VISIBLE, "window should be visible\n"); ok(style & WS_MINIMIZE, "window should be minimized\n"); ok(!(style & WS_MAXIMIZE), "window should not be maximized\n"); + GetWindowRect(hwnd, &rcMinimized); + ok(!EqualRect(&rcMain, &rcMinimized), "rects shouldn't match\n"); + /* shouldn't be able to resize minimized windows */ + ret = SetWindowPos(hwnd, 0, 0, 0, + (rcMinimized.right - rcMinimized.left) * 2, + (rcMinimized.bottom - rcMinimized.top) * 2, + SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER); + ok(ret, "not expected ret: %lu\n", ret); GetWindowRect(hwnd, &rc); - ok(!EqualRect(&rcMain, &rc), "rects shouldn't match\n"); + ok(EqualRect(&rc, &rcMinimized), "rects should match\n"); ShowWindow(hwnd, SW_RESTORE); ok(ret, "not expected ret: %lu\n", ret); @@ -5448,16 +5779,29 @@ static void test_layered_window(void) COLORREF key = 0; BYTE alpha = 0; DWORD flags = 0; + POINT pt = { 0, 0 }; + SIZE sz = { 200, 200 }; + HDC hdc; + HBITMAP hbm; BOOL ret; - if (!pGetLayeredWindowAttributes || !pSetLayeredWindowAttributes) + if (!pGetLayeredWindowAttributes || !pSetLayeredWindowAttributes || !pUpdateLayeredWindow) { win_skip( "layered windows not supported\n" ); return; } + + hdc = CreateCompatibleDC( 0 ); + hbm = CreateCompatibleBitmap( hdc, 200, 200 ); + SelectObject( hdc, hbm ); + hwnd = CreateWindowExA(0, "MainWindowClass", "message window", WS_CAPTION, 100, 100, 200, 200, 0, 0, 0, NULL); assert( hwnd ); + SetLastError( 0xdeadbeef ); + ret = pUpdateLayeredWindow( hwnd, 0, NULL, &sz, hdc, &pt, 0, NULL, ULW_OPAQUE ); + ok( !ret, "UpdateLayeredWindow should fail on non-layered window\n" ); + ok( GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError() ); ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags ); ok( !ret, "GetLayeredWindowAttributes should fail on non-layered window\n" ); ret = pSetLayeredWindowAttributes( hwnd, 0, 0, LWA_ALPHA ); @@ -5465,6 +5809,10 @@ static void test_layered_window(void) SetWindowLong( hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED ); ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags ); ok( !ret, "GetLayeredWindowAttributes should fail on layered but not initialized window\n" ); + ret = pUpdateLayeredWindow( hwnd, 0, NULL, &sz, hdc, &pt, 0, NULL, ULW_OPAQUE ); + ok( ret, "UpdateLayeredWindow should succeed on layered window\n" ); + ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags ); + ok( !ret, "GetLayeredWindowAttributes should fail on layered but not initialized window\n" ); ret = pSetLayeredWindowAttributes( hwnd, 0x123456, 44, LWA_ALPHA ); ok( ret, "SetLayeredWindowAttributes should succeed on layered window\n" ); ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags ); @@ -5472,14 +5820,23 @@ static void test_layered_window(void) ok( key == 0x123456 || key == 0, "wrong color key %x\n", key ); ok( alpha == 44, "wrong alpha %u\n", alpha ); ok( flags == LWA_ALPHA, "wrong flags %x\n", flags ); + SetLastError( 0xdeadbeef ); + ret = pUpdateLayeredWindow( hwnd, 0, NULL, &sz, hdc, &pt, 0, NULL, ULW_OPAQUE ); + ok( !ret, "UpdateLayeredWindow should fail on layered but initialized window\n" ); + ok( GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError() ); /* clearing WS_EX_LAYERED resets attributes */ SetWindowLong( hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) & ~WS_EX_LAYERED ); + SetLastError( 0xdeadbeef ); + ret = pUpdateLayeredWindow( hwnd, 0, NULL, &sz, hdc, &pt, 0, NULL, ULW_OPAQUE ); + ok( !ret, "UpdateLayeredWindow should fail on non-layered window\n" ); ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags ); ok( !ret, "GetLayeredWindowAttributes should fail on no longer layered window\n" ); SetWindowLong( hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED ); ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags ); ok( !ret, "GetLayeredWindowAttributes should fail on layered but not initialized window\n" ); + ret = pUpdateLayeredWindow( hwnd, 0, NULL, &sz, hdc, &pt, 0, NULL, ULW_OPAQUE ); + ok( ret, "UpdateLayeredWindow should succeed on layered window\n" ); ret = pSetLayeredWindowAttributes( hwnd, 0x654321, 22, LWA_COLORKEY | LWA_ALPHA ); ok( ret, "SetLayeredWindowAttributes should succeed on layered window\n" ); ret = pGetLayeredWindowAttributes( hwnd, &key, &alpha, &flags ); @@ -5487,6 +5844,10 @@ static void test_layered_window(void) ok( key == 0x654321, "wrong color key %x\n", key ); ok( alpha == 22, "wrong alpha %u\n", alpha ); ok( flags == (LWA_COLORKEY | LWA_ALPHA), "wrong flags %x\n", flags ); + SetLastError( 0xdeadbeef ); + ret = pUpdateLayeredWindow( hwnd, 0, NULL, &sz, hdc, &pt, 0, NULL, ULW_OPAQUE ); + ok( !ret, "UpdateLayeredWindow should fail on layered but initialized window\n" ); + ok( GetLastError() == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError() ); ret = pSetLayeredWindowAttributes( hwnd, 0x888888, 33, LWA_COLORKEY ); ok( ret, "SetLayeredWindowAttributes should succeed on layered window\n" ); @@ -5520,6 +5881,8 @@ static void test_layered_window(void) ok( flags == 0, "wrong flags %x\n", flags ); DestroyWindow( hwnd ); + DeleteDC( hdc ); + DeleteObject( hbm ); } static MONITORINFO mi; @@ -5881,7 +6244,8 @@ static void test_thick_child_size(HWND parentWindow) cls.lpszMenuName = NULL; cls.lpszClassName = className; SetLastError(0xdeadbeef); - ok(RegisterClassA(&cls),"RegisterClassA failed, error: %u\n", GetLastError()); + success = RegisterClassA(&cls); + ok(success,"RegisterClassA failed, error: %u\n", GetLastError()); for(i = 0; i < NUMBER_OF_THICK_CHILD_TESTS; i++) { @@ -5973,7 +6337,7 @@ static void test_winregion(void) { HWND hwnd; RECT r; - int ret; + int ret, width; HRGN hrgn; if (!pGetWindowRgnBox) @@ -6006,23 +6370,249 @@ static void test_winregion(void) ok( r.left == 2 && r.top == 3 && r.right == 10 && r.bottom == 15, "Expected (2,3,10,15), got (%d,%d,%d,%d)\n", r.left, r.top, r.right, r.bottom); - DeleteObject(hrgn); + if (pMirrorRgn) + { + hrgn = CreateRectRgn(2, 3, 10, 15); + ret = pMirrorRgn( hwnd, hrgn ); + ok( ret == TRUE, "MirrorRgn failed %u\n", ret ); + r.left = r.top = r.right = r.bottom = 0; + GetWindowRect( hwnd, &r ); + width = r.right - r.left; + r.left = r.top = r.right = r.bottom = 0; + ret = GetRgnBox( hrgn, &r ); + ok( ret == SIMPLEREGION, "GetRgnBox failed %u\n", ret ); + ok( r.left == width - 10 && r.top == 3 && r.right == width - 2 && r.bottom == 15, + "Wrong rectangle (%d,%d,%d,%d) for width %d\n", r.left, r.top, r.right, r.bottom, width ); + } + else win_skip( "MirrorRgn not supported\n" ); } DestroyWindow(hwnd); } +static void test_rtl_layout(void) +{ + HWND parent, child; + RECT r; + POINT pt; + + if (!pSetProcessDefaultLayout) + { + win_skip( "SetProcessDefaultLayout not supported\n" ); + return; + } + + parent = CreateWindowExA(WS_EX_LAYOUTRTL, "static", NULL, WS_POPUP, 100, 100, 300, 300, NULL, 0, 0, NULL); + child = CreateWindowExA(0, "static", NULL, WS_CHILD, 10, 10, 20, 20, parent, 0, 0, NULL); + + GetWindowRect( parent, &r ); + ok( r.left == 100 && r.right == 400, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom ); + GetClientRect( parent, &r ); + ok( r.left == 0 && r.right == 300, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom ); + GetClientRect( child, &r ); + ok( r.left == 0 && r.right == 20, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom ); + MapWindowPoints( child, parent, (POINT *)&r, 2 ); + ok( r.left == 10 && r.right == 30, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom ); + GetWindowRect( child, &r ); + ok( r.left == 370 && r.right == 390, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom ); + MapWindowPoints( NULL, parent, (POINT *)&r, 2 ); + ok( r.left == 10 && r.right == 30, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom ); + GetWindowRect( child, &r ); + MapWindowPoints( NULL, parent, (POINT *)&r, 1 ); + MapWindowPoints( NULL, parent, (POINT *)&r + 1, 1 ); + ok( r.left == 30 && r.right == 10, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom ); + pt.x = pt.y = 12; + MapWindowPoints( child, parent, &pt, 1 ); + ok( pt.x == 22 && pt.y == 22, "wrong point %d,%d\n", pt.x, pt.y ); + SetWindowPos( parent, 0, 0, 0, 250, 250, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE ); + GetWindowRect( parent, &r ); + ok( r.left == 100 && r.right == 350, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom ); + GetWindowRect( child, &r ); + ok( r.left == 320 && r.right == 340, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom ); + SetWindowLongW( parent, GWL_EXSTYLE, 0 ); + GetWindowRect( child, &r ); + ok( r.left == 320 && r.right == 340, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom ); + MapWindowPoints( NULL, parent, (POINT *)&r, 2 ); + ok( r.left == 220 && r.right == 240, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom ); + SetWindowLongW( parent, GWL_EXSTYLE, WS_EX_LAYOUTRTL ); + GetWindowRect( child, &r ); + ok( r.left == 320 && r.right == 340, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom ); + MapWindowPoints( NULL, parent, (POINT *)&r, 2 ); + ok( r.left == 10 && r.right == 30, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom ); + SetWindowPos( child, 0, 0, 0, 30, 30, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE ); + GetWindowRect( child, &r ); + ok( r.left == 310 && r.right == 340, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom ); + MapWindowPoints( NULL, parent, (POINT *)&r, 2 ); + ok( r.left == 10 && r.right == 40, "wrong rect %d,%d - %d,%d\n", r.left, r.top, r.right, r.bottom ); + DestroyWindow( child ); + DestroyWindow( parent ); +} + +static void test_FlashWindowEx(void) +{ + HWND hwnd; + FLASHWINFO finfo; + BOOL ret; + + if (!pFlashWindowEx) + { + win_skip( "FlashWindowEx not supported\n" ); + return; + } + + hwnd = CreateWindowExA( 0, "MainWindowClass", "FlashWindow", WS_POPUP, + 0, 0, 0, 0, 0, 0, 0, NULL ); + ok( hwnd != 0, "CreateWindowExA error %d\n", GetLastError() ); + + finfo.cbSize = sizeof(FLASHWINFO); + finfo.dwFlags = FLASHW_TIMER; + finfo.uCount = 3; + finfo.dwTimeout = 200; + finfo.hwnd = NULL; + SetLastError(0xdeadbeef); + ret = pFlashWindowEx(&finfo); + todo_wine ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, + "FlashWindowEx returned with %d\n", GetLastError()); + + finfo.hwnd = hwnd; + SetLastError(0xdeadbeef); + ret = pFlashWindowEx(NULL); + todo_wine ok(!ret && GetLastError() == ERROR_NOACCESS, + "FlashWindowEx returned with %d\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = pFlashWindowEx(&finfo); + todo_wine ok(!ret, "FlashWindowEx succeeded\n"); + + finfo.cbSize = sizeof(FLASHWINFO) - 1; + SetLastError(0xdeadbeef); + ret = pFlashWindowEx(&finfo); + todo_wine ok(!ret && GetLastError()==ERROR_INVALID_PARAMETER, + "FlashWindowEx succeeded\n"); + + finfo.cbSize = sizeof(FLASHWINFO) + 1; + SetLastError(0xdeadbeef); + ret = pFlashWindowEx(&finfo); + todo_wine ok(!ret && GetLastError()==ERROR_INVALID_PARAMETER, + "FlashWindowEx succeeded\n"); + finfo.cbSize = sizeof(FLASHWINFO); + + DestroyWindow( hwnd ); + + SetLastError(0xdeadbeef); + ret = pFlashWindowEx(&finfo); + todo_wine ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, + "FlashWindowEx returned with %d\n", GetLastError()); + + ok(finfo.cbSize == sizeof(FLASHWINFO), "FlashWindowEx modified cdSize to %x\n", finfo.cbSize); + ok(finfo.hwnd == hwnd, "FlashWindowEx modified hwnd to %p\n", finfo.hwnd); + ok(finfo.dwFlags == FLASHW_TIMER, "FlashWindowEx modified dwFlags to %x\n", finfo.dwFlags); + ok(finfo.uCount == 3, "FlashWindowEx modified uCount to %x\n", finfo.uCount); + ok(finfo.dwTimeout == 200, "FlashWindowEx modified dwTimeout to %x\n", finfo.dwTimeout); + + hwnd = CreateWindowExA( 0, "MainWindowClass", "FlashWindow", WS_VISIBLE | WS_POPUPWINDOW, + 0, 0, 0, 0, 0, 0, 0, NULL ); + ok( hwnd != 0, "CreateWindowExA error %d\n", GetLastError() ); + finfo.hwnd = hwnd; + + SetLastError(0xdeadbeef); + ret = pFlashWindowEx(NULL); + todo_wine ok(!ret && GetLastError() == ERROR_NOACCESS, + "FlashWindowEx returned with %d\n", GetLastError()); + + SetLastError(0xdeadbeef); + ret = pFlashWindowEx(&finfo); + todo_wine ok(!ret, "FlashWindowEx succeeded\n"); + + ok(finfo.cbSize == sizeof(FLASHWINFO), "FlashWindowEx modified cdSize to %x\n", finfo.cbSize); + ok(finfo.hwnd == hwnd, "FlashWindowEx modified hwnd to %p\n", finfo.hwnd); + ok(finfo.dwFlags == FLASHW_TIMER, "FlashWindowEx modified dwFlags to %x\n", finfo.dwFlags); + ok(finfo.uCount == 3, "FlashWindowEx modified uCount to %x\n", finfo.uCount); + ok(finfo.dwTimeout == 200, "FlashWindowEx modified dwTimeout to %x\n", finfo.dwTimeout); + + finfo.dwFlags = FLASHW_STOP; + SetLastError(0xdeadbeef); + ret = pFlashWindowEx(&finfo); + ok(ret, "FlashWindowEx failed with %d\n", GetLastError()); + + DestroyWindow( hwnd ); +} + +static void test_FindWindowEx(void) +{ + HWND hwnd, found; + CHAR title[1]; + + hwnd = CreateWindowExA( 0, "MainWindowClass", "caption", WS_POPUP, 0,0,0,0, 0, 0, 0, NULL ); + ok( hwnd != 0, "CreateWindowExA error %d\n", GetLastError() ); + + title[0] = 0; + + found = FindWindowExA( 0, 0, "MainWindowClass", title ); + ok( found == NULL, "expected a NULL hwnd\n" ); + found = FindWindowExA( 0, 0, "MainWindowClass", NULL ); + ok( found == hwnd, "found is %p, expected a valid hwnd\n", found ); + + DestroyWindow( hwnd ); + + hwnd = CreateWindowExA( 0, "MainWindowClass", NULL, WS_POPUP, 0,0,0,0, 0, 0, 0, NULL ); + ok( hwnd != 0, "CreateWindowExA error %d\n", GetLastError() ); + + found = FindWindowExA( 0, 0, "MainWindowClass", title ); + ok( found == hwnd, "found is %p, expected a valid hwnd\n", found ); + found = FindWindowExA( 0, 0, "MainWindowClass", NULL ); + ok( found == hwnd, "found is %p, expected a valid hwnd\n", found ); + + DestroyWindow( hwnd ); + + /* test behaviour with a window title that is an empty character */ + found = FindWindowExA( 0, 0, "Shell_TrayWnd", title ); + ok( found != NULL, "found is NULL, expected a valid hwnd\n" ); + found = FindWindowExA( 0, 0, "Shell_TrayWnd", NULL ); + ok( found != NULL, "found is NULL, expected a valid hwnd\n" ); +} + +static void test_GetLastActivePopup(void) +{ + HWND hwndOwner, hwndPopup1, hwndPopup2; + + hwndOwner = CreateWindowExA(0, "MainWindowClass", NULL, + WS_VISIBLE | WS_POPUPWINDOW, + 100, 100, 200, 200, + NULL, 0, GetModuleHandle(0), NULL); + hwndPopup1 = CreateWindowExA(0, "MainWindowClass", NULL, + WS_VISIBLE | WS_POPUPWINDOW, + 100, 100, 200, 200, + hwndOwner, 0, GetModuleHandle(0), NULL); + hwndPopup2 = CreateWindowExA(0, "MainWindowClass", NULL, + WS_VISIBLE | WS_POPUPWINDOW, + 100, 100, 200, 200, + hwndPopup1, 0, GetModuleHandle(0), NULL); + ok( GetLastActivePopup(hwndOwner) == hwndPopup2, "wrong last active popup\n" ); + DestroyWindow( hwndPopup2 ); + DestroyWindow( hwndPopup1 ); + DestroyWindow( hwndOwner ); +} + START_TEST(win) { HMODULE user32 = GetModuleHandleA( "user32.dll" ); + HMODULE gdi32 = GetModuleHandleA("gdi32.dll"); pGetAncestor = (void *)GetProcAddress( user32, "GetAncestor" ); pGetWindowInfo = (void *)GetProcAddress( user32, "GetWindowInfo" ); pGetWindowModuleFileNameA = (void *)GetProcAddress( user32, "GetWindowModuleFileNameA" ); pGetLayeredWindowAttributes = (void *)GetProcAddress( user32, "GetLayeredWindowAttributes" ); pSetLayeredWindowAttributes = (void *)GetProcAddress( user32, "SetLayeredWindowAttributes" ); + pUpdateLayeredWindow = (void *)GetProcAddress( user32, "UpdateLayeredWindow" ); pGetMonitorInfoA = (void *)GetProcAddress( user32, "GetMonitorInfoA" ); pMonitorFromPoint = (void *)GetProcAddress( user32, "MonitorFromPoint" ); pGetWindowRgnBox = (void *)GetProcAddress( user32, "GetWindowRgnBox" ); pGetGUIThreadInfo = (void *)GetProcAddress( user32, "GetGUIThreadInfo" ); + pGetProcessDefaultLayout = (void *)GetProcAddress( user32, "GetProcessDefaultLayout" ); + pSetProcessDefaultLayout = (void *)GetProcAddress( user32, "SetProcessDefaultLayout" ); + pFlashWindowEx = (void *)GetProcAddress( user32, "FlashWindowEx" ); + pGetLayout = (void *)GetProcAddress( gdi32, "GetLayout" ); + pSetLayout = (void *)GetProcAddress( gdi32, "SetLayout" ); + pMirrorRgn = (void *)GetProcAddress( gdi32, "MirrorRgn" ); if (!RegisterWindowClasses()) assert(0); @@ -6033,6 +6623,10 @@ START_TEST(win) hhook = SetWindowsHookExA(WH_CBT, cbt_hook_proc, 0, GetCurrentThreadId()); if (!hhook) win_skip( "Cannot set CBT hook, skipping some tests\n" ); + /* make sure that these tests are executed first */ + test_FindWindowEx(); + test_SetParent(); + hwndMain = CreateWindowExA(/*WS_EX_TOOLWINDOW*/ 0, "MainWindowClass", "Main window", WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP, @@ -6059,15 +6653,16 @@ START_TEST(win) test_capture_2(); test_capture_3(hwndMain, hwndMain2); test_capture_4(); + test_rtl_layout(); + test_FlashWindowEx(); test_CreateWindow(); test_parent_owner(); - test_SetParent(); test_enum_thread_windows(); test_mdi(); test_icons(); - test_SetWindowPos(hwndMain); + test_SetWindowPos(hwndMain, hwndMain2); test_SetMenu(hwndMain); test_SetFocus(hwndMain); test_SetActiveWindow(hwndMain); @@ -6076,6 +6671,7 @@ START_TEST(win) test_children_zorder(hwndMain); test_popup_zorder(hwndMain2, hwndMain, WS_POPUP); test_popup_zorder(hwndMain2, hwndMain, 0); + test_GetLastActivePopup(); test_keyboard_input(hwndMain); test_mouse_input(hwndMain); test_validatergn(hwndMain); @@ -6098,11 +6694,14 @@ START_TEST(win) test_Expose(); test_layered_window(); - test_SetForegroundWindow(hwndMain); - if(!winetest_interactive) - skip("bug 5957: skipping test_shell_window, it crashes ros/win7 explorer\n"); + if(!winetest_interactive) + skip("skipping test_SetForegroundWindow, Hangs on WaitForSingleObject line 2771\n"); else - test_shell_window(); + test_SetForegroundWindow(hwndMain); + if(!winetest_interactive) + skip("bug 5957: skipping test_shell_window, it crashes ros/win7 explorer\n"); + else + test_shell_window(); test_handles( hwndMain ); test_winregion(); diff --git a/winetests/user32/wsprintf.c b/winetests/user32/wsprintf.c index bca16bd9f86..5370df4636a 100755 --- a/winetests/user32/wsprintf.c +++ b/winetests/user32/wsprintf.c @@ -23,39 +23,93 @@ #include "windef.h" #include "winbase.h" #include "winuser.h" +#include "winnls.h" + +static const struct +{ + const char *fmt; + ULONGLONG value; + const char *res; +} i64_formats[] = +{ + { "%I64X", ((ULONGLONG)0x12345 << 32) | 0x67890a, "123450067890A" }, + { "%I32X", ((ULONGLONG)0x12345 << 32) | 0x67890a, "67890A" }, + { "%I64d", (ULONGLONG)543210 * 1000000, "543210000000" }, + { "%I64X", (LONGLONG)-0x12345, "FFFFFFFFFFFEDCBB" }, + { "%I32x", (LONGLONG)-0x12345, "fffedcbb" }, + { "%I64u", (LONGLONG)-123, "18446744073709551493" }, + { "%Id", (LONGLONG)-12345, "-12345" }, +#ifdef _WIN64 + { "%Ix", ((ULONGLONG)0x12345 << 32) | 0x67890a, "123450067890a" }, + { "%Ix", (LONGLONG)-0x12345, "fffffffffffedcbb" }, + { "%p", (LONGLONG)-0x12345, "FFFFFFFFFFFEDCBB" }, +#else + { "%Ix", ((ULONGLONG)0x12345 << 32) | 0x67890a, "67890a" }, + { "%Ix", (LONGLONG)-0x12345, "fffedcbb" }, + { "%p", (LONGLONG)-0x12345, "FFFEDCBB" }, +#endif +}; static void wsprintfATest(void) { char buf[25]; + unsigned int i; int rc; rc=wsprintfA(buf, "%010ld", -1); - ok(rc == 10, "wsPrintfA length failure: rc=%d error=%d\n",rc,GetLastError()); + ok(rc == 10, "wsprintfA length failure: rc=%d error=%d\n",rc,GetLastError()); ok((lstrcmpA(buf, "-000000001") == 0), "wsprintfA zero padded negative value failure: buf=[%s]\n",buf); + rc = wsprintfA(buf, "%I64X", (ULONGLONG)0); + if (rc == 4 && !lstrcmpA(buf, "I64X")) + { + win_skip( "I64 formats not supported\n" ); + return; + } + for (i = 0; i < sizeof(i64_formats)/sizeof(i64_formats[0]); i++) + { + rc = wsprintfA(buf, i64_formats[i].fmt, i64_formats[i].value); + ok(rc == strlen(i64_formats[i].res), "%u: wsprintfA length failure: rc=%d\n", i, rc); + ok(!strcmp(buf, i64_formats[i].res), "%u: wrong result [%s]\n", i, buf); + } } static void wsprintfWTest(void) { - static const WCHAR fmt[] = {'%','0','1','0','l','d','\0'}; - static const WCHAR target[] = {'-','0','0','0','0','0','0','0','0','1', '\0'}; - WCHAR buf[25]; + static const WCHAR fmt_010ld[] = {'%','0','1','0','l','d','\0'}; + static const WCHAR res_010ld[] = {'-','0','0','0','0','0','0','0','0','1', '\0'}; + static const WCHAR fmt_I64x[] = {'%','I','6','4','x',0}; + WCHAR buf[25], fmt[25], res[25]; + unsigned int i; int rc; - rc=wsprintfW(buf, fmt, -1); + rc=wsprintfW(buf, fmt_010ld, -1); if (rc==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED) { win_skip("wsprintfW is not implemented\n"); return; } ok(rc == 10, "wsPrintfW length failure: rc=%d error=%d\n",rc,GetLastError()); - ok((lstrcmpW(buf, target) == 0), + ok((lstrcmpW(buf, res_010ld) == 0), "wsprintfW zero padded negative value failure\n"); + rc = wsprintfW(buf, fmt_I64x, (ULONGLONG)0 ); + if (rc == 4 && !lstrcmpW(buf, fmt_I64x + 1)) + { + win_skip( "I64 formats not supported\n" ); + return; + } + for (i = 0; i < sizeof(i64_formats)/sizeof(i64_formats[0]); i++) + { + MultiByteToWideChar( CP_ACP, 0, i64_formats[i].fmt, -1, fmt, sizeof(fmt)/sizeof(WCHAR) ); + MultiByteToWideChar( CP_ACP, 0, i64_formats[i].res, -1, res, sizeof(res)/sizeof(WCHAR) ); + rc = wsprintfW(buf, fmt, i64_formats[i].value); + ok(rc == lstrlenW(res), "%u: wsprintfW length failure: rc=%d\n", i, rc); + ok(!lstrcmpW(buf, res), "%u: wrong result [%s]\n", i, wine_dbgstr_w(buf)); + } } /* Test if the CharUpper / CharLower functions return true 16 bit results, - if the input is a 16 bit input value. Up to Wine 11-2003 the input value - 0xff returns 0xffffffff. */ + if the input is a 16 bit input value. */ static void CharUpperTest(void) {