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.

380 lines
11 KiB

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