wine-staging/patches/shell32-SHGetStockIconInfo/0001-shell32-Improve-semi-stub-SHGetStockIconInfo-try-fin.patch
2024-08-07 16:02:00 +10:00

235 lines
8.4 KiB
Diff

From 0d5690ffe44182224aef5488508a8eeb2750e757 Mon Sep 17 00:00:00 2001
From: Louis Lenders <xerox.xerox2000x@gmail.com>
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 <xerox.xerox2000x@gmail.com>
---
dlls/shell32/iconcache.c | 156 +++++++++++++++++++++++++++++++--
dlls/shell32/tests/shelllink.c | 15 ++++
2 files changed, 164 insertions(+), 7 deletions(-)
diff --git a/dlls/shell32/iconcache.c b/dlls/shell32/iconcache.c
index 03eea049d0c..4a84b2055fe 100644
--- a/dlls/shell32/iconcache.c
+++ b/dlls/shell32/iconcache.c
@@ -1021,6 +1021,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.@]
*
@@ -1038,25 +1151,54 @@ INT WINAPI SHGetIconOverlayIndexW(LPCWSTR pszIconPath, INT iIconIndex)
*/
HRESULT WINAPI SHGetStockIconInfo(SHSTOCKICONID id, UINT flags, SHSTOCKICONINFO *sii)
{
- FIXME("(%d, 0x%x, %p) semi-stub\n", id, flags, sii);
+ HMODULE hmod;
+
+ 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);
-
- /* no icons defined: use default */
- sii->iIcon = -IDI_SHELL_FILE;
lstrcatW(sii->szPath, L"\\shell32.dll");
- if (flags)
- FIXME("flags 0x%x not implemented\n", flags);
-
sii->hIcon = NULL;
if (flags & SHGSI_ICON)
sii->hIcon = LoadIconW(GetModuleHandleW(sii->szPath), MAKEINTRESOURCEW(sii->iIcon));
sii->iSysImageIndex = -1;
+ /* 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(L"shell32.dll");
+ 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);
+
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 f13155ade2f..c70bc9d5946 100644
--- a/dlls/shell32/tests/shelllink.c
+++ b/dlls/shell32/tests/shelllink.c
@@ -1119,6 +1119,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%lx\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%lx (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.43.0