[SHELL32]
[reactos.git] / reactos / dll / win32 / shell32 / folders / CRegFolder.cpp
1 /*
2 * ReactOS Shell
3 *
4 * Copyright 2016 Giannis Adamopoulos
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include <precomp.h>
22
23 WINE_DEFAULT_DEBUG_CHANNEL (shell);
24
25 HRESULT CGuidItemContextMenu_CreateInstance(PCIDLIST_ABSOLUTE pidlFolder,
26 HWND hwnd,
27 UINT cidl,
28 PCUITEMID_CHILD_ARRAY apidl,
29 IShellFolder *psf,
30 IContextMenu **ppcm)
31 {
32 HKEY hKeys[10];
33 UINT cKeys = 0;
34
35 GUID *pGuid = _ILGetGUIDPointer(apidl[0]);
36 if (pGuid)
37 {
38 LPOLESTR pwszCLSID;
39 WCHAR key[60];
40
41 wcscpy(key, L"CLSID\\");
42 HRESULT hr = StringFromCLSID(*pGuid, &pwszCLSID);
43 if (hr == S_OK)
44 {
45 wcscpy(&key[6], pwszCLSID);
46 AddClassKeyToArray(key, hKeys, &cKeys);
47 }
48 }
49 AddClassKeyToArray(L"Folder", hKeys, &cKeys);
50
51 return CDefFolderMenu_Create2(pidlFolder, hwnd, cidl, apidl, psf, NULL, cKeys, hKeys, ppcm);
52 }
53
54 HRESULT CGuidItemExtractIcon_CreateInstance(LPCITEMIDLIST pidl, REFIID iid, LPVOID * ppvOut)
55 {
56 CComPtr<IDefaultExtractIconInit> initIcon;
57 HRESULT hr;
58 GUID const * riid;
59 int icon_idx;
60 WCHAR wTemp[MAX_PATH];
61
62 hr = SHCreateDefaultExtractIcon(IID_PPV_ARG(IDefaultExtractIconInit,&initIcon));
63 if (FAILED(hr))
64 return hr;
65
66 if (_ILIsDesktop(pidl))
67 {
68 initIcon->SetNormalIcon(swShell32Name, -IDI_SHELL_DESKTOP);
69 return initIcon->QueryInterface(iid, ppvOut);
70 }
71
72 riid = _ILGetGUIDPointer(pidl);
73 if (!riid)
74 return E_FAIL;
75
76 /* my computer and other shell extensions */
77 static const WCHAR fmt[] = { 'C', 'L', 'S', 'I', 'D', '\\',
78 '{', '%', '0', '8', 'l', 'x', '-', '%', '0', '4', 'x', '-', '%', '0', '4', 'x', '-',
79 '%', '0', '2', 'x', '%', '0', '2', 'x', '-', '%', '0', '2', 'x', '%', '0', '2', 'x',
80 '%', '0', '2', 'x', '%', '0', '2', 'x', '%', '0', '2', 'x', '%', '0', '2', 'x', '}', 0
81 };
82 WCHAR xriid[50];
83
84 swprintf(xriid, fmt,
85 riid->Data1, riid->Data2, riid->Data3,
86 riid->Data4[0], riid->Data4[1], riid->Data4[2], riid->Data4[3],
87 riid->Data4[4], riid->Data4[5], riid->Data4[6], riid->Data4[7]);
88
89 const WCHAR* iconname = NULL;
90 if (_ILIsBitBucket(pidl))
91 {
92 static const WCHAR szFull[] = {'F','u','l','l',0};
93 static const WCHAR szEmpty[] = {'E','m','p','t','y',0};
94 CComPtr<IEnumIDList> EnumIDList;
95 CoInitialize(NULL);
96
97 CComPtr<IShellFolder2> psfRecycleBin;
98 CComPtr<IShellFolder> psfDesktop;
99 hr = SHGetDesktopFolder(&psfDesktop);
100
101 if (SUCCEEDED(hr))
102 hr = psfDesktop->BindToObject(pidl, NULL, IID_PPV_ARG(IShellFolder2, &psfRecycleBin));
103 if (SUCCEEDED(hr))
104 hr = psfRecycleBin->EnumObjects(NULL, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &EnumIDList);
105
106 ULONG itemcount;
107 LPITEMIDLIST pidl = NULL;
108 if (SUCCEEDED(hr) && (hr = EnumIDList->Next(1, &pidl, &itemcount)) == S_OK)
109 {
110 CoTaskMemFree(pidl);
111 iconname = szFull;
112 } else {
113 iconname = szEmpty;
114 }
115 }
116
117 if (HCR_GetIconW(xriid, wTemp, iconname, MAX_PATH, &icon_idx))
118 {
119 initIcon->SetNormalIcon(wTemp, icon_idx);
120 }
121 else
122 {
123 if (IsEqualGUID(*riid, CLSID_MyComputer))
124 initIcon->SetNormalIcon(swShell32Name, -IDI_SHELL_MY_COMPUTER);
125 else if (IsEqualGUID(*riid, CLSID_MyDocuments))
126 initIcon->SetNormalIcon(swShell32Name, -IDI_SHELL_MY_DOCUMENTS);
127 else if (IsEqualGUID(*riid, CLSID_NetworkPlaces))
128 initIcon->SetNormalIcon(swShell32Name, -IDI_SHELL_MY_NETWORK_PLACES);
129 else
130 initIcon->SetNormalIcon(swShell32Name, -IDI_SHELL_FOLDER);
131 }
132
133 return initIcon->QueryInterface(iid, ppvOut);
134 }
135
136 class CRegFolder :
137 public CComObjectRootEx<CComMultiThreadModelNoCS>,
138 public IShellFolder2
139 {
140 private:
141 GUID m_guid;
142 CAtlStringW m_rootPath;
143 CComHeapPtr<ITEMIDLIST> m_pidlRoot;
144
145 HRESULT GetGuidItemAttributes (LPCITEMIDLIST pidl, LPDWORD pdwAttributes);
146 public:
147 CRegFolder();
148 ~CRegFolder();
149 HRESULT WINAPI Initialize(const GUID *pGuid, LPCITEMIDLIST pidlRoot, LPCWSTR lpszPath);
150
151 // IShellFolder
152 virtual HRESULT WINAPI ParseDisplayName(HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName, ULONG *pchEaten, PIDLIST_RELATIVE *ppidl, ULONG *pdwAttributes);
153 virtual HRESULT WINAPI EnumObjects(HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList);
154 virtual HRESULT WINAPI BindToObject(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut);
155 virtual HRESULT WINAPI BindToStorage(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut);
156 virtual HRESULT WINAPI CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2);
157 virtual HRESULT WINAPI CreateViewObject(HWND hwndOwner, REFIID riid, LPVOID *ppvOut);
158 virtual HRESULT WINAPI GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, DWORD *rgfInOut);
159 virtual HRESULT WINAPI GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_ARRAY apidl, REFIID riid, UINT * prgfInOut, LPVOID * ppvOut);
160 virtual HRESULT WINAPI GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET strRet);
161 virtual HRESULT WINAPI SetNameOf(HWND hwndOwner, PCUITEMID_CHILD pidl, LPCOLESTR lpName, DWORD dwFlags, PITEMID_CHILD *pPidlOut);
162
163 /* ShellFolder2 */
164 virtual HRESULT WINAPI GetDefaultSearchGUID(GUID *pguid);
165 virtual HRESULT WINAPI EnumSearches(IEnumExtraSearch **ppenum);
166 virtual HRESULT WINAPI GetDefaultColumn(DWORD dwRes, ULONG *pSort, ULONG *pDisplay);
167 virtual HRESULT WINAPI GetDefaultColumnState(UINT iColumn, DWORD *pcsFlags);
168 virtual HRESULT WINAPI GetDetailsEx(PCUITEMID_CHILD pidl, const SHCOLUMNID *pscid, VARIANT *pv);
169 virtual HRESULT WINAPI GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDETAILS *psd);
170 virtual HRESULT WINAPI MapColumnToSCID(UINT column, SHCOLUMNID *pscid);
171
172 DECLARE_NOT_AGGREGATABLE(CRegFolder)
173
174 DECLARE_PROTECT_FINAL_CONSTRUCT()
175
176 BEGIN_COM_MAP(CRegFolder)
177 COM_INTERFACE_ENTRY_IID(IID_IShellFolder2, IShellFolder2)
178 COM_INTERFACE_ENTRY_IID(IID_IShellFolder, IShellFolder)
179 END_COM_MAP()
180 };
181
182 CRegFolder::CRegFolder()
183 {
184 }
185
186 CRegFolder::~CRegFolder()
187 {
188 }
189
190 HRESULT WINAPI CRegFolder::Initialize(const GUID *pGuid, LPCITEMIDLIST pidlRoot, LPCWSTR lpszPath)
191 {
192 memcpy(&m_guid, pGuid, sizeof(m_guid));
193
194 m_rootPath = lpszPath;
195 if (!m_rootPath)
196 return E_OUTOFMEMORY;
197
198 m_pidlRoot.Attach(ILClone(pidlRoot));
199 if (!m_pidlRoot)
200 return E_OUTOFMEMORY;
201
202 return S_OK;
203 }
204
205 HRESULT CRegFolder::GetGuidItemAttributes (LPCITEMIDLIST pidl, LPDWORD pdwAttributes)
206 {
207 DWORD dwAttributes = *pdwAttributes;
208
209 /* First try to get them from the registry */
210 if (!HCR_GetFolderAttributes(pidl, pdwAttributes))
211 {
212 /* We couldn't get anything */
213 *pdwAttributes = 0;
214 }
215
216 /* Items have more attributes when on desktop */
217 if (_ILIsDesktop(m_pidlRoot))
218 {
219 *pdwAttributes |= (dwAttributes & (SFGAO_CANLINK|SFGAO_CANDELETE|SFGAO_CANRENAME|SFGAO_HASPROPSHEET));
220 }
221
222 /* In any case, links can be created */
223 if (*pdwAttributes == NULL)
224 {
225 *pdwAttributes |= (dwAttributes & SFGAO_CANLINK);
226 }
227 return S_OK;
228 }
229
230 HRESULT WINAPI CRegFolder::ParseDisplayName(HWND hwndOwner, LPBC pbc, LPOLESTR lpszDisplayName,
231 ULONG *pchEaten, PIDLIST_RELATIVE *ppidl, ULONG *pdwAttributes)
232 {
233 LPITEMIDLIST pidl;
234
235 if (!lpszDisplayName || !ppidl)
236 return E_INVALIDARG;
237
238 *ppidl = 0;
239
240 if (pchEaten)
241 *pchEaten = 0;
242
243 UINT cch = wcslen(lpszDisplayName);
244 if (cch < 39 || lpszDisplayName[0] != L':' || lpszDisplayName[1] != L':')
245 return E_FAIL;
246
247 pidl = _ILCreateGuidFromStrW(lpszDisplayName + 2);
248 if (pidl == NULL)
249 return E_FAIL;
250
251 if (cch < 41)
252 {
253 *ppidl = pidl;
254 if (pdwAttributes && *pdwAttributes)
255 {
256 GetGuidItemAttributes(*ppidl, pdwAttributes);
257 }
258 }
259 else
260 {
261 HRESULT hr = SHELL32_ParseNextElement(this, hwndOwner, pbc, &pidl, lpszDisplayName + 41, pchEaten, pdwAttributes);
262 if (SUCCEEDED(hr))
263 {
264 *ppidl = pidl;
265 }
266 return hr;
267 }
268
269 return S_OK;
270 }
271
272 HRESULT WINAPI CRegFolder::EnumObjects(HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST *ppEnumIDList)
273 {
274 return E_NOTIMPL;
275 }
276
277 HRESULT WINAPI CRegFolder::BindToObject(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
278 {
279 CComPtr<IPersistFolder> pFolder;
280 HRESULT hr;
281
282 if (!ppvOut || !pidl || !pidl->mkid.cb)
283 return E_INVALIDARG;
284
285 *ppvOut = NULL;
286
287 GUID *pGUID = _ILGetGUIDPointer(pidl);
288 if (!pGUID)
289 {
290 ERR("CRegFolder::BindToObject called for non guid item!\n");
291 return E_INVALIDARG;
292 }
293
294 LPITEMIDLIST pidlChild = ILCloneFirst (pidl);
295 if (!pidlChild)
296 return E_OUTOFMEMORY;
297
298 CComPtr<IShellFolder> psf;
299 hr = SHELL32_CoCreateInitSF(m_pidlRoot, NULL, pidlChild, pGUID, -1, IID_PPV_ARG(IShellFolder, &psf));
300 ILFree(pidlChild);
301 if (FAILED(hr))
302 return hr;
303
304 if (_ILIsPidlSimple (pidl))
305 {
306 return psf->QueryInterface(riid, ppvOut);
307 }
308 else
309 {
310 return psf->BindToObject(ILGetNext (pidl), pbcReserved, riid, ppvOut);
311 }
312 }
313
314 HRESULT WINAPI CRegFolder::BindToStorage(PCUIDLIST_RELATIVE pidl, LPBC pbcReserved, REFIID riid, LPVOID *ppvOut)
315 {
316 return E_NOTIMPL;
317 }
318
319 HRESULT WINAPI CRegFolder::CompareIDs(LPARAM lParam, PCUIDLIST_RELATIVE pidl1, PCUIDLIST_RELATIVE pidl2)
320 {
321 if (!pidl1 || !pidl2 || pidl1->mkid.cb == 0 || pidl2->mkid.cb == 0)
322 {
323 ERR("Got an empty pidl!\n");
324 return E_INVALIDARG;
325 }
326
327 GUID const *clsid1 = _ILGetGUIDPointer (pidl1);
328 GUID const *clsid2 = _ILGetGUIDPointer (pidl2);
329
330 if (!clsid1 && !clsid2)
331 {
332 ERR("Got no guid pidl!\n");
333 return E_INVALIDARG;
334 }
335 else if (clsid1 && clsid2)
336 {
337 if (memcmp(clsid1, clsid2, sizeof(GUID)) == 0)
338 return SHELL32_CompareChildren(this, lParam, pidl1, pidl2);
339
340 return SHELL32_CompareDetails(this, lParam, pidl1, pidl2);
341 }
342
343 /* Guid folders come first compared to everything else */
344 return MAKE_COMPARE_HRESULT(clsid1 ? -1 : 1);
345 }
346
347 HRESULT WINAPI CRegFolder::CreateViewObject(HWND hwndOwner, REFIID riid, LPVOID *ppvOut)
348 {
349 return E_NOTIMPL;
350 }
351
352 HRESULT WINAPI CRegFolder::GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, DWORD *rgfInOut)
353 {
354 if (!rgfInOut || !cidl || !apidl)
355 return E_INVALIDARG;
356
357 if (*rgfInOut == 0)
358 *rgfInOut = ~0;
359
360 while(cidl > 0 && *apidl)
361 {
362 if (_ILIsSpecialFolder(*apidl))
363 GetGuidItemAttributes(*apidl, rgfInOut);
364 else
365 ERR("Got an unkown pidl here!\n");
366 apidl++;
367 cidl--;
368 }
369
370 /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
371 *rgfInOut &= ~SFGAO_VALIDATE;
372
373 return S_OK;
374 }
375
376 HRESULT WINAPI CRegFolder::GetUIObjectOf(HWND hwndOwner, UINT cidl, PCUITEMID_CHILD_ARRAY apidl,
377 REFIID riid, UINT * prgfInOut, LPVOID * ppvOut)
378 {
379 LPVOID pObj = NULL;
380 HRESULT hr = E_INVALIDARG;
381
382 if (!ppvOut)
383 return hr;
384
385 *ppvOut = NULL;
386
387 if ((IsEqualIID (riid, IID_IExtractIconA) || IsEqualIID (riid, IID_IExtractIconW)) && (cidl == 1))
388 {
389 hr = CGuidItemExtractIcon_CreateInstance(apidl[0], riid, &pObj);
390 }
391 else if (IsEqualIID (riid, IID_IContextMenu) && (cidl >= 1))
392 {
393 if (!_ILGetGUIDPointer (apidl[0]))
394 {
395 ERR("Got non guid item!\n");
396 return E_FAIL;
397 }
398
399 hr = CGuidItemContextMenu_CreateInstance(m_pidlRoot, hwndOwner, cidl, apidl, static_cast<IShellFolder*>(this), (IContextMenu**)&pObj);
400 }
401 else
402 {
403 hr = E_NOINTERFACE;
404 }
405
406 *ppvOut = pObj;
407 return hr;
408
409 }
410
411 HRESULT WINAPI CRegFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl, DWORD dwFlags, LPSTRRET strRet)
412 {
413 if (!strRet || (!_ILIsSpecialFolder(pidl) && pidl != NULL))
414 return E_INVALIDARG;
415
416 if (!pidl || !pidl->mkid.cb)
417 {
418 if ((GET_SHGDN_RELATION(dwFlags) == SHGDN_NORMAL) && (GET_SHGDN_FOR(dwFlags) & SHGDN_FORPARSING))
419 {
420 LPWSTR pszPath = (LPWSTR)CoTaskMemAlloc((MAX_PATH + 1) * sizeof(WCHAR));
421 if (!pszPath)
422 return E_OUTOFMEMORY;
423
424 /* parsing name like ::{...} */
425 pszPath[0] = ':';
426 pszPath[1] = ':';
427 SHELL32_GUIDToStringW(m_guid, &pszPath[2]);
428
429 strRet->uType = STRRET_WSTR;
430 strRet->pOleStr = pszPath;
431
432 return S_OK;
433 }
434 else
435 {
436 return HCR_GetClassName(m_guid, strRet);
437 }
438 }
439
440 HRESULT hr;
441 GUID const *clsid = _ILGetGUIDPointer (pidl);
442
443 /* First of all check if we need to query the name from the child item */
444 if (GET_SHGDN_FOR (dwFlags) == SHGDN_FORPARSING &&
445 GET_SHGDN_RELATION (dwFlags) == SHGDN_NORMAL)
446 {
447 int bWantsForParsing = FALSE;
448
449 /*
450 * We can only get a filesystem path from a shellfolder if the
451 * value WantsFORPARSING in CLSID\\{...}\\shellfolder exists.
452 *
453 * Exception: The MyComputer folder doesn't have this key,
454 * but any other filesystem backed folder it needs it.
455 */
456 if (IsEqualIID (*clsid, CLSID_MyComputer))
457 {
458 bWantsForParsing = TRUE;
459 }
460 else
461 {
462 HKEY hkeyClass;
463 if (HCR_RegOpenClassIDKey(*clsid, &hkeyClass))
464 {
465 LONG res = SHGetValueW(hkeyClass, L"Shellfolder", L"WantsForParsing", NULL, NULL, NULL);
466 bWantsForParsing = (res == ERROR_SUCCESS);
467 RegCloseKey(hkeyClass);
468 }
469 }
470
471 if (bWantsForParsing)
472 {
473 /*
474 * we need the filesystem path to the destination folder.
475 * Only the folder itself can know it
476 */
477 return SHELL32_GetDisplayNameOfChild (this, pidl, dwFlags, strRet);
478 }
479 }
480
481 /* Allocate the buffer for the result */
482 LPWSTR pszPath = (LPWSTR)CoTaskMemAlloc((MAX_PATH + 1) * sizeof(WCHAR));
483 if (!pszPath)
484 return E_OUTOFMEMORY;
485
486 hr = S_OK;
487
488 if (GET_SHGDN_FOR (dwFlags) == SHGDN_FORPARSING)
489 {
490 wcscpy(pszPath, m_rootPath);
491 PWCHAR pItemName = &pszPath[wcslen(pszPath)];
492
493 /* parsing name like ::{...} */
494 pItemName[0] = ':';
495 pItemName[1] = ':';
496 SHELL32_GUIDToStringW (*clsid, &pItemName[2]);
497 }
498 else
499 {
500 /* user friendly name */
501 if (!HCR_GetClassNameW (*clsid, pszPath, MAX_PATH))
502 hr = E_FAIL;
503 }
504
505 if (SUCCEEDED(hr))
506 {
507 strRet->uType = STRRET_WSTR;
508 strRet->pOleStr = pszPath;
509 }
510 else
511 {
512 CoTaskMemFree(pszPath);
513 }
514
515 return hr;
516 }
517
518 HRESULT WINAPI CRegFolder::SetNameOf(HWND hwndOwner, PCUITEMID_CHILD pidl, /* simple pidl */
519 LPCOLESTR lpName, DWORD dwFlags, PITEMID_CHILD *pPidlOut)
520 {
521 GUID const *clsid = _ILGetGUIDPointer (pidl);
522 LPOLESTR pStr;
523 HRESULT hr;
524 WCHAR szName[100];
525
526 if (!clsid)
527 {
528 ERR("Pidl is not reg item!\n");
529 return E_FAIL;
530 }
531
532 hr = StringFromCLSID(*clsid, &pStr);
533 if (FAILED_UNEXPECTEDLY(hr))
534 return hr;
535
536 swprintf(szName, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\CLSID\\%s", pStr);
537
538 DWORD cbData = (wcslen(lpName) + 1) * sizeof(WCHAR);
539 LONG res = SHSetValueW(HKEY_CURRENT_USER, szName, NULL, RRF_RT_REG_SZ, lpName, cbData);
540
541 CoTaskMemFree(pStr);
542
543 if (res == ERROR_SUCCESS)
544 {
545 *pPidlOut = ILClone(pidl);
546 return S_OK;
547 }
548
549 return E_FAIL;
550 }
551
552
553 HRESULT WINAPI CRegFolder::GetDefaultSearchGUID(GUID *pguid)
554 {
555 return E_NOTIMPL;
556 }
557
558 HRESULT WINAPI CRegFolder::EnumSearches(IEnumExtraSearch ** ppenum)
559 {
560 return E_NOTIMPL;
561 }
562
563 HRESULT WINAPI CRegFolder::GetDefaultColumn(DWORD dwRes, ULONG *pSort, ULONG *pDisplay)
564 {
565 if (pSort)
566 *pSort = 0;
567 if (pDisplay)
568 *pDisplay = 0;
569
570 return S_OK;
571 }
572
573 HRESULT WINAPI CRegFolder::GetDefaultColumnState(UINT iColumn, DWORD *pcsFlags)
574 {
575 if (iColumn >= 2)
576 return E_INVALIDARG;
577 *pcsFlags = SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT;
578 return S_OK;
579 }
580
581 HRESULT WINAPI CRegFolder::GetDetailsEx(PCUITEMID_CHILD pidl, const SHCOLUMNID *pscid, VARIANT *pv)
582 {
583 return E_NOTIMPL;
584 }
585
586 HRESULT WINAPI CRegFolder::GetDetailsOf(PCUITEMID_CHILD pidl, UINT iColumn, SHELLDETAILS *psd)
587 {
588 if (!psd || iColumn >= 2)
589 return E_INVALIDARG;
590
591 GUID const *clsid = _ILGetGUIDPointer (pidl);
592
593 if (!clsid)
594 {
595 ERR("Pidl is not reg item!\n");
596 return E_INVALIDARG;
597 }
598
599 switch(iColumn)
600 {
601 case 0: /* name */
602 return GetDisplayNameOf(pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
603 case 1: /* comment */
604 HKEY hKey;
605 if (HCR_RegOpenClassIDKey(*clsid, &hKey))
606 {
607 psd->str.cStr[0] = 0x00;
608 psd->str.uType = STRRET_CSTR;
609 RegLoadMUIStringA(hKey, "InfoTip", psd->str.cStr, MAX_PATH, NULL, 0, NULL);
610 RegCloseKey(hKey);
611 return S_OK;
612 }
613 }
614 return E_FAIL;
615 }
616
617 HRESULT WINAPI CRegFolder::MapColumnToSCID(UINT column, SHCOLUMNID *pscid)
618 {
619 return E_NOTIMPL;
620 }
621
622 /* In latest windows version this is exported but it takes different arguments! */
623 HRESULT CRegFolder_CreateInstance(const GUID *pGuid, LPCITEMIDLIST pidlRoot, LPCWSTR lpszPath, REFIID riid, void **ppv)
624 {
625 return ShellObjectCreatorInit<CRegFolder>(pGuid, pidlRoot, lpszPath, riid, ppv);
626 }