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 WCHAR swShell32Name
[MAX_PATH
];
24 DWORD NumIconOverlayHandlers
= 0;
25 IShellIconOverlayIdentifier
** Handlers
= NULL
;
27 static HRESULT
getIconLocationForFolder(LPCITEMIDLIST pidl
, UINT uFlags
,
28 LPWSTR szIconFile
, UINT cchMax
, int *piIndex
, UINT
*pwFlags
)
30 static const WCHAR shellClassInfo
[] = { '.', 'S', 'h', 'e', 'l', 'l', 'C', 'l', 'a', 's', 's', 'I', 'n', 'f', 'o', 0 };
31 static const WCHAR iconFile
[] = { 'I', 'c', 'o', 'n', 'F', 'i', 'l', 'e', 0 };
32 static const WCHAR clsid
[] = { 'C', 'L', 'S', 'I', 'D', 0 };
33 static const WCHAR clsid2
[] = { 'C', 'L', 'S', 'I', 'D', '2', 0 };
34 static const WCHAR iconIndex
[] = { 'I', 'c', 'o', 'n', 'I', 'n', 'd', 'e', 'x', 0 };
35 static const WCHAR wszDesktopIni
[] = { 'd','e','s','k','t','o','p','.','i','n','i',0 };
38 if (!(uFlags
& GIL_DEFAULTICON
) && (_ILGetFileAttributes(ILFindLastID(pidl
), NULL
, 0) & (FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_READONLY
)) != 0 )
40 WCHAR wszFolderPath
[MAX_PATH
];
42 if (!SHGetPathFromIDListW(pidl
, wszFolderPath
))
45 PathAppendW(wszFolderPath
, wszDesktopIni
);
47 if (PathFileExistsW(wszFolderPath
))
49 WCHAR wszPath
[MAX_PATH
];
50 WCHAR wszCLSIDValue
[CHARS_IN_GUID
];
52 if (GetPrivateProfileStringW(shellClassInfo
, iconFile
, NULL
, wszPath
, MAX_PATH
, wszFolderPath
))
54 ExpandEnvironmentStringsW(wszPath
, szIconFile
, cchMax
);
56 *piIndex
= GetPrivateProfileIntW(shellClassInfo
, iconIndex
, 0, wszFolderPath
);
59 else if (GetPrivateProfileStringW(shellClassInfo
, clsid
, NULL
, wszCLSIDValue
, CHARS_IN_GUID
, wszFolderPath
) &&
60 HCR_GetIconW(wszCLSIDValue
, szIconFile
, NULL
, cchMax
, &icon_idx
))
65 else if (GetPrivateProfileStringW(shellClassInfo
, clsid2
, NULL
, wszCLSIDValue
, CHARS_IN_GUID
, wszFolderPath
) &&
66 HCR_GetIconW(wszCLSIDValue
, szIconFile
, NULL
, cchMax
, &icon_idx
))
74 static const WCHAR folder
[] = { 'F', 'o', 'l', 'd', 'e', 'r', 0 };
76 if (!HCR_GetIconW(folder
, szIconFile
, NULL
, cchMax
, &icon_idx
))
78 lstrcpynW(szIconFile
, swShell32Name
, cchMax
);
79 icon_idx
= -IDI_SHELL_FOLDER
;
82 if (uFlags
& GIL_OPENICON
)
83 *piIndex
= icon_idx
< 0 ? icon_idx
- 1 : icon_idx
+ 1;
90 void InitIconOverlays(void)
93 DWORD dwIndex
, dwResult
, dwSize
;
94 WCHAR szName
[MAX_PATH
];
98 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, L
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ShellIconOverlayIdentifiers", 0, KEY_READ
, &hKey
) != ERROR_SUCCESS
)
101 if (RegQueryInfoKeyW(hKey
, NULL
, NULL
, NULL
, &dwResult
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
) != ERROR_SUCCESS
)
107 Handlers
= (IShellIconOverlayIdentifier
**)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwResult
* sizeof(IShellIconOverlayIdentifier
*));
120 dwSize
= sizeof(szName
) / sizeof(WCHAR
);
121 dwResult
= RegEnumKeyExW(hKey
, dwIndex
, szName
, &dwSize
, NULL
, NULL
, NULL
, NULL
);
123 if (dwResult
== ERROR_NO_MORE_ITEMS
)
126 if (dwResult
== ERROR_SUCCESS
)
128 dwSize
= sizeof(szValue
) / sizeof(WCHAR
);
129 if (RegGetValueW(hKey
, szName
, NULL
, RRF_RT_REG_SZ
, NULL
, szValue
, &dwSize
) == ERROR_SUCCESS
)
131 CComPtr
<IShellIconOverlayIdentifier
> Overlay
;
133 CLSIDFromString(szValue
, &clsid
);
134 dwResult
= CoCreateInstance(clsid
, NULL
, CLSCTX_INPROC_SERVER
, IID_PPV_ARG(IShellIconOverlayIdentifier
, &Overlay
));
135 if (dwResult
== S_OK
)
137 Handlers
[NumIconOverlayHandlers
] = Overlay
.Detach();
138 NumIconOverlayHandlers
++;
151 GetIconOverlay(LPCITEMIDLIST pidl
, WCHAR
* wTemp
, int* pIndex
)
159 WCHAR szPath
[MAX_PATH
];
161 if(!SHGetPathFromIDListW(pidl
, szPath
))
165 HighestPriority
= 101;
166 IconIndex
= NumIconOverlayHandlers
;
167 for(Index
= 0; Index
< NumIconOverlayHandlers
; Index
++)
169 hResult
= Handlers
[Index
]->IsMemberOf(szPath
, SFGAO_FILESYSTEM
);
172 hResult
= Handlers
[Index
]->GetPriority(&Priority
);
175 if (Priority
< HighestPriority
)
177 HighestPriority
= Priority
;
184 if (IconIndex
== NumIconOverlayHandlers
)
187 hResult
= Handlers
[IconIndex
]->GetOverlayInfo(wTemp
, MAX_PATH
, pIndex
, &Flags
);
195 /**************************************************************************
196 * IExtractIconW_Constructor
198 IExtractIconW
* IExtractIconW_Constructor(LPCITEMIDLIST pidl
)
200 CComPtr
<IDefaultExtractIconInit
> initIcon
;
201 CComPtr
<IExtractIconW
> extractIcon
;
205 CHAR sTemp
[MAX_PATH
];
206 WCHAR wTemp
[MAX_PATH
];
207 LPITEMIDLIST pSimplePidl
= ILFindLastID(pidl
);
210 hr
= SHCreateDefaultExtractIcon(IID_PPV_ARG(IDefaultExtractIconInit
,&initIcon
));
214 hr
= initIcon
->QueryInterface(IID_PPV_ARG(IExtractIconW
,&extractIcon
));
218 if (_ILIsDesktop(pSimplePidl
))
220 initIcon
->SetNormalIcon(swShell32Name
, -IDI_SHELL_DESKTOP
);
222 else if ((riid
= _ILGetGUIDPointer(pSimplePidl
)))
224 /* my computer and other shell extensions */
225 static const WCHAR fmt
[] = { 'C', 'L', 'S', 'I', 'D', '\\',
226 '{', '%', '0', '8', 'l', 'x', '-', '%', '0', '4', 'x', '-', '%', '0', '4', 'x', '-',
227 '%', '0', '2', 'x', '%', '0', '2', 'x', '-', '%', '0', '2', 'x', '%', '0', '2', 'x',
228 '%', '0', '2', 'x', '%', '0', '2', 'x', '%', '0', '2', 'x', '%', '0', '2', 'x', '}', 0
233 riid
->Data1
, riid
->Data2
, riid
->Data3
,
234 riid
->Data4
[0], riid
->Data4
[1], riid
->Data4
[2], riid
->Data4
[3],
235 riid
->Data4
[4], riid
->Data4
[5], riid
->Data4
[6], riid
->Data4
[7]);
237 const WCHAR
* iconname
= NULL
;
238 if (_ILIsBitBucket(pSimplePidl
))
240 static const WCHAR szFull
[] = {'F','u','l','l',0};
241 static const WCHAR szEmpty
[] = {'E','m','p','t','y',0};
242 CComPtr
<IEnumIDList
> EnumIDList
;
245 CComPtr
<IShellFolder2
> psfRecycleBin
;
246 CComPtr
<IShellFolder
> psfDesktop
;
247 hr
= SHGetDesktopFolder(&psfDesktop
);
250 hr
= psfDesktop
->BindToObject(pSimplePidl
, NULL
, IID_PPV_ARG(IShellFolder2
, &psfRecycleBin
));
252 hr
= psfRecycleBin
->EnumObjects(NULL
, SHCONTF_FOLDERS
| SHCONTF_NONFOLDERS
, &EnumIDList
);
255 LPITEMIDLIST pidl
= NULL
;
256 if (SUCCEEDED(hr
) && (hr
= EnumIDList
->Next(1, &pidl
, &itemcount
)) == S_OK
)
265 if (HCR_GetIconW(xriid
, wTemp
, iconname
, MAX_PATH
, &icon_idx
))
267 initIcon
->SetNormalIcon(wTemp
, icon_idx
);
271 if (IsEqualGUID(*riid
, CLSID_MyComputer
))
272 initIcon
->SetNormalIcon(swShell32Name
, -IDI_SHELL_MY_COMPUTER
);
273 else if (IsEqualGUID(*riid
, CLSID_MyDocuments
))
274 initIcon
->SetNormalIcon(swShell32Name
, -IDI_SHELL_MY_DOCUMENTS
);
275 else if (IsEqualGUID(*riid
, CLSID_NetworkPlaces
))
276 initIcon
->SetNormalIcon(swShell32Name
, -IDI_SHELL_MY_NETWORK_PLACES
);
278 initIcon
->SetNormalIcon(swShell32Name
, -IDI_SHELL_FOLDER
);
282 else if (_ILIsDrive (pSimplePidl
))
284 static const WCHAR drive
[] = { 'D', 'r', 'i', 'v', 'e', 0 };
287 if (_ILGetDrive(pSimplePidl
, sTemp
, MAX_PATH
))
289 switch(GetDriveTypeA(sTemp
))
291 case DRIVE_REMOVABLE
:
292 icon_idx
= IDI_SHELL_3_14_FLOPPY
;
295 icon_idx
= IDI_SHELL_CDROM
;
298 icon_idx
= IDI_SHELL_NETDRIVE
;
301 icon_idx
= IDI_SHELL_RAMDISK
;
303 case DRIVE_NO_ROOT_DIR
:
304 icon_idx
= IDI_SHELL_CDROM
;
311 initIcon
->SetNormalIcon(swShell32Name
, -icon_idx
);
315 if (HCR_GetIconW(drive
, wTemp
, NULL
, MAX_PATH
, &icon_idx
))
316 initIcon
->SetNormalIcon(wTemp
, icon_idx
);
318 initIcon
->SetNormalIcon(swShell32Name
, -IDI_SHELL_DRIVE
);
322 else if (_ILIsFolder (pSimplePidl
))
324 if (SUCCEEDED(getIconLocationForFolder(
325 pidl
, 0, wTemp
, MAX_PATH
,
329 initIcon
->SetNormalIcon(wTemp
, icon_idx
);
330 // FIXME: if/when getIconLocationForFolder does something for
331 // GIL_FORSHORTCUT, code below should be uncommented. and
332 // the following line removed.
333 initIcon
->SetShortcutIcon(wTemp
, icon_idx
);
335 if (SUCCEEDED(getIconLocationForFolder(
336 pidl
, GIL_DEFAULTICON
, wTemp
, MAX_PATH
,
340 initIcon
->SetDefaultIcon(wTemp
, icon_idx
);
342 // if (SUCCEEDED(getIconLocationForFolder(
343 // pidl, GIL_FORSHORTCUT, wTemp, MAX_PATH,
347 // initIcon->SetShortcutIcon(wTemp, icon_idx);
349 if (SUCCEEDED(getIconLocationForFolder(
350 pidl
, GIL_OPENICON
, wTemp
, MAX_PATH
,
354 initIcon
->SetOpenIcon(wTemp
, icon_idx
);
361 if (_ILIsCPanelStruct(pSimplePidl
))
363 if (SUCCEEDED(CPanel_GetIconLocationW(pSimplePidl
, wTemp
, MAX_PATH
, &icon_idx
)))
366 else if (_ILGetExtension(pSimplePidl
, sTemp
, MAX_PATH
))
368 if (HCR_MapTypeToValueA(sTemp
, sTemp
, MAX_PATH
, TRUE
)
369 && HCR_GetIconA(sTemp
, sTemp
, NULL
, MAX_PATH
, &icon_idx
))
371 if (!lstrcmpA("%1", sTemp
)) /* icon is in the file */
373 SHGetPathFromIDListW(pidl
, wTemp
);
378 MultiByteToWideChar(CP_ACP
, 0, sTemp
, -1, wTemp
, MAX_PATH
);
383 else if (!lstrcmpiA(sTemp
, "lnkfile"))
385 /* extract icon from shell shortcut */
386 CComPtr
<IShellFolder
> dsf
;
387 CComPtr
<IShellLinkW
> psl
;
389 if (SUCCEEDED(SHGetDesktopFolder(&dsf
)))
391 HRESULT hr
= dsf
->GetUIObjectOf(NULL
, 1, (LPCITEMIDLIST
*) &pidl
, IID_NULL_PPV_ARG(IShellLinkW
, &psl
));
395 hr
= psl
->GetIconLocation(wTemp
, MAX_PATH
, &icon_idx
);
397 if (SUCCEEDED(hr
) && *sTemp
)
407 initIcon
->SetNormalIcon(swShell32Name
, 0);
409 initIcon
->SetNormalIcon(wTemp
, icon_idx
);
412 return extractIcon
.Detach();
415 /**************************************************************************
416 * IExtractIconA_Constructor
418 IExtractIconA
* IExtractIconA_Constructor(LPCITEMIDLIST pidl
)
420 CComPtr
<IExtractIconW
> extractIconW
;
421 CComPtr
<IExtractIconA
> extractIconA
;
424 extractIconW
= IExtractIconW_Constructor(pidl
);
428 hr
= extractIconW
->QueryInterface(IID_PPV_ARG(IExtractIconA
, &extractIconA
));
431 return extractIconA
.Detach();