IENUMCP.CPP

/* 
* IENUMCP.CPP
*
* Standard implementation of an IConnectionPoint enumerator with the
* IEnumConnectionPoints interface that will generally not need
* modification.
*
* Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
*
* Kraig Brockschmidt, Microsoft
* Internet : kraigb@microsoft.com
* Compuserve: >INTERNET:kraigb@microsoft.com
*/


#include "ienumcp.h"


/*
* CEnumConnectionPoints::CEnumConnectionPoints
* CEnumConnectionPoints::~CEnumConnectionPoints
*
* Parameters (Constructor):
* pUnkRef LPUNKNOWN to use for reference counting.
* cPoints ULONG number of connection points in rgpCP
* rgpCP LPCONNECTIONPOINT * to the array to enumerate.
*/

CEnumConnectionPoints::CEnumConnectionPoints(LPUNKNOWN pUnkRef
, ULONG cPoints, LPCONNECTIONPOINT *rgpCP)
{
UINT i;

m_cRef=0;
m_pUnkRef=pUnkRef;

m_iCur=0;
m_cPoints=cPoints;
m_rgpCP=new LPCONNECTIONPOINT[(UINT)cPoints];

if (NULL!=m_rgpCP)
{
for (i=0; i < cPoints; i++)
m_rgpCP[i]=rgpCP[i];
}

return;
}


CEnumConnectionPoints::~CEnumConnectionPoints(void)
{
if (NULL!=m_rgpCP)
delete [] m_rgpCP;

return;
}






/*
* CEnumConnectionPoints::QueryInterface
* CEnumConnectionPoints::AddRef
* CEnumConnectionPoints::Release
*
* Purpose:
* IUnknown members for CEnumConnectionPoints object.
*/

STDMETHODIMP CEnumConnectionPoints::QueryInterface(REFIID riid
, LPVOID *ppv)
{
*ppv=NULL;

/*
* Enumerators are separate objects, not the data object, so
* we only need to support out IUnknown and IEnumConnectionPoints
* interfaces here with no concern for aggregation.
*/
if (IID_IUnknown==riid || IID_IEnumConnectionPoints==riid)
*ppv=(LPVOID)this;

if (NULL!=*ppv)
{
((LPUNKNOWN)*ppv)->AddRef();
return NOERROR;
}

return ResultFromScode(E_NOINTERFACE);
}


STDMETHODIMP_(ULONG) CEnumConnectionPoints::AddRef(void)
{
++m_cRef;
m_pUnkRef->AddRef();
return m_cRef;
}

STDMETHODIMP_(ULONG) CEnumConnectionPoints::Release(void)
{
m_pUnkRef->Release();

if (0L!=--m_cRef)
return m_cRef;

delete this;
return 0;
}





/*
* CEnumConnectionPoints::Next
*
* Purpose:
* Returns the next element in the enumeration.
*
* Parameters:
* cPoints ULONG number of connection points to return.
* pCP LPCONNECTIONPOINT in which to store the returned
* pointers.
* pulEnum ULONG * in which to return how many we
* enumerated.
*
* Return Value:
* HRESULT NOERROR if successful, S_FALSE otherwise,
*/

STDMETHODIMP CEnumConnectionPoints::Next(ULONG cPoints
, LPCONNECTIONPOINT *pCP, ULONG *pulEnum)
{
ULONG cReturn=0L;

if (NULL==m_rgpCP)
return ResultFromScode(S_FALSE);

if (NULL==pulEnum)
{
if (1L!=cPoints)
return ResultFromScode(E_POINTER);
}
else
*pulEnum=0L;

if (NULL==pCP || m_iCur >= m_cPoints)
return ResultFromScode(S_FALSE);

while (m_iCur < m_cPoints && cPoints > 0)
{
*pCP=m_rgpCP[m_iCur++];

if (NULL!=*pCP)
(*pCP)->AddRef();

pCP++;
cReturn++;
cPoints--;
}

if (NULL!=pulEnum)
*pulEnum=cReturn;

return NOERROR;
}







/*
* CEnumConnectionPoints::Skip
*
* Purpose:
* Skips the next n elements in the enumeration.
*
* Parameters:
* cSkip ULONG number of elements to skip.
*
* Return Value:
* HRESULT NOERROR if successful, S_FALSE if we could not
* skip the requested number.
*/

STDMETHODIMP CEnumConnectionPoints::Skip(ULONG cSkip)
{
if (((m_iCur+cSkip) >= m_cPoints) || NULL==m_rgpCP)
return ResultFromScode(S_FALSE);

m_iCur+=cSkip;
return NOERROR;
}






/*
* CEnumConnectionPoints::Reset
*
* Purpose:
* Resets the current element index in the enumeration to zero.
*
* Parameters:
* None
*/

STDMETHODIMP CEnumConnectionPoints::Reset(void)
{
m_iCur=0;
return NOERROR;
}






/*
* CEnumConnectionPoints::Clone
*
* Purpose:
* Returns another IEnumConnectionPoints with the same state as ourselves.
*
* Parameters:
* ppEnum LPENUMCONNECTIONPOINTS * in which to return the
* new object.
*/

STDMETHODIMP CEnumConnectionPoints::Clone
(LPENUMCONNECTIONPOINTS *ppEnum)
{
PCEnumConnectionPoints pNew;

*ppEnum=NULL;

//Create the clone
pNew=new CEnumConnectionPoints(m_pUnkRef, m_cPoints, m_rgpCP);

if (NULL==pNew)
return ResultFromScode(E_OUTOFMEMORY);

pNew->AddRef();
pNew->m_iCur=m_iCur;

*ppEnum=pNew;
return NOERROR;
}