mfmediaengine: Remove unnecessary import library.
[wine.git] / dlls / shell32 / shellitem.c
blob4693641d6ef2bf9638e957a26064b53f2a5c1b68
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 } ShellItem;
44 typedef struct _CustomDestinationList {
45 ICustomDestinationList ICustomDestinationList_iface;
46 LONG ref;
47 } CustomDestinationList;
49 static inline ShellItem *impl_from_IShellItem2(IShellItem2 *iface)
51 return CONTAINING_RECORD(iface, ShellItem, IShellItem2_iface);
54 static inline ShellItem *impl_from_IPersistIDList( IPersistIDList *iface )
56 return CONTAINING_RECORD(iface, ShellItem, IPersistIDList_iface);
59 static inline CustomDestinationList *impl_from_ICustomDestinationList( ICustomDestinationList *iface )
61 return CONTAINING_RECORD(iface, CustomDestinationList, ICustomDestinationList_iface);
64 static HRESULT WINAPI ShellItem_QueryInterface(IShellItem2 *iface, REFIID riid,
65 void **ppv)
67 ShellItem *This = impl_from_IShellItem2(iface);
69 TRACE("(%p, %s, %p)\n", iface, debugstr_guid(riid), ppv);
71 if (!ppv) return E_INVALIDARG;
73 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IShellItem, riid) ||
74 IsEqualIID(&IID_IShellItem2, riid))
76 *ppv = &This->IShellItem2_iface;
78 else if (IsEqualIID(&IID_IPersist, riid) || IsEqualIID(&IID_IPersistIDList, riid))
80 *ppv = &This->IPersistIDList_iface;
82 else {
83 FIXME("not implemented for %s\n", shdebugstr_guid(riid));
84 *ppv = NULL;
85 return E_NOINTERFACE;
88 IUnknown_AddRef((IUnknown*)*ppv);
89 return S_OK;
92 static ULONG WINAPI ShellItem_AddRef(IShellItem2 *iface)
94 ShellItem *This = impl_from_IShellItem2(iface);
95 ULONG ref = InterlockedIncrement(&This->ref);
97 TRACE("(%p), new refcount=%i\n", iface, ref);
99 return ref;
102 static ULONG WINAPI ShellItem_Release(IShellItem2 *iface)
104 ShellItem *This = impl_from_IShellItem2(iface);
105 ULONG ref = InterlockedDecrement(&This->ref);
107 TRACE("(%p), new refcount=%i\n", iface, ref);
109 if (ref == 0)
111 ILFree(This->pidl);
112 heap_free(This);
115 return ref;
118 static HRESULT ShellItem_get_parent_pidl(ShellItem *This, LPITEMIDLIST *parent_pidl)
120 *parent_pidl = ILClone(This->pidl);
121 if (*parent_pidl)
123 if (ILRemoveLastID(*parent_pidl))
124 return S_OK;
125 else
127 ILFree(*parent_pidl);
128 *parent_pidl = NULL;
129 return E_INVALIDARG;
132 else
134 *parent_pidl = NULL;
135 return E_OUTOFMEMORY;
139 static HRESULT ShellItem_get_parent_shellfolder(ShellItem *This, IShellFolder **ppsf)
141 LPITEMIDLIST parent_pidl;
142 IShellFolder *desktop;
143 HRESULT ret;
145 ret = ShellItem_get_parent_pidl(This, &parent_pidl);
146 if (SUCCEEDED(ret))
148 ret = SHGetDesktopFolder(&desktop);
149 if (SUCCEEDED(ret))
151 if (_ILIsDesktop(parent_pidl))
153 *ppsf = desktop;
155 else
157 ret = IShellFolder_BindToObject(desktop, parent_pidl, NULL, &IID_IShellFolder, (void**)ppsf);
158 IShellFolder_Release(desktop);
161 ILFree(parent_pidl);
164 return ret;
167 static HRESULT ShellItem_get_shellfolder(ShellItem *This, IBindCtx *pbc, IShellFolder **ppsf)
169 IShellFolder *desktop;
170 HRESULT ret;
172 ret = SHGetDesktopFolder(&desktop);
173 if (SUCCEEDED(ret))
175 if (_ILIsDesktop(This->pidl))
177 *ppsf = desktop;
178 IShellFolder_AddRef(*ppsf);
180 else
182 ret = IShellFolder_BindToObject(desktop, This->pidl, pbc, &IID_IShellFolder, (void**)ppsf);
185 IShellFolder_Release(desktop);
188 return ret;
191 static HRESULT WINAPI ShellItem_BindToHandler(IShellItem2 *iface, IBindCtx *pbc,
192 REFGUID rbhid, REFIID riid, void **ppvOut)
194 ShellItem *This = impl_from_IShellItem2(iface);
195 HRESULT ret;
196 TRACE("(%p,%p,%s,%p,%p)\n", iface, pbc, shdebugstr_guid(rbhid), riid, ppvOut);
198 *ppvOut = NULL;
199 if (IsEqualGUID(rbhid, &BHID_SFObject))
201 IShellFolder *psf;
202 ret = ShellItem_get_shellfolder(This, pbc, &psf);
203 if (SUCCEEDED(ret))
205 ret = IShellFolder_QueryInterface(psf, riid, ppvOut);
206 IShellFolder_Release(psf);
208 return ret;
210 else if (IsEqualGUID(rbhid, &BHID_SFUIObject))
212 IShellFolder *psf_parent;
213 if (_ILIsDesktop(This->pidl))
214 ret = SHGetDesktopFolder(&psf_parent);
215 else
216 ret = ShellItem_get_parent_shellfolder(This, &psf_parent);
218 if (SUCCEEDED(ret))
220 LPCITEMIDLIST pidl = ILFindLastID(This->pidl);
221 ret = IShellFolder_GetUIObjectOf(psf_parent, NULL, 1, &pidl, riid, NULL, ppvOut);
222 IShellFolder_Release(psf_parent);
224 return ret;
226 else if (IsEqualGUID(rbhid, &BHID_DataObject))
228 return ShellItem_BindToHandler(&This->IShellItem2_iface, pbc, &BHID_SFUIObject,
229 &IID_IDataObject, ppvOut);
232 FIXME("Unsupported BHID %s.\n", debugstr_guid(rbhid));
234 return MK_E_NOOBJECT;
237 static HRESULT WINAPI ShellItem_GetParent(IShellItem2 *iface, IShellItem **ppsi)
239 ShellItem *This = impl_from_IShellItem2(iface);
240 LPITEMIDLIST parent_pidl;
241 HRESULT ret;
243 TRACE("(%p,%p)\n", iface, ppsi);
245 ret = ShellItem_get_parent_pidl(This, &parent_pidl);
246 if (SUCCEEDED(ret))
248 ret = SHCreateShellItem(NULL, NULL, parent_pidl, ppsi);
249 ILFree(parent_pidl);
252 return ret;
255 static HRESULT WINAPI ShellItem_GetDisplayName(IShellItem2 *iface, SIGDN sigdnName,
256 LPWSTR *ppszName)
258 ShellItem *This = impl_from_IShellItem2(iface);
259 TRACE("(%p,%x,%p)\n", iface, sigdnName, ppszName);
261 return SHGetNameFromIDList(This->pidl, sigdnName, ppszName);
264 static HRESULT WINAPI ShellItem_GetAttributes(IShellItem2 *iface, SFGAOF sfgaoMask,
265 SFGAOF *psfgaoAttribs)
267 ShellItem *This = impl_from_IShellItem2(iface);
268 IShellFolder *parent_folder;
269 LPITEMIDLIST child_pidl;
270 HRESULT ret;
272 TRACE("(%p,%x,%p)\n", iface, sfgaoMask, psfgaoAttribs);
274 if (_ILIsDesktop(This->pidl))
275 ret = SHGetDesktopFolder(&parent_folder);
276 else
277 ret = ShellItem_get_parent_shellfolder(This, &parent_folder);
278 if (SUCCEEDED(ret))
280 child_pidl = ILFindLastID(This->pidl);
281 *psfgaoAttribs = sfgaoMask;
282 ret = IShellFolder_GetAttributesOf(parent_folder, 1, (LPCITEMIDLIST*)&child_pidl, psfgaoAttribs);
283 *psfgaoAttribs &= sfgaoMask;
284 IShellFolder_Release(parent_folder);
286 if (SUCCEEDED(ret))
288 if(sfgaoMask == *psfgaoAttribs)
289 return S_OK;
290 else
291 return S_FALSE;
295 return ret;
298 static HRESULT WINAPI ShellItem_Compare(IShellItem2 *iface, IShellItem *oth,
299 SICHINTF hint, int *piOrder)
301 LPWSTR dispname, dispname_oth;
302 HRESULT ret;
303 TRACE("(%p,%p,%x,%p)\n", iface, oth, hint, piOrder);
305 if(hint & (SICHINT_CANONICAL | SICHINT_ALLFIELDS))
306 FIXME("Unsupported flags 0x%08x\n", hint);
308 ret = IShellItem2_GetDisplayName(iface, SIGDN_DESKTOPABSOLUTEEDITING, &dispname);
309 if(SUCCEEDED(ret))
311 ret = IShellItem_GetDisplayName(oth, SIGDN_DESKTOPABSOLUTEEDITING, &dispname_oth);
312 if(SUCCEEDED(ret))
314 *piOrder = lstrcmpiW(dispname, dispname_oth);
315 CoTaskMemFree(dispname_oth);
317 CoTaskMemFree(dispname);
320 if(SUCCEEDED(ret) && *piOrder &&
321 (hint & SICHINT_TEST_FILESYSPATH_IF_NOT_EQUAL))
323 LPWSTR dispname, dispname_oth;
325 TRACE("Testing filesystem path.\n");
326 ret = IShellItem2_GetDisplayName(iface, SIGDN_FILESYSPATH, &dispname);
327 if(SUCCEEDED(ret))
329 ret = IShellItem_GetDisplayName(oth, SIGDN_FILESYSPATH, &dispname_oth);
330 if(SUCCEEDED(ret))
332 *piOrder = lstrcmpiW(dispname, dispname_oth);
333 CoTaskMemFree(dispname_oth);
335 CoTaskMemFree(dispname);
339 if(FAILED(ret))
340 return ret;
342 if(*piOrder)
343 return S_FALSE;
344 else
345 return S_OK;
348 static HRESULT WINAPI ShellItem2_GetPropertyStore(IShellItem2 *iface, GETPROPERTYSTOREFLAGS flags,
349 REFIID riid, void **ppv)
351 ShellItem *This = impl_from_IShellItem2(iface);
352 FIXME("Stub: %p (%d, %s, %p)\n", This, flags, shdebugstr_guid(riid), ppv);
353 return E_NOTIMPL;
356 static HRESULT WINAPI ShellItem2_GetPropertyStoreWithCreateObject(IShellItem2 *iface,
357 GETPROPERTYSTOREFLAGS flags, IUnknown *punkCreateObject, REFIID riid, void **ppv)
359 ShellItem *This = impl_from_IShellItem2(iface);
360 FIXME("Stub: %p (%08x, %p, %s, %p)\n",
361 This, flags, punkCreateObject, shdebugstr_guid(riid), ppv);
362 return E_NOTIMPL;
365 static HRESULT WINAPI ShellItem2_GetPropertyStoreForKeys(IShellItem2 *iface, const PROPERTYKEY *rgKeys,
366 UINT cKeys, GETPROPERTYSTOREFLAGS flags, REFIID riid, void **ppv)
368 ShellItem *This = impl_from_IShellItem2(iface);
369 FIXME("Stub: %p (%p, %d, %08x, %s, %p)\n",
370 This, rgKeys, cKeys, flags, shdebugstr_guid(riid), ppv);
371 return E_NOTIMPL;
374 static HRESULT WINAPI ShellItem2_GetPropertyDescriptionList(IShellItem2 *iface,
375 REFPROPERTYKEY keyType, REFIID riid, void **ppv)
377 ShellItem *This = impl_from_IShellItem2(iface);
378 FIXME("Stub: %p (%p, %s, %p)\n", This, keyType, debugstr_guid(riid), ppv);
379 return E_NOTIMPL;
382 static HRESULT WINAPI ShellItem2_Update(IShellItem2 *iface, IBindCtx *pbc)
384 ShellItem *This = impl_from_IShellItem2(iface);
385 FIXME("Stub: %p (%p)\n", This, pbc);
386 return E_NOTIMPL;
389 static HRESULT WINAPI ShellItem2_GetProperty(IShellItem2 *iface, REFPROPERTYKEY key, PROPVARIANT *ppropvar)
391 ShellItem *This = impl_from_IShellItem2(iface);
392 FIXME("Stub: %p (%p, %p)\n", This, key, ppropvar);
393 return E_NOTIMPL;
396 static HRESULT WINAPI ShellItem2_GetCLSID(IShellItem2 *iface, REFPROPERTYKEY key, CLSID *pclsid)
398 ShellItem *This = impl_from_IShellItem2(iface);
399 FIXME("Stub: %p (%p, %p)\n", This, key, pclsid);
400 return E_NOTIMPL;
403 static HRESULT WINAPI ShellItem2_GetFileTime(IShellItem2 *iface, REFPROPERTYKEY key, FILETIME *pft)
405 ShellItem *This = impl_from_IShellItem2(iface);
406 FIXME("Stub: %p (%p, %p)\n", This, key, pft);
407 return E_NOTIMPL;
410 static HRESULT WINAPI ShellItem2_GetInt32(IShellItem2 *iface, REFPROPERTYKEY key, int *pi)
412 ShellItem *This = impl_from_IShellItem2(iface);
413 FIXME("Stub: %p (%p, %p)\n", This, key, pi);
414 return E_NOTIMPL;
417 static HRESULT WINAPI ShellItem2_GetString(IShellItem2 *iface, REFPROPERTYKEY key, LPWSTR *ppsz)
419 ShellItem *This = impl_from_IShellItem2(iface);
420 FIXME("Stub: %p (%p, %p)\n", This, key, ppsz);
421 return E_NOTIMPL;
424 static HRESULT WINAPI ShellItem2_GetUInt32(IShellItem2 *iface, REFPROPERTYKEY key, ULONG *pui)
426 ShellItem *This = impl_from_IShellItem2(iface);
427 FIXME("Stub: %p (%p, %p)\n", This, key, pui);
428 return E_NOTIMPL;
431 static HRESULT WINAPI ShellItem2_GetUInt64(IShellItem2 *iface, REFPROPERTYKEY key, ULONGLONG *pull)
433 ShellItem *This = impl_from_IShellItem2(iface);
434 FIXME("Stub: %p (%p, %p)\n", This, key, pull);
435 return E_NOTIMPL;
438 static HRESULT WINAPI ShellItem2_GetBool(IShellItem2 *iface, REFPROPERTYKEY key, BOOL *pf)
440 ShellItem *This = impl_from_IShellItem2(iface);
441 FIXME("Stub: %p (%p, %p)\n", This, key, pf);
442 return E_NOTIMPL;
446 static const IShellItem2Vtbl ShellItem2_Vtbl = {
447 ShellItem_QueryInterface,
448 ShellItem_AddRef,
449 ShellItem_Release,
450 ShellItem_BindToHandler,
451 ShellItem_GetParent,
452 ShellItem_GetDisplayName,
453 ShellItem_GetAttributes,
454 ShellItem_Compare,
455 ShellItem2_GetPropertyStore,
456 ShellItem2_GetPropertyStoreWithCreateObject,
457 ShellItem2_GetPropertyStoreForKeys,
458 ShellItem2_GetPropertyDescriptionList,
459 ShellItem2_Update,
460 ShellItem2_GetProperty,
461 ShellItem2_GetCLSID,
462 ShellItem2_GetFileTime,
463 ShellItem2_GetInt32,
464 ShellItem2_GetString,
465 ShellItem2_GetUInt32,
466 ShellItem2_GetUInt64,
467 ShellItem2_GetBool
470 static HRESULT WINAPI ShellItem_IPersistIDList_QueryInterface(IPersistIDList *iface,
471 REFIID riid, void **ppv)
473 ShellItem *This = impl_from_IPersistIDList(iface);
474 return IShellItem2_QueryInterface(&This->IShellItem2_iface, riid, ppv);
477 static ULONG WINAPI ShellItem_IPersistIDList_AddRef(IPersistIDList *iface)
479 ShellItem *This = impl_from_IPersistIDList(iface);
480 return IShellItem2_AddRef(&This->IShellItem2_iface);
483 static ULONG WINAPI ShellItem_IPersistIDList_Release(IPersistIDList *iface)
485 ShellItem *This = impl_from_IPersistIDList(iface);
486 return IShellItem2_Release(&This->IShellItem2_iface);
489 static HRESULT WINAPI ShellItem_IPersistIDList_GetClassID(IPersistIDList* iface,
490 CLSID *pClassID)
492 *pClassID = CLSID_ShellItem;
493 return S_OK;
496 static HRESULT WINAPI ShellItem_IPersistIDList_SetIDList(IPersistIDList* iface,
497 LPCITEMIDLIST pidl)
499 ShellItem *This = impl_from_IPersistIDList(iface);
500 LPITEMIDLIST new_pidl;
502 TRACE("(%p,%p)\n", This, pidl);
504 new_pidl = ILClone(pidl);
506 if (new_pidl)
508 ILFree(This->pidl);
509 This->pidl = new_pidl;
510 return S_OK;
512 else
513 return E_OUTOFMEMORY;
516 static HRESULT WINAPI ShellItem_IPersistIDList_GetIDList(IPersistIDList* iface,
517 LPITEMIDLIST *ppidl)
519 ShellItem *This = impl_from_IPersistIDList(iface);
521 TRACE("(%p,%p)\n", This, ppidl);
523 *ppidl = ILClone(This->pidl);
524 if (*ppidl)
525 return S_OK;
526 else
527 return E_OUTOFMEMORY;
530 static const IPersistIDListVtbl ShellItem_IPersistIDList_Vtbl = {
531 ShellItem_IPersistIDList_QueryInterface,
532 ShellItem_IPersistIDList_AddRef,
533 ShellItem_IPersistIDList_Release,
534 ShellItem_IPersistIDList_GetClassID,
535 ShellItem_IPersistIDList_SetIDList,
536 ShellItem_IPersistIDList_GetIDList
540 HRESULT WINAPI IShellItem_Constructor(IUnknown *pUnkOuter, REFIID riid, void **ppv)
542 ShellItem *This;
543 HRESULT ret;
545 TRACE("(%p,%s)\n",pUnkOuter, debugstr_guid(riid));
547 *ppv = NULL;
549 if (pUnkOuter) return CLASS_E_NOAGGREGATION;
551 This = heap_alloc(sizeof(*This));
552 This->IShellItem2_iface.lpVtbl = &ShellItem2_Vtbl;
553 This->ref = 1;
554 This->pidl = NULL;
555 This->IPersistIDList_iface.lpVtbl = &ShellItem_IPersistIDList_Vtbl;
557 ret = IShellItem2_QueryInterface(&This->IShellItem2_iface, riid, ppv);
558 IShellItem2_Release(&This->IShellItem2_iface);
560 return ret;
563 HRESULT WINAPI SHCreateShellItem(LPCITEMIDLIST pidlParent,
564 IShellFolder *psfParent, LPCITEMIDLIST pidl, IShellItem **ppsi)
566 LPITEMIDLIST new_pidl;
567 HRESULT ret;
569 TRACE("(%p,%p,%p,%p)\n", pidlParent, psfParent, pidl, ppsi);
571 *ppsi = NULL;
573 if (!pidl)
575 return E_INVALIDARG;
577 else if (pidlParent || psfParent)
579 LPITEMIDLIST temp_parent=NULL;
580 if (!pidlParent)
582 IPersistFolder2* ppf2Parent;
584 if (FAILED(IShellFolder_QueryInterface(psfParent, &IID_IPersistFolder2, (void**)&ppf2Parent)))
586 FIXME("couldn't get IPersistFolder2 interface of parent\n");
587 return E_NOINTERFACE;
590 if (FAILED(IPersistFolder2_GetCurFolder(ppf2Parent, &temp_parent)))
592 FIXME("couldn't get parent PIDL\n");
593 IPersistFolder2_Release(ppf2Parent);
594 return E_NOINTERFACE;
597 pidlParent = temp_parent;
598 IPersistFolder2_Release(ppf2Parent);
601 new_pidl = ILCombine(pidlParent, pidl);
602 ILFree(temp_parent);
604 if (!new_pidl)
605 return E_OUTOFMEMORY;
607 else
609 new_pidl = ILClone(pidl);
610 if (!new_pidl)
611 return E_OUTOFMEMORY;
614 ret = SHCreateItemFromIDList(new_pidl, &IID_IShellItem, (void**)ppsi);
615 ILFree(new_pidl);
617 return ret;
620 HRESULT WINAPI SHCreateItemFromParsingName(PCWSTR pszPath,
621 IBindCtx *pbc, REFIID riid, void **ppv)
623 LPITEMIDLIST pidl;
624 HRESULT ret;
626 *ppv = NULL;
628 ret = SHParseDisplayName(pszPath, pbc, &pidl, 0, NULL);
629 if(SUCCEEDED(ret))
631 ret = SHCreateItemFromIDList(pidl, riid, ppv);
632 ILFree(pidl);
634 return ret;
637 HRESULT WINAPI SHCreateItemFromRelativeName(IShellItem *parent, PCWSTR name, IBindCtx *pbc,
638 REFIID riid, void **ppv)
640 LPITEMIDLIST pidl_folder = NULL, pidl = NULL;
641 IShellFolder *desktop = NULL, *folder = NULL;
642 HRESULT hr;
644 TRACE("(%p, %s, %p, %s, %p)\n", parent, wine_dbgstr_w(name), pbc, debugstr_guid(riid), ppv);
646 if(!ppv)
647 return E_INVALIDARG;
648 *ppv = NULL;
649 if(!name)
650 return E_INVALIDARG;
652 hr = SHGetIDListFromObject((IUnknown*)parent, &pidl_folder);
653 if(hr != S_OK)
654 return hr;
656 hr = SHGetDesktopFolder(&desktop);
657 if(hr != S_OK)
658 goto cleanup;
660 if(!_ILIsDesktop(pidl_folder))
662 hr = IShellFolder_BindToObject(desktop, pidl_folder, NULL, &IID_IShellFolder,
663 (void**)&folder);
664 if(hr != S_OK)
665 goto cleanup;
668 hr = IShellFolder_ParseDisplayName(folder ? folder : desktop, NULL, pbc, (LPWSTR)name,
669 NULL, &pidl, NULL);
670 if(hr != S_OK)
671 goto cleanup;
672 hr = SHCreateItemFromIDList(pidl, riid, ppv);
674 cleanup:
675 if(pidl_folder)
676 ILFree(pidl_folder);
677 if(pidl)
678 ILFree(pidl);
679 if(desktop)
680 IShellFolder_Release(desktop);
681 if(folder)
682 IShellFolder_Release(folder);
683 return hr;
686 HRESULT WINAPI SHCreateItemFromIDList(PCIDLIST_ABSOLUTE pidl, REFIID riid, void **ppv)
688 IPersistIDList *persist;
689 HRESULT ret;
691 if(!pidl)
692 return E_INVALIDARG;
694 *ppv = NULL;
695 ret = IShellItem_Constructor(NULL, &IID_IPersistIDList, (void**)&persist);
696 if(FAILED(ret))
697 return ret;
699 ret = IPersistIDList_SetIDList(persist, pidl);
700 if(FAILED(ret))
702 IPersistIDList_Release(persist);
703 return ret;
706 ret = IPersistIDList_QueryInterface(persist, riid, ppv);
707 IPersistIDList_Release(persist);
708 return ret;
711 HRESULT WINAPI SHCreateItemInKnownFolder(REFKNOWNFOLDERID rfid, DWORD flags,
712 PCWSTR filename, REFIID riid, void **ppv)
714 HRESULT hr;
715 IShellItem *parent = NULL;
716 LPITEMIDLIST pidl = NULL;
718 TRACE("(%p, %x, %s, %s, %p)\n", rfid, flags, wine_dbgstr_w(filename),
719 debugstr_guid(riid), ppv);
721 if(!rfid || !ppv)
722 return E_INVALIDARG;
724 *ppv = NULL;
725 hr = SHGetKnownFolderIDList(rfid, flags, NULL, &pidl);
726 if(hr != S_OK)
727 return hr;
729 hr = SHCreateItemFromIDList(pidl, &IID_IShellItem, (void**)&parent);
730 if(hr != S_OK)
732 ILFree(pidl);
733 return hr;
736 if(filename)
737 hr = SHCreateItemFromRelativeName(parent, filename, NULL, riid, ppv);
738 else
739 hr = IShellItem_QueryInterface(parent, riid, ppv);
741 ILFree(pidl);
742 IShellItem_Release(parent);
743 return hr;
746 HRESULT WINAPI SHGetItemFromDataObject(IDataObject *pdtobj,
747 DATAOBJ_GET_ITEM_FLAGS dwFlags, REFIID riid, void **ppv)
749 FORMATETC fmt;
750 STGMEDIUM medium;
751 HRESULT ret;
753 TRACE("%p, %x, %s, %p\n", pdtobj, dwFlags, debugstr_guid(riid), ppv);
755 if(!pdtobj)
756 return E_INVALIDARG;
758 fmt.cfFormat = RegisterClipboardFormatW(CFSTR_SHELLIDLISTW);
759 fmt.ptd = NULL;
760 fmt.dwAspect = DVASPECT_CONTENT;
761 fmt.lindex = -1;
762 fmt.tymed = TYMED_HGLOBAL;
764 ret = IDataObject_GetData(pdtobj, &fmt, &medium);
765 if(SUCCEEDED(ret))
767 LPIDA pida = GlobalLock(medium.u.hGlobal);
769 if((pida->cidl > 1 && !(dwFlags & DOGIF_ONLY_IF_ONE)) ||
770 pida->cidl == 1)
772 LPITEMIDLIST pidl;
774 /* Get the first pidl (parent + child1) */
775 pidl = ILCombine((LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[0]),
776 (LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[1]));
778 ret = SHCreateItemFromIDList(pidl, riid, ppv);
779 ILFree(pidl);
781 else
783 ret = E_FAIL;
786 GlobalUnlock(medium.u.hGlobal);
787 GlobalFree(medium.u.hGlobal);
790 if(FAILED(ret) && !(dwFlags & DOGIF_NO_HDROP))
792 TRACE("Attempting to fall back on CF_HDROP.\n");
794 fmt.cfFormat = CF_HDROP;
795 fmt.ptd = NULL;
796 fmt.dwAspect = DVASPECT_CONTENT;
797 fmt.lindex = -1;
798 fmt.tymed = TYMED_HGLOBAL;
800 ret = IDataObject_GetData(pdtobj, &fmt, &medium);
801 if(SUCCEEDED(ret))
803 DROPFILES *df = GlobalLock(medium.u.hGlobal);
804 LPBYTE files = (LPBYTE)df + df->pFiles;
805 BOOL multiple_files = FALSE;
807 ret = E_FAIL;
808 if(!df->fWide)
810 WCHAR filename[MAX_PATH];
811 PCSTR first_file = (PCSTR)files;
812 if(*(files + lstrlenA(first_file) + 1) != 0)
813 multiple_files = TRUE;
815 if( !(multiple_files && (dwFlags & DOGIF_ONLY_IF_ONE)) )
817 MultiByteToWideChar(CP_ACP, 0, first_file, -1, filename, MAX_PATH);
818 ret = SHCreateItemFromParsingName(filename, NULL, riid, ppv);
821 else
823 PCWSTR first_file = (PCWSTR)files;
824 if(*((PCWSTR)files + lstrlenW(first_file) + 1) != 0)
825 multiple_files = TRUE;
827 if( !(multiple_files && (dwFlags & DOGIF_ONLY_IF_ONE)) )
828 ret = SHCreateItemFromParsingName(first_file, NULL, riid, ppv);
831 GlobalUnlock(medium.u.hGlobal);
832 GlobalFree(medium.u.hGlobal);
836 if(FAILED(ret) && !(dwFlags & DOGIF_NO_URL))
838 FIXME("Failed to create item, should try CF_URL.\n");
841 return ret;
844 HRESULT WINAPI SHGetItemFromObject(IUnknown *punk, REFIID riid, void **ppv)
846 LPITEMIDLIST pidl;
847 HRESULT ret;
849 ret = SHGetIDListFromObject(punk, &pidl);
850 if(SUCCEEDED(ret))
852 ret = SHCreateItemFromIDList(pidl, riid, ppv);
853 ILFree(pidl);
856 return ret;
859 /*************************************************************************
860 * IEnumShellItems implementation
862 typedef struct {
863 IEnumShellItems IEnumShellItems_iface;
864 LONG ref;
866 IShellItemArray *array;
867 DWORD count;
868 DWORD position;
869 } IEnumShellItemsImpl;
871 static inline IEnumShellItemsImpl *impl_from_IEnumShellItems(IEnumShellItems *iface)
873 return CONTAINING_RECORD(iface, IEnumShellItemsImpl, IEnumShellItems_iface);
876 static HRESULT WINAPI IEnumShellItems_fnQueryInterface(IEnumShellItems *iface,
877 REFIID riid,
878 void **ppvObject)
880 IEnumShellItemsImpl *This = impl_from_IEnumShellItems(iface);
881 TRACE("%p (%s, %p)\n", This, shdebugstr_guid(riid), ppvObject);
883 *ppvObject = NULL;
884 if(IsEqualIID(riid, &IID_IEnumShellItems) ||
885 IsEqualIID(riid, &IID_IUnknown))
887 *ppvObject = &This->IEnumShellItems_iface;
890 if(*ppvObject)
892 IUnknown_AddRef((IUnknown*)*ppvObject);
893 return S_OK;
896 return E_NOINTERFACE;
899 static ULONG WINAPI IEnumShellItems_fnAddRef(IEnumShellItems *iface)
901 IEnumShellItemsImpl *This = impl_from_IEnumShellItems(iface);
902 LONG ref = InterlockedIncrement(&This->ref);
903 TRACE("%p - ref %d\n", This, ref);
905 return ref;
908 static ULONG WINAPI IEnumShellItems_fnRelease(IEnumShellItems *iface)
910 IEnumShellItemsImpl *This = impl_from_IEnumShellItems(iface);
911 LONG ref = InterlockedDecrement(&This->ref);
912 TRACE("%p - ref %d\n", This, ref);
914 if(!ref)
916 TRACE("Freeing.\n");
917 IShellItemArray_Release(This->array);
918 heap_free(This);
919 return 0;
922 return ref;
925 static HRESULT WINAPI IEnumShellItems_fnNext(IEnumShellItems* iface,
926 ULONG celt,
927 IShellItem **rgelt,
928 ULONG *pceltFetched)
930 IEnumShellItemsImpl *This = impl_from_IEnumShellItems(iface);
931 HRESULT hr = S_FALSE;
932 UINT i;
933 ULONG fetched = 0;
934 TRACE("%p (%d %p %p)\n", This, celt, rgelt, pceltFetched);
936 if(pceltFetched == NULL && celt != 1)
937 return E_INVALIDARG;
939 for(i = This->position; fetched < celt && i < This->count; i++) {
940 hr = IShellItemArray_GetItemAt(This->array, i, &rgelt[fetched]);
941 if(FAILED(hr))
942 break;
943 fetched++;
944 This->position++;
947 if(SUCCEEDED(hr))
949 if(pceltFetched != NULL)
950 *pceltFetched = fetched;
952 if(fetched > 0)
953 return S_OK;
955 return S_FALSE;
958 return hr;
961 static HRESULT WINAPI IEnumShellItems_fnSkip(IEnumShellItems* iface, ULONG celt)
963 IEnumShellItemsImpl *This = impl_from_IEnumShellItems(iface);
964 TRACE("%p (%d)\n", This, celt);
966 This->position = min(This->position + celt, This->count-1);
968 return S_OK;
971 static HRESULT WINAPI IEnumShellItems_fnReset(IEnumShellItems* iface)
973 IEnumShellItemsImpl *This = impl_from_IEnumShellItems(iface);
974 TRACE("%p\n", This);
976 This->position = 0;
978 return S_OK;
981 static HRESULT WINAPI IEnumShellItems_fnClone(IEnumShellItems* iface, IEnumShellItems **ppenum)
983 IEnumShellItemsImpl *This = impl_from_IEnumShellItems(iface);
984 TRACE("%p (%p)\n", This, ppenum);
986 /* Not implemented anywhere */
987 *ppenum = NULL;
989 return E_NOTIMPL;
992 static const IEnumShellItemsVtbl vt_IEnumShellItems = {
993 IEnumShellItems_fnQueryInterface,
994 IEnumShellItems_fnAddRef,
995 IEnumShellItems_fnRelease,
996 IEnumShellItems_fnNext,
997 IEnumShellItems_fnSkip,
998 IEnumShellItems_fnReset,
999 IEnumShellItems_fnClone
1002 static HRESULT IEnumShellItems_Constructor(IShellItemArray *array, IEnumShellItems **ppesi)
1004 IEnumShellItemsImpl *This;
1005 HRESULT ret;
1007 This = heap_alloc(sizeof(*This));
1008 if(!This)
1009 return E_OUTOFMEMORY;
1011 This->ref = 1;
1012 This->IEnumShellItems_iface.lpVtbl = &vt_IEnumShellItems;
1013 This->array = array;
1014 This->position = 0;
1016 IShellItemArray_AddRef(This->array);
1017 IShellItemArray_GetCount(This->array, &This->count);
1019 ret = IEnumShellItems_QueryInterface(&This->IEnumShellItems_iface, &IID_IEnumShellItems, (void**)ppesi);
1020 IEnumShellItems_Release(&This->IEnumShellItems_iface);
1022 return ret;
1026 /*************************************************************************
1027 * IShellItemArray implementation
1029 typedef struct {
1030 IShellItemArray IShellItemArray_iface;
1031 LONG ref;
1033 IShellItem **array;
1034 DWORD item_count;
1035 } IShellItemArrayImpl;
1037 static inline IShellItemArrayImpl *impl_from_IShellItemArray(IShellItemArray *iface)
1039 return CONTAINING_RECORD(iface, IShellItemArrayImpl, IShellItemArray_iface);
1042 static HRESULT WINAPI IShellItemArray_fnQueryInterface(IShellItemArray *iface,
1043 REFIID riid,
1044 void **ppvObject)
1046 IShellItemArrayImpl *This = impl_from_IShellItemArray(iface);
1047 TRACE("%p (%s, %p)\n", This, shdebugstr_guid(riid), ppvObject);
1049 *ppvObject = NULL;
1050 if(IsEqualIID(riid, &IID_IShellItemArray) ||
1051 IsEqualIID(riid, &IID_IUnknown))
1053 *ppvObject = &This->IShellItemArray_iface;
1056 if(*ppvObject)
1058 IUnknown_AddRef((IUnknown*)*ppvObject);
1059 return S_OK;
1062 return E_NOINTERFACE;
1065 static ULONG WINAPI IShellItemArray_fnAddRef(IShellItemArray *iface)
1067 IShellItemArrayImpl *This = impl_from_IShellItemArray(iface);
1068 LONG ref = InterlockedIncrement(&This->ref);
1069 TRACE("%p - ref %d\n", This, ref);
1071 return ref;
1074 static ULONG WINAPI IShellItemArray_fnRelease(IShellItemArray *iface)
1076 IShellItemArrayImpl *This = impl_from_IShellItemArray(iface);
1077 LONG ref = InterlockedDecrement(&This->ref);
1078 TRACE("%p - ref %d\n", This, ref);
1080 if(!ref)
1082 UINT i;
1083 TRACE("Freeing.\n");
1085 for(i = 0; i < This->item_count; i++)
1086 IShellItem_Release(This->array[i]);
1088 heap_free(This->array);
1089 heap_free(This);
1090 return 0;
1093 return ref;
1096 static HRESULT WINAPI IShellItemArray_fnBindToHandler(IShellItemArray *iface,
1097 IBindCtx *pbc,
1098 REFGUID bhid,
1099 REFIID riid,
1100 void **ppvOut)
1102 IShellItemArrayImpl *This = impl_from_IShellItemArray(iface);
1103 FIXME("Stub: %p (%p, %s, %s, %p)\n",
1104 This, pbc, shdebugstr_guid(bhid), shdebugstr_guid(riid), ppvOut);
1106 return E_NOTIMPL;
1109 static HRESULT WINAPI IShellItemArray_fnGetPropertyStore(IShellItemArray *iface,
1110 GETPROPERTYSTOREFLAGS flags,
1111 REFIID riid,
1112 void **ppv)
1114 IShellItemArrayImpl *This = impl_from_IShellItemArray(iface);
1115 FIXME("Stub: %p (%x, %s, %p)\n", This, flags, shdebugstr_guid(riid), ppv);
1117 return E_NOTIMPL;
1120 static HRESULT WINAPI IShellItemArray_fnGetPropertyDescriptionList(IShellItemArray *iface,
1121 REFPROPERTYKEY keyType,
1122 REFIID riid,
1123 void **ppv)
1125 IShellItemArrayImpl *This = impl_from_IShellItemArray(iface);
1126 FIXME("Stub: %p (%p, %s, %p)\n",
1127 This, keyType, shdebugstr_guid(riid), ppv);
1129 return E_NOTIMPL;
1132 static HRESULT WINAPI IShellItemArray_fnGetAttributes(IShellItemArray *iface,
1133 SIATTRIBFLAGS AttribFlags,
1134 SFGAOF sfgaoMask,
1135 SFGAOF *psfgaoAttribs)
1137 IShellItemArrayImpl *This = impl_from_IShellItemArray(iface);
1138 HRESULT hr = S_OK;
1139 SFGAOF attr;
1140 UINT i;
1141 TRACE("%p (%x, %x, %p)\n", This, AttribFlags, sfgaoMask, psfgaoAttribs);
1143 if(AttribFlags & ~(SIATTRIBFLAGS_AND|SIATTRIBFLAGS_OR))
1144 FIXME("%08x contains unsupported attribution flags\n", AttribFlags);
1146 for(i = 0; i < This->item_count; i++)
1148 hr = IShellItem_GetAttributes(This->array[i], sfgaoMask, &attr);
1149 if(FAILED(hr))
1150 break;
1152 if(i == 0)
1154 *psfgaoAttribs = attr;
1155 continue;
1158 switch(AttribFlags & SIATTRIBFLAGS_MASK)
1160 case SIATTRIBFLAGS_AND:
1161 *psfgaoAttribs &= attr;
1162 break;
1163 case SIATTRIBFLAGS_OR:
1164 *psfgaoAttribs |= attr;
1165 break;
1169 if(SUCCEEDED(hr))
1171 if(*psfgaoAttribs == sfgaoMask)
1172 return S_OK;
1174 return S_FALSE;
1177 return hr;
1180 static HRESULT WINAPI IShellItemArray_fnGetCount(IShellItemArray *iface,
1181 DWORD *pdwNumItems)
1183 IShellItemArrayImpl *This = impl_from_IShellItemArray(iface);
1184 TRACE("%p (%p)\n", This, pdwNumItems);
1186 *pdwNumItems = This->item_count;
1188 return S_OK;
1191 static HRESULT WINAPI IShellItemArray_fnGetItemAt(IShellItemArray *iface,
1192 DWORD dwIndex,
1193 IShellItem **ppsi)
1195 IShellItemArrayImpl *This = impl_from_IShellItemArray(iface);
1196 TRACE("%p (%x, %p)\n", This, dwIndex, ppsi);
1198 /* zero indexed */
1199 if(dwIndex + 1 > This->item_count)
1200 return E_FAIL;
1202 *ppsi = This->array[dwIndex];
1203 IShellItem_AddRef(*ppsi);
1205 return S_OK;
1208 static HRESULT WINAPI IShellItemArray_fnEnumItems(IShellItemArray *iface,
1209 IEnumShellItems **ppenumShellItems)
1211 IShellItemArrayImpl *This = impl_from_IShellItemArray(iface);
1212 TRACE("%p (%p)\n", This, ppenumShellItems);
1213 return IEnumShellItems_Constructor(iface, ppenumShellItems);
1216 static const IShellItemArrayVtbl vt_IShellItemArray = {
1217 IShellItemArray_fnQueryInterface,
1218 IShellItemArray_fnAddRef,
1219 IShellItemArray_fnRelease,
1220 IShellItemArray_fnBindToHandler,
1221 IShellItemArray_fnGetPropertyStore,
1222 IShellItemArray_fnGetPropertyDescriptionList,
1223 IShellItemArray_fnGetAttributes,
1224 IShellItemArray_fnGetCount,
1225 IShellItemArray_fnGetItemAt,
1226 IShellItemArray_fnEnumItems
1229 /* Caller is responsible to AddRef all items */
1230 static HRESULT create_shellitemarray(IShellItem **items, DWORD count, IShellItemArray **ret)
1232 IShellItemArrayImpl *This;
1234 TRACE("(%p, %d, %p)\n", items, count, ret);
1236 This = heap_alloc(sizeof(*This));
1237 if(!This)
1238 return E_OUTOFMEMORY;
1240 This->IShellItemArray_iface.lpVtbl = &vt_IShellItemArray;
1241 This->ref = 1;
1243 This->array = heap_alloc(count*sizeof(IShellItem*));
1244 if (!This->array)
1246 heap_free(This);
1247 return E_OUTOFMEMORY;
1249 memcpy(This->array, items, count*sizeof(IShellItem*));
1250 This->item_count = count;
1252 *ret = &This->IShellItemArray_iface;
1253 return S_OK;
1256 HRESULT WINAPI SHCreateShellItemArray(PCIDLIST_ABSOLUTE pidlParent,
1257 IShellFolder *psf,
1258 UINT cidl,
1259 PCUITEMID_CHILD_ARRAY ppidl,
1260 IShellItemArray **ppsiItemArray)
1262 IShellItem **array;
1263 HRESULT ret = E_FAIL;
1264 UINT i;
1266 TRACE("%p, %p, %d, %p, %p\n", pidlParent, psf, cidl, ppidl, ppsiItemArray);
1268 *ppsiItemArray = NULL;
1270 if(!pidlParent && !psf)
1271 return E_POINTER;
1273 if(!ppidl)
1274 return E_INVALIDARG;
1276 array = heap_alloc_zero(cidl*sizeof(IShellItem*));
1277 if(!array)
1278 return E_OUTOFMEMORY;
1280 for(i = 0; i < cidl; i++)
1282 ret = SHCreateShellItem(pidlParent, psf, ppidl[i], &array[i]);
1283 if(FAILED(ret)) break;
1286 if(SUCCEEDED(ret))
1288 ret = create_shellitemarray(array, cidl, ppsiItemArray);
1289 if(SUCCEEDED(ret))
1291 heap_free(array);
1292 return ret;
1296 /* Something failed, clean up. */
1297 for(i = 0; i < cidl; i++)
1298 if(array[i]) IShellItem_Release(array[i]);
1299 heap_free(array);
1300 return ret;
1303 HRESULT WINAPI SHCreateShellItemArrayFromShellItem(IShellItem *item, REFIID riid, void **ppv)
1305 IShellItemArray *array;
1306 HRESULT ret;
1308 TRACE("%p, %s, %p\n", item, shdebugstr_guid(riid), ppv);
1310 *ppv = NULL;
1312 IShellItem_AddRef(item);
1313 ret = create_shellitemarray(&item, 1, &array);
1314 if(FAILED(ret))
1316 IShellItem_Release(item);
1317 return ret;
1320 ret = IShellItemArray_QueryInterface(array, riid, ppv);
1321 IShellItemArray_Release(array);
1322 return ret;
1325 HRESULT WINAPI SHCreateShellItemArrayFromDataObject(IDataObject *pdo, REFIID riid, void **ppv)
1327 IShellItemArray *psia;
1328 FORMATETC fmt;
1329 STGMEDIUM medium;
1330 HRESULT ret;
1332 TRACE("%p, %s, %p\n", pdo, shdebugstr_guid(riid), ppv);
1334 if(!pdo)
1335 return E_INVALIDARG;
1337 *ppv = NULL;
1339 fmt.cfFormat = RegisterClipboardFormatW(CFSTR_SHELLIDLISTW);
1340 fmt.ptd = NULL;
1341 fmt.dwAspect = DVASPECT_CONTENT;
1342 fmt.lindex = -1;
1343 fmt.tymed = TYMED_HGLOBAL;
1345 ret = IDataObject_GetData(pdo, &fmt, &medium);
1346 if(SUCCEEDED(ret))
1348 LPIDA pida = GlobalLock(medium.u.hGlobal);
1349 LPCITEMIDLIST parent_pidl;
1350 LPCITEMIDLIST *children;
1351 UINT i;
1352 TRACE("Converting %d objects.\n", pida->cidl);
1354 parent_pidl = (LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[0]);
1356 children = heap_alloc(sizeof(LPCITEMIDLIST)*pida->cidl);
1357 for(i = 0; i < pida->cidl; i++)
1358 children[i] = (LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[i+1]);
1360 ret = SHCreateShellItemArray(parent_pidl, NULL, pida->cidl, children, &psia);
1362 heap_free(children);
1364 GlobalUnlock(medium.u.hGlobal);
1365 GlobalFree(medium.u.hGlobal);
1368 if(SUCCEEDED(ret))
1370 ret = IShellItemArray_QueryInterface(psia, riid, ppv);
1371 IShellItemArray_Release(psia);
1374 return ret;
1377 HRESULT WINAPI SHCreateShellItemArrayFromIDLists(UINT cidl,
1378 PCIDLIST_ABSOLUTE_ARRAY pidl_array,
1379 IShellItemArray **psia)
1381 IShellItem **array;
1382 HRESULT ret;
1383 UINT i;
1384 TRACE("%d, %p, %p\n", cidl, pidl_array, psia);
1386 *psia = NULL;
1388 if(cidl == 0)
1389 return E_INVALIDARG;
1391 array = heap_alloc_zero(cidl*sizeof(IShellItem*));
1392 if(!array)
1393 return E_OUTOFMEMORY;
1395 for(i = 0; i < cidl; i++)
1397 ret = SHCreateShellItem(NULL, NULL, pidl_array[i], &array[i]);
1398 if(FAILED(ret))
1399 break;
1402 if(SUCCEEDED(ret))
1404 ret = create_shellitemarray(array, cidl, psia);
1405 heap_free(array);
1406 if(SUCCEEDED(ret))
1407 return ret;
1410 for(i = 0; i < cidl; i++)
1411 if(array[i]) IShellItem_Release(array[i]);
1412 heap_free(array);
1413 *psia = NULL;
1414 return ret;
1417 HRESULT WINAPI SHGetPropertyStoreFromParsingName(const WCHAR *path, IBindCtx *pbc, GETPROPERTYSTOREFLAGS flags,
1418 REFIID riid, void **ppv)
1420 IShellItem2 *item;
1421 HRESULT hr;
1423 TRACE("(%s %p %#x %p %p)\n", debugstr_w(path), pbc, flags, riid, ppv);
1425 hr = SHCreateItemFromParsingName(path, pbc, &IID_IShellItem2, (void **)&item);
1426 if(SUCCEEDED(hr))
1428 hr = IShellItem2_GetPropertyStore(item, flags, riid, ppv);
1429 IShellItem2_Release(item);
1432 return hr;
1435 static HRESULT WINAPI CustomDestinationList_QueryInterface(ICustomDestinationList *iface, REFIID riid, void **obj)
1437 CustomDestinationList *This = impl_from_ICustomDestinationList(iface);
1439 TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), obj);
1441 if (IsEqualIID(&IID_ICustomDestinationList, riid) || IsEqualIID(&IID_IUnknown, riid))
1443 *obj = &This->ICustomDestinationList_iface;
1445 else {
1446 WARN("Unsupported interface %s.\n", shdebugstr_guid(riid));
1447 *obj = NULL;
1448 return E_NOINTERFACE;
1451 IUnknown_AddRef((IUnknown*)*obj);
1452 return S_OK;
1455 static ULONG WINAPI CustomDestinationList_AddRef(ICustomDestinationList *iface)
1457 CustomDestinationList *This = impl_from_ICustomDestinationList(iface);
1458 ULONG ref = InterlockedIncrement(&This->ref);
1460 TRACE("(%p), new refcount=%i\n", This, ref);
1462 return ref;
1465 static ULONG WINAPI CustomDestinationList_Release(ICustomDestinationList *iface)
1467 CustomDestinationList *This = impl_from_ICustomDestinationList(iface);
1468 ULONG ref = InterlockedDecrement(&This->ref);
1470 TRACE("(%p), new refcount=%i\n", This, ref);
1472 if (ref == 0)
1473 heap_free(This);
1475 return ref;
1478 static HRESULT WINAPI CustomDestinationList_SetAppID(ICustomDestinationList *iface, const WCHAR *appid)
1480 CustomDestinationList *This = impl_from_ICustomDestinationList(iface);
1482 FIXME("%p (%s): stub\n", This, debugstr_w(appid));
1484 return E_NOTIMPL;
1487 static HRESULT WINAPI CustomDestinationList_BeginList(ICustomDestinationList *iface, UINT *min_slots, REFIID riid, void **obj)
1489 CustomDestinationList *This = impl_from_ICustomDestinationList(iface);
1491 FIXME("%p (%p %s %p): stub\n", This, min_slots, debugstr_guid(riid), obj);
1493 return E_NOTIMPL;
1496 static HRESULT WINAPI CustomDestinationList_AppendCategory(ICustomDestinationList *iface, const WCHAR *category, IObjectArray *array)
1498 CustomDestinationList *This = impl_from_ICustomDestinationList(iface);
1500 FIXME("%p (%s %p): stub\n", This, debugstr_w(category), array);
1502 return E_NOTIMPL;
1505 static HRESULT WINAPI CustomDestinationList_AppendKnownCategory(ICustomDestinationList *iface, KNOWNDESTCATEGORY category)
1507 CustomDestinationList *This = impl_from_ICustomDestinationList(iface);
1509 FIXME("%p (%d): stub\n", This, category);
1511 return E_NOTIMPL;
1514 static HRESULT WINAPI CustomDestinationList_AddUserTasks(ICustomDestinationList *iface, IObjectArray *tasks)
1516 CustomDestinationList *This = impl_from_ICustomDestinationList(iface);
1518 FIXME("%p (%p): stub\n", This, tasks);
1520 return E_NOTIMPL;
1523 static HRESULT WINAPI CustomDestinationList_CommitList(ICustomDestinationList *iface)
1525 CustomDestinationList *This = impl_from_ICustomDestinationList(iface);
1527 FIXME("%p: stub\n", This);
1529 return E_NOTIMPL;
1532 static HRESULT WINAPI CustomDestinationList_GetRemovedDestinations(ICustomDestinationList *iface, REFIID riid, void **obj)
1534 CustomDestinationList *This = impl_from_ICustomDestinationList(iface);
1536 FIXME("%p (%s %p): stub\n", This, debugstr_guid(riid), obj);
1538 return E_NOTIMPL;
1541 static HRESULT WINAPI CustomDestinationList_DeleteList(ICustomDestinationList *iface, const WCHAR *appid)
1543 CustomDestinationList *This = impl_from_ICustomDestinationList(iface);
1545 FIXME("%p (%s): stub\n", This, debugstr_w(appid));
1547 return E_NOTIMPL;
1550 static HRESULT WINAPI CustomDestinationList_AbortList(ICustomDestinationList *iface)
1552 CustomDestinationList *This = impl_from_ICustomDestinationList(iface);
1554 FIXME("%p: stub\n", This);
1556 return E_NOTIMPL;
1559 static const ICustomDestinationListVtbl CustomDestinationListVtbl =
1561 CustomDestinationList_QueryInterface,
1562 CustomDestinationList_AddRef,
1563 CustomDestinationList_Release,
1564 CustomDestinationList_SetAppID,
1565 CustomDestinationList_BeginList,
1566 CustomDestinationList_AppendCategory,
1567 CustomDestinationList_AppendKnownCategory,
1568 CustomDestinationList_AddUserTasks,
1569 CustomDestinationList_CommitList,
1570 CustomDestinationList_GetRemovedDestinations,
1571 CustomDestinationList_DeleteList,
1572 CustomDestinationList_AbortList
1575 HRESULT WINAPI CustomDestinationList_Constructor(IUnknown *outer, REFIID riid, void **obj)
1577 CustomDestinationList *list;
1578 HRESULT hr;
1580 TRACE("%p %s %p\n", outer, debugstr_guid(riid), obj);
1582 if (outer)
1583 return CLASS_E_NOAGGREGATION;
1585 if(!(list = heap_alloc(sizeof(*list))))
1586 return E_OUTOFMEMORY;
1588 list->ICustomDestinationList_iface.lpVtbl = &CustomDestinationListVtbl;
1589 list->ref = 1;
1591 hr = ICustomDestinationList_QueryInterface(&list->ICustomDestinationList_iface, riid, obj);
1592 ICustomDestinationList_Release(&list->ICustomDestinationList_iface);
1593 return hr;