Fix signed/unsigned comparison warnings.
[wine] / dlls / shell32 / dataobject.c
1 /*
2  *      IEnumFORMATETC, IDataObject
3  *
4  * selecting and droping objects within the shell and/or common dialogs
5  *
6  *      Copyright 1998, 1999    <juergen.schmied@metronet.de>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22 #include <string.h>
23
24 #define NONAMELESSUNION
25 #define NONAMELESSSTRUCT
26 #include "windef.h"
27 #include "wingdi.h"
28 #include "pidl.h"
29 #include "winerror.h"
30 #include "shell32_main.h"
31 #include "wine/debug.h"
32 #include "undocshell.h"
33
34 WINE_DEFAULT_DEBUG_CHANNEL(shell);
35
36 /***********************************************************************
37 *   IEnumFORMATETC implementation
38 */
39
40 typedef struct
41 {
42     /* IUnknown fields */
43     IEnumFORMATETCVtbl *lpVtbl;
44     DWORD                        ref;
45     /* IEnumFORMATETC fields */
46     UINT        posFmt;
47     UINT        countFmt;
48     LPFORMATETC pFmt;
49 } IEnumFORMATETCImpl;
50
51 static HRESULT WINAPI IEnumFORMATETC_fnQueryInterface(LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj);
52 static ULONG WINAPI IEnumFORMATETC_fnAddRef(LPENUMFORMATETC iface);
53 static ULONG WINAPI IEnumFORMATETC_fnRelease(LPENUMFORMATETC iface);
54 static HRESULT WINAPI IEnumFORMATETC_fnNext(LPENUMFORMATETC iface, ULONG celt, FORMATETC* rgelt, ULONG* pceltFethed);
55 static HRESULT WINAPI IEnumFORMATETC_fnSkip(LPENUMFORMATETC iface, ULONG celt);
56 static HRESULT WINAPI IEnumFORMATETC_fnReset(LPENUMFORMATETC iface);
57 static HRESULT WINAPI IEnumFORMATETC_fnClone(LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum);
58
59 static struct IEnumFORMATETCVtbl efvt =
60 {
61         IEnumFORMATETC_fnQueryInterface,
62         IEnumFORMATETC_fnAddRef,
63     IEnumFORMATETC_fnRelease,
64     IEnumFORMATETC_fnNext,
65     IEnumFORMATETC_fnSkip,
66     IEnumFORMATETC_fnReset,
67     IEnumFORMATETC_fnClone
68 };
69
70 LPENUMFORMATETC IEnumFORMATETC_Constructor(UINT cfmt, const FORMATETC afmt[])
71 {
72         IEnumFORMATETCImpl* ef;
73         DWORD size=cfmt * sizeof(FORMATETC);
74
75         ef=(IEnumFORMATETCImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IEnumFORMATETCImpl));
76
77         if(ef)
78         {
79           ef->ref=1;
80           ef->lpVtbl=&efvt;
81
82           ef->countFmt = cfmt;
83           ef->pFmt = SHAlloc (size);
84
85           if (ef->pFmt)
86           {
87             memcpy(ef->pFmt, afmt, size);
88           }
89         }
90
91         TRACE("(%p)->(%u,%p)\n",ef, cfmt, afmt);
92         return (LPENUMFORMATETC)ef;
93 }
94
95 static HRESULT WINAPI IEnumFORMATETC_fnQueryInterface(LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj)
96 {
97         IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
98         TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
99
100         *ppvObj = NULL;
101
102         if(IsEqualIID(riid, &IID_IUnknown))
103         {
104           *ppvObj = This;
105         }
106         else if(IsEqualIID(riid, &IID_IEnumFORMATETC))
107         {
108           *ppvObj = (IEnumFORMATETC*)This;
109         }
110
111         if(*ppvObj)
112         {
113           IUnknown_AddRef((IUnknown*)(*ppvObj));
114           TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
115           return S_OK;
116         }
117         TRACE("-- Interface: E_NOINTERFACE\n");
118         return E_NOINTERFACE;
119
120 }
121
122 static ULONG WINAPI IEnumFORMATETC_fnAddRef(LPENUMFORMATETC iface)
123 {
124         IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
125         TRACE("(%p)->(count=%lu)\n",This, This->ref);
126         return ++(This->ref);
127 }
128
129 static ULONG WINAPI IEnumFORMATETC_fnRelease(LPENUMFORMATETC iface)
130 {
131         IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
132         TRACE("(%p)->()\n",This);
133
134         if (!--(This->ref))
135         {
136           TRACE(" destroying IEnumFORMATETC(%p)\n",This);
137           if (This->pFmt)
138           {
139             SHFree (This->pFmt);
140           }
141           HeapFree(GetProcessHeap(),0,This);
142           return 0;
143         }
144         return This->ref;
145 }
146
147 static HRESULT WINAPI IEnumFORMATETC_fnNext(LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
148 {
149         IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
150         UINT i;
151
152         TRACE("(%p)->(%lu,%p)\n", This, celt, rgelt);
153
154         if(!This->pFmt)return S_FALSE;
155         if(!rgelt) return E_INVALIDARG;
156         if (pceltFethed)  *pceltFethed = 0;
157
158         for(i = 0; This->posFmt < This->countFmt && celt > i; i++)
159         {
160           *rgelt++ = This->pFmt[This->posFmt++];
161         }
162
163         if (pceltFethed) *pceltFethed = i;
164
165         return ((i == celt) ? S_OK : S_FALSE);
166 }
167
168 static HRESULT WINAPI IEnumFORMATETC_fnSkip(LPENUMFORMATETC iface, ULONG celt)
169 {
170         IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
171         TRACE("(%p)->(num=%lu)\n", This, celt);
172
173         if((This->posFmt + celt) >= This->countFmt) return S_FALSE;
174         This->posFmt += celt;
175         return S_OK;
176 }
177
178 static HRESULT WINAPI IEnumFORMATETC_fnReset(LPENUMFORMATETC iface)
179 {
180         IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
181         TRACE("(%p)->()\n", This);
182
183         This->posFmt = 0;
184         return S_OK;
185 }
186
187 static HRESULT WINAPI IEnumFORMATETC_fnClone(LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum)
188 {
189         IEnumFORMATETCImpl *This = (IEnumFORMATETCImpl *)iface;
190         TRACE("(%p)->(ppenum=%p)\n", This, ppenum);
191
192         if (!ppenum) return E_INVALIDARG;
193         *ppenum = IEnumFORMATETC_Constructor(This->countFmt, This->pFmt);
194         if(*ppenum)
195            IEnumFORMATETC_fnSkip(*ppenum, This->posFmt);
196         return S_OK;
197 }
198
199
200 /***********************************************************************
201 *   IDataObject implementation
202 */
203
204 /* number of supported formats */
205 #define MAX_FORMATS 4
206
207 typedef struct
208 {
209         /* IUnknown fields */
210         IDataObjectVtbl *lpVtbl;
211         DWORD           ref;
212
213         /* IDataObject fields */
214         LPITEMIDLIST    pidl;
215         LPITEMIDLIST *  apidl;
216         UINT            cidl;
217
218         FORMATETC       pFormatEtc[MAX_FORMATS];
219         UINT            cfShellIDList;
220         UINT            cfFileNameA;
221         UINT            cfFileNameW;
222
223 } IDataObjectImpl;
224
225 static struct IDataObjectVtbl dtovt;
226
227 /**************************************************************************
228 *  IDataObject_Constructor
229 */
230 LPDATAOBJECT IDataObject_Constructor(HWND hwndOwner, LPCITEMIDLIST pMyPidl, LPCITEMIDLIST * apidl, UINT cidl)
231 {
232         IDataObjectImpl* dto;
233
234         dto = (IDataObjectImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDataObjectImpl));
235
236         if (dto)
237         {
238           dto->ref = 1;
239           dto->lpVtbl = &dtovt;
240           dto->pidl = ILClone(pMyPidl);
241           dto->apidl = _ILCopyaPidl(apidl, cidl);
242           dto->cidl = cidl;
243
244           dto->cfShellIDList = RegisterClipboardFormatA(CFSTR_SHELLIDLIST);
245           dto->cfFileNameA = RegisterClipboardFormatA(CFSTR_FILENAMEA);
246           dto->cfFileNameW = RegisterClipboardFormatA(CFSTR_FILENAMEW);
247           InitFormatEtc(dto->pFormatEtc[0], dto->cfShellIDList, TYMED_HGLOBAL);
248           InitFormatEtc(dto->pFormatEtc[1], CF_HDROP, TYMED_HGLOBAL);
249           InitFormatEtc(dto->pFormatEtc[2], dto->cfFileNameA, TYMED_HGLOBAL);
250           InitFormatEtc(dto->pFormatEtc[3], dto->cfFileNameW, TYMED_HGLOBAL);
251         }
252
253         TRACE("(%p)->(apidl=%p cidl=%u)\n",dto, apidl, cidl);
254         return (LPDATAOBJECT)dto;
255 }
256
257 /***************************************************************************
258 *  IDataObject_QueryInterface
259 */
260 static HRESULT WINAPI IDataObject_fnQueryInterface(LPDATAOBJECT iface, REFIID riid, LPVOID * ppvObj)
261 {
262         IDataObjectImpl *This = (IDataObjectImpl *)iface;
263         TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
264
265         *ppvObj = NULL;
266
267         if(IsEqualIID(riid, &IID_IUnknown))          /*IUnknown*/
268         {
269           *ppvObj = This;
270         }
271         else if(IsEqualIID(riid, &IID_IDataObject))  /*IDataObject*/
272         {
273           *ppvObj = (IDataObject*)This;
274         }
275
276         if(*ppvObj)
277         {
278           IUnknown_AddRef((IUnknown*)*ppvObj);
279           TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
280           return S_OK;
281         }
282         TRACE("-- Interface: E_NOINTERFACE\n");
283         return E_NOINTERFACE;
284 }
285
286 /**************************************************************************
287 *  IDataObject_AddRef
288 */
289 static ULONG WINAPI IDataObject_fnAddRef(LPDATAOBJECT iface)
290 {
291         IDataObjectImpl *This = (IDataObjectImpl *)iface;
292         TRACE("(%p)->(count=%lu)\n",This, This->ref);
293         return ++(This->ref);
294 }
295
296 /**************************************************************************
297 *  IDataObject_Release
298 */
299 static ULONG WINAPI IDataObject_fnRelease(LPDATAOBJECT iface)
300 {
301         IDataObjectImpl *This = (IDataObjectImpl *)iface;
302         TRACE("(%p)->()\n",This);
303
304         if (!--(This->ref))
305         {
306           TRACE(" destroying IDataObject(%p)\n",This);
307           _ILFreeaPidl(This->apidl, This->cidl);
308           ILFree(This->pidl),
309           HeapFree(GetProcessHeap(),0,This);
310           return 0;
311         }
312         return This->ref;
313 }
314
315 /**************************************************************************
316 * IDataObject_fnGetData
317 */
318 static HRESULT WINAPI IDataObject_fnGetData(LPDATAOBJECT iface, LPFORMATETC pformatetcIn, STGMEDIUM *pmedium)
319 {
320         IDataObjectImpl *This = (IDataObjectImpl *)iface;
321
322         char    szTemp[256];
323
324         szTemp[0]=0;
325         GetClipboardFormatNameA (pformatetcIn->cfFormat, szTemp, 256);
326         TRACE("(%p)->(%p %p format=%s)\n", This, pformatetcIn, pmedium, szTemp);
327
328         if (pformatetcIn->cfFormat == This->cfShellIDList)
329         {
330           if (This->cidl < 1) return(E_UNEXPECTED);
331           pmedium->u.hGlobal = RenderSHELLIDLIST(This->pidl, This->apidl, This->cidl);
332         }
333         else if (pformatetcIn->cfFormat == CF_HDROP)
334         {
335           if (This->cidl < 1) return(E_UNEXPECTED);
336           pmedium->u.hGlobal = RenderHDROP(This->pidl, This->apidl, This->cidl);
337         }
338         else if (pformatetcIn->cfFormat == This->cfFileNameA)
339         {
340           if (This->cidl < 1) return(E_UNEXPECTED);
341           pmedium->u.hGlobal = RenderFILENAMEA(This->pidl, This->apidl, This->cidl);
342         }
343         else if (pformatetcIn->cfFormat == This->cfFileNameW)
344         {
345           if (This->cidl < 1) return(E_UNEXPECTED);
346           pmedium->u.hGlobal = RenderFILENAMEW(This->pidl, This->apidl, This->cidl);
347         }
348         else
349         {
350           FIXME("-- expected clipformat not implemented\n");
351           return (E_INVALIDARG);
352         }
353         if (pmedium->u.hGlobal)
354         {
355           pmedium->tymed = TYMED_HGLOBAL;
356           pmedium->pUnkForRelease = NULL;
357           return S_OK;
358         }
359         return E_OUTOFMEMORY;
360 }
361
362 static HRESULT WINAPI IDataObject_fnGetDataHere(LPDATAOBJECT iface, LPFORMATETC pformatetc, STGMEDIUM *pmedium)
363 {
364         IDataObjectImpl *This = (IDataObjectImpl *)iface;
365         FIXME("(%p)->()\n", This);
366         return E_NOTIMPL;
367 }
368
369 static HRESULT WINAPI IDataObject_fnQueryGetData(LPDATAOBJECT iface, LPFORMATETC pformatetc)
370 {
371         IDataObjectImpl *This = (IDataObjectImpl *)iface;
372         UINT i;
373
374         TRACE("(%p)->(fmt=0x%08x tym=0x%08lx)\n", This, pformatetc->cfFormat, pformatetc->tymed);
375
376         if(!(DVASPECT_CONTENT & pformatetc->dwAspect))
377           return DV_E_DVASPECT;
378
379         /* check our formats table what we have */
380         for (i=0; i<MAX_FORMATS; i++)
381         {
382           if ((This->pFormatEtc[i].cfFormat == pformatetc->cfFormat)
383            && (This->pFormatEtc[i].tymed == pformatetc->tymed))
384           {
385             return S_OK;
386           }
387         }
388
389         return DV_E_TYMED;
390 }
391
392 static HRESULT WINAPI IDataObject_fnGetCanonicalFormatEtc(LPDATAOBJECT iface, LPFORMATETC pformatectIn, LPFORMATETC pformatetcOut)
393 {
394         IDataObjectImpl *This = (IDataObjectImpl *)iface;
395         FIXME("(%p)->()\n", This);
396         return E_NOTIMPL;
397 }
398
399 static HRESULT WINAPI IDataObject_fnSetData(LPDATAOBJECT iface, LPFORMATETC pformatetc, STGMEDIUM *pmedium, BOOL fRelease)
400 {
401         IDataObjectImpl *This = (IDataObjectImpl *)iface;
402         FIXME("(%p)->()\n", This);
403         return E_NOTIMPL;
404 }
405
406 static HRESULT WINAPI IDataObject_fnEnumFormatEtc(LPDATAOBJECT iface, DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc)
407 {
408         IDataObjectImpl *This = (IDataObjectImpl *)iface;
409
410         TRACE("(%p)->()\n", This);
411         *ppenumFormatEtc=NULL;
412
413         /* only get data */
414         if (DATADIR_GET == dwDirection)
415         {
416           *ppenumFormatEtc = IEnumFORMATETC_Constructor(MAX_FORMATS, This->pFormatEtc);
417           return (*ppenumFormatEtc) ? S_OK : E_FAIL;
418         }
419
420         return E_NOTIMPL;
421 }
422
423 static HRESULT WINAPI IDataObject_fnDAdvise(LPDATAOBJECT iface, FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection)
424 {
425         IDataObjectImpl *This = (IDataObjectImpl *)iface;
426         FIXME("(%p)->()\n", This);
427         return E_NOTIMPL;
428 }
429 static HRESULT WINAPI IDataObject_fnDUnadvise(LPDATAOBJECT iface, DWORD dwConnection)
430 {
431         IDataObjectImpl *This = (IDataObjectImpl *)iface;
432         FIXME("(%p)->()\n", This);
433         return E_NOTIMPL;
434 }
435 static HRESULT WINAPI IDataObject_fnEnumDAdvise(LPDATAOBJECT iface, IEnumSTATDATA **ppenumAdvise)
436 {
437         IDataObjectImpl *This = (IDataObjectImpl *)iface;
438         FIXME("(%p)->()\n", This);
439         return E_NOTIMPL;
440 }
441
442 static struct IDataObjectVtbl dtovt =
443 {
444         IDataObject_fnQueryInterface,
445         IDataObject_fnAddRef,
446         IDataObject_fnRelease,
447         IDataObject_fnGetData,
448         IDataObject_fnGetDataHere,
449         IDataObject_fnQueryGetData,
450         IDataObject_fnGetCanonicalFormatEtc,
451         IDataObject_fnSetData,
452         IDataObject_fnEnumFormatEtc,
453         IDataObject_fnDAdvise,
454         IDataObject_fnDUnadvise,
455         IDataObject_fnEnumDAdvise
456 };