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_VTABLE(IEnumFORMATETC)* lpvtbl;
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);
85 WINE_StringFromCLSID((LPCLSID)riid,xriid);
86 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,xriid,ppvObj);
90 if(IsEqualIID(riid, &IID_IUnknown))
93 else if(IsEqualIID(riid, &IID_IEnumFORMATETC))
94 { *ppvObj = (IDataObject*)This;
98 { IEnumFORMATETC_AddRef((IEnumFORMATETC*)*ppvObj);
99 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
102 TRACE("-- Interface: E_NOINTERFACE\n");
103 return E_NOINTERFACE;
106 static ULONG WINAPI IEnumFORMATETC_fnAddRef(LPENUMFORMATETC iface)
108 ICOM_THIS(IEnumFORMATETCImpl,iface);
109 TRACE("(%p)->(count=%lu)\n",This, This->ref);
111 return ++(This->ref);
113 static ULONG WINAPI IEnumFORMATETC_fnRelease(LPENUMFORMATETC iface)
115 ICOM_THIS(IEnumFORMATETCImpl,iface);
116 TRACE("(%p)->()\n",This);
121 { TRACE(" destroying IEnumFORMATETC(%p)\n",This);
123 { SHFree (This->pFmt);
125 HeapFree(GetProcessHeap(),0,This);
130 static HRESULT WINAPI IEnumFORMATETC_fnNext(LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
132 ICOM_THIS(IEnumFORMATETCImpl,iface);
134 HRESULT hres = S_FALSE;
136 TRACE("(%p)->()\n", This);
138 if (This->posFmt < This->countFmt)
140 cfetch = This->countFmt - This->posFmt;
146 memcpy(rgelt, &This->pFmt[This->posFmt], cfetch * sizeof(FORMATETC));
147 This->posFmt += cfetch;
156 *pceltFethed = cfetch;
161 static HRESULT WINAPI IEnumFORMATETC_fnSkip(LPENUMFORMATETC iface, ULONG celt)
163 ICOM_THIS(IEnumFORMATETCImpl,iface);
164 FIXME("(%p)->(num=%lu)\n", This, celt);
166 This->posFmt += celt;
167 if (This->posFmt > This->countFmt)
169 This->posFmt = This->countFmt;
174 static HRESULT WINAPI IEnumFORMATETC_fnReset(LPENUMFORMATETC iface)
176 ICOM_THIS(IEnumFORMATETCImpl,iface);
177 FIXME("(%p)->()\n", This);
182 static HRESULT WINAPI IEnumFORMATETC_fnClone(LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum)
184 ICOM_THIS(IEnumFORMATETCImpl,iface);
185 FIXME("(%p)->(ppenum=%p)\n", This, ppenum);
189 /**************************************************************************
190 * IDLList "Item ID List List"
193 * interal data holder for IDataObject
195 #define STDMETHOD(xfn) HRESULT (CALLBACK *fn##xfn)
196 #define STDMETHOD_(type,xfn) type (CALLBACK *fn##xfn)
199 typedef struct tagLPIDLLIST *LPIDLLIST, IDLList;
201 #define THIS LPIDLLIST me
208 typedef struct IDLList_VTable
209 { STDMETHOD_(UINT, GetState)(THIS);
210 STDMETHOD_(LPITEMIDLIST, GetElement)(THIS_ UINT nIndex);
211 STDMETHOD_(UINT, GetCount)(THIS);
212 STDMETHOD_(BOOL, StoreItem)(THIS_ LPITEMIDLIST pidl);
213 STDMETHOD_(BOOL, AddItems)(THIS_ LPITEMIDLIST *apidl, UINT cidl);
214 STDMETHOD_(BOOL, InitList)(THIS);
215 STDMETHOD_(void, CleanList)(THIS);
216 } IDLList_VTable,*LPIDLLIST_VTABLE;
219 { LPIDLLIST_VTABLE lpvtbl;
224 extern LPIDLLIST IDLList_Constructor (UINT uStep);
225 extern void IDLList_Destructor(LPIDLLIST me);
230 /**************************************************************************
231 * IDLList "Item ID List List"
234 static UINT WINAPI IDLList_GetState(LPIDLLIST this);
235 static LPITEMIDLIST WINAPI IDLList_GetElement(LPIDLLIST this, UINT nIndex);
236 static UINT WINAPI IDLList_GetCount(LPIDLLIST this);
237 static BOOL WINAPI IDLList_StoreItem(LPIDLLIST this, LPITEMIDLIST pidl);
238 static BOOL WINAPI IDLList_AddItems(LPIDLLIST this, LPITEMIDLIST *apidl, UINT cidl);
239 static BOOL WINAPI IDLList_InitList(LPIDLLIST this);
240 static void WINAPI IDLList_CleanList(LPIDLLIST this);
242 static IDLList_VTable idllvt =
252 LPIDLLIST IDLList_Constructor (UINT uStep)
255 lpidll = (LPIDLLIST)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDLList));
259 lpidll->lpvtbl=&idllvt;
263 TRACE("(%p)\n",lpidll);
266 void IDLList_Destructor(LPIDLLIST this)
267 { TRACE("(%p)\n",this);
268 IDLList_CleanList(this);
271 static UINT WINAPI IDLList_GetState(LPIDLLIST this)
272 { TRACE("(%p)->(uStep=%u dpa=%p)\n",this, this->uStep, this->dpa);
274 if (this->uStep == 0)
279 return(State_OutOfMem);
281 return(State_UnInit);
283 static LPITEMIDLIST WINAPI IDLList_GetElement(LPIDLLIST this, UINT nIndex)
284 { TRACE("(%p)->(index=%u)\n",this, nIndex);
285 return((LPITEMIDLIST)pDPA_GetPtr(this->dpa, nIndex));
287 static UINT WINAPI IDLList_GetCount(LPIDLLIST this)
288 { TRACE("(%p)\n",this);
289 return(IDLList_GetState(this)==State_Init ? DPA_GetPtrCount(this->dpa) : 0);
291 static BOOL WINAPI IDLList_StoreItem(LPIDLLIST this, LPITEMIDLIST pidl)
292 { TRACE("(%p)->(pidl=%p)\n",this, pidl);
294 { if (IDLList_InitList(this) && pDPA_InsertPtr(this->dpa, 0x7fff, (LPSTR)pidl)>=0)
298 IDLList_CleanList(this);
301 static BOOL WINAPI IDLList_AddItems(LPIDLLIST this, LPITEMIDLIST *apidl, UINT cidl)
303 TRACE("(%p)->(apidl=%p cidl=%u)\n",this, apidl, cidl);
305 for (i=0; i<cidl; ++i)
306 { if (!IDLList_StoreItem(this, ILClone((LPCITEMIDLIST)apidl[i])))
311 static BOOL WINAPI IDLList_InitList(LPIDLLIST this)
312 { TRACE("(%p)\n",this);
313 switch (IDLList_GetState(this))
322 this->dpa = pDPA_Create(this->uStep);
324 return(IDLList_InitList(this));
327 static void WINAPI IDLList_CleanList(LPIDLLIST this)
329 TRACE("(%p)\n",this);
331 if (this->uStep != 0)
341 for (i=DPA_GetPtrCount(this->dpa)-1; i>=0; --i)
342 { ILFree(IDLList_GetElement(this,i));
345 pDPA_Destroy(this->dpa);
350 /***********************************************************************
351 * IDataObject implementation
353 /* number of supported formats */
354 #define MAX_FORMATS 1
358 /* IUnknown fields */
359 ICOM_VTABLE(IDataObject)* lpvtbl;
362 /* IDataObject fields */
363 LPIDLLIST lpill; /* the data of the dataobject */
366 FORMATETC pFormatEtc[MAX_FORMATS];
368 UINT cfFileGroupDesc;
373 static struct ICOM_VTABLE(IDataObject) dtovt;
375 /**************************************************************************
376 * IDataObject_Constructor
378 LPDATAOBJECT IDataObject_Constructor(HWND hwndOwner, LPITEMIDLIST pMyPidl, LPITEMIDLIST * apidl, UINT cidl)
380 IDataObjectImpl* dto;
382 dto = (IDataObjectImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDataObjectImpl));
388 dto->pidl=ILClone(pMyPidl);
390 /* fill the ItemID List List */
391 dto->lpill = IDLList_Constructor (8);
395 dto->lpill->lpvtbl->fnAddItems(dto->lpill, apidl, cidl);
398 dto->cfShellIDList = RegisterClipboardFormatA(CFSTR_SHELLIDLIST);
399 /* dto->cfFileGroupDesc = RegisterClipboardFormatA(CFSTR_FILEDESCRIPTORA);
400 dto->cfFileContents = RegisterClipboardFormatA(CFSTR_FILECONTENTS);
402 InitFormatEtc(dto->pFormatEtc[0], dto->cfShellIDList, TYMED_HGLOBAL);
407 TRACE("(%p)->(apidl=%p cidl=%u)\n",dto, apidl, cidl);
408 return (LPDATAOBJECT)dto;
410 /***************************************************************************
411 * IDataObject_QueryInterface
413 static HRESULT WINAPI IDataObject_fnQueryInterface(LPDATAOBJECT iface, REFIID riid, LPVOID * ppvObj)
415 ICOM_THIS(IDataObjectImpl,iface);
417 WINE_StringFromCLSID((LPCLSID)riid,xriid);
418 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,xriid,ppvObj);
422 if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/
425 else if(IsEqualIID(riid, &IID_IDataObject)) /*IDataObject*/
426 { *ppvObj = (IDataObject*)This;
430 { IDataObject_AddRef((IDataObject*)*ppvObj);
431 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
434 TRACE("-- Interface: E_NOINTERFACE\n");
435 return E_NOINTERFACE;
437 /**************************************************************************
440 static ULONG WINAPI IDataObject_fnAddRef(LPDATAOBJECT iface)
442 ICOM_THIS(IDataObjectImpl,iface);
444 TRACE("(%p)->(count=%lu)\n",This, This->ref);
447 return ++(This->ref);
449 /**************************************************************************
450 * IDataObject_Release
452 static ULONG WINAPI IDataObject_fnRelease(LPDATAOBJECT iface)
454 ICOM_THIS(IDataObjectImpl,iface);
455 TRACE("(%p)->()\n",This);
460 { TRACE(" destroying IDataObject(%p)\n",This);
461 IDLList_Destructor(This->lpill);
462 HeapFree(GetProcessHeap(),0,This);
468 /**************************************************************************
469 * IDataObject_fnGetData
471 static HRESULT WINAPI IDataObject_fnGetData(LPDATAOBJECT iface, LPFORMATETC pformatetcIn, STGMEDIUM *pmedium)
473 ICOM_THIS(IDataObjectImpl,iface);
477 DWORD sizeCIDA, sizePidl, nOffset, nSize;
483 GetClipboardFormatNameA (pformatetcIn->cfFormat, szTemp, 256);
484 TRACE("(%p)->(%p %p format=%s)\n", This, pformatetcIn, pmedium, szTemp);
486 /* test expected format */
487 if (!(pformatetcIn->cfFormat == This->cfShellIDList))
489 FIXME("-- clipformat not implemented\n");
490 return (E_INVALIDARG);
493 if (pformatetcIn->ptd==NULL
494 && (pformatetcIn->dwAspect & DVASPECT_CONTENT)
495 && pformatetcIn->lindex==-1
496 && (pformatetcIn->tymed&TYMED_HGLOBAL))
498 cItems = This->lpill->lpvtbl->fnGetCount(This->lpill);
499 if (cItems < 1) return(E_UNEXPECTED);
501 sizeCIDA = sizeof(CIDA) + sizeof (UINT)*(cItems); /* without any pidl */
502 sizePidl = ILGetSize (This->pidl); /* add root pidl */
504 nSize = sizeCIDA + sizePidl;
505 hmem = GlobalAlloc(GHND|GMEM_SHARE, nSize);
506 if (!hmem) return(E_OUTOFMEMORY);
507 pcida = GlobalLock (hmem);
509 nOffset = sizeCIDA; /* start after the CIDA */
510 pcida->cidl = cItems;
512 pcida->aoffset[0] = nOffset; /* first element */
513 memcpy(((LPBYTE)pcida)+nOffset, This->pidl, sizePidl);
517 for (i=0; i< cItems; i++)
519 pidl = This->lpill->lpvtbl->fnGetElement(This->lpill, i);
520 sizePidl = ILGetSize (pidl);
521 nSize += sizePidl; /* size of the structure */
524 GlobalUnlock(hmem); /* grow memory */
525 hmem = GlobalReAlloc(hmem, nSize, GHND|GMEM_SHARE);
526 if (!hmem) return(E_OUTOFMEMORY);
527 pcida = GlobalLock (hmem);
529 pcida->aoffset[i+1] = nOffset; /* copy element */
530 memcpy(((LPBYTE)pcida)+nOffset, pidl, sizePidl);
536 pmedium->tymed = TYMED_HGLOBAL;
537 pmedium->u.hGlobal = hmem;
538 pmedium->pUnkForRelease = NULL;
540 TRACE("(%p)->(cida at %p)\n", This, pcida);
544 FIXME("-- can't serve format\n");
545 return (E_INVALIDARG);
547 static HRESULT WINAPI IDataObject_fnGetDataHere(LPDATAOBJECT iface, LPFORMATETC pformatetc, STGMEDIUM *pmedium)
549 ICOM_THIS(IDataObjectImpl,iface);
550 FIXME("(%p)->()\n", This);
553 static HRESULT WINAPI IDataObject_fnQueryGetData(LPDATAOBJECT iface, LPFORMATETC pformatetc)
555 ICOM_THIS(IDataObjectImpl,iface);
558 TRACE("(%p)->(fmt=0x%08x tym=0x%08lx)\n", This, pformatetc->cfFormat, pformatetc->tymed);
560 if(!(DVASPECT_CONTENT & pformatetc->dwAspect))
561 return DV_E_DVASPECT;
563 /* check our formats table what we have */
564 for (i=0; i<MAX_FORMATS; i++)
566 if ((This->pFormatEtc[i].cfFormat == pformatetc->cfFormat)
567 && (This->pFormatEtc[i].tymed == pformatetc->tymed))
575 static HRESULT WINAPI IDataObject_fnGetCanonicalFormatEtc(LPDATAOBJECT iface, LPFORMATETC pformatectIn, LPFORMATETC pformatetcOut)
577 ICOM_THIS(IDataObjectImpl,iface);
578 FIXME("(%p)->()\n", This);
581 static HRESULT WINAPI IDataObject_fnSetData(LPDATAOBJECT iface, LPFORMATETC pformatetc, STGMEDIUM *pmedium, BOOL fRelease)
583 ICOM_THIS(IDataObjectImpl,iface);
584 FIXME("(%p)->()\n", This);
587 static HRESULT WINAPI IDataObject_fnEnumFormatEtc(LPDATAOBJECT iface, DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc)
589 ICOM_THIS(IDataObjectImpl,iface);
591 TRACE("(%p)->()\n", This);
592 *ppenumFormatEtc=NULL;
595 if (DATADIR_GET == dwDirection)
597 *ppenumFormatEtc = IEnumFORMATETC_Constructor(MAX_FORMATS, This->pFormatEtc);
598 return (*ppenumFormatEtc) ? S_OK : E_FAIL;
603 static HRESULT WINAPI IDataObject_fnDAdvise(LPDATAOBJECT iface, FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection)
605 ICOM_THIS(IDataObjectImpl,iface);
606 FIXME("(%p)->()\n", This);
609 static HRESULT WINAPI IDataObject_fnDUnadvise(LPDATAOBJECT iface, DWORD dwConnection)
611 ICOM_THIS(IDataObjectImpl,iface);
612 FIXME("(%p)->()\n", This);
615 static HRESULT WINAPI IDataObject_fnEnumDAdvise(LPDATAOBJECT iface, IEnumSTATDATA **ppenumAdvise)
617 ICOM_THIS(IDataObjectImpl,iface);
618 FIXME("(%p)->()\n", This);
622 static struct ICOM_VTABLE(IDataObject) dtovt =
624 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
625 IDataObject_fnQueryInterface,
626 IDataObject_fnAddRef,
627 IDataObject_fnRelease,
628 IDataObject_fnGetData,
629 IDataObject_fnGetDataHere,
630 IDataObject_fnQueryGetData,
631 IDataObject_fnGetCanonicalFormatEtc,
632 IDataObject_fnSetData,
633 IDataObject_fnEnumFormatEtc,
634 IDataObject_fnDAdvise,
635 IDataObject_fnDUnadvise,
636 IDataObject_fnEnumDAdvise