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
25 #define NONAMELESSUNION
29 #include "wine/debug.h"
32 #include "shell32_main.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
37 typedef struct _ShellItem
{
38 IShellItem2 IShellItem2_iface
;
41 IPersistIDList IPersistIDList_iface
;
44 typedef struct _CustomDestinationList
{
45 ICustomDestinationList ICustomDestinationList_iface
;
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
,
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
;
83 FIXME("not implemented for %s\n", shdebugstr_guid(riid
));
88 IUnknown_AddRef((IUnknown
*)*ppv
);
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
);
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
);
118 static HRESULT
ShellItem_get_parent_pidl(ShellItem
*This
, LPITEMIDLIST
*parent_pidl
)
120 *parent_pidl
= ILClone(This
->pidl
);
123 if (ILRemoveLastID(*parent_pidl
))
127 ILFree(*parent_pidl
);
135 return E_OUTOFMEMORY
;
139 static HRESULT
ShellItem_get_parent_shellfolder(ShellItem
*This
, IShellFolder
**ppsf
)
141 LPITEMIDLIST parent_pidl
;
142 IShellFolder
*desktop
;
145 ret
= ShellItem_get_parent_pidl(This
, &parent_pidl
);
148 ret
= SHGetDesktopFolder(&desktop
);
151 if (_ILIsDesktop(parent_pidl
))
157 ret
= IShellFolder_BindToObject(desktop
, parent_pidl
, NULL
, &IID_IShellFolder
, (void**)ppsf
);
158 IShellFolder_Release(desktop
);
167 static HRESULT
ShellItem_get_shellfolder(ShellItem
*This
, IBindCtx
*pbc
, IShellFolder
**ppsf
)
169 IShellFolder
*desktop
;
172 ret
= SHGetDesktopFolder(&desktop
);
175 if (_ILIsDesktop(This
->pidl
))
178 IShellFolder_AddRef(*ppsf
);
182 ret
= IShellFolder_BindToObject(desktop
, This
->pidl
, pbc
, &IID_IShellFolder
, (void**)ppsf
);
185 IShellFolder_Release(desktop
);
191 static HRESULT WINAPI
ShellItem_BindToHandler(IShellItem2
*iface
, IBindCtx
*pbc
,
192 REFGUID rbhid
, REFIID riid
, void **ppvOut
)
194 ShellItem
*This
= impl_from_IShellItem2(iface
);
196 TRACE("(%p,%p,%s,%p,%p)\n", iface
, pbc
, shdebugstr_guid(rbhid
), riid
, ppvOut
);
199 if (IsEqualGUID(rbhid
, &BHID_SFObject
))
202 ret
= ShellItem_get_shellfolder(This
, pbc
, &psf
);
205 ret
= IShellFolder_QueryInterface(psf
, riid
, ppvOut
);
206 IShellFolder_Release(psf
);
210 else if (IsEqualGUID(rbhid
, &BHID_SFUIObject
))
212 IShellFolder
*psf_parent
;
213 if (_ILIsDesktop(This
->pidl
))
214 ret
= SHGetDesktopFolder(&psf_parent
);
216 ret
= ShellItem_get_parent_shellfolder(This
, &psf_parent
);
220 LPCITEMIDLIST pidl
= ILFindLastID(This
->pidl
);
221 ret
= IShellFolder_GetUIObjectOf(psf_parent
, NULL
, 1, &pidl
, riid
, NULL
, ppvOut
);
222 IShellFolder_Release(psf_parent
);
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
;
243 TRACE("(%p,%p)\n", iface
, ppsi
);
245 ret
= ShellItem_get_parent_pidl(This
, &parent_pidl
);
248 ret
= SHCreateShellItem(NULL
, NULL
, parent_pidl
, ppsi
);
255 static HRESULT WINAPI
ShellItem_GetDisplayName(IShellItem2
*iface
, SIGDN sigdnName
,
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
;
272 TRACE("(%p,%x,%p)\n", iface
, sfgaoMask
, psfgaoAttribs
);
274 if (_ILIsDesktop(This
->pidl
))
275 ret
= SHGetDesktopFolder(&parent_folder
);
277 ret
= ShellItem_get_parent_shellfolder(This
, &parent_folder
);
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
);
288 if(sfgaoMask
== *psfgaoAttribs
)
298 static HRESULT WINAPI
ShellItem_Compare(IShellItem2
*iface
, IShellItem
*oth
,
299 SICHINTF hint
, int *piOrder
)
301 LPWSTR dispname
, dispname_oth
;
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
);
311 ret
= IShellItem_GetDisplayName(oth
, SIGDN_DESKTOPABSOLUTEEDITING
, &dispname_oth
);
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
);
329 ret
= IShellItem_GetDisplayName(oth
, SIGDN_FILESYSPATH
, &dispname_oth
);
332 *piOrder
= lstrcmpiW(dispname
, dispname_oth
);
333 CoTaskMemFree(dispname_oth
);
335 CoTaskMemFree(dispname
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
446 static const IShellItem2Vtbl ShellItem2_Vtbl
= {
447 ShellItem_QueryInterface
,
450 ShellItem_BindToHandler
,
452 ShellItem_GetDisplayName
,
453 ShellItem_GetAttributes
,
455 ShellItem2_GetPropertyStore
,
456 ShellItem2_GetPropertyStoreWithCreateObject
,
457 ShellItem2_GetPropertyStoreForKeys
,
458 ShellItem2_GetPropertyDescriptionList
,
460 ShellItem2_GetProperty
,
462 ShellItem2_GetFileTime
,
464 ShellItem2_GetString
,
465 ShellItem2_GetUInt32
,
466 ShellItem2_GetUInt64
,
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
,
492 *pClassID
= CLSID_ShellItem
;
496 static HRESULT WINAPI
ShellItem_IPersistIDList_SetIDList(IPersistIDList
* iface
,
499 ShellItem
*This
= impl_from_IPersistIDList(iface
);
500 LPITEMIDLIST new_pidl
;
502 TRACE("(%p,%p)\n", This
, pidl
);
504 new_pidl
= ILClone(pidl
);
509 This
->pidl
= new_pidl
;
513 return E_OUTOFMEMORY
;
516 static HRESULT WINAPI
ShellItem_IPersistIDList_GetIDList(IPersistIDList
* iface
,
519 ShellItem
*This
= impl_from_IPersistIDList(iface
);
521 TRACE("(%p,%p)\n", This
, ppidl
);
523 *ppidl
= ILClone(This
->pidl
);
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
)
545 TRACE("(%p,%s)\n",pUnkOuter
, debugstr_guid(riid
));
549 if (pUnkOuter
) return CLASS_E_NOAGGREGATION
;
551 This
= heap_alloc(sizeof(*This
));
552 This
->IShellItem2_iface
.lpVtbl
= &ShellItem2_Vtbl
;
555 This
->IPersistIDList_iface
.lpVtbl
= &ShellItem_IPersistIDList_Vtbl
;
557 ret
= IShellItem2_QueryInterface(&This
->IShellItem2_iface
, riid
, ppv
);
558 IShellItem2_Release(&This
->IShellItem2_iface
);
563 HRESULT WINAPI
SHCreateShellItem(LPCITEMIDLIST pidlParent
,
564 IShellFolder
*psfParent
, LPCITEMIDLIST pidl
, IShellItem
**ppsi
)
566 LPITEMIDLIST new_pidl
;
569 TRACE("(%p,%p,%p,%p)\n", pidlParent
, psfParent
, pidl
, ppsi
);
577 else if (pidlParent
|| psfParent
)
579 LPITEMIDLIST temp_parent
=NULL
;
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
);
605 return E_OUTOFMEMORY
;
609 new_pidl
= ILClone(pidl
);
611 return E_OUTOFMEMORY
;
614 ret
= SHCreateItemFromIDList(new_pidl
, &IID_IShellItem
, (void**)ppsi
);
620 HRESULT WINAPI
SHCreateItemFromParsingName(PCWSTR pszPath
,
621 IBindCtx
*pbc
, REFIID riid
, void **ppv
)
628 ret
= SHParseDisplayName(pszPath
, pbc
, &pidl
, 0, NULL
);
631 ret
= SHCreateItemFromIDList(pidl
, riid
, ppv
);
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
;
644 TRACE("(%p, %s, %p, %s, %p)\n", parent
, wine_dbgstr_w(name
), pbc
, debugstr_guid(riid
), ppv
);
652 hr
= SHGetIDListFromObject((IUnknown
*)parent
, &pidl_folder
);
656 hr
= SHGetDesktopFolder(&desktop
);
660 if(!_ILIsDesktop(pidl_folder
))
662 hr
= IShellFolder_BindToObject(desktop
, pidl_folder
, NULL
, &IID_IShellFolder
,
668 hr
= IShellFolder_ParseDisplayName(folder
? folder
: desktop
, NULL
, pbc
, (LPWSTR
)name
,
672 hr
= SHCreateItemFromIDList(pidl
, riid
, ppv
);
680 IShellFolder_Release(desktop
);
682 IShellFolder_Release(folder
);
686 HRESULT WINAPI
SHCreateItemFromIDList(PCIDLIST_ABSOLUTE pidl
, REFIID riid
, void **ppv
)
688 IPersistIDList
*persist
;
695 ret
= IShellItem_Constructor(NULL
, &IID_IPersistIDList
, (void**)&persist
);
699 ret
= IPersistIDList_SetIDList(persist
, pidl
);
702 IPersistIDList_Release(persist
);
706 ret
= IPersistIDList_QueryInterface(persist
, riid
, ppv
);
707 IPersistIDList_Release(persist
);
711 HRESULT WINAPI
SHCreateItemInKnownFolder(REFKNOWNFOLDERID rfid
, DWORD flags
,
712 PCWSTR filename
, REFIID riid
, void **ppv
)
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
);
725 hr
= SHGetKnownFolderIDList(rfid
, flags
, NULL
, &pidl
);
729 hr
= SHCreateItemFromIDList(pidl
, &IID_IShellItem
, (void**)&parent
);
737 hr
= SHCreateItemFromRelativeName(parent
, filename
, NULL
, riid
, ppv
);
739 hr
= IShellItem_QueryInterface(parent
, riid
, ppv
);
742 IShellItem_Release(parent
);
746 HRESULT WINAPI
SHGetItemFromDataObject(IDataObject
*pdtobj
,
747 DATAOBJ_GET_ITEM_FLAGS dwFlags
, REFIID riid
, void **ppv
)
753 TRACE("%p, %x, %s, %p\n", pdtobj
, dwFlags
, debugstr_guid(riid
), ppv
);
758 fmt
.cfFormat
= RegisterClipboardFormatW(CFSTR_SHELLIDLISTW
);
760 fmt
.dwAspect
= DVASPECT_CONTENT
;
762 fmt
.tymed
= TYMED_HGLOBAL
;
764 ret
= IDataObject_GetData(pdtobj
, &fmt
, &medium
);
767 LPIDA pida
= GlobalLock(medium
.u
.hGlobal
);
769 if((pida
->cidl
> 1 && !(dwFlags
& DOGIF_ONLY_IF_ONE
)) ||
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
);
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
;
796 fmt
.dwAspect
= DVASPECT_CONTENT
;
798 fmt
.tymed
= TYMED_HGLOBAL
;
800 ret
= IDataObject_GetData(pdtobj
, &fmt
, &medium
);
803 DROPFILES
*df
= GlobalLock(medium
.u
.hGlobal
);
804 LPBYTE files
= (LPBYTE
)df
+ df
->pFiles
;
805 BOOL multiple_files
= FALSE
;
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
);
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");
844 HRESULT WINAPI
SHGetItemFromObject(IUnknown
*punk
, REFIID riid
, void **ppv
)
849 ret
= SHGetIDListFromObject(punk
, &pidl
);
852 ret
= SHCreateItemFromIDList(pidl
, riid
, ppv
);
859 /*************************************************************************
860 * IEnumShellItems implementation
863 IEnumShellItems IEnumShellItems_iface
;
866 IShellItemArray
*array
;
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
,
880 IEnumShellItemsImpl
*This
= impl_from_IEnumShellItems(iface
);
881 TRACE("%p (%s, %p)\n", This
, shdebugstr_guid(riid
), ppvObject
);
884 if(IsEqualIID(riid
, &IID_IEnumShellItems
) ||
885 IsEqualIID(riid
, &IID_IUnknown
))
887 *ppvObject
= &This
->IEnumShellItems_iface
;
892 IUnknown_AddRef((IUnknown
*)*ppvObject
);
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
);
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
);
917 IShellItemArray_Release(This
->array
);
925 static HRESULT WINAPI
IEnumShellItems_fnNext(IEnumShellItems
* iface
,
930 IEnumShellItemsImpl
*This
= impl_from_IEnumShellItems(iface
);
931 HRESULT hr
= S_FALSE
;
934 TRACE("%p (%d %p %p)\n", This
, celt
, rgelt
, pceltFetched
);
936 if(pceltFetched
== NULL
&& celt
!= 1)
939 for(i
= This
->position
; fetched
< celt
&& i
< This
->count
; i
++) {
940 hr
= IShellItemArray_GetItemAt(This
->array
, i
, &rgelt
[fetched
]);
949 if(pceltFetched
!= NULL
)
950 *pceltFetched
= fetched
;
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);
971 static HRESULT WINAPI
IEnumShellItems_fnReset(IEnumShellItems
* iface
)
973 IEnumShellItemsImpl
*This
= impl_from_IEnumShellItems(iface
);
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 */
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
;
1007 This
= heap_alloc(sizeof(*This
));
1009 return E_OUTOFMEMORY
;
1012 This
->IEnumShellItems_iface
.lpVtbl
= &vt_IEnumShellItems
;
1013 This
->array
= array
;
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
);
1026 /*************************************************************************
1027 * IShellItemArray implementation
1030 IShellItemArray IShellItemArray_iface
;
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
,
1046 IShellItemArrayImpl
*This
= impl_from_IShellItemArray(iface
);
1047 TRACE("%p (%s, %p)\n", This
, shdebugstr_guid(riid
), ppvObject
);
1050 if(IsEqualIID(riid
, &IID_IShellItemArray
) ||
1051 IsEqualIID(riid
, &IID_IUnknown
))
1053 *ppvObject
= &This
->IShellItemArray_iface
;
1058 IUnknown_AddRef((IUnknown
*)*ppvObject
);
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
);
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
);
1083 TRACE("Freeing.\n");
1085 for(i
= 0; i
< This
->item_count
; i
++)
1086 IShellItem_Release(This
->array
[i
]);
1088 heap_free(This
->array
);
1096 static HRESULT WINAPI
IShellItemArray_fnBindToHandler(IShellItemArray
*iface
,
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
);
1109 static HRESULT WINAPI
IShellItemArray_fnGetPropertyStore(IShellItemArray
*iface
,
1110 GETPROPERTYSTOREFLAGS flags
,
1114 IShellItemArrayImpl
*This
= impl_from_IShellItemArray(iface
);
1115 FIXME("Stub: %p (%x, %s, %p)\n", This
, flags
, shdebugstr_guid(riid
), ppv
);
1120 static HRESULT WINAPI
IShellItemArray_fnGetPropertyDescriptionList(IShellItemArray
*iface
,
1121 REFPROPERTYKEY keyType
,
1125 IShellItemArrayImpl
*This
= impl_from_IShellItemArray(iface
);
1126 FIXME("Stub: %p (%p, %s, %p)\n",
1127 This
, keyType
, shdebugstr_guid(riid
), ppv
);
1132 static HRESULT WINAPI
IShellItemArray_fnGetAttributes(IShellItemArray
*iface
,
1133 SIATTRIBFLAGS AttribFlags
,
1135 SFGAOF
*psfgaoAttribs
)
1137 IShellItemArrayImpl
*This
= impl_from_IShellItemArray(iface
);
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
);
1154 *psfgaoAttribs
= attr
;
1158 switch(AttribFlags
& SIATTRIBFLAGS_MASK
)
1160 case SIATTRIBFLAGS_AND
:
1161 *psfgaoAttribs
&= attr
;
1163 case SIATTRIBFLAGS_OR
:
1164 *psfgaoAttribs
|= attr
;
1171 if(*psfgaoAttribs
== sfgaoMask
)
1180 static HRESULT WINAPI
IShellItemArray_fnGetCount(IShellItemArray
*iface
,
1183 IShellItemArrayImpl
*This
= impl_from_IShellItemArray(iface
);
1184 TRACE("%p (%p)\n", This
, pdwNumItems
);
1186 *pdwNumItems
= This
->item_count
;
1191 static HRESULT WINAPI
IShellItemArray_fnGetItemAt(IShellItemArray
*iface
,
1195 IShellItemArrayImpl
*This
= impl_from_IShellItemArray(iface
);
1196 TRACE("%p (%x, %p)\n", This
, dwIndex
, ppsi
);
1199 if(dwIndex
+ 1 > This
->item_count
)
1202 *ppsi
= This
->array
[dwIndex
];
1203 IShellItem_AddRef(*ppsi
);
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
));
1238 return E_OUTOFMEMORY
;
1240 This
->IShellItemArray_iface
.lpVtbl
= &vt_IShellItemArray
;
1243 This
->array
= heap_alloc(count
*sizeof(IShellItem
*));
1247 return E_OUTOFMEMORY
;
1249 memcpy(This
->array
, items
, count
*sizeof(IShellItem
*));
1250 This
->item_count
= count
;
1252 *ret
= &This
->IShellItemArray_iface
;
1256 HRESULT WINAPI
SHCreateShellItemArray(PCIDLIST_ABSOLUTE pidlParent
,
1259 PCUITEMID_CHILD_ARRAY ppidl
,
1260 IShellItemArray
**ppsiItemArray
)
1263 HRESULT ret
= E_FAIL
;
1266 TRACE("%p, %p, %d, %p, %p\n", pidlParent
, psf
, cidl
, ppidl
, ppsiItemArray
);
1268 *ppsiItemArray
= NULL
;
1270 if(!pidlParent
&& !psf
)
1274 return E_INVALIDARG
;
1276 array
= heap_alloc_zero(cidl
*sizeof(IShellItem
*));
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;
1288 ret
= create_shellitemarray(array
, cidl
, ppsiItemArray
);
1296 /* Something failed, clean up. */
1297 for(i
= 0; i
< cidl
; i
++)
1298 if(array
[i
]) IShellItem_Release(array
[i
]);
1303 HRESULT WINAPI
SHCreateShellItemArrayFromShellItem(IShellItem
*item
, REFIID riid
, void **ppv
)
1305 IShellItemArray
*array
;
1308 TRACE("%p, %s, %p\n", item
, shdebugstr_guid(riid
), ppv
);
1312 IShellItem_AddRef(item
);
1313 ret
= create_shellitemarray(&item
, 1, &array
);
1316 IShellItem_Release(item
);
1320 ret
= IShellItemArray_QueryInterface(array
, riid
, ppv
);
1321 IShellItemArray_Release(array
);
1325 HRESULT WINAPI
SHCreateShellItemArrayFromDataObject(IDataObject
*pdo
, REFIID riid
, void **ppv
)
1327 IShellItemArray
*psia
;
1332 TRACE("%p, %s, %p\n", pdo
, shdebugstr_guid(riid
), ppv
);
1335 return E_INVALIDARG
;
1339 fmt
.cfFormat
= RegisterClipboardFormatW(CFSTR_SHELLIDLISTW
);
1341 fmt
.dwAspect
= DVASPECT_CONTENT
;
1343 fmt
.tymed
= TYMED_HGLOBAL
;
1345 ret
= IDataObject_GetData(pdo
, &fmt
, &medium
);
1348 LPIDA pida
= GlobalLock(medium
.u
.hGlobal
);
1349 LPCITEMIDLIST parent_pidl
;
1350 LPCITEMIDLIST
*children
;
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
);
1370 ret
= IShellItemArray_QueryInterface(psia
, riid
, ppv
);
1371 IShellItemArray_Release(psia
);
1377 HRESULT WINAPI
SHCreateShellItemArrayFromIDLists(UINT cidl
,
1378 PCIDLIST_ABSOLUTE_ARRAY pidl_array
,
1379 IShellItemArray
**psia
)
1384 TRACE("%d, %p, %p\n", cidl
, pidl_array
, psia
);
1389 return E_INVALIDARG
;
1391 array
= heap_alloc_zero(cidl
*sizeof(IShellItem
*));
1393 return E_OUTOFMEMORY
;
1395 for(i
= 0; i
< cidl
; i
++)
1397 ret
= SHCreateShellItem(NULL
, NULL
, pidl_array
[i
], &array
[i
]);
1404 ret
= create_shellitemarray(array
, cidl
, psia
);
1410 for(i
= 0; i
< cidl
; i
++)
1411 if(array
[i
]) IShellItem_Release(array
[i
]);
1417 HRESULT WINAPI
SHGetPropertyStoreFromParsingName(const WCHAR
*path
, IBindCtx
*pbc
, GETPROPERTYSTOREFLAGS flags
,
1418 REFIID riid
, void **ppv
)
1423 TRACE("(%s %p %#x %p %p)\n", debugstr_w(path
), pbc
, flags
, riid
, ppv
);
1425 hr
= SHCreateItemFromParsingName(path
, pbc
, &IID_IShellItem2
, (void **)&item
);
1428 hr
= IShellItem2_GetPropertyStore(item
, flags
, riid
, ppv
);
1429 IShellItem2_Release(item
);
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
;
1446 WARN("Unsupported interface %s.\n", shdebugstr_guid(riid
));
1448 return E_NOINTERFACE
;
1451 IUnknown_AddRef((IUnknown
*)*obj
);
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
);
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
);
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
));
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
);
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
);
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
);
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
);
1523 static HRESULT WINAPI
CustomDestinationList_CommitList(ICustomDestinationList
*iface
)
1525 CustomDestinationList
*This
= impl_from_ICustomDestinationList(iface
);
1527 FIXME("%p: stub\n", This
);
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
);
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
));
1550 static HRESULT WINAPI
CustomDestinationList_AbortList(ICustomDestinationList
*iface
)
1552 CustomDestinationList
*This
= impl_from_ICustomDestinationList(iface
);
1554 FIXME("%p: stub\n", This
);
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
;
1580 TRACE("%p %s %p\n", outer
, debugstr_guid(riid
), obj
);
1583 return CLASS_E_NOAGGREGATION
;
1585 if(!(list
= heap_alloc(sizeof(*list
))))
1586 return E_OUTOFMEMORY
;
1588 list
->ICustomDestinationList_iface
.lpVtbl
= &CustomDestinationListVtbl
;
1591 hr
= ICustomDestinationList_QueryInterface(&list
->ICustomDestinationList_iface
, riid
, obj
);
1592 ICustomDestinationList_Release(&list
->ICustomDestinationList_iface
);