home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / mfc / ole / inproc / enumvar.cpp next >
C/C++ Source or Header  |  1998-03-26  |  5KB  |  204 lines

  1. // enumvar.cpp : implementation file
  2. //
  3. // This is a part of the Microsoft Foundation Classes C++ library.
  4. // Copyright (C) 1992-1998 Microsoft Corporation
  5. // All rights reserved.
  6. //
  7. // This source code is only intended as a supplement to the
  8. // Microsoft Foundation Classes Reference and related
  9. // electronic documentation provided with the library.
  10. // See these sources for detailed information regarding the
  11. // Microsoft Foundation Classes product.
  12.  
  13. #include "stdafx.h"
  14. #include "inproc.h"
  15. #include "enumvar.h"
  16.  
  17. #ifdef _DEBUG
  18. #undef THIS_FILE
  19. static char BASED_CODE THIS_FILE[] = __FILE__;
  20. #endif
  21.  
  22. /////////////////////////////////////////////////////////////////////////////
  23. // CEnumVariant
  24.  
  25. IMPLEMENT_DYNCREATE(CEnumVariant, CCmdTarget)
  26.  
  27. CEnumVariant::CEnumVariant()
  28. {
  29.     m_nIndex = 0;
  30.     m_nCount = 0;
  31.     m_pContents = NULL;
  32.  
  33.     m_pClonedFrom = NULL;
  34.  
  35.     // To keep the application running as long as an OLE automation
  36.     //  object is active, the constructor calls AfxOleLockApp.
  37.  
  38.     AfxOleLockApp();
  39. }
  40.  
  41. CEnumVariant::~CEnumVariant()
  42. {
  43.     if (m_pClonedFrom != NULL)
  44.     {
  45.         m_pClonedFrom->ExternalRelease();
  46.     }
  47.     else
  48.     {
  49.         for (int i = 0; i < m_nCount; ++i)
  50.             VariantClear(&m_pContents[i]);
  51.         delete[] m_pContents;
  52.     }
  53.  
  54.     // To terminate the application when all objects created with
  55.     //  with OLE automation, the destructor calls AfxOleUnlockApp.
  56.  
  57.     AfxOleUnlockApp();
  58. }
  59.  
  60. void CEnumVariant::OnFinalRelease()
  61. {
  62.     // When the last reference for an automation object is released
  63.     //  OnFinalRelease is called.  This implementation deletes the
  64.     //  object.  Add additional cleanup required for your object before
  65.     //  deleting it from memory.
  66.  
  67.     delete this;
  68. }
  69.  
  70. void CEnumVariant::SetContents(VARIANT* pContents, int nCount, int nIndex)
  71. {
  72.     ASSERT(nIndex < nCount);
  73.     ASSERT(nCount == 0 || pContents != NULL);
  74.     ASSERT(pContents == NULL ||
  75.         AfxIsValidAddress(pContents, sizeof(VARIANT)*nCount, FALSE));
  76.  
  77.     m_nCount = nCount;
  78.     m_pContents = pContents;
  79.     m_nIndex = nIndex;
  80. }
  81.  
  82. BEGIN_MESSAGE_MAP(CEnumVariant, CCmdTarget)
  83.     //{{AFX_MSG_MAP(CEnumVariant)
  84.         // NOTE - the ClassWizard will add and remove mapping macros here.
  85.     //}}AFX_MSG_MAP
  86. END_MESSAGE_MAP()
  87.  
  88. /////////////////////////////////////////////////////////////////////////////
  89. // CEnumVariant interfaces
  90.  
  91. static void CopyVariantArray(VARIANT* pDest, VARIANT* pSrc, int nCount)
  92. {
  93.     for (int i = 0; i < nCount; ++i)
  94.         VariantInit(&pDest[i]);
  95.     for (i = 0; i < nCount; ++i)
  96.     {
  97.         SCODE sc = GetScode(VariantCopy(&pDest[i], &pSrc[i]));
  98.         if (sc != NOERROR)
  99.         {
  100.             while (--i >= 0)
  101.                 VariantClear(&pDest[i]);
  102.             AfxThrowMemoryException();
  103.         }
  104.     }
  105. }
  106.  
  107. BEGIN_INTERFACE_MAP(CEnumVariant, CCmdTarget)
  108.     INTERFACE_PART(CEnumVariant, IID_IEnumVARIANT, EnumVARIANT)
  109. END_INTERFACE_MAP()
  110.  
  111. STDMETHODIMP_(ULONG) CEnumVariant::XEnumVARIANT::AddRef()
  112. {
  113.     METHOD_PROLOGUE(CEnumVariant, EnumVARIANT)
  114.     return pThis->ExternalAddRef();
  115. }
  116.  
  117. STDMETHODIMP_(ULONG) CEnumVariant::XEnumVARIANT::Release()
  118. {
  119.     METHOD_PROLOGUE(CEnumVariant, EnumVARIANT)
  120.     return pThis->ExternalRelease();
  121. }
  122.  
  123. STDMETHODIMP CEnumVariant::XEnumVARIANT::QueryInterface(REFIID iid, void** ppvObj)
  124. {
  125.     METHOD_PROLOGUE(CEnumVariant, EnumVARIANT)
  126.     return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj) ;
  127. }
  128.  
  129. STDMETHODIMP CEnumVariant::XEnumVARIANT::Next(ULONG celt, VARIANT* rgvar, ULONG* pceltFetched)
  130. {
  131.     METHOD_PROLOGUE(CEnumVariant, EnumVARIANT)
  132.  
  133.     ASSERT(celt > 0);
  134.     ASSERT(celt == 1 || pceltFetched != NULL);
  135.  
  136.     if (pceltFetched != NULL)
  137.         *pceltFetched = 0;
  138.  
  139.     int nFetched = min(pThis->m_nCount - pThis->m_nIndex, (int)celt);
  140.  
  141.     TRY
  142.     {
  143.         CopyVariantArray(rgvar, pThis->m_pContents + pThis->m_nIndex, nFetched);
  144.     }
  145.     CATCH_ALL(e)
  146.     {
  147.         return E_OUTOFMEMORY;
  148.     }
  149.     END_CATCH_ALL
  150.  
  151.     pThis->m_nIndex += nFetched;
  152.     if (pceltFetched != NULL)
  153.         *pceltFetched = nFetched;
  154.  
  155.     return nFetched == (int)celt ? NOERROR : S_FALSE;
  156. }
  157.  
  158. STDMETHODIMP CEnumVariant::XEnumVARIANT::Skip(unsigned long celt)
  159. {
  160.     METHOD_PROLOGUE(CEnumVariant, EnumVARIANT)
  161.  
  162.     int nSkip = (int)celt;
  163.     if (nSkip + pThis->m_nIndex > pThis->m_nCount)
  164.         nSkip = pThis->m_nCount - pThis->m_nIndex;
  165.     pThis->m_nIndex += nSkip;
  166.  
  167.     return nSkip == (int)celt ? NOERROR : S_FALSE;
  168. }
  169.  
  170. STDMETHODIMP CEnumVariant::XEnumVARIANT::Reset()
  171. {
  172.     METHOD_PROLOGUE(CEnumVariant, EnumVARIANT)
  173.  
  174.     pThis->m_nIndex = 0;
  175.  
  176.     return NOERROR;
  177. }
  178.  
  179. STDMETHODIMP CEnumVariant::XEnumVARIANT::Clone(IEnumVARIANT** ppenum)
  180. {
  181.     METHOD_PROLOGUE(CEnumVariant, EnumVARIANT)
  182.  
  183.     CEnumVariant* pClone;
  184.     TRY
  185.     {
  186.         pClone = new CEnumVariant;
  187.         pClone->SetContents(pThis->m_pContents, pThis->m_nCount, pThis->m_nIndex);
  188.  
  189.         pClone->m_pClonedFrom = pThis;
  190.         pThis->ExternalAddRef();
  191.     }
  192.     CATCH_ALL(e)
  193.     {
  194.         return E_OUTOFMEMORY;
  195.     }
  196.     END_CATCH_ALL
  197.     *ppenum = &pClone->m_xEnumVARIANT;
  198.  
  199.     return NOERROR;
  200. }
  201.  
  202. /////////////////////////////////////////////////////////////////////////////
  203. // CEnumVariant message handlers
  204.