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.

432 lines
9.6 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. }
  137. Error:
  138. RETURN(NULL);
  139. }
  140. //
  141. // Constructor
  142. //
  143. THISCLASS::THISCLASS( )
  144. {
  145. TraceClsFunc( "" );
  146. TraceMsg( TF_FUNC, "%s()\n", __THISCLASS__ );
  147. InterlockIncrement( g_cObjects );
  148. TraceFuncExit();
  149. }
  150. STDMETHODIMP
  151. THISCLASS::Init(
  152. LPQITABLE pQITable )
  153. {
  154. HRESULT hr = S_OK;
  155. TraceClsFunc( "Init( " );
  156. TraceMsg( TF_FUNC, "pQITable = 0x%08x )\n", pQITable );
  157. //
  158. // Generate new Vtbls for each interface
  159. //
  160. LPVOID *pthisVtbl = (LPVOID*) (IUnknown*) this;
  161. LPVOID *ppthatVtbl = (LPVOID*) pQITable->pvtbl;
  162. DWORD dwSize = ( 3 + pQITable->cFunctions ) * sizeof(LPVOID);
  163. // Interface tracking information initialization
  164. Assert( _vtbl.cRef == 0 );
  165. _vtbl.pszInterface = pQITable->pszName;
  166. // This is so we can get to our object's "this" pointer
  167. // after someone jumped to our IUnknown.
  168. _vtbl.pITracker = (LPUNKNOWN) this;
  169. // Copy the orginal vtbl.
  170. CopyMemory( &_vtbl.lpfnQueryInterface, *ppthatVtbl, dwSize );
  171. // Copy our IUnknown vtbl to the beginning 3 entries.
  172. CopyMemory( &_vtbl.lpfnQueryInterface, *pthisVtbl, 3 * sizeof(LPVOID) );
  173. // Remember the old vtbl so we can jump to the orginal objects
  174. // IUnknown functions.
  175. _vtbl.pOrginalVtbl = (LPVTBL) *ppthatVtbl;
  176. // Remember the "punk" pointer so we can pass it back in when
  177. // we jump to the orginal objects IUnknown functions.
  178. _vtbl.punk = (LPUNKNOWN) pQITable->pvtbl;
  179. // And finally, point the objects vtbl for this interface to
  180. // our newly created vtbl.
  181. *ppthatVtbl = &_vtbl.lpfnQueryInterface;
  182. TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, TF_FUNC,
  183. L"Tracking %s Interface...\n", _vtbl.pszInterface );
  184. HRETURN(hr);
  185. }
  186. //
  187. // Destructor
  188. //
  189. THISCLASS::~THISCLASS( )
  190. {
  191. TraceClsFunc( "" );
  192. TraceMsg( TF_FUNC, "~%s()\n", __THISCLASS__ );
  193. InterlockDecrement( g_cObjects );
  194. TraceFuncExit();
  195. };
  196. // ************************************************************************
  197. //
  198. // IUnknown
  199. //
  200. // ************************************************************************
  201. //
  202. // QueryInterface()
  203. //
  204. STDMETHODIMP
  205. THISCLASS::QueryInterface(
  206. REFIID riid,
  207. LPVOID *ppv )
  208. {
  209. // TraceClsFunc( "[IUnknown] QueryInterface( )\n" );
  210. //
  211. // Translate call to get our this pointer
  212. //
  213. LPVOID* punk = (LPVOID*) (LPUNKNOWN) this;
  214. LPVTBL2 pvtbl = (LPVTBL2) ((LPBYTE)*punk - VTBL2OFFSET);
  215. LPTHISCLASS that = (LPTHISCLASS) pvtbl->pITracker;
  216. //
  217. // Jump to our real implementation
  218. //
  219. HRESULT hr = that->_QueryInterface( riid, ppv );
  220. // HRETURN(hr);
  221. return hr;
  222. }
  223. //
  224. // AddRef()
  225. //
  226. STDMETHODIMP_(ULONG)
  227. THISCLASS::AddRef( void )
  228. {
  229. // TraceClsFunc( "[IUnknown] AddRef( )\n" );
  230. //
  231. // Translate call to get our this pointer
  232. //
  233. LPVOID* punk = (LPVOID*) (LPUNKNOWN) this;
  234. LPVTBL2 pvtbl = (LPVTBL2) ((LPBYTE)*punk - VTBL2OFFSET);
  235. LPTHISCLASS that = (LPTHISCLASS) pvtbl->pITracker;
  236. //
  237. // Jump to our real implementation
  238. //
  239. ULONG ul = that->_AddRef( );
  240. // RETURN(ul);
  241. return ul;
  242. }
  243. //
  244. // Release()
  245. //
  246. STDMETHODIMP_(ULONG)
  247. THISCLASS::Release( void )
  248. {
  249. // TraceClsFunc( "[IUnknown] Release( )\n" );
  250. //
  251. // Translate call to get our this pointer
  252. //
  253. LPVOID* punk = (LPVOID*) (LPUNKNOWN) this;
  254. LPVTBL2 pvtbl = (LPVTBL2) ((LPBYTE)*punk - VTBL2OFFSET);
  255. LPTHISCLASS that = (LPTHISCLASS) pvtbl->pITracker;
  256. //
  257. // Jump to our real implementation
  258. //
  259. ULONG ul = that->_Release( );
  260. // RETURN(ul);
  261. return ul;
  262. }
  263. // ************************************************************************
  264. //
  265. // IUnknown2
  266. //
  267. // ************************************************************************
  268. //
  269. // _QueryInterface()
  270. //
  271. STDMETHODIMP
  272. THISCLASS::_QueryInterface(
  273. REFIID riid,
  274. LPVOID *ppv )
  275. {
  276. #ifdef NOISY_QI
  277. TraceClsFunc( "");
  278. TraceMsg( TF_FUNC, "{%s} QueryInterface( ... )\n", _vtbl.pszInterface );
  279. #else
  280. InterlockIncrement(g_dwCounter)
  281. TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, TF_FUNC, L"{%s} QueryInterface( ... )\n",
  282. _vtbl.pszInterface );
  283. #endif
  284. HRESULT hr = _vtbl.pOrginalVtbl->lpfnQueryInterface( _vtbl.punk, riid, ppv );
  285. #ifdef NOISY_QI
  286. HRETURN(hr);
  287. #else
  288. TraceMessage( TEXT(__FILE__), __LINE__, g_szModule, TF_FUNC, TEXT("V\n") );
  289. InterlockDecrement(g_dwCounter);
  290. return(hr);
  291. #endif
  292. }
  293. //
  294. // _AddRef()
  295. //
  296. STDMETHODIMP_(ULONG)
  297. THISCLASS::_AddRef( void )
  298. {
  299. #ifdef NOISY_QI
  300. TraceClsFunc( "");
  301. TraceMsg( TF_FUNC, "{%s} AddRef( )\n", _vtbl.pszInterface );
  302. #else
  303. InterlockIncrement(g_dwCounter)
  304. TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, TF_FUNC, L"{%s} AddRef()\n",
  305. _vtbl.pszInterface );
  306. #endif
  307. ULONG ul = _vtbl.pOrginalVtbl->lpfnAddRef( _vtbl.punk );
  308. InterlockIncrement( _vtbl.cRef );
  309. #ifdef NOISY_QI
  310. RETURN(ul);
  311. #else
  312. TraceMessage( TEXT(__FILE__), __LINE__, g_szModule, TF_FUNC, TEXT("V I=%u, O=%u\n"),
  313. _vtbl.cRef, ul );
  314. InterlockDecrement(g_dwCounter);
  315. return ul;
  316. #endif
  317. }
  318. //
  319. // _Release()
  320. //
  321. STDMETHODIMP_(ULONG)
  322. THISCLASS::_Release( void )
  323. {
  324. #ifdef NOISY_QI
  325. TraceClsFunc( "");
  326. TraceMsg( TF_FUNC, "{%s} Release( )\n", _vtbl.pszInterface );
  327. #else
  328. InterlockIncrement(g_dwCounter)
  329. TraceMessage( TEXT(__FILE__), __LINE__, __MODULE__, TF_FUNC, L"{%s} Release()\n",
  330. _vtbl.pszInterface );
  331. #endif
  332. ULONG ul = _vtbl.pOrginalVtbl->lpfnRelease( _vtbl.punk );
  333. InterlockDecrement( _vtbl.cRef );
  334. if ( ul )
  335. {
  336. #ifdef NOISY_QI
  337. RETURN(ul);
  338. #else
  339. TraceMessage( TEXT(__FILE__), __LINE__, g_szModule, TF_FUNC, TEXT("V I=%u, O=%u\n"),
  340. _vtbl.cRef, ul );
  341. InterlockDecrement(g_dwCounter);
  342. return ul;
  343. #endif
  344. }
  345. //
  346. // TODO: Figure out how to destroy the tracking objects.
  347. //
  348. #ifdef NOISY_QI
  349. RETURN(ul);
  350. #else
  351. TraceMessage( TEXT(__FILE__), __LINE__, g_szModule, TF_FUNC, TEXT("V I=%u, O=%u\n"),
  352. _vtbl.cRef, ul );
  353. InterlockDecrement(g_dwCounter);
  354. return ul;
  355. #endif
  356. }
  357. //
  358. // END DEBUG
  359. //
  360. ///////////////////////////////////////
  361. #endif // DEBUG
  362. #endif // NO_TRACE_INTERFACES