You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
263 lines
6.0 KiB
263 lines
6.0 KiB
/*************************************************************************
|
|
**
|
|
** 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;
|
|
}
|
|
|
|
|
|
|
|
|
|
|