* Addendum to r65483.
[reactos.git] / base / shell / rshell / CMergedFolder.cpp
1 /*
2 * Shell Menu Site
3 *
4 * Copyright 2014 David Quintana
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 St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20 #include "precomp.h"
21 #include <atlwin.h>
22 #include <shlwapi_undoc.h>
23
24 #include "CMergedFolder.h"
25
26 WINE_DEFAULT_DEBUG_CHANNEL(CMergedFolder);
27
28 struct LocalPidlInfo
29 {
30 BOOL shared;
31 IShellFolder * parent;
32 LPITEMIDLIST pidl;
33 };
34
35 class CEnumMergedFolder :
36 public CComObjectRootEx<CComMultiThreadModelNoCS>,
37 public IEnumIDList
38 {
39
40 private:
41 CComPtr<IShellFolder> m_UserLocalFolder;
42 CComPtr<IShellFolder> m_AllUSersFolder;
43
44 HWND m_HwndOwner;
45 SHCONTF m_Flags;
46
47 HDSA m_hDsa;
48 UINT m_hDsaIndex;
49 UINT m_hDsaCount;
50
51 public:
52 CEnumMergedFolder();
53 virtual ~CEnumMergedFolder();
54
55 DECLARE_NOT_AGGREGATABLE(CEnumMergedFolder)
56 DECLARE_PROTECT_FINAL_CONSTRUCT()
57
58 BEGIN_COM_MAP(CEnumMergedFolder)
59 COM_INTERFACE_ENTRY_IID(IID_IEnumIDList, IEnumIDList)
60 END_COM_MAP()
61
62 int DsaDeleteCallback(LocalPidlInfo * info);
63
64 static int CALLBACK s_DsaDeleteCallback(void *pItem, void *pData);
65
66 HRESULT SetSources(IShellFolder * userLocal, IShellFolder * allUSers);
67 HRESULT Begin(HWND hwndOwner, SHCONTF flags);
68 HRESULT FindPidlInList(HWND hwndOwner, LPCITEMIDLIST pcidl, LocalPidlInfo * pinfo);
69
70 virtual HRESULT STDMETHODCALLTYPE Next(
71 ULONG celt,
72 LPITEMIDLIST *rgelt,
73 ULONG *pceltFetched);
74
75 virtual HRESULT STDMETHODCALLTYPE Skip(ULONG celt);
76 virtual HRESULT STDMETHODCALLTYPE Reset();
77 virtual HRESULT STDMETHODCALLTYPE Clone(IEnumIDList **ppenum);
78 };
79
80 CEnumMergedFolder::CEnumMergedFolder() :
81 m_UserLocalFolder(NULL),
82 m_AllUSersFolder(NULL),
83 m_HwndOwner(NULL),
84 m_Flags(0),
85 m_hDsa(NULL),
86 m_hDsaIndex(0),
87 m_hDsaCount(0)
88 {
89 }
90
91 CEnumMergedFolder::~CEnumMergedFolder()
92 {
93 DSA_DestroyCallback(m_hDsa, s_DsaDeleteCallback, this);
94 }
95
96 int CEnumMergedFolder::DsaDeleteCallback(LocalPidlInfo * info)
97 {
98 ILFree(info->pidl);
99 return 0;
100 }
101
102 int CALLBACK CEnumMergedFolder::s_DsaDeleteCallback(void *pItem, void *pData)
103 {
104 CEnumMergedFolder * mf = (CEnumMergedFolder*) pData;
105 LocalPidlInfo * item = (LocalPidlInfo*) pItem;
106 return mf->DsaDeleteCallback(item);
107 }
108
109 HRESULT CEnumMergedFolder::SetSources(IShellFolder * userLocal, IShellFolder * allUSers)
110 {
111 m_UserLocalFolder = userLocal;
112 m_AllUSersFolder = allUSers;
113
114 TRACE("SetSources %p %p\n", userLocal, allUSers);
115 return S_OK;
116 }
117
118 HRESULT CEnumMergedFolder::Begin(HWND hwndOwner, SHCONTF flags)
119 {
120 HRESULT hr;
121
122 if (m_hDsa && m_HwndOwner == hwndOwner && m_Flags == flags)
123 {
124 return Reset();
125 }
126
127 TRACE("Search conditions changed, recreating list...\n");
128
129 CComPtr<IEnumIDList> userLocal;
130 CComPtr<IEnumIDList> allUSers;
131 hr = m_UserLocalFolder->EnumObjects(hwndOwner, flags, &userLocal);
132 if (FAILED_UNEXPECTEDLY(hr))
133 return hr;
134 hr = m_AllUSersFolder->EnumObjects(hwndOwner, flags, &allUSers);
135 if (FAILED_UNEXPECTEDLY(hr))
136 {
137 userLocal = NULL;
138 return hr;
139 }
140
141 if (!m_hDsa)
142 {
143 m_hDsa = DSA_Create(sizeof(LocalPidlInfo), 10);
144 }
145
146 DSA_EnumCallback(m_hDsa, s_DsaDeleteCallback, this);
147 DSA_DeleteAllItems(m_hDsa);
148 m_hDsaCount = 0;
149
150 HRESULT hr1 = S_OK;
151 HRESULT hr2 = S_OK;
152 LPITEMIDLIST pidl1 = NULL;
153 LPITEMIDLIST pidl2 = NULL;
154 int order = 0;
155 do
156 {
157 if (order <= 0)
158 {
159 if (hr1 == S_OK)
160 {
161 hr1 = userLocal->Next(1, &pidl1, NULL);
162 if (FAILED_UNEXPECTEDLY(hr1))
163 return hr1;
164 }
165 else
166 {
167 pidl1 = NULL;
168 }
169 }
170 if (order >= 0)
171 {
172 if (hr2 == S_OK)
173 {
174 hr2 = allUSers->Next(1, &pidl2, NULL);
175 if (FAILED_UNEXPECTEDLY(hr2))
176 return hr2;
177 }
178 else
179 {
180 pidl2 = NULL;
181 }
182 }
183
184 if (hr1 == S_OK && hr2 == S_OK)
185 {
186 LPWSTR name1;
187 LPWSTR name2;
188 STRRET str1 = { STRRET_WSTR };
189 STRRET str2 = { STRRET_WSTR };
190 hr = m_UserLocalFolder->GetDisplayNameOf(pidl1, SHGDN_FORPARSING | SHGDN_INFOLDER, &str1);
191 if (FAILED(hr))
192 return hr;
193 hr = m_AllUSersFolder->GetDisplayNameOf(pidl2, SHGDN_FORPARSING | SHGDN_INFOLDER, &str2);
194 if (FAILED(hr))
195 return hr;
196 StrRetToStrW(&str1, pidl1, &name1);
197 StrRetToStrW(&str2, pidl2, &name2);
198 order = StrCmpW(name1, name2);
199
200 TRACE("Both sources are S_OK, comparison between %S and %S returns %d\n", name1, name2, order);
201
202 CoTaskMemFree(name1);
203 CoTaskMemFree(name2);
204 }
205 else if (hr1 == S_OK)
206 {
207 order = -1;
208
209 TRACE("Both sources are S_OK, forcing %d\n", order);
210 }
211 else if (hr2 == S_OK)
212 {
213 order = 1;
214
215 TRACE("Both sources are S_OK, forcing %d\n", order);
216 }
217 else
218 {
219 TRACE("None of the sources\n");
220 break;
221 }
222
223 LocalPidlInfo info = { FALSE };
224 if (order < 0)
225 {
226 info.parent = m_UserLocalFolder;
227 info.pidl = ILClone(pidl1);
228 ILFree(pidl1);
229 }
230 else if (order > 0)
231 {
232 info.parent = m_AllUSersFolder;
233 info.pidl = ILClone(pidl2);
234 ILFree(pidl2);
235 }
236 else // if (order == 0)
237 {
238 info.shared = TRUE;
239 info.parent = m_UserLocalFolder;
240 info.pidl = ILClone(pidl1);
241 ILFree(pidl1);
242 ILFree(pidl2);
243 }
244
245 TRACE("Inserting item %d with parent %p and pidl { cb=%d }\n", m_hDsaCount, info.parent, info.pidl->mkid.cb);
246 int idx = DSA_InsertItem(m_hDsa, DSA_APPEND, &info);
247 TRACE("New index: %d\n", idx);
248
249 m_hDsaCount++;
250
251 } while (hr1 == S_OK || hr2 == S_OK);
252
253 m_HwndOwner = hwndOwner;
254 m_Flags = flags;
255
256 return Reset();
257 }
258
259 HRESULT CEnumMergedFolder::FindPidlInList(HWND hwndOwner, LPCITEMIDLIST pcidl, LocalPidlInfo * pinfo)
260 {
261 HRESULT hr;
262
263 if (!m_hDsa)
264 {
265 Begin(hwndOwner, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS);
266 }
267
268 TRACE("Searching for pidl { cb=%d } in a list of %d items\n", pcidl->mkid.cb, m_hDsaCount);
269
270 for (int i = 0; i < (int)m_hDsaCount; i++)
271 {
272 LocalPidlInfo * tinfo = (LocalPidlInfo *)DSA_GetItemPtr(m_hDsa, i);
273 if (!tinfo)
274 return E_FAIL;
275
276 LocalPidlInfo info = *tinfo;
277
278 TRACE("Comparing with item at %d with parent %p and pidl { cb=%d }\n", i, info.parent, info.pidl->mkid.cb);
279
280 hr = info.parent->CompareIDs(0, info.pidl, pcidl);
281 if (FAILED_UNEXPECTEDLY(hr))
282 return hr;
283
284 if (hr == S_OK)
285 {
286 *pinfo = info;
287 return S_OK;
288 }
289 else
290 {
291 TRACE("Comparison returned %d\n", (int) (short) (hr & 0xFFFF));
292 }
293 }
294
295 TRACE("Pidl not found\n");
296 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
297 }
298
299 HRESULT STDMETHODCALLTYPE CEnumMergedFolder::Next(
300 ULONG celt,
301 LPITEMIDLIST *rgelt,
302 ULONG *pceltFetched)
303 {
304 if (pceltFetched) *pceltFetched = 0;
305
306 if (m_hDsaIndex == m_hDsaCount)
307 return S_FALSE;
308
309 for (int i = 0; i < (int)celt;)
310 {
311 LocalPidlInfo * tinfo = (LocalPidlInfo *) DSA_GetItemPtr(m_hDsa, m_hDsaIndex);
312 if (!tinfo)
313 return E_FAIL;
314
315 LocalPidlInfo info = *tinfo;
316
317 TRACE("Returning next item at %d with parent %p and pidl { cb=%d }\n", m_hDsaIndex, info.parent, info.pidl->mkid.cb);
318
319 // FIXME: ILClone shouldn't be needed here! This should be causing leaks
320 if (rgelt) rgelt[i] = ILClone(info.pidl);
321 i++;
322
323 m_hDsaIndex++;
324 if (m_hDsaIndex == m_hDsaCount)
325 {
326 if (pceltFetched) *pceltFetched = i;
327 return (i == (int)celt) ? S_OK : S_FALSE;
328 }
329 }
330
331 if (pceltFetched) *pceltFetched = celt;
332 return S_OK;
333 }
334
335 HRESULT STDMETHODCALLTYPE CEnumMergedFolder::Skip(ULONG celt)
336 {
337 return Next(celt, NULL, NULL);
338 }
339
340 HRESULT STDMETHODCALLTYPE CEnumMergedFolder::Reset()
341 {
342 m_hDsaIndex = 0;
343 return S_OK;
344 }
345
346 HRESULT STDMETHODCALLTYPE CEnumMergedFolder::Clone(
347 IEnumIDList **ppenum)
348 {
349 UNIMPLEMENTED;
350 return E_NOTIMPL;
351 }
352
353 //-----------------------------------------------------------------------------
354 // CMergedFolder
355
356 extern "C"
357 HRESULT WINAPI CMergedFolder_Constructor(REFIID riid, LPVOID *ppv)
358 {
359 return ShellObjectCreator<CMergedFolder>(riid, ppv);
360 }
361
362 CMergedFolder::CMergedFolder() :
363 m_UserLocal(NULL),
364 m_AllUSers(NULL),
365 m_EnumSource(NULL),
366 m_UserLocalPidl(NULL),
367 m_AllUsersPidl(NULL),
368 m_shellPidl(NULL)
369 {
370 }
371
372 CMergedFolder::~CMergedFolder()
373 {
374 if (m_UserLocalPidl) ILFree(m_UserLocalPidl);
375 if (m_AllUsersPidl) ILFree(m_AllUsersPidl);
376 }
377
378 // IAugmentedShellFolder2
379 HRESULT STDMETHODCALLTYPE CMergedFolder::AddNameSpace(LPGUID lpGuid, IShellFolder * psf, LPCITEMIDLIST pcidl, ULONG dwUnknown)
380 {
381 if (lpGuid)
382 {
383 TRACE("FIXME: No idea how to handle the GUID\n");
384 return E_NOTIMPL;
385 }
386
387 TRACE("AddNameSpace %p %p\n", m_UserLocal.p, m_AllUSers.p);
388
389 // FIXME: Use a DSA to store the list of merged namespaces, together with their related info (psf, pidl, ...)
390 // For now, assume only 2 will ever be used, and ignore all the other data.
391 if (!m_UserLocal)
392 {
393 m_UserLocal = psf;
394 m_UserLocalPidl = ILClone(pcidl);
395 return S_OK;
396 }
397
398 if (m_AllUSers)
399 return E_FAIL;
400
401 m_AllUSers = psf;
402 m_AllUsersPidl = ILClone(pcidl);
403
404 m_EnumSource = new CComObject<CEnumMergedFolder>();
405 return m_EnumSource->SetSources(m_UserLocal, m_AllUSers);
406 }
407
408 HRESULT STDMETHODCALLTYPE CMergedFolder::GetNameSpaceID(LPCITEMIDLIST pcidl, LPGUID lpGuid)
409 {
410 UNIMPLEMENTED;
411 return E_NOTIMPL;
412 }
413
414 HRESULT STDMETHODCALLTYPE CMergedFolder::QueryNameSpace(ULONG dwUnknown, LPGUID lpGuid, IShellFolder ** ppsf)
415 {
416 UNIMPLEMENTED;
417 return E_NOTIMPL;
418 }
419
420 HRESULT STDMETHODCALLTYPE CMergedFolder::EnumNameSpace(ULONG dwUnknown, PULONG lpUnknown)
421 {
422 UNIMPLEMENTED;
423 return E_NOTIMPL;
424 }
425
426 HRESULT STDMETHODCALLTYPE CMergedFolder::UnWrapIDList(LPCITEMIDLIST pcidl, LONG lUnknown, IShellFolder ** ppsf, LPITEMIDLIST * ppidl1, LPITEMIDLIST *ppidl2, LONG * lpUnknown)
427 {
428 UNIMPLEMENTED;
429 return E_NOTIMPL;
430 }
431
432 // IShellFolder
433 HRESULT STDMETHODCALLTYPE CMergedFolder::ParseDisplayName(
434 HWND hwndOwner,
435 LPBC pbcReserved,
436 LPOLESTR lpszDisplayName,
437 ULONG *pchEaten,
438 LPITEMIDLIST *ppidl,
439 ULONG *pdwAttributes)
440 {
441 HRESULT hr;
442 LocalPidlInfo info;
443 LPITEMIDLIST pidl;
444
445 if (!ppidl) return E_FAIL;
446
447 if (pchEaten) *pchEaten = 0;
448 if (pdwAttributes) *pdwAttributes = 0;
449
450 TRACE("ParseDisplayName name=%S\n", lpszDisplayName);
451
452 hr = m_UserLocal->ParseDisplayName(hwndOwner, pbcReserved, lpszDisplayName, pchEaten, &pidl, pdwAttributes);
453 if (SUCCEEDED(hr))
454 {
455 TRACE("ParseDisplayName result local\n");
456 hr = m_EnumSource->FindPidlInList(hwndOwner, pidl, &info);
457 if (SUCCEEDED(hr))
458 {
459 ILFree(pidl);
460 *ppidl = ILClone(info.pidl);
461 return hr;
462 }
463 }
464
465 hr = m_AllUSers->ParseDisplayName(hwndOwner, pbcReserved, lpszDisplayName, pchEaten, &pidl, pdwAttributes);
466 if (SUCCEEDED(hr))
467 {
468 TRACE("ParseDisplayName result common\n");
469 hr = m_EnumSource->FindPidlInList(hwndOwner, pidl, &info);
470 if (SUCCEEDED(hr))
471 {
472 ILFree(pidl);
473 *ppidl = ILClone(info.pidl);
474 return hr;
475 }
476 }
477
478 if (ppidl) *ppidl = NULL;
479 if (pchEaten) *pchEaten = 0;
480 if (pdwAttributes) *pdwAttributes = 0;
481 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
482 }
483
484 HRESULT STDMETHODCALLTYPE CMergedFolder::EnumObjects(
485 HWND hwndOwner,
486 SHCONTF grfFlags,
487 IEnumIDList **ppenumIDList)
488 {
489 TRACE("EnumObjects\n");
490 HRESULT hr = m_EnumSource->QueryInterface(IID_PPV_ARG(IEnumIDList, ppenumIDList));
491 if (FAILED_UNEXPECTEDLY(hr))
492 return hr;
493 return m_EnumSource->Begin(hwndOwner, grfFlags);
494 }
495
496 HRESULT STDMETHODCALLTYPE CMergedFolder::BindToObject(
497 LPCITEMIDLIST pidl,
498 LPBC pbcReserved,
499 REFIID riid,
500 void **ppvOut)
501 {
502 LocalPidlInfo info;
503 HRESULT hr;
504
505 hr = m_EnumSource->FindPidlInList(NULL, pidl, &info);
506 if (FAILED_UNEXPECTEDLY(hr))
507 return hr;
508
509 TRACE("BindToObject shared = %d\n", info.shared);
510
511 if (!info.shared)
512 return info.parent->BindToObject(info.pidl, pbcReserved, riid, ppvOut);
513
514 if (riid != IID_IShellFolder)
515 return E_FAIL;
516
517 CComPtr<IShellFolder> fld1;
518 CComPtr<IShellFolder> fld2;
519
520 hr = m_UserLocal->BindToObject(info.pidl, pbcReserved, IID_PPV_ARG(IShellFolder, &fld1));
521 if (FAILED_UNEXPECTEDLY(hr))
522 return hr;
523
524 hr = m_AllUSers->BindToObject(info.pidl, pbcReserved, IID_PPV_ARG(IShellFolder, &fld2));
525 if (FAILED_UNEXPECTEDLY(hr))
526 return hr;
527
528 CComPtr<IAugmentedShellFolder> pasf;
529 hr = CMergedFolder_Constructor(IID_PPV_ARG(IAugmentedShellFolder, &pasf));
530 if (FAILED_UNEXPECTEDLY(hr))
531 return hr;
532
533 hr = pasf->QueryInterface(riid, ppvOut);
534 if (FAILED_UNEXPECTEDLY(hr))
535 return hr;
536
537 hr = pasf->AddNameSpace(NULL, fld1, info.pidl, 0xFF00);
538 if (FAILED_UNEXPECTEDLY(hr))
539 return hr;
540
541 hr = pasf->AddNameSpace(NULL, fld2, info.pidl, 0x0000);
542 if (FAILED_UNEXPECTEDLY(hr))
543 return hr;
544
545 return hr;
546 }
547
548 HRESULT STDMETHODCALLTYPE CMergedFolder::BindToStorage(
549 LPCITEMIDLIST pidl,
550 LPBC pbcReserved,
551 REFIID riid,
552 void **ppvObj)
553 {
554 UNIMPLEMENTED;
555 return E_NOTIMPL;
556 }
557
558 HRESULT STDMETHODCALLTYPE CMergedFolder::CompareIDs(
559 LPARAM lParam,
560 LPCITEMIDLIST pidl1,
561 LPCITEMIDLIST pidl2)
562 {
563 TRACE("CompareIDs\n");
564 return m_UserLocal->CompareIDs(lParam, pidl1, pidl2);
565 }
566
567 HRESULT STDMETHODCALLTYPE CMergedFolder::CreateViewObject(
568 HWND hwndOwner,
569 REFIID riid,
570 void **ppvOut)
571 {
572 UNIMPLEMENTED;
573 return E_NOTIMPL;
574 }
575
576 HRESULT STDMETHODCALLTYPE CMergedFolder::GetAttributesOf(
577 UINT cidl,
578 LPCITEMIDLIST *apidl,
579 SFGAOF *rgfInOut)
580 {
581 LocalPidlInfo info;
582 HRESULT hr;
583
584 TRACE("GetAttributesOf\n");
585
586 for (int i = 0; i < (int)cidl; i++)
587 {
588 LPCITEMIDLIST pidl = apidl[i];
589
590 hr = m_EnumSource->FindPidlInList(NULL, pidl, &info);
591 if (FAILED_UNEXPECTEDLY(hr))
592 return hr;
593
594 pidl = info.pidl;
595
596 SFGAOF * pinOut1 = rgfInOut ? rgfInOut + i : NULL;
597
598 hr = info.parent->GetAttributesOf(1, &pidl, pinOut1);
599
600 if (FAILED_UNEXPECTEDLY(hr))
601 return hr;
602 }
603
604 return S_OK;
605 }
606
607 HRESULT STDMETHODCALLTYPE CMergedFolder::GetUIObjectOf(
608 HWND hwndOwner,
609 UINT cidl,
610 LPCITEMIDLIST *apidl,
611 REFIID riid,
612 UINT *prgfInOut,
613 void **ppvOut)
614 {
615 LocalPidlInfo info;
616 HRESULT hr;
617
618 TRACE("GetUIObjectOf\n");
619
620 for (int i = 0; i < (int)cidl; i++)
621 {
622 LPCITEMIDLIST pidl = apidl[i];
623
624 TRACE("Processing GetUIObjectOf item %d of %u...\n", i, cidl);
625
626 hr = m_EnumSource->FindPidlInList(hwndOwner, pidl, &info);
627 if (FAILED_UNEXPECTEDLY(hr))
628 return hr;
629
630 pidl = info.pidl;
631
632 TRACE("FindPidlInList succeeded with parent %p and pidl { db=%d }\n", info.parent, info.pidl->mkid.cb);
633
634 UINT * pinOut1 = prgfInOut ? prgfInOut+i : NULL;
635 void** ppvOut1 = ppvOut ? ppvOut + i : NULL;
636
637 hr = info.parent->GetUIObjectOf(hwndOwner, 1, &pidl, riid, pinOut1, ppvOut1);
638
639 if (FAILED_UNEXPECTEDLY(hr))
640 return hr;
641 }
642
643 return S_OK;
644 }
645
646 HRESULT STDMETHODCALLTYPE CMergedFolder::GetDisplayNameOf(
647 LPCITEMIDLIST pidl,
648 SHGDNF uFlags,
649 STRRET *lpName)
650 {
651 LocalPidlInfo info;
652 HRESULT hr;
653
654 TRACE("GetDisplayNameOf\n");
655
656 hr = m_EnumSource->FindPidlInList(NULL, pidl, &info);
657 if (FAILED_UNEXPECTEDLY(hr))
658 return hr;
659
660 hr = info.parent->GetDisplayNameOf(info.pidl, uFlags, lpName);
661
662 if (FAILED_UNEXPECTEDLY(hr))
663 return hr;
664 return S_OK;
665 }
666
667 HRESULT STDMETHODCALLTYPE CMergedFolder::SetNameOf(
668 HWND hwnd,
669 LPCITEMIDLIST pidl,
670 LPCOLESTR lpszName,
671 SHGDNF uFlags,
672 LPITEMIDLIST *ppidlOut)
673 {
674 UNIMPLEMENTED;
675 return E_NOTIMPL;
676 }
677
678 // IPersist
679 HRESULT STDMETHODCALLTYPE CMergedFolder::GetClassID(CLSID *lpClassId)
680 {
681 UNIMPLEMENTED;
682 return E_NOTIMPL;
683 }
684
685 // IPersistFolder
686 HRESULT STDMETHODCALLTYPE CMergedFolder::Initialize(LPCITEMIDLIST pidl)
687 {
688 m_shellPidl = ILClone(pidl);
689 return S_OK;
690 }
691
692 // IPersistFolder2
693 HRESULT STDMETHODCALLTYPE CMergedFolder::GetCurFolder(LPITEMIDLIST * pidl)
694 {
695 if (pidl)
696 *pidl = m_shellPidl;
697 return S_OK;
698 }
699
700 // IShellFolder2
701 HRESULT STDMETHODCALLTYPE CMergedFolder::GetDefaultSearchGUID(
702 GUID *lpguid)
703 {
704 UNIMPLEMENTED;
705 return E_NOTIMPL;
706 }
707
708 HRESULT STDMETHODCALLTYPE CMergedFolder::EnumSearches(
709 IEnumExtraSearch **ppenum)
710 {
711 UNIMPLEMENTED;
712 return E_NOTIMPL;
713 }
714
715 HRESULT STDMETHODCALLTYPE CMergedFolder::GetDefaultColumn(
716 DWORD dwReserved,
717 ULONG *pSort,
718 ULONG *pDisplay)
719 {
720 UNIMPLEMENTED;
721 return E_NOTIMPL;
722 }
723
724 HRESULT STDMETHODCALLTYPE CMergedFolder::GetDefaultColumnState(
725 UINT iColumn,
726 SHCOLSTATEF *pcsFlags)
727 {
728 UNIMPLEMENTED;
729 return E_NOTIMPL;
730 }
731
732 HRESULT STDMETHODCALLTYPE CMergedFolder::GetDetailsEx(
733 LPCITEMIDLIST pidl,
734 const SHCOLUMNID *pscid,
735 VARIANT *pv)
736 {
737 LocalPidlInfo info;
738 HRESULT hr;
739
740 TRACE("GetDetailsEx\n");
741
742 hr = m_EnumSource->FindPidlInList(NULL, pidl, &info);
743 if (FAILED_UNEXPECTEDLY(hr))
744 return hr;
745
746 CComPtr<IShellFolder2> parent2;
747 hr = info.parent->QueryInterface(IID_PPV_ARG(IShellFolder2, &parent2));
748 if (FAILED_UNEXPECTEDLY(hr))
749 return hr;
750
751 hr = parent2->GetDetailsEx(info.pidl, pscid, pv);
752 if (FAILED_UNEXPECTEDLY(hr))
753 return hr;
754 return S_OK;
755 }
756
757 HRESULT STDMETHODCALLTYPE CMergedFolder::GetDetailsOf(
758 LPCITEMIDLIST pidl,
759 UINT iColumn,
760 SHELLDETAILS *psd)
761 {
762 LocalPidlInfo info;
763 HRESULT hr;
764
765 TRACE("GetDetailsOf\n");
766
767 hr = m_EnumSource->FindPidlInList(NULL, pidl, &info);
768 if (FAILED_UNEXPECTEDLY(hr))
769 return hr;
770
771 CComPtr<IShellFolder2> parent2;
772 hr = info.parent->QueryInterface(IID_PPV_ARG(IShellFolder2, &parent2));
773 if (FAILED_UNEXPECTEDLY(hr))
774 return hr;
775
776 hr = parent2->GetDetailsOf(info.pidl, iColumn, psd);
777
778 if (FAILED_UNEXPECTEDLY(hr))
779 return hr;
780 return S_OK;
781 }
782
783 HRESULT STDMETHODCALLTYPE CMergedFolder::MapColumnToSCID(
784 UINT iColumn,
785 SHCOLUMNID *pscid)
786 {
787 UNIMPLEMENTED;
788 return E_NOTIMPL;
789 }