Andrew Riedi a écrit :
> changelog: user32: Test destroying the cursor of a parent process.
>
> --
> Andrew Riedi
> ------------------------------------------------------------------------
>
> From 25a6a6a2eee92c4325d730ff85bd7cdf01bf2ace Mon Sep 17 00:00:00 2001
> From: Andrew Riedi <andrewriedi(a)gmail.com>
> Date: Tue, 8 Jan 2008 05:03:55 -0800
> Subject: [PATCH] user32: Test destroying the cursor of a parent process.
>
> ---
> dlls/user32/tests/cursoricon.c | 201 ++++++++++++++++++++++++++++++++++++++++
> 1 files changed, 201 insertions(+), 0 deletions(-)
>
> diff --git a/dlls/user32/tests/cursoricon.c b/dlls/user32/tests/cursoricon.c
> index 781282c..c2beffa 100644
> --- a/dlls/user32/tests/cursoricon.c
> +++ b/dlls/user32/tests/cursoricon.c
> @@ -32,6 +32,205 @@
> #include "wingdi.h"
> #include "winuser.h"
>
> +static char **test_argv;
> +static int test_argc;
> +static HWND child = 0;
> +static HWND parent = 0;
> +static HANDLE child_process;
> +
> +#define PROC_INIT (WM_USER+1)
> +
> +LRESULT CALLBACK callback_child(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
> +{
> + BOOL ret;
> + DWORD error;
> +
> + switch (msg)
> + {
> + /* Destroy the cursor. */
> + case WM_USER+1:
> + SetLastError(0xdeadbeef);
> + ret = DestroyCursor((HCURSOR) lParam);
> + error = GetLastError();
> + todo_wine {
> + ok(!ret, "DestroyCursor on the active cursor succeeded.\n");
> + ok(error == ERROR_DESTROY_OBJECT_OF_OTHER_THREAD,
> + "Last error: 0x%08x\n", error);
> + }
> + return TRUE;
> + case WM_DESTROY:
> + PostQuitMessage(0);
> + return 0;
> + }
> +
> + return DefWindowProc(hwnd, msg, wParam, lParam);
> +}
> +
> +LRESULT CALLBACK callback_parent(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
> +{
> + if (msg == PROC_INIT)
> + {
> + child = (HWND) wParam;
> + return TRUE;
> + }
> +
> + return DefWindowProc(hwnd, msg, wParam, lParam);
> +}
> +
> +static void do_child(void)
> +{
> + WNDCLASS class;
> + MSG msg;
> + BOOL ret;
> +
> + /* Register a new class. */
> + class.style = CS_GLOBALCLASS;
> + class.lpfnWndProc = callback_child;
> + class.cbClsExtra = 0;
> + class.cbWndExtra = 0;
> + class.hInstance = GetModuleHandle(NULL);
> + class.hIcon = NULL;
> + class.hCursor = NULL;
> + class.hbrBackground = NULL;
> + class.lpszMenuName = NULL;
> + class.lpszClassName = "cursor_child";
> +
> + SetLastError(0xdeadbeef);
> + ret = RegisterClass(&class);
> + ok(ret, "Failed to register window class. Error: %d\n", GetLastError());
> +
> + /* Create a window. */
> + child = CreateWindowA("cursor_child", "cursor_child", WS_POPUP | WS_VISIBLE,
> + 0, 0, 200, 200, 0, 0, 0, NULL);
> + ok(child != 0, "CreateWindowA error %d\n", GetLastError());
> +
> + /* Let the parent know our HWND. */
> + PostMessage(parent, PROC_INIT, (WPARAM) child, 0);
> +
> + /* Receive messages. */
> + while ((ret = GetMessage(&msg, child, 0, 0)))
> + {
> + ok(ret != -1, "GetMessage failed. Error: %d\n", GetLastError());
> + TranslateMessage(&msg);
> + DispatchMessage(&msg);
> + }
> +}
> +
> +static void do_parent(void)
> +{
> + char path_name[MAX_PATH];
> + PROCESS_INFORMATION info;
> + STARTUPINFOA startup;
> + WNDCLASS class;
> + MSG msg;
> + BOOL ret;
> +
> + /* Register a new class. */
> + class.style = CS_GLOBALCLASS;
> + class.lpfnWndProc = callback_parent;
> + class.cbClsExtra = 0;
> + class.cbWndExtra = 0;
> + class.hInstance = GetModuleHandle(NULL);
> + class.hIcon = NULL;
> + class.hCursor = NULL;
> + class.hbrBackground = NULL;
> + class.lpszMenuName = NULL;
> + class.lpszClassName = "cursor_parent";
> +
> + SetLastError(0xdeadbeef);
> + ret = RegisterClass(&class);
> + ok(ret, "Failed to register window class. Error: %d\n", GetLastError());
> +
> + /* Create a window. */
> + parent = CreateWindowA("cursor_parent", "cursor_parent", WS_POPUP | WS_VISIBLE,
> + 0, 0, 200, 200, 0, 0, 0, NULL);
> + ok(parent != 0, "CreateWindowA error %d\n", GetLastError());
> +
> + /* Start child process. */
> + memset(&startup, 0, sizeof(startup));
> + startup.cb = sizeof(startup);
> + startup.dwFlags = STARTF_USESHOWWINDOW;
> + startup.wShowWindow = SW_SHOWNORMAL;
> +
> + sprintf(path_name, "%s cursoricon %x", test_argv[0], (unsigned int) parent);
> + ok(CreateProcessA(NULL, path_name, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess failed.\n");
> + child_process = info.hProcess;
> +
> + /* Wait for child window handle. */
> + while ((child == 0) && (ret = GetMessage(&msg, parent, 0, 0)))
> + {
> + ok(ret != -1, "GetMessage failed. Error: %d\n", GetLastError());
> + TranslateMessage(&msg);
> + DispatchMessage(&msg);
> + }
> +}
> +
> +static void init(void)
> +{
> + test_argc = winetest_get_mainargs(&test_argv);
> +
> + /* Child process. */
> + if (test_argc >= 3)
> + {
> + sscanf (test_argv[2], "%x", (unsigned int *) &parent);
> +
> + ok(parent != NULL, "Parent not found.\n");
> + if (parent == NULL)
> + exit(1);
> +
> + do_child();
> + exit(0);
> + }
> + else
> + {
> + do_parent();
> + }
> +}
> +
> +static void finish_process(void)
> +{
> + DWORD exit_code;
> + BOOL ret;
> +
> + SendMessage(child, WM_CLOSE, 0, 0);
> + ok(WaitForSingleObject(child_process, 30000) == WAIT_OBJECT_0, "Child process termination failed.\n");
> +
> + ret = GetExitCodeProcess(child_process, &exit_code);
> + ok(ret, "GetExitCodeProcess() failed. Error: 0x%08x\n", GetLastError());
> + ok(exit_code == 0, "Exit code == %d.\n", exit_code);
> +}
> +
> +static void test_child_process(void)
> +{
> + static const BYTE bmp_bits[4096];
> + HCURSOR cursor;
> + ICONINFO cursorInfo;
> + UINT display_bpp;
> + HDC hdc;
> +
> + /* Create and set a dummy cursor. */
> + hdc = GetDC(0);
> + display_bpp = GetDeviceCaps(hdc, BITSPIXEL);
> + ReleaseDC(0, hdc);
> +
> + cursorInfo.fIcon = FALSE;
> + cursorInfo.xHotspot = 0;
> + cursorInfo.yHotspot = 0;
> + cursorInfo.hbmMask = CreateBitmap(32, 32, 1, 1, bmp_bits);
> + cursorInfo.hbmColor = CreateBitmap(32, 32, 1, display_bpp, bmp_bits);
> +
> + cursor = CreateIconIndirect(&cursorInfo);
> + ok(cursor != NULL, "CreateIconIndirect returned %p.\n", cursor);
> +
> + SetCursor(cursor);
> +
> + /* Destroy the cursor. */
> + SendMessage(child, WM_USER+1, (WPARAM) parent, (LPARAM) cursor);
> +
> + /* Finish the child process. */
> + finish_process();
> +}
> +
> static void test_CopyImage_Check(HBITMAP bitmap, UINT flags, INT copyWidth, INT copyHeight,
> INT expectedWidth, INT expectedHeight, WORD expectedDepth, BOOL dibExpected)
> {
> @@ -471,6 +670,7 @@ static void test_DestroyCursor(void)
>
> START_TEST(cursoricon)
> {
> + init();
> test_CopyImage_Bitmap(1);
> test_CopyImage_Bitmap(4);
> test_CopyImage_Bitmap(8);
> @@ -480,4 +680,5 @@ START_TEST(cursoricon)
> test_initial_cursor();
> test_CreateIcon();
> test_DestroyCursor();
> + test_child_process();
> }
>
> ------------------------------------------------------------------------
>
>
>
IMO, the ok() tests in the child process are a bad idea (they won't be
counted, nor returned as errors, by the parent process)
all the tests should be done in parent, see kernel32/tests/process.c for
some example on how to do it properly
A+
--
Eric Pouech
"The problem with designing something completely foolproof is to underestimate the ingenuity of a complete idiot." (Douglas Adams)