mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
217 lines
4.4 KiB
217 lines
4.4 KiB
// This is a part of the Microsoft Foundation Classes C++ library.
|
|
// Copyright (C) 1992-1995 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 nFetched = 0;
|
|
|
|
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;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|