2 * IEnumFORMATETC, IDataObject
4 * selecting and droping objects within the shell and/or common dialogs
6 * Copyright 1998 <juergen.schmied@metronet.de>
13 #include "shell32_main.h"
16 DEFAULT_DEBUG_CHANNEL(shell)
19 UINT cfFileGroupDesc=0;
20 UINT cfFileContents=0;
22 /***********************************************************************
23 * IEnumFORMATETC implementation
28 ICOM_VTABLE(IEnumFORMATETC)* lpvtbl;
30 /* IEnumFORMATETC fields */
36 static HRESULT WINAPI IEnumFORMATETC_fnQueryInterface(LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj);
37 static ULONG WINAPI IEnumFORMATETC_fnAddRef(LPENUMFORMATETC iface);
38 static ULONG WINAPI IEnumFORMATETC_fnRelease(LPENUMFORMATETC iface);
39 static HRESULT WINAPI IEnumFORMATETC_fnNext(LPENUMFORMATETC iface, ULONG celt, FORMATETC* rgelt, ULONG* pceltFethed);
40 static HRESULT WINAPI IEnumFORMATETC_fnSkip(LPENUMFORMATETC iface, ULONG celt);
41 static HRESULT WINAPI IEnumFORMATETC_fnReset(LPENUMFORMATETC iface);
42 static HRESULT WINAPI IEnumFORMATETC_fnClone(LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum);
44 static struct ICOM_VTABLE(IEnumFORMATETC) efvt =
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(),0,sizeof(IEnumFORMATETCImpl));
66 ef->pFmt = SHAlloc (size);
69 { memcpy(ef->pFmt, afmt, size);
72 TRACE(shell,"(%p)->()\n",ef);
74 return (LPENUMFORMATETC)ef;
76 static HRESULT WINAPI IEnumFORMATETC_fnQueryInterface(LPENUMFORMATETC iface, REFIID riid, LPVOID* ppvObj)
78 ICOM_THIS(IEnumFORMATETCImpl,iface);
80 WINE_StringFromCLSID((LPCLSID)riid,xriid);
81 TRACE(shell,"(%p)->(\n\tIID:\t%s,%p)\n",This,xriid,ppvObj);
85 if(IsEqualIID(riid, &IID_IUnknown))
88 else if(IsEqualIID(riid, &IID_IEnumFORMATETC))
89 { *ppvObj = (IDataObject*)This;
93 { IEnumFORMATETC_AddRef((IEnumFORMATETC*)*ppvObj);
94 TRACE(shell,"-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
97 TRACE(shell,"-- Interface: E_NOINTERFACE\n");
101 static ULONG WINAPI IEnumFORMATETC_fnAddRef(LPENUMFORMATETC iface)
103 ICOM_THIS(IEnumFORMATETCImpl,iface);
104 TRACE(shell,"(%p)->(count=%lu)\n",This, This->ref);
106 return ++(This->ref);
108 static ULONG WINAPI IEnumFORMATETC_fnRelease(LPENUMFORMATETC iface)
110 ICOM_THIS(IEnumFORMATETCImpl,iface);
111 TRACE(shell,"(%p)->()\n",This);
116 { TRACE(shell," destroying IEnumFORMATETC(%p)\n",This);
118 { SHFree (This->pFmt);
120 HeapFree(GetProcessHeap(),0,This);
125 static HRESULT WINAPI IEnumFORMATETC_fnNext(LPENUMFORMATETC iface, ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
127 ICOM_THIS(IEnumFORMATETCImpl,iface);
129 HRESULT hres = S_FALSE;
131 TRACE (shell, "(%p)->()\n", This);
133 if (This->posFmt < This->countFmt)
134 { cfetch = This->countFmt - This->posFmt;
139 memcpy(rgelt, &This->pFmt[This->posFmt], cfetch * sizeof(FORMATETC));
140 This->posFmt += cfetch;
147 { *pceltFethed = cfetch;
152 static HRESULT WINAPI IEnumFORMATETC_fnSkip(LPENUMFORMATETC iface, ULONG celt)
154 ICOM_THIS(IEnumFORMATETCImpl,iface);
155 FIXME (shell, "(%p)->(num=%lu)\n", This, celt);
157 This->posFmt += celt;
158 if (This->posFmt > This->countFmt)
159 { This->posFmt = This->countFmt;
164 static HRESULT WINAPI IEnumFORMATETC_fnReset(LPENUMFORMATETC iface)
166 ICOM_THIS(IEnumFORMATETCImpl,iface);
167 FIXME (shell, "(%p)->()\n", This);
172 static HRESULT WINAPI IEnumFORMATETC_fnClone(LPENUMFORMATETC iface, LPENUMFORMATETC* ppenum)
174 ICOM_THIS(IEnumFORMATETCImpl,iface);
175 FIXME (shell, "(%p)->(ppenum=%p)\n", This, ppenum);
179 /**************************************************************************
180 * IDLList "Item ID List List"
183 * interal data holder for IDataObject
185 #define STDMETHOD(xfn) HRESULT (CALLBACK *fn##xfn)
186 #define STDMETHOD_(type,xfn) type (CALLBACK *fn##xfn)
189 typedef struct tagLPIDLLIST *LPIDLLIST, IDLList;
191 #define THIS LPIDLLIST me
198 typedef struct IDLList_VTable
199 { STDMETHOD_(UINT, GetState)(THIS);
200 STDMETHOD_(LPITEMIDLIST, GetElement)(THIS_ UINT nIndex);
201 STDMETHOD_(UINT, GetCount)(THIS);
202 STDMETHOD_(BOOL, StoreItem)(THIS_ LPITEMIDLIST pidl);
203 STDMETHOD_(BOOL, AddItems)(THIS_ LPITEMIDLIST *apidl, UINT cidl);
204 STDMETHOD_(BOOL, InitList)(THIS);
205 STDMETHOD_(void, CleanList)(THIS);
206 } IDLList_VTable,*LPIDLLIST_VTABLE;
209 { LPIDLLIST_VTABLE lpvtbl;
214 extern LPIDLLIST IDLList_Constructor (UINT uStep);
215 extern void IDLList_Destructor(LPIDLLIST me);
220 /**************************************************************************
221 * IDLList "Item ID List List"
224 static UINT WINAPI IDLList_GetState(LPIDLLIST this);
225 static LPITEMIDLIST WINAPI IDLList_GetElement(LPIDLLIST this, UINT nIndex);
226 static UINT WINAPI IDLList_GetCount(LPIDLLIST this);
227 static BOOL WINAPI IDLList_StoreItem(LPIDLLIST this, LPITEMIDLIST pidl);
228 static BOOL WINAPI IDLList_AddItems(LPIDLLIST this, LPITEMIDLIST *apidl, UINT cidl);
229 static BOOL WINAPI IDLList_InitList(LPIDLLIST this);
230 static void WINAPI IDLList_CleanList(LPIDLLIST this);
232 static IDLList_VTable idllvt =
242 LPIDLLIST IDLList_Constructor (UINT uStep)
244 if (!(lpidll = (LPIDLLIST)HeapAlloc(GetProcessHeap(),0,sizeof(IDLList))))
247 lpidll->lpvtbl=&idllvt;
251 TRACE (shell,"(%p)\n",lpidll);
254 void IDLList_Destructor(LPIDLLIST this)
255 { TRACE (shell,"(%p)\n",this);
256 IDLList_CleanList(this);
259 static UINT WINAPI IDLList_GetState(LPIDLLIST this)
260 { TRACE (shell,"(%p)->(uStep=%u dpa=%p)\n",this, this->uStep, this->dpa);
262 if (this->uStep == 0)
265 return(State_OutOfMem);
267 return(State_UnInit);
269 static LPITEMIDLIST WINAPI IDLList_GetElement(LPIDLLIST this, UINT nIndex)
270 { TRACE (shell,"(%p)->(index=%u)\n",this, nIndex);
271 return((LPITEMIDLIST)pDPA_GetPtr(this->dpa, nIndex));
273 static UINT WINAPI IDLList_GetCount(LPIDLLIST this)
274 { TRACE (shell,"(%p)\n",this);
275 return(IDLList_GetState(this)==State_Init ? DPA_GetPtrCount(this->dpa) : 0);
277 static BOOL WINAPI IDLList_StoreItem(LPIDLLIST this, LPITEMIDLIST pidl)
278 { TRACE (shell,"(%p)->(pidl=%p)\n",this, pidl);
280 { if (IDLList_InitList(this) && pDPA_InsertPtr(this->dpa, 0x7fff, (LPSTR)pidl)>=0)
284 IDLList_CleanList(this);
287 static BOOL WINAPI IDLList_AddItems(LPIDLLIST this, LPITEMIDLIST *apidl, UINT cidl)
289 TRACE (shell,"(%p)->(apidl=%p cidl=%u)\n",this, apidl, cidl);
291 for (i=0; i<cidl; ++i)
292 { if (!IDLList_StoreItem(this, ILClone((LPCITEMIDLIST)apidl[i])))
297 static BOOL WINAPI IDLList_InitList(LPIDLLIST this)
298 { TRACE (shell,"(%p)\n",this);
299 switch (IDLList_GetState(this))
308 this->dpa = pDPA_Create(this->uStep);
310 return(IDLList_InitList(this));
313 static void WINAPI IDLList_CleanList(LPIDLLIST this)
315 TRACE (shell,"(%p)\n",this);
317 if (this->uStep != 0)
327 for (i=DPA_GetPtrCount(this->dpa)-1; i>=0; --i)
328 { ILFree(IDLList_GetElement(this,i));
331 pDPA_Destroy(this->dpa);
336 /***********************************************************************
337 * IDataObject implementation
342 /* IUnknown fields */
343 ICOM_VTABLE(IDataObject)* lpvtbl;
345 /* IDataObject fields */
347 LPIDLLIST lpill; /* the data of the dataobject */
351 static HRESULT WINAPI IDataObject_fnQueryInterface(LPDATAOBJECT iface, REFIID riid, LPVOID* ppvObj);
352 static ULONG WINAPI IDataObject_fnAddRef(LPDATAOBJECT iface);
353 static ULONG WINAPI IDataObject_fnRelease(LPDATAOBJECT iface);
354 static HRESULT WINAPI IDataObject_fnGetData(LPDATAOBJECT iface, LPFORMATETC pformatetcIn, STGMEDIUM* pmedium);
355 static HRESULT WINAPI IDataObject_fnGetDataHere(LPDATAOBJECT iface, LPFORMATETC pformatetc, STGMEDIUM* pmedium);
356 static HRESULT WINAPI IDataObject_fnQueryGetData(LPDATAOBJECT iface, LPFORMATETC pformatetc);
357 static HRESULT WINAPI IDataObject_fnGetCanonicalFormatEtc(LPDATAOBJECT iface, LPFORMATETC pformatectIn, LPFORMATETC pformatetcOut);
358 static HRESULT WINAPI IDataObject_fnSetData(LPDATAOBJECT iface, LPFORMATETC pformatetc, STGMEDIUM* pmedium, BOOL fRelease);
359 static HRESULT WINAPI IDataObject_fnEnumFormatEtc(LPDATAOBJECT iface, DWORD dwDirection, IEnumFORMATETC** ppenumFormatEtc);
360 static HRESULT WINAPI IDataObject_fnDAdvise(LPDATAOBJECT iface, FORMATETC* pformatetc, DWORD advf, IAdviseSink* pAdvSink, DWORD* pdwConnection);
361 static HRESULT WINAPI IDataObject_fnDUnadvise(LPDATAOBJECT iface, DWORD dwConnection);
362 static HRESULT WINAPI IDataObject_fnEnumDAdvise(LPDATAOBJECT iface, IEnumSTATDATA **ppenumAdvise);
364 static struct ICOM_VTABLE(IDataObject) dtovt =
366 IDataObject_fnQueryInterface,
367 IDataObject_fnAddRef,
368 IDataObject_fnRelease,
369 IDataObject_fnGetData,
370 IDataObject_fnGetDataHere,
371 IDataObject_fnQueryGetData,
372 IDataObject_fnGetCanonicalFormatEtc,
373 IDataObject_fnSetData,
374 IDataObject_fnEnumFormatEtc,
375 IDataObject_fnDAdvise,
376 IDataObject_fnDUnadvise,
377 IDataObject_fnEnumDAdvise
380 /**************************************************************************
381 * IDataObject_Constructor
383 LPDATAOBJECT IDataObject_Constructor(HWND hwndOwner, LPSHELLFOLDER psf, LPITEMIDLIST * apidl, UINT cidl)
385 IDataObjectImpl* dto;
386 if (!(dto = (IDataObjectImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IDataObjectImpl))))
392 dto->pidl=ILClone(((IGenericSFImpl*)psf)->pMyPidl); /* FIXME:add a reference and don't copy*/
394 /* fill the ItemID List List */
395 dto->lpill = IDLList_Constructor (8);
399 dto->lpill->lpvtbl->fnAddItems(dto->lpill, apidl, cidl);
401 TRACE(shell,"(%p)->(sf=%p apidl=%p cidl=%u)\n",dto, psf, apidl, cidl);
403 return (LPDATAOBJECT)dto;
405 /***************************************************************************
406 * IDataObject_QueryInterface
408 static HRESULT WINAPI IDataObject_fnQueryInterface(LPDATAOBJECT iface, REFIID riid, LPVOID * ppvObj)
410 ICOM_THIS(IDataObjectImpl,iface);
412 WINE_StringFromCLSID((LPCLSID)riid,xriid);
413 TRACE(shell,"(%p)->(\n\tIID:\t%s,%p)\n",This,xriid,ppvObj);
417 if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/
420 else if(IsEqualIID(riid, &IID_IDataObject)) /*IDataObject*/
421 { *ppvObj = (IDataObject*)This;
425 { IDataObject_AddRef((IDataObject*)*ppvObj);
426 TRACE(shell,"-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
429 TRACE(shell,"-- Interface: E_NOINTERFACE\n");
430 return E_NOINTERFACE;
432 /**************************************************************************
435 static ULONG WINAPI IDataObject_fnAddRef(LPDATAOBJECT iface)
437 ICOM_THIS(IDataObjectImpl,iface);
439 TRACE(shell,"(%p)->(count=%lu)\n",This, This->ref);
442 return ++(This->ref);
444 /**************************************************************************
445 * IDataObject_Release
447 static ULONG WINAPI IDataObject_fnRelease(LPDATAOBJECT iface)
449 ICOM_THIS(IDataObjectImpl,iface);
450 TRACE(shell,"(%p)->()\n",This);
455 { TRACE(shell," destroying IDataObject(%p)\n",This);
456 IDLList_Destructor(This->lpill);
457 HeapFree(GetProcessHeap(),0,This);
462 /**************************************************************************
463 * DATAOBJECT_InitShellIDList (internal)
466 * get or register the "Shell IDList Array" clipformat
468 static BOOL DATAOBJECT_InitShellIDList(void)
473 cfShellIDList = RegisterClipboardFormatA(CFSTR_SHELLIDLIST);
474 return(cfShellIDList != 0);
477 /**************************************************************************
478 * DATAOBJECT_InitFileGroupDesc (internal)
481 * get or register the "FileGroupDescriptor" clipformat
483 /* FIXME: DATAOBJECT_InitFileGroupDesc is not used (19981226)
484 static BOOL32 DATAOBJECT_InitFileGroupDesc(void)
485 { if (cfFileGroupDesc)
489 cfFileGroupDesc = RegisterClipboardFormatA(CFSTR_FILEDESCRIPTORA);
490 return(cfFileGroupDesc != 0);
493 /**************************************************************************
494 * DATAOBJECT_InitFileContents (internal)
497 * get or register the "FileContents" clipformat
499 /* FIXME: DATAOBJECT_InitFileContents is not used (19981226)
500 static BOOL32 DATAOBJECT_InitFileContents(void)
501 { if (cfFileContents)
505 cfFileContents = RegisterClipboardFormatA(CFSTR_FILECONTENTS);
506 return(cfFileContents != 0);
510 /**************************************************************************
511 * interface implementation
513 static HRESULT WINAPI IDataObject_fnGetData(LPDATAOBJECT iface, LPFORMATETC pformatetcIn, STGMEDIUM *pmedium)
515 ICOM_THIS(IDataObjectImpl,iface);
518 DWORD size, size1, size2;
523 GetClipboardFormatNameA (pformatetcIn->cfFormat, temp, 256);
524 WARN (shell, "(%p)->(%p %p format=%s)semi-stub\n", This, pformatetcIn, pmedium, temp);
526 if (!DATAOBJECT_InitShellIDList()) /* is the clipformat registred? */
527 { return(E_UNEXPECTED);
530 if (pformatetcIn->cfFormat == cfShellIDList)
531 { if (pformatetcIn->ptd==NULL
532 && (pformatetcIn->dwAspect & DVASPECT_CONTENT)
533 && pformatetcIn->lindex==-1
534 && (pformatetcIn->tymed&TYMED_HGLOBAL))
535 { cItems = This->lpill->lpvtbl->fnGetCount(This->lpill);
537 { return(E_UNEXPECTED);
539 pidl = This->lpill->lpvtbl->fnGetElement(This->lpill, 0);
544 /*hack consider only the first item*/
546 size = sizeof(CIDA) + sizeof (UINT)*(cItems-1);
547 size1 = ILGetSize (This->pidl);
548 size2 = ILGetSize (pidl);
549 hmem = GlobalAlloc(GMEM_FIXED, size+size1+size2);
550 pcida = GlobalLock (hmem);
552 { return(E_OUTOFMEMORY);
556 pcida->aoffset[0] = size;
557 pcida->aoffset[1] = size+size1;
559 TRACE(shell,"-- %lu %lu %lu\n",size, size1, size2 );
560 TRACE(shell,"-- %p %p\n",This->pidl, pidl);
561 TRACE(shell,"-- %p %p %p\n",pcida, (LPBYTE)pcida+size,(LPBYTE)pcida+size+size1);
563 memcpy ((LPBYTE)pcida+size, This->pidl, size1);
564 memcpy ((LPBYTE)pcida+size+size1, pidl, size2);
565 TRACE(shell,"-- after copy\n");
569 pmedium->tymed = TYMED_HGLOBAL;
570 pmedium->u.hGlobal = (HGLOBAL)pcida;
571 pmedium->pUnkForRelease = NULL;
572 TRACE(shell,"-- ready\n");
576 FIXME (shell, "-- clipformat not implemented\n");
577 return (E_INVALIDARG);
579 static HRESULT WINAPI IDataObject_fnGetDataHere(LPDATAOBJECT iface, LPFORMATETC pformatetc, STGMEDIUM *pmedium)
581 ICOM_THIS(IDataObjectImpl,iface);
582 FIXME (shell, "(%p)->()\n", This);
585 static HRESULT WINAPI IDataObject_fnQueryGetData(LPDATAOBJECT iface, LPFORMATETC pformatetc)
587 ICOM_THIS(IDataObjectImpl,iface);
588 FIXME (shell, "(%p)->()\n", This);
591 static HRESULT WINAPI IDataObject_fnGetCanonicalFormatEtc(LPDATAOBJECT iface, LPFORMATETC pformatectIn, LPFORMATETC pformatetcOut)
593 ICOM_THIS(IDataObjectImpl,iface);
594 FIXME (shell, "(%p)->()\n", This);
597 static HRESULT WINAPI IDataObject_fnSetData(LPDATAOBJECT iface, LPFORMATETC pformatetc, STGMEDIUM *pmedium, BOOL fRelease)
599 ICOM_THIS(IDataObjectImpl,iface);
600 FIXME (shell, "(%p)->()\n", This);
603 static HRESULT WINAPI IDataObject_fnEnumFormatEtc(LPDATAOBJECT iface, DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc)
605 ICOM_THIS(IDataObjectImpl,iface);
606 FIXME (shell, "(%p)->()\n", This);
609 static HRESULT WINAPI IDataObject_fnDAdvise(LPDATAOBJECT iface, FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection)
611 ICOM_THIS(IDataObjectImpl,iface);
612 FIXME (shell, "(%p)->()\n", This);
615 static HRESULT WINAPI IDataObject_fnDUnadvise(LPDATAOBJECT iface, DWORD dwConnection)
617 ICOM_THIS(IDataObjectImpl,iface);
618 FIXME (shell, "(%p)->()\n", This);
621 static HRESULT WINAPI IDataObject_fnEnumDAdvise(LPDATAOBJECT iface, IEnumSTATDATA **ppenumAdvise)
623 ICOM_THIS(IDataObjectImpl,iface);
624 FIXME (shell, "(%p)->()\n", This);