2 * IShellItem and IShellItemArray implementations
4 * Copyright 2008 Vincent Povirk for CodeWeavers
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.
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.
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
22 #include "wine/port.h"
28 #define NONAMELESSUNION
32 #include "wine/debug.h"
35 #include "shell32_main.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
40 typedef struct _ShellItem
{
41 IShellItem2 IShellItem2_iface
;
44 IPersistIDList IPersistIDList_iface
;
47 typedef struct _CustomDestinationList
{
48 ICustomDestinationList ICustomDestinationList_iface
;
50 } CustomDestinationList
;
52 static inline ShellItem
*impl_from_IShellItem2(IShellItem2
*iface
)
54 return CONTAINING_RECORD(iface
, ShellItem
, IShellItem2_iface
);
57 static inline ShellItem
*impl_from_IPersistIDList( IPersistIDList
*iface
)
59 return CONTAINING_RECORD(iface
, ShellItem
, IPersistIDList_iface
);
62 static inline CustomDestinationList
*impl_from_ICustomDestinationList( ICustomDestinationList
*iface
)
64 return CONTAINING_RECORD(iface
, CustomDestinationList
, ICustomDestinationList_iface
);
67 static HRESULT WINAPI
ShellItem_QueryInterface(IShellItem2
*iface
, REFIID riid
,
70 ShellItem
*This
= impl_from_IShellItem2(iface
);
72 TRACE("(%p, %s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
74 if (!ppv
) return E_INVALIDARG
;
76 if (IsEqualIID(&IID_IUnknown
, riid
) || IsEqualIID(&IID_IShellItem
, riid
) ||
77 IsEqualIID(&IID_IShellItem2
, riid
))
79 *ppv
= &This
->IShellItem2_iface
;
81 else if (IsEqualIID(&IID_IPersist
, riid
) || IsEqualIID(&IID_IPersistIDList
, riid
))
83 *ppv
= &This
->IPersistIDList_iface
;
86 FIXME("not implemented for %s\n", shdebugstr_guid(riid
));
91 IUnknown_AddRef((IUnknown
*)*ppv
);
95 static ULONG WINAPI
ShellItem_AddRef(IShellItem2
*iface
)
97 ShellItem
*This
= impl_from_IShellItem2(iface
);
98 ULONG ref
= InterlockedIncrement(&This
->ref
);
100 TRACE("(%p), new refcount=%i\n", iface
, ref
);
105 static ULONG WINAPI
ShellItem_Release(IShellItem2
*iface
)
107 ShellItem
*This
= impl_from_IShellItem2(iface
);
108 ULONG ref
= InterlockedDecrement(&This
->ref
);
110 TRACE("(%p), new refcount=%i\n", iface
, ref
);
115 HeapFree(GetProcessHeap(), 0, This
);
121 static HRESULT
ShellItem_get_parent_pidl(ShellItem
*This
, LPITEMIDLIST
*parent_pidl
)
123 *parent_pidl
= ILClone(This
->pidl
);
126 if (ILRemoveLastID(*parent_pidl
))
130 ILFree(*parent_pidl
);
138 return E_OUTOFMEMORY
;
142 static HRESULT
ShellItem_get_parent_shellfolder(ShellItem
*This
, IShellFolder
**ppsf
)
144 LPITEMIDLIST parent_pidl
;
145 IShellFolder
*desktop
;
148 ret
= ShellItem_get_parent_pidl(This
, &parent_pidl
);
151 ret
= SHGetDesktopFolder(&desktop
);
154 if (_ILIsDesktop(parent_pidl
))
160 ret
= IShellFolder_BindToObject(desktop
, parent_pidl
, NULL
, &IID_IShellFolder
, (void**)ppsf
);
161 IShellFolder_Release(desktop
);
170 static HRESULT
ShellItem_get_shellfolder(ShellItem
*This
, IBindCtx
*pbc
, IShellFolder
**ppsf
)
172 IShellFolder
*desktop
;
175 ret
= SHGetDesktopFolder(&desktop
);
178 if (_ILIsDesktop(This
->pidl
))
181 IShellFolder_AddRef(*ppsf
);
185 ret
= IShellFolder_BindToObject(desktop
, This
->pidl
, pbc
, &IID_IShellFolder
, (void**)ppsf
);
188 IShellFolder_Release(desktop
);
194 static HRESULT WINAPI
ShellItem_BindToHandler(IShellItem2
*iface
, IBindCtx
*pbc
,
195 REFGUID rbhid
, REFIID riid
, void **ppvOut
)
197 ShellItem
*This
= impl_from_IShellItem2(iface
);
199 TRACE("(%p,%p,%s,%p,%p)\n", iface
, pbc
, shdebugstr_guid(rbhid
), riid
, ppvOut
);
202 if (IsEqualGUID(rbhid
, &BHID_SFObject
))
205 ret
= ShellItem_get_shellfolder(This
, pbc
, &psf
);
208 ret
= IShellFolder_QueryInterface(psf
, riid
, ppvOut
);
209 IShellFolder_Release(psf
);
213 else if (IsEqualGUID(rbhid
, &BHID_SFUIObject
))
215 IShellFolder
*psf_parent
;
216 if (_ILIsDesktop(This
->pidl
))
217 ret
= SHGetDesktopFolder(&psf_parent
);
219 ret
= ShellItem_get_parent_shellfolder(This
, &psf_parent
);
223 LPCITEMIDLIST pidl
= ILFindLastID(This
->pidl
);
224 ret
= IShellFolder_GetUIObjectOf(psf_parent
, NULL
, 1, &pidl
, riid
, NULL
, ppvOut
);
225 IShellFolder_Release(psf_parent
);
229 else if (IsEqualGUID(rbhid
, &BHID_DataObject
))
231 return ShellItem_BindToHandler(&This
->IShellItem2_iface
, pbc
, &BHID_SFUIObject
,
232 &IID_IDataObject
, ppvOut
);
235 FIXME("Unsupported BHID %s.\n", debugstr_guid(rbhid
));
237 return MK_E_NOOBJECT
;
240 static HRESULT WINAPI
ShellItem_GetParent(IShellItem2
*iface
, IShellItem
**ppsi
)
242 ShellItem
*This
= impl_from_IShellItem2(iface
);
243 LPITEMIDLIST parent_pidl
;
246 TRACE("(%p,%p)\n", iface
, ppsi
);
248 ret
= ShellItem_get_parent_pidl(This
, &parent_pidl
);
251 ret
= SHCreateShellItem(NULL
, NULL
, parent_pidl
, ppsi
);
258 static HRESULT WINAPI
ShellItem_GetDisplayName(IShellItem2
*iface
, SIGDN sigdnName
,
261 ShellItem
*This
= impl_from_IShellItem2(iface
);
262 TRACE("(%p,%x,%p)\n", iface
, sigdnName
, ppszName
);
264 return SHGetNameFromIDList(This
->pidl
, sigdnName
, ppszName
);
267 static HRESULT WINAPI
ShellItem_GetAttributes(IShellItem2
*iface
, SFGAOF sfgaoMask
,
268 SFGAOF
*psfgaoAttribs
)
270 ShellItem
*This
= impl_from_IShellItem2(iface
);
271 IShellFolder
*parent_folder
;
272 LPITEMIDLIST child_pidl
;
275 TRACE("(%p,%x,%p)\n", iface
, sfgaoMask
, psfgaoAttribs
);
277 if (_ILIsDesktop(This
->pidl
))
278 ret
= SHGetDesktopFolder(&parent_folder
);
280 ret
= ShellItem_get_parent_shellfolder(This
, &parent_folder
);
283 child_pidl
= ILFindLastID(This
->pidl
);
284 *psfgaoAttribs
= sfgaoMask
;
285 ret
= IShellFolder_GetAttributesOf(parent_folder
, 1, (LPCITEMIDLIST
*)&child_pidl
, psfgaoAttribs
);
286 *psfgaoAttribs
&= sfgaoMask
;
287 IShellFolder_Release(parent_folder
);
291 if(sfgaoMask
== *psfgaoAttribs
)
301 static HRESULT WINAPI
ShellItem_Compare(IShellItem2
*iface
, IShellItem
*oth
,
302 SICHINTF hint
, int *piOrder
)
304 LPWSTR dispname
, dispname_oth
;
306 TRACE("(%p,%p,%x,%p)\n", iface
, oth
, hint
, piOrder
);
308 if(hint
& (SICHINT_CANONICAL
| SICHINT_ALLFIELDS
))
309 FIXME("Unsupported flags 0x%08x\n", hint
);
311 ret
= IShellItem2_GetDisplayName(iface
, SIGDN_DESKTOPABSOLUTEEDITING
, &dispname
);
314 ret
= IShellItem_GetDisplayName(oth
, SIGDN_DESKTOPABSOLUTEEDITING
, &dispname_oth
);
317 *piOrder
= lstrcmpiW(dispname
, dispname_oth
);
318 CoTaskMemFree(dispname_oth
);
320 CoTaskMemFree(dispname
);
323 if(SUCCEEDED(ret
) && *piOrder
&&
324 (hint
& SICHINT_TEST_FILESYSPATH_IF_NOT_EQUAL
))
326 LPWSTR dispname
, dispname_oth
;
328 TRACE("Testing filesystem path.\n");
329 ret
= IShellItem2_GetDisplayName(iface
, SIGDN_FILESYSPATH
, &dispname
);
332 ret
= IShellItem_GetDisplayName(oth
, SIGDN_FILESYSPATH
, &dispname_oth
);
335 *piOrder
= lstrcmpiW(dispname
, dispname_oth
);
336 CoTaskMemFree(dispname_oth
);
338 CoTaskMemFree(dispname
);
351 static HRESULT WINAPI
ShellItem2_GetPropertyStore(IShellItem2
*iface
, GETPROPERTYSTOREFLAGS flags
,
352 REFIID riid
, void **ppv
)
354 ShellItem
*This
= impl_from_IShellItem2(iface
);
355 FIXME("Stub: %p (%d, %s, %p)\n", This
, flags
, shdebugstr_guid(riid
), ppv
);
359 static HRESULT WINAPI
ShellItem2_GetPropertyStoreWithCreateObject(IShellItem2
*iface
,
360 GETPROPERTYSTOREFLAGS flags
, IUnknown
*punkCreateObject
, REFIID riid
, void **ppv
)
362 ShellItem
*This
= impl_from_IShellItem2(iface
);
363 FIXME("Stub: %p (%08x, %p, %s, %p)\n",
364 This
, flags
, punkCreateObject
, shdebugstr_guid(riid
), ppv
);
368 static HRESULT WINAPI
ShellItem2_GetPropertyStoreForKeys(IShellItem2
*iface
, const PROPERTYKEY
*rgKeys
,
369 UINT cKeys
, GETPROPERTYSTOREFLAGS flags
, REFIID riid
, void **ppv
)
371 ShellItem
*This
= impl_from_IShellItem2(iface
);
372 FIXME("Stub: %p (%p, %d, %08x, %s, %p)\n",
373 This
, rgKeys
, cKeys
, flags
, shdebugstr_guid(riid
), ppv
);
377 static HRESULT WINAPI
ShellItem2_GetPropertyDescriptionList(IShellItem2
*iface
,
378 REFPROPERTYKEY keyType
, REFIID riid
, void **ppv
)
380 ShellItem
*This
= impl_from_IShellItem2(iface
);
381 FIXME("Stub: %p (%p, %s, %p)\n", This
, keyType
, debugstr_guid(riid
), ppv
);
385 static HRESULT WINAPI
ShellItem2_Update(IShellItem2
*iface
, IBindCtx
*pbc
)
387 ShellItem
*This
= impl_from_IShellItem2(iface
);
388 FIXME("Stub: %p (%p)\n", This
, pbc
);
392 static HRESULT WINAPI
ShellItem2_GetProperty(IShellItem2
*iface
, REFPROPERTYKEY key
, PROPVARIANT
*ppropvar
)
394 ShellItem
*This
= impl_from_IShellItem2(iface
);
395 FIXME("Stub: %p (%p, %p)\n", This
, key
, ppropvar
);
399 static HRESULT WINAPI
ShellItem2_GetCLSID(IShellItem2
*iface
, REFPROPERTYKEY key
, CLSID
*pclsid
)
401 ShellItem
*This
= impl_from_IShellItem2(iface
);
402 FIXME("Stub: %p (%p, %p)\n", This
, key
, pclsid
);
406 static HRESULT WINAPI
ShellItem2_GetFileTime(IShellItem2
*iface
, REFPROPERTYKEY key
, FILETIME
*pft
)
408 ShellItem
*This
= impl_from_IShellItem2(iface
);
409 FIXME("Stub: %p (%p, %p)\n", This
, key
, pft
);
413 static HRESULT WINAPI
ShellItem2_GetInt32(IShellItem2
*iface
, REFPROPERTYKEY key
, int *pi
)
415 ShellItem
*This
= impl_from_IShellItem2(iface
);
416 FIXME("Stub: %p (%p, %p)\n", This
, key
, pi
);
420 static HRESULT WINAPI
ShellItem2_GetString(IShellItem2
*iface
, REFPROPERTYKEY key
, LPWSTR
*ppsz
)
422 ShellItem
*This
= impl_from_IShellItem2(iface
);
423 FIXME("Stub: %p (%p, %p)\n", This
, key
, ppsz
);
427 static HRESULT WINAPI
ShellItem2_GetUInt32(IShellItem2
*iface
, REFPROPERTYKEY key
, ULONG
*pui
)
429 ShellItem
*This
= impl_from_IShellItem2(iface
);
430 FIXME("Stub: %p (%p, %p)\n", This
, key
, pui
);
434 static HRESULT WINAPI
ShellItem2_GetUInt64(IShellItem2
*iface
, REFPROPERTYKEY key
, ULONGLONG
*pull
)
436 ShellItem
*This
= impl_from_IShellItem2(iface
);
437 FIXME("Stub: %p (%p, %p)\n", This
, key
, pull
);
441 static HRESULT WINAPI
ShellItem2_GetBool(IShellItem2
*iface
, REFPROPERTYKEY key
, BOOL
*pf
)
443 ShellItem
*This
= impl_from_IShellItem2(iface
);
444 FIXME("Stub: %p (%p, %p)\n", This
, key
, pf
);
449 static const IShellItem2Vtbl ShellItem2_Vtbl
= {
450 ShellItem_QueryInterface
,
453 ShellItem_BindToHandler
,
455 ShellItem_GetDisplayName
,
456 ShellItem_GetAttributes
,
458 ShellItem2_GetPropertyStore
,
459 ShellItem2_GetPropertyStoreWithCreateObject
,
460 ShellItem2_GetPropertyStoreForKeys
,
461 ShellItem2_GetPropertyDescriptionList
,
463 ShellItem2_GetProperty
,
465 ShellItem2_GetFileTime
,
467 ShellItem2_GetString
,
468 ShellItem2_GetUInt32
,
469 ShellItem2_GetUInt64
,
473 static HRESULT WINAPI
ShellItem_IPersistIDList_QueryInterface(IPersistIDList
*iface
,
474 REFIID riid
, void **ppv
)
476 ShellItem
*This
= impl_from_IPersistIDList(iface
);
477 return IShellItem2_QueryInterface(&This
->IShellItem2_iface
, riid
, ppv
);
480 static ULONG WINAPI
ShellItem_IPersistIDList_AddRef(IPersistIDList
*iface
)
482 ShellItem
*This
= impl_from_IPersistIDList(iface
);
483 return IShellItem2_AddRef(&This
->IShellItem2_iface
);
486 static ULONG WINAPI
ShellItem_IPersistIDList_Release(IPersistIDList
*iface
)
488 ShellItem
*This
= impl_from_IPersistIDList(iface
);
489 return IShellItem2_Release(&This
->IShellItem2_iface
);
492 static HRESULT WINAPI
ShellItem_IPersistIDList_GetClassID(IPersistIDList
* iface
,
495 *pClassID
= CLSID_ShellItem
;
499 static HRESULT WINAPI
ShellItem_IPersistIDList_SetIDList(IPersistIDList
* iface
,
502 ShellItem
*This
= impl_from_IPersistIDList(iface
);
503 LPITEMIDLIST new_pidl
;
505 TRACE("(%p,%p)\n", This
, pidl
);
507 new_pidl
= ILClone(pidl
);
512 This
->pidl
= new_pidl
;
516 return E_OUTOFMEMORY
;
519 static HRESULT WINAPI
ShellItem_IPersistIDList_GetIDList(IPersistIDList
* iface
,
522 ShellItem
*This
= impl_from_IPersistIDList(iface
);
524 TRACE("(%p,%p)\n", This
, ppidl
);
526 *ppidl
= ILClone(This
->pidl
);
530 return E_OUTOFMEMORY
;
533 static const IPersistIDListVtbl ShellItem_IPersistIDList_Vtbl
= {
534 ShellItem_IPersistIDList_QueryInterface
,
535 ShellItem_IPersistIDList_AddRef
,
536 ShellItem_IPersistIDList_Release
,
537 ShellItem_IPersistIDList_GetClassID
,
538 ShellItem_IPersistIDList_SetIDList
,
539 ShellItem_IPersistIDList_GetIDList
543 HRESULT WINAPI
IShellItem_Constructor(IUnknown
*pUnkOuter
, REFIID riid
, void **ppv
)
548 TRACE("(%p,%s)\n",pUnkOuter
, debugstr_guid(riid
));
552 if (pUnkOuter
) return CLASS_E_NOAGGREGATION
;
554 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(ShellItem
));
555 This
->IShellItem2_iface
.lpVtbl
= &ShellItem2_Vtbl
;
558 This
->IPersistIDList_iface
.lpVtbl
= &ShellItem_IPersistIDList_Vtbl
;
560 ret
= IShellItem2_QueryInterface(&This
->IShellItem2_iface
, riid
, ppv
);
561 IShellItem2_Release(&This
->IShellItem2_iface
);
566 HRESULT WINAPI
SHCreateShellItem(LPCITEMIDLIST pidlParent
,
567 IShellFolder
*psfParent
, LPCITEMIDLIST pidl
, IShellItem
**ppsi
)
569 LPITEMIDLIST new_pidl
;
572 TRACE("(%p,%p,%p,%p)\n", pidlParent
, psfParent
, pidl
, ppsi
);
580 else if (pidlParent
|| psfParent
)
582 LPITEMIDLIST temp_parent
=NULL
;
585 IPersistFolder2
* ppf2Parent
;
587 if (FAILED(IShellFolder_QueryInterface(psfParent
, &IID_IPersistFolder2
, (void**)&ppf2Parent
)))
589 FIXME("couldn't get IPersistFolder2 interface of parent\n");
590 return E_NOINTERFACE
;
593 if (FAILED(IPersistFolder2_GetCurFolder(ppf2Parent
, &temp_parent
)))
595 FIXME("couldn't get parent PIDL\n");
596 IPersistFolder2_Release(ppf2Parent
);
597 return E_NOINTERFACE
;
600 pidlParent
= temp_parent
;
601 IPersistFolder2_Release(ppf2Parent
);
604 new_pidl
= ILCombine(pidlParent
, pidl
);
608 return E_OUTOFMEMORY
;
612 new_pidl
= ILClone(pidl
);
614 return E_OUTOFMEMORY
;
617 ret
= SHCreateItemFromIDList(new_pidl
, &IID_IShellItem
, (void**)ppsi
);
623 HRESULT WINAPI
SHCreateItemFromParsingName(PCWSTR pszPath
,
624 IBindCtx
*pbc
, REFIID riid
, void **ppv
)
631 ret
= SHParseDisplayName(pszPath
, pbc
, &pidl
, 0, NULL
);
634 ret
= SHCreateItemFromIDList(pidl
, riid
, ppv
);
640 HRESULT WINAPI
SHCreateItemFromIDList(PCIDLIST_ABSOLUTE pidl
, REFIID riid
, void **ppv
)
642 IPersistIDList
*persist
;
649 ret
= IShellItem_Constructor(NULL
, &IID_IPersistIDList
, (void**)&persist
);
653 ret
= IPersistIDList_SetIDList(persist
, pidl
);
656 IPersistIDList_Release(persist
);
660 ret
= IPersistIDList_QueryInterface(persist
, riid
, ppv
);
661 IPersistIDList_Release(persist
);
665 HRESULT WINAPI
SHGetItemFromDataObject(IDataObject
*pdtobj
,
666 DATAOBJ_GET_ITEM_FLAGS dwFlags
, REFIID riid
, void **ppv
)
672 TRACE("%p, %x, %s, %p\n", pdtobj
, dwFlags
, debugstr_guid(riid
), ppv
);
677 fmt
.cfFormat
= RegisterClipboardFormatW(CFSTR_SHELLIDLISTW
);
679 fmt
.dwAspect
= DVASPECT_CONTENT
;
681 fmt
.tymed
= TYMED_HGLOBAL
;
683 ret
= IDataObject_GetData(pdtobj
, &fmt
, &medium
);
686 LPIDA pida
= GlobalLock(medium
.u
.hGlobal
);
688 if((pida
->cidl
> 1 && !(dwFlags
& DOGIF_ONLY_IF_ONE
)) ||
693 /* Get the first pidl (parent + child1) */
694 pidl
= ILCombine((LPCITEMIDLIST
) ((LPBYTE
)pida
+pida
->aoffset
[0]),
695 (LPCITEMIDLIST
) ((LPBYTE
)pida
+pida
->aoffset
[1]));
697 ret
= SHCreateItemFromIDList(pidl
, riid
, ppv
);
705 GlobalUnlock(medium
.u
.hGlobal
);
706 GlobalFree(medium
.u
.hGlobal
);
709 if(FAILED(ret
) && !(dwFlags
& DOGIF_NO_HDROP
))
711 TRACE("Attempting to fall back on CF_HDROP.\n");
713 fmt
.cfFormat
= CF_HDROP
;
715 fmt
.dwAspect
= DVASPECT_CONTENT
;
717 fmt
.tymed
= TYMED_HGLOBAL
;
719 ret
= IDataObject_GetData(pdtobj
, &fmt
, &medium
);
722 DROPFILES
*df
= GlobalLock(medium
.u
.hGlobal
);
723 LPBYTE files
= (LPBYTE
)df
+ df
->pFiles
;
724 BOOL multiple_files
= FALSE
;
729 WCHAR filename
[MAX_PATH
];
730 PCSTR first_file
= (PCSTR
)files
;
731 if(*(files
+ lstrlenA(first_file
) + 1) != 0)
732 multiple_files
= TRUE
;
734 if( !(multiple_files
&& (dwFlags
& DOGIF_ONLY_IF_ONE
)) )
736 MultiByteToWideChar(CP_ACP
, 0, first_file
, -1, filename
, MAX_PATH
);
737 ret
= SHCreateItemFromParsingName(filename
, NULL
, riid
, ppv
);
742 PCWSTR first_file
= (PCWSTR
)files
;
743 if(*((PCWSTR
)files
+ lstrlenW(first_file
) + 1) != 0)
744 multiple_files
= TRUE
;
746 if( !(multiple_files
&& (dwFlags
& DOGIF_ONLY_IF_ONE
)) )
747 ret
= SHCreateItemFromParsingName(first_file
, NULL
, riid
, ppv
);
750 GlobalUnlock(medium
.u
.hGlobal
);
751 GlobalFree(medium
.u
.hGlobal
);
755 if(FAILED(ret
) && !(dwFlags
& DOGIF_NO_URL
))
757 FIXME("Failed to create item, should try CF_URL.\n");
763 HRESULT WINAPI
SHGetItemFromObject(IUnknown
*punk
, REFIID riid
, void **ppv
)
768 ret
= SHGetIDListFromObject(punk
, &pidl
);
771 ret
= SHCreateItemFromIDList(pidl
, riid
, ppv
);
778 /*************************************************************************
779 * IEnumShellItems implementation
782 IEnumShellItems IEnumShellItems_iface
;
785 IShellItemArray
*array
;
788 } IEnumShellItemsImpl
;
790 static inline IEnumShellItemsImpl
*impl_from_IEnumShellItems(IEnumShellItems
*iface
)
792 return CONTAINING_RECORD(iface
, IEnumShellItemsImpl
, IEnumShellItems_iface
);
795 static HRESULT WINAPI
IEnumShellItems_fnQueryInterface(IEnumShellItems
*iface
,
799 IEnumShellItemsImpl
*This
= impl_from_IEnumShellItems(iface
);
800 TRACE("%p (%s, %p)\n", This
, shdebugstr_guid(riid
), ppvObject
);
803 if(IsEqualIID(riid
, &IID_IEnumShellItems
) ||
804 IsEqualIID(riid
, &IID_IUnknown
))
806 *ppvObject
= &This
->IEnumShellItems_iface
;
811 IUnknown_AddRef((IUnknown
*)*ppvObject
);
815 return E_NOINTERFACE
;
818 static ULONG WINAPI
IEnumShellItems_fnAddRef(IEnumShellItems
*iface
)
820 IEnumShellItemsImpl
*This
= impl_from_IEnumShellItems(iface
);
821 LONG ref
= InterlockedIncrement(&This
->ref
);
822 TRACE("%p - ref %d\n", This
, ref
);
827 static ULONG WINAPI
IEnumShellItems_fnRelease(IEnumShellItems
*iface
)
829 IEnumShellItemsImpl
*This
= impl_from_IEnumShellItems(iface
);
830 LONG ref
= InterlockedDecrement(&This
->ref
);
831 TRACE("%p - ref %d\n", This
, ref
);
836 IShellItemArray_Release(This
->array
);
837 HeapFree(GetProcessHeap(), 0, This
);
844 static HRESULT WINAPI
IEnumShellItems_fnNext(IEnumShellItems
* iface
,
849 IEnumShellItemsImpl
*This
= impl_from_IEnumShellItems(iface
);
850 HRESULT hr
= S_FALSE
;
853 TRACE("%p (%d %p %p)\n", This
, celt
, rgelt
, pceltFetched
);
855 if(pceltFetched
== NULL
&& celt
!= 1)
858 for(i
= This
->position
; fetched
< celt
&& i
< This
->count
; i
++) {
859 hr
= IShellItemArray_GetItemAt(This
->array
, i
, &rgelt
[fetched
]);
868 if(pceltFetched
!= NULL
)
869 *pceltFetched
= fetched
;
880 static HRESULT WINAPI
IEnumShellItems_fnSkip(IEnumShellItems
* iface
, ULONG celt
)
882 IEnumShellItemsImpl
*This
= impl_from_IEnumShellItems(iface
);
883 TRACE("%p (%d)\n", This
, celt
);
885 This
->position
= min(This
->position
+ celt
, This
->count
-1);
890 static HRESULT WINAPI
IEnumShellItems_fnReset(IEnumShellItems
* iface
)
892 IEnumShellItemsImpl
*This
= impl_from_IEnumShellItems(iface
);
900 static HRESULT WINAPI
IEnumShellItems_fnClone(IEnumShellItems
* iface
, IEnumShellItems
**ppenum
)
902 IEnumShellItemsImpl
*This
= impl_from_IEnumShellItems(iface
);
903 TRACE("%p (%p)\n", This
, ppenum
);
905 /* Not implemented anywhere */
911 static const IEnumShellItemsVtbl vt_IEnumShellItems
= {
912 IEnumShellItems_fnQueryInterface
,
913 IEnumShellItems_fnAddRef
,
914 IEnumShellItems_fnRelease
,
915 IEnumShellItems_fnNext
,
916 IEnumShellItems_fnSkip
,
917 IEnumShellItems_fnReset
,
918 IEnumShellItems_fnClone
921 static HRESULT
IEnumShellItems_Constructor(IShellItemArray
*array
, IEnumShellItems
**ppesi
)
923 IEnumShellItemsImpl
*This
;
926 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(IEnumShellItemsImpl
));
928 return E_OUTOFMEMORY
;
931 This
->IEnumShellItems_iface
.lpVtbl
= &vt_IEnumShellItems
;
935 IShellItemArray_AddRef(This
->array
);
936 IShellItemArray_GetCount(This
->array
, &This
->count
);
938 ret
= IEnumShellItems_QueryInterface(&This
->IEnumShellItems_iface
, &IID_IEnumShellItems
, (void**)ppesi
);
939 IEnumShellItems_Release(&This
->IEnumShellItems_iface
);
945 /*************************************************************************
946 * IShellItemArray implementation
949 IShellItemArray IShellItemArray_iface
;
954 } IShellItemArrayImpl
;
956 static inline IShellItemArrayImpl
*impl_from_IShellItemArray(IShellItemArray
*iface
)
958 return CONTAINING_RECORD(iface
, IShellItemArrayImpl
, IShellItemArray_iface
);
961 static HRESULT WINAPI
IShellItemArray_fnQueryInterface(IShellItemArray
*iface
,
965 IShellItemArrayImpl
*This
= impl_from_IShellItemArray(iface
);
966 TRACE("%p (%s, %p)\n", This
, shdebugstr_guid(riid
), ppvObject
);
969 if(IsEqualIID(riid
, &IID_IShellItemArray
) ||
970 IsEqualIID(riid
, &IID_IUnknown
))
972 *ppvObject
= &This
->IShellItemArray_iface
;
977 IUnknown_AddRef((IUnknown
*)*ppvObject
);
981 return E_NOINTERFACE
;
984 static ULONG WINAPI
IShellItemArray_fnAddRef(IShellItemArray
*iface
)
986 IShellItemArrayImpl
*This
= impl_from_IShellItemArray(iface
);
987 LONG ref
= InterlockedIncrement(&This
->ref
);
988 TRACE("%p - ref %d\n", This
, ref
);
993 static ULONG WINAPI
IShellItemArray_fnRelease(IShellItemArray
*iface
)
995 IShellItemArrayImpl
*This
= impl_from_IShellItemArray(iface
);
996 LONG ref
= InterlockedDecrement(&This
->ref
);
997 TRACE("%p - ref %d\n", This
, ref
);
1002 TRACE("Freeing.\n");
1004 for(i
= 0; i
< This
->item_count
; i
++)
1005 IShellItem_Release(This
->array
[i
]);
1007 HeapFree(GetProcessHeap(), 0, This
->array
);
1008 HeapFree(GetProcessHeap(), 0, This
);
1015 static HRESULT WINAPI
IShellItemArray_fnBindToHandler(IShellItemArray
*iface
,
1021 IShellItemArrayImpl
*This
= impl_from_IShellItemArray(iface
);
1022 FIXME("Stub: %p (%p, %s, %s, %p)\n",
1023 This
, pbc
, shdebugstr_guid(bhid
), shdebugstr_guid(riid
), ppvOut
);
1028 static HRESULT WINAPI
IShellItemArray_fnGetPropertyStore(IShellItemArray
*iface
,
1029 GETPROPERTYSTOREFLAGS flags
,
1033 IShellItemArrayImpl
*This
= impl_from_IShellItemArray(iface
);
1034 FIXME("Stub: %p (%x, %s, %p)\n", This
, flags
, shdebugstr_guid(riid
), ppv
);
1039 static HRESULT WINAPI
IShellItemArray_fnGetPropertyDescriptionList(IShellItemArray
*iface
,
1040 REFPROPERTYKEY keyType
,
1044 IShellItemArrayImpl
*This
= impl_from_IShellItemArray(iface
);
1045 FIXME("Stub: %p (%p, %s, %p)\n",
1046 This
, keyType
, shdebugstr_guid(riid
), ppv
);
1051 static HRESULT WINAPI
IShellItemArray_fnGetAttributes(IShellItemArray
*iface
,
1052 SIATTRIBFLAGS AttribFlags
,
1054 SFGAOF
*psfgaoAttribs
)
1056 IShellItemArrayImpl
*This
= impl_from_IShellItemArray(iface
);
1060 TRACE("%p (%x, %x, %p)\n", This
, AttribFlags
, sfgaoMask
, psfgaoAttribs
);
1062 if(AttribFlags
& ~(SIATTRIBFLAGS_AND
|SIATTRIBFLAGS_OR
))
1063 FIXME("%08x contains unsupported attribution flags\n", AttribFlags
);
1065 for(i
= 0; i
< This
->item_count
; i
++)
1067 hr
= IShellItem_GetAttributes(This
->array
[i
], sfgaoMask
, &attr
);
1073 *psfgaoAttribs
= attr
;
1077 switch(AttribFlags
& SIATTRIBFLAGS_MASK
)
1079 case SIATTRIBFLAGS_AND
:
1080 *psfgaoAttribs
&= attr
;
1082 case SIATTRIBFLAGS_OR
:
1083 *psfgaoAttribs
|= attr
;
1090 if(*psfgaoAttribs
== sfgaoMask
)
1099 static HRESULT WINAPI
IShellItemArray_fnGetCount(IShellItemArray
*iface
,
1102 IShellItemArrayImpl
*This
= impl_from_IShellItemArray(iface
);
1103 TRACE("%p (%p)\n", This
, pdwNumItems
);
1105 *pdwNumItems
= This
->item_count
;
1110 static HRESULT WINAPI
IShellItemArray_fnGetItemAt(IShellItemArray
*iface
,
1114 IShellItemArrayImpl
*This
= impl_from_IShellItemArray(iface
);
1115 TRACE("%p (%x, %p)\n", This
, dwIndex
, ppsi
);
1118 if(dwIndex
+ 1 > This
->item_count
)
1121 *ppsi
= This
->array
[dwIndex
];
1122 IShellItem_AddRef(*ppsi
);
1127 static HRESULT WINAPI
IShellItemArray_fnEnumItems(IShellItemArray
*iface
,
1128 IEnumShellItems
**ppenumShellItems
)
1130 IShellItemArrayImpl
*This
= impl_from_IShellItemArray(iface
);
1131 TRACE("%p (%p)\n", This
, ppenumShellItems
);
1132 return IEnumShellItems_Constructor(iface
, ppenumShellItems
);
1135 static const IShellItemArrayVtbl vt_IShellItemArray
= {
1136 IShellItemArray_fnQueryInterface
,
1137 IShellItemArray_fnAddRef
,
1138 IShellItemArray_fnRelease
,
1139 IShellItemArray_fnBindToHandler
,
1140 IShellItemArray_fnGetPropertyStore
,
1141 IShellItemArray_fnGetPropertyDescriptionList
,
1142 IShellItemArray_fnGetAttributes
,
1143 IShellItemArray_fnGetCount
,
1144 IShellItemArray_fnGetItemAt
,
1145 IShellItemArray_fnEnumItems
1148 /* Caller is responsible to AddRef all items */
1149 static HRESULT
create_shellitemarray(IShellItem
**items
, DWORD count
, IShellItemArray
**ret
)
1151 IShellItemArrayImpl
*This
;
1153 TRACE("(%p, %d, %p)\n", items
, count
, ret
);
1155 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(IShellItemArrayImpl
));
1157 return E_OUTOFMEMORY
;
1159 This
->IShellItemArray_iface
.lpVtbl
= &vt_IShellItemArray
;
1162 This
->array
= HeapAlloc(GetProcessHeap(), 0, count
*sizeof(IShellItem
*));
1165 HeapFree(GetProcessHeap(), 0, This
);
1166 return E_OUTOFMEMORY
;
1168 memcpy(This
->array
, items
, count
*sizeof(IShellItem
*));
1169 This
->item_count
= count
;
1171 *ret
= &This
->IShellItemArray_iface
;
1175 HRESULT WINAPI
SHCreateShellItemArray(PCIDLIST_ABSOLUTE pidlParent
,
1178 PCUITEMID_CHILD_ARRAY ppidl
,
1179 IShellItemArray
**ppsiItemArray
)
1182 HRESULT ret
= E_FAIL
;
1185 TRACE("%p, %p, %d, %p, %p\n", pidlParent
, psf
, cidl
, ppidl
, ppsiItemArray
);
1187 *ppsiItemArray
= NULL
;
1189 if(!pidlParent
&& !psf
)
1193 return E_INVALIDARG
;
1195 array
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, cidl
*sizeof(IShellItem
*));
1197 return E_OUTOFMEMORY
;
1199 for(i
= 0; i
< cidl
; i
++)
1201 ret
= SHCreateShellItem(pidlParent
, psf
, ppidl
[i
], &array
[i
]);
1202 if(FAILED(ret
)) break;
1207 ret
= create_shellitemarray(array
, cidl
, ppsiItemArray
);
1208 HeapFree(GetProcessHeap(), 0, array
);
1213 /* Something failed, clean up. */
1214 for(i
= 0; i
< cidl
; i
++)
1215 if(array
[i
]) IShellItem_Release(array
[i
]);
1216 HeapFree(GetProcessHeap(), 0, array
);
1220 HRESULT WINAPI
SHCreateShellItemArrayFromShellItem(IShellItem
*item
, REFIID riid
, void **ppv
)
1222 IShellItemArray
*array
;
1225 TRACE("%p, %s, %p\n", item
, shdebugstr_guid(riid
), ppv
);
1229 IShellItem_AddRef(item
);
1230 ret
= create_shellitemarray(&item
, 1, &array
);
1233 IShellItem_Release(item
);
1237 ret
= IShellItemArray_QueryInterface(array
, riid
, ppv
);
1238 IShellItemArray_Release(array
);
1242 HRESULT WINAPI
SHCreateShellItemArrayFromDataObject(IDataObject
*pdo
, REFIID riid
, void **ppv
)
1244 IShellItemArray
*psia
;
1249 TRACE("%p, %s, %p\n", pdo
, shdebugstr_guid(riid
), ppv
);
1252 return E_INVALIDARG
;
1256 fmt
.cfFormat
= RegisterClipboardFormatW(CFSTR_SHELLIDLISTW
);
1258 fmt
.dwAspect
= DVASPECT_CONTENT
;
1260 fmt
.tymed
= TYMED_HGLOBAL
;
1262 ret
= IDataObject_GetData(pdo
, &fmt
, &medium
);
1265 LPIDA pida
= GlobalLock(medium
.u
.hGlobal
);
1266 LPCITEMIDLIST parent_pidl
;
1267 LPCITEMIDLIST
*children
;
1269 TRACE("Converting %d objects.\n", pida
->cidl
);
1271 parent_pidl
= (LPCITEMIDLIST
) ((LPBYTE
)pida
+pida
->aoffset
[0]);
1273 children
= HeapAlloc(GetProcessHeap(), 0, sizeof(LPCITEMIDLIST
)*pida
->cidl
);
1274 for(i
= 0; i
< pida
->cidl
; i
++)
1275 children
[i
] = (LPCITEMIDLIST
) ((LPBYTE
)pida
+pida
->aoffset
[i
+1]);
1277 ret
= SHCreateShellItemArray(parent_pidl
, NULL
, pida
->cidl
, children
, &psia
);
1279 HeapFree(GetProcessHeap(), 0, children
);
1281 GlobalUnlock(medium
.u
.hGlobal
);
1282 GlobalFree(medium
.u
.hGlobal
);
1287 ret
= IShellItemArray_QueryInterface(psia
, riid
, ppv
);
1288 IShellItemArray_Release(psia
);
1294 HRESULT WINAPI
SHCreateShellItemArrayFromIDLists(UINT cidl
,
1295 PCIDLIST_ABSOLUTE_ARRAY pidl_array
,
1296 IShellItemArray
**psia
)
1301 TRACE("%d, %p, %p\n", cidl
, pidl_array
, psia
);
1306 return E_INVALIDARG
;
1308 array
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, cidl
*sizeof(IShellItem
*));
1310 return E_OUTOFMEMORY
;
1312 for(i
= 0; i
< cidl
; i
++)
1314 ret
= SHCreateShellItem(NULL
, NULL
, pidl_array
[i
], &array
[i
]);
1321 ret
= create_shellitemarray(array
, cidl
, psia
);
1322 HeapFree(GetProcessHeap(), 0, array
);
1327 for(i
= 0; i
< cidl
; i
++)
1328 if(array
[i
]) IShellItem_Release(array
[i
]);
1329 HeapFree(GetProcessHeap(), 0, array
);
1334 HRESULT WINAPI
SHGetPropertyStoreFromParsingName(const WCHAR
*path
, IBindCtx
*pbc
, GETPROPERTYSTOREFLAGS flags
,
1335 REFIID riid
, void **ppv
)
1340 TRACE("(%s %p %#x %p %p)\n", debugstr_w(path
), pbc
, flags
, riid
, ppv
);
1342 hr
= SHCreateItemFromParsingName(path
, pbc
, &IID_IShellItem2
, (void **)&item
);
1345 hr
= IShellItem2_GetPropertyStore(item
, flags
, riid
, ppv
);
1346 IShellItem2_Release(item
);
1352 static HRESULT WINAPI
CustomDestinationList_QueryInterface(ICustomDestinationList
*iface
, REFIID riid
, void **obj
)
1354 CustomDestinationList
*This
= impl_from_ICustomDestinationList(iface
);
1356 TRACE("(%p, %s, %p)\n", This
, debugstr_guid(riid
), obj
);
1358 if (IsEqualIID(&IID_ICustomDestinationList
, riid
) || IsEqualIID(&IID_IUnknown
, riid
))
1360 *obj
= &This
->ICustomDestinationList_iface
;
1363 FIXME("not implemented for %s\n", shdebugstr_guid(riid
));
1365 return E_NOINTERFACE
;
1368 IUnknown_AddRef((IUnknown
*)*obj
);
1372 static ULONG WINAPI
CustomDestinationList_AddRef(ICustomDestinationList
*iface
)
1374 CustomDestinationList
*This
= impl_from_ICustomDestinationList(iface
);
1375 ULONG ref
= InterlockedIncrement(&This
->ref
);
1377 TRACE("(%p), new refcount=%i\n", This
, ref
);
1382 static ULONG WINAPI
CustomDestinationList_Release(ICustomDestinationList
*iface
)
1384 CustomDestinationList
*This
= impl_from_ICustomDestinationList(iface
);
1385 ULONG ref
= InterlockedDecrement(&This
->ref
);
1387 TRACE("(%p), new refcount=%i\n", This
, ref
);
1390 HeapFree(GetProcessHeap(), 0, This
);
1395 static HRESULT WINAPI
CustomDestinationList_SetAppID(ICustomDestinationList
*iface
, const WCHAR
*appid
)
1397 CustomDestinationList
*This
= impl_from_ICustomDestinationList(iface
);
1399 FIXME("%p (%s): stub\n", This
, debugstr_w(appid
));
1404 static HRESULT WINAPI
CustomDestinationList_BeginList(ICustomDestinationList
*iface
, UINT
*min_slots
, REFIID riid
, void **obj
)
1406 CustomDestinationList
*This
= impl_from_ICustomDestinationList(iface
);
1408 FIXME("%p (%p %s %p): stub\n", This
, min_slots
, debugstr_guid(riid
), obj
);
1413 static HRESULT WINAPI
CustomDestinationList_AppendCategory(ICustomDestinationList
*iface
, const WCHAR
*category
, IObjectArray
*array
)
1415 CustomDestinationList
*This
= impl_from_ICustomDestinationList(iface
);
1417 FIXME("%p (%s %p): stub\n", This
, debugstr_w(category
), array
);
1422 static HRESULT WINAPI
CustomDestinationList_AppendKnownCategory(ICustomDestinationList
*iface
, KNOWNDESTCATEGORY category
)
1424 CustomDestinationList
*This
= impl_from_ICustomDestinationList(iface
);
1426 FIXME("%p (%d): stub\n", This
, category
);
1431 static HRESULT WINAPI
CustomDestinationList_AddUserTasks(ICustomDestinationList
*iface
, IObjectArray
*tasks
)
1433 CustomDestinationList
*This
= impl_from_ICustomDestinationList(iface
);
1435 FIXME("%p (%p): stub\n", This
, tasks
);
1440 static HRESULT WINAPI
CustomDestinationList_CommitList(ICustomDestinationList
*iface
)
1442 CustomDestinationList
*This
= impl_from_ICustomDestinationList(iface
);
1444 FIXME("%p: stub\n", This
);
1449 static HRESULT WINAPI
CustomDestinationList_GetRemovedDestinations(ICustomDestinationList
*iface
, REFIID riid
, void **obj
)
1451 CustomDestinationList
*This
= impl_from_ICustomDestinationList(iface
);
1453 FIXME("%p (%s %p): stub\n", This
, debugstr_guid(riid
), obj
);
1458 static HRESULT WINAPI
CustomDestinationList_DeleteList(ICustomDestinationList
*iface
, const WCHAR
*appid
)
1460 CustomDestinationList
*This
= impl_from_ICustomDestinationList(iface
);
1462 FIXME("%p (%s): stub\n", This
, debugstr_w(appid
));
1467 static HRESULT WINAPI
CustomDestinationList_AbortList(ICustomDestinationList
*iface
)
1469 CustomDestinationList
*This
= impl_from_ICustomDestinationList(iface
);
1471 FIXME("%p: stub\n", This
);
1476 static const ICustomDestinationListVtbl CustomDestinationListVtbl
=
1478 CustomDestinationList_QueryInterface
,
1479 CustomDestinationList_AddRef
,
1480 CustomDestinationList_Release
,
1481 CustomDestinationList_SetAppID
,
1482 CustomDestinationList_BeginList
,
1483 CustomDestinationList_AppendCategory
,
1484 CustomDestinationList_AppendKnownCategory
,
1485 CustomDestinationList_AddUserTasks
,
1486 CustomDestinationList_CommitList
,
1487 CustomDestinationList_GetRemovedDestinations
,
1488 CustomDestinationList_DeleteList
,
1489 CustomDestinationList_AbortList
1492 HRESULT WINAPI
CustomDestinationList_Constructor(IUnknown
*outer
, REFIID riid
, void **obj
)
1494 CustomDestinationList
*list
;
1497 TRACE("%p %s %p\n", outer
, debugstr_guid(riid
), obj
);
1500 return CLASS_E_NOAGGREGATION
;
1502 if(!(list
= HeapAlloc(GetProcessHeap(), 0, sizeof(*list
))))
1503 return E_OUTOFMEMORY
;
1505 list
->ICustomDestinationList_iface
.lpVtbl
= &CustomDestinationListVtbl
;
1508 hr
= ICustomDestinationList_QueryInterface(&list
->ICustomDestinationList_iface
, riid
, obj
);
1509 ICustomDestinationList_Release(&list
->ICustomDestinationList_iface
);