home *** CD-ROM | disk | FTP | other *** search
- // This is a part of the Microsoft Foundation Classes C++ library.
- // Copyright (C) 1992-1998 Microsoft Corporation
- // All rights reserved.
- //
- // This source code is only intended as a supplement to the
- // Microsoft Foundation Classes Reference and related
- // electronic documentation provided with the library.
- // See these sources for detailed information regarding the
- // Microsoft Foundation Classes product.
-
- #include "stdafx.h"
-
- #ifdef AFX_OLE3_SEG
- #pragma code_seg(AFX_OLE3_SEG)
- #endif
-
- #ifdef _DEBUG
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
-
- #define new DEBUG_NEW
-
- /////////////////////////////////////////////////////////////////////////////
- // CEnumArray (provides OLE enumerator for arbitrary items in an array)
-
- CEnumArray::CEnumArray(size_t nSizeElem, const void* pvEnum, UINT nSize,
- BOOL bNeedFree)
- {
- m_nSizeElem = nSizeElem;
- m_pClonedFrom = NULL;
-
- m_nCurPos = 0;
- m_nSize = nSize;
- m_pvEnum = (BYTE*)pvEnum;
- m_bNeedFree = bNeedFree;
-
- ASSERT_VALID(this);
- }
-
- CEnumArray::~CEnumArray()
- {
- ASSERT_VALID(this);
-
- // release the clone pointer (only for clones)
- if (m_pClonedFrom != NULL)
- {
- m_pClonedFrom->InternalRelease();
- ASSERT(!m_bNeedFree);
- }
-
- // release the pointer (should only happen on non-clones)
- if (m_bNeedFree)
- {
- ASSERT(m_pClonedFrom == NULL);
- delete m_pvEnum;
- }
- }
-
- BOOL CEnumArray::OnNext(void* pv)
- {
- ASSERT_VALID(this);
-
- if (m_nCurPos >= m_nSize)
- return FALSE;
-
- memcpy(pv, &m_pvEnum[m_nCurPos*m_nSizeElem], m_nSizeElem);
- ++m_nCurPos;
- return TRUE;
- }
-
- BOOL CEnumArray::OnSkip()
- {
- ASSERT_VALID(this);
-
- if (m_nCurPos >= m_nSize)
- return FALSE;
-
- return ++m_nCurPos < m_nSize;
- }
-
- void CEnumArray::OnReset()
- {
- ASSERT_VALID(this);
-
- m_nCurPos = 0;
- }
-
- CEnumArray* CEnumArray::OnClone()
- {
- ASSERT_VALID(this);
-
- // set up an exact copy of this object
- // (derivatives may have to replace this code)
- CEnumArray* pClone;
- pClone = new CEnumArray(m_nSizeElem, m_pvEnum, m_nSize);
- ASSERT(pClone != NULL);
- ASSERT(!pClone->m_bNeedFree); // clones should never free themselves
- pClone->m_nCurPos = m_nCurPos;
-
- // finally, return the clone to OLE
- ASSERT_VALID(pClone);
- return pClone;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // CEnumArray::XEnumVOID implementation
-
- STDMETHODIMP_(ULONG) CEnumArray::XEnumVOID::AddRef()
- {
- METHOD_PROLOGUE_EX_(CEnumArray, EnumVOID)
- return pThis->ExternalAddRef();
- }
-
- STDMETHODIMP_(ULONG) CEnumArray::XEnumVOID::Release()
- {
- METHOD_PROLOGUE_EX_(CEnumArray, EnumVOID)
- return pThis->ExternalRelease();
- }
-
- STDMETHODIMP CEnumArray::XEnumVOID::QueryInterface(
- REFIID iid, LPVOID* ppvObj)
- {
- METHOD_PROLOGUE_EX_(CEnumArray, EnumVOID)
- return pThis->ExternalQueryInterface(&iid, ppvObj);
- }
-
- STDMETHODIMP CEnumArray::XEnumVOID::Next(
- ULONG celt, void* reelt, ULONG* pceltFetched)
- {
- METHOD_PROLOGUE_EX(CEnumArray, EnumVOID);
- ASSERT_VALID(pThis);
-
- if (pceltFetched != NULL)
- *pceltFetched = 0;
-
- ASSERT(celt > 0);
- ASSERT(celt == 1 || pceltFetched != NULL);
-
- BYTE* pchCur = (BYTE*)reelt;
-
- ULONG celtT = celt;
- SCODE sc = E_UNEXPECTED;
- TRY
- {
- while (celtT != 0 && pThis->OnNext((void*)pchCur))
- {
- pchCur += pThis->m_nSizeElem;
- --celtT;
- }
- if (pceltFetched != NULL)
- *pceltFetched = celt - celtT;
- sc = celtT == 0 ? S_OK : S_FALSE;
- }
- END_TRY
-
- return sc;
- }
-
- STDMETHODIMP CEnumArray::XEnumVOID::Skip(ULONG celt)
- {
- METHOD_PROLOGUE_EX(CEnumArray, EnumVOID);
- ASSERT_VALID(pThis);
-
- ULONG celtT = celt;
- SCODE sc = E_UNEXPECTED;
- TRY
- {
- while (celtT != 0 && pThis->OnSkip())
- --celtT;
- sc = celtT == 0 ? S_OK : S_FALSE;
- }
- END_TRY
-
- return celtT != 0 ? S_FALSE : S_OK;
- }
-
- STDMETHODIMP CEnumArray::XEnumVOID::Reset()
- {
- METHOD_PROLOGUE_EX(CEnumArray, EnumVOID);
- ASSERT_VALID(pThis);
-
- pThis->OnReset();
- return S_OK;
- }
-
- STDMETHODIMP CEnumArray::XEnumVOID::Clone(IEnumVOID** ppenm)
- {
- METHOD_PROLOGUE_EX(CEnumArray, EnumVOID);
- ASSERT_VALID(pThis);
-
- *ppenm = NULL;
-
- SCODE sc = E_UNEXPECTED;
- TRY
- {
- CEnumArray* pEnumHelper = pThis->OnClone();
- ASSERT_VALID(pEnumHelper);
-
- // we use an extra reference to keep the original object alive
- // (the extra reference is removed in the clone's destructor)
- if (pThis->m_pClonedFrom != NULL)
- pEnumHelper->m_pClonedFrom = pThis->m_pClonedFrom;
- else
- pEnumHelper->m_pClonedFrom = pThis;
- pEnumHelper->m_pClonedFrom->InternalAddRef();
- *ppenm = &pEnumHelper->m_xEnumVOID;
-
- sc = S_OK;
- }
- END_TRY
-
- return sc;
- }
-
- /////////////////////////////////////////////////////////////////////////////
-