OLEDOBJ2.CPP
Upload User: zoutaiqi
Upload Date: 2019-11-18
Package Size: 1363k
Code Size: 21k
Category:

Windows Develop

Development Platform:

Visual C++

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10. #include "stdafx.h"
  11. #ifdef AFX_OLE3_SEG
  12. #pragma code_seg(AFX_OLE3_SEG)
  13. #endif
  14. #ifdef _DEBUG
  15. #undef THIS_FILE
  16. static char THIS_FILE[] = __FILE__;
  17. #endif
  18. #define new DEBUG_NEW
  19. /////////////////////////////////////////////////////////////////////////////
  20. // COleDataSource implementation
  21. struct AFX_DATACACHE_ENTRY
  22. {
  23. FORMATETC m_formatEtc;
  24. STGMEDIUM m_stgMedium;
  25. DATADIR m_nDataDir;
  26. };
  27. /////////////////////////////////////////////////////////////////////////////
  28. // COleDataSource construction & destruction
  29. COleDataSource::COleDataSource()
  30. {
  31. m_pDataCache = NULL;
  32. m_nMaxSize = 0;
  33. m_nSize = 0;
  34. m_nGrowBy = 10;
  35. }
  36. COleDataSource::~COleDataSource()
  37. {
  38. // clear clipboard source if this object was on the clipboard
  39. _AFX_OLE_STATE* pOleState = _afxOleState;
  40. if (this == pOleState->m_pClipboardSource)
  41. pOleState->m_pClipboardSource = NULL;
  42. // free the clipboard data cache
  43. Empty();
  44. }
  45. void COleDataSource::Empty()
  46. {
  47. if (m_pDataCache != NULL)
  48. {
  49. ASSERT(m_nMaxSize != 0);
  50. ASSERT(m_nSize != 0);
  51. // release all of the STGMEDIUMs and FORMATETCs
  52. for (UINT nIndex = 0; nIndex < m_nSize; nIndex++)
  53. {
  54. CoTaskMemFree(m_pDataCache[nIndex].m_formatEtc.ptd);
  55. ::ReleaseStgMedium(&m_pDataCache[nIndex].m_stgMedium);
  56. }
  57. // delete the cache
  58. delete[] m_pDataCache;
  59. m_pDataCache = NULL;
  60. m_nMaxSize = 0;
  61. m_nSize = 0;
  62. }
  63. ASSERT(m_pDataCache == NULL);
  64. ASSERT(m_nMaxSize == 0);
  65. ASSERT(m_nSize == 0);
  66. }
  67. /////////////////////////////////////////////////////////////////////////////
  68. // COleDataSource clipboard API wrappers
  69. void COleDataSource::SetClipboard()
  70. {
  71. ASSERT_VALID(this);
  72. // attempt OLE set clipboard operation
  73. LPDATAOBJECT lpDataObject = (LPDATAOBJECT)GetInterface(&IID_IDataObject);
  74. SCODE sc = ::OleSetClipboard(lpDataObject);
  75. if (sc != S_OK)
  76. AfxThrowOleException(sc);
  77. // success - set as current clipboard source
  78. _afxOleState->m_pClipboardSource = this;
  79. ASSERT(::OleIsCurrentClipboard(lpDataObject) == S_OK);
  80. InternalRelease();
  81. }
  82. void PASCAL COleDataSource::FlushClipboard()
  83. {
  84. if (GetClipboardOwner() != NULL)
  85. {
  86. // active clipboard source and it is on the clipboard - flush it
  87. ::OleFlushClipboard();
  88. // shouldn't be clipboard owner any more...
  89. ASSERT(GetClipboardOwner() == NULL);
  90. }
  91. }
  92. COleDataSource* PASCAL COleDataSource::GetClipboardOwner()
  93. {
  94. _AFX_OLE_STATE* pOleState = _afxOleState;
  95. if (pOleState->m_pClipboardSource == NULL)
  96. return NULL;    // can't own the clipboard if pClipboardSource isn't set
  97. ASSERT_VALID(pOleState->m_pClipboardSource);
  98. LPDATAOBJECT lpDataObject = (LPDATAOBJECT)
  99. pOleState->m_pClipboardSource->GetInterface(&IID_IDataObject);
  100. if (::OleIsCurrentClipboard(lpDataObject) != S_OK)
  101. {
  102. pOleState->m_pClipboardSource = NULL;
  103. return NULL;    // don't own the clipboard anymore
  104. }
  105. // return current clipboard source
  106. return pOleState->m_pClipboardSource;
  107. }
  108. /////////////////////////////////////////////////////////////////////////////
  109. // COleDataSource cache allocation
  110. AFX_DATACACHE_ENTRY* COleDataSource::GetCacheEntry(
  111. LPFORMATETC lpFormatEtc, DATADIR nDataDir)
  112. {
  113. AFX_DATACACHE_ENTRY* pEntry = Lookup(lpFormatEtc, nDataDir);
  114. if (pEntry != NULL)
  115. {
  116. // cleanup current entry and return it
  117. CoTaskMemFree(pEntry->m_formatEtc.ptd);
  118. ::ReleaseStgMedium(&pEntry->m_stgMedium);
  119. }
  120. else
  121. {
  122. // allocate space for item at m_nSize (at least room for 1 item)
  123. if (m_pDataCache == NULL || m_nSize == m_nMaxSize)
  124. {
  125. ASSERT(m_nGrowBy != 0);
  126. AFX_DATACACHE_ENTRY* pCache = new AFX_DATACACHE_ENTRY[m_nMaxSize+m_nGrowBy];
  127. m_nMaxSize += m_nGrowBy;
  128. if (m_pDataCache != NULL)
  129. {
  130. memcpy(pCache, m_pDataCache, m_nSize * sizeof(AFX_DATACACHE_ENTRY));
  131. delete[] m_pDataCache;
  132. }
  133. m_pDataCache = pCache;
  134. }
  135. ASSERT(m_pDataCache != NULL);
  136. ASSERT(m_nMaxSize != 0);
  137. pEntry = &m_pDataCache[m_nSize++];
  138. }
  139. // fill the cache entry with the format and data direction and return it
  140. pEntry->m_nDataDir = nDataDir;
  141. pEntry->m_formatEtc = *lpFormatEtc;
  142. return pEntry;
  143. }
  144. /////////////////////////////////////////////////////////////////////////////
  145. // COleDataSource operations
  146. // for HGLOBAL based cached render
  147. void COleDataSource::CacheGlobalData(CLIPFORMAT cfFormat, HGLOBAL hGlobal,
  148. LPFORMATETC lpFormatEtc)
  149. {
  150. ASSERT(hGlobal != NULL);
  151. ASSERT(lpFormatEtc == NULL ||
  152. AfxIsValidAddress(lpFormatEtc, sizeof(FORMATETC), FALSE));
  153. // fill in FORMATETC struct
  154. FORMATETC formatEtc;
  155. lpFormatEtc = _AfxFillFormatEtc(lpFormatEtc, cfFormat, &formatEtc);
  156. lpFormatEtc->tymed = TYMED_HGLOBAL;
  157. // add it to the cache
  158. AFX_DATACACHE_ENTRY* pEntry = GetCacheEntry(lpFormatEtc, DATADIR_GET);
  159. pEntry->m_stgMedium.tymed = TYMED_HGLOBAL;
  160. pEntry->m_stgMedium.hGlobal = hGlobal;
  161. pEntry->m_stgMedium.pUnkForRelease = NULL;
  162. }
  163. // for raw LPSTGMEDIUM cached render
  164. void COleDataSource::CacheData(CLIPFORMAT cfFormat, LPSTGMEDIUM lpStgMedium,
  165. LPFORMATETC lpFormatEtc)
  166. {
  167. ASSERT(lpStgMedium == NULL || lpStgMedium->tymed != TYMED_NULL);
  168. ASSERT(AfxIsValidAddress(lpStgMedium, sizeof(STGMEDIUM), FALSE));
  169. ASSERT(lpFormatEtc == NULL ||
  170. AfxIsValidAddress(lpFormatEtc, sizeof(FORMATETC), FALSE));
  171. // fill in FORMATETC struct
  172. FORMATETC formatEtc;
  173. lpFormatEtc = _AfxFillFormatEtc(lpFormatEtc, cfFormat, &formatEtc);
  174. // Only these TYMED_GDI formats can be copied, so can't serve as
  175. //  cache content (you must use DelayRenderData instead)
  176. // When using COleServerItem::CopyToClipboard this means providing an
  177. //  override of COleServerItem::OnGetClipboardData to provide a custom
  178. //  delayed rendering clipboard object.
  179. ASSERT(lpStgMedium->tymed != TYMED_GDI ||
  180. lpFormatEtc->cfFormat == CF_METAFILEPICT ||
  181. lpFormatEtc->cfFormat == CF_PALETTE ||
  182. lpFormatEtc->cfFormat == CF_BITMAP);
  183. lpFormatEtc->tymed = lpStgMedium->tymed;
  184. // add it to the cache
  185. AFX_DATACACHE_ENTRY* pEntry = GetCacheEntry(lpFormatEtc, DATADIR_GET);
  186. pEntry->m_stgMedium = *lpStgMedium;
  187. }
  188. // for CFile* based delayed render
  189. void COleDataSource::DelayRenderFileData(CLIPFORMAT cfFormat,
  190. LPFORMATETC lpFormatEtc)
  191. {
  192. ASSERT(lpFormatEtc == NULL ||
  193. AfxIsValidAddress(lpFormatEtc, sizeof(FORMATETC), FALSE));
  194. // fill in FORMATETC struct
  195. FORMATETC formatEtc;
  196. lpFormatEtc = _AfxFillFormatEtc(lpFormatEtc, cfFormat, &formatEtc);
  197. lpFormatEtc->tymed |= TYMED_ISTREAM|TYMED_HGLOBAL;
  198. // add it to the cache
  199. AFX_DATACACHE_ENTRY* pEntry = GetCacheEntry(lpFormatEtc, DATADIR_GET);
  200. pEntry->m_stgMedium.tymed = TYMED_NULL;
  201. pEntry->m_stgMedium.hGlobal = NULL;
  202. pEntry->m_stgMedium.pUnkForRelease = NULL;
  203. }
  204. // for LPSTGMEDIUM or HGLOBAL based delayed render
  205. void COleDataSource::DelayRenderData(CLIPFORMAT cfFormat, LPFORMATETC lpFormatEtc)
  206. {
  207. ASSERT(lpFormatEtc == NULL ||
  208. AfxIsValidAddress(lpFormatEtc, sizeof(FORMATETC), FALSE));
  209. // fill in FORMATETC struct
  210. FORMATETC formatEtc;
  211. if (lpFormatEtc == NULL)
  212. {
  213. lpFormatEtc = _AfxFillFormatEtc(lpFormatEtc, cfFormat, &formatEtc);
  214. lpFormatEtc->tymed = TYMED_HGLOBAL;
  215. }
  216. // insure that cfFormat member is set
  217. if (cfFormat != 0)
  218. lpFormatEtc->cfFormat = cfFormat;
  219. // add it to the cache
  220. AFX_DATACACHE_ENTRY* pEntry = GetCacheEntry(lpFormatEtc, DATADIR_GET);
  221. memset(&pEntry->m_stgMedium, 0, sizeof pEntry->m_stgMedium);
  222. }
  223. // DelaySetData -- used to allow SetData on given LPFORMATETC
  224. void COleDataSource::DelaySetData(CLIPFORMAT cfFormat, LPFORMATETC lpFormatEtc)
  225. {
  226. ASSERT(lpFormatEtc == NULL ||
  227. AfxIsValidAddress(lpFormatEtc, sizeof(FORMATETC), FALSE));
  228. // fill in FORMATETC struct
  229. FORMATETC formatEtc;
  230. lpFormatEtc = _AfxFillFormatEtc(lpFormatEtc, cfFormat, &formatEtc);
  231. // add it to the cache
  232. AFX_DATACACHE_ENTRY* pEntry = GetCacheEntry(lpFormatEtc, DATADIR_SET);
  233. pEntry->m_stgMedium.tymed = TYMED_NULL;
  234. pEntry->m_stgMedium.hGlobal = NULL;
  235. pEntry->m_stgMedium.pUnkForRelease = NULL;
  236. }
  237. /////////////////////////////////////////////////////////////////////////////
  238. // COleDataSource cache implementation
  239. AFX_DATACACHE_ENTRY* COleDataSource::Lookup(
  240. LPFORMATETC lpFormatEtc, DATADIR nDataDir) const
  241. {
  242. AFX_DATACACHE_ENTRY* pLast = NULL;
  243. // look for suitable match to lpFormatEtc in cache
  244. for (UINT nIndex = 0; nIndex < m_nSize; nIndex++)
  245. {
  246. // get entry from cache at nIndex
  247. AFX_DATACACHE_ENTRY* pCache = &m_pDataCache[nIndex];
  248. FORMATETC *pCacheFormat = &pCache->m_formatEtc;
  249. // check for match
  250. if (pCacheFormat->cfFormat == lpFormatEtc->cfFormat &&
  251. (pCacheFormat->tymed & lpFormatEtc->tymed) != 0 &&
  252. (pCache->m_stgMedium.tymed == TYMED_NULL ||
  253. pCacheFormat->lindex == lpFormatEtc->lindex) &&
  254. pCacheFormat->dwAspect == lpFormatEtc->dwAspect &&
  255. pCache->m_nDataDir == nDataDir)
  256. {
  257. // for backward compatibility we match even if we never
  258. // find an exact match for the DVTARGETDEVICE
  259. pLast = pCache;
  260. DVTARGETDEVICE* ptd1 = pCacheFormat->ptd;
  261. DVTARGETDEVICE* ptd2 = lpFormatEtc->ptd;
  262. if (ptd1 == NULL && ptd2 == NULL)
  263. {
  264. // both target devices are NULL (exact match), so return it
  265. break;
  266. }
  267. if (ptd1 != NULL && ptd2 != NULL &&
  268. ptd1->tdSize == ptd2->tdSize &&
  269. memcmp(ptd1, ptd2, ptd1->tdSize) == 0)
  270. {
  271. // exact match, so return it
  272. break;
  273. }
  274. // continue looking for better match
  275. }
  276. }
  277. return pLast;    // not found
  278. }
  279. /////////////////////////////////////////////////////////////////////////////
  280. // COleDataSource overidable default implementation
  281. BOOL COleDataSource::OnRenderGlobalData(
  282. LPFORMATETC /*lpFormatEtc*/, HGLOBAL* /*phGlobal*/)
  283. {
  284. return FALSE;   // default does nothing
  285. }
  286. BOOL COleDataSource::OnRenderFileData(
  287. LPFORMATETC /*lpFormatEtc*/, CFile* /*pFile*/)
  288. {
  289. return FALSE;   // default does nothing
  290. }
  291. BOOL COleDataSource::OnRenderData(
  292. LPFORMATETC lpFormatEtc, LPSTGMEDIUM lpStgMedium)
  293. {
  294. // attempt TYMED_HGLOBAL as prefered format
  295. if (lpFormatEtc->tymed & TYMED_HGLOBAL)
  296. {
  297. // attempt HGLOBAL delay render hook
  298. HGLOBAL hGlobal = lpStgMedium->hGlobal;
  299. if (OnRenderGlobalData(lpFormatEtc, &hGlobal))
  300. {
  301. ASSERT(lpStgMedium->tymed != TYMED_HGLOBAL ||
  302. (lpStgMedium->hGlobal == hGlobal));
  303. ASSERT(hGlobal != NULL);
  304. lpStgMedium->tymed = TYMED_HGLOBAL;
  305. lpStgMedium->hGlobal = hGlobal;
  306. return TRUE;
  307. }
  308. // attempt CFile* based delay render hook
  309. CSharedFile file;
  310. if (lpStgMedium->tymed == TYMED_HGLOBAL)
  311. {
  312. ASSERT(lpStgMedium->hGlobal != NULL);
  313. file.SetHandle(lpStgMedium->hGlobal, FALSE);
  314. }
  315. if (OnRenderFileData(lpFormatEtc, &file))
  316. {
  317. lpStgMedium->tymed = TYMED_HGLOBAL;
  318. lpStgMedium->hGlobal = file.Detach();
  319. ASSERT(lpStgMedium->hGlobal != NULL);
  320. return TRUE;
  321. }
  322. if (lpStgMedium->tymed == TYMED_HGLOBAL)
  323. file.Detach();
  324. }
  325. // attempt TYMED_ISTREAM format
  326. if (lpFormatEtc->tymed & TYMED_ISTREAM)
  327. {
  328. COleStreamFile file;
  329. if (lpStgMedium->tymed == TYMED_ISTREAM)
  330. {
  331. ASSERT(lpStgMedium->pstm != NULL);
  332. file.Attach(lpStgMedium->pstm);
  333. }
  334. else
  335. {
  336. if (!file.CreateMemoryStream())
  337. AfxThrowMemoryException();
  338. }
  339. // get data into the stream
  340. if (OnRenderFileData(lpFormatEtc, &file))
  341. {
  342. lpStgMedium->tymed = TYMED_ISTREAM;
  343. lpStgMedium->pstm = file.Detach();
  344. return TRUE;
  345. }
  346. if (lpStgMedium->tymed == TYMED_ISTREAM)
  347. file.Detach();
  348. }
  349. return FALSE;   // default does nothing
  350. }
  351. BOOL COleDataSource::OnSetData(
  352. LPFORMATETC /*lpFormatEtc*/, LPSTGMEDIUM /*lpStgMedium*/, BOOL /*bRelease*/)
  353. {
  354. return FALSE;   // default does nothing
  355. }
  356. /////////////////////////////////////////////////////////////////////////////
  357. // CEnumFormatEtc - enumerator for array for FORMATETC structures
  358. class CEnumFormatEtc : public CEnumArray
  359. {
  360. // Constructors
  361. public:
  362. CEnumFormatEtc();
  363. // Operations
  364. void AddFormat(const FORMATETC* lpFormatEtc);
  365. // Implementation
  366. public:
  367. virtual ~CEnumFormatEtc();
  368. protected:
  369. virtual BOOL OnNext(void* pv);
  370. UINT m_nMaxSize;    // number of items allocated (>= m_nSize)
  371. DECLARE_INTERFACE_MAP()
  372. };
  373. BEGIN_INTERFACE_MAP(CEnumFormatEtc, CEnumArray)
  374. INTERFACE_PART(CEnumFormatEtc, IID_IEnumFORMATETC, EnumVOID)
  375. END_INTERFACE_MAP()
  376. CEnumFormatEtc::CEnumFormatEtc()
  377. : CEnumArray(sizeof(FORMATETC), NULL, 0, TRUE)
  378. {
  379. m_nMaxSize = 0;
  380. }
  381. CEnumFormatEtc::~CEnumFormatEtc()
  382. {
  383. if (m_pClonedFrom == NULL)
  384. {
  385. // release all of the pointers to DVTARGETDEVICE
  386. LPFORMATETC lpFormatEtc = (LPFORMATETC)m_pvEnum;
  387. for (UINT nIndex = 0; nIndex < m_nSize; nIndex++)
  388. CoTaskMemFree(lpFormatEtc[nIndex].ptd);
  389. }
  390. // destructor will free the actual array (if it was not a clone)
  391. }
  392. BOOL CEnumFormatEtc::OnNext(void* pv)
  393. {
  394. if (!CEnumArray::OnNext(pv))
  395. return FALSE;
  396. // any outgoing formatEtc may require the DVTARGETDEVICE to
  397. //  be copied (the caller has responsibility to free it)
  398. LPFORMATETC lpFormatEtc = (LPFORMATETC)pv;
  399. if (lpFormatEtc->ptd != NULL)
  400. {
  401. lpFormatEtc->ptd = _AfxOleCopyTargetDevice(lpFormatEtc->ptd);
  402. if (lpFormatEtc->ptd == NULL)
  403. AfxThrowMemoryException();
  404. }
  405. // otherwise, copying worked...
  406. return TRUE;
  407. }
  408. void CEnumFormatEtc::AddFormat(const FORMATETC* lpFormatEtc)
  409. {
  410. ASSERT(m_nSize <= m_nMaxSize);
  411. if (m_nSize == m_nMaxSize)
  412. {
  413. // not enough space for new item -- allocate more
  414. FORMATETC* pListNew = new FORMATETC[m_nSize+10];
  415. m_nMaxSize += 10;
  416. memcpy(pListNew, m_pvEnum, m_nSize*sizeof(FORMATETC));
  417. delete m_pvEnum;
  418. m_pvEnum = (BYTE*)pListNew;
  419. }
  420. // add this item to the list
  421. ASSERT(m_nSize < m_nMaxSize);
  422. FORMATETC* pFormat = &((FORMATETC*)m_pvEnum)[m_nSize];
  423. pFormat->cfFormat = lpFormatEtc->cfFormat;
  424. pFormat->ptd = lpFormatEtc->ptd;
  425. // Note: ownership of lpFormatEtc->ptd is transfered with this call.
  426. pFormat->dwAspect = lpFormatEtc->dwAspect;
  427. pFormat->lindex = lpFormatEtc->lindex;
  428. pFormat->tymed = lpFormatEtc->tymed;
  429. ++m_nSize;
  430. }
  431. /////////////////////////////////////////////////////////////////////////////
  432. // COleDataSource::XDataObject
  433. BEGIN_INTERFACE_MAP(COleDataSource, CCmdTarget)
  434. INTERFACE_PART(COleDataSource, IID_IDataObject, DataObject)
  435. END_INTERFACE_MAP()
  436. STDMETHODIMP_(ULONG) COleDataSource::XDataObject::AddRef()
  437. {
  438. METHOD_PROLOGUE_EX_(COleDataSource, DataObject)
  439. return pThis->ExternalAddRef();
  440. }
  441. STDMETHODIMP_(ULONG) COleDataSource::XDataObject::Release()
  442. {
  443. METHOD_PROLOGUE_EX_(COleDataSource, DataObject)
  444. return pThis->ExternalRelease();
  445. }
  446. STDMETHODIMP COleDataSource::XDataObject::QueryInterface(
  447. REFIID iid, LPVOID* ppvObj)
  448. {
  449. METHOD_PROLOGUE_EX_(COleDataSource, DataObject)
  450. return pThis->ExternalQueryInterface(&iid, ppvObj);
  451. }
  452. STDMETHODIMP COleDataSource::XDataObject::GetData(
  453. LPFORMATETC lpFormatEtc, LPSTGMEDIUM lpStgMedium)
  454. {
  455. METHOD_PROLOGUE_EX(COleDataSource, DataObject)
  456. ASSERT_VALID(pThis);
  457. // attempt to find match in the cache
  458. AFX_DATACACHE_ENTRY* pCache = pThis->Lookup(lpFormatEtc, DATADIR_GET);
  459. if (pCache == NULL)
  460. return DATA_E_FORMATETC;
  461. // use cache if entry is not delay render
  462. memset(lpStgMedium, 0, sizeof(STGMEDIUM));
  463. if (pCache->m_stgMedium.tymed != TYMED_NULL)
  464. {
  465. // Copy the cached medium into the lpStgMedium provided by caller.
  466. if (!_AfxCopyStgMedium(lpFormatEtc->cfFormat, lpStgMedium,
  467.   &pCache->m_stgMedium))
  468. return DATA_E_FORMATETC;
  469. // format was supported for copying
  470. return S_OK;
  471. }
  472. SCODE sc = DATA_E_FORMATETC;
  473. TRY
  474. {
  475. // attempt LPSTGMEDIUM based delay render
  476. if (pThis->OnRenderData(lpFormatEtc, lpStgMedium))
  477. sc = S_OK;
  478. }
  479. CATCH_ALL(e)
  480. {
  481. sc = COleException::Process(e);
  482. DELETE_EXCEPTION(e);
  483. }
  484. END_CATCH_ALL
  485. return sc;
  486. }
  487. STDMETHODIMP COleDataSource::XDataObject::GetDataHere(
  488. LPFORMATETC lpFormatEtc, LPSTGMEDIUM lpStgMedium)
  489. {
  490. METHOD_PROLOGUE_EX(COleDataSource, DataObject)
  491. ASSERT_VALID(pThis);
  492. // these two must be the same
  493. ASSERT(lpFormatEtc->tymed == lpStgMedium->tymed);
  494. lpFormatEtc->tymed = lpStgMedium->tymed;    // but just in case...
  495. // attempt to find match in the cache
  496. AFX_DATACACHE_ENTRY* pCache = pThis->Lookup(lpFormatEtc, DATADIR_GET);
  497. if (pCache == NULL)
  498. return DATA_E_FORMATETC;
  499. // handle cached medium and copy
  500. if (pCache->m_stgMedium.tymed != TYMED_NULL)
  501. {
  502. // found a cached format -- copy it to dest medium
  503. ASSERT(pCache->m_stgMedium.tymed == lpStgMedium->tymed);
  504. if (!_AfxCopyStgMedium(lpFormatEtc->cfFormat, lpStgMedium,
  505.   &pCache->m_stgMedium))
  506. return DATA_E_FORMATETC;
  507. // format was supported for copying
  508. return S_OK;
  509. }
  510. SCODE sc = DATA_E_FORMATETC;
  511. TRY
  512. {
  513. // attempt LPSTGMEDIUM based delay render
  514. if (pThis->OnRenderData(lpFormatEtc, lpStgMedium))
  515. sc = S_OK;
  516. }
  517. CATCH_ALL(e)
  518. {
  519. sc = COleException::Process(e);
  520. DELETE_EXCEPTION(e);
  521. }
  522. END_CATCH_ALL
  523. return sc;
  524. }
  525. STDMETHODIMP COleDataSource::XDataObject::QueryGetData(LPFORMATETC lpFormatEtc)
  526. {
  527. METHOD_PROLOGUE_EX_(COleDataSource, DataObject)
  528. // attempt to find match in the cache
  529. AFX_DATACACHE_ENTRY* pCache = pThis->Lookup(lpFormatEtc, DATADIR_GET);
  530. if (pCache == NULL)
  531. return DATA_E_FORMATETC;
  532. // it was found in the cache or can be rendered -- success
  533. return S_OK;
  534. }
  535. STDMETHODIMP COleDataSource::XDataObject::GetCanonicalFormatEtc(
  536. LPFORMATETC /*lpFormatEtcIn*/, LPFORMATETC /*lpFormatEtcOut*/)
  537. {
  538. // because we support the target-device (ptd) for server metafile format,
  539. //  all members of the FORMATETC are significant.
  540. return DATA_S_SAMEFORMATETC;
  541. }
  542. STDMETHODIMP COleDataSource::XDataObject::SetData(
  543. LPFORMATETC lpFormatEtc, LPSTGMEDIUM lpStgMedium, BOOL bRelease)
  544. {
  545. METHOD_PROLOGUE_EX(COleDataSource, DataObject)
  546. ASSERT_VALID(pThis);
  547. ASSERT(lpFormatEtc->tymed == lpStgMedium->tymed);
  548. // attempt to find match in the cache
  549. AFX_DATACACHE_ENTRY* pCache = pThis->Lookup(lpFormatEtc, DATADIR_SET);
  550. if (pCache == NULL)
  551. return DATA_E_FORMATETC;
  552. ASSERT(pCache->m_stgMedium.tymed == TYMED_NULL);
  553. SCODE sc = E_UNEXPECTED;
  554. TRY
  555. {
  556. // attempt LPSTGMEDIUM based SetData
  557. if (pThis->OnSetData(lpFormatEtc, lpStgMedium, bRelease))
  558. sc = S_OK;
  559. }
  560. CATCH_ALL(e)
  561. {
  562. sc = COleException::Process(e);
  563. DELETE_EXCEPTION(e);
  564. }
  565. END_CATCH_ALL
  566. return sc;
  567. }
  568. STDMETHODIMP COleDataSource::XDataObject::EnumFormatEtc(
  569. DWORD dwDirection, LPENUMFORMATETC* ppenumFormatEtc)
  570. {
  571. METHOD_PROLOGUE_EX_(COleDataSource, DataObject)
  572. *ppenumFormatEtc = NULL;
  573. CEnumFormatEtc* pFormatList = NULL;
  574. SCODE sc = E_OUTOFMEMORY;
  575. TRY
  576. {
  577. // generate a format list from the cache
  578. pFormatList = new CEnumFormatEtc;
  579. for (UINT nIndex = 0; nIndex < pThis->m_nSize; nIndex++)
  580. {
  581. AFX_DATACACHE_ENTRY* pCache = &pThis->m_pDataCache[nIndex];
  582. if ((DWORD)pCache->m_nDataDir & dwDirection)
  583. {
  584. // entry should be enumerated -- add it to the list
  585. FORMATETC formatEtc;
  586. _AfxOleCopyFormatEtc(&formatEtc, &pCache->m_formatEtc);
  587. pFormatList->AddFormat(&formatEtc);
  588. }
  589. }
  590. // give it away to OLE (ref count is already 1)
  591. *ppenumFormatEtc = (LPENUMFORMATETC)&pFormatList->m_xEnumVOID;
  592. sc = S_OK;
  593. }
  594. END_TRY
  595. return sc;
  596. }
  597. STDMETHODIMP COleDataSource::XDataObject::DAdvise(
  598. FORMATETC* /*pFormatetc*/, DWORD /*advf*/,
  599. LPADVISESINK /*pAdvSink*/, DWORD* pdwConnection)
  600. {
  601. *pdwConnection = 0;
  602. return OLE_E_ADVISENOTSUPPORTED;
  603. }
  604. STDMETHODIMP COleDataSource::XDataObject::DUnadvise(DWORD /*dwConnection*/)
  605. {
  606. return OLE_E_ADVISENOTSUPPORTED;
  607. }
  608. STDMETHODIMP COleDataSource::XDataObject::EnumDAdvise(
  609. LPENUMSTATDATA* ppenumAdvise)
  610. {
  611. *ppenumAdvise = NULL;
  612. return OLE_E_ADVISENOTSUPPORTED;
  613. }
  614. /////////////////////////////////////////////////////////////////////////////
  615. // COleDataSource diagnostics
  616. #ifdef _DEBUG
  617. void COleDataSource::AssertValid() const
  618. {
  619. CCmdTarget::AssertValid();
  620. ASSERT(m_nSize <= m_nMaxSize);
  621. ASSERT(m_nMaxSize != 0 || m_pDataCache == NULL);
  622. }
  623. void COleDataSource::Dump(CDumpContext& dc) const
  624. {
  625. CCmdTarget::Dump(dc);
  626. dc << "m_nMaxSize = " << m_nMaxSize;
  627. dc << "nm_nSize = " << m_nSize;
  628. dc << "nm_pDataCache = " << m_pDataCache;
  629. for (UINT n = 0; n < m_nSize; n++)
  630. {
  631. dc << "ntentry [" << n << "] = {";
  632. AFX_DATACACHE_ENTRY& rEntry = m_pDataCache[n];
  633. dc << "nt m_formatEtc.cfFormat = " << rEntry.m_formatEtc.cfFormat;
  634. dc << "nt m_formatEtc.pdt = " << rEntry.m_formatEtc.ptd;
  635. dc << "nt m_formatEtc.dwAspect = " << rEntry.m_formatEtc.dwAspect;
  636. dc << "nt m_formatEtc.lindex = " << rEntry.m_formatEtc.lindex;
  637. dc << "nt m_formatEtc.tymed = " << rEntry.m_formatEtc.tymed;
  638. dc << "nt m_stgMedium.tymed = " << rEntry.m_stgMedium.tymed;
  639. dc << "nt m_nDataDir = " << (UINT)rEntry.m_nDataDir;
  640. dc << "nt}";
  641. }
  642. dc << "n";
  643. }
  644. #endif //_DEBUG
  645. /////////////////////////////////////////////////////////////////////////////