msdasql: Implement IColumnsRowset GetAvailableColumns.
[wine.git] / dlls / shell32 / shellitem.c
bloba6d4ee9ef07e41c685a91afa208419df212a7ebe
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 <stdio.h>
22 #include <stdarg.h>
24 #define COBJMACROS
25 #define NONAMELESSUNION
27 #include "windef.h"
28 #include "winbase.h"
29 #include "wine/debug.h"
31 #include "pidl.h"
32 #include "shell32_main.h"
33 #include "debughlp.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(shell);
37 typedef struct _ShellItem {
38 IShellItem2 IShellItem2_iface;
39 LONG ref;
40 LPITEMIDLIST pidl;
41 IPersistIDList IPersistIDList_iface;
42 IShellItemImageFactory IShellItemImageFactory_iface;
43 } ShellItem;
45 typedef struct _CustomDestinationList {
46 ICustomDestinationList ICustomDestinationList_iface;
47 LONG ref;
48 } CustomDestinationList;
50 static inline ShellItem *impl_from_IShellItem2(IShellItem2 *iface)
52 return CONTAINING_RECORD(iface, ShellItem, IShellItem2_iface);
55 static inline ShellItem *impl_from_IPersistIDList( IPersistIDList *iface )
57 return CONTAINING_RECORD(iface, ShellItem, IPersistIDList_iface);
60 static inline ShellItem *impl_from_IShellItemImageFactory( IShellItemImageFactory *iface )
62 return CONTAINING_RECORD(iface, ShellItem, IShellItemImageFactory_iface);
65 static inline CustomDestinationList *impl_from_ICustomDestinationList( ICustomDestinationList *iface )
67 return CONTAINING_RECORD(iface, CustomDestinationList, ICustomDestinationList_iface);
70 static HRESULT WINAPI ShellItem_QueryInterface(IShellItem2 *iface, REFIID riid,
71 void **ppv)
73 ShellItem *This = impl_from_IShellItem2(iface);
75 TRACE("(%p, %s, %p)\n", iface, debugstr_guid(riid), ppv);
77 if (!ppv) return E_INVALIDARG;
79 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IShellItem, riid) ||
80 IsEqualIID(&IID_IShellItem2, riid))
82 *ppv = &This->IShellItem2_iface;
84 else if (IsEqualIID(&IID_IPersist, riid) || IsEqualIID(&IID_IPersistIDList, riid))
86 *ppv = &This->IPersistIDList_iface;
88 else if (IsEqualIID(&IID_IShellItemImageFactory, riid))
90 *ppv = &This->IShellItemImageFactory_iface;
92 else {
93 FIXME("not implemented for %s\n", shdebugstr_guid(riid));
94 *ppv = NULL;
95 return E_NOINTERFACE;
98 IUnknown_AddRef((IUnknown*)*ppv);
99 return S_OK;
102 static ULONG WINAPI ShellItem_AddRef(IShellItem2 *iface)
104 ShellItem *This = impl_from_IShellItem2(iface);
105 ULONG ref = InterlockedIncrement(&This->ref);
107 TRACE("(%p), new refcount=%li\n", iface, ref);
109 return ref;
112 static ULONG WINAPI ShellItem_Release(IShellItem2 *iface)
114 ShellItem *This = impl_from_IShellItem2(iface);
115 ULONG ref = InterlockedDecrement(&This->ref);
117 TRACE("(%p), new refcount=%li\n", iface, ref);
119 if (ref == 0)
121 ILFree(This->pidl);
122 heap_free(This);
125 return ref;
128 static HRESULT ShellItem_get_parent_pidl(ShellItem *This, LPITEMIDLIST *parent_pidl)
130 *parent_pidl = ILClone(This->pidl);
131 if (*parent_pidl)
133 if (ILRemoveLastID(*parent_pidl))
134 return S_OK;
135 else
137 ILFree(*parent_pidl);
138 *parent_pidl = NULL;
139 return E_INVALIDARG;
142 else
144 *parent_pidl = NULL;
145 return E_OUTOFMEMORY;
149 static HRESULT ShellItem_get_parent_shellfolder(ShellItem *This, IShellFolder **ppsf)
151 LPITEMIDLIST parent_pidl;
152 IShellFolder *desktop;
153 HRESULT ret;
155 ret = ShellItem_get_parent_pidl(This, &parent_pidl);
156 if (SUCCEEDED(ret))
158 ret = SHGetDesktopFolder(&desktop);
159 if (SUCCEEDED(ret))
161 if (_ILIsDesktop(parent_pidl))
163 *ppsf = desktop;
165 else
167 ret = IShellFolder_BindToObject(desktop, parent_pidl, NULL, &IID_IShellFolder, (void**)ppsf);
168 IShellFolder_Release(desktop);
171 ILFree(parent_pidl);
174 return ret;
177 static HRESULT ShellItem_get_shellfolder(ShellItem *This, IBindCtx *pbc, IShellFolder **ppsf)
179 IShellFolder *desktop;
180 HRESULT ret;
182 ret = SHGetDesktopFolder(&desktop);
183 if (SUCCEEDED(ret))
185 if (_ILIsDesktop(This->pidl))
187 *ppsf = desktop;
188 IShellFolder_AddRef(*ppsf);
190 else
192 ret = IShellFolder_BindToObject(desktop, This->pidl, pbc, &IID_IShellFolder, (void**)ppsf);
195 IShellFolder_Release(desktop);
198 return ret;
201 static HRESULT WINAPI ShellItem_BindToHandler(IShellItem2 *iface, IBindCtx *pbc,
202 REFGUID rbhid, REFIID riid, void **ppvOut)
204 ShellItem *This = impl_from_IShellItem2(iface);
205 HRESULT ret;
206 TRACE("(%p,%p,%s,%p,%p)\n", iface, pbc, shdebugstr_guid(rbhid), riid, ppvOut);
208 *ppvOut = NULL;
209 if (IsEqualGUID(rbhid, &BHID_SFObject))
211 IShellFolder *psf;
212 ret = ShellItem_get_shellfolder(This, pbc, &psf);
213 if (SUCCEEDED(ret))
215 ret = IShellFolder_QueryInterface(psf, riid, ppvOut);
216 IShellFolder_Release(psf);
218 return ret;
220 else if (IsEqualGUID(rbhid, &BHID_SFUIObject))
222 IShellFolder *psf_parent;
223 if (_ILIsDesktop(This->pidl))
224 ret = SHGetDesktopFolder(&psf_parent);
225 else
226 ret = ShellItem_get_parent_shellfolder(This, &psf_parent);
228 if (SUCCEEDED(ret))
230 LPCITEMIDLIST pidl = ILFindLastID(This->pidl);
231 ret = IShellFolder_GetUIObjectOf(psf_parent, NULL, 1, &pidl, riid, NULL, ppvOut);
232 IShellFolder_Release(psf_parent);
234 return ret;
236 else if (IsEqualGUID(rbhid, &BHID_DataObject))
238 return ShellItem_BindToHandler(&This->IShellItem2_iface, pbc, &BHID_SFUIObject,
239 &IID_IDataObject, ppvOut);
242 FIXME("Unsupported BHID %s.\n", debugstr_guid(rbhid));
244 return MK_E_NOOBJECT;
247 static HRESULT WINAPI ShellItem_GetParent(IShellItem2 *iface, IShellItem **ppsi)
249 ShellItem *This = impl_from_IShellItem2(iface);
250 LPITEMIDLIST parent_pidl;
251 HRESULT ret;
253 TRACE("(%p,%p)\n", iface, ppsi);
255 ret = ShellItem_get_parent_pidl(This, &parent_pidl);
256 if (SUCCEEDED(ret))
258 ret = SHCreateShellItem(NULL, NULL, parent_pidl, ppsi);
259 ILFree(parent_pidl);
262 return ret;
265 static HRESULT WINAPI ShellItem_GetDisplayName(IShellItem2 *iface, SIGDN sigdnName,
266 LPWSTR *ppszName)
268 ShellItem *This = impl_from_IShellItem2(iface);
269 TRACE("(%p,%x,%p)\n", iface, sigdnName, ppszName);
271 return SHGetNameFromIDList(This->pidl, sigdnName, ppszName);
274 static HRESULT WINAPI ShellItem_GetAttributes(IShellItem2 *iface, SFGAOF sfgaoMask,
275 SFGAOF *psfgaoAttribs)
277 ShellItem *This = impl_from_IShellItem2(iface);
278 IShellFolder *parent_folder;
279 LPITEMIDLIST child_pidl;
280 HRESULT ret;
282 TRACE("(%p,%lx,%p)\n", iface, sfgaoMask, psfgaoAttribs);
284 if (_ILIsDesktop(This->pidl))
285 ret = SHGetDesktopFolder(&parent_folder);
286 else
287 ret = ShellItem_get_parent_shellfolder(This, &parent_folder);
288 if (SUCCEEDED(ret))
290 child_pidl = ILFindLastID(This->pidl);
291 *psfgaoAttribs = sfgaoMask;
292 ret = IShellFolder_GetAttributesOf(parent_folder, 1, (LPCITEMIDLIST*)&child_pidl, psfgaoAttribs);
293 *psfgaoAttribs &= sfgaoMask;
294 IShellFolder_Release(parent_folder);
296 if (SUCCEEDED(ret))
298 if(sfgaoMask == *psfgaoAttribs)
299 return S_OK;
300 else
301 return S_FALSE;
305 return ret;
308 static HRESULT WINAPI ShellItem_Compare(IShellItem2 *iface, IShellItem *oth,
309 SICHINTF hint, int *piOrder)
311 LPWSTR dispname, dispname_oth;
312 HRESULT ret;
313 TRACE("(%p,%p,%lx,%p)\n", iface, oth, hint, piOrder);
315 if(hint & (SICHINT_CANONICAL | SICHINT_ALLFIELDS))
316 FIXME("Unsupported flags 0x%08lx\n", hint);
318 ret = IShellItem2_GetDisplayName(iface, SIGDN_DESKTOPABSOLUTEEDITING, &dispname);
319 if(SUCCEEDED(ret))
321 ret = IShellItem_GetDisplayName(oth, SIGDN_DESKTOPABSOLUTEEDITING, &dispname_oth);
322 if(SUCCEEDED(ret))
324 *piOrder = lstrcmpiW(dispname, dispname_oth);
325 CoTaskMemFree(dispname_oth);
327 CoTaskMemFree(dispname);
330 if(SUCCEEDED(ret) && *piOrder &&
331 (hint & SICHINT_TEST_FILESYSPATH_IF_NOT_EQUAL))
333 LPWSTR dispname, dispname_oth;
335 TRACE("Testing filesystem path.\n");
336 ret = IShellItem2_GetDisplayName(iface, SIGDN_FILESYSPATH, &dispname);
337 if(SUCCEEDED(ret))
339 ret = IShellItem_GetDisplayName(oth, SIGDN_FILESYSPATH, &dispname_oth);
340 if(SUCCEEDED(ret))
342 *piOrder = lstrcmpiW(dispname, dispname_oth);
343 CoTaskMemFree(dispname_oth);
345 CoTaskMemFree(dispname);
349 if(FAILED(ret))
350 return ret;
352 if(*piOrder)
353 return S_FALSE;
354 else
355 return S_OK;
358 static HRESULT WINAPI ShellItem2_GetPropertyStore(IShellItem2 *iface, GETPROPERTYSTOREFLAGS flags,
359 REFIID riid, void **ppv)
361 ShellItem *This = impl_from_IShellItem2(iface);
362 FIXME("Stub: %p (%d, %s, %p)\n", This, flags, shdebugstr_guid(riid), ppv);
363 return E_NOTIMPL;
366 static HRESULT WINAPI ShellItem2_GetPropertyStoreWithCreateObject(IShellItem2 *iface,
367 GETPROPERTYSTOREFLAGS flags, IUnknown *punkCreateObject, REFIID riid, void **ppv)
369 ShellItem *This = impl_from_IShellItem2(iface);
370 FIXME("Stub: %p (%08x, %p, %s, %p)\n",
371 This, flags, punkCreateObject, shdebugstr_guid(riid), ppv);
372 return E_NOTIMPL;
375 static HRESULT WINAPI ShellItem2_GetPropertyStoreForKeys(IShellItem2 *iface, const PROPERTYKEY *rgKeys,
376 UINT cKeys, GETPROPERTYSTOREFLAGS flags, REFIID riid, void **ppv)
378 ShellItem *This = impl_from_IShellItem2(iface);
379 FIXME("Stub: %p (%p, %d, %08x, %s, %p)\n",
380 This, rgKeys, cKeys, flags, shdebugstr_guid(riid), ppv);
381 return E_NOTIMPL;
384 static HRESULT WINAPI ShellItem2_GetPropertyDescriptionList(IShellItem2 *iface,
385 REFPROPERTYKEY keyType, REFIID riid, void **ppv)
387 ShellItem *This = impl_from_IShellItem2(iface);
388 FIXME("Stub: %p (%p, %s, %p)\n", This, keyType, debugstr_guid(riid), ppv);
389 return E_NOTIMPL;
392 static HRESULT WINAPI ShellItem2_Update(IShellItem2 *iface, IBindCtx *pbc)
394 ShellItem *This = impl_from_IShellItem2(iface);
395 FIXME("Stub: %p (%p)\n", This, pbc);
396 return E_NOTIMPL;
399 static HRESULT WINAPI ShellItem2_GetProperty(IShellItem2 *iface, REFPROPERTYKEY key, PROPVARIANT *ppropvar)
401 ShellItem *This = impl_from_IShellItem2(iface);
402 FIXME("Stub: %p (%p, %p)\n", This, key, ppropvar);
403 return E_NOTIMPL;
406 static HRESULT WINAPI ShellItem2_GetCLSID(IShellItem2 *iface, REFPROPERTYKEY key, CLSID *pclsid)
408 ShellItem *This = impl_from_IShellItem2(iface);
409 FIXME("Stub: %p (%p, %p)\n", This, key, pclsid);
410 return E_NOTIMPL;
413 static HRESULT WINAPI ShellItem2_GetFileTime(IShellItem2 *iface, REFPROPERTYKEY key, FILETIME *pft)
415 ShellItem *This = impl_from_IShellItem2(iface);
416 FIXME("Stub: %p (%p, %p)\n", This, key, pft);
417 return E_NOTIMPL;
420 static HRESULT WINAPI ShellItem2_GetInt32(IShellItem2 *iface, REFPROPERTYKEY key, int *pi)
422 ShellItem *This = impl_from_IShellItem2(iface);
423 FIXME("Stub: %p (%p, %p)\n", This, key, pi);
424 return E_NOTIMPL;
427 static HRESULT WINAPI ShellItem2_GetString(IShellItem2 *iface, REFPROPERTYKEY key, LPWSTR *ppsz)
429 ShellItem *This = impl_from_IShellItem2(iface);
430 FIXME("Stub: %p (%p, %p)\n", This, key, ppsz);
431 return E_NOTIMPL;
434 static HRESULT WINAPI ShellItem2_GetUInt32(IShellItem2 *iface, REFPROPERTYKEY key, ULONG *pui)
436 ShellItem *This = impl_from_IShellItem2(iface);
437 FIXME("Stub: %p (%p, %p)\n", This, key, pui);
438 return E_NOTIMPL;
441 static HRESULT WINAPI ShellItem2_GetUInt64(IShellItem2 *iface, REFPROPERTYKEY key, ULONGLONG *pull)
443 ShellItem *This = impl_from_IShellItem2(iface);
444 FIXME("Stub: %p (%p, %p)\n", This, key, pull);
445 return E_NOTIMPL;
448 static HRESULT WINAPI ShellItem2_GetBool(IShellItem2 *iface, REFPROPERTYKEY key, BOOL *pf)
450 ShellItem *This = impl_from_IShellItem2(iface);
451 FIXME("Stub: %p (%p, %p)\n", This, key, pf);
452 return E_NOTIMPL;
456 static const IShellItem2Vtbl ShellItem2_Vtbl = {
457 ShellItem_QueryInterface,
458 ShellItem_AddRef,
459 ShellItem_Release,
460 ShellItem_BindToHandler,
461 ShellItem_GetParent,
462 ShellItem_GetDisplayName,
463 ShellItem_GetAttributes,
464 ShellItem_Compare,
465 ShellItem2_GetPropertyStore,
466 ShellItem2_GetPropertyStoreWithCreateObject,
467 ShellItem2_GetPropertyStoreForKeys,
468 ShellItem2_GetPropertyDescriptionList,
469 ShellItem2_Update,
470 ShellItem2_GetProperty,
471 ShellItem2_GetCLSID,
472 ShellItem2_GetFileTime,
473 ShellItem2_GetInt32,
474 ShellItem2_GetString,
475 ShellItem2_GetUInt32,
476 ShellItem2_GetUInt64,
477 ShellItem2_GetBool
480 static HRESULT WINAPI ShellItem_IPersistIDList_QueryInterface(IPersistIDList *iface,
481 REFIID riid, void **ppv)
483 ShellItem *This = impl_from_IPersistIDList(iface);
484 return IShellItem2_QueryInterface(&This->IShellItem2_iface, riid, ppv);
487 static ULONG WINAPI ShellItem_IPersistIDList_AddRef(IPersistIDList *iface)
489 ShellItem *This = impl_from_IPersistIDList(iface);
490 return IShellItem2_AddRef(&This->IShellItem2_iface);
493 static ULONG WINAPI ShellItem_IPersistIDList_Release(IPersistIDList *iface)
495 ShellItem *This = impl_from_IPersistIDList(iface);
496 return IShellItem2_Release(&This->IShellItem2_iface);
499 static HRESULT WINAPI ShellItem_IPersistIDList_GetClassID(IPersistIDList* iface,
500 CLSID *pClassID)
502 *pClassID = CLSID_ShellItem;
503 return S_OK;
506 static HRESULT WINAPI ShellItem_IPersistIDList_SetIDList(IPersistIDList* iface,
507 LPCITEMIDLIST pidl)
509 ShellItem *This = impl_from_IPersistIDList(iface);
510 LPITEMIDLIST new_pidl;
512 TRACE("(%p,%p)\n", This, pidl);
514 new_pidl = ILClone(pidl);
516 if (new_pidl)
518 ILFree(This->pidl);
519 This->pidl = new_pidl;
520 return S_OK;
522 else
523 return E_OUTOFMEMORY;
526 static HRESULT WINAPI ShellItem_IPersistIDList_GetIDList(IPersistIDList* iface,
527 LPITEMIDLIST *ppidl)
529 ShellItem *This = impl_from_IPersistIDList(iface);
531 TRACE("(%p,%p)\n", This, ppidl);
533 *ppidl = ILClone(This->pidl);
534 if (*ppidl)
535 return S_OK;
536 else
537 return E_OUTOFMEMORY;
540 static const IPersistIDListVtbl ShellItem_IPersistIDList_Vtbl = {
541 ShellItem_IPersistIDList_QueryInterface,
542 ShellItem_IPersistIDList_AddRef,
543 ShellItem_IPersistIDList_Release,
544 ShellItem_IPersistIDList_GetClassID,
545 ShellItem_IPersistIDList_SetIDList,
546 ShellItem_IPersistIDList_GetIDList
549 static HRESULT WINAPI ShellItem_IShellItemImageFactory_QueryInterface(IShellItemImageFactory *iface,
550 REFIID riid, void **ppv)
552 ShellItem *This = impl_from_IShellItemImageFactory(iface);
553 return IShellItem2_QueryInterface(&This->IShellItem2_iface, riid, ppv);
556 static ULONG WINAPI ShellItem_IShellItemImageFactory_AddRef(IShellItemImageFactory *iface)
558 ShellItem *This = impl_from_IShellItemImageFactory(iface);
559 return IShellItem2_AddRef(&This->IShellItem2_iface);
562 static ULONG WINAPI ShellItem_IShellItemImageFactory_Release(IShellItemImageFactory *iface)
564 ShellItem *This = impl_from_IShellItemImageFactory(iface);
565 return IShellItem2_Release(&This->IShellItem2_iface);
568 static HRESULT WINAPI ShellItem_IShellItemImageFactory_GetImage(IShellItemImageFactory *iface,
569 SIZE size, SIIGBF flags, HBITMAP *phbm)
571 ShellItem *This = impl_from_IShellItemImageFactory(iface);
572 static const BITMAPINFOHEADER dummy_bmi_header = {
573 .biSize = sizeof(dummy_bmi_header),
574 .biWidth = 1,
575 .biHeight = 1,
576 .biPlanes = 1,
577 .biBitCount = 32,
578 .biCompression = BI_RGB
580 static int once;
582 if (!once++)
583 FIXME("%p ({%lu, %lu} %d %p): stub\n", This, size.cx, size.cy, flags, phbm);
585 if (!(*phbm = CreateDIBSection(NULL, (const BITMAPINFO *)&dummy_bmi_header,
586 DIB_RGB_COLORS, NULL, NULL, 0)))
588 return E_OUTOFMEMORY;
591 return S_OK;
594 static const IShellItemImageFactoryVtbl ShellItem_IShellItemImageFactory_Vtbl = {
595 ShellItem_IShellItemImageFactory_QueryInterface,
596 ShellItem_IShellItemImageFactory_AddRef,
597 ShellItem_IShellItemImageFactory_Release,
598 ShellItem_IShellItemImageFactory_GetImage,
602 HRESULT WINAPI IShellItem_Constructor(IUnknown *pUnkOuter, REFIID riid, void **ppv)
604 ShellItem *This;
605 HRESULT ret;
607 TRACE("(%p,%s)\n",pUnkOuter, debugstr_guid(riid));
609 *ppv = NULL;
611 if (pUnkOuter) return CLASS_E_NOAGGREGATION;
613 This = heap_alloc(sizeof(*This));
614 This->IShellItem2_iface.lpVtbl = &ShellItem2_Vtbl;
615 This->ref = 1;
616 This->pidl = NULL;
617 This->IPersistIDList_iface.lpVtbl = &ShellItem_IPersistIDList_Vtbl;
618 This->IShellItemImageFactory_iface.lpVtbl = &ShellItem_IShellItemImageFactory_Vtbl;
620 ret = IShellItem2_QueryInterface(&This->IShellItem2_iface, riid, ppv);
621 IShellItem2_Release(&This->IShellItem2_iface);
623 return ret;
626 HRESULT WINAPI SHCreateShellItem(LPCITEMIDLIST pidlParent,
627 IShellFolder *psfParent, LPCITEMIDLIST pidl, IShellItem **ppsi)
629 LPITEMIDLIST new_pidl;
630 HRESULT ret;
632 TRACE("(%p,%p,%p,%p)\n", pidlParent, psfParent, pidl, ppsi);
634 *ppsi = NULL;
636 if (!pidl)
638 return E_INVALIDARG;
640 else if (pidlParent || psfParent)
642 LPITEMIDLIST temp_parent=NULL;
643 if (!pidlParent)
645 IPersistFolder2* ppf2Parent;
647 if (FAILED(IShellFolder_QueryInterface(psfParent, &IID_IPersistFolder2, (void**)&ppf2Parent)))
649 FIXME("couldn't get IPersistFolder2 interface of parent\n");
650 return E_NOINTERFACE;
653 if (FAILED(IPersistFolder2_GetCurFolder(ppf2Parent, &temp_parent)))
655 FIXME("couldn't get parent PIDL\n");
656 IPersistFolder2_Release(ppf2Parent);
657 return E_NOINTERFACE;
660 pidlParent = temp_parent;
661 IPersistFolder2_Release(ppf2Parent);
664 new_pidl = ILCombine(pidlParent, pidl);
665 ILFree(temp_parent);
667 if (!new_pidl)
668 return E_OUTOFMEMORY;
670 else
672 new_pidl = ILClone(pidl);
673 if (!new_pidl)
674 return E_OUTOFMEMORY;
677 ret = SHCreateItemFromIDList(new_pidl, &IID_IShellItem, (void**)ppsi);
678 ILFree(new_pidl);
680 return ret;
683 HRESULT WINAPI SHCreateItemFromParsingName(PCWSTR pszPath,
684 IBindCtx *pbc, REFIID riid, void **ppv)
686 LPITEMIDLIST pidl;
687 HRESULT ret;
689 *ppv = NULL;
691 ret = SHParseDisplayName(pszPath, pbc, &pidl, 0, NULL);
692 if(SUCCEEDED(ret))
694 ret = SHCreateItemFromIDList(pidl, riid, ppv);
695 ILFree(pidl);
697 return ret;
700 HRESULT WINAPI SHCreateItemFromRelativeName(IShellItem *parent, PCWSTR name, IBindCtx *pbc,
701 REFIID riid, void **ppv)
703 LPITEMIDLIST pidl_folder = NULL, pidl = NULL;
704 IShellFolder *desktop = NULL, *folder = NULL;
705 HRESULT hr;
707 TRACE("(%p, %s, %p, %s, %p)\n", parent, wine_dbgstr_w(name), pbc, debugstr_guid(riid), ppv);
709 if(!ppv)
710 return E_INVALIDARG;
711 *ppv = NULL;
712 if(!name)
713 return E_INVALIDARG;
715 hr = SHGetIDListFromObject((IUnknown*)parent, &pidl_folder);
716 if(hr != S_OK)
717 return hr;
719 hr = SHGetDesktopFolder(&desktop);
720 if(hr != S_OK)
721 goto cleanup;
723 if(!_ILIsDesktop(pidl_folder))
725 hr = IShellFolder_BindToObject(desktop, pidl_folder, NULL, &IID_IShellFolder,
726 (void**)&folder);
727 if(hr != S_OK)
728 goto cleanup;
731 hr = IShellFolder_ParseDisplayName(folder ? folder : desktop, NULL, pbc, (LPWSTR)name,
732 NULL, &pidl, NULL);
733 if(hr != S_OK)
734 goto cleanup;
735 hr = SHCreateItemFromIDList(pidl, riid, ppv);
737 cleanup:
738 if(pidl_folder)
739 ILFree(pidl_folder);
740 if(pidl)
741 ILFree(pidl);
742 if(desktop)
743 IShellFolder_Release(desktop);
744 if(folder)
745 IShellFolder_Release(folder);
746 return hr;
749 HRESULT WINAPI SHCreateItemFromIDList(PCIDLIST_ABSOLUTE pidl, REFIID riid, void **ppv)
751 IPersistIDList *persist;
752 HRESULT ret;
754 if(!pidl)
755 return E_INVALIDARG;
757 *ppv = NULL;
758 ret = IShellItem_Constructor(NULL, &IID_IPersistIDList, (void**)&persist);
759 if(FAILED(ret))
760 return ret;
762 ret = IPersistIDList_SetIDList(persist, pidl);
763 if(FAILED(ret))
765 IPersistIDList_Release(persist);
766 return ret;
769 ret = IPersistIDList_QueryInterface(persist, riid, ppv);
770 IPersistIDList_Release(persist);
771 return ret;
774 HRESULT WINAPI SHCreateItemInKnownFolder(REFKNOWNFOLDERID rfid, DWORD flags,
775 PCWSTR filename, REFIID riid, void **ppv)
777 HRESULT hr;
778 IShellItem *parent = NULL;
779 LPITEMIDLIST pidl = NULL;
781 TRACE("(%p, %lx, %s, %s, %p)\n", rfid, flags, wine_dbgstr_w(filename),
782 debugstr_guid(riid), ppv);
784 if(!rfid || !ppv)
785 return E_INVALIDARG;
787 *ppv = NULL;
788 hr = SHGetKnownFolderIDList(rfid, flags, NULL, &pidl);
789 if(hr != S_OK)
790 return hr;
792 hr = SHCreateItemFromIDList(pidl, &IID_IShellItem, (void**)&parent);
793 if(hr != S_OK)
795 ILFree(pidl);
796 return hr;
799 if(filename)
800 hr = SHCreateItemFromRelativeName(parent, filename, NULL, riid, ppv);
801 else
802 hr = IShellItem_QueryInterface(parent, riid, ppv);
804 ILFree(pidl);
805 IShellItem_Release(parent);
806 return hr;
809 HRESULT WINAPI SHGetItemFromDataObject(IDataObject *pdtobj,
810 DATAOBJ_GET_ITEM_FLAGS dwFlags, REFIID riid, void **ppv)
812 FORMATETC fmt;
813 STGMEDIUM medium;
814 HRESULT ret;
816 TRACE("%p, %x, %s, %p\n", pdtobj, dwFlags, debugstr_guid(riid), ppv);
818 if(!pdtobj)
819 return E_INVALIDARG;
821 fmt.cfFormat = RegisterClipboardFormatW(CFSTR_SHELLIDLISTW);
822 fmt.ptd = NULL;
823 fmt.dwAspect = DVASPECT_CONTENT;
824 fmt.lindex = -1;
825 fmt.tymed = TYMED_HGLOBAL;
827 ret = IDataObject_GetData(pdtobj, &fmt, &medium);
828 if(SUCCEEDED(ret))
830 LPIDA pida = GlobalLock(medium.u.hGlobal);
832 if((pida->cidl > 1 && !(dwFlags & DOGIF_ONLY_IF_ONE)) ||
833 pida->cidl == 1)
835 LPITEMIDLIST pidl;
837 /* Get the first pidl (parent + child1) */
838 pidl = ILCombine((LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[0]),
839 (LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[1]));
841 ret = SHCreateItemFromIDList(pidl, riid, ppv);
842 ILFree(pidl);
844 else
846 ret = E_FAIL;
849 GlobalUnlock(medium.u.hGlobal);
850 GlobalFree(medium.u.hGlobal);
853 if(FAILED(ret) && !(dwFlags & DOGIF_NO_HDROP))
855 TRACE("Attempting to fall back on CF_HDROP.\n");
857 fmt.cfFormat = CF_HDROP;
858 fmt.ptd = NULL;
859 fmt.dwAspect = DVASPECT_CONTENT;
860 fmt.lindex = -1;
861 fmt.tymed = TYMED_HGLOBAL;
863 ret = IDataObject_GetData(pdtobj, &fmt, &medium);
864 if(SUCCEEDED(ret))
866 DROPFILES *df = GlobalLock(medium.u.hGlobal);
867 LPBYTE files = (LPBYTE)df + df->pFiles;
868 BOOL multiple_files = FALSE;
870 ret = E_FAIL;
871 if(!df->fWide)
873 WCHAR filename[MAX_PATH];
874 PCSTR first_file = (PCSTR)files;
875 if(*(files + lstrlenA(first_file) + 1) != 0)
876 multiple_files = TRUE;
878 if( !(multiple_files && (dwFlags & DOGIF_ONLY_IF_ONE)) )
880 MultiByteToWideChar(CP_ACP, 0, first_file, -1, filename, MAX_PATH);
881 ret = SHCreateItemFromParsingName(filename, NULL, riid, ppv);
884 else
886 PCWSTR first_file = (PCWSTR)files;
887 if(*((PCWSTR)files + lstrlenW(first_file) + 1) != 0)
888 multiple_files = TRUE;
890 if( !(multiple_files && (dwFlags & DOGIF_ONLY_IF_ONE)) )
891 ret = SHCreateItemFromParsingName(first_file, NULL, riid, ppv);
894 GlobalUnlock(medium.u.hGlobal);
895 GlobalFree(medium.u.hGlobal);
899 if(FAILED(ret) && !(dwFlags & DOGIF_NO_URL))
901 FIXME("Failed to create item, should try CF_URL.\n");
904 return ret;
907 HRESULT WINAPI SHGetItemFromObject(IUnknown *punk, REFIID riid, void **ppv)
909 LPITEMIDLIST pidl;
910 HRESULT ret;
912 ret = SHGetIDListFromObject(punk, &pidl);
913 if(SUCCEEDED(ret))
915 ret = SHCreateItemFromIDList(pidl, riid, ppv);
916 ILFree(pidl);
919 return ret;
922 /*************************************************************************
923 * IEnumShellItems implementation
925 typedef struct {
926 IEnumShellItems IEnumShellItems_iface;
927 LONG ref;
929 IShellItemArray *array;
930 DWORD count;
931 DWORD position;
932 } IEnumShellItemsImpl;
934 static inline IEnumShellItemsImpl *impl_from_IEnumShellItems(IEnumShellItems *iface)
936 return CONTAINING_RECORD(iface, IEnumShellItemsImpl, IEnumShellItems_iface);
939 static HRESULT WINAPI IEnumShellItems_fnQueryInterface(IEnumShellItems *iface,
940 REFIID riid,
941 void **ppvObject)
943 IEnumShellItemsImpl *This = impl_from_IEnumShellItems(iface);
944 TRACE("%p (%s, %p)\n", This, shdebugstr_guid(riid), ppvObject);
946 *ppvObject = NULL;
947 if(IsEqualIID(riid, &IID_IEnumShellItems) ||
948 IsEqualIID(riid, &IID_IUnknown))
950 *ppvObject = &This->IEnumShellItems_iface;
953 if(*ppvObject)
955 IUnknown_AddRef((IUnknown*)*ppvObject);
956 return S_OK;
959 return E_NOINTERFACE;
962 static ULONG WINAPI IEnumShellItems_fnAddRef(IEnumShellItems *iface)
964 IEnumShellItemsImpl *This = impl_from_IEnumShellItems(iface);
965 LONG ref = InterlockedIncrement(&This->ref);
966 TRACE("%p - ref %ld\n", This, ref);
968 return ref;
971 static ULONG WINAPI IEnumShellItems_fnRelease(IEnumShellItems *iface)
973 IEnumShellItemsImpl *This = impl_from_IEnumShellItems(iface);
974 LONG ref = InterlockedDecrement(&This->ref);
975 TRACE("%p - ref %ld\n", This, ref);
977 if(!ref)
979 TRACE("Freeing.\n");
980 IShellItemArray_Release(This->array);
981 heap_free(This);
982 return 0;
985 return ref;
988 static HRESULT WINAPI IEnumShellItems_fnNext(IEnumShellItems* iface,
989 ULONG celt,
990 IShellItem **rgelt,
991 ULONG *pceltFetched)
993 IEnumShellItemsImpl *This = impl_from_IEnumShellItems(iface);
994 HRESULT hr = S_FALSE;
995 UINT i;
996 ULONG fetched = 0;
997 TRACE("%p (%ld %p %p)\n", This, celt, rgelt, pceltFetched);
999 if(pceltFetched == NULL && celt != 1)
1000 return E_INVALIDARG;
1002 for(i = This->position; fetched < celt && i < This->count; i++) {
1003 hr = IShellItemArray_GetItemAt(This->array, i, &rgelt[fetched]);
1004 if(FAILED(hr))
1005 break;
1006 fetched++;
1007 This->position++;
1010 if(SUCCEEDED(hr))
1012 if(pceltFetched != NULL)
1013 *pceltFetched = fetched;
1015 if(fetched > 0)
1016 return S_OK;
1018 return S_FALSE;
1021 return hr;
1024 static HRESULT WINAPI IEnumShellItems_fnSkip(IEnumShellItems* iface, ULONG celt)
1026 IEnumShellItemsImpl *This = impl_from_IEnumShellItems(iface);
1027 TRACE("%p (%ld)\n", This, celt);
1029 This->position = min(This->position + celt, This->count-1);
1031 return S_OK;
1034 static HRESULT WINAPI IEnumShellItems_fnReset(IEnumShellItems* iface)
1036 IEnumShellItemsImpl *This = impl_from_IEnumShellItems(iface);
1037 TRACE("%p\n", This);
1039 This->position = 0;
1041 return S_OK;
1044 static HRESULT WINAPI IEnumShellItems_fnClone(IEnumShellItems* iface, IEnumShellItems **ppenum)
1046 IEnumShellItemsImpl *This = impl_from_IEnumShellItems(iface);
1047 TRACE("%p (%p)\n", This, ppenum);
1049 /* Not implemented anywhere */
1050 *ppenum = NULL;
1052 return E_NOTIMPL;
1055 static const IEnumShellItemsVtbl vt_IEnumShellItems = {
1056 IEnumShellItems_fnQueryInterface,
1057 IEnumShellItems_fnAddRef,
1058 IEnumShellItems_fnRelease,
1059 IEnumShellItems_fnNext,
1060 IEnumShellItems_fnSkip,
1061 IEnumShellItems_fnReset,
1062 IEnumShellItems_fnClone
1065 static HRESULT IEnumShellItems_Constructor(IShellItemArray *array, IEnumShellItems **ppesi)
1067 IEnumShellItemsImpl *This;
1068 HRESULT ret;
1070 This = heap_alloc(sizeof(*This));
1071 if(!This)
1072 return E_OUTOFMEMORY;
1074 This->ref = 1;
1075 This->IEnumShellItems_iface.lpVtbl = &vt_IEnumShellItems;
1076 This->array = array;
1077 This->position = 0;
1079 IShellItemArray_AddRef(This->array);
1080 IShellItemArray_GetCount(This->array, &This->count);
1082 ret = IEnumShellItems_QueryInterface(&This->IEnumShellItems_iface, &IID_IEnumShellItems, (void**)ppesi);
1083 IEnumShellItems_Release(&This->IEnumShellItems_iface);
1085 return ret;
1089 /*************************************************************************
1090 * IShellItemArray implementation
1092 typedef struct {
1093 IShellItemArray IShellItemArray_iface;
1094 LONG ref;
1096 IShellItem **array;
1097 DWORD item_count;
1098 } IShellItemArrayImpl;
1100 static inline IShellItemArrayImpl *impl_from_IShellItemArray(IShellItemArray *iface)
1102 return CONTAINING_RECORD(iface, IShellItemArrayImpl, IShellItemArray_iface);
1105 static HRESULT WINAPI IShellItemArray_fnQueryInterface(IShellItemArray *iface,
1106 REFIID riid,
1107 void **ppvObject)
1109 IShellItemArrayImpl *This = impl_from_IShellItemArray(iface);
1110 TRACE("%p (%s, %p)\n", This, shdebugstr_guid(riid), ppvObject);
1112 *ppvObject = NULL;
1113 if(IsEqualIID(riid, &IID_IShellItemArray) ||
1114 IsEqualIID(riid, &IID_IUnknown))
1116 *ppvObject = &This->IShellItemArray_iface;
1119 if(*ppvObject)
1121 IUnknown_AddRef((IUnknown*)*ppvObject);
1122 return S_OK;
1125 return E_NOINTERFACE;
1128 static ULONG WINAPI IShellItemArray_fnAddRef(IShellItemArray *iface)
1130 IShellItemArrayImpl *This = impl_from_IShellItemArray(iface);
1131 LONG ref = InterlockedIncrement(&This->ref);
1132 TRACE("%p - ref %ld\n", This, ref);
1134 return ref;
1137 static ULONG WINAPI IShellItemArray_fnRelease(IShellItemArray *iface)
1139 IShellItemArrayImpl *This = impl_from_IShellItemArray(iface);
1140 LONG ref = InterlockedDecrement(&This->ref);
1141 TRACE("%p - ref %ld\n", This, ref);
1143 if(!ref)
1145 UINT i;
1146 TRACE("Freeing.\n");
1148 for(i = 0; i < This->item_count; i++)
1149 IShellItem_Release(This->array[i]);
1151 heap_free(This->array);
1152 heap_free(This);
1153 return 0;
1156 return ref;
1159 static HRESULT WINAPI IShellItemArray_fnBindToHandler(IShellItemArray *iface,
1160 IBindCtx *pbc,
1161 REFGUID bhid,
1162 REFIID riid,
1163 void **ppvOut)
1165 IShellItemArrayImpl *This = impl_from_IShellItemArray(iface);
1166 FIXME("Stub: %p (%p, %s, %s, %p)\n",
1167 This, pbc, shdebugstr_guid(bhid), shdebugstr_guid(riid), ppvOut);
1169 return E_NOTIMPL;
1172 static HRESULT WINAPI IShellItemArray_fnGetPropertyStore(IShellItemArray *iface,
1173 GETPROPERTYSTOREFLAGS flags,
1174 REFIID riid,
1175 void **ppv)
1177 IShellItemArrayImpl *This = impl_from_IShellItemArray(iface);
1178 FIXME("Stub: %p (%x, %s, %p)\n", This, flags, shdebugstr_guid(riid), ppv);
1180 return E_NOTIMPL;
1183 static HRESULT WINAPI IShellItemArray_fnGetPropertyDescriptionList(IShellItemArray *iface,
1184 REFPROPERTYKEY keyType,
1185 REFIID riid,
1186 void **ppv)
1188 IShellItemArrayImpl *This = impl_from_IShellItemArray(iface);
1189 FIXME("Stub: %p (%p, %s, %p)\n",
1190 This, keyType, shdebugstr_guid(riid), ppv);
1192 return E_NOTIMPL;
1195 static HRESULT WINAPI IShellItemArray_fnGetAttributes(IShellItemArray *iface,
1196 SIATTRIBFLAGS AttribFlags,
1197 SFGAOF sfgaoMask,
1198 SFGAOF *psfgaoAttribs)
1200 IShellItemArrayImpl *This = impl_from_IShellItemArray(iface);
1201 HRESULT hr = S_OK;
1202 SFGAOF attr;
1203 UINT i;
1204 TRACE("%p (%x, %lx, %p)\n", This, AttribFlags, sfgaoMask, psfgaoAttribs);
1206 if(AttribFlags & ~(SIATTRIBFLAGS_AND|SIATTRIBFLAGS_OR))
1207 FIXME("%08x contains unsupported attribution flags\n", AttribFlags);
1209 for(i = 0; i < This->item_count; i++)
1211 hr = IShellItem_GetAttributes(This->array[i], sfgaoMask, &attr);
1212 if(FAILED(hr))
1213 break;
1215 if(i == 0)
1217 *psfgaoAttribs = attr;
1218 continue;
1221 switch(AttribFlags & SIATTRIBFLAGS_MASK)
1223 case SIATTRIBFLAGS_AND:
1224 *psfgaoAttribs &= attr;
1225 break;
1226 case SIATTRIBFLAGS_OR:
1227 *psfgaoAttribs |= attr;
1228 break;
1232 if(SUCCEEDED(hr))
1234 if(*psfgaoAttribs == sfgaoMask)
1235 return S_OK;
1237 return S_FALSE;
1240 return hr;
1243 static HRESULT WINAPI IShellItemArray_fnGetCount(IShellItemArray *iface,
1244 DWORD *pdwNumItems)
1246 IShellItemArrayImpl *This = impl_from_IShellItemArray(iface);
1247 TRACE("%p (%p)\n", This, pdwNumItems);
1249 *pdwNumItems = This->item_count;
1251 return S_OK;
1254 static HRESULT WINAPI IShellItemArray_fnGetItemAt(IShellItemArray *iface,
1255 DWORD dwIndex,
1256 IShellItem **ppsi)
1258 IShellItemArrayImpl *This = impl_from_IShellItemArray(iface);
1259 TRACE("%p (%lx, %p)\n", This, dwIndex, ppsi);
1261 /* zero indexed */
1262 if(dwIndex + 1 > This->item_count)
1263 return E_FAIL;
1265 *ppsi = This->array[dwIndex];
1266 IShellItem_AddRef(*ppsi);
1268 return S_OK;
1271 static HRESULT WINAPI IShellItemArray_fnEnumItems(IShellItemArray *iface,
1272 IEnumShellItems **ppenumShellItems)
1274 IShellItemArrayImpl *This = impl_from_IShellItemArray(iface);
1275 TRACE("%p (%p)\n", This, ppenumShellItems);
1276 return IEnumShellItems_Constructor(iface, ppenumShellItems);
1279 static const IShellItemArrayVtbl vt_IShellItemArray = {
1280 IShellItemArray_fnQueryInterface,
1281 IShellItemArray_fnAddRef,
1282 IShellItemArray_fnRelease,
1283 IShellItemArray_fnBindToHandler,
1284 IShellItemArray_fnGetPropertyStore,
1285 IShellItemArray_fnGetPropertyDescriptionList,
1286 IShellItemArray_fnGetAttributes,
1287 IShellItemArray_fnGetCount,
1288 IShellItemArray_fnGetItemAt,
1289 IShellItemArray_fnEnumItems
1292 /* Caller is responsible to AddRef all items */
1293 static HRESULT create_shellitemarray(IShellItem **items, DWORD count, IShellItemArray **ret)
1295 IShellItemArrayImpl *This;
1297 TRACE("(%p, %ld, %p)\n", items, count, ret);
1299 This = heap_alloc(sizeof(*This));
1300 if(!This)
1301 return E_OUTOFMEMORY;
1303 This->IShellItemArray_iface.lpVtbl = &vt_IShellItemArray;
1304 This->ref = 1;
1306 This->array = heap_alloc(count*sizeof(IShellItem*));
1307 if (!This->array)
1309 heap_free(This);
1310 return E_OUTOFMEMORY;
1312 memcpy(This->array, items, count*sizeof(IShellItem*));
1313 This->item_count = count;
1315 *ret = &This->IShellItemArray_iface;
1316 return S_OK;
1319 HRESULT WINAPI SHCreateShellItemArray(PCIDLIST_ABSOLUTE pidlParent,
1320 IShellFolder *psf,
1321 UINT cidl,
1322 PCUITEMID_CHILD_ARRAY ppidl,
1323 IShellItemArray **ppsiItemArray)
1325 IShellItem **array;
1326 HRESULT ret = E_FAIL;
1327 UINT i;
1329 TRACE("%p, %p, %d, %p, %p\n", pidlParent, psf, cidl, ppidl, ppsiItemArray);
1331 *ppsiItemArray = NULL;
1333 if(!pidlParent && !psf)
1334 return E_POINTER;
1336 if(!ppidl)
1337 return E_INVALIDARG;
1339 array = heap_alloc_zero(cidl*sizeof(IShellItem*));
1340 if(!array)
1341 return E_OUTOFMEMORY;
1343 for(i = 0; i < cidl; i++)
1345 ret = SHCreateShellItem(pidlParent, psf, ppidl[i], &array[i]);
1346 if(FAILED(ret)) break;
1349 if(SUCCEEDED(ret))
1351 ret = create_shellitemarray(array, cidl, ppsiItemArray);
1354 if(FAILED(ret))
1356 for(i = 0; i < cidl; i++)
1357 if(array[i]) IShellItem_Release(array[i]);
1359 heap_free(array);
1360 return ret;
1363 HRESULT WINAPI SHCreateShellItemArrayFromShellItem(IShellItem *item, REFIID riid, void **ppv)
1365 IShellItemArray *array;
1366 HRESULT ret;
1368 TRACE("%p, %s, %p\n", item, shdebugstr_guid(riid), ppv);
1370 *ppv = NULL;
1372 IShellItem_AddRef(item);
1373 ret = create_shellitemarray(&item, 1, &array);
1374 if(FAILED(ret))
1376 IShellItem_Release(item);
1377 return ret;
1380 ret = IShellItemArray_QueryInterface(array, riid, ppv);
1381 IShellItemArray_Release(array);
1382 return ret;
1385 HRESULT WINAPI SHCreateShellItemArrayFromDataObject(IDataObject *pdo, REFIID riid, void **ppv)
1387 IShellItemArray *psia;
1388 FORMATETC fmt;
1389 STGMEDIUM medium;
1390 HRESULT ret;
1392 TRACE("%p, %s, %p\n", pdo, shdebugstr_guid(riid), ppv);
1394 if(!pdo)
1395 return E_INVALIDARG;
1397 *ppv = NULL;
1399 fmt.cfFormat = RegisterClipboardFormatW(CFSTR_SHELLIDLISTW);
1400 fmt.ptd = NULL;
1401 fmt.dwAspect = DVASPECT_CONTENT;
1402 fmt.lindex = -1;
1403 fmt.tymed = TYMED_HGLOBAL;
1405 ret = IDataObject_GetData(pdo, &fmt, &medium);
1406 if(SUCCEEDED(ret))
1408 LPIDA pida = GlobalLock(medium.u.hGlobal);
1409 LPCITEMIDLIST parent_pidl;
1410 LPCITEMIDLIST *children;
1411 UINT i;
1412 TRACE("Converting %d objects.\n", pida->cidl);
1414 parent_pidl = (LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[0]);
1416 children = heap_alloc(sizeof(LPCITEMIDLIST)*pida->cidl);
1417 for(i = 0; i < pida->cidl; i++)
1418 children[i] = (LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[i+1]);
1420 ret = SHCreateShellItemArray(parent_pidl, NULL, pida->cidl, children, &psia);
1422 heap_free(children);
1424 GlobalUnlock(medium.u.hGlobal);
1425 GlobalFree(medium.u.hGlobal);
1428 if(SUCCEEDED(ret))
1430 ret = IShellItemArray_QueryInterface(psia, riid, ppv);
1431 IShellItemArray_Release(psia);
1434 return ret;
1437 HRESULT WINAPI SHCreateShellItemArrayFromIDLists(UINT cidl,
1438 PCIDLIST_ABSOLUTE_ARRAY pidl_array,
1439 IShellItemArray **psia)
1441 IShellItem **array;
1442 HRESULT ret;
1443 UINT i;
1444 TRACE("%d, %p, %p\n", cidl, pidl_array, psia);
1446 *psia = NULL;
1448 if(cidl == 0)
1449 return E_INVALIDARG;
1451 array = heap_alloc_zero(cidl*sizeof(IShellItem*));
1452 if(!array)
1453 return E_OUTOFMEMORY;
1455 for(i = 0; i < cidl; i++)
1457 ret = SHCreateShellItem(NULL, NULL, pidl_array[i], &array[i]);
1458 if(FAILED(ret))
1459 break;
1462 if(SUCCEEDED(ret))
1464 ret = create_shellitemarray(array, cidl, psia);
1467 if(FAILED(ret))
1469 for(i = 0; i < cidl; i++)
1470 if(array[i]) IShellItem_Release(array[i]);
1471 *psia = NULL;
1473 heap_free(array);
1474 return ret;
1477 HRESULT WINAPI SHGetPropertyStoreFromParsingName(const WCHAR *path, IBindCtx *pbc, GETPROPERTYSTOREFLAGS flags,
1478 REFIID riid, void **ppv)
1480 IShellItem2 *item;
1481 HRESULT hr;
1483 TRACE("(%s %p %#x %p %p)\n", debugstr_w(path), pbc, flags, riid, ppv);
1485 hr = SHCreateItemFromParsingName(path, pbc, &IID_IShellItem2, (void **)&item);
1486 if(SUCCEEDED(hr))
1488 hr = IShellItem2_GetPropertyStore(item, flags, riid, ppv);
1489 IShellItem2_Release(item);
1492 return hr;
1495 static HRESULT WINAPI CustomDestinationList_QueryInterface(ICustomDestinationList *iface, REFIID riid, void **obj)
1497 CustomDestinationList *This = impl_from_ICustomDestinationList(iface);
1499 TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), obj);
1501 if (IsEqualIID(&IID_ICustomDestinationList, riid) || IsEqualIID(&IID_IUnknown, riid))
1503 *obj = &This->ICustomDestinationList_iface;
1505 else {
1506 WARN("Unsupported interface %s.\n", shdebugstr_guid(riid));
1507 *obj = NULL;
1508 return E_NOINTERFACE;
1511 IUnknown_AddRef((IUnknown*)*obj);
1512 return S_OK;
1515 static ULONG WINAPI CustomDestinationList_AddRef(ICustomDestinationList *iface)
1517 CustomDestinationList *This = impl_from_ICustomDestinationList(iface);
1518 ULONG ref = InterlockedIncrement(&This->ref);
1520 TRACE("(%p), new refcount=%li\n", This, ref);
1522 return ref;
1525 static ULONG WINAPI CustomDestinationList_Release(ICustomDestinationList *iface)
1527 CustomDestinationList *This = impl_from_ICustomDestinationList(iface);
1528 ULONG ref = InterlockedDecrement(&This->ref);
1530 TRACE("(%p), new refcount=%li\n", This, ref);
1532 if (ref == 0)
1533 heap_free(This);
1535 return ref;
1538 static HRESULT WINAPI CustomDestinationList_SetAppID(ICustomDestinationList *iface, const WCHAR *appid)
1540 CustomDestinationList *This = impl_from_ICustomDestinationList(iface);
1542 FIXME("%p (%s): stub\n", This, debugstr_w(appid));
1544 return E_NOTIMPL;
1547 static HRESULT WINAPI CustomDestinationList_BeginList(ICustomDestinationList *iface, UINT *min_slots, REFIID riid, void **obj)
1549 CustomDestinationList *This = impl_from_ICustomDestinationList(iface);
1551 FIXME("%p (%p %s %p): stub\n", This, min_slots, debugstr_guid(riid), obj);
1553 return E_NOTIMPL;
1556 static HRESULT WINAPI CustomDestinationList_AppendCategory(ICustomDestinationList *iface, const WCHAR *category, IObjectArray *array)
1558 CustomDestinationList *This = impl_from_ICustomDestinationList(iface);
1560 FIXME("%p (%s %p): stub\n", This, debugstr_w(category), array);
1562 return E_NOTIMPL;
1565 static HRESULT WINAPI CustomDestinationList_AppendKnownCategory(ICustomDestinationList *iface, KNOWNDESTCATEGORY category)
1567 CustomDestinationList *This = impl_from_ICustomDestinationList(iface);
1569 FIXME("%p (%d): stub\n", This, category);
1571 return E_NOTIMPL;
1574 static HRESULT WINAPI CustomDestinationList_AddUserTasks(ICustomDestinationList *iface, IObjectArray *tasks)
1576 CustomDestinationList *This = impl_from_ICustomDestinationList(iface);
1578 FIXME("%p (%p): stub\n", This, tasks);
1580 return E_NOTIMPL;
1583 static HRESULT WINAPI CustomDestinationList_CommitList(ICustomDestinationList *iface)
1585 CustomDestinationList *This = impl_from_ICustomDestinationList(iface);
1587 FIXME("%p: stub\n", This);
1589 return E_NOTIMPL;
1592 static HRESULT WINAPI CustomDestinationList_GetRemovedDestinations(ICustomDestinationList *iface, REFIID riid, void **obj)
1594 CustomDestinationList *This = impl_from_ICustomDestinationList(iface);
1596 FIXME("%p (%s %p): stub\n", This, debugstr_guid(riid), obj);
1598 return E_NOTIMPL;
1601 static HRESULT WINAPI CustomDestinationList_DeleteList(ICustomDestinationList *iface, const WCHAR *appid)
1603 CustomDestinationList *This = impl_from_ICustomDestinationList(iface);
1605 FIXME("%p (%s): stub\n", This, debugstr_w(appid));
1607 return E_NOTIMPL;
1610 static HRESULT WINAPI CustomDestinationList_AbortList(ICustomDestinationList *iface)
1612 CustomDestinationList *This = impl_from_ICustomDestinationList(iface);
1614 FIXME("%p: stub\n", This);
1616 return E_NOTIMPL;
1619 static const ICustomDestinationListVtbl CustomDestinationListVtbl =
1621 CustomDestinationList_QueryInterface,
1622 CustomDestinationList_AddRef,
1623 CustomDestinationList_Release,
1624 CustomDestinationList_SetAppID,
1625 CustomDestinationList_BeginList,
1626 CustomDestinationList_AppendCategory,
1627 CustomDestinationList_AppendKnownCategory,
1628 CustomDestinationList_AddUserTasks,
1629 CustomDestinationList_CommitList,
1630 CustomDestinationList_GetRemovedDestinations,
1631 CustomDestinationList_DeleteList,
1632 CustomDestinationList_AbortList
1635 HRESULT WINAPI CustomDestinationList_Constructor(IUnknown *outer, REFIID riid, void **obj)
1637 CustomDestinationList *list;
1638 HRESULT hr;
1640 TRACE("%p %s %p\n", outer, debugstr_guid(riid), obj);
1642 if (outer)
1643 return CLASS_E_NOAGGREGATION;
1645 if(!(list = heap_alloc(sizeof(*list))))
1646 return E_OUTOFMEMORY;
1648 list->ICustomDestinationList_iface.lpVtbl = &CustomDestinationListVtbl;
1649 list->ref = 1;
1651 hr = ICustomDestinationList_QueryInterface(&list->ICustomDestinationList_iface, riid, obj);
1652 ICustomDestinationList_Release(&list->ICustomDestinationList_iface);
1653 return hr;