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(LPCITEMIDLIST pidl
, UINT uFlags
,
30 LPWSTR szIconFile
, UINT cchMax
, int *piIndex
, UINT
*pwFlags
)
33 WCHAR wszPath
[MAX_PATH
];
34 WCHAR wszCLSIDValue
[CHARS_IN_GUID
];
35 static const WCHAR shellClassInfo
[] = { '.', 'S', 'h', 'e', 'l', 'l', 'C', 'l', 'a', 's', 's', 'I', 'n', 'f', 'o', 0 };
36 static const WCHAR iconFile
[] = { 'I', 'c', 'o', 'n', 'F', 'i', 'l', 'e', 0 };
37 static const WCHAR clsid
[] = { 'C', 'L', 'S', 'I', 'D', 0 };
38 static const WCHAR clsid2
[] = { 'C', 'L', 'S', 'I', 'D', '2', 0 };
39 static const WCHAR iconIndex
[] = { 'I', 'c', 'o', 'n', 'I', 'n', 'd', 'e', 'x', 0 };
41 if (SHELL32_GetCustomFolderAttribute(pidl
, shellClassInfo
, iconFile
,
44 WCHAR wszIconIndex
[10];
45 SHELL32_GetCustomFolderAttribute(pidl
, shellClassInfo
, iconIndex
,
47 *piIndex
= _wtoi(wszIconIndex
);
49 else if (SHELL32_GetCustomFolderAttribute(pidl
, shellClassInfo
, clsid
,
50 wszCLSIDValue
, CHARS_IN_GUID
) &&
51 HCR_GetDefaultIconW(wszCLSIDValue
, szIconFile
, cchMax
, &icon_idx
))
55 else if (SHELL32_GetCustomFolderAttribute(pidl
, shellClassInfo
, clsid2
,
56 wszCLSIDValue
, CHARS_IN_GUID
) &&
57 HCR_GetDefaultIconW(wszCLSIDValue
, szIconFile
, cchMax
, &icon_idx
))
63 static const WCHAR folder
[] = { 'F', 'o', 'l', 'd', 'e', 'r', 0 };
65 if (!HCR_GetDefaultIconW(folder
, szIconFile
, cchMax
, &icon_idx
))
67 lstrcpynW(szIconFile
, swShell32Name
, cchMax
);
68 icon_idx
= -IDI_SHELL_FOLDER
;
71 if (uFlags
& GIL_OPENICON
)
72 *piIndex
= icon_idx
< 0 ? icon_idx
- 1 : icon_idx
+ 1;
80 void InitIconOverlays(void)
83 DWORD dwIndex
, dwResult
, dwSize
;
84 WCHAR szName
[MAX_PATH
];
87 IShellIconOverlayIdentifier
* Overlay
;
89 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, L
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ShellIconOverlayIdentifiers", 0, KEY_READ
, &hKey
) != ERROR_SUCCESS
)
92 if (RegQueryInfoKeyW(hKey
, NULL
, NULL
, NULL
, &dwResult
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
) != ERROR_SUCCESS
)
98 Handlers
= (IShellIconOverlayIdentifier
**)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwResult
* sizeof(IShellIconOverlayIdentifier
*));
111 dwSize
= sizeof(szName
) / sizeof(WCHAR
);
112 dwResult
= RegEnumKeyExW(hKey
, dwIndex
, szName
, &dwSize
, NULL
, NULL
, NULL
, NULL
);
114 if (dwResult
== ERROR_NO_MORE_ITEMS
)
117 if (dwResult
== ERROR_SUCCESS
)
119 dwSize
= sizeof(szValue
) / sizeof(WCHAR
);
120 if (RegGetValueW(hKey
, szName
, NULL
, RRF_RT_REG_SZ
, NULL
, szValue
, &dwSize
) == ERROR_SUCCESS
)
123 CLSIDFromString(szValue
, &clsid
);
124 dwResult
= CoCreateInstance(clsid
, NULL
, CLSCTX_INPROC_SERVER
, IID_IUnknown
, (LPVOID
*)&Overlay
);
125 if (dwResult
== S_OK
)
127 Handlers
[NumIconOverlayHandlers
] = Overlay
;
128 NumIconOverlayHandlers
++;
141 GetIconOverlay(LPCITEMIDLIST pidl
, WCHAR
* wTemp
, int* pIndex
)
149 WCHAR szPath
[MAX_PATH
];
151 if(!SHGetPathFromIDListW(pidl
, szPath
))
155 HighestPriority
= 101;
156 IconIndex
= NumIconOverlayHandlers
;
157 for(Index
= 0; Index
< NumIconOverlayHandlers
; Index
++)
159 hResult
= Handlers
[Index
]->IsMemberOf(szPath
, SFGAO_FILESYSTEM
);
162 hResult
= Handlers
[Index
]->GetPriority(&Priority
);
165 if (Priority
< HighestPriority
)
167 HighestPriority
= Priority
;
174 if (IconIndex
== NumIconOverlayHandlers
)
177 hResult
= Handlers
[IconIndex
]->GetOverlayInfo(wTemp
, MAX_PATH
, pIndex
, &Flags
);
185 /**************************************************************************
186 * IExtractIconW_Constructor
188 IExtractIconW
* IExtractIconW_Constructor(LPCITEMIDLIST pidl
)
190 CComPtr
<IDefaultExtractIconInit
> initIcon
;
191 IExtractIconW
*extractIcon
;
195 CHAR sTemp
[MAX_PATH
];
196 WCHAR wTemp
[MAX_PATH
];
197 LPITEMIDLIST pSimplePidl
= ILFindLastID(pidl
);
200 hr
= SHCreateDefaultExtractIcon(IID_IDefaultExtractIconInit
, (void **)&initIcon
);
204 hr
= initIcon
->QueryInterface(IID_IExtractIconW
, (void **)&extractIcon
);
208 if (_ILIsDesktop(pSimplePidl
))
210 initIcon
->SetNormalIcon(swShell32Name
, -IDI_SHELL_DESKTOP
);
212 else if ((riid
= _ILGetGUIDPointer(pSimplePidl
)))
214 /* my computer and other shell extensions */
215 static const WCHAR fmt
[] = { 'C', 'L', 'S', 'I', 'D', '\\',
216 '{', '%', '0', '8', 'l', 'x', '-', '%', '0', '4', 'x', '-', '%', '0', '4', 'x', '-',
217 '%', '0', '2', 'x', '%', '0', '2', 'x', '-', '%', '0', '2', 'x', '%', '0', '2', 'x',
218 '%', '0', '2', 'x', '%', '0', '2', 'x', '%', '0', '2', 'x', '%', '0', '2', 'x', '}', 0
223 riid
->Data1
, riid
->Data2
, riid
->Data3
,
224 riid
->Data4
[0], riid
->Data4
[1], riid
->Data4
[2], riid
->Data4
[3],
225 riid
->Data4
[4], riid
->Data4
[5], riid
->Data4
[6], riid
->Data4
[7]);
227 if (HCR_GetDefaultIconW(xriid
, wTemp
, MAX_PATH
, &icon_idx
))
229 initIcon
->SetNormalIcon(wTemp
, icon_idx
);
233 if (IsEqualGUID(*riid
, CLSID_MyComputer
))
234 initIcon
->SetNormalIcon(swShell32Name
, -IDI_SHELL_MY_COMPUTER
);
235 else if (IsEqualGUID(*riid
, CLSID_MyDocuments
))
236 initIcon
->SetNormalIcon(swShell32Name
, -IDI_SHELL_MY_DOCUMENTS
);
237 else if (IsEqualGUID(*riid
, CLSID_NetworkPlaces
))
238 initIcon
->SetNormalIcon(swShell32Name
, -IDI_SHELL_MY_NETWORK_PLACES
);
240 initIcon
->SetNormalIcon(swShell32Name
, -IDI_SHELL_FOLDER
);
244 else if (_ILIsDrive (pSimplePidl
))
246 static const WCHAR drive
[] = { 'D', 'r', 'i', 'v', 'e', 0 };
249 if (_ILGetDrive(pSimplePidl
, sTemp
, MAX_PATH
))
251 switch(GetDriveTypeA(sTemp
))
253 case DRIVE_REMOVABLE
:
254 icon_idx
= IDI_SHELL_FLOPPY
;
257 icon_idx
= IDI_SHELL_CDROM
;
260 icon_idx
= IDI_SHELL_NETDRIVE
;
263 icon_idx
= IDI_SHELL_RAMDISK
;
265 case DRIVE_NO_ROOT_DIR
:
266 icon_idx
= IDI_SHELL_CDROM
;
273 initIcon
->SetNormalIcon(swShell32Name
, -icon_idx
);
277 if (HCR_GetDefaultIconW(drive
, wTemp
, MAX_PATH
, &icon_idx
))
278 initIcon
->SetNormalIcon(wTemp
, icon_idx
);
280 initIcon
->SetNormalIcon(swShell32Name
, -IDI_SHELL_DRIVE
);
284 else if (_ILIsFolder (pSimplePidl
))
286 if (SUCCEEDED(getIconLocationForFolder(
287 pidl
, 0, wTemp
, MAX_PATH
,
291 initIcon
->SetNormalIcon(wTemp
, icon_idx
);
293 if (SUCCEEDED(getIconLocationForFolder(
294 pidl
, GIL_DEFAULTICON
, wTemp
, MAX_PATH
,
298 initIcon
->SetDefaultIcon(wTemp
, icon_idx
);
300 if (SUCCEEDED(getIconLocationForFolder(
301 pidl
, GIL_FORSHORTCUT
, wTemp
, MAX_PATH
,
305 initIcon
->SetShortcutIcon(wTemp
, icon_idx
);
307 if (SUCCEEDED(getIconLocationForFolder(
308 pidl
, GIL_OPENICON
, wTemp
, MAX_PATH
,
312 initIcon
->SetOpenIcon(wTemp
, icon_idx
);
319 if (_ILIsCPanelStruct(pSimplePidl
))
321 if (SUCCEEDED(CPanel_GetIconLocationW(pSimplePidl
, wTemp
, MAX_PATH
, &icon_idx
)))
324 else if (_ILGetExtension(pSimplePidl
, sTemp
, MAX_PATH
))
326 if (HCR_MapTypeToValueA(sTemp
, sTemp
, MAX_PATH
, TRUE
)
327 && HCR_GetDefaultIconA(sTemp
, sTemp
, MAX_PATH
, &icon_idx
))
329 if (!lstrcmpA("%1", sTemp
)) /* icon is in the file */
331 SHGetPathFromIDListW(pidl
, wTemp
);
336 MultiByteToWideChar(CP_ACP
, 0, sTemp
, -1, wTemp
, MAX_PATH
);
341 else if (!lstrcmpiA(sTemp
, "lnkfile"))
343 /* extract icon from shell shortcut */
344 CComPtr
<IShellFolder
> dsf
;
345 CComPtr
<IShellLinkW
> psl
;
347 if (SUCCEEDED(SHGetDesktopFolder(&dsf
)))
349 HRESULT hr
= dsf
->GetUIObjectOf(NULL
, 1, (LPCITEMIDLIST
*)&pidl
, IID_IShellLinkW
, NULL
, (LPVOID
*)&psl
);
353 hr
= psl
->GetIconLocation(wTemp
, MAX_PATH
, &icon_idx
);
355 if (SUCCEEDED(hr
) && *sTemp
)
365 initIcon
->SetNormalIcon(swShell32Name
, 0);
367 initIcon
->SetNormalIcon(wTemp
, icon_idx
);
373 /**************************************************************************
374 * IExtractIconA_Constructor
376 IExtractIconA
* IExtractIconA_Constructor(LPCITEMIDLIST pidl
)
378 IExtractIconW
*extractIconW
;
379 IExtractIconA
*extractIconA
;
382 extractIconW
= IExtractIconW_Constructor(pidl
);
386 hr
= extractIconW
->QueryInterface(IID_IExtractIconA
, (void **)&extractIconA
);
387 extractIconW
->Release();