Changed // comments to /* */ so WINE compiles with non-gcc compilers
[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 "shlobj.h"
11 #include "pidl.h"
12 #include "winerror.h"
13 #include "shell32_main.h"
14
15 UINT32 cfShellIDList=0;
16 UINT32 cfFileGroupDesc=0;
17 UINT32 cfFileContents=0;
18
19 /***********************************************************************
20 *   IEnumFORMATETC implementation
21 */
22 static HRESULT WINAPI IEnumFORMATETC_QueryInterface (LPENUMFORMATETC this, REFIID riid, LPVOID * ppvObj);
23 static ULONG WINAPI IEnumFORMATETC_AddRef (LPENUMFORMATETC this);
24 static ULONG WINAPI IEnumFORMATETC_Release (LPENUMFORMATETC this);
25 static HRESULT WINAPI IEnumFORMATETC_Next(LPENUMFORMATETC this, ULONG celt, FORMATETC32 *rgelt, ULONG *pceltFethed);
26 static HRESULT WINAPI IEnumFORMATETC_Skip(LPENUMFORMATETC this, ULONG celt);
27 static HRESULT WINAPI IEnumFORMATETC_Reset(LPENUMFORMATETC this);
28 static HRESULT WINAPI IEnumFORMATETC_Clone(LPENUMFORMATETC this, LPENUMFORMATETC* ppenum);
29
30 static struct IEnumFORMATETC_VTable efvt = 
31 {       IEnumFORMATETC_QueryInterface,
32         IEnumFORMATETC_AddRef,
33         IEnumFORMATETC_Release,
34         IEnumFORMATETC_Next,
35         IEnumFORMATETC_Skip,
36         IEnumFORMATETC_Reset,
37         IEnumFORMATETC_Clone
38 };
39
40 extern LPENUMFORMATETC IEnumFORMATETC_Constructor(UINT32 cfmt, const FORMATETC32 afmt[])
41 {       LPENUMFORMATETC ef;
42         DWORD size=cfmt * sizeof(FORMATETC32);
43         
44         ef=(LPENUMFORMATETC)HeapAlloc(GetProcessHeap(),0,sizeof(IEnumFORMATETC));
45         ef->ref=1;
46         ef->lpvtbl=&efvt;
47
48         ef->posFmt = 0;
49         ef->countFmt = cfmt;
50         ef->pFmt = SHAlloc (size);
51
52         if (ef->pFmt)
53         { memcpy(ef->pFmt, afmt, size);
54         }
55
56         TRACE(shell,"(%p)->()\n",ef);
57         return ef;
58 }
59 static HRESULT WINAPI IEnumFORMATETC_QueryInterface (LPENUMFORMATETC this, REFIID riid, LPVOID * ppvObj)
60 {       char    xriid[50];
61         WINE_StringFromCLSID((LPCLSID)riid,xriid);
62         TRACE(shell,"(%p)->(\n\tIID:\t%s,%p)\n",this,xriid,ppvObj);
63
64                         *ppvObj = NULL;
65
66         if(IsEqualIID(riid, &IID_IUnknown))
67         { *ppvObj = this; 
68         }
69         else if(IsEqualIID(riid, &IID_IEnumFORMATETC))
70         { *ppvObj = (IDataObject*)this;
71         }   
72
73         if(*ppvObj)
74         { (*(LPENUMFORMATETC*)ppvObj)->lpvtbl->fnAddRef(this);      
75           TRACE(shell,"-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
76           return S_OK;
77         }
78         TRACE(shell,"-- Interface: E_NOINTERFACE\n");
79         return E_NOINTERFACE;
80
81 }
82 static ULONG WINAPI IEnumFORMATETC_AddRef (LPENUMFORMATETC this)
83 {       TRACE(shell,"(%p)->(count=%lu)\n",this,(this->ref)+1);
84         return ++(this->ref);
85 }
86 static ULONG WINAPI IEnumFORMATETC_Release (LPENUMFORMATETC this)
87 {       TRACE(shell,"(%p)->()\n",this);
88         if (!--(this->ref)) 
89         { TRACE(shell," destroying IEnumFORMATETC(%p)\n",this);
90           if (this->pFmt)
91           { SHFree (this->pFmt);
92           }
93           HeapFree(GetProcessHeap(),0,this);
94           return 0;
95         }
96         return this->ref;
97 }
98 static HRESULT WINAPI IEnumFORMATETC_Next(LPENUMFORMATETC this, ULONG celt, FORMATETC32 *rgelt, ULONG *pceltFethed)
99 {       UINT32 cfetch;
100         HRESULT hres = S_FALSE;
101
102         TRACE (shell, "(%p)->()\n", this);
103
104         if (this->posFmt < this->countFmt)
105         { cfetch = this->countFmt - this->posFmt;
106           if (cfetch >= celt)
107           { cfetch = celt;
108             hres = S_OK;
109           }
110           memcpy(rgelt, &this->pFmt[this->posFmt], cfetch * sizeof(FORMATETC32));
111           this->posFmt += cfetch;
112         }
113         else
114         { cfetch = 0;
115         }
116
117         if (pceltFethed)
118         { *pceltFethed = cfetch;
119         }
120
121         return hres;
122 }
123 static HRESULT WINAPI IEnumFORMATETC_Skip(LPENUMFORMATETC this, ULONG celt)
124 {       FIXME (shell, "(%p)->(num=%lu)\n", this, celt);
125
126         this->posFmt += celt;
127         if (this->posFmt > this->countFmt)
128         { this->posFmt = this->countFmt;
129           return S_FALSE;
130         }
131         return S_OK;
132 }
133 static HRESULT WINAPI IEnumFORMATETC_Reset(LPENUMFORMATETC this)
134 {       FIXME (shell, "(%p)->()\n", this);
135
136         this->posFmt = 0;
137         return S_OK;
138 }
139 static HRESULT WINAPI IEnumFORMATETC_Clone(LPENUMFORMATETC this, LPENUMFORMATETC* ppenum)
140 {       FIXME (shell, "(%p)->(ppenum=%p)\n", this, ppenum);
141         return E_NOTIMPL;
142 }
143
144 /***********************************************************************
145 *   IDataObject implementation
146 */
147
148 static HRESULT WINAPI IDataObject_QueryInterface (LPDATAOBJECT, REFIID riid, LPVOID * ppvObj);
149 static ULONG WINAPI IDataObject_AddRef (LPDATAOBJECT);
150 static ULONG WINAPI IDataObject_Release (LPDATAOBJECT);
151 static HRESULT WINAPI IDataObject_GetData (LPDATAOBJECT, LPFORMATETC32 pformatetcIn, STGMEDIUM32 *pmedium);
152 static HRESULT WINAPI IDataObject_GetDataHere(LPDATAOBJECT, LPFORMATETC32 pformatetc, STGMEDIUM32 *pmedium);
153 static HRESULT WINAPI IDataObject_QueryGetData(LPDATAOBJECT, LPFORMATETC32 pformatetc);
154 static HRESULT WINAPI IDataObject_GetCanonicalFormatEtc(LPDATAOBJECT, LPFORMATETC32 pformatectIn, LPFORMATETC32 pformatetcOut);
155 static HRESULT WINAPI IDataObject_SetData(LPDATAOBJECT, LPFORMATETC32 pformatetc, STGMEDIUM32 *pmedium, BOOL32 fRelease);
156 static HRESULT WINAPI IDataObject_EnumFormatEtc(LPDATAOBJECT, DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc);
157 static HRESULT WINAPI IDataObject_DAdvise (LPDATAOBJECT, LPFORMATETC32 *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection);
158 static HRESULT WINAPI IDataObject_DUnadvise(LPDATAOBJECT, DWORD dwConnection);
159 static HRESULT WINAPI IDataObject_EnumDAdvise(LPDATAOBJECT, IEnumSTATDATA **ppenumAdvise);
160
161 static struct IDataObject_VTable dtovt = 
162 {       IDataObject_QueryInterface,
163         IDataObject_AddRef,
164         IDataObject_Release,
165         IDataObject_GetData,
166         IDataObject_GetDataHere,
167         IDataObject_QueryGetData,
168         IDataObject_GetCanonicalFormatEtc,
169         IDataObject_SetData,
170         IDataObject_EnumFormatEtc,
171         IDataObject_DAdvise,
172         IDataObject_DUnadvise,
173         IDataObject_EnumDAdvise
174 };
175
176 /**************************************************************************
177 *  IDataObject_Constructor
178 */
179 LPDATAOBJECT IDataObject_Constructor(HWND32 hwndOwner, LPSHELLFOLDER psf, LPITEMIDLIST * apidl, UINT32 cidl)
180 {       LPDATAOBJECT dto;
181         if (!(dto = (LPDATAOBJECT)HeapAlloc(GetProcessHeap(),0,sizeof(IDataObject))))
182           return NULL;
183           
184         dto->ref=1;
185         dto->lpvtbl=&dtovt;
186         dto->psf=psf;
187         dto->pidl=ILClone(psf->mpidl); /* FIXME:add a reference and don't copy*/
188
189         /* fill the ItemID List List */
190         dto->lpill = IDLList_Constructor (8);
191         if (! dto->lpill )
192           return NULL;
193           
194         dto->lpill->lpvtbl->fnAddItems(dto->lpill, apidl, cidl); 
195         
196         TRACE(shell,"(%p)->(sf=%p apidl=%p cidl=%u)\n",dto, psf, apidl, cidl);
197         return dto;
198 }
199 /***************************************************************************
200 *  IDataObject_QueryInterface
201 */
202 static HRESULT WINAPI IDataObject_QueryInterface (LPDATAOBJECT this, REFIID riid, LPVOID * ppvObj)
203 {       char    xriid[50];
204         WINE_StringFromCLSID((LPCLSID)riid,xriid);
205         TRACE(shell,"(%p)->(\n\tIID:\t%s,%p)\n",this,xriid,ppvObj);
206
207         *ppvObj = NULL;
208
209         if(IsEqualIID(riid, &IID_IUnknown))          /*IUnknown*/
210         { *ppvObj = this; 
211         }
212         else if(IsEqualIID(riid, &IID_IDataObject))  /*IDataObject*/
213         { *ppvObj = (IDataObject*)this;
214         }   
215
216         if(*ppvObj)
217         { (*(LPDATAOBJECT*)ppvObj)->lpvtbl->fnAddRef(this);      
218           TRACE(shell,"-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
219           return S_OK;
220         }
221         TRACE(shell,"-- Interface: E_NOINTERFACE\n");
222         return E_NOINTERFACE;
223 }   
224 /**************************************************************************
225 *  IDataObject_AddRef
226 */
227 static ULONG WINAPI IDataObject_AddRef(LPDATAOBJECT this)
228 {       TRACE(shell,"(%p)->(count=%lu)\n",this,(this->ref)+1);
229         return ++(this->ref);
230 }
231 /**************************************************************************
232 *  IDataObject_Release
233 */
234 static ULONG WINAPI IDataObject_Release(LPDATAOBJECT this)
235 {       TRACE(shell,"(%p)->()\n",this);
236         if (!--(this->ref)) 
237         { TRACE(shell," destroying IDataObject(%p)\n",this);
238           IDLList_Destructor(this->lpill);
239           HeapFree(GetProcessHeap(),0,this);
240           return 0;
241         }
242         return this->ref;
243 }
244 /**************************************************************************
245 * DATAOBJECT_InitShellIDList (internal)
246 *
247 * NOTES
248 *  get or register the "Shell IDList Array" clipformat
249 */
250 static BOOL32 DATAOBJECT_InitShellIDList(void)
251 {       if (cfShellIDList)
252         { return(TRUE);
253         }
254
255         cfShellIDList = RegisterClipboardFormat32A(CFSTR_SHELLIDLIST);
256         return(cfShellIDList != 0);
257 }
258
259 /**************************************************************************
260 * DATAOBJECT_InitFileGroupDesc (internal)
261 *
262 * NOTES
263 *  get or register the "FileGroupDescriptor" clipformat
264 */
265 static BOOL32 DATAOBJECT_InitFileGroupDesc(void)
266 {       if (cfFileGroupDesc)
267         { return(TRUE);
268         }
269
270         cfFileGroupDesc = RegisterClipboardFormat32A(CFSTR_FILEDESCRIPTORA);
271         return(cfFileGroupDesc != 0);
272 }
273 /**************************************************************************
274 * DATAOBJECT_InitFileContents (internal)
275
276 * NOTES
277  * get or register the "FileContents" clipformat
278 */
279 static BOOL32 DATAOBJECT_InitFileContents(void)
280 {       if (cfFileContents)
281         { return(TRUE);
282         }
283
284         cfFileContents = RegisterClipboardFormat32A(CFSTR_FILECONTENTS);
285         return(cfFileContents != 0);
286 }
287
288
289 /**************************************************************************
290 * interface implementation
291 */
292 static HRESULT WINAPI IDataObject_GetData (LPDATAOBJECT this, LPFORMATETC32 pformatetcIn, STGMEDIUM32 *pmedium)
293 {       char    temp[256];
294         UINT32  cItems;
295         DWORD   size, size1, size2;
296         LPITEMIDLIST pidl;
297         LPCIDA pcida;
298         HGLOBAL32 hmem;
299         
300         GetClipboardFormatName32A (pformatetcIn->cfFormat, temp, 256);
301         WARN (shell, "(%p)->(%p %p format=%s)semi-stub\n", this, pformatetcIn, pmedium, temp);
302
303         if (!DATAOBJECT_InitShellIDList())      /* is the clipformat registred? */
304         { return(E_UNEXPECTED);
305         }
306         
307         if (pformatetcIn->cfFormat == cfShellIDList)
308         { if (pformatetcIn->ptd==NULL 
309                 && (pformatetcIn->dwAspect & DVASPECT_CONTENT) 
310                 && pformatetcIn->lindex==-1
311                 && (pformatetcIn->tymed&TYMED_HGLOBAL))
312           { cItems = this->lpill->lpvtbl->fnGetCount(this->lpill);
313             if (cItems < 1)
314             { return(E_UNEXPECTED);
315             }
316             pidl = this->lpill->lpvtbl->fnGetElement(this->lpill, 0);
317
318             pdump(this->pidl);
319             pdump(pidl);
320             
321             /*hack consider only the first item*/
322             cItems = 2;
323             size = sizeof(CIDA) + sizeof (UINT32)*(cItems-1);
324             size1 = ILGetSize (this->pidl);
325             size2 = ILGetSize (pidl);
326             hmem = GlobalAlloc32(GMEM_FIXED, size+size1+size2);
327             pcida = GlobalLock32 (hmem);
328             if (!pcida)
329             { return(E_OUTOFMEMORY);
330             }
331
332             pcida->cidl = 1;
333             pcida->aoffset[0] = size;
334             pcida->aoffset[1] = size+size1;
335
336             TRACE(shell,"-- %lu %lu %lu\n",size, size1, size2 );
337             TRACE(shell,"-- %p %p\n",this->pidl, pidl);
338             TRACE(shell,"-- %p %p %p\n",pcida, (LPBYTE)pcida+size,(LPBYTE)pcida+size+size1);
339             
340             memcpy ((LPBYTE)pcida+size, this->pidl, size1);
341             memcpy ((LPBYTE)pcida+size+size1, pidl, size2);
342             TRACE(shell,"-- after copy\n");
343
344             GlobalUnlock32(hmem);
345             
346             pmedium->tymed = TYMED_HGLOBAL;
347             pmedium->u.hGlobal = (HGLOBAL32)pcida;
348             pmedium->pUnkForRelease = NULL;
349             TRACE(shell,"-- ready\n");
350             return(NOERROR);
351           }
352         }
353         FIXME (shell, "-- clipformat not implemented\n");
354         return (E_INVALIDARG);
355 }
356 static HRESULT WINAPI IDataObject_GetDataHere(LPDATAOBJECT this, LPFORMATETC32 pformatetc, STGMEDIUM32 *pmedium)
357 {       FIXME (shell, "(%p)->()\n", this);
358         return E_NOTIMPL;
359 }
360 static HRESULT WINAPI IDataObject_QueryGetData(LPDATAOBJECT this, LPFORMATETC32 pformatetc)
361 {       FIXME (shell, "(%p)->()\n", this);
362         return E_NOTIMPL;
363 }
364 static HRESULT WINAPI IDataObject_GetCanonicalFormatEtc(LPDATAOBJECT this, LPFORMATETC32 pformatectIn, LPFORMATETC32 pformatetcOut)
365 {       FIXME (shell, "(%p)->()\n", this);
366         return E_NOTIMPL;
367 }
368 static HRESULT WINAPI IDataObject_SetData(LPDATAOBJECT this, LPFORMATETC32 pformatetc, STGMEDIUM32 *pmedium, BOOL32 fRelease)
369 {       FIXME (shell, "(%p)->()\n", this);
370         return E_NOTIMPL;
371 }
372 static HRESULT WINAPI IDataObject_EnumFormatEtc(LPDATAOBJECT this, DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc)
373 {       FIXME (shell, "(%p)->()\n", this);
374         return E_NOTIMPL;
375 }
376 static HRESULT WINAPI IDataObject_DAdvise (LPDATAOBJECT this, LPFORMATETC32 *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection)
377 {       FIXME (shell, "(%p)->()\n", this);
378         return E_NOTIMPL;
379 }
380 static HRESULT WINAPI IDataObject_DUnadvise(LPDATAOBJECT this, DWORD dwConnection)
381 {       FIXME (shell, "(%p)->()\n", this);
382         return E_NOTIMPL;
383 }
384 static HRESULT WINAPI IDataObject_EnumDAdvise(LPDATAOBJECT this, IEnumSTATDATA **ppenumAdvise)
385 {       FIXME (shell, "(%p)->()\n", this);
386         return E_NOTIMPL;
387 }