2 * IShellItem implementation
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
22 #include "wine/port.h"
28 #define NONAMELESSUNION
29 #define NONAMELESSSTRUCT
33 #include "wine/debug.h"
36 #include "shell32_main.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(shell);
41 typedef struct _ShellItem {
42 const IShellItemVtbl *lpIShellItemVtbl;
45 const IPersistIDListVtbl *lpIPersistIDListVtbl;
49 static inline ShellItem *impl_from_IPersistIDList( IPersistIDList *iface )
51 return (ShellItem*)((char*)iface - FIELD_OFFSET(ShellItem, lpIPersistIDListVtbl));
55 static HRESULT WINAPI ShellItem_QueryInterface(IShellItem *iface, REFIID riid,
58 ShellItem *This = (ShellItem*)iface;
60 TRACE("(%p,%p,%p)\n", iface, riid, ppv);
62 if (!ppv) return E_INVALIDARG;
64 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IShellItem, riid))
68 else if (IsEqualIID(&IID_IPersist, riid) || IsEqualIID(&IID_IPersistIDList, riid))
70 *ppv = &(This->lpIPersistIDListVtbl);
73 FIXME("not implemented for %s\n", shdebugstr_guid(riid));
78 IUnknown_AddRef((IUnknown*)*ppv);
82 static ULONG WINAPI ShellItem_AddRef(IShellItem *iface)
84 ShellItem *This = (ShellItem*)iface;
85 ULONG ref = InterlockedIncrement(&This->ref);
87 TRACE("(%p), new refcount=%i\n", iface, ref);
92 static ULONG WINAPI ShellItem_Release(IShellItem *iface)
94 ShellItem *This = (ShellItem*)iface;
95 ULONG ref = InterlockedDecrement(&This->ref);
97 TRACE("(%p), new refcount=%i\n", iface, ref);
102 HeapFree(GetProcessHeap(), 0, This);
108 static HRESULT ShellItem_get_parent_pidl(ShellItem *This, LPITEMIDLIST *parent_pidl)
110 *parent_pidl = ILClone(This->pidl);
113 if (ILRemoveLastID(*parent_pidl))
117 ILFree(*parent_pidl);
125 return E_OUTOFMEMORY;
129 static HRESULT ShellItem_get_parent_shellfolder(ShellItem *This, IShellFolder **ppsf)
131 LPITEMIDLIST parent_pidl;
132 IShellFolder *desktop;
135 ret = ShellItem_get_parent_pidl(This, &parent_pidl);
138 ret = SHGetDesktopFolder(&desktop);
141 ret = IShellFolder_BindToObject(desktop, parent_pidl, NULL, &IID_IShellFolder, (void**)ppsf);
142 IShellFolder_Release(desktop);
150 static HRESULT WINAPI ShellItem_BindToHandler(IShellItem *iface, IBindCtx *pbc,
151 REFGUID rbhid, REFIID riid, void **ppvOut)
153 FIXME("(%p,%p,%s,%p,%p)\n", iface, pbc, shdebugstr_guid(rbhid), riid, ppvOut);
160 static HRESULT WINAPI ShellItem_GetParent(IShellItem *iface, IShellItem **ppsi)
162 ShellItem *This = (ShellItem*)iface;
163 LPITEMIDLIST parent_pidl;
166 TRACE("(%p,%p)\n", iface, ppsi);
168 ret = ShellItem_get_parent_pidl(This, &parent_pidl);
171 ret = SHCreateShellItem(NULL, NULL, parent_pidl, ppsi);
178 static HRESULT WINAPI ShellItem_GetDisplayName(IShellItem *iface, SIGDN sigdnName,
181 ShellItem *This = (ShellItem*)iface;
182 TRACE("(%p,%x,%p)\n", iface, sigdnName, ppszName);
184 return SHGetNameFromIDList(This->pidl, sigdnName, ppszName);
187 static HRESULT WINAPI ShellItem_GetAttributes(IShellItem *iface, SFGAOF sfgaoMask,
188 SFGAOF *psfgaoAttribs)
190 ShellItem *This = (ShellItem*)iface;
191 IShellFolder *parent_folder;
192 LPITEMIDLIST child_pidl;
195 TRACE("(%p,%x,%p)\n", iface, sfgaoMask, psfgaoAttribs);
197 ret = ShellItem_get_parent_shellfolder(This, &parent_folder);
200 child_pidl = ILFindLastID(This->pidl);
201 *psfgaoAttribs = sfgaoMask;
202 ret = IShellFolder_GetAttributesOf(parent_folder, 1, (LPCITEMIDLIST*)&child_pidl, psfgaoAttribs);
203 IShellFolder_Release(parent_folder);
209 static HRESULT WINAPI ShellItem_Compare(IShellItem *iface, IShellItem *oth,
210 SICHINTF hint, int *piOrder)
212 FIXME("(%p,%p,%x,%p)\n", iface, oth, hint, piOrder);
217 static const IShellItemVtbl ShellItem_Vtbl = {
218 ShellItem_QueryInterface,
221 ShellItem_BindToHandler,
223 ShellItem_GetDisplayName,
224 ShellItem_GetAttributes,
229 static HRESULT ShellItem_GetClassID(ShellItem* This, CLSID *pClassID)
231 TRACE("(%p,%p)\n", This, pClassID);
233 *pClassID = CLSID_ShellItem;
238 static HRESULT WINAPI ShellItem_IPersistIDList_QueryInterface(IPersistIDList *iface,
239 REFIID riid, void **ppv)
241 ShellItem *This = impl_from_IPersistIDList(iface);
242 return ShellItem_QueryInterface((IShellItem*)This, riid, ppv);
245 static ULONG WINAPI ShellItem_IPersistIDList_AddRef(IPersistIDList *iface)
247 ShellItem *This = impl_from_IPersistIDList(iface);
248 return ShellItem_AddRef((IShellItem*)This);
251 static ULONG WINAPI ShellItem_IPersistIDList_Release(IPersistIDList *iface)
253 ShellItem *This = impl_from_IPersistIDList(iface);
254 return ShellItem_Release((IShellItem*)This);
257 static HRESULT WINAPI ShellItem_IPersistIDList_GetClassID(IPersistIDList* iface,
260 ShellItem *This = impl_from_IPersistIDList(iface);
262 return ShellItem_GetClassID(This, pClassID);
265 static HRESULT WINAPI ShellItem_IPersistIDList_SetIDList(IPersistIDList* iface,
268 ShellItem *This = impl_from_IPersistIDList(iface);
269 LPITEMIDLIST new_pidl;
271 TRACE("(%p,%p)\n", This, pidl);
273 new_pidl = ILClone(pidl);
278 This->pidl = new_pidl;
282 return E_OUTOFMEMORY;
285 static HRESULT WINAPI ShellItem_IPersistIDList_GetIDList(IPersistIDList* iface,
288 ShellItem *This = impl_from_IPersistIDList(iface);
290 TRACE("(%p,%p)\n", This, ppidl);
292 *ppidl = ILClone(This->pidl);
296 return E_OUTOFMEMORY;
299 static const IPersistIDListVtbl ShellItem_IPersistIDList_Vtbl = {
300 ShellItem_IPersistIDList_QueryInterface,
301 ShellItem_IPersistIDList_AddRef,
302 ShellItem_IPersistIDList_Release,
303 ShellItem_IPersistIDList_GetClassID,
304 ShellItem_IPersistIDList_SetIDList,
305 ShellItem_IPersistIDList_GetIDList
309 HRESULT WINAPI IShellItem_Constructor(IUnknown *pUnkOuter, REFIID riid, void **ppv)
314 TRACE("(%p,%s)\n",pUnkOuter, debugstr_guid(riid));
318 if (pUnkOuter) return CLASS_E_NOAGGREGATION;
320 This = HeapAlloc(GetProcessHeap(), 0, sizeof(ShellItem));
321 This->lpIShellItemVtbl = &ShellItem_Vtbl;
324 This->lpIPersistIDListVtbl = &ShellItem_IPersistIDList_Vtbl;
326 ret = ShellItem_QueryInterface((IShellItem*)This, riid, ppv);
327 ShellItem_Release((IShellItem*)This);
332 HRESULT WINAPI SHCreateShellItem(LPCITEMIDLIST pidlParent,
333 IShellFolder *psfParent, LPCITEMIDLIST pidl, IShellItem **ppsi)
336 LPITEMIDLIST new_pidl;
339 TRACE("(%p,%p,%p,%p)\n", pidlParent, psfParent, pidl, ppsi);
345 else if (pidlParent || psfParent)
347 LPITEMIDLIST temp_parent=NULL;
350 IPersistFolder2* ppf2Parent;
352 if (FAILED(IPersistFolder2_QueryInterface(psfParent, &IID_IPersistFolder2, (void**)&ppf2Parent)))
354 FIXME("couldn't get IPersistFolder2 interface of parent\n");
355 return E_NOINTERFACE;
358 if (FAILED(IPersistFolder2_GetCurFolder(ppf2Parent, &temp_parent)))
360 FIXME("couldn't get parent PIDL\n");
361 IPersistFolder2_Release(ppf2Parent);
362 return E_NOINTERFACE;
365 pidlParent = temp_parent;
366 IPersistFolder2_Release(ppf2Parent);
369 new_pidl = ILCombine(pidlParent, pidl);
373 return E_OUTOFMEMORY;
377 new_pidl = ILClone(pidl);
379 return E_OUTOFMEMORY;
382 ret = IShellItem_Constructor(NULL, &IID_IShellItem, (void**)&This);
385 *ppsi = (IShellItem*)This;
386 This->pidl = new_pidl;
396 HRESULT WINAPI SHCreateItemFromParsingName(PCWSTR pszPath,
397 IBindCtx *pbc, REFIID riid, void **ppv)
404 ret = SHParseDisplayName(pszPath, pbc, &pidl, 0, NULL);
408 ret = IShellItem_Constructor(NULL, riid, (void**)&This);
423 HRESULT WINAPI SHCreateItemFromIDList(PCIDLIST_ABSOLUTE pidl, REFIID riid, void **ppv)
431 ret = IShellItem_Constructor(NULL, riid, ppv);
434 psiimpl = (ShellItem*)*ppv;
435 psiimpl->pidl = ILClone(pidl);