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 const IShellItemVtbl
*lpIShellItemVtbl
;
45 const IPersistIDListVtbl
*lpIPersistIDListVtbl
;
49 static inline ShellItem
*impl_from_IPersistIDList( IPersistIDList
*iface
)
51 return (ShellItem
*)((char*)iface
- FIELD_OFFSET(ShellItem
, lpIPersistIDListVtbl
));
55 static HRESULT WINAPI
ShellItem_QueryInterface(IShellItem
*iface
, REFIID riid
,
58 ShellItem
*This
= (ShellItem
*)iface
;
60 TRACE("(%p,%p,%p)\n", iface
, riid
, ppv
);
62 if (!ppv
) return E_INVALIDARG
;
64 if (IsEqualIID(&IID_IUnknown
, riid
) || IsEqualIID(&IID_IShellItem
, riid
))
68 else if (IsEqualIID(&IID_IPersist
, riid
) || IsEqualIID(&IID_IPersistIDList
, riid
))
70 *ppv
= &(This
->lpIPersistIDListVtbl
);
73 FIXME("not implemented for %s\n", shdebugstr_guid(riid
));
78 IUnknown_AddRef((IUnknown
*)*ppv
);
82 static ULONG WINAPI
ShellItem_AddRef(IShellItem
*iface
)
84 ShellItem
*This
= (ShellItem
*)iface
;
85 ULONG ref
= InterlockedIncrement(&This
->ref
);
87 TRACE("(%p), new refcount=%i\n", iface
, ref
);
92 static ULONG WINAPI
ShellItem_Release(IShellItem
*iface
)
94 ShellItem
*This
= (ShellItem
*)iface
;
95 ULONG ref
= InterlockedDecrement(&This
->ref
);
97 TRACE("(%p), new refcount=%i\n", iface
, ref
);
102 HeapFree(GetProcessHeap(), 0, This
);
108 static HRESULT
ShellItem_get_parent_pidl(ShellItem
*This
, LPITEMIDLIST
*parent_pidl
)
110 *parent_pidl
= ILClone(This
->pidl
);
113 if (ILRemoveLastID(*parent_pidl
))
117 ILFree(*parent_pidl
);
125 return E_OUTOFMEMORY
;
129 static HRESULT
ShellItem_get_parent_shellfolder(ShellItem
*This
, IShellFolder
**ppsf
)
131 LPITEMIDLIST parent_pidl
;
132 IShellFolder
*desktop
;
135 ret
= ShellItem_get_parent_pidl(This
, &parent_pidl
);
138 ret
= SHGetDesktopFolder(&desktop
);
141 ret
= IShellFolder_BindToObject(desktop
, parent_pidl
, NULL
, &IID_IShellFolder
, (void**)ppsf
);
142 IShellFolder_Release(desktop
);
150 static HRESULT
ShellItem_get_shellfolder(ShellItem
*This
, IBindCtx
*pbc
, IShellFolder
**ppsf
)
152 IShellFolder
*desktop
;
155 ret
= SHGetDesktopFolder(&desktop
);
158 if (_ILIsDesktop(This
->pidl
))
161 IShellFolder_AddRef(*ppsf
);
165 ret
= IShellFolder_BindToObject(desktop
, This
->pidl
, pbc
, &IID_IShellFolder
, (void**)ppsf
);
168 IShellFolder_Release(desktop
);
174 static HRESULT WINAPI
ShellItem_BindToHandler(IShellItem
*iface
, IBindCtx
*pbc
,
175 REFGUID rbhid
, REFIID riid
, void **ppvOut
)
177 ShellItem
*This
= (ShellItem
*)iface
;
179 TRACE("(%p,%p,%s,%p,%p)\n", iface
, pbc
, shdebugstr_guid(rbhid
), riid
, ppvOut
);
182 if (IsEqualGUID(rbhid
, &BHID_SFObject
))
185 ret
= ShellItem_get_shellfolder(This
, pbc
, &psf
);
188 ret
= IShellFolder_QueryInterface(psf
, riid
, ppvOut
);
189 IShellFolder_Release(psf
);
193 else if (IsEqualGUID(rbhid
, &BHID_SFUIObject
))
195 IShellFolder
*psf_parent
;
196 if (_ILIsDesktop(This
->pidl
))
197 ret
= SHGetDesktopFolder(&psf_parent
);
199 ret
= ShellItem_get_parent_shellfolder(This
, &psf_parent
);
203 LPCITEMIDLIST pidl
= ILFindLastID(This
->pidl
);
204 ret
= IShellFolder_GetUIObjectOf(psf_parent
, NULL
, 1, &pidl
, riid
, NULL
, ppvOut
);
205 IShellFolder_Release(psf_parent
);
209 else if (IsEqualGUID(rbhid
, &BHID_DataObject
))
211 return ShellItem_BindToHandler((IShellItem
*)This
, pbc
, &BHID_SFUIObject
, &IID_IDataObject
, ppvOut
);
214 FIXME("Unsupported BHID %s.\n", debugstr_guid(rbhid
));
216 return MK_E_NOOBJECT
;
219 static HRESULT WINAPI
ShellItem_GetParent(IShellItem
*iface
, IShellItem
**ppsi
)
221 ShellItem
*This
= (ShellItem
*)iface
;
222 LPITEMIDLIST parent_pidl
;
225 TRACE("(%p,%p)\n", iface
, ppsi
);
227 ret
= ShellItem_get_parent_pidl(This
, &parent_pidl
);
230 ret
= SHCreateShellItem(NULL
, NULL
, parent_pidl
, ppsi
);
237 static HRESULT WINAPI
ShellItem_GetDisplayName(IShellItem
*iface
, SIGDN sigdnName
,
240 ShellItem
*This
= (ShellItem
*)iface
;
241 TRACE("(%p,%x,%p)\n", iface
, sigdnName
, ppszName
);
243 return SHGetNameFromIDList(This
->pidl
, sigdnName
, ppszName
);
246 static HRESULT WINAPI
ShellItem_GetAttributes(IShellItem
*iface
, SFGAOF sfgaoMask
,
247 SFGAOF
*psfgaoAttribs
)
249 ShellItem
*This
= (ShellItem
*)iface
;
250 IShellFolder
*parent_folder
;
251 LPITEMIDLIST child_pidl
;
254 TRACE("(%p,%x,%p)\n", iface
, sfgaoMask
, psfgaoAttribs
);
256 ret
= ShellItem_get_parent_shellfolder(This
, &parent_folder
);
259 child_pidl
= ILFindLastID(This
->pidl
);
260 *psfgaoAttribs
= sfgaoMask
;
261 ret
= IShellFolder_GetAttributesOf(parent_folder
, 1, (LPCITEMIDLIST
*)&child_pidl
, psfgaoAttribs
);
262 IShellFolder_Release(parent_folder
);
268 static HRESULT WINAPI
ShellItem_Compare(IShellItem
*iface
, IShellItem
*oth
,
269 SICHINTF hint
, int *piOrder
)
271 LPWSTR dispname
, dispname_oth
;
273 TRACE("(%p,%p,%x,%p)\n", iface
, oth
, hint
, piOrder
);
275 if(hint
& (SICHINT_CANONICAL
| SICHINT_ALLFIELDS
))
276 FIXME("Unsupported flags 0x%08x\n", hint
);
278 ret
= IShellItem_GetDisplayName(iface
, SIGDN_DESKTOPABSOLUTEEDITING
, &dispname
);
281 ret
= IShellItem_GetDisplayName(oth
, SIGDN_DESKTOPABSOLUTEEDITING
, &dispname_oth
);
284 *piOrder
= lstrcmpiW(dispname
, dispname_oth
);
285 CoTaskMemFree(dispname_oth
);
287 CoTaskMemFree(dispname
);
290 if(SUCCEEDED(ret
) && *piOrder
&&
291 (hint
& SICHINT_TEST_FILESYSPATH_IF_NOT_EQUAL
))
293 LPWSTR dispname
, dispname_oth
;
295 TRACE("Testing filesystem path.\n");
296 ret
= IShellItem_GetDisplayName(iface
, SIGDN_FILESYSPATH
, &dispname
);
299 ret
= IShellItem_GetDisplayName(oth
, SIGDN_FILESYSPATH
, &dispname_oth
);
302 *piOrder
= lstrcmpiW(dispname
, dispname_oth
);
303 CoTaskMemFree(dispname_oth
);
305 CoTaskMemFree(dispname
);
318 static const IShellItemVtbl ShellItem_Vtbl
= {
319 ShellItem_QueryInterface
,
322 ShellItem_BindToHandler
,
324 ShellItem_GetDisplayName
,
325 ShellItem_GetAttributes
,
330 static HRESULT
ShellItem_GetClassID(ShellItem
* This
, CLSID
*pClassID
)
332 TRACE("(%p,%p)\n", This
, pClassID
);
334 *pClassID
= CLSID_ShellItem
;
339 static HRESULT WINAPI
ShellItem_IPersistIDList_QueryInterface(IPersistIDList
*iface
,
340 REFIID riid
, void **ppv
)
342 ShellItem
*This
= impl_from_IPersistIDList(iface
);
343 return ShellItem_QueryInterface((IShellItem
*)This
, riid
, ppv
);
346 static ULONG WINAPI
ShellItem_IPersistIDList_AddRef(IPersistIDList
*iface
)
348 ShellItem
*This
= impl_from_IPersistIDList(iface
);
349 return ShellItem_AddRef((IShellItem
*)This
);
352 static ULONG WINAPI
ShellItem_IPersistIDList_Release(IPersistIDList
*iface
)
354 ShellItem
*This
= impl_from_IPersistIDList(iface
);
355 return ShellItem_Release((IShellItem
*)This
);
358 static HRESULT WINAPI
ShellItem_IPersistIDList_GetClassID(IPersistIDList
* iface
,
361 ShellItem
*This
= impl_from_IPersistIDList(iface
);
363 return ShellItem_GetClassID(This
, pClassID
);
366 static HRESULT WINAPI
ShellItem_IPersistIDList_SetIDList(IPersistIDList
* iface
,
369 ShellItem
*This
= impl_from_IPersistIDList(iface
);
370 LPITEMIDLIST new_pidl
;
372 TRACE("(%p,%p)\n", This
, pidl
);
374 new_pidl
= ILClone(pidl
);
379 This
->pidl
= new_pidl
;
383 return E_OUTOFMEMORY
;
386 static HRESULT WINAPI
ShellItem_IPersistIDList_GetIDList(IPersistIDList
* iface
,
389 ShellItem
*This
= impl_from_IPersistIDList(iface
);
391 TRACE("(%p,%p)\n", This
, ppidl
);
393 *ppidl
= ILClone(This
->pidl
);
397 return E_OUTOFMEMORY
;
400 static const IPersistIDListVtbl ShellItem_IPersistIDList_Vtbl
= {
401 ShellItem_IPersistIDList_QueryInterface
,
402 ShellItem_IPersistIDList_AddRef
,
403 ShellItem_IPersistIDList_Release
,
404 ShellItem_IPersistIDList_GetClassID
,
405 ShellItem_IPersistIDList_SetIDList
,
406 ShellItem_IPersistIDList_GetIDList
410 HRESULT WINAPI
IShellItem_Constructor(IUnknown
*pUnkOuter
, REFIID riid
, void **ppv
)
415 TRACE("(%p,%s)\n",pUnkOuter
, debugstr_guid(riid
));
419 if (pUnkOuter
) return CLASS_E_NOAGGREGATION
;
421 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(ShellItem
));
422 This
->lpIShellItemVtbl
= &ShellItem_Vtbl
;
425 This
->lpIPersistIDListVtbl
= &ShellItem_IPersistIDList_Vtbl
;
427 ret
= ShellItem_QueryInterface((IShellItem
*)This
, riid
, ppv
);
428 ShellItem_Release((IShellItem
*)This
);
433 HRESULT WINAPI
SHCreateShellItem(LPCITEMIDLIST pidlParent
,
434 IShellFolder
*psfParent
, LPCITEMIDLIST pidl
, IShellItem
**ppsi
)
437 LPITEMIDLIST new_pidl
;
440 TRACE("(%p,%p,%p,%p)\n", pidlParent
, psfParent
, pidl
, ppsi
);
446 else if (pidlParent
|| psfParent
)
448 LPITEMIDLIST temp_parent
=NULL
;
451 IPersistFolder2
* ppf2Parent
;
453 if (FAILED(IPersistFolder2_QueryInterface(psfParent
, &IID_IPersistFolder2
, (void**)&ppf2Parent
)))
455 FIXME("couldn't get IPersistFolder2 interface of parent\n");
456 return E_NOINTERFACE
;
459 if (FAILED(IPersistFolder2_GetCurFolder(ppf2Parent
, &temp_parent
)))
461 FIXME("couldn't get parent PIDL\n");
462 IPersistFolder2_Release(ppf2Parent
);
463 return E_NOINTERFACE
;
466 pidlParent
= temp_parent
;
467 IPersistFolder2_Release(ppf2Parent
);
470 new_pidl
= ILCombine(pidlParent
, pidl
);
474 return E_OUTOFMEMORY
;
478 new_pidl
= ILClone(pidl
);
480 return E_OUTOFMEMORY
;
483 ret
= IShellItem_Constructor(NULL
, &IID_IShellItem
, (void**)&This
);
486 *ppsi
= (IShellItem
*)This
;
487 This
->pidl
= new_pidl
;
497 HRESULT WINAPI
SHCreateItemFromParsingName(PCWSTR pszPath
,
498 IBindCtx
*pbc
, REFIID riid
, void **ppv
)
505 ret
= SHParseDisplayName(pszPath
, pbc
, &pidl
, 0, NULL
);
509 ret
= IShellItem_Constructor(NULL
, riid
, (void**)&This
);
524 HRESULT WINAPI
SHCreateItemFromIDList(PCIDLIST_ABSOLUTE pidl
, REFIID riid
, void **ppv
)
532 ret
= IShellItem_Constructor(NULL
, riid
, ppv
);
535 psiimpl
= (ShellItem
*)*ppv
;
536 psiimpl
->pidl
= ILClone(pidl
);
542 HRESULT WINAPI
SHGetItemFromDataObject(IDataObject
*pdtobj
,
543 DATAOBJ_GET_ITEM_FLAGS dwFlags
, REFIID riid
, void **ppv
)
549 TRACE("%p, %x, %s, %p\n", pdtobj
, dwFlags
, debugstr_guid(riid
), ppv
);
554 fmt
.cfFormat
= RegisterClipboardFormatW(CFSTR_SHELLIDLISTW
);
556 fmt
.dwAspect
= DVASPECT_CONTENT
;
558 fmt
.tymed
= TYMED_HGLOBAL
;
560 ret
= IDataObject_GetData(pdtobj
, &fmt
, &medium
);
563 LPIDA pida
= GlobalLock(medium
.u
.hGlobal
);
565 if((pida
->cidl
> 1 && !(dwFlags
& DOGIF_ONLY_IF_ONE
)) ||
570 /* Get the first pidl (parent + child1) */
571 pidl
= ILCombine((LPCITEMIDLIST
) ((LPBYTE
)pida
+pida
->aoffset
[0]),
572 (LPCITEMIDLIST
) ((LPBYTE
)pida
+pida
->aoffset
[1]));
574 ret
= SHCreateItemFromIDList(pidl
, riid
, ppv
);
582 GlobalUnlock(medium
.u
.hGlobal
);
583 GlobalFree(medium
.u
.hGlobal
);
586 if(FAILED(ret
) && !(dwFlags
& DOGIF_NO_HDROP
))
588 TRACE("Attempting to fall back on CF_HDROP.\n");
590 fmt
.cfFormat
= CF_HDROP
;
592 fmt
.dwAspect
= DVASPECT_CONTENT
;
594 fmt
.tymed
= TYMED_HGLOBAL
;
596 ret
= IDataObject_GetData(pdtobj
, &fmt
, &medium
);
599 DROPFILES
*df
= GlobalLock(medium
.u
.hGlobal
);
600 LPBYTE files
= (LPBYTE
)df
+ df
->pFiles
;
601 BOOL multiple_files
= FALSE
;
606 WCHAR filename
[MAX_PATH
];
607 PCSTR first_file
= (PCSTR
)files
;
608 if(*(files
+ lstrlenA(first_file
) + 1) != 0)
609 multiple_files
= TRUE
;
611 if( !(multiple_files
&& (dwFlags
& DOGIF_ONLY_IF_ONE
)) )
613 MultiByteToWideChar(CP_ACP
, 0, first_file
, -1, filename
, MAX_PATH
);
614 ret
= SHCreateItemFromParsingName(filename
, NULL
, riid
, ppv
);
619 PCWSTR first_file
= (PCWSTR
)files
;
620 if(*((PCWSTR
)files
+ lstrlenW(first_file
) + 1) != 0)
621 multiple_files
= TRUE
;
623 if( !(multiple_files
&& (dwFlags
& DOGIF_ONLY_IF_ONE
)) )
624 ret
= SHCreateItemFromParsingName(first_file
, NULL
, riid
, ppv
);
627 GlobalUnlock(medium
.u
.hGlobal
);
628 GlobalFree(medium
.u
.hGlobal
);
632 if(FAILED(ret
) && !(dwFlags
& DOGIF_NO_URL
))
634 FIXME("Failed to create item, should try CF_URL.\n");
640 HRESULT WINAPI
SHGetItemFromObject(IUnknown
*punk
, REFIID riid
, void **ppv
)
645 ret
= SHGetIDListFromObject(punk
, &pidl
);
648 ret
= SHCreateItemFromIDList(pidl
, riid
, ppv
);
655 /*************************************************************************
656 * IShellItemArray implementation
659 const IShellItemArrayVtbl
*lpVtbl
;
664 } IShellItemArrayImpl
;
666 static HRESULT WINAPI
IShellItemArray_fnQueryInterface(IShellItemArray
*iface
,
670 IShellItemArrayImpl
*This
= (IShellItemArrayImpl
*)iface
;
671 TRACE("%p (%s, %p)\n", This
, shdebugstr_guid(riid
), ppvObject
);
674 if(IsEqualIID(riid
, &IID_IShellItemArray
) ||
675 IsEqualIID(riid
, &IID_IUnknown
))
682 IUnknown_AddRef((IUnknown
*)*ppvObject
);
686 return E_NOINTERFACE
;
689 static ULONG WINAPI
IShellItemArray_fnAddRef(IShellItemArray
*iface
)
691 IShellItemArrayImpl
*This
= (IShellItemArrayImpl
*)iface
;
692 LONG ref
= InterlockedIncrement(&This
->ref
);
693 TRACE("%p - ref %d\n", This
, ref
);
698 static ULONG WINAPI
IShellItemArray_fnRelease(IShellItemArray
*iface
)
700 IShellItemArrayImpl
*This
= (IShellItemArrayImpl
*)iface
;
701 LONG ref
= InterlockedDecrement(&This
->ref
);
702 TRACE("%p - ref %d\n", This
, ref
);
709 for(i
= 0; i
< This
->item_count
; i
++)
710 IShellItem_Release(This
->array
[i
]);
712 HeapFree(GetProcessHeap(), 0, This
->array
);
713 HeapFree(GetProcessHeap(), 0, This
);
720 static HRESULT WINAPI
IShellItemArray_fnBindToHandler(IShellItemArray
*iface
,
726 IShellItemArrayImpl
*This
= (IShellItemArrayImpl
*)iface
;
727 FIXME("Stub: %p (%p, %s, %s, %p)\n",
728 This
, pbc
, shdebugstr_guid(bhid
), shdebugstr_guid(riid
), ppvOut
);
733 static HRESULT WINAPI
IShellItemArray_fnGetPropertyStore(IShellItemArray
*iface
,
734 GETPROPERTYSTOREFLAGS flags
,
738 IShellItemArrayImpl
*This
= (IShellItemArrayImpl
*)iface
;
739 FIXME("Stub: %p (%x, %s, %p)\n", This
, flags
, shdebugstr_guid(riid
), ppv
);
744 static HRESULT WINAPI
IShellItemArray_fnGetPropertyDescriptionList(IShellItemArray
*iface
,
745 REFPROPERTYKEY keyType
,
749 IShellItemArrayImpl
*This
= (IShellItemArrayImpl
*)iface
;
750 FIXME("Stub: %p (%p, %s, %p)\n",
751 This
, keyType
, shdebugstr_guid(riid
), ppv
);
756 static HRESULT WINAPI
IShellItemArray_fnGetAttributes(IShellItemArray
*iface
,
757 SIATTRIBFLAGS AttribFlags
,
759 SFGAOF
*psfgaoAttribs
)
761 IShellItemArrayImpl
*This
= (IShellItemArrayImpl
*)iface
;
762 FIXME("Stub: %p (%x, %x, %p)\n", This
, AttribFlags
, sfgaoMask
, psfgaoAttribs
);
767 static HRESULT WINAPI
IShellItemArray_fnGetCount(IShellItemArray
*iface
,
770 IShellItemArrayImpl
*This
= (IShellItemArrayImpl
*)iface
;
771 TRACE("%p (%p)\n", This
, pdwNumItems
);
773 *pdwNumItems
= This
->item_count
;
778 static HRESULT WINAPI
IShellItemArray_fnGetItemAt(IShellItemArray
*iface
,
782 IShellItemArrayImpl
*This
= (IShellItemArrayImpl
*)iface
;
783 TRACE("%p (%x, %p)\n", This
, dwIndex
, ppsi
);
786 if(dwIndex
+ 1 > This
->item_count
)
789 *ppsi
= This
->array
[dwIndex
];
790 IShellItem_AddRef(*ppsi
);
795 static HRESULT WINAPI
IShellItemArray_fnEnumItems(IShellItemArray
*iface
,
796 IEnumShellItems
**ppenumShellItems
)
798 IShellItemArrayImpl
*This
= (IShellItemArrayImpl
*)iface
;
799 FIXME("Stub: %p (%p)\n", This
, ppenumShellItems
);
804 static const IShellItemArrayVtbl vt_IShellItemArray
= {
805 IShellItemArray_fnQueryInterface
,
806 IShellItemArray_fnAddRef
,
807 IShellItemArray_fnRelease
,
808 IShellItemArray_fnBindToHandler
,
809 IShellItemArray_fnGetPropertyStore
,
810 IShellItemArray_fnGetPropertyDescriptionList
,
811 IShellItemArray_fnGetAttributes
,
812 IShellItemArray_fnGetCount
,
813 IShellItemArray_fnGetItemAt
,
814 IShellItemArray_fnEnumItems
817 static HRESULT
IShellItemArray_Constructor(IUnknown
*pUnkOuter
, REFIID riid
, void **ppv
)
819 IShellItemArrayImpl
*This
;
822 TRACE("(%p, %s, %p)\n",pUnkOuter
, debugstr_guid(riid
), ppv
);
825 return CLASS_E_NOAGGREGATION
;
827 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(IShellItemArrayImpl
));
829 return E_OUTOFMEMORY
;
832 This
->lpVtbl
= &vt_IShellItemArray
;
834 This
->item_count
= 0;
836 ret
= IShellItemArray_QueryInterface((IShellItemArray
*)This
, riid
, ppv
);
837 IShellItemArray_Release((IShellItemArray
*)This
);
842 HRESULT WINAPI
SHCreateShellItemArray(PCIDLIST_ABSOLUTE pidlParent
,
845 PCUITEMID_CHILD_ARRAY ppidl
,
846 IShellItemArray
**ppsiItemArray
)
848 IShellItemArrayImpl
*This
;
850 HRESULT ret
= E_FAIL
;
853 TRACE("%p, %p, %d, %p, %p\n", pidlParent
, psf
, cidl
, ppidl
, ppsiItemArray
);
855 if(!pidlParent
&& !psf
)
861 array
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, cidl
*sizeof(IShellItem
*));
863 return E_OUTOFMEMORY
;
865 for(i
= 0; i
< cidl
; i
++)
867 ret
= SHCreateShellItem(pidlParent
, psf
, ppidl
[i
], &array
[i
]);
868 if(FAILED(ret
)) break;
873 ret
= IShellItemArray_Constructor(NULL
, &IID_IShellItemArray
, (void**)&This
);
877 This
->item_count
= cidl
;
878 *ppsiItemArray
= (IShellItemArray
*)This
;
884 /* Something failed, clean up. */
885 for(i
= 0; i
< cidl
; i
++)
886 if(array
[i
]) IShellItem_Release(array
[i
]);
887 HeapFree(GetProcessHeap(), 0, array
);
888 *ppsiItemArray
= NULL
;
892 HRESULT WINAPI
SHCreateShellItemArrayFromShellItem(IShellItem
*psi
, REFIID riid
, void **ppv
)
894 IShellItemArrayImpl
*This
;
898 TRACE("%p, %s, %p\n", psi
, shdebugstr_guid(riid
), ppv
);
900 array
= HeapAlloc(GetProcessHeap(), 0, sizeof(IShellItem
*));
902 return E_OUTOFMEMORY
;
904 ret
= IShellItemArray_Constructor(NULL
, riid
, (void**)&This
);
908 IShellItem_AddRef(psi
);
910 This
->item_count
= 1;
915 HeapFree(GetProcessHeap(), 0, array
);
922 HRESULT WINAPI
SHCreateShellItemArrayFromDataObject(IDataObject
*pdo
, REFIID riid
, void **ppv
)
924 IShellItemArray
*psia
;
929 TRACE("%p, %s, %p\n", pdo
, shdebugstr_guid(riid
), ppv
);
936 fmt
.cfFormat
= RegisterClipboardFormatW(CFSTR_SHELLIDLISTW
);
938 fmt
.dwAspect
= DVASPECT_CONTENT
;
940 fmt
.tymed
= TYMED_HGLOBAL
;
942 ret
= IDataObject_GetData(pdo
, &fmt
, &medium
);
945 LPIDA pida
= GlobalLock(medium
.u
.hGlobal
);
946 LPCITEMIDLIST parent_pidl
;
947 LPCITEMIDLIST
*children
;
949 TRACE("Converting %d objects.\n", pida
->cidl
);
951 parent_pidl
= (LPCITEMIDLIST
) ((LPBYTE
)pida
+pida
->aoffset
[0]);
953 children
= HeapAlloc(GetProcessHeap(), 0, sizeof(LPCITEMIDLIST
)*pida
->cidl
);
954 for(i
= 0; i
< pida
->cidl
; i
++)
955 children
[i
] = (LPCITEMIDLIST
) ((LPBYTE
)pida
+pida
->aoffset
[i
+1]);
957 ret
= SHCreateShellItemArray(parent_pidl
, NULL
, pida
->cidl
, children
, (IShellItemArray
**)&psia
);
959 HeapFree(GetProcessHeap(), 0, children
);
961 GlobalUnlock(medium
.u
.hGlobal
);
962 GlobalFree(medium
.u
.hGlobal
);
967 ret
= IShellItemArray_QueryInterface(psia
, riid
, ppv
);
968 IShellItemArray_Release(psia
);