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
**ppFormat
)
132 return ShellObjectCreatorInit
<IEnumFORMATETCImpl
>(cfmt
, afmt
, IID_PPV_ARG(IEnumFORMATETC
, ppFormat
));
136 /***********************************************************************
137 * IDataObject implementation
140 /* number of supported formats */
141 #define MAX_FORMATS 5
144 public CComObjectRootEx
<CComMultiThreadModelNoCS
>,
146 public IAsyncOperation
150 PIDLIST_RELATIVE
*apidl
;
154 FORMATETC pFormatEtc
[MAX_FORMATS
];
158 UINT cfPreferredDropEffect
;
163 HRESULT WINAPI
Initialize(HWND hwndOwner
, PCIDLIST_ABSOLUTE pMyPidl
, PCUIDLIST_RELATIVE_ARRAY apidlx
, UINT cidlx
);
166 virtual HRESULT WINAPI
GetData(LPFORMATETC pformatetcIn
, STGMEDIUM
*pmedium
);
167 virtual HRESULT WINAPI
GetDataHere(LPFORMATETC pformatetc
, STGMEDIUM
*pmedium
);
168 virtual HRESULT WINAPI
QueryGetData(LPFORMATETC pformatetc
);
169 virtual HRESULT WINAPI
GetCanonicalFormatEtc(LPFORMATETC pformatectIn
, LPFORMATETC pformatetcOut
);
170 virtual HRESULT WINAPI
SetData(LPFORMATETC pformatetc
, STGMEDIUM
*pmedium
, BOOL fRelease
);
171 virtual HRESULT WINAPI
EnumFormatEtc(DWORD dwDirection
, IEnumFORMATETC
**ppenumFormatEtc
);
172 virtual HRESULT WINAPI
DAdvise(FORMATETC
*pformatetc
, DWORD advf
, IAdviseSink
*pAdvSink
, DWORD
*pdwConnection
);
173 virtual HRESULT WINAPI
DUnadvise(DWORD dwConnection
);
174 virtual HRESULT WINAPI
EnumDAdvise(IEnumSTATDATA
**ppenumAdvise
);
175 virtual HRESULT WINAPI
GetAsyncMode(BOOL
*pfIsOpAsync
);
176 virtual HRESULT WINAPI
InOperation(BOOL
*pfInAsyncOp
);
177 virtual HRESULT WINAPI
SetAsyncMode(BOOL fDoOpAsync
);
178 virtual HRESULT WINAPI
StartOperation(IBindCtx
*pbcReserved
);
179 virtual HRESULT WINAPI
EndOperation(HRESULT hResult
, IBindCtx
*pbcReserved
, DWORD dwEffects
);
181 BEGIN_COM_MAP(CIDLDataObj
)
182 COM_INTERFACE_ENTRY_IID(IID_IDataObject
, IDataObject
)
183 COM_INTERFACE_ENTRY_IID(IID_IAsyncOperation
, IAsyncOperation
)
187 CIDLDataObj::CIDLDataObj()
196 cfPreferredDropEffect
= 0;
200 CIDLDataObj::~CIDLDataObj()
202 TRACE(" destroying IDataObject(%p)\n",this);
203 _ILFreeaPidl(apidl
, cidl
);
207 HRESULT WINAPI
CIDLDataObj::Initialize(HWND hwndOwner
, PCIDLIST_ABSOLUTE pMyPidl
, PCUIDLIST_RELATIVE_ARRAY apidlx
, UINT cidlx
)
209 pidl
= ILClone(pMyPidl
);
210 apidl
= _ILCopyaPidl(apidlx
, cidlx
);
211 if (pidl
== NULL
|| apidl
== NULL
)
212 return E_OUTOFMEMORY
;
214 dropeffect
= DROPEFFECT_COPY
;
216 cfShellIDList
= RegisterClipboardFormatW(CFSTR_SHELLIDLIST
);
217 cfFileNameA
= RegisterClipboardFormatA(CFSTR_FILENAMEA
);
218 cfFileNameW
= RegisterClipboardFormatW(CFSTR_FILENAMEW
);
219 cfPreferredDropEffect
= RegisterClipboardFormatW(CFSTR_PREFERREDDROPEFFECTW
);
220 InitFormatEtc(pFormatEtc
[0], cfShellIDList
, TYMED_HGLOBAL
);
221 InitFormatEtc(pFormatEtc
[1], CF_HDROP
, TYMED_HGLOBAL
);
222 InitFormatEtc(pFormatEtc
[2], cfFileNameA
, TYMED_HGLOBAL
);
223 InitFormatEtc(pFormatEtc
[3], cfFileNameW
, TYMED_HGLOBAL
);
224 InitFormatEtc(pFormatEtc
[4], cfPreferredDropEffect
, TYMED_HGLOBAL
);
228 static HGLOBAL
RenderPREFEREDDROPEFFECT (DWORD dwFlags
)
233 TRACE("(0x%08x)\n", dwFlags
);
235 hGlobal
= GlobalAlloc(GHND
|GMEM_SHARE
, sizeof(DWORD
));
236 if(!hGlobal
) return hGlobal
;
237 pdwFlag
= (DWORD
*)GlobalLock(hGlobal
);
239 GlobalUnlock(hGlobal
);
243 /**************************************************************************
244 * IDataObject_fnGetData
246 HRESULT WINAPI
CIDLDataObj::GetData(LPFORMATETC pformatetcIn
, STGMEDIUM
*pmedium
)
251 GetClipboardFormatNameA (pformatetcIn
->cfFormat
, szTemp
, 256);
252 TRACE("(%p)->(%p %p format=%s)\n", this, pformatetcIn
, pmedium
, szTemp
);
254 if (pformatetcIn
->cfFormat
== cfShellIDList
)
256 if (cidl
< 1) return(E_UNEXPECTED
);
257 pmedium
->hGlobal
= RenderSHELLIDLIST(pidl
, apidl
, cidl
);
259 else if (pformatetcIn
->cfFormat
== CF_HDROP
)
261 if (cidl
< 1) return(E_UNEXPECTED
);
262 pmedium
->hGlobal
= RenderHDROP(pidl
, apidl
, cidl
);
264 else if (pformatetcIn
->cfFormat
== cfFileNameA
)
266 if (cidl
< 1) return(E_UNEXPECTED
);
267 pmedium
->hGlobal
= RenderFILENAMEA(pidl
, apidl
, cidl
);
269 else if (pformatetcIn
->cfFormat
== cfFileNameW
)
271 if (cidl
< 1) return(E_UNEXPECTED
);
272 pmedium
->hGlobal
= RenderFILENAMEW(pidl
, apidl
, cidl
);
274 else if (pformatetcIn
->cfFormat
== cfPreferredDropEffect
)
276 pmedium
->hGlobal
= RenderPREFEREDDROPEFFECT(dropeffect
);
280 FIXME("-- expected clipformat not implemented\n");
281 return (E_INVALIDARG
);
283 if (pmedium
->hGlobal
)
285 pmedium
->tymed
= TYMED_HGLOBAL
;
286 pmedium
->pUnkForRelease
= NULL
;
289 return E_OUTOFMEMORY
;
292 HRESULT WINAPI
CIDLDataObj::GetDataHere(LPFORMATETC pformatetc
, STGMEDIUM
*pmedium
)
294 FIXME("(%p)->()\n", this);
298 HRESULT WINAPI
CIDLDataObj::QueryGetData(LPFORMATETC pformatetc
)
302 TRACE("(%p)->(fmt=0x%08x tym=0x%08x)\n", this, pformatetc
->cfFormat
, pformatetc
->tymed
);
304 if(!(DVASPECT_CONTENT
& pformatetc
->dwAspect
))
305 return DV_E_DVASPECT
;
307 /* check our formats table what we have */
308 for (i
=0; i
<MAX_FORMATS
; i
++)
310 if ((pFormatEtc
[i
].cfFormat
== pformatetc
->cfFormat
)
311 && (pFormatEtc
[i
].tymed
== pformatetc
->tymed
))
320 HRESULT WINAPI
CIDLDataObj::GetCanonicalFormatEtc(LPFORMATETC pformatectIn
, LPFORMATETC pformatetcOut
)
322 FIXME("(%p)->()\n", this);
326 HRESULT WINAPI
CIDLDataObj::SetData(LPFORMATETC pformatetc
, STGMEDIUM
*pmedium
, BOOL fRelease
)
328 if (pformatetc
->cfFormat
== cfPreferredDropEffect
)
330 const DWORD
*src
= (const DWORD
*)GlobalLock(pmedium
->hGlobal
);
334 GlobalUnlock(pmedium
->hGlobal
);
337 FIXME("Error setting data");
341 FIXME("(%p)->()\n", this);
345 HRESULT WINAPI
CIDLDataObj::EnumFormatEtc(DWORD dwDirection
, IEnumFORMATETC
**ppenumFormatEtc
)
347 TRACE("(%p)->()\n", this);
348 *ppenumFormatEtc
= NULL
;
351 if (DATADIR_GET
== dwDirection
)
353 return IEnumFORMATETC_Constructor(MAX_FORMATS
, pFormatEtc
, ppenumFormatEtc
);
359 HRESULT WINAPI
CIDLDataObj::DAdvise(FORMATETC
*pformatetc
, DWORD advf
, IAdviseSink
*pAdvSink
, DWORD
*pdwConnection
)
361 FIXME("(%p)->()\n", this);
365 HRESULT WINAPI
CIDLDataObj::DUnadvise(DWORD dwConnection
)
367 FIXME("(%p)->()\n", this);
371 HRESULT WINAPI
CIDLDataObj::EnumDAdvise(IEnumSTATDATA
**ppenumAdvise
)
373 FIXME("(%p)->()\n", this);
377 HRESULT WINAPI
CIDLDataObj::GetAsyncMode(BOOL
*pfIsOpAsync
)
379 TRACE("(%p)->()\n", this);
380 *pfIsOpAsync
= doasync
;
383 HRESULT WINAPI
CIDLDataObj::InOperation(BOOL
*pfInAsyncOp
)
385 FIXME("(%p)->()\n", this);
388 HRESULT WINAPI
CIDLDataObj::SetAsyncMode(BOOL fDoOpAsync
)
390 TRACE("(%p)->()\n", this);
391 doasync
= fDoOpAsync
;
395 HRESULT WINAPI
CIDLDataObj::StartOperation(IBindCtx
*pbcReserved
)
397 FIXME("(%p)->()\n", this);
400 HRESULT WINAPI
CIDLDataObj::EndOperation(HRESULT hResult
, IBindCtx
*pbcReserved
, DWORD dwEffects
)
402 FIXME("(%p)->()\n", this);
408 /**************************************************************************
409 * IDataObject_Constructor
411 HRESULT
IDataObject_Constructor(HWND hwndOwner
, PCIDLIST_ABSOLUTE pMyPidl
, PCUIDLIST_RELATIVE_ARRAY apidl
, UINT cidl
, IDataObject
**dataObject
)
413 return ShellObjectCreatorInit
<CIDLDataObj
>(hwndOwner
, pMyPidl
, apidl
, cidl
, IID_PPV_ARG(IDataObject
, dataObject
));
416 /*************************************************************************
417 * SHCreateDataObject [SHELL32.@]
421 HRESULT WINAPI
SHCreateDataObject(PCIDLIST_ABSOLUTE pidlFolder
, UINT cidl
, PCUITEMID_CHILD_ARRAY apidl
, IDataObject
*pdtInner
, REFIID riid
, void **ppv
)
423 if (IsEqualIID(riid
, IID_IDataObject
))
425 return CIDLData_CreateFromIDArray(pidlFolder
, cidl
, apidl
, (IDataObject
**)ppv
);