226 lines
7.4 KiB
C++
226 lines
7.4 KiB
C++
//+---------------------------------------------------------------------------
|
||
//
|
||
// Microsoft Windows
|
||
// Copyright (C) Microsoft Corporation, 1992 - 1997.
|
||
//
|
||
// File: cdispmgr.cxx
|
||
//
|
||
// Contents: The dispatch manager -- a class to manage
|
||
// multiple IDispatch-callable interfaces.
|
||
//
|
||
// History: ??-???-?? KrishnaG created
|
||
// 07-Sep-97 t-blakej Commented, cleaned up, made
|
||
// independent of ADSI.
|
||
//
|
||
//----------------------------------------------------------------------------
|
||
|
||
//
|
||
// Dispatch manager description:
|
||
//
|
||
|
||
//
|
||
// The dispatch manager is a way to invoke methods on an object that has
|
||
// more than one COM interface. The regular GetIDsOfNames and Invoke
|
||
// methods assume only a single ITypeInfo to look up and call names from;
|
||
// if an object has more than one interface, it has multiple ITypeInfo's,
|
||
// and it has to explicitly check each one. The dispatch manager implements
|
||
// the IDispatch methods, and keeps track of as many ITypeInfos as necessary.
|
||
//
|
||
// To use the dispatch manager, an object should store a pointer to a
|
||
// CAggregatorDispMgr object and delegate all IDispatch calls to it, or perhaps
|
||
// inherit from it directly. The method
|
||
//
|
||
// HRESULT CAggregatorDispMgr::LoadTypeInfoEntry(
|
||
// REFIID libid, REFIID iid, void *pIntf, DISPID SpecialId)
|
||
//
|
||
// is used to load the type information for the object into the dispatch
|
||
// manager. The arguments to this method are:
|
||
//
|
||
// REFIID libid - IID of the type library to load from
|
||
// REFIID iid - IID of the interface to load
|
||
// void *pIntf - pointer to the interface on the containing
|
||
// object
|
||
// DISPID SpecialId - DISPID_REGULAR for most things (see below);
|
||
// DISPID_VALUE for interfaces which implement
|
||
// the containing object's "value" property;
|
||
// DISPID_NEWENUM for interfaces which implement
|
||
// the containing object's "NewEnum" method
|
||
//
|
||
// DISPID_REGULAR is defined to be 1 by all ADSI providers, but not in
|
||
// any top-level include file. So
|
||
// non-ADSI users of the dispatch manager will probably have to define it
|
||
// explicitly.
|
||
//
|
||
// The LoadTypeInfoEntry method should be called at constructor time of
|
||
// the containing object. After all the type information is loaded, the
|
||
// dispatch manager can start servicing GetIDsOfNames and Invoke calls.
|
||
//
|
||
//
|
||
// For ADSI, there are two other calls to load information into the dispatch
|
||
// manager:
|
||
//
|
||
// void CAggregatorDispMgr::RegisterPropertyCache(IPropertyCache *pPropertyCache);
|
||
// void CAggregatorDispMgr::RegisterBaseDispatchPtr(IDispatch *pDispatch);
|
||
//
|
||
// The first method registers a property cache of the containing object;
|
||
// this is used in the ADSI providers to cache attributes of a directory
|
||
// server object. See iprops.hxx for more information.
|
||
//
|
||
// The second method is a hack used to get around a lack of inheritance.
|
||
// If an object A implements IDispatch and some other dual interfaces,
|
||
// and an object B derives from A and also implements IDispatch and some
|
||
// other dual interfaces, this method can be used in object B to use A's
|
||
// dispatch manager as a "backup" to its own. This way B doesn't have to
|
||
// load the type information about the interfaces it inherits from A.
|
||
// (Also, if A has an ADSI property cache, then callers of B's IDispatch
|
||
// methods can get at the underlying property cache.)
|
||
//
|
||
// The function
|
||
//
|
||
// void FreeTypeInfoTable();
|
||
//
|
||
// should be called at global destructor or library-unload time. Currently,
|
||
// all the ADSI libraries do it separately; NOTE - make an object to do it
|
||
// automatically in the dispatch manager.
|
||
//
|
||
//
|
||
// The DISPIDs returned by GetIDsOfNames are 32 bit values laid out
|
||
// as follows:
|
||
//
|
||
// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
|
||
// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
|
||
// +-+-------------+---------------+-------------------------------+
|
||
// |X| DispMgrId | TypeInfoId | DispId |
|
||
// +-+-------------+---------------+-------------------------------+
|
||
//
|
||
// where
|
||
//
|
||
// X - is reserved and never set. This would turn the value negative
|
||
// (which would overlap with some Automation-reserved DISPIDs.)
|
||
//
|
||
// DispMgrId - identifies the dispatch manager (used when stringing
|
||
// dispatch managers together via RegisterBaseDispatchPtr).
|
||
//
|
||
// TypeInfoId - uniquely identifies the interface within this
|
||
// dispatch manager.
|
||
//
|
||
// DispId - uniquely identifies the name within the interface.
|
||
//
|
||
// So if an object uses the dispatch manager, it shouldn't try to only use
|
||
// it for just GetIDsOfNames or just Invoke, since the DISPIDs returned are
|
||
// not necessarily the ones in the type library.
|
||
//
|
||
//////////////////////////////////////////////////////////////////////////////
|
||
|
||
// Forward declarations:
|
||
struct IPropertyCache;
|
||
/*
|
||
typedef struct _typeinfoentry
|
||
{
|
||
LONG TypeInfoId;
|
||
void *ptypeinfo;
|
||
void *pInterfacePointer;
|
||
struct _typeinfoentry *pNext;
|
||
} TYPEINFOENTRY, *PTYPEINFOENTRY;*/
|
||
|
||
class CAggregatorDispMgr
|
||
{
|
||
public:
|
||
CAggregatorDispMgr::CAggregatorDispMgr();
|
||
CAggregatorDispMgr::~CAggregatorDispMgr();
|
||
|
||
//
|
||
// The IDispatch methods are the main interface of the Dispatch Manager.
|
||
//
|
||
STDMETHOD(GetTypeInfoCount)(THIS_ UINT FAR* pctinfo);
|
||
|
||
STDMETHOD(GetTypeInfo)(THIS_ UINT itinfo, LCID lcid, ITypeInfo **pptinfo);
|
||
|
||
STDMETHOD(GetIDsOfNames)(THIS_ REFIID riid, LPWSTR *rgszNames,
|
||
UINT cNames, LCID lcid, DISPID *rgdispid);
|
||
|
||
STDMETHOD(Invoke)(THIS_ DISPID dispidMember, REFIID riid, LCID lcid,
|
||
WORD wFlags, DISPPARAMS *pdispparams, VARIANT *pvarResult,
|
||
EXCEPINFO *pexcepinfo, UINT *puArgErr);
|
||
|
||
//
|
||
// Methods for initializing the dispatch manager.
|
||
//
|
||
void
|
||
CAggregatorDispMgr::RegisterPropertyCache(IPropertyCache* pPropertyCache);
|
||
|
||
void
|
||
CAggregatorDispMgr::RegisterBaseDispatchPtr(IDispatch *pDispatch);
|
||
|
||
HRESULT
|
||
CAggregatorDispMgr::LoadTypeInfoEntry(
|
||
REFIID libid,
|
||
REFIID iid,
|
||
void * pIntf,
|
||
DISPID SpecialId
|
||
);
|
||
|
||
private:
|
||
void *
|
||
CAggregatorDispMgr::getInterfacePtr(LONG TypeInfoId);
|
||
|
||
ITypeInfo *
|
||
CAggregatorDispMgr::getTypeInfo(LONG TypeInfoId);
|
||
|
||
PTYPEINFOENTRY
|
||
CAggregatorDispMgr::FindTypeInfoEntry(LONG TypeInfoId);
|
||
|
||
HRESULT
|
||
CAggregatorDispMgr::AddTypeInfo(void FAR *ptypeinfo, void * pIntfptr);
|
||
|
||
|
||
STDMETHODIMP
|
||
CAggregatorDispMgr::TypeInfoInvoke(DISPID dispidMember, REFIID iid, LCID lcid,
|
||
unsigned short wFlags, DISPPARAMS FAR* pdispparams,
|
||
VARIANT FAR* pvarResult, EXCEPINFO FAR* pexcepinfo,
|
||
unsigned int FAR* puArgErr);
|
||
|
||
HRESULT
|
||
CAggregatorDispMgr::MarkAsNewEnum(void *pTypeInfo);
|
||
|
||
HRESULT
|
||
CAggregatorDispMgr::MarkAsItem(void *pTypeInfo);
|
||
|
||
PTYPEINFOENTRY
|
||
CAggregatorDispMgr::FindTypeInfo(void *pTypeInfo);
|
||
|
||
LONG
|
||
CAggregatorDispMgr::gentypeinfoid();
|
||
|
||
protected:
|
||
|
||
LONG _dwTypeInfoId;
|
||
PTYPEINFOENTRY _pTypeInfoEntry;
|
||
PTYPEINFOENTRY _pDispidNewEnum;
|
||
PTYPEINFOENTRY _pDispidValue;
|
||
|
||
IPropertyCache *_pPropertyCache;
|
||
LONG _dwPropCacheID;
|
||
};
|
||
|
||
#define BAIL_IF_ERROR(hr) if (FAILED(hr)) { goto cleanup; }
|
||
|
||
// deprecated
|
||
HRESULT
|
||
LoadTypeInfoEntry(
|
||
CAggregatorDispMgr * pDispMgr,
|
||
REFIID libid,
|
||
REFIID iid,
|
||
void * pIntf,
|
||
DISPID SpecialId
|
||
);
|
||
|
||
HRESULT
|
||
AggregatorDynamicDispidInvoke(
|
||
IPropertyCache * pPropertyCache,
|
||
DISPID dispid,
|
||
unsigned short wFlags,
|
||
DISPPARAMS *pdispparams,
|
||
VARIANT * pvarResult
|
||
);
|
||
|