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.

373 lines
10 KiB

  1. #include "pch.h"
  2. #include "stddef.h"
  3. #pragma hdrstop
  4. // free a DSA
  5. int _DestroyCB(LPVOID pItem, LPVOID pData)
  6. {
  7. DATAOBJECTITEM *pdoi = (DATAOBJECTITEM*)pItem;
  8. LocalFreeStringW(&pdoi->pszPath);
  9. LocalFreeStringW(&pdoi->pszObjectClass);
  10. return 1;
  11. }
  12. STDAPI_(void) FreeDataObjectDSA(HDSA hdsaObjects)
  13. {
  14. DSA_DestroyCallback(hdsaObjects, _DestroyCB, NULL);
  15. }
  16. // IDataObject stuff
  17. CLIPFORMAT g_cfDsObjectNames = 0;
  18. typedef struct
  19. {
  20. UINT cfFormat;
  21. STGMEDIUM medium;
  22. } OTHERFMT;
  23. class CDataObject : public IDataObject
  24. {
  25. public:
  26. CDataObject(HDSA hdsaObjects, BOOL fAdmin);
  27. ~CDataObject();
  28. // IUnknown
  29. STDMETHOD(QueryInterface)(REFIID riid, LPVOID* ppvObject);
  30. STDMETHOD_(ULONG, AddRef)();
  31. STDMETHOD_(ULONG, Release)();
  32. // IDataObject
  33. STDMETHODIMP GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium);
  34. STDMETHODIMP GetDataHere(FORMATETC *pformatetc, STGMEDIUM *pmedium)
  35. { return E_NOTIMPL; }
  36. STDMETHODIMP QueryGetData(FORMATETC *pformatetc);
  37. STDMETHODIMP GetCanonicalFormatEtc(FORMATETC *pformatectIn, FORMATETC *pformatetcOut)
  38. { return DATA_S_SAMEFORMATETC; }
  39. STDMETHODIMP SetData(FORMATETC *pformatetc, STGMEDIUM *pmedium, BOOL fRelease);
  40. STDMETHODIMP EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc)
  41. { return E_NOTIMPL; }
  42. STDMETHODIMP DAdvise(FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection)
  43. { return OLE_E_ADVISENOTSUPPORTED; }
  44. STDMETHODIMP DUnadvise(DWORD dwConnection)
  45. { return OLE_E_ADVISENOTSUPPORTED; }
  46. STDMETHODIMP EnumDAdvise(IEnumSTATDATA **ppenumAdvise)
  47. { return OLE_E_ADVISENOTSUPPORTED; }
  48. private:
  49. LONG _cRef;
  50. BOOL _fAdmin;
  51. HDSA _hdsaObjects; // array of the objects
  52. HDSA _hdsaOtherFmt;
  53. static INT s_OtherFmtDestroyCB(LPVOID pVoid, LPVOID pData);
  54. void _RegisterClipFormats(void);
  55. HRESULT _GetDsObjectNames(FORMATETC* pFmt, STGMEDIUM* pMedium);
  56. };
  57. STDAPI CDataObject_CreateInstance(HDSA dsaObjects, BOOL fAdmin, REFIID riid, void **ppv)
  58. {
  59. CDataObject *pdo = new CDataObject(dsaObjects, fAdmin);
  60. if (!pdo)
  61. return E_OUTOFMEMORY;
  62. HRESULT hr = pdo->QueryInterface(riid, ppv);
  63. pdo->Release();
  64. return hr;
  65. }
  66. // IDataObject implementation
  67. void CDataObject::_RegisterClipFormats(void)
  68. {
  69. if (!g_cfDsObjectNames)
  70. g_cfDsObjectNames = (CLIPFORMAT)RegisterClipboardFormat(CFSTR_DSOBJECTNAMES);
  71. }
  72. CDataObject::CDataObject(HDSA dsaObjects, BOOL fAdmin) :
  73. _hdsaObjects(dsaObjects),
  74. _fAdmin(fAdmin),
  75. _cRef(1)
  76. {
  77. DllAddRef();
  78. _RegisterClipFormats(); // ensure our private formats are registered
  79. }
  80. // destruction
  81. INT CDataObject::s_OtherFmtDestroyCB(LPVOID pVoid, LPVOID pData)
  82. {
  83. OTHERFMT *pOtherFmt = (OTHERFMT*)pVoid;
  84. ReleaseStgMedium(&pOtherFmt->medium);
  85. return 1;
  86. }
  87. CDataObject::~CDataObject()
  88. {
  89. FreeDataObjectDSA(_hdsaObjects);
  90. if ( _hdsaOtherFmt )
  91. DSA_DestroyCallback(_hdsaOtherFmt, s_OtherFmtDestroyCB, NULL);
  92. DllRelease();
  93. }
  94. // QI handling
  95. ULONG CDataObject::AddRef()
  96. {
  97. return InterlockedIncrement(&_cRef);
  98. }
  99. ULONG CDataObject::Release()
  100. {
  101. TraceAssert( 0 != _cRef );
  102. ULONG cRef = InterlockedDecrement(&_cRef);
  103. if ( 0 == cRef )
  104. {
  105. delete this;
  106. }
  107. return cRef;
  108. }
  109. HRESULT CDataObject::QueryInterface(REFIID riid, void **ppv)
  110. {
  111. static const QITAB qit[] =
  112. {
  113. QITABENT(CDataObject, IDataObject), // IID_IDataObject
  114. {0, 0 },
  115. };
  116. return QISearch(this, qit, riid, ppv);
  117. }
  118. // fetch the object names from the IDataObject
  119. HRESULT CDataObject::_GetDsObjectNames(FORMATETC* pFmt, STGMEDIUM* pMedium)
  120. {
  121. IDsDisplaySpecifier *pdds;
  122. HRESULT hr = CoCreateInstance(CLSID_DsDisplaySpecifier, NULL, CLSCTX_INPROC_SERVER, IID_IDsDisplaySpecifier, (void **)&pdds);
  123. if (SUCCEEDED(hr))
  124. {
  125. int count = DSA_GetItemCount(_hdsaObjects);
  126. int i;
  127. // lets walk the array of items trying to determine which items
  128. // are to be returned to the caller.
  129. DWORD cbStruct = SIZEOF(DSOBJECTNAMES);
  130. DWORD offset = SIZEOF(DSOBJECTNAMES);
  131. for (i = 0 ; i < count; i++)
  132. {
  133. DATAOBJECTITEM* pdoi = (DATAOBJECTITEM*)DSA_GetItemPtr(_hdsaObjects, i);
  134. // string offset is offset by the number of structures
  135. offset += SIZEOF(DSOBJECT);
  136. // adjust the size of the total structure
  137. cbStruct += SIZEOF(DSOBJECT);
  138. cbStruct += StringByteSizeW(pdoi->pszPath);
  139. cbStruct += StringByteSizeW(pdoi->pszObjectClass);
  140. }
  141. // we have walked the structure, we know the size so lets return
  142. // the structure to the caller.
  143. DSOBJECTNAMES *pDsObjectNames;
  144. hr = AllocStorageMedium(pFmt, pMedium, cbStruct, (LPVOID*)&pDsObjectNames);
  145. if (SUCCEEDED(hr))
  146. {
  147. pDsObjectNames->clsidNamespace = CLSID_MicrosoftDS;
  148. pDsObjectNames->cItems = count;
  149. for (i = 0 ; i < count; i++)
  150. {
  151. DATAOBJECTITEM* pdoi = (DATAOBJECTITEM*)DSA_GetItemPtr(_hdsaObjects, i);
  152. // is this class a conatiner, if so then lets return that to the caller
  153. if (pdoi->fIsContainer)
  154. pDsObjectNames->aObjects[i].dwFlags |= DSOBJECT_ISCONTAINER;
  155. if (_fAdmin)
  156. pDsObjectNames->aObjects[i].dwProviderFlags = DSPROVIDER_ADVANCED;
  157. // copy the strings to the buffer
  158. pDsObjectNames->aObjects[i].offsetName = offset;
  159. StringByteCopyW(pDsObjectNames, offset, pdoi->pszPath);
  160. offset += StringByteSizeW(pdoi->pszPath);
  161. pDsObjectNames->aObjects[i].offsetClass = offset;
  162. StringByteCopyW(pDsObjectNames, offset, pdoi->pszObjectClass);
  163. offset += StringByteSizeW(pdoi->pszObjectClass);
  164. }
  165. if ( FAILED(hr) )
  166. ReleaseStgMedium(pMedium);
  167. }
  168. pdds->Release();
  169. }
  170. return hr;
  171. }
  172. // IDataObject methods
  173. STDMETHODIMP CDataObject::GetData(FORMATETC* pFmt, STGMEDIUM* pMedium)
  174. {
  175. int i;
  176. HRESULT hr = S_OK;
  177. TraceEnter(TRACE_DATAOBJ, "CDataObject::GetData");
  178. if ( !pFmt || !pMedium )
  179. ExitGracefully(hr, E_INVALIDARG, "Bad arguments to GetData");
  180. if ( pFmt->cfFormat == g_cfDsObjectNames )
  181. {
  182. hr = _GetDsObjectNames(pFmt, pMedium);
  183. FailGracefully(hr, "Failed when build CF_DSOBJECTNAMES");
  184. }
  185. else
  186. {
  187. hr = DV_E_FORMATETC; // failed
  188. for ( i = 0 ; _hdsaOtherFmt && (i < DSA_GetItemCount(_hdsaOtherFmt)); i++ )
  189. {
  190. OTHERFMT *pOtherFmt = (OTHERFMT*)DSA_GetItemPtr(_hdsaOtherFmt, i);
  191. TraceAssert(pOtherFmt);
  192. if ( pOtherFmt->cfFormat == pFmt->cfFormat )
  193. {
  194. hr = CopyStorageMedium(pFmt, pMedium, &pOtherFmt->medium);
  195. FailGracefully(hr, "Failed to copy the storage medium");
  196. }
  197. }
  198. }
  199. exit_gracefully:
  200. TraceLeaveResult(hr);
  201. }
  202. STDMETHODIMP CDataObject::QueryGetData(FORMATETC* pFmt)
  203. {
  204. HRESULT hr;
  205. INT i;
  206. BOOL fSupported = FALSE;
  207. TraceEnter(TRACE_DATAOBJ, "CDataObject::QueryGetData");
  208. // check the valid clipboard formats either the static list, or the
  209. // DSA which contains the ones we have been set with.
  210. if (pFmt->cfFormat == g_cfDsObjectNames)
  211. {
  212. fSupported = TRUE;
  213. }
  214. else
  215. {
  216. for ( i = 0 ; !fSupported && _hdsaOtherFmt && (i < DSA_GetItemCount(_hdsaOtherFmt)) ; i++ )
  217. {
  218. OTHERFMT *pOtherFmt = (OTHERFMT*)DSA_GetItemPtr(_hdsaOtherFmt, i);
  219. TraceAssert(pOtherFmt);
  220. if ( pOtherFmt->cfFormat == pFmt->cfFormat )
  221. {
  222. TraceMsg("Format is supported (set via ::SetData");
  223. fSupported = TRUE;
  224. }
  225. }
  226. }
  227. if ( !fSupported )
  228. ExitGracefully(hr, DV_E_FORMATETC, "Bad format passed to QueryGetData");
  229. // format looks good, lets check the other parameters
  230. if ( !( pFmt->tymed & TYMED_HGLOBAL ) )
  231. ExitGracefully(hr, E_INVALIDARG, "Non HGLOBAL StgMedium requested");
  232. if ( ( pFmt->ptd ) || !( pFmt->dwAspect & DVASPECT_CONTENT) || !( pFmt->lindex == -1 ) )
  233. ExitGracefully(hr, E_INVALIDARG, "Bad format requested");
  234. hr = S_OK; // successs
  235. exit_gracefully:
  236. TraceLeaveResult(hr);
  237. }
  238. STDMETHODIMP CDataObject::SetData(FORMATETC* pFmt, STGMEDIUM* pMedium, BOOL fRelease)
  239. {
  240. HRESULT hr;
  241. INT i;
  242. OTHERFMT otherfmt = { 0 };
  243. TraceEnter(TRACE_DATAOBJ, "CDataObject::SetData");
  244. // All the user to store data with our DataObject, however we are
  245. // only interested in allowing them to this with particular clipboard formats
  246. if ( fRelease && !( pFmt->tymed & TYMED_HGLOBAL ) )
  247. ExitGracefully(hr, E_INVALIDARG, "fRelease == TRUE, but not a HGLOBAL allocation");
  248. if ( !_hdsaOtherFmt )
  249. {
  250. _hdsaOtherFmt = DSA_Create(SIZEOF(OTHERFMT), 4);
  251. TraceAssert(_hdsaOtherFmt);
  252. if ( !_hdsaOtherFmt )
  253. ExitGracefully(hr, E_OUTOFMEMORY, "Failed to allocate the DSA for items");
  254. }
  255. // if there is another copy of this data in the IDataObject then lets discard it.
  256. for ( i = 0 ; i < DSA_GetItemCount(_hdsaOtherFmt) ; i++ )
  257. {
  258. OTHERFMT *pOtherFmt = (OTHERFMT*)DSA_GetItemPtr(_hdsaOtherFmt, i);
  259. TraceAssert(pOtherFmt);
  260. if ( pOtherFmt->cfFormat == pFmt->cfFormat )
  261. {
  262. Trace(TEXT("Discarding previous entry for this format at index %d"), i);
  263. ReleaseStgMedium(&pOtherFmt->medium);
  264. DSA_DeleteItem(_hdsaOtherFmt, i);
  265. break;
  266. }
  267. }
  268. // now put a copy of the data passed to ::SetData into the DSA.
  269. otherfmt.cfFormat = pFmt->cfFormat;
  270. hr = CopyStorageMedium(pFmt, &otherfmt.medium, pMedium);
  271. FailGracefully(hr, "Failed to copy the STORAGEMEIDUM");
  272. if ( -1 == DSA_AppendItem(_hdsaOtherFmt, &otherfmt) )
  273. {
  274. ReleaseStgMedium(&otherfmt.medium);
  275. ExitGracefully(hr, E_OUTOFMEMORY, "Failed to add the data to the DSA");
  276. }
  277. hr = S_OK; // success
  278. exit_gracefully:
  279. TraceLeaveResult(hr);
  280. }