[PATCH] user32: Implement InternalGetWindowIcon().

Zebediah Figura z.figura12 at gmail.com
Tue May 18 01:16:16 CDT 2021


Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47915
Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
 dlls/user32/tests/win.c | 109 +++++++++++++++++++++++++++++++++++++++-
 dlls/user32/user32.spec |   1 +
 dlls/user32/win.c       |  51 +++++++++++++++++++
 3 files changed, 160 insertions(+), 1 deletion(-)

diff --git a/dlls/user32/tests/win.c b/dlls/user32/tests/win.c
index a37afd2dc5e..3f58f7a2b11 100644
--- a/dlls/user32/tests/win.c
+++ b/dlls/user32/tests/win.c
@@ -64,6 +64,7 @@ static BOOL (WINAPI *pGetWindowDisplayAffinity)(HWND hwnd, DWORD *affinity);
 static BOOL (WINAPI *pSetWindowDisplayAffinity)(HWND hwnd, DWORD affinity);
 static BOOL (WINAPI *pAdjustWindowRectExForDpi)(LPRECT,DWORD,BOOL,DWORD,UINT);
 static BOOL (WINAPI *pSystemParametersInfoForDpi)(UINT,UINT,void*,UINT,UINT);
+static HICON (WINAPI *pInternalGetWindowIcon)(HWND window, UINT type);
 
 static BOOL test_lbuttondown_flag;
 static DWORD num_gettext_msgs;
@@ -2369,6 +2370,19 @@ todo_wine
     DestroyWindow(mdi_hwndMain);
 }
 
+static DWORD WINAPI internal_get_icon_thread(void *arg)
+{
+    HICON icon;
+    BOOL ret;
+
+    icon = pInternalGetWindowIcon( arg, ICON_BIG );
+    ok( icon != 0, "expected nonzero icon\n" );
+    ret = DestroyIcon( icon );
+    ok( ret, "got error %u\n", GetLastError() );
+
+    return 0;
+}
+
 static void test_icons(void)
 {
     WNDCLASSEXA cls;
@@ -2377,7 +2391,9 @@ static void test_icons(void)
     HICON icon2 = LoadIconA(0, (LPCSTR)IDI_QUESTION);
     HICON small_icon = LoadImageA(0, (LPCSTR)IDI_APPLICATION, IMAGE_ICON,
                                   GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), LR_SHARED );
-    HICON res;
+    HICON res, res2, res3;
+    HANDLE thread;
+    BOOL ret;
 
     cls.cbSize = sizeof(cls);
     cls.style = 0;
@@ -2400,35 +2416,125 @@ static void test_icons(void)
 
     res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
     ok( res == 0, "wrong big icon %p/0\n", res );
+    SetLastError( 0xdeadbeef );
+    res2 = pInternalGetWindowIcon( hwnd, ICON_BIG );
+    ok( res2 != 0, "expected nonzero icon\n" );
+    ok( GetLastError() == 0xdeadbeef, "got error %u\n", GetLastError() );
+    res3 = pInternalGetWindowIcon( hwnd, ICON_BIG );
+    ok( res3 && res3 != res2, "got %p\n", res3 );
+    ret = DestroyIcon( res2 );
+    ok( ret, "got error %u\n", GetLastError() );
+    ret = DestroyIcon( res3 );
+    ok( ret, "got error %u\n", GetLastError() );
+
     res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_BIG, (LPARAM)icon );
     ok( res == 0, "wrong previous big icon %p/0\n", res );
     res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
     ok( res == icon, "wrong big icon after set %p/%p\n", res, icon );
+    res2 = pInternalGetWindowIcon( hwnd, ICON_BIG );
+    ok( res2 && res2 != icon, "got %p\n", res2 );
+    res3 = pInternalGetWindowIcon( hwnd, ICON_BIG );
+    ok( res3 && res3 != res2, "got %p\n", res3 );
+    ret = DestroyIcon( res2 );
+    ok( ret, "got error %u\n", GetLastError() );
+    ret = DestroyIcon( res3 );
+    ok( ret, "got error %u\n", GetLastError() );
+
     res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_BIG, (LPARAM)icon2 );
     ok( res == icon, "wrong previous big icon %p/%p\n", res, icon );
     res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
     ok( res == icon2, "wrong big icon after set %p/%p\n", res, icon2 );
+    res2 = pInternalGetWindowIcon( hwnd, ICON_BIG );
+    ok( res2 && res2 != icon2, "got %p\n", res2 );
+    ret = DestroyIcon( res2 );
+    ok( ret, "got error %u\n", GetLastError() );
 
     res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL, 0 );
     ok( res == 0, "wrong small icon %p/0\n", res );
+    res2 = pInternalGetWindowIcon( hwnd, ICON_SMALL );
+    ok( res2 != 0, "expected nonzero icon\n" );
+    res3 = pInternalGetWindowIcon( hwnd, ICON_SMALL );
+    ok( res3 && res3 != res2, "got %p\n", res3 );
+    ret = DestroyIcon( res2 );
+    ok( ret, "got error %u\n", GetLastError() );
+    ret = DestroyIcon( res3 );
+    ok( ret, "got error %u\n", GetLastError() );
+
     res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
     ok( (res && res != small_icon && res != icon2) || broken(!res), "wrong small2 icon %p\n", res );
+    res2 = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
+    ok( res2 == res, "expected icon to match\n" );
+    res2 = pInternalGetWindowIcon( hwnd, ICON_SMALL2 );
+    ok( res2 && res2 != small_icon && res2 != icon2 && res2 != res, "got %p\n", res2 );
+    res3 = pInternalGetWindowIcon( hwnd, ICON_SMALL2 );
+    ok( res3 && res3 != res2, "got %p\n", res3 );
+    ret = DestroyIcon( res2 );
+    ok( ret, "got error %u\n", GetLastError() );
+    ret = DestroyIcon( res3 );
+    ok( ret, "got error %u\n", GetLastError() );
+
     res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_SMALL, (LPARAM)icon );
     ok( res == 0, "wrong previous small icon %p/0\n", res );
     res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL, 0 );
     ok( res == icon, "wrong small icon after set %p/%p\n", res, icon );
+    res2 = pInternalGetWindowIcon( hwnd, ICON_SMALL );
+    ok( res2 && res2 != icon, "got %p\n", res2 );
+    res3 = pInternalGetWindowIcon( hwnd, ICON_SMALL );
+    ok( res3 && res3 != res2, "got %p\n", res3 );
+    ret = DestroyIcon( res2 );
+    ok( ret, "got error %u\n", GetLastError() );
+    ret = DestroyIcon( res3 );
+    ok( ret, "got error %u\n", GetLastError() );
+
     res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
     ok( res == icon || broken(!res), "wrong small2 icon after set %p/%p\n", res, icon );
+    res2 = pInternalGetWindowIcon( hwnd, ICON_SMALL2 );
+    ok( res2 && res2 != icon && res2 != res, "got %p\n", res2 );
+    res3 = pInternalGetWindowIcon( hwnd, ICON_SMALL2 );
+    ok( res3 && res3 != res2, "got %p\n", res3 );
+    ret = DestroyIcon( res2 );
+    ok( ret, "got error %u\n", GetLastError() );
+    ret = DestroyIcon( res3 );
+    ok( ret, "got error %u\n", GetLastError() );
+
     res = (HICON)SendMessageA( hwnd, WM_SETICON, ICON_SMALL, (LPARAM)small_icon );
     ok( res == icon, "wrong previous small icon %p/%p\n", res, icon );
     res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL, 0 );
     ok( res == small_icon, "wrong small icon after set %p/%p\n", res, small_icon );
+    res2 = pInternalGetWindowIcon( hwnd, ICON_SMALL );
+    ok( res2 && res2 != small_icon, "got %p\n", res2 );
+    ret = DestroyIcon( res2 );
+    ok( ret, "got error %u\n", GetLastError() );
+
     res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_SMALL2, 0 );
     ok( res == small_icon || broken(!res), "wrong small2 icon after set %p/%p\n", res, small_icon );
+    res2 = pInternalGetWindowIcon( hwnd, ICON_SMALL2 );
+    ok( res2 && res2 != small_icon && res2 != res, "got %p\n", res2 );
+    ret = DestroyIcon( res2 );
+    ok( ret, "got error %u\n", GetLastError() );
 
     /* make sure the big icon hasn't changed */
     res = (HICON)SendMessageA( hwnd, WM_GETICON, ICON_BIG, 0 );
     ok( res == icon2, "wrong big icon after set %p/%p\n", res, icon2 );
+    res2 = pInternalGetWindowIcon( hwnd, ICON_BIG );
+    ok( res2 && res2 != icon2, "got %p\n", res2 );
+    ret = DestroyIcon( res2 );
+    ok( ret, "got error %u\n", GetLastError() );
+
+    SetLastError( 0xdeadbeef );
+    res = pInternalGetWindowIcon( NULL, ICON_BIG );
+    ok( !res, "got %p\n", res );
+    ok( GetLastError() == ERROR_INVALID_WINDOW_HANDLE, "got error %u\n", GetLastError() );
+
+    SetLastError( 0xdeadbeef );
+    res = pInternalGetWindowIcon( hwnd, 0xdeadbeef );
+    ok( !res, "got %p\n", res );
+    ok( GetLastError() == ERROR_INVALID_PARAMETER, "got error %u\n", GetLastError() );
+
+    thread = CreateThread( NULL, 0, internal_get_icon_thread, hwnd, 0, NULL );
+    ret = WaitForSingleObject( thread, 1000 );
+    ok( !ret, "wait timed out\n" );
+    CloseHandle( thread );
 
     DestroyWindow( hwnd );
 }
@@ -12027,6 +12133,7 @@ START_TEST(win)
     pSetWindowDisplayAffinity = (void *)GetProcAddress( user32, "SetWindowDisplayAffinity" );
     pAdjustWindowRectExForDpi = (void *)GetProcAddress( user32, "AdjustWindowRectExForDpi" );
     pSystemParametersInfoForDpi = (void *)GetProcAddress( user32, "SystemParametersInfoForDpi" );
+    pInternalGetWindowIcon = (void *)GetProcAddress( user32, "InternalGetWindowIcon" );
 
     if (argc == 4)
     {
diff --git a/dlls/user32/user32.spec b/dlls/user32/user32.spec
index 190ee74fd6c..391e304a063 100644
--- a/dlls/user32/user32.spec
+++ b/dlls/user32/user32.spec
@@ -445,6 +445,7 @@
 @ stdcall InsertMenuItemA(long long long ptr)
 @ stdcall InsertMenuItemW(long long long ptr)
 @ stdcall InsertMenuW(long long long long ptr)
+@ stdcall InternalGetWindowIcon(ptr long)
 @ stdcall InternalGetWindowText(long ptr long)
 @ stdcall IntersectRect(ptr ptr ptr)
 @ stdcall InvalidateRect(long ptr long)
diff --git a/dlls/user32/win.c b/dlls/user32/win.c
index 680defc2071..bd540953278 100644
--- a/dlls/user32/win.c
+++ b/dlls/user32/win.c
@@ -4239,3 +4239,54 @@ BOOL WINAPI SetWindowCompositionAttribute(HWND hwnd, void *data)
     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
     return FALSE;
 }
+
+/***********************************************************************
+ *              InternalGetWindowIcon   (USER32.@)
+ */
+HICON WINAPI InternalGetWindowIcon( HWND hwnd, UINT type )
+{
+    WND *win = WIN_GetPtr( hwnd );
+    HICON ret;
+
+    TRACE( "hwnd %p, type %#x\n", hwnd, type );
+
+    if (!win)
+    {
+        SetLastError( ERROR_INVALID_WINDOW_HANDLE );
+        return 0;
+    }
+    if (win == WND_OTHER_PROCESS || win == WND_DESKTOP)
+    {
+        if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
+        return 0;
+    }
+
+    switch (type)
+    {
+        case ICON_BIG:
+            ret = win->hIcon;
+            if (!ret) ret = (HICON)GetClassLongPtrW( hwnd, GCLP_HICON );
+            break;
+
+        case ICON_SMALL:
+            ret = win->hIconSmall;
+            if (!ret) ret = (HICON)GetClassLongPtrW( hwnd, GCLP_HICONSM );
+            break;
+
+        case ICON_SMALL2:
+            ret = win->hIconSmall ? win->hIconSmall : win->hIconSmall2;
+            if (!ret) ret = (HICON)GetClassLongPtrW( hwnd, GCLP_HICONSM );
+            break;
+
+        default:
+            SetLastError( ERROR_INVALID_PARAMETER );
+            WIN_ReleasePtr( win );
+            return 0;
+    }
+
+    if (!ret) ret = LoadIconW( 0, (const WCHAR *)IDI_WINLOGO );
+    ret = CopyIcon( ret );
+
+    WIN_ReleasePtr( win );
+    return ret;
+}
-- 
2.30.2




More information about the wine-devel mailing list