widl: Properly align name table entries.
[wine.git] / dlls / shell32 / shellitem.c
blob93a60d63bd1c4b0a91559a49864a0f261612b994
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 #include "windef.h"
26 #include "winbase.h"
27 #include "wine/debug.h"
29 #include "pidl.h"
30 #include "shell32_main.h"
31 #include "debughlp.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(shell);
35 struct shell_item {
36 IShellItem2 IShellItem2_iface;
37 LONG ref;
38 LPITEMIDLIST pidl;
39 IPersistIDList IPersistIDList_iface;
40 IShellItemImageFactory IShellItemImageFactory_iface;
43 typedef struct _CustomDestinationList {
44 ICustomDestinationList ICustomDestinationList_iface;
45 LONG ref;
46 } CustomDestinationList;
48 static struct shell_item *impl_from_IShellItem2(IShellItem2 *iface)
50 return CONTAINING_RECORD(iface, struct shell_item, IShellItem2_iface);
53 static struct shell_item *impl_from_IPersistIDList(IPersistIDList *iface)
55 return CONTAINING_RECORD(iface, struct shell_item, IPersistIDList_iface);
58 static struct shell_item *impl_from_IShellItemImageFactory(IShellItemImageFactory *iface)
60 return CONTAINING_RECORD(iface, struct shell_item, IShellItemImageFactory_iface);
63 static inline CustomDestinationList *impl_from_ICustomDestinationList( ICustomDestinationList *iface )
65 return CONTAINING_RECORD(iface, CustomDestinationList, ICustomDestinationList_iface);
68 static HRESULT WINAPI ShellItem_QueryInterface(IShellItem2 *iface, REFIID riid,
69 void **ppv)
71 struct shell_item *This = impl_from_IShellItem2(iface);
73 TRACE("(%p, %s, %p)\n", iface, debugstr_guid(riid), ppv);
75 if (!ppv) return E_INVALIDARG;
77 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IShellItem, riid) ||
78 IsEqualIID(&IID_IShellItem2, riid))
80 *ppv = &This->IShellItem2_iface;
82 else if (IsEqualIID(&IID_IPersist, riid) || IsEqualIID(&IID_IPersistIDList, riid))
84 *ppv = &This->IPersistIDList_iface;
86 else if (IsEqualIID(&IID_IShellItemImageFactory, riid))
88 *ppv = &This->IShellItemImageFactory_iface;
90 else {
91 FIXME("not implemented for %s\n", shdebugstr_guid(riid));
92 *ppv = NULL;
93 return E_NOINTERFACE;
96 IUnknown_AddRef((IUnknown*)*ppv);
97 return S_OK;
100 static ULONG WINAPI ShellItem_AddRef(IShellItem2 *iface)
102 struct shell_item *This = impl_from_IShellItem2(iface);
103 ULONG ref = InterlockedIncrement(&This->ref);
105 TRACE("(%p), new refcount=%li\n", iface, ref);
107 return ref;
110 static ULONG WINAPI ShellItem_Release(IShellItem2 *iface)
112 struct shell_item *This = impl_from_IShellItem2(iface);
113 ULONG ref = InterlockedDecrement(&This->ref);
115 TRACE("(%p), new refcount=%li\n", iface, ref);
117 if (ref == 0)
119 ILFree(This->pidl);
120 free(This);
123 return ref;
126 static HRESULT ShellItem_get_parent_pidl(struct shell_item *This, ITEMIDLIST **parent_pidl)
128 *parent_pidl = ILClone(This->pidl);
129 if (*parent_pidl)
131 if (ILRemoveLastID(*parent_pidl))
132 return S_OK;
133 else
135 ILFree(*parent_pidl);
136 *parent_pidl = NULL;
137 return E_INVALIDARG;
140 else
142 *parent_pidl = NULL;
143 return E_OUTOFMEMORY;
147 static HRESULT ShellItem_get_parent_shellfolder(struct shell_item *This, IShellFolder **ppsf)
149 LPITEMIDLIST parent_pidl;
150 IShellFolder *desktop;
151 HRESULT ret;
153 ret = ShellItem_get_parent_pidl(This, &parent_pidl);
154 if (SUCCEEDED(ret))
156 ret = SHGetDesktopFolder(&desktop);
157 if (SUCCEEDED(ret))
159 if (_ILIsDesktop(parent_pidl))
161 *ppsf = desktop;
163 else
165 ret = IShellFolder_BindToObject(desktop, parent_pidl, NULL, &IID_IShellFolder, (void**)ppsf);
166 IShellFolder_Release(desktop);
169 ILFree(parent_pidl);
172 return ret;
175 static HRESULT ShellItem_get_shellfolder(struct shell_item *This, IBindCtx *pbc, IShellFolder **ppsf)
177 IShellFolder *desktop;
178 HRESULT ret;
180 ret = SHGetDesktopFolder(&desktop);
181 if (SUCCEEDED(ret))
183 if (_ILIsDesktop(This->pidl))
185 *ppsf = desktop;
186 IShellFolder_AddRef(*ppsf);
188 else
190 ret = IShellFolder_BindToObject(desktop, This->pidl, pbc, &IID_IShellFolder, (void**)ppsf);
193 IShellFolder_Release(desktop);
196 return ret;
199 static HRESULT WINAPI ShellItem_BindToHandler(IShellItem2 *iface, IBindCtx *pbc,
200 REFGUID rbhid, REFIID riid, void **ppvOut)
202 struct shell_item *This = impl_from_IShellItem2(iface);
203 HRESULT ret;
204 TRACE("(%p,%p,%s,%p,%p)\n", iface, pbc, shdebugstr_guid(rbhid), riid, ppvOut);
206 *ppvOut = NULL;
207 if (IsEqualGUID(rbhid, &BHID_SFObject))
209 IShellFolder *psf;
210 ret = ShellItem_get_shellfolder(This, pbc, &psf);
211 if (SUCCEEDED(ret))
213 ret = IShellFolder_QueryInterface(psf, riid, ppvOut);
214 IShellFolder_Release(psf);
216 return ret;
218 else if (IsEqualGUID(rbhid, &BHID_SFUIObject))
220 IShellFolder *psf_parent;
221 if (_ILIsDesktop(This->pidl))
222 ret = SHGetDesktopFolder(&psf_parent);
223 else
224 ret = ShellItem_get_parent_shellfolder(This, &psf_parent);
226 if (SUCCEEDED(ret))
228 LPCITEMIDLIST pidl = ILFindLastID(This->pidl);
229 ret = IShellFolder_GetUIObjectOf(psf_parent, NULL, 1, &pidl, riid, NULL, ppvOut);
230 IShellFolder_Release(psf_parent);
232 return ret;
234 else if (IsEqualGUID(rbhid, &BHID_DataObject))
236 return ShellItem_BindToHandler(&This->IShellItem2_iface, pbc, &BHID_SFUIObject,
237 &IID_IDataObject, ppvOut);
240 FIXME("Unsupported BHID %s.\n", debugstr_guid(rbhid));
242 return MK_E_NOOBJECT;
245 static HRESULT WINAPI ShellItem_GetParent(IShellItem2 *iface, IShellItem **ppsi)
247 struct shell_item *This = impl_from_IShellItem2(iface);
248 LPITEMIDLIST parent_pidl;
249 HRESULT ret;
251 TRACE("(%p,%p)\n", iface, ppsi);
253 ret = ShellItem_get_parent_pidl(This, &parent_pidl);
254 if (SUCCEEDED(ret))
256 ret = SHCreateShellItem(NULL, NULL, parent_pidl, ppsi);
257 ILFree(parent_pidl);
260 return ret;
263 static HRESULT WINAPI ShellItem_GetDisplayName(IShellItem2 *iface, SIGDN sigdnName,
264 LPWSTR *ppszName)
266 struct shell_item *This = impl_from_IShellItem2(iface);
267 TRACE("(%p,%x,%p)\n", iface, sigdnName, ppszName);
269 return SHGetNameFromIDList(This->pidl, sigdnName, ppszName);
272 static HRESULT WINAPI ShellItem_GetAttributes(IShellItem2 *iface, SFGAOF sfgaoMask,
273 SFGAOF *psfgaoAttribs)
275 struct shell_item *This = impl_from_IShellItem2(iface);
276 IShellFolder *parent_folder;
277 LPITEMIDLIST child_pidl;
278 HRESULT ret;
280 TRACE("(%p,%lx,%p)\n", iface, sfgaoMask, psfgaoAttribs);
282 if (_ILIsDesktop(This->pidl))
283 ret = SHGetDesktopFolder(&parent_folder);
284 else
285 ret = ShellItem_get_parent_shellfolder(This, &parent_folder);
286 if (SUCCEEDED(ret))
288 child_pidl = ILFindLastID(This->pidl);
289 *psfgaoAttribs = sfgaoMask;
290 ret = IShellFolder_GetAttributesOf(parent_folder, 1, (LPCITEMIDLIST*)&child_pidl, psfgaoAttribs);
291 *psfgaoAttribs &= sfgaoMask;
292 IShellFolder_Release(parent_folder);
294 if (SUCCEEDED(ret))
296 if(sfgaoMask == *psfgaoAttribs)
297 return S_OK;
298 else
299 return S_FALSE;
303 return ret;
306 static HRESULT WINAPI ShellItem_Compare(IShellItem2 *iface, IShellItem *oth,
307 SICHINTF hint, int *piOrder)
309 LPWSTR dispname, dispname_oth;
310 HRESULT ret;
311 TRACE("(%p,%p,%lx,%p)\n", iface, oth, hint, piOrder);
313 if(hint & (SICHINT_CANONICAL | SICHINT_ALLFIELDS))
314 FIXME("Unsupported flags 0x%08lx\n", hint);
316 ret = IShellItem2_GetDisplayName(iface, SIGDN_DESKTOPABSOLUTEEDITING, &dispname);
317 if(SUCCEEDED(ret))
319 ret = IShellItem_GetDisplayName(oth, SIGDN_DESKTOPABSOLUTEEDITING, &dispname_oth);
320 if(SUCCEEDED(ret))
322 *piOrder = lstrcmpiW(dispname, dispname_oth);
323 CoTaskMemFree(dispname_oth);
325 CoTaskMemFree(dispname);
328 if(SUCCEEDED(ret) && *piOrder &&
329 (hint & SICHINT_TEST_FILESYSPATH_IF_NOT_EQUAL))
331 LPWSTR dispname, dispname_oth;
333 TRACE("Testing filesystem path.\n");
334 ret = IShellItem2_GetDisplayName(iface, SIGDN_FILESYSPATH, &dispname);
335 if(SUCCEEDED(ret))
337 ret = IShellItem_GetDisplayName(oth, SIGDN_FILESYSPATH, &dispname_oth);
338 if(SUCCEEDED(ret))
340 *piOrder = lstrcmpiW(dispname, dispname_oth);
341 CoTaskMemFree(dispname_oth);
343 CoTaskMemFree(dispname);
347 if(FAILED(ret))
348 return ret;
350 if(*piOrder)
351 return S_FALSE;
352 else
353 return S_OK;
356 static HRESULT WINAPI ShellItem2_GetPropertyStore(IShellItem2 *iface, GETPROPERTYSTOREFLAGS flags,
357 REFIID riid, void **ppv)
359 struct shell_item *This = impl_from_IShellItem2(iface);
360 FIXME("Stub: %p (%d, %s, %p)\n", This, flags, shdebugstr_guid(riid), ppv);
361 return E_NOTIMPL;
364 static HRESULT WINAPI ShellItem2_GetPropertyStoreWithCreateObject(IShellItem2 *iface,
365 GETPROPERTYSTOREFLAGS flags, IUnknown *punkCreateObject, REFIID riid, void **ppv)
367 struct shell_item *This = impl_from_IShellItem2(iface);
368 FIXME("Stub: %p (%08x, %p, %s, %p)\n",
369 This, flags, punkCreateObject, shdebugstr_guid(riid), ppv);
370 return E_NOTIMPL;
373 static HRESULT WINAPI ShellItem2_GetPropertyStoreForKeys(IShellItem2 *iface, const PROPERTYKEY *rgKeys,
374 UINT cKeys, GETPROPERTYSTOREFLAGS flags, REFIID riid, void **ppv)
376 struct shell_item *This = impl_from_IShellItem2(iface);
377 FIXME("Stub: %p (%p, %d, %08x, %s, %p)\n",
378 This, rgKeys, cKeys, flags, shdebugstr_guid(riid), ppv);
379 return E_NOTIMPL;
382 static HRESULT WINAPI ShellItem2_GetPropertyDescriptionList(IShellItem2 *iface,
383 REFPROPERTYKEY keyType, REFIID riid, void **ppv)
385 struct shell_item *This = impl_from_IShellItem2(iface);
386 FIXME("Stub: %p (%p, %s, %p)\n", This, keyType, debugstr_guid(riid), ppv);
387 return E_NOTIMPL;
390 static HRESULT WINAPI ShellItem2_Update(IShellItem2 *iface, IBindCtx *pbc)
392 struct shell_item *This = impl_from_IShellItem2(iface);
393 FIXME("Stub: %p (%p)\n", This, pbc);
394 return E_NOTIMPL;
397 static HRESULT WINAPI ShellItem2_GetProperty(IShellItem2 *iface, REFPROPERTYKEY key, PROPVARIANT *ppropvar)
399 struct shell_item *This = impl_from_IShellItem2(iface);
400 FIXME("Stub: %p (%p, %p)\n", This, key, ppropvar);
401 return E_NOTIMPL;
404 static HRESULT WINAPI ShellItem2_GetCLSID(IShellItem2 *iface, REFPROPERTYKEY key, CLSID *pclsid)
406 struct shell_item *This = impl_from_IShellItem2(iface);
407 FIXME("Stub: %p (%p, %p)\n", This, key, pclsid);
408 return E_NOTIMPL;
411 static HRESULT WINAPI ShellItem2_GetFileTime(IShellItem2 *iface, REFPROPERTYKEY key, FILETIME *pft)
413 struct shell_item *This = impl_from_IShellItem2(iface);
414 FIXME("Stub: %p (%p, %p)\n", This, key, pft);
415 return E_NOTIMPL;
418 static HRESULT WINAPI ShellItem2_GetInt32(IShellItem2 *iface, REFPROPERTYKEY key, int *pi)
420 struct shell_item *This = impl_from_IShellItem2(iface);
421 FIXME("Stub: %p (%p, %p)\n", This, key, pi);
422 return E_NOTIMPL;
425 static HRESULT WINAPI ShellItem2_GetString(IShellItem2 *iface, REFPROPERTYKEY key, LPWSTR *ppsz)
427 struct shell_item *This = impl_from_IShellItem2(iface);
428 FIXME("Stub: %p (%p, %p)\n", This, key, ppsz);
429 return E_NOTIMPL;
432 static HRESULT WINAPI ShellItem2_GetUInt32(IShellItem2 *iface, REFPROPERTYKEY key, ULONG *pui)
434 struct shell_item *This = impl_from_IShellItem2(iface);
435 FIXME("Stub: %p (%p, %p)\n", This, key, pui);
436 return E_NOTIMPL;
439 static HRESULT WINAPI ShellItem2_GetUInt64(IShellItem2 *iface, REFPROPERTYKEY key, ULONGLONG *pull)
441 struct shell_item *This = impl_from_IShellItem2(iface);
442 FIXME("Stub: %p (%p, %p)\n", This, key, pull);
443 return E_NOTIMPL;
446 static HRESULT WINAPI ShellItem2_GetBool(IShellItem2 *iface, REFPROPERTYKEY key, BOOL *pf)
448 struct shell_item *This = impl_from_IShellItem2(iface);
449 FIXME("Stub: %p (%p, %p)\n", This, key, pf);
450 return E_NOTIMPL;
454 static const IShellItem2Vtbl ShellItem2_Vtbl = {
455 ShellItem_QueryInterface,
456 ShellItem_AddRef,
457 ShellItem_Release,
458 ShellItem_BindToHandler,
459 ShellItem_GetParent,
460 ShellItem_GetDisplayName,
461 ShellItem_GetAttributes,
462 ShellItem_Compare,
463 ShellItem2_GetPropertyStore,
464 ShellItem2_GetPropertyStoreWithCreateObject,
465 ShellItem2_GetPropertyStoreForKeys,
466 ShellItem2_GetPropertyDescriptionList,
467 ShellItem2_Update,
468 ShellItem2_GetProperty,
469 ShellItem2_GetCLSID,
470 ShellItem2_GetFileTime,
471 ShellItem2_GetInt32,
472 ShellItem2_GetString,
473 ShellItem2_GetUInt32,
474 ShellItem2_GetUInt64,
475 ShellItem2_GetBool
478 static HRESULT WINAPI ShellItem_IPersistIDList_QueryInterface(IPersistIDList *iface,
479 REFIID riid, void **ppv)
481 struct shell_item *This = impl_from_IPersistIDList(iface);
482 return IShellItem2_QueryInterface(&This->IShellItem2_iface, riid, ppv);
485 static ULONG WINAPI ShellItem_IPersistIDList_AddRef(IPersistIDList *iface)
487 struct shell_item *This = impl_from_IPersistIDList(iface);
488 return IShellItem2_AddRef(&This->IShellItem2_iface);
491 static ULONG WINAPI ShellItem_IPersistIDList_Release(IPersistIDList *iface)
493 struct shell_item *This = impl_from_IPersistIDList(iface);
494 return IShellItem2_Release(&This->IShellItem2_iface);
497 static HRESULT WINAPI ShellItem_IPersistIDList_GetClassID(IPersistIDList* iface,
498 CLSID *pClassID)
500 *pClassID = CLSID_ShellItem;
501 return S_OK;
504 static HRESULT WINAPI ShellItem_IPersistIDList_SetIDList(IPersistIDList* iface,
505 LPCITEMIDLIST pidl)
507 struct shell_item *This = impl_from_IPersistIDList(iface);
508 LPITEMIDLIST new_pidl;
510 TRACE("(%p,%p)\n", This, pidl);
512 new_pidl = ILClone(pidl);
514 if (new_pidl)
516 ILFree(This->pidl);
517 This->pidl = new_pidl;
518 return S_OK;
520 else
521 return E_OUTOFMEMORY;
524 static HRESULT WINAPI ShellItem_IPersistIDList_GetIDList(IPersistIDList* iface,
525 LPITEMIDLIST *ppidl)
527 struct shell_item *This = impl_from_IPersistIDList(iface);
529 TRACE("(%p,%p)\n", This, ppidl);
531 *ppidl = ILClone(This->pidl);
532 if (*ppidl)
533 return S_OK;
534 else
535 return E_OUTOFMEMORY;
538 static const IPersistIDListVtbl ShellItem_IPersistIDList_Vtbl = {
539 ShellItem_IPersistIDList_QueryInterface,
540 ShellItem_IPersistIDList_AddRef,
541 ShellItem_IPersistIDList_Release,
542 ShellItem_IPersistIDList_GetClassID,
543 ShellItem_IPersistIDList_SetIDList,
544 ShellItem_IPersistIDList_GetIDList
547 static HRESULT WINAPI ShellItem_IShellItemImageFactory_QueryInterface(IShellItemImageFactory *iface,
548 REFIID riid, void **ppv)
550 struct shell_item *This = impl_from_IShellItemImageFactory(iface);
551 return IShellItem2_QueryInterface(&This->IShellItem2_iface, riid, ppv);
554 static ULONG WINAPI ShellItem_IShellItemImageFactory_AddRef(IShellItemImageFactory *iface)
556 struct shell_item *This = impl_from_IShellItemImageFactory(iface);
557 return IShellItem2_AddRef(&This->IShellItem2_iface);
560 static ULONG WINAPI ShellItem_IShellItemImageFactory_Release(IShellItemImageFactory *iface)
562 struct shell_item *This = impl_from_IShellItemImageFactory(iface);
563 return IShellItem2_Release(&This->IShellItem2_iface);
566 static HRESULT WINAPI ShellItem_IShellItemImageFactory_GetImage(IShellItemImageFactory *iface,
567 SIZE size, SIIGBF flags, HBITMAP *phbm)
569 struct shell_item *This = impl_from_IShellItemImageFactory(iface);
570 static const BITMAPINFOHEADER dummy_bmi_header = {
571 .biSize = sizeof(dummy_bmi_header),
572 .biWidth = 1,
573 .biHeight = 1,
574 .biPlanes = 1,
575 .biBitCount = 32,
576 .biCompression = BI_RGB
578 static int once;
580 if (!once++)
581 FIXME("%p ({%lu, %lu} %d %p): stub\n", This, size.cx, size.cy, flags, phbm);
583 if (!(*phbm = CreateDIBSection(NULL, (const BITMAPINFO *)&dummy_bmi_header,
584 DIB_RGB_COLORS, NULL, NULL, 0)))
586 return E_OUTOFMEMORY;
589 return S_OK;
592 static const IShellItemImageFactoryVtbl ShellItem_IShellItemImageFactory_Vtbl = {
593 ShellItem_IShellItemImageFactory_QueryInterface,
594 ShellItem_IShellItemImageFactory_AddRef,
595 ShellItem_IShellItemImageFactory_Release,
596 ShellItem_IShellItemImageFactory_GetImage,
600 HRESULT WINAPI IShellItem_Constructor(IUnknown *pUnkOuter, REFIID riid, void **ppv)
602 struct shell_item *This;
603 HRESULT ret;
605 TRACE("(%p,%s)\n",pUnkOuter, debugstr_guid(riid));
607 *ppv = NULL;
609 if (pUnkOuter) return CLASS_E_NOAGGREGATION;
611 This = malloc(sizeof(*This));
612 This->IShellItem2_iface.lpVtbl = &ShellItem2_Vtbl;
613 This->ref = 1;
614 This->pidl = NULL;
615 This->IPersistIDList_iface.lpVtbl = &ShellItem_IPersistIDList_Vtbl;
616 This->IShellItemImageFactory_iface.lpVtbl = &ShellItem_IShellItemImageFactory_Vtbl;
618 ret = IShellItem2_QueryInterface(&This->IShellItem2_iface, riid, ppv);
619 IShellItem2_Release(&This->IShellItem2_iface);
621 return ret;
624 HRESULT WINAPI SHCreateShellItem(LPCITEMIDLIST pidlParent,
625 IShellFolder *psfParent, LPCITEMIDLIST pidl, IShellItem **ppsi)
627 LPITEMIDLIST new_pidl;
628 HRESULT ret;
630 TRACE("(%p,%p,%p,%p)\n", pidlParent, psfParent, pidl, ppsi);
632 *ppsi = NULL;
634 if (!pidl)
636 return E_INVALIDARG;
638 else if (pidlParent || psfParent)
640 LPITEMIDLIST temp_parent=NULL;
641 if (!pidlParent)
643 IPersistFolder2* ppf2Parent;
645 if (FAILED(IShellFolder_QueryInterface(psfParent, &IID_IPersistFolder2, (void**)&ppf2Parent)))
647 FIXME("couldn't get IPersistFolder2 interface of parent\n");
648 return E_NOINTERFACE;
651 if (FAILED(IPersistFolder2_GetCurFolder(ppf2Parent, &temp_parent)))
653 FIXME("couldn't get parent PIDL\n");
654 IPersistFolder2_Release(ppf2Parent);
655 return E_NOINTERFACE;
658 pidlParent = temp_parent;
659 IPersistFolder2_Release(ppf2Parent);
662 new_pidl = ILCombine(pidlParent, pidl);
663 ILFree(temp_parent);
665 if (!new_pidl)
666 return E_OUTOFMEMORY;
668 else
670 new_pidl = ILClone(pidl);
671 if (!new_pidl)
672 return E_OUTOFMEMORY;
675 ret = SHCreateItemFromIDList(new_pidl, &IID_IShellItem, (void**)ppsi);
676 ILFree(new_pidl);
678 return ret;
681 HRESULT WINAPI SHCreateItemFromParsingName(PCWSTR pszPath,
682 IBindCtx *pbc, REFIID riid, void **ppv)
684 LPITEMIDLIST pidl;
685 HRESULT ret;
687 *ppv = NULL;
689 ret = SHParseDisplayName(pszPath, pbc, &pidl, 0, NULL);
690 if(SUCCEEDED(ret))
692 ret = SHCreateItemFromIDList(pidl, riid, ppv);
693 ILFree(pidl);
695 return ret;
698 HRESULT WINAPI SHCreateItemFromRelativeName(IShellItem *parent, PCWSTR name, IBindCtx *pbc,
699 REFIID riid, void **ppv)
701 LPITEMIDLIST pidl_folder = NULL, pidl = NULL;
702 IShellFolder *desktop = NULL, *folder = NULL;
703 HRESULT hr;
705 TRACE("(%p, %s, %p, %s, %p)\n", parent, wine_dbgstr_w(name), pbc, debugstr_guid(riid), ppv);
707 if(!ppv)
708 return E_INVALIDARG;
709 *ppv = NULL;
710 if(!name)
711 return E_INVALIDARG;
713 hr = SHGetIDListFromObject((IUnknown*)parent, &pidl_folder);
714 if(hr != S_OK)
715 return hr;
717 hr = SHGetDesktopFolder(&desktop);
718 if(hr != S_OK)
719 goto cleanup;
721 if(!_ILIsDesktop(pidl_folder))
723 hr = IShellFolder_BindToObject(desktop, pidl_folder, NULL, &IID_IShellFolder,
724 (void**)&folder);
725 if(hr != S_OK)
726 goto cleanup;
729 hr = IShellFolder_ParseDisplayName(folder ? folder : desktop, NULL, pbc, (LPWSTR)name,
730 NULL, &pidl, NULL);
731 if(hr != S_OK)
732 goto cleanup;
733 hr = SHCreateItemFromIDList(pidl, riid, ppv);
735 cleanup:
736 if(pidl_folder)
737 ILFree(pidl_folder);
738 if(pidl)
739 ILFree(pidl);
740 if(desktop)
741 IShellFolder_Release(desktop);
742 if(folder)
743 IShellFolder_Release(folder);
744 return hr;
747 HRESULT WINAPI SHCreateItemFromIDList(PCIDLIST_ABSOLUTE pidl, REFIID riid, void **ppv)
749 IPersistIDList *persist;
750 HRESULT ret;
752 if(!pidl)
753 return E_INVALIDARG;
755 *ppv = NULL;
756 ret = IShellItem_Constructor(NULL, &IID_IPersistIDList, (void**)&persist);
757 if(FAILED(ret))
758 return ret;
760 ret = IPersistIDList_SetIDList(persist, pidl);
761 if(FAILED(ret))
763 IPersistIDList_Release(persist);
764 return ret;
767 ret = IPersistIDList_QueryInterface(persist, riid, ppv);
768 IPersistIDList_Release(persist);
769 return ret;
772 HRESULT WINAPI SHCreateItemWithParent(PCIDLIST_ABSOLUTE pidl_parent, IShellFolder *psf,
773 PCUITEMID_CHILD pidl, REFIID riid, void **ppv)
775 FIXME("(%p, %p, %p, %s, %p)\n", pidl_parent, psf, pidl, debugstr_guid(riid), ppv);
777 return E_NOTIMPL;
780 HRESULT WINAPI SHCreateItemInKnownFolder(REFKNOWNFOLDERID rfid, DWORD flags,
781 PCWSTR filename, REFIID riid, void **ppv)
783 HRESULT hr;
784 IShellItem *parent = NULL;
785 LPITEMIDLIST pidl = NULL;
787 TRACE("(%p, %lx, %s, %s, %p)\n", rfid, flags, wine_dbgstr_w(filename),
788 debugstr_guid(riid), ppv);
790 if(!rfid || !ppv)
791 return E_INVALIDARG;
793 *ppv = NULL;
794 hr = SHGetKnownFolderIDList(rfid, flags, NULL, &pidl);
795 if(hr != S_OK)
796 return hr;
798 hr = SHCreateItemFromIDList(pidl, &IID_IShellItem, (void**)&parent);
799 if(hr != S_OK)
801 ILFree(pidl);
802 return hr;
805 if(filename)
806 hr = SHCreateItemFromRelativeName(parent, filename, NULL, riid, ppv);
807 else
808 hr = IShellItem_QueryInterface(parent, riid, ppv);
810 ILFree(pidl);
811 IShellItem_Release(parent);
812 return hr;
815 HRESULT WINAPI SHGetItemFromDataObject(IDataObject *pdtobj,
816 DATAOBJ_GET_ITEM_FLAGS dwFlags, REFIID riid, void **ppv)
818 FORMATETC fmt;
819 STGMEDIUM medium;
820 HRESULT ret;
822 TRACE("%p, %x, %s, %p\n", pdtobj, dwFlags, debugstr_guid(riid), ppv);
824 if(!pdtobj)
825 return E_INVALIDARG;
827 fmt.cfFormat = RegisterClipboardFormatW(CFSTR_SHELLIDLISTW);
828 fmt.ptd = NULL;
829 fmt.dwAspect = DVASPECT_CONTENT;
830 fmt.lindex = -1;
831 fmt.tymed = TYMED_HGLOBAL;
833 ret = IDataObject_GetData(pdtobj, &fmt, &medium);
834 if(SUCCEEDED(ret))
836 LPIDA pida = GlobalLock(medium.hGlobal);
838 if((pida->cidl > 1 && !(dwFlags & DOGIF_ONLY_IF_ONE)) ||
839 pida->cidl == 1)
841 LPITEMIDLIST pidl;
843 /* Get the first pidl (parent + child1) */
844 pidl = ILCombine((LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[0]),
845 (LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[1]));
847 ret = SHCreateItemFromIDList(pidl, riid, ppv);
848 ILFree(pidl);
850 else
852 ret = E_FAIL;
855 GlobalUnlock(medium.hGlobal);
856 GlobalFree(medium.hGlobal);
859 if(FAILED(ret) && !(dwFlags & DOGIF_NO_HDROP))
861 TRACE("Attempting to fall back on CF_HDROP.\n");
863 fmt.cfFormat = CF_HDROP;
864 fmt.ptd = NULL;
865 fmt.dwAspect = DVASPECT_CONTENT;
866 fmt.lindex = -1;
867 fmt.tymed = TYMED_HGLOBAL;
869 ret = IDataObject_GetData(pdtobj, &fmt, &medium);
870 if(SUCCEEDED(ret))
872 DROPFILES *df = GlobalLock(medium.hGlobal);
873 LPBYTE files = (LPBYTE)df + df->pFiles;
874 BOOL multiple_files = FALSE;
876 ret = E_FAIL;
877 if(!df->fWide)
879 WCHAR filename[MAX_PATH];
880 PCSTR first_file = (PCSTR)files;
881 if(*(files + lstrlenA(first_file) + 1) != 0)
882 multiple_files = TRUE;
884 if( !(multiple_files && (dwFlags & DOGIF_ONLY_IF_ONE)) )
886 MultiByteToWideChar(CP_ACP, 0, first_file, -1, filename, MAX_PATH);
887 ret = SHCreateItemFromParsingName(filename, NULL, riid, ppv);
890 else
892 PCWSTR first_file = (PCWSTR)files;
893 if(*((PCWSTR)files + lstrlenW(first_file) + 1) != 0)
894 multiple_files = TRUE;
896 if( !(multiple_files && (dwFlags & DOGIF_ONLY_IF_ONE)) )
897 ret = SHCreateItemFromParsingName(first_file, NULL, riid, ppv);
900 GlobalUnlock(medium.hGlobal);
901 GlobalFree(medium.hGlobal);
905 if(FAILED(ret) && !(dwFlags & DOGIF_NO_URL))
907 FIXME("Failed to create item, should try CF_URL.\n");
910 return ret;
913 HRESULT WINAPI SHGetItemFromObject(IUnknown *punk, REFIID riid, void **ppv)
915 LPITEMIDLIST pidl;
916 HRESULT ret;
918 ret = SHGetIDListFromObject(punk, &pidl);
919 if(SUCCEEDED(ret))
921 ret = SHCreateItemFromIDList(pidl, riid, ppv);
922 ILFree(pidl);
925 return ret;
928 /*************************************************************************
929 * IEnumShellItems implementation
931 typedef struct {
932 IEnumShellItems IEnumShellItems_iface;
933 LONG ref;
935 IShellItemArray *array;
936 DWORD count;
937 DWORD position;
938 } IEnumShellItemsImpl;
940 static inline IEnumShellItemsImpl *impl_from_IEnumShellItems(IEnumShellItems *iface)
942 return CONTAINING_RECORD(iface, IEnumShellItemsImpl, IEnumShellItems_iface);
945 static HRESULT WINAPI IEnumShellItems_fnQueryInterface(IEnumShellItems *iface,
946 REFIID riid,
947 void **ppvObject)
949 IEnumShellItemsImpl *This = impl_from_IEnumShellItems(iface);
950 TRACE("%p (%s, %p)\n", This, shdebugstr_guid(riid), ppvObject);
952 *ppvObject = NULL;
953 if(IsEqualIID(riid, &IID_IEnumShellItems) ||
954 IsEqualIID(riid, &IID_IUnknown))
956 *ppvObject = &This->IEnumShellItems_iface;
959 if(*ppvObject)
961 IUnknown_AddRef((IUnknown*)*ppvObject);
962 return S_OK;
965 return E_NOINTERFACE;
968 static ULONG WINAPI IEnumShellItems_fnAddRef(IEnumShellItems *iface)
970 IEnumShellItemsImpl *This = impl_from_IEnumShellItems(iface);
971 LONG ref = InterlockedIncrement(&This->ref);
972 TRACE("%p - ref %ld\n", This, ref);
974 return ref;
977 static ULONG WINAPI IEnumShellItems_fnRelease(IEnumShellItems *iface)
979 IEnumShellItemsImpl *This = impl_from_IEnumShellItems(iface);
980 LONG ref = InterlockedDecrement(&This->ref);
981 TRACE("%p - ref %ld\n", This, ref);
983 if(!ref)
985 TRACE("Freeing.\n");
986 IShellItemArray_Release(This->array);
987 free(This);
988 return 0;
991 return ref;
994 static HRESULT WINAPI IEnumShellItems_fnNext(IEnumShellItems* iface,
995 ULONG celt,
996 IShellItem **rgelt,
997 ULONG *pceltFetched)
999 IEnumShellItemsImpl *This = impl_from_IEnumShellItems(iface);
1000 HRESULT hr = S_FALSE;
1001 UINT i;
1002 ULONG fetched = 0;
1003 TRACE("%p (%ld %p %p)\n", This, celt, rgelt, pceltFetched);
1005 if(pceltFetched == NULL && celt != 1)
1006 return E_INVALIDARG;
1008 for(i = This->position; fetched < celt && i < This->count; i++) {
1009 hr = IShellItemArray_GetItemAt(This->array, i, &rgelt[fetched]);
1010 if(FAILED(hr))
1011 break;
1012 fetched++;
1013 This->position++;
1016 if(SUCCEEDED(hr))
1018 if(pceltFetched != NULL)
1019 *pceltFetched = fetched;
1021 if(fetched > 0)
1022 return S_OK;
1024 return S_FALSE;
1027 return hr;
1030 static HRESULT WINAPI IEnumShellItems_fnSkip(IEnumShellItems* iface, ULONG celt)
1032 IEnumShellItemsImpl *This = impl_from_IEnumShellItems(iface);
1033 TRACE("%p (%ld)\n", This, celt);
1035 This->position = min(This->position + celt, This->count-1);
1037 return S_OK;
1040 static HRESULT WINAPI IEnumShellItems_fnReset(IEnumShellItems* iface)
1042 IEnumShellItemsImpl *This = impl_from_IEnumShellItems(iface);
1043 TRACE("%p\n", This);
1045 This->position = 0;
1047 return S_OK;
1050 static HRESULT WINAPI IEnumShellItems_fnClone(IEnumShellItems* iface, IEnumShellItems **ppenum)
1052 IEnumShellItemsImpl *This = impl_from_IEnumShellItems(iface);
1053 TRACE("%p (%p)\n", This, ppenum);
1055 /* Not implemented anywhere */
1056 *ppenum = NULL;
1058 return E_NOTIMPL;
1061 static const IEnumShellItemsVtbl vt_IEnumShellItems = {
1062 IEnumShellItems_fnQueryInterface,
1063 IEnumShellItems_fnAddRef,
1064 IEnumShellItems_fnRelease,
1065 IEnumShellItems_fnNext,
1066 IEnumShellItems_fnSkip,
1067 IEnumShellItems_fnReset,
1068 IEnumShellItems_fnClone
1071 static HRESULT IEnumShellItems_Constructor(IShellItemArray *array, IEnumShellItems **ppesi)
1073 IEnumShellItemsImpl *This;
1074 HRESULT ret;
1076 This = malloc(sizeof(*This));
1077 if(!This)
1078 return E_OUTOFMEMORY;
1080 This->ref = 1;
1081 This->IEnumShellItems_iface.lpVtbl = &vt_IEnumShellItems;
1082 This->array = array;
1083 This->position = 0;
1085 IShellItemArray_AddRef(This->array);
1086 IShellItemArray_GetCount(This->array, &This->count);
1088 ret = IEnumShellItems_QueryInterface(&This->IEnumShellItems_iface, &IID_IEnumShellItems, (void**)ppesi);
1089 IEnumShellItems_Release(&This->IEnumShellItems_iface);
1091 return ret;
1095 /*************************************************************************
1096 * IShellItemArray implementation
1098 typedef struct {
1099 IShellItemArray IShellItemArray_iface;
1100 LONG ref;
1102 IShellItem **array;
1103 DWORD item_count;
1104 } IShellItemArrayImpl;
1106 static inline IShellItemArrayImpl *impl_from_IShellItemArray(IShellItemArray *iface)
1108 return CONTAINING_RECORD(iface, IShellItemArrayImpl, IShellItemArray_iface);
1111 static HRESULT WINAPI IShellItemArray_fnQueryInterface(IShellItemArray *iface,
1112 REFIID riid,
1113 void **ppvObject)
1115 IShellItemArrayImpl *This = impl_from_IShellItemArray(iface);
1116 TRACE("%p (%s, %p)\n", This, shdebugstr_guid(riid), ppvObject);
1118 *ppvObject = NULL;
1119 if(IsEqualIID(riid, &IID_IShellItemArray) ||
1120 IsEqualIID(riid, &IID_IUnknown))
1122 *ppvObject = &This->IShellItemArray_iface;
1125 if(*ppvObject)
1127 IUnknown_AddRef((IUnknown*)*ppvObject);
1128 return S_OK;
1131 return E_NOINTERFACE;
1134 static ULONG WINAPI IShellItemArray_fnAddRef(IShellItemArray *iface)
1136 IShellItemArrayImpl *This = impl_from_IShellItemArray(iface);
1137 LONG ref = InterlockedIncrement(&This->ref);
1138 TRACE("%p - ref %ld\n", This, ref);
1140 return ref;
1143 static ULONG WINAPI IShellItemArray_fnRelease(IShellItemArray *iface)
1145 IShellItemArrayImpl *This = impl_from_IShellItemArray(iface);
1146 LONG ref = InterlockedDecrement(&This->ref);
1147 TRACE("%p - ref %ld\n", This, ref);
1149 if(!ref)
1151 UINT i;
1152 TRACE("Freeing.\n");
1154 for(i = 0; i < This->item_count; i++)
1155 IShellItem_Release(This->array[i]);
1157 free(This->array);
1158 free(This);
1159 return 0;
1162 return ref;
1165 static HRESULT WINAPI IShellItemArray_fnBindToHandler(IShellItemArray *iface,
1166 IBindCtx *pbc,
1167 REFGUID bhid,
1168 REFIID riid,
1169 void **ppvOut)
1171 IShellItemArrayImpl *This = impl_from_IShellItemArray(iface);
1172 FIXME("Stub: %p (%p, %s, %s, %p)\n",
1173 This, pbc, shdebugstr_guid(bhid), shdebugstr_guid(riid), ppvOut);
1175 return E_NOTIMPL;
1178 static HRESULT WINAPI IShellItemArray_fnGetPropertyStore(IShellItemArray *iface,
1179 GETPROPERTYSTOREFLAGS flags,
1180 REFIID riid,
1181 void **ppv)
1183 IShellItemArrayImpl *This = impl_from_IShellItemArray(iface);
1184 FIXME("Stub: %p (%x, %s, %p)\n", This, flags, shdebugstr_guid(riid), ppv);
1186 return E_NOTIMPL;
1189 static HRESULT WINAPI IShellItemArray_fnGetPropertyDescriptionList(IShellItemArray *iface,
1190 REFPROPERTYKEY keyType,
1191 REFIID riid,
1192 void **ppv)
1194 IShellItemArrayImpl *This = impl_from_IShellItemArray(iface);
1195 FIXME("Stub: %p (%p, %s, %p)\n",
1196 This, keyType, shdebugstr_guid(riid), ppv);
1198 return E_NOTIMPL;
1201 static HRESULT WINAPI IShellItemArray_fnGetAttributes(IShellItemArray *iface,
1202 SIATTRIBFLAGS AttribFlags,
1203 SFGAOF sfgaoMask,
1204 SFGAOF *psfgaoAttribs)
1206 IShellItemArrayImpl *This = impl_from_IShellItemArray(iface);
1207 HRESULT hr = S_OK;
1208 SFGAOF attr;
1209 UINT i;
1210 TRACE("%p (%x, %lx, %p)\n", This, AttribFlags, sfgaoMask, psfgaoAttribs);
1212 if(AttribFlags & ~(SIATTRIBFLAGS_AND|SIATTRIBFLAGS_OR))
1213 FIXME("%08x contains unsupported attribution flags\n", AttribFlags);
1215 for(i = 0; i < This->item_count; i++)
1217 hr = IShellItem_GetAttributes(This->array[i], sfgaoMask, &attr);
1218 if(FAILED(hr))
1219 break;
1221 if(i == 0)
1223 *psfgaoAttribs = attr;
1224 continue;
1227 switch(AttribFlags & SIATTRIBFLAGS_MASK)
1229 case SIATTRIBFLAGS_AND:
1230 *psfgaoAttribs &= attr;
1231 break;
1232 case SIATTRIBFLAGS_OR:
1233 *psfgaoAttribs |= attr;
1234 break;
1238 if(SUCCEEDED(hr))
1240 if(*psfgaoAttribs == sfgaoMask)
1241 return S_OK;
1243 return S_FALSE;
1246 return hr;
1249 static HRESULT WINAPI IShellItemArray_fnGetCount(IShellItemArray *iface,
1250 DWORD *pdwNumItems)
1252 IShellItemArrayImpl *This = impl_from_IShellItemArray(iface);
1253 TRACE("%p (%p)\n", This, pdwNumItems);
1255 *pdwNumItems = This->item_count;
1257 return S_OK;
1260 static HRESULT WINAPI IShellItemArray_fnGetItemAt(IShellItemArray *iface,
1261 DWORD dwIndex,
1262 IShellItem **ppsi)
1264 IShellItemArrayImpl *This = impl_from_IShellItemArray(iface);
1265 TRACE("%p (%lx, %p)\n", This, dwIndex, ppsi);
1267 /* zero indexed */
1268 if(dwIndex + 1 > This->item_count)
1269 return E_FAIL;
1271 *ppsi = This->array[dwIndex];
1272 IShellItem_AddRef(*ppsi);
1274 return S_OK;
1277 static HRESULT WINAPI IShellItemArray_fnEnumItems(IShellItemArray *iface,
1278 IEnumShellItems **ppenumShellItems)
1280 IShellItemArrayImpl *This = impl_from_IShellItemArray(iface);
1281 TRACE("%p (%p)\n", This, ppenumShellItems);
1282 return IEnumShellItems_Constructor(iface, ppenumShellItems);
1285 static const IShellItemArrayVtbl vt_IShellItemArray = {
1286 IShellItemArray_fnQueryInterface,
1287 IShellItemArray_fnAddRef,
1288 IShellItemArray_fnRelease,
1289 IShellItemArray_fnBindToHandler,
1290 IShellItemArray_fnGetPropertyStore,
1291 IShellItemArray_fnGetPropertyDescriptionList,
1292 IShellItemArray_fnGetAttributes,
1293 IShellItemArray_fnGetCount,
1294 IShellItemArray_fnGetItemAt,
1295 IShellItemArray_fnEnumItems
1298 /* Caller is responsible to AddRef all items */
1299 static HRESULT create_shellitemarray(IShellItem **items, DWORD count, IShellItemArray **ret)
1301 IShellItemArrayImpl *This;
1303 TRACE("(%p, %ld, %p)\n", items, count, ret);
1305 This = malloc(sizeof(*This));
1306 if(!This)
1307 return E_OUTOFMEMORY;
1309 This->IShellItemArray_iface.lpVtbl = &vt_IShellItemArray;
1310 This->ref = 1;
1312 This->array = malloc(count * sizeof(IShellItem*));
1313 if (!This->array)
1315 free(This);
1316 return E_OUTOFMEMORY;
1318 memcpy(This->array, items, count*sizeof(IShellItem*));
1319 This->item_count = count;
1321 *ret = &This->IShellItemArray_iface;
1322 return S_OK;
1325 HRESULT WINAPI SHCreateShellItemArray(PCIDLIST_ABSOLUTE pidlParent,
1326 IShellFolder *psf,
1327 UINT cidl,
1328 PCUITEMID_CHILD_ARRAY ppidl,
1329 IShellItemArray **ppsiItemArray)
1331 IShellItem **array;
1332 HRESULT ret = E_FAIL;
1333 UINT i;
1335 TRACE("%p, %p, %d, %p, %p\n", pidlParent, psf, cidl, ppidl, ppsiItemArray);
1337 *ppsiItemArray = NULL;
1339 if(!pidlParent && !psf)
1340 return E_POINTER;
1342 if(!ppidl)
1343 return E_INVALIDARG;
1345 array = calloc(cidl, sizeof(IShellItem*));
1346 if(!array)
1347 return E_OUTOFMEMORY;
1349 for(i = 0; i < cidl; i++)
1351 ret = SHCreateShellItem(pidlParent, psf, ppidl[i], &array[i]);
1352 if(FAILED(ret)) break;
1355 if(SUCCEEDED(ret))
1357 ret = create_shellitemarray(array, cidl, ppsiItemArray);
1360 if(FAILED(ret))
1362 for(i = 0; i < cidl; i++)
1363 if(array[i]) IShellItem_Release(array[i]);
1365 free(array);
1366 return ret;
1369 HRESULT WINAPI SHCreateShellItemArrayFromShellItem(IShellItem *item, REFIID riid, void **ppv)
1371 IShellItemArray *array;
1372 HRESULT ret;
1374 TRACE("%p, %s, %p\n", item, shdebugstr_guid(riid), ppv);
1376 *ppv = NULL;
1378 IShellItem_AddRef(item);
1379 ret = create_shellitemarray(&item, 1, &array);
1380 if(FAILED(ret))
1382 IShellItem_Release(item);
1383 return ret;
1386 ret = IShellItemArray_QueryInterface(array, riid, ppv);
1387 IShellItemArray_Release(array);
1388 return ret;
1391 HRESULT WINAPI SHCreateShellItemArrayFromDataObject(IDataObject *pdo, REFIID riid, void **ppv)
1393 IShellItemArray *psia;
1394 FORMATETC fmt;
1395 STGMEDIUM medium;
1396 HRESULT ret;
1398 TRACE("%p, %s, %p\n", pdo, shdebugstr_guid(riid), ppv);
1400 if(!pdo)
1401 return E_INVALIDARG;
1403 *ppv = NULL;
1405 fmt.cfFormat = RegisterClipboardFormatW(CFSTR_SHELLIDLISTW);
1406 fmt.ptd = NULL;
1407 fmt.dwAspect = DVASPECT_CONTENT;
1408 fmt.lindex = -1;
1409 fmt.tymed = TYMED_HGLOBAL;
1411 ret = IDataObject_GetData(pdo, &fmt, &medium);
1412 if(SUCCEEDED(ret))
1414 LPIDA pida = GlobalLock(medium.hGlobal);
1415 LPCITEMIDLIST parent_pidl;
1416 LPCITEMIDLIST *children;
1417 UINT i;
1418 TRACE("Converting %d objects.\n", pida->cidl);
1420 parent_pidl = (LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[0]);
1422 children = malloc(sizeof(const ITEMIDLIST*) * pida->cidl);
1423 for(i = 0; i < pida->cidl; i++)
1424 children[i] = (LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[i+1]);
1426 ret = SHCreateShellItemArray(parent_pidl, NULL, pida->cidl, children, &psia);
1428 free(children);
1430 GlobalUnlock(medium.hGlobal);
1431 GlobalFree(medium.hGlobal);
1434 if(SUCCEEDED(ret))
1436 ret = IShellItemArray_QueryInterface(psia, riid, ppv);
1437 IShellItemArray_Release(psia);
1440 return ret;
1443 HRESULT WINAPI SHCreateShellItemArrayFromIDLists(UINT cidl,
1444 PCIDLIST_ABSOLUTE_ARRAY pidl_array,
1445 IShellItemArray **psia)
1447 IShellItem **array;
1448 HRESULT ret;
1449 UINT i;
1450 TRACE("%d, %p, %p\n", cidl, pidl_array, psia);
1452 *psia = NULL;
1454 if(cidl == 0)
1455 return E_INVALIDARG;
1457 array = calloc(cidl, sizeof(IShellItem*));
1458 if(!array)
1459 return E_OUTOFMEMORY;
1461 for(i = 0; i < cidl; i++)
1463 ret = SHCreateShellItem(NULL, NULL, pidl_array[i], &array[i]);
1464 if(FAILED(ret))
1465 break;
1468 if(SUCCEEDED(ret))
1470 ret = create_shellitemarray(array, cidl, psia);
1473 if(FAILED(ret))
1475 for(i = 0; i < cidl; i++)
1476 if(array[i]) IShellItem_Release(array[i]);
1477 *psia = NULL;
1479 free(array);
1480 return ret;
1483 HRESULT WINAPI SHGetPropertyStoreFromParsingName(const WCHAR *path, IBindCtx *pbc, GETPROPERTYSTOREFLAGS flags,
1484 REFIID riid, void **ppv)
1486 IShellItem2 *item;
1487 HRESULT hr;
1489 TRACE("(%s %p %#x %p %p)\n", debugstr_w(path), pbc, flags, riid, ppv);
1491 hr = SHCreateItemFromParsingName(path, pbc, &IID_IShellItem2, (void **)&item);
1492 if(SUCCEEDED(hr))
1494 hr = IShellItem2_GetPropertyStore(item, flags, riid, ppv);
1495 IShellItem2_Release(item);
1498 return hr;
1501 static HRESULT WINAPI CustomDestinationList_QueryInterface(ICustomDestinationList *iface, REFIID riid, void **obj)
1503 CustomDestinationList *This = impl_from_ICustomDestinationList(iface);
1505 TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), obj);
1507 if (IsEqualIID(&IID_ICustomDestinationList, riid) || IsEqualIID(&IID_IUnknown, riid))
1509 *obj = &This->ICustomDestinationList_iface;
1511 else {
1512 WARN("Unsupported interface %s.\n", shdebugstr_guid(riid));
1513 *obj = NULL;
1514 return E_NOINTERFACE;
1517 IUnknown_AddRef((IUnknown*)*obj);
1518 return S_OK;
1521 static ULONG WINAPI CustomDestinationList_AddRef(ICustomDestinationList *iface)
1523 CustomDestinationList *This = impl_from_ICustomDestinationList(iface);
1524 ULONG ref = InterlockedIncrement(&This->ref);
1526 TRACE("(%p), new refcount=%li\n", This, ref);
1528 return ref;
1531 static ULONG WINAPI CustomDestinationList_Release(ICustomDestinationList *iface)
1533 CustomDestinationList *This = impl_from_ICustomDestinationList(iface);
1534 ULONG ref = InterlockedDecrement(&This->ref);
1536 TRACE("(%p), new refcount=%li\n", This, ref);
1538 if (ref == 0)
1539 free(This);
1541 return ref;
1544 static HRESULT WINAPI CustomDestinationList_SetAppID(ICustomDestinationList *iface, const WCHAR *appid)
1546 CustomDestinationList *This = impl_from_ICustomDestinationList(iface);
1548 FIXME("%p (%s): stub\n", This, debugstr_w(appid));
1550 return E_NOTIMPL;
1553 static HRESULT WINAPI CustomDestinationList_BeginList(ICustomDestinationList *iface, UINT *min_slots, REFIID riid, void **obj)
1555 CustomDestinationList *This = impl_from_ICustomDestinationList(iface);
1557 FIXME("%p (%p %s %p): stub\n", This, min_slots, debugstr_guid(riid), obj);
1559 return E_NOTIMPL;
1562 static HRESULT WINAPI CustomDestinationList_AppendCategory(ICustomDestinationList *iface, const WCHAR *category, IObjectArray *array)
1564 CustomDestinationList *This = impl_from_ICustomDestinationList(iface);
1566 FIXME("%p (%s %p): stub\n", This, debugstr_w(category), array);
1568 return E_NOTIMPL;
1571 static HRESULT WINAPI CustomDestinationList_AppendKnownCategory(ICustomDestinationList *iface, KNOWNDESTCATEGORY category)
1573 CustomDestinationList *This = impl_from_ICustomDestinationList(iface);
1575 FIXME("%p (%d): stub\n", This, category);
1577 return E_NOTIMPL;
1580 static HRESULT WINAPI CustomDestinationList_AddUserTasks(ICustomDestinationList *iface, IObjectArray *tasks)
1582 CustomDestinationList *This = impl_from_ICustomDestinationList(iface);
1584 FIXME("%p (%p): stub\n", This, tasks);
1586 return E_NOTIMPL;
1589 static HRESULT WINAPI CustomDestinationList_CommitList(ICustomDestinationList *iface)
1591 CustomDestinationList *This = impl_from_ICustomDestinationList(iface);
1593 FIXME("%p: stub\n", This);
1595 return E_NOTIMPL;
1598 static HRESULT WINAPI CustomDestinationList_GetRemovedDestinations(ICustomDestinationList *iface, REFIID riid, void **obj)
1600 CustomDestinationList *This = impl_from_ICustomDestinationList(iface);
1602 FIXME("%p (%s %p): stub\n", This, debugstr_guid(riid), obj);
1604 return E_NOTIMPL;
1607 static HRESULT WINAPI CustomDestinationList_DeleteList(ICustomDestinationList *iface, const WCHAR *appid)
1609 CustomDestinationList *This = impl_from_ICustomDestinationList(iface);
1611 FIXME("%p (%s): stub\n", This, debugstr_w(appid));
1613 return E_NOTIMPL;
1616 static HRESULT WINAPI CustomDestinationList_AbortList(ICustomDestinationList *iface)
1618 CustomDestinationList *This = impl_from_ICustomDestinationList(iface);
1620 FIXME("%p: stub\n", This);
1622 return E_NOTIMPL;
1625 static const ICustomDestinationListVtbl CustomDestinationListVtbl =
1627 CustomDestinationList_QueryInterface,
1628 CustomDestinationList_AddRef,
1629 CustomDestinationList_Release,
1630 CustomDestinationList_SetAppID,
1631 CustomDestinationList_BeginList,
1632 CustomDestinationList_AppendCategory,
1633 CustomDestinationList_AppendKnownCategory,
1634 CustomDestinationList_AddUserTasks,
1635 CustomDestinationList_CommitList,
1636 CustomDestinationList_GetRemovedDestinations,
1637 CustomDestinationList_DeleteList,
1638 CustomDestinationList_AbortList
1641 HRESULT WINAPI CustomDestinationList_Constructor(IUnknown *outer, REFIID riid, void **obj)
1643 CustomDestinationList *list;
1644 HRESULT hr;
1646 TRACE("%p %s %p\n", outer, debugstr_guid(riid), obj);
1648 if (outer)
1649 return CLASS_E_NOAGGREGATION;
1651 if(!(list = malloc(sizeof(*list))))
1652 return E_OUTOFMEMORY;
1654 list->ICustomDestinationList_iface.lpVtbl = &CustomDestinationListVtbl;
1655 list->ref = 1;
1657 hr = ICustomDestinationList_QueryInterface(&list->ICustomDestinationList_iface, riid, obj);
1658 ICustomDestinationList_Release(&list->ICustomDestinationList_iface);
1659 return hr;
1662 HRESULT WINAPI SHSetTemporaryPropertyForItem(IShellItem *psi, REFPROPERTYKEY propkey, REFPROPVARIANT propvar)
1664 FIXME("%p %p %p: stub\n", psi, propkey, propvar);
1666 return E_NOTIMPL;