2 * IEnumFORMATETC, IDataObject
4 * selecting and droping objects within the shell and/or common dialogs
6 * Copyright 1998, 1999 <juergen.schmied@metronet.de>
13 #include "shell32_main.h"
14 #include "debugtools.h"
15 #include "wine/undocshell.h"
16 #include "wine/obj_dataobject.h"
18 DEFAULT_DEBUG_CHANNEL(shell)
20 /***********************************************************************
21 * IEnumFORMATETC implementation
27 ICOM_VFIELD(IEnumFORMATETC);
29 /* IEnumFORMATETC fields */
35 static HRESULT WINAPI IEnumFORMATETC_fnQueryInterface(LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj);
36 static ULONG WINAPI IEnumFORMATETC_fnAddRef(LPENUMFORMATETC iface);
37 static ULONG WINAPI IEnumFORMATETC_fnRelease(LPENUMFORMATETC iface);
38 static HRESULT WINAPI IEnumFORMATETC_fnNext(LPENUMFORMATETC iface, ULONG celt, FORMATETC* rgelt, ULONG* pceltFethed);
39 static HRESULT WINAPI IEnumFORMATETC_fnSkip(LPENUMFORMATETC iface, ULONG celt);
40 static HRESULT WINAPI IEnumFORMATETC_fnReset(LPENUMFORMATETC iface);
41 static HRESULT WINAPI IEnumFORMATETC_fnClone(LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum);
43 static struct ICOM_VTABLE(IEnumFORMATETC) efvt =
45 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
46 IEnumFORMATETC_fnQueryInterface,
47 IEnumFORMATETC_fnAddRef,
48 IEnumFORMATETC_fnRelease,
49 IEnumFORMATETC_fnNext,
50 IEnumFORMATETC_fnSkip,
51 IEnumFORMATETC_fnReset,
52 IEnumFORMATETC_fnClone
55 LPENUMFORMATETC IEnumFORMATETC_Constructor(UINT cfmt, const FORMATETC afmt[])
57 IEnumFORMATETCImpl* ef;
58 DWORD size=cfmt * sizeof(FORMATETC);
60 ef=(IEnumFORMATETCImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IEnumFORMATETCImpl));
68 ef->pFmt = SHAlloc (size);
72 memcpy(ef->pFmt, afmt, size);
78 TRACE("(%p)->()\n",ef);
79 return (LPENUMFORMATETC)ef;
81 static HRESULT WINAPI IEnumFORMATETC_fnQueryInterface(LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj)
83 ICOM_THIS(IEnumFORMATETCImpl,iface);
84 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
88 if(IsEqualIID(riid, &IID_IUnknown))
91 else if(IsEqualIID(riid, &IID_IEnumFORMATETC))
92 { *ppvObj = (IDataObject*)This;
96 { IEnumFORMATETC_AddRef((IEnumFORMATETC*)*ppvObj);
97 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
100 TRACE("-- Interface: E_NOINTERFACE\n");
101 return E_NOINTERFACE;
104 static ULONG WINAPI IEnumFORMATETC_fnAddRef(LPENUMFORMATETC iface)
106 ICOM_THIS(IEnumFORMATETCImpl,iface);
107 TRACE("(%p)->(count=%lu)\n",This, This->ref);
109 return ++(This->ref);
111 static ULONG WINAPI IEnumFORMATETC_fnRelease(LPENUMFORMATETC iface)
113 ICOM_THIS(IEnumFORMATETCImpl,iface);
114 TRACE("(%p)->()\n",This);
119 { TRACE(" destroying IEnumFORMATETC(%p)\n",This);
121 { SHFree (This->pFmt);
123 HeapFree(GetProcessHeap(),0,This);
128 static HRESULT WINAPI IEnumFORMATETC_fnNext(LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
130 ICOM_THIS(IEnumFORMATETCImpl,iface);
132 HRESULT hres = S_FALSE;
134 TRACE("(%p)->()\n", This);
136 if (This->posFmt < This->countFmt)
138 cfetch = This->countFmt - This->posFmt;
144 memcpy(rgelt, &This->pFmt[This->posFmt], cfetch * sizeof(FORMATETC));
145 This->posFmt += cfetch;
154 *pceltFethed = cfetch;
159 static HRESULT WINAPI IEnumFORMATETC_fnSkip(LPENUMFORMATETC iface, ULONG celt)
161 ICOM_THIS(IEnumFORMATETCImpl,iface);
162 FIXME("(%p)->(num=%lu)\n", This, celt);
164 This->posFmt += celt;
165 if (This->posFmt > This->countFmt)
167 This->posFmt = This->countFmt;
172 static HRESULT WINAPI IEnumFORMATETC_fnReset(LPENUMFORMATETC iface)
174 ICOM_THIS(IEnumFORMATETCImpl,iface);
175 FIXME("(%p)->()\n", This);
180 static HRESULT WINAPI IEnumFORMATETC_fnClone(LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum)
182 ICOM_THIS(IEnumFORMATETCImpl,iface);
183 FIXME("(%p)->(ppenum=%p)\n", This, ppenum);
187 /**************************************************************************
188 * IDLList "Item ID List List"
191 * interal data holder for IDataObject
193 #define STDMETHOD(xfn) HRESULT (CALLBACK *fn##xfn)
194 #define STDMETHOD_(type,xfn) type (CALLBACK *fn##xfn)
197 typedef struct tagLPIDLLIST *LPIDLLIST, IDLList;
199 #define THIS LPIDLLIST me
206 typedef struct IDLList_VTable
207 { STDMETHOD_(UINT, GetState)(THIS);
208 STDMETHOD_(LPITEMIDLIST, GetElement)(THIS_ UINT nIndex);
209 STDMETHOD_(UINT, GetCount)(THIS);
210 STDMETHOD_(BOOL, StoreItem)(THIS_ LPITEMIDLIST pidl);
211 STDMETHOD_(BOOL, AddItems)(THIS_ LPITEMIDLIST *apidl, UINT cidl);
212 STDMETHOD_(BOOL, InitList)(THIS);
213 STDMETHOD_(void, CleanList)(THIS);
214 } IDLList_VTable,*LPIDLLIST_VTABLE;
217 { LPIDLLIST_VTABLE lpvtbl;
222 extern LPIDLLIST IDLList_Constructor (UINT uStep);
223 extern void IDLList_Destructor(LPIDLLIST me);
228 /**************************************************************************
229 * IDLList "Item ID List List"
232 static UINT WINAPI IDLList_GetState(LPIDLLIST this);
233 static LPITEMIDLIST WINAPI IDLList_GetElement(LPIDLLIST this, UINT nIndex);
234 static UINT WINAPI IDLList_GetCount(LPIDLLIST this);
235 static BOOL WINAPI IDLList_StoreItem(LPIDLLIST this, LPITEMIDLIST pidl);
236 static BOOL WINAPI IDLList_AddItems(LPIDLLIST this, LPITEMIDLIST *apidl, UINT cidl);
237 static BOOL WINAPI IDLList_InitList(LPIDLLIST this);
238 static void WINAPI IDLList_CleanList(LPIDLLIST this);
240 static IDLList_VTable idllvt =
250 LPIDLLIST IDLList_Constructor (UINT uStep)
253 lpidll = (LPIDLLIST)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDLList));
257 lpidll->lpvtbl=&idllvt;
261 TRACE("(%p)\n",lpidll);
264 void IDLList_Destructor(LPIDLLIST this)
265 { TRACE("(%p)\n",this);
266 IDLList_CleanList(this);
269 static UINT WINAPI IDLList_GetState(LPIDLLIST this)
270 { TRACE("(%p)->(uStep=%u dpa=%p)\n",this, this->uStep, this->dpa);
272 if (this->uStep == 0)
277 return(State_OutOfMem);
279 return(State_UnInit);
281 static LPITEMIDLIST WINAPI IDLList_GetElement(LPIDLLIST this, UINT nIndex)
282 { TRACE("(%p)->(index=%u)\n",this, nIndex);
283 return((LPITEMIDLIST)pDPA_GetPtr(this->dpa, nIndex));
285 static UINT WINAPI IDLList_GetCount(LPIDLLIST this)
286 { TRACE("(%p)\n",this);
287 return(IDLList_GetState(this)==State_Init ? DPA_GetPtrCount(this->dpa) : 0);
289 static BOOL WINAPI IDLList_StoreItem(LPIDLLIST this, LPITEMIDLIST pidl)
290 { TRACE("(%p)->(pidl=%p)\n",this, pidl);
292 { if (IDLList_InitList(this) && pDPA_InsertPtr(this->dpa, 0x7fff, (LPSTR)pidl)>=0)
296 IDLList_CleanList(this);
299 static BOOL WINAPI IDLList_AddItems(LPIDLLIST this, LPITEMIDLIST *apidl, UINT cidl)
301 TRACE("(%p)->(apidl=%p cidl=%u)\n",this, apidl, cidl);
303 for (i=0; i<cidl; ++i)
304 { if (!IDLList_StoreItem(this, ILClone((LPCITEMIDLIST)apidl[i])))
309 static BOOL WINAPI IDLList_InitList(LPIDLLIST this)
310 { TRACE("(%p)\n",this);
311 switch (IDLList_GetState(this))
320 this->dpa = pDPA_Create(this->uStep);
322 return(IDLList_InitList(this));
325 static void WINAPI IDLList_CleanList(LPIDLLIST this)
327 TRACE("(%p)\n",this);
329 if (this->uStep != 0)
339 for (i=DPA_GetPtrCount(this->dpa)-1; i>=0; --i)
340 { ILFree(IDLList_GetElement(this,i));
343 pDPA_Destroy(this->dpa);
348 /***********************************************************************
349 * IDataObject implementation
351 /* number of supported formats */
352 #define MAX_FORMATS 1
356 /* IUnknown fields */
357 ICOM_VFIELD(IDataObject);
360 /* IDataObject fields */
361 LPIDLLIST lpill; /* the data of the dataobject */
364 FORMATETC pFormatEtc[MAX_FORMATS];
366 UINT cfFileGroupDesc;
371 static struct ICOM_VTABLE(IDataObject) dtovt;
373 /**************************************************************************
374 * IDataObject_Constructor
376 LPDATAOBJECT IDataObject_Constructor(HWND hwndOwner, LPITEMIDLIST pMyPidl, LPITEMIDLIST * apidl, UINT cidl)
378 IDataObjectImpl* dto;
380 dto = (IDataObjectImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDataObjectImpl));
385 ICOM_VTBL(dto)=&dtovt;
386 dto->pidl=ILClone(pMyPidl);
388 /* fill the ItemID List List */
389 dto->lpill = IDLList_Constructor (8);
393 dto->lpill->lpvtbl->fnAddItems(dto->lpill, apidl, cidl);
396 dto->cfShellIDList = RegisterClipboardFormatA(CFSTR_SHELLIDLIST);
397 /* dto->cfFileGroupDesc = RegisterClipboardFormatA(CFSTR_FILEDESCRIPTORA);
398 dto->cfFileContents = RegisterClipboardFormatA(CFSTR_FILECONTENTS);
400 InitFormatEtc(dto->pFormatEtc[0], dto->cfShellIDList, TYMED_HGLOBAL);
405 TRACE("(%p)->(apidl=%p cidl=%u)\n",dto, apidl, cidl);
406 return (LPDATAOBJECT)dto;
408 /***************************************************************************
409 * IDataObject_QueryInterface
411 static HRESULT WINAPI IDataObject_fnQueryInterface(LPDATAOBJECT iface, REFIID riid, LPVOID * ppvObj)
413 ICOM_THIS(IDataObjectImpl,iface);
414 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
418 if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/
421 else if(IsEqualIID(riid, &IID_IDataObject)) /*IDataObject*/
422 { *ppvObj = (IDataObject*)This;
426 { IDataObject_AddRef((IDataObject*)*ppvObj);
427 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
430 TRACE("-- Interface: E_NOINTERFACE\n");
431 return E_NOINTERFACE;
433 /**************************************************************************
436 static ULONG WINAPI IDataObject_fnAddRef(LPDATAOBJECT iface)
438 ICOM_THIS(IDataObjectImpl,iface);
440 TRACE("(%p)->(count=%lu)\n",This, This->ref);
443 return ++(This->ref);
445 /**************************************************************************
446 * IDataObject_Release
448 static ULONG WINAPI IDataObject_fnRelease(LPDATAOBJECT iface)
450 ICOM_THIS(IDataObjectImpl,iface);
451 TRACE("(%p)->()\n",This);
456 { TRACE(" destroying IDataObject(%p)\n",This);
457 IDLList_Destructor(This->lpill);
458 HeapFree(GetProcessHeap(),0,This);
464 /**************************************************************************
465 * IDataObject_fnGetData
467 static HRESULT WINAPI IDataObject_fnGetData(LPDATAOBJECT iface, LPFORMATETC pformatetcIn, STGMEDIUM *pmedium)
469 ICOM_THIS(IDataObjectImpl,iface);
473 DWORD sizeCIDA, sizePidl, nOffset, nSize;
479 GetClipboardFormatNameA (pformatetcIn->cfFormat, szTemp, 256);
480 TRACE("(%p)->(%p %p format=%s)\n", This, pformatetcIn, pmedium, szTemp);
482 /* test expected format */
483 if (!(pformatetcIn->cfFormat == This->cfShellIDList))
485 FIXME("-- clipformat not implemented\n");
486 return (E_INVALIDARG);
489 if (pformatetcIn->ptd==NULL
490 && (pformatetcIn->dwAspect & DVASPECT_CONTENT)
491 && pformatetcIn->lindex==-1
492 && (pformatetcIn->tymed&TYMED_HGLOBAL))
494 cItems = This->lpill->lpvtbl->fnGetCount(This->lpill);
495 if (cItems < 1) return(E_UNEXPECTED);
497 sizeCIDA = sizeof(CIDA) + sizeof (UINT)*(cItems); /* without any pidl */
498 sizePidl = ILGetSize (This->pidl); /* add root pidl */
500 nSize = sizeCIDA + sizePidl;
501 hmem = GlobalAlloc(GHND|GMEM_SHARE, nSize);
502 if (!hmem) return(E_OUTOFMEMORY);
503 pcida = GlobalLock (hmem);
505 nOffset = sizeCIDA; /* start after the CIDA */
506 pcida->cidl = cItems;
508 pcida->aoffset[0] = nOffset; /* first element */
509 memcpy(((LPBYTE)pcida)+nOffset, This->pidl, sizePidl);
513 for (i=0; i< cItems; i++)
515 pidl = This->lpill->lpvtbl->fnGetElement(This->lpill, i);
516 sizePidl = ILGetSize (pidl);
517 nSize += sizePidl; /* size of the structure */
520 GlobalUnlock(hmem); /* grow memory */
521 hmem = GlobalReAlloc(hmem, nSize, GHND|GMEM_SHARE);
522 if (!hmem) return(E_OUTOFMEMORY);
523 pcida = GlobalLock (hmem);
525 pcida->aoffset[i+1] = nOffset; /* copy element */
526 memcpy(((LPBYTE)pcida)+nOffset, pidl, sizePidl);
532 pmedium->tymed = TYMED_HGLOBAL;
533 pmedium->u.hGlobal = hmem;
534 pmedium->pUnkForRelease = NULL;
536 TRACE("(%p)->(cida at %p)\n", This, pcida);
540 FIXME("-- can't serve format\n");
541 return (E_INVALIDARG);
543 static HRESULT WINAPI IDataObject_fnGetDataHere(LPDATAOBJECT iface, LPFORMATETC pformatetc, STGMEDIUM *pmedium)
545 ICOM_THIS(IDataObjectImpl,iface);
546 FIXME("(%p)->()\n", This);
549 static HRESULT WINAPI IDataObject_fnQueryGetData(LPDATAOBJECT iface, LPFORMATETC pformatetc)
551 ICOM_THIS(IDataObjectImpl,iface);
554 TRACE("(%p)->(fmt=0x%08x tym=0x%08lx)\n", This, pformatetc->cfFormat, pformatetc->tymed);
556 if(!(DVASPECT_CONTENT & pformatetc->dwAspect))
557 return DV_E_DVASPECT;
559 /* check our formats table what we have */
560 for (i=0; i<MAX_FORMATS; i++)
562 if ((This->pFormatEtc[i].cfFormat == pformatetc->cfFormat)
563 && (This->pFormatEtc[i].tymed == pformatetc->tymed))
571 static HRESULT WINAPI IDataObject_fnGetCanonicalFormatEtc(LPDATAOBJECT iface, LPFORMATETC pformatectIn, LPFORMATETC pformatetcOut)
573 ICOM_THIS(IDataObjectImpl,iface);
574 FIXME("(%p)->()\n", This);
577 static HRESULT WINAPI IDataObject_fnSetData(LPDATAOBJECT iface, LPFORMATETC pformatetc, STGMEDIUM *pmedium, BOOL fRelease)
579 ICOM_THIS(IDataObjectImpl,iface);
580 FIXME("(%p)->()\n", This);
583 static HRESULT WINAPI IDataObject_fnEnumFormatEtc(LPDATAOBJECT iface, DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc)
585 ICOM_THIS(IDataObjectImpl,iface);
587 TRACE("(%p)->()\n", This);
588 *ppenumFormatEtc=NULL;
591 if (DATADIR_GET == dwDirection)
593 *ppenumFormatEtc = IEnumFORMATETC_Constructor(MAX_FORMATS, This->pFormatEtc);
594 return (*ppenumFormatEtc) ? S_OK : E_FAIL;
599 static HRESULT WINAPI IDataObject_fnDAdvise(LPDATAOBJECT iface, FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection)
601 ICOM_THIS(IDataObjectImpl,iface);
602 FIXME("(%p)->()\n", This);
605 static HRESULT WINAPI IDataObject_fnDUnadvise(LPDATAOBJECT iface, DWORD dwConnection)
607 ICOM_THIS(IDataObjectImpl,iface);
608 FIXME("(%p)->()\n", This);
611 static HRESULT WINAPI IDataObject_fnEnumDAdvise(LPDATAOBJECT iface, IEnumSTATDATA **ppenumAdvise)
613 ICOM_THIS(IDataObjectImpl,iface);
614 FIXME("(%p)->()\n", This);
618 static struct ICOM_VTABLE(IDataObject) dtovt =
620 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
621 IDataObject_fnQueryInterface,
622 IDataObject_fnAddRef,
623 IDataObject_fnRelease,
624 IDataObject_fnGetData,
625 IDataObject_fnGetDataHere,
626 IDataObject_fnQueryGetData,
627 IDataObject_fnGetCanonicalFormatEtc,
628 IDataObject_fnSetData,
629 IDataObject_fnEnumFormatEtc,
630 IDataObject_fnDAdvise,
631 IDataObject_fnDUnadvise,
632 IDataObject_fnEnumDAdvise