IEnumVARIANT and IEnumXXX

IEnumVARIANT is an enumerator interface used in COM/DCOM. Collection objects can be represented as IEnumVARIANT. The IEnumVARIANT interface has these methods.

  • Clone - Creates a copy of the current state of enumeration.
  • Next - Retrieves the specified items in the enumeration sequence.
  • Reset - Resets the enumeration sequence to the beginning.
  • Skip - Attempts to skip over the next celt elements in the enumeration sequence.

IEnumVARIANT example IDL

CWEEKDAYSENUMXXXLib is a COM server with coclass Weekdays and IWeekdays interface. GetEnumerator() function of IWeekdays returns IEnumVARIANT enumerator object which is a collection of BSTRs containing week days name.

import "oaidl.idl";
import "ocidl.idl";
[
  object,
  uuid(37291CD6-6A49-4B1D-A110-FABD8402722A),
  dual,
  helpstring("IWeekdays Interface"),
  pointer_default(unique)
]
interface IWeekdays : IDispatch
{
  [id(0xfffffffc), helpstring("method GetEnumerator")]
  HRESULT GetEnumerator([out,retval] IEnumVARIANT **pDays);
};
[
  uuid(3AC6B05B-A8BC-4213-82E8-14AD17C9FE7D),
  version(1.0),
  helpstring("CWeekDaysEnumXXX 1.0 Type Library")
]
library CWEEKDAYSENUMXXXLib
{
  importlib("stdole32.tlb");
  importlib("stdole2.tlb");

  [
    uuid(17975251-FF69-44B4-ABFA-58225428B4CE),
    helpstring("Weekdays Class")
  ]
  coclass Weekdays
  {
    [default] interface IWeekdays;
  };
};

IEnumVARIANT implementation C++

class CEnumWeekdays: public IEnumVARIANT
{

protected:
  int m_nCursor;
  VARIANT m_DayVars[5];
  ULONG m_nRef;

public:

CEnumWeekdays()
{
  unsigned short *days[5] = {L"Monday",L"Tuesday",L"Wednesday",L"Thursday",L"Friday"};
  m_nCursor = 0;
  m_nRef = 0;
  for (int i = 0; i < 5; i++ ) {
    VariantInit(&m_DayVars[i]);
    m_DayVars[i].vt = VT_BSTR;
    m_DayVars[i].bstrVal = SysAllocString(days[i]);
  }
}
virtual long __stdcall QueryInterface(const struct _GUID & iid,void ** ppvObject)
{ 
  if ( iid == IID_IUnknown) {
    *ppvObject = dynamic_cast( this );
  } else
  if ( iid == IID_IEnumVARIANT) {
    *ppvObject = dynamic_cast( this );
  }else {
    *ppvObject = NULL;
    return E_NOINTERFACE;
  }
  this->AddRef();
  return S_OK;
}

virtual unsigned long __stdcall AddRef(void)
{ 
  return ++m_nRef;
}

virtual unsigned long __stdcall Release(void)
{
  int ref = --m_nRef;
  if(ref == 0) {
    for (int i = 0; i < 5; i++ ) {
      SysFreeString( m_DayVars[i].bstrVal);
    }
    delete this;
  }
  return ref;
}
    
virtual HRESULT __stdcall  Next(
                ULONG celt,
                VARIANT * rgVar,
                ULONG * pCeltFetched
            )
{
  UINT current = m_nCursor;

  if(rgVar == NULL)
    return E_POINTER;

  m_nCursor += celt;
  if(current > 4){
    if(rgVar)rgVar = NULL;
    return S_FALSE;
  }
  int out;
  out = m_nCursor - current;
  memcpy(rgVar, &m_DayVars[current], (out)*sizeof(VARIANT));

  if(pCeltFetched)
    *pCeltFetched = out;

  return S_OK;
}

virtual HRESULT __stdcall Skip(
               ULONG celt
            )
{
  m_nCursor += celt;
  if(m_nCursor > 4) {
    m_nCursor = 4;
  }
  return S_OK;
}

virtual HRESULT __stdcall Reset(
            )
{
  m_nCursor = 0;
  return S_OK;
}


virtual HRESULT __stdcall Clone(
                IEnumVARIANT ** ppEnum
            )
{
  if(ppEnum == NULL)
    return E_POINTER;

  *ppEnum = (IEnumVARIANT*)new CEnumWeekdays();

  if(*ppEnum == NULL)
    return E_OUTOFMEMORY;

  (*ppEnum)->AddRef();
  return S_OK;
}

};

CWeekdays class   GetEnumerator()

class ATL_NO_VTABLE CWeekdays : 
	public CComObjectRootEx,
	public CComCoClass,
	public IDispatchImpl
{
public:
	CWeekdays()
	{
	}

DECLARE_REGISTRY_RESOURCEID(IDR_WEEKDAYS)

DECLARE_PROTECT_FINAL_CONSTRUCT()

BEGIN_COM_MAP(CWeekdays)
	COM_INTERFACE_ENTRY(IWeekdays)
	COM_INTERFACE_ENTRY(IDispatch)
END_COM_MAP()

// IWeekdays
public:
	STDMETHOD(GetEnumerator)(/*[out,retval]*/ IEnumVARIANT **pDays);
};
STDMETHODIMP CWeekdays::GetEnumerator(IEnumVARIANT **pDays)
{
  CEnumWeekdays *pEnum = new CEnumWeekdays();
  if(pEnum == NULL)
    return E_OUTOFMEMORY;

  pEnum->AddRef();
  (*pDays) =dynamic_cast(pEnum);
  return S_OK;
}

IEnumVARIANT VB client

Dim EnumerableObj As IEnumVARIANT

Private Sub Form_Load()
  Set EnumerableClassObj = New CWEEKDAYSENUMXXXLib.Weekdays
  Dim day As Variant
  Dim str As String
  For Each day In EnumerableClassObj
    str = str & day & ","
  Next
  MsgBox str
  Set EnumerableClassObj = Nothing
End Sub

IEnumVARIANT VB client output

IEnumVARIANT VB client output

About our authors: Team EQA

You have viewed 1 page out of 67. Your COM/DCOM learning is 0.00% complete. Login to check your learning progress.

#