GME  13
EnumVar.cpp
Go to the documentation of this file.
00001 // EnumVar.cpp : implementation file
00002 //
00003 
00004 #include "stdafx.h"
00005 #include "gme.h"
00006 #include "EnumVar.h"
00007 
00008 #ifdef _DEBUG
00009 #undef THIS_FILE
00010 static char BASED_CODE THIS_FILE[] = __FILE__;
00011 #endif
00012 
00014 // CEnumVariant
00015 
00016 IMPLEMENT_DYNCREATE(CEnumVariant, CCmdTarget)
00017 
00018 CEnumVariant::CEnumVariant()
00019 {
00020         m_nIndex = 0;
00021         m_nCount = 0;
00022         m_pContents = NULL;
00023 
00024         m_pClonedFrom = NULL;
00025 
00026         // To keep the application running as long as an OLE automation
00027         //  object is active, the constructor calls AfxOleLockApp.
00028 
00029         AfxOleLockApp();
00030 }
00031 
00032 CEnumVariant::~CEnumVariant()
00033 {
00034         if (m_pClonedFrom != NULL)
00035         {
00036                 m_pClonedFrom->ExternalRelease();
00037         }
00038         else
00039         {
00040                 for (int i = 0; i < m_nCount; ++i)
00041                         VariantClear(&m_pContents[i]);
00042                 delete[] m_pContents;
00043         }
00044 
00045         // To terminate the application when all objects created with
00046         //  with OLE automation, the destructor calls AfxOleUnlockApp.
00047 
00048         AfxOleUnlockApp();
00049 }
00050 
00051 void CEnumVariant::OnFinalRelease()
00052 {
00053         // When the last reference for an automation object is released
00054         //  OnFinalRelease is called.  This implementation deletes the
00055         //  object.  Add additional cleanup required for your object before
00056         //  deleting it from memory.
00057 
00058         delete this;
00059 }
00060 
00061 void CEnumVariant::SetContents(VARIANT* pContents, int nCount, int nIndex)
00062 {
00063         ASSERT(nIndex < nCount);
00064         ASSERT(nCount == 0 || pContents != NULL);
00065         ASSERT(pContents == NULL ||
00066                 AfxIsValidAddress(pContents, sizeof(VARIANT)*nCount, FALSE));
00067 
00068         m_nCount = nCount;
00069         m_pContents = pContents;
00070         m_nIndex = nIndex;
00071 }
00072 
00073 BEGIN_MESSAGE_MAP(CEnumVariant, CCmdTarget)
00074         //{{AFX_MSG_MAP(CEnumVariant)
00075                 // NOTE - the ClassWizard will add and remove mapping macros here.
00076         //}}AFX_MSG_MAP
00077 END_MESSAGE_MAP()
00078 
00080 // CEnumVariant interfaces
00081 
00082 static void CopyVariantArray(VARIANT* pDest, VARIANT* pSrc, int nCount)
00083 {
00084         for (int i = 0; i < nCount; ++i)
00085                 VariantInit(&pDest[i]);
00086         for (int i = 0; i < nCount; ++i)
00087         {
00088                 SCODE sc = GetScode(VariantCopy(&pDest[i], &pSrc[i]));
00089                 if (sc != NOERROR)
00090                 {
00091                         while (--i >= 0)
00092                                 VariantClear(&pDest[i]);
00093                         AfxThrowMemoryException();
00094                 }
00095         }
00096 }
00097 
00098 BEGIN_INTERFACE_MAP(CEnumVariant, CCmdTarget)
00099         INTERFACE_PART(CEnumVariant, IID_IEnumVARIANT, EnumVARIANT)
00100 END_INTERFACE_MAP()
00101 
00102 STDMETHODIMP_(ULONG) CEnumVariant::XEnumVARIANT::AddRef()
00103 {
00104         METHOD_PROLOGUE(CEnumVariant, EnumVARIANT)
00105         return pThis->ExternalAddRef();
00106 }
00107 
00108 STDMETHODIMP_(ULONG) CEnumVariant::XEnumVARIANT::Release()
00109 {
00110         METHOD_PROLOGUE(CEnumVariant, EnumVARIANT)
00111         return pThis->ExternalRelease();
00112 }
00113 
00114 STDMETHODIMP CEnumVariant::XEnumVARIANT::QueryInterface(REFIID iid, void** ppvObj)
00115 {
00116         METHOD_PROLOGUE(CEnumVariant, EnumVARIANT)
00117         return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj) ;
00118 }
00119 
00120 STDMETHODIMP CEnumVariant::XEnumVARIANT::Next(ULONG celt, VARIANT* rgvar, ULONG* pceltFetched)
00121 {
00122         METHOD_PROLOGUE(CEnumVariant, EnumVARIANT)
00123 
00124         ASSERT(celt > 0);
00125         ASSERT(celt == 1 || pceltFetched != NULL);
00126 
00127         if (pceltFetched != NULL)
00128                 *pceltFetched = 0;
00129 
00130         int nFetched = min(pThis->m_nCount - pThis->m_nIndex, (int)celt);
00131 
00132         TRY
00133         {
00134                 CopyVariantArray(rgvar, pThis->m_pContents + pThis->m_nIndex, nFetched);
00135         }
00136         CATCH_ALL(e)
00137         {
00138                 return E_OUTOFMEMORY;
00139         }
00140         END_CATCH_ALL
00141 
00142         pThis->m_nIndex += nFetched;
00143         if (pceltFetched != NULL)
00144                 *pceltFetched = nFetched;
00145 
00146         return nFetched == (int)celt ? NOERROR : S_FALSE;
00147 }
00148 
00149 STDMETHODIMP CEnumVariant::XEnumVARIANT::Skip(unsigned long celt)
00150 {
00151         METHOD_PROLOGUE(CEnumVariant, EnumVARIANT)
00152 
00153         int nSkip = (int)celt;
00154         if (nSkip + pThis->m_nIndex > pThis->m_nCount)
00155                 nSkip = pThis->m_nCount - pThis->m_nIndex;
00156         pThis->m_nIndex += nSkip;
00157 
00158         return nSkip == (int)celt ? NOERROR : S_FALSE;
00159 }
00160 
00161 STDMETHODIMP CEnumVariant::XEnumVARIANT::Reset()
00162 {
00163         METHOD_PROLOGUE(CEnumVariant, EnumVARIANT)
00164 
00165         pThis->m_nIndex = 0;
00166 
00167         return NOERROR;
00168 }
00169 
00170 STDMETHODIMP CEnumVariant::XEnumVARIANT::Clone(IEnumVARIANT** ppenum)
00171 {
00172         METHOD_PROLOGUE(CEnumVariant, EnumVARIANT)
00173 
00174         CEnumVariant* pClone;
00175         TRY
00176         {
00177                 pClone = new CEnumVariant;
00178                 pClone->SetContents(pThis->m_pContents, pThis->m_nCount, pThis->m_nIndex);
00179 
00180                 pClone->m_pClonedFrom = pThis;
00181                 pThis->ExternalAddRef();
00182         }
00183         CATCH_ALL(e)
00184         {
00185                 return E_OUTOFMEMORY;
00186         }
00187         END_CATCH_ALL
00188         *ppenum = &pClone->m_xEnumVARIANT;
00189 
00190         return NOERROR;
00191 }
00192 
00194 // CEnumVariant message handlers