2 * IEnumFORMATETC, IDataObject
4 * selecting and droping 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
25 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
27 /***********************************************************************
28 * IEnumFORMATETC implementation
31 class IEnumFORMATETCImpl
:
32 public CComObjectRootEx
<CComMultiThreadModelNoCS
>,
41 ~IEnumFORMATETCImpl();
42 HRESULT WINAPI
Initialize(UINT cfmt
, const FORMATETC afmt
[]);
45 virtual HRESULT WINAPI
Next(ULONG celt
, FORMATETC
*rgelt
, ULONG
*pceltFethed
);
46 virtual HRESULT WINAPI
Skip(ULONG celt
);
47 virtual HRESULT WINAPI
Reset();
48 virtual HRESULT WINAPI
Clone(LPENUMFORMATETC
* ppenum
);
50 BEGIN_COM_MAP(IEnumFORMATETCImpl
)
51 COM_INTERFACE_ENTRY_IID(IID_IEnumFORMATETC
, IEnumFORMATETC
)
55 IEnumFORMATETCImpl::IEnumFORMATETCImpl()
62 IEnumFORMATETCImpl::~IEnumFORMATETCImpl()
66 HRESULT WINAPI
IEnumFORMATETCImpl::Initialize(UINT cfmt
, const FORMATETC afmt
[])
70 size
= cfmt
* sizeof(FORMATETC
);
72 pFmt
= (LPFORMATETC
)SHAlloc(size
);
76 memcpy(pFmt
, afmt
, size
);
80 HRESULT WINAPI
IEnumFORMATETCImpl::Next(ULONG celt
, FORMATETC
*rgelt
, ULONG
*pceltFethed
)
84 TRACE("(%p)->(%u,%p)\n", this, celt
, rgelt
);
86 if(!pFmt
)return S_FALSE
;
87 if(!rgelt
) return E_INVALIDARG
;
88 if (pceltFethed
) *pceltFethed
= 0;
90 for(i
= 0; posFmt
< countFmt
&& celt
> i
; i
++)
92 *rgelt
++ = pFmt
[posFmt
++];
95 if (pceltFethed
) *pceltFethed
= i
;
97 return ((i
== celt
) ? S_OK
: S_FALSE
);
100 HRESULT WINAPI
IEnumFORMATETCImpl::Skip(ULONG celt
)
102 TRACE("(%p)->(num=%u)\n", this, celt
);
104 if (posFmt
+ celt
>= countFmt
) return S_FALSE
;
109 HRESULT WINAPI
IEnumFORMATETCImpl::Reset()
111 TRACE("(%p)->()\n", this);
117 HRESULT WINAPI
IEnumFORMATETCImpl::Clone(LPENUMFORMATETC
* ppenum
)
121 TRACE("(%p)->(ppenum=%p)\n", this, ppenum
);
123 if (!ppenum
) return E_INVALIDARG
;
124 hResult
= IEnumFORMATETC_Constructor(countFmt
, pFmt
, ppenum
);
125 if (FAILED (hResult
))
127 return (*ppenum
)->Skip(posFmt
);
130 HRESULT
IEnumFORMATETC_Constructor(UINT cfmt
, const FORMATETC afmt
[], IEnumFORMATETC
**enumerator
)
132 CComObject
<IEnumFORMATETCImpl
> *theEnumerator
;
133 CComPtr
<IEnumFORMATETC
> result
;
136 if (enumerator
== NULL
)
139 ATLTRY (theEnumerator
= new CComObject
<IEnumFORMATETCImpl
>);
140 if (theEnumerator
== NULL
)
141 return E_OUTOFMEMORY
;
142 hResult
= theEnumerator
->QueryInterface (IID_PPV_ARG(IEnumFORMATETC
, &result
));
143 if (FAILED (hResult
))
145 delete theEnumerator
;
148 hResult
= theEnumerator
->Initialize (cfmt
, afmt
);
149 if (FAILED (hResult
))
151 *enumerator
= result
.Detach ();
152 TRACE("(%p)->(%u,%p)\n", *enumerator
, cfmt
, afmt
);
157 /***********************************************************************
158 * IDataObject implementation
161 /* number of supported formats */
162 #define MAX_FORMATS 5
164 class IDataObjectImpl
:
165 public CComObjectRootEx
<CComMultiThreadModelNoCS
>,
167 public IAsyncOperation
171 LPITEMIDLIST
* apidl
;
175 FORMATETC pFormatEtc
[MAX_FORMATS
];
179 UINT cfPreferredDropEffect
;
184 HRESULT WINAPI
Initialize(HWND hwndOwner
, LPCITEMIDLIST pMyPidl
, LPCITEMIDLIST
* apidlx
, UINT cidlx
);
187 virtual HRESULT WINAPI
GetData(LPFORMATETC pformatetcIn
, STGMEDIUM
*pmedium
);
188 virtual HRESULT WINAPI
GetDataHere(LPFORMATETC pformatetc
, STGMEDIUM
*pmedium
);
189 virtual HRESULT WINAPI
QueryGetData(LPFORMATETC pformatetc
);
190 virtual HRESULT WINAPI
GetCanonicalFormatEtc(LPFORMATETC pformatectIn
, LPFORMATETC pformatetcOut
);
191 virtual HRESULT WINAPI
SetData(LPFORMATETC pformatetc
, STGMEDIUM
*pmedium
, BOOL fRelease
);
192 virtual HRESULT WINAPI
EnumFormatEtc(DWORD dwDirection
, IEnumFORMATETC
**ppenumFormatEtc
);
193 virtual HRESULT WINAPI
DAdvise(FORMATETC
*pformatetc
, DWORD advf
, IAdviseSink
*pAdvSink
, DWORD
*pdwConnection
);
194 virtual HRESULT WINAPI
DUnadvise(DWORD dwConnection
);
195 virtual HRESULT WINAPI
EnumDAdvise(IEnumSTATDATA
**ppenumAdvise
);
196 virtual HRESULT WINAPI
GetAsyncMode(BOOL
*pfIsOpAsync
);
197 virtual HRESULT WINAPI
InOperation(BOOL
*pfInAsyncOp
);
198 virtual HRESULT WINAPI
SetAsyncMode(BOOL fDoOpAsync
);
199 virtual HRESULT WINAPI
StartOperation(IBindCtx
*pbcReserved
);
200 virtual HRESULT WINAPI
EndOperation(HRESULT hResult
, IBindCtx
*pbcReserved
, DWORD dwEffects
);
202 BEGIN_COM_MAP(IDataObjectImpl
)
203 COM_INTERFACE_ENTRY_IID(IID_IDataObject
, IDataObject
)
204 COM_INTERFACE_ENTRY_IID(IID_IAsyncOperation
, IAsyncOperation
)
208 IDataObjectImpl::IDataObjectImpl()
217 cfPreferredDropEffect
= 0;
221 IDataObjectImpl::~IDataObjectImpl()
223 TRACE(" destroying IDataObject(%p)\n",this);
224 _ILFreeaPidl(apidl
, cidl
);
228 HRESULT WINAPI
IDataObjectImpl::Initialize(HWND hwndOwner
, LPCITEMIDLIST pMyPidl
, LPCITEMIDLIST
* apidlx
, UINT cidlx
)
230 pidl
= ILClone(pMyPidl
);
231 apidl
= _ILCopyaPidl(apidlx
, cidlx
);
232 if (pidl
== NULL
|| apidl
== NULL
)
233 return E_OUTOFMEMORY
;
235 dropeffect
= DROPEFFECT_COPY
;
237 cfShellIDList
= RegisterClipboardFormatW(CFSTR_SHELLIDLIST
);
238 cfFileNameA
= RegisterClipboardFormatA(CFSTR_FILENAMEA
);
239 cfFileNameW
= RegisterClipboardFormatW(CFSTR_FILENAMEW
);
240 cfPreferredDropEffect
= RegisterClipboardFormatW(CFSTR_PREFERREDDROPEFFECTW
);
241 InitFormatEtc(pFormatEtc
[0], cfShellIDList
, TYMED_HGLOBAL
);
242 InitFormatEtc(pFormatEtc
[1], CF_HDROP
, TYMED_HGLOBAL
);
243 InitFormatEtc(pFormatEtc
[2], cfFileNameA
, TYMED_HGLOBAL
);
244 InitFormatEtc(pFormatEtc
[3], cfFileNameW
, TYMED_HGLOBAL
);
245 InitFormatEtc(pFormatEtc
[4], cfPreferredDropEffect
, TYMED_HGLOBAL
);
249 /**************************************************************************
250 * IDataObject_fnGetData
252 HRESULT WINAPI
IDataObjectImpl::GetData(LPFORMATETC pformatetcIn
, STGMEDIUM
*pmedium
)
257 GetClipboardFormatNameA (pformatetcIn
->cfFormat
, szTemp
, 256);
258 TRACE("(%p)->(%p %p format=%s)\n", this, pformatetcIn
, pmedium
, szTemp
);
260 if (pformatetcIn
->cfFormat
== cfShellIDList
)
262 if (cidl
< 1) return(E_UNEXPECTED
);
263 pmedium
->hGlobal
= RenderSHELLIDLIST(pidl
, apidl
, cidl
);
265 else if (pformatetcIn
->cfFormat
== CF_HDROP
)
267 if (cidl
< 1) return(E_UNEXPECTED
);
268 pmedium
->hGlobal
= RenderHDROP(pidl
, apidl
, cidl
);
270 else if (pformatetcIn
->cfFormat
== cfFileNameA
)
272 if (cidl
< 1) return(E_UNEXPECTED
);
273 pmedium
->hGlobal
= RenderFILENAMEA(pidl
, apidl
, cidl
);
275 else if (pformatetcIn
->cfFormat
== cfFileNameW
)
277 if (cidl
< 1) return(E_UNEXPECTED
);
278 pmedium
->hGlobal
= RenderFILENAMEW(pidl
, apidl
, cidl
);
280 else if (pformatetcIn
->cfFormat
== cfPreferredDropEffect
)
282 pmedium
->hGlobal
= RenderPREFEREDDROPEFFECT(dropeffect
);
286 FIXME("-- expected clipformat not implemented\n");
287 return (E_INVALIDARG
);
289 if (pmedium
->hGlobal
)
291 pmedium
->tymed
= TYMED_HGLOBAL
;
292 pmedium
->pUnkForRelease
= NULL
;
295 return E_OUTOFMEMORY
;
298 HRESULT WINAPI
IDataObjectImpl::GetDataHere(LPFORMATETC pformatetc
, STGMEDIUM
*pmedium
)
300 FIXME("(%p)->()\n", this);
304 HRESULT WINAPI
IDataObjectImpl::QueryGetData(LPFORMATETC pformatetc
)
308 TRACE("(%p)->(fmt=0x%08x tym=0x%08x)\n", this, pformatetc
->cfFormat
, pformatetc
->tymed
);
310 if(!(DVASPECT_CONTENT
& pformatetc
->dwAspect
))
311 return DV_E_DVASPECT
;
313 /* check our formats table what we have */
314 for (i
=0; i
<MAX_FORMATS
; i
++)
316 if ((pFormatEtc
[i
].cfFormat
== pformatetc
->cfFormat
)
317 && (pFormatEtc
[i
].tymed
== pformatetc
->tymed
))
326 HRESULT WINAPI
IDataObjectImpl::GetCanonicalFormatEtc(LPFORMATETC pformatectIn
, LPFORMATETC pformatetcOut
)
328 FIXME("(%p)->()\n", this);
332 HRESULT WINAPI
IDataObjectImpl::SetData(LPFORMATETC pformatetc
, STGMEDIUM
*pmedium
, BOOL fRelease
)
334 if (pformatetc
->cfFormat
== cfPreferredDropEffect
)
336 const DWORD
*src
= (const DWORD
*)GlobalLock(pmedium
->hGlobal
);
340 GlobalUnlock(pmedium
->hGlobal
);
343 FIXME("Error setting data");
347 FIXME("(%p)->()\n", this);
351 HRESULT WINAPI
IDataObjectImpl::EnumFormatEtc(DWORD dwDirection
, IEnumFORMATETC
**ppenumFormatEtc
)
353 TRACE("(%p)->()\n", this);
354 *ppenumFormatEtc
= NULL
;
357 if (DATADIR_GET
== dwDirection
)
359 return IEnumFORMATETC_Constructor(MAX_FORMATS
, pFormatEtc
, ppenumFormatEtc
);
365 HRESULT WINAPI
IDataObjectImpl::DAdvise(FORMATETC
*pformatetc
, DWORD advf
, IAdviseSink
*pAdvSink
, DWORD
*pdwConnection
)
367 FIXME("(%p)->()\n", this);
371 HRESULT WINAPI
IDataObjectImpl::DUnadvise(DWORD dwConnection
)
373 FIXME("(%p)->()\n", this);
377 HRESULT WINAPI
IDataObjectImpl::EnumDAdvise(IEnumSTATDATA
**ppenumAdvise
)
379 FIXME("(%p)->()\n", this);
383 HRESULT WINAPI
IDataObjectImpl::GetAsyncMode(BOOL
*pfIsOpAsync
)
385 TRACE("(%p)->()\n", this);
386 *pfIsOpAsync
= doasync
;
389 HRESULT WINAPI
IDataObjectImpl::InOperation(BOOL
*pfInAsyncOp
)
391 FIXME("(%p)->()\n", this);
394 HRESULT WINAPI
IDataObjectImpl::SetAsyncMode(BOOL fDoOpAsync
)
396 TRACE("(%p)->()\n", this);
397 doasync
= fDoOpAsync
;
401 HRESULT WINAPI
IDataObjectImpl::StartOperation(IBindCtx
*pbcReserved
)
403 FIXME("(%p)->()\n", this);
406 HRESULT WINAPI
IDataObjectImpl::EndOperation(HRESULT hResult
, IBindCtx
*pbcReserved
, DWORD dwEffects
)
408 FIXME("(%p)->()\n", this);
414 /**************************************************************************
415 * IDataObject_Constructor
417 HRESULT
IDataObject_Constructor(HWND hwndOwner
, LPCITEMIDLIST pMyPidl
, LPCITEMIDLIST
* apidl
, UINT cidl
, IDataObject
**dataObject
)
419 CComObject
<IDataObjectImpl
> *theDataObject
;
420 CComPtr
<IDataObject
> result
;
423 if (dataObject
== NULL
)
426 ATLTRY (theDataObject
= new CComObject
<IDataObjectImpl
>);
427 if (theDataObject
== NULL
)
428 return E_OUTOFMEMORY
;
429 hResult
= theDataObject
->QueryInterface(IID_PPV_ARG(IDataObject
, &result
));
430 if (FAILED (hResult
))
432 delete theDataObject
;
435 hResult
= theDataObject
->Initialize (hwndOwner
, pMyPidl
, apidl
, cidl
);
436 if (FAILED (hResult
))
438 *dataObject
= result
.Detach ();
439 TRACE("(%p)->(apidl=%p cidl=%u)\n", *dataObject
, apidl
, cidl
);
443 /*************************************************************************
444 * SHCreateDataObject [SHELL32.@]
448 HRESULT WINAPI
SHCreateDataObject(LPCITEMIDLIST pidlFolder
, UINT cidl
, LPCITEMIDLIST
* apidl
, IDataObject
*pdtInner
, REFIID riid
, void **ppv
)
450 if (IsEqualIID(riid
, IID_IDataObject
))
452 return CIDLData_CreateFromIDArray(pidlFolder
, cidl
, apidl
, (IDataObject
**)ppv
);