/************************************************************************* ** ** 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 #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 (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; }