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@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; }