ReactOS 0.4.15-dev-8241-g63935f8
CIDLDataObj.cpp
Go to the documentation of this file.
1/*
2 * PROJECT: shell32
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)
7 */
8
9#include "precomp.h"
10
12
13/***********************************************************************
14* IEnumFORMATETC implementation
15*/
16
18 public CComObjectRootEx<CComMultiThreadModelNoCS>,
19 public IEnumFORMATETC
20{
21private:
25public:
28 HRESULT WINAPI Initialize(UINT cfmt, const FORMATETC afmt[]);
29
30 // *****************
31 STDMETHOD(Next)(ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed) override;
32 STDMETHOD(Skip)(ULONG celt) override;
33 STDMETHOD(Reset)() override;
34 STDMETHOD(Clone)(LPENUMFORMATETC* ppenum) override;
35
39};
40
42{
43 posFmt = 0;
44 countFmt = 0;
45 pFmt = NULL;
46}
47
49{
50}
51
53{
54 DWORD size;
55
56 size = cfmt * sizeof(FORMATETC);
57 countFmt = cfmt;
59 if (pFmt == NULL)
60 return E_OUTOFMEMORY;
61
62 memcpy(pFmt, afmt, size);
63 return S_OK;
64}
65
67{
68 UINT i;
69
70 TRACE("(%p)->(%u,%p)\n", this, celt, rgelt);
71
72 if (!pFmt)
73 return S_FALSE;
74 if (!rgelt)
75 return E_INVALIDARG;
76 if (pceltFethed)
77 *pceltFethed = 0;
78
79 for (i = 0; posFmt < countFmt && celt > i; i++)
80 {
81 *rgelt++ = pFmt[posFmt++];
82 }
83
84 if (pceltFethed)
85 *pceltFethed = i;
86
87 return ((i == celt) ? S_OK : S_FALSE);
88}
89
91{
92 TRACE("(%p)->(num=%u)\n", this, celt);
93
94 if (posFmt + celt >= countFmt)
95 return S_FALSE;
96 posFmt += celt;
97 return S_OK;
98}
99
101{
102 TRACE("(%p)->()\n", this);
103
104 posFmt = 0;
105 return S_OK;
106}
107
109{
110 HRESULT hResult;
111
112 TRACE("(%p)->(ppenum=%p)\n", this, ppenum);
113
114 if (!ppenum) return E_INVALIDARG;
115 hResult = IEnumFORMATETC_Constructor(countFmt, pFmt, ppenum);
116 if (FAILED_UNEXPECTEDLY(hResult))
117 return hResult;
118 return (*ppenum)->Skip(posFmt);
119}
120
121HRESULT IEnumFORMATETC_Constructor(UINT cfmt, const FORMATETC afmt[], IEnumFORMATETC **ppFormat)
122{
123 return ShellObjectCreatorInit<IEnumFORMATETCImpl>(cfmt, afmt, IID_PPV_ARG(IEnumFORMATETC, ppFormat));
124}
125
126
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
131*/
132
134 public CComObjectRootEx<CComMultiThreadModelNoCS>,
135 public IDataObject,
136 public IAsyncOperation
137{
138private:
144public:
145 CIDLDataObj();
146 ~CIDLDataObj();
147 HRESULT WINAPI Initialize(HWND hwndOwner, PCIDLIST_ABSOLUTE pMyPidl, PCUIDLIST_RELATIVE_ARRAY apidlx, UINT cidlx, BOOL bAddAdditionalFormats);
148
149 // *** IDataObject methods ***
150 STDMETHOD(GetData)(LPFORMATETC pformatetcIn, STGMEDIUM *pmedium) override;
151 STDMETHOD(GetDataHere)(LPFORMATETC pformatetc, STGMEDIUM *pmedium) override;
152 STDMETHOD(QueryGetData)(LPFORMATETC pformatetc) override;
153 STDMETHOD(GetCanonicalFormatEtc)(LPFORMATETC pformatectIn, LPFORMATETC pformatetcOut) override;
154 STDMETHOD(SetData)(LPFORMATETC pformatetc, STGMEDIUM *pmedium, BOOL fRelease) override;
155 STDMETHOD(EnumFormatEtc)(DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc) override;
156 STDMETHOD(DAdvise)(FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection) override;
157 STDMETHOD(DUnadvise)(DWORD dwConnection) override;
158 STDMETHOD(EnumDAdvise)(IEnumSTATDATA **ppenumAdvise) override;
159
160 // *** IAsyncOperation methods ***
161 STDMETHOD(SetAsyncMode)(BOOL fDoOpAsync) override;
162 STDMETHOD(GetAsyncMode)(BOOL *pfIsOpAsync) override;
163 STDMETHOD(StartOperation)(IBindCtx *pbcReserved) override;
164 STDMETHOD(InOperation)(BOOL *pfInAsyncOp) override;
165 STDMETHOD(EndOperation)(HRESULT hResult, IBindCtx *pbcReserved, DWORD dwEffects) override;
166
169 COM_INTERFACE_ENTRY_IID(IID_IAsyncOperation, IAsyncOperation)
171};
172
174{
175 m_cfShellIDList = 0;
177 m_FailGetHDrop = false;
178}
179
181{
182 TRACE(" destroying IDataObject(%p)\n", this);
183
184 for (int n = 0; n < m_Storage.GetSize(); ++n)
185 {
187 }
190}
191
192HRESULT WINAPI CIDLDataObj::Initialize(HWND hwndOwner, PCIDLIST_ABSOLUTE pMyPidl, PCUIDLIST_RELATIVE_ARRAY apidlx, UINT cidlx, BOOL bAddAdditionalFormats)
193{
194 HGLOBAL hida = RenderSHELLIDLIST((LPITEMIDLIST)pMyPidl, (LPITEMIDLIST*)apidlx, cidlx);
195 if (!hida)
196 {
197 ERR("Failed to render " CFSTR_SHELLIDLISTA "\n");
198 return E_OUTOFMEMORY;
199 }
200
202
203 FORMATETC Format = { (CLIPFORMAT)m_cfShellIDList, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
204 STGMEDIUM medium = {0};
205 medium.tymed = TYMED_HGLOBAL;
206 medium.hGlobal = hida;
207 HRESULT hr = SetData(&Format, &medium, TRUE);
208 if (!FAILED_UNEXPECTEDLY(hr) && bAddAdditionalFormats)
209 {
210 /* The Windows default shell IDataObject::GetData fails with DV_E_CLIPFORMAT if the desktop is present.
211 * Windows does return HDROP in EnumFormatEtc and does not fail until GetData is called.
212 * Failing GetData causes 7-Zip 23.01 to not add its menu to the desktop folder. */
213 for (UINT i = 0; i < cidlx; ++i)
214 {
215 if (ILIsEmpty(apidlx[i]) && ILIsEmpty(pMyPidl))
216 m_FailGetHDrop = true;
217 }
218
219 Format.cfFormat = CF_HDROP;
220 medium.hGlobal = RenderHDROP((LPITEMIDLIST)pMyPidl, (LPITEMIDLIST*)apidlx, cidlx);
221 hr = SetData(&Format, &medium, TRUE);
223 return hr;
224
226 medium.hGlobal = RenderFILENAMEA((LPITEMIDLIST)pMyPidl, (LPITEMIDLIST*)apidlx, cidlx);
227 hr = SetData(&Format, &medium, TRUE);
229 return hr;
230
232 medium.hGlobal = RenderFILENAMEW((LPITEMIDLIST)pMyPidl, (LPITEMIDLIST*)apidlx, cidlx);
233 hr = SetData(&Format, &medium, TRUE);
235 return hr;
236 }
237
238 return hr;
239}
240
241
242HRESULT WINAPI CIDLDataObj::GetData(LPFORMATETC pformatetcIn, STGMEDIUM *pmedium)
243{
244 if (TRACE_ON(shell))
245 {
246 char szTemp[256] = {0};
247 GetClipboardFormatNameA (pformatetcIn->cfFormat, szTemp, 256);
248 TRACE("(%p)->(%p %p format=%s)\n", this, pformatetcIn, pmedium, szTemp);
249 }
250 pmedium->hGlobal = NULL;
251 pmedium->pUnkForRelease = NULL;
252 for (int n = 0; n < m_Formats.GetSize(); ++n)
253 {
254 const FORMATETC& fmt = m_Formats[n];
255 if (fmt.cfFormat == pformatetcIn->cfFormat &&
256 fmt.dwAspect == pformatetcIn->dwAspect &&
257 fmt.tymed == pformatetcIn->tymed)
258 {
259 if (m_FailGetHDrop && fmt.cfFormat == CF_HDROP)
260 return DV_E_CLIPFORMAT;
261
262 if (pformatetcIn->tymed != TYMED_HGLOBAL)
263 {
265 return E_INVALIDARG;
266 }
267 else
268 {
269 *pmedium = m_Storage[n];
270 return QueryInterface(IID_PPV_ARG(IUnknown, &pmedium->pUnkForRelease));
271 }
272 }
273 }
274
275 return E_INVALIDARG;
276}
277
278HRESULT WINAPI CIDLDataObj::GetDataHere(LPFORMATETC pformatetc, STGMEDIUM *pmedium)
279{
280 FIXME("(%p)->()\n", this);
281 return E_NOTIMPL;
282}
283
285{
286 TRACE("(%p)->(fmt=0x%08x tym=0x%08x)\n", this, pformatetc->cfFormat, pformatetc->tymed);
287
288 for (int n = 0; n < m_Formats.GetSize(); ++n)
289 {
290 const FORMATETC& fmt = m_Formats[n];
291 if (fmt.cfFormat == pformatetc->cfFormat &&
292 fmt.dwAspect == pformatetc->dwAspect &&
293 fmt.tymed == pformatetc->tymed)
294 {
295 return S_OK;
296 }
297 }
298
299 return S_FALSE;
300}
301
302HRESULT WINAPI CIDLDataObj::GetCanonicalFormatEtc(LPFORMATETC pformatectIn, LPFORMATETC pformatetcOut)
303{
304 //FIXME("(%p)->()\n", this);
306}
307
308HRESULT WINAPI CIDLDataObj::SetData(LPFORMATETC pformatetc, STGMEDIUM *pmedium, BOOL fRelease)
309{
310 if (!fRelease)
311 return E_INVALIDARG;
312
313 for (int n = 0; n < m_Formats.GetSize(); ++n)
314 {
315 const FORMATETC& fmt = m_Formats[n];
316 if (fmt.cfFormat == pformatetc->cfFormat &&
317 fmt.dwAspect == pformatetc->dwAspect &&
318 fmt.tymed == pformatetc->tymed)
319 {
321 m_Storage[n] = *pmedium;
322 return S_OK;
323 }
324 }
325
326 m_Formats.Add(*pformatetc);
327 m_Storage.Add(*pmedium);
328
329 return S_OK;
330}
331
333{
334 TRACE("(%p)->()\n", this);
335 *ppenumFormatEtc = NULL;
336
337 /* only get data */
338 if (DATADIR_GET == dwDirection)
339 {
340 return IEnumFORMATETC_Constructor(m_Formats.GetSize(), m_Formats.GetData(), ppenumFormatEtc);
341 }
342
343 return E_NOTIMPL;
344}
345
346HRESULT WINAPI CIDLDataObj::DAdvise(FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection)
347{
349}
350
352{
354}
355
357{
359}
360
362{
363 TRACE("(%p)->()\n", this);
364 *pfIsOpAsync = m_doasync;
365 return S_OK;
366}
368{
369 FIXME("(%p)->()\n", this);
370 return E_NOTIMPL;
371}
373{
374 TRACE("(%p)->()\n", this);
375 m_doasync = fDoOpAsync;
376 return S_OK;
377}
378
380{
381 TRACE("(%p)->()\n", this);
382 return E_NOTIMPL;
383}
385{
386 TRACE("(%p)->()\n", this);
387 return E_NOTIMPL;
388}
389
390
391
392/**************************************************************************
393 * IDataObject_Constructor
394 */
395HRESULT IDataObject_Constructor(HWND hwndOwner, PCIDLIST_ABSOLUTE pMyPidl, PCUIDLIST_RELATIVE_ARRAY apidl, UINT cidl, BOOL bExtendedObject, IDataObject **dataObject)
396{
397 if (!dataObject)
398 return E_INVALIDARG;
399 return ShellObjectCreatorInit<CIDLDataObj>(hwndOwner, pMyPidl, apidl, cidl, bExtendedObject, IID_PPV_ARG(IDataObject, dataObject));
400}
401
402/*************************************************************************
403 * SHCreateDataObject [SHELL32.@]
404 *
405 */
406
408{
410 {
411 if (pdtInner)
413 return IDataObject_Constructor(NULL, pidlFolder, apidl, cidl, TRUE, (IDataObject **)ppv);
414 }
415 return E_FAIL;
416}
417
418/*************************************************************************
419 * SHCreateFileDataObject [SHELL32.740]
420 *
421 */
422
424{
425 if (pDataInner)
427 return IDataObject_Constructor(NULL, pidlFolder, apidl, cidl, TRUE, ppDataObj);
428}
HRESULT IDataObject_Constructor(HWND hwndOwner, PCIDLIST_ABSOLUTE pMyPidl, PCUIDLIST_RELATIVE_ARRAY apidl, UINT cidl, BOOL bExtendedObject, IDataObject **dataObject)
HRESULT IEnumFORMATETC_Constructor(UINT cfmt, const FORMATETC afmt[], IEnumFORMATETC **ppFormat)
HRESULT WINAPI SHCreateDataObject(PCIDLIST_ABSOLUTE pidlFolder, UINT cidl, PCUITEMID_CHILD_ARRAY apidl, IDataObject *pdtInner, REFIID riid, void **ppv)
HRESULT WINAPI SHCreateFileDataObject(PCIDLIST_ABSOLUTE pidlFolder, UINT cidl, PCUITEMID_CHILD_ARRAY apidl, IDataObject *pDataInner, IDataObject **ppDataObj)
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define CF_HDROP
Definition: constants.h:410
void shell(int argc, const char *argv[])
Definition: cmds.c:1231
#define STDMETHOD(m)
Definition: basetyps.h:62
#define FIXME(fmt,...)
Definition: debug.h:114
#define UNIMPLEMENTED
Definition: debug.h:118
#define ERR(fmt,...)
Definition: debug.h:113
int GetSize() const
Definition: atlsimpcoll.h:104
BOOL Add(const T &t)
Definition: atlsimpcoll.h:58
STDMETHOD() SetAsyncMode(BOOL fDoOpAsync) override
STDMETHOD() SetData(LPFORMATETC pformatetc, STGMEDIUM *pmedium, BOOL fRelease) override
bool m_FailGetHDrop
UINT m_cfShellIDList
STDMETHOD() GetData(LPFORMATETC pformatetcIn, STGMEDIUM *pmedium) override
STDMETHOD() GetCanonicalFormatEtc(LPFORMATETC pformatectIn, LPFORMATETC pformatetcOut) override
STDMETHOD() DAdvise(FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection) override
STDMETHOD() EnumDAdvise(IEnumSTATDATA **ppenumAdvise) override
STDMETHOD() GetAsyncMode(BOOL *pfIsOpAsync) override
STDMETHOD() EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc) override
CSimpleArray< STGMEDIUM > m_Storage
STDMETHOD() EndOperation(HRESULT hResult, IBindCtx *pbcReserved, DWORD dwEffects) override
HRESULT WINAPI Initialize(HWND hwndOwner, PCIDLIST_ABSOLUTE pMyPidl, PCUIDLIST_RELATIVE_ARRAY apidlx, UINT cidlx, BOOL bAddAdditionalFormats)
STDMETHOD() DUnadvise(DWORD dwConnection) override
STDMETHOD() StartOperation(IBindCtx *pbcReserved) override
CSimpleArray< FORMATETC > m_Formats
STDMETHOD() GetDataHere(LPFORMATETC pformatetc, STGMEDIUM *pmedium) override
STDMETHOD() QueryGetData(LPFORMATETC pformatetc) override
STDMETHOD() InOperation(BOOL *pfInAsyncOp) override
HRESULT WINAPI Initialize(UINT cfmt, const FORMATETC afmt[])
Definition: CIDLDataObj.cpp:52
LPFORMATETC pFmt
Definition: CIDLDataObj.cpp:24
STDMETHOD() Reset() override
STDMETHOD() Clone(LPENUMFORMATETC *ppenum) override
STDMETHOD() Next(ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed) override
Definition: CIDLDataObj.cpp:66
STDMETHOD() Skip(ULONG celt) override
Definition: CIDLDataObj.cpp:90
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_INVALIDARG
Definition: ddrawi.h:101
#define E_NOTIMPL
Definition: ddrawi.h:99
#define E_FAIL
Definition: ddrawi.h:102
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define TRACE_ON(x)
Definition: compat.h:75
#define FAILED_UNEXPECTEDLY(hr)
Definition: precomp.h:121
void WINAPI ReleaseStgMedium(STGMEDIUM *pmedium)
Definition: ole2.c:2033
HGLOBAL RenderSHELLIDLIST(LPITEMIDLIST pidlRoot, LPITEMIDLIST *apidl, UINT cidl)
Definition: clipboard.c:148
HGLOBAL RenderHDROP(LPITEMIDLIST pidlRoot, LPITEMIDLIST *apidl, UINT cidl)
Definition: clipboard.c:56
HGLOBAL RenderFILENAMEW(LPITEMIDLIST pidlRoot, LPITEMIDLIST *apidl, UINT cidl)
Definition: clipboard.c:222
HGLOBAL RenderFILENAMEA(LPITEMIDLIST pidlRoot, LPITEMIDLIST *apidl, UINT cidl)
Definition: clipboard.c:190
LPVOID WINAPI SHAlloc(SIZE_T len)
Definition: shellole.c:304
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLsizeiptr size
Definition: glext.h:5919
GLdouble n
Definition: glext.h:7729
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
REFIID riid
Definition: atlbase.h:39
REFIID LPVOID * ppv
Definition: atlbase.h:39
struct IEnumFORMATETC::tagFORMATETC * LPFORMATETC
struct IEnumFORMATETC::tagFORMATETC FORMATETC
HRESULT QueryInterface([in] REFIID riid, [out, iid_is(riid)] void **ppvObject)
#define S_OK
Definition: intsafe.h:52
#define BEGIN_COM_MAP(x)
Definition: atlcom.h:581
#define COM_INTERFACE_ENTRY_IID(iid, x)
Definition: atlcom.h:601
#define END_COM_MAP()
Definition: atlcom.h:592
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
unsigned int UINT
Definition: ndis.h:50
const GUID IID_IEnumFORMATETC
const GUID IID_IDataObject
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
#define REFIID
Definition: guiddef.h:118
HRESULT hr
Definition: shlfolder.c:183
#define CFSTR_SHELLIDLIST
Definition: shlobj.h:550
#define CFSTR_SHELLIDLISTA
Definition: shlobj.h:418
#define CFSTR_FILENAMEA
Definition: shlobj.h:425
static const WCHAR CFSTR_FILENAMEW[]
Definition: shlobj.h:516
static BOOL ILIsEmpty(_In_opt_ PCUIDLIST_RELATIVE pidl)
Definition: shlobj.h:2512
ITEMIDLIST UNALIGNED * LPITEMIDLIST
Definition: shtypes.idl:41
const PCUITEMID_CHILD * PCUITEMID_CHILD_ARRAY
Definition: shtypes.idl:71
const PCUIDLIST_RELATIVE * PCUIDLIST_RELATIVE_ARRAY
Definition: shtypes.idl:58
#define TRACE(s)
Definition: solgame.cpp:4
Definition: dsound.c:943
uint32_t ULONG
Definition: typedefs.h:59
#define WINAPI
Definition: msvc.h:6
#define S_FALSE
Definition: winerror.h:2357
#define DV_E_CLIPFORMAT
Definition: winerror.h:2639
#define OLE_E_ADVISENOTSUPPORTED
Definition: winerror.h:2617
#define DATA_S_SAMEFORMATETC
Definition: winerror.h:2674
int WINAPI GetClipboardFormatNameA(_In_ UINT format, _Out_writes_(cchMaxCount) LPSTR lpszFormatName, _In_ int cchMaxCount)
UINT WINAPI RegisterClipboardFormatW(_In_ LPCWSTR)
UINT WINAPI RegisterClipboardFormatA(_In_ LPCSTR)
static void Initialize()
Definition: xlate.c:212
#define IID_PPV_ARG(Itype, ppType)