3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4 * PURPOSE: IEnumFORMATETC, IDataObject implementation
5 * COPYRIGHT: Copyright 1998, 1999 <juergen.schmied@metronet.de>
6 * Copyright 2019 Mark Jansen (mark.jansen@reactos.org)
11 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
13 /***********************************************************************
14 * IEnumFORMATETC implementation
17 class IEnumFORMATETCImpl
:
18 public CComObjectRootEx
<CComMultiThreadModelNoCS
>,
27 ~IEnumFORMATETCImpl();
28 HRESULT WINAPI
Initialize(UINT cfmt
, const FORMATETC afmt
[]);
31 virtual HRESULT WINAPI
Next(ULONG celt
, FORMATETC
*rgelt
, ULONG
*pceltFethed
);
32 virtual HRESULT WINAPI
Skip(ULONG celt
);
33 virtual HRESULT WINAPI
Reset();
34 virtual HRESULT WINAPI
Clone(LPENUMFORMATETC
* ppenum
);
36 BEGIN_COM_MAP(IEnumFORMATETCImpl
)
37 COM_INTERFACE_ENTRY_IID(IID_IEnumFORMATETC
, IEnumFORMATETC
)
41 IEnumFORMATETCImpl::IEnumFORMATETCImpl()
48 IEnumFORMATETCImpl::~IEnumFORMATETCImpl()
52 HRESULT WINAPI
IEnumFORMATETCImpl::Initialize(UINT cfmt
, const FORMATETC afmt
[])
56 size
= cfmt
* sizeof(FORMATETC
);
58 pFmt
= (LPFORMATETC
)SHAlloc(size
);
62 memcpy(pFmt
, afmt
, size
);
66 HRESULT WINAPI
IEnumFORMATETCImpl::Next(ULONG celt
, FORMATETC
*rgelt
, ULONG
*pceltFethed
)
70 TRACE("(%p)->(%u,%p)\n", this, celt
, rgelt
);
79 for (i
= 0; posFmt
< countFmt
&& celt
> i
; i
++)
81 *rgelt
++ = pFmt
[posFmt
++];
87 return ((i
== celt
) ? S_OK
: S_FALSE
);
90 HRESULT WINAPI
IEnumFORMATETCImpl::Skip(ULONG celt
)
92 TRACE("(%p)->(num=%u)\n", this, celt
);
94 if (posFmt
+ celt
>= countFmt
)
100 HRESULT WINAPI
IEnumFORMATETCImpl::Reset()
102 TRACE("(%p)->()\n", this);
108 HRESULT WINAPI
IEnumFORMATETCImpl::Clone(LPENUMFORMATETC
* ppenum
)
112 TRACE("(%p)->(ppenum=%p)\n", this, ppenum
);
114 if (!ppenum
) return E_INVALIDARG
;
115 hResult
= IEnumFORMATETC_Constructor(countFmt
, pFmt
, ppenum
);
116 if (FAILED_UNEXPECTEDLY(hResult
))
118 return (*ppenum
)->Skip(posFmt
);
121 HRESULT
IEnumFORMATETC_Constructor(UINT cfmt
, const FORMATETC afmt
[], IEnumFORMATETC
**ppFormat
)
123 return ShellObjectCreatorInit
<IEnumFORMATETCImpl
>(cfmt
, afmt
, IID_PPV_ARG(IEnumFORMATETC
, ppFormat
));
127 /***********************************************************************
128 * IDataObject implementation
129 * For now (2019-10-12) it's compatible with 2k3's data object
130 * See shell32_apitest!CIDLData for changes between versions
134 public CComObjectRootEx
<CComMultiThreadModelNoCS
>,
136 public IAsyncOperation
139 CSimpleArray
<FORMATETC
> m_Formats
;
140 CSimpleArray
<STGMEDIUM
> m_Storage
;
141 UINT m_cfShellIDList
;
146 HRESULT WINAPI
Initialize(HWND hwndOwner
, PCIDLIST_ABSOLUTE pMyPidl
, PCUIDLIST_RELATIVE_ARRAY apidlx
, UINT cidlx
, BOOL bAddAdditionalFormats
);
148 // *** IDataObject methods ***
149 virtual HRESULT WINAPI
GetData(LPFORMATETC pformatetcIn
, STGMEDIUM
*pmedium
);
150 virtual HRESULT WINAPI
GetDataHere(LPFORMATETC pformatetc
, STGMEDIUM
*pmedium
);
151 virtual HRESULT WINAPI
QueryGetData(LPFORMATETC pformatetc
);
152 virtual HRESULT WINAPI
GetCanonicalFormatEtc(LPFORMATETC pformatectIn
, LPFORMATETC pformatetcOut
);
153 virtual HRESULT WINAPI
SetData(LPFORMATETC pformatetc
, STGMEDIUM
*pmedium
, BOOL fRelease
);
154 virtual HRESULT WINAPI
EnumFormatEtc(DWORD dwDirection
, IEnumFORMATETC
**ppenumFormatEtc
);
155 virtual HRESULT WINAPI
DAdvise(FORMATETC
*pformatetc
, DWORD advf
, IAdviseSink
*pAdvSink
, DWORD
*pdwConnection
);
156 virtual HRESULT WINAPI
DUnadvise(DWORD dwConnection
);
157 virtual HRESULT WINAPI
EnumDAdvise(IEnumSTATDATA
**ppenumAdvise
);
159 // *** IAsyncOperation methods ***
160 virtual HRESULT WINAPI
SetAsyncMode(BOOL fDoOpAsync
);
161 virtual HRESULT WINAPI
GetAsyncMode(BOOL
*pfIsOpAsync
);
162 virtual HRESULT WINAPI
StartOperation(IBindCtx
*pbcReserved
);
163 virtual HRESULT WINAPI
InOperation(BOOL
*pfInAsyncOp
);
164 virtual HRESULT WINAPI
EndOperation(HRESULT hResult
, IBindCtx
*pbcReserved
, DWORD dwEffects
);
166 BEGIN_COM_MAP(CIDLDataObj
)
167 COM_INTERFACE_ENTRY_IID(IID_IDataObject
, IDataObject
)
168 COM_INTERFACE_ENTRY_IID(IID_IAsyncOperation
, IAsyncOperation
)
172 CIDLDataObj::CIDLDataObj()
178 CIDLDataObj::~CIDLDataObj()
180 TRACE(" destroying IDataObject(%p)\n", this);
182 for (int n
= 0; n
< m_Storage
.GetSize(); ++n
)
184 ReleaseStgMedium(&m_Storage
[n
]);
186 m_Formats
.RemoveAll();
187 m_Storage
.RemoveAll();
190 HRESULT WINAPI
CIDLDataObj::Initialize(HWND hwndOwner
, PCIDLIST_ABSOLUTE pMyPidl
, PCUIDLIST_RELATIVE_ARRAY apidlx
, UINT cidlx
, BOOL bAddAdditionalFormats
)
192 HGLOBAL hida
= RenderSHELLIDLIST((LPITEMIDLIST
)pMyPidl
, (LPITEMIDLIST
*)apidlx
, cidlx
);
195 ERR("Failed to render " CFSTR_SHELLIDLISTA
"\n");
196 return E_OUTOFMEMORY
;
199 m_cfShellIDList
= RegisterClipboardFormatW(CFSTR_SHELLIDLIST
);
201 FORMATETC Format
= { (CLIPFORMAT
)m_cfShellIDList
, NULL
, DVASPECT_CONTENT
, -1, TYMED_HGLOBAL
};
202 STGMEDIUM medium
= {0};
203 medium
.tymed
= TYMED_HGLOBAL
;
204 medium
.hGlobal
= hida
;
205 HRESULT hr
= SetData(&Format
, &medium
, TRUE
);
206 if (!FAILED_UNEXPECTEDLY(hr
) && bAddAdditionalFormats
)
208 Format
.cfFormat
= CF_HDROP
;
209 medium
.hGlobal
= RenderHDROP((LPITEMIDLIST
)pMyPidl
, (LPITEMIDLIST
*)apidlx
, cidlx
);
210 hr
= SetData(&Format
, &medium
, TRUE
);
211 if (FAILED_UNEXPECTEDLY(hr
))
214 Format
.cfFormat
= RegisterClipboardFormatA(CFSTR_FILENAMEA
);
215 medium
.hGlobal
= RenderFILENAMEA((LPITEMIDLIST
)pMyPidl
, (LPITEMIDLIST
*)apidlx
, cidlx
);
216 hr
= SetData(&Format
, &medium
, TRUE
);
217 if (FAILED_UNEXPECTEDLY(hr
))
220 Format
.cfFormat
= RegisterClipboardFormatW(CFSTR_FILENAMEW
);
221 medium
.hGlobal
= RenderFILENAMEW((LPITEMIDLIST
)pMyPidl
, (LPITEMIDLIST
*)apidlx
, cidlx
);
222 hr
= SetData(&Format
, &medium
, TRUE
);
223 if (FAILED_UNEXPECTEDLY(hr
))
231 HRESULT WINAPI
CIDLDataObj::GetData(LPFORMATETC pformatetcIn
, STGMEDIUM
*pmedium
)
235 char szTemp
[256] = {0};
236 GetClipboardFormatNameA (pformatetcIn
->cfFormat
, szTemp
, 256);
237 TRACE("(%p)->(%p %p format=%s)\n", this, pformatetcIn
, pmedium
, szTemp
);
239 pmedium
->hGlobal
= NULL
;
240 pmedium
->pUnkForRelease
= NULL
;
241 for (int n
= 0; n
< m_Formats
.GetSize(); ++n
)
243 const FORMATETC
& fmt
= m_Formats
[n
];
244 if (fmt
.cfFormat
== pformatetcIn
->cfFormat
&&
245 fmt
.dwAspect
== pformatetcIn
->dwAspect
&&
246 fmt
.tymed
== pformatetcIn
->tymed
)
248 if (pformatetcIn
->tymed
!= TYMED_HGLOBAL
)
255 *pmedium
= m_Storage
[n
];
256 return QueryInterface(IID_PPV_ARG(IUnknown
, &pmedium
->pUnkForRelease
));
264 HRESULT WINAPI
CIDLDataObj::GetDataHere(LPFORMATETC pformatetc
, STGMEDIUM
*pmedium
)
266 FIXME("(%p)->()\n", this);
270 HRESULT WINAPI
CIDLDataObj::QueryGetData(LPFORMATETC pformatetc
)
272 TRACE("(%p)->(fmt=0x%08x tym=0x%08x)\n", this, pformatetc
->cfFormat
, pformatetc
->tymed
);
274 for (int n
= 0; n
< m_Formats
.GetSize(); ++n
)
276 const FORMATETC
& fmt
= m_Formats
[n
];
277 if (fmt
.cfFormat
== pformatetc
->cfFormat
&&
278 fmt
.dwAspect
== pformatetc
->dwAspect
&&
279 fmt
.tymed
== pformatetc
->tymed
)
288 HRESULT WINAPI
CIDLDataObj::GetCanonicalFormatEtc(LPFORMATETC pformatectIn
, LPFORMATETC pformatetcOut
)
290 //FIXME("(%p)->()\n", this);
291 return DATA_S_SAMEFORMATETC
;
294 HRESULT WINAPI
CIDLDataObj::SetData(LPFORMATETC pformatetc
, STGMEDIUM
*pmedium
, BOOL fRelease
)
299 for (int n
= 0; n
< m_Formats
.GetSize(); ++n
)
301 const FORMATETC
& fmt
= m_Formats
[n
];
302 if (fmt
.cfFormat
== pformatetc
->cfFormat
&&
303 fmt
.dwAspect
== pformatetc
->dwAspect
&&
304 fmt
.tymed
== pformatetc
->tymed
)
306 ReleaseStgMedium(&m_Storage
[n
]);
307 m_Storage
[n
] = *pmedium
;
312 m_Formats
.Add(*pformatetc
);
313 m_Storage
.Add(*pmedium
);
318 HRESULT WINAPI
CIDLDataObj::EnumFormatEtc(DWORD dwDirection
, IEnumFORMATETC
**ppenumFormatEtc
)
320 TRACE("(%p)->()\n", this);
321 *ppenumFormatEtc
= NULL
;
324 if (DATADIR_GET
== dwDirection
)
326 return IEnumFORMATETC_Constructor(m_Formats
.GetSize(), m_Formats
.GetData(), ppenumFormatEtc
);
332 HRESULT WINAPI
CIDLDataObj::DAdvise(FORMATETC
*pformatetc
, DWORD advf
, IAdviseSink
*pAdvSink
, DWORD
*pdwConnection
)
334 return OLE_E_ADVISENOTSUPPORTED
;
337 HRESULT WINAPI
CIDLDataObj::DUnadvise(DWORD dwConnection
)
339 return OLE_E_ADVISENOTSUPPORTED
;
342 HRESULT WINAPI
CIDLDataObj::EnumDAdvise(IEnumSTATDATA
**ppenumAdvise
)
344 return OLE_E_ADVISENOTSUPPORTED
;
347 HRESULT WINAPI
CIDLDataObj::GetAsyncMode(BOOL
*pfIsOpAsync
)
349 TRACE("(%p)->()\n", this);
350 *pfIsOpAsync
= m_doasync
;
353 HRESULT WINAPI
CIDLDataObj::InOperation(BOOL
*pfInAsyncOp
)
355 FIXME("(%p)->()\n", this);
358 HRESULT WINAPI
CIDLDataObj::SetAsyncMode(BOOL fDoOpAsync
)
360 TRACE("(%p)->()\n", this);
361 m_doasync
= fDoOpAsync
;
365 HRESULT WINAPI
CIDLDataObj::StartOperation(IBindCtx
*pbcReserved
)
367 TRACE("(%p)->()\n", this);
370 HRESULT WINAPI
CIDLDataObj::EndOperation(HRESULT hResult
, IBindCtx
*pbcReserved
, DWORD dwEffects
)
372 TRACE("(%p)->()\n", this);
378 /**************************************************************************
379 * IDataObject_Constructor
381 HRESULT
IDataObject_Constructor(HWND hwndOwner
, PCIDLIST_ABSOLUTE pMyPidl
, PCUIDLIST_RELATIVE_ARRAY apidl
, UINT cidl
, BOOL bExtendedObject
, IDataObject
**dataObject
)
385 return ShellObjectCreatorInit
<CIDLDataObj
>(hwndOwner
, pMyPidl
, apidl
, cidl
, bExtendedObject
, IID_PPV_ARG(IDataObject
, dataObject
));
388 /*************************************************************************
389 * SHCreateDataObject [SHELL32.@]
393 HRESULT WINAPI
SHCreateDataObject(PCIDLIST_ABSOLUTE pidlFolder
, UINT cidl
, PCUITEMID_CHILD_ARRAY apidl
, IDataObject
*pdtInner
, REFIID riid
, void **ppv
)
395 if (IsEqualIID(riid
, IID_IDataObject
))
399 return IDataObject_Constructor(NULL
, pidlFolder
, apidl
, cidl
, TRUE
, (IDataObject
**)ppv
);
404 /*************************************************************************
405 * SHCreateFileDataObject [SHELL32.740]
409 HRESULT WINAPI
SHCreateFileDataObject(PCIDLIST_ABSOLUTE pidlFolder
, UINT cidl
, PCUITEMID_CHILD_ARRAY apidl
, IDataObject
* pDataInner
, IDataObject
** ppDataObj
)
413 return IDataObject_Constructor(NULL
, pidlFolder
, apidl
, cidl
, TRUE
, ppDataObj
);