windows-nt/Source/XPSP1/NT/base/remoteboot/admin/qi.h
2020-09-26 16:20:57 +08:00

244 lines
6.2 KiB
C++

//
// 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, TEXT(#_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 = lstrcmp( TEXT(#_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 = lstrcmp( TEXT(#_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_