From 251c8ea94d813c7d5c84fd32752830eabc95e523 Mon Sep 17 00:00:00 2001 From: Daniel Santos Date: Tue, 9 Jun 2009 17:00:39 -0500 Subject: user32/tests: Add more intensive tests for SetCursor. --- dlls/user32/tests/cursoricon.c | 152 ++++++++++++++++++++++++++++++++++------ 1 files changed, 131 insertions(+), 21 deletions(-) diff --git a/dlls/user32/tests/cursoricon.c b/dlls/user32/tests/cursoricon.c index 9475534..a3571f5 100644 --- a/dlls/user32/tests/cursoricon.c +++ b/dlls/user32/tests/cursoricon.c @@ -76,10 +76,11 @@ 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"); + todo_wine 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); + error == 0xdeadbeef, /* vista */ + "Last error: %u\n", error); return TRUE; case WM_DESTROY: PostQuitMessage(0); @@ -768,9 +769,88 @@ static void test_LoadImageFile(const unsigned char * image_data, DeleteFileA(filename); } +/************************************************************************* + * test_SetCursor + * + * Encapsulates tests to SetCursor() function. + * + * PARAMS + * target [I] A handle to use when calling SetCursor + * shouldFail [I] Rather of not it should fail + * line [I] The line this function was called from. + * retValTodo [I] True if return value is broken in wine (wine's return value + * is broken in some, but not all cases) + * + * RETURNS + * The return value of the SetCursor() call. + */ +static HCURSOR test_SetCursor(HANDLE hNewCursor, BOOL shouldFail, int line, + BOOL retValTodo) +{ + HCURSOR cursor1, cursor2, cursor3; + DWORD error; + + /* GetCursor should have no errors */ + SetLastError(0xdeadbeef); + cursor1 = GetCursor(); + error = GetLastError(); + ok_(__FILE__, line)(error == 0xdeadbeef, + "GetCursor() changed last error: %u.\n", + error); + + /* Call SetCursor on supplied handle */ + SetLastError(0xdeadbeef); + cursor2 = SetCursor(hNewCursor); + error = GetLastError(); + cursor3 = GetCursor(); + + if (shouldFail) { + todo_wine ok_(__FILE__, line)(error == ERROR_INVALID_CURSOR_HANDLE, + "Last error is %u (0x%08x), expected " + "ERROR_INVALID_CURSOR_HANDLE (%u).\n", + error, error, ERROR_INVALID_CURSOR_HANDLE); + + if(retValTodo) { + todo_wine ok_(__FILE__, line)(!cursor2, + "SetCursor() returned non-zero (%p).\n", + cursor2); + } else { + ok_(__FILE__, line)(!cursor2, + "SetCursor() returned non-zero (%p).\n", + cursor2); + } + + todo_wine ok_(__FILE__, line)(cursor1 == cursor3, + "SetCursor() changed cursor.\n"); + } else { + /* WinXP: For some reason, SetCursor() is returning NULL when hNewCursor + * is NULL. Is it this way on other versions? MSDN says it should + * return the old cursor. + */ + if(hNewCursor) { + ok_(__FILE__, line)(cursor1 == cursor2, + "SetCursor() did not return the previous cursor, " + "expected %p, got %p.\n", + cursor1, cursor2); + } else { + todo_wine ok_(__FILE__, line)(!cursor2, + "SetCursor() returned %p, expected NULL.\n", + cursor2); + } + + ok_(__FILE__, line)(cursor3 == hNewCursor, + "GetCursor() did not return the value we previously passed to " + "SetCursor(). Expected %p, got %p.\n", + hNewCursor, cursor3); + } + + return cursor2; +} + static void test_LoadImage(void) { HANDLE handle; + HCURSOR cursor; BOOL ret; DWORD error, bytes_written; CURSORICONFILEDIR *icon_data; @@ -845,6 +925,12 @@ static void test_LoadImage(void) ok(icon_info.hbmMask != NULL, "No hbmMask!\n"); } + /* Test SetCursor with this icon */ + cursor = test_SetCursor(handle, FALSE, __LINE__, TRUE); + + /* Now change it back to the previous cursor */ + test_SetCursor(cursor, FALSE, __LINE__, FALSE); + /* Clean up. */ SetLastError(0xdeadbeef); ret = DestroyCursor(handle); @@ -855,6 +941,10 @@ static void test_LoadImage(void) HeapFree(GetProcessHeap(), 0, icon_data); DeleteFileA("icon.ico"); + /* Test passing invalid handles to SetCursor. */ + test_SetCursor(handle, TRUE, __LINE__, FALSE); + test_SetCursor(GetCurrentThread(), TRUE, __LINE__, TRUE); + test_LoadImageFile(bmpimage, sizeof(bmpimage), "bmp", 1); test_LoadImageFile(gifimage, sizeof(gifimage), "gif", 0); test_LoadImageFile(gif4pixel, sizeof(gif4pixel), "gif", 0); @@ -981,29 +1071,53 @@ static void test_DestroyCursor(void) if(!cursor) { return; } - SetCursor(cursor); + test_SetCursor(cursor, FALSE, __LINE__, FALSE); + + /* When you attempt to destroy the current cursor, windows obliges you. + * On win9x, it returns TRUE (indicating success) and on NT it returns + * FALSE, but neither sets the last error. + */ SetLastError(0xdeadbeef); ret = DestroyCursor(cursor); - ok(!ret || broken(ret) /* succeeds on win9x */, "DestroyCursor on the active cursor succeeded\n"); error = GetLastError(); - ok(error == 0xdeadbeef, "Last error: %u\n", error); + ok(error == 0xdeadbeef, "Last error: 0x%x.\n", error); + ok(!ret || broken(ret) /* succeeds on win9x */, + "DestroyCursor on the active cursor returned TRUE.\n"); + + /* QUESTION: This if statment effectively skips these tests on win9x, do we + * want to do that? */ if (!ret) { cursor2 = GetCursor(); ok(cursor2 == cursor, "Active was set to %p when trying to destroy it\n", cursor2); - SetCursor(NULL); - /* Trying to destroy the cursor properly fails now with - * ERROR_INVALID_CURSOR_HANDLE. This happens because we called - * DestroyCursor() 2+ times after calling SetCursor(). The calls to - * GetCursor() and SetCursor(NULL) in between make no difference. */ + /* Make sure showing/hiding the invalid cursor still works. */ + SetLastError(0xdeadbeef); + ok(ShowCursor(TRUE) == 1, "Cursor count != 1\n"); + ok(GetLastError() == 0xdeadbeef, "Last error: 0x%x.\n", GetLastError()); + + SetLastError(0xdeadbeef); + ok(ShowCursor(FALSE) == 0, "Cursor count != 0\n"); + ok(GetLastError() == 0xdeadbeef, "Last error: 0x%x.\n", GetLastError()); + test_SetCursor(NULL, FALSE, __LINE__, FALSE); + + /* Trying to destroy the cursor again fails now with + * ERROR_INVALID_CURSOR_HANDLE. This happens because we've previously + * called DestroyCursor() on this handle. The calls to GetCursor() + * and SetCursor(NULL) in between make no difference. It would appear + * that windows doesn't mind having an invalid cursor handle as its + * current cursor much the way a comatose person doesn't mind a + * stranger in their hospital room. + */ + SetLastError(0xdeadbeef); ret = DestroyCursor(cursor); todo_wine { ok(!ret, "DestroyCursor succeeded.\n"); error = GetLastError(); - ok(error == ERROR_INVALID_CURSOR_HANDLE || error == 0xdeadbeef, /* vista */ - "Last error: 0x%08x\n", error); + ok(error == ERROR_INVALID_CURSOR_HANDLE + || broken(error == 0xdeadbeef), /* vista */ + "Last error: 0x%08x\n", error); } } @@ -1015,17 +1129,13 @@ static void test_DestroyCursor(void) SetLastError(0xdeadbeef); ret = DestroyCursor(cursor); - ok(ret || broken(!ret) /* fails on win9x */, "DestroyCursor on the active cursor failed.\n"); error = GetLastError(); - ok(error == 0xdeadbeef, "Last error: 0x%08x\n", error); + ok(error == 0xdeadbeef, "Last error: 0x%x.\n", error); + ok(ret || broken(!ret) /* fails on win9x */, + "DestroyCursor on OEM cursor failed.\n"); /* Try setting the cursor to a destroyed OEM cursor. */ - SetLastError(0xdeadbeef); - SetCursor(cursor); - error = GetLastError(); - todo_wine { - ok(error == 0xdeadbeef, "Last error: 0x%08x\n", error); - } + test_SetCursor(cursor, FALSE, __LINE__, FALSE); /* Check if LoadCursor() returns the same handle with the same icon. */ cursor2 = LoadCursor(NULL, IDC_ARROW); -- 1.6.3.1