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.
243 lines
6.4 KiB
243 lines
6.4 KiB
//
|
|
// Copyright 1997 - Microsoft
|
|
//
|
|
|
|
//
|
|
// QI.H - Handles the query interface functions
|
|
//
|
|
|
|
#ifndef _QI_H_
|
|
#define _QI_H_
|
|
|
|
///////////////////////////////////////
|
|
//
|
|
// QueryInterface Definitions
|
|
//
|
|
typedef struct {
|
|
LPUNKNOWN pvtbl; // "punk" - pointer to a specific interface
|
|
const struct _GUID *riid; // GUID of interfaace
|
|
|
|
#ifdef DEBUG
|
|
LPCTSTR pszName; // Text name of interface - used to make sure tables are consistant
|
|
DWORD cFunctions; // Number of function entries in this interface's vtbl.
|
|
#endif // DEBUG
|
|
|
|
} QITABLE, *LPQITABLE, QIENTRY, *LPQIENTRY;
|
|
|
|
///////////////////////////////////////
|
|
//
|
|
// Quick-Lookup table declaration macro
|
|
//
|
|
#define DECLARE_QITABLE( _Class) QITABLE _QITable[ARRAYSIZE(QIT_##_Class)];
|
|
|
|
///////////////////////////////////////
|
|
//
|
|
// Quick-Lookup table construction macros
|
|
//
|
|
#ifdef DEBUG
|
|
#define DEFINE_QI( _iface, _name, _nFunctions ) \
|
|
{ NULL, &_iface, L#_name, _nFunctions },
|
|
#else // RETAIL
|
|
#define DEFINE_QI( _iface, _name, _nFunctions ) \
|
|
{ NULL, &_iface },
|
|
#endif // DEBUG
|
|
|
|
#define BEGIN_QITABLE( _Class ) \
|
|
static const QITABLE QIT_##_Class[] = { DEFINE_QI( IID_IUnknown, IUnknown, 0 )
|
|
|
|
#define END_QITABLE { NULL, NULL } };
|
|
|
|
///////////////////////////////////////
|
|
//
|
|
// Common Quick-Lookup QueryInterface( )
|
|
//
|
|
extern HRESULT
|
|
QueryInterface(
|
|
LPVOID that,
|
|
LPQITABLE pQI,
|
|
REFIID riid,
|
|
LPVOID *ppv );
|
|
|
|
#ifdef DEBUG
|
|
///////////////////////////////////////
|
|
//
|
|
// BEGIN DEBUG
|
|
//
|
|
|
|
#ifndef NO_TRACE_INTERFACES
|
|
///////////////////////////////////////
|
|
//
|
|
// BEGIN DEBUG INTERFACE TRACKING
|
|
//
|
|
#pragma message("BUILD: Interface tracking enabled")
|
|
|
|
///////////////////////////////////////
|
|
//
|
|
// Debug Quick-Lookup QI Interface Macros
|
|
//
|
|
|
|
// Begins construction of the runtime Quick-Lookup table.
|
|
// Adds IUnknown by default.
|
|
#define BEGIN_QITABLE_IMP( _Class, _IUnknownPrimaryInterface ) \
|
|
int _i = 0; \
|
|
CopyMemory( _QITable, &QIT_##_Class, sizeof( QIT_##_Class ) ); \
|
|
_QITable[_i].pvtbl = (_IUnknownPrimaryInterface *) this;
|
|
|
|
// Checks that the QIENTRY matches the current QITABLE_IMP.
|
|
#define QITABLE_IMP( _Interface ) \
|
|
_i++; \
|
|
_QITable[_i].pvtbl = (_Interface *) this; \
|
|
{ int ___i = wcscmp( L#_Interface, _QITable[_i].pszName ); \
|
|
AssertMsg( ___i == 0, \
|
|
"DEFINE_QIs and QITABLE_IMPs don't match. Incorrect order.\n" ); }
|
|
|
|
// Verifies that the number of entries in the QITABLE match
|
|
// the number of QITABLE_IMP in the runtime section
|
|
#define END_QITABLE_IMP( _Class ) \
|
|
AssertMsg( _i == ( ARRAYSIZE( QIT_##_Class ) - 2 ), \
|
|
"The number of DEFINE_QIs and QITABLE_IMPs don't match.\n" ); \
|
|
LPVOID pCITracker; \
|
|
TraceMsgDo( pCITracker = CITracker_CreateInstance( _QITable ), "0x%08x" );
|
|
|
|
///////////////////////////////////////
|
|
//
|
|
// CITracker Structures
|
|
//
|
|
typedef HRESULT (CALLBACK *LPFNQUERYINTERFACE)(
|
|
LPUNKNOWN punk,
|
|
REFIID riid,
|
|
LPVOID* ppv );
|
|
|
|
typedef ULONG (CALLBACK *LPFNADDREF)(
|
|
LPUNKNOWN punk );
|
|
|
|
typedef ULONG (CALLBACK *LPFNRELEASE)(
|
|
LPUNKNOWN punk );
|
|
|
|
typedef struct __vtbl {
|
|
LPFNQUERYINTERFACE lpfnQueryInterface;
|
|
LPFNADDREF lpfnAddRef;
|
|
LPFNRELEASE lpfnRelease;
|
|
} VTBL, *LPVTBL;
|
|
|
|
typedef struct __vtbl2 {
|
|
LPCTSTR pszInterface;
|
|
UINT cRef;
|
|
LPUNKNOWN punk;
|
|
LPVTBL pOrginalVtbl;
|
|
LPUNKNOWN pITracker;
|
|
// These must be last and in this order QI, AddRef, Release.
|
|
LPFNQUERYINTERFACE lpfnQueryInterface;
|
|
LPFNADDREF lpfnAddRef;
|
|
LPFNRELEASE lpfnRelease;
|
|
} VTBL2, *LPVTBL2;
|
|
|
|
#define VTBL2OFFSET ( sizeof( VTBL2 ) - ( 3 * sizeof(LPVOID) ) )
|
|
|
|
///////////////////////////////////////
|
|
//
|
|
// CITracker Functions
|
|
//
|
|
LPVOID
|
|
CITracker_CreateInstance(
|
|
LPQITABLE pQITable ); // QI Table of the object
|
|
|
|
///////////////////////////////////////
|
|
//
|
|
// CCITracker Class
|
|
//
|
|
//
|
|
class
|
|
CITracker:
|
|
public IUnknown
|
|
{
|
|
private: // Members
|
|
VTBL2 _vtbl;
|
|
|
|
private: // Methods
|
|
CITracker( );
|
|
~CITracker( );
|
|
STDMETHOD(Init)( LPQITABLE pQITable );
|
|
|
|
public: // Methods
|
|
friend LPVOID CITracker_CreateInstance( LPQITABLE pQITable );
|
|
|
|
// IUnknown (Translates to IUnknown2)
|
|
STDMETHOD(QueryInterface)( REFIID riid, LPVOID *ppv );
|
|
STDMETHOD_(ULONG, AddRef)(void);
|
|
STDMETHOD_(ULONG, Release)(void);
|
|
|
|
// IUnknown2 (Real Implementation)
|
|
STDMETHOD(_QueryInterface)( REFIID riid, LPVOID *ppv );
|
|
STDMETHOD_(ULONG, _AddRef)(void);
|
|
STDMETHOD_(ULONG, _Release)(void);
|
|
};
|
|
|
|
typedef CITracker* LPITRACKER;
|
|
|
|
//
|
|
// END DEBUG INTERFACE TRACKING
|
|
//
|
|
///////////////////////////////////////
|
|
#else // !NO_TRACE_INTERFACES
|
|
///////////////////////////////////////
|
|
//
|
|
// BEGIN DEBUG WITHOUT INTERFACE TRACKING
|
|
//
|
|
|
|
// Begins construction of the runtime Quick-Lookup table.
|
|
// Adds IUnknown by default.
|
|
#define BEGIN_QITABLE_IMP( _Class, _IUnknownPrimaryInterface ) \
|
|
int _i = 0; \
|
|
LPVOID pCITracker; \
|
|
CopyMemory( _QITable, &QIT_##_Class, sizeof( QIT_##_Class ) ); \
|
|
_QITable[_i].pvtbl = (_IUnknownPrimaryInterface *) this;
|
|
|
|
// Adds a CITracker to interface and checks that the QIENRTY
|
|
// matches the current QITABLE_IMP.
|
|
#define QITABLE_IMP( _Interface ) \
|
|
_i++; \
|
|
_QITable[_i].pvtbl = (_Interface *) this; \
|
|
{ int ___i = wcscmp( L#_Interface, _QITable[_i].pszName ); \
|
|
AssertMsg( ___i == 0, \
|
|
"DEFINE_QIs and QITABLE_IMPs don't match. Incorrect order.\n" ); }
|
|
|
|
// Verifies that the number of entries in the QITABLE match
|
|
// the number of QITABLE_IMP in the runtime section
|
|
#define END_QITABLE_IMP( _Class )\
|
|
AssertMsg( _i == ( ARRAYSIZE( QIT_##_Class ) - 2 ), \
|
|
"The number of DEFINE_QIs and QITABLE_IMPs don't match.\n" );
|
|
|
|
//
|
|
// END DEBUG INTERFACE TRACKING
|
|
//
|
|
///////////////////////////////////////
|
|
#endif // NO_TRACE_INTERFACES
|
|
|
|
#else
|
|
///////////////////////////////////////
|
|
//
|
|
// BEGIN RETAIL
|
|
//
|
|
|
|
//
|
|
// Debug Macros -> Retail Code
|
|
//
|
|
#define BEGIN_QITABLE_IMP( _Class, _IUnknownPrimaryInterface ) \
|
|
int _i = 0; \
|
|
CopyMemory( _QITable, &QIT_##_Class, sizeof( QIT_##_Class ) ); \
|
|
_QITable[_i++].pvtbl = (_IUnknownPrimaryInterface *) this;
|
|
|
|
#define QITABLE_IMP( _Interface ) \
|
|
_QITable[_i++].pvtbl = (_Interface *) this;
|
|
|
|
#define END_QITABLE_IMP( _Class )
|
|
|
|
|
|
//
|
|
// END RETAIL
|
|
//
|
|
///////////////////////////////////////
|
|
#endif // DEBUG
|
|
|
|
#endif _QI_H_
|