ReactOS  0.4.15-dev-1152-g6c94e4f
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 {
21 private:
25 public:
28  HRESULT WINAPI Initialize(UINT cfmt, const FORMATETC afmt[]);
29 
30  // *****************
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);
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 
121 HRESULT 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 
133 class CIDLDataObj :
134  public CComObjectRootEx<CComMultiThreadModelNoCS>,
135  public IDataObject,
136  public IAsyncOperation
137 {
138 private:
143 public:
144  CIDLDataObj();
145  ~CIDLDataObj();
146  HRESULT WINAPI Initialize(HWND hwndOwner, PCIDLIST_ABSOLUTE pMyPidl, PCUIDLIST_RELATIVE_ARRAY apidlx, UINT cidlx, BOOL bAddAdditionalFormats);
147 
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);
158 
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);
165 
168  COM_INTERFACE_ENTRY_IID(IID_IAsyncOperation, IAsyncOperation)
169 END_COM_MAP()
170 };
171 
173 {
174  m_cfShellIDList = 0;
175  m_doasync = FALSE;
176 }
177 
179 {
180  TRACE(" destroying IDataObject(%p)\n", this);
181 
182  for (int n = 0; n < m_Storage.GetSize(); ++n)
183  {
185  }
188 }
189 
190 HRESULT WINAPI CIDLDataObj::Initialize(HWND hwndOwner, PCIDLIST_ABSOLUTE pMyPidl, PCUIDLIST_RELATIVE_ARRAY apidlx, UINT cidlx, BOOL bAddAdditionalFormats)
191 {
192  HGLOBAL hida = RenderSHELLIDLIST((LPITEMIDLIST)pMyPidl, (LPITEMIDLIST*)apidlx, cidlx);
193  if (!hida)
194  {
195  ERR("Failed to render " CFSTR_SHELLIDLISTA "\n");
196  return E_OUTOFMEMORY;
197  }
198 
200 
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)
207  {
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))
212  return hr;
213 
215  medium.hGlobal = RenderFILENAMEA((LPITEMIDLIST)pMyPidl, (LPITEMIDLIST*)apidlx, cidlx);
216  hr = SetData(&Format, &medium, TRUE);
217  if (FAILED_UNEXPECTEDLY(hr))
218  return hr;
219 
221  medium.hGlobal = RenderFILENAMEW((LPITEMIDLIST)pMyPidl, (LPITEMIDLIST*)apidlx, cidlx);
222  hr = SetData(&Format, &medium, TRUE);
223  if (FAILED_UNEXPECTEDLY(hr))
224  return hr;
225  }
226 
227  return hr;
228 }
229 
230 
231 HRESULT WINAPI CIDLDataObj::GetData(LPFORMATETC pformatetcIn, STGMEDIUM *pmedium)
232 {
233  if (TRACE_ON(shell))
234  {
235  char szTemp[256] = {0};
236  GetClipboardFormatNameA (pformatetcIn->cfFormat, szTemp, 256);
237  TRACE("(%p)->(%p %p format=%s)\n", this, pformatetcIn, pmedium, szTemp);
238  }
239  pmedium->hGlobal = NULL;
240  pmedium->pUnkForRelease = NULL;
241  for (int n = 0; n < m_Formats.GetSize(); ++n)
242  {
243  const FORMATETC& fmt = m_Formats[n];
244  if (fmt.cfFormat == pformatetcIn->cfFormat &&
245  fmt.dwAspect == pformatetcIn->dwAspect &&
246  fmt.tymed == pformatetcIn->tymed)
247  {
248  if (pformatetcIn->tymed != TYMED_HGLOBAL)
249  {
251  return E_INVALIDARG;
252  }
253  else
254  {
255  *pmedium = m_Storage[n];
256  return QueryInterface(IID_PPV_ARG(IUnknown, &pmedium->pUnkForRelease));
257  }
258  }
259  }
260 
261  return E_INVALIDARG;
262 }
263 
264 HRESULT WINAPI CIDLDataObj::GetDataHere(LPFORMATETC pformatetc, STGMEDIUM *pmedium)
265 {
266  FIXME("(%p)->()\n", this);
267  return E_NOTIMPL;
268 }
269 
270 HRESULT WINAPI CIDLDataObj::QueryGetData(LPFORMATETC pformatetc)
271 {
272  TRACE("(%p)->(fmt=0x%08x tym=0x%08x)\n", this, pformatetc->cfFormat, pformatetc->tymed);
273 
274  for (int n = 0; n < m_Formats.GetSize(); ++n)
275  {
276  const FORMATETC& fmt = m_Formats[n];
277  if (fmt.cfFormat == pformatetc->cfFormat &&
278  fmt.dwAspect == pformatetc->dwAspect &&
279  fmt.tymed == pformatetc->tymed)
280  {
281  return S_OK;
282  }
283  }
284 
285  return S_FALSE;
286 }
287 
288 HRESULT WINAPI CIDLDataObj::GetCanonicalFormatEtc(LPFORMATETC pformatectIn, LPFORMATETC pformatetcOut)
289 {
290  //FIXME("(%p)->()\n", this);
291  return DATA_S_SAMEFORMATETC;
292 }
293 
294 HRESULT WINAPI CIDLDataObj::SetData(LPFORMATETC pformatetc, STGMEDIUM *pmedium, BOOL fRelease)
295 {
296  if (!fRelease)
297  return E_INVALIDARG;
298 
299  for (int n = 0; n < m_Formats.GetSize(); ++n)
300  {
301  const FORMATETC& fmt = m_Formats[n];
302  if (fmt.cfFormat == pformatetc->cfFormat &&
303  fmt.dwAspect == pformatetc->dwAspect &&
304  fmt.tymed == pformatetc->tymed)
305  {
307  m_Storage[n] = *pmedium;
308  return S_OK;
309  }
310  }
311 
312  m_Formats.Add(*pformatetc);
313  m_Storage.Add(*pmedium);
314 
315  return S_OK;
316 }
317 
319 {
320  TRACE("(%p)->()\n", this);
321  *ppenumFormatEtc = NULL;
322 
323  /* only get data */
324  if (DATADIR_GET == dwDirection)
325  {
326  return IEnumFORMATETC_Constructor(m_Formats.GetSize(), m_Formats.GetData(), ppenumFormatEtc);
327  }
328 
329  return E_NOTIMPL;
330 }
331 
332 HRESULT WINAPI CIDLDataObj::DAdvise(FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection)
333 {
335 }
336 
338 {
340 }
341 
343 {
345 }
346 
348 {
349  TRACE("(%p)->()\n", this);
350  *pfIsOpAsync = m_doasync;
351  return S_OK;
352 }
354 {
355  FIXME("(%p)->()\n", this);
356  return E_NOTIMPL;
357 }
359 {
360  TRACE("(%p)->()\n", this);
361  m_doasync = fDoOpAsync;
362  return S_OK;
363 }
364 
366 {
367  TRACE("(%p)->()\n", this);
368  return E_NOTIMPL;
369 }
371 {
372  TRACE("(%p)->()\n", this);
373  return E_NOTIMPL;
374 }
375 
376 
377 
378 /**************************************************************************
379  * IDataObject_Constructor
380  */
381 HRESULT IDataObject_Constructor(HWND hwndOwner, PCIDLIST_ABSOLUTE pMyPidl, PCUIDLIST_RELATIVE_ARRAY apidl, UINT cidl, BOOL bExtendedObject, IDataObject **dataObject)
382 {
383  if (!dataObject)
384  return E_INVALIDARG;
385  return ShellObjectCreatorInit<CIDLDataObj>(hwndOwner, pMyPidl, apidl, cidl, bExtendedObject, IID_PPV_ARG(IDataObject, dataObject));
386 }
387 
388 /*************************************************************************
389  * SHCreateDataObject [SHELL32.@]
390  *
391  */
392 
394 {
396  {
397  if (pdtInner)
399  return IDataObject_Constructor(NULL, pidlFolder, apidl, cidl, TRUE, (IDataObject **)ppv);
400  }
401  return E_FAIL;
402 }
virtual HRESULT WINAPI SetData(LPFORMATETC pformatetc, STGMEDIUM *pmedium, BOOL fRelease)
virtual HRESULT WINAPI SetAsyncMode(BOOL fDoOpAsync)
HGLOBAL RenderHDROP(LPITEMIDLIST pidlRoot, LPITEMIDLIST *apidl, UINT cidl)
Definition: clipboard.c:54
const PCUIDLIST_RELATIVE * PCUIDLIST_RELATIVE_ARRAY
Definition: shtypes.idl:58
UINT m_cfShellIDList
#define REFIID
Definition: guiddef.h:118
BOOL Add(const T &t)
Definition: atlsimpcoll.h:58
#define CFSTR_SHELLIDLIST
Definition: shlobj.h:477
HRESULT hr
Definition: shlfolder.c:183
#define DATA_S_SAMEFORMATETC
Definition: winerror.h:2674
HRESULT WINAPI SHCreateDataObject(PCIDLIST_ABSOLUTE pidlFolder, UINT cidl, PCUITEMID_CHILD_ARRAY apidl, IDataObject *pdtInner, REFIID riid, void **ppv)
void WINAPI ReleaseStgMedium(STGMEDIUM *pmedium)
Definition: ole2.c:2033
#define TRUE
Definition: types.h:120
REFIID riid
Definition: precomp.h:44
UINT WINAPI RegisterClipboardFormatW(_In_ LPCWSTR)
virtual HRESULT WINAPI QueryGetData(LPFORMATETC pformatetc)
virtual HRESULT WINAPI GetAsyncMode(BOOL *pfIsOpAsync)
REFIID LPVOID * ppv
Definition: atlbase.h:39
GLdouble n
Definition: glext.h:7729
CSimpleArray< FORMATETC > m_Formats
virtual HRESULT WINAPI InOperation(BOOL *pfInAsyncOp)
const GUID IID_IDataObject
#define IID_PPV_ARG(Itype, ppType)
#define E_FAIL
Definition: ddrawi.h:102
int GetSize() const
Definition: atlsimpcoll.h:104
virtual HRESULT WINAPI EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc)
HRESULT IEnumFORMATETC_Constructor(UINT cfmt, const FORMATETC afmt[], IEnumFORMATETC **ppFormat)
virtual HRESULT WINAPI GetCanonicalFormatEtc(LPFORMATETC pformatectIn, LPFORMATETC pformatetcOut)
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
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define FALSE
Definition: types.h:117
const PCUITEMID_CHILD * PCUITEMID_CHILD_ARRAY
Definition: shtypes.idl:71
unsigned int BOOL
Definition: ntddk_ex.h:94
virtual HRESULT WINAPI Next(ULONG celt, FORMATETC *rgelt, ULONG *pceltFethed)
Definition: CIDLDataObj.cpp:66
#define FIXME(fmt,...)
Definition: debug.h:111
#define S_FALSE
Definition: winerror.h:2357
#define E_INVALIDARG
Definition: ddrawi.h:101
smooth NULL
Definition: ftsmooth.c:416
#define CF_HDROP
Definition: constants.h:410
HRESULT IDataObject_Constructor(HWND hwndOwner, PCIDLIST_ABSOLUTE pMyPidl, PCUIDLIST_RELATIVE_ARRAY apidl, UINT cidl, BOOL bExtendedObject, IDataObject **dataObject)
virtual HRESULT WINAPI EndOperation(HRESULT hResult, IBindCtx *pbcReserved, DWORD dwEffects)
#define BEGIN_COM_MAP(x)
Definition: atlcom.h:541
virtual HRESULT WINAPI GetDataHere(LPFORMATETC pformatetc, STGMEDIUM *pmedium)
#define TRACE(s)
Definition: solgame.cpp:4
GLsizeiptr size
Definition: glext.h:5919
WINE_DEFAULT_DEBUG_CHANNEL(shell)
LONG HRESULT
Definition: typedefs.h:79
#define FAILED_UNEXPECTEDLY(hr)
Definition: shellutils.h:71
#define WINAPI
Definition: msvc.h:6
virtual HRESULT WINAPI EnumDAdvise(IEnumSTATDATA **ppenumAdvise)
unsigned long DWORD
Definition: ntddk_ex.h:95
HGLOBAL RenderFILENAMEW(LPITEMIDLIST pidlRoot, LPITEMIDLIST *apidl, UINT cidl)
Definition: clipboard.c:220
const GUID IID_IEnumFORMATETC
HGLOBAL RenderFILENAMEA(LPITEMIDLIST pidlRoot, LPITEMIDLIST *apidl, UINT cidl)
Definition: clipboard.c:188
HRESULT WINAPI Initialize(UINT cfmt, const FORMATETC afmt[])
Definition: CIDLDataObj.cpp:52
virtual HRESULT WINAPI DAdvise(FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection)
struct IEnumFORMATETC::tagFORMATETC FORMATETC
CSimpleArray< STGMEDIUM > m_Storage
virtual HRESULT WINAPI Clone(LPENUMFORMATETC *ppenum)
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
virtual HRESULT WINAPI Skip(ULONG celt)
Definition: CIDLDataObj.cpp:90
virtual HRESULT WINAPI DUnadvise(DWORD dwConnection)
UINT WINAPI RegisterClipboardFormatA(_In_ LPCSTR)
#define ERR(fmt,...)
Definition: debug.h:110
#define OLE_E_ADVISENOTSUPPORTED
Definition: winerror.h:2617
#define S_OK
Definition: intsafe.h:51
void shell(int argc, const char *argv[])
Definition: cmds.c:1231
#define COM_INTERFACE_ENTRY_IID(iid, x)
Definition: atlcom.h:561
HRESULT WINAPI Initialize(HWND hwndOwner, PCIDLIST_ABSOLUTE pMyPidl, PCUIDLIST_RELATIVE_ARRAY apidlx, UINT cidlx, BOOL bAddAdditionalFormats)
#define E_NOTIMPL
Definition: ddrawi.h:99
unsigned int UINT
Definition: ndis.h:50
HRESULT QueryInterface([in] REFIID riid, [out, iid_is(riid)] void **ppvObject)
LPFORMATETC pFmt
Definition: CIDLDataObj.cpp:24
static const WCHAR CFSTR_FILENAMEW[]
Definition: shlobj.h:443
unsigned int ULONG
Definition: retypes.h:1
#define CFSTR_SHELLIDLISTA
Definition: shlobj.h:345
#define UNIMPLEMENTED
Definition: debug.h:115
#define CFSTR_FILENAMEA
Definition: shlobj.h:352
#define END_COM_MAP()
Definition: atlcom.h:552
virtual HRESULT WINAPI GetData(LPFORMATETC pformatetcIn, STGMEDIUM *pmedium)
ITEMIDLIST UNALIGNED * LPITEMIDLIST
Definition: shtypes.idl:41
#define TRACE_ON(x)
Definition: compat.h:75
Definition: dsound.c:943
LPVOID WINAPI SHAlloc(SIZE_T len)
Definition: shellole.c:309
virtual HRESULT WINAPI Reset()
HGLOBAL RenderSHELLIDLIST(LPITEMIDLIST pidlRoot, LPITEMIDLIST *apidl, UINT cidl)
Definition: clipboard.c:146
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
struct IEnumFORMATETC::tagFORMATETC * LPFORMATETC
int WINAPI GetClipboardFormatNameA(_In_ UINT format, _Out_writes_(cchMaxCount) LPSTR lpszFormatName, _In_ int cchMaxCount)
virtual HRESULT WINAPI StartOperation(IBindCtx *pbcReserved)