diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index c737b4b7..977b119b 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -296,6 +296,7 @@ patch_enable_all () enable_shell32_Progress_Dialog="$1" enable_shell32_SFGAO_HASSUBFOLDER="$1" enable_shell32_SHFileOperation_Move="$1" + enable_shell32_SHGetStockIconInfo="$1" enable_shell32_Toolbar_Bitmaps="$1" enable_shell32_UnixFS="$1" enable_shlwapi_AssocGetPerceivedType="$1" @@ -1053,6 +1054,9 @@ patch_enable () shell32-SHFileOperation_Move) enable_shell32_SHFileOperation_Move="$2" ;; + shell32-SHGetStockIconInfo) + enable_shell32_SHGetStockIconInfo="$2" + ;; shell32-Toolbar_Bitmaps) enable_shell32_Toolbar_Bitmaps="$2" ;; @@ -6224,6 +6228,21 @@ if test "$enable_shell32_SFGAO_HASSUBFOLDER" -eq 1; then ) >> "$patchlist" fi +# Patchset shell32-SHGetStockIconInfo +# | +# | This patchset fixes the following Wine bugs: +# | * [#45868] Improve semi-stub SHGetStockIconInfo +# | +# | Modified files: +# | * dlls/shell32/iconcache.c, dlls/shell32/tests/shelllink.c +# | +if test "$enable_shell32_SHGetStockIconInfo" -eq 1; then + patch_apply shell32-SHGetStockIconInfo/0001-shell32-Improve-semi-stub-SHGetStockIconInfo-try-fin.patch + ( + printf '%s\n' '+ { "Louis Lenders", "shell32: Improve semi-stub SHGetStockIconInfo, try find existing iconhandle.", 1 },'; + ) >> "$patchlist" +fi + # Patchset shell32-Toolbar_Bitmaps # | # | This patchset fixes the following Wine bugs: diff --git a/patches/shell32-SHGetStockIconInfo/0001-shell32-Improve-semi-stub-SHGetStockIconInfo-try-fin.patch b/patches/shell32-SHGetStockIconInfo/0001-shell32-Improve-semi-stub-SHGetStockIconInfo-try-fin.patch new file mode 100644 index 00000000..3171d66a --- /dev/null +++ b/patches/shell32-SHGetStockIconInfo/0001-shell32-Improve-semi-stub-SHGetStockIconInfo-try-fin.patch @@ -0,0 +1,235 @@ +From 3c48b07b4aeaf7bfae61c5e43382fd2165ae31bd Mon Sep 17 00:00:00 2001 +From: Louis Lenders +Date: Fri, 12 Oct 2018 11:57:18 +0200 +Subject: [PATCH] shell32: Improve semi-stub SHGetStockIconInfo, try find + existing iconhandle + +v3: try find handle to existing icon + +this is the best I can come up with for now, on windows afaict all these icons mostly come from imegares.dll +so the attached patch is not really how windows does it + +Fix for bug https://bugs.winehq.org/show_bug.cgi?id=45868 + +Signed-off-by: Louis Lenders +--- + dlls/shell32/iconcache.c | 158 +++++++++++++++++++++++++++++++-- + dlls/shell32/tests/shelllink.c | 15 ++++ + 2 files changed, 165 insertions(+), 8 deletions(-) + +diff --git a/dlls/shell32/iconcache.c b/dlls/shell32/iconcache.c +index 6107e0c33b..da3e043d95 100644 +--- a/dlls/shell32/iconcache.c ++++ b/dlls/shell32/iconcache.c +@@ -987,6 +987,119 @@ INT WINAPI SHGetIconOverlayIndexW(LPCWSTR pszIconPath, INT iIconIndex) + return -1; + } + ++/**************************************************************************** ++ * For SHGetStockIconInfo ++ */ ++typedef struct { ++ SHSTOCKICONID id; ++ DWORD iconid; ++} SI_ENTRY; ++ ++static const SI_ENTRY si_table[] = ++{ ++ [0] = { SIID_DOCNOASSOC, IDI_SHELL_FILE}, ++ [1] = { SIID_DOCASSOC, IDI_SHELL_DOCUMENT}, ++ [2] = { SIID_APPLICATION, IDI_SHELL_WINDOW}, ++ [3] = { SIID_FOLDER, IDI_SHELL_FOLDER}, ++ [4] = { SIID_FOLDEROPEN, IDI_SHELL_FOLDER_OPEN}, ++ [5] = { SIID_DRIVE525, 0}, ++ [6] = { SIID_DRIVE35, 0}, ++ [7] = { SIID_DRIVERREMOVE, 0}, ++ [8] = { SIID_DRIVERFIXED, IDI_SHELL_DRIVE}, ++ [9] = { SIID_DRIVERNET, IDI_SHELL_NETDRIVE}, ++ [10] = { SIID_DRIVERNETDISABLE, IDI_SHELL_NETDRIVE2}, ++ [11] = { SIID_DRIVERCD, IDI_SHELL_OPTICAL_DRIVE}, ++ [12] = { SIID_DRIVERRAM, IDI_SHELL_RAMDISK}, ++ [13] = { SIID_WORLD, 0}, ++ /* Missing: 14 */ ++ [15] = { SIID_SERVER, 0}, ++ [16] = { SIID_PRINTER, IDI_SHELL_PRINT}, ++ [17] = { SIID_MYNETWORK, 0}, ++ /* Missing: 18 - 21 */ ++ [22] = { SIID_FIND, 0}, ++ [23] = { SIID_HELP, IDI_SHELL_HELP}, ++ /* Missing: 24 - 27 */ ++ [28] = {SIID_SHARE, 0}, ++ [29] = {SIID_LINK, 0}, ++ [30] = {SIID_SLOWFILE, 0}, ++ [31] = {SIID_RECYCLER, IDI_SHELL_TRASH_FOLDER}, ++ [32] = {SIID_RECYCLERFULL, IDI_SHELL_FULL_RECYCLE_BIN}, ++ /* Missing: 33 - 39 */ ++ [40] = {SIID_MEDIACDAUDIO, 0}, ++ /* Missing: 41 - 46 */ ++ [47] = {SIID_LOCK, IDI_SHELL_PASSWORDS}, ++ /* Missing: 48 */ ++ [49] = {SIID_AUTOLIST, 0}, ++ [50] = {SIID_PRINTERNET, 0}, ++ [51] = {SIID_SERVERSHARE, 0}, ++ [52] = {SIID_PRINTERFAX, 0}, ++ [53] = {SIID_PRINTERFAXNET, 0}, ++ [54] = {SIID_PRINTERFILE, 0}, ++ [55] = {SIID_STACK, 0}, ++ [56] = {SIID_MEDIASVCD, 0}, ++ [57] = {SIID_STUFFEDFOLDER, 0}, ++ [58] = {SIID_DRIVEUNKNOWN, 0}, ++ [59] = {SIID_DRIVEDVD, 0}, ++ [60] = {SIID_MEDIADVD, 0}, ++ [61] = {SIID_MEDIADVDRAM, 0}, ++ [62] = {SIID_MEDIADVDRW, 0}, ++ [63] = {SIID_MEDIADVDR, 0}, ++ [64] = {SIID_MEDIADVDROM, 0}, ++ [65] = {SIID_MEDIACDAUDIOPLUS, 0}, ++ [66] = {SIID_MEDIACDRW, 0}, ++ [67] = {SIID_MEDIACDR, 0}, ++ [68] = {SIID_MEDIACDBURN, 0}, ++ [69] = {SIID_MEDIABLANKCD, 0}, ++ [70] = {SIID_MEDIACDROM, 0}, ++ [71] = {SIID_AUDIOFILES, IDI_SHELL_AUDIO_FILE}, ++ [72] = {SIID_IMAGEFILES, IDI_SHELL_IMAGE_FILE}, ++ [73] = {SIID_VIDEOFILES, IDI_SHELL_VIDEO_FILE}, ++ [74] = {SIID_MIXEDFILES, 0}, ++ [75] = {SIID_FOLDERBACK, 0}, ++ [76] = {SIID_FOLDERFRONT, 0}, ++ [77] = {SIID_SHIELD, 0}, ++ [78] = {SIID_WARNING, 0}, ++ [79] = {SIID_INFO, 0}, ++ [80] = {SIID_ERROR, 0}, ++ [81] = {SIID_KEY, 0}, ++ [82] = {SIID_SOFTWARE, 0}, ++ [83] = {SIID_RENAME, IDI_SHELL_RENAME}, ++ [84] = {SIID_DELETE, IDI_SHELL_CONFIRM_DELETE}, ++ [85] = {SIID_MEDIAAUDIODVD, 0}, ++ [86] = {SIID_MEDIAMOVIEDVD, 0}, ++ [87] = {SIID_MEDIAENHANCEDCD, 0}, ++ [88] = {SIID_MEDIAENHANCEDDVD, 0}, ++ [89] = {SIID_MEDIAHDDVD, 0}, ++ [90] = {SIID_MEDIABLUERAY, 0}, ++ [91] = {SIID_MEDIAVCD, 0}, ++ [92] = {SIID_MEDIADVDPLUSR, 0}, ++ [93] = {SIID_MEDIADVDPLUSRW, 0}, ++ [94] = {SIID_DESKTOPPC, IDI_SHELL_MY_COMPUTER}, ++ [95] = {SIID_MOBILEPC, 0}, ++ [96] = {SIID_USERS, IDI_SHELL_USERS}, ++ [97] = {SIID_MEDIASMARTMEDIA, 0}, ++ [98] = {SIID_MEDIACOMPACTFLASH, 0}, ++ [99] = {SIID_DEVICECELLPHONE, 0}, ++ [100] = {SIID_DEVICECAMERA, 0}, ++ [101] = {SIID_DEVICEVIDEOCAMERA, 0}, ++ [102] = {SIID_DEVICEAUDIOPLAYER, 0}, ++ [103] = {SIID_NETWORKCONNECT, 0}, ++ [104] = {SIID_INTERNET, IDI_SHELL_WEB_BROWSER}, ++ [105] = {SIID_ZIPFILE, 0}, ++ [106] = {SIID_SETTINGS, IDI_SHELL_SETTINGS}, ++ /* Missing: 107 - 131 */ ++ [132] = {SIID_DRIVEHDDVD, 0}, ++ [133] = {SIID_DRIVEBD, 0}, ++ [134] = {SIID_MEDIAHDDVDROM, 0}, ++ [135] = {SIID_MEDIAHDDVDR, 0}, ++ [136] = {SIID_MEDIAHDDVDRAM, 0}, ++ [137] = {SIID_MEDIABDROM, 0}, ++ [138] = {SIID_MEDIABDR, 0}, ++ [139] = {SIID_MEDIABDRE, 0}, ++ [140] = {SIID_CLUSTEREDDRIVE, 0} ++ /* Missing: 141 - 180 and SIID_MAX_ICONS = 181*/ ++ }; ++ + /**************************************************************************** + * SHGetStockIconInfo [SHELL32.@] + * +@@ -1004,25 +1117,54 @@ INT WINAPI SHGetIconOverlayIndexW(LPCWSTR pszIconPath, INT iIconIndex) + */ + HRESULT WINAPI SHGetStockIconInfo(SHSTOCKICONID id, UINT flags, SHSTOCKICONINFO *sii) + { +- static const WCHAR shell32dll[] = {'\\','s','h','e','l','l','3','2','.','d','l','l',0}; ++ static const WCHAR shell32dllW[] = {'s','h','e','l','l','3','2','.','d','l','l',0}; ++ static const WCHAR slashW[] = {'\\',0}; ++ HMODULE hmod; + +- FIXME("(%d, 0x%x, %p) semi-stub\n", id, flags, sii); ++ TRACE("(%d, 0x%x, %p)\n", id, flags, sii); + if ((id < 0) || (id >= SIID_MAX_ICONS) || !sii || (sii->cbSize != sizeof(SHSTOCKICONINFO))) { + return E_INVALIDARG; + } + + GetSystemDirectoryW(sii->szPath, MAX_PATH); ++ lstrcatW(sii->szPath, slashW); ++ lstrcatW(sii->szPath, shell32dllW); ++ ++ sii->hIcon = NULL; ++ sii->iSysImageIndex = -1; + +- /* no icons defined: use default */ +- sii->iIcon = -IDI_SHELL_FILE; +- lstrcatW(sii->szPath, shell32dll); ++ /* this is not how windows does it, on windows picked mostly from imageres.dll !*/ ++ if (si_table[id].iconid) ++ sii->iIcon = sii->iSysImageIndex - si_table[id].id; ++ else ++ { ++ FIXME("Couldn`t find SIID %d, returning default values (IDI_SHELL_FILE)\n", id); ++ sii->iIcon = sii->iSysImageIndex - IDI_SHELL_FILE; ++ } ++ ++ if (flags & SHGSI_ICON) ++ { ++ flags &= ~SHGSI_ICON; ++ ++ hmod = GetModuleHandleW(shell32dllW); ++ if (hmod) ++ { ++ if (si_table[id].iconid) ++ sii->hIcon = LoadIconW(hmod, MAKEINTRESOURCEW(si_table[id].iconid)); ++ else ++ sii->hIcon = LoadIconW(hmod, MAKEINTRESOURCEW(IDI_SHELL_FILE)); ++ } ++ ++ if (!sii->hIcon) ++ { ++ ERR("failed to get an icon handle\n"); ++ return E_INVALIDARG; ++ } ++ } + + if (flags) + FIXME("flags 0x%x not implemented\n", flags); + +- sii->hIcon = NULL; +- sii->iSysImageIndex = -1; +- + TRACE("%3d: returning %s (%d)\n", id, debugstr_w(sii->szPath), sii->iIcon); + + return S_OK; +diff --git a/dlls/shell32/tests/shelllink.c b/dlls/shell32/tests/shelllink.c +index 3bfd9cbe38..e7e3dac987 100644 +--- a/dlls/shell32/tests/shelllink.c ++++ b/dlls/shell32/tests/shelllink.c +@@ -1139,6 +1139,21 @@ static void test_SHGetStockIconInfo(void) + /* there is a NULL check for the struct */ + hr = pSHGetStockIconInfo(SIID_FOLDER, SHGSI_ICONLOCATION, NULL); + ok(hr == E_INVALIDARG, "NULL: got 0x%x\n", hr); ++ ++ for(i = 0; i < 140; i++) /* highest on wvista, i > 140 gives E_INVALIDARG, win7 can go higher */ ++ { ++ memset(buffer, 0, sizeof(buffer)); ++ sii->cbSize = sizeof(SHSTOCKICONINFO); ++ hr = pSHGetStockIconInfo(i, SHGSI_ICON | SHGSI_SMALLICON, sii); ++ ok(hr == S_OK, "got 0x%x (expected S_OK)\n", hr); ++ ok(sii->hIcon != NULL, "got NULL, expected an icon handle\n"); ++ ok(sii->iIcon != 0, "got unexpected 0 for SIID %d\n", i); /* howto find out exact sii->iIcon value??? */ ++ ok(sii->iSysImageIndex == -1, "got %d (expected -1)\n", sii->iSysImageIndex); ++ ok(DestroyIcon(sii->hIcon), "DestroyIcon failed\n"); ++ if (winetest_debug > 1) ++ trace("%3d: got iSysImageIndex %3d, iIcon %3d and %s\n", i, sii->iSysImageIndex, ++ sii->iIcon, wine_dbgstr_w(sii->szPath)); ++ } + } + + static void test_SHExtractIcons(void) +-- +2.19.1 + diff --git a/patches/shell32-SHGetStockIconInfo/definition b/patches/shell32-SHGetStockIconInfo/definition new file mode 100644 index 00000000..eb4ab237 --- /dev/null +++ b/patches/shell32-SHGetStockIconInfo/definition @@ -0,0 +1 @@ +Fixes: [45868] Improve semi-stub SHGetStockIconInfo