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.

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