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.

433 lines
9.2 KiB

  1. //
  2. // Copyright 1997 - Microsoft
  3. //
  4. //
  5. // QI.CPP - Handles the QueryInterface
  6. //
  7. #include "pch.h"
  8. //
  9. // Begin Class Definitions
  10. //
  11. DEFINE_MODULE("IMADMUI")
  12. //
  13. // QueryInterface()
  14. //
  15. extern HRESULT
  16. QueryInterface(
  17. LPVOID that,
  18. LPQITABLE pQI,
  19. REFIID riid,
  20. LPVOID* ppv )
  21. {
  22. TraceMsg( TF_FUNC, "[IUnknown] QueryInterface( riid=" );
  23. HRESULT hr = E_NOINTERFACE;
  24. Assert( ppv != NULL );
  25. *ppv = NULL;
  26. for( int i = 0; pQI[ i ].pvtbl; i++ )
  27. {
  28. if ( riid == *pQI[ i ].riid )
  29. {
  30. #ifdef DEBUG
  31. TraceMsg( TF_FUNC, "%s, ppv=0x%08x )\n", pQI[i].pszName, ppv );
  32. #endif // DEBUG
  33. *ppv = pQI[ i ].pvtbl;
  34. hr = S_OK;
  35. break;
  36. }
  37. }
  38. if ( hr == E_NOINTERFACE )
  39. {
  40. TraceMsgGUID( TF_FUNC, riid );
  41. TraceMsg( TF_FUNC, ", ppv=0x%08x )\n", ppv );
  42. }
  43. if ( SUCCEEDED( hr ) )
  44. {
  45. ( (IUnknown *) *ppv )->AddRef();
  46. }
  47. return hr;
  48. }
  49. ///////////////////////////////////////
  50. //
  51. // NOISY_QI
  52. //
  53. #ifndef NOISY_QI
  54. #undef TraceMsg
  55. #define TraceMsg 1 ? (void)0 : (void)
  56. #undef TraceFunc
  57. #define TraceFunc 1 ? (void)0 : (void)
  58. #undef TraceClsFunc
  59. #define TraceClsFunc 1 ? (void)0 : (void)
  60. #undef TraceFuncExit
  61. #define TraceFuncExit()
  62. #undef HRETURN
  63. #define HRETURN(_hr) return(_hr)
  64. #undef RETURN
  65. #define RETURN(_fn) return(_fn)
  66. #undef ErrorMsg
  67. #define ErrorMsg 1 ? (void)0 : (void)
  68. #endif // NOISY_QI
  69. //
  70. // END NOISY_QI
  71. //
  72. ///////////////////////////////////////
  73. #ifndef NO_TRACE_INTERFACES
  74. #ifdef DEBUG
  75. ///////////////////////////////////////
  76. //
  77. // BEGIN DEBUG
  78. //
  79. ///////////////////////////////////////
  80. //
  81. // CITracker
  82. //
  83. //
  84. DEFINE_THISCLASS("CITracker");
  85. #define THISCLASS CITracker
  86. #define LPTHISCLASS LPITRACKER
  87. // ************************************************************************
  88. //
  89. // Constructor / Destructor
  90. //
  91. // ************************************************************************
  92. //
  93. // Special new( ) for CITracker
  94. //
  95. #undef new
  96. void* __cdecl operator new( unsigned int nSize, LPCTSTR pszFile, const int iLine, LPCTSTR pszModule, UINT nExtra )
  97. {
  98. return DebugAlloc( pszFile, iLine, pszModule, GPTR, nSize + nExtra, __THISCLASS__ );
  99. }
  100. #define new new( TEXT(__FILE__), __LINE__, __MODULE__, nExtra )
  101. //
  102. // CreateInstance()
  103. //
  104. LPVOID
  105. CITracker_CreateInstance(
  106. LPQITABLE pQITable )
  107. {
  108. TraceFunc( "CITracker_CreateInstance( " );
  109. TraceMsg( TF_FUNC, "pQITable = 0x%08x )\n", pQITable );
  110. if ( !pQITable )
  111. {
  112. THR( E_POINTER );
  113. RETURN(NULL);
  114. }
  115. HRESULT hr;
  116. //
  117. // Add up the space needed for all the vtbls
  118. //
  119. for( int i = 1; pQITable[i].riid; i++ )
  120. {
  121. UINT nExtra = VTBL2OFFSET + (( 3 + pQITable[i].cFunctions ) * sizeof(LPVOID));
  122. // The "new" below is a macro that needs "nExtra" defined. (see above)
  123. LPTHISCLASS lpc = new THISCLASS( );
  124. if ( !lpc )
  125. {
  126. hr = THR(E_OUTOFMEMORY);
  127. goto Error;
  128. }
  129. hr = THR( lpc->Init( &pQITable[i] ) );
  130. if ( hr )
  131. {
  132. delete lpc;
  133. lpc = NULL;
  134. goto Error;
  135. }
  136. // DebugMemoryDelete( lpc );
  137. }
  138. Error:
  139. RETURN(NULL);
  140. }
  141. //
  142. // Constructor
  143. //
  144. THISCLASS::THISCLASS( )
  145. {
  146. TraceClsFunc( "" );
  147. TraceMsg( TF_FUNC, "%s()\n", __THISCLASS__ );
  148. InterlockIncrement( g_cObjects );
  149. TraceFuncExit();
  150. }
  151. STDMETHODIMP
  152. THISCLASS::Init(
  153. LPQITABLE pQITable )
  154. {
  155. HRESULT hr = S_OK;
  156. TraceClsFunc( "Init( " );
  157. TraceMsg( TF_FUNC, "pQITable = 0x%08x )\n", pQITable );
  158. //
  159. // Generate new Vtbls for each interface
  160. //
  161. LPVOID *pthisVtbl = (LPVOID*) (IUnknown*) this;
  162. LPVOID *ppthatVtbl = (LPVOID*) pQITable->pvtbl;
  163. DWORD dwSize = ( 3 + pQITable->cFunctions ) * sizeof(LPVOID);
  164. // Interface tracking information initialization
  165. Assert( _vtbl.cRef == 0 );
  166. _vtbl.pszInterface = pQITable->pszName;
  167. // This is so we can get to our object's "this" pointer
  168. // after someone jumped to our IUnknown.
  169. _vtbl.pITracker = (LPUNKNOWN) this;
  170. // Copy the orginal vtbl.
  171. CopyMemory( &_vtbl.lpfnQueryInterface, *ppthatVtbl, dwSize );
  172. // Copy our IUnknown vtbl to the beginning 3 entries.
  173. CopyMemory( &_vtbl.lpfnQueryInterface, *pthisVtbl, 3 * sizeof(LPVOID) );
  174. // Remember the old vtbl so we can jump to the orginal objects
  175. // IUnknown functions.
  176. _vtbl.pOrginalVtbl = (LPVTBL) *ppthatVtbl;
  177. // Remember the "punk" pointer so we can pass it back in when
  178. // we jump to the orginal objects IUnknown functions.
  179. _vtbl.punk = (LPUNKNOWN) pQITable->pvtbl;
  180. // And finally, point the objects vtbl for this interface to
  181. // our newly created vtbl.
  182. *ppthatVtbl = &_vtbl.lpfnQueryInterface;
  183. TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, TF_FUNC,
  184. L"Tracking %s Interface...\n", _vtbl.pszInterface );
  185. HRETURN(hr);
  186. }
  187. //
  188. // Destructor
  189. //
  190. THISCLASS::~THISCLASS( )
  191. {
  192. TraceClsFunc( "" );
  193. TraceMsg( TF_FUNC, "~%s()\n", __THISCLASS__ );
  194. InterlockDecrement( g_cObjects );
  195. TraceFuncExit();
  196. };
  197. // ************************************************************************
  198. //
  199. // IUnknown
  200. //
  201. // ************************************************************************
  202. //
  203. // QueryInterface()
  204. //
  205. STDMETHODIMP
  206. THISCLASS::QueryInterface(
  207. REFIID riid,
  208. LPVOID *ppv )
  209. {
  210. // TraceClsFunc( "[IUnknown] QueryInterface( )\n" );
  211. //
  212. // Translate call to get our this pointer
  213. //
  214. LPVOID* punk = (LPVOID*) (LPUNKNOWN) this;
  215. LPVTBL2 pvtbl = (LPVTBL2) ((LPBYTE)*punk - VTBL2OFFSET);
  216. LPTHISCLASS that = (LPTHISCLASS) pvtbl->pITracker;
  217. //
  218. // Jump to our real implementation
  219. //
  220. HRESULT hr = that->_QueryInterface( riid, ppv );
  221. // HRETURN(hr);
  222. return hr;
  223. }
  224. //
  225. // AddRef()
  226. //
  227. STDMETHODIMP_(ULONG)
  228. THISCLASS::AddRef( void )
  229. {
  230. // TraceClsFunc( "[IUnknown] AddRef( )\n" );
  231. //
  232. // Translate call to get our this pointer
  233. //
  234. LPVOID* punk = (LPVOID*) (LPUNKNOWN) this;
  235. LPVTBL2 pvtbl = (LPVTBL2) ((LPBYTE)*punk - VTBL2OFFSET);
  236. LPTHISCLASS that = (LPTHISCLASS) pvtbl->pITracker;
  237. //
  238. // Jump to our real implementation
  239. //
  240. ULONG ul = that->_AddRef( );
  241. // RETURN(ul);
  242. return ul;
  243. }
  244. //
  245. // Release()
  246. //
  247. STDMETHODIMP_(ULONG)
  248. THISCLASS::Release( void )
  249. {
  250. // TraceClsFunc( "[IUnknown] Release( )\n" );
  251. //
  252. // Translate call to get our this pointer
  253. //
  254. LPVOID* punk = (LPVOID*) (LPUNKNOWN) this;
  255. LPVTBL2 pvtbl = (LPVTBL2) ((LPBYTE)*punk - VTBL2OFFSET);
  256. LPTHISCLASS that = (LPTHISCLASS) pvtbl->pITracker;
  257. //
  258. // Jump to our real implementation
  259. //
  260. ULONG ul = that->_Release( );
  261. // RETURN(ul);
  262. return ul;
  263. }
  264. // ************************************************************************
  265. //
  266. // IUnknown2
  267. //
  268. // ************************************************************************
  269. //
  270. // _QueryInterface()
  271. //
  272. STDMETHODIMP
  273. THISCLASS::_QueryInterface(
  274. REFIID riid,
  275. LPVOID *ppv )
  276. {
  277. #ifdef NOISY_QI
  278. TraceClsFunc( "");
  279. TraceMsg( TF_FUNC, "{%s} QueryInterface( ... )\n", _vtbl.pszInterface );
  280. #else
  281. InterlockIncrement(g_dwCounter)
  282. TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, TF_FUNC, L"{%s} QueryInterface( ... )\n",
  283. _vtbl.pszInterface );
  284. #endif
  285. HRESULT hr = _vtbl.pOrginalVtbl->lpfnQueryInterface( _vtbl.punk, riid, ppv );
  286. #ifdef NOISY_QI
  287. HRETURN(hr);
  288. #else
  289. TraceMessage( TEXT(__FILE__), __LINE__, g_szModule, TF_FUNC, TEXT("V\n") );
  290. InterlockDecrement(g_dwCounter);
  291. return(hr);
  292. #endif
  293. }
  294. //
  295. // _AddRef()
  296. //
  297. STDMETHODIMP_(ULONG)
  298. THISCLASS::_AddRef( void )
  299. {
  300. #ifdef NOISY_QI
  301. TraceClsFunc( "");
  302. TraceMsg( TF_FUNC, "{%s} AddRef( )\n", _vtbl.pszInterface );
  303. #else
  304. InterlockIncrement(g_dwCounter)
  305. TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, TF_FUNC, L"{%s} AddRef()\n",
  306. _vtbl.pszInterface );
  307. #endif
  308. ULONG ul = _vtbl.pOrginalVtbl->lpfnAddRef( _vtbl.punk );
  309. InterlockIncrement( _vtbl.cRef );
  310. #ifdef NOISY_QI
  311. RETURN(ul);
  312. #else
  313. TraceMessage( TEXT(__FILE__), __LINE__, g_szModule, TF_FUNC, TEXT("V I=%u, O=%u\n"),
  314. _vtbl.cRef, ul );
  315. InterlockDecrement(g_dwCounter);
  316. return ul;
  317. #endif
  318. }
  319. //
  320. // _Release()
  321. //
  322. STDMETHODIMP_(ULONG)
  323. THISCLASS::_Release( void )
  324. {
  325. #ifdef NOISY_QI
  326. TraceClsFunc( "");
  327. TraceMsg( TF_FUNC, "{%s} Release( )\n", _vtbl.pszInterface );
  328. #else
  329. InterlockIncrement(g_dwCounter)
  330. TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, TF_FUNC, L"{%s} Release()\n",
  331. _vtbl.pszInterface );
  332. #endif
  333. ULONG ul = _vtbl.pOrginalVtbl->lpfnRelease( _vtbl.punk );
  334. InterlockDecrement( _vtbl.cRef );
  335. if ( ul )
  336. {
  337. #ifdef NOISY_QI
  338. RETURN(ul);
  339. #else
  340. TraceMessage( TEXT(__FILE__), __LINE__, g_szModule, TF_FUNC, TEXT("V I=%u, O=%u\n"),
  341. _vtbl.cRef, ul );
  342. InterlockDecrement(g_dwCounter);
  343. return ul;
  344. #endif
  345. }
  346. //
  347. // TODO: Figure out how to destroy the tracking objects.
  348. //
  349. #ifdef NOISY_QI
  350. RETURN(ul);
  351. #else
  352. TraceMessage( TEXT(__FILE__), __LINE__, g_szModule, TF_FUNC, TEXT("V I=%u, O=%u\n"),
  353. _vtbl.cRef, ul );
  354. InterlockDecrement(g_dwCounter);
  355. return ul;
  356. #endif
  357. }
  358. //
  359. // END DEBUG
  360. //
  361. ///////////////////////////////////////
  362. #endif // DEBUG
  363. #endif // NO_TRACE_INTERFACES