Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

233 lines
3.9 KiB

#ifndef _NMENUM_H_
#define _NMENUM_H_
#include "oblist.h"
// IEnumNmX
//
template <class IEnumNmX, const IID* piidEnumNmX, class INmX, class CNmX>
class CEnumNmX : public IEnumNmX
{
private:
INmX **m_pList; // The list
int m_iCurr; // Current index number
int m_iMax; // Maximum index
ULONG m_cRef;
public:
CEnumNmX(COBLIST * pList, int cItems) :
m_iCurr(0),
m_iMax(0),
m_pList(NULL),
m_cRef(1)
{
if ((NULL != pList) && (0 != cItems))
{
m_pList = new INmX* [cItems];
if (NULL != m_pList)
{
POSITION pos = pList->GetHeadPosition();
while ((NULL != pos) && (m_iMax < cItems))
{
INmX *pINmX = (INmX *) (CNmX *) pList->GetNext(pos);
ASSERT(NULL != pINmX);
pINmX->AddRef();
m_pList[m_iMax] = pINmX;
m_iMax++;
}
}
}
// ApiDebugMsg(("CEnumNmX - Constructed(%08X)", this));
}
CEnumNmX(COBLIST * pList)
{
int cItems = 0;
if (NULL != pList)
{
POSITION pos = pList->GetHeadPosition();
while (NULL != pos)
{
pList->GetNext(pos);
cItems++;
}
}
CEnumNmX(pList, cItems);
}
CEnumNmX(CNmX **rgpNmX, ULONG cItems) :
m_iCurr(0),
m_iMax(0),
m_pList(NULL),
m_cRef(1)
{
if (NULL != rgpNmX)
{
m_pList = new INmX* [cItems];
if (NULL != m_pList)
{
m_iMax = cItems;
for (int i = 0; i < m_iMax; ++i)
{
ASSERT(NULL != rgpNmX[i]);
rgpNmX[i]->AddRef();
m_pList[i] = rgpNmX[i];
}
}
}
// ApiDebugMsg(("CEnumNmX - Constructed(%08X)", this));
}
~CEnumNmX(void)
{
for (int i = 0; i < m_iMax; ++i)
{
ASSERT(NULL != m_pList[i]);
m_pList[i]->Release();
}
delete m_pList;
// ApiDebugMsg(("CEnumNmX - Destructed (%08X)", this));
}
STDMETHODIMP_(ULONG) AddRef(void)
{
return ++m_cRef;
}
STDMETHODIMP_(ULONG) Release(void)
{
ASSERT(m_cRef > 0);
if (m_cRef > 0)
{
m_cRef--;
}
ULONG cRef = m_cRef;
if (0 == cRef)
{
delete this;
}
return cRef;
}
STDMETHODIMP QueryInterface(REFIID riid, PVOID *ppv)
{
HRESULT hr = S_OK;
if ((riid == *piidEnumNmX) || (riid == IID_IUnknown))
{
*ppv = (IEnumNmX *)this;
// ApiDebugMsg(("CEnumNmX::QueryInterface(): Returning IEnumNmX."));
}
else
{
hr = E_NOINTERFACE;
*ppv = NULL;
// ApiDebugMsg(("CEnumNmX::QueryInterface(): Called on unknown interface."));
}
if (S_OK == hr)
{
AddRef();
}
return hr;
}
STDMETHODIMP Next(ULONG cItem, INmX **rgpNmX, ULONG *pcFetched)
{
ULONG cCopied = 0;
if ((0 == cItem) && (NULL == rgpNmX) && (NULL != pcFetched))
{
// Return the number of remaining elements
*pcFetched = m_iMax - m_iCurr;
return S_OK;
}
if ((NULL == rgpNmX) || ((NULL == pcFetched) && (cItem != 1)))
return E_POINTER;
if (NULL != m_pList)
{
while ((cCopied < cItem) && (m_iCurr < m_iMax))
{
*rgpNmX = m_pList[m_iCurr];
ASSERT(NULL != *rgpNmX);
(*rgpNmX)->AddRef();
rgpNmX++;
cCopied++;
m_iCurr++;
}
}
if (pcFetched != NULL)
*pcFetched = cCopied;
return ((cItem == cCopied) ? S_OK : S_FALSE);
}
STDMETHODIMP Skip(ULONG cItem)
{
m_iCurr += cItem;
if (m_iCurr >= m_iMax)
{
// Past the end of the list
m_iCurr = m_iMax;
return S_FALSE;
}
return S_OK;
}
STDMETHODIMP Reset()
{
m_iCurr = 0;
return S_OK;
}
STDMETHODIMP Clone(IEnumNmX **ppEnum)
{
if (NULL == ppEnum)
return E_POINTER;
HRESULT hr = S_OK;
CEnumNmX * pEnum = new CEnumNmX(NULL, 0);
if (NULL == pEnum)
{
hr = E_OUTOFMEMORY;
}
else if (NULL != m_pList)
{
pEnum->m_pList = new INmX*[m_iMax];
if (NULL == pEnum->m_pList)
{
delete pEnum;
pEnum = NULL;
hr = E_OUTOFMEMORY;
}
else
{
pEnum->m_iCurr = m_iCurr;
pEnum->m_iMax = m_iMax;
for (int i = 0; i < m_iMax; ++i)
{
ASSERT(NULL != m_pList[i]);
m_pList[i]->AddRef();
pEnum->m_pList[i] = m_pList[i];
}
}
}
*ppEnum = pEnum;
return hr;
}
};
#endif // _NMENUM_H_