shell32/tests: Skip some tests on Win95 because of W-functions.
[wine] / dlls / shell32 / shellitem.c
1 /*
2  * IShellItem implementation
3  *
4  * Copyright 2008 Vincent Povirk for CodeWeavers
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include "config.h"
22 #include "wine/port.h"
23
24 #include <stdio.h>
25 #include <stdarg.h>
26
27 #define COBJMACROS
28 #define NONAMELESSUNION
29 #define NONAMELESSSTRUCT
30
31 #include "windef.h"
32 #include "winbase.h"
33 #include "wine/debug.h"
34
35 #include "pidl.h"
36 #include "shell32_main.h"
37 #include "debughlp.h"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(shell);
40
41 typedef struct _ShellItem {
42     const IShellItemVtbl    *lpIShellItemVtbl;
43     LONG                    ref;
44     LPITEMIDLIST            pidl;
45     const IPersistIDListVtbl *lpIPersistIDListVtbl;
46 } ShellItem;
47
48
49 static inline ShellItem *impl_from_IPersistIDList( IPersistIDList *iface )
50 {
51     return (ShellItem*)((char*)iface - FIELD_OFFSET(ShellItem, lpIPersistIDListVtbl));
52 }
53
54
55 static HRESULT WINAPI ShellItem_QueryInterface(IShellItem *iface, REFIID riid,
56     void **ppv)
57 {
58     ShellItem *This = (ShellItem*)iface;
59
60     TRACE("(%p,%p,%p)\n", iface, riid, ppv);
61
62     if (!ppv) return E_INVALIDARG;
63
64     if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IShellItem, riid))
65     {
66         *ppv = This;
67     }
68     else if (IsEqualIID(&IID_IPersist, riid) || IsEqualIID(&IID_IPersistIDList, riid))
69     {
70         *ppv = &(This->lpIPersistIDListVtbl);
71     }
72     else {
73         FIXME("not implemented for %s\n", shdebugstr_guid(riid));
74         *ppv = NULL;
75         return E_NOINTERFACE;
76     }
77
78     IUnknown_AddRef((IUnknown*)*ppv);
79     return S_OK;
80 }
81
82 static ULONG WINAPI ShellItem_AddRef(IShellItem *iface)
83 {
84     ShellItem *This = (ShellItem*)iface;
85     ULONG ref = InterlockedIncrement(&This->ref);
86
87     TRACE("(%p), new refcount=%i\n", iface, ref);
88
89     return ref;
90 }
91
92 static ULONG WINAPI ShellItem_Release(IShellItem *iface)
93 {
94     ShellItem *This = (ShellItem*)iface;
95     ULONG ref = InterlockedDecrement(&This->ref);
96
97     TRACE("(%p), new refcount=%i\n", iface, ref);
98
99     if (ref == 0)
100     {
101         ILFree(This->pidl);
102         HeapFree(GetProcessHeap(), 0, This);
103     }
104
105     return ref;
106 }
107
108 static HRESULT WINAPI ShellItem_BindToHandler(IShellItem *iface, IBindCtx *pbc,
109     REFGUID rbhid, REFIID riid, void **ppvOut)
110 {
111     FIXME("(%p,%p,%s,%p,%p)\n", iface, pbc, shdebugstr_guid(rbhid), riid, ppvOut);
112
113     *ppvOut = NULL;
114
115     return E_NOTIMPL;
116 }
117
118 static HRESULT WINAPI ShellItem_GetParent(IShellItem *iface, IShellItem **ppsi)
119 {
120     FIXME("(%p,%p)\n", iface, ppsi);
121
122     *ppsi = NULL;
123
124     return E_NOTIMPL;
125 }
126
127 static HRESULT WINAPI ShellItem_GetDisplayName(IShellItem *iface, SIGDN sigdnName,
128     LPWSTR *ppszName)
129 {
130     FIXME("(%p,%x,%p)\n", iface, sigdnName, ppszName);
131
132     *ppszName = NULL;
133
134     return E_NOTIMPL;
135 }
136
137 static HRESULT WINAPI ShellItem_GetAttributes(IShellItem *iface, SFGAOF sfgaoMask,
138     SFGAOF *psfgaoAttribs)
139 {
140     FIXME("(%p,%x,%p)\n", iface, sfgaoMask, psfgaoAttribs);
141
142     *psfgaoAttribs = 0;
143
144     return E_NOTIMPL;
145 }
146
147 static HRESULT WINAPI ShellItem_Compare(IShellItem *iface, IShellItem *oth,
148     SICHINTF hint, int *piOrder)
149 {
150     FIXME("(%p,%p,%x,%p)\n", iface, oth, hint, piOrder);
151
152     return E_NOTIMPL;
153 }
154
155 static const IShellItemVtbl ShellItem_Vtbl = {
156     ShellItem_QueryInterface,
157     ShellItem_AddRef,
158     ShellItem_Release,
159     ShellItem_BindToHandler,
160     ShellItem_GetParent,
161     ShellItem_GetDisplayName,
162     ShellItem_GetAttributes,
163     ShellItem_Compare
164 };
165
166
167 static HRESULT ShellItem_GetClassID(ShellItem* This, CLSID *pClassID)
168 {
169     TRACE("(%p,%p)\n", This, pClassID);
170
171     *pClassID = CLSID_ShellItem;
172     return S_OK;
173 }
174
175
176 static HRESULT WINAPI ShellItem_IPersistIDList_QueryInterface(IPersistIDList *iface,
177     REFIID riid, void **ppv)
178 {
179     ShellItem *This = impl_from_IPersistIDList(iface);
180     return ShellItem_QueryInterface((IShellItem*)This, riid, ppv);
181 }
182
183 static ULONG WINAPI ShellItem_IPersistIDList_AddRef(IPersistIDList *iface)
184 {
185     ShellItem *This = impl_from_IPersistIDList(iface);
186     return ShellItem_AddRef((IShellItem*)This);
187 }
188
189 static ULONG WINAPI ShellItem_IPersistIDList_Release(IPersistIDList *iface)
190 {
191     ShellItem *This = impl_from_IPersistIDList(iface);
192     return ShellItem_Release((IShellItem*)This);
193 }
194
195 static HRESULT WINAPI ShellItem_IPersistIDList_GetClassID(IPersistIDList* iface,
196     CLSID *pClassID)
197 {
198     ShellItem *This = impl_from_IPersistIDList(iface);
199
200     return ShellItem_GetClassID(This, pClassID);
201 }
202
203 static HRESULT WINAPI ShellItem_IPersistIDList_SetIDList(IPersistIDList* iface,
204     LPCITEMIDLIST pidl)
205 {
206     ShellItem *This = impl_from_IPersistIDList(iface);
207     LPITEMIDLIST new_pidl;
208
209     TRACE("(%p,%p)\n", This, pidl);
210
211     new_pidl = ILClone(pidl);
212
213     if (new_pidl)
214     {
215         ILFree(This->pidl);
216         This->pidl = new_pidl;
217         return S_OK;
218     }
219     else
220         return E_OUTOFMEMORY;
221 }
222
223 static HRESULT WINAPI ShellItem_IPersistIDList_GetIDList(IPersistIDList* iface,
224     LPITEMIDLIST *ppidl)
225 {
226     ShellItem *This = impl_from_IPersistIDList(iface);
227
228     TRACE("(%p,%p)\n", This, ppidl);
229
230     *ppidl = ILClone(This->pidl);
231     if (*ppidl)
232         return S_OK;
233     else
234         return E_OUTOFMEMORY;
235 }
236
237 static const IPersistIDListVtbl ShellItem_IPersistIDList_Vtbl = {
238     ShellItem_IPersistIDList_QueryInterface,
239     ShellItem_IPersistIDList_AddRef,
240     ShellItem_IPersistIDList_Release,
241     ShellItem_IPersistIDList_GetClassID,
242     ShellItem_IPersistIDList_SetIDList,
243     ShellItem_IPersistIDList_GetIDList
244 };
245
246
247 HRESULT WINAPI IShellItem_Constructor(IUnknown *pUnkOuter, REFIID riid, void **ppv)
248 {
249     ShellItem *This;
250     HRESULT ret;
251
252     TRACE("(%p,%s)\n",pUnkOuter, debugstr_guid(riid));
253
254     *ppv = NULL;
255
256     if (pUnkOuter) return CLASS_E_NOAGGREGATION;
257
258     This = HeapAlloc(GetProcessHeap(), 0, sizeof(ShellItem));
259     This->lpIShellItemVtbl = &ShellItem_Vtbl;
260     This->ref = 1;
261     This->pidl = NULL;
262     This->lpIPersistIDListVtbl = &ShellItem_IPersistIDList_Vtbl;
263
264     ret = ShellItem_QueryInterface((IShellItem*)This, riid, ppv);
265     ShellItem_Release((IShellItem*)This);
266
267     return ret;
268 }
269
270 HRESULT WINAPI SHCreateShellItem(LPCITEMIDLIST pidlParent,
271     IShellFolder *psfParent, LPCITEMIDLIST pidl, IShellItem **ppsi)
272 {
273     ShellItem *This;
274     LPITEMIDLIST new_pidl;
275     HRESULT ret;
276
277     TRACE("(%p,%p,%p,%p)\n", pidlParent, psfParent, pidl, ppsi);
278
279     if (!pidlParent && !psfParent && pidl)
280     {
281         new_pidl = ILClone(pidl);
282         if (!new_pidl)
283             return E_OUTOFMEMORY;
284     }
285     else
286     {
287         FIXME("(%p,%p,%p) not implemented\n", pidlParent, psfParent, pidl);
288         return E_NOINTERFACE;
289     }
290
291     ret = IShellItem_Constructor(NULL, &IID_IShellItem, (void**)&This);
292     if (This)
293     {
294         *ppsi = (IShellItem*)This;
295         This->pidl = new_pidl;
296     }
297     else
298     {
299         *ppsi = NULL;
300         ILFree(new_pidl);
301     }
302     return ret;
303 }