home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / mfc / src / oleenum.cpp < prev    next >
C/C++ Source or Header  |  1998-06-16  |  5KB  |  217 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. // CEnumArray (provides OLE enumerator for arbitrary items in an array)
  26.  
  27. CEnumArray::CEnumArray(size_t nSizeElem, const void* pvEnum, UINT nSize,
  28.     BOOL bNeedFree)
  29. {
  30.     m_nSizeElem = nSizeElem;
  31.     m_pClonedFrom = NULL;
  32.  
  33.     m_nCurPos = 0;
  34.     m_nSize = nSize;
  35.     m_pvEnum = (BYTE*)pvEnum;
  36.     m_bNeedFree = bNeedFree;
  37.  
  38.     ASSERT_VALID(this);
  39. }
  40.  
  41. CEnumArray::~CEnumArray()
  42. {
  43.     ASSERT_VALID(this);
  44.  
  45.     // release the clone pointer (only for clones)
  46.     if (m_pClonedFrom != NULL)
  47.     {
  48.         m_pClonedFrom->InternalRelease();
  49.         ASSERT(!m_bNeedFree);
  50.     }
  51.  
  52.     // release the pointer (should only happen on non-clones)
  53.     if (m_bNeedFree)
  54.     {
  55.         ASSERT(m_pClonedFrom == NULL);
  56.         delete m_pvEnum;
  57.     }
  58. }
  59.  
  60. BOOL CEnumArray::OnNext(void* pv)
  61. {
  62.     ASSERT_VALID(this);
  63.  
  64.     if (m_nCurPos >= m_nSize)
  65.         return FALSE;
  66.  
  67.     memcpy(pv, &m_pvEnum[m_nCurPos*m_nSizeElem], m_nSizeElem);
  68.     ++m_nCurPos;
  69.     return TRUE;
  70. }
  71.  
  72. BOOL CEnumArray::OnSkip()
  73. {
  74.     ASSERT_VALID(this);
  75.  
  76.     if (m_nCurPos >= m_nSize)
  77.         return FALSE;
  78.  
  79.     return ++m_nCurPos < m_nSize;
  80. }
  81.  
  82. void CEnumArray::OnReset()
  83. {
  84.     ASSERT_VALID(this);
  85.  
  86.     m_nCurPos = 0;
  87. }
  88.  
  89. CEnumArray* CEnumArray::OnClone()
  90. {
  91.     ASSERT_VALID(this);
  92.  
  93.     // set up an exact copy of this object
  94.     //  (derivatives may have to replace this code)
  95.     CEnumArray* pClone;
  96.     pClone = new CEnumArray(m_nSizeElem, m_pvEnum, m_nSize);
  97.     ASSERT(pClone != NULL);
  98.     ASSERT(!pClone->m_bNeedFree);   // clones should never free themselves
  99.     pClone->m_nCurPos = m_nCurPos;
  100.  
  101.     // finally, return the clone to OLE
  102.     ASSERT_VALID(pClone);
  103.     return pClone;
  104. }
  105.  
  106. /////////////////////////////////////////////////////////////////////////////
  107. // CEnumArray::XEnumVOID implementation
  108.  
  109. STDMETHODIMP_(ULONG) CEnumArray::XEnumVOID::AddRef()
  110. {
  111.     METHOD_PROLOGUE_EX_(CEnumArray, EnumVOID)
  112.     return pThis->ExternalAddRef();
  113. }
  114.  
  115. STDMETHODIMP_(ULONG) CEnumArray::XEnumVOID::Release()
  116. {
  117.     METHOD_PROLOGUE_EX_(CEnumArray, EnumVOID)
  118.     return pThis->ExternalRelease();
  119. }
  120.  
  121. STDMETHODIMP CEnumArray::XEnumVOID::QueryInterface(
  122.     REFIID iid, LPVOID* ppvObj)
  123. {
  124.     METHOD_PROLOGUE_EX_(CEnumArray, EnumVOID)
  125.     return pThis->ExternalQueryInterface(&iid, ppvObj);
  126. }
  127.  
  128. STDMETHODIMP CEnumArray::XEnumVOID::Next(
  129.     ULONG celt, void* reelt, ULONG* pceltFetched)
  130. {
  131.     METHOD_PROLOGUE_EX(CEnumArray, EnumVOID);
  132.     ASSERT_VALID(pThis);
  133.  
  134.     if (pceltFetched != NULL)
  135.         *pceltFetched = 0;
  136.  
  137.     ASSERT(celt > 0);
  138.     ASSERT(celt == 1 || pceltFetched != NULL);
  139.  
  140.     BYTE* pchCur = (BYTE*)reelt;
  141.  
  142.     ULONG celtT = celt;
  143.     SCODE sc = E_UNEXPECTED;
  144.     TRY
  145.     {
  146.         while (celtT != 0 && pThis->OnNext((void*)pchCur))
  147.         {
  148.             pchCur += pThis->m_nSizeElem;
  149.             --celtT;
  150.         }
  151.         if (pceltFetched != NULL)
  152.             *pceltFetched = celt - celtT;
  153.         sc = celtT == 0 ? S_OK : S_FALSE;
  154.     }
  155.     END_TRY
  156.  
  157.     return sc;
  158. }
  159.  
  160. STDMETHODIMP CEnumArray::XEnumVOID::Skip(ULONG celt)
  161. {
  162.     METHOD_PROLOGUE_EX(CEnumArray, EnumVOID);
  163.     ASSERT_VALID(pThis);
  164.  
  165.     ULONG celtT = celt;
  166.     SCODE sc = E_UNEXPECTED;
  167.     TRY
  168.     {
  169.         while (celtT != 0 && pThis->OnSkip())
  170.             --celtT;
  171.         sc = celtT == 0 ? S_OK : S_FALSE;
  172.     }
  173.     END_TRY
  174.  
  175.     return celtT != 0 ? S_FALSE : S_OK;
  176. }
  177.  
  178. STDMETHODIMP CEnumArray::XEnumVOID::Reset()
  179. {
  180.     METHOD_PROLOGUE_EX(CEnumArray, EnumVOID);
  181.     ASSERT_VALID(pThis);
  182.  
  183.     pThis->OnReset();
  184.     return S_OK;
  185. }
  186.  
  187. STDMETHODIMP CEnumArray::XEnumVOID::Clone(IEnumVOID** ppenm)
  188. {
  189.     METHOD_PROLOGUE_EX(CEnumArray, EnumVOID);
  190.     ASSERT_VALID(pThis);
  191.  
  192.     *ppenm = NULL;
  193.  
  194.     SCODE sc = E_UNEXPECTED;
  195.     TRY
  196.     {
  197.         CEnumArray* pEnumHelper = pThis->OnClone();
  198.         ASSERT_VALID(pEnumHelper);
  199.  
  200.         // we use an extra reference to keep the original object alive
  201.         //  (the extra reference is removed in the clone's destructor)
  202.         if (pThis->m_pClonedFrom != NULL)
  203.             pEnumHelper->m_pClonedFrom = pThis->m_pClonedFrom;
  204.         else
  205.             pEnumHelper->m_pClonedFrom = pThis;
  206.         pEnumHelper->m_pClonedFrom->InternalAddRef();
  207.         *ppenm = &pEnumHelper->m_xEnumVOID;
  208.  
  209.         sc = S_OK;
  210.     }
  211.     END_TRY
  212.  
  213.     return sc;
  214. }
  215.  
  216. /////////////////////////////////////////////////////////////////////////////
  217.