//=--------------------------------------------------------------------------= // 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; }