text: //+--------------------------------------------------------------------------
  //
  // Microsoft Windows
  // Copyright (C) Microsoft Corporation, 1996 - 1999
  //
  // File:        enum.cpp
  //
  // Contents:    Cert Server Database interface implementation
  //
  //---------------------------------------------------------------------------
  
  #include <pch.cpp>
  
  #pragma hdrstop
  
  #include "csprop.h"
  #include "row.h"
  #include "enum.h"
  #include "db.h"
  #include "dbw.h"
  
  #define __dwFILE__	__dwFILE_CERTDB_ENUM_CPP__
  
  
  #if DBG
  LONG g_cCertDBName;
  LONG g_cCertDBNameTotal;
  #endif
  
  CEnumCERTDBNAME::CEnumCERTDBNAME()
  {
      DBGCODE(InterlockedIncrement(&g_cCertDBName));
      DBGCODE(InterlockedIncrement(&g_cCertDBNameTotal));
      m_prow = NULL;
      m_cRef = 1;
  }
  
  
  CEnumCERTDBNAME::~CEnumCERTDBNAME()
  {
      DBGCODE(InterlockedDecrement(&g_cCertDBName));
      _Cleanup();
  }
  
  
  // CEnumCERTDBNAME implementation
  VOID
  CEnumCERTDBNAME::_Cleanup()
  {
      if (NULL != m_prow)
      {
  	((CCertDBRow *) m_prow)->EnumerateClose(m_tableid);
  	m_prow->Release();
      }
  }
  
  
  HRESULT
  CEnumCERTDBNAME::Open(
      IN ICertDBRow *prow,
      IN JET_TABLEID tableid,
      IN DWORD Flags)
  {
      HRESULT hr;
      
      if (NULL == prow)
      {
  	hr = E_POINTER;
  	_JumpError(hr, error, "NULL parm");
      }
      prow->AddRef();
  
      m_fNoMoreData = FALSE;
      m_prow = prow;
      m_tableid = tableid;
      m_Flags = Flags;
      m_ielt = 0;
      m_cskip = 0;
      hr = S_OK;
  
  error:
      return(hr);
  }
  
  
  // IEnumCERTDBNAME implementation
  STDMETHODIMP
  CEnumCERTDBNAME::Next(
      /* [in] */  ULONG       celt,
      /* [out] */ CERTDBNAME *rgelt,
      /* [out] */ ULONG      *pceltFetched)
  {
      HRESULT hr;
  
      if (NULL == rgelt || NULL == pceltFetched)
      {
  	hr = E_POINTER;
  	_JumpError(hr, error, "NULL parm");
      }
      *pceltFetched = 0;
      if (NULL == m_prow)
      {
  	hr = E_UNEXPECTED;
  	_JumpError(hr, error, "NULL m_prow");
      }
      if (m_fNoMoreData)
      {
  	hr = S_FALSE;
  	goto error;
      }
  
      CSASSERT(0 <= m_ielt);
      CSASSERT(0 <= m_ielt + m_cskip);
      DBGPRINT((
  	DBG_SS_CERTDBI,
  	"Enum::Next(celt=%d) ielt=%d, skip=%d\n",
  	celt,
  	m_ielt,
  	m_cskip));
  
      hr = ((CCertDBRow *) m_prow)->EnumerateNext(
  					&m_Flags,
  					m_tableid,
  					m_cskip,
  					celt,
  					rgelt,
  					pceltFetched);
      if (S_FALSE == hr)
      {
  	m_fNoMoreData = TRUE;
      }
      else
      {
  	_JumpIfError(hr, error, "EnumerateNext");
      }
      m_ielt += m_cskip;
      m_ielt += *pceltFetched;
      m_cskip = 0;
  
  error:
      return(hr);
  }
  
  
  STDMETHODIMP
  CEnumCERTDBNAME::Skip(
      /* [in] */  LONG  celt,
      /* [out] */ LONG *pielt)
  {
      HRESULT hr;
      LONG cskipnew;
      
      if (NULL == pielt)
      {
  	hr = E_POINTER;
  	_JumpError(hr, error, "NULL parm");
      }
      if (NULL == m_prow)
      {
  	hr = E_UNEXPECTED;
  	_JumpError(hr, error, "NULL m_prow");
      }
      cskipnew = m_cskip + celt;
  
      DBGPRINT((
  	DBG_SS_CERTDBI,
  	"Enum::Skip(%d) ielt=%d: %d --> %d, skip=%d --> %d\n",
  	celt,
  	m_ielt,
  	m_ielt + m_cskip,
  	m_ielt + cskipnew,
  	m_cskip,
  	cskipnew));
  
      CSASSERT(0 <= m_ielt);
      if (0 > cskipnew)
      {
  	if (0 > m_ielt + cskipnew)
  	{
  	    hr = E_INVALIDARG;
  	    _JumpError(hr, error, "Skip back to before start");
  	}
  	m_fNoMoreData = FALSE;
      }
  
      *pielt = m_ielt + cskipnew;
      m_cskip = cskipnew;
      hr = S_OK;
  
  error:
      return(hr);
  }
  
  
  STDMETHODIMP
  CEnumCERTDBNAME::Reset(VOID)
  {
      HRESULT hr;
      LONG iDummy;
  
      hr = Skip(-(m_ielt + m_cskip), &iDummy);
      _JumpIfError(hr, error, "Skip");
  
      CSASSERT(0 == iDummy);
  
  error:
      return(hr);
  }
  
  
  STDMETHODIMP
  CEnumCERTDBNAME::Clone(
      /* [out] */ IEnumCERTDBNAME **ppenum)
  {
      HRESULT hr;
      LONG iDummy;
  
      if (NULL == ppenum)
      {
  	hr = E_POINTER;
  	_JumpError(hr, error, "NULL parm");
      }
      *ppenum = NULL;
      if (NULL == m_prow)
      {
  	hr = E_UNEXPECTED;
  	_JumpError(hr, error, "NULL m_prow");
      }
  
      hr = ((CCertDBRow *) m_prow)->EnumCertDBName(
  					    CIE_TABLE_MASK & m_Flags,
  					    ppenum);
      _JumpIfError(hr, error, "EnumerateCertDBName");
  
      (*ppenum)->Skip(m_ielt + m_cskip, &iDummy);
  
  error:
      return(hr);
  }
  
  
  // IUnknown implementation
  STDMETHODIMP
  CEnumCERTDBNAME::QueryInterface(
      const IID& iid,
      void **ppv)
  {
      HRESULT hr;
      
      if (NULL == ppv)
      {
  	hr = E_POINTER;
  	_JumpError(hr, error, "NULL parm");
      }
      if (iid == IID_IUnknown)
      {
  	*ppv = static_cast<IEnumCERTDBNAME *>(this);
      }
      else if (iid == IID_IEnumCERTDBNAME)
      {
  	*ppv = static_cast<IEnumCERTDBNAME *>(this);
      }
      else
      {
  	*ppv = NULL;
  	hr = E_NOINTERFACE;
  	_JumpError(hr, error, "IID");
      }
      reinterpret_cast<IUnknown *>(*ppv)->AddRef();
      hr = S_OK;
  
  error:
      return(hr);
  }
  
  
  ULONG STDMETHODCALLTYPE
  CEnumCERTDBNAME::AddRef()
  {
      return(InterlockedIncrement(&m_cRef));
  }
  
  
  ULONG STDMETHODCALLTYPE
  CEnumCERTDBNAME::Release()
  {
      ULONG cRef = InterlockedDecrement(&m_cRef);
  
      if (0 == cRef)
      {
  	delete this;
      }
      return(cRef);
  }
  
  
  #if 0
  STDMETHODIMP
  CEnumCERTDBNAME::InterfaceSupportsErrorInfo(
      IN REFIID riid)
  {
      static const IID *arr[] =
      {
  	&IID_IEnumCERTDBNAME,
      };
  
      for (int i = 0; i < sizeof(arr)/sizeof(arr[0]); i++)
      {
  	if (InlineIsEqualGUID(*arr[i], riid))
  	{
  	    return(S_OK);
  	}
      }
      return(S_FALSE);
  }
  #endif
  