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.

857 lines
25 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1999-2002 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // CITracker.CPP
  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) 14-JUN-2001
  16. // Geoffrey Pease (GPease) 19-NOV-1999
  17. //
  18. // Notes:
  19. // Define NO_TRACE_INTERFACES to disable interface tracking in DEBUG
  20. // builds.
  21. //
  22. // Define TRACE_INTERFACES_ENABLED to enable interface tracking in RETAIL
  23. // builds.
  24. //
  25. // Define FULL_TRACE_INTERFACES_ENABLED to enable full interface
  26. // tracking in RETAIL builds. Full interface tracking is enabled if
  27. // interface tracking is enabled and building for X86.
  28. // Full interface tracking is X86 specific for now. It can be adapted for
  29. // other platforms as required. Since today, most of our developement is
  30. // done on the X86 platform, there is not a need to do this (yet).
  31. //
  32. //////////////////////////////////////////////////////////////////////////////
  33. //#include "pch.h"
  34. #include <shlwapi.h>
  35. #include <StrSafe.h>
  36. #if defined( TRACE_INTERFACES_ENABLED )
  37. ///////////////////////////////////////
  38. //
  39. // BEGIN TRACE_INTERFACES_ENABLED
  40. //
  41. #if defined( DEBUG )
  42. //////////////////////////////////////////////////////////////////////////////
  43. //
  44. // PszDebugFindInterface
  45. //
  46. // Description:
  47. // Uses the Interface Tracking Table (g_itTable) to lookup a human
  48. // readable name for the riidIn. If no matching interface is found. it
  49. // will use the pszBufOut to format a GUID string and return it.
  50. //
  51. // Arguments:
  52. // riidIn - The interface ID to lookup.
  53. // pszBufOut - Buffer to use if interface not found to format GUID.
  54. //
  55. // Return Values:
  56. // Never NULL. It will always a valid string pointer to either the
  57. // interface name or to pszBufOut.
  58. //
  59. // Notes:
  60. // pszBufOut must be at least cchGUID_STRING_SIZE in size.
  61. //
  62. //////////////////////////////////////////////////////////////////////////////
  63. LPCWSTR
  64. PszDebugFindInterface(
  65. REFIID riidIn,
  66. LPWSTR pszBufOut
  67. )
  68. {
  69. if ( IsTraceFlagSet( mtfQUERYINTERFACE ) )
  70. {
  71. int idx;
  72. for ( idx = 0; g_itTable[ idx ].riid != NULL; idx++ )
  73. {
  74. if ( riidIn == *g_itTable[ idx ].riid )
  75. {
  76. return g_itTable[ idx ].pszName;
  77. } // if: found interface
  78. } // for: searching for interface
  79. THR( StringCchPrintfW(
  80. pszBufOut
  81. , cchGUID_STRING_SIZE
  82. , L"{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}"
  83. , riidIn.Data1
  84. , riidIn.Data2
  85. , riidIn.Data3
  86. , riidIn.Data4[0]
  87. , riidIn.Data4[1]
  88. , riidIn.Data4[2]
  89. , riidIn.Data4[3]
  90. , riidIn.Data4[4]
  91. , riidIn.Data4[5]
  92. , riidIn.Data4[6]
  93. , riidIn.Data4[7]
  94. ) );
  95. } // if: query interface is on
  96. else
  97. {
  98. return L"riid";
  99. } // else: just print riid
  100. return pszBufOut;
  101. } //*** PszDebugFindInterface
  102. #endif // DEBUG
  103. //
  104. // END TRACE_INTERFACES_ENABLED
  105. //
  106. ///////////////////////////////////////
  107. #endif // TRACE_INTERFACES_ENABLED
  108. // ************************************************************************
  109. #if defined( FULL_TRACE_INTERFACES_ENABLED )
  110. ///////////////////////////////////////
  111. //
  112. // BEGIN FULL_TRACE_INTERFACES_ENABLED
  113. //
  114. //
  115. // Globals
  116. //
  117. static IDeadObjTracker * g_pidoTracker = NULL; // dead object - there is only one.
  118. #ifndef NOISY_TRACE_INTERFACES
  119. ///////////////////////////////////////
  120. //
  121. // DEBUG !NOISY_TRACE_INTERFACES
  122. //
  123. //
  124. // Undefining these macros to make the CITracker quiet.
  125. //
  126. #undef TraceFunc
  127. #define TraceFunc 1 ? (void)0 : (void)
  128. #undef TraceFunc1
  129. #define TraceFunc1 1 ? (void)0 : (void)
  130. #undef TraceFunc2
  131. #define TraceFunc2 1 ? (void)0 : (void)
  132. #undef TraceFunc3
  133. #define TraceFunc3 1 ? (void)0 : (void)
  134. #undef TraceFunc4
  135. #define TraceFunc4 1 ? (void)0 : (void)
  136. #undef TraceFunc5
  137. #define TraceFunc5 1 ? (void)0 : (void)
  138. #undef TraceFunc6
  139. #define TraceFunc6 1 ? (void)0 : (void)
  140. #undef TraceQIFunc
  141. #define TraceQIFunc 1 ? (void)0 : (void)
  142. #undef TraceFuncExit
  143. #define TraceFuncExit()
  144. #undef FRETURN
  145. #define FRETURN( _u )
  146. #undef HRETURN
  147. #define HRETURN(_hr) return(_hr)
  148. #undef RETURN
  149. #define RETURN(_fn) return(_fn)
  150. #undef RRETURN
  151. #define RRETURN( _fn ) return(_fn)
  152. //
  153. // END !NOISY_TRACE_INTERFACES
  154. //
  155. ///////////////////////////////////////
  156. #endif // NOISY_TRACE_INTERFACES
  157. #if defined( DEBUG )
  158. //
  159. // These are internal to debug.cpp but not published in debug.h.
  160. //
  161. BOOL
  162. IsDebugFlagSet(
  163. TRACEFLAG tfIn
  164. );
  165. void
  166. DebugInitializeBuffer(
  167. LPCWSTR pszFileIn,
  168. const int nLineIn,
  169. LPCWSTR pszModuleIn,
  170. LPWSTR pszBufIn,
  171. INT * pcchInout,
  172. LPWSTR * ppszBufOut
  173. );
  174. #endif // DEBUG
  175. ///////////////////////////////////////
  176. //
  177. // CITracker Definition
  178. //
  179. //
  180. DEFINE_THISCLASS("CITracker");
  181. #define THISCLASS CITracker
  182. #define LPTHISCLASS CITracker*
  183. // ************************************************************************
  184. //
  185. // Constructor / Destructor
  186. //
  187. // ************************************************************************
  188. //////////////////////////////////////////////////////////////////////////////
  189. //
  190. // Special new() for CITracker
  191. //
  192. // Description:
  193. // Creates an object the size of the object plus nExtraIn bytes. This
  194. // allows the Vtable that the CITracker object is tracking to be
  195. // appended to the end of the CITracker object.
  196. //
  197. //////////////////////////////////////////////////////////////////////////////
  198. #ifdef new
  199. #undef new
  200. #endif
  201. void*
  202. __cdecl
  203. operator new(
  204. unsigned int nSizeIn,
  205. LPCWSTR pszFileIn,
  206. const int nLineIn,
  207. LPCWSTR pszModuleIn,
  208. UINT nExtraIn,
  209. LPCWSTR pszNameIn
  210. )
  211. {
  212. void * pv = HeapAlloc( GetProcessHeap(), 0, nSizeIn + nExtraIn );
  213. return TraceMemoryAdd( mmbtOBJECT, pv, pszFileIn, nLineIn, pszModuleIn, nSizeIn + nExtraIn, L"CITracker" );
  214. } //*** operator new
  215. //////////////////////////////////////////////////////////////////////////////
  216. //
  217. // DebugTrackInterface
  218. //
  219. // Description:
  220. // Create an interface tracker for the given interface.
  221. //
  222. // Arguments:
  223. // pszNameIn - Name to associate with object that the punk references.
  224. // riidIn - Interface IID of the interface to be tracked.
  225. // punkIn - Interface pointer to track.
  226. // cRefIn - Initialize ref count on the interface.
  227. //
  228. // Return Values:
  229. // On failure, this will be punkIn.
  230. // On success, pointer to an object that implements the interface to
  231. // be tracked.
  232. //
  233. //////////////////////////////////////////////////////////////////////////////
  234. LPUNKNOWN
  235. DebugTrackInterface(
  236. LPCWSTR pszFileIn,
  237. const int nLineIn,
  238. LPCWSTR pszModuleIn,
  239. LPCWSTR pszNameIn,
  240. REFIID riidIn,
  241. LPUNKNOWN punkIn,
  242. LONG cRefIn
  243. )
  244. {
  245. TraceFunc3( "pszNameIn = '%ws', riidIn, punkIn = 0x%08x, cRefIn = %u",
  246. pszNameIn,
  247. punkIn,
  248. cRefIn
  249. );
  250. UINT nEntry = 0;
  251. LPUNKNOWN punkOut = punkIn;
  252. //
  253. // Scan the table looking for the matching interface definition.
  254. //
  255. for( nEntry = 0; g_itTable[ nEntry ].riid != NULL; nEntry++ )
  256. {
  257. if ( riidIn == *g_itTable[ nEntry ].riid )
  258. {
  259. //
  260. // Figure out how much "extra" to allocate onto the CITracker.
  261. //
  262. UINT nExtra = ( 3 + g_itTable[ nEntry ].cFunctions ) * sizeof(LPVOID);
  263. //
  264. // Create a name for the tracker.
  265. //
  266. // TODO: gpease 19-NOV-1999
  267. // Maybe merge this in with the nExtra(??).
  268. //
  269. LPWSTR pszName;
  270. DWORD cch = ( wcslen( g_itTable[ nEntry ].pszName ) + wcslen( pszNameIn ) + 3 + 2 ); // '::[' + ']' + NULL
  271. pszName = (LPWSTR) HeapAlloc( GetProcessHeap(), 0, cch * sizeof( *pszName ) );
  272. THR( StringCchPrintfW( pszName, cch, L"%ws::[%ws]", pszNameIn, g_itTable[ nEntry ].pszName ) );
  273. //
  274. // Create the tracker.
  275. //
  276. LPTHISCLASS pc = new( pszFileIn, nLineIn, pszModuleIn, nExtra, pszName ) THISCLASS();
  277. if ( pc != NULL )
  278. {
  279. HRESULT hr;
  280. //
  281. // Initialize the tracker.
  282. //
  283. hr = THR( pc->Init( &punkOut, punkIn, &g_itTable[ nEntry ], pszName, cRefIn ) );
  284. if ( FAILED( hr ) )
  285. {
  286. //
  287. // If it failed, delete it.
  288. //
  289. delete pc;
  290. } // if: failed to initialize
  291. } // if: got memory
  292. break; // exit loop
  293. } // if: matched interface
  294. } // for: more entries in table
  295. AssertMsg( g_itTable[ nEntry ].riid != NULL, "There has been a request to track an interface that is not in the interface table." );
  296. RETURN( punkOut );
  297. } //*** DebugTrackInterface
  298. //////////////////////////////////////////////////////////////////////////////
  299. //
  300. // CITracker::CITracker( void )
  301. //
  302. //////////////////////////////////////////////////////////////////////////////
  303. CITracker::CITracker( void )
  304. {
  305. TraceFunc( "" );
  306. //
  307. // KB: gpease 10-OCT-1998
  308. // This class will leak objects to help catch bad components
  309. // that call back into released interfaces therefore this
  310. // DLL will not be able to be released.
  311. //
  312. if ( g_tfModule & mtfCITRACKERS )
  313. {
  314. //
  315. // Only count CITrackers if tracking is enabled.
  316. //
  317. InterlockedIncrement( &g_cObjects );
  318. }
  319. TraceFuncExit();
  320. } //*** CITracker::ctor
  321. //////////////////////////////////////////////////////////////////////////////
  322. //
  323. // CITracker::Init
  324. //
  325. // Description:
  326. // Initializes the CITracker object. It creates a copy of the VTable
  327. // of the interface to be tracked replacing the QI, AddRef and Release
  328. // methods with its own IUnknown. This allows CITracker to be "in the
  329. // loop" for those calls.
  330. //
  331. // Arguments:
  332. // ppunkOut - The "punk" to be passed around.
  333. // punkIn - The interface to be copied and tracked.
  334. // piteIn - The interface table entry for the interface.
  335. // pszNameIn - The name to be given to this CITracker.
  336. // fAddRefIn - TRUE is the CITracker should start with a Ref Count of 1.
  337. //
  338. // Return Values:
  339. // S_OK - Success.
  340. //
  341. //////////////////////////////////////////////////////////////////////////////
  342. STDMETHODIMP
  343. CITracker::Init(
  344. LPUNKNOWN * ppunkOut,
  345. LPUNKNOWN punkIn,
  346. const INTERFACE_TABLE_ENTRY * piteIn,
  347. LPCWSTR pszNameIn,
  348. LONG cRefIn
  349. )
  350. {
  351. HRESULT hr = S_OK;
  352. TraceFunc5( "ppunkOut = 0x%08x, punkIn = 0x%08x, iteIn = %ws, pszNameIn = '%ws', cRefIn = %u",
  353. ppunkOut,
  354. punkIn,
  355. piteIn->pszName,
  356. pszNameIn,
  357. cRefIn
  358. );
  359. //
  360. // Generate new Vtbls for each interface
  361. //
  362. LPVOID * pthisVtbl = (LPVOID*) (IUnknownTracker *) this;
  363. DWORD dwSize = ( 3 + piteIn->cFunctions ) * sizeof( LPVOID );
  364. AssertMsg( dwSize < 30 * sizeof( LPVOID ), "Need to make Dead Obj and IUnknownTracker larger!" );
  365. //
  366. // Interface tracking information initialization
  367. //
  368. m_vtbl.cRef = cRefIn;
  369. m_vtbl.pszInterface = pszNameIn;
  370. m_vtbl.dwSize = dwSize;
  371. //
  372. // Copy our IUnknownTracker vtbl to our "fix-up-able" vtbl
  373. //
  374. CopyMemory( &m_vtbl.lpfnQueryInterface, *pthisVtbl, dwSize );
  375. //
  376. // Remember the "punk" pointer so we can pass it back in when
  377. // we jump to the orginal objects IUnknown functions.
  378. //
  379. m_vtbl.punk = (LPUNKNOWN) punkIn;
  380. //
  381. // And finally, point the objects vtbl for this interface to
  382. // our newly created vtbl.
  383. //
  384. m_vtbl.pNewVtbl = (VTBL *) &m_vtbl.lpfnQueryInterface;
  385. *pthisVtbl = m_vtbl.pNewVtbl;
  386. *ppunkOut = (LPUNKNOWN) (IUnknownTracker *) this;
  387. TraceMsg( mtfCITRACKERS, L"TRACK: Tracking %ws Interface (%#x)", m_vtbl.pszInterface, punkIn );
  388. HRETURN( hr );
  389. } //*** CITracker::Init
  390. //////////////////////////////////////////////////////////////////////////////
  391. //
  392. // CITracker::~CITracker( void )
  393. //
  394. //////////////////////////////////////////////////////////////////////////////
  395. CITracker::~CITracker( void )
  396. {
  397. TraceFunc1( "for %ws", m_vtbl.pszInterface );
  398. if ( m_vtbl.pszInterface != NULL )
  399. {
  400. HeapFree( GetProcessHeap(), 0, (LPVOID) m_vtbl.pszInterface );
  401. } // if: have interface pointer
  402. if ( g_tfModule & mtfCITRACKERS )
  403. {
  404. //
  405. // Only count CITrackers if tracking is enabled.
  406. //
  407. InterlockedDecrement( &g_cObjects );
  408. }
  409. TraceFuncExit();
  410. } //*** CITracker::dtor
  411. // ************************************************************************
  412. //
  413. // IUnknownTracker
  414. //
  415. // ************************************************************************
  416. ///////////////////////////////////////////////////////////////////////////////
  417. //
  418. // STDMETHODIMP
  419. // CITracker::QueryInterface(
  420. // REFIID riid,
  421. // LPVOID * ppv
  422. // )
  423. //
  424. ///////////////////////////////////////////////////////////////////////////////
  425. STDMETHODIMP
  426. CITracker::QueryInterface(
  427. REFIID riid,
  428. LPVOID * ppv
  429. )
  430. {
  431. TraceFunc1( "{%ws}", m_vtbl.pszInterface );
  432. TraceMsg( mtfCITRACKERS, "TRACK: + %ws::QueryInterface()", m_vtbl.pszInterface );
  433. //
  434. // Call the punk's QueryInterface().
  435. //
  436. HRESULT hr = m_vtbl.punk->QueryInterface( riid, ppv );
  437. //
  438. // KB: TRACK_ALL_QIED_INTERFACES gpease 25-NOV-1999
  439. // Thinking out loud, should we track all interfaces QI'ed from
  440. // a tracked interface auto-magically? If so, turn this #define
  441. // on.
  442. //
  443. // #define TRACK_ALL_QIED_INTERFACES
  444. #if defined( TRACK_ALL_QIED_INTERFACES )
  445. if ( !IsEqualIID( riid, IID_IUnknown )
  446. )
  447. {
  448. *ppv = DebugTrackInterface( L"<Unknown>",
  449. 0,
  450. __MODULE__,
  451. m_vtbl.pszInterface,
  452. riid,
  453. (IUnknown*) *ppv,
  454. TRUE
  455. );
  456. } // if: not the IUnknown
  457. #endif
  458. TraceMsg( mtfCITRACKERS,
  459. "TRACK: V %ws::QueryInterface() [ *ppv = %#x ]",
  460. m_vtbl.pszInterface,
  461. *ppv
  462. );
  463. HRETURN( hr );
  464. } //*** CITracker::QueryInterface
  465. ///////////////////////////////////////////////////////////////////////////////
  466. //
  467. // STDMETHODIMP_( ULONG )
  468. // CITracker::AddRef( void )
  469. //
  470. ///////////////////////////////////////////////////////////////////////////////
  471. STDMETHODIMP_( ULONG )
  472. CITracker::AddRef( void )
  473. {
  474. TraceFunc1( "{%ws}", m_vtbl.pszInterface );
  475. TraceMsg( mtfCITRACKERS, "TRACK: + %ws AddRef() [ CITracker = %#08x ]", m_vtbl.pszInterface, this );
  476. //
  477. // Call the punk's AddRef().
  478. //
  479. ULONG ul = m_vtbl.punk->AddRef();
  480. //
  481. // Increment our counter.
  482. //
  483. ULONG ulvtbl = InterlockedIncrement( (LONG *) &m_vtbl.cRef );
  484. TraceMsg( mtfCITRACKERS,
  485. "TRACK: V %ws AddRef() [ I = %u, O = %u, CITracker = %#08x ]",
  486. m_vtbl.pszInterface,
  487. ulvtbl,
  488. ul,
  489. this
  490. );
  491. AssertMsg( ul >= ulvtbl, "The objects ref should be higher than the interfaces." );
  492. RETURN( ul );
  493. } //*** CITracker::AddRef
  494. ///////////////////////////////////////////////////////////////////////////////
  495. //
  496. // STDMETHODIMP_( ULONG )
  497. // CITracker::Release( void )
  498. //
  499. ///////////////////////////////////////////////////////////////////////////////
  500. STDMETHODIMP_( ULONG )
  501. CITracker::Release( void )
  502. {
  503. TraceFunc1( "{%ws}", m_vtbl.pszInterface );
  504. TraceMsg( mtfCITRACKERS, "TRACK: + %ws Release() [ CITracker = %#08x ]", m_vtbl.pszInterface, this );
  505. //
  506. // Call the punk's Release().
  507. //
  508. ULONG ul = m_vtbl.punk->Release();
  509. //
  510. // Decrement our counter.
  511. //
  512. ULONG ulvtbl = InterlockedDecrement( (LONG *) &m_vtbl.cRef );
  513. TraceMsg( mtfCITRACKERS,
  514. "TRACK: V %ws Release() [ I = %u, O = %u, CITracker = %#08x ]",
  515. m_vtbl.pszInterface,
  516. ulvtbl,
  517. ul,
  518. this
  519. );
  520. //
  521. // Our ref count should always be less than the punk's ref count.
  522. //
  523. AssertMsg( ul >= ulvtbl, "The objects ref should be higher than the interfaces." );
  524. if ( ulvtbl )
  525. {
  526. RETURN( ulvtbl );
  527. } // if: we still have a ref
  528. if ( g_pidoTracker == NULL )
  529. {
  530. //
  531. // Create a dead object - if more than one is created at a time, we might leak it.
  532. //
  533. // TODO: gpease 19-NOV-1999
  534. // Work on not leaking "extra" dead objects.
  535. //
  536. g_pidoTracker = new( TEXT(__FILE__), __LINE__, __MODULE__, 0, L"Dead Object" ) IDeadObjTracker();
  537. // Don't track this object
  538. TraceMemoryDelete( g_pidoTracker, FALSE );
  539. } // if: no dead object
  540. Assert( g_pidoTracker != NULL );
  541. if ( g_pidoTracker != NULL )
  542. {
  543. LPVOID * pthisVtbl = (LPVOID *) (IUnknownTracker *) this;
  544. LPVOID * ppthatVtbl = (LPVOID *) (IDeadObjTracker *) g_pidoTracker;
  545. // Copy the DeadObj vtbl.
  546. CopyMemory( &m_vtbl.lpfnQueryInterface, *ppthatVtbl, m_vtbl.dwSize );
  547. //
  548. // Don't really delete it, but fake the debug output as if we did.
  549. //
  550. TraceFunc1( "for %ws", m_vtbl.pszInterface );
  551. TraceMsg( mtfCITRACKERS, "TRACK: # %ws set to dead object [ punk = %#08x ]", m_vtbl.pszInterface, pthisVtbl );
  552. FRETURN( 0 );
  553. // Stop tracking this object.
  554. TraceMemoryDelete( this, FALSE );
  555. } // if: dead object created
  556. else
  557. {
  558. //
  559. // No dead object; nuke ourselves. This will at least cause an AV if
  560. // the program tries to call on our interface alerting the programmer
  561. // that somethings wrong.
  562. //
  563. delete this;
  564. } // else: no dead object
  565. RETURN(0);
  566. } //*** CITracker::Release
  567. //****************************************************************************
  568. //
  569. // IDeadObjTracker - The dead interface object tracker.
  570. //
  571. // This object is shunted into release interfaces that were being tracked by
  572. // the CITracker class. Any calls to a released interface will end up causing
  573. // an Assert and if execution continues it will return E_FAIL.
  574. //
  575. //****************************************************************************
  576. //////////////////////////////////////////////////////////////////////////////
  577. //
  578. // IDeadObjTracker:Stub(x)
  579. //
  580. //////////////////////////////////////////////////////////////////////////////
  581. #define IDeadObjTrackerStub( _iStubNum ) \
  582. STDMETHODIMP \
  583. IDeadObjTracker::Stub##_iStubNum( LPVOID * punk ) \
  584. { \
  585. const int cchDebugMessageSize = 255; \
  586. WCHAR szMessage[ cchDebugMessageSize ]; \
  587. LRESULT lResult;\
  588. \
  589. DebugMsg( "*ERROR* %ws: Entered %ws (%#08x) after it was released. Returning E_FAIL.", \
  590. __MODULE__, \
  591. m_vtbl.pszInterface, \
  592. this \
  593. ); \
  594. \
  595. THR( StringCchPrintfW( \
  596. szMessage \
  597. , cchDebugMessageSize \
  598. , L"Entered %ws (%#08p) after it was released.\n\nDo you want to break here?\n\n(If you do not break, E_FAIL will be returned.)" \
  599. , m_vtbl.pszInterface \
  600. , this \
  601. ) ); \
  602. \
  603. lResult = MessageBox( NULL, szMessage, L"Dead Interface", MB_YESNO | MB_ICONWARNING );\
  604. if ( lResult == IDYES \
  605. ) \
  606. { \
  607. DEBUG_BREAK; \
  608. } \
  609. \
  610. return E_FAIL; \
  611. }
  612. IDeadObjTrackerStub(0);
  613. IDeadObjTrackerStub(1);
  614. IDeadObjTrackerStub(2);
  615. IDeadObjTrackerStub(3);
  616. IDeadObjTrackerStub(4);
  617. IDeadObjTrackerStub(5);
  618. IDeadObjTrackerStub(6);
  619. IDeadObjTrackerStub(7);
  620. IDeadObjTrackerStub(8);
  621. IDeadObjTrackerStub(9);
  622. IDeadObjTrackerStub(10);
  623. IDeadObjTrackerStub(11);
  624. IDeadObjTrackerStub(12);
  625. IDeadObjTrackerStub(13);
  626. IDeadObjTrackerStub(14);
  627. IDeadObjTrackerStub(15);
  628. IDeadObjTrackerStub(16);
  629. IDeadObjTrackerStub(17);
  630. IDeadObjTrackerStub(18);
  631. IDeadObjTrackerStub(19);
  632. IDeadObjTrackerStub(20);
  633. IDeadObjTrackerStub(21);
  634. IDeadObjTrackerStub(22);
  635. IDeadObjTrackerStub(23);
  636. IDeadObjTrackerStub(24);
  637. IDeadObjTrackerStub(25);
  638. IDeadObjTrackerStub(26);
  639. IDeadObjTrackerStub(27);
  640. IDeadObjTrackerStub(28);
  641. IDeadObjTrackerStub(29);
  642. IDeadObjTrackerStub(30);
  643. //****************************************************************************
  644. //
  645. // IUnknownTracker stub
  646. //
  647. // This merely directs the incoming call back to the orginal object. The
  648. // IUnknown methods will be remapped the the CITracker methods.
  649. //
  650. //****************************************************************************
  651. //////////////////////////////////////////////////////////////////////////////
  652. //
  653. // STDMETHODIMP
  654. // IUnknownTracker::QueryInterface(
  655. // REFIID riid,
  656. // LPVOID * ppv
  657. // )
  658. //
  659. //////////////////////////////////////////////////////////////////////////////
  660. STDMETHODIMP
  661. IUnknownTracker::QueryInterface(
  662. REFIID riid,
  663. LPVOID * ppv
  664. )
  665. {
  666. ErrorMsg( "How did you get here?", 0 );
  667. AssertMsg( 0, "You shouldn't be here!" );
  668. return E_FAIL;
  669. } //*** IUnknownTracker::QueryInterface
  670. //////////////////////////////////////////////////////////////////////////////
  671. //
  672. // STDMETHODIMP_( ULONG )
  673. // IUnknownTracker::AddRef( void )
  674. //
  675. //////////////////////////////////////////////////////////////////////////////
  676. STDMETHODIMP_( ULONG )
  677. IUnknownTracker::AddRef( void )
  678. {
  679. ErrorMsg( "How did you get here?", 0 );
  680. AssertMsg( 0, "You shouldn't be here!" );
  681. return static_cast< ULONG >( -1 );
  682. } //*** IUnknownTracker::AddRef
  683. //////////////////////////////////////////////////////////////////////////////
  684. //
  685. // STDMETHODIMP_( ULONG )
  686. // IUnknownTracker::Release( void )
  687. //
  688. //////////////////////////////////////////////////////////////////////////////
  689. STDMETHODIMP_( ULONG )
  690. IUnknownTracker::Release( void )
  691. {
  692. ErrorMsg( "How did you get here?", 0 );
  693. AssertMsg( 0, "You shouldn't be here!" );
  694. return static_cast< ULONG >( -1 );
  695. } //*** IUnknownTracker::Release
  696. //////////////////////////////////////////////////////////////////////////////
  697. //
  698. // STDMETHODIMP_(void)
  699. // IUnknownTracker::Stub(x)
  700. //
  701. // These are just stubs to redirect the call to the "real" method on the punk.
  702. // We actually dissappear from the call stack.
  703. //
  704. //////////////////////////////////////////////////////////////////////////////
  705. #define IUnknownTrackerStub( i ) \
  706. void \
  707. _declspec(naked) \
  708. IUnknownTracker::Stub##i() \
  709. { \
  710. _asm mov eax, ss:4[esp] \
  711. _asm mov ecx, 8[eax] \
  712. _asm mov eax, [ecx] \
  713. _asm mov ss:4[esp], ecx \
  714. _asm jmp dword ptr cs:(4*i)[eax] \
  715. }
  716. IUnknownTrackerStub(3);
  717. IUnknownTrackerStub(4);
  718. IUnknownTrackerStub(5);
  719. IUnknownTrackerStub(6);
  720. IUnknownTrackerStub(7);
  721. IUnknownTrackerStub(8);
  722. IUnknownTrackerStub(9);
  723. IUnknownTrackerStub(10);
  724. IUnknownTrackerStub(11);
  725. IUnknownTrackerStub(12);
  726. IUnknownTrackerStub(13);
  727. IUnknownTrackerStub(14);
  728. IUnknownTrackerStub(15);
  729. IUnknownTrackerStub(16);
  730. IUnknownTrackerStub(17);
  731. IUnknownTrackerStub(18);
  732. IUnknownTrackerStub(19);
  733. IUnknownTrackerStub(20);
  734. IUnknownTrackerStub(21);
  735. IUnknownTrackerStub(22);
  736. IUnknownTrackerStub(23);
  737. IUnknownTrackerStub(24);
  738. IUnknownTrackerStub(25);
  739. IUnknownTrackerStub(26);
  740. IUnknownTrackerStub(27);
  741. IUnknownTrackerStub(28);
  742. IUnknownTrackerStub(29);
  743. IUnknownTrackerStub(30);
  744. //
  745. // END FULL_TRACE_INTERFACES_ENABLED
  746. //
  747. ///////////////////////////////////////
  748. #endif // FULL_TRACE_INTERFACES_ENABLED