- New implementation of SendMessage, ReceiveMessage, ReplyMessage functions
[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  <juergen.schmied@metronet.de>
7  */
8 #include "debug.h"
9 #include "wintypes.h"
10 #include "wine/obj_base.h"
11 #include "wine/obj_storage.h"
12 #include "wine/obj_moniker.h"
13 #include "wine/obj_dataobject.h"
14 #include "objbase.h"
15 #include "pidl.h"
16 #include "winerror.h"
17 #include "shell32_main.h"
18
19 UINT32 cfShellIDList=0;
20 UINT32 cfFileGroupDesc=0;
21 UINT32 cfFileContents=0;
22
23 /***********************************************************************
24 *   IEnumFORMATETC implementation
25 */
26 typedef struct 
27 {
28     /* IUnknown fields */
29     ICOM_VTABLE(IEnumFORMATETC)* lpvtbl;
30     DWORD                        ref;
31     /* IEnumFORMATETC fields */
32     UINT32        posFmt;
33     UINT32        countFmt;
34     LPFORMATETC32 pFmt;
35 } IEnumFORMATETCImpl;
36
37 static HRESULT WINAPI IEnumFORMATETC_fnQueryInterface(LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj);
38 static ULONG WINAPI IEnumFORMATETC_fnAddRef(LPENUMFORMATETC iface);
39 static ULONG WINAPI IEnumFORMATETC_fnRelease(LPENUMFORMATETC iface);
40 static HRESULT WINAPI IEnumFORMATETC_fnNext(LPENUMFORMATETC iface, ULONG celt, FORMATETC32* rgelt, ULONG* pceltFethed);
41 static HRESULT WINAPI IEnumFORMATETC_fnSkip(LPENUMFORMATETC iface, ULONG celt);
42 static HRESULT WINAPI IEnumFORMATETC_fnReset(LPENUMFORMATETC iface);
43 static HRESULT WINAPI IEnumFORMATETC_fnClone(LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum);
44
45 static struct ICOM_VTABLE(IEnumFORMATETC) efvt = 
46 {
47         IEnumFORMATETC_fnQueryInterface,
48         IEnumFORMATETC_fnAddRef,
49     IEnumFORMATETC_fnRelease,
50     IEnumFORMATETC_fnNext,
51     IEnumFORMATETC_fnSkip,
52     IEnumFORMATETC_fnReset,
53     IEnumFORMATETC_fnClone
54 };
55
56 LPENUMFORMATETC IEnumFORMATETC_Constructor(UINT32 cfmt, const FORMATETC32 afmt[])
57 {
58         IEnumFORMATETCImpl* ef;
59         DWORD size=cfmt * sizeof(FORMATETC32);
60         
61         ef=(IEnumFORMATETCImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IEnumFORMATETCImpl));
62         ef->ref=1;
63         ef->lpvtbl=&efvt;
64
65         ef->posFmt = 0;
66         ef->countFmt = cfmt;
67         ef->pFmt = SHAlloc (size);
68
69         if (ef->pFmt)
70         { memcpy(ef->pFmt, afmt, size);
71         }
72
73         TRACE(shell,"(%p)->()\n",ef);
74         shell32_ObjCount++;
75         return (LPENUMFORMATETC)ef;
76 }
77 static HRESULT WINAPI IEnumFORMATETC_fnQueryInterface(LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj)
78 {
79         ICOM_THIS(IEnumFORMATETCImpl,iface);
80         char    xriid[50];
81         WINE_StringFromCLSID((LPCLSID)riid,xriid);
82         TRACE(shell,"(%p)->(\n\tIID:\t%s,%p)\n",This,xriid,ppvObj);
83
84                         *ppvObj = NULL;
85
86         if(IsEqualIID(riid, &IID_IUnknown))
87         { *ppvObj = This; 
88         }
89         else if(IsEqualIID(riid, &IID_IEnumFORMATETC))
90         { *ppvObj = (IDataObject*)This;
91         }   
92
93         if(*ppvObj)
94         { IEnumFORMATETC_AddRef((IEnumFORMATETC*)*ppvObj);
95           TRACE(shell,"-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
96           return S_OK;
97         }
98         TRACE(shell,"-- Interface: E_NOINTERFACE\n");
99         return E_NOINTERFACE;
100
101 }
102 static ULONG WINAPI IEnumFORMATETC_fnAddRef(LPENUMFORMATETC iface)
103 {
104         ICOM_THIS(IEnumFORMATETCImpl,iface);
105         TRACE(shell,"(%p)->(count=%lu)\n",This,(This->ref)+1);
106         shell32_ObjCount++;
107         return ++(This->ref);
108 }
109 static ULONG WINAPI IEnumFORMATETC_fnRelease(LPENUMFORMATETC iface)
110 {
111         ICOM_THIS(IEnumFORMATETCImpl,iface);
112         TRACE(shell,"(%p)->()\n",This);
113
114         shell32_ObjCount--;
115
116         if (!--(This->ref)) 
117         { TRACE(shell," destroying IEnumFORMATETC(%p)\n",This);
118           if (This->pFmt)
119           { SHFree (This->pFmt);
120           }
121           HeapFree(GetProcessHeap(),0,This);
122           return 0;
123         }
124         return This->ref;
125 }
126 static HRESULT WINAPI IEnumFORMATETC_fnNext(LPENUMFORMATETC iface, ULONG celt, FORMATETC32 *rgelt, ULONG *pceltFethed)
127 {
128         ICOM_THIS(IEnumFORMATETCImpl,iface);
129         UINT32 cfetch;
130         HRESULT hres = S_FALSE;
131
132         TRACE (shell, "(%p)->()\n", This);
133
134         if (This->posFmt < This->countFmt)
135         { cfetch = This->countFmt - This->posFmt;
136           if (cfetch >= celt)
137           { cfetch = celt;
138             hres = S_OK;
139           }
140           memcpy(rgelt, &This->pFmt[This->posFmt], cfetch * sizeof(FORMATETC32));
141           This->posFmt += cfetch;
142         }
143         else
144         { cfetch = 0;
145         }
146
147         if (pceltFethed)
148         { *pceltFethed = cfetch;
149         }
150
151         return hres;
152 }
153 static HRESULT WINAPI IEnumFORMATETC_fnSkip(LPENUMFORMATETC iface, ULONG celt)
154 {
155         ICOM_THIS(IEnumFORMATETCImpl,iface);
156         FIXME (shell, "(%p)->(num=%lu)\n", This, celt);
157
158         This->posFmt += celt;
159         if (This->posFmt > This->countFmt)
160         { This->posFmt = This->countFmt;
161           return S_FALSE;
162         }
163         return S_OK;
164 }
165 static HRESULT WINAPI IEnumFORMATETC_fnReset(LPENUMFORMATETC iface)
166 {
167         ICOM_THIS(IEnumFORMATETCImpl,iface);
168         FIXME (shell, "(%p)->()\n", This);
169
170         This->posFmt = 0;
171         return S_OK;
172 }
173 static HRESULT WINAPI IEnumFORMATETC_fnClone(LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum)
174 {
175         ICOM_THIS(IEnumFORMATETCImpl,iface);
176         FIXME (shell, "(%p)->(ppenum=%p)\n", This, ppenum);
177         return E_NOTIMPL;
178 }
179
180 /***********************************************************************
181 *   IDataObject implementation
182 */
183 typedef struct
184 {
185     /* IUnknown fields */
186     ICOM_VTABLE(IDataObject)* lpvtbl;
187     DWORD                     ref;
188     /* IDataObject fields */
189     LPSHELLFOLDER psf;
190     LPIDLLIST     lpill;       /* the data of the dataobject */
191     LPITEMIDLIST  pidl;     
192 } IDataObjectImpl;
193
194 static HRESULT WINAPI IDataObject_fnQueryInterface(LPDATAOBJECT iface, REFIID riid, LPVOID* ppvObj);
195 static ULONG WINAPI IDataObject_fnAddRef(LPDATAOBJECT iface);
196 static ULONG WINAPI IDataObject_fnRelease(LPDATAOBJECT iface);
197 static HRESULT WINAPI IDataObject_fnGetData(LPDATAOBJECT iface, LPFORMATETC32 pformatetcIn, STGMEDIUM32* pmedium);
198 static HRESULT WINAPI IDataObject_fnGetDataHere(LPDATAOBJECT iface, LPFORMATETC32 pformatetc, STGMEDIUM32* pmedium);
199 static HRESULT WINAPI IDataObject_fnQueryGetData(LPDATAOBJECT iface, LPFORMATETC32 pformatetc);
200 static HRESULT WINAPI IDataObject_fnGetCanonicalFormatEtc(LPDATAOBJECT iface, LPFORMATETC32 pformatectIn, LPFORMATETC32 pformatetcOut);
201 static HRESULT WINAPI IDataObject_fnSetData(LPDATAOBJECT iface, LPFORMATETC32 pformatetc, STGMEDIUM32* pmedium, BOOL32 fRelease);
202 static HRESULT WINAPI IDataObject_fnEnumFormatEtc(LPDATAOBJECT iface, DWORD dwDirection, IEnumFORMATETC** ppenumFormatEtc);
203 static HRESULT WINAPI IDataObject_fnDAdvise(LPDATAOBJECT iface, LPFORMATETC32* pformatetc, DWORD advf, IAdviseSink* pAdvSink, DWORD* pdwConnection);
204 static HRESULT WINAPI IDataObject_fnDUnadvise(LPDATAOBJECT iface, DWORD dwConnection);
205 static HRESULT WINAPI IDataObject_fnEnumDAdvise(LPDATAOBJECT iface, IEnumSTATDATA **ppenumAdvise);
206
207 static struct ICOM_VTABLE(IDataObject) dtovt = 
208 {
209         IDataObject_fnQueryInterface,
210         IDataObject_fnAddRef,
211     IDataObject_fnRelease,
212     IDataObject_fnGetData,
213     IDataObject_fnGetDataHere,
214     IDataObject_fnQueryGetData,
215     IDataObject_fnGetCanonicalFormatEtc,
216     IDataObject_fnSetData,
217     IDataObject_fnEnumFormatEtc,
218     IDataObject_fnDAdvise,
219     IDataObject_fnDUnadvise,
220     IDataObject_fnEnumDAdvise
221 };
222
223 /**************************************************************************
224 *  IDataObject_Constructor
225 */
226 LPDATAOBJECT IDataObject_Constructor(HWND32 hwndOwner, LPSHELLFOLDER psf, LPITEMIDLIST * apidl, UINT32 cidl)
227 {
228         IDataObjectImpl* dto;
229         if (!(dto = (IDataObjectImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IDataObjectImpl))))
230           return NULL;
231           
232         dto->ref=1;
233         dto->lpvtbl=&dtovt;
234         dto->psf=psf;
235         dto->pidl=ILClone(psf->mpidl); /* FIXME:add a reference and don't copy*/
236
237         /* fill the ItemID List List */
238         dto->lpill = IDLList_Constructor (8);
239         if (! dto->lpill )
240           return NULL;
241           
242         dto->lpill->lpvtbl->fnAddItems(dto->lpill, apidl, cidl); 
243         
244         TRACE(shell,"(%p)->(sf=%p apidl=%p cidl=%u)\n",dto, psf, apidl, cidl);
245         shell32_ObjCount++;
246         return (LPDATAOBJECT)dto;
247 }
248 /***************************************************************************
249 *  IDataObject_QueryInterface
250 */
251 static HRESULT WINAPI IDataObject_fnQueryInterface(LPDATAOBJECT iface, REFIID riid, LPVOID * ppvObj)
252 {
253         ICOM_THIS(IDataObjectImpl,iface);
254         char    xriid[50];
255         WINE_StringFromCLSID((LPCLSID)riid,xriid);
256         TRACE(shell,"(%p)->(\n\tIID:\t%s,%p)\n",This,xriid,ppvObj);
257
258         *ppvObj = NULL;
259
260         if(IsEqualIID(riid, &IID_IUnknown))          /*IUnknown*/
261         { *ppvObj = This; 
262         }
263         else if(IsEqualIID(riid, &IID_IDataObject))  /*IDataObject*/
264         { *ppvObj = (IDataObject*)This;
265         }   
266
267         if(*ppvObj)
268         { IDataObject_AddRef((IDataObject*)*ppvObj);      
269           TRACE(shell,"-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
270           return S_OK;
271         }
272         TRACE(shell,"-- Interface: E_NOINTERFACE\n");
273         return E_NOINTERFACE;
274 }   
275 /**************************************************************************
276 *  IDataObject_AddRef
277 */
278 static ULONG WINAPI IDataObject_fnAddRef(LPDATAOBJECT iface)
279 {
280         ICOM_THIS(IDataObjectImpl,iface);
281
282         TRACE(shell,"(%p)->(count=%lu)\n",This,(This->ref)+1);
283
284         shell32_ObjCount++;
285         return ++(This->ref);
286 }
287 /**************************************************************************
288 *  IDataObject_Release
289 */
290 static ULONG WINAPI IDataObject_fnRelease(LPDATAOBJECT iface)
291 {
292         ICOM_THIS(IDataObjectImpl,iface);
293         TRACE(shell,"(%p)->()\n",This);
294
295         shell32_ObjCount--;
296
297         if (!--(This->ref)) 
298         { TRACE(shell," destroying IDataObject(%p)\n",This);
299           IDLList_Destructor(This->lpill);
300           HeapFree(GetProcessHeap(),0,This);
301           return 0;
302         }
303         return This->ref;
304 }
305 /**************************************************************************
306 * DATAOBJECT_InitShellIDList (internal)
307 *
308 * NOTES
309 *  get or register the "Shell IDList Array" clipformat
310 */
311 static BOOL32 DATAOBJECT_InitShellIDList(void)
312 {       if (cfShellIDList)
313         { return(TRUE);
314         }
315
316         cfShellIDList = RegisterClipboardFormat32A(CFSTR_SHELLIDLIST);
317         return(cfShellIDList != 0);
318 }
319
320 /**************************************************************************
321 * DATAOBJECT_InitFileGroupDesc (internal)
322 *
323 * NOTES
324 *  get or register the "FileGroupDescriptor" clipformat
325 */
326 /* FIXME: DATAOBJECT_InitFileGroupDesc is not used (19981226)
327 static BOOL32 DATAOBJECT_InitFileGroupDesc(void)
328 {       if (cfFileGroupDesc)
329         { return(TRUE);
330         }
331
332         cfFileGroupDesc = RegisterClipboardFormat32A(CFSTR_FILEDESCRIPTORA);
333         return(cfFileGroupDesc != 0);
334 }
335 */
336 /**************************************************************************
337 * DATAOBJECT_InitFileContents (internal)
338
339 * NOTES
340  * get or register the "FileContents" clipformat
341 */
342 /* FIXME: DATAOBJECT_InitFileContents is not used (19981226)
343 static BOOL32 DATAOBJECT_InitFileContents(void)
344 {       if (cfFileContents)
345         { return(TRUE);
346         }
347
348         cfFileContents = RegisterClipboardFormat32A(CFSTR_FILECONTENTS);
349         return(cfFileContents != 0);
350 }
351 */
352
353 /**************************************************************************
354 * interface implementation
355 */
356 static HRESULT WINAPI IDataObject_fnGetData(LPDATAOBJECT iface, LPFORMATETC32 pformatetcIn, STGMEDIUM32 *pmedium)
357 {
358         ICOM_THIS(IDataObjectImpl,iface);
359         char    temp[256];
360         UINT32  cItems;
361         DWORD   size, size1, size2;
362         LPITEMIDLIST pidl;
363         LPCIDA pcida;
364         HGLOBAL32 hmem;
365         
366         GetClipboardFormatName32A (pformatetcIn->cfFormat, temp, 256);
367         WARN (shell, "(%p)->(%p %p format=%s)semi-stub\n", This, pformatetcIn, pmedium, temp);
368
369         if (!DATAOBJECT_InitShellIDList())      /* is the clipformat registred? */
370         { return(E_UNEXPECTED);
371         }
372         
373         if (pformatetcIn->cfFormat == cfShellIDList)
374         { if (pformatetcIn->ptd==NULL 
375                 && (pformatetcIn->dwAspect & DVASPECT_CONTENT) 
376                 && pformatetcIn->lindex==-1
377                 && (pformatetcIn->tymed&TYMED_HGLOBAL))
378           { cItems = This->lpill->lpvtbl->fnGetCount(This->lpill);
379             if (cItems < 1)
380             { return(E_UNEXPECTED);
381             }
382             pidl = This->lpill->lpvtbl->fnGetElement(This->lpill, 0);
383
384             pdump(This->pidl);
385             pdump(pidl);
386             
387             /*hack consider only the first item*/
388             cItems = 2;
389             size = sizeof(CIDA) + sizeof (UINT32)*(cItems-1);
390             size1 = ILGetSize (This->pidl);
391             size2 = ILGetSize (pidl);
392             hmem = GlobalAlloc32(GMEM_FIXED, size+size1+size2);
393             pcida = GlobalLock32 (hmem);
394             if (!pcida)
395             { return(E_OUTOFMEMORY);
396             }
397
398             pcida->cidl = 1;
399             pcida->aoffset[0] = size;
400             pcida->aoffset[1] = size+size1;
401
402             TRACE(shell,"-- %lu %lu %lu\n",size, size1, size2 );
403             TRACE(shell,"-- %p %p\n",This->pidl, pidl);
404             TRACE(shell,"-- %p %p %p\n",pcida, (LPBYTE)pcida+size,(LPBYTE)pcida+size+size1);
405             
406             memcpy ((LPBYTE)pcida+size, This->pidl, size1);
407             memcpy ((LPBYTE)pcida+size+size1, pidl, size2);
408             TRACE(shell,"-- after copy\n");
409
410             GlobalUnlock32(hmem);
411             
412             pmedium->tymed = TYMED_HGLOBAL;
413             pmedium->u.hGlobal = (HGLOBAL32)pcida;
414             pmedium->pUnkForRelease = NULL;
415             TRACE(shell,"-- ready\n");
416             return(NOERROR);
417           }
418         }
419         FIXME (shell, "-- clipformat not implemented\n");
420         return (E_INVALIDARG);
421 }
422 static HRESULT WINAPI IDataObject_fnGetDataHere(LPDATAOBJECT iface, LPFORMATETC32 pformatetc, STGMEDIUM32 *pmedium)
423 {
424         ICOM_THIS(IDataObjectImpl,iface);
425         FIXME (shell, "(%p)->()\n", This);
426         return E_NOTIMPL;
427 }
428 static HRESULT WINAPI IDataObject_fnQueryGetData(LPDATAOBJECT iface, LPFORMATETC32 pformatetc)
429 {
430         ICOM_THIS(IDataObjectImpl,iface);
431         FIXME (shell, "(%p)->()\n", This);
432         return E_NOTIMPL;
433 }
434 static HRESULT WINAPI IDataObject_fnGetCanonicalFormatEtc(LPDATAOBJECT iface, LPFORMATETC32 pformatectIn, LPFORMATETC32 pformatetcOut)
435 {
436         ICOM_THIS(IDataObjectImpl,iface);
437         FIXME (shell, "(%p)->()\n", This);
438         return E_NOTIMPL;
439 }
440 static HRESULT WINAPI IDataObject_fnSetData(LPDATAOBJECT iface, LPFORMATETC32 pformatetc, STGMEDIUM32 *pmedium, BOOL32 fRelease)
441 {
442         ICOM_THIS(IDataObjectImpl,iface);
443         FIXME (shell, "(%p)->()\n", This);
444         return E_NOTIMPL;
445 }
446 static HRESULT WINAPI IDataObject_fnEnumFormatEtc(LPDATAOBJECT iface, DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc)
447 {
448         ICOM_THIS(IDataObjectImpl,iface);
449         FIXME (shell, "(%p)->()\n", This);
450         return E_NOTIMPL;
451 }
452 static HRESULT WINAPI IDataObject_fnDAdvise(LPDATAOBJECT iface, LPFORMATETC32 *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection)
453 {
454         ICOM_THIS(IDataObjectImpl,iface);
455         FIXME (shell, "(%p)->()\n", This);
456         return E_NOTIMPL;
457 }
458 static HRESULT WINAPI IDataObject_fnDUnadvise(LPDATAOBJECT iface, DWORD dwConnection)
459 {
460         ICOM_THIS(IDataObjectImpl,iface);
461         FIXME (shell, "(%p)->()\n", This);
462         return E_NOTIMPL;
463 }
464 static HRESULT WINAPI IDataObject_fnEnumDAdvise(LPDATAOBJECT iface, IEnumSTATDATA **ppenumAdvise)
465 {
466         ICOM_THIS(IDataObjectImpl,iface);
467         FIXME (shell, "(%p)->()\n", This);
468         return E_NOTIMPL;
469 }