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.

1068 lines
33 KiB

  1. /*++
  2. Copyright (C) 1997-1999 Microsoft Corporation
  3. Module Name:
  4. ntperf.cpp
  5. Abstract:
  6. Mapped NT5 Perf counter provider
  7. History:
  8. raymcc 02-Dec-97 Created.
  9. raymcc 20-Feb-98 Updated to use new initializer.
  10. bobw 8-Jun-98 tuned up
  11. --*/
  12. #include "wpheader.h"
  13. #include <stdio.h>
  14. #include "oahelp.inl"
  15. #define __WBEMSECURITY 1
  16. //***************************************************************************
  17. //
  18. // CNt5PerfProvider constructor
  19. //
  20. //***************************************************************************
  21. // ok
  22. CNt5PerfProvider::CNt5PerfProvider(enumCLSID OriginClsid)
  23. {
  24. m_lRef = 0;
  25. m_OriginClsid = OriginClsid;
  26. m_hClassMapMutex = CreateMutex(NULL, FALSE, NULL);
  27. }
  28. //***************************************************************************
  29. //
  30. // CNt5PerfProvider destructor
  31. //
  32. //***************************************************************************
  33. // ok
  34. CNt5PerfProvider::~CNt5PerfProvider()
  35. {
  36. int i;
  37. CClassMapInfo *pClassElem;
  38. assert (m_lRef == 0);
  39. for (i = 0; i < m_aCache.Size(); i++) {
  40. pClassElem = (CClassMapInfo *) m_aCache[i];
  41. m_PerfObject.RemoveClass (pClassElem->m_pClassDef);
  42. delete pClassElem;
  43. }
  44. m_aCache.Empty(); // reset the buffer pointers
  45. if (m_hClassMapMutex != 0)
  46. CloseHandle(m_hClassMapMutex);
  47. // RegCloseKey(HKEY_PERFORMANCE_DATA); // causes more problems than it solves
  48. }
  49. //***************************************************************************
  50. //
  51. // CNt5PerfProvider::AddRef
  52. //
  53. // Standard COM AddRef().
  54. //
  55. //***************************************************************************
  56. // ok
  57. ULONG CNt5PerfProvider::AddRef()
  58. {
  59. return InterlockedIncrement(&m_lRef);
  60. }
  61. //***************************************************************************
  62. //
  63. // CNt5PerfProvider::Release
  64. //
  65. // Standard COM Release().
  66. //
  67. //***************************************************************************
  68. // ok
  69. ULONG CNt5PerfProvider::Release()
  70. {
  71. long lRef = InterlockedDecrement(&m_lRef);
  72. if(lRef == 0) {
  73. delete this;
  74. }
  75. return lRef;
  76. }
  77. //***************************************************************************
  78. //
  79. // CNt5PerfProvider::QueryInterface
  80. //
  81. // Standard COM QueryInterface(). We have to support two interfaces,
  82. // the IWbemHiPerfProvider interface itself to provide the objects and
  83. // the IWbemProviderInit interface to initialize the provider.
  84. //
  85. //***************************************************************************
  86. // ok
  87. HRESULT CNt5PerfProvider::QueryInterface(REFIID riid, void** ppv)
  88. {
  89. HRESULT hReturn;
  90. if (riid == IID_IUnknown || riid == IID_IWbemHiPerfProvider) {
  91. *ppv = (IWbemHiPerfProvider*) this;
  92. AddRef();
  93. hReturn = S_OK;
  94. } else if (riid == IID_IWbemProviderInit) {
  95. *ppv = (IWbemProviderInit *) this;
  96. AddRef();
  97. hReturn = S_OK;
  98. } else {
  99. hReturn = E_NOINTERFACE;
  100. }
  101. return hReturn;
  102. }
  103. //***************************************************************************
  104. //
  105. // CNt5PerfProvider::Initialize
  106. //
  107. // Called once during startup. Indicates to the provider which
  108. // namespace it is being invoked for and which User. It also supplies
  109. // a back pointer to CIMOM so that class definitions can be retrieved.
  110. //
  111. // We perform any one-time initialization in this routine. The
  112. // final call to Release() is for any cleanup.
  113. //
  114. // <wszUser> The current user.
  115. // <lFlags> Reserved.
  116. // <wszNamespace> The namespace for which we are being activated.
  117. // <wszLocale> The locale under which we are to be running.
  118. // <pNamespace> An active pointer back into the current namespace
  119. // from which we can retrieve schema objects.
  120. // <pCtx> The user's context object. We simply reuse this
  121. // during any reentrant operations into CIMOM.
  122. // <pInitSink> The sink to which we indicate our readiness.
  123. //
  124. //***************************************************************************
  125. // ok
  126. HRESULT CNt5PerfProvider::Initialize(
  127. /* [unique][in] */ LPWSTR wszUser,
  128. /* [in] */ LONG lFlags,
  129. /* [in] */ LPWSTR wszNamespace,
  130. /* [unique][in] */ LPWSTR wszLocale,
  131. /* [in] */ IWbemServices __RPC_FAR *pNamespace,
  132. /* [in] */ IWbemContext __RPC_FAR *pCtx,
  133. /* [in] */ IWbemProviderInitSink __RPC_FAR *pInitSink
  134. )
  135. {
  136. UNREFERENCED_PARAMETER(wszUser);
  137. UNREFERENCED_PARAMETER(lFlags);
  138. UNREFERENCED_PARAMETER(wszNamespace);
  139. UNREFERENCED_PARAMETER(wszLocale);
  140. UNREFERENCED_PARAMETER(pNamespace);
  141. UNREFERENCED_PARAMETER(pCtx);
  142. pInitSink->SetStatus(0, WBEM_S_INITIALIZED);
  143. return NO_ERROR;
  144. }
  145. //***************************************************************************
  146. //
  147. // CNt5PerfProvider::QueryInstances
  148. //
  149. // Called whenever a complete, fresh list of instances for a given
  150. // class is required. The objects are constructed and sent back to the
  151. // caller through the sink. The sink can be used in-line as here, or
  152. // the call can return and a separate thread could be used to deliver
  153. // the instances to the sink.
  154. //
  155. // Parameters:
  156. // <pNamespace> A pointer to the relevant namespace. This
  157. // should not be AddRef'ed or retained past the
  158. // execution of this method.
  159. // <wszClass> The class name for which instances are required.
  160. // <lFlags> Reserved.
  161. // <pCtx> The user-supplied context (used during callbacks
  162. // into CIMOM).
  163. // <pSink> The sink to which to deliver the objects. The objects
  164. // can be delivered synchronously through the duration
  165. // of this call or asynchronously (assuming we
  166. // had a separate thread). A IWbemObjectSink::SetStatus
  167. // call is required at the end of the sequence.
  168. //
  169. //***************************************************************************
  170. // ok
  171. HRESULT CNt5PerfProvider::QueryInstances(
  172. /* [in] */ IWbemServices __RPC_FAR *pNamespace,
  173. /* [string][in] */ WCHAR __RPC_FAR *wszClass,
  174. /* [in] */ long lFlags,
  175. /* [in] */ IWbemContext __RPC_FAR *pCtx,
  176. /* [in] */ IWbemObjectSink __RPC_FAR *pSink
  177. )
  178. {
  179. HRESULT hReturn;
  180. BOOL bRes ;
  181. CClassMapInfo *pClsMap = NULL;
  182. UNREFERENCED_PARAMETER(lFlags);
  183. #ifdef __WBEMSECURITY
  184. hReturn = CoImpersonateClient(); // make sure we're legit.
  185. BOOL fRevert = SUCCEEDED( hReturn );
  186. // The following error appears to occur when we are in-proc and there is no
  187. // proxy/stub, so we are effectively impersonating already
  188. if ( RPC_E_CALL_COMPLETE == hReturn ) {
  189. hReturn = S_OK;
  190. }
  191. if (S_OK == hReturn) {
  192. hReturn = CheckImpersonationLevel();
  193. }
  194. // Check Registry security here.
  195. if ((hReturn != S_OK) || (!HasPermission())) {
  196. // if Impersonation level is incorrect or
  197. // the caller doesn't have permission to read
  198. // from the registry, then they cannot continue
  199. hReturn = WBEM_E_ACCESS_DENIED;
  200. }
  201. #else
  202. hReturn = S_OK;
  203. #endif
  204. if (hReturn == S_OK) {
  205. if (pNamespace == 0 || wszClass == 0 || pSink == 0) {
  206. hReturn = WBEM_E_INVALID_PARAMETER;
  207. } else {
  208. // Ensure the class is in our cache and mapped.
  209. // ============================================
  210. bRes = MapClass(pNamespace, wszClass, pCtx);
  211. if (bRes == FALSE) {
  212. // Class is not one of ours.
  213. hReturn = WBEM_E_INVALID_CLASS;
  214. } else {
  215. pClsMap = FindClassMap(wszClass);
  216. if (pClsMap == NULL) {
  217. hReturn = WBEM_E_INVALID_CLASS;
  218. }
  219. }
  220. if (hReturn == NO_ERROR) {
  221. // Refresh the instances.
  222. // ======================
  223. PerfHelper::QueryInstances(&m_PerfObject, pClsMap, pSink);
  224. // Tell CIMOM we are finished.
  225. // ===========================
  226. pSink->SetStatus(0, WBEM_NO_ERROR, 0, 0);
  227. hReturn = NO_ERROR;
  228. }
  229. }
  230. } else {
  231. // return error
  232. }
  233. #ifdef __WBEMSECURITY
  234. // Revert if we successfuly impersonated the user
  235. if ( fRevert )
  236. {
  237. CoRevertToSelf();
  238. }
  239. #endif
  240. return hReturn;
  241. }
  242. //***************************************************************************
  243. //
  244. // CNt5PerfProvider::CreateRefresher
  245. //
  246. // Called whenever a new refresher is needed by the client.
  247. //
  248. // Parameters:
  249. // <pNamespace> A pointer to the relevant namespace. Not used.
  250. // <lFlags> Not used.
  251. // <ppRefresher> Receives the requested refresher.
  252. //
  253. //***************************************************************************
  254. // ok
  255. HRESULT CNt5PerfProvider::CreateRefresher(
  256. /* [in] */ IWbemServices __RPC_FAR *pNamespace,
  257. /* [in] */ long lFlags,
  258. /* [out] */ IWbemRefresher __RPC_FAR *__RPC_FAR *ppRefresher
  259. )
  260. {
  261. HRESULT hReturn;
  262. CNt5Refresher *pNewRefresher;
  263. UNREFERENCED_PARAMETER(lFlags);
  264. #ifdef __WBEMSECURITY
  265. hReturn = CoImpersonateClient(); // make sure we're legit.
  266. BOOL fRevert = SUCCEEDED( hReturn );
  267. // The following error appears to occur when we are in-proc and there is no
  268. // proxy/stub, so we are effectively impersonating already
  269. if ( RPC_E_CALL_COMPLETE == hReturn ) {
  270. hReturn = S_OK;
  271. }
  272. if (S_OK == hReturn) {
  273. hReturn = CheckImpersonationLevel();
  274. }
  275. // Check Registry security here.
  276. if ((hReturn != S_OK) || (!HasPermission())) {
  277. // if Impersonation level is incorrect or
  278. // the caller doesn't have permission to read
  279. // from the registry, then they cannot continue
  280. hReturn = WBEM_E_ACCESS_DENIED;
  281. }
  282. #else
  283. hReturn = S_OK;
  284. #endif
  285. if (hReturn == S_OK) {
  286. if (pNamespace == 0 || ppRefresher == 0) {
  287. hReturn = WBEM_E_INVALID_PARAMETER;
  288. } else {
  289. // Construct a new empty refresher.
  290. // ================================
  291. pNewRefresher = new CNt5Refresher (this);
  292. if (pNewRefresher != NULL) {
  293. // Follow COM rules and AddRef() the thing before sending it back.
  294. // ===============================================================
  295. pNewRefresher->AddRef();
  296. *ppRefresher = pNewRefresher;
  297. hReturn = NO_ERROR;
  298. } else {
  299. hReturn = WBEM_E_OUT_OF_MEMORY;
  300. }
  301. }
  302. }
  303. #ifdef __WBEMSECURITY
  304. // Revert if we successfuly impersonated the user
  305. if ( fRevert )
  306. {
  307. CoRevertToSelf();
  308. }
  309. #endif
  310. return hReturn;
  311. }
  312. //***************************************************************************
  313. //
  314. // CNt5PerfProvider::CreateRefresherObject
  315. //
  316. // Called whenever a user wants to include an object in a refresher.
  317. //
  318. // Parameters:
  319. // <pNamespace> A pointer to the relevant namespace in CIMOM.
  320. // <pTemplate> A pointer to a copy of the object which is to be
  321. // added. This object itself cannot be used, as
  322. // it not owned locally.
  323. // <pRefresher> The refresher to which to add the object.
  324. // <lFlags> Not used.
  325. // <pContext> Not used here.
  326. // <ppRefreshable> A pointer to the internal object which was added
  327. // to the refresher.
  328. // <plId> The Object Id (for identification during removal).
  329. //
  330. //***************************************************************************
  331. // ok
  332. HRESULT CNt5PerfProvider::CreateRefresherObject(
  333. /* [in] */ IWbemServices __RPC_FAR *pNamespace,
  334. /* [in] */ IWbemObjectAccess __RPC_FAR *pTemplate,
  335. /* [in] */ IWbemRefresher __RPC_FAR *pRefresher,
  336. /* [in] */ long lFlags,
  337. /* [in] */ IWbemContext __RPC_FAR *pContext,
  338. /* [string][in] */ LPCWSTR wszClass,
  339. /* [in] */ IWbemHiPerfEnum __RPC_FAR *pHiPerfEnum,
  340. /* [out] */ IWbemObjectAccess __RPC_FAR *__RPC_FAR *ppRefreshable,
  341. /* [out] */ long __RPC_FAR *plId
  342. )
  343. {
  344. IWbemClassObject *pOriginal = 0;
  345. IWbemClassObject *pNewCopy = 0;
  346. IWbemObjectAccess *pNewAccess = 0;
  347. CNt5Refresher *pRef = 0;
  348. CClassMapInfo *pClsMap;
  349. VARIANT v;
  350. BOOL bRes;
  351. HRESULT hReturn = NO_ERROR;
  352. UNREFERENCED_PARAMETER(lFlags);
  353. if (ppRefreshable != NULL) {
  354. // Initialize the argument
  355. *ppRefreshable = 0;
  356. }
  357. // init the variant
  358. VariantInit(&v);
  359. if (pTemplate != NULL) {
  360. // Make a copy of the template object.
  361. // ===================================
  362. hReturn = pTemplate->QueryInterface(IID_IWbemClassObject, (LPVOID *) &pOriginal);
  363. if (hReturn == NO_ERROR) {
  364. hReturn = pOriginal->Clone(&pNewCopy);
  365. // Get the class name of the object.
  366. // =================================
  367. if (hReturn == NO_ERROR) {
  368. hReturn = pOriginal->Get(CBSTR(cszClassName), 0, &v, 0, 0);
  369. if ((hReturn == NO_ERROR) && (v.vt != VT_BSTR)) {
  370. hReturn = WBEM_E_INVALID_CLASS;
  371. }
  372. }
  373. // We are now done with the original object
  374. // ========================================
  375. pOriginal->Release();
  376. }
  377. if (hReturn == NO_ERROR) {
  378. // We now get the IWbemObjectAccess form of the cloned object
  379. // and release the unused interface.
  380. // ==========================================================
  381. hReturn = pNewCopy->QueryInterface(IID_IWbemObjectAccess, (LPVOID *) &pNewAccess);
  382. if (hReturn == NO_ERROR) {
  383. pNewCopy->Release(); // We don't need the IWbemClassObject interface any more
  384. // We now have an IWbemObjectAccess pointer for the refreshable
  385. // object in <pNewAccess>.
  386. // ============================================================
  387. }
  388. }
  389. } else {
  390. // copy the class name passed in
  391. v.vt = VT_BSTR;
  392. v.bstrVal = SysAllocString(wszClass);
  393. }
  394. if (hReturn == NO_ERROR) {
  395. // cast refresher pointer to our refresher object
  396. pRef = (CNt5Refresher *) pRefresher;
  397. // Map the class info for this instance.
  398. // =====================================
  399. bRes = MapClass(pNamespace, V_BSTR(&v), pContext);
  400. if (bRes == FALSE) {
  401. // Class is not one of ours.
  402. if (pNewAccess != NULL) pNewAccess->Release();
  403. hReturn = WBEM_E_INVALID_CLASS;
  404. } else {
  405. pClsMap = FindClassMap(V_BSTR(&v));
  406. if (pClsMap == 0) {
  407. if (pNewAccess != NULL) pNewAccess->Release();
  408. hReturn = WBEM_E_INVALID_CLASS;
  409. } else {
  410. // Add the object to the refresher.
  411. if (pHiPerfEnum != NULL) {
  412. // then this is an Enum object so add it
  413. bRes = pRef->AddEnum (
  414. pHiPerfEnum,
  415. pClsMap,
  416. plId);
  417. if (bRes) {
  418. // Return new ID to caller
  419. // ==========================
  420. hReturn = NO_ERROR;
  421. } else {
  422. // unable to add enumerator
  423. hReturn = GetLastError();
  424. }
  425. } else {
  426. // This method will AddRef() the object before returning.
  427. // ======================================================
  428. bRes = pRef->AddObject(
  429. &pNewAccess,
  430. pClsMap,
  431. plId);
  432. if (bRes) {
  433. // Return object to the user.
  434. // ==========================
  435. *ppRefreshable = pNewAccess;
  436. hReturn = NO_ERROR;
  437. } else {
  438. // unable to add object
  439. hReturn = GetLastError();
  440. }
  441. }
  442. }
  443. }
  444. }
  445. VariantClear(&v);
  446. return hReturn;
  447. }
  448. //***************************************************************************
  449. //
  450. // CNt5PerfProvider::CreateRefreshableObject
  451. //
  452. // Called whenever a user wants to include an object in a refresher.
  453. //
  454. // Parameters:
  455. // <pNamespace> A pointer to the relevant namespace in CIMOM.
  456. // <pTemplate> A pointer to a copy of the object which is to be
  457. // added. This object itself cannot be used, as
  458. // it not owned locally.
  459. // <pRefresher> The refresher to which to add the object.
  460. // <lFlags> Not used.
  461. // <pContext> Not used here.
  462. // <ppRefreshable> A pointer to the internal object which was added
  463. // to the refresher.
  464. // <plId> The Object Id (for identification during removal).
  465. //
  466. //***************************************************************************
  467. // ok
  468. HRESULT CNt5PerfProvider::CreateRefreshableObject(
  469. /* [in] */ IWbemServices __RPC_FAR *pNamespace,
  470. /* [in] */ IWbemObjectAccess __RPC_FAR *pTemplate,
  471. /* [in] */ IWbemRefresher __RPC_FAR *pRefresher,
  472. /* [in] */ long lFlags,
  473. /* [in] */ IWbemContext __RPC_FAR *pContext,
  474. /* [out] */ IWbemObjectAccess __RPC_FAR *__RPC_FAR *ppRefreshable,
  475. /* [out] */ long __RPC_FAR *plId
  476. )
  477. {
  478. HRESULT hReturn = NO_ERROR;
  479. #ifdef __WBEMSECURITY
  480. hReturn = CoImpersonateClient(); // make sure we're legit.
  481. BOOL fRevert = SUCCEEDED( hReturn );
  482. // The following error appears to occur when we are in-proc and there is no
  483. // proxy/stub, so we are effectively impersonating already
  484. if ( RPC_E_CALL_COMPLETE == hReturn ) {
  485. hReturn = S_OK;
  486. }
  487. if (S_OK == hReturn) {
  488. hReturn = CheckImpersonationLevel();
  489. }
  490. // Check Registry security here.
  491. if ((hReturn != S_OK) || (!HasPermission())) {
  492. // if Impersonation level is incorrect or
  493. // the caller doesn't have permission to read
  494. // from the registry, then they cannot continue
  495. hReturn = WBEM_E_ACCESS_DENIED;
  496. }
  497. #else
  498. hReturn = S_OK;
  499. #endif
  500. if (hReturn == S_OK) {
  501. hReturn = CreateRefresherObject(
  502. pNamespace,
  503. pTemplate,
  504. pRefresher,
  505. lFlags,
  506. pContext,
  507. NULL,
  508. NULL,
  509. ppRefreshable,
  510. plId);
  511. }
  512. #ifdef __WBEMSECURITY
  513. // Revert if we successfuly impersonated the user
  514. if ( fRevert )
  515. {
  516. CoRevertToSelf();
  517. }
  518. #endif
  519. return hReturn;
  520. }
  521. //***************************************************************************
  522. //
  523. // CNt5PerfProvider::StopRefreshing
  524. //
  525. // Called whenever a user wants to remove an object from a refresher.
  526. //
  527. // Parameters:
  528. // <pRefresher> The refresher object from which we are to
  529. // remove the perf object.
  530. // <lId> The ID of the object.
  531. // <lFlags> Not used.
  532. //
  533. //***************************************************************************
  534. // ok
  535. HRESULT CNt5PerfProvider::StopRefreshing(
  536. /* [in] */ IWbemRefresher __RPC_FAR *pRefresher,
  537. /* [in] */ long lId,
  538. /* [in] */ long lFlags
  539. )
  540. {
  541. CNt5Refresher *pRef;
  542. BOOL bRes ;
  543. HRESULT hReturn;
  544. UNREFERENCED_PARAMETER(lFlags);
  545. #ifdef __WBEMSECURITY
  546. hReturn = CoImpersonateClient(); // make sure we're legit.
  547. BOOL fRevert = SUCCEEDED( hReturn );
  548. // The following error appears to occur when we are in-proc and there is no
  549. // proxy/stub, so we are effectively impersonating already
  550. if ( RPC_E_CALL_COMPLETE == hReturn ) {
  551. hReturn = S_OK;
  552. }
  553. if (S_OK == hReturn) {
  554. hReturn = CheckImpersonationLevel();
  555. }
  556. // Check Registry security here.
  557. if ((hReturn != S_OK) || (!HasPermission())) {
  558. // if Impersonation level is incorrect or
  559. // the caller doesn't have permission to read
  560. // from the registry, then they cannot continue
  561. hReturn = WBEM_E_ACCESS_DENIED;
  562. }
  563. #else
  564. hReturn = S_OK;
  565. #endif
  566. if (hReturn == S_OK) {
  567. pRef = (CNt5Refresher *) pRefresher;
  568. bRes = pRef->RemoveObject(lId);
  569. if (bRes == FALSE) {
  570. hReturn = WBEM_E_FAILED;
  571. } else {
  572. hReturn = WBEM_NO_ERROR;
  573. }
  574. }
  575. #ifdef __WBEMSECURITY
  576. // Revert if we successfuly impersonated the user
  577. if ( fRevert )
  578. {
  579. CoRevertToSelf();
  580. }
  581. #endif
  582. return hReturn;
  583. }
  584. HRESULT CNt5PerfProvider::CreateRefreshableEnum(
  585. /* [in] */ IWbemServices __RPC_FAR *pNamespace,
  586. /* [string][in] */ LPCWSTR wszClass,
  587. /* [in] */ IWbemRefresher __RPC_FAR *pRefresher,
  588. /* [in] */ long lFlags,
  589. /* [in] */ IWbemContext __RPC_FAR *pContext,
  590. /* [in] */ IWbemHiPerfEnum __RPC_FAR *pHiPerfEnum,
  591. /* [out] */ long __RPC_FAR *plId)
  592. {
  593. HRESULT hReturn;
  594. #ifdef __WBEMSECURITY
  595. hReturn = CoImpersonateClient(); // make sure we're legit.
  596. BOOL fRevert = SUCCEEDED( hReturn );
  597. // The following error appears to occur when we are in-proc and there is no
  598. // proxy/stub, so we are effectively impersonating already
  599. if ( RPC_E_CALL_COMPLETE == hReturn ) {
  600. hReturn = S_OK;
  601. }
  602. if (S_OK == hReturn) {
  603. hReturn = CheckImpersonationLevel();
  604. }
  605. // Check Registry security here.
  606. if ((hReturn != S_OK) || (!HasPermission())) {
  607. // if Impersonation level is incorrect or
  608. // the caller doesn't have permission to read
  609. // from the registry, then they cannot continue
  610. hReturn = WBEM_E_ACCESS_DENIED;
  611. }
  612. #else
  613. hReturn = S_OK;
  614. #endif
  615. if (hReturn == S_OK) {
  616. hReturn = CreateRefresherObject(
  617. pNamespace,
  618. NULL,
  619. pRefresher,
  620. lFlags,
  621. pContext,
  622. wszClass,
  623. pHiPerfEnum,
  624. NULL,
  625. plId);
  626. }
  627. #ifdef __WBEMSECURITY
  628. // Revert if we successfuly impersonated the user
  629. if ( fRevert )
  630. {
  631. CoRevertToSelf();
  632. }
  633. #endif
  634. return hReturn;
  635. }
  636. HRESULT CNt5PerfProvider::GetObjects(
  637. /* [in] */ IWbemServices __RPC_FAR *pNamespace,
  638. /* [in] */ long lNumObjects,
  639. /* [size_is][in] */ IWbemObjectAccess __RPC_FAR *__RPC_FAR *apObj,
  640. /* [in] */ long lFlags,
  641. /* [in] */ IWbemContext __RPC_FAR *pContext)
  642. {
  643. DBG_UNREFERENCED_PARAMETER(pNamespace);
  644. DBG_UNREFERENCED_PARAMETER(lNumObjects);
  645. DBG_UNREFERENCED_PARAMETER(apObj);
  646. DBG_UNREFERENCED_PARAMETER(lFlags);
  647. DBG_UNREFERENCED_PARAMETER(pContext);
  648. return WBEM_E_METHOD_NOT_IMPLEMENTED;
  649. }
  650. //***************************************************************************
  651. //
  652. // CNt5PerfProvider::MapClass
  653. //
  654. // Adds the class map to an internal cache.
  655. //
  656. // <pClsMap> The pointer to the map info to add. This pointer
  657. // is acquired by this function and should not be
  658. // deleted by the caller.
  659. //
  660. //***************************************************************************
  661. // ok
  662. BOOL CNt5PerfProvider::AddClassMap(
  663. IN CClassMapInfo *pClsMap
  664. )
  665. {
  666. DWORD dwResult = ERROR_SUCCESS;
  667. int i;
  668. CClassMapInfo *pTracer;
  669. int nNumElements;
  670. if (m_hClassMapMutex != 0) {
  671. if (WAIT_OBJECT_0 == WaitForSingleObject(m_hClassMapMutex, cdwClassMapTimeout)) {
  672. nNumElements = m_aCache.Size();
  673. // Because of a problem in which perflibs seem to ignore supported methods of updating
  674. // the perflib names database (lodctr/unlodctr), do a quick initial traversal to ensure
  675. // that we don't have any duplicate object indices, since this can cause real problems
  676. // during adding and refreshing, since incorrect indexes can be returned.
  677. for (i = 0; i < nNumElements; i++) {
  678. pTracer = (CClassMapInfo *) m_aCache[i];
  679. // We've got a problem -- we cannot add this class
  680. if (pClsMap->m_dwObjectId == pTracer->m_dwObjectId )
  681. {
  682. ReleaseMutex( m_hClassMapMutex );
  683. return FALSE;
  684. }
  685. }
  686. for (i = 0; i < nNumElements; i++) {
  687. pTracer = (CClassMapInfo *) m_aCache[i];
  688. if (_wcsicmp(pClsMap->m_pszClassName, pTracer->m_pszClassName) < 0) {
  689. m_aCache.InsertAt(i, pClsMap);
  690. break;
  691. }
  692. }
  693. if (i == nNumElements) {
  694. // If here, add it to the end.
  695. // ===========================
  696. m_aCache.Add(pClsMap);
  697. }
  698. // make sure the library is in the list
  699. dwResult = m_PerfObject.AddClass (pClsMap->m_pClassDef, TRUE);
  700. ReleaseMutex(m_hClassMapMutex);
  701. } else {
  702. dwResult = ERROR_LOCK_FAILED;
  703. }
  704. }
  705. return (dwResult == ERROR_SUCCESS);
  706. }
  707. //***************************************************************************
  708. //
  709. // CNt5PerfProvider::FindClassMap
  710. //
  711. //***************************************************************************
  712. // ok
  713. CClassMapInfo *CNt5PerfProvider::FindClassMap(
  714. LPWSTR pszClassName
  715. )
  716. {
  717. int l = 0;
  718. int u;
  719. int m;
  720. CClassMapInfo *pClsMap;
  721. CClassMapInfo *pClsMapReturn = NULL;
  722. // Binary search the cache.
  723. // ========================
  724. if (m_hClassMapMutex != 0) {
  725. if (WAIT_OBJECT_0 == WaitForSingleObject(m_hClassMapMutex, cdwClassMapTimeout)) {
  726. u = m_aCache.Size() - 1;
  727. while (l <= u) {
  728. m = (l + u) / 2;
  729. pClsMap = (CClassMapInfo *) m_aCache[m];
  730. if (pClsMap != NULL) {
  731. if (_wcsicmp(pszClassName, pClsMap->m_pszClassName) < 0) {
  732. u = m - 1;
  733. } else if (_wcsicmp(pszClassName, pClsMap->m_pszClassName) > 0) {
  734. l = m + 1;
  735. } else { // Hit!
  736. pClsMapReturn = pClsMap;
  737. break;
  738. }
  739. } else {
  740. break;
  741. }
  742. }
  743. ReleaseMutex(m_hClassMapMutex);
  744. }
  745. }
  746. return pClsMapReturn;
  747. }
  748. //***************************************************************************
  749. //
  750. // CNt5PerfProvider::MapClass
  751. //
  752. // Retrieves the requested class and places it in the cache.
  753. //
  754. // Parameters:
  755. // pNs The namespace which contains the class definition.
  756. // wsClass The class name.
  757. // pCtx The inbound context object. Only used for reentrant
  758. // calls.
  759. //
  760. //***************************************************************************
  761. // ok
  762. BOOL CNt5PerfProvider::MapClass(
  763. IN IWbemServices *pNs,
  764. IN WCHAR *wszClass,
  765. IN IWbemContext *pCtx
  766. )
  767. {
  768. HRESULT hRes = 0;
  769. BOOL bReturn = FALSE;
  770. IWbemClassObject *pClsDef = 0;
  771. IWbemQualifierSet *pQSet = 0;
  772. VARIANT v;
  773. CClassMapInfo *pMapInfo = 0;
  774. if (m_hClassMapMutex != 0) {
  775. if (WAIT_OBJECT_0 == WaitForSingleObject(m_hClassMapMutex, cdwClassMapTimeout)) {
  776. // See if the class is already in the cache.
  777. // =========================================
  778. if (FindClassMap(wszClass) != 0) {
  779. // already loaded so quit now
  780. bReturn = TRUE;
  781. } else {
  782. // Get the class definition from CIMOM.
  783. // ====================================
  784. hRes = pNs->GetObject(CBSTR(wszClass), 0, pCtx, &pClsDef, 0);
  785. if (hRes == NO_ERROR) {
  786. // Verify the class is one of ours by checking
  787. // the "provider" qualifier to ensure it matches
  788. // the name that we we have for this component.
  789. // =============================================
  790. hRes = pClsDef->GetQualifierSet(&pQSet);
  791. if (hRes == NO_ERROR) {
  792. VariantInit(&v);
  793. hRes = pQSet->Get(CBSTR(cszProvider), 0, &v, 0);
  794. pQSet->Release();
  795. if ((hRes == NO_ERROR) && (v.vt == VT_BSTR)) {
  796. if (_wcsicmp(V_BSTR(&v), cszProviderName) == 0) {
  797. // Get the property handles and mappings to the perf counter ids
  798. // by calling the Map() method of CClassMapInfo.
  799. // ==============================================================
  800. pMapInfo = new CClassMapInfo;
  801. if (pMapInfo != NULL) {
  802. if (pMapInfo->Map(pClsDef)) {
  803. // Add it to the cache.
  804. // ====================
  805. bReturn = AddClassMap(pMapInfo);
  806. } else {
  807. // unable to add this to the cache
  808. delete pMapInfo;
  809. //pClsDef->Release(); // this was not AddRef'd so no need to Release
  810. }
  811. } else {
  812. // inable to create new class
  813. bReturn = FALSE;
  814. }
  815. } else {
  816. // unable to read provider qualifier so bail
  817. // as this isn't a dynamic provider
  818. pClsDef->Release();
  819. }
  820. } else {
  821. SetLastError ((DWORD)WBEM_E_INVALID_PROVIDER_REGISTRATION);
  822. }
  823. VariantClear(&v);
  824. } else {
  825. // unable to get qualifiers
  826. pClsDef->Release();
  827. }
  828. } else {
  829. // Unable to retrieve the class definition
  830. }
  831. }
  832. ReleaseMutex(m_hClassMapMutex);
  833. }
  834. }
  835. return bReturn;
  836. }
  837. //***************************************************************************
  838. //
  839. // CNt5PerfProvider::HasPermission
  840. //
  841. // tests to see if the caller has permission to access the functions
  842. //
  843. // Parameters:
  844. // void N/A
  845. //
  846. //***************************************************************************
  847. // ok
  848. BOOL CNt5PerfProvider::HasPermission (void)
  849. {
  850. DWORD dwStatus;
  851. HKEY hKeyTest;
  852. BOOL bReturn;
  853. dwStatus = RegOpenKeyExW (
  854. HKEY_LOCAL_MACHINE,
  855. (LPCWSTR)L"Software\\Microsoft\\Windows NT\\CurrentVersion\\WbemPerf",
  856. 0, KEY_READ, &hKeyTest);
  857. if ((dwStatus == ERROR_SUCCESS) || (dwStatus == ERROR_FILE_NOT_FOUND)) {
  858. bReturn = TRUE;
  859. if (dwStatus == ERROR_SUCCESS) RegCloseKey (hKeyTest);
  860. } else {
  861. bReturn = FALSE;
  862. }
  863. return bReturn;
  864. }
  865. //***************************************************************************
  866. //
  867. // CNt5PerfProvider::CheckImpersonationLevel
  868. //
  869. // tests caller's security impersonation level for correct access
  870. //
  871. // Only call here if CoImpersonate worked.
  872. //
  873. // Parameters:
  874. // void N/A
  875. //
  876. //***************************************************************************
  877. // ok
  878. HRESULT CNt5PerfProvider::CheckImpersonationLevel (void)
  879. {
  880. HRESULT hr = WBEM_E_ACCESS_DENIED;
  881. BOOL bReturn;
  882. // Now, let's check the impersonation level. First, get the thread token
  883. HANDLE hThreadTok;
  884. DWORD dwImp, dwBytesReturned;
  885. bReturn = OpenThreadToken(
  886. GetCurrentThread(),
  887. TOKEN_QUERY,
  888. TRUE,
  889. &hThreadTok);
  890. if (!bReturn) {
  891. // If the CoImpersonate works, but the OpenThreadToken fails, we are running under the
  892. // process token (either local system, or if we are running with /exe, the rights of
  893. // the logged in user). In either case, impersonation rights don't apply. We have the
  894. // full rights of that user.
  895. hr = WBEM_S_NO_ERROR;
  896. } else {
  897. // We really do have a thread token, so let's retrieve its level
  898. bReturn = GetTokenInformation(
  899. hThreadTok,
  900. TokenImpersonationLevel,
  901. &dwImp,
  902. sizeof(DWORD),
  903. &dwBytesReturned);
  904. if (bReturn) {
  905. // Is the impersonation level Impersonate?
  906. if ((dwImp == SecurityImpersonation) || (dwImp == SecurityDelegation)) {
  907. hr = WBEM_S_NO_ERROR;
  908. } else {
  909. hr = WBEM_E_ACCESS_DENIED;
  910. }
  911. } else {
  912. hr = WBEM_E_FAILED;
  913. }
  914. // Done with this handle
  915. CloseHandle(hThreadTok);
  916. }
  917. return hr;
  918. }