Source code of Windows XP (NT5)
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.2 KiB

  1. //
  2. // Copyright 1997 - Microsoft
  3. //
  4. //
  5. // QI.H - Handles the query interface functions
  6. //
  7. #ifndef _QI_H_
  8. #define _QI_H_
  9. ///////////////////////////////////////
  10. //
  11. // QueryInterface Definitions
  12. //
  13. typedef struct {
  14. LPUNKNOWN pvtbl; // "punk" - pointer to a specific interface
  15. const struct _GUID *riid; // GUID of interfaace
  16. #ifdef DEBUG
  17. LPCTSTR pszName; // Text name of interface - used to make sure tables are consistant
  18. DWORD cFunctions; // Number of function entries in this interface's vtbl.
  19. #endif // DEBUG
  20. } QITABLE, *LPQITABLE, QIENTRY, *LPQIENTRY;
  21. ///////////////////////////////////////
  22. //
  23. // Quick-Lookup table declaration macro
  24. //
  25. #define DECLARE_QITABLE( _Class) QITABLE _QITable[ARRAYSIZE(QIT_##_Class)];
  26. ///////////////////////////////////////
  27. //
  28. // Quick-Lookup table construction macros
  29. //
  30. #ifdef DEBUG
  31. #define DEFINE_QI( _iface, _name, _nFunctions ) \
  32. { NULL, &_iface, TEXT(#_name), _nFunctions },
  33. #else // RETAIL
  34. #define DEFINE_QI( _iface, _name, _nFunctions ) \
  35. { NULL, &_iface },
  36. #endif // DEBUG
  37. #define BEGIN_QITABLE( _Class ) \
  38. static const QITABLE QIT_##_Class[] = { DEFINE_QI( IID_IUnknown, IUnknown, 0 )
  39. #define END_QITABLE { NULL, NULL } };
  40. ///////////////////////////////////////
  41. //
  42. // Common Quick-Lookup QueryInterface( )
  43. //
  44. extern HRESULT
  45. QueryInterface(
  46. LPVOID that,
  47. LPQITABLE pQI,
  48. REFIID riid,
  49. LPVOID *ppv );
  50. #ifdef DEBUG
  51. ///////////////////////////////////////
  52. //
  53. // BEGIN DEBUG
  54. //
  55. #ifndef NO_TRACE_INTERFACES
  56. ///////////////////////////////////////
  57. //
  58. // BEGIN DEBUG INTERFACE TRACKING
  59. //
  60. #pragma message("BUILD: Interface tracking enabled")
  61. ///////////////////////////////////////
  62. //
  63. // Debug Quick-Lookup QI Interface Macros
  64. //
  65. // Begins construction of the runtime Quick-Lookup table.
  66. // Adds IUnknown by default.
  67. #define BEGIN_QITABLE_IMP( _Class, _IUnknownPrimaryInterface ) \
  68. int _i = 0; \
  69. CopyMemory( _QITable, &QIT_##_Class, sizeof( QIT_##_Class ) ); \
  70. _QITable[_i].pvtbl = (_IUnknownPrimaryInterface *) this;
  71. // Checks that the QIENTRY matches the current QITABLE_IMP.
  72. #define QITABLE_IMP( _Interface ) \
  73. _i++; \
  74. _QITable[_i].pvtbl = (_Interface *) this; \
  75. { int ___i = lstrcmp( TEXT(#_Interface), _QITable[_i].pszName ); \
  76. AssertMsg( ___i == 0, \
  77. "DEFINE_QIs and QITABLE_IMPs don't match. Incorrect order.\n" ); }
  78. // Verifies that the number of entries in the QITABLE match
  79. // the number of QITABLE_IMP in the runtime section
  80. #define END_QITABLE_IMP( _Class ) \
  81. AssertMsg( _i == ( ARRAYSIZE( QIT_##_Class ) - 2 ), \
  82. "The number of DEFINE_QIs and QITABLE_IMPs don't match.\n" ); \
  83. LPVOID pCITracker; \
  84. TraceMsgDo( pCITracker = CITracker_CreateInstance( _QITable ), "0x%08x" );
  85. ///////////////////////////////////////
  86. //
  87. // CITracker Structures
  88. //
  89. typedef HRESULT (CALLBACK *LPFNQUERYINTERFACE)(
  90. LPUNKNOWN punk,
  91. REFIID riid,
  92. LPVOID* ppv );
  93. typedef ULONG (CALLBACK *LPFNADDREF)(
  94. LPUNKNOWN punk );
  95. typedef ULONG (CALLBACK *LPFNRELEASE)(
  96. LPUNKNOWN punk );
  97. typedef struct __vtbl {
  98. LPFNQUERYINTERFACE lpfnQueryInterface;
  99. LPFNADDREF lpfnAddRef;
  100. LPFNRELEASE lpfnRelease;
  101. } VTBL, *LPVTBL;
  102. typedef struct __vtbl2 {
  103. LPCTSTR pszInterface;
  104. UINT cRef;
  105. LPUNKNOWN punk;
  106. LPVTBL pOrginalVtbl;
  107. LPUNKNOWN pITracker;
  108. // These must be last and in this order QI, AddRef, Release.
  109. LPFNQUERYINTERFACE lpfnQueryInterface;
  110. LPFNADDREF lpfnAddRef;
  111. LPFNRELEASE lpfnRelease;
  112. } VTBL2, *LPVTBL2;
  113. #define VTBL2OFFSET ( sizeof( VTBL2 ) - ( 3 * sizeof(LPVOID) ) )
  114. ///////////////////////////////////////
  115. //
  116. // CITracker Functions
  117. //
  118. LPVOID
  119. CITracker_CreateInstance(
  120. LPQITABLE pQITable ); // QI Table of the object
  121. ///////////////////////////////////////
  122. //
  123. // CCITracker Class
  124. //
  125. //
  126. class
  127. CITracker:
  128. public IUnknown
  129. {
  130. private: // Members
  131. VTBL2 _vtbl;
  132. private: // Methods
  133. CITracker( );
  134. ~CITracker( );
  135. STDMETHOD(Init)( LPQITABLE pQITable );
  136. public: // Methods
  137. friend LPVOID CITracker_CreateInstance( LPQITABLE pQITable );
  138. // IUnknown (Translates to IUnknown2)
  139. STDMETHOD(QueryInterface)( REFIID riid, LPVOID *ppv );
  140. STDMETHOD_(ULONG, AddRef)(void);
  141. STDMETHOD_(ULONG, Release)(void);
  142. // IUnknown2 (Real Implementation)
  143. STDMETHOD(_QueryInterface)( REFIID riid, LPVOID *ppv );
  144. STDMETHOD_(ULONG, _AddRef)(void);
  145. STDMETHOD_(ULONG, _Release)(void);
  146. };
  147. typedef CITracker* LPITRACKER;
  148. //
  149. // END DEBUG INTERFACE TRACKING
  150. //
  151. ///////////////////////////////////////
  152. #else // !NO_TRACE_INTERFACES
  153. ///////////////////////////////////////
  154. //
  155. // BEGIN DEBUG WITHOUT INTERFACE TRACKING
  156. //
  157. // Begins construction of the runtime Quick-Lookup table.
  158. // Adds IUnknown by default.
  159. #define BEGIN_QITABLE_IMP( _Class, _IUnknownPrimaryInterface ) \
  160. int _i = 0; \
  161. LPVOID pCITracker; \
  162. CopyMemory( _QITable, &QIT_##_Class, sizeof( QIT_##_Class ) ); \
  163. _QITable[_i].pvtbl = (_IUnknownPrimaryInterface *) this;
  164. // Adds a CITracker to interface and checks that the QIENRTY
  165. // matches the current QITABLE_IMP.
  166. #define QITABLE_IMP( _Interface ) \
  167. _i++; \
  168. _QITable[_i].pvtbl = (_Interface *) this; \
  169. { int ___i = lstrcmp( TEXT(#_Interface), _QITable[_i].pszName ); \
  170. AssertMsg( ___i == 0, \
  171. "DEFINE_QIs and QITABLE_IMPs don't match. Incorrect order.\n" ); }
  172. // Verifies that the number of entries in the QITABLE match
  173. // the number of QITABLE_IMP in the runtime section
  174. #define END_QITABLE_IMP( _Class )\
  175. AssertMsg( _i == ( ARRAYSIZE( QIT_##_Class ) - 2 ), \
  176. "The number of DEFINE_QIs and QITABLE_IMPs don't match.\n" );
  177. //
  178. // END DEBUG INTERFACE TRACKING
  179. //
  180. ///////////////////////////////////////
  181. #endif // NO_TRACE_INTERFACES
  182. #else
  183. ///////////////////////////////////////
  184. //
  185. // BEGIN RETAIL
  186. //
  187. //
  188. // Debug Macros -> Retail Code
  189. //
  190. #define BEGIN_QITABLE_IMP( _Class, _IUnknownPrimaryInterface ) \
  191. int _i = 0; \
  192. CopyMemory( _QITable, &QIT_##_Class, sizeof( QIT_##_Class ) ); \
  193. _QITable[_i++].pvtbl = (_IUnknownPrimaryInterface *) this;
  194. #define QITABLE_IMP( _Interface ) \
  195. _QITable[_i++].pvtbl = (_Interface *) this;
  196. #define END_QITABLE_IMP( _Class )
  197. //
  198. // END RETAIL
  199. //
  200. ///////////////////////////////////////
  201. #endif // DEBUG
  202. #endif _QI_H_