2 * Copyright 1997 Marcus Meissner
3 * Copyright 1998 Juergen Schmied
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
24 WCHAR swShell32Name
[MAX_PATH
];
26 DWORD NumIconOverlayHandlers
= 0;
27 IShellIconOverlayIdentifier
** Handlers
= NULL
;
29 static HRESULT
getIconLocationForFolder(IShellFolder
* psf
, LPCITEMIDLIST pidl
, UINT uFlags
,
30 LPWSTR szIconFile
, UINT cchMax
, int *piIndex
, UINT
*pwFlags
)
32 static const WCHAR shellClassInfo
[] = { '.', 'S', 'h', 'e', 'l', 'l', 'C', 'l', 'a', 's', 's', 'I', 'n', 'f', 'o', 0 };
33 static const WCHAR iconFile
[] = { 'I', 'c', 'o', 'n', 'F', 'i', 'l', 'e', 0 };
34 static const WCHAR clsid
[] = { 'C', 'L', 'S', 'I', 'D', 0 };
35 static const WCHAR clsid2
[] = { 'C', 'L', 'S', 'I', 'D', '2', 0 };
36 static const WCHAR iconIndex
[] = { 'I', 'c', 'o', 'n', 'I', 'n', 'd', 'e', 'x', 0 };
37 static const WCHAR wszDesktopIni
[] = { 'd','e','s','k','t','o','p','.','i','n','i',0 };
40 if (!(uFlags
& GIL_DEFAULTICON
) && (_ILGetFileAttributes(ILFindLastID(pidl
), NULL
, 0) & (FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_READONLY
)) != 0 )
42 WCHAR wszFolderPath
[MAX_PATH
];
44 if (!ILGetDisplayNameExW(psf
, pidl
, wszFolderPath
, 0))
47 PathAppendW(wszFolderPath
, wszDesktopIni
);
49 if (PathFileExistsW(wszFolderPath
))
51 WCHAR wszPath
[MAX_PATH
];
52 WCHAR wszCLSIDValue
[CHARS_IN_GUID
];
54 if (GetPrivateProfileStringW(shellClassInfo
, iconFile
, NULL
, wszPath
, MAX_PATH
, wszFolderPath
))
56 ExpandEnvironmentStringsW(wszPath
, szIconFile
, cchMax
);
58 *piIndex
= GetPrivateProfileIntW(shellClassInfo
, iconIndex
, 0, wszFolderPath
);
61 else if (GetPrivateProfileStringW(shellClassInfo
, clsid
, NULL
, wszCLSIDValue
, CHARS_IN_GUID
, wszFolderPath
) &&
62 HCR_GetIconW(wszCLSIDValue
, szIconFile
, NULL
, cchMax
, &icon_idx
))
67 else if (GetPrivateProfileStringW(shellClassInfo
, clsid2
, NULL
, wszCLSIDValue
, CHARS_IN_GUID
, wszFolderPath
) &&
68 HCR_GetIconW(wszCLSIDValue
, szIconFile
, NULL
, cchMax
, &icon_idx
))
76 static const WCHAR folder
[] = { 'F', 'o', 'l', 'd', 'e', 'r', 0 };
78 if (!HCR_GetIconW(folder
, szIconFile
, NULL
, cchMax
, &icon_idx
))
80 lstrcpynW(szIconFile
, swShell32Name
, cchMax
);
81 icon_idx
= -IDI_SHELL_FOLDER
;
84 if (uFlags
& GIL_OPENICON
)
85 *piIndex
= icon_idx
< 0 ? icon_idx
- 1 : icon_idx
+ 1;
92 static void InitIconOverlays(void)
95 DWORD dwIndex
, dwResult
, dwSize
;
96 WCHAR szName
[MAX_PATH
];
100 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, L
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ShellIconOverlayIdentifiers", 0, KEY_READ
, &hKey
) != ERROR_SUCCESS
)
103 if (RegQueryInfoKeyW(hKey
, NULL
, NULL
, NULL
, &dwResult
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
) != ERROR_SUCCESS
)
109 Handlers
= (IShellIconOverlayIdentifier
**)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwResult
* sizeof(IShellIconOverlayIdentifier
*));
122 dwSize
= sizeof(szName
) / sizeof(WCHAR
);
123 dwResult
= RegEnumKeyExW(hKey
, dwIndex
, szName
, &dwSize
, NULL
, NULL
, NULL
, NULL
);
125 if (dwResult
== ERROR_NO_MORE_ITEMS
)
128 if (dwResult
== ERROR_SUCCESS
)
130 dwSize
= sizeof(szValue
) / sizeof(WCHAR
);
131 if (RegGetValueW(hKey
, szName
, NULL
, RRF_RT_REG_SZ
, NULL
, szValue
, &dwSize
) == ERROR_SUCCESS
)
133 CComPtr
<IShellIconOverlayIdentifier
> Overlay
;
135 CLSIDFromString(szValue
, &clsid
);
136 dwResult
= CoCreateInstance(clsid
, NULL
, CLSCTX_INPROC_SERVER
, IID_PPV_ARG(IShellIconOverlayIdentifier
, &Overlay
));
137 if (dwResult
== S_OK
)
139 Handlers
[NumIconOverlayHandlers
] = Overlay
.Detach();
140 NumIconOverlayHandlers
++;
153 GetIconOverlay(LPCITEMIDLIST pidl
, WCHAR
* wTemp
, int* pIndex
)
161 WCHAR szPath
[MAX_PATH
];
163 if(!SHGetPathFromIDListW(pidl
, szPath
))
169 HighestPriority
= 101;
170 IconIndex
= NumIconOverlayHandlers
;
171 for(Index
= 0; Index
< NumIconOverlayHandlers
; Index
++)
173 hResult
= Handlers
[Index
]->IsMemberOf(szPath
, SFGAO_FILESYSTEM
);
176 hResult
= Handlers
[Index
]->GetPriority(&Priority
);
179 if (Priority
< HighestPriority
)
181 HighestPriority
= Priority
;
188 if (IconIndex
== NumIconOverlayHandlers
)
191 hResult
= Handlers
[IconIndex
]->GetOverlayInfo(wTemp
, MAX_PATH
, pIndex
, &Flags
);
199 HRESULT
CFSExtractIcon_CreateInstance(IShellFolder
* psf
, LPCITEMIDLIST pidl
, REFIID iid
, LPVOID
* ppvOut
)
201 CComPtr
<IDefaultExtractIconInit
> initIcon
;
204 UINT flags
= 0; // FIXME: Use it!
205 CHAR sTemp
[MAX_PATH
] = "";
206 WCHAR wTemp
[MAX_PATH
] = L
"";
208 hr
= SHCreateDefaultExtractIcon(IID_PPV_ARG(IDefaultExtractIconInit
,&initIcon
));
212 if (_ILIsFolder (pidl
))
214 if (SUCCEEDED(getIconLocationForFolder(psf
,
215 pidl
, 0, wTemp
, _countof(wTemp
),
219 initIcon
->SetNormalIcon(wTemp
, icon_idx
);
220 // FIXME: if/when getIconLocationForFolder does something for
221 // GIL_FORSHORTCUT, code below should be uncommented. and
222 // the following line removed.
223 initIcon
->SetShortcutIcon(wTemp
, icon_idx
);
225 if (SUCCEEDED(getIconLocationForFolder(psf
,
226 pidl
, GIL_DEFAULTICON
, wTemp
, _countof(wTemp
),
230 initIcon
->SetDefaultIcon(wTemp
, icon_idx
);
232 // if (SUCCEEDED(getIconLocationForFolder(psf,
233 // pidl, GIL_FORSHORTCUT, wTemp, _countof(wTemp),
237 // initIcon->SetShortcutIcon(wTemp, icon_idx);
239 if (SUCCEEDED(getIconLocationForFolder(psf
,
240 pidl
, GIL_OPENICON
, wTemp
, _countof(wTemp
),
244 initIcon
->SetOpenIcon(wTemp
, icon_idx
);
251 if (_ILGetExtension(pidl
, sTemp
, _countof(sTemp
)))
253 if (HCR_MapTypeToValueA(sTemp
, sTemp
, _countof(sTemp
), TRUE
)
254 && HCR_GetIconA(sTemp
, sTemp
, NULL
, _countof(sTemp
), &icon_idx
))
256 if (!lstrcmpA("%1", sTemp
)) /* icon is in the file */
258 ILGetDisplayNameExW(psf
, pidl
, wTemp
, 0);
263 MultiByteToWideChar(CP_ACP
, 0, sTemp
, -1, wTemp
, _countof(wTemp
));
268 else if (!lstrcmpiA(sTemp
, "lnkfile"))
270 /* extract icon from shell shortcut */
271 CComPtr
<IShellLinkW
> psl
;
272 CComPtr
<IExtractIconW
> pei
;
274 HRESULT hr
= psf
->GetUIObjectOf(NULL
, 1, &pidl
, IID_NULL_PPV_ARG(IShellLinkW
, &psl
));
277 hr
= psl
->GetIconLocation(wTemp
, _countof(wTemp
), &icon_idx
);
278 if (FAILED(hr
) || !*wTemp
)
280 /* The icon was not found directly, try to retrieve it from the shell link target */
281 hr
= psl
->QueryInterface(IID_PPV_ARG(IExtractIconW
, &pei
));
282 if (FAILED(hr
) || !pei
)
283 TRACE("No IExtractIconW interface!\n");
285 hr
= pei
->GetIconLocation(GIL_FORSHELL
, wTemp
, _countof(wTemp
), &icon_idx
, &flags
);
288 if (SUCCEEDED(hr
) && *wTemp
)
294 /* FIXME: We should normally use the correct icon format according to 'flags' */
297 initIcon
->SetNormalIcon(swShell32Name
, 0);
299 initIcon
->SetNormalIcon(wTemp
, icon_idx
);
302 return initIcon
->QueryInterface(iid
, ppvOut
);