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.

846 lines
24 KiB

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