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 for (int n
= 0; n
< m_Formats
.GetSize(); ++n
)
241 const FORMATETC
& fmt
= m_Formats
[n
];
242 if (fmt
.cfFormat
== pformatetcIn
->cfFormat
&&
243 fmt
.dwAspect
== pformatetcIn
->dwAspect
&&
244 fmt
.tymed
== pformatetcIn
->tymed
)
246 if (pformatetcIn
->tymed
!= TYMED_HGLOBAL
)
253 *pmedium
= m_Storage
[n
];
254 return QueryInterface(IID_PPV_ARG(IUnknown
, &pmedium
->pUnkForRelease
));
262 HRESULT WINAPI
CIDLDataObj::GetDataHere(LPFORMATETC pformatetc
, STGMEDIUM
*pmedium
)
264 FIXME("(%p)->()\n", this);
268 HRESULT WINAPI
CIDLDataObj::QueryGetData(LPFORMATETC pformatetc
)
270 TRACE("(%p)->(fmt=0x%08x tym=0x%08x)\n", this, pformatetc
->cfFormat
, pformatetc
->tymed
);
272 for (int n
= 0; n
< m_Formats
.GetSize(); ++n
)
274 const FORMATETC
& fmt
= m_Formats
[n
];
275 if (fmt
.cfFormat
== pformatetc
->cfFormat
&&
276 fmt
.dwAspect
== pformatetc
->dwAspect
&&
277 fmt
.tymed
== pformatetc
->tymed
)
286 HRESULT WINAPI
CIDLDataObj::GetCanonicalFormatEtc(LPFORMATETC pformatectIn
, LPFORMATETC pformatetcOut
)
288 //FIXME("(%p)->()\n", this);
289 return DATA_S_SAMEFORMATETC
;
292 HRESULT WINAPI
CIDLDataObj::SetData(LPFORMATETC pformatetc
, STGMEDIUM
*pmedium
, BOOL fRelease
)
297 for (int n
= 0; n
< m_Formats
.GetSize(); ++n
)
299 const FORMATETC
& fmt
= m_Formats
[n
];
300 if (fmt
.cfFormat
== pformatetc
->cfFormat
&&
301 fmt
.dwAspect
== pformatetc
->dwAspect
&&
302 fmt
.tymed
== pformatetc
->tymed
)
304 ReleaseStgMedium(&m_Storage
[n
]);
305 m_Storage
[n
] = *pmedium
;
310 m_Formats
.Add(*pformatetc
);
311 m_Storage
.Add(*pmedium
);
316 HRESULT WINAPI
CIDLDataObj::EnumFormatEtc(DWORD dwDirection
, IEnumFORMATETC
**ppenumFormatEtc
)
318 TRACE("(%p)->()\n", this);
319 *ppenumFormatEtc
= NULL
;
322 if (DATADIR_GET
== dwDirection
)
324 return IEnumFORMATETC_Constructor(m_Formats
.GetSize(), m_Formats
.GetData(), ppenumFormatEtc
);
330 HRESULT WINAPI
CIDLDataObj::DAdvise(FORMATETC
*pformatetc
, DWORD advf
, IAdviseSink
*pAdvSink
, DWORD
*pdwConnection
)
332 return OLE_E_ADVISENOTSUPPORTED
;
335 HRESULT WINAPI
CIDLDataObj::DUnadvise(DWORD dwConnection
)
337 return OLE_E_ADVISENOTSUPPORTED
;
340 HRESULT WINAPI
CIDLDataObj::EnumDAdvise(IEnumSTATDATA
**ppenumAdvise
)
342 return OLE_E_ADVISENOTSUPPORTED
;
345 HRESULT WINAPI
CIDLDataObj::GetAsyncMode(BOOL
*pfIsOpAsync
)
347 TRACE("(%p)->()\n", this);
348 *pfIsOpAsync
= m_doasync
;
351 HRESULT WINAPI
CIDLDataObj::InOperation(BOOL
*pfInAsyncOp
)
353 FIXME("(%p)->()\n", this);
356 HRESULT WINAPI
CIDLDataObj::SetAsyncMode(BOOL fDoOpAsync
)
358 TRACE("(%p)->()\n", this);
359 m_doasync
= fDoOpAsync
;
363 HRESULT WINAPI
CIDLDataObj::StartOperation(IBindCtx
*pbcReserved
)
365 TRACE("(%p)->()\n", this);
368 HRESULT WINAPI
CIDLDataObj::EndOperation(HRESULT hResult
, IBindCtx
*pbcReserved
, DWORD dwEffects
)
370 TRACE("(%p)->()\n", this);
376 /**************************************************************************
377 * IDataObject_Constructor
379 HRESULT
IDataObject_Constructor(HWND hwndOwner
, PCIDLIST_ABSOLUTE pMyPidl
, PCUIDLIST_RELATIVE_ARRAY apidl
, UINT cidl
, BOOL bExtendedObject
, IDataObject
**dataObject
)
383 return ShellObjectCreatorInit
<CIDLDataObj
>(hwndOwner
, pMyPidl
, apidl
, cidl
, bExtendedObject
, IID_PPV_ARG(IDataObject
, dataObject
));
386 /*************************************************************************
387 * SHCreateDataObject [SHELL32.@]
391 HRESULT WINAPI
SHCreateDataObject(PCIDLIST_ABSOLUTE pidlFolder
, UINT cidl
, PCUITEMID_CHILD_ARRAY apidl
, IDataObject
*pdtInner
, REFIID riid
, void **ppv
)
393 if (IsEqualIID(riid
, IID_IDataObject
))
397 return IDataObject_Constructor(NULL
, pidlFolder
, apidl
, cidl
, TRUE
, (IDataObject
**)ppv
);