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.

538 lines
17 KiB

  1. ////////////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // WDMPerf.cpp
  4. //
  5. // Module: WMI WDM high performance provider
  6. //
  7. // This file includes the provider and refresher code.
  8. //
  9. // Copyright (c) 2000-2001 Microsoft Corporation, All Rights Reserved
  10. //
  11. ////////////////////////////////////////////////////////////////////////////////////////
  12. #include "precomp.h"
  13. #if defined(_AMD64_) || defined(_IA64_)
  14. ULONG Hash ( const LONG a_Arg ) {return a_Arg;}
  15. #include <Allocator.cpp>
  16. #endif
  17. ////////////////////////////////////////////////////////////////////////////////////////
  18. //
  19. // CRefresher
  20. //
  21. ////////////////////////////////////////////////////////////////////////////////////////
  22. CRefresher::CRefresher(CWMI_Prov* pProvider)
  23. {
  24. m_lRef = 0;
  25. // ===========================================================
  26. // Retain a copy of the provider
  27. // ===========================================================
  28. m_pProvider = pProvider;
  29. if (m_pProvider)
  30. {
  31. m_pProvider->AddRef();
  32. }
  33. // ===========================================================
  34. // Increment the global COM object counter
  35. // ===========================================================
  36. InterlockedIncrement(&g_cObj);
  37. }
  38. ////////////////////////////////////////////////////////////////////////////////////////
  39. CRefresher::~CRefresher()
  40. {
  41. // ===========================================================
  42. // Release the provider
  43. // ===========================================================
  44. if (m_pProvider){
  45. m_pProvider->Release();
  46. }
  47. // ===========================================================
  48. // Decrement the global COM object counter
  49. // ===========================================================
  50. InterlockedDecrement(&g_cObj);
  51. }
  52. ////////////////////////////////////////////////////////////////////////////////////////
  53. //
  54. // Standard COM mterface
  55. //
  56. ////////////////////////////////////////////////////////////////////////////////////////
  57. STDMETHODIMP CRefresher::QueryInterface(REFIID riid, void** ppv)
  58. {
  59. HRESULT hr = E_NOINTERFACE;
  60. *ppv = NULL;
  61. if (riid == IID_IUnknown)
  62. {
  63. *ppv = (LPVOID)(IUnknown*)this;
  64. }
  65. else if (riid == IID_IWbemRefresher)
  66. {
  67. *ppv = (LPVOID)(IWbemRefresher*)this;
  68. }
  69. if( *ppv )
  70. {
  71. AddRef();
  72. hr = S_OK;
  73. }
  74. return hr;
  75. }
  76. ////////////////////////////////////////////////////////////////////////////////////////
  77. //
  78. // Standard COM AddRef
  79. //
  80. ////////////////////////////////////////////////////////////////////////////////////////
  81. STDMETHODIMP_(ULONG) CRefresher::AddRef()
  82. {
  83. return InterlockedIncrement(&m_lRef);
  84. }
  85. ////////////////////////////////////////////////////////////////////////////////////////
  86. //
  87. // Standard COM Release
  88. //
  89. ////////////////////////////////////////////////////////////////////////////////////////
  90. STDMETHODIMP_(ULONG) CRefresher::Release()
  91. {
  92. long lRef = InterlockedDecrement(&m_lRef);
  93. if(lRef == 0)
  94. {
  95. delete this;
  96. }
  97. return lRef;
  98. }
  99. ////////////////////////////////////////////////////////////////////////////////////////
  100. //**************************************************************************************
  101. //
  102. // Externally called
  103. //
  104. //**************************************************************************************
  105. ////////////////////////////////////////////////////////////////////////////////////////
  106. ////////////////////////////////////////////////////////////////////////////////////////
  107. //
  108. // Executed to refresh a set of instances bound to the particular refresher.
  109. //
  110. // In most situations the instance data, such as counter values and
  111. // the set of current instances within any existing enumerators, would
  112. // be updated whenever Refresh was called.
  113. //
  114. ////////////////////////////////////////////////////////////////////////////////////////
  115. STDMETHODIMP CRefresher::Refresh(/* [in] */ long lFlags)
  116. {
  117. HRESULT hr = WBEM_NO_ERROR;
  118. IWbemObjectAccess* pObj = NULL;
  119. SetStructuredExceptionHandler seh;
  120. CWMIHiPerfShell WMI(TRUE);
  121. try
  122. {
  123. // ================================================================
  124. // Updates all instances that have been added to the refresher, and
  125. // updates their counter values
  126. // ================================================================
  127. hr = WMI.Initialize(TRUE,WMIGUID_QUERY,m_pProvider->HandleMapPtr(),NULL,m_pProvider->ServicesPtr(),NULL,NULL);
  128. if( SUCCEEDED(hr))
  129. {
  130. WMI.SetHiPerfHandleMap(&m_HiPerfHandleMap);
  131. hr = WMI.RefreshCompleteList();
  132. }
  133. }
  134. STANDARD_CATCH
  135. return hr;
  136. }
  137. ////////////////////////////////////////////////////////////////////////////////////////
  138. //
  139. // Called whenever a complete, fresh list of instances for a given class is required.
  140. //
  141. // The objects are constructed and sent back to the caller through the sink.
  142. //
  143. // Parameters:
  144. // pNamespace - A pointer to the relevant namespace.
  145. // wszClass - The class name for which instances are required.
  146. // lFlags - Reserved.
  147. // pCtx - The user-supplied context (not used here).
  148. // pSink - The sink to which to deliver the objects. The objects
  149. // can be delivered synchronously through the duration
  150. // of this call or asynchronously (assuming we
  151. // had a separate thread). A IWbemObjectSink::SetStatus
  152. // call is required at the end of the sequence.
  153. //
  154. ////////////////////////////////////////////////////////////////////////////////////////
  155. STDMETHODIMP CWMI_Prov::QueryInstances( IWbemServices __RPC_FAR *pNamespace,
  156. WCHAR __RPC_FAR *wcsClass, long lFlags,
  157. IWbemContext __RPC_FAR *pCtx, IWbemObjectSink __RPC_FAR *pHandler )
  158. {
  159. // Since we have implemented a IWbemServices interface, this code lives in CreateInstanceEnum instead
  160. return E_NOTIMPL;
  161. }
  162. ////////////////////////////////////////////////////////////////////////////////////////
  163. //
  164. // Called whenever a new refresher is needed by the client.
  165. //
  166. // Parameters:
  167. // pNamespace - A pointer to the relevant namespace. Not used.
  168. // lFlags - Reserved.
  169. // ppRefresher - Receives the requested refresher.
  170. //
  171. ////////////////////////////////////////////////////////////////////////////////////////
  172. STDMETHODIMP CWMI_Prov::CreateRefresher( IWbemServices __RPC_FAR *pNamespace, long lFlags,
  173. IWbemRefresher __RPC_FAR *__RPC_FAR *ppRefresher )
  174. {
  175. HRESULT hr = WBEM_E_FAILED;
  176. CWMIHiPerfShell WMI(TRUE);
  177. SetStructuredExceptionHandler seh;
  178. if (pNamespace == 0 || ppRefresher == 0)
  179. {
  180. return WBEM_E_INVALID_PARAMETER;
  181. }
  182. // =========================================================
  183. // Construct and initialize a new empty refresher
  184. // =========================================================
  185. try
  186. {
  187. hr = WMI.Initialize(TRUE,WMIGUID_QUERY,&m_HandleMap,NULL,pNamespace,NULL,NULL);
  188. if( SUCCEEDED(hr))
  189. {
  190. CRefresher* pNewRefresher = new CRefresher(this);
  191. if( pNewRefresher )
  192. {
  193. // =========================================================
  194. // Follow COM rules and AddRef() the thing before sending it
  195. // back
  196. // =========================================================
  197. pNewRefresher->AddRef();
  198. *ppRefresher = pNewRefresher;
  199. hr = WBEM_NO_ERROR;
  200. }
  201. }
  202. }
  203. STANDARD_CATCH
  204. return hr;
  205. }
  206. ////////////////////////////////////////////////////////////////////////////////////////
  207. //
  208. // Called whenever a user wants to include an object in a refresher.
  209. //
  210. // Note that the object returned in ppRefreshable is a clone of the
  211. // actual instance maintained by the provider. If refreshers shared
  212. // a copy of the same instance, then a refresh call on one of the
  213. // refreshers would impact the state of both refreshers. This would
  214. // break the refresher rules. Instances in a refresher are only
  215. // allowed to be updated when 'Refresh' is called.
  216. //
  217. // Parameters:
  218. // pNamespace - A pointer to the relevant namespace in WINMGMT.
  219. // pTemplate - A pointer to a copy of the object which is to be
  220. // added. This object itself cannot be used, as
  221. // it not owned locally.
  222. // pRefresher - The refresher to which to add the object.
  223. // lFlags - Not used.
  224. // pContext - Not used here.
  225. // ppRefreshable - A pointer to the internal object which was added
  226. // to the refresher.
  227. // plId - The Object Id (for identification during removal).
  228. //
  229. ////////////////////////////////////////////////////////////////////////////////////////
  230. STDMETHODIMP CWMI_Prov::CreateRefreshableObject( IWbemServices __RPC_FAR *pNamespace,
  231. IWbemObjectAccess __RPC_FAR *pAccess,
  232. IWbemRefresher __RPC_FAR *pRefresher,
  233. long lFlags,
  234. IWbemContext __RPC_FAR *pCtx,
  235. IWbemObjectAccess __RPC_FAR *__RPC_FAR *ppRefreshable,
  236. long __RPC_FAR *plId )
  237. {
  238. HRESULT hr = WBEM_E_FAILED;
  239. CWMIHiPerfShell WMI(FALSE);
  240. SetStructuredExceptionHandler seh;
  241. if (pNamespace == 0 || pAccess == 0 || pRefresher == 0)
  242. {
  243. return WBEM_E_INVALID_PARAMETER;
  244. }
  245. // =========================================================
  246. // The refresher being supplied by the caller is actually
  247. // one of our own refreshers, so a simple cast is convenient
  248. // so that we can access private members.
  249. // =========================================================
  250. try
  251. {
  252. #if defined(_AMD64_) || defined(_IA64_)
  253. if (m_HashTable == NULL)
  254. {
  255. hr = WBEM_E_OUT_OF_MEMORY;
  256. }
  257. else
  258. #endif
  259. {
  260. hr = WMI.Initialize(TRUE,WMIGUID_QUERY,&m_HandleMap,NULL,pNamespace,NULL,pCtx);
  261. if( SUCCEEDED(hr))
  262. {
  263. CRefresher *pOurRefresher = (CRefresher *) pRefresher;
  264. if( pOurRefresher )
  265. {
  266. // =================================================
  267. // Add the object to the refresher. The ID is set by
  268. // AddObject
  269. // =================================================
  270. WMI.SetHiPerfHandleMap(pOurRefresher->HiPerfHandleMap());
  271. ULONG_PTR realId = 0;
  272. hr = WMI.AddAccessObjectToRefresher(pAccess,ppRefreshable, &realId);
  273. #if defined(_AMD64_) || defined(_IA64_)
  274. if (SUCCEEDED(hr))
  275. {
  276. CCritical_SectionWrapper csw(&m_CS);
  277. if (csw.IsLocked())
  278. {
  279. *plId = m_ID;
  280. m_ID++;
  281. if (e_StatusCode_Success != m_HashTable->Insert (*plId, realId))
  282. {
  283. hr = WBEM_E_FAILED;
  284. }
  285. }
  286. else
  287. {
  288. hr = WBEM_E_FAILED;
  289. }
  290. }
  291. #else
  292. *plId = realId;
  293. #endif
  294. }
  295. }
  296. }
  297. }
  298. STANDARD_CATCH
  299. return hr;
  300. }
  301. ////////////////////////////////////////////////////////////////////////////////////////
  302. //
  303. // Called when an enumerator is being added to a refresher. The
  304. // enumerator will obtain a fresh set of instances of the specified
  305. // class every time that refresh is called.
  306. //
  307. // wszClass must be examined to determine which class the enumerator
  308. // is being assigned.
  309. //
  310. // Parameters:
  311. // pNamespace - A pointer to the relevant namespace.
  312. // wszClass - The class name for the requested enumerator.
  313. // pRefresher - The refresher object for which we will add the enumerator
  314. // lFlags - Reserved.
  315. // pContext - Not used here.
  316. // pHiPerfEnum - The enumerator to add to the refresher.
  317. // plId - A provider specified ID for the enumerator.
  318. //
  319. ////////////////////////////////////////////////////////////////////////////////////////
  320. STDMETHODIMP CWMI_Prov::CreateRefreshableEnum( IWbemServices* pNamespace,
  321. LPCWSTR wcsClass,
  322. IWbemRefresher* pRefresher,
  323. long lFlags, IWbemContext* pCtx,
  324. IWbemHiPerfEnum* pHiPerfEnum, long* plId )
  325. {
  326. HRESULT hr = WBEM_E_FAILED;
  327. SetStructuredExceptionHandler seh;
  328. if( !pHiPerfEnum || wcsClass == NULL || (wcslen(wcsClass) == 0))
  329. {
  330. return WBEM_E_INVALID_PARAMETER;
  331. }
  332. CWMIHiPerfShell WMI(FALSE);
  333. // ===========================================================
  334. // The refresher being supplied by the caller is actually
  335. // one of our own refreshers, so a simple cast is convenient
  336. // so that we can access private members.
  337. // ===========================================================
  338. try
  339. {
  340. #if defined(_AMD64_) || defined(_IA64_)
  341. if (m_HashTable == NULL)
  342. {
  343. hr = WBEM_E_OUT_OF_MEMORY;
  344. }
  345. else
  346. #endif
  347. {
  348. hr = WMI.Initialize(TRUE,WMIGUID_QUERY,&m_HandleMap,(WCHAR*)wcsClass,pNamespace,NULL,pCtx);
  349. if( SUCCEEDED(hr))
  350. {
  351. ULONG_PTR realId = 0;
  352. CRefresher *pOurRefresher = (CRefresher *) pRefresher;
  353. if( pOurRefresher )
  354. {
  355. // ===========================================================
  356. // Add the enumerator to the refresher
  357. // ===========================================================
  358. WMI.SetHiPerfHandleMap(pOurRefresher->HiPerfHandleMap());
  359. hr = WMI.AddEnumeratorObjectToRefresher(pHiPerfEnum,&realId);
  360. #if defined(_AMD64_) || defined(_IA64_)
  361. if (SUCCEEDED(hr))
  362. {
  363. CCritical_SectionWrapper csw(&m_CS);
  364. if (csw.IsLocked())
  365. {
  366. *plId = m_ID;
  367. m_ID++;
  368. if (e_StatusCode_Success != m_HashTable->Insert (*plId, realId))
  369. {
  370. hr = WBEM_E_FAILED;
  371. }
  372. }
  373. else
  374. {
  375. hr = WBEM_E_FAILED;
  376. }
  377. }
  378. #else
  379. *plId = realId;
  380. #endif
  381. }
  382. if(SUCCEEDED(hr))
  383. {
  384. if(FAILED(hr = WMI.RefreshCompleteList()))
  385. {
  386. // This function is called before as RemoveObjectFromHandleMap
  387. // deletes the member variables and resets the pointers
  388. WMI.RemoveObjectFromHandleMap(realId);
  389. *plId = 0;
  390. }
  391. }
  392. }
  393. }
  394. }
  395. STANDARD_CATCH
  396. return hr;
  397. }
  398. ////////////////////////////////////////////////////////////////////////////////////////
  399. //
  400. // Called whenever a user wants to remove an object from a refresher.
  401. //
  402. // Parameters:
  403. // pRefresher - The refresher object from which we are to remove the
  404. // perf object.
  405. // lId - The ID of the object.
  406. // lFlags - Not used.
  407. //
  408. ////////////////////////////////////////////////////////////////////////////////////////
  409. STDMETHODIMP CWMI_Prov::StopRefreshing( IWbemRefresher __RPC_FAR *pInRefresher, long lId, long lFlags )
  410. {
  411. HRESULT hr = WBEM_S_NO_ERROR;
  412. CWMIHiPerfShell WMI(TRUE);
  413. SetStructuredExceptionHandler seh;
  414. // ===========================================================
  415. // The refresher being supplied by the caller is actually
  416. // one of our own refreshers, so a simple cast is convenient
  417. // so that we can access private members.
  418. // ===========================================================
  419. try
  420. {
  421. #if defined(_AMD64_) || defined(_IA64_)
  422. ULONG_PTR realId = 0;
  423. if (m_HashTable != NULL)
  424. {
  425. CCritical_SectionWrapper csw(&m_CS);
  426. if (csw.IsLocked())
  427. {
  428. if (e_StatusCode_Success != m_HashTable->Find (lId, realId))
  429. {
  430. hr = WBEM_E_FAILED;
  431. }
  432. else
  433. {
  434. m_HashTable->Delete (lId) ;
  435. }
  436. }
  437. else
  438. {
  439. hr = WBEM_E_FAILED;
  440. }
  441. }
  442. else
  443. {
  444. hr = WBEM_E_OUT_OF_MEMORY;
  445. }
  446. #else
  447. ULONG_PTR realId = lId;
  448. #endif
  449. if (SUCCEEDED(hr))
  450. {
  451. hr = WMI.Initialize(TRUE,WMIGUID_QUERY,&m_HandleMap,NULL,m_pIWbemServices,NULL, NULL);
  452. if( SUCCEEDED(hr))
  453. {
  454. CRefresher *pRefresher = (CRefresher *) pInRefresher;
  455. WMI.SetHiPerfHandleMap(pRefresher->HiPerfHandleMap());
  456. if(FAILED(hr))
  457. {
  458. // This function is called before as RemoveObjectFromHandleMap
  459. // deletes the member variables and resets the pointers
  460. }
  461. else
  462. {
  463. hr = WMI.RemoveObjectFromHandleMap(realId);
  464. }
  465. }
  466. }
  467. }
  468. STANDARD_CATCH
  469. return hr;
  470. }
  471. ////////////////////////////////////////////////////////////////////////////////////////
  472. //
  473. // Called when a request is made to provide all instances currently being managed by
  474. // the provider in the specified namespace.
  475. //
  476. // Parameters:
  477. // pNamespace - A pointer to the relevant namespace.
  478. // lNumObjects - The number of instances being returned.
  479. // apObj - The array of instances being returned.
  480. // lFlags - Reserved.
  481. // pContext - Not used here.
  482. //
  483. ////////////////////////////////////////////////////////////////////////////////////////
  484. STDMETHODIMP CWMI_Prov::GetObjects( IWbemServices* pNamespace, long lNumObjects,
  485. IWbemObjectAccess** apObj, long lFlags,
  486. IWbemContext* pCtx)
  487. {
  488. // Since we have implemented a IWbemServices interface, this code lives in CreateInstanceEnum instead
  489. return E_NOTIMPL;
  490. }