ReactOS  0.4.14-dev-358-gbef841c
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  for (int n = 0; n < m_Formats.GetSize(); ++n)
240  {
241  const FORMATETC& fmt = m_Formats[n];
242  if (fmt.cfFormat == pformatetcIn->cfFormat &&
243  fmt.dwAspect == pformatetcIn->dwAspect &&
244  fmt.tymed == pformatetcIn->tymed)
245  {
246  if (pformatetcIn->tymed != TYMED_HGLOBAL)
247  {
249  return E_INVALIDARG;
250  }
251  else
252  {
253  *pmedium = m_Storage[n];
254  return QueryInterface(IID_PPV_ARG(IUnknown, &pmedium->pUnkForRelease));
255  }
256  }
257  }
258 
259  return E_INVALIDARG;
260 }
261 
262 HRESULT WINAPI CIDLDataObj::GetDataHere(LPFORMATETC pformatetc, STGMEDIUM *pmedium)
263 {
264  FIXME("(%p)->()\n", this);
265  return E_NOTIMPL;
266 }
267 
268 HRESULT WINAPI CIDLDataObj::QueryGetData(LPFORMATETC pformatetc)
269 {
270  TRACE("(%p)->(fmt=0x%08x tym=0x%08x)\n", this, pformatetc->cfFormat, pformatetc->tymed);
271 
272  for (int n = 0; n < m_Formats.GetSize(); ++n)
273  {
274  const FORMATETC& fmt = m_Formats[n];
275  if (fmt.cfFormat == pformatetc->cfFormat &&
276  fmt.dwAspect == pformatetc->dwAspect &&
277  fmt.tymed == pformatetc->tymed)
278  {
279  return S_OK;
280  }
281  }
282 
283  return S_FALSE;
284 }
285 
286 HRESULT WINAPI CIDLDataObj::GetCanonicalFormatEtc(LPFORMATETC pformatectIn, LPFORMATETC pformatetcOut)
287 {
288  //FIXME("(%p)->()\n", this);
289  return DATA_S_SAMEFORMATETC;
290 }
291 
292 HRESULT WINAPI CIDLDataObj::SetData(LPFORMATETC pformatetc, STGMEDIUM *pmedium, BOOL fRelease)
293 {
294  if (!fRelease)
295  return E_INVALIDARG;
296 
297  for (int n = 0; n < m_Formats.GetSize(); ++n)
298  {
299  const FORMATETC& fmt = m_Formats[n];
300  if (fmt.cfFormat == pformatetc->cfFormat &&
301  fmt.dwAspect == pformatetc->dwAspect &&
302  fmt.tymed == pformatetc->tymed)
303  {
305  m_Storage[n] = *pmedium;
306  return S_OK;
307  }
308  }
309 
310  m_Formats.Add(*pformatetc);
311  m_Storage.Add(*pmedium);
312 
313  return S_OK;
314 }
315 
317 {
318  TRACE("(%p)->()\n", this);
319  *ppenumFormatEtc = NULL;
320 
321  /* only get data */
322  if (DATADIR_GET == dwDirection)
323  {
324  return IEnumFORMATETC_Constructor(m_Formats.GetSize(), m_Formats.GetData(), ppenumFormatEtc);
325  }
326 
327  return E_NOTIMPL;
328 }
329 
330 HRESULT WINAPI CIDLDataObj::DAdvise(FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection)
331 {
333 }
334 
336 {
338 }
339 
341 {
343 }
344 
346 {
347  TRACE("(%p)->()\n", this);
348  *pfIsOpAsync = m_doasync;
349  return S_OK;
350 }
352 {
353  FIXME("(%p)->()\n", this);
354  return E_NOTIMPL;
355 }
357 {
358  TRACE("(%p)->()\n", this);
359  m_doasync = fDoOpAsync;
360  return S_OK;
361 }
362 
364 {
365  TRACE("(%p)->()\n", this);
366  return E_NOTIMPL;
367 }
369 {
370  TRACE("(%p)->()\n", this);
371  return E_NOTIMPL;
372 }
373 
374 
375 
376 /**************************************************************************
377  * IDataObject_Constructor
378  */
379 HRESULT IDataObject_Constructor(HWND hwndOwner, PCIDLIST_ABSOLUTE pMyPidl, PCUIDLIST_RELATIVE_ARRAY apidl, UINT cidl, BOOL bExtendedObject, IDataObject **dataObject)
380 {
381  if (!dataObject)
382  return E_INVALIDARG;
383  return ShellObjectCreatorInit<CIDLDataObj>(hwndOwner, pMyPidl, apidl, cidl, bExtendedObject, IID_PPV_ARG(IDataObject, dataObject));
384 }
385 
386 /*************************************************************************
387  * SHCreateDataObject [SHELL32.@]
388  *
389  */
390 
392 {
394  {
395  if (pdtInner)
397  return IDataObject_Constructor(NULL, pidlFolder, apidl, cidl, TRUE, (IDataObject **)ppv);
398  }
399  return E_FAIL;
400 }
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
#define TRUE
Definition: types.h:120
BOOL Add(const T &t)
Definition: atlsimpcoll.h:58
#define CFSTR_SHELLIDLIST
Definition: shlobj.h:469
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
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
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:110
#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:77
#define FAILED_UNEXPECTEDLY(hr)
Definition: shellutils.h:71
#define WINAPI
Definition: msvc.h:8
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:109
#define OLE_E_ADVISENOTSUPPORTED
Definition: winerror.h:2617
#define S_OK
Definition: intsafe.h:59
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:435
unsigned int ULONG
Definition: retypes.h:1
#define CFSTR_SHELLIDLISTA
Definition: shlobj.h:337
#define UNIMPLEMENTED
Definition: debug.h:114
#define CFSTR_FILENAMEA
Definition: shlobj.h:344
#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:65
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)