#ifndef _IENUMVARIANT_H_
#define _IENUMVARIANT_H_
// Our ICollection VTable's GUID
// {F69902B1-20A0-4e99-97ED-CD671AA87B5C}
DEFINE_GUID(IID_ICollection, 0xf69902b1, 0x20a0, 0x4e99, 0x97, 0xed, 0xcd, 0x67, 0x1a, 0xa8, 0x7b, 0x5c);
// Our ICollection's VTable
#undef INTERFACE
#define INTERFACE ICollection
DECLARE_INTERFACE_ (INTERFACE, IDispatch)
{
// IUnknown functions
STDMETHOD (QueryInterface) (THIS_ REFIID, void **) PURE;
STDMETHOD_ (ULONG, AddRef) (THIS) PURE;
STDMETHOD_ (ULONG, Release) (THIS) PURE;
// IDispatch functions
STDMETHOD_ (ULONG, GetTypeInfoCount)(THIS_ UINT *) PURE;
STDMETHOD_ (ULONG, GetTypeInfo) (THIS_ UINT, LCID, ITypeInfo **) PURE;
STDMETHOD_ (ULONG, GetIDsOfNames) (THIS_ REFIID, LPOLESTR *, UINT, LCID, DISPID *) PURE;
STDMETHOD_ (ULONG, Invoke) (THIS_ DISPID, REFIID, LCID, WORD, DISPPARAMS *, VARIANT *, EXCEPINFO *, UINT *) PURE;
// Extra functions
STDMETHOD (Count) (THIS_ long *);
STDMETHOD (Item) (THIS_ long, VARIANT *);
STDMETHOD (_NewEnum) (THIS_ IUnknown **);
};
// My IENUMITEM struct. This stores a value for one item
// in our linked list of items
typedef struct _IENUMITEM {
struct _IENUMITEM *next; // A linked list of IENUMITEMs. Must be the first field
VARIANT value; // This item's value
} IENUMITEM;
// My IENUMLIST struct. This stores linked list of IENUMITEMs,
// plus it has as DWORD reference count of how many collection
// and IEnumVARIANT are currently referencing the list
typedef struct {
struct _IENUMITEM *head; // A linked list of IENUMITEMs. Must be the first field
DWORD count;
} IENUMLIST;
// Above, we use a macro which defines our ICollection struct
// as so:
//
// typedef struct {
// ICollectionVtbl *lpVtbl;
// } ICollection;
//
// In other words, it defines our ICollection to have nothing
// but a pointer to its VTable. And of course, every COM object must
// start with a pointer to its VTable.
//
// But we actually want to add some more members to our ICollection.
// So here we'll define a MyRealICollection that contains those extra
// members.
//
// We add a DWORD reference count so that this ICollection can be
// allocated (for example, we allocate an ICollection when our
// IExample5 object's GetPorts() calls allocPortsCollection) and
// later freed.
//
// We also add a pointer to the IENUMLIST pertinent to this
// particular ICollection. For example, when we create an ICollection
// for allocPortsCollection(), we'll set this to point to the global
// variable "PortsList" which is the IENUMLIST of our list of port names.
// For our needs, we need only one list for each type of ICollection
// we create. (ie, All ICollections to list our port names will reference
// the same global IENUMLIST)
typedef struct {
ICollectionVtbl *lpVtbl;
DWORD count;
IENUMLIST *list;
} MyRealICollection;
IENUMITEM * allocIENUMITEM(VARIANT *);
void freeOneItem(IENUMITEM *, IENUMITEM **);
void freeEnumList(IENUMLIST *);
IDispatch * allocICollection(IENUMLIST *);
void initCollectionTypeInfo(void);
void freeCollectionTypeInfo(void);
// These simply inc/dec the global variable OutstandingObjects
// whenever we allocate/free an object that is given to an app
extern void incOutstandingObjects(void);
extern DWORD decOutstandingObjects(void);
// Include the header files of all sources that use our generic collection/IEnumVARIANT.
// This means our sources only have to #include "IEnumVariant.h" to include all related
// stuff
#include "PortNames.h"
#include "NetCards.h"
#endif // _IENUMVARIANT_H_