[PATCH] shell32: Resize from the first available icon to fill missing icon sizes.

Gabriel Ivăncescu gabrielopcode at gmail.com
Fri Mar 19 09:07:51 CDT 2021


The issue is not in PrivateExtractIconsW: it fails on Windows on such
malformed executables as well (see bug report).

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45696
Signed-off-by: Gabriel Ivăncescu <gabrielopcode at gmail.com>
---
 dlls/shell32/iconcache.c | 27 +++++++++++++++++++++++++--
 1 file changed, 25 insertions(+), 2 deletions(-)

diff --git a/dlls/shell32/iconcache.c b/dlls/shell32/iconcache.c
index d1be540..265cb87 100644
--- a/dlls/shell32/iconcache.c
+++ b/dlls/shell32/iconcache.c
@@ -362,6 +362,7 @@ static INT SIC_LoadIcon (const WCHAR *sourcefile, INT index, DWORD flags)
 {
     HICON hicons[ARRAY_SIZE(shell_imagelists)] = { 0 };
     HICON hshortcuts[ARRAY_SIZE(hicons)] = { 0 };
+    HICON first_icon = NULL;
     unsigned int i;
     SIZE size;
     INT ret = -1;
@@ -369,8 +370,30 @@ static INT SIC_LoadIcon (const WCHAR *sourcefile, INT index, DWORD flags)
     for (i = 0; i < ARRAY_SIZE(hicons); i++)
     {
         get_imagelist_icon_size( i, &size );
-        if (!PrivateExtractIconsW( sourcefile, index, size.cx, size.cy, &hicons[i], 0, 1, 0 ))
-            WARN("Failed to load icon %d from %s.\n", index, debugstr_w(sourcefile));
+        PrivateExtractIconsW( sourcefile, index, size.cx, size.cy, &hicons[i], 0, 1, 0 );
+        if (!hicons[i])
+            WARN("Failed to load icon %d (%dx%d) from %s.\n", index, size.cx, size.cy, debugstr_w(sourcefile));
+        else if (!first_icon)
+            first_icon = hicons[i];
+    }
+
+    if (!first_icon)
+    {
+        WARN("No valid icon of any size was able to be loaded.\n");
+        return ret;
+    }
+
+    /* It is possible that PrivateExtractIconsW fails for some sizes, if the executable
+       is malformed (packed, obfuscated, etc), and does fail only on certain sizes even
+       on Windows. Create the missing sizes by resizing from the first available icon. */
+    for (i = 0; i < ARRAY_SIZE(hicons); i++)
+    {
+        if (hicons[i]) continue;
+
+        /* If this fails, we have to abort to prevent the image lists from
+           becoming out of sync and completely screwing the icons up */
+        get_imagelist_icon_size(i, &size);
+        hicons[i] = CopyImage(first_icon, IMAGE_ICON, size.cx, size.cy, 0);
         if (!hicons[i]) goto fail;
     }
 
-- 
2.30.0




More information about the wine-devel mailing list