|
|
//=--------------------------------------------------------------------------=
// StandardEnum.Cpp
//=--------------------------------------------------------------------------=
// Copyright 1995 Microsoft Corporation. All Rights Reserved.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//=--------------------------------------------------------------------------=
//
// implementation of a generic enumerator object.
//
#include "pch.h"
#include "StdEnum.H"
SZTHISFILE
//=--------------------------------------------------------------------------=
// CStandardEnum::CStandardEnum
//=--------------------------------------------------------------------------=
// create the object and initialize the refcount
//
// Parameters:
// none
//
// Notes: This default constructor only exists so that derived classes can be created
// Internal debug checks have been added to confirm that internal
// state is correctly set before use (calls to Next, Skip, etc)
//
//
#pragma warning(disable:4355) // using 'this' in constructor
CStandardEnum::CStandardEnum() : CUnknownObject(NULL, (IEnumGeneric *)this), m_iid(IID_IUnknown), m_cElements(0), m_cbElementSize(0), m_iCurrent(0), m_rgElements(NULL), m_pfnCopyElement(NULL) { m_pEnumClonedFrom = NULL; } #pragma warning(default:4355) // using 'this' in constructor
//=--------------------------------------------------------------------------=
// CStandardEnum::CStandardEnum
//=--------------------------------------------------------------------------=
// create the object and initialize the refcount
//
// Parameters:
// REFCLSID - [in] type of enumerator that we are
// int - [in] number of elements in the enumeration
// int - [in] size of each element
// void * - [in] pointer to element data
// void (WINAPI *pfnCopyElement)(void *, const void *, DWORD)
// - [in] copying function
//
// Notes:
//
#pragma warning(disable:4355) // using 'this' in constructor
CStandardEnum::CStandardEnum ( REFCLSID rclsid, int cElements, int cbElementSize, void *rgElements, void (WINAPI *pfnCopyElement)(void *, const void *, DWORD) ) : CUnknownObject(NULL, (IEnumGeneric *)this), m_iid(rclsid), m_cElements(cElements), m_cbElementSize(cbElementSize), m_iCurrent(0), m_rgElements(rgElements), m_pfnCopyElement(pfnCopyElement) { m_pEnumClonedFrom = NULL; } #pragma warning(default:4355) // using 'this' in constructor
//=--------------------------------------------------------------------------=
// CStandardEnum::CStandardEnum
//=--------------------------------------------------------------------------=
// "it is not death, but dying, which is terrible."
// - Henry Fielding (1707-54)
//
// Notes:
//
CStandardEnum::~CStandardEnum () { // if we're a cloned object, then just release our parent object and
// we're done. otherwise, free up the allocated memory we were given
//
if (m_pEnumClonedFrom) m_pEnumClonedFrom->Release(); else { if (m_rgElements) CtlHeapFree(g_hHeap, 0, m_rgElements); } }
//=--------------------------------------------------------------------------=
// CStandardEnum::InternalQueryInterface
//=--------------------------------------------------------------------------=
// we support our internal iid, and that's all
//
// Parameters:
// REFIID - [in] interface they want
// void ** - [out] where they want to put the resulting object ptr.
//
// Output:
// HRESULT - S_OK, E_NOINTERFACE
//
// Notes:
//
HRESULT CStandardEnum::InternalQueryInterface ( REFIID riid, void **ppvObjOut ) { if (DO_GUIDS_MATCH(riid, m_iid) || DO_GUIDS_MATCH(riid, IID_IUnknown)) { ExternalAddRef(); *ppvObjOut = (IEnumGeneric *)this; return S_OK; }
return E_NOINTERFACE; }
//=--------------------------------------------------------------------------=
// CStandardEnum::Next
//=--------------------------------------------------------------------------=
// returns the next dude in our iteration
//
// Parameters:
// unsigned long - [in] count of elements requested
// void * - [out] array of slots to put values in.
// unsigned long * - [out] actual number fetched
//
// Output:
// HRESULT - S_OK, E_INVALIDARG, S_FALSE
//
// Notes:
//
STDMETHODIMP CStandardEnum::Next ( unsigned long cElm, void *rgDest, unsigned long *pcElmOut ) { ASSERT(m_pfnCopyElement, "NULL m_pfnCopyElement is invalid CStandardEnum state!");
unsigned long cElementsFetched = 0; void *pElementDest = rgDest; const void *pElementSrc = (const BYTE *)m_rgElements + (m_cbElementSize * m_iCurrent);
while (cElementsFetched < cElm) {
// if we hit EOF, break out
//
if (m_iCurrent >= m_cElements) break;
// copy the element out for them
//
m_pfnCopyElement(pElementDest, pElementSrc, m_cbElementSize);
// increase the counters
//
pElementDest = (LPBYTE)pElementDest + m_cbElementSize; pElementSrc = (const BYTE *)pElementSrc + m_cbElementSize; m_iCurrent++; cElementsFetched++; }
if (pcElmOut) *pcElmOut = cElementsFetched;
return (cElementsFetched < cElm)? S_FALSE : S_OK; }
//=--------------------------------------------------------------------------=
// CStandardEnum::Skip
//=--------------------------------------------------------------------------=
// skips the requested number of rows.
//
// Parameters:
// unsigned long - [in] number to skip
//
// Output:
// HRESULT - S_OK, S_FALSE
//
// Notes:
//
STDMETHODIMP CStandardEnum::Skip ( unsigned long cSkip ) { ASSERT(m_pfnCopyElement, "NULL m_pfnCopyElement is invalid CStandardEnum state!");
// handle running off the end
//
if (m_iCurrent + (int)cSkip > m_cElements) { m_iCurrent = m_cElements; return S_FALSE; }
m_iCurrent += cSkip; return S_OK; }
//=--------------------------------------------------------------------------=
// CStandardEnum::Reset
//=--------------------------------------------------------------------------=
// reset the counter.
//
// Output:
// HRESULT - S_OK
//
// Notes:
//
STDMETHODIMP CStandardEnum::Reset ( void ) { m_iCurrent = 0; return S_OK; }
//=--------------------------------------------------------------------------=
// CStandardEnum::Clone
//=--------------------------------------------------------------------------=
// clones the object and gives the new one the same position
//
// Parameters:
// IEnumVARIANT ** - [out] where to put the new object.
//
// Output;
// HRESULT - S_OK, E_OUTOFMEMORY
//
// Notes:
//
STDMETHODIMP CStandardEnum::Clone ( IEnumGeneric **ppEnumClone ) { ASSERT(m_pfnCopyElement, "NULL m_pfnCopyElement is invalid CStandardEnum state!");
CStandardEnum *pNewEnum;
*ppEnumClone = NULL;
pNewEnum = New CStandardEnum(m_iid, m_cElements, m_cbElementSize, m_rgElements, m_pfnCopyElement); RETURN_ON_NULLALLOC(pNewEnum);
// hold on to who we were cloned from so m_rgElements stays alive, and we don't
// have to copy it.
//
pNewEnum->m_pEnumClonedFrom = this; pNewEnum->m_iCurrent = m_iCurrent;
// AddRef() ourselves on their behalf.
//
AddRef(); *ppEnumClone = (IEnumGeneric *)pNewEnum; return S_OK; }
|