Home COM GDI+ WebBrowser Data Access

IEnumVARIANT Interface

 

IID_IEnumVARIANT

{00020404-0000-0000-C000-000000000046}

 

 

The IEnumVARIANT interface provides a method for enumerating a collection of variants, including heterogeneous collections of objects and intrinsic types. Callers of this interface do not need to know the specific type (or types) of the elements in the collection.

 

 

Methods in VTable order

IUnknown Methods

Description

QueryInterface

Returns pointers to supported interfaces.

AddRef

Increments reference count.

Release

Decrements reference count.

IEnumVARIANT Methods

Description

Next

Gets the next items in the enumeration sequence.

Skip

Attempts to skip over the next celt elements in the enumeration sequence.

Reset

Resets the enumeration sequence to the beginning.

Clone

Creates a copy of the current state of enumeration.

 

Next

 

FUNCTION IEnumVARIANT_Next ( _

  BYVAL pthis AS DWORD PTR _

, BYVAL celt AS DWORD _

, BYVAL rgelt AS DWORD _

, BYREF pceltFetched AS DWORD _

  ) AS LONG
 

  LOCAL HRESULT AS LONG
  CALL DWORD @@pthis[3] USING IEnumVARIANT_Next (pthis, celt, rgelt, pceltFetched) TO HRESULT
  FUNCTION = HRESULT
 

END FUNCTION

 

 

Skip

 

FUNCTION IEnumVARIANT_Skip ( _

  BYVAL pthis AS DWORD PTR _

, BYVAL celt AS DWORD _

  ) AS LONG
 

  LOCAL HRESULT AS LONG
  CALL DWORD @@pthis[4] USING IEnumVARIANT_Skip (pthis, celt) TO HRESULT
  FUNCTION = HRESULT
 

END FUNCTION

 

 

Reset

 

FUNCTION IEnumVARIANT_Reset ( _

  BYVAL pthis AS DWORD PTR _

  ) AS LONG
 

  LOCAL HRESULT AS LONG
  CALL DWORD @@pthis[5] USING IEnumVARIANT_Reset (pthis) TO HRESULT
  FUNCTION = HRESULT
 

END FUNCTION

 

 

Clone

 

FUNCTION IEnumVARIANT_Clone ( _

  BYVAL pthis AS DWORD PTR _

, BYVAL ppenum AS DWORD _

  ) AS LONG
 

  LOCAL HRESULT AS LONG
  CALL DWORD @@pthis[6] USING IEnumVARIANT_Clone (pthis, ppenum) TO HRESULT
  FUNCTION = HRESULT
 

END FUNCTION

 

 

 

Collection's Enumerator

 

 

Enumerates a collection and returns its contents in an array of variants. Collections can be enumerated using the Item property of the interfaces, but in many cases, it expects a key instead of am index. In the case of the FileSystemObject, to enumerate the Files collection you will need to pass the name of a file to get a reference that allows to get the name of this file! In such a situation, we need a generic enumerator, such the ForEach function of Visual Basic. The following wrapper functions provide access to the IEnumVARIANT interface, and an example of how to use it.

 

 

 

' *********************************************************************************************
' ENUMERATOR
' *********************************************************************************************
' Enumerates a collection and returns its contents in an array of variants.
' This is a generic enumerator, so you don't need to select any typelib to generate it.
' Collections are in general enumerated using the Item property of the interfaces, but in
' many cases, it expects a key instead of am index. In the case of the FileSystemObject, to
' enumerate the Files collection you will need to pass the name of a file to get a reference
' that allows to get the name of this file! In such a situation, we need a generic enumerator,
' such the ForEach function of Visual Basic. The following wrapper functions provide access to
' the IEnumVARIANT interface, and an example of how to use it.
' *********************************************************************************************

' ********************************************************************************************
' EXCEPINFO structure
' ********************************************************************************************
TYPE TB_Collection_EXCEPINFO
   wCode AS WORD               ' An error code describing the error.
   wReserved AS WORD           ' Reserved
   bstrSource AS DWORD         ' Source of the exception.
   bstrDescription AS DWORD    ' Textual description of the error.
   bstrHelpFile AS DWORD       ' Help file path.
   dwHelpContext AS DWORD      ' Help context ID.
   pvReserved AS DWORD         ' Reserved.
   pfnDeferredFillIn AS DWORD  ' Pointer to function that fills in Help and description info.
   scode AS DWORD              ' An error code describing the error.
END TYPE
' ********************************************************************************************

' ********************************************************************************************
' Returns a pointer to a specified interface on an object to which a client currently holds an
' interface pointer. This function must call IUnknown_AddRef on the pointer it returns.
' ********************************************************************************************
FUNCTION TB_Collection_IUnknown_QueryInterface (BYVAL pthis AS DWORD PTR, BYREF riid AS GUID, BYREF ppvObj AS DWORD) AS LONG
    LOCAL HRESULT AS LONG
    IF ISFALSE pthis THEN FUNCTION = &H80004003 : EXIT FUNCTION   ' %E_POINTER
    CALL DWORD @@pthis[0] USING TB_Collection_IUnknown_QueryInterface(pthis, riid, ppvObj) TO HRESULT
    FUNCTION = HRESULT
END FUNCTION
' ********************************************************************************************

' ********************************************************************************************
' The IUnknown::AddRef method increments the reference count for an interface on an object. It
' should be called for every new copy of a pointer to an interface on a given object.
' ********************************************************************************************
FUNCTION TB_Collection_IUnknown_AddRef (BYVAL pthis AS DWORD PTR) AS DWORD
    LOCAL DWRESULT AS LONG
    IF ISFALSE pthis THEN FUNCTION = &H80004003 : EXIT FUNCTION   ' %E_POINTER
    CALL DWORD @@pthis[1] USING TB_Collection_IUnknown_AddRef(pthis) TO DWRESULT
    FUNCTION = DWRESULT
END FUNCTION
' ********************************************************************************************

' ********************************************************************************************
' Decrements the reference count for the calling interface on a object. If the reference count
' on the object falls to 0, the object is freed from memory.
' ********************************************************************************************
FUNCTION TB_Collection_IUnknown_Release (BYVAL pthis AS DWORD PTR) AS DWORD
    LOCAL DWRESULT AS DWORD
    IF ISFALSE pthis THEN FUNCTION = &H80004003 : EXIT FUNCTION   ' %E_POINTER
    CALL DWORD @@pthis[2] USING TB_Collection_IUnknown_Release(pthis) TO DWRESULT
    FUNCTION = DWRESULT
END FUNCTION
' ********************************************************************************************

' ********************************************************************************************
' Provides access to properties and methods exposed by an object.
' ********************************************************************************************
FUNCTION TB_Collection_IDispatch_Invoke (BYVAL pthis AS DWORD PTR, BYVAL dispidMember AS LONG, BYREF riid AS GUID, _
    BYVAL lcid AS DWORD, BYVAL wFlags AS WORD, BYREF pdispparams AS DISPPARAMS, BYREF pvarResult AS VARIANT, _
    BYREF pexcepinfo AS TB_Collection_EXCEPINFO, BYREF puArgErr AS DWORD) AS LONG

    LOCAL HRESULT AS LONG
    IF ISFALSE pthis THEN FUNCTION = &H80004003 : EXIT FUNCTION   ' %E_POINTER
    CALL DWORD @@pthis[6] USING TB_Collection_IDispatch_Invoke(pthis, dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr) TO HRESULT
    FUNCTION = HRESULT

END FUNCTION
' ********************************************************************************************

' *********************************************************************************************
' HRESULT Next([in] UI4 celt, [in] *VARIANT rgvar, [out] *UI4 pceltFetched)
' The Next method enumerates the next celt elements in the enumerator's list, returning them in
' rgelt along with the actual number of enumerated elements in pceltFetched.
' Parameters:
' celt
'   [in] Number of items in the array.
' rgelt
'   [out] Address of array containing items.
' pceltFetched
'   [out] Address of variable containing actual number of items.
' Return Value:
'   Returns %S_OK if the method succeeds.
' *********************************************************************************************
FUNCTION TB_Collection_IEnumVARIANT_Next (BYVAL pthis AS DWORD PTR, BYVAL celt AS DWORD, BYVAL rgelt AS DWORD, BYREF pceltFetched AS DWORD) AS LONG
    LOCAL HRESULT AS LONG
    IF ISFALSE pthis THEN FUNCTION = &H80004003 : EXIT FUNCTION   ' %E_POINTER
    CALL DWORD @@pthis[3] USING TB_Collection_IEnumVARIANT_Next(pthis, celt, rgelt, pceltFetched) TO HRESULT
    FUNCTION = HRESULT
END FUNCTION
' *********************************************************************************************

' *********************************************************************************************
' HRESULT Skip([in] UI4 celt)
' The Skip method Instructs the enumerator to skip the next celt elements in the enumeration so
' the next call to TB_Collection_IEnumVARIANT_Next does not return those elements.
' Parameter:
' celt
'   [in] Number of items to skip.
' Return Value:
'   Returns %S_OK if the method succeeds.
' *********************************************************************************************
FUNCTION TB_Collection_IEnumVARIANT_Skip (BYVAL pthis AS DWORD  PTR, BYVAL celt AS DWORD) AS LONG
    LOCAL HRESULT AS LONG
    IF ISFALSE pthis THEN FUNCTION = &H80004003 : EXIT FUNCTION   ' %E_POINTER
    CALL DWORD @@pthis[4] USING TB_Collection_IEnumVARIANT_Skip(pthis, celt) TO HRESULT
    FUNCTION = HRESULT
END FUNCTION
' *********************************************************************************************

' *********************************************************************************************
' HRESULT Reset()
' The Reset method instructs the enumerator to position itself at the beginning of the list
' of elements.
' Return Value:
'   Returns %S_OK if the method succeeds.
' *********************************************************************************************
FUNCTION TB_Collection_IEnumVARIANT_Reset (BYVAL pthis AS DWORD PTR) AS LONG
    LOCAL HRESULT AS LONG
    IF ISFALSE pthis THEN FUNCTION = &H80004003 : EXIT FUNCTION   ' %E_POINTER
    CALL DWORD @@pthis[5] USING TB_Collection_IEnumVARIANT_Reset(pthis) TO HRESULT
    FUNCTION = HRESULT
END FUNCTION
' *********************************************************************************************

' *********************************************************************************************
' HRESULT Clone([out] **IEnumVARIANT ppenum)
' The Clone method creates another items enumerator with the same state as the current
' enumerator to iterate over the same list. This method makes it possible to record a point in
' the enumeration sequence in order to return to that point at a later time.
' Parameters:
' ppenum
'   [out] Address of a variable that receives the IEnumVARIANT interface pointer.
' Return Value:
'   Returns %S_OK if the method succeeds.
' Remarks
'   The caller must release the new enumerator separately from the first enumerator.
' *********************************************************************************************
FUNCTION TB_Collection_IEnumVARIANT_Clone (BYVAL pthis AS DWORD PTR, BYVAL ppenum AS DWORD) AS LONG
    LOCAL HRESULT AS LONG
    IF ISFALSE pthis THEN FUNCTION = &H80004003 : EXIT FUNCTION   ' %E_POINTER
    CALL DWORD @@pthis[6] USING TB_Collection_IEnumVARIANT_Clone(pthis, ppenum) TO HRESULT
    FUNCTION = HRESULT
END FUNCTION
' *********************************************************************************************

' ********************************************************************************************
' _NewEnum method  [Restricted]
' Member identifier: -4 (_NewEnum always has a DispID of -4)
' Returns a a reference to the IUnknown interface of a collection.
' Notes: Some objects declare it as a method and others as a property, so we are passing
' both flags, %DISPATH_METHOD (=1) and %DISPATCH_PROPERTYGET (=2) = 1 OR 2.
' The _NewEnum property can have a different VTable offset for each collection. Since we want
' a generic function, we have to call Invoke taking advantage of the fact that _NewEnum has
' always a DispID of -4.
' ********************************************************************************************
FUNCTION TB_Collection_NewEnum (BYVAL pthis AS DWORD, BYREF ppenum AS DWORD) AS DWORD
    DIM IID_NULL AS GUID
    DIM uDispParams AS DISPPARAMS
    DIM vResult AS VARIANT
    DIM puArgErr AS DWORD
    ppenum = 0
    IF ISFALSE pthis THEN FUNCTION = &H80004003 : EXIT FUNCTION   ' %E_POINTER
    FUNCTION = TB_Collection_IDispatch_Invoke (pthis, -4, IID_NULL, 0, 1 OR 2, uDispParams, vResult, BYVAL 0, puArgErr)
    ppenum = VARIANT#(vResult)
    IF ISTRUE ppenum THEN TB_Collection_IUnknown_AddRef ppenum   ' increment the reference counter
END FUNCTION
' ********************************************************************************************

' *********************************************************************************************
' Returns the number of objects of the collection.
' Provides the same functionality as the Count property of the object.
' *********************************************************************************************
FUNCTION TB_Collection_Count (BYVAL pthis AS DWORD) AS LONG

    LOCAL HRESULT AS LONG               ' // COM result code
    LOCAL IID_IEnumVariant AS GUID      ' // GUID of the IEnumVARIANT interface
    LOCAL pEnum AS DWORD                ' // Address of a pointer to the collection
    LOCAL pIEnumVARIANT AS DWORD        ' // Address of a pointer to the IEnumVARIANT interface
    LOCAL nCount AS LONG                ' // Number of elements in the collection
    LOCAL celtFetched AS DWORD          ' // Number of elements fetched
    LOCAL dwArray AS DWORD              ' // Pointer to the first element in the array
    LOCAL vVar AS VARIANT               ' // General purpose variant

    IID_IEnumVARIANT = GUID$("{00020404-0000-0000-c000-000000000046}")

    ' Check for null pointer
    IF ISFALSE pthis THEN EXIT FUNCTION

    ' Get a reference to the Enumerator object
    HRESULT = TB_Collection_NewEnum (pthis, pEnum)
    IF ISTRUE HRESULT OR ISFALSE pEnum THEN EXIT FUNCTION

    ' Get a pointer to the IEnumVARIANT interface.
    HRESULT = TB_Collection_IUnknown_QueryInterface (pEnum, IID_IEnumVARIANT, pIEnumVARIANT)
    IF ISTRUE HRESULT OR ISFALSE pIEnumVARIANT THEN
       TB_Collection_IUnknown_Release pEnum
       EXIT FUNCTION
    END IF

    ' Release the collection's enumerator interface.
    ' Note: If pEnum and pIEnumVARIANT are the same, this will decrease the reference count;
    ' otherwise, it will release the enumerator interface.
    TB_Collection_IUnknown_Release pEnum

    ' Position the enumerator at the beginning of the list
    HRESULT = TB_Collection_IEnumVARIANT_Reset(pIEnumVARIANT)
    IF ISTRUE HRESULT THEN
       TB_Collection_IUnknown_Release pIEnumVARIANT
       EXIT FUNCTION
    END IF

    ' Parses the collection
    DO
       ' Fetch an element of the collection
       HRESULT = TB_Collection_IEnumVARIANT_Next (pIEnumVARIANT, 1, BYVAL VARPTR(vVar), celtFetched)
       IF ISTRUE HRESULT OR celtFetched < 1 THEN EXIT DO
       nCount = nCount + 1
    LOOP

    ' Release the interface
    TB_Collection_IUnknown_Release pIEnumVARIANT

    ' Return the number of objects retrieved
    FUNCTION = nCount

  END FUNCTION
' *********************************************************************************************

' *********************************************************************************************
' TB_EnumCollection
' *********************************************************************************************
' - Helper function to enumerate collectios. Returns an array of pointers to objects.
'   This provides similar functionality to the Visual Basic's ForEach function.
'   We need it to enumerate collections than expect a key instead of an index.
'   It is also much faster to enumerate an entire collection using this method that using
'   the Item property, that should be reserved to get a single object of the collection.
' Parameters:
'   pthis   = Pointer to the interface whose collection we want to enumerate.
'   vArray  = Dimensioned array of variants.
' Return Value:
'   An HRESULT (&H80004003 = %E_POINTER) or error 461 (array not dimensioned)
' Example:
' The code below demonstrates the use of the enumerator with the FileSystemObject.
'
'  #DIM ALL
'  #DEBUG ERROR ON
'  #INCLUDE "win32api.inc"
'  #INCLUDE "TB_ENUM.inc"
'
'  FUNCTION PBMAIN
'
'    ' -------------------------------------------------------------------------
'    ' ** STARTUP **
'    ' -------------------------------------------------------------------------
'    ' Create an instance of the object.
'    ' -------------------------------------------------------------------------
'    LOCAL oFso AS DISPATCH
'    SET oFso = NEW DISPATCH IN "Scripting.FileSystemObject"
'    IF ISFALSE ISOBJECT(oFso) THEN EXIT FUNCTION
'    ' -------------------------------------------------------------------------
'
'    ' --------------------------------------------------------------------------
'    ' Get a reference to the Folder object
'    ' --------------------------------------------------------------------------
'    LOCAL oFolder AS DISPATCH
'    LOCAL vFolder AS VARIANT
'    LOCAL vPath AS VARIANT
'    vPath = "c:\pbwin70\bin\"
'
'    OBJECT CALL oFso.GetFolder(vPath) TO vFolder
'    SET oFolder = vFolder
'    ' --------------------------------------------------------------------------
'
'    ' --------------------------------------------------------------------------
'    ' Get a reference to the Files collection
'    ' --------------------------------------------------------------------------
'    LOCAL oFiles AS DISPATCH
'    LOCAL vFiles AS VARIANT
'    OBJECT GET oFolder.Files TO vFiles
'    SET oFiles = vFiles
'    ' --------------------------------------------------------------------------
'
'    ' --------------------------------------------------------------------------
'    ' Release the Folder interface
'    ' --------------------------------------------------------------------------
'    SET oFolder = NOTHING
'
'    ' --------------------------------------------------------------------------
'    ' Get the number of files
'    ' --------------------------------------------------------------------------
'    LOCAL vFilesCount AS VARIANT
'    LOCAL nCount AS LONG
'    OBJECT GET oFiles.Count TO vFilesCount
'    nCount = VARIANT#(vFilesCount)
'    ' --------------------------------------------------------------------------
'
'    ' --------------------------------------------------------------------------
'    ' Enumerate the Files collection
'    ' --------------------------------------------------------------------------
'    LOCAL oItem AS DISPATCH
'    LOCAL i AS LONG
'    LOCAL vName AS VARIANT
'    LOCAL vRes AS VARIANT
'
'    DIM vArray (1 TO nCount) AS VARIANT           ' // DIM an array of variants
'    TB_EnumCollection(OBJPTR(oFiles), vArray())  ' // Enumerate the collection
'
'    FOR i = LBOUND(vArray) TO UBOUND(vArray)
'       SET oItem = vArray(i)                      ' // Assign the interface reference
'       IF OBJRESULT THEN EXIT FOR                 ' // Exit on failure
'       vName = EMPTY                              ' // Empty the variant
'       OBJECT GET oItem.Name TO vName             ' // Get the name of the file
'       PRINT VARIANT$(vName)                      ' // Show it
'       SET oItem = NOTHING                        ' // Release the interface
'    NEXT
'
'    ' -------------------------------------------------------------------------
'    ' ** CLEANUP **
'    ' -------------------------------------------------------------------------
'    SET oFiles = NOTHING  ' Release the Files interface
'    SET oFso = NOTHING    ' Release the FileSystemObject object
'
'    WAITKEY$
'
'  END FUNCTION
'
' *********************************************************************************************
FUNCTION TB_EnumCollection (BYVAL pthis AS DWORD, vArray() AS VARIANT) AS LONG

    LOCAL HRESULT AS LONG               ' // COM result code
    LOCAL IID_IEnumVariant AS GUID      ' // GUID of the IEnumVARIANT interface
    LOCAL pEnum AS DWORD                ' // Address of a pointer to the collection
    LOCAL pIEnumVARIANT AS DWORD        ' // Address of a pointer to the IEnumVARIANT interface
    LOCAL nCount AS LONG                ' // Number of elements to fetch
    LOCAL celtFetched AS DWORD          ' // Number of elements fetched
    LOCAL dwArray AS DWORD              ' // Pointer to the first element in the array
    LOCAL vVar AS VARIANT               ' // General purpose variant

    IID_IEnumVARIANT = GUID$("{00020404-0000-0000-c000-000000000046}")

    ' Check for null pointer
    IF ISFALSE pthis THEN FUNCTION = &H80004003 : EXIT FUNCTION   ' %E_POINTER

    ' Number of elements in the array
    nCount = ARRAYATTR(vArray(), 4)
    IF nCount = 0 THEN FUNCTION = 461 : EXIT FUNCTION   ' Array not dimensioned

    ' Get a reference to the Enumerator object
    HRESULT = TB_Collection_NewEnum (pthis, pEnum)
    IF ISTRUE HRESULT THEN FUNCTION = HRESULT : EXIT FUNCTION
    IF ISFALSE pEnum THEN FUNCTION = &H80004003 : EXIT FUNCTION

    ' Get a pointer to the IEnumVARIANT interface.
    HRESULT = TB_Collection_IUnknown_QueryInterface (pEnum, IID_IEnumVARIANT, pIEnumVARIANT)
    IF ISTRUE HRESULT THEN
       FUNCTION = HRESULT
       TB_Collection_IUnknown_Release pEnum
       EXIT FUNCTION
    END IF

    IF ISFALSE pIEnumVARIANT THEN
       FUNCTION = &H80004003
       TB_Collection_IUnknown_Release pEnum
       EXIT FUNCTION
    END IF

    ' Release the collection's enumerator interface.
    ' Note: If pEnum and pIEnumVARIANT are the same, this will decrease the reference count;
    ' otherwise, it will release the enumerator interface.
    TB_Collection_IUnknown_Release pEnum

    ' Position the enumerator at the beginning of the list of elements
    HRESULT = TB_Collection_IEnumVARIANT_Reset (pIEnumVARIANT)

    IF ISTRUE HRESULT THEN
       FUNCTION = HRESULT
       TB_Collection_IUnknown_Release pIEnumVARIANT
       EXIT FUNCTION
    END IF

    ' Fetch nCount elements of the collection
    dwArray = VARPTR(vArray(LBOUND(vArray)))
    HRESULT = TB_Collection_IEnumVARIANT_Next (pIEnumVARIANT, nCount, dwArray, celtFetched)
    FUNCTION = HRESULT

    ' Release the interface
    TB_Collection_IUnknown_Release pIEnumVARIANT

END FUNCTION
' *********************************************************************************************

 

 

Page last updated on Thursday, 16 March 2006 19:57:55 +0100