Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

258 lines
6.7 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Copyright (C) 1993-1996 Microsoft Corporation. All Rights Reserved.
  3. //
  4. // MODULE: dataobj.cpp
  5. //
  6. // PURPOSE: Implements a generic IDataObject that can be used for simple
  7. // drag and drop scenarios.
  8. //
  9. // HISTORY:
  10. //
  11. #include "pch.hxx"
  12. #include "dllmain.h"
  13. #include "msoert.h"
  14. #include <BadStrFunctions.h>
  15. CDataObject::CDataObject ()
  16. {
  17. m_cRef = 1;
  18. m_pInfo = 0;
  19. m_celtInfo = 0;
  20. m_pfnFree = 0;
  21. }
  22. CDataObject::~CDataObject ()
  23. {
  24. if (m_pfnFree)
  25. m_pfnFree(m_pInfo, m_celtInfo);
  26. }
  27. //
  28. // FUNCTION: Init
  29. //
  30. // PURPOSE: Allows the caller to provide the object with data and formats.
  31. //
  32. // PARAMETERS:
  33. // [in] pDataObjInfo - An array of DATAOBJINFO structs which contain the
  34. // data and formats that the data object will provide.
  35. // [in] celt - The number of elements in pDataObjInfo.
  36. // [in] pfnFree - callback to free allocated data
  37. //
  38. // RETURNS:
  39. // S_OK - The object is initialized OK.
  40. // E_INVALIDARG - Either pDataObjInfo is NULL or celt is zero.
  41. //
  42. // COMMENTS:
  43. // Note, after the caller gives the object pDataObjInfo, this object owns
  44. // that data and will be responsible for freeing it.
  45. //
  46. HRESULT CDataObject::Init(PDATAOBJINFO pDataObjInfo, DWORD celt, PFNFREEDATAOBJ pfnFree)
  47. {
  48. if (!pDataObjInfo || celt == 0)
  49. return (E_INVALIDARG);
  50. // Hold on to the data
  51. m_pInfo = pDataObjInfo;
  52. m_celtInfo = celt;
  53. m_pfnFree = pfnFree;
  54. return (S_OK);
  55. }
  56. STDMETHODIMP CDataObject::QueryInterface (REFIID riid, LPVOID* ppv)
  57. {
  58. *ppv = NULL;
  59. if (IsEqualIID(riid, IID_IUnknown))
  60. {
  61. *ppv = (LPVOID)(IUnknown*) this;
  62. }
  63. else if (IsEqualIID(riid, IID_IDataObject))
  64. {
  65. *ppv = (LPVOID)(IDataObject*) this;
  66. }
  67. if (NULL == *ppv)
  68. return (E_NOINTERFACE);
  69. ((LPUNKNOWN) *ppv)->AddRef();
  70. return (S_OK);
  71. }
  72. STDMETHODIMP_(ULONG) CDataObject::AddRef (void)
  73. {
  74. return (++m_cRef);
  75. }
  76. STDMETHODIMP_(ULONG) CDataObject::Release (void)
  77. {
  78. ULONG cRef = --m_cRef;
  79. if (0 == m_cRef)
  80. delete this;
  81. return (cRef);
  82. }
  83. STDMETHODIMP CDataObject::GetData (LPFORMATETC pFE, LPSTGMEDIUM pStgMedium)
  84. {
  85. HRESULT hr = E_INVALIDARG;
  86. Assert(pStgMedium && pFE);
  87. if (pStgMedium && pFE)
  88. {
  89. HGLOBAL hGlobal = NULL;
  90. LPVOID pv = NULL;
  91. hr = DV_E_FORMATETC;
  92. ZeroMemory(pStgMedium, sizeof(STGMEDIUM));
  93. // Loop through the pInfo array to see if any of the elements has the
  94. // same clipboard format as pFE
  95. for (DWORD i = 0; i < m_celtInfo; i++)
  96. {
  97. if (pFE->cfFormat == m_pInfo[i].fe.cfFormat)
  98. {
  99. // Make a copy of the data for this pInfo
  100. hGlobal = GlobalAlloc(GMEM_SHARE | GHND, m_pInfo[i].cbData);
  101. if (!hGlobal)
  102. return (E_OUTOFMEMORY);
  103. pv = GlobalLock(hGlobal);
  104. if (!pv)
  105. {
  106. hr = E_POINTER;
  107. break;
  108. }
  109. else
  110. {
  111. CopyMemory(pv, m_pInfo[i].pData, m_pInfo[i].cbData);
  112. GlobalUnlock(hGlobal);
  113. // Fill in the pStgMedium struct
  114. if (pFE->tymed & TYMED_HGLOBAL)
  115. {
  116. pStgMedium->hGlobal = hGlobal;
  117. pStgMedium->tymed = TYMED_HGLOBAL;
  118. return (S_OK);
  119. }
  120. else if (pFE->tymed & TYMED_ISTREAM)
  121. {
  122. // If the user wants a stream, convert our HGLOBAL to a stream
  123. if (SUCCEEDED(CreateStreamOnHGlobal(hGlobal, TRUE, &pStgMedium->pstm)))
  124. {
  125. pStgMedium->tymed = TYMED_ISTREAM;
  126. return (S_OK);
  127. }
  128. else
  129. {
  130. return (STG_E_MEDIUMFULL);
  131. }
  132. }
  133. else
  134. {
  135. GlobalFree(hGlobal);
  136. return (DV_E_TYMED);
  137. }
  138. }
  139. }
  140. }
  141. }
  142. return hr;
  143. }
  144. STDMETHODIMP CDataObject::GetDataHere (LPFORMATETC pFE, LPSTGMEDIUM pStgMedium)
  145. {
  146. return E_NOTIMPL;
  147. }
  148. STDMETHODIMP CDataObject::QueryGetData(LPFORMATETC pFE)
  149. {
  150. BOOL fReturn = FALSE;
  151. // Check the aspects we support. Implementations of this object will only
  152. // support DVASPECT_CONTENT.
  153. if (pFE && !(DVASPECT_CONTENT & pFE->dwAspect))
  154. return (DV_E_DVASPECT);
  155. if (pFE)
  156. {
  157. // Now check for an appropriate TYMED.
  158. fReturn = (pFE->tymed & TYMED_HGLOBAL) || (pFE->tymed & TYMED_ISTREAM);
  159. }
  160. return (fReturn ? S_OK : DV_E_TYMED);
  161. }
  162. STDMETHODIMP CDataObject::GetCanonicalFormatEtc(LPFORMATETC pFEIn,
  163. LPFORMATETC pFEOut)
  164. {
  165. if (NULL == pFEOut)
  166. return (E_INVALIDARG);
  167. pFEOut->ptd = NULL;
  168. return (DATA_S_SAMEFORMATETC);
  169. }
  170. STDMETHODIMP CDataObject::EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC** ppEnum)
  171. {
  172. if (DATADIR_GET == dwDirection)
  173. {
  174. if (SUCCEEDED(CreateEnumFormatEtc(this, m_celtInfo, m_pInfo, NULL, ppEnum)))
  175. return (S_OK);
  176. else
  177. return (E_FAIL);
  178. }
  179. else
  180. {
  181. *ppEnum = NULL;
  182. return (E_NOTIMPL);
  183. }
  184. }
  185. STDMETHODIMP CDataObject::SetData(LPFORMATETC pFE, LPSTGMEDIUM pStgMedium, BOOL fRelease)
  186. {
  187. return E_NOTIMPL;
  188. }
  189. STDMETHODIMP CDataObject::DAdvise(LPFORMATETC pFE, DWORD advf, IAdviseSink* ppAdviseSink, LPDWORD pdwConnection)
  190. {
  191. return E_NOTIMPL;
  192. }
  193. STDMETHODIMP CDataObject::DUnadvise(DWORD dwConnection)
  194. {
  195. return E_NOTIMPL;
  196. }
  197. STDMETHODIMP CDataObject::EnumDAdvise(IEnumSTATDATA** ppEnumAdvise)
  198. {
  199. return E_NOTIMPL;
  200. }
  201. OESTDAPI_(HRESULT) CreateDataObject(PDATAOBJINFO pDataObjInfo, DWORD celt, PFNFREEDATAOBJ pfnFree, IDataObject **ppDataObj)
  202. {
  203. CDataObject *pDataObj;
  204. HRESULT hr;
  205. pDataObj = new CDataObject();
  206. if (!pDataObj)
  207. return E_OUTOFMEMORY;
  208. hr = pDataObj->Init(pDataObjInfo, celt, pfnFree);
  209. if (FAILED(hr))
  210. goto error;
  211. hr = pDataObj->QueryInterface(IID_IDataObject, (LPVOID *)ppDataObj);
  212. error:
  213. pDataObj->Release();
  214. return hr;
  215. }