shell32: Implement SHCreateShellItemArrayFromShellItem.
[wine/wine-gecko.git] / dlls / shell32 / shellitem.c
blob68cd32e10c55ef4e26966474beff4f6fcea48c26
1 /*
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
21 #include "config.h"
22 #include "wine/port.h"
24 #include <stdio.h>
25 #include <stdarg.h>
27 #define COBJMACROS
28 #define NONAMELESSUNION
29 #define NONAMELESSSTRUCT
31 #include "windef.h"
32 #include "winbase.h"
33 #include "wine/debug.h"
35 #include "pidl.h"
36 #include "shell32_main.h"
37 #include "debughlp.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(shell);
41 typedef struct _ShellItem {
42 const IShellItemVtbl *lpIShellItemVtbl;
43 LONG ref;
44 LPITEMIDLIST pidl;
45 const IPersistIDListVtbl *lpIPersistIDListVtbl;
46 } ShellItem;
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,
56 void **ppv)
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))
66 *ppv = This;
68 else if (IsEqualIID(&IID_IPersist, riid) || IsEqualIID(&IID_IPersistIDList, riid))
70 *ppv = &(This->lpIPersistIDListVtbl);
72 else {
73 FIXME("not implemented for %s\n", shdebugstr_guid(riid));
74 *ppv = NULL;
75 return E_NOINTERFACE;
78 IUnknown_AddRef((IUnknown*)*ppv);
79 return S_OK;
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);
89 return 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);
99 if (ref == 0)
101 ILFree(This->pidl);
102 HeapFree(GetProcessHeap(), 0, This);
105 return ref;
108 static HRESULT ShellItem_get_parent_pidl(ShellItem *This, LPITEMIDLIST *parent_pidl)
110 *parent_pidl = ILClone(This->pidl);
111 if (*parent_pidl)
113 if (ILRemoveLastID(*parent_pidl))
114 return S_OK;
115 else
117 ILFree(*parent_pidl);
118 *parent_pidl = NULL;
119 return E_INVALIDARG;
122 else
124 *parent_pidl = NULL;
125 return E_OUTOFMEMORY;
129 static HRESULT ShellItem_get_parent_shellfolder(ShellItem *This, IShellFolder **ppsf)
131 LPITEMIDLIST parent_pidl;
132 IShellFolder *desktop;
133 HRESULT ret;
135 ret = ShellItem_get_parent_pidl(This, &parent_pidl);
136 if (SUCCEEDED(ret))
138 ret = SHGetDesktopFolder(&desktop);
139 if (SUCCEEDED(ret))
141 ret = IShellFolder_BindToObject(desktop, parent_pidl, NULL, &IID_IShellFolder, (void**)ppsf);
142 IShellFolder_Release(desktop);
144 ILFree(parent_pidl);
147 return ret;
150 static HRESULT WINAPI ShellItem_BindToHandler(IShellItem *iface, IBindCtx *pbc,
151 REFGUID rbhid, REFIID riid, void **ppvOut)
153 FIXME("(%p,%p,%s,%p,%p)\n", iface, pbc, shdebugstr_guid(rbhid), riid, ppvOut);
155 *ppvOut = NULL;
157 return E_NOTIMPL;
160 static HRESULT WINAPI ShellItem_GetParent(IShellItem *iface, IShellItem **ppsi)
162 ShellItem *This = (ShellItem*)iface;
163 LPITEMIDLIST parent_pidl;
164 HRESULT ret;
166 TRACE("(%p,%p)\n", iface, ppsi);
168 ret = ShellItem_get_parent_pidl(This, &parent_pidl);
169 if (SUCCEEDED(ret))
171 ret = SHCreateShellItem(NULL, NULL, parent_pidl, ppsi);
172 ILFree(parent_pidl);
175 return ret;
178 static HRESULT WINAPI ShellItem_GetDisplayName(IShellItem *iface, SIGDN sigdnName,
179 LPWSTR *ppszName)
181 ShellItem *This = (ShellItem*)iface;
182 TRACE("(%p,%x,%p)\n", iface, sigdnName, ppszName);
184 return SHGetNameFromIDList(This->pidl, sigdnName, ppszName);
187 static HRESULT WINAPI ShellItem_GetAttributes(IShellItem *iface, SFGAOF sfgaoMask,
188 SFGAOF *psfgaoAttribs)
190 ShellItem *This = (ShellItem*)iface;
191 IShellFolder *parent_folder;
192 LPITEMIDLIST child_pidl;
193 HRESULT ret;
195 TRACE("(%p,%x,%p)\n", iface, sfgaoMask, psfgaoAttribs);
197 ret = ShellItem_get_parent_shellfolder(This, &parent_folder);
198 if (SUCCEEDED(ret))
200 child_pidl = ILFindLastID(This->pidl);
201 *psfgaoAttribs = sfgaoMask;
202 ret = IShellFolder_GetAttributesOf(parent_folder, 1, (LPCITEMIDLIST*)&child_pidl, psfgaoAttribs);
203 IShellFolder_Release(parent_folder);
206 return ret;
209 static HRESULT WINAPI ShellItem_Compare(IShellItem *iface, IShellItem *oth,
210 SICHINTF hint, int *piOrder)
212 LPWSTR dispname, dispname_oth;
213 HRESULT ret;
214 TRACE("(%p,%p,%x,%p)\n", iface, oth, hint, piOrder);
216 if(hint & (SICHINT_CANONICAL | SICHINT_ALLFIELDS))
217 FIXME("Unsupported flags 0x%08x\n", hint);
219 ret = IShellItem_GetDisplayName(iface, SIGDN_DESKTOPABSOLUTEEDITING, &dispname);
220 if(SUCCEEDED(ret))
222 ret = IShellItem_GetDisplayName(oth, SIGDN_DESKTOPABSOLUTEEDITING, &dispname_oth);
223 if(SUCCEEDED(ret))
225 *piOrder = lstrcmpiW(dispname, dispname_oth);
226 CoTaskMemFree(dispname_oth);
228 CoTaskMemFree(dispname);
231 if(SUCCEEDED(ret) && *piOrder &&
232 (hint & SICHINT_TEST_FILESYSPATH_IF_NOT_EQUAL))
234 LPWSTR dispname, dispname_oth;
236 TRACE("Testing filesystem path.\n");
237 ret = IShellItem_GetDisplayName(iface, SIGDN_FILESYSPATH, &dispname);
238 if(SUCCEEDED(ret))
240 ret = IShellItem_GetDisplayName(oth, SIGDN_FILESYSPATH, &dispname_oth);
241 if(SUCCEEDED(ret))
243 *piOrder = lstrcmpiW(dispname, dispname_oth);
244 CoTaskMemFree(dispname_oth);
246 CoTaskMemFree(dispname);
250 if(FAILED(ret))
251 return ret;
253 if(*piOrder)
254 return S_FALSE;
255 else
256 return S_OK;
259 static const IShellItemVtbl ShellItem_Vtbl = {
260 ShellItem_QueryInterface,
261 ShellItem_AddRef,
262 ShellItem_Release,
263 ShellItem_BindToHandler,
264 ShellItem_GetParent,
265 ShellItem_GetDisplayName,
266 ShellItem_GetAttributes,
267 ShellItem_Compare
271 static HRESULT ShellItem_GetClassID(ShellItem* This, CLSID *pClassID)
273 TRACE("(%p,%p)\n", This, pClassID);
275 *pClassID = CLSID_ShellItem;
276 return S_OK;
280 static HRESULT WINAPI ShellItem_IPersistIDList_QueryInterface(IPersistIDList *iface,
281 REFIID riid, void **ppv)
283 ShellItem *This = impl_from_IPersistIDList(iface);
284 return ShellItem_QueryInterface((IShellItem*)This, riid, ppv);
287 static ULONG WINAPI ShellItem_IPersistIDList_AddRef(IPersistIDList *iface)
289 ShellItem *This = impl_from_IPersistIDList(iface);
290 return ShellItem_AddRef((IShellItem*)This);
293 static ULONG WINAPI ShellItem_IPersistIDList_Release(IPersistIDList *iface)
295 ShellItem *This = impl_from_IPersistIDList(iface);
296 return ShellItem_Release((IShellItem*)This);
299 static HRESULT WINAPI ShellItem_IPersistIDList_GetClassID(IPersistIDList* iface,
300 CLSID *pClassID)
302 ShellItem *This = impl_from_IPersistIDList(iface);
304 return ShellItem_GetClassID(This, pClassID);
307 static HRESULT WINAPI ShellItem_IPersistIDList_SetIDList(IPersistIDList* iface,
308 LPCITEMIDLIST pidl)
310 ShellItem *This = impl_from_IPersistIDList(iface);
311 LPITEMIDLIST new_pidl;
313 TRACE("(%p,%p)\n", This, pidl);
315 new_pidl = ILClone(pidl);
317 if (new_pidl)
319 ILFree(This->pidl);
320 This->pidl = new_pidl;
321 return S_OK;
323 else
324 return E_OUTOFMEMORY;
327 static HRESULT WINAPI ShellItem_IPersistIDList_GetIDList(IPersistIDList* iface,
328 LPITEMIDLIST *ppidl)
330 ShellItem *This = impl_from_IPersistIDList(iface);
332 TRACE("(%p,%p)\n", This, ppidl);
334 *ppidl = ILClone(This->pidl);
335 if (*ppidl)
336 return S_OK;
337 else
338 return E_OUTOFMEMORY;
341 static const IPersistIDListVtbl ShellItem_IPersistIDList_Vtbl = {
342 ShellItem_IPersistIDList_QueryInterface,
343 ShellItem_IPersistIDList_AddRef,
344 ShellItem_IPersistIDList_Release,
345 ShellItem_IPersistIDList_GetClassID,
346 ShellItem_IPersistIDList_SetIDList,
347 ShellItem_IPersistIDList_GetIDList
351 HRESULT WINAPI IShellItem_Constructor(IUnknown *pUnkOuter, REFIID riid, void **ppv)
353 ShellItem *This;
354 HRESULT ret;
356 TRACE("(%p,%s)\n",pUnkOuter, debugstr_guid(riid));
358 *ppv = NULL;
360 if (pUnkOuter) return CLASS_E_NOAGGREGATION;
362 This = HeapAlloc(GetProcessHeap(), 0, sizeof(ShellItem));
363 This->lpIShellItemVtbl = &ShellItem_Vtbl;
364 This->ref = 1;
365 This->pidl = NULL;
366 This->lpIPersistIDListVtbl = &ShellItem_IPersistIDList_Vtbl;
368 ret = ShellItem_QueryInterface((IShellItem*)This, riid, ppv);
369 ShellItem_Release((IShellItem*)This);
371 return ret;
374 HRESULT WINAPI SHCreateShellItem(LPCITEMIDLIST pidlParent,
375 IShellFolder *psfParent, LPCITEMIDLIST pidl, IShellItem **ppsi)
377 ShellItem *This;
378 LPITEMIDLIST new_pidl;
379 HRESULT ret;
381 TRACE("(%p,%p,%p,%p)\n", pidlParent, psfParent, pidl, ppsi);
383 if (!pidl)
385 return E_INVALIDARG;
387 else if (pidlParent || psfParent)
389 LPITEMIDLIST temp_parent=NULL;
390 if (!pidlParent)
392 IPersistFolder2* ppf2Parent;
394 if (FAILED(IPersistFolder2_QueryInterface(psfParent, &IID_IPersistFolder2, (void**)&ppf2Parent)))
396 FIXME("couldn't get IPersistFolder2 interface of parent\n");
397 return E_NOINTERFACE;
400 if (FAILED(IPersistFolder2_GetCurFolder(ppf2Parent, &temp_parent)))
402 FIXME("couldn't get parent PIDL\n");
403 IPersistFolder2_Release(ppf2Parent);
404 return E_NOINTERFACE;
407 pidlParent = temp_parent;
408 IPersistFolder2_Release(ppf2Parent);
411 new_pidl = ILCombine(pidlParent, pidl);
412 ILFree(temp_parent);
414 if (!new_pidl)
415 return E_OUTOFMEMORY;
417 else
419 new_pidl = ILClone(pidl);
420 if (!new_pidl)
421 return E_OUTOFMEMORY;
424 ret = IShellItem_Constructor(NULL, &IID_IShellItem, (void**)&This);
425 if (This)
427 *ppsi = (IShellItem*)This;
428 This->pidl = new_pidl;
430 else
432 *ppsi = NULL;
433 ILFree(new_pidl);
435 return ret;
438 HRESULT WINAPI SHCreateItemFromParsingName(PCWSTR pszPath,
439 IBindCtx *pbc, REFIID riid, void **ppv)
441 LPITEMIDLIST pidl;
442 HRESULT ret;
444 *ppv = NULL;
446 ret = SHParseDisplayName(pszPath, pbc, &pidl, 0, NULL);
447 if(SUCCEEDED(ret))
449 ShellItem *This;
450 ret = IShellItem_Constructor(NULL, riid, (void**)&This);
452 if(SUCCEEDED(ret))
454 This->pidl = pidl;
455 *ppv = (void*)This;
457 else
459 ILFree(pidl);
462 return ret;
465 HRESULT WINAPI SHCreateItemFromIDList(PCIDLIST_ABSOLUTE pidl, REFIID riid, void **ppv)
467 ShellItem *psiimpl;
468 HRESULT ret;
470 if(!pidl)
471 return E_INVALIDARG;
473 ret = IShellItem_Constructor(NULL, riid, ppv);
474 if(SUCCEEDED(ret))
476 psiimpl = (ShellItem*)*ppv;
477 psiimpl->pidl = ILClone(pidl);
480 return ret;
483 HRESULT WINAPI SHGetItemFromDataObject(IDataObject *pdtobj,
484 DATAOBJ_GET_ITEM_FLAGS dwFlags, REFIID riid, void **ppv)
486 FORMATETC fmt;
487 STGMEDIUM medium;
488 HRESULT ret;
490 TRACE("%p, %x, %s, %p\n", pdtobj, dwFlags, debugstr_guid(riid), ppv);
492 if(!pdtobj)
493 return E_INVALIDARG;
495 fmt.cfFormat = RegisterClipboardFormatW(CFSTR_SHELLIDLISTW);
496 fmt.ptd = NULL;
497 fmt.dwAspect = DVASPECT_CONTENT;
498 fmt.lindex = -1;
499 fmt.tymed = TYMED_HGLOBAL;
501 ret = IDataObject_GetData(pdtobj, &fmt, &medium);
502 if(SUCCEEDED(ret))
504 LPIDA pida = GlobalLock(medium.u.hGlobal);
506 if((pida->cidl > 1 && !(dwFlags & DOGIF_ONLY_IF_ONE)) ||
507 pida->cidl == 1)
509 LPITEMIDLIST pidl;
511 /* Get the first pidl (parent + child1) */
512 pidl = ILCombine((LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[0]),
513 (LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[1]));
515 ret = SHCreateItemFromIDList(pidl, riid, ppv);
516 ILFree(pidl);
518 else
520 ret = E_FAIL;
523 GlobalUnlock(medium.u.hGlobal);
524 GlobalFree(medium.u.hGlobal);
527 if(FAILED(ret) && !(dwFlags & DOGIF_NO_HDROP))
529 TRACE("Attempting to fall back on CF_HDROP.\n");
531 fmt.cfFormat = CF_HDROP;
532 fmt.ptd = NULL;
533 fmt.dwAspect = DVASPECT_CONTENT;
534 fmt.lindex = -1;
535 fmt.tymed = TYMED_HGLOBAL;
537 ret = IDataObject_GetData(pdtobj, &fmt, &medium);
538 if(SUCCEEDED(ret))
540 DROPFILES *df = GlobalLock(medium.u.hGlobal);
541 LPBYTE files = (LPBYTE)df + df->pFiles;
542 BOOL multiple_files = FALSE;
544 ret = E_FAIL;
545 if(!df->fWide)
547 WCHAR filename[MAX_PATH];
548 PCSTR first_file = (PCSTR)files;
549 if(*(files + lstrlenA(first_file) + 1) != 0)
550 multiple_files = TRUE;
552 if( !(multiple_files && (dwFlags & DOGIF_ONLY_IF_ONE)) )
554 MultiByteToWideChar(CP_ACP, 0, first_file, -1, filename, MAX_PATH);
555 ret = SHCreateItemFromParsingName(filename, NULL, riid, ppv);
558 else
560 PCWSTR first_file = (PCWSTR)files;
561 if(*((PCWSTR)files + lstrlenW(first_file) + 1) != 0)
562 multiple_files = TRUE;
564 if( !(multiple_files && (dwFlags & DOGIF_ONLY_IF_ONE)) )
565 ret = SHCreateItemFromParsingName(first_file, NULL, riid, ppv);
568 GlobalUnlock(medium.u.hGlobal);
569 GlobalFree(medium.u.hGlobal);
573 if(FAILED(ret) && !(dwFlags & DOGIF_NO_URL))
575 FIXME("Failed to create item, should try CF_URL.\n");
578 return ret;
581 HRESULT WINAPI SHGetItemFromObject(IUnknown *punk, REFIID riid, void **ppv)
583 LPITEMIDLIST pidl;
584 HRESULT ret;
586 ret = SHGetIDListFromObject(punk, &pidl);
587 if(SUCCEEDED(ret))
589 ret = SHCreateItemFromIDList(pidl, riid, ppv);
590 ILFree(pidl);
593 return ret;
596 /*************************************************************************
597 * IShellItemArray implementation
599 typedef struct {
600 const IShellItemArrayVtbl *lpVtbl;
601 LONG ref;
603 IShellItem **array;
604 DWORD item_count;
605 } IShellItemArrayImpl;
607 static HRESULT WINAPI IShellItemArray_fnQueryInterface(IShellItemArray *iface,
608 REFIID riid,
609 void **ppvObject)
611 IShellItemArrayImpl *This = (IShellItemArrayImpl *)iface;
612 TRACE("%p (%s, %p)\n", This, shdebugstr_guid(riid), ppvObject);
614 *ppvObject = NULL;
615 if(IsEqualIID(riid, &IID_IShellItemArray) ||
616 IsEqualIID(riid, &IID_IUnknown))
618 *ppvObject = This;
621 if(*ppvObject)
623 IUnknown_AddRef((IUnknown*)*ppvObject);
624 return S_OK;
627 return E_NOINTERFACE;
630 static ULONG WINAPI IShellItemArray_fnAddRef(IShellItemArray *iface)
632 IShellItemArrayImpl *This = (IShellItemArrayImpl *)iface;
633 LONG ref = InterlockedIncrement(&This->ref);
634 TRACE("%p - ref %d\n", This, ref);
636 return ref;
639 static ULONG WINAPI IShellItemArray_fnRelease(IShellItemArray *iface)
641 IShellItemArrayImpl *This = (IShellItemArrayImpl *)iface;
642 LONG ref = InterlockedDecrement(&This->ref);
643 TRACE("%p - ref %d\n", This, ref);
645 if(!ref)
647 UINT i;
648 TRACE("Freeing.\n");
650 for(i = 0; i < This->item_count; i++)
651 IShellItem_Release(This->array[i]);
653 HeapFree(GetProcessHeap(), 0, This->array);
654 HeapFree(GetProcessHeap(), 0, This);
655 return 0;
658 return ref;
661 static HRESULT WINAPI IShellItemArray_fnBindToHandler(IShellItemArray *iface,
662 IBindCtx *pbc,
663 REFGUID bhid,
664 REFIID riid,
665 void **ppvOut)
667 IShellItemArrayImpl *This = (IShellItemArrayImpl *)iface;
668 FIXME("Stub: %p (%p, %s, %s, %p)\n",
669 This, pbc, shdebugstr_guid(bhid), shdebugstr_guid(riid), ppvOut);
671 return E_NOTIMPL;
674 static HRESULT WINAPI IShellItemArray_fnGetPropertyStore(IShellItemArray *iface,
675 GETPROPERTYSTOREFLAGS flags,
676 REFIID riid,
677 void **ppv)
679 IShellItemArrayImpl *This = (IShellItemArrayImpl *)iface;
680 FIXME("Stub: %p (%x, %s, %p)\n", This, flags, shdebugstr_guid(riid), ppv);
682 return E_NOTIMPL;
685 static HRESULT WINAPI IShellItemArray_fnGetPropertyDescriptionList(IShellItemArray *iface,
686 REFPROPERTYKEY keyType,
687 REFIID riid,
688 void **ppv)
690 IShellItemArrayImpl *This = (IShellItemArrayImpl *)iface;
691 FIXME("Stub: %p (%p, %s, %p)\n",
692 This, keyType, shdebugstr_guid(riid), ppv);
694 return E_NOTIMPL;
697 static HRESULT WINAPI IShellItemArray_fnGetAttributes(IShellItemArray *iface,
698 SIATTRIBFLAGS AttribFlags,
699 SFGAOF sfgaoMask,
700 SFGAOF *psfgaoAttribs)
702 IShellItemArrayImpl *This = (IShellItemArrayImpl *)iface;
703 FIXME("Stub: %p (%x, %x, %p)\n", This, AttribFlags, sfgaoMask, psfgaoAttribs);
705 return E_NOTIMPL;
708 static HRESULT WINAPI IShellItemArray_fnGetCount(IShellItemArray *iface,
709 DWORD *pdwNumItems)
711 IShellItemArrayImpl *This = (IShellItemArrayImpl *)iface;
712 TRACE("%p (%p)\n", This, pdwNumItems);
714 *pdwNumItems = This->item_count;
716 return S_OK;
719 static HRESULT WINAPI IShellItemArray_fnGetItemAt(IShellItemArray *iface,
720 DWORD dwIndex,
721 IShellItem **ppsi)
723 IShellItemArrayImpl *This = (IShellItemArrayImpl *)iface;
724 TRACE("%p (%x, %p)\n", This, dwIndex, ppsi);
726 /* zero indexed */
727 if(dwIndex + 1 > This->item_count)
728 return E_FAIL;
730 *ppsi = This->array[dwIndex];
731 IShellItem_AddRef(*ppsi);
733 return S_OK;
736 static HRESULT WINAPI IShellItemArray_fnEnumItems(IShellItemArray *iface,
737 IEnumShellItems **ppenumShellItems)
739 IShellItemArrayImpl *This = (IShellItemArrayImpl *)iface;
740 FIXME("Stub: %p (%p)\n", This, ppenumShellItems);
742 return E_NOTIMPL;
745 static const IShellItemArrayVtbl vt_IShellItemArray = {
746 IShellItemArray_fnQueryInterface,
747 IShellItemArray_fnAddRef,
748 IShellItemArray_fnRelease,
749 IShellItemArray_fnBindToHandler,
750 IShellItemArray_fnGetPropertyStore,
751 IShellItemArray_fnGetPropertyDescriptionList,
752 IShellItemArray_fnGetAttributes,
753 IShellItemArray_fnGetCount,
754 IShellItemArray_fnGetItemAt,
755 IShellItemArray_fnEnumItems
758 static HRESULT WINAPI IShellItemArray_Constructor(IUnknown *pUnkOuter, REFIID riid, void **ppv)
760 IShellItemArrayImpl *This;
761 HRESULT ret;
763 TRACE("(%p, %s, %p)\n",pUnkOuter, debugstr_guid(riid), ppv);
765 if(pUnkOuter)
766 return CLASS_E_NOAGGREGATION;
768 This = HeapAlloc(GetProcessHeap(), 0, sizeof(IShellItemArrayImpl));
769 if(!This)
770 return E_OUTOFMEMORY;
772 This->ref = 1;
773 This->lpVtbl = &vt_IShellItemArray;
775 ret = IShellItemArray_QueryInterface((IShellItemArray*)This, riid, ppv);
776 IShellItemArray_Release((IShellItemArray*)This);
778 return ret;
781 HRESULT WINAPI SHCreateShellItemArray(PCIDLIST_ABSOLUTE pidlParent,
782 IShellFolder *psf,
783 UINT cidl,
784 PCUITEMID_CHILD_ARRAY ppidl,
785 IShellItemArray **ppsiItemArray)
787 IShellItemArrayImpl *This;
788 IShellItem **array;
789 HRESULT ret = E_FAIL;
790 UINT i;
792 TRACE("%p, %p, %d, %p, %p\n", pidlParent, psf, cidl, ppidl, ppsiItemArray);
794 if(!pidlParent && !psf)
795 return E_POINTER;
797 if(!ppidl)
798 return E_INVALIDARG;
800 array = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cidl*sizeof(IShellItem*));
801 if(!array)
802 return E_OUTOFMEMORY;
804 for(i = 0; i < cidl; i++)
806 ret = SHCreateShellItem(pidlParent, psf, ppidl[i], &array[i]);
807 if(FAILED(ret)) break;
810 if(SUCCEEDED(ret))
812 ret = IShellItemArray_Constructor(NULL, &IID_IShellItemArray, (void**)&This);
813 if(SUCCEEDED(ret))
815 This->array = array;
816 This->item_count = cidl;
817 *ppsiItemArray = (IShellItemArray*)This;
819 return ret;
823 /* Something failed, clean up. */
824 for(i = 0; i < cidl; i++)
825 if(array[i]) IShellItem_Release(array[i]);
826 HeapFree(GetProcessHeap(), 0, array);
827 *ppsiItemArray = NULL;
828 return ret;
831 HRESULT WINAPI SHCreateShellItemArrayFromShellItem(IShellItem *psi, REFIID riid, void **ppv)
833 IShellItemArrayImpl *This;
834 IShellItem **array;
835 HRESULT ret;
837 TRACE("%p, %s, %p\n", psi, shdebugstr_guid(riid), ppv);
839 array = HeapAlloc(GetProcessHeap(), 0, sizeof(IShellItem*));
840 if(!array)
841 return E_OUTOFMEMORY;
843 ret = IShellItemArray_Constructor(NULL, riid, (void**)&This);
844 if(SUCCEEDED(ret))
846 array[0] = psi;
847 IShellItem_AddRef(psi);
848 This->array = array;
849 This->item_count = 1;
850 *ppv = This;
852 else
854 HeapFree(GetProcessHeap(), 0, array);
855 *ppv = NULL;
858 return ret;