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
29 #define NONAMELESSSTRUCT
33 #include "wine/debug.h"
36 #include "shell32_main.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
41 typedef struct _ShellItem
{
42 IShellItem2 IShellItem2_iface
;
45 IPersistIDList IPersistIDList_iface
;
48 static inline ShellItem
*impl_from_IShellItem2(IShellItem2
*iface
)
50 return CONTAINING_RECORD(iface
, ShellItem
, IShellItem2_iface
);
54 static inline ShellItem
*impl_from_IPersistIDList( IPersistIDList
*iface
)
56 return CONTAINING_RECORD(iface
, ShellItem
, IPersistIDList_iface
);
60 static HRESULT WINAPI
ShellItem_QueryInterface(IShellItem2
*iface
, REFIID riid
,
63 ShellItem
*This
= impl_from_IShellItem2(iface
);
65 TRACE("(%p,%p,%p)\n", iface
, riid
, ppv
);
67 if (!ppv
) return E_INVALIDARG
;
69 if (IsEqualIID(&IID_IUnknown
, riid
) || IsEqualIID(&IID_IShellItem
, riid
) ||
70 IsEqualIID(&IID_IShellItem2
, riid
))
72 *ppv
= &This
->IShellItem2_iface
;
74 else if (IsEqualIID(&IID_IPersist
, riid
) || IsEqualIID(&IID_IPersistIDList
, riid
))
76 *ppv
= &This
->IPersistIDList_iface
;
79 FIXME("not implemented for %s\n", shdebugstr_guid(riid
));
84 IUnknown_AddRef((IUnknown
*)*ppv
);
88 static ULONG WINAPI
ShellItem_AddRef(IShellItem2
*iface
)
90 ShellItem
*This
= impl_from_IShellItem2(iface
);
91 ULONG ref
= InterlockedIncrement(&This
->ref
);
93 TRACE("(%p), new refcount=%i\n", iface
, ref
);
98 static ULONG WINAPI
ShellItem_Release(IShellItem2
*iface
)
100 ShellItem
*This
= impl_from_IShellItem2(iface
);
101 ULONG ref
= InterlockedDecrement(&This
->ref
);
103 TRACE("(%p), new refcount=%i\n", iface
, ref
);
108 HeapFree(GetProcessHeap(), 0, This
);
114 static HRESULT
ShellItem_get_parent_pidl(ShellItem
*This
, LPITEMIDLIST
*parent_pidl
)
116 *parent_pidl
= ILClone(This
->pidl
);
119 if (ILRemoveLastID(*parent_pidl
))
123 ILFree(*parent_pidl
);
131 return E_OUTOFMEMORY
;
135 static HRESULT
ShellItem_get_parent_shellfolder(ShellItem
*This
, IShellFolder
**ppsf
)
137 LPITEMIDLIST parent_pidl
;
138 IShellFolder
*desktop
;
141 ret
= ShellItem_get_parent_pidl(This
, &parent_pidl
);
144 ret
= SHGetDesktopFolder(&desktop
);
147 ret
= IShellFolder_BindToObject(desktop
, parent_pidl
, NULL
, &IID_IShellFolder
, (void**)ppsf
);
148 IShellFolder_Release(desktop
);
156 static HRESULT
ShellItem_get_shellfolder(ShellItem
*This
, IBindCtx
*pbc
, IShellFolder
**ppsf
)
158 IShellFolder
*desktop
;
161 ret
= SHGetDesktopFolder(&desktop
);
164 if (_ILIsDesktop(This
->pidl
))
167 IShellFolder_AddRef(*ppsf
);
171 ret
= IShellFolder_BindToObject(desktop
, This
->pidl
, pbc
, &IID_IShellFolder
, (void**)ppsf
);
174 IShellFolder_Release(desktop
);
180 static HRESULT WINAPI
ShellItem_BindToHandler(IShellItem2
*iface
, IBindCtx
*pbc
,
181 REFGUID rbhid
, REFIID riid
, void **ppvOut
)
183 ShellItem
*This
= impl_from_IShellItem2(iface
);
185 TRACE("(%p,%p,%s,%p,%p)\n", iface
, pbc
, shdebugstr_guid(rbhid
), riid
, ppvOut
);
188 if (IsEqualGUID(rbhid
, &BHID_SFObject
))
191 ret
= ShellItem_get_shellfolder(This
, pbc
, &psf
);
194 ret
= IShellFolder_QueryInterface(psf
, riid
, ppvOut
);
195 IShellFolder_Release(psf
);
199 else if (IsEqualGUID(rbhid
, &BHID_SFUIObject
))
201 IShellFolder
*psf_parent
;
202 if (_ILIsDesktop(This
->pidl
))
203 ret
= SHGetDesktopFolder(&psf_parent
);
205 ret
= ShellItem_get_parent_shellfolder(This
, &psf_parent
);
209 LPCITEMIDLIST pidl
= ILFindLastID(This
->pidl
);
210 ret
= IShellFolder_GetUIObjectOf(psf_parent
, NULL
, 1, &pidl
, riid
, NULL
, ppvOut
);
211 IShellFolder_Release(psf_parent
);
215 else if (IsEqualGUID(rbhid
, &BHID_DataObject
))
217 return ShellItem_BindToHandler(&This
->IShellItem2_iface
, pbc
, &BHID_SFUIObject
,
218 &IID_IDataObject
, ppvOut
);
221 FIXME("Unsupported BHID %s.\n", debugstr_guid(rbhid
));
223 return MK_E_NOOBJECT
;
226 static HRESULT WINAPI
ShellItem_GetParent(IShellItem2
*iface
, IShellItem
**ppsi
)
228 ShellItem
*This
= impl_from_IShellItem2(iface
);
229 LPITEMIDLIST parent_pidl
;
232 TRACE("(%p,%p)\n", iface
, ppsi
);
234 ret
= ShellItem_get_parent_pidl(This
, &parent_pidl
);
237 ret
= SHCreateShellItem(NULL
, NULL
, parent_pidl
, ppsi
);
244 static HRESULT WINAPI
ShellItem_GetDisplayName(IShellItem2
*iface
, SIGDN sigdnName
,
247 ShellItem
*This
= impl_from_IShellItem2(iface
);
248 TRACE("(%p,%x,%p)\n", iface
, sigdnName
, ppszName
);
250 return SHGetNameFromIDList(This
->pidl
, sigdnName
, ppszName
);
253 static HRESULT WINAPI
ShellItem_GetAttributes(IShellItem2
*iface
, SFGAOF sfgaoMask
,
254 SFGAOF
*psfgaoAttribs
)
256 ShellItem
*This
= impl_from_IShellItem2(iface
);
257 IShellFolder
*parent_folder
;
258 LPITEMIDLIST child_pidl
;
261 TRACE("(%p,%x,%p)\n", iface
, sfgaoMask
, psfgaoAttribs
);
263 if (_ILIsDesktop(This
->pidl
))
264 ret
= SHGetDesktopFolder(&parent_folder
);
266 ret
= ShellItem_get_parent_shellfolder(This
, &parent_folder
);
269 child_pidl
= ILFindLastID(This
->pidl
);
270 *psfgaoAttribs
= sfgaoMask
;
271 ret
= IShellFolder_GetAttributesOf(parent_folder
, 1, (LPCITEMIDLIST
*)&child_pidl
, psfgaoAttribs
);
272 *psfgaoAttribs
&= sfgaoMask
;
273 IShellFolder_Release(parent_folder
);
275 if(sfgaoMask
== *psfgaoAttribs
)
284 static HRESULT WINAPI
ShellItem_Compare(IShellItem2
*iface
, IShellItem
*oth
,
285 SICHINTF hint
, int *piOrder
)
287 LPWSTR dispname
, dispname_oth
;
289 TRACE("(%p,%p,%x,%p)\n", iface
, oth
, hint
, piOrder
);
291 if(hint
& (SICHINT_CANONICAL
| SICHINT_ALLFIELDS
))
292 FIXME("Unsupported flags 0x%08x\n", hint
);
294 ret
= IShellItem2_GetDisplayName(iface
, SIGDN_DESKTOPABSOLUTEEDITING
, &dispname
);
297 ret
= IShellItem_GetDisplayName(oth
, SIGDN_DESKTOPABSOLUTEEDITING
, &dispname_oth
);
300 *piOrder
= lstrcmpiW(dispname
, dispname_oth
);
301 CoTaskMemFree(dispname_oth
);
303 CoTaskMemFree(dispname
);
306 if(SUCCEEDED(ret
) && *piOrder
&&
307 (hint
& SICHINT_TEST_FILESYSPATH_IF_NOT_EQUAL
))
309 LPWSTR dispname
, dispname_oth
;
311 TRACE("Testing filesystem path.\n");
312 ret
= IShellItem2_GetDisplayName(iface
, SIGDN_FILESYSPATH
, &dispname
);
315 ret
= IShellItem_GetDisplayName(oth
, SIGDN_FILESYSPATH
, &dispname_oth
);
318 *piOrder
= lstrcmpiW(dispname
, dispname_oth
);
319 CoTaskMemFree(dispname_oth
);
321 CoTaskMemFree(dispname
);
334 static HRESULT WINAPI
ShellItem2_GetPropertyStore(IShellItem2
*iface
, GETPROPERTYSTOREFLAGS flags
,
335 REFIID riid
, void **ppv
)
337 ShellItem
*This
= impl_from_IShellItem2(iface
);
338 FIXME("Stub: %p (%d, %s, %p)\n", This
, flags
, shdebugstr_guid(riid
), ppv
);
342 static HRESULT WINAPI
ShellItem2_GetPropertyStoreWithCreateObject(IShellItem2
*iface
,
343 GETPROPERTYSTOREFLAGS flags
, IUnknown
*punkCreateObject
, REFIID riid
, void **ppv
)
345 ShellItem
*This
= impl_from_IShellItem2(iface
);
346 FIXME("Stub: %p (%08x, %p, %s, %p)\n",
347 This
, flags
, punkCreateObject
, shdebugstr_guid(riid
), ppv
);
351 static HRESULT WINAPI
ShellItem2_GetPropertyStoreForKeys(IShellItem2
*iface
, const PROPERTYKEY
*rgKeys
,
352 UINT cKeys
, GETPROPERTYSTOREFLAGS flags
, REFIID riid
, void **ppv
)
354 ShellItem
*This
= impl_from_IShellItem2(iface
);
355 FIXME("Stub: %p (%p, %d, %08x, %s, %p)\n",
356 This
, rgKeys
, cKeys
, flags
, shdebugstr_guid(riid
), ppv
);
360 static HRESULT WINAPI
ShellItem2_GetPropertyDescriptionList(IShellItem2
*iface
,
361 REFPROPERTYKEY keyType
, REFIID riid
, void **ppv
)
363 ShellItem
*This
= impl_from_IShellItem2(iface
);
364 FIXME("Stub: %p (%p, %s, %p)\n", This
, keyType
, debugstr_guid(riid
), ppv
);
368 static HRESULT WINAPI
ShellItem2_Update(IShellItem2
*iface
, IBindCtx
*pbc
)
370 ShellItem
*This
= impl_from_IShellItem2(iface
);
371 FIXME("Stub: %p (%p)\n", This
, pbc
);
375 static HRESULT WINAPI
ShellItem2_GetProperty(IShellItem2
*iface
, REFPROPERTYKEY key
, PROPVARIANT
*ppropvar
)
377 ShellItem
*This
= impl_from_IShellItem2(iface
);
378 FIXME("Stub: %p (%p, %p)\n", This
, key
, ppropvar
);
382 static HRESULT WINAPI
ShellItem2_GetCLSID(IShellItem2
*iface
, REFPROPERTYKEY key
, CLSID
*pclsid
)
384 ShellItem
*This
= impl_from_IShellItem2(iface
);
385 FIXME("Stub: %p (%p, %p)\n", This
, key
, pclsid
);
389 static HRESULT WINAPI
ShellItem2_GetFileTime(IShellItem2
*iface
, REFPROPERTYKEY key
, FILETIME
*pft
)
391 ShellItem
*This
= impl_from_IShellItem2(iface
);
392 FIXME("Stub: %p (%p, %p)\n", This
, key
, pft
);
396 static HRESULT WINAPI
ShellItem2_GetInt32(IShellItem2
*iface
, REFPROPERTYKEY key
, int *pi
)
398 ShellItem
*This
= impl_from_IShellItem2(iface
);
399 FIXME("Stub: %p (%p, %p)\n", This
, key
, pi
);
403 static HRESULT WINAPI
ShellItem2_GetString(IShellItem2
*iface
, REFPROPERTYKEY key
, LPWSTR
*ppsz
)
405 ShellItem
*This
= impl_from_IShellItem2(iface
);
406 FIXME("Stub: %p (%p, %p)\n", This
, key
, ppsz
);
410 static HRESULT WINAPI
ShellItem2_GetUInt32(IShellItem2
*iface
, REFPROPERTYKEY key
, ULONG
*pui
)
412 ShellItem
*This
= impl_from_IShellItem2(iface
);
413 FIXME("Stub: %p (%p, %p)\n", This
, key
, pui
);
417 static HRESULT WINAPI
ShellItem2_GetUInt64(IShellItem2
*iface
, REFPROPERTYKEY key
, ULONGLONG
*pull
)
419 ShellItem
*This
= impl_from_IShellItem2(iface
);
420 FIXME("Stub: %p (%p, %p)\n", This
, key
, pull
);
424 static HRESULT WINAPI
ShellItem2_GetBool(IShellItem2
*iface
, REFPROPERTYKEY key
, BOOL
*pf
)
426 ShellItem
*This
= impl_from_IShellItem2(iface
);
427 FIXME("Stub: %p (%p, %p)\n", This
, key
, pf
);
432 static const IShellItem2Vtbl ShellItem2_Vtbl
= {
433 ShellItem_QueryInterface
,
436 ShellItem_BindToHandler
,
438 ShellItem_GetDisplayName
,
439 ShellItem_GetAttributes
,
441 ShellItem2_GetPropertyStore
,
442 ShellItem2_GetPropertyStoreWithCreateObject
,
443 ShellItem2_GetPropertyStoreForKeys
,
444 ShellItem2_GetPropertyDescriptionList
,
446 ShellItem2_GetProperty
,
448 ShellItem2_GetFileTime
,
450 ShellItem2_GetString
,
451 ShellItem2_GetUInt32
,
452 ShellItem2_GetUInt64
,
456 static HRESULT WINAPI
ShellItem_IPersistIDList_QueryInterface(IPersistIDList
*iface
,
457 REFIID riid
, void **ppv
)
459 ShellItem
*This
= impl_from_IPersistIDList(iface
);
460 return IShellItem2_QueryInterface(&This
->IShellItem2_iface
, riid
, ppv
);
463 static ULONG WINAPI
ShellItem_IPersistIDList_AddRef(IPersistIDList
*iface
)
465 ShellItem
*This
= impl_from_IPersistIDList(iface
);
466 return IShellItem2_AddRef(&This
->IShellItem2_iface
);
469 static ULONG WINAPI
ShellItem_IPersistIDList_Release(IPersistIDList
*iface
)
471 ShellItem
*This
= impl_from_IPersistIDList(iface
);
472 return IShellItem2_Release(&This
->IShellItem2_iface
);
475 static HRESULT WINAPI
ShellItem_IPersistIDList_GetClassID(IPersistIDList
* iface
,
478 *pClassID
= CLSID_ShellItem
;
482 static HRESULT WINAPI
ShellItem_IPersistIDList_SetIDList(IPersistIDList
* iface
,
485 ShellItem
*This
= impl_from_IPersistIDList(iface
);
486 LPITEMIDLIST new_pidl
;
488 TRACE("(%p,%p)\n", This
, pidl
);
490 new_pidl
= ILClone(pidl
);
495 This
->pidl
= new_pidl
;
499 return E_OUTOFMEMORY
;
502 static HRESULT WINAPI
ShellItem_IPersistIDList_GetIDList(IPersistIDList
* iface
,
505 ShellItem
*This
= impl_from_IPersistIDList(iface
);
507 TRACE("(%p,%p)\n", This
, ppidl
);
509 *ppidl
= ILClone(This
->pidl
);
513 return E_OUTOFMEMORY
;
516 static const IPersistIDListVtbl ShellItem_IPersistIDList_Vtbl
= {
517 ShellItem_IPersistIDList_QueryInterface
,
518 ShellItem_IPersistIDList_AddRef
,
519 ShellItem_IPersistIDList_Release
,
520 ShellItem_IPersistIDList_GetClassID
,
521 ShellItem_IPersistIDList_SetIDList
,
522 ShellItem_IPersistIDList_GetIDList
526 HRESULT WINAPI
IShellItem_Constructor(IUnknown
*pUnkOuter
, REFIID riid
, void **ppv
)
531 TRACE("(%p,%s)\n",pUnkOuter
, debugstr_guid(riid
));
535 if (pUnkOuter
) return CLASS_E_NOAGGREGATION
;
537 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(ShellItem
));
538 This
->IShellItem2_iface
.lpVtbl
= &ShellItem2_Vtbl
;
541 This
->IPersistIDList_iface
.lpVtbl
= &ShellItem_IPersistIDList_Vtbl
;
543 ret
= IShellItem2_QueryInterface(&This
->IShellItem2_iface
, riid
, ppv
);
544 IShellItem2_Release(&This
->IShellItem2_iface
);
549 HRESULT WINAPI
SHCreateShellItem(LPCITEMIDLIST pidlParent
,
550 IShellFolder
*psfParent
, LPCITEMIDLIST pidl
, IShellItem
**ppsi
)
553 LPITEMIDLIST new_pidl
;
556 TRACE("(%p,%p,%p,%p)\n", pidlParent
, psfParent
, pidl
, ppsi
);
564 else if (pidlParent
|| psfParent
)
566 LPITEMIDLIST temp_parent
=NULL
;
569 IPersistFolder2
* ppf2Parent
;
571 if (FAILED(IShellFolder_QueryInterface(psfParent
, &IID_IPersistFolder2
, (void**)&ppf2Parent
)))
573 FIXME("couldn't get IPersistFolder2 interface of parent\n");
574 return E_NOINTERFACE
;
577 if (FAILED(IPersistFolder2_GetCurFolder(ppf2Parent
, &temp_parent
)))
579 FIXME("couldn't get parent PIDL\n");
580 IPersistFolder2_Release(ppf2Parent
);
581 return E_NOINTERFACE
;
584 pidlParent
= temp_parent
;
585 IPersistFolder2_Release(ppf2Parent
);
588 new_pidl
= ILCombine(pidlParent
, pidl
);
592 return E_OUTOFMEMORY
;
596 new_pidl
= ILClone(pidl
);
598 return E_OUTOFMEMORY
;
601 ret
= IShellItem_Constructor(NULL
, &IID_IShellItem
, (void**)&This
);
604 *ppsi
= (IShellItem
*)&This
->IShellItem2_iface
;
605 This
->pidl
= new_pidl
;
614 HRESULT WINAPI
SHCreateItemFromParsingName(PCWSTR pszPath
,
615 IBindCtx
*pbc
, REFIID riid
, void **ppv
)
622 ret
= SHParseDisplayName(pszPath
, pbc
, &pidl
, 0, NULL
);
626 ret
= IShellItem_Constructor(NULL
, riid
, (void**)&This
);
641 HRESULT WINAPI
SHCreateItemFromIDList(PCIDLIST_ABSOLUTE pidl
, REFIID riid
, void **ppv
)
649 ret
= IShellItem_Constructor(NULL
, riid
, ppv
);
652 psiimpl
= (ShellItem
*)*ppv
;
653 psiimpl
->pidl
= ILClone(pidl
);
659 HRESULT WINAPI
SHGetItemFromDataObject(IDataObject
*pdtobj
,
660 DATAOBJ_GET_ITEM_FLAGS dwFlags
, REFIID riid
, void **ppv
)
666 TRACE("%p, %x, %s, %p\n", pdtobj
, dwFlags
, debugstr_guid(riid
), ppv
);
671 fmt
.cfFormat
= RegisterClipboardFormatW(CFSTR_SHELLIDLISTW
);
673 fmt
.dwAspect
= DVASPECT_CONTENT
;
675 fmt
.tymed
= TYMED_HGLOBAL
;
677 ret
= IDataObject_GetData(pdtobj
, &fmt
, &medium
);
680 LPIDA pida
= GlobalLock(medium
.u
.hGlobal
);
682 if((pida
->cidl
> 1 && !(dwFlags
& DOGIF_ONLY_IF_ONE
)) ||
687 /* Get the first pidl (parent + child1) */
688 pidl
= ILCombine((LPCITEMIDLIST
) ((LPBYTE
)pida
+pida
->aoffset
[0]),
689 (LPCITEMIDLIST
) ((LPBYTE
)pida
+pida
->aoffset
[1]));
691 ret
= SHCreateItemFromIDList(pidl
, riid
, ppv
);
699 GlobalUnlock(medium
.u
.hGlobal
);
700 GlobalFree(medium
.u
.hGlobal
);
703 if(FAILED(ret
) && !(dwFlags
& DOGIF_NO_HDROP
))
705 TRACE("Attempting to fall back on CF_HDROP.\n");
707 fmt
.cfFormat
= CF_HDROP
;
709 fmt
.dwAspect
= DVASPECT_CONTENT
;
711 fmt
.tymed
= TYMED_HGLOBAL
;
713 ret
= IDataObject_GetData(pdtobj
, &fmt
, &medium
);
716 DROPFILES
*df
= GlobalLock(medium
.u
.hGlobal
);
717 LPBYTE files
= (LPBYTE
)df
+ df
->pFiles
;
718 BOOL multiple_files
= FALSE
;
723 WCHAR filename
[MAX_PATH
];
724 PCSTR first_file
= (PCSTR
)files
;
725 if(*(files
+ lstrlenA(first_file
) + 1) != 0)
726 multiple_files
= TRUE
;
728 if( !(multiple_files
&& (dwFlags
& DOGIF_ONLY_IF_ONE
)) )
730 MultiByteToWideChar(CP_ACP
, 0, first_file
, -1, filename
, MAX_PATH
);
731 ret
= SHCreateItemFromParsingName(filename
, NULL
, riid
, ppv
);
736 PCWSTR first_file
= (PCWSTR
)files
;
737 if(*((PCWSTR
)files
+ lstrlenW(first_file
) + 1) != 0)
738 multiple_files
= TRUE
;
740 if( !(multiple_files
&& (dwFlags
& DOGIF_ONLY_IF_ONE
)) )
741 ret
= SHCreateItemFromParsingName(first_file
, NULL
, riid
, ppv
);
744 GlobalUnlock(medium
.u
.hGlobal
);
745 GlobalFree(medium
.u
.hGlobal
);
749 if(FAILED(ret
) && !(dwFlags
& DOGIF_NO_URL
))
751 FIXME("Failed to create item, should try CF_URL.\n");
757 HRESULT WINAPI
SHGetItemFromObject(IUnknown
*punk
, REFIID riid
, void **ppv
)
762 ret
= SHGetIDListFromObject(punk
, &pidl
);
765 ret
= SHCreateItemFromIDList(pidl
, riid
, ppv
);
772 /*************************************************************************
773 * IEnumShellItems implementation
776 IEnumShellItems IEnumShellItems_iface
;
779 IShellItemArray
*array
;
782 } IEnumShellItemsImpl
;
784 static inline IEnumShellItemsImpl
*impl_from_IEnumShellItems(IEnumShellItems
*iface
)
786 return CONTAINING_RECORD(iface
, IEnumShellItemsImpl
, IEnumShellItems_iface
);
789 static HRESULT WINAPI
IEnumShellItems_fnQueryInterface(IEnumShellItems
*iface
,
793 IEnumShellItemsImpl
*This
= impl_from_IEnumShellItems(iface
);
794 TRACE("%p (%s, %p)\n", This
, shdebugstr_guid(riid
), ppvObject
);
797 if(IsEqualIID(riid
, &IID_IEnumShellItems
) ||
798 IsEqualIID(riid
, &IID_IUnknown
))
800 *ppvObject
= &This
->IEnumShellItems_iface
;
805 IUnknown_AddRef((IUnknown
*)*ppvObject
);
809 return E_NOINTERFACE
;
812 static ULONG WINAPI
IEnumShellItems_fnAddRef(IEnumShellItems
*iface
)
814 IEnumShellItemsImpl
*This
= impl_from_IEnumShellItems(iface
);
815 LONG ref
= InterlockedIncrement(&This
->ref
);
816 TRACE("%p - ref %d\n", This
, ref
);
821 static ULONG WINAPI
IEnumShellItems_fnRelease(IEnumShellItems
*iface
)
823 IEnumShellItemsImpl
*This
= impl_from_IEnumShellItems(iface
);
824 LONG ref
= InterlockedDecrement(&This
->ref
);
825 TRACE("%p - ref %d\n", This
, ref
);
830 IShellItemArray_Release(This
->array
);
831 HeapFree(GetProcessHeap(), 0, This
);
838 static HRESULT WINAPI
IEnumShellItems_fnNext(IEnumShellItems
* iface
,
843 IEnumShellItemsImpl
*This
= impl_from_IEnumShellItems(iface
);
844 HRESULT hr
= S_FALSE
;
847 TRACE("%p (%d %p %p)\n", This
, celt
, rgelt
, pceltFetched
);
849 if(pceltFetched
== NULL
&& celt
!= 1)
852 for(i
= This
->position
; fetched
< celt
&& i
< This
->count
; i
++) {
853 hr
= IShellItemArray_GetItemAt(This
->array
, i
, &rgelt
[fetched
]);
862 if(pceltFetched
!= NULL
)
863 *pceltFetched
= fetched
;
874 static HRESULT WINAPI
IEnumShellItems_fnSkip(IEnumShellItems
* iface
, ULONG celt
)
876 IEnumShellItemsImpl
*This
= impl_from_IEnumShellItems(iface
);
877 TRACE("%p (%d)\n", This
, celt
);
879 This
->position
= min(This
->position
+ celt
, This
->count
-1);
884 static HRESULT WINAPI
IEnumShellItems_fnReset(IEnumShellItems
* iface
)
886 IEnumShellItemsImpl
*This
= impl_from_IEnumShellItems(iface
);
894 static HRESULT WINAPI
IEnumShellItems_fnClone(IEnumShellItems
* iface
, IEnumShellItems
**ppenum
)
896 IEnumShellItemsImpl
*This
= impl_from_IEnumShellItems(iface
);
897 TRACE("%p (%p)\n", This
, ppenum
);
899 /* Not implemented anywhere */
905 static const IEnumShellItemsVtbl vt_IEnumShellItems
= {
906 IEnumShellItems_fnQueryInterface
,
907 IEnumShellItems_fnAddRef
,
908 IEnumShellItems_fnRelease
,
909 IEnumShellItems_fnNext
,
910 IEnumShellItems_fnSkip
,
911 IEnumShellItems_fnReset
,
912 IEnumShellItems_fnClone
915 static HRESULT
IEnumShellItems_Constructor(IShellItemArray
*array
, IEnumShellItems
**ppesi
)
917 IEnumShellItemsImpl
*This
;
920 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(IEnumShellItemsImpl
));
922 return E_OUTOFMEMORY
;
925 This
->IEnumShellItems_iface
.lpVtbl
= &vt_IEnumShellItems
;
929 IShellItemArray_AddRef(This
->array
);
930 IShellItemArray_GetCount(This
->array
, &This
->count
);
932 ret
= IEnumShellItems_QueryInterface(&This
->IEnumShellItems_iface
, &IID_IEnumShellItems
, (void**)ppesi
);
933 IEnumShellItems_Release(&This
->IEnumShellItems_iface
);
939 /*************************************************************************
940 * IShellItemArray implementation
943 IShellItemArray IShellItemArray_iface
;
948 } IShellItemArrayImpl
;
950 static inline IShellItemArrayImpl
*impl_from_IShellItemArray(IShellItemArray
*iface
)
952 return CONTAINING_RECORD(iface
, IShellItemArrayImpl
, IShellItemArray_iface
);
955 static HRESULT WINAPI
IShellItemArray_fnQueryInterface(IShellItemArray
*iface
,
959 IShellItemArrayImpl
*This
= impl_from_IShellItemArray(iface
);
960 TRACE("%p (%s, %p)\n", This
, shdebugstr_guid(riid
), ppvObject
);
963 if(IsEqualIID(riid
, &IID_IShellItemArray
) ||
964 IsEqualIID(riid
, &IID_IUnknown
))
966 *ppvObject
= &This
->IShellItemArray_iface
;
971 IUnknown_AddRef((IUnknown
*)*ppvObject
);
975 return E_NOINTERFACE
;
978 static ULONG WINAPI
IShellItemArray_fnAddRef(IShellItemArray
*iface
)
980 IShellItemArrayImpl
*This
= impl_from_IShellItemArray(iface
);
981 LONG ref
= InterlockedIncrement(&This
->ref
);
982 TRACE("%p - ref %d\n", This
, ref
);
987 static ULONG WINAPI
IShellItemArray_fnRelease(IShellItemArray
*iface
)
989 IShellItemArrayImpl
*This
= impl_from_IShellItemArray(iface
);
990 LONG ref
= InterlockedDecrement(&This
->ref
);
991 TRACE("%p - ref %d\n", This
, ref
);
998 for(i
= 0; i
< This
->item_count
; i
++)
999 IShellItem_Release(This
->array
[i
]);
1001 HeapFree(GetProcessHeap(), 0, This
->array
);
1002 HeapFree(GetProcessHeap(), 0, This
);
1009 static HRESULT WINAPI
IShellItemArray_fnBindToHandler(IShellItemArray
*iface
,
1015 IShellItemArrayImpl
*This
= impl_from_IShellItemArray(iface
);
1016 FIXME("Stub: %p (%p, %s, %s, %p)\n",
1017 This
, pbc
, shdebugstr_guid(bhid
), shdebugstr_guid(riid
), ppvOut
);
1022 static HRESULT WINAPI
IShellItemArray_fnGetPropertyStore(IShellItemArray
*iface
,
1023 GETPROPERTYSTOREFLAGS flags
,
1027 IShellItemArrayImpl
*This
= impl_from_IShellItemArray(iface
);
1028 FIXME("Stub: %p (%x, %s, %p)\n", This
, flags
, shdebugstr_guid(riid
), ppv
);
1033 static HRESULT WINAPI
IShellItemArray_fnGetPropertyDescriptionList(IShellItemArray
*iface
,
1034 REFPROPERTYKEY keyType
,
1038 IShellItemArrayImpl
*This
= impl_from_IShellItemArray(iface
);
1039 FIXME("Stub: %p (%p, %s, %p)\n",
1040 This
, keyType
, shdebugstr_guid(riid
), ppv
);
1045 static HRESULT WINAPI
IShellItemArray_fnGetAttributes(IShellItemArray
*iface
,
1046 SIATTRIBFLAGS AttribFlags
,
1048 SFGAOF
*psfgaoAttribs
)
1050 IShellItemArrayImpl
*This
= impl_from_IShellItemArray(iface
);
1054 TRACE("%p (%x, %x, %p)\n", This
, AttribFlags
, sfgaoMask
, psfgaoAttribs
);
1056 if(AttribFlags
& ~(SIATTRIBFLAGS_AND
|SIATTRIBFLAGS_OR
))
1057 FIXME("%08x contains unsupported attribution flags\n", AttribFlags
);
1059 for(i
= 0; i
< This
->item_count
; i
++)
1061 hr
= IShellItem_GetAttributes(This
->array
[i
], sfgaoMask
, &attr
);
1067 *psfgaoAttribs
= attr
;
1071 switch(AttribFlags
& SIATTRIBFLAGS_MASK
)
1073 case SIATTRIBFLAGS_AND
:
1074 *psfgaoAttribs
&= attr
;
1076 case SIATTRIBFLAGS_OR
:
1077 *psfgaoAttribs
|= attr
;
1084 if(*psfgaoAttribs
== sfgaoMask
)
1093 static HRESULT WINAPI
IShellItemArray_fnGetCount(IShellItemArray
*iface
,
1096 IShellItemArrayImpl
*This
= impl_from_IShellItemArray(iface
);
1097 TRACE("%p (%p)\n", This
, pdwNumItems
);
1099 *pdwNumItems
= This
->item_count
;
1104 static HRESULT WINAPI
IShellItemArray_fnGetItemAt(IShellItemArray
*iface
,
1108 IShellItemArrayImpl
*This
= impl_from_IShellItemArray(iface
);
1109 TRACE("%p (%x, %p)\n", This
, dwIndex
, ppsi
);
1112 if(dwIndex
+ 1 > This
->item_count
)
1115 *ppsi
= This
->array
[dwIndex
];
1116 IShellItem_AddRef(*ppsi
);
1121 static HRESULT WINAPI
IShellItemArray_fnEnumItems(IShellItemArray
*iface
,
1122 IEnumShellItems
**ppenumShellItems
)
1124 IShellItemArrayImpl
*This
= impl_from_IShellItemArray(iface
);
1126 TRACE("%p (%p)\n", This
, ppenumShellItems
);
1128 hr
= IEnumShellItems_Constructor(iface
, ppenumShellItems
);
1133 static const IShellItemArrayVtbl vt_IShellItemArray
= {
1134 IShellItemArray_fnQueryInterface
,
1135 IShellItemArray_fnAddRef
,
1136 IShellItemArray_fnRelease
,
1137 IShellItemArray_fnBindToHandler
,
1138 IShellItemArray_fnGetPropertyStore
,
1139 IShellItemArray_fnGetPropertyDescriptionList
,
1140 IShellItemArray_fnGetAttributes
,
1141 IShellItemArray_fnGetCount
,
1142 IShellItemArray_fnGetItemAt
,
1143 IShellItemArray_fnEnumItems
1146 static HRESULT
IShellItemArray_Constructor(IUnknown
*pUnkOuter
, REFIID riid
, void **ppv
)
1148 IShellItemArrayImpl
*This
;
1151 TRACE("(%p, %s, %p)\n",pUnkOuter
, debugstr_guid(riid
), ppv
);
1154 return CLASS_E_NOAGGREGATION
;
1156 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(IShellItemArrayImpl
));
1158 return E_OUTOFMEMORY
;
1161 This
->IShellItemArray_iface
.lpVtbl
= &vt_IShellItemArray
;
1163 This
->item_count
= 0;
1165 ret
= IShellItemArray_QueryInterface(&This
->IShellItemArray_iface
, riid
, ppv
);
1166 IShellItemArray_Release(&This
->IShellItemArray_iface
);
1171 HRESULT WINAPI
SHCreateShellItemArray(PCIDLIST_ABSOLUTE pidlParent
,
1174 PCUITEMID_CHILD_ARRAY ppidl
,
1175 IShellItemArray
**ppsiItemArray
)
1177 IShellItemArrayImpl
*This
;
1179 HRESULT ret
= E_FAIL
;
1182 TRACE("%p, %p, %d, %p, %p\n", pidlParent
, psf
, cidl
, ppidl
, ppsiItemArray
);
1184 if(!pidlParent
&& !psf
)
1188 return E_INVALIDARG
;
1190 array
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, cidl
*sizeof(IShellItem
*));
1192 return E_OUTOFMEMORY
;
1194 for(i
= 0; i
< cidl
; i
++)
1196 ret
= SHCreateShellItem(pidlParent
, psf
, ppidl
[i
], &array
[i
]);
1197 if(FAILED(ret
)) break;
1202 ret
= IShellItemArray_Constructor(NULL
, &IID_IShellItemArray
, (void**)&This
);
1205 This
->array
= array
;
1206 This
->item_count
= cidl
;
1207 *ppsiItemArray
= &This
->IShellItemArray_iface
;
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
);
1217 *ppsiItemArray
= NULL
;
1221 HRESULT WINAPI
SHCreateShellItemArrayFromShellItem(IShellItem
*psi
, REFIID riid
, void **ppv
)
1223 IShellItemArrayImpl
*This
;
1227 TRACE("%p, %s, %p\n", psi
, shdebugstr_guid(riid
), ppv
);
1229 array
= HeapAlloc(GetProcessHeap(), 0, sizeof(IShellItem
*));
1231 return E_OUTOFMEMORY
;
1233 ret
= IShellItemArray_Constructor(NULL
, riid
, (void**)&This
);
1237 IShellItem_AddRef(psi
);
1238 This
->array
= array
;
1239 This
->item_count
= 1;
1244 HeapFree(GetProcessHeap(), 0, array
);
1251 HRESULT WINAPI
SHCreateShellItemArrayFromDataObject(IDataObject
*pdo
, REFIID riid
, void **ppv
)
1253 IShellItemArray
*psia
;
1258 TRACE("%p, %s, %p\n", pdo
, shdebugstr_guid(riid
), ppv
);
1261 return E_INVALIDARG
;
1265 fmt
.cfFormat
= RegisterClipboardFormatW(CFSTR_SHELLIDLISTW
);
1267 fmt
.dwAspect
= DVASPECT_CONTENT
;
1269 fmt
.tymed
= TYMED_HGLOBAL
;
1271 ret
= IDataObject_GetData(pdo
, &fmt
, &medium
);
1274 LPIDA pida
= GlobalLock(medium
.u
.hGlobal
);
1275 LPCITEMIDLIST parent_pidl
;
1276 LPCITEMIDLIST
*children
;
1278 TRACE("Converting %d objects.\n", pida
->cidl
);
1280 parent_pidl
= (LPCITEMIDLIST
) ((LPBYTE
)pida
+pida
->aoffset
[0]);
1282 children
= HeapAlloc(GetProcessHeap(), 0, sizeof(LPCITEMIDLIST
)*pida
->cidl
);
1283 for(i
= 0; i
< pida
->cidl
; i
++)
1284 children
[i
] = (LPCITEMIDLIST
) ((LPBYTE
)pida
+pida
->aoffset
[i
+1]);
1286 ret
= SHCreateShellItemArray(parent_pidl
, NULL
, pida
->cidl
, children
, &psia
);
1288 HeapFree(GetProcessHeap(), 0, children
);
1290 GlobalUnlock(medium
.u
.hGlobal
);
1291 GlobalFree(medium
.u
.hGlobal
);
1296 ret
= IShellItemArray_QueryInterface(psia
, riid
, ppv
);
1297 IShellItemArray_Release(psia
);
1303 HRESULT WINAPI
SHCreateShellItemArrayFromIDLists(UINT cidl
,
1304 PCIDLIST_ABSOLUTE_ARRAY pidl_array
,
1305 IShellItemArray
**psia
)
1307 IShellItemArrayImpl
*This
;
1311 TRACE("%d, %p, %p\n", cidl
, pidl_array
, psia
);
1316 return E_INVALIDARG
;
1318 array
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IShellItem
*));
1320 return E_OUTOFMEMORY
;
1322 for(i
= 0; i
< cidl
; i
++)
1324 ret
= SHCreateShellItem(NULL
, NULL
, pidl_array
[i
], &array
[i
]);
1331 ret
= IShellItemArray_Constructor(NULL
, &IID_IShellItemArray
, (void**)psia
);
1334 This
= impl_from_IShellItemArray(*psia
);
1335 This
->array
= array
;
1336 This
->item_count
= cidl
;
1341 for(i
= 0; i
< cidl
; i
++)
1342 if(array
[i
]) IShellItem_Release(array
[i
]);
1343 HeapFree(GetProcessHeap(), 0, array
);