Recovery of release 990110 after disk crash.
[wine.git] / dlls / shell32 / dataobject.c
blob849a92d52150b4198a11a60c2d2096bf28eae976
1 /*
2 * IEnumFORMATETC, IDataObject
4 * selecting and droping objects within the shell and/or common dialogs
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"
19 UINT32 cfShellIDList=0;
20 UINT32 cfFileGroupDesc=0;
21 UINT32 cfFileContents=0;
23 /***********************************************************************
24 * IEnumFORMATETC implementation
26 typedef struct _IEnumFORMATETC
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;
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);
45 static struct ICOM_VTABLE(IEnumFORMATETC) efvt =
48 IEnumFORMATETC_fnQueryInterface,
49 IEnumFORMATETC_fnAddRef,
50 IEnumFORMATETC_fnRelease
52 IEnumFORMATETC_fnNext,
53 IEnumFORMATETC_fnSkip,
54 IEnumFORMATETC_fnReset,
55 IEnumFORMATETC_fnClone
58 LPENUMFORMATETC IEnumFORMATETC_Constructor(UINT32 cfmt, const FORMATETC32 afmt[])
60 _IEnumFORMATETC* ef;
61 DWORD size=cfmt * sizeof(FORMATETC32);
63 ef=(_IEnumFORMATETC*)HeapAlloc(GetProcessHeap(),0,sizeof(_IEnumFORMATETC));
64 ef->ref=1;
65 ef->lpvtbl=&efvt;
67 ef->posFmt = 0;
68 ef->countFmt = cfmt;
69 ef->pFmt = SHAlloc (size);
71 if (ef->pFmt)
72 { memcpy(ef->pFmt, afmt, size);
75 TRACE(shell,"(%p)->()\n",ef);
76 return (LPENUMFORMATETC)ef;
78 static HRESULT WINAPI IEnumFORMATETC_fnQueryInterface(LPUNKNOWN iface, REFIID riid, LPVOID* ppvObj)
80 ICOM_THIS(IEnumFORMATETC,iface);
81 char xriid[50];
82 WINE_StringFromCLSID((LPCLSID)riid,xriid);
83 TRACE(shell,"(%p)->(\n\tIID:\t%s,%p)\n",this,xriid,ppvObj);
85 *ppvObj = NULL;
87 if(IsEqualIID(riid, &IID_IUnknown))
88 { *ppvObj = this;
90 else if(IsEqualIID(riid, &IID_IEnumFORMATETC))
91 { *ppvObj = (IDataObject*)this;
94 if(*ppvObj)
95 { IEnumFORMATETC_AddRef((IEnumFORMATETC*)*ppvObj);
96 TRACE(shell,"-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
97 return S_OK;
99 TRACE(shell,"-- Interface: E_NOINTERFACE\n");
100 return E_NOINTERFACE;
103 static ULONG WINAPI IEnumFORMATETC_fnAddRef(LPUNKNOWN iface)
105 ICOM_THIS(IEnumFORMATETC,iface);
106 TRACE(shell,"(%p)->(count=%lu)\n",this,(this->ref)+1);
107 return ++(this->ref);
109 static ULONG WINAPI IEnumFORMATETC_fnRelease(LPUNKNOWN iface)
111 ICOM_THIS(IEnumFORMATETC,iface);
112 TRACE(shell,"(%p)->()\n",this);
113 if (!--(this->ref))
114 { TRACE(shell," destroying IEnumFORMATETC(%p)\n",this);
115 if (this->pFmt)
116 { SHFree (this->pFmt);
118 HeapFree(GetProcessHeap(),0,this);
119 return 0;
121 return this->ref;
123 static HRESULT WINAPI IEnumFORMATETC_fnNext(LPENUMFORMATETC iface, ULONG celt, FORMATETC32 *rgelt, ULONG *pceltFethed)
125 ICOM_THIS(IEnumFORMATETC,iface);
126 UINT32 cfetch;
127 HRESULT hres = S_FALSE;
129 TRACE (shell, "(%p)->()\n", this);
131 if (this->posFmt < this->countFmt)
132 { cfetch = this->countFmt - this->posFmt;
133 if (cfetch >= celt)
134 { cfetch = celt;
135 hres = S_OK;
137 memcpy(rgelt, &this->pFmt[this->posFmt], cfetch * sizeof(FORMATETC32));
138 this->posFmt += cfetch;
140 else
141 { cfetch = 0;
144 if (pceltFethed)
145 { *pceltFethed = cfetch;
148 return hres;
150 static HRESULT WINAPI IEnumFORMATETC_fnSkip(LPENUMFORMATETC iface, ULONG celt)
152 ICOM_THIS(IEnumFORMATETC,iface);
153 FIXME (shell, "(%p)->(num=%lu)\n", this, celt);
155 this->posFmt += celt;
156 if (this->posFmt > this->countFmt)
157 { this->posFmt = this->countFmt;
158 return S_FALSE;
160 return S_OK;
162 static HRESULT WINAPI IEnumFORMATETC_fnReset(LPENUMFORMATETC iface)
164 ICOM_THIS(IEnumFORMATETC,iface);
165 FIXME (shell, "(%p)->()\n", this);
167 this->posFmt = 0;
168 return S_OK;
170 static HRESULT WINAPI IEnumFORMATETC_fnClone(LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum)
172 ICOM_THIS(IEnumFORMATETC,iface);
173 FIXME (shell, "(%p)->(ppenum=%p)\n", this, ppenum);
174 return E_NOTIMPL;
177 /***********************************************************************
178 * IDataObject implementation
180 typedef struct _IDataObject
182 /* IUnknown fields */
183 ICOM_VTABLE(IDataObject)* lpvtbl;
184 DWORD ref;
185 /* IDataObject fields */
186 LPSHELLFOLDER psf;
187 LPIDLLIST lpill; /* the data of the dataobject */
188 LPITEMIDLIST pidl;
189 } _IDataObject;
191 static HRESULT WINAPI IDataObject_fnQueryInterface(LPUNKNOWN iface, REFIID riid, LPVOID* ppvObj);
192 static ULONG WINAPI IDataObject_fnAddRef(LPUNKNOWN iface);
193 static ULONG WINAPI IDataObject_fnRelease(LPUNKNOWN iface);
194 static HRESULT WINAPI IDataObject_fnGetData(LPDATAOBJECT iface, LPFORMATETC32 pformatetcIn, STGMEDIUM32* pmedium);
195 static HRESULT WINAPI IDataObject_fnGetDataHere(LPDATAOBJECT iface, LPFORMATETC32 pformatetc, STGMEDIUM32* pmedium);
196 static HRESULT WINAPI IDataObject_fnQueryGetData(LPDATAOBJECT iface, LPFORMATETC32 pformatetc);
197 static HRESULT WINAPI IDataObject_fnGetCanonicalFormatEtc(LPDATAOBJECT iface, LPFORMATETC32 pformatectIn, LPFORMATETC32 pformatetcOut);
198 static HRESULT WINAPI IDataObject_fnSetData(LPDATAOBJECT iface, LPFORMATETC32 pformatetc, STGMEDIUM32* pmedium, BOOL32 fRelease);
199 static HRESULT WINAPI IDataObject_fnEnumFormatEtc(LPDATAOBJECT iface, DWORD dwDirection, IEnumFORMATETC** ppenumFormatEtc);
200 static HRESULT WINAPI IDataObject_fnDAdvise(LPDATAOBJECT iface, LPFORMATETC32* pformatetc, DWORD advf, IAdviseSink* pAdvSink, DWORD* pdwConnection);
201 static HRESULT WINAPI IDataObject_fnDUnadvise(LPDATAOBJECT iface, DWORD dwConnection);
202 static HRESULT WINAPI IDataObject_fnEnumDAdvise(LPDATAOBJECT iface, IEnumSTATDATA **ppenumAdvise);
204 static struct ICOM_VTABLE(IDataObject) dtovt =
207 IDataObject_fnQueryInterface,
208 IDataObject_fnAddRef,
209 IDataObject_fnRelease
211 IDataObject_fnGetData,
212 IDataObject_fnGetDataHere,
213 IDataObject_fnQueryGetData,
214 IDataObject_fnGetCanonicalFormatEtc,
215 IDataObject_fnSetData,
216 IDataObject_fnEnumFormatEtc,
217 IDataObject_fnDAdvise,
218 IDataObject_fnDUnadvise,
219 IDataObject_fnEnumDAdvise
222 /**************************************************************************
223 * IDataObject_Constructor
225 LPDATAOBJECT IDataObject_Constructor(HWND32 hwndOwner, LPSHELLFOLDER psf, LPITEMIDLIST * apidl, UINT32 cidl)
227 _IDataObject* dto;
228 if (!(dto = (_IDataObject*)HeapAlloc(GetProcessHeap(),0,sizeof(_IDataObject))))
229 return NULL;
231 dto->ref=1;
232 dto->lpvtbl=&dtovt;
233 dto->psf=psf;
234 dto->pidl=ILClone(psf->mpidl); /* FIXME:add a reference and don't copy*/
236 /* fill the ItemID List List */
237 dto->lpill = IDLList_Constructor (8);
238 if (! dto->lpill )
239 return NULL;
241 dto->lpill->lpvtbl->fnAddItems(dto->lpill, apidl, cidl);
243 TRACE(shell,"(%p)->(sf=%p apidl=%p cidl=%u)\n",dto, psf, apidl, cidl);
244 return (LPDATAOBJECT)dto;
246 /***************************************************************************
247 * IDataObject_QueryInterface
249 static HRESULT WINAPI IDataObject_fnQueryInterface (LPUNKNOWN iface, REFIID riid, LPVOID * ppvObj)
251 ICOM_THIS(IDataObject,iface);
252 char xriid[50];
253 WINE_StringFromCLSID((LPCLSID)riid,xriid);
254 TRACE(shell,"(%p)->(\n\tIID:\t%s,%p)\n",this,xriid,ppvObj);
256 *ppvObj = NULL;
258 if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/
259 { *ppvObj = this;
261 else if(IsEqualIID(riid, &IID_IDataObject)) /*IDataObject*/
262 { *ppvObj = (IDataObject*)this;
265 if(*ppvObj)
266 { IDataObject_AddRef((IDataObject*)*ppvObj);
267 TRACE(shell,"-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
268 return S_OK;
270 TRACE(shell,"-- Interface: E_NOINTERFACE\n");
271 return E_NOINTERFACE;
273 /**************************************************************************
274 * IDataObject_AddRef
276 static ULONG WINAPI IDataObject_fnAddRef(LPUNKNOWN iface)
278 ICOM_THIS(IDataObject,iface);
279 TRACE(shell,"(%p)->(count=%lu)\n",this,(this->ref)+1);
280 return ++(this->ref);
282 /**************************************************************************
283 * IDataObject_Release
285 static ULONG WINAPI IDataObject_fnRelease(LPUNKNOWN iface)
287 ICOM_THIS(IDataObject,iface);
288 TRACE(shell,"(%p)->()\n",this);
289 if (!--(this->ref))
290 { TRACE(shell," destroying IDataObject(%p)\n",this);
291 IDLList_Destructor(this->lpill);
292 HeapFree(GetProcessHeap(),0,this);
293 return 0;
295 return this->ref;
297 /**************************************************************************
298 * DATAOBJECT_InitShellIDList (internal)
300 * NOTES
301 * get or register the "Shell IDList Array" clipformat
303 static BOOL32 DATAOBJECT_InitShellIDList(void)
304 { if (cfShellIDList)
305 { return(TRUE);
308 cfShellIDList = RegisterClipboardFormat32A(CFSTR_SHELLIDLIST);
309 return(cfShellIDList != 0);
312 /**************************************************************************
313 * DATAOBJECT_InitFileGroupDesc (internal)
315 * NOTES
316 * get or register the "FileGroupDescriptor" clipformat
318 /* FIXME: DATAOBJECT_InitFileGroupDesc is not used (19981226)
319 static BOOL32 DATAOBJECT_InitFileGroupDesc(void)
320 { if (cfFileGroupDesc)
321 { return(TRUE);
324 cfFileGroupDesc = RegisterClipboardFormat32A(CFSTR_FILEDESCRIPTORA);
325 return(cfFileGroupDesc != 0);
328 /**************************************************************************
329 * DATAOBJECT_InitFileContents (internal)
331 * NOTES
332 * get or register the "FileContents" clipformat
334 /* FIXME: DATAOBJECT_InitFileContents is not used (19981226)
335 static BOOL32 DATAOBJECT_InitFileContents(void)
336 { if (cfFileContents)
337 { return(TRUE);
340 cfFileContents = RegisterClipboardFormat32A(CFSTR_FILECONTENTS);
341 return(cfFileContents != 0);
345 /**************************************************************************
346 * interface implementation
348 static HRESULT WINAPI IDataObject_fnGetData(LPDATAOBJECT iface, LPFORMATETC32 pformatetcIn, STGMEDIUM32 *pmedium)
350 ICOM_THIS(IDataObject,iface);
351 char temp[256];
352 UINT32 cItems;
353 DWORD size, size1, size2;
354 LPITEMIDLIST pidl;
355 LPCIDA pcida;
356 HGLOBAL32 hmem;
358 GetClipboardFormatName32A (pformatetcIn->cfFormat, temp, 256);
359 WARN (shell, "(%p)->(%p %p format=%s)semi-stub\n", this, pformatetcIn, pmedium, temp);
361 if (!DATAOBJECT_InitShellIDList()) /* is the clipformat registred? */
362 { return(E_UNEXPECTED);
365 if (pformatetcIn->cfFormat == cfShellIDList)
366 { if (pformatetcIn->ptd==NULL
367 && (pformatetcIn->dwAspect & DVASPECT_CONTENT)
368 && pformatetcIn->lindex==-1
369 && (pformatetcIn->tymed&TYMED_HGLOBAL))
370 { cItems = this->lpill->lpvtbl->fnGetCount(this->lpill);
371 if (cItems < 1)
372 { return(E_UNEXPECTED);
374 pidl = this->lpill->lpvtbl->fnGetElement(this->lpill, 0);
376 pdump(this->pidl);
377 pdump(pidl);
379 /*hack consider only the first item*/
380 cItems = 2;
381 size = sizeof(CIDA) + sizeof (UINT32)*(cItems-1);
382 size1 = ILGetSize (this->pidl);
383 size2 = ILGetSize (pidl);
384 hmem = GlobalAlloc32(GMEM_FIXED, size+size1+size2);
385 pcida = GlobalLock32 (hmem);
386 if (!pcida)
387 { return(E_OUTOFMEMORY);
390 pcida->cidl = 1;
391 pcida->aoffset[0] = size;
392 pcida->aoffset[1] = size+size1;
394 TRACE(shell,"-- %lu %lu %lu\n",size, size1, size2 );
395 TRACE(shell,"-- %p %p\n",this->pidl, pidl);
396 TRACE(shell,"-- %p %p %p\n",pcida, (LPBYTE)pcida+size,(LPBYTE)pcida+size+size1);
398 memcpy ((LPBYTE)pcida+size, this->pidl, size1);
399 memcpy ((LPBYTE)pcida+size+size1, pidl, size2);
400 TRACE(shell,"-- after copy\n");
402 GlobalUnlock32(hmem);
404 pmedium->tymed = TYMED_HGLOBAL;
405 pmedium->u.hGlobal = (HGLOBAL32)pcida;
406 pmedium->pUnkForRelease = NULL;
407 TRACE(shell,"-- ready\n");
408 return(NOERROR);
411 FIXME (shell, "-- clipformat not implemented\n");
412 return (E_INVALIDARG);
414 static HRESULT WINAPI IDataObject_fnGetDataHere(LPDATAOBJECT iface, LPFORMATETC32 pformatetc, STGMEDIUM32 *pmedium)
416 ICOM_THIS(IDataObject,iface);
417 FIXME (shell, "(%p)->()\n", this);
418 return E_NOTIMPL;
420 static HRESULT WINAPI IDataObject_fnQueryGetData(LPDATAOBJECT iface, LPFORMATETC32 pformatetc)
422 ICOM_THIS(IDataObject,iface);
423 FIXME (shell, "(%p)->()\n", this);
424 return E_NOTIMPL;
426 static HRESULT WINAPI IDataObject_fnGetCanonicalFormatEtc(LPDATAOBJECT iface, LPFORMATETC32 pformatectIn, LPFORMATETC32 pformatetcOut)
428 ICOM_THIS(IDataObject,iface);
429 FIXME (shell, "(%p)->()\n", this);
430 return E_NOTIMPL;
432 static HRESULT WINAPI IDataObject_fnSetData(LPDATAOBJECT iface, LPFORMATETC32 pformatetc, STGMEDIUM32 *pmedium, BOOL32 fRelease)
434 ICOM_THIS(IDataObject,iface);
435 FIXME (shell, "(%p)->()\n", this);
436 return E_NOTIMPL;
438 static HRESULT WINAPI IDataObject_fnEnumFormatEtc(LPDATAOBJECT iface, DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc)
440 ICOM_THIS(IDataObject,iface);
441 FIXME (shell, "(%p)->()\n", this);
442 return E_NOTIMPL;
444 static HRESULT WINAPI IDataObject_fnDAdvise(LPDATAOBJECT iface, LPFORMATETC32 *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection)
446 ICOM_THIS(IDataObject,iface);
447 FIXME (shell, "(%p)->()\n", this);
448 return E_NOTIMPL;
450 static HRESULT WINAPI IDataObject_fnDUnadvise(LPDATAOBJECT iface, DWORD dwConnection)
452 ICOM_THIS(IDataObject,iface);
453 FIXME (shell, "(%p)->()\n", this);
454 return E_NOTIMPL;
456 static HRESULT WINAPI IDataObject_fnEnumDAdvise(LPDATAOBJECT iface, IEnumSTATDATA **ppenumAdvise)
458 ICOM_THIS(IDataObject,iface);
459 FIXME (shell, "(%p)->()\n", this);
460 return E_NOTIMPL;