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_IEnumFORMATETC
, (void **)&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 4
164 class IDataObjectImpl
:
165 public CComObjectRootEx
<CComMultiThreadModelNoCS
>,
170 LPITEMIDLIST
* apidl
;
173 FORMATETC pFormatEtc
[MAX_FORMATS
];
180 HRESULT WINAPI
Initialize(HWND hwndOwner
, LPCITEMIDLIST pMyPidl
, LPCITEMIDLIST
* apidlx
, UINT cidlx
);
183 virtual HRESULT WINAPI
GetData(LPFORMATETC pformatetcIn
, STGMEDIUM
*pmedium
);
184 virtual HRESULT WINAPI
GetDataHere(LPFORMATETC pformatetc
, STGMEDIUM
*pmedium
);
185 virtual HRESULT WINAPI
QueryGetData(LPFORMATETC pformatetc
);
186 virtual HRESULT WINAPI
GetCanonicalFormatEtc(LPFORMATETC pformatectIn
, LPFORMATETC pformatetcOut
);
187 virtual HRESULT WINAPI
SetData(LPFORMATETC pformatetc
, STGMEDIUM
*pmedium
, BOOL fRelease
);
188 virtual HRESULT WINAPI
EnumFormatEtc(DWORD dwDirection
, IEnumFORMATETC
**ppenumFormatEtc
);
189 virtual HRESULT WINAPI
DAdvise(FORMATETC
*pformatetc
, DWORD advf
, IAdviseSink
*pAdvSink
, DWORD
*pdwConnection
);
190 virtual HRESULT WINAPI
DUnadvise(DWORD dwConnection
);
191 virtual HRESULT WINAPI
EnumDAdvise(IEnumSTATDATA
**ppenumAdvise
);
193 BEGIN_COM_MAP(IDataObjectImpl
)
194 COM_INTERFACE_ENTRY_IID(IID_IDataObject
, IDataObject
)
198 IDataObjectImpl::IDataObjectImpl()
208 IDataObjectImpl::~IDataObjectImpl()
210 TRACE(" destroying IDataObject(%p)\n",this);
211 _ILFreeaPidl(apidl
, cidl
);
215 HRESULT WINAPI
IDataObjectImpl::Initialize(HWND hwndOwner
, LPCITEMIDLIST pMyPidl
, LPCITEMIDLIST
* apidlx
, UINT cidlx
)
217 pidl
= ILClone(pMyPidl
);
218 apidl
= _ILCopyaPidl(apidlx
, cidlx
);
219 if (pidl
== NULL
|| apidl
== NULL
)
220 return E_OUTOFMEMORY
;
223 cfShellIDList
= RegisterClipboardFormatW(CFSTR_SHELLIDLIST
);
224 cfFileNameA
= RegisterClipboardFormatA(CFSTR_FILENAMEA
);
225 cfFileNameW
= RegisterClipboardFormatW(CFSTR_FILENAMEW
);
226 InitFormatEtc(pFormatEtc
[0], cfShellIDList
, TYMED_HGLOBAL
);
227 InitFormatEtc(pFormatEtc
[1], CF_HDROP
, TYMED_HGLOBAL
);
228 InitFormatEtc(pFormatEtc
[2], cfFileNameA
, TYMED_HGLOBAL
);
229 InitFormatEtc(pFormatEtc
[3], cfFileNameW
, TYMED_HGLOBAL
);
233 /**************************************************************************
234 * IDataObject_fnGetData
236 HRESULT WINAPI
IDataObjectImpl::GetData(LPFORMATETC pformatetcIn
, STGMEDIUM
*pmedium
)
241 GetClipboardFormatNameA (pformatetcIn
->cfFormat
, szTemp
, 256);
242 TRACE("(%p)->(%p %p format=%s)\n", this, pformatetcIn
, pmedium
, szTemp
);
244 if (pformatetcIn
->cfFormat
== cfShellIDList
)
246 if (cidl
< 1) return(E_UNEXPECTED
);
247 pmedium
->hGlobal
= RenderSHELLIDLIST(pidl
, apidl
, cidl
);
249 else if (pformatetcIn
->cfFormat
== CF_HDROP
)
251 if (cidl
< 1) return(E_UNEXPECTED
);
252 pmedium
->hGlobal
= RenderHDROP(pidl
, apidl
, cidl
);
254 else if (pformatetcIn
->cfFormat
== cfFileNameA
)
256 if (cidl
< 1) return(E_UNEXPECTED
);
257 pmedium
->hGlobal
= RenderFILENAMEA(pidl
, apidl
, cidl
);
259 else if (pformatetcIn
->cfFormat
== cfFileNameW
)
261 if (cidl
< 1) return(E_UNEXPECTED
);
262 pmedium
->hGlobal
= RenderFILENAMEW(pidl
, apidl
, cidl
);
266 FIXME("-- expected clipformat not implemented\n");
267 return (E_INVALIDARG
);
269 if (pmedium
->hGlobal
)
271 pmedium
->tymed
= TYMED_HGLOBAL
;
272 pmedium
->pUnkForRelease
= NULL
;
275 return E_OUTOFMEMORY
;
278 HRESULT WINAPI
IDataObjectImpl::GetDataHere(LPFORMATETC pformatetc
, STGMEDIUM
*pmedium
)
280 FIXME("(%p)->()\n", this);
284 HRESULT WINAPI
IDataObjectImpl::QueryGetData(LPFORMATETC pformatetc
)
288 TRACE("(%p)->(fmt=0x%08x tym=0x%08x)\n", this, pformatetc
->cfFormat
, pformatetc
->tymed
);
290 if(!(DVASPECT_CONTENT
& pformatetc
->dwAspect
))
291 return DV_E_DVASPECT
;
293 /* check our formats table what we have */
294 for (i
=0; i
<MAX_FORMATS
; i
++)
296 if ((pFormatEtc
[i
].cfFormat
== pformatetc
->cfFormat
)
297 && (pFormatEtc
[i
].tymed
== pformatetc
->tymed
))
306 HRESULT WINAPI
IDataObjectImpl::GetCanonicalFormatEtc(LPFORMATETC pformatectIn
, LPFORMATETC pformatetcOut
)
308 FIXME("(%p)->()\n", this);
312 HRESULT WINAPI
IDataObjectImpl::SetData(LPFORMATETC pformatetc
, STGMEDIUM
*pmedium
, BOOL fRelease
)
314 FIXME("(%p)->()\n", this);
318 HRESULT WINAPI
IDataObjectImpl::EnumFormatEtc(DWORD dwDirection
, IEnumFORMATETC
**ppenumFormatEtc
)
320 TRACE("(%p)->()\n", this);
321 *ppenumFormatEtc
= NULL
;
324 if (DATADIR_GET
== dwDirection
)
326 return IEnumFORMATETC_Constructor(MAX_FORMATS
, pFormatEtc
, ppenumFormatEtc
);
332 HRESULT WINAPI
IDataObjectImpl::DAdvise(FORMATETC
*pformatetc
, DWORD advf
, IAdviseSink
*pAdvSink
, DWORD
*pdwConnection
)
334 FIXME("(%p)->()\n", this);
338 HRESULT WINAPI
IDataObjectImpl::DUnadvise(DWORD dwConnection
)
340 FIXME("(%p)->()\n", this);
344 HRESULT WINAPI
IDataObjectImpl::EnumDAdvise(IEnumSTATDATA
**ppenumAdvise
)
346 FIXME("(%p)->()\n", this);
350 /**************************************************************************
351 * IDataObject_Constructor
353 HRESULT
IDataObject_Constructor(HWND hwndOwner
, LPCITEMIDLIST pMyPidl
, LPCITEMIDLIST
* apidl
, UINT cidl
, IDataObject
**dataObject
)
355 CComObject
<IDataObjectImpl
> *theDataObject
;
356 CComPtr
<IDataObject
> result
;
359 if (dataObject
== NULL
)
362 ATLTRY (theDataObject
= new CComObject
<IDataObjectImpl
>);
363 if (theDataObject
== NULL
)
364 return E_OUTOFMEMORY
;
365 hResult
= theDataObject
->QueryInterface (IID_IDataObject
, (void **)&result
);
366 if (FAILED (hResult
))
368 delete theDataObject
;
371 hResult
= theDataObject
->Initialize (hwndOwner
, pMyPidl
, apidl
, cidl
);
372 if (FAILED (hResult
))
374 *dataObject
= result
.Detach ();
375 TRACE("(%p)->(apidl=%p cidl=%u)\n", *dataObject
, apidl
, cidl
);
379 /*************************************************************************
380 * SHCreateDataObject [SHELL32.@]
384 HRESULT WINAPI
SHCreateDataObject(LPCITEMIDLIST pidlFolder
, UINT cidl
, LPCITEMIDLIST
* apidl
, IDataObject
*pdtInner
, REFIID riid
, void **ppv
)
386 if (IsEqualIID(riid
, IID_IDataObject
))
388 return CIDLData_CreateFromIDArray(pidlFolder
, cidl
, apidl
, (IDataObject
**)ppv
);