GME
13
|
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