home *** CD-ROM | disk | FTP | other *** search
/ Team Palmtops 7 / Palmtops_numero07.iso / WinCE / SDKWindowsCE / HandHeldPCPro30 / sdk.exe / Jupiter SDK / data1.cab / MFC / src / oledobj2.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1999-02-19  |  21.5 KB  |  780 lines

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