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"
14 #include "debugtools.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 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
47 IEnumFORMATETC_fnQueryInterface
,
48 IEnumFORMATETC_fnAddRef
,
49 IEnumFORMATETC_fnRelease
,
50 IEnumFORMATETC_fnNext
,
51 IEnumFORMATETC_fnSkip
,
52 IEnumFORMATETC_fnReset
,
53 IEnumFORMATETC_fnClone
56 LPENUMFORMATETC
IEnumFORMATETC_Constructor(UINT cfmt
, const FORMATETC afmt
[])
58 IEnumFORMATETCImpl
* ef
;
59 DWORD size
=cfmt
* sizeof(FORMATETC
);
61 ef
=(IEnumFORMATETCImpl
*)HeapAlloc(GetProcessHeap(),0,sizeof(IEnumFORMATETCImpl
));
67 ef
->pFmt
= SHAlloc (size
);
70 { memcpy(ef
->pFmt
, afmt
, size
);
73 TRACE("(%p)->()\n",ef
);
75 return (LPENUMFORMATETC
)ef
;
77 static HRESULT WINAPI
IEnumFORMATETC_fnQueryInterface(LPENUMFORMATETC iface
, REFIID riid
, LPVOID
* ppvObj
)
79 ICOM_THIS(IEnumFORMATETCImpl
,iface
);
81 WINE_StringFromCLSID((LPCLSID
)riid
,xriid
);
82 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This
,xriid
,ppvObj
);
86 if(IsEqualIID(riid
, &IID_IUnknown
))
89 else if(IsEqualIID(riid
, &IID_IEnumFORMATETC
))
90 { *ppvObj
= (IDataObject
*)This
;
94 { IEnumFORMATETC_AddRef((IEnumFORMATETC
*)*ppvObj
);
95 TRACE("-- Interface: (%p)->(%p)\n",ppvObj
,*ppvObj
);
98 TRACE("-- Interface: E_NOINTERFACE\n");
102 static ULONG WINAPI
IEnumFORMATETC_fnAddRef(LPENUMFORMATETC iface
)
104 ICOM_THIS(IEnumFORMATETCImpl
,iface
);
105 TRACE("(%p)->(count=%lu)\n",This
, This
->ref
);
107 return ++(This
->ref
);
109 static ULONG WINAPI
IEnumFORMATETC_fnRelease(LPENUMFORMATETC iface
)
111 ICOM_THIS(IEnumFORMATETCImpl
,iface
);
112 TRACE("(%p)->()\n",This
);
117 { TRACE(" destroying IEnumFORMATETC(%p)\n",This
);
119 { SHFree (This
->pFmt
);
121 HeapFree(GetProcessHeap(),0,This
);
126 static HRESULT WINAPI
IEnumFORMATETC_fnNext(LPENUMFORMATETC iface
, ULONG celt
, FORMATETC
*rgelt
, ULONG
*pceltFethed
)
128 ICOM_THIS(IEnumFORMATETCImpl
,iface
);
130 HRESULT hres
= S_FALSE
;
132 TRACE("(%p)->()\n", This
);
134 if (This
->posFmt
< This
->countFmt
)
135 { cfetch
= This
->countFmt
- This
->posFmt
;
140 memcpy(rgelt
, &This
->pFmt
[This
->posFmt
], cfetch
* sizeof(FORMATETC
));
141 This
->posFmt
+= cfetch
;
148 { *pceltFethed
= cfetch
;
153 static HRESULT WINAPI
IEnumFORMATETC_fnSkip(LPENUMFORMATETC iface
, ULONG celt
)
155 ICOM_THIS(IEnumFORMATETCImpl
,iface
);
156 FIXME("(%p)->(num=%lu)\n", This
, celt
);
158 This
->posFmt
+= celt
;
159 if (This
->posFmt
> This
->countFmt
)
160 { This
->posFmt
= This
->countFmt
;
165 static HRESULT WINAPI
IEnumFORMATETC_fnReset(LPENUMFORMATETC iface
)
167 ICOM_THIS(IEnumFORMATETCImpl
,iface
);
168 FIXME("(%p)->()\n", This
);
173 static HRESULT WINAPI
IEnumFORMATETC_fnClone(LPENUMFORMATETC iface
, LPENUMFORMATETC
* ppenum
)
175 ICOM_THIS(IEnumFORMATETCImpl
,iface
);
176 FIXME("(%p)->(ppenum=%p)\n", This
, ppenum
);
180 /**************************************************************************
181 * IDLList "Item ID List List"
184 * interal data holder for IDataObject
186 #define STDMETHOD(xfn) HRESULT (CALLBACK *fn##xfn)
187 #define STDMETHOD_(type,xfn) type (CALLBACK *fn##xfn)
190 typedef struct tagLPIDLLIST
*LPIDLLIST
, IDLList
;
192 #define THIS LPIDLLIST me
199 typedef struct IDLList_VTable
200 { STDMETHOD_(UINT
, GetState
)(THIS
);
201 STDMETHOD_(LPITEMIDLIST
, GetElement
)(THIS_ UINT nIndex
);
202 STDMETHOD_(UINT
, GetCount
)(THIS
);
203 STDMETHOD_(BOOL
, StoreItem
)(THIS_ LPITEMIDLIST pidl
);
204 STDMETHOD_(BOOL
, AddItems
)(THIS_ LPITEMIDLIST
*apidl
, UINT cidl
);
205 STDMETHOD_(BOOL
, InitList
)(THIS
);
206 STDMETHOD_(void, CleanList
)(THIS
);
207 } IDLList_VTable
,*LPIDLLIST_VTABLE
;
210 { LPIDLLIST_VTABLE lpvtbl
;
215 extern LPIDLLIST
IDLList_Constructor (UINT uStep
);
216 extern void IDLList_Destructor(LPIDLLIST me
);
221 /**************************************************************************
222 * IDLList "Item ID List List"
225 static UINT WINAPI
IDLList_GetState(LPIDLLIST
this);
226 static LPITEMIDLIST WINAPI
IDLList_GetElement(LPIDLLIST
this, UINT nIndex
);
227 static UINT WINAPI
IDLList_GetCount(LPIDLLIST
this);
228 static BOOL WINAPI
IDLList_StoreItem(LPIDLLIST
this, LPITEMIDLIST pidl
);
229 static BOOL WINAPI
IDLList_AddItems(LPIDLLIST
this, LPITEMIDLIST
*apidl
, UINT cidl
);
230 static BOOL WINAPI
IDLList_InitList(LPIDLLIST
this);
231 static void WINAPI
IDLList_CleanList(LPIDLLIST
this);
233 static IDLList_VTable idllvt
=
243 LPIDLLIST
IDLList_Constructor (UINT uStep
)
245 if (!(lpidll
= (LPIDLLIST
)HeapAlloc(GetProcessHeap(),0,sizeof(IDLList
))))
248 lpidll
->lpvtbl
=&idllvt
;
252 TRACE("(%p)\n",lpidll
);
255 void IDLList_Destructor(LPIDLLIST
this)
256 { TRACE("(%p)\n",this);
257 IDLList_CleanList(this);
260 static UINT WINAPI
IDLList_GetState(LPIDLLIST
this)
261 { TRACE("(%p)->(uStep=%u dpa=%p)\n",this, this->uStep
, this->dpa
);
263 if (this->uStep
== 0)
266 return(State_OutOfMem
);
268 return(State_UnInit
);
270 static LPITEMIDLIST WINAPI
IDLList_GetElement(LPIDLLIST
this, UINT nIndex
)
271 { TRACE("(%p)->(index=%u)\n",this, nIndex
);
272 return((LPITEMIDLIST
)pDPA_GetPtr(this->dpa
, nIndex
));
274 static UINT WINAPI
IDLList_GetCount(LPIDLLIST
this)
275 { TRACE("(%p)\n",this);
276 return(IDLList_GetState(this)==State_Init
? DPA_GetPtrCount(this->dpa
) : 0);
278 static BOOL WINAPI
IDLList_StoreItem(LPIDLLIST
this, LPITEMIDLIST pidl
)
279 { TRACE("(%p)->(pidl=%p)\n",this, pidl
);
281 { if (IDLList_InitList(this) && pDPA_InsertPtr(this->dpa
, 0x7fff, (LPSTR
)pidl
)>=0)
285 IDLList_CleanList(this);
288 static BOOL WINAPI
IDLList_AddItems(LPIDLLIST
this, LPITEMIDLIST
*apidl
, UINT cidl
)
290 TRACE("(%p)->(apidl=%p cidl=%u)\n",this, apidl
, cidl
);
292 for (i
=0; i
<cidl
; ++i
)
293 { if (!IDLList_StoreItem(this, ILClone((LPCITEMIDLIST
)apidl
[i
])))
298 static BOOL WINAPI
IDLList_InitList(LPIDLLIST
this)
299 { TRACE("(%p)\n",this);
300 switch (IDLList_GetState(this))
309 this->dpa
= pDPA_Create(this->uStep
);
311 return(IDLList_InitList(this));
314 static void WINAPI
IDLList_CleanList(LPIDLLIST
this)
316 TRACE("(%p)\n",this);
318 if (this->uStep
!= 0)
328 for (i
=DPA_GetPtrCount(this->dpa
)-1; i
>=0; --i
)
329 { ILFree(IDLList_GetElement(this,i
));
332 pDPA_Destroy(this->dpa
);
337 /***********************************************************************
338 * IDataObject implementation
343 /* IUnknown fields */
344 ICOM_VTABLE(IDataObject
)* lpvtbl
;
346 /* IDataObject fields */
348 LPIDLLIST lpill
; /* the data of the dataobject */
352 static HRESULT WINAPI
IDataObject_fnQueryInterface(LPDATAOBJECT iface
, REFIID riid
, LPVOID
* ppvObj
);
353 static ULONG WINAPI
IDataObject_fnAddRef(LPDATAOBJECT iface
);
354 static ULONG WINAPI
IDataObject_fnRelease(LPDATAOBJECT iface
);
355 static HRESULT WINAPI
IDataObject_fnGetData(LPDATAOBJECT iface
, LPFORMATETC pformatetcIn
, STGMEDIUM
* pmedium
);
356 static HRESULT WINAPI
IDataObject_fnGetDataHere(LPDATAOBJECT iface
, LPFORMATETC pformatetc
, STGMEDIUM
* pmedium
);
357 static HRESULT WINAPI
IDataObject_fnQueryGetData(LPDATAOBJECT iface
, LPFORMATETC pformatetc
);
358 static HRESULT WINAPI
IDataObject_fnGetCanonicalFormatEtc(LPDATAOBJECT iface
, LPFORMATETC pformatectIn
, LPFORMATETC pformatetcOut
);
359 static HRESULT WINAPI
IDataObject_fnSetData(LPDATAOBJECT iface
, LPFORMATETC pformatetc
, STGMEDIUM
* pmedium
, BOOL fRelease
);
360 static HRESULT WINAPI
IDataObject_fnEnumFormatEtc(LPDATAOBJECT iface
, DWORD dwDirection
, IEnumFORMATETC
** ppenumFormatEtc
);
361 static HRESULT WINAPI
IDataObject_fnDAdvise(LPDATAOBJECT iface
, FORMATETC
* pformatetc
, DWORD advf
, IAdviseSink
* pAdvSink
, DWORD
* pdwConnection
);
362 static HRESULT WINAPI
IDataObject_fnDUnadvise(LPDATAOBJECT iface
, DWORD dwConnection
);
363 static HRESULT WINAPI
IDataObject_fnEnumDAdvise(LPDATAOBJECT iface
, IEnumSTATDATA
**ppenumAdvise
);
365 static struct ICOM_VTABLE(IDataObject
) dtovt
=
367 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
368 IDataObject_fnQueryInterface
,
369 IDataObject_fnAddRef
,
370 IDataObject_fnRelease
,
371 IDataObject_fnGetData
,
372 IDataObject_fnGetDataHere
,
373 IDataObject_fnQueryGetData
,
374 IDataObject_fnGetCanonicalFormatEtc
,
375 IDataObject_fnSetData
,
376 IDataObject_fnEnumFormatEtc
,
377 IDataObject_fnDAdvise
,
378 IDataObject_fnDUnadvise
,
379 IDataObject_fnEnumDAdvise
382 /**************************************************************************
383 * IDataObject_Constructor
385 LPDATAOBJECT
IDataObject_Constructor(HWND hwndOwner
, LPSHELLFOLDER psf
, LPITEMIDLIST
* apidl
, UINT cidl
)
387 IDataObjectImpl
* dto
;
388 if (!(dto
= (IDataObjectImpl
*)HeapAlloc(GetProcessHeap(),0,sizeof(IDataObjectImpl
))))
394 dto
->pidl
=ILClone(((IGenericSFImpl
*)psf
)->pMyPidl
); /* FIXME:add a reference and don't copy*/
396 /* fill the ItemID List List */
397 dto
->lpill
= IDLList_Constructor (8);
401 dto
->lpill
->lpvtbl
->fnAddItems(dto
->lpill
, apidl
, cidl
);
403 TRACE("(%p)->(sf=%p apidl=%p cidl=%u)\n",dto
, psf
, apidl
, cidl
);
405 return (LPDATAOBJECT
)dto
;
407 /***************************************************************************
408 * IDataObject_QueryInterface
410 static HRESULT WINAPI
IDataObject_fnQueryInterface(LPDATAOBJECT iface
, REFIID riid
, LPVOID
* ppvObj
)
412 ICOM_THIS(IDataObjectImpl
,iface
);
414 WINE_StringFromCLSID((LPCLSID
)riid
,xriid
);
415 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This
,xriid
,ppvObj
);
419 if(IsEqualIID(riid
, &IID_IUnknown
)) /*IUnknown*/
422 else if(IsEqualIID(riid
, &IID_IDataObject
)) /*IDataObject*/
423 { *ppvObj
= (IDataObject
*)This
;
427 { IDataObject_AddRef((IDataObject
*)*ppvObj
);
428 TRACE("-- Interface: (%p)->(%p)\n",ppvObj
,*ppvObj
);
431 TRACE("-- Interface: E_NOINTERFACE\n");
432 return E_NOINTERFACE
;
434 /**************************************************************************
437 static ULONG WINAPI
IDataObject_fnAddRef(LPDATAOBJECT iface
)
439 ICOM_THIS(IDataObjectImpl
,iface
);
441 TRACE("(%p)->(count=%lu)\n",This
, This
->ref
);
444 return ++(This
->ref
);
446 /**************************************************************************
447 * IDataObject_Release
449 static ULONG WINAPI
IDataObject_fnRelease(LPDATAOBJECT iface
)
451 ICOM_THIS(IDataObjectImpl
,iface
);
452 TRACE("(%p)->()\n",This
);
457 { TRACE(" destroying IDataObject(%p)\n",This
);
458 IDLList_Destructor(This
->lpill
);
459 HeapFree(GetProcessHeap(),0,This
);
464 /**************************************************************************
465 * DATAOBJECT_InitShellIDList (internal)
468 * get or register the "Shell IDList Array" clipformat
470 static BOOL
DATAOBJECT_InitShellIDList(void)
475 cfShellIDList
= RegisterClipboardFormatA(CFSTR_SHELLIDLIST
);
476 return(cfShellIDList
!= 0);
479 /**************************************************************************
480 * DATAOBJECT_InitFileGroupDesc (internal)
483 * get or register the "FileGroupDescriptor" clipformat
485 /* FIXME: DATAOBJECT_InitFileGroupDesc is not used (19981226)
486 static BOOL32 DATAOBJECT_InitFileGroupDesc(void)
487 { if (cfFileGroupDesc)
491 cfFileGroupDesc = RegisterClipboardFormatA(CFSTR_FILEDESCRIPTORA);
492 return(cfFileGroupDesc != 0);
495 /**************************************************************************
496 * DATAOBJECT_InitFileContents (internal)
499 * get or register the "FileContents" clipformat
501 /* FIXME: DATAOBJECT_InitFileContents is not used (19981226)
502 static BOOL32 DATAOBJECT_InitFileContents(void)
503 { if (cfFileContents)
507 cfFileContents = RegisterClipboardFormatA(CFSTR_FILECONTENTS);
508 return(cfFileContents != 0);
512 /**************************************************************************
513 * interface implementation
515 static HRESULT WINAPI
IDataObject_fnGetData(LPDATAOBJECT iface
, LPFORMATETC pformatetcIn
, STGMEDIUM
*pmedium
)
517 ICOM_THIS(IDataObjectImpl
,iface
);
520 DWORD size
, size1
, size2
;
525 GetClipboardFormatNameA (pformatetcIn
->cfFormat
, temp
, 256);
526 WARN("(%p)->(%p %p format=%s)semi-stub\n", This
, pformatetcIn
, pmedium
, temp
);
528 if (!DATAOBJECT_InitShellIDList()) /* is the clipformat registred? */
529 { return(E_UNEXPECTED
);
532 if (pformatetcIn
->cfFormat
== cfShellIDList
)
533 { if (pformatetcIn
->ptd
==NULL
534 && (pformatetcIn
->dwAspect
& DVASPECT_CONTENT
)
535 && pformatetcIn
->lindex
==-1
536 && (pformatetcIn
->tymed
&TYMED_HGLOBAL
))
537 { cItems
= This
->lpill
->lpvtbl
->fnGetCount(This
->lpill
);
539 { return(E_UNEXPECTED
);
541 pidl
= This
->lpill
->lpvtbl
->fnGetElement(This
->lpill
, 0);
546 /*hack consider only the first item*/
548 size
= sizeof(CIDA
) + sizeof (UINT
)*(cItems
-1);
549 size1
= ILGetSize (This
->pidl
);
550 size2
= ILGetSize (pidl
);
551 hmem
= GlobalAlloc(GMEM_FIXED
, size
+size1
+size2
);
552 pcida
= GlobalLock (hmem
);
554 { return(E_OUTOFMEMORY
);
558 pcida
->aoffset
[0] = size
;
559 pcida
->aoffset
[1] = size
+size1
;
561 TRACE("-- %lu %lu %lu\n",size
, size1
, size2
);
562 TRACE("-- %p %p\n",This
->pidl
, pidl
);
563 TRACE("-- %p %p %p\n",pcida
, (LPBYTE
)pcida
+size
,(LPBYTE
)pcida
+size
+size1
);
565 memcpy ((LPBYTE
)pcida
+size
, This
->pidl
, size1
);
566 memcpy ((LPBYTE
)pcida
+size
+size1
, pidl
, size2
);
567 TRACE("-- after copy\n");
571 pmedium
->tymed
= TYMED_HGLOBAL
;
572 pmedium
->u
.hGlobal
= (HGLOBAL
)pcida
;
573 pmedium
->pUnkForRelease
= NULL
;
578 FIXME("-- clipformat not implemented\n");
579 return (E_INVALIDARG
);
581 static HRESULT WINAPI
IDataObject_fnGetDataHere(LPDATAOBJECT iface
, LPFORMATETC pformatetc
, STGMEDIUM
*pmedium
)
583 ICOM_THIS(IDataObjectImpl
,iface
);
584 FIXME("(%p)->()\n", This
);
587 static HRESULT WINAPI
IDataObject_fnQueryGetData(LPDATAOBJECT iface
, LPFORMATETC pformatetc
)
589 ICOM_THIS(IDataObjectImpl
,iface
);
590 FIXME("(%p)->()\n", This
);
593 static HRESULT WINAPI
IDataObject_fnGetCanonicalFormatEtc(LPDATAOBJECT iface
, LPFORMATETC pformatectIn
, LPFORMATETC pformatetcOut
)
595 ICOM_THIS(IDataObjectImpl
,iface
);
596 FIXME("(%p)->()\n", This
);
599 static HRESULT WINAPI
IDataObject_fnSetData(LPDATAOBJECT iface
, LPFORMATETC pformatetc
, STGMEDIUM
*pmedium
, BOOL fRelease
)
601 ICOM_THIS(IDataObjectImpl
,iface
);
602 FIXME("(%p)->()\n", This
);
605 static HRESULT WINAPI
IDataObject_fnEnumFormatEtc(LPDATAOBJECT iface
, DWORD dwDirection
, IEnumFORMATETC
**ppenumFormatEtc
)
607 ICOM_THIS(IDataObjectImpl
,iface
);
608 FIXME("(%p)->()\n", This
);
611 static HRESULT WINAPI
IDataObject_fnDAdvise(LPDATAOBJECT iface
, FORMATETC
*pformatetc
, DWORD advf
, IAdviseSink
*pAdvSink
, DWORD
*pdwConnection
)
613 ICOM_THIS(IDataObjectImpl
,iface
);
614 FIXME("(%p)->()\n", This
);
617 static HRESULT WINAPI
IDataObject_fnDUnadvise(LPDATAOBJECT iface
, DWORD dwConnection
)
619 ICOM_THIS(IDataObjectImpl
,iface
);
620 FIXME("(%p)->()\n", This
);
623 static HRESULT WINAPI
IDataObject_fnEnumDAdvise(LPDATAOBJECT iface
, IEnumSTATDATA
**ppenumAdvise
)
625 ICOM_THIS(IDataObjectImpl
,iface
);
626 FIXME("(%p)->()\n", This
);