shlwapi: Implement SHPropertyBag_ReadLONG.
[wine.git] / dlls / shell32 / shellitem.c
blob29f072fdb56181ebb24cef6643a69875a3e17899
1 /*
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
21 #include "config.h"
22 #include "wine/port.h"
24 #include <stdio.h>
25 #include <stdarg.h>
27 #define COBJMACROS
28 #define NONAMELESSUNION
29 #define NONAMELESSSTRUCT
31 #include "windef.h"
32 #include "winbase.h"
33 #include "wine/debug.h"
35 #include "pidl.h"
36 #include "shell32_main.h"
37 #include "debughlp.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(shell);
41 typedef struct _ShellItem {
42 const IShellItemVtbl *lpIShellItemVtbl;
43 LONG ref;
44 LPITEMIDLIST pidl;
45 const IPersistIDListVtbl *lpIPersistIDListVtbl;
46 } ShellItem;
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,
56 void **ppv)
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))
66 *ppv = This;
68 else if (IsEqualIID(&IID_IPersist, riid) || IsEqualIID(&IID_IPersistIDList, riid))
70 *ppv = &(This->lpIPersistIDListVtbl);
72 else {
73 FIXME("not implemented for %s\n", shdebugstr_guid(riid));
74 *ppv = NULL;
75 return E_NOINTERFACE;
78 IUnknown_AddRef((IUnknown*)*ppv);
79 return S_OK;
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);
89 return 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);
99 if (ref == 0)
101 ILFree(This->pidl);
102 HeapFree(GetProcessHeap(), 0, This);
105 return ref;
108 static HRESULT ShellItem_get_parent_pidl(ShellItem *This, LPITEMIDLIST *parent_pidl)
110 *parent_pidl = ILClone(This->pidl);
111 if (*parent_pidl)
113 if (ILRemoveLastID(*parent_pidl))
114 return S_OK;
115 else
117 ILFree(*parent_pidl);
118 *parent_pidl = NULL;
119 return E_INVALIDARG;
122 else
124 *parent_pidl = NULL;
125 return E_OUTOFMEMORY;
129 static HRESULT ShellItem_get_parent_shellfolder(ShellItem *This, IShellFolder **ppsf)
131 LPITEMIDLIST parent_pidl;
132 IShellFolder *desktop;
133 HRESULT ret;
135 ret = ShellItem_get_parent_pidl(This, &parent_pidl);
136 if (SUCCEEDED(ret))
138 ret = SHGetDesktopFolder(&desktop);
139 if (SUCCEEDED(ret))
141 ret = IShellFolder_BindToObject(desktop, parent_pidl, NULL, &IID_IShellFolder, (void**)ppsf);
142 IShellFolder_Release(desktop);
144 ILFree(parent_pidl);
147 return ret;
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);
155 *ppvOut = NULL;
157 return E_NOTIMPL;
160 static HRESULT WINAPI ShellItem_GetParent(IShellItem *iface, IShellItem **ppsi)
162 ShellItem *This = (ShellItem*)iface;
163 LPITEMIDLIST parent_pidl;
164 HRESULT ret;
166 TRACE("(%p,%p)\n", iface, ppsi);
168 ret = ShellItem_get_parent_pidl(This, &parent_pidl);
169 if (SUCCEEDED(ret))
171 ret = SHCreateShellItem(NULL, NULL, parent_pidl, ppsi);
172 ILFree(parent_pidl);
175 return ret;
178 static HRESULT WINAPI ShellItem_GetDisplayName(IShellItem *iface, SIGDN sigdnName,
179 LPWSTR *ppszName)
181 FIXME("(%p,%x,%p)\n", iface, sigdnName, ppszName);
183 *ppszName = NULL;
185 return E_NOTIMPL;
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;
194 HRESULT ret;
196 TRACE("(%p,%x,%p)\n", iface, sfgaoMask, psfgaoAttribs);
198 ret = ShellItem_get_parent_shellfolder(This, &parent_folder);
199 if (SUCCEEDED(ret))
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);
207 return ret;
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);
215 return E_NOTIMPL;
218 static const IShellItemVtbl ShellItem_Vtbl = {
219 ShellItem_QueryInterface,
220 ShellItem_AddRef,
221 ShellItem_Release,
222 ShellItem_BindToHandler,
223 ShellItem_GetParent,
224 ShellItem_GetDisplayName,
225 ShellItem_GetAttributes,
226 ShellItem_Compare
230 static HRESULT ShellItem_GetClassID(ShellItem* This, CLSID *pClassID)
232 TRACE("(%p,%p)\n", This, pClassID);
234 *pClassID = CLSID_ShellItem;
235 return S_OK;
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,
259 CLSID *pClassID)
261 ShellItem *This = impl_from_IPersistIDList(iface);
263 return ShellItem_GetClassID(This, pClassID);
266 static HRESULT WINAPI ShellItem_IPersistIDList_SetIDList(IPersistIDList* iface,
267 LPCITEMIDLIST pidl)
269 ShellItem *This = impl_from_IPersistIDList(iface);
270 LPITEMIDLIST new_pidl;
272 TRACE("(%p,%p)\n", This, pidl);
274 new_pidl = ILClone(pidl);
276 if (new_pidl)
278 ILFree(This->pidl);
279 This->pidl = new_pidl;
280 return S_OK;
282 else
283 return E_OUTOFMEMORY;
286 static HRESULT WINAPI ShellItem_IPersistIDList_GetIDList(IPersistIDList* iface,
287 LPITEMIDLIST *ppidl)
289 ShellItem *This = impl_from_IPersistIDList(iface);
291 TRACE("(%p,%p)\n", This, ppidl);
293 *ppidl = ILClone(This->pidl);
294 if (*ppidl)
295 return S_OK;
296 else
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)
312 ShellItem *This;
313 HRESULT ret;
315 TRACE("(%p,%s)\n",pUnkOuter, debugstr_guid(riid));
317 *ppv = NULL;
319 if (pUnkOuter) return CLASS_E_NOAGGREGATION;
321 This = HeapAlloc(GetProcessHeap(), 0, sizeof(ShellItem));
322 This->lpIShellItemVtbl = &ShellItem_Vtbl;
323 This->ref = 1;
324 This->pidl = NULL;
325 This->lpIPersistIDListVtbl = &ShellItem_IPersistIDList_Vtbl;
327 ret = ShellItem_QueryInterface((IShellItem*)This, riid, ppv);
328 ShellItem_Release((IShellItem*)This);
330 return ret;
333 HRESULT WINAPI SHCreateShellItem(LPCITEMIDLIST pidlParent,
334 IShellFolder *psfParent, LPCITEMIDLIST pidl, IShellItem **ppsi)
336 ShellItem *This;
337 LPITEMIDLIST new_pidl;
338 HRESULT ret;
340 TRACE("(%p,%p,%p,%p)\n", pidlParent, psfParent, pidl, ppsi);
342 if (!pidl)
344 return E_INVALIDARG;
346 else if (pidlParent || psfParent)
348 LPITEMIDLIST temp_parent=NULL;
349 if (!pidlParent)
351 IPersistFolder2* ppf2Parent;
353 if (FAILED(IPersistFolder2_QueryInterface(psfParent, &IID_IPersistFolder2, (void**)&ppf2Parent)))
355 FIXME("couldn't get IPersistFolder2 interface of parent\n");
356 return E_NOINTERFACE;
359 if (FAILED(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);
371 ILFree(temp_parent);
373 if (!new_pidl)
374 return E_OUTOFMEMORY;
376 else
378 new_pidl = ILClone(pidl);
379 if (!new_pidl)
380 return E_OUTOFMEMORY;
383 ret = IShellItem_Constructor(NULL, &IID_IShellItem, (void**)&This);
384 if (This)
386 *ppsi = (IShellItem*)This;
387 This->pidl = new_pidl;
389 else
391 *ppsi = NULL;
392 ILFree(new_pidl);
394 return ret;