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 FIXME("(%p,%x,%p)\n", iface, sigdnName, ppszName);
188 static HRESULT WINAPI ShellItem_GetAttributes(IShellItem *iface, SFGAOF sfgaoMask,
189 SFGAOF *psfgaoAttribs)
191 ShellItem *This = (ShellItem*)iface;
192 IShellFolder *parent_folder;
193 LPITEMIDLIST child_pidl;
196 TRACE("(%p,%x,%p)\n", iface, sfgaoMask, psfgaoAttribs);
198 ret = ShellItem_get_parent_shellfolder(This, &parent_folder);
201 child_pidl = ILFindLastID(This->pidl);
202 *psfgaoAttribs = sfgaoMask;
203 ret = IShellFolder_GetAttributesOf(parent_folder, 1, (LPCITEMIDLIST*)&child_pidl, psfgaoAttribs);
204 IShellFolder_Release(parent_folder);
210 static HRESULT WINAPI ShellItem_Compare(IShellItem *iface, IShellItem *oth,
211 SICHINTF hint, int *piOrder)
213 FIXME("(%p,%p,%x,%p)\n", iface, oth, hint, piOrder);
218 static const IShellItemVtbl ShellItem_Vtbl = {
219 ShellItem_QueryInterface,
222 ShellItem_BindToHandler,
224 ShellItem_GetDisplayName,
225 ShellItem_GetAttributes,
230 static HRESULT ShellItem_GetClassID(ShellItem* This, CLSID *pClassID)
232 TRACE("(%p,%p)\n", This, pClassID);
234 *pClassID = CLSID_ShellItem;
239 static HRESULT WINAPI ShellItem_IPersistIDList_QueryInterface(IPersistIDList *iface,
240 REFIID riid, void **ppv)
242 ShellItem *This = impl_from_IPersistIDList(iface);
243 return ShellItem_QueryInterface((IShellItem*)This, riid, ppv);
246 static ULONG WINAPI ShellItem_IPersistIDList_AddRef(IPersistIDList *iface)
248 ShellItem *This = impl_from_IPersistIDList(iface);
249 return ShellItem_AddRef((IShellItem*)This);
252 static ULONG WINAPI ShellItem_IPersistIDList_Release(IPersistIDList *iface)
254 ShellItem *This = impl_from_IPersistIDList(iface);
255 return ShellItem_Release((IShellItem*)This);
258 static HRESULT WINAPI ShellItem_IPersistIDList_GetClassID(IPersistIDList* iface,
261 ShellItem *This = impl_from_IPersistIDList(iface);
263 return ShellItem_GetClassID(This, pClassID);
266 static HRESULT WINAPI ShellItem_IPersistIDList_SetIDList(IPersistIDList* iface,
269 ShellItem *This = impl_from_IPersistIDList(iface);
270 LPITEMIDLIST new_pidl;
272 TRACE("(%p,%p)\n", This, pidl);
274 new_pidl = ILClone(pidl);
279 This->pidl = new_pidl;
283 return E_OUTOFMEMORY;
286 static HRESULT WINAPI ShellItem_IPersistIDList_GetIDList(IPersistIDList* iface,
289 ShellItem *This = impl_from_IPersistIDList(iface);
291 TRACE("(%p,%p)\n", This, ppidl);
293 *ppidl = ILClone(This->pidl);
297 return E_OUTOFMEMORY;
300 static const IPersistIDListVtbl ShellItem_IPersistIDList_Vtbl = {
301 ShellItem_IPersistIDList_QueryInterface,
302 ShellItem_IPersistIDList_AddRef,
303 ShellItem_IPersistIDList_Release,
304 ShellItem_IPersistIDList_GetClassID,
305 ShellItem_IPersistIDList_SetIDList,
306 ShellItem_IPersistIDList_GetIDList
310 HRESULT WINAPI IShellItem_Constructor(IUnknown *pUnkOuter, REFIID riid, void **ppv)
315 TRACE("(%p,%s)\n",pUnkOuter, debugstr_guid(riid));
319 if (pUnkOuter) return CLASS_E_NOAGGREGATION;
321 This = HeapAlloc(GetProcessHeap(), 0, sizeof(ShellItem));
322 This->lpIShellItemVtbl = &ShellItem_Vtbl;
325 This->lpIPersistIDListVtbl = &ShellItem_IPersistIDList_Vtbl;
327 ret = ShellItem_QueryInterface((IShellItem*)This, riid, ppv);
328 ShellItem_Release((IShellItem*)This);
333 HRESULT WINAPI SHCreateShellItem(LPCITEMIDLIST pidlParent,
334 IShellFolder *psfParent, LPCITEMIDLIST pidl, IShellItem **ppsi)
337 LPITEMIDLIST new_pidl;
340 TRACE("(%p,%p,%p,%p)\n", pidlParent, psfParent, pidl, ppsi);
346 else if (pidlParent || psfParent)
348 LPITEMIDLIST temp_parent=NULL;
351 IPersistFolder2* ppf2Parent;
353 if (!SUCCEEDED(IPersistFolder2_QueryInterface(psfParent, &IID_IPersistFolder2, (void**)&ppf2Parent)))
355 FIXME("couldn't get IPersistFolder2 interface of parent\n");
356 return E_NOINTERFACE;
359 if (!SUCCEEDED(IPersistFolder2_GetCurFolder(ppf2Parent, &temp_parent)))
361 FIXME("couldn't get parent PIDL\n");
362 IPersistFolder2_Release(ppf2Parent);
363 return E_NOINTERFACE;
366 pidlParent = temp_parent;
367 IPersistFolder2_Release(ppf2Parent);
370 new_pidl = ILCombine(pidlParent, pidl);
374 return E_OUTOFMEMORY;
378 new_pidl = ILClone(pidl);
380 return E_OUTOFMEMORY;
383 ret = IShellItem_Constructor(NULL, &IID_IShellItem, (void**)&This);
386 *ppsi = (IShellItem*)This;
387 This->pidl = new_pidl;