2 * IEnumFORMATETC, IDataObject
4 * selecting and dropping objects within the shell and/or common dialogs
6 * Copyright 1998, 1999 <juergen.schmied@metronet.de>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
29 #include "shell32_main.h"
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
34 /***********************************************************************
35 * IEnumFORMATETC implementation
41 IEnumFORMATETC IEnumFORMATETC_iface
;
43 /* IEnumFORMATETC fields */
49 static inline IEnumFORMATETCImpl
*impl_from_IEnumFORMATETC(IEnumFORMATETC
*iface
)
51 return CONTAINING_RECORD(iface
, IEnumFORMATETCImpl
, IEnumFORMATETC_iface
);
54 static HRESULT WINAPI
IEnumFORMATETC_fnQueryInterface(
55 LPENUMFORMATETC iface
, REFIID riid
, LPVOID
* ppvObj
)
57 IEnumFORMATETCImpl
*This
= impl_from_IEnumFORMATETC(iface
);
58 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This
,debugstr_guid(riid
),ppvObj
);
62 if(IsEqualIID(riid
, &IID_IUnknown
) ||
63 IsEqualIID(riid
, &IID_IEnumFORMATETC
))
65 *ppvObj
= &This
->IEnumFORMATETC_iface
;
70 IUnknown_AddRef((IUnknown
*)(*ppvObj
));
71 TRACE("-- Interface: (%p)->(%p)\n",ppvObj
,*ppvObj
);
74 TRACE("-- Interface: E_NOINTERFACE\n");
78 static ULONG WINAPI
IEnumFORMATETC_fnAddRef(LPENUMFORMATETC iface
)
80 IEnumFORMATETCImpl
*This
= impl_from_IEnumFORMATETC(iface
);
81 ULONG refCount
= InterlockedIncrement(&This
->ref
);
83 TRACE("(%p)->(count=%lu)\n", This
, refCount
- 1);
88 static ULONG WINAPI
IEnumFORMATETC_fnRelease(LPENUMFORMATETC iface
)
90 IEnumFORMATETCImpl
*This
= impl_from_IEnumFORMATETC(iface
);
91 ULONG refCount
= InterlockedDecrement(&This
->ref
);
93 TRACE("(%p)->(%lu)\n", This
, refCount
+ 1);
97 TRACE(" destroying IEnumFORMATETC(%p)\n",This
);
104 static HRESULT WINAPI
IEnumFORMATETC_fnNext(LPENUMFORMATETC iface
, ULONG celt
, FORMATETC
*rgelt
, ULONG
*pceltFethed
)
106 IEnumFORMATETCImpl
*This
= impl_from_IEnumFORMATETC(iface
);
109 TRACE("(%p)->(%lu,%p)\n", This
, celt
, rgelt
);
111 if(!This
->pFmt
)return S_FALSE
;
112 if(!rgelt
) return E_INVALIDARG
;
113 if (pceltFethed
) *pceltFethed
= 0;
115 for(i
= 0; This
->posFmt
< This
->countFmt
&& celt
> i
; i
++)
117 *rgelt
++ = This
->pFmt
[This
->posFmt
++];
120 if (pceltFethed
) *pceltFethed
= i
;
122 return ((i
== celt
) ? S_OK
: S_FALSE
);
125 static HRESULT WINAPI
IEnumFORMATETC_fnSkip(LPENUMFORMATETC iface
, ULONG celt
)
127 IEnumFORMATETCImpl
*This
= impl_from_IEnumFORMATETC(iface
);
128 TRACE("(%p)->(num=%lu)\n", This
, celt
);
130 if((This
->posFmt
+ celt
) >= This
->countFmt
) return S_FALSE
;
131 This
->posFmt
+= celt
;
135 static HRESULT WINAPI
IEnumFORMATETC_fnReset(LPENUMFORMATETC iface
)
137 IEnumFORMATETCImpl
*This
= impl_from_IEnumFORMATETC(iface
);
138 TRACE("(%p)->()\n", This
);
144 static HRESULT WINAPI
IEnumFORMATETC_fnClone(LPENUMFORMATETC iface
, LPENUMFORMATETC
* ppenum
)
146 IEnumFORMATETCImpl
*This
= impl_from_IEnumFORMATETC(iface
);
147 TRACE("(%p)->(ppenum=%p)\n", This
, ppenum
);
149 if (!ppenum
) return E_INVALIDARG
;
150 *ppenum
= IEnumFORMATETC_Constructor(This
->countFmt
, This
->pFmt
);
152 IEnumFORMATETC_fnSkip(*ppenum
, This
->posFmt
);
156 static const IEnumFORMATETCVtbl efvt
=
158 IEnumFORMATETC_fnQueryInterface
,
159 IEnumFORMATETC_fnAddRef
,
160 IEnumFORMATETC_fnRelease
,
161 IEnumFORMATETC_fnNext
,
162 IEnumFORMATETC_fnSkip
,
163 IEnumFORMATETC_fnReset
,
164 IEnumFORMATETC_fnClone
167 LPENUMFORMATETC
IEnumFORMATETC_Constructor(UINT cfmt
, const FORMATETC afmt
[])
169 IEnumFORMATETCImpl
* ef
;
170 DWORD size
=cfmt
* sizeof(FORMATETC
);
172 ef
= calloc(1, sizeof(*ef
));
177 ef
->IEnumFORMATETC_iface
.lpVtbl
= &efvt
;
180 ef
->pFmt
= SHAlloc (size
);
183 memcpy(ef
->pFmt
, afmt
, size
);
186 TRACE("(%p)->(%u,%p)\n",ef
, cfmt
, afmt
);
187 return &ef
->IEnumFORMATETC_iface
;
198 IDataObject IDataObject_iface
;
205 static inline IDataObjectImpl
*impl_from_IDataObject(IDataObject
*iface
)
207 return CONTAINING_RECORD(iface
, IDataObjectImpl
, IDataObject_iface
);
210 /***************************************************************************
211 * IDataObject_QueryInterface
213 static HRESULT WINAPI
IDataObject_fnQueryInterface(IDataObject
*iface
, REFIID riid
, LPVOID
* ppvObj
)
215 IDataObjectImpl
*This
= impl_from_IDataObject(iface
);
216 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This
,debugstr_guid(riid
),ppvObj
);
220 if(IsEqualIID(riid
, &IID_IUnknown
) ||
221 IsEqualIID(riid
, &IID_IDataObject
))
223 *ppvObj
= &This
->IDataObject_iface
;
228 IUnknown_AddRef((IUnknown
*)*ppvObj
);
229 TRACE("-- Interface: (%p)->(%p)\n",ppvObj
,*ppvObj
);
232 TRACE("-- Interface: E_NOINTERFACE\n");
233 return E_NOINTERFACE
;
236 /**************************************************************************
239 static ULONG WINAPI
IDataObject_fnAddRef(IDataObject
*iface
)
241 IDataObjectImpl
*This
= impl_from_IDataObject(iface
);
242 ULONG refCount
= InterlockedIncrement(&This
->ref
);
244 TRACE("(%p)->(count=%lu)\n", This
, refCount
- 1);
249 /**************************************************************************
250 * IDataObject_Release
252 static ULONG WINAPI
IDataObject_fnRelease(IDataObject
*iface
)
254 IDataObjectImpl
*obj
= impl_from_IDataObject(iface
);
255 ULONG refcount
= InterlockedDecrement(&obj
->ref
);
257 TRACE("%p decreasing refcount to %lu.\n", obj
, refcount
);
261 for (size_t i
= 0; i
< obj
->data_count
; ++i
)
262 GlobalFree(obj
->data
[i
].global
);
269 /**************************************************************************
270 * IDataObject_fnGetData
272 static HRESULT WINAPI
IDataObject_fnGetData(IDataObject
*iface
, FORMATETC
*format
, STGMEDIUM
*medium
)
274 IDataObjectImpl
*obj
= impl_from_IDataObject(iface
);
276 TRACE("iface %p, format %p, medium %p.\n", iface
, format
, medium
);
278 if (!(format
->tymed
& TYMED_HGLOBAL
))
280 FIXME("Unrecognized tymed %#lx, returning DV_E_FORMATETC.\n", format
->tymed
);
281 return DV_E_FORMATETC
;
284 for (size_t i
= 0; i
< obj
->data_count
; ++i
)
286 if (obj
->data
[i
].cf
== format
->cfFormat
)
288 HGLOBAL src_global
= obj
->data
[i
].global
;
289 size_t size
= GlobalSize(src_global
);
294 if (!(dst_global
= GlobalAlloc(GMEM_MOVEABLE
, size
)))
295 return E_OUTOFMEMORY
;
296 src
= GlobalLock(src_global
);
297 dst
= GlobalLock(dst_global
);
298 memcpy(dst
, src
, size
);
299 GlobalUnlock(src_global
);
300 GlobalUnlock(dst_global
);
302 medium
->tymed
= TYMED_HGLOBAL
;
303 medium
->pUnkForRelease
= NULL
;
304 medium
->hGlobal
= dst_global
;
309 return DV_E_FORMATETC
;
312 static HRESULT WINAPI
IDataObject_fnGetDataHere(IDataObject
*iface
, LPFORMATETC pformatetc
, STGMEDIUM
*pmedium
)
314 IDataObjectImpl
*This
= impl_from_IDataObject(iface
);
315 FIXME("(%p)->()\n", This
);
319 static HRESULT WINAPI
IDataObject_fnQueryGetData(IDataObject
*iface
, FORMATETC
*format
)
321 IDataObjectImpl
*obj
= impl_from_IDataObject(iface
);
323 TRACE("iface %p, format %p.\n", iface
, format
);
325 if (!(format
->tymed
& TYMED_HGLOBAL
))
327 FIXME("Unrecognized tymed %#lx, returning S_FALSE.\n", format
->tymed
);
331 for (size_t i
= 0; i
< obj
->data_count
; ++i
)
333 if (obj
->data
[i
].cf
== format
->cfFormat
)
340 static HRESULT WINAPI
IDataObject_fnGetCanonicalFormatEtc(IDataObject
*iface
, LPFORMATETC pformatectIn
, LPFORMATETC pformatetcOut
)
342 IDataObjectImpl
*This
= impl_from_IDataObject(iface
);
343 FIXME("(%p)->()\n", This
);
347 static HRESULT WINAPI
IDataObject_fnSetData(IDataObject
*iface
,
348 FORMATETC
*format
, STGMEDIUM
*medium
, BOOL release
)
350 IDataObjectImpl
*obj
= impl_from_IDataObject(iface
);
351 struct data
*new_array
;
353 TRACE("iface %p, format %p, medium %p, release %d.\n", iface
, format
, medium
, release
);
358 if (format
->tymed
!= TYMED_HGLOBAL
)
360 FIXME("Unhandled format tymed %#lx.\n", format
->tymed
);
364 if (medium
->tymed
!= TYMED_HGLOBAL
)
366 FIXME("Unhandled medium tymed %#lx.\n", format
->tymed
);
370 if (medium
->pUnkForRelease
)
371 FIXME("Ignoring IUnknown %p.\n", medium
->pUnkForRelease
);
373 for (size_t i
= 0; i
< obj
->data_count
; ++i
)
375 if (obj
->data
[i
].cf
== format
->cfFormat
)
377 GlobalFree(obj
->data
[i
].global
);
378 obj
->data
[i
].global
= medium
->hGlobal
;
383 if (!(new_array
= realloc(obj
->data
, (obj
->data_count
+ 1) * sizeof(*obj
->data
))))
384 return E_OUTOFMEMORY
;
385 obj
->data
= new_array
;
386 obj
->data
[obj
->data_count
].cf
= format
->cfFormat
;
387 obj
->data
[obj
->data_count
].global
= medium
->hGlobal
;
392 static HRESULT WINAPI
IDataObject_fnEnumFormatEtc(IDataObject
*iface
, DWORD direction
, IEnumFORMATETC
**out
)
394 IDataObjectImpl
*obj
= impl_from_IDataObject(iface
);
397 TRACE("iface %p, direction %#lx, out %p.\n", iface
, direction
, out
);
399 if (!(formats
= calloc(obj
->data_count
, sizeof(*formats
))))
400 return E_OUTOFMEMORY
;
401 for (size_t i
= 0; i
< obj
->data_count
; ++i
)
402 InitFormatEtc(formats
[i
], obj
->data
[i
].cf
, TYMED_HGLOBAL
);
404 if (!(*out
= IEnumFORMATETC_Constructor(obj
->data_count
, formats
)))
407 return E_OUTOFMEMORY
;
413 static HRESULT WINAPI
IDataObject_fnDAdvise(IDataObject
*iface
, FORMATETC
*pformatetc
, DWORD advf
, IAdviseSink
*pAdvSink
, DWORD
*pdwConnection
)
415 IDataObjectImpl
*This
= impl_from_IDataObject(iface
);
416 FIXME("(%p)->()\n", This
);
419 static HRESULT WINAPI
IDataObject_fnDUnadvise(IDataObject
*iface
, DWORD dwConnection
)
421 IDataObjectImpl
*This
= impl_from_IDataObject(iface
);
422 FIXME("(%p)->()\n", This
);
425 static HRESULT WINAPI
IDataObject_fnEnumDAdvise(IDataObject
*iface
, IEnumSTATDATA
**ppenumAdvise
)
427 IDataObjectImpl
*This
= impl_from_IDataObject(iface
);
428 FIXME("(%p)->()\n", This
);
432 static const IDataObjectVtbl dtovt
=
434 IDataObject_fnQueryInterface
,
435 IDataObject_fnAddRef
,
436 IDataObject_fnRelease
,
437 IDataObject_fnGetData
,
438 IDataObject_fnGetDataHere
,
439 IDataObject_fnQueryGetData
,
440 IDataObject_fnGetCanonicalFormatEtc
,
441 IDataObject_fnSetData
,
442 IDataObject_fnEnumFormatEtc
,
443 IDataObject_fnDAdvise
,
444 IDataObject_fnDUnadvise
,
445 IDataObject_fnEnumDAdvise
448 /**************************************************************************
449 * IDataObject_Constructor
451 IDataObject
*IDataObject_Constructor(HWND hwnd
, const ITEMIDLIST
*root_pidl
,
452 const ITEMIDLIST
**pidls
, UINT pidl_count
)
454 IDataObjectImpl
*obj
;
456 if (!(obj
= calloc(1, sizeof(*obj
))))
460 obj
->IDataObject_iface
.lpVtbl
= &dtovt
;
461 obj
->data
= calloc(4, sizeof(*obj
->data
));
462 obj
->data
[0].cf
= RegisterClipboardFormatW(CFSTR_SHELLIDLISTW
);
463 obj
->data
[0].global
= RenderSHELLIDLIST(root_pidl
, pidls
, pidl_count
);
464 obj
->data
[1].cf
= CF_HDROP
;
465 obj
->data
[1].global
= RenderHDROP(root_pidl
, pidls
, pidl_count
);
466 obj
->data
[2].cf
= RegisterClipboardFormatA(CFSTR_FILENAMEA
);
467 obj
->data
[2].global
= RenderFILENAMEA(root_pidl
, pidls
, pidl_count
);
468 obj
->data
[3].cf
= RegisterClipboardFormatW(CFSTR_FILENAMEW
);
469 obj
->data
[3].global
= RenderFILENAMEW(root_pidl
, pidls
, pidl_count
);
472 TRACE("Created data object %p.\n", obj
);
473 return &obj
->IDataObject_iface
;