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.

1075 lines
35 KiB

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