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