Restored managed mode config file option.
[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 #include "pidl.h"
25 #include "winerror.h"
26 #include "shell32_main.h"
27 #include "wine/debug.h"
28 #include "undocshell.h"
29 #include "wine/obj_dataobject.h"
30
31 WINE_DEFAULT_DEBUG_CHANNEL(shell);
32
33 /***********************************************************************
34 *   IEnumFORMATETC implementation
35 */
36
37 typedef struct 
38 {
39     /* IUnknown fields */
40     ICOM_VFIELD(IEnumFORMATETC);
41     DWORD                        ref;
42     /* IEnumFORMATETC fields */
43     UINT        posFmt;
44     UINT        countFmt;
45     LPFORMATETC pFmt;
46 } IEnumFORMATETCImpl;
47
48 static HRESULT WINAPI IEnumFORMATETC_fnQueryInterface(LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj);
49 static ULONG WINAPI IEnumFORMATETC_fnAddRef(LPENUMFORMATETC iface);
50 static ULONG WINAPI IEnumFORMATETC_fnRelease(LPENUMFORMATETC iface);
51 static HRESULT WINAPI IEnumFORMATETC_fnNext(LPENUMFORMATETC iface, ULONG celt, FORMATETC* rgelt, ULONG* pceltFethed);
52 static HRESULT WINAPI IEnumFORMATETC_fnSkip(LPENUMFORMATETC iface, ULONG celt);
53 static HRESULT WINAPI IEnumFORMATETC_fnReset(LPENUMFORMATETC iface);
54 static HRESULT WINAPI IEnumFORMATETC_fnClone(LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum);
55
56 static struct ICOM_VTABLE(IEnumFORMATETC) efvt = 
57 {
58     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
59         IEnumFORMATETC_fnQueryInterface,
60         IEnumFORMATETC_fnAddRef,
61     IEnumFORMATETC_fnRelease,
62     IEnumFORMATETC_fnNext,
63     IEnumFORMATETC_fnSkip,
64     IEnumFORMATETC_fnReset,
65     IEnumFORMATETC_fnClone
66 };
67
68 LPENUMFORMATETC IEnumFORMATETC_Constructor(UINT cfmt, const FORMATETC afmt[])
69 {
70         IEnumFORMATETCImpl* ef;
71         DWORD size=cfmt * sizeof(FORMATETC);
72         
73         ef=(IEnumFORMATETCImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IEnumFORMATETCImpl));
74
75         if(ef)
76         {
77           ef->ref=1;
78           ICOM_VTBL(ef)=&efvt;
79
80           ef->countFmt = cfmt;
81           ef->pFmt = SHAlloc (size);
82
83           if (ef->pFmt)
84           {
85             memcpy(ef->pFmt, afmt, size);
86           }
87
88           shell32_ObjCount++;
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         ICOM_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         ICOM_THIS(IEnumFORMATETCImpl,iface);
125         TRACE("(%p)->(count=%lu)\n",This, This->ref);
126         shell32_ObjCount++;
127         return ++(This->ref);
128 }
129
130 static ULONG WINAPI IEnumFORMATETC_fnRelease(LPENUMFORMATETC iface)
131 {
132         ICOM_THIS(IEnumFORMATETCImpl,iface);
133         TRACE("(%p)->()\n",This);
134
135         shell32_ObjCount--;
136
137         if (!--(This->ref)) 
138         {
139           TRACE(" destroying IEnumFORMATETC(%p)\n",This);
140           if (This->pFmt)
141           {
142             SHFree (This->pFmt);
143           }
144           HeapFree(GetProcessHeap(),0,This);
145           return 0;
146         }
147         return This->ref;
148 }
149
150 static HRESULT WINAPI IEnumFORMATETC_fnNext(LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
151 {
152         ICOM_THIS(IEnumFORMATETCImpl,iface);
153         int i;
154
155         TRACE("(%p)->(%lu,%p)\n", This, celt, rgelt);
156
157         if(!This->pFmt)return S_FALSE;
158         if(!rgelt) return E_INVALIDARG;
159         if (pceltFethed)  *pceltFethed = 0;
160
161         for(i = 0; This->posFmt < This->countFmt && celt > i; i++)
162         {
163           *rgelt++ = This->pFmt[This->posFmt++];
164         }
165
166         if (pceltFethed) *pceltFethed = i;
167
168         return ((i == celt) ? S_OK : S_FALSE);
169 }
170
171 static HRESULT WINAPI IEnumFORMATETC_fnSkip(LPENUMFORMATETC iface, ULONG celt)
172 {
173         ICOM_THIS(IEnumFORMATETCImpl,iface);
174         TRACE("(%p)->(num=%lu)\n", This, celt);
175
176         if((This->posFmt + celt) >= This->countFmt) return S_FALSE;
177         This->posFmt += celt;
178         return S_OK;
179 }
180
181 static HRESULT WINAPI IEnumFORMATETC_fnReset(LPENUMFORMATETC iface)
182 {
183         ICOM_THIS(IEnumFORMATETCImpl,iface);
184         TRACE("(%p)->()\n", This);
185
186         This->posFmt = 0;
187         return S_OK;
188 }
189
190 static HRESULT WINAPI IEnumFORMATETC_fnClone(LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum)
191 {
192         ICOM_THIS(IEnumFORMATETCImpl,iface);
193         TRACE("(%p)->(ppenum=%p)\n", This, ppenum);
194
195         if (!ppenum) return E_INVALIDARG;
196         *ppenum = IEnumFORMATETC_Constructor(This->countFmt, This->pFmt);
197         return S_OK;
198 }
199
200
201 /***********************************************************************
202 *   IDataObject implementation
203 */
204
205 /* number of supported formats */
206 #define MAX_FORMATS 3
207
208 typedef struct
209 {
210         /* IUnknown fields */
211         ICOM_VFIELD(IDataObject);
212         DWORD           ref;
213
214         /* IDataObject fields */
215         LPITEMIDLIST    pidl;
216         LPITEMIDLIST *  apidl;
217         UINT            cidl;
218
219         FORMATETC       pFormatEtc[MAX_FORMATS];
220         UINT            cfShellIDList;
221         UINT            cfFileName;
222
223 } IDataObjectImpl;
224
225 static struct ICOM_VTABLE(IDataObject) dtovt;
226
227 /**************************************************************************
228 *  IDataObject_Constructor
229 */
230 LPDATAOBJECT IDataObject_Constructor(HWND hwndOwner, LPITEMIDLIST pMyPidl, LPITEMIDLIST * 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           ICOM_VTBL(dto) = &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->cfFileName = RegisterClipboardFormatA(CFSTR_FILENAMEA);
246           InitFormatEtc(dto->pFormatEtc[0], dto->cfShellIDList, TYMED_HGLOBAL);
247           InitFormatEtc(dto->pFormatEtc[1], CF_HDROP, TYMED_HGLOBAL);
248           InitFormatEtc(dto->pFormatEtc[2], dto->cfFileName, TYMED_HGLOBAL);
249
250           shell32_ObjCount++;
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         ICOM_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         ICOM_THIS(IDataObjectImpl,iface);
292
293         TRACE("(%p)->(count=%lu)\n",This, This->ref);
294
295         shell32_ObjCount++;
296         return ++(This->ref);
297 }
298
299 /**************************************************************************
300 *  IDataObject_Release
301 */
302 static ULONG WINAPI IDataObject_fnRelease(LPDATAOBJECT iface)
303 {
304         ICOM_THIS(IDataObjectImpl,iface);
305         TRACE("(%p)->()\n",This);
306
307         shell32_ObjCount--;
308
309         if (!--(This->ref)) 
310         {
311           TRACE(" destroying IDataObject(%p)\n",This);
312           _ILFreeaPidl(This->apidl, This->cidl);
313           HeapFree(GetProcessHeap(),0,This);
314           return 0;
315         }
316         return This->ref;
317 }
318
319 /**************************************************************************
320 * IDataObject_fnGetData
321 */
322 static HRESULT WINAPI IDataObject_fnGetData(LPDATAOBJECT iface, LPFORMATETC pformatetcIn, STGMEDIUM *pmedium)
323 {
324         ICOM_THIS(IDataObjectImpl,iface);
325
326         char    szTemp[256];
327         
328         szTemp[0]=0;
329         GetClipboardFormatNameA (pformatetcIn->cfFormat, szTemp, 256);
330         TRACE("(%p)->(%p %p format=%s)\n", This, pformatetcIn, pmedium, szTemp);
331
332         if (pformatetcIn->cfFormat == This->cfShellIDList)
333         {
334           if (This->cidl < 1) return(E_UNEXPECTED);
335           pmedium->u.hGlobal = RenderSHELLIDLIST(This->pidl, This->apidl, This->cidl);
336         }
337         else if (pformatetcIn->cfFormat == CF_HDROP)
338         {
339           if (This->cidl < 1) return(E_UNEXPECTED);
340           pmedium->u.hGlobal = RenderHDROP(This->pidl, This->apidl, This->cidl);
341         }
342         else if (pformatetcIn->cfFormat == This->cfFileName)
343         {
344           if (This->cidl < 1) return(E_UNEXPECTED);
345           pmedium->u.hGlobal = RenderFILENAME(This->pidl, This->apidl, This->cidl);
346         }
347         else
348         {
349           FIXME("-- expected clipformat not implemented\n");
350           return (E_INVALIDARG);
351         }
352         if (pmedium->u.hGlobal)
353         {
354           pmedium->tymed = TYMED_HGLOBAL;
355           pmedium->pUnkForRelease = NULL;
356           return S_OK;
357         }
358         return E_OUTOFMEMORY;
359 }
360
361 static HRESULT WINAPI IDataObject_fnGetDataHere(LPDATAOBJECT iface, LPFORMATETC pformatetc, STGMEDIUM *pmedium)
362 {
363         ICOM_THIS(IDataObjectImpl,iface);
364         FIXME("(%p)->()\n", This);
365         return E_NOTIMPL;
366 }
367
368 static HRESULT WINAPI IDataObject_fnQueryGetData(LPDATAOBJECT iface, LPFORMATETC pformatetc)
369 {
370         ICOM_THIS(IDataObjectImpl,iface);
371         UINT i;
372         
373         TRACE("(%p)->(fmt=0x%08x tym=0x%08lx)\n", This, pformatetc->cfFormat, pformatetc->tymed);
374         
375         if(!(DVASPECT_CONTENT & pformatetc->dwAspect))
376           return DV_E_DVASPECT;
377
378         /* check our formats table what we have */
379         for (i=0; i<MAX_FORMATS; i++)
380         {
381           if ((This->pFormatEtc[i].cfFormat == pformatetc->cfFormat)
382            && (This->pFormatEtc[i].tymed == pformatetc->tymed))
383           {
384             return S_OK;
385           }
386         }
387
388         return DV_E_TYMED;
389 }
390
391 static HRESULT WINAPI IDataObject_fnGetCanonicalFormatEtc(LPDATAOBJECT iface, LPFORMATETC pformatectIn, LPFORMATETC pformatetcOut)
392 {
393         ICOM_THIS(IDataObjectImpl,iface);
394         FIXME("(%p)->()\n", This);
395         return E_NOTIMPL;
396 }
397
398 static HRESULT WINAPI IDataObject_fnSetData(LPDATAOBJECT iface, LPFORMATETC pformatetc, STGMEDIUM *pmedium, BOOL fRelease)
399 {
400         ICOM_THIS(IDataObjectImpl,iface);
401         FIXME("(%p)->()\n", This);
402         return E_NOTIMPL;
403 }
404
405 static HRESULT WINAPI IDataObject_fnEnumFormatEtc(LPDATAOBJECT iface, DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc)
406 {
407         ICOM_THIS(IDataObjectImpl,iface);
408
409         TRACE("(%p)->()\n", This);
410         *ppenumFormatEtc=NULL;
411
412         /* only get data */
413         if (DATADIR_GET == dwDirection)
414         {
415           *ppenumFormatEtc = IEnumFORMATETC_Constructor(MAX_FORMATS, This->pFormatEtc);
416           return (*ppenumFormatEtc) ? S_OK : E_FAIL;
417         }
418         
419         return E_NOTIMPL;
420 }
421
422 static HRESULT WINAPI IDataObject_fnDAdvise(LPDATAOBJECT iface, FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection)
423 {
424         ICOM_THIS(IDataObjectImpl,iface);
425         FIXME("(%p)->()\n", This);
426         return E_NOTIMPL;
427 }
428 static HRESULT WINAPI IDataObject_fnDUnadvise(LPDATAOBJECT iface, DWORD dwConnection)
429 {
430         ICOM_THIS(IDataObjectImpl,iface);
431         FIXME("(%p)->()\n", This);
432         return E_NOTIMPL;
433 }
434 static HRESULT WINAPI IDataObject_fnEnumDAdvise(LPDATAOBJECT iface, IEnumSTATDATA **ppenumAdvise)
435 {
436         ICOM_THIS(IDataObjectImpl,iface);
437         FIXME("(%p)->()\n", This);
438         return E_NOTIMPL;
439 }
440
441 static struct ICOM_VTABLE(IDataObject) dtovt = 
442 {
443         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
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 };
457