Signed-off-by: Ziqing Hui zhui@codeweavers.com --- dlls/user32/tests/cursoricon.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/dlls/user32/tests/cursoricon.c b/dlls/user32/tests/cursoricon.c index 33ca2e3cb63..267aff70fb5 100644 --- a/dlls/user32/tests/cursoricon.c +++ b/dlls/user32/tests/cursoricon.c @@ -2505,7 +2505,7 @@ static void test_ShowCursor(void) memset( &info, 0, sizeof(info) ); info.cbSize = sizeof(info); ok( pGetCursorInfo( &info ), "GetCursorInfo failed\n" ); - ok( info.flags & CURSOR_SHOWING, "cursor not shown in info\n" ); + ok( info.flags & (CURSOR_SHOWING | CURSOR_SUPPRESSED), "Got unexpected cursor state\n" ); }
event_start = CreateEventW( NULL, FALSE, FALSE, NULL ); @@ -2529,7 +2529,7 @@ static void test_ShowCursor(void) info.cbSize = sizeof(info); ok( pGetCursorInfo( &info ), "GetCursorInfo failed\n" ); /* global show count is not affected since we don't have a window */ - ok( info.flags & CURSOR_SHOWING, "cursor not shown in info\n" ); + ok( info.flags & (CURSOR_SHOWING | CURSOR_SUPPRESSED), "Got unexpected cursor state\n" ); }
parent_id = 0; @@ -2582,7 +2582,7 @@ static void test_ShowCursor(void) { info.cbSize = sizeof(info); ok( pGetCursorInfo( &info ), "GetCursorInfo failed\n" ); - ok( info.flags & CURSOR_SHOWING, "cursor not shown in info\n" ); + ok( info.flags & (CURSOR_SHOWING | CURSOR_SUPPRESSED), "Got unexpected cursor state\n" ); }
count = ShowCursor( TRUE ); @@ -2594,7 +2594,7 @@ static void test_ShowCursor(void) { info.cbSize = sizeof(info); ok( pGetCursorInfo( &info ), "GetCursorInfo failed\n" ); - ok( info.flags & CURSOR_SHOWING, "cursor not shown in info\n" ); + ok( info.flags & (CURSOR_SHOWING | CURSOR_SUPPRESSED), "Got unexpected cursor state\n" ); } }
The tests show that shared icon created by CreateIconFromResourceEx() won't be destroyed by DestroyIcon(). However, a second call to it for the same icon bits will return a different handle.
Signed-off-by: Ziqing Hui zhui@codeweavers.com --- dlls/user32/tests/cursoricon.c | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-)
diff --git a/dlls/user32/tests/cursoricon.c b/dlls/user32/tests/cursoricon.c index 267aff70fb5..b1a8c48b35d 100644 --- a/dlls/user32/tests/cursoricon.c +++ b/dlls/user32/tests/cursoricon.c @@ -1541,7 +1541,7 @@ static void test_LoadImage(void)
static void test_CreateIconFromResource(void) { - HANDLE handle; + HANDLE handle, old_handle; BOOL ret; DWORD error; BITMAPINFOHEADER *icon_header; @@ -1646,7 +1646,6 @@ static void test_CreateIconFromResource(void) * 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 */ @@ -1678,6 +1677,35 @@ static void test_CreateIconFromResource(void) ok(ret, "DestroyCursor() failed.\n"); error = GetLastError(); ok(error == 0xdeadbeef, "Last error: %u\n", error); + + /* Test creating and destroying a non-shared icon. */ + handle = CreateIconFromResourceEx((BYTE *)icon_header, ICON_RES_SIZE, TRUE, 0x00030000, + 0, 0, LR_DEFAULTSIZE); + ok(handle != NULL, "Create icon failed, error %u.\n", GetLastError()); + ret = DestroyIcon(handle); + ok(ret, "Destroy icon failed, error %u.\n", GetLastError()); + ret = GetIconInfo(handle, &icon_info); + ok(!ret, "Get info succeeded.\n"); + ok(GetLastError() == ERROR_INVALID_CURSOR_HANDLE, "Got unexpected error %u.\n", error); + + /* Test creating and destroying a shared icon from heap bits. */ + handle = CreateIconFromResourceEx((BYTE *)icon_header, ICON_RES_SIZE, TRUE, 0x00030000, + 0, 0, LR_DEFAULTSIZE | LR_SHARED); + ok(handle != NULL, "Create icon failed, error %u.\n", GetLastError()); + ret = DestroyIcon(handle); + ok(ret, "Destroy icon failed, error %u.\n", GetLastError()); + ret = GetIconInfo(handle, &icon_info); + todo_wine + ok(ret, "Get info failed, error %u.\n", GetLastError()); + + /* Test creating a shared icon from heap bits that has been created before. */ + old_handle = handle; + handle = CreateIconFromResourceEx((BYTE *)icon_header, ICON_RES_SIZE, TRUE, 0x00030000, + 0, 0, LR_DEFAULTSIZE | LR_SHARED); + ok(handle != NULL, "Create icon failed, error %u.\n", GetLastError()); + ok(handle != old_handle, "Expect a different handle.\n"); + + HeapFree(GetProcessHeap(), 0, hotspot); }
static int check_cursor_data( HDC hdc, HCURSOR hCursor, void *data, int length)
Signed-off-by: Ziqing Hui zhui@codeweavers.com --- dlls/user32/tests/cursoricon.c | 49 ++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+)
diff --git a/dlls/user32/tests/cursoricon.c b/dlls/user32/tests/cursoricon.c index b1a8c48b35d..8b7640682f4 100644 --- a/dlls/user32/tests/cursoricon.c +++ b/dlls/user32/tests/cursoricon.c @@ -1539,6 +1539,13 @@ static void test_LoadImage(void) test_LoadImage_working_directory(); }
+static BOOL CALLBACK find_res_proc(HMODULE module, LPCSTR type, LPSTR name, LONG_PTR param) +{ + char **res_name = (char **)param; + *res_name = name; + return FALSE; +} + static void test_CreateIconFromResource(void) { HANDLE handle, old_handle; @@ -1547,6 +1554,13 @@ static void test_CreateIconFromResource(void) BITMAPINFOHEADER *icon_header; INT16 *hotspot; ICONINFO icon_info; + HMODULE user32; + char *res_name; + HRSRC rsrc; + HGLOBAL res; + BYTE *bits; + UINT size; +
#define ICON_RES_WIDTH 32 #define ICON_RES_HEIGHT 32 @@ -1706,6 +1720,41 @@ static void test_CreateIconFromResource(void) ok(handle != old_handle, "Expect a different handle.\n");
HeapFree(GetProcessHeap(), 0, hotspot); + + /* Get icon resource bits */ + user32 = GetModuleHandleA("user32.dll"); + EnumResourceNamesA(user32, (const char *)RT_GROUP_ICON, find_res_proc, (LONG_PTR)&res_name); + rsrc = FindResourceA(user32, res_name, (const char *)RT_GROUP_ICON); + ok(rsrc != NULL, "Find resource failed, error %u.\n", GetLastError()); + res = LoadResource(user32, rsrc); + ok(res != NULL, "Load resource failed, error %u.\n", GetLastError()); + bits = LockResource(res); + ok(bits != NULL, "Lock resource failed, error %u.\n", GetLastError()); + + res_name = (char *)LookupIconIdFromDirectory(bits, TRUE); + rsrc = FindResourceA(user32, res_name, (const char *)RT_ICON); + ok(rsrc != NULL, "Find resource failed, error %u.\n", GetLastError()); + size = SizeofResource(user32, rsrc); + ok(size != 0, "Get resource size failed, error %u.\n", GetLastError()); + res = LoadResource(user32, rsrc); + ok(res != NULL, "Load resource failed, error %u.\n", GetLastError()); + bits = LockResource(res); + ok(bits != NULL, "Lock resource failed, error %u.\n", GetLastError()); + + /* Test creating and destroying a shared icon from resource bits. */ + handle = CreateIconFromResourceEx(bits, size, TRUE, 0x00030000, 0, 0, LR_DEFAULTSIZE | LR_SHARED); + ok(handle != NULL, "Create icon failed, error %u\n", GetLastError()); + ret = DestroyIcon(handle); + ok(ret, "Destroy icon failed, error %u.\n", GetLastError()); + ret = GetIconInfo(handle, &icon_info); + todo_wine + ok(ret, "Get info failed, error %u.\n", GetLastError()); + + /* Test creating a shared icon from resource bits that has been created before. */ + old_handle = handle; + handle = CreateIconFromResourceEx(bits, size, TRUE, 0x00030000, 0, 0, LR_DEFAULTSIZE | LR_SHARED); + ok(handle != NULL, "Create icon failed, error %u.\n", GetLastError()); + ok(handle != old_handle, "Expect a different handle.\n"); }
static int check_cursor_data( HDC hdc, HCURSOR hCursor, void *data, int length)
It makes sure that shared icon/cursor created by CreateIconFromResourceEx() won't be destroyed by Destroy{Icon,Cursor}().
Signed-off-by: Ziqing Hui zhui@codeweavers.com --- dlls/user32/cursoricon.c | 13 +++++++++---- dlls/user32/tests/cursoricon.c | 2 -- 2 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/dlls/user32/cursoricon.c b/dlls/user32/cursoricon.c index ba5c5d8904c..f107255c8c0 100644 --- a/dlls/user32/cursoricon.c +++ b/dlls/user32/cursoricon.c @@ -76,6 +76,7 @@ struct cursoricon_object HMODULE module; /* module for icons loaded from resources */ LPWSTR resname; /* resource name for icons loaded from resources */ HRSRC rsrc; /* resource for shared icons */ + BOOL is_shared; /* whether this object is shared */ BOOL is_icon; /* whether icon or cursor */ BOOL is_ani; /* whether this object is a static cursor or an animated cursor */ UINT delay; /* delay between this frame and the next (in jiffies) */ @@ -1224,10 +1225,14 @@ done: } else info->resname = MAKEINTRESOURCEW( LOWORD(resname) );
- if (module && (cFlag & LR_SHARED)) + if (cFlag & LR_SHARED) { - info->rsrc = rsrc; - list_add_head( &icon_cache, &info->entry ); + info->is_shared = TRUE; + if (module) + { + info->rsrc = rsrc; + list_add_head( &icon_cache, &info->entry ); + } } release_user_handle_ptr( info ); } @@ -1871,7 +1876,7 @@ BOOL WINAPI DestroyIcon( HICON hIcon )
if (obj) { - BOOL shared = (obj->rsrc != NULL); + BOOL shared = obj->is_shared; release_user_handle_ptr( obj ); ret = (NtUserGetCursor() != hIcon); if (!shared) free_icon_handle( hIcon ); diff --git a/dlls/user32/tests/cursoricon.c b/dlls/user32/tests/cursoricon.c index 8b7640682f4..53c25a831e8 100644 --- a/dlls/user32/tests/cursoricon.c +++ b/dlls/user32/tests/cursoricon.c @@ -1709,7 +1709,6 @@ static void test_CreateIconFromResource(void) ret = DestroyIcon(handle); ok(ret, "Destroy icon failed, error %u.\n", GetLastError()); ret = GetIconInfo(handle, &icon_info); - todo_wine ok(ret, "Get info failed, error %u.\n", GetLastError());
/* Test creating a shared icon from heap bits that has been created before. */ @@ -1747,7 +1746,6 @@ static void test_CreateIconFromResource(void) ret = DestroyIcon(handle); ok(ret, "Destroy icon failed, error %u.\n", GetLastError()); ret = GetIconInfo(handle, &icon_info); - todo_wine ok(ret, "Get info failed, error %u.\n", GetLastError());
/* Test creating a shared icon from resource bits that has been created before. */