|
|
/*************************************************************************
** ** This is a part of the Microsoft Source Code Samples. ** ** Copyright 1992 - 1998 Microsoft Corporation. All rights reserved. ** ** This source code is only intended as a supplement to Microsoft Development ** Tools and/or WinHelp documentation. See these sources for detailed ** information regarding the Microsoft samples programs. ** ** OLE Automation TypeLibrary Browse Helper Sample ** ** enumvar.cpp ** ** CEnumVariant implementation ** ** Written by Microsoft Product Support Services, Windows Developer Support ** *************************************************************************/
#include <windows.h>
#include "precomp.h"
#include "Enumvar.h"
/*
* CEnumVariant::Create * * Purpose: * Creates an instance of the IEnumVARIANT enumerator object and initializes it. * * Parameters: * psa Safe array containing items to be enumerated. * cElements Number of items to be enumerated. * ppenumvariant Returns enumerator object. * * Return Value: * HRESULT * */ //static
HRESULT CEnumVariant::Create(SAFEARRAY FAR* psa, ULONG cElements, CEnumVariant** ppenumvariant) { HRESULT hr; CEnumVariant FAR* penumvariant = NULL; long lLBound; *ppenumvariant = NULL; penumvariant = new CEnumVariant(); if (penumvariant == NULL) goto error; penumvariant->m_cRef = 0; // Copy elements into safe array that is used in enumerator implemenatation and
// initialize state of enumerator.
hr = SafeArrayGetLBound(psa, 1, &lLBound); if (FAILED(hr)) goto error; penumvariant->m_cElements = cElements; penumvariant->m_lLBound = lLBound; penumvariant->m_lCurrent = lLBound; hr = SafeArrayCopy(psa, &penumvariant->m_psa); if (FAILED(hr)) goto error; *ppenumvariant = penumvariant; return NOERROR; error: if (penumvariant == NULL) return E_OUTOFMEMORY; if (penumvariant->m_psa) SafeArrayDestroy(penumvariant->m_psa); penumvariant->m_psa = NULL; delete penumvariant; return hr; } /*
* CEnumVariant::CEnumVariant * * Purpose: * Constructor for CEnumVariant object. Initializes members to NULL. * */ CEnumVariant::CEnumVariant() { m_psa = NULL; } /*
* CEnumVariant::~CEnumVariant * * Purpose: * Destructor for CEnumVariant object. * */ CEnumVariant::~CEnumVariant() { if (m_psa) SafeArrayDestroy(m_psa); } /*
* CEnumVariant::QueryInterface, AddRef, Release * * Purpose: * Implements IUnknown::QueryInterface, AddRef, Release * */ STDMETHODIMP CEnumVariant::QueryInterface(REFIID iid, void FAR* FAR* ppv) { *ppv = NULL; if (iid == IID_IUnknown || iid == IID_IEnumVARIANT) *ppv = this; else return E_NOINTERFACE; AddRef(); return NOERROR; } STDMETHODIMP_(ULONG) CEnumVariant::AddRef(void) { #ifdef _DEBUG
TCHAR ach[50]; wsprintf(ach, TEXT("Ref = %ld, Enum\r\n"), m_cRef+1); TRACE_OUT((ach)); #endif
return ++m_cRef; // AddRef Application Object if enumerator will outlive application object
} STDMETHODIMP_(ULONG) CEnumVariant::Release(void) { #ifdef _DEBUG
TCHAR ach[50]; wsprintf(ach, TEXT("Ref = %ld, Enum\r\n"), m_cRef-1); TRACE_OUT((ach)); #endif
if(--m_cRef == 0) { delete this; return 0; } return m_cRef; } /*
* CEnumVariant::Next * * Purpose: * Retrieves the next cElements elements. Implements IEnumVARIANT::Next. * */ STDMETHODIMP CEnumVariant::Next(ULONG cElements, VARIANT FAR* pvar, ULONG FAR* pcElementFetched) { HRESULT hr; ULONG l; long l1; ULONG l2; if (pcElementFetched != NULL) *pcElementFetched = 0; // Retrieve the next cElements elements.
for (l1=m_lCurrent, l2=0; l1<(long)(m_lLBound+m_cElements) && l2<cElements; l1++, l2++) { hr = SafeArrayGetElement(m_psa, &l1, &pvar[l2]); if (FAILED(hr)) goto error; } // Set count of elements retrieved
if (pcElementFetched != NULL) *pcElementFetched = l2; m_lCurrent = l1; return (l2 < cElements) ? S_FALSE : NOERROR; error: for (l=0; l<cElements; l++) VariantClear(&pvar[l]); return hr; } /*
* CEnumVariant::Skip * * Purpose: * Skips the next cElements elements. Implements IEnumVARIANT::Skip. * */ STDMETHODIMP CEnumVariant::Skip(ULONG cElements) { m_lCurrent += cElements; if (m_lCurrent > (long)(m_lLBound+m_cElements)) { m_lCurrent = m_lLBound+m_cElements; return S_FALSE; } else return NOERROR; } /*
* CEnumVariant::Reset * * Purpose: * Resets the current element in the enumerator to the beginning. Implements IEnumVARIANT::Reset. * */ STDMETHODIMP CEnumVariant::Reset() { m_lCurrent = m_lLBound; return NOERROR; } /*
* CEnumVariant::Clone * * Purpose: * Creates a copy of the current enumeration state. Implements IEnumVARIANT::Clone. * */ STDMETHODIMP CEnumVariant::Clone(IEnumVARIANT FAR* FAR* ppenum) { CEnumVariant FAR* penum = NULL; HRESULT hr; *ppenum = NULL; hr = CEnumVariant::Create(m_psa, m_cElements, &penum); if (FAILED(hr)) goto error; penum->AddRef(); penum->m_lCurrent = m_lCurrent; *ppenum = penum; return NOERROR; error: if (penum) penum->Release(); return hr; }
|