85f3873a2bf1bc9b7b6e9168261de969d02d9883
[reactos.git] / reactos / dll / win32 / shell32 / folders.cpp
1 /*
2 * Copyright 1997 Marcus Meissner
3 * Copyright 1998 Juergen Schmied
4 *
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.
9 *
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.
14 *
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
18 */
19
20 #include "precomp.h"
21
22 WINE_DEFAULT_DEBUG_CHANNEL(shell);
23
24 WCHAR swShell32Name[MAX_PATH];
25
26 DWORD NumIconOverlayHandlers = 0;
27 IShellIconOverlayIdentifier ** Handlers = NULL;
28
29 static HRESULT getIconLocationForFolder(LPCITEMIDLIST pidl, UINT uFlags,
30 LPWSTR szIconFile, UINT cchMax, int *piIndex, UINT *pwFlags)
31 {
32 int icon_idx;
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 };
40
41 if (SHELL32_GetCustomFolderAttribute(pidl, shellClassInfo, iconFile,
42 wszPath, MAX_PATH))
43 {
44 WCHAR wszIconIndex[10];
45 SHELL32_GetCustomFolderAttribute(pidl, shellClassInfo, iconIndex,
46 wszIconIndex, 10);
47 *piIndex = _wtoi(wszIconIndex);
48 }
49 else if (SHELL32_GetCustomFolderAttribute(pidl, shellClassInfo, clsid,
50 wszCLSIDValue, CHARS_IN_GUID) &&
51 HCR_GetDefaultIconW(wszCLSIDValue, szIconFile, cchMax, &icon_idx))
52 {
53 *piIndex = icon_idx;
54 }
55 else if (SHELL32_GetCustomFolderAttribute(pidl, shellClassInfo, clsid2,
56 wszCLSIDValue, CHARS_IN_GUID) &&
57 HCR_GetDefaultIconW(wszCLSIDValue, szIconFile, cchMax, &icon_idx))
58 {
59 *piIndex = icon_idx;
60 }
61 else
62 {
63 static const WCHAR folder[] = { 'F', 'o', 'l', 'd', 'e', 'r', 0 };
64
65 if (!HCR_GetDefaultIconW(folder, szIconFile, cchMax, &icon_idx))
66 {
67 lstrcpynW(szIconFile, swShell32Name, cchMax);
68 icon_idx = -IDI_SHELL_FOLDER;
69 }
70
71 if (uFlags & GIL_OPENICON)
72 *piIndex = icon_idx < 0 ? icon_idx - 1 : icon_idx + 1;
73 else
74 *piIndex = icon_idx;
75 }
76
77 return S_OK;
78 }
79
80 void InitIconOverlays(void)
81 {
82 HKEY hKey;
83 DWORD dwIndex, dwResult, dwSize;
84 WCHAR szName[MAX_PATH];
85 WCHAR szValue[100];
86 CLSID clsid;
87 IShellIconOverlayIdentifier * Overlay;
88
89 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ShellIconOverlayIdentifiers", 0, KEY_READ, &hKey) != ERROR_SUCCESS)
90 return;
91
92 if (RegQueryInfoKeyW(hKey, NULL, NULL, NULL, &dwResult, NULL, NULL, NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
93 {
94 RegCloseKey(hKey);
95 return;
96 }
97
98 Handlers = (IShellIconOverlayIdentifier **)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwResult * sizeof(IShellIconOverlayIdentifier*));
99 if (!Handlers)
100 {
101 RegCloseKey(hKey);
102 return;
103 }
104
105 dwIndex = 0;
106
107 CoInitialize(0);
108
109 do
110 {
111 dwSize = sizeof(szName) / sizeof(WCHAR);
112 dwResult = RegEnumKeyExW(hKey, dwIndex, szName, &dwSize, NULL, NULL, NULL, NULL);
113
114 if (dwResult == ERROR_NO_MORE_ITEMS)
115 break;
116
117 if (dwResult == ERROR_SUCCESS)
118 {
119 dwSize = sizeof(szValue) / sizeof(WCHAR);
120 if (RegGetValueW(hKey, szName, NULL, RRF_RT_REG_SZ, NULL, szValue, &dwSize) == ERROR_SUCCESS)
121 {
122
123 CLSIDFromString(szValue, &clsid);
124 dwResult = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (LPVOID*)&Overlay);
125 if (dwResult == S_OK)
126 {
127 Handlers[NumIconOverlayHandlers] = Overlay;
128 NumIconOverlayHandlers++;
129 }
130 }
131 }
132
133 dwIndex++;
134
135 } while(1);
136
137 RegCloseKey(hKey);
138 }
139
140 BOOL
141 GetIconOverlay(LPCITEMIDLIST pidl, WCHAR * wTemp, int* pIndex)
142 {
143 DWORD Index;
144 HRESULT hResult;
145 int Priority;
146 int HighestPriority;
147 ULONG IconIndex;
148 ULONG Flags;
149 WCHAR szPath[MAX_PATH];
150
151 if(!SHGetPathFromIDListW(pidl, szPath))
152 return FALSE;
153
154
155 HighestPriority = 101;
156 IconIndex = NumIconOverlayHandlers;
157 for(Index = 0; Index < NumIconOverlayHandlers; Index++)
158 {
159 hResult = Handlers[Index]->IsMemberOf(szPath, SFGAO_FILESYSTEM);
160 if (hResult == S_OK)
161 {
162 hResult = Handlers[Index]->GetPriority(&Priority);
163 if (hResult == S_OK)
164 {
165 if (Priority < HighestPriority)
166 {
167 HighestPriority = Priority;
168 IconIndex = Index;
169 }
170 }
171 }
172 }
173
174 if (IconIndex == NumIconOverlayHandlers)
175 return FALSE;
176
177 hResult = Handlers[IconIndex]->GetOverlayInfo(wTemp, MAX_PATH, pIndex, &Flags);
178
179 if (hResult == S_OK)
180 return TRUE;
181 else
182 return FALSE;
183 }
184
185 /**************************************************************************
186 * IExtractIconW_Constructor
187 */
188 IExtractIconW* IExtractIconW_Constructor(LPCITEMIDLIST pidl)
189 {
190 CComPtr<IDefaultExtractIconInit> initIcon;
191 IExtractIconW *extractIcon;
192 GUID const * riid;
193 int icon_idx;
194 UINT flags;
195 CHAR sTemp[MAX_PATH];
196 WCHAR wTemp[MAX_PATH];
197 LPITEMIDLIST pSimplePidl = ILFindLastID(pidl);
198 HRESULT hr;
199
200 hr = SHCreateDefaultExtractIcon(IID_PPV_ARG(IDefaultExtractIconInit,&initIcon));
201 if (FAILED(hr))
202 return NULL;
203
204 hr = initIcon->QueryInterface(IID_PPV_ARG(IExtractIconW,&extractIcon));
205 if (FAILED(hr))
206 return NULL;
207
208 if (_ILIsDesktop(pSimplePidl))
209 {
210 initIcon->SetNormalIcon(swShell32Name, -IDI_SHELL_DESKTOP);
211 }
212 else if ((riid = _ILGetGUIDPointer(pSimplePidl)))
213 {
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
219 };
220 WCHAR xriid[50];
221
222 swprintf(xriid, fmt,
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]);
226
227 if (HCR_GetDefaultIconW(xriid, wTemp, MAX_PATH, &icon_idx))
228 {
229 initIcon->SetNormalIcon(wTemp, icon_idx);
230 }
231 else
232 {
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);
239 else
240 initIcon->SetNormalIcon(swShell32Name, -IDI_SHELL_FOLDER);
241 }
242 }
243
244 else if (_ILIsDrive (pSimplePidl))
245 {
246 static const WCHAR drive[] = { 'D', 'r', 'i', 'v', 'e', 0 };
247 int icon_idx = -1;
248
249 if (_ILGetDrive(pSimplePidl, sTemp, MAX_PATH))
250 {
251 switch(GetDriveTypeA(sTemp))
252 {
253 case DRIVE_REMOVABLE:
254 icon_idx = IDI_SHELL_FLOPPY;
255 break;
256 case DRIVE_CDROM:
257 icon_idx = IDI_SHELL_CDROM;
258 break;
259 case DRIVE_REMOTE:
260 icon_idx = IDI_SHELL_NETDRIVE;
261 break;
262 case DRIVE_RAMDISK:
263 icon_idx = IDI_SHELL_RAMDISK;
264 break;
265 case DRIVE_NO_ROOT_DIR:
266 icon_idx = IDI_SHELL_CDROM;
267 break;
268 }
269 }
270
271 if (icon_idx != -1)
272 {
273 initIcon->SetNormalIcon(swShell32Name, -icon_idx);
274 }
275 else
276 {
277 if (HCR_GetDefaultIconW(drive, wTemp, MAX_PATH, &icon_idx))
278 initIcon->SetNormalIcon(wTemp, icon_idx);
279 else
280 initIcon->SetNormalIcon(swShell32Name, -IDI_SHELL_DRIVE);
281 }
282 }
283
284 else if (_ILIsFolder (pSimplePidl))
285 {
286 if (SUCCEEDED(getIconLocationForFolder(
287 pidl, 0, wTemp, MAX_PATH,
288 &icon_idx,
289 &flags)))
290 {
291 initIcon->SetNormalIcon(wTemp, icon_idx);
292 }
293 if (SUCCEEDED(getIconLocationForFolder(
294 pidl, GIL_DEFAULTICON, wTemp, MAX_PATH,
295 &icon_idx,
296 &flags)))
297 {
298 initIcon->SetDefaultIcon(wTemp, icon_idx);
299 }
300 if (SUCCEEDED(getIconLocationForFolder(
301 pidl, GIL_FORSHORTCUT, wTemp, MAX_PATH,
302 &icon_idx,
303 &flags)))
304 {
305 initIcon->SetShortcutIcon(wTemp, icon_idx);
306 }
307 if (SUCCEEDED(getIconLocationForFolder(
308 pidl, GIL_OPENICON, wTemp, MAX_PATH,
309 &icon_idx,
310 &flags)))
311 {
312 initIcon->SetOpenIcon(wTemp, icon_idx);
313 }
314 }
315 else
316 {
317 BOOL found = FALSE;
318
319 if (_ILIsCPanelStruct(pSimplePidl))
320 {
321 if (SUCCEEDED(CPanel_GetIconLocationW(pSimplePidl, wTemp, MAX_PATH, &icon_idx)))
322 found = TRUE;
323 }
324 else if (_ILGetExtension(pSimplePidl, sTemp, MAX_PATH))
325 {
326 if (HCR_MapTypeToValueA(sTemp, sTemp, MAX_PATH, TRUE)
327 && HCR_GetDefaultIconA(sTemp, sTemp, MAX_PATH, &icon_idx))
328 {
329 if (!lstrcmpA("%1", sTemp)) /* icon is in the file */
330 {
331 SHGetPathFromIDListW(pidl, wTemp);
332 icon_idx = 0;
333 }
334 else
335 {
336 MultiByteToWideChar(CP_ACP, 0, sTemp, -1, wTemp, MAX_PATH);
337 }
338
339 found = TRUE;
340 }
341 else if (!lstrcmpiA(sTemp, "lnkfile"))
342 {
343 /* extract icon from shell shortcut */
344 CComPtr<IShellFolder> dsf;
345 CComPtr<IShellLinkW> psl;
346
347 if (SUCCEEDED(SHGetDesktopFolder(&dsf)))
348 {
349 HRESULT hr = dsf->GetUIObjectOf(NULL, 1, (LPCITEMIDLIST*)&pidl, IID_IShellLinkW, NULL, (LPVOID *)&psl);
350
351 if (SUCCEEDED(hr))
352 {
353 hr = psl->GetIconLocation(wTemp, MAX_PATH, &icon_idx);
354
355 if (SUCCEEDED(hr) && *sTemp)
356 found = TRUE;
357
358 }
359 }
360 }
361 }
362
363 if (!found)
364 /* default icon */
365 initIcon->SetNormalIcon(swShell32Name, 0);
366 else
367 initIcon->SetNormalIcon(wTemp, icon_idx);
368 }
369
370 return extractIcon;
371 }
372
373 /**************************************************************************
374 * IExtractIconA_Constructor
375 */
376 IExtractIconA* IExtractIconA_Constructor(LPCITEMIDLIST pidl)
377 {
378 IExtractIconW *extractIconW;
379 IExtractIconA *extractIconA;
380 HRESULT hr;
381
382 extractIconW = IExtractIconW_Constructor(pidl);
383 if (!extractIconW)
384 return NULL;
385
386 hr = extractIconW->QueryInterface(IID_PPV_ARG(IExtractIconA, &extractIconA));
387 extractIconW->Release();
388 if (FAILED(hr))
389 return NULL;
390 return extractIconA;
391 }