Leaked source code of windows server 2003
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.

389 lines
12 KiB

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