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
;