ENUMSTAT.C

/************************************************************************* 
**
** OLE 2 Utility Code
**
** enumstat.c
**
** This file contains a standard implementation of IEnumStatData
** interface.
** This file is part of the OLE 2.0 User Interface support library.
**
** (c) Copyright Microsoft Corp. 1990 - 1996 All Rights Reserved
**
*************************************************************************/

#define STRICT 1
#include "olestd.h"


typedef struct tagOleStdEnumStatData {
IEnumSTATDATAVtbl FAR* lpVtbl;
ULONG m_dwRefs; /* referance count */
ULONG m_nIndex; /* current index in list */
ULONG m_nCount; /* how many items in list */
LPSTATDATA m_lpStat; /* list of STATDATA */
} OLESTDENUMSTATDATA, FAR* LPOLESTDENUMSTATDATA;

VOID OleStdEnumStatData_Destroy(LPOLESTDENUMSTATDATA pStat);

STDMETHODIMP OleStdEnumStatData_QueryInterface(
LPENUMSTATDATA lpThis, REFIID riid, LPVOID FAR* ppobj);
STDMETHODIMP_(ULONG) OleStdEnumStatData_AddRef(LPENUMSTATDATA lpThis);
STDMETHODIMP_(ULONG) OleStdEnumStatData_Release(LPENUMSTATDATA lpThis);
STDMETHODIMP OleStdEnumStatData_Next(LPENUMSTATDATA lpThis, ULONG celt,
LPSTATDATA rgelt, ULONG FAR* pceltFetched);
STDMETHODIMP OleStdEnumStatData_Skip(LPENUMSTATDATA lpThis, ULONG celt);
STDMETHODIMP OleStdEnumStatData_Reset(LPENUMSTATDATA lpThis);
STDMETHODIMP OleStdEnumStatData_Clone(LPENUMSTATDATA lpThis,
LPENUMSTATDATA FAR* ppenum);

static IEnumSTATDATAVtbl g_EnumSTATDATAVtbl = {
OleStdEnumStatData_QueryInterface,
OleStdEnumStatData_AddRef,
OleStdEnumStatData_Release,
OleStdEnumStatData_Next,
OleStdEnumStatData_Skip,
OleStdEnumStatData_Reset,
OleStdEnumStatData_Clone,
};

/////////////////////////////////////////////////////////////////////////////

STDAPI_(BOOL)
OleStdCopyStatData(LPSTATDATA pDest, LPSTATDATA pSrc)
//----------------------------------------------------------------------------
//
//----------------------------------------------------------------------------
{
if ((pDest == NULL) || (pSrc == NULL)) {
return FALSE;
}

if (OleStdCopyFormatEtc(&pDest->formatetc, &pSrc->formatetc) == FALSE) {
return FALSE;
}

pDest->advf = pSrc->advf;
pDest->pAdvSink = pSrc->pAdvSink;
pDest->dwConnection = pSrc->dwConnection;

if (pDest->pAdvSink != NULL) {
pDest->pAdvSink->lpVtbl->AddRef(pDest->pAdvSink);
}

return TRUE;

} /* OleStdCopyStatData()
*/

STDAPI_(LPENUMSTATDATA)
OleStdEnumStatData_Create(ULONG nCount, LPSTATDATA lpStatOrg)
//----------------------------------------------------------------------------
//
//----------------------------------------------------------------------------
{
LPMALLOC lpMalloc=NULL;
LPOLESTDENUMSTATDATA lpSD=NULL;
DWORD dwSize;
WORD i;
HRESULT hRes;

hRes = CoGetMalloc(MEMCTX_TASK, &lpMalloc);
if (hRes != NOERROR) {
return NULL;
}

lpSD = (LPOLESTDENUMSTATDATA)lpMalloc->lpVtbl->Alloc(lpMalloc,
sizeof(OLESTDENUMSTATDATA));
if (lpSD == NULL) {
goto errReturn;
}

lpSD->lpVtbl = &g_EnumSTATDATAVtbl;
lpSD->m_dwRefs = 1;
lpSD->m_nCount = nCount;
lpSD->m_nIndex = 0;

dwSize = sizeof(STATDATA) * lpSD->m_nCount;

lpSD->m_lpStat = (LPSTATDATA)lpMalloc->lpVtbl->Alloc(lpMalloc, dwSize);
if (lpSD->m_lpStat == NULL)
goto errReturn;

lpMalloc->lpVtbl->Release(lpMalloc);

for (i=0; i<nCount; i++) {
OleStdCopyStatData(
(LPSTATDATA)&(lpSD->m_lpStat[i]), (LPSTATDATA)&(lpStatOrg[i]));
}

g_dwObjectCount++ ;

return (LPENUMSTATDATA)lpSD;

errReturn:
if (lpSD != NULL)
lpMalloc->lpVtbl->Free(lpMalloc, lpSD);

if (lpMalloc != NULL)
lpMalloc->lpVtbl->Release(lpMalloc);

return NULL;

} /* OleStdEnumStatData_Create()
*/


VOID
OleStdEnumStatData_Destroy(LPOLESTDENUMSTATDATA lpSD)
//----------------------------------------------------------------------------
//
//----------------------------------------------------------------------------
{
LPMALLOC lpMalloc=NULL;
WORD i;

if (lpSD != NULL) {

if (CoGetMalloc(MEMCTX_TASK, &lpMalloc) == NOERROR) {

/* NOTE: we MUST free any memory that was allocated for
** TARGETDEVICES contained within the STATDATA elements.
*/
for (i=0; i<lpSD->m_nCount; i++) {
if( lpSD->m_lpStat[i].pAdvSink )
lpSD->m_lpStat[i].pAdvSink->lpVtbl->Release(lpSD->m_lpStat[i].pAdvSink);

OleStdFree(lpSD->m_lpStat[i].formatetc.ptd);
}

if (lpSD->m_lpStat != NULL) {
lpMalloc->lpVtbl->Free(lpMalloc, lpSD->m_lpStat);
}

lpMalloc->lpVtbl->Free(lpMalloc, lpSD);
lpMalloc->lpVtbl->Release(lpMalloc);
}
}

g_dwObjectCount-- ;

} /* OleStdEnumStatData_Destroy()
*/


STDMETHODIMP
OleStdEnumStatData_QueryInterface(
LPENUMSTATDATA lpThis, REFIID riid, LPVOID FAR* ppobj)
//----------------------------------------------------------------------------
//
//----------------------------------------------------------------------------
{
LPOLESTDENUMSTATDATA lpSD = (LPOLESTDENUMSTATDATA)lpThis;
*ppobj = NULL;

if (IsEqualIID(riid,&IID_IUnknown) || IsEqualIID(riid,&IID_IEnumSTATDATA)){
*ppobj = (LPVOID)lpSD;
}

if (*ppobj == NULL) return E_NOINTERFACE;
else{
OleStdEnumStatData_AddRef(lpThis);
return NOERROR;
}

} /* OleStdEnumStatData_QueryInterface()
*/


STDMETHODIMP_(ULONG)
OleStdEnumStatData_AddRef(LPENUMSTATDATA lpThis)
//----------------------------------------------------------------------------
//
//----------------------------------------------------------------------------
{
LPOLESTDENUMSTATDATA lpSD = (LPOLESTDENUMSTATDATA)lpThis;
return lpSD->m_dwRefs++;

} /* OleStdEnumStatData_AddRef()
*/


STDMETHODIMP_(ULONG)
OleStdEnumStatData_Release(LPENUMSTATDATA lpThis)
//----------------------------------------------------------------------------
//
//----------------------------------------------------------------------------
{
LPOLESTDENUMSTATDATA lpSD = (LPOLESTDENUMSTATDATA)lpThis;
DWORD dwRefs = --lpSD->m_dwRefs;

if (dwRefs == 0)
OleStdEnumStatData_Destroy(lpSD);

return dwRefs;

} /* OleStdEnumStatData_Release()
*/


STDMETHODIMP
OleStdEnumStatData_Next(LPENUMSTATDATA lpThis, ULONG celt, LPSTATDATA rgelt,
ULONG FAR* pceltFetched)
//----------------------------------------------------------------------------
//
//----------------------------------------------------------------------------
{
LPOLESTDENUMSTATDATA lpSD = (LPOLESTDENUMSTATDATA)lpThis;
ULONG i=0;
ULONG nOffset;

if (rgelt == NULL) {
return E_INVALIDARG;
}

while (i < celt) {
nOffset = lpSD->m_nIndex + i;

if (nOffset < lpSD->m_nCount) {
OleStdCopyStatData(
(LPSTATDATA)&(rgelt[i]), (LPSTATDATA)&(lpSD->m_lpStat[nOffset]));
i++;
}else{
break;
}
}

lpSD->m_nIndex += (WORD)i;

if (pceltFetched != NULL) {
*pceltFetched = i;
}

if (i != celt) {
return S_FALSE;
}

return NOERROR;
} /* OleStdEnumStatData_Next()
*/


STDMETHODIMP
OleStdEnumStatData_Skip(LPENUMSTATDATA lpThis, ULONG celt)
//----------------------------------------------------------------------------
//
//----------------------------------------------------------------------------
{
LPOLESTDENUMSTATDATA lpSD = (LPOLESTDENUMSTATDATA)lpThis;
ULONG i=0;
ULONG nOffset;

while (i < celt) {
nOffset = lpSD->m_nIndex + i;

if (nOffset < lpSD->m_nCount) {
i++;
}else{
break;
}
}

lpSD->m_nIndex += (WORD)i;

if (i != celt) {
return S_FALSE;
}

return NOERROR;
} /* OleStdEnumStatData_Skip()
*/


STDMETHODIMP
OleStdEnumStatData_Reset(LPENUMSTATDATA lpThis)
//----------------------------------------------------------------------------
//
//----------------------------------------------------------------------------
{
LPOLESTDENUMSTATDATA lpSD = (LPOLESTDENUMSTATDATA)lpThis;
lpSD->m_nIndex = 0;

return NOERROR;
} /* OleStdEnumStatData_Reset()
*/


STDMETHODIMP
OleStdEnumStatData_Clone(LPENUMSTATDATA lpThis, LPENUMSTATDATA FAR* ppenum)
//----------------------------------------------------------------------------
//
//----------------------------------------------------------------------------
{
LPOLESTDENUMSTATDATA lpSD = (LPOLESTDENUMSTATDATA)lpThis;

if (ppenum == NULL) {
return E_INVALIDARG;
}

*ppenum = OleStdEnumStatData_Create(lpSD->m_nCount, lpSD->m_lpStat);

// make sure cloned enumerator has same index state as the original
if (*ppenum) {
LPOLESTDENUMSTATDATA lpSDClone = (LPOLESTDENUMSTATDATA)*ppenum;
lpSDClone->m_nIndex = lpSD->m_nIndex;
return NOERROR;
} else
return E_OUTOFMEMORY;

} /* OleStdEnumStatData_Clone()
*/