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