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.

365 lines
11 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1999 - 2000 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // CITracker.H
  7. //
  8. // Description:
  9. // Implementation of a COM interface tracker.
  10. //
  11. // [Documentation:]
  12. // Debugging.PPT - A power-point presentation of the debug utilities.
  13. //
  14. // Maintained By:
  15. // Geoffrey Pease (gpease) 19-NOV-1999
  16. //
  17. // Notes:
  18. // This is X86 specific for now. It can be adapted for other platforms
  19. // as required. Since today, most of our developement is done on the
  20. // X86 platform, there is not a need to do this (yet).
  21. //
  22. // Define NO_TRACE_INTERFACES to disable interface tracking in DEBUG
  23. // builds.
  24. //
  25. // Define TRACE_INTERFACES_ENABLED to enable interface tracking in RETAIL
  26. // builds.
  27. //
  28. //////////////////////////////////////////////////////////////////////////////
  29. #pragma once
  30. //
  31. // Combine this complex expression in to one simple #define.
  32. //
  33. #if ( DBG==1 || defined( _DEBUG ) ) && !defined( NO_TRACE_INTERFACES )
  34. #define TRACE_INTERFACES_ENABLED
  35. #endif
  36. #if defined( _X86_ )
  37. ///////////////////////////////////////
  38. //
  39. // BEGIN _X86_
  40. //
  41. #if defined( TRACE_INTERFACES_ENABLED )
  42. ///////////////////////////////////////
  43. //
  44. // BEGIN DEBUG INTERFACE TRACKING
  45. //
  46. #pragma message("BUILD: Interface Tracking Enabled")
  47. ///////////////////////////////////////
  48. //
  49. // TraceInterface definitions
  50. //
  51. typedef struct {
  52. const struct _GUID * riid;
  53. LPCTSTR pszName;
  54. ULONG cFunctions;
  55. } INTERFACE_TABLE[], INTERFACE_TABLE_ENTRY, * LPINTERFACE_TABLE_ENTRY;
  56. //
  57. // Interface Table
  58. //
  59. // This table is used in builds in which interface tracking was turned on. It
  60. // is used to map an name with a particular IID. It also helps the CITracker
  61. // determine the size of the interfaces Vtable to mimic (haven't figured out
  62. // a runtime or compile time way to do this).
  63. //
  64. extern const INTERFACE_TABLE g_itTable;
  65. //////////////////////////////////////////////////////////////////////////////
  66. //
  67. // MACRO
  68. // _interface *
  69. // TraceInterface(
  70. // _nameIn,
  71. // _interface,
  72. // _punkIn,
  73. // _addrefIn
  74. // )
  75. //
  76. // Description:
  77. // This is the macro wrapper for DebugTrackInterface( ) which is only
  78. // defined in DEBUG builds. Using the TraceInterface( ) macro eliminates
  79. // the need for specifying compile time parameters as well as the
  80. // #ifdef/#endif definitions around the call.
  81. //
  82. // This "routine" creates a CITracker for the interface specified by
  83. // _interface and returns a new punk to the interface. You specify the
  84. // initial ref count on the interface using the _addrefIn parameter. You
  85. // can assign a name to the object that the interface refereneces in the
  86. // _nameIn parameter. The returned punk will be cast to the _interface
  87. // parameter.
  88. //
  89. // If there is insufficent memory to create the CITracker, the _punkIn
  90. // will be returned instead. There is no need to check the output for
  91. // failures as they are all handle internally to provide worry-free use.
  92. //
  93. // If you are getting an AV after adding tracing to the interface, this
  94. // usually indicates that the Interface Table entry for that interface
  95. // is incorrect. Double check the number of methods on the interface
  96. // against the tables.
  97. //
  98. // Arguments:
  99. // _nameIn - Name of the object this interface references (string).
  100. // _interface - Name of the interface (typedef).
  101. // _punkIn - Pointer to interface to track
  102. // _addrefIn - Initial reference count on the interface.
  103. //
  104. // Return Values:
  105. // a VALID _interface pointer
  106. // Points to the CITracker that can be used as if it were the
  107. // orginal _punkIn. If there was insufficent memory, the orginal
  108. // _punkIn will be returned.
  109. //
  110. // NOTES:
  111. // _addrefIn should be 0 if your going to be giving out the interface
  112. // from your QueryInterface routine if you AddRef( ) before giving it
  113. // out (typical QueryInterface( ) routines do this ).
  114. //
  115. //////////////////////////////////////////////////////////////////////////////
  116. #define TraceInterface( _nameIn, _interface, _punkIn, _addrefIn ) \
  117. reinterpret_cast<_interface*>( \
  118. DebugTrackInterface( TEXT(__FILE__), \
  119. __LINE__, \
  120. __MODULE__, \
  121. _nameIn, \
  122. IID_##_interface, \
  123. static_cast<_interface*>( _punkIn), \
  124. _addrefIn \
  125. ) )
  126. ///////////////////////////////////////
  127. //
  128. // IID --> Name lookup stuff
  129. //
  130. #if defined( DEBUG )
  131. static const cchGUID_STRING_SIZE = sizeof("{12345678-1234-1234-1234-123456789012}");
  132. #define PszTraceFindInterface( _riid, _szguid ) \
  133. ( g_tfModule ? PszDebugFindInterface( _riid, _szguid ) : TEXT("riid") )
  134. LPCTSTR
  135. PszDebugFindInterface(
  136. REFIID riidIn,
  137. LPTSTR pszGuidBufOut
  138. );
  139. #endif // DEBUG
  140. ///////////////////////////////////////
  141. //
  142. // CITracker Structures
  143. //
  144. typedef HRESULT (CALLBACK *LPFNQUERYINTERFACE)(
  145. LPUNKNOWN punk,
  146. REFIID riid,
  147. LPVOID* ppv );
  148. typedef ULONG (CALLBACK *LPFNADDREF)(
  149. LPUNKNOWN punk );
  150. typedef ULONG (CALLBACK *LPFNRELEASE)(
  151. LPUNKNOWN punk );
  152. typedef struct __vtbl {
  153. LPFNQUERYINTERFACE lpfnQueryInterface;
  154. LPFNADDREF lpfnAddRef;
  155. LPFNRELEASE lpfnRelease;
  156. } VTBL, *LPVTBL;
  157. typedef struct __vtbl2 {
  158. ULONG cRef;
  159. LPUNKNOWN punk;
  160. LPCTSTR pszInterface;
  161. DWORD dwSize;
  162. LPVTBL pNewVtbl;
  163. // These must be last and in this order: QI, AddRef, Release.
  164. LPFNQUERYINTERFACE lpfnQueryInterface;
  165. LPFNADDREF lpfnAddRef;
  166. LPFNRELEASE lpfnRelease;
  167. // additional vtbl entries hang off the end
  168. } VTBL2, *LPVTBL2;
  169. #define VTBL2OFFSET ( sizeof( VTBL2 ) - ( 3 * sizeof(LPVOID) ) )
  170. ///////////////////////////////////////
  171. //
  172. // CITracker Functions
  173. //
  174. LPUNKNOWN
  175. DebugTrackInterface(
  176. LPCTSTR pszFileIn,
  177. const int nLineIn,
  178. LPCTSTR pszModuleIn,
  179. LPCTSTR pszNameIn,
  180. REFIID riidIn,
  181. LPUNKNOWN pvtblIn,
  182. LONG cRefIn
  183. );
  184. ///////////////////////////////////////
  185. //
  186. // interface IUnknownTracker
  187. //
  188. //
  189. class
  190. IUnknownTracker :
  191. public IUnknown
  192. {
  193. public:
  194. STDMETHOD(QueryInterface)( REFIID riid, LPVOID *ppv );
  195. STDMETHOD_(ULONG, AddRef)( void );
  196. STDMETHOD_(ULONG, Release)( void );
  197. STDMETHOD_(void, Stub3 )( void );
  198. STDMETHOD_(void, Stub4 )( void );
  199. STDMETHOD_(void, Stub5 )( void );
  200. STDMETHOD_(void, Stub6 )( void );
  201. STDMETHOD_(void, Stub7 )( void );
  202. STDMETHOD_(void, Stub8 )( void );
  203. STDMETHOD_(void, Stub9 )( void );
  204. STDMETHOD_(void, Stub10 )( void );
  205. STDMETHOD_(void, Stub11 )( void );
  206. STDMETHOD_(void, Stub12 )( void );
  207. STDMETHOD_(void, Stub13 )( void );
  208. STDMETHOD_(void, Stub14 )( void );
  209. STDMETHOD_(void, Stub15 )( void );
  210. STDMETHOD_(void, Stub16 )( void );
  211. STDMETHOD_(void, Stub17 )( void );
  212. STDMETHOD_(void, Stub18 )( void );
  213. STDMETHOD_(void, Stub19 )( void );
  214. STDMETHOD_(void, Stub20 )( void );
  215. STDMETHOD_(void, Stub21 )( void );
  216. STDMETHOD_(void, Stub22 )( void );
  217. STDMETHOD_(void, Stub23 )( void );
  218. STDMETHOD_(void, Stub24 )( void );
  219. STDMETHOD_(void, Stub25 )( void );
  220. STDMETHOD_(void, Stub26 )( void );
  221. STDMETHOD_(void, Stub27 )( void );
  222. STDMETHOD_(void, Stub28 )( void );
  223. STDMETHOD_(void, Stub29 )( void );
  224. STDMETHOD_(void, Stub30 )( void );
  225. }; //*** interface IUnknownTracker
  226. ///////////////////////////////////////
  227. //
  228. // interface IDeadObjTracker
  229. //
  230. class
  231. IDeadObjTracker
  232. {
  233. private: // Members
  234. VTBL2 m_vtbl;
  235. public:
  236. STDMETHOD( Stub0 )( LPVOID* punk );
  237. STDMETHOD( Stub1 )( LPVOID* punk );
  238. STDMETHOD( Stub2 )( LPVOID* punk );
  239. STDMETHOD( Stub3 )( LPVOID* punk );
  240. STDMETHOD( Stub4 )( LPVOID* punk );
  241. STDMETHOD( Stub5 )( LPVOID* punk );
  242. STDMETHOD( Stub6 )( LPVOID* punk );
  243. STDMETHOD( Stub7 )( LPVOID* punk );
  244. STDMETHOD( Stub8 )( LPVOID* punk );
  245. STDMETHOD( Stub9 )( LPVOID* punk );
  246. STDMETHOD( Stub10 )( LPVOID* punk );
  247. STDMETHOD( Stub11 )( LPVOID* punk );
  248. STDMETHOD( Stub12 )( LPVOID* punk );
  249. STDMETHOD( Stub13 )( LPVOID* punk );
  250. STDMETHOD( Stub14 )( LPVOID* punk );
  251. STDMETHOD( Stub15 )( LPVOID* punk );
  252. STDMETHOD( Stub16 )( LPVOID* punk );
  253. STDMETHOD( Stub17 )( LPVOID* punk );
  254. STDMETHOD( Stub18 )( LPVOID* punk );
  255. STDMETHOD( Stub19 )( LPVOID* punk );
  256. STDMETHOD( Stub20 )( LPVOID* punk );
  257. STDMETHOD( Stub21 )( LPVOID* punk );
  258. STDMETHOD( Stub22 )( LPVOID* punk );
  259. STDMETHOD( Stub23 )( LPVOID* punk );
  260. STDMETHOD( Stub24 )( LPVOID* punk );
  261. STDMETHOD( Stub25 )( LPVOID* punk );
  262. STDMETHOD( Stub26 )( LPVOID* punk );
  263. STDMETHOD( Stub27 )( LPVOID* punk );
  264. STDMETHOD( Stub28 )( LPVOID* punk );
  265. STDMETHOD( Stub29 )( LPVOID* punk );
  266. STDMETHOD( Stub30 )( LPVOID* punk );
  267. }; //*** interface IDeadObject
  268. ///////////////////////////////////////
  269. //
  270. // CITracker Class
  271. //
  272. class
  273. CITracker:
  274. public IUnknownTracker
  275. {
  276. private: // Members
  277. VTBL2 m_vtbl;
  278. private: // Methods
  279. CITracker( );
  280. ~CITracker( );
  281. STDMETHOD(Init)( LPUNKNOWN * ppunkOut,
  282. LPUNKNOWN punkIn,
  283. const INTERFACE_TABLE_ENTRY * piteIn,
  284. LPCTSTR pszNameIn,
  285. LONG cRefIn
  286. );
  287. public: // Methods
  288. friend LPUNKNOWN DebugTrackInterface( LPCTSTR pszFileIn,
  289. const int nLineIn,
  290. LPCTSTR pszModuleIn,
  291. LPCTSTR pszNameIn,
  292. REFIID riidIn,
  293. LPUNKNOWN pvtblIn,
  294. LONG cRefIn
  295. );
  296. // IUnknown
  297. STDMETHOD(QueryInterface)( REFIID riid, LPVOID *ppv );
  298. STDMETHOD_(ULONG, AddRef)(void);
  299. STDMETHOD_(ULONG, Release)(void);
  300. }; //*** class CITracker
  301. //
  302. // END DEBUG INTERFACE TRACKING
  303. //
  304. ///////////////////////////////////////
  305. #else // !TRACE_INTERFACES_ENABLED
  306. ///////////////////////////////////////
  307. //
  308. // BEGIN DEBUG WITHOUT INTERFACE TRACKING
  309. //
  310. #define TraceInterface( _nameIn, _interface, _punkIn, _faddrefIn ) static_cast<##_interface *>( _punkIn );
  311. #define PszDebugFindInterface( _riid, _szGuid ) L"<unknown>"
  312. //
  313. // END DEBUG INTERFACE TRACKING
  314. //
  315. ///////////////////////////////////////
  316. #endif // TRACE_INTERFACES_ENABLED
  317. //
  318. // END _X86_
  319. //
  320. ///////////////////////////////////////
  321. #else // !_X86_
  322. ///////////////////////////////////////
  323. //
  324. // BEGIN !_X86_
  325. //
  326. #define TraceInterface( _nameIn, _riidIn, _punkIn, _faddrefIn ) _punkIn
  327. #define PszDebugFindInterface( _riid, _szGuid ) L"<unknown>"
  328. //
  329. // END !_X86_
  330. //
  331. ///////////////////////////////////////
  332. #endif // _X86_