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.

5381 lines
204 KiB

  1. /*++
  2. Copyright (C) 1995-1999 Microsoft Corporation
  3. Module Name:
  4. wmi.c
  5. Abstract:
  6. WMI interface functions exported by PDH.DLL
  7. --*/
  8. #include <windows.h>
  9. #include <winperf.h>
  10. #include "mbctype.h"
  11. #include <mbctype.h>
  12. #include <pdh.h>
  13. #include <pdhmsg.h>
  14. #include <assert.h>
  15. #include "wbemdef.h"
  16. #include "pdhitype.h"
  17. #include "pdhidef.h"
  18. #include "strings.h"
  19. #define PERF_TIMER_FIELD \
  20. (PERF_TIMER_TICK | PERF_TIMER_100NS | PERF_OBJECT_TIMER)
  21. __inline
  22. VOID
  23. PdhiSysFreeString(
  24. BSTR *x
  25. )
  26. {
  27. if (x != NULL) {
  28. if (*x != NULL) {
  29. SysFreeString(*x);
  30. *x = NULL;
  31. }
  32. }
  33. }
  34. // at this point, calling the refresher while adding items to the refresher
  35. // doesn't work. so for the time being, we'll use this interlock to prevent
  36. // a collision
  37. static BOOL bDontRefresh = FALSE;
  38. // Prototype
  39. HRESULT WbemSetProxyBlanket(
  40. IUnknown *pInterface,
  41. DWORD dwAuthnSvc,
  42. DWORD dwAuthzSvc,
  43. OLECHAR *pServerPrincName,
  44. DWORD dwAuthLevel,
  45. DWORD dwImpLevel,
  46. RPC_AUTH_IDENTITY_HANDLE pAuthInfo,
  47. DWORD dwCapabilities );
  48. HRESULT SetWbemSecurity( IUnknown *pInterface )
  49. {
  50. return WbemSetProxyBlanket( pInterface, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL,
  51. RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE );
  52. }
  53. // This is the same timeout value the refresher uses so we can pretend
  54. // we're doing the same thing.
  55. #define WBEM_REFRESHER_TIMEOUT 10000
  56. // This class is designed to encapsulate the IWbemRefresher functionality
  57. // The definition and implementation are all in this source file
  58. class CWbemRefresher : public IUnknown
  59. {
  60. protected:
  61. LONG m_lRefCount;
  62. // The primitives that will control the multithreading stuff
  63. HANDLE m_hQuitEvent;
  64. HANDLE m_hDoWorkEvent;
  65. HANDLE m_hWorkDoneEvent;
  66. HANDLE m_hRefrMutex;
  67. HANDLE m_hInitializedEvent;
  68. HANDLE m_hThread;
  69. DWORD m_dwThreadId;
  70. BOOL m_fThreadOk;
  71. // These are the pass-thru variables we will use as placeholders
  72. // as we perform our operations. Note that a couple are missing.
  73. // This is because we are not really using them in our code, so
  74. // no sense in adding anything we don't really need.
  75. IStream* m_pNSStream;
  76. LPCWSTR m_wszPath;
  77. LPCWSTR m_wszClassName;
  78. long m_lFlags;
  79. IWbemClassObject** m_ppRefreshable;
  80. IWbemHiPerfEnum** m_ppEnum;
  81. long* m_plId;
  82. long m_lId;
  83. HRESULT m_hOperResult;
  84. // This is what will be set to indicate to the thread which operation
  85. // it is supposed to perform.
  86. typedef enum
  87. {
  88. eRefrOpNone,
  89. eRefrOpRefresh,
  90. eRefrOpAddByPath,
  91. eRefrOpAddEnum,
  92. eRefrOpRemove,
  93. eRefrOpLast
  94. } tRefrOps;
  95. tRefrOps m_eRefrOp;
  96. // Thread ebtryt
  97. class XRefresher : public IWbemRefresher
  98. {
  99. protected:
  100. CWbemRefresher* m_pOuter;
  101. public:
  102. XRefresher( CWbemRefresher* pOuter ) : m_pOuter( pOuter ) {};
  103. ~XRefresher() {};
  104. STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID FAR* ppvObj);
  105. STDMETHOD_(ULONG, AddRef)(THIS);
  106. STDMETHOD_(ULONG, Release)(THIS);
  107. STDMETHOD(Refresh)(long lFlags);
  108. } m_xRefresher;
  109. class XConfigRefresher : public IWbemConfigureRefresher
  110. {
  111. protected:
  112. CWbemRefresher* m_pOuter;
  113. public:
  114. XConfigRefresher( CWbemRefresher* pOuter ) : m_pOuter( pOuter ) {};
  115. ~XConfigRefresher() {};
  116. STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID FAR* ppvObj);
  117. STDMETHOD_(ULONG, AddRef)(THIS);
  118. STDMETHOD_(ULONG, Release)(THIS);
  119. STDMETHOD(AddObjectByPath)(IWbemServices* pNamespace, LPCWSTR wszPath,
  120. long lFlags, IWbemContext* pContext,
  121. IWbemClassObject** ppRefreshable, long* plId);
  122. STDMETHOD(AddObjectByTemplate)(IWbemServices* pNamespace,
  123. IWbemClassObject* pTemplate,
  124. long lFlags, IWbemContext* pContext,
  125. IWbemClassObject** ppRefreshable, long* plId);
  126. STDMETHOD(AddRefresher)(IWbemRefresher* pRefresher, long lFlags,
  127. long* plId);
  128. STDMETHOD(Remove)(long lId, long lFlags);
  129. STDMETHOD(AddEnum)( IWbemServices* pNamespace, LPCWSTR wscClassName,
  130. long lFlags, IWbemContext* pContext, IWbemHiPerfEnum** ppEnum,
  131. long* plId );
  132. } m_xConfigRefresher;
  133. protected:
  134. void Initialize( void );
  135. void Cleanup( void );
  136. // Operation helpers
  137. HRESULT SignalRefresher( void );
  138. HRESULT SetRefresherParams( IWbemServices* pNamespace, tRefrOps eOp,
  139. LPCWSTR pwszPath, LPCWSTR pwszClassName, long lFlags,
  140. IWbemClassObject** ppRefreshable, IWbemHiPerfEnum** ppEnum, long* plId,
  141. long lId );
  142. void ClearRefresherParams( void );
  143. DWORD WINAPI RealEntry( void );
  144. static DWORD WINAPI ThreadProc( void * pThis )
  145. {
  146. return ((CWbemRefresher*) pThis)->RealEntry();
  147. }
  148. public:
  149. CWbemRefresher();
  150. virtual ~CWbemRefresher();
  151. STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID FAR* ppvObj);
  152. STDMETHOD_(ULONG, AddRef)(THIS);
  153. STDMETHOD_(ULONG, Release)(THIS);
  154. // The real implementations
  155. STDMETHOD(AddObjectByPath)(IWbemServices* pNamespace, LPCWSTR wszPath,
  156. long lFlags, IWbemContext* pContext,
  157. IWbemClassObject** ppRefreshable, long* plId);
  158. STDMETHOD(AddObjectByTemplate)(IWbemServices* pNamespace,
  159. IWbemClassObject* pTemplate,
  160. long lFlags, IWbemContext* pContext,
  161. IWbemClassObject** ppRefreshable, long* plId);
  162. STDMETHOD(AddRefresher)(IWbemRefresher* pRefresher, long lFlags,
  163. long* plId);
  164. STDMETHOD(Remove)(long lId, long lFlags);
  165. STDMETHOD(AddEnum)( IWbemServices* pNamespace, LPCWSTR wscClassName,
  166. long lFlags, IWbemContext* pContext, IWbemHiPerfEnum** ppEnum,
  167. long* plId );
  168. STDMETHOD(Refresh)(long lFlags);
  169. };
  170. /*
  171. ** Begin CWbemRefresher Implementation
  172. */
  173. #if _MSC_VER >= 1200
  174. #pragma warning(push)
  175. #endif
  176. #pragma warning(disable:4355)
  177. // CTor and DTor
  178. CWbemRefresher::CWbemRefresher( void )
  179. : m_lRefCount(0), m_xRefresher( this ), m_xConfigRefresher( this ),
  180. m_hQuitEvent( NULL ),
  181. m_hDoWorkEvent( NULL ), m_hRefrMutex( NULL ), m_hInitializedEvent( NULL ),
  182. m_hThread( NULL ), m_hWorkDoneEvent( NULL ), m_dwThreadId( 0 ),
  183. m_pNSStream( NULL ), m_wszPath( NULL ), m_wszClassName( NULL ),
  184. m_lFlags( 0L ), m_ppRefreshable( NULL ), m_ppEnum( NULL ), m_plId( NULL ),
  185. m_eRefrOp( eRefrOpRefresh ), m_hOperResult( WBEM_S_NO_ERROR ), m_fThreadOk( FALSE ),
  186. m_lId( 0 )
  187. {
  188. Initialize();
  189. }
  190. #if _MSC_VER >= 1200
  191. #pragma warning(pop)
  192. #else
  193. #pragma warning(default:4355)
  194. #endif
  195. CWbemRefresher::~CWbemRefresher( void )
  196. {
  197. Cleanup();
  198. }
  199. void CWbemRefresher::Initialize( void )
  200. {
  201. // Now create the events, mutexes and our pal, the MTA thread on which all of
  202. // the operations will run
  203. m_hQuitEvent = CreateEventW( NULL, FALSE, FALSE, NULL );
  204. m_hDoWorkEvent = CreateEventW( NULL, FALSE, FALSE, NULL );
  205. m_hInitializedEvent = CreateEventW( NULL, FALSE, FALSE, NULL );
  206. m_hWorkDoneEvent = CreateEventW( NULL, FALSE, FALSE, NULL );
  207. m_hRefrMutex = CreateMutexW( NULL, FALSE, NULL );
  208. // If we don't have all these, something's gone south
  209. if ( NULL == m_hQuitEvent ||
  210. NULL == m_hDoWorkEvent ||
  211. NULL == m_hInitializedEvent ||
  212. NULL == m_hWorkDoneEvent ||
  213. NULL == m_hRefrMutex )
  214. {
  215. return;
  216. }
  217. // Kick off the thread and wait for the initialized event signal (we'll give it
  218. // 5 seconds...if it don't get signalled in that timeframe, something is most likely
  219. // wrong, but we'll bounce out so whoever allocated us isn't left wondering what
  220. // to do).
  221. m_hThread = CreateThread( NULL, 0, CWbemRefresher::ThreadProc,
  222. (void*) this, 0, &m_dwThreadId );
  223. if ( NULL == m_hThread )
  224. {
  225. return;
  226. }
  227. WaitForSingleObject( m_hInitializedEvent, 5000 );
  228. }
  229. void CWbemRefresher::Cleanup( void )
  230. {
  231. // If we have a thread, tell it to go away
  232. if ( NULL != m_hThread )
  233. {
  234. // Signal the quit event and give the thread a 5 second grace period
  235. // to shutdown. If it don't, don't worry, just close the handle and go away.
  236. SetEvent( m_hQuitEvent );
  237. WaitForSingleObject( m_hThread, 5000 );
  238. CloseHandle( m_hThread );
  239. m_hThread = NULL;
  240. }
  241. // Cleanup the primitives
  242. if ( NULL != m_hQuitEvent )
  243. {
  244. CloseHandle( m_hQuitEvent );
  245. m_hQuitEvent = NULL;
  246. }
  247. if ( NULL != m_hDoWorkEvent )
  248. {
  249. CloseHandle( m_hDoWorkEvent );
  250. m_hDoWorkEvent = NULL;
  251. }
  252. if ( NULL != m_hInitializedEvent )
  253. {
  254. CloseHandle( m_hInitializedEvent );
  255. m_hInitializedEvent = NULL;
  256. }
  257. if ( NULL != m_hWorkDoneEvent )
  258. {
  259. CloseHandle( m_hWorkDoneEvent );
  260. m_hWorkDoneEvent = NULL;
  261. }
  262. if ( NULL != m_hRefrMutex )
  263. {
  264. CloseHandle( m_hRefrMutex );
  265. m_hRefrMutex = NULL;
  266. }
  267. }
  268. DWORD CWbemRefresher::RealEntry( void )
  269. {
  270. // Grab hold of all the things we may care about in case some evil timing
  271. // problem occurs, so we don't get left trying to hit on member variables that
  272. // don't exist anymore.
  273. HANDLE hQuitEvent = m_hQuitEvent,
  274. hDoWorkEvent = m_hDoWorkEvent,
  275. hInitializedEvent = m_hInitializedEvent,
  276. hWorkDoneEvent = m_hWorkDoneEvent;
  277. DWORD dwWait = 0;
  278. HANDLE ahEvents[2];
  279. ahEvents[0] = hDoWorkEvent;
  280. ahEvents[1] = hQuitEvent;
  281. // Initialize this thread
  282. HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  283. if (hr == S_FALSE) {
  284. // COM library is already initialized, we can continue;
  285. //
  286. hr = S_OK;
  287. }
  288. // Now get the refresher and config refresher pointers.
  289. IWbemRefresher* pWbemRefresher = NULL;
  290. IWbemConfigureRefresher* pWbemConfig = NULL;
  291. if ( SUCCEEDED( hr ) )
  292. {
  293. hr = CoCreateInstance (CLSID_WbemRefresher, 0, CLSCTX_SERVER,
  294. IID_IWbemRefresher, (LPVOID *)&pWbemRefresher);
  295. if ( SUCCEEDED( hr ) )
  296. {
  297. pWbemRefresher->QueryInterface( IID_IWbemConfigureRefresher, (LPVOID *) &pWbemConfig );
  298. }
  299. }
  300. // Obviously we can't go any further if we don't have our pointers correctly
  301. // setup.
  302. m_fThreadOk = SUCCEEDED( hr );
  303. // Ready to go --- Signal the Initialized Event
  304. SetEvent( hInitializedEvent );
  305. if ( m_fThreadOk )
  306. {
  307. while ( ( dwWait = WaitForMultipleObjects( 2, ahEvents, FALSE, INFINITE ) ) == WAIT_OBJECT_0 )
  308. {
  309. // Don't continue if quit is signalled
  310. if ( WaitForSingleObject( hQuitEvent, 0 ) == WAIT_OBJECT_0 )
  311. {
  312. break;
  313. }
  314. // This is where we'll do the real operation
  315. switch( m_eRefrOp )
  316. {
  317. case eRefrOpRefresh:
  318. {
  319. m_hOperResult = pWbemRefresher->Refresh( m_lFlags );
  320. break;
  321. }
  322. // For both of these ops, we will need to umarshal the
  323. // namespace
  324. case eRefrOpAddEnum:
  325. case eRefrOpAddByPath:
  326. {
  327. IWbemServices* pNamespace = NULL;
  328. // Unmarshal the interface, then set security
  329. m_hOperResult = CoGetInterfaceAndReleaseStream(
  330. m_pNSStream, IID_IWbemServices,
  331. (void**) &pNamespace );
  332. m_pNSStream = NULL;
  333. if ( SUCCEEDED( m_hOperResult ) )
  334. {
  335. m_hOperResult = SetWbemSecurity( pNamespace );
  336. if ( SUCCEEDED( m_hOperResult ) )
  337. {
  338. if ( eRefrOpAddByPath == m_eRefrOp )
  339. {
  340. m_hOperResult = pWbemConfig->AddObjectByPath(
  341. pNamespace, m_wszPath, m_lFlags, NULL,
  342. m_ppRefreshable, m_plId );
  343. }
  344. else
  345. {
  346. m_hOperResult = pWbemConfig->AddEnum(
  347. pNamespace, m_wszClassName, m_lFlags, NULL,
  348. m_ppEnum, m_plId );
  349. }
  350. }
  351. pNamespace->Release();
  352. }
  353. break;
  354. }
  355. case eRefrOpRemove:
  356. {
  357. m_hOperResult = pWbemConfig->Remove( m_lId, m_lFlags );
  358. break;
  359. }
  360. default:
  361. {
  362. m_hOperResult = WBEM_E_FAILED;
  363. }
  364. }
  365. // Signal the event to let a waiting thread know we're done doing
  366. // what it asked us to do.
  367. SetEvent( hWorkDoneEvent );
  368. }
  369. }
  370. // This means we're not processing anymore (for whatever reason)
  371. m_fThreadOk = FALSE;
  372. // Cleanup our pointers
  373. if ( NULL != pWbemRefresher )
  374. {
  375. pWbemRefresher->Release();
  376. }
  377. if ( NULL != pWbemConfig )
  378. {
  379. pWbemConfig->Release();
  380. }
  381. CoUninitialize();
  382. return 0;
  383. }
  384. // CWbemRefresher class functions
  385. SCODE CWbemRefresher::QueryInterface(REFIID riid, LPVOID FAR* ppvObj)
  386. {
  387. *ppvObj = 0;
  388. if (IID_IUnknown==riid)
  389. {
  390. *ppvObj = (IUnknown*)this;
  391. AddRef();
  392. return NOERROR;
  393. }
  394. else if ( IID_IWbemRefresher == riid )
  395. {
  396. *ppvObj = (IWbemRefresher*) &m_xRefresher;
  397. AddRef();
  398. return NOERROR;
  399. }
  400. else if ( IID_IWbemConfigureRefresher == riid )
  401. {
  402. *ppvObj = (IWbemConfigureRefresher*) &m_xConfigRefresher;
  403. AddRef();
  404. return NOERROR;
  405. }
  406. return ResultFromScode(E_NOINTERFACE);
  407. }
  408. ULONG CWbemRefresher::AddRef()
  409. {
  410. return InterlockedIncrement(&m_lRefCount);
  411. }
  412. ULONG CWbemRefresher::Release()
  413. {
  414. long lRef = InterlockedDecrement(&m_lRefCount);
  415. if (0 != lRef)
  416. return lRef;
  417. delete this;
  418. return 0;
  419. }
  420. HRESULT CWbemRefresher::SignalRefresher( void )
  421. {
  422. HRESULT hr = WBEM_S_NO_ERROR;
  423. if ( SetEvent( m_hDoWorkEvent ) )
  424. {
  425. if ( WaitForSingleObject( m_hWorkDoneEvent, INFINITE ) == WAIT_OBJECT_0 )
  426. {
  427. hr = m_hOperResult;
  428. }
  429. else
  430. {
  431. hr = WBEM_E_FAILED;
  432. }
  433. }
  434. else
  435. {
  436. hr = WBEM_E_FAILED;
  437. }
  438. ClearRefresherParams();
  439. return hr;
  440. }
  441. HRESULT CWbemRefresher::SetRefresherParams( IWbemServices* pNamespace, tRefrOps eOp,
  442. LPCWSTR pwszPath, LPCWSTR pwszClassName, long lFlags,
  443. IWbemClassObject** ppRefreshable, IWbemHiPerfEnum** ppEnum, long* plId,
  444. long lId )
  445. {
  446. HRESULT hr = WBEM_S_NO_ERROR;
  447. if ( NULL != pNamespace )
  448. {
  449. // Marshal the namespace pointer into the stream member
  450. hr = CoMarshalInterThreadInterfaceInStream( IID_IWbemServices, pNamespace,
  451. &m_pNSStream );
  452. }
  453. else
  454. {
  455. m_pNSStream = NULL;
  456. }
  457. if ( SUCCEEDED( hr ) )
  458. {
  459. m_eRefrOp = eOp;
  460. m_wszPath = pwszPath;
  461. m_wszClassName = pwszClassName,
  462. m_lFlags = lFlags;
  463. m_ppRefreshable = ppRefreshable;
  464. m_ppEnum = ppEnum;
  465. m_plId = plId;
  466. m_lId = lId;
  467. }
  468. return hr;
  469. }
  470. void CWbemRefresher::ClearRefresherParams( void )
  471. {
  472. m_pNSStream = NULL;
  473. m_eRefrOp = eRefrOpNone;
  474. m_wszPath = NULL;
  475. m_wszClassName = NULL,
  476. m_lFlags = 0L;
  477. m_ppRefreshable = NULL;
  478. m_ppEnum = NULL;
  479. m_plId = NULL;
  480. m_lId = 0L;
  481. m_hOperResult = WBEM_S_NO_ERROR;
  482. }
  483. // These are the real method implementations
  484. STDMETHODIMP CWbemRefresher::AddObjectByPath(
  485. IWbemServices* pNamespace, LPCWSTR wszPath,
  486. long lFlags, IWbemContext* pContext,
  487. IWbemClassObject** ppRefreshable, long* plId)
  488. {
  489. HRESULT hr = WBEM_E_FAILED;
  490. UNREFERENCED_PARAMETER (pContext);
  491. if ( WaitForSingleObject( m_hRefrMutex, WBEM_REFRESHER_TIMEOUT ) == WAIT_OBJECT_0 )
  492. {
  493. // Check that the thread is still running
  494. if ( m_fThreadOk )
  495. {
  496. // Setup the parameters and perform the operation
  497. hr = SetRefresherParams( pNamespace, eRefrOpAddByPath, wszPath, NULL,
  498. lFlags, ppRefreshable, NULL, plId, 0L );
  499. if ( SUCCEEDED( hr ) )
  500. {
  501. // This is where we ask the thread to do the work
  502. hr = SignalRefresher();
  503. }
  504. }
  505. else
  506. {
  507. hr = WBEM_E_FAILED;
  508. }
  509. ReleaseMutex( m_hRefrMutex );
  510. }
  511. else
  512. {
  513. hr = WBEM_E_REFRESHER_BUSY;
  514. }
  515. return hr;
  516. }
  517. STDMETHODIMP CWbemRefresher::AddObjectByTemplate(
  518. IWbemServices* pNamespace,
  519. IWbemClassObject* pTemplate,
  520. long lFlags, IWbemContext* pContext,
  521. IWbemClassObject** ppRefreshable, long* plId)
  522. {
  523. UNREFERENCED_PARAMETER (pNamespace);
  524. UNREFERENCED_PARAMETER (pTemplate);
  525. UNREFERENCED_PARAMETER (lFlags);
  526. UNREFERENCED_PARAMETER (pContext);
  527. UNREFERENCED_PARAMETER (ppRefreshable);
  528. UNREFERENCED_PARAMETER (plId);
  529. // We don't call this internally, so don't implement
  530. return WBEM_E_METHOD_NOT_IMPLEMENTED;
  531. }
  532. STDMETHODIMP CWbemRefresher::Remove(long lId, long lFlags)
  533. {
  534. HRESULT hr = WBEM_E_FAILED;
  535. UNREFERENCED_PARAMETER (lId);
  536. UNREFERENCED_PARAMETER (lFlags);
  537. if ( WaitForSingleObject( m_hRefrMutex, WBEM_REFRESHER_TIMEOUT ) == WAIT_OBJECT_0 )
  538. {
  539. // Check that the thread is still running
  540. if ( m_fThreadOk )
  541. {
  542. // Setup the parameters and perform the operation
  543. hr = SetRefresherParams( NULL, eRefrOpRemove, NULL, NULL,
  544. lFlags, NULL, NULL, NULL, lId );
  545. if ( SUCCEEDED( hr ) )
  546. {
  547. // This is where we ask the thread to do the work
  548. hr = SignalRefresher();
  549. }
  550. }
  551. else
  552. {
  553. hr = WBEM_E_FAILED;
  554. }
  555. ReleaseMutex( m_hRefrMutex );
  556. }
  557. else
  558. {
  559. hr = WBEM_E_REFRESHER_BUSY;
  560. }
  561. return hr;
  562. }
  563. STDMETHODIMP CWbemRefresher::AddRefresher(
  564. IWbemRefresher* pRefresher, long lFlags, long* plId)
  565. {
  566. UNREFERENCED_PARAMETER (lFlags);
  567. UNREFERENCED_PARAMETER (pRefresher);
  568. UNREFERENCED_PARAMETER (plId);
  569. // We don't call this internally, so don't implement
  570. return WBEM_E_METHOD_NOT_IMPLEMENTED;
  571. }
  572. HRESULT CWbemRefresher::AddEnum(
  573. IWbemServices* pNamespace, LPCWSTR wszClassName,
  574. long lFlags, IWbemContext* pContext, IWbemHiPerfEnum** ppEnum,
  575. long* plId)
  576. {
  577. HRESULT hr = WBEM_E_FAILED;
  578. UNREFERENCED_PARAMETER (pContext);
  579. if ( WaitForSingleObject( m_hRefrMutex, WBEM_REFRESHER_TIMEOUT ) == WAIT_OBJECT_0 )
  580. {
  581. // Check that the thread is still running
  582. if ( m_fThreadOk )
  583. {
  584. // Setup the parameters and perform the operation
  585. hr = SetRefresherParams( pNamespace, eRefrOpAddEnum, NULL, wszClassName,
  586. lFlags, NULL, ppEnum, plId, 0L );
  587. if ( SUCCEEDED( hr ) )
  588. {
  589. // This is where we ask the thread to do the work
  590. hr = SignalRefresher();
  591. }
  592. }
  593. else
  594. {
  595. hr = WBEM_E_FAILED;
  596. }
  597. ReleaseMutex( m_hRefrMutex );
  598. }
  599. else
  600. {
  601. hr = WBEM_E_REFRESHER_BUSY;
  602. }
  603. return hr;
  604. }
  605. STDMETHODIMP CWbemRefresher::Refresh( long lFlags )
  606. {
  607. HRESULT hr = WBEM_E_FAILED;
  608. if ( WaitForSingleObject( m_hRefrMutex, WBEM_REFRESHER_TIMEOUT ) == WAIT_OBJECT_0 )
  609. {
  610. // Check that the thread is still running
  611. if ( m_fThreadOk )
  612. {
  613. // Setup the parameters and perform the operation
  614. hr = SetRefresherParams( NULL, eRefrOpRefresh, NULL, NULL,
  615. lFlags, NULL, NULL, NULL, 0L );
  616. if ( SUCCEEDED( hr ) )
  617. {
  618. // This is where we ask the thread to do the work
  619. hr = SignalRefresher();
  620. }
  621. }
  622. else
  623. {
  624. hr = WBEM_E_FAILED;
  625. }
  626. ReleaseMutex( m_hRefrMutex );
  627. }
  628. else
  629. {
  630. hr = WBEM_E_REFRESHER_BUSY;
  631. }
  632. return hr;
  633. }
  634. // XRefresher
  635. SCODE CWbemRefresher::XRefresher::QueryInterface(REFIID riid, LPVOID FAR* ppvObj)
  636. {
  637. return m_pOuter->QueryInterface( riid, ppvObj );
  638. }
  639. ULONG CWbemRefresher::XRefresher::AddRef()
  640. {
  641. return m_pOuter->AddRef();
  642. }
  643. ULONG CWbemRefresher::XRefresher::Release()
  644. {
  645. return m_pOuter->Release();
  646. }
  647. STDMETHODIMP CWbemRefresher::XRefresher::Refresh( long lFlags )
  648. {
  649. // Pass through
  650. return m_pOuter->Refresh( lFlags );
  651. }
  652. // XConfigRefresher
  653. SCODE CWbemRefresher::XConfigRefresher::QueryInterface(REFIID riid, LPVOID FAR* ppvObj)
  654. {
  655. return m_pOuter->QueryInterface( riid, ppvObj );
  656. }
  657. ULONG CWbemRefresher::XConfigRefresher::AddRef()
  658. {
  659. return m_pOuter->AddRef();
  660. }
  661. ULONG CWbemRefresher::XConfigRefresher::Release()
  662. {
  663. return m_pOuter->Release();
  664. }
  665. STDMETHODIMP CWbemRefresher::XConfigRefresher::AddObjectByPath(
  666. IWbemServices* pNamespace, LPCWSTR wszPath,
  667. long lFlags, IWbemContext* pContext,
  668. IWbemClassObject** ppRefreshable, long* plId)
  669. {
  670. // Pass through
  671. return m_pOuter->AddObjectByPath( pNamespace, wszPath, lFlags, pContext,
  672. ppRefreshable, plId );
  673. }
  674. STDMETHODIMP CWbemRefresher::XConfigRefresher::AddObjectByTemplate(
  675. IWbemServices* pNamespace,
  676. IWbemClassObject* pTemplate,
  677. long lFlags, IWbemContext* pContext,
  678. IWbemClassObject** ppRefreshable, long* plId)
  679. {
  680. // Pass through
  681. return m_pOuter->AddObjectByTemplate( pNamespace, pTemplate, lFlags, pContext,
  682. ppRefreshable, plId );
  683. }
  684. STDMETHODIMP CWbemRefresher::XConfigRefresher::Remove(long lId, long lFlags)
  685. {
  686. return m_pOuter->Remove( lId, lFlags );
  687. }
  688. STDMETHODIMP CWbemRefresher::XConfigRefresher::AddRefresher(
  689. IWbemRefresher* pRefresher, long lFlags, long* plId)
  690. {
  691. return m_pOuter->AddRefresher( pRefresher, lFlags, plId );
  692. }
  693. HRESULT CWbemRefresher::XConfigRefresher::AddEnum(
  694. IWbemServices* pNamespace, LPCWSTR wszClassName,
  695. long lFlags, IWbemContext* pContext, IWbemHiPerfEnum** ppEnum,
  696. long* plId)
  697. {
  698. return m_pOuter->AddEnum( pNamespace, wszClassName, lFlags, pContext,
  699. ppEnum, plId );
  700. }
  701. /*
  702. ** End CWbemRefresher Implementation!
  703. */
  704. // HELPER Function to establish the CWbemRefresher Interface pass-thru
  705. HRESULT CoCreateRefresher( IWbemRefresher** ppRefresher )
  706. {
  707. HRESULT hr = WBEM_S_NO_ERROR;
  708. // Allocate the pass-thru object then, if successful, get
  709. // the interface pointer out of it
  710. CWbemRefresher* pWbemRefresher = new CWbemRefresher;
  711. if ( NULL != pWbemRefresher )
  712. {
  713. hr = pWbemRefresher->QueryInterface( IID_IWbemRefresher, (LPVOID*) ppRefresher );
  714. }
  715. else
  716. {
  717. hr = WBEM_E_OUT_OF_MEMORY;
  718. }
  719. return hr;
  720. }
  721. PPDHI_WBEM_SERVER_DEF pFirstWbemServer = NULL;
  722. //BOOL bWbemInitialized = FALSE;
  723. BOOL bSecurityInitialized = FALSE;
  724. IGlobalInterfaceTable * gp_GIT = NULL;
  725. BOOL PdhiCoInitialize( void )
  726. {
  727. HRESULT sc = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  728. if ( !bSecurityInitialized )
  729. {
  730. // In case it hasn't been
  731. HRESULT hr = CoInitializeSecurity(
  732. NULL, //Points to security descriptor
  733. -1L, //Count of entries in asAuthSvc -1 means use default
  734. NULL, //Array of names to register
  735. NULL, //Reserved for future use
  736. RPC_C_AUTHN_LEVEL_PKT, //The default authentication level
  737. // for proxies
  738. RPC_C_IMP_LEVEL_IMPERSONATE, //The default impersonation level
  739. // for proxies
  740. NULL, //Authentication information for
  741. // each authentication service
  742. EOAC_NONE, //Additional client and/or
  743. // server-side capabilities
  744. NULL //Reserved for future use
  745. );
  746. bSecurityInitialized = (hr == S_OK || hr == RPC_E_TOO_LATE);
  747. }
  748. if (gp_GIT == NULL) {
  749. HRESULT hr1 = CoCreateInstance(CLSID_StdGlobalInterfaceTable,
  750. NULL,
  751. CLSCTX_INPROC_SERVER,
  752. IID_IGlobalInterfaceTable,
  753. (void **) & gp_GIT);
  754. if (hr1 != ERROR_SUCCESS) {
  755. gp_GIT = NULL;
  756. }
  757. }
  758. // We will only return that this succeeded if the call to CoInitializeEx
  759. // returned S_FALSE. If it didn't, it either errored or returned S_OK.
  760. // If S_OK, we will assume that the client isn't doing any COM stuff
  761. // natively. If S_FALSE, the client already CoInitialized this thread
  762. // so we just bumped up the ref count and should cleanup on the way
  763. // out
  764. return (S_FALSE == sc);
  765. }
  766. void PdhiCoUninitialize( void )
  767. {
  768. CoUninitialize();
  769. }
  770. PDH_FUNCTION PdhiCloseWbemServer (PPDHI_WBEM_SERVER_DEF pWbemServer);
  771. PDH_FUNCTION
  772. PdhiDisconnectWbemServer (
  773. PPDHI_WBEM_SERVER_DEF pWbemServer
  774. )
  775. {
  776. PDH_STATUS pdhReturn = ERROR_SUCCESS;
  777. if (pWbemServer != NULL) {
  778. pWbemServer->lRefCount--;
  779. if (pWbemServer->lRefCount < 0) {
  780. pWbemServer->lRefCount = 0;
  781. }
  782. }
  783. return pdhReturn;
  784. }
  785. PDH_FUNCTION
  786. PdhiFreeWbemQuery (
  787. PPDHI_QUERY pThisQuery
  788. )
  789. {
  790. HRESULT hRes;
  791. if (!bProcessIsDetaching) {
  792. if ((pThisQuery->pRefresherCfg) != NULL) {
  793. hRes = pThisQuery->pRefresherCfg->Release ();
  794. pThisQuery->pRefresherCfg = NULL;
  795. }
  796. if ((pThisQuery->pRefresher) != NULL) {
  797. hRes = pThisQuery->pRefresher->Release ();
  798. pThisQuery->pRefresher = NULL;
  799. }
  800. }
  801. return ERROR_SUCCESS;
  802. }
  803. PDH_FUNCTION
  804. PdhiCloseWbemCounter (
  805. PPDHI_COUNTER pThisCounter
  806. )
  807. {
  808. HRESULT hRes;
  809. BOOLEAN bRemoveRefresher = TRUE;
  810. if (!bProcessIsDetaching) {
  811. if (pThisCounter->pOwner->pRefresherCfg != NULL) {
  812. PPDHI_QUERY pQuery = pThisCounter->pOwner;
  813. PPDHI_COUNTER pCounter = pQuery->pCounterListHead;
  814. do {
  815. if (pCounter == NULL) {
  816. bRemoveRefresher = FALSE;
  817. }
  818. else if (pCounter != pThisCounter && pCounter->lWbemRefreshId
  819. == pThisCounter->lWbemRefreshId) {
  820. bRemoveRefresher = FALSE;
  821. }
  822. else {
  823. pCounter = pCounter->next.flink;
  824. }
  825. }
  826. while (bRemoveRefresher && pCounter != NULL
  827. && pCounter != pQuery->pCounterListHead);
  828. if (bRemoveRefresher) {
  829. hRes = pThisCounter->pOwner->pRefresherCfg->Remove(
  830. pThisCounter->lWbemRefreshId, 0L);
  831. }
  832. // assert (hRes == S_OK); the function returns a BOOL even though it's defined as an HRESULT
  833. // pThisCounter->pOwner->pRefresherCfg->Release();
  834. // pThisCounter->pOwner->pRefresherCfg = NULL;
  835. }
  836. if (pThisCounter->pWbemAccess != NULL) {
  837. pThisCounter->pWbemAccess->Release();
  838. pThisCounter->pWbemAccess = NULL;
  839. }
  840. if (pThisCounter->pWbemObject != NULL) {
  841. pThisCounter->pWbemObject->Release();
  842. pThisCounter->pWbemObject = NULL;
  843. }
  844. }
  845. return ERROR_SUCCESS;
  846. }
  847. PDH_FUNCTION
  848. PdhiBreakWbemMachineName (
  849. LPCWSTR szMachineAndNamespace,
  850. LPWSTR szMachine,
  851. LPWSTR szNamespace
  852. )
  853. /*
  854. assumes szMachine and szPath are large enough to hold the result
  855. */
  856. {
  857. LPWSTR szSrc = NULL;
  858. LPWSTR szDest = NULL;
  859. assert (szMachine != NULL);
  860. assert (szNamespace != NULL);
  861. szSrc = (LPWSTR)szMachineAndNamespace;
  862. if (szSrc == NULL) {
  863. // then use local machine and default namespace
  864. lstrcpyW (szMachine, szStaticLocalMachineName); // local machine
  865. lstrcpyW (szNamespace, cszWbemDefaultPerfRoot);
  866. return ERROR_SUCCESS;
  867. } else {
  868. // break into components
  869. if (*szSrc != NULL) {
  870. // there's a string, see if it's a machine or a namespace
  871. if ((szSrc[0] == L'\\') && (szSrc[1] == L'\\')) {
  872. szDest = szMachine;
  873. // then there's a machine name
  874. *szDest++ = *szSrc++;
  875. *szDest++ = *szSrc++;
  876. while ((*szSrc != 0) && (*szSrc != L'\\')){
  877. *szDest++ = *szSrc++;
  878. }
  879. *szDest = 0;
  880. } else {
  881. // no machine so use default
  882. // it must be just a namespace
  883. }
  884. } else {
  885. // no machine so use default
  886. }
  887. if (szDest == NULL) {
  888. // nothing found yet, so insert local machine as default
  889. szDest = szMachine;
  890. lstrcpyW (szDest, szStaticLocalMachineName);
  891. }
  892. szDest = szNamespace;
  893. if (*szSrc != 0) {
  894. // if there's a namespace then copy it
  895. szSrc++; // move past backslash
  896. while (*szSrc != 0) {
  897. *szDest++ = *szSrc++;
  898. }
  899. *szDest = 0;
  900. } else {
  901. // else return the default;
  902. lstrcpyW (szDest, cszWbemDefaultPerfRoot);
  903. }
  904. return ERROR_SUCCESS;
  905. }
  906. }
  907. PDH_FUNCTION
  908. PdhiMakeWbemInstancePath (
  909. IN PDH_COUNTER_PATH_ELEMENTS_W *pCounterPathElements,
  910. IN LPWSTR szFullPathBuffer,
  911. IN BOOL bMakeRelativePath
  912. )
  913. {
  914. WCHAR szMachine[MAX_PATH];
  915. WCHAR szNamespace[MAX_PATH];
  916. WCHAR szWbemInstance[MAX_PATH];
  917. LPWSTR szSrc, szDest;
  918. // the function assumes that the path buffer is sufficiently large
  919. // to hold the result
  920. //
  921. //
  922. // the wbem class instance path consists of one of the following formats:
  923. // for perf objects with one and only one instance (singleton classes in
  924. // WBEM parlance) the format is
  925. //
  926. // <objectname>=@
  927. //
  928. // for object with instances, the format is
  929. //
  930. // <objectname>.Name="<instancename>"
  931. //
  932. if (!bMakeRelativePath) {
  933. PdhiBreakWbemMachineName (
  934. pCounterPathElements->szMachineName,
  935. szMachine,
  936. szNamespace);
  937. lstrcpyW (szFullPathBuffer, szMachine);
  938. lstrcatW (szFullPathBuffer, cszBackSlash);
  939. lstrcatW (szFullPathBuffer, szNamespace);
  940. lstrcatW (szFullPathBuffer, cszColon);
  941. } else {
  942. *szFullPathBuffer = 0;
  943. }
  944. if (pCounterPathElements->szInstanceName == NULL) {
  945. // then apply the singleton logic
  946. lstrcatW (szFullPathBuffer, pCounterPathElements->szObjectName);
  947. lstrcatW (szFullPathBuffer, cszSingletonInstance);
  948. } else {
  949. // wbem will interpret the backslash character as an
  950. // escape char (as "C" does) so we'll have to double each
  951. // backslash in the string to make it come out OK
  952. szDest = &szWbemInstance[0];
  953. if (pCounterPathElements->szParentInstance != NULL) {
  954. szSrc = pCounterPathElements->szParentInstance;
  955. while (*szSrc != 0) {
  956. *szDest = *szSrc;
  957. if (*szSrc == BACKSLASH_L) {
  958. *++szDest = BACKSLASH_L;
  959. }
  960. szDest++;
  961. szSrc++;
  962. assert (szDest < &szWbemInstance[MAX_PATH]);
  963. }
  964. *szDest++ = '/'; // parent/child delimiter
  965. }
  966. szSrc = pCounterPathElements->szInstanceName;
  967. while (*szSrc != 0) {
  968. *szDest = *szSrc;
  969. if (*szSrc == BACKSLASH_L) {
  970. *++szDest = BACKSLASH_L;
  971. }
  972. szDest++;
  973. szSrc++;
  974. assert (szDest < &szWbemInstance[MAX_PATH]);
  975. }
  976. *szDest = 0;
  977. // apply the instance name format
  978. lstrcatW (szFullPathBuffer, pCounterPathElements->szObjectName);
  979. lstrcatW (szFullPathBuffer, cszNameParam);
  980. lstrcatW (szFullPathBuffer, szWbemInstance);
  981. lstrcatW (szFullPathBuffer, cszDoubleQuote);
  982. }
  983. return ERROR_SUCCESS;
  984. }
  985. PDH_FUNCTION
  986. PdhiWbemGetCounterPropertyName (
  987. IWbemClassObject *pThisClass,
  988. LPCWSTR szCounterDisplayName,
  989. LPWSTR szPropertyName,
  990. DWORD dwPropertyNameSize
  991. )
  992. {
  993. HRESULT hResult;
  994. PDH_STATUS pdhStatus = PDH_CSTATUS_NO_COUNTER;
  995. SAFEARRAY *psaNames = NULL;
  996. long lLower;
  997. long lUpper = 0;
  998. long lCount;
  999. BSTR bsPropName = NULL;
  1000. BSTR bsCountertype = NULL;
  1001. BSTR bsDisplayname = NULL;
  1002. VARIANT vName, vCountertype;
  1003. IWbemQualifierSet *pQualSet = NULL;
  1004. VariantInit (&vName);
  1005. VariantInit (&vCountertype);
  1006. // get the properties of this class as a Safe Array
  1007. hResult = pThisClass->GetNames (NULL,
  1008. WBEM_FLAG_NONSYSTEM_ONLY, NULL, &psaNames);
  1009. if (hResult == WBEM_NO_ERROR) {
  1010. hResult = SafeArrayGetLBound (psaNames, 1, &lLower);
  1011. if (hResult == S_OK) {
  1012. hResult = SafeArrayGetUBound (psaNames, 1, &lUpper);
  1013. }
  1014. if (hResult == S_OK) {
  1015. bsCountertype = SysAllocString (cszCountertype);
  1016. bsDisplayname = SysAllocString (cszDisplayname);
  1017. if (bsCountertype && bsDisplayname) {
  1018. for (lCount = lLower; lCount <= lUpper; lCount++) {
  1019. hResult = SafeArrayGetElement (psaNames, &lCount, &bsPropName);
  1020. if (hResult == S_OK) {
  1021. // this is the desired counter so
  1022. // get the qualifier set for this property
  1023. hResult = pThisClass->GetPropertyQualifierSet (
  1024. bsPropName, &pQualSet);
  1025. if (hResult == WBEM_NO_ERROR) {
  1026. LONG lCounterType;
  1027. // make sure this is a perf counter property
  1028. hResult = pQualSet->Get (bsCountertype, 0, &vCountertype, NULL);
  1029. if (hResult == WBEM_NO_ERROR) {
  1030. lCounterType = V_I4(&vCountertype);
  1031. // then see if this is a displayable counter
  1032. if (!(lCounterType & PERF_DISPLAY_NOSHOW) ||
  1033. (lCounterType == PERF_AVERAGE_BULK)) {
  1034. // by testing for the counter type
  1035. // get the display name for this property
  1036. hResult = pQualSet->Get (bsDisplayname, 0, &vName, NULL);
  1037. if (hResult == WBEM_NO_ERROR) {
  1038. // display name found compare it
  1039. if (lstrcmpiW(szCounterDisplayName, V_BSTR(&vName)) == 0) {
  1040. // then this is the correct property so return
  1041. if ((DWORD)lstrlenW(bsPropName) < dwPropertyNameSize) {
  1042. lstrcpyW (szPropertyName, (LPWSTR)bsPropName);
  1043. pdhStatus = ERROR_SUCCESS;
  1044. pQualSet->Release();
  1045. pQualSet = NULL;
  1046. break;
  1047. } else {
  1048. pdhStatus = PDH_MORE_DATA;
  1049. }
  1050. } else {
  1051. //not this property so continue
  1052. }
  1053. }
  1054. } else {
  1055. // this is a "don't show" counter so skip it
  1056. }
  1057. } else {
  1058. // unable to get the counter type so it's probably
  1059. // not a perf counter property, skip it and continue
  1060. }
  1061. VariantClear (&vName);
  1062. VariantClear (&vCountertype);
  1063. pQualSet->Release();
  1064. pQualSet = NULL;
  1065. } else {
  1066. // unable to read qualifiers so skip
  1067. continue;
  1068. }
  1069. } else {
  1070. // unable to read element in SafeArray
  1071. pdhStatus = PDH_WBEM_ERROR;
  1072. SetLastError(hResult);
  1073. }
  1074. } // end for each element in SafeArray
  1075. } else {
  1076. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  1077. }
  1078. PdhiSysFreeString (&bsCountertype);
  1079. PdhiSysFreeString (&bsDisplayname);
  1080. } else {
  1081. // unable to get array boundries
  1082. pdhStatus = PDH_WBEM_ERROR;
  1083. SetLastError (hResult);
  1084. }
  1085. } else {
  1086. // unable to get property strings
  1087. pdhStatus = PDH_WBEM_ERROR;
  1088. SetLastError (hResult);
  1089. }
  1090. VariantClear (&vName);
  1091. VariantClear (&vCountertype);
  1092. if (psaNames != NULL) {
  1093. // Clear the SafeArray if it exists
  1094. SafeArrayDestroy( psaNames );
  1095. }
  1096. // make sure it was released
  1097. assert (pQualSet == NULL);
  1098. return pdhStatus;
  1099. }
  1100. PDH_FUNCTION
  1101. PdhiWbemGetCounterDisplayName (
  1102. IWbemClassObject *pThisClass,
  1103. LPCWSTR szCounterName,
  1104. LPWSTR szDisplayName,
  1105. DWORD dwDisplayNameSize
  1106. )
  1107. {
  1108. HRESULT hResult;
  1109. PDH_STATUS pdhStatus = PDH_CSTATUS_NO_COUNTER;
  1110. SAFEARRAY *psaNames = NULL;
  1111. long lLower;
  1112. long lUpper = 0;
  1113. long lCount;
  1114. BSTR bsPropName = NULL;
  1115. BSTR bsCountertype = NULL;
  1116. BSTR bsDisplayname = NULL;
  1117. VARIANT vName, vCountertype;
  1118. IWbemQualifierSet *pQualSet = NULL;
  1119. VariantInit (&vName);
  1120. VariantInit (&vCountertype);
  1121. // get the properties of this class as a Safe Array
  1122. hResult = pThisClass->GetNames (NULL,
  1123. WBEM_FLAG_NONSYSTEM_ONLY, NULL, &psaNames);
  1124. if (hResult == WBEM_NO_ERROR) {
  1125. hResult = SafeArrayGetLBound (psaNames, 1, &lLower);
  1126. if (hResult == S_OK) {
  1127. hResult = SafeArrayGetUBound (psaNames, 1, &lUpper);
  1128. }
  1129. if (hResult == S_OK) {
  1130. bsCountertype = SysAllocString (cszCountertype);
  1131. bsDisplayname = SysAllocString (cszDisplayname);
  1132. if (bsCountertype && bsDisplayname) {
  1133. for (lCount = lLower; lCount <= lUpper; lCount++) {
  1134. hResult = SafeArrayGetElement (psaNames, &lCount, &bsPropName);
  1135. if (hResult == S_OK) {
  1136. if (lstrcmpiW ((LPWSTR)bsPropName, szCounterName) == 0) {
  1137. // this is the desired counter so
  1138. // get the qualifier set for this property
  1139. hResult = pThisClass->GetPropertyQualifierSet (
  1140. bsPropName, &pQualSet);
  1141. if (hResult == WBEM_NO_ERROR) {
  1142. LONG lCounterType;
  1143. // make sure this is a perf counter property
  1144. hResult = pQualSet->Get (bsCountertype, 0, &vCountertype, NULL);
  1145. if (hResult == WBEM_NO_ERROR) {
  1146. lCounterType = V_I4(&vCountertype);
  1147. // then see if this is a displayable counter
  1148. if (!(lCounterType & PERF_DISPLAY_NOSHOW) ||
  1149. (lCounterType == PERF_AVERAGE_BULK)) {
  1150. // by testing for the counter type
  1151. // get the display name for this property
  1152. hResult = pQualSet->Get (bsDisplayname, 0, &vName, NULL);
  1153. if (hResult == WBEM_NO_ERROR) {
  1154. // display name found so copy and break
  1155. if ((DWORD)lstrlenW(V_BSTR(&vName)) < dwDisplayNameSize) {
  1156. lstrcpyW (szDisplayName, V_BSTR(&vName));
  1157. pdhStatus = ERROR_SUCCESS;
  1158. pQualSet->Release();
  1159. pQualSet = NULL;
  1160. break;
  1161. } else {
  1162. pdhStatus = PDH_MORE_DATA;
  1163. }
  1164. }
  1165. } else {
  1166. // this is a "don't show" counter so skip it
  1167. }
  1168. } else {
  1169. // unable to get the counter type so it's probably
  1170. // not a perf counter property, skip it and continue
  1171. }
  1172. VariantClear (&vName);
  1173. VariantClear (&vCountertype);
  1174. pQualSet->Release();
  1175. pQualSet = NULL;
  1176. } else {
  1177. // unable to read qualifiers so skip
  1178. continue;
  1179. }
  1180. } else {
  1181. // aren't interested in this property, so
  1182. continue;
  1183. }
  1184. } else {
  1185. // unable to read element in SafeArray
  1186. pdhStatus = PDH_WBEM_ERROR;
  1187. SetLastError(hResult);
  1188. }
  1189. } // end for each element in SafeArray
  1190. } else {
  1191. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  1192. }
  1193. PdhiSysFreeString (&bsCountertype);
  1194. PdhiSysFreeString (&bsDisplayname);
  1195. } else {
  1196. // unable to get array boundries
  1197. pdhStatus = PDH_WBEM_ERROR;
  1198. SetLastError (hResult);
  1199. }
  1200. } else {
  1201. // unable to get property strings
  1202. pdhStatus = PDH_WBEM_ERROR;
  1203. SetLastError (hResult);
  1204. }
  1205. VariantClear (&vName);
  1206. VariantClear (&vCountertype);
  1207. // Clear the SafeArray if it exists
  1208. if ( NULL != psaNames )
  1209. {
  1210. SafeArrayDestroy( psaNames );
  1211. }
  1212. // make sure it was released
  1213. assert (pQualSet == NULL);
  1214. return pdhStatus;
  1215. }
  1216. PDH_FUNCTION
  1217. PdhiWbemGetClassObjectByName (
  1218. PPDHI_WBEM_SERVER_DEF pThisServer,
  1219. LPCWSTR szClassName,
  1220. IWbemClassObject **pReturnClass
  1221. )
  1222. {
  1223. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  1224. HRESULT hResult;
  1225. BSTR bsClassName;
  1226. IWbemClassObject *pThisClass = NULL;
  1227. bsClassName = SysAllocString (szClassName);
  1228. if (bsClassName) {
  1229. hResult = pThisServer->pSvc->GetObject (
  1230. bsClassName, // class name
  1231. WBEM_FLAG_USE_AMENDED_QUALIFIERS, NULL,
  1232. &pThisClass,
  1233. NULL);
  1234. PdhiSysFreeString (&bsClassName);
  1235. if (hResult != WBEM_NO_ERROR) {
  1236. pdhStatus = PDH_WBEM_ERROR;
  1237. SetLastError (hResult);
  1238. } else {
  1239. *pReturnClass = pThisClass;
  1240. }
  1241. } else {
  1242. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  1243. }
  1244. return (pdhStatus);
  1245. }
  1246. PDH_FUNCTION
  1247. PdhiWbemGetClassDisplayName (
  1248. PPDHI_WBEM_SERVER_DEF pThisServer,
  1249. LPCWSTR szClassName,
  1250. LPWSTR szClassDisplayName,
  1251. DWORD dwClassDisplayNameSize,
  1252. IWbemClassObject **pReturnClass
  1253. )
  1254. {
  1255. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  1256. HRESULT hResult;
  1257. BSTR bsClassName;
  1258. BSTR bsClass;
  1259. BSTR bsDisplayName;
  1260. VARIANT vName;
  1261. LPWSTR szDisplayName;
  1262. IWbemClassObject *pThisClass = NULL;
  1263. IWbemQualifierSet *pQualSet = NULL;
  1264. VariantInit (&vName);
  1265. bsClassName = SysAllocString (szClassName);
  1266. if (bsClassName) {
  1267. hResult = pThisServer->pSvc->GetObject (
  1268. bsClassName, // class name
  1269. WBEM_FLAG_USE_AMENDED_QUALIFIERS, NULL,
  1270. &pThisClass,
  1271. NULL);
  1272. if (hResult != WBEM_NO_ERROR) {
  1273. pdhStatus = PDH_WBEM_ERROR;
  1274. SetLastError (hResult);
  1275. }
  1276. PdhiSysFreeString (&bsClassName);
  1277. } else {
  1278. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  1279. }
  1280. if (pdhStatus == ERROR_SUCCESS) {
  1281. // get the display name property of this class
  1282. pThisClass->GetQualifierSet (&pQualSet);
  1283. if (pQualSet != NULL) {
  1284. bsDisplayName = SysAllocString (cszDisplayname);
  1285. if (bsDisplayName) {
  1286. hResult = pQualSet->Get (bsDisplayName, 0, &vName, 0);
  1287. if (hResult == WBEM_E_NOT_FOUND) {
  1288. // then this has not display name so
  1289. // pull the class name
  1290. bsClass = SysAllocString (cszClass);
  1291. if (bsClass) {
  1292. hResult = pThisClass->Get (bsClass, 0, &vName, 0, 0);
  1293. PdhiSysFreeString (&bsClass);
  1294. } else {
  1295. hResult = WBEM_E_OUT_OF_MEMORY;
  1296. }
  1297. } else {
  1298. hResult = WBEM_E_OUT_OF_MEMORY;
  1299. }
  1300. pQualSet->Release();
  1301. } else {
  1302. hResult = WBEM_E_OUT_OF_MEMORY;
  1303. }
  1304. } else {
  1305. hResult = WBEM_E_NOT_FOUND;
  1306. }
  1307. if (hResult == WBEM_E_NOT_FOUND) {
  1308. //unable to look up a display name so nothing to return
  1309. pdhStatus = PDH_WBEM_ERROR;
  1310. SetLastError (hResult);
  1311. } else if (hResult == WBEM_E_OUT_OF_MEMORY) {
  1312. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  1313. SetLastError(hResult);
  1314. } else if (hResult == S_OK) {
  1315. // copy string to caller's buffers
  1316. szDisplayName = V_BSTR(&vName);
  1317. if ((DWORD)lstrlenW(szDisplayName) < dwClassDisplayNameSize) {
  1318. lstrcpyW (szClassDisplayName, szDisplayName);
  1319. pdhStatus = ERROR_SUCCESS;
  1320. }
  1321. if (pReturnClass != NULL) {
  1322. // return the class pointer, the caller will close it
  1323. *pReturnClass = pThisClass;
  1324. } else {
  1325. // close it
  1326. pThisClass->Release();
  1327. }
  1328. }
  1329. }
  1330. VariantClear (&vName);
  1331. return pdhStatus;
  1332. }
  1333. BOOL
  1334. PdhiIsSingletonClass (
  1335. IWbemClassObject *pThisClass
  1336. )
  1337. {
  1338. HRESULT hResult;
  1339. BOOL bReturnValue = FALSE; //
  1340. BSTR bsSingleton = NULL;
  1341. VARIANT vValue;
  1342. IWbemQualifierSet *pQualSet = NULL;
  1343. bsSingleton = SysAllocString (cszSingleton);
  1344. if (bsSingleton) {
  1345. VariantInit (&vValue);
  1346. // get the display name of this class
  1347. pThisClass->GetQualifierSet (&pQualSet);
  1348. if (pQualSet != NULL) {
  1349. hResult = pQualSet->Get (bsSingleton, 0, &vValue, 0);
  1350. pQualSet->Release();
  1351. } else {
  1352. hResult = WBEM_E_NOT_FOUND;
  1353. }
  1354. if (hResult == ERROR_SUCCESS) {
  1355. bReturnValue = TRUE;
  1356. }
  1357. VariantClear (&vValue);
  1358. PdhiSysFreeString (&bsSingleton);
  1359. } else {
  1360. bReturnValue = FALSE;
  1361. }
  1362. return bReturnValue;
  1363. }
  1364. #pragma warning ( disable : 4127 )
  1365. PDH_FUNCTION
  1366. PdhiEnumWbemServerObjects(
  1367. IN PPDHI_WBEM_SERVER_DEF pThisServer,
  1368. IN LPVOID mszObjectList,
  1369. IN LPDWORD pcchBufferSize,
  1370. IN DWORD dwDetailLevel,
  1371. IN BOOL bRefresh,
  1372. IN BOOL bUnicode
  1373. );
  1374. PDH_FUNCTION
  1375. PdhiWbemGetObjectClassName (
  1376. PPDHI_WBEM_SERVER_DEF pThisServer,
  1377. LPCWSTR szObjectName,
  1378. LPWSTR szObjectClassName,
  1379. DWORD dwObjectClassNameSize,
  1380. IWbemClassObject **pReturnClass
  1381. )
  1382. {
  1383. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  1384. HRESULT hResult;
  1385. LONG lResult;
  1386. assert(pThisServer != NULL);
  1387. assert(szObjectName != NULL);
  1388. assert(szObjectClassName != NULL);
  1389. assert(dwObjectClassNameSize > 0);
  1390. if (pThisServer->pObjList == NULL) {
  1391. DWORD dwSize = 0;
  1392. pdhStatus = PdhiEnumWbemServerObjects(
  1393. pThisServer,
  1394. NULL,
  1395. & dwSize,
  1396. PERF_DETAIL_WIZARD | PERF_DETAIL_COSTLY,
  1397. TRUE,
  1398. TRUE);
  1399. if (pThisServer->pObjList != NULL) {
  1400. pdhStatus = ERROR_SUCCESS;
  1401. }
  1402. }
  1403. if (pThisServer->pObjList != NULL) {
  1404. PPDHI_WBEM_OBJECT_DEF pObject = pThisServer->pObjList;
  1405. pdhStatus = PDH_CSTATUS_NO_OBJECT;
  1406. while (pObject != NULL) {
  1407. lResult = lstrcmpiW(pObject->szDisplay, szObjectName);
  1408. if (lResult == 0) {
  1409. if ( ((DWORD) lstrlenW(pObject->szObject))
  1410. < dwObjectClassNameSize) {
  1411. pdhStatus = ERROR_SUCCESS;
  1412. lstrcpyW(szObjectClassName, pObject->szObject);
  1413. }
  1414. else {
  1415. pdhStatus = PDH_MORE_DATA;
  1416. }
  1417. if (pObject->pClass == NULL) {
  1418. BSTR bsClassName = SysAllocString(pObject->szObject);
  1419. if (bsClassName) {
  1420. hResult = pThisServer->pSvc->GetObject(
  1421. bsClassName, WBEM_FLAG_USE_AMENDED_QUALIFIERS, NULL, & pObject->pClass, NULL);
  1422. if (hResult != WBEM_NO_ERROR) {
  1423. SetLastError(hResult);
  1424. pdhStatus = PDH_WBEM_ERROR;
  1425. }
  1426. else if (pReturnClass != NULL) {
  1427. * pReturnClass = pObject->pClass;
  1428. }
  1429. }
  1430. else {
  1431. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  1432. }
  1433. }
  1434. else if (pReturnClass != NULL) {
  1435. * pReturnClass = pObject->pClass;
  1436. }
  1437. break;
  1438. }
  1439. pObject = pObject->pNext;
  1440. }
  1441. }
  1442. return pdhStatus;
  1443. }
  1444. #pragma warning ( default : 4127 )
  1445. PDH_FUNCTION
  1446. PdhiAddWbemServer (
  1447. LPCWSTR szMachineName,
  1448. PPDHI_WBEM_SERVER_DEF *pWbemServer
  1449. )
  1450. {
  1451. IWbemLocator *pWbemLocator = 0;
  1452. IWbemServices *pWbemServices = 0;
  1453. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  1454. HRESULT hResult;
  1455. DWORD dwResult;
  1456. DWORD dwStrLen = 0;
  1457. PPDHI_WBEM_SERVER_DEF pNewServer = NULL;
  1458. WCHAR szLocalMachineName[MAX_PATH];
  1459. WCHAR szLocalServerPath[MAX_PATH];
  1460. WCHAR szLocalNameSpaceString[MAX_PATH];
  1461. WCHAR szLocale[32];
  1462. // szMachineName can be null,
  1463. // that means use the local machine and default namespace
  1464. assert (pWbemServer != NULL);
  1465. // connect to locator
  1466. dwResult = CoCreateInstance (CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER,
  1467. IID_IWbemLocator, (LPVOID *)&pWbemLocator);
  1468. if (dwResult != S_OK) {
  1469. SetLastError (dwResult);
  1470. pdhStatus = PDH_CANNOT_CONNECT_MACHINE;
  1471. }
  1472. if (pdhStatus == ERROR_SUCCESS) {
  1473. PdhiBreakWbemMachineName (
  1474. szMachineName,
  1475. szLocalMachineName,
  1476. szLocalNameSpaceString);
  1477. lstrcpyW (szLocalServerPath, szLocalMachineName);
  1478. lstrcatW (szLocalServerPath, szLocalNameSpaceString);
  1479. // Create the locale
  1480. swprintf( szLocale, L"MS_%hX", GetUserDefaultUILanguage());
  1481. // try to connect to the service
  1482. hResult = pWbemLocator->ConnectServer (
  1483. szLocalServerPath,
  1484. NULL, NULL, szLocale,
  1485. 0L,
  1486. 0,0,
  1487. &pWbemServices);
  1488. if (hResult) {
  1489. SetLastError (hResult);
  1490. pdhStatus = PDH_CANNOT_CONNECT_WMI_SERVER;
  1491. } else {
  1492. dwStrLen = lstrlenW (szLocalMachineName ) + 1;
  1493. }
  1494. // free the locator
  1495. pWbemLocator->Release();
  1496. }
  1497. // If we succeeded, we need to set Interface Security on the proxy and its
  1498. // IUnknown in order for Impersonation to correctly work.
  1499. if ( pdhStatus == ERROR_SUCCESS )
  1500. {
  1501. pdhStatus = SetWbemSecurity( pWbemServices );
  1502. }
  1503. if (pdhStatus == ERROR_SUCCESS) {
  1504. // everything went ok so save this connection
  1505. if (*pWbemServer == NULL) {
  1506. // then this is a new connection
  1507. pNewServer = (PPDHI_WBEM_SERVER_DEF)G_ALLOC (sizeof (PDHI_WBEM_SERVER_DEF) + (dwStrLen * sizeof (WCHAR)));
  1508. if (pNewServer == NULL) {
  1509. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  1510. } else {
  1511. // insert this at the head of the list
  1512. pNewServer->pNext = pFirstWbemServer;
  1513. pFirstWbemServer = pNewServer;
  1514. pNewServer->szMachine = (LPWSTR)&pNewServer[1];
  1515. lstrcpyW (pNewServer->szMachine, szLocalMachineName);
  1516. pNewServer->lRefCount = 0; // it'll be incremented in the connect function
  1517. *pWbemServer = pNewServer;
  1518. }
  1519. } else {
  1520. // we are reconnecting and reusing an old memory block
  1521. // so just update the pointer
  1522. pNewServer = *pWbemServer;
  1523. }
  1524. // if reconnecting or connecting for the first time, this should be NULL
  1525. assert (pNewServer->pSvc == NULL);
  1526. if (pdhStatus == ERROR_SUCCESS) {
  1527. // update fields
  1528. // load the name fields
  1529. pNewServer->pSvc = pWbemServices;
  1530. pNewServer->pObjList = NULL;
  1531. pNewServer->dwCache = 0;
  1532. if (gp_GIT != NULL) {
  1533. HRESULT hrTmp = gp_GIT->RegisterInterfaceInGlobal(
  1534. pWbemServices,
  1535. IID_IWbemServices,
  1536. & (pNewServer->dwCache));
  1537. DebugPrint((3,"RegisterInterfaceInGlobal(0x%08X,0x%08X,%d)\n",
  1538. hrTmp, pNewServer->pSvc, pNewServer->dwCache));
  1539. if (! SUCCEEDED(hrTmp)) {
  1540. pWbemServices->Release();
  1541. pNewServer->pSvc = NULL;
  1542. pNewServer->dwCache = 0;
  1543. pdhStatus = PDH_WBEM_ERROR;
  1544. }
  1545. }
  1546. else {
  1547. pWbemServices->Release();
  1548. pNewServer->pSvc = NULL;
  1549. pNewServer->dwCache = 0;
  1550. pdhStatus = PDH_WBEM_ERROR;
  1551. }
  1552. } else {
  1553. // something failed so return a NULL for the server pointer
  1554. *pWbemServer = NULL;
  1555. }
  1556. } else {
  1557. // unable to connect so return NULL
  1558. *pWbemServer = NULL;
  1559. }
  1560. // if there was an eror, then free the new sever memory
  1561. if ((* pWbemServer) == NULL) G_FREE(pNewServer);
  1562. return pdhStatus;
  1563. }
  1564. PDH_FUNCTION
  1565. PdhiCloseWbemServer (
  1566. PPDHI_WBEM_SERVER_DEF pWbemServer
  1567. )
  1568. {
  1569. assert (pWbemServer != NULL);
  1570. if (!bProcessIsDetaching) {
  1571. if (pWbemServer != NULL) {
  1572. if (pWbemServer->pObjList != NULL) {
  1573. PPDHI_WBEM_OBJECT_DEF pObject = pWbemServer->pObjList;
  1574. PPDHI_WBEM_OBJECT_DEF pNext;
  1575. pWbemServer->pObjList = NULL;
  1576. while (pObject != NULL) {
  1577. pNext = pObject->pNext;
  1578. if (pObject->pClass != NULL) pObject->pClass->Release();
  1579. G_FREE(pObject);
  1580. pObject = pNext;
  1581. }
  1582. }
  1583. if (pWbemServer->pSvc != NULL) {
  1584. // this is about all that's currently required
  1585. pWbemServer->pSvc->Release();
  1586. pWbemServer->pSvc = NULL;
  1587. } else {
  1588. // no server is connected
  1589. }
  1590. } else {
  1591. // no structure exists
  1592. }
  1593. }
  1594. return ERROR_SUCCESS;
  1595. }
  1596. PDH_FUNCTION
  1597. PdhiConnectWbemServer (
  1598. LPCWSTR szMachineName,
  1599. PPDHI_WBEM_SERVER_DEF *pWbemServer
  1600. )
  1601. {
  1602. PDH_STATUS pdhStatus = PDH_CANNOT_CONNECT_MACHINE;
  1603. PPDHI_WBEM_SERVER_DEF pThisServer = NULL;
  1604. LPWSTR szWideMachineName = NULL;
  1605. LPWSTR szWideNamespace = NULL;
  1606. LPWSTR szMachineNameArg = NULL;
  1607. // get the local machine name & default name space if the caller
  1608. // has passed in a NULL machine name
  1609. if (szMachineName == NULL) {
  1610. szWideMachineName = (LPWSTR) G_ALLOC (2048 + 1024); // this should be long enough
  1611. if (szWideMachineName == NULL) {
  1612. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  1613. } else {
  1614. szWideNamespace = (LPWSTR)((LPBYTE)szWideMachineName + 2048);
  1615. }
  1616. if (pdhStatus != PDH_MEMORY_ALLOCATION_FAILURE) {
  1617. pdhStatus = PdhiBreakWbemMachineName (
  1618. NULL,
  1619. szWideMachineName,
  1620. szWideNamespace);
  1621. // lstrcatW (szWideMachineName, cszBackSlash);
  1622. // lstrcatW (szWideMachineName, szWideNamespace);
  1623. szMachineNameArg = szWideMachineName;
  1624. }
  1625. } else {
  1626. szMachineNameArg = (LPWSTR)szMachineName;
  1627. pdhStatus = ERROR_SUCCESS;
  1628. }
  1629. if (pdhStatus == ERROR_SUCCESS) {
  1630. // walk down list of connected servers and find the requested one
  1631. assert (pWbemServer != NULL);
  1632. for (pThisServer = pFirstWbemServer;
  1633. pThisServer != NULL;
  1634. pThisServer = pThisServer->pNext) {
  1635. // machine name includes the namespace
  1636. if (lstrcmpiW(pThisServer->szMachine, szMachineNameArg) == 0) {
  1637. pdhStatus = ERROR_SUCCESS;
  1638. break;
  1639. }
  1640. }
  1641. if (pThisServer == NULL) {
  1642. // then add it to the list and return it
  1643. pdhStatus = PdhiAddWbemServer (
  1644. szMachineNameArg,
  1645. &pThisServer);
  1646. } else {
  1647. // make sure the server is really there
  1648. // this is just a dummy call to see if the server will respond
  1649. // with an error or RPC will respond with an error that there's
  1650. // no server anymore.
  1651. HRESULT hrTest;
  1652. if (gp_GIT != NULL) {
  1653. IWbemServices * pSvc = NULL;
  1654. hrTest = gp_GIT->GetInterfaceFromGlobal(
  1655. pThisServer->dwCache,
  1656. IID_IWbemServices,
  1657. (void **) & pSvc);
  1658. if (SUCCEEDED(hrTest)) {
  1659. if (pSvc != pThisServer->pSvc) {
  1660. DebugPrint((3,"GetInterfaceFromGlobal(0x%08X,%d,0x%08X,0x%08X)\n",
  1661. hrTest, pThisServer->dwCache, pThisServer->pSvc, pSvc));
  1662. pThisServer->pSvc = NULL;
  1663. if (pThisServer->pObjList != NULL) {
  1664. PPDHI_WBEM_OBJECT_DEF pObject;
  1665. PPDHI_WBEM_OBJECT_DEF pNext;
  1666. pObject = pThisServer->pObjList;
  1667. pThisServer->pObjList = NULL;
  1668. while (pObject != NULL) {
  1669. pNext = pObject->pNext;
  1670. G_FREE(pObject);
  1671. pObject = pNext;
  1672. }
  1673. }
  1674. }
  1675. }
  1676. else {
  1677. DebugPrint((3,"GetInterfaceFromGlobal(0x%08X,%d,0x%08X,0x%08X)\n",
  1678. hrTest, pThisServer->dwCache, pThisServer->pSvc, pSvc));
  1679. pThisServer->pSvc = NULL;
  1680. if (pThisServer->pObjList != NULL) {
  1681. PPDHI_WBEM_OBJECT_DEF pObject;
  1682. PPDHI_WBEM_OBJECT_DEF pNext;
  1683. pObject = pThisServer->pObjList;
  1684. pThisServer->pObjList = NULL;
  1685. while (pObject != NULL) {
  1686. pNext = pObject->pNext;
  1687. G_FREE(pObject);
  1688. pObject = pNext;
  1689. }
  1690. }
  1691. }
  1692. }
  1693. else {
  1694. pThisServer->pSvc = NULL;
  1695. if (pThisServer->pObjList != NULL) {
  1696. PPDHI_WBEM_OBJECT_DEF pObject;
  1697. PPDHI_WBEM_OBJECT_DEF pNext;
  1698. pObject = pThisServer->pObjList;
  1699. pThisServer->pObjList = NULL;
  1700. while (pObject != NULL) {
  1701. pNext = pObject->pNext;
  1702. G_FREE(pObject);
  1703. pObject = pNext;
  1704. }
  1705. }
  1706. }
  1707. if (pThisServer->pSvc != NULL) {
  1708. hrTest = pThisServer->pSvc->CancelAsyncCall(NULL);
  1709. } else {
  1710. // there is no service connected so set the HRESULT to
  1711. // get the next block to try and reconnect
  1712. hrTest = 0x800706BF; // some bad status value thats NOT WBEM_E_INVALID_PARAMETER
  1713. }
  1714. // if the error is WBEM_E_INVALID_PARAMETER then the server is there
  1715. // so we can continue
  1716. // else if the error is something else then try to reconnect by closing and
  1717. // reopening this connection
  1718. if (hrTest != WBEM_E_INVALID_PARAMETER) {
  1719. PdhiCloseWbemServer(pThisServer);
  1720. pdhStatus = PdhiAddWbemServer (
  1721. szMachineNameArg,
  1722. &pThisServer);
  1723. }
  1724. }
  1725. *pWbemServer = pThisServer;
  1726. if (pdhStatus == ERROR_SUCCESS) pThisServer->lRefCount++;
  1727. }
  1728. if (szWideMachineName != NULL) G_FREE (szWideMachineName);
  1729. return pdhStatus;
  1730. }
  1731. PDH_FUNCTION
  1732. PdhiFreeAllWbemServers (
  1733. )
  1734. {
  1735. PPDHI_WBEM_SERVER_DEF pThisServer;
  1736. PPDHI_WBEM_SERVER_DEF pNextServer;
  1737. pThisServer = pFirstWbemServer;
  1738. while (pThisServer != NULL) {
  1739. pNextServer = pThisServer->pNext;
  1740. PdhiCloseWbemServer (pThisServer);
  1741. G_FREE(pThisServer);
  1742. pThisServer = pNextServer;
  1743. }
  1744. pFirstWbemServer = NULL;
  1745. if (gp_GIT != NULL) {
  1746. gp_GIT->Release();
  1747. gp_GIT = NULL;
  1748. }
  1749. return ERROR_SUCCESS;
  1750. }
  1751. PDH_FUNCTION
  1752. PdhiGetWbemExplainText (
  1753. IN LPCWSTR szMachineName,
  1754. IN LPCWSTR szObjectName,
  1755. IN LPCWSTR szCounterName,
  1756. IN LPWSTR szExplain,
  1757. IN LPDWORD pdwExplain
  1758. )
  1759. {
  1760. PDH_STATUS Status = ERROR_SUCCESS;
  1761. HRESULT hResult;
  1762. BOOL bDisconnect = FALSE;
  1763. VARIANT vsExplain;
  1764. WCHAR szObjectClassName[MAX_PATH];
  1765. PPDHI_WBEM_SERVER_DEF pThisServer = NULL;
  1766. IEnumWbemClassObject * pEnum = NULL;
  1767. IWbemClassObject * pThisObject = NULL;
  1768. IWbemQualifierSet * pQualSet = NULL;
  1769. BOOL fCoInitialized = PdhiCoInitialize();
  1770. if (szMachineName == NULL || szObjectName == NULL) {
  1771. Status = PDH_INVALID_ARGUMENT;
  1772. }
  1773. if (szExplain != NULL && * pdwExplain != 0) {
  1774. ZeroMemory(szExplain, * pdwExplain);
  1775. }
  1776. if (Status == ERROR_SUCCESS) {
  1777. Status = PdhiConnectWbemServer(szMachineName, &pThisServer);
  1778. }
  1779. if (Status == ERROR_SUCCESS) {
  1780. bDisconnect = TRUE;
  1781. Status = PdhiWbemGetObjectClassName(
  1782. pThisServer,
  1783. szObjectName,
  1784. szObjectClassName,
  1785. MAX_PATH,
  1786. & pThisObject);
  1787. }
  1788. if (Status == ERROR_SUCCESS) {
  1789. VariantInit(& vsExplain);
  1790. if (szCounterName != NULL) {
  1791. SAFEARRAY * psaNames = NULL;
  1792. LONG lLower = 0;
  1793. LONG lUpper = 0;
  1794. LONG lCount = 0;
  1795. BSTR bsPropName = NULL;
  1796. VARIANT vName;
  1797. VARIANT vCountertype;
  1798. LONG lCounterType;
  1799. VariantInit (& vName);
  1800. VariantInit (& vCountertype);
  1801. hResult = pThisObject->GetNames(
  1802. NULL,
  1803. WBEM_FLAG_NONSYSTEM_ONLY,
  1804. NULL,
  1805. & psaNames);
  1806. if (hResult == WBEM_NO_ERROR) {
  1807. hResult = SafeArrayGetLBound(psaNames, 1, & lLower);
  1808. if (hResult == S_OK) {
  1809. hResult = SafeArrayGetUBound(psaNames, 1, & lUpper);
  1810. }
  1811. if (hResult == S_OK) {
  1812. for (lCount = lLower; lCount <= lUpper; lCount++) {
  1813. hResult = SafeArrayGetElement(
  1814. psaNames,
  1815. & lCount,
  1816. & bsPropName);
  1817. if (hResult == S_OK) {
  1818. hResult = pThisObject->GetPropertyQualifierSet(
  1819. bsPropName,
  1820. & pQualSet);
  1821. if (hResult == S_OK) {
  1822. hResult = pQualSet->Get(
  1823. cszCountertype,
  1824. 0,
  1825. & vCountertype,
  1826. NULL);
  1827. if (hResult == S_OK) {
  1828. lCounterType = V_I4(& vCountertype);
  1829. if ( ! (lCounterType & PERF_DISPLAY_NOSHOW)
  1830. || (lCounterType == PERF_AVERAGE_BULK)) {
  1831. hResult = pQualSet->Get(
  1832. cszDisplayname,
  1833. 0,
  1834. & vName,
  1835. NULL);
  1836. if ( hResult == S_OK
  1837. && vName.vt == VT_BSTR) {
  1838. if (lstrcmpiW(szCounterName,
  1839. V_BSTR(& vName)) == 0) {
  1840. hResult = pQualSet->Get(
  1841. cszExplainText,
  1842. 0,
  1843. & vsExplain,
  1844. NULL);
  1845. if ( hResult == S_OK
  1846. && vsExplain.vt == VT_BSTR) {
  1847. LPWSTR szResult = V_BSTR(& vsExplain);
  1848. if (((DWORD) lstrlenW(szResult)) < (* pdwExplain)) {
  1849. lstrcpyW(szExplain, szResult);
  1850. Status = ERROR_SUCCESS;
  1851. }
  1852. else {
  1853. * pdwExplain = (DWORD) lstrlenW(szResult);
  1854. Status = PDH_MORE_DATA;
  1855. }
  1856. }
  1857. pQualSet->Release();
  1858. break;
  1859. }
  1860. }
  1861. }
  1862. }
  1863. pQualSet->Release();
  1864. }
  1865. }
  1866. else {
  1867. SetLastError(hResult);
  1868. Status = PDH_WBEM_ERROR;
  1869. }
  1870. }
  1871. }
  1872. else {
  1873. SetLastError(hResult);
  1874. Status = PDH_WBEM_ERROR;
  1875. }
  1876. }
  1877. else {
  1878. SetLastError(hResult);
  1879. Status = PDH_WBEM_ERROR;
  1880. }
  1881. VariantClear(& vName);
  1882. VariantClear(& vCountertype);
  1883. }
  1884. else {
  1885. // get counter object explain text
  1886. //
  1887. pThisObject->GetQualifierSet(& pQualSet);
  1888. if (pQualSet != NULL) {
  1889. hResult = pQualSet->Get(cszExplainText, 0, & vsExplain, 0);
  1890. if (hResult == S_OK) {
  1891. LPWSTR szResult = V_BSTR(& vsExplain);
  1892. if (((DWORD) lstrlenW(szResult)) < (* pdwExplain)) {
  1893. lstrcpyW(szExplain, szResult);
  1894. Status = ERROR_SUCCESS;
  1895. }
  1896. else {
  1897. * pdwExplain = (DWORD) lstrlenW(szResult);
  1898. Status = PDH_MORE_DATA;
  1899. }
  1900. }
  1901. else {
  1902. SetLastError(hResult);
  1903. Status = PDH_WBEM_ERROR;
  1904. }
  1905. pQualSet->Release();
  1906. }
  1907. else {
  1908. SetLastError(WBEM_E_NOT_FOUND);
  1909. Status = PDH_WBEM_ERROR;
  1910. }
  1911. }
  1912. //pThisObject->Release();
  1913. VariantClear(& vsExplain);
  1914. }
  1915. if (bDisconnect) {
  1916. if (Status == ERROR_SUCCESS) {
  1917. Status = PdhiDisconnectWbemServer(pThisServer);
  1918. }
  1919. else {
  1920. PdhiDisconnectWbemServer(pThisServer);
  1921. }
  1922. }
  1923. if ( fCoInitialized )
  1924. {
  1925. PdhiCoUninitialize();
  1926. }
  1927. return Status;
  1928. }
  1929. PDH_FUNCTION
  1930. PdhiEnumWbemMachines (
  1931. IN LPVOID pMachineList,
  1932. IN LPDWORD pcchBufferSize,
  1933. IN BOOL bUnicode
  1934. )
  1935. {
  1936. PDH_STATUS pdhStatus;
  1937. PPDHI_WBEM_SERVER_DEF pThisServer = NULL;
  1938. DWORD dwCharsLeftInBuffer = *pcchBufferSize;
  1939. DWORD dwBufferSize = 0;
  1940. DWORD dwStrLen;
  1941. DWORD dwResult;
  1942. assert (pcchBufferSize != NULL);
  1943. // CoInitialize() if we need to
  1944. BOOL fCoInitialized = PdhiCoInitialize();
  1945. // test to see if we've connected to the local machine yet, if not then do it
  1946. if (pFirstWbemServer == NULL) {
  1947. // add local machine
  1948. pdhStatus = PdhiAddWbemServer (
  1949. NULL,
  1950. &pThisServer);
  1951. }
  1952. // walk down list of known machines and find the machines that are using
  1953. // the specified name space.
  1954. pThisServer = pFirstWbemServer;
  1955. while (pThisServer != NULL) {
  1956. dwStrLen = lstrlenW (pThisServer->szMachine) + 1;
  1957. if ((pMachineList != NULL) && (dwCharsLeftInBuffer > dwStrLen)) {
  1958. // then it will fit so add it
  1959. dwResult = AddUniqueWideStringToMultiSz (
  1960. pMachineList, pThisServer->szMachine, bUnicode);
  1961. if (dwResult > 0) {
  1962. dwBufferSize = dwResult;
  1963. dwCharsLeftInBuffer = *pcchBufferSize - dwBufferSize;
  1964. } // else
  1965. // this string is already in the list so
  1966. // nothing was added
  1967. } else {
  1968. // just add the string length to estimate the buffer size
  1969. // required
  1970. dwCharsLeftInBuffer = 0; // to prevent any other strings from being added
  1971. dwBufferSize += dwStrLen;
  1972. }
  1973. pThisServer = pThisServer->pNext;
  1974. }// end of while loop
  1975. if (dwBufferSize <= *pcchBufferSize) {
  1976. // the buffer size includes both term nulls
  1977. pdhStatus = ERROR_SUCCESS;
  1978. } else {
  1979. // add terminating MSZ Null char size
  1980. dwBufferSize++;
  1981. // there wasn't enough room. See if a buffer was passed in
  1982. pdhStatus = PDH_MORE_DATA;
  1983. }
  1984. // return the size used or required
  1985. *pcchBufferSize = dwBufferSize;
  1986. // CoUninitialize if necessary
  1987. if ( fCoInitialized )
  1988. {
  1989. PdhiCoUninitialize();
  1990. }
  1991. return pdhStatus;
  1992. }
  1993. #pragma warning ( disable : 4127 )
  1994. PDH_FUNCTION
  1995. PdhiEnumWbemServerObjects(
  1996. IN PPDHI_WBEM_SERVER_DEF pThisServer,
  1997. IN LPVOID mszObjectList,
  1998. IN LPDWORD pcchBufferSize,
  1999. IN DWORD dwDetailLevel,
  2000. IN BOOL bRefresh, // ignored
  2001. IN BOOL bUnicode)
  2002. {
  2003. // this function enumerates the classes that are subclassed
  2004. // from the Win32_PerfRawData Superclass
  2005. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  2006. HRESULT hResult;
  2007. DWORD dwCharsLeftInBuffer = *pcchBufferSize;
  2008. DWORD dwBufferSize = 0;
  2009. DWORD dwStrLen;
  2010. DWORD dwRtnCount;
  2011. DWORD dwResult;
  2012. DWORD dwDetailLevelDesired;
  2013. DWORD dwItemDetailLevel = 0;
  2014. LPWSTR szClassName;
  2015. VARIANT vName;
  2016. VARIANT vClass;
  2017. VARIANT vDetailLevel;
  2018. BOOL bPerfDefault = FALSE;
  2019. BSTR bsTemp = NULL;
  2020. BSTR bsDisplayName = NULL;
  2021. BSTR bsClass = NULL;
  2022. BSTR bsCostly = NULL;
  2023. BSTR bsDetailLevel = NULL;
  2024. BSTR bsPerfDefault = NULL;
  2025. BOOL bGetCostlyItems = FALSE;
  2026. BOOL bIsCostlyItem = FALSE;
  2027. BOOL bDisconnectServer = FALSE;
  2028. IEnumWbemClassObject * pEnum = NULL;
  2029. IWbemClassObject * pThisClass = NULL;
  2030. IWbemQualifierSet * pQualSet = NULL;
  2031. PPDHI_WBEM_OBJECT_DEF pHead = NULL;
  2032. PPDHI_WBEM_OBJECT_DEF pObject = NULL;
  2033. DBG_UNREFERENCED_PARAMETER(bRefresh);
  2034. VariantInit(& vName);
  2035. VariantInit(& vClass);
  2036. VariantInit(& vDetailLevel);
  2037. if (pThisServer->pObjList != NULL) {
  2038. PPDHI_WBEM_OBJECT_DEF pObject = pThisServer->pObjList;
  2039. PPDHI_WBEM_OBJECT_DEF pNext;
  2040. pThisServer->pObjList = NULL;
  2041. while (pObject != NULL) {
  2042. pNext = pObject->pNext;
  2043. if (pObject->pClass != NULL) pObject->pClass->Release();
  2044. G_FREE(pObject);
  2045. pObject = pNext;
  2046. }
  2047. }
  2048. // create an enumerator of the PerfRawData class
  2049. bsTemp = SysAllocString (cszPerfRawData);
  2050. if (bsTemp) {
  2051. hResult = pThisServer->pSvc->CreateClassEnum (
  2052. bsTemp,
  2053. WBEM_FLAG_DEEP | WBEM_FLAG_USE_AMENDED_QUALIFIERS,
  2054. NULL,
  2055. & pEnum);
  2056. PdhiSysFreeString(&bsTemp);
  2057. bDisconnectServer = TRUE;
  2058. // Set security on the proxy
  2059. if (SUCCEEDED(hResult))
  2060. {
  2061. hResult = SetWbemSecurity(pEnum);
  2062. }
  2063. if (hResult != WBEM_NO_ERROR) {
  2064. pdhStatus = PDH_WBEM_ERROR;
  2065. SetLastError (hResult);
  2066. }
  2067. } else {
  2068. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  2069. }
  2070. if (pdhStatus == ERROR_SUCCESS) {
  2071. // set costly flag
  2072. bGetCostlyItems = ((dwDetailLevel & PERF_DETAIL_COSTLY) == PERF_DETAIL_COSTLY);
  2073. dwDetailLevelDesired = (DWORD)(dwDetailLevel & PERF_DETAIL_STANDARD);
  2074. bsCostly = SysAllocString (cszCostly);
  2075. bsDisplayName = SysAllocString (cszDisplayname);
  2076. bsClass = SysAllocString (cszClass);
  2077. bsDetailLevel = SysAllocString (cszPerfdetail);
  2078. bsPerfDefault = SysAllocString(cszPerfdefault);
  2079. if (bsCostly && bsDisplayName && bsClass && bsDetailLevel) {
  2080. while (TRUE) {
  2081. hResult = pEnum->Next (
  2082. WBEM_INFINITE, // timeout
  2083. 1, // return only 1 object
  2084. &pThisClass,
  2085. &dwRtnCount);
  2086. // no more classes
  2087. if ((pThisClass == NULL) || (dwRtnCount == 0)) break;
  2088. // get the display name of this class
  2089. bIsCostlyItem = FALSE; // assume it's not unless proven otherwise
  2090. bPerfDefault = FALSE;
  2091. hResult = pThisClass->Get(bsClass, 0, & vClass, 0, 0);
  2092. pThisClass->GetQualifierSet (&pQualSet);
  2093. if (pQualSet != NULL) {
  2094. VariantClear (&vName);
  2095. hResult = pQualSet->Get (bsCostly, 0, &vName, 0);
  2096. if (hResult == S_OK) {
  2097. bIsCostlyItem = TRUE;
  2098. }
  2099. hResult = pQualSet->Get (bsDetailLevel, 0, &vDetailLevel, 0);
  2100. if (hResult == S_OK) {
  2101. dwItemDetailLevel = (DWORD)V_I4(&vDetailLevel);
  2102. } else {
  2103. dwItemDetailLevel = 0;
  2104. }
  2105. VariantClear(&vName);
  2106. hResult = pQualSet->Get(bsPerfDefault, 0, & vName, 0);
  2107. if (hResult != WBEM_E_NOT_FOUND) {
  2108. bPerfDefault = (BOOL) V_BOOL(& vName);
  2109. }
  2110. VariantClear(&vName);
  2111. hResult = pQualSet->Get(bsDisplayName, 0, & vName, 0);
  2112. pQualSet->Release();
  2113. } else {
  2114. hResult = WBEM_E_NOT_FOUND;
  2115. }
  2116. if (hResult == WBEM_E_NOT_FOUND) {
  2117. // then this has not display name so
  2118. // pull the class name
  2119. hResult = pThisClass->Get(bsClass, 0, & vName, 0, 0);
  2120. }
  2121. if (hResult == WBEM_E_NOT_FOUND) {
  2122. szClassName = (LPWSTR) cszNotFound;
  2123. } else {
  2124. szClassName = (LPWSTR) V_BSTR(&vName);
  2125. }
  2126. if (((bIsCostlyItem && bGetCostlyItems) || // if costly and we want them
  2127. (!bIsCostlyItem)) && (dwItemDetailLevel <= dwDetailLevelDesired)) {
  2128. dwStrLen = lstrlenW (szClassName) + 1;
  2129. if ((mszObjectList != NULL) && (dwCharsLeftInBuffer > dwStrLen)) {
  2130. // then it will fit so add it
  2131. dwResult = AddUniqueWideStringToMultiSz (
  2132. mszObjectList, szClassName, bUnicode);
  2133. if (dwResult > 0) {
  2134. dwBufferSize = dwResult;
  2135. dwCharsLeftInBuffer = *pcchBufferSize - dwBufferSize;
  2136. } // else
  2137. } else {
  2138. // just add the string length to estimate the buffer size
  2139. // required
  2140. dwCharsLeftInBuffer = 0; // to prevent any other strings from being added
  2141. dwBufferSize += dwStrLen;
  2142. }
  2143. }
  2144. if (lstrcmpiW(szClassName, cszNotFound) != 0) {
  2145. LPWSTR szClass = (LPWSTR) V_BSTR(& vClass);
  2146. DWORD dwSize = sizeof(PDHI_WBEM_OBJECT_DEF)
  2147. + sizeof(WCHAR) * ( lstrlenW(szClassName)
  2148. + lstrlenW(szClass) + 2);
  2149. pObject = (PPDHI_WBEM_OBJECT_DEF) G_ALLOC(dwSize);
  2150. if (pObject != NULL) {
  2151. pObject->bDefault = bPerfDefault;
  2152. pObject->szObject = (LPWSTR) (((LPBYTE) pObject)
  2153. + sizeof(PDHI_WBEM_OBJECT_DEF));
  2154. lstrcpyW(pObject->szObject, szClass);
  2155. pObject->szDisplay = (LPWSTR) (((LPBYTE) pObject)
  2156. + sizeof(PDHI_WBEM_OBJECT_DEF)
  2157. + sizeof(WCHAR) * (lstrlenW(szClass) + 1));
  2158. lstrcpyW(pObject->szDisplay, szClassName);
  2159. pObject->pNext = pHead;
  2160. pHead = pObject;
  2161. }
  2162. else {
  2163. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  2164. pThisClass->Release();
  2165. break;
  2166. }
  2167. }
  2168. // clear the variant
  2169. VariantClear(& vName);
  2170. VariantClear(& vClass);
  2171. VariantClear(& vDetailLevel);
  2172. // free this class
  2173. pThisClass->Release();
  2174. }
  2175. dwBufferSize ++; // the final NULL
  2176. if (dwBufferSize <= *pcchBufferSize) {
  2177. pdhStatus = ERROR_SUCCESS;
  2178. } else {
  2179. // there wasn't enough room. See if a buffer was passed in
  2180. pdhStatus = PDH_MORE_DATA;
  2181. }
  2182. // return the size used or required
  2183. *pcchBufferSize = dwBufferSize;
  2184. }
  2185. } else {
  2186. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  2187. }
  2188. PdhiSysFreeString(& bsDisplayName);
  2189. PdhiSysFreeString(& bsClass);
  2190. PdhiSysFreeString(& bsCostly);
  2191. PdhiSysFreeString(& bsDetailLevel);
  2192. PdhiSysFreeString(& bsPerfDefault);
  2193. VariantClear(& vName);
  2194. VariantClear(& vClass);
  2195. VariantClear(& vDetailLevel);
  2196. if (pEnum != NULL) pEnum->Release();
  2197. if (pdhStatus == ERROR_SUCCESS || pdhStatus == PDH_MORE_DATA) {
  2198. pThisServer->pObjList = pHead;
  2199. }
  2200. else {
  2201. pObject = pHead;
  2202. while (pObject != NULL) {
  2203. pHead = pObject->pNext;
  2204. G_FREE(pObject);
  2205. pObject = pHead;
  2206. }
  2207. }
  2208. if (bDisconnectServer) {
  2209. if (pdhStatus == ERROR_SUCCESS) {
  2210. pdhStatus = PdhiDisconnectWbemServer (pThisServer);
  2211. } else {
  2212. // keep error code from function body
  2213. PdhiDisconnectWbemServer (pThisServer);
  2214. }
  2215. }
  2216. return pdhStatus;
  2217. }
  2218. PDH_FUNCTION
  2219. PdhiEnumWbemObjects(
  2220. IN LPCWSTR szWideMachineName,
  2221. IN LPVOID mszObjectList,
  2222. IN LPDWORD pcchBufferSize,
  2223. IN DWORD dwDetailLevel,
  2224. IN BOOL bRefresh, // ignored
  2225. IN BOOL bUnicode)
  2226. {
  2227. PDH_STATUS pdhStatus;
  2228. PPDHI_WBEM_SERVER_DEF pThisServer;
  2229. BOOL fCoInitialized = PdhiCoInitialize();
  2230. pdhStatus = PdhiConnectWbemServer(szWideMachineName, & pThisServer);
  2231. if (pdhStatus == ERROR_SUCCESS) {
  2232. pdhStatus = PdhiEnumWbemServerObjects(pThisServer,
  2233. mszObjectList,
  2234. pcchBufferSize,
  2235. dwDetailLevel,
  2236. bRefresh,
  2237. bUnicode);
  2238. }
  2239. if (fCoInitialized) {
  2240. PdhiCoUninitialize();
  2241. }
  2242. return pdhStatus;
  2243. }
  2244. PDH_FUNCTION
  2245. PdhiGetDefaultWbemObject (
  2246. IN LPCWSTR szMachineName,
  2247. IN LPVOID szDefaultObjectName,
  2248. IN LPDWORD pcchBufferSize,
  2249. IN BOOL bUnicode)
  2250. {
  2251. // walk down the list of WBEM perf classes and find the one with the
  2252. // default qualifier
  2253. PDH_STATUS pdhStatus;
  2254. PPDHI_WBEM_SERVER_DEF pThisServer;
  2255. HRESULT hResult;
  2256. DWORD dwBufferSize = 0;
  2257. DWORD dwStrLen;
  2258. BOOL bDisconnectServer = FALSE;
  2259. // CoInitialize() if we need to
  2260. BOOL fCoInitialized = PdhiCoInitialize();
  2261. pdhStatus = PdhiConnectWbemServer (
  2262. szMachineName,
  2263. &pThisServer);
  2264. if (pdhStatus == ERROR_SUCCESS) {
  2265. bDisconnectServer = TRUE;
  2266. if (pThisServer->pObjList == NULL) {
  2267. DWORD dwSize = 0;
  2268. pdhStatus = PdhiEnumWbemServerObjects(
  2269. pThisServer,
  2270. NULL,
  2271. & dwSize,
  2272. PERF_DETAIL_WIZARD | PERF_DETAIL_COSTLY,
  2273. TRUE,
  2274. TRUE);
  2275. if (pThisServer->pObjList != NULL) {
  2276. pdhStatus = ERROR_SUCCESS;
  2277. }
  2278. }
  2279. if (pThisServer->pObjList != NULL) {
  2280. PPDHI_WBEM_OBJECT_DEF pObject = pThisServer->pObjList;
  2281. pdhStatus = PDH_CSTATUS_NO_OBJECT;
  2282. while (pObject != NULL) {
  2283. if (pObject->bDefault) {
  2284. pdhStatus = ERROR_SUCCESS;
  2285. if (bUnicode) {
  2286. dwStrLen = lstrlenW(pObject->szDisplay);
  2287. if ( szDefaultObjectName != NULL
  2288. && dwStrLen < * pcchBufferSize) {
  2289. lstrcpyW((LPWSTR) szDefaultObjectName,
  2290. pObject->szDisplay);
  2291. }
  2292. else {
  2293. pdhStatus = PDH_MORE_DATA;
  2294. }
  2295. dwBufferSize = dwStrLen + 1;
  2296. }
  2297. else {
  2298. dwStrLen = * pcchBufferSize;
  2299. pdhStatus = PdhiConvertUnicodeToAnsi( _getmbcp(),
  2300. pObject->szDisplay,
  2301. (LPSTR) szDefaultObjectName,
  2302. & dwStrLen);
  2303. dwBufferSize = dwStrLen;
  2304. }
  2305. }
  2306. pObject = pObject->pNext;
  2307. }
  2308. }
  2309. }
  2310. // return the size used or required
  2311. * pcchBufferSize = dwBufferSize;
  2312. if (bDisconnectServer) {
  2313. if (pdhStatus == ERROR_SUCCESS) {
  2314. pdhStatus = PdhiDisconnectWbemServer (pThisServer);
  2315. } else {
  2316. // keep error code from function body
  2317. PdhiDisconnectWbemServer (pThisServer);
  2318. }
  2319. }
  2320. // CoUninitialize if necessary
  2321. if ( fCoInitialized )
  2322. {
  2323. PdhiCoUninitialize();
  2324. }
  2325. return pdhStatus;
  2326. }
  2327. PDH_FUNCTION
  2328. PdhiEnumWbemObjectItems (
  2329. IN LPCWSTR szWideMachineName,
  2330. IN LPCWSTR szWideObjectName,
  2331. IN LPVOID mszCounterList,
  2332. IN LPDWORD pcchCounterListLength,
  2333. IN LPVOID mszInstanceList,
  2334. IN LPDWORD pcchInstanceListLength,
  2335. IN DWORD dwDetailLevel,
  2336. IN DWORD dwFlags,
  2337. IN BOOL bUnicode
  2338. )
  2339. {
  2340. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  2341. PDH_STATUS CounterStatus = ERROR_SUCCESS;
  2342. PDH_STATUS InstanceStatus = ERROR_SUCCESS;
  2343. DWORD dwStrLen;
  2344. PPDHI_WBEM_SERVER_DEF pThisServer;
  2345. HRESULT hResult;
  2346. DWORD dwReturnCount;
  2347. DWORD dwCounterStringLen = 0;
  2348. DWORD dwInstanceStringLen = 0;
  2349. LPWSTR szNextWideString = NULL;
  2350. LPSTR szNextAnsiString = NULL;
  2351. WCHAR szObjectClassName[MAX_PATH];
  2352. BSTR bsName = NULL;
  2353. BSTR bsClassName = NULL;
  2354. BOOL bSingletonClass = FALSE;
  2355. VARIANT vName;
  2356. DWORD bDisconnectServer = FALSE;
  2357. IWbemClassObject *pThisClass = NULL;
  2358. IWbemQualifierSet *pQualSet = NULL;
  2359. DBG_UNREFERENCED_PARAMETER (dwFlags);
  2360. assert (szWideObjectName != NULL);
  2361. assert (pcchCounterListLength != NULL);
  2362. assert (pcchInstanceListLength != NULL);
  2363. // CoInitialize() if we need to
  2364. BOOL fCoInitialized = PdhiCoInitialize();
  2365. pdhStatus = PdhiConnectWbemServer (
  2366. szWideMachineName,
  2367. &pThisServer);
  2368. // enumerate the instances
  2369. if (pdhStatus == ERROR_SUCCESS) {
  2370. pdhStatus = PdhiWbemGetObjectClassName (
  2371. pThisServer,
  2372. szWideObjectName,
  2373. &szObjectClassName[0],
  2374. sizeof(szObjectClassName) / sizeof(szObjectClassName[0]),
  2375. &pThisClass);
  2376. assert (pThisClass != NULL);
  2377. bDisconnectServer = TRUE;
  2378. if (pdhStatus == ERROR_SUCCESS) {
  2379. bSingletonClass = PdhiIsSingletonClass (pThisClass);
  2380. } else if (pThisClass == NULL) {
  2381. pdhStatus = PDH_CSTATUS_NO_OBJECT;
  2382. } else {
  2383. // unable to find matching perf class
  2384. // return status returned by method
  2385. }
  2386. }
  2387. //enumerate the counter properties
  2388. if (pdhStatus == ERROR_SUCCESS) {
  2389. SAFEARRAY *psaNames = NULL;
  2390. long lLower;
  2391. long lUpper = 0;
  2392. long lCount;
  2393. BSTR bsPropName = NULL;
  2394. BSTR bsCountertype = NULL;
  2395. BSTR bsDisplayname = NULL;
  2396. BSTR bsDetailLevel = NULL;
  2397. VARIANT vCountertype;
  2398. VARIANT vDetailLevel;
  2399. DWORD dwItemDetailLevel;
  2400. VariantInit (&vName);
  2401. VariantInit (&vCountertype);
  2402. VariantInit (&vDetailLevel);
  2403. assert (pThisClass != NULL);
  2404. dwDetailLevel &= PERF_DETAIL_STANDARD; // mask off any inappropriate bits
  2405. // get the properties of this class as a Safe Array
  2406. hResult = pThisClass->GetNames (NULL,
  2407. WBEM_FLAG_NONSYSTEM_ONLY, NULL, &psaNames);
  2408. if (hResult == WBEM_NO_ERROR) {
  2409. hResult = SafeArrayGetLBound (psaNames, 1, &lLower);
  2410. if (hResult == S_OK) {
  2411. hResult = SafeArrayGetUBound (psaNames, 1, &lUpper);
  2412. }
  2413. if (hResult == S_OK) {
  2414. szNextAnsiString = (LPSTR)mszCounterList;
  2415. szNextWideString = (LPWSTR)mszCounterList;
  2416. bsCountertype = SysAllocString (cszCountertype);
  2417. bsDisplayname = SysAllocString (cszDisplayname);
  2418. bsDetailLevel = SysAllocString (cszPerfdetail);
  2419. if (bsCountertype && bsDisplayname && bsDetailLevel) {
  2420. for (lCount = lLower; lCount <= lUpper; lCount++) {
  2421. hResult = SafeArrayGetElement (psaNames, &lCount, &bsPropName);
  2422. if (hResult == S_OK) {
  2423. // get the qualifier set for this property
  2424. hResult = pThisClass->GetPropertyQualifierSet (
  2425. bsPropName, &pQualSet);
  2426. if (hResult == WBEM_NO_ERROR) {
  2427. LONG lCounterType;
  2428. hResult = pQualSet->Get (bsDetailLevel, 0, &vDetailLevel, 0);
  2429. if (hResult == S_OK) {
  2430. dwItemDetailLevel = (DWORD)V_I4(&vDetailLevel);
  2431. } else {
  2432. dwItemDetailLevel = 0;
  2433. }
  2434. // make sure this is a perf counter property
  2435. hResult = pQualSet->Get (bsCountertype, 0, &vCountertype, NULL);
  2436. if (hResult == WBEM_NO_ERROR) {
  2437. lCounterType = V_I4(&vCountertype);
  2438. // then see if this is a displayable counter
  2439. if ((!(lCounterType & PERF_DISPLAY_NOSHOW) ||
  2440. (lCounterType == PERF_AVERAGE_BULK)) &&
  2441. (dwItemDetailLevel <= dwDetailLevel)) {
  2442. // by testing for the counter type
  2443. // get the display name for this property
  2444. hResult = pQualSet->Get (bsDisplayname, 0, &vName, NULL);
  2445. if (hResult == WBEM_NO_ERROR && vName.vt == VT_BSTR) {
  2446. // display name found
  2447. if (bUnicode) {
  2448. dwStrLen = lstrlenW (V_BSTR(&vName)) + 1;
  2449. if ( (mszCounterList != NULL)
  2450. && ( (dwCounterStringLen + dwStrLen)
  2451. <= (* pcchCounterListLength))) {
  2452. lstrcpyW (szNextWideString, V_BSTR(&vName));
  2453. szNextWideString += dwStrLen;
  2454. }
  2455. else {
  2456. pdhStatus = PDH_MORE_DATA;
  2457. }
  2458. } else {
  2459. dwStrLen = (dwCounterStringLen < * pcchCounterListLength)
  2460. ? (* pcchCounterListLength - dwCounterStringLen)
  2461. : (0);
  2462. pdhStatus = PdhiConvertUnicodeToAnsi(_getmbcp(),
  2463. V_BSTR(& vName), szNextAnsiString, & dwStrLen);
  2464. if (pdhStatus == ERROR_SUCCESS) {
  2465. szNextAnsiString += dwStrLen;
  2466. }
  2467. }
  2468. dwCounterStringLen += dwStrLen;
  2469. }
  2470. } else {
  2471. // this is a "don't show" counter so skip it
  2472. }
  2473. } else {
  2474. // unable to get the counter type so it's probably
  2475. // not a perf counter property, skip it and continue
  2476. }
  2477. VariantClear (&vName);
  2478. VariantClear (&vCountertype);
  2479. VariantClear (&vDetailLevel);
  2480. pQualSet->Release();
  2481. } else {
  2482. // no properties so continue with the next one
  2483. }
  2484. } else {
  2485. // unable to read element in SafeArray
  2486. pdhStatus = PDH_WBEM_ERROR;
  2487. SetLastError(hResult);
  2488. }
  2489. } // end for each element in SafeArray
  2490. } else {
  2491. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  2492. }
  2493. PdhiSysFreeString (&bsCountertype);
  2494. PdhiSysFreeString (&bsDisplayname);
  2495. PdhiSysFreeString (&bsDetailLevel);
  2496. } else {
  2497. // unable to get array boundries
  2498. pdhStatus = PDH_WBEM_ERROR;
  2499. SetLastError (hResult);
  2500. }
  2501. } else {
  2502. // unable to get property strings
  2503. pdhStatus = PDH_WBEM_ERROR;
  2504. SetLastError (hResult);
  2505. }
  2506. dwCounterStringLen ++; // final NULL for MSZ
  2507. if (dwCounterStringLen > * pcchCounterListLength) {
  2508. pdhStatus = PDH_MORE_DATA;
  2509. }
  2510. if (pdhStatus == ERROR_SUCCESS) {
  2511. if (bUnicode) {
  2512. if (szNextWideString != NULL) {
  2513. if (szNextWideString != (LPWSTR)mszCounterList) {
  2514. *szNextWideString++ = 0;
  2515. } else {
  2516. // nothing returned
  2517. dwCounterStringLen = 0;
  2518. }
  2519. } else {
  2520. // then this is just a length query so return
  2521. // include the the MSZ term null char
  2522. CounterStatus = PDH_MORE_DATA;
  2523. }
  2524. } else {
  2525. if (szNextAnsiString != NULL) {
  2526. if (szNextAnsiString != (LPSTR)mszCounterList) {
  2527. *szNextAnsiString ++ = 0;
  2528. } else {
  2529. dwCounterStringLen = 0;
  2530. }
  2531. } else {
  2532. // then this is just a length query so return
  2533. // include the the MSZ term null char
  2534. CounterStatus = PDH_MORE_DATA;
  2535. }
  2536. }
  2537. }
  2538. else {
  2539. CounterStatus = pdhStatus;
  2540. }
  2541. VariantClear (&vName);
  2542. VariantClear (&vCountertype);
  2543. VariantClear (&vDetailLevel);
  2544. // Clear the SafeArray if it exists
  2545. if ( NULL != psaNames )
  2546. {
  2547. SafeArrayDestroy( psaNames );
  2548. psaNames = NULL;
  2549. }
  2550. *pcchCounterListLength = dwCounterStringLen;
  2551. //pThisClass->Release();
  2552. }
  2553. // Get instance strings if necessary
  2554. if (pdhStatus == ERROR_SUCCESS || pdhStatus == PDH_MORE_DATA) {
  2555. szNextAnsiString = (LPSTR) mszInstanceList;
  2556. szNextWideString = (LPWSTR) mszInstanceList;
  2557. if (!bSingletonClass) {
  2558. IWbemRefresher * pRefresher = NULL;
  2559. IWbemConfigureRefresher * pConfig = NULL;
  2560. IWbemHiPerfEnum * pEnum = NULL;
  2561. LONG lID;
  2562. DWORD dwNumReturned = 1;
  2563. DWORD dwNumObjects = 0;
  2564. DWORD i;
  2565. IWbemObjectAccess ** apEnumAccess = NULL;
  2566. CIMTYPE cimType;
  2567. WCHAR szName[SMALL_BUFFER_SIZE];
  2568. LONG lNameHandle = -1;
  2569. LONG lSize1 = SMALL_BUFFER_SIZE;
  2570. LONG lSize2 = 0;
  2571. hResult = CoCreateInstance(CLSID_WbemRefresher,
  2572. NULL,
  2573. CLSCTX_INPROC_SERVER,
  2574. IID_IWbemRefresher,
  2575. (void **) & pRefresher);
  2576. if (SUCCEEDED(hResult)) {
  2577. hResult = pRefresher->QueryInterface(
  2578. IID_IWbemConfigureRefresher,
  2579. (void **) & pConfig);
  2580. if (SUCCEEDED(hResult)) {
  2581. hResult = pConfig->AddEnum(pThisServer->pSvc,
  2582. szObjectClassName,
  2583. 0,
  2584. NULL,
  2585. & pEnum,
  2586. & lID);
  2587. if (SUCCEEDED(hResult)) {
  2588. hResult = pRefresher->Refresh(0L);
  2589. if (SUCCEEDED(hResult)) {
  2590. hResult = pEnum->GetObjects(0L,
  2591. dwNumObjects,
  2592. apEnumAccess,
  2593. & dwNumReturned);
  2594. if (hResult == WBEM_E_BUFFER_TOO_SMALL) {
  2595. apEnumAccess = (IWbemObjectAccess **)
  2596. G_ALLOC(dwNumReturned
  2597. * sizeof(IWbemObjectAccess *));
  2598. if (apEnumAccess != NULL) {
  2599. ZeroMemory(apEnumAccess, dwNumReturned
  2600. * sizeof(IWbemObjectAccess *));
  2601. dwNumObjects = dwNumReturned;
  2602. hResult = pEnum->GetObjects(0L,
  2603. dwNumObjects,
  2604. apEnumAccess,
  2605. & dwNumReturned);
  2606. }
  2607. else {
  2608. hResult = WBEM_E_OUT_OF_MEMORY;
  2609. }
  2610. }
  2611. if (SUCCEEDED(hResult)) {
  2612. for (i = 0; i < dwNumReturned; i ++) {
  2613. hResult = apEnumAccess[i]->GetPropertyHandle(
  2614. cszName,
  2615. & cimType,
  2616. & lNameHandle);
  2617. if (SUCCEEDED(hResult) && lNameHandle != -1) {
  2618. ZeroMemory(szName,
  2619. SMALL_BUFFER_SIZE * sizeof(WCHAR));
  2620. hResult = apEnumAccess[i]->ReadPropertyValue(
  2621. lNameHandle,
  2622. lSize1,
  2623. & lSize2,
  2624. (LPBYTE) szName);
  2625. if (SUCCEEDED(hResult) && lstrlenW(szName) > 0) {
  2626. if (bUnicode) {
  2627. dwStrLen = lstrlenW(szName) + 1;
  2628. if ( (mszInstanceList != NULL)
  2629. && ( (dwInstanceStringLen + dwStrLen)
  2630. < (* pcchInstanceListLength))) {
  2631. lstrcpyW (szNextWideString, szName);
  2632. szNextWideString += dwStrLen;
  2633. }
  2634. else {
  2635. pdhStatus = PDH_MORE_DATA;
  2636. }
  2637. }
  2638. else {
  2639. dwStrLen = (dwInstanceStringLen <= * pcchInstanceListLength)
  2640. ? (* pcchInstanceListLength - dwInstanceStringLen)
  2641. : (0);
  2642. pdhStatus = PdhiConvertUnicodeToAnsi(
  2643. _getmbcp(),
  2644. szName,
  2645. szNextAnsiString,
  2646. & dwStrLen);
  2647. if (pdhStatus == ERROR_SUCCESS) {
  2648. szNextAnsiString += dwStrLen;
  2649. }
  2650. }
  2651. dwInstanceStringLen += dwStrLen;
  2652. }
  2653. }
  2654. apEnumAccess[i]->Release();
  2655. }
  2656. }
  2657. }
  2658. }
  2659. }
  2660. }
  2661. if (! SUCCEEDED(hResult)) {
  2662. SetLastError(hResult);
  2663. pdhStatus = PDH_WBEM_ERROR;
  2664. }
  2665. else if (dwInstanceStringLen == 0) {
  2666. dwInstanceStringLen = 2;
  2667. if ( szNextWideString != NULL
  2668. && dwInstanceStringLen <= * pcchInstanceListLength) {
  2669. * szNextWideString = L'\0';
  2670. szNextWideString ++;
  2671. }
  2672. if ( szNextAnsiString != NULL
  2673. && dwInstanceStringLen <= * pcchInstanceListLength) {
  2674. * szNextAnsiString = '\0';
  2675. szNextAnsiString ++;
  2676. }
  2677. }
  2678. else {
  2679. dwInstanceStringLen ++;
  2680. }
  2681. if (apEnumAccess != NULL) G_FREE(apEnumAccess);
  2682. if (pEnum != NULL) pEnum->Release();
  2683. if (pConfig != NULL) pConfig->Release();
  2684. if (pRefresher != NULL) pRefresher->Release();
  2685. }
  2686. if (dwInstanceStringLen > * pcchInstanceListLength) {
  2687. pdhStatus = PDH_MORE_DATA;
  2688. }
  2689. if (pdhStatus == ERROR_SUCCESS) {
  2690. if (bUnicode) {
  2691. if (szNextWideString != NULL) {
  2692. if (szNextWideString != (LPWSTR)mszInstanceList) {
  2693. *szNextWideString++ = 0;
  2694. } else {
  2695. dwInstanceStringLen = 0;
  2696. }
  2697. } else if (dwInstanceStringLen > 0) {
  2698. // then this is just a length query so return
  2699. // include the the MSZ term null char
  2700. InstanceStatus = PDH_MORE_DATA;
  2701. }
  2702. } else {
  2703. if (szNextAnsiString != NULL) {
  2704. if (szNextAnsiString != (LPSTR)mszInstanceList) {
  2705. *szNextAnsiString++ = 0;
  2706. } else {
  2707. dwInstanceStringLen = 0;
  2708. }
  2709. } else if (dwInstanceStringLen > 0) {
  2710. // then this is just a length query so return
  2711. // include the the MSZ term null char
  2712. InstanceStatus = PDH_MORE_DATA;
  2713. }
  2714. }
  2715. }
  2716. else {
  2717. InstanceStatus = pdhStatus;
  2718. }
  2719. *pcchInstanceListLength = dwInstanceStringLen;
  2720. }
  2721. VariantClear (&vName);
  2722. if (bDisconnectServer) {
  2723. if (pdhStatus == ERROR_SUCCESS) {
  2724. pdhStatus = PdhiDisconnectWbemServer (pThisServer);
  2725. } else {
  2726. // keep error code from function body
  2727. PdhiDisconnectWbemServer (pThisServer);
  2728. }
  2729. }
  2730. // CoUninitialize if necessary
  2731. if ( fCoInitialized )
  2732. {
  2733. PdhiCoUninitialize();
  2734. }
  2735. if (pdhStatus == ERROR_SUCCESS) {
  2736. pdhStatus = (CounterStatus == ERROR_SUCCESS)
  2737. ? (InstanceStatus) : (CounterStatus);
  2738. }
  2739. return pdhStatus;
  2740. }
  2741. #pragma warning ( default : 4127 )
  2742. PDH_FUNCTION
  2743. PdhiGetDefaultWbemProperty (
  2744. IN LPCWSTR szMachineName,
  2745. IN LPCWSTR szObjectName,
  2746. IN LPVOID szDefaultCounterName,
  2747. IN LPDWORD pcchBufferSize,
  2748. IN BOOL bUnicode
  2749. )
  2750. {
  2751. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  2752. DWORD dwStrLen;
  2753. PPDHI_WBEM_SERVER_DEF pThisServer;
  2754. HRESULT hResult;
  2755. DWORD dwCounterStringLen = 0;
  2756. WCHAR szObjectClassName[MAX_PATH];
  2757. DWORD bDisconnectServer = FALSE;
  2758. BOOL bFound = FALSE;
  2759. IWbemClassObject *pThisClass = NULL;
  2760. IWbemQualifierSet *pQualSet = NULL;
  2761. assert (szMachineName != NULL);
  2762. assert (szObjectName != NULL);
  2763. assert (pcchBufferSize != NULL);
  2764. // CoInitialize() if we need to
  2765. BOOL fCoInitialized = PdhiCoInitialize();
  2766. pdhStatus = PdhiConnectWbemServer (
  2767. szMachineName,
  2768. &pThisServer);
  2769. // enumerate the instances
  2770. if (pdhStatus == ERROR_SUCCESS) {
  2771. pdhStatus = PdhiWbemGetObjectClassName (
  2772. pThisServer,
  2773. szObjectName,
  2774. &szObjectClassName[0],
  2775. sizeof(szObjectClassName) / sizeof(szObjectClassName[0]),
  2776. &pThisClass);
  2777. bDisconnectServer = TRUE;
  2778. }
  2779. //enumerate the counter properties
  2780. if (pdhStatus == ERROR_SUCCESS) {
  2781. SAFEARRAY *psaNames = NULL;
  2782. long lLower;
  2783. long lUpper = 0;
  2784. long lCount;
  2785. BSTR bsPropName = NULL;
  2786. BSTR bsDisplayname = NULL;
  2787. BSTR bsPerfDefault = NULL;
  2788. VARIANT vName, vCountertype;
  2789. VariantInit (&vName);
  2790. VariantInit (&vCountertype);
  2791. // get the properties of this class as a Safe Array
  2792. hResult = pThisClass->GetNames (NULL,
  2793. WBEM_FLAG_NONSYSTEM_ONLY, NULL, &psaNames);
  2794. if (hResult == WBEM_NO_ERROR) {
  2795. hResult = SafeArrayGetLBound (psaNames, 1, &lLower);
  2796. if (hResult == S_OK) {
  2797. hResult = SafeArrayGetUBound (psaNames, 1, &lUpper);
  2798. }
  2799. if (hResult == S_OK) {
  2800. bsDisplayname = SysAllocString (cszDisplayname);
  2801. bsPerfDefault = SysAllocString (cszPerfdefault);
  2802. if (bsDisplayname && bsPerfDefault) {
  2803. for (lCount = lLower; lCount <= lUpper; lCount++) {
  2804. hResult = SafeArrayGetElement (psaNames, &lCount, &bsPropName);
  2805. if (hResult == S_OK) {
  2806. // get the qualifier set for this property
  2807. hResult = pThisClass->GetPropertyQualifierSet (
  2808. bsPropName, &pQualSet);
  2809. if (hResult == WBEM_NO_ERROR) {
  2810. // make sure this is a perf counter property
  2811. hResult = pQualSet->Get (bsPerfDefault, 0, &vCountertype, NULL);
  2812. if (hResult == WBEM_NO_ERROR) {
  2813. if ((BOOL)V_BOOL(&vCountertype)) {
  2814. // found the default property so load it and return
  2815. hResult = pQualSet->Get (bsDisplayname, 0, &vName, NULL);
  2816. if (hResult == WBEM_NO_ERROR) {
  2817. // display name found
  2818. bFound = TRUE;
  2819. if (bUnicode) {
  2820. dwStrLen = lstrlenW (V_BSTR(&vName)) + 1;
  2821. if ( (szDefaultCounterName != NULL)
  2822. && (dwStrLen <= * pcchBufferSize)) {
  2823. lstrcpyW ((LPWSTR)szDefaultCounterName,
  2824. (LPWSTR)V_BSTR(&vName));
  2825. }
  2826. else {
  2827. pdhStatus = PDH_MORE_DATA;
  2828. }
  2829. }
  2830. else {
  2831. dwStrLen = * pcchBufferSize;
  2832. pdhStatus = PdhiConvertUnicodeToAnsi(_getmbcp(),
  2833. (LPWSTR) V_BSTR(& vName),
  2834. (LPSTR) szDefaultCounterName,
  2835. & dwStrLen);
  2836. }
  2837. // this is either the amount used or the amount needed
  2838. dwCounterStringLen = dwStrLen;
  2839. // free qualifier set
  2840. pQualSet->Release();
  2841. // now leave
  2842. break;
  2843. } else {
  2844. // no qualifier so assume FALSE
  2845. }
  2846. } else {
  2847. // value found but is FALSE
  2848. }
  2849. }
  2850. // free the qualifier set
  2851. pQualSet->Release();
  2852. // clear variants
  2853. VariantClear (&vName);
  2854. VariantClear (&vCountertype);
  2855. } else {
  2856. // no Qualifiers so continue with the next one
  2857. }
  2858. } else {
  2859. // unable to read element in SafeArray
  2860. pdhStatus = PDH_WBEM_ERROR;
  2861. SetLastError(hResult);
  2862. }
  2863. } // end for each element in SafeArray
  2864. } else {
  2865. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  2866. }
  2867. // no default defined for this object
  2868. if ((pdhStatus == ERROR_SUCCESS) && !bFound) pdhStatus = PDH_CSTATUS_NO_COUNTER;
  2869. PdhiSysFreeString (&bsPerfDefault);
  2870. PdhiSysFreeString (&bsDisplayname);
  2871. } else {
  2872. // unable to get array boundries
  2873. pdhStatus = PDH_WBEM_ERROR;
  2874. SetLastError (hResult);
  2875. }
  2876. } else {
  2877. // unable to get property strings
  2878. pdhStatus = PDH_WBEM_ERROR;
  2879. SetLastError (hResult);
  2880. }
  2881. if ( NULL != psaNames )
  2882. {
  2883. SafeArrayDestroy( psaNames );
  2884. }
  2885. VariantClear (&vName);
  2886. VariantClear (&vCountertype);
  2887. //pThisClass->Release();
  2888. }
  2889. *pcchBufferSize = dwCounterStringLen;
  2890. if (bDisconnectServer) {
  2891. if (pdhStatus == ERROR_SUCCESS) {
  2892. pdhStatus = PdhiDisconnectWbemServer (pThisServer);
  2893. } else {
  2894. // keep error code from function body
  2895. PdhiDisconnectWbemServer (pThisServer);
  2896. }
  2897. }
  2898. // CoUninitialize if necessary
  2899. if ( fCoInitialized )
  2900. {
  2901. PdhiCoUninitialize();
  2902. }
  2903. return pdhStatus;
  2904. }
  2905. PDH_FUNCTION
  2906. PdhiEncodeWbemPathW (
  2907. IN PDH_COUNTER_PATH_ELEMENTS_W *pCounterPathElements,
  2908. IN LPWSTR szFullPathBuffer,
  2909. IN LPDWORD pcchBufferSize,
  2910. IN LANGID LangId,
  2911. IN DWORD dwFlags
  2912. )
  2913. /*++
  2914. converts a set of path elements in either Registry or WBEM format
  2915. to a path in either Registry or WBEM format as defined by the flags.
  2916. --*/
  2917. {
  2918. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  2919. DWORD dwBuffSize;
  2920. LPWSTR szTempPath = NULL;
  2921. DWORD dwCurSize = 0;
  2922. LPWSTR szThisChar;
  2923. IWbemClassObject *pWbemClass = NULL;
  2924. PPDHI_WBEM_SERVER_DEF pWbemServer = NULL;
  2925. DWORD bDisconnectServer = FALSE;
  2926. DBG_UNREFERENCED_PARAMETER (LangId);
  2927. assert (pCounterPathElements != NULL); // this is not allowed
  2928. assert (dwFlags != 0); // this should be caught by the calling fn.
  2929. assert (pcchBufferSize != NULL); // this is required
  2930. // CoInitialize() if we need to
  2931. BOOL fCoInitialized = PdhiCoInitialize();
  2932. // create a working buffer the same size as the one passed in
  2933. if (*pcchBufferSize == 0L) {
  2934. dwBuffSize = *pcchBufferSize * sizeof(WCHAR);
  2935. } else {
  2936. dwBuffSize = 1024 * sizeof(WCHAR); // just something to work with
  2937. }
  2938. szTempPath = (LPWSTR) G_ALLOC(dwBuffSize);
  2939. if (szTempPath == NULL) {
  2940. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  2941. } else if (pdhStatus == ERROR_SUCCESS) {
  2942. szTempPath[0] = L'\0';
  2943. // start by adding the machine name to the path
  2944. if (pCounterPathElements->szMachineName != NULL) {
  2945. lstrcpyW (szTempPath, pCounterPathElements->szMachineName);
  2946. if (dwFlags == (PDH_PATH_WBEM_INPUT)) {
  2947. // if this is a wbem element in to a registry path out,
  2948. // then remove the namespace which occurs starting at the
  2949. // second backslash
  2950. for (szThisChar = &szTempPath[2];
  2951. (*szThisChar != 0) && (*szThisChar != L'\\');
  2952. szThisChar++);
  2953. if (*szThisChar != 0) *szThisChar = 0;
  2954. } else if (dwFlags == (PDH_PATH_WBEM_RESULT)) {
  2955. // if this is a registry element in to a WBEM out, then
  2956. // append the default namespace to the machine name
  2957. //NAMEFIX lstrcatW (szTempPath, cszWbemDefaultPerfRoot);
  2958. }
  2959. } else {
  2960. // no machine name specified so add the default machine
  2961. // and default namespace for a wbem output path
  2962. if (dwFlags == (PDH_PATH_WBEM_RESULT)) {
  2963. lstrcpyW (szTempPath, cszDoubleBackSlashDot); // default machine
  2964. //NAMEFIX lstrcatW (szTempPath, cszWbemDefaultPerfRoot);
  2965. } else {
  2966. // no entry required for the registry path
  2967. }
  2968. }
  2969. dwCurSize = lstrlenW(szTempPath);
  2970. // now add the object or class name
  2971. if (pdhStatus == ERROR_SUCCESS) {
  2972. if (pCounterPathElements->szObjectName != NULL) {
  2973. DWORD dwSize;
  2974. WCHAR szTempObjectString[1024];
  2975. dwSize = 1024;
  2976. ZeroMemory(szTempObjectString, sizeof(WCHAR) * 1024);
  2977. // then the input is different from the output
  2978. // so convert from one to the other
  2979. // and default name space since perf counters won't be
  2980. // found elsewhere
  2981. pdhStatus = PdhiConnectWbemServer (
  2982. NULL, // use local machine
  2983. &pWbemServer);
  2984. if (pdhStatus == ERROR_SUCCESS) {
  2985. bDisconnectServer = TRUE;
  2986. if (dwFlags & PDH_PATH_WBEM_INPUT) {
  2987. // convert the WBEM Class to the display name
  2988. pdhStatus = PdhiWbemGetClassDisplayName (
  2989. pWbemServer,
  2990. pCounterPathElements->szObjectName,
  2991. &szTempObjectString[0],
  2992. dwSize,
  2993. &pWbemClass);
  2994. // add a backslash path separator for registry output
  2995. if (pdhStatus == ERROR_SUCCESS) {
  2996. if (dwFlags & PDH_PATH_WBEM_RESULT) {
  2997. lstrcatW(szTempPath, cszColon);
  2998. // just copy the string, but save
  2999. lstrcpyW (szTempObjectString, pCounterPathElements->szObjectName);
  3000. } else {
  3001. lstrcatW(szTempPath, cszBackSlash);
  3002. // copy the retrieved string
  3003. }
  3004. }
  3005. } else {
  3006. // convert the display name to a Wbem class name
  3007. pdhStatus = PdhiWbemGetObjectClassName (
  3008. pWbemServer,
  3009. pCounterPathElements->szObjectName,
  3010. &szTempObjectString[0],
  3011. dwSize,
  3012. &pWbemClass);
  3013. // add a colon path separator
  3014. lstrcatW(szTempPath, cszColon);
  3015. }
  3016. if (pdhStatus == ERROR_SUCCESS) {
  3017. //then add the string
  3018. lstrcatW(szTempPath, szTempObjectString);
  3019. dwCurSize += lstrlenW(szTempObjectString) + 1; // includes delimiter
  3020. }
  3021. if (bDisconnectServer) {
  3022. if (pdhStatus == ERROR_SUCCESS) {
  3023. pdhStatus = PdhiDisconnectWbemServer (pWbemServer);
  3024. } else {
  3025. // keep error code from function body
  3026. PdhiDisconnectWbemServer (pWbemServer);
  3027. }
  3028. }
  3029. }
  3030. } else {
  3031. // no object name, so bad structure
  3032. pdhStatus = PDH_CSTATUS_NO_OBJECT;
  3033. }
  3034. }
  3035. // check for instance entries to add before adding the counter.
  3036. if (pdhStatus == ERROR_SUCCESS) {
  3037. if (pCounterPathElements->szInstanceName != NULL) {
  3038. lstrcatW (szTempPath, cszLeftParen);
  3039. dwCurSize += 1;
  3040. if (pCounterPathElements->szParentInstance != NULL) {
  3041. lstrcatW (szTempPath, pCounterPathElements->szParentInstance);
  3042. lstrcatW (szTempPath, cszSlash);
  3043. dwCurSize += lstrlenW( pCounterPathElements->szParentInstance ) + 1;
  3044. }
  3045. lstrcatW (szTempPath, pCounterPathElements->szInstanceName);
  3046. lstrcatW (szTempPath, cszRightParen);
  3047. dwCurSize += lstrlenW( pCounterPathElements->szInstanceName ) + 1;
  3048. } else {
  3049. // this is OK
  3050. assert (pCounterPathElements->szParentInstance == NULL);
  3051. assert (pCounterPathElements->dwInstanceIndex == 0);
  3052. }
  3053. }
  3054. // add counter name
  3055. if (pdhStatus == ERROR_SUCCESS) {
  3056. if (pCounterPathElements->szCounterName != NULL) {
  3057. DWORD dwSize;
  3058. WCHAR szTempCounterString[1024];
  3059. dwSize = 1024;
  3060. // then the input is different from the output
  3061. // so convert from one to the other
  3062. // and default name space since perf counters won't be
  3063. // found elsewhere
  3064. assert (pWbemServer != NULL);
  3065. if (pdhStatus == ERROR_SUCCESS) {
  3066. // add a backslash path separator
  3067. lstrcatW(szTempPath, cszBackSlash);
  3068. if (dwFlags & PDH_PATH_WBEM_INPUT) {
  3069. // convert the WBEM Class to the display name
  3070. pdhStatus = PdhiWbemGetCounterDisplayName (
  3071. pWbemClass,
  3072. pCounterPathElements->szCounterName,
  3073. &szTempCounterString[0],
  3074. dwSize);
  3075. if (dwFlags & PDH_PATH_WBEM_RESULT) {
  3076. // just copy the string, but save
  3077. // the class pointer
  3078. lstrcpyW (szTempCounterString, pCounterPathElements->szCounterName);
  3079. } else {
  3080. // copy the retrieved string
  3081. }
  3082. } else {
  3083. // convert the display name to a Wbem class name
  3084. pdhStatus = PdhiWbemGetCounterPropertyName (
  3085. pWbemClass,
  3086. pCounterPathElements->szCounterName,
  3087. &szTempCounterString[0],
  3088. dwSize);
  3089. }
  3090. if (pdhStatus == ERROR_SUCCESS) {
  3091. //then add the string
  3092. lstrcatW(szTempPath, szTempCounterString);
  3093. dwCurSize += lstrlenW(szTempCounterString) + 1; // includes delimiter
  3094. }
  3095. }
  3096. } else {
  3097. // no object name, so bad structure
  3098. pdhStatus = PDH_CSTATUS_NO_COUNTER;
  3099. }
  3100. }
  3101. assert (dwCurSize == (DWORD)lstrlenW(szTempPath));
  3102. }
  3103. if (pdhStatus == ERROR_SUCCESS) {
  3104. // copy path to the caller's buffer if it will fit
  3105. assert (dwCurSize == (DWORD)lstrlenW(szTempPath));
  3106. if (dwCurSize < *pcchBufferSize) {
  3107. if (szFullPathBuffer != NULL) {
  3108. lstrcpyW (szFullPathBuffer, szTempPath);
  3109. }
  3110. } else {
  3111. if (szFullPathBuffer != NULL) {
  3112. // the buffer passed in is too small
  3113. pdhStatus = PDH_MORE_DATA;
  3114. }
  3115. }
  3116. *pcchBufferSize = dwCurSize;
  3117. }
  3118. //if (pWbemClass != NULL) pWbemClass->Release();
  3119. // CoUninitialize if necessary
  3120. if ( fCoInitialized )
  3121. {
  3122. PdhiCoUninitialize();
  3123. }
  3124. if (szTempPath != NULL) G_FREE(szTempPath);
  3125. return pdhStatus;
  3126. }
  3127. PDH_FUNCTION
  3128. PdhiEncodeWbemPathA (
  3129. PDH_COUNTER_PATH_ELEMENTS_A *pCounterPathElements,
  3130. LPSTR szFullPathBuffer,
  3131. LPDWORD pcchBufferSize,
  3132. LANGID LangId,
  3133. DWORD dwFlags
  3134. )
  3135. {
  3136. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  3137. LPWSTR wszNextString;
  3138. LPWSTR wszReturnBuffer;
  3139. PDH_COUNTER_PATH_ELEMENTS_W *pWideCounterPathElements;
  3140. DWORD dwcchBufferSize;
  3141. DWORD dwBuffSize;
  3142. DWORD dwDest;
  3143. // get required buffer size...
  3144. dwBuffSize = sizeof (PDH_COUNTER_PATH_ELEMENTS_W);
  3145. if (pCounterPathElements->szMachineName != NULL) {
  3146. dwBuffSize += (lstrlenA(pCounterPathElements->szMachineName) + 1) * sizeof(WCHAR);
  3147. }
  3148. if (pCounterPathElements->szObjectName != NULL) {
  3149. dwBuffSize += (lstrlenA(pCounterPathElements->szObjectName) + 1) * sizeof(WCHAR);
  3150. }
  3151. if (pCounterPathElements->szInstanceName != NULL) {
  3152. dwBuffSize += (lstrlenA(pCounterPathElements->szInstanceName) + 1) * sizeof(WCHAR);
  3153. }
  3154. if (pCounterPathElements->szParentInstance != NULL) {
  3155. dwBuffSize += (lstrlenA(pCounterPathElements->szParentInstance) + 1) * sizeof(WCHAR);
  3156. }
  3157. if (pCounterPathElements->szCounterName != NULL) {
  3158. dwBuffSize += (lstrlenA(pCounterPathElements->szCounterName) + 1) * sizeof(WCHAR);
  3159. }
  3160. // add in room for the return buffer
  3161. dwcchBufferSize = * pcchBufferSize;
  3162. dwBuffSize += dwcchBufferSize * sizeof(WCHAR);
  3163. pWideCounterPathElements = (PDH_COUNTER_PATH_ELEMENTS_W *)G_ALLOC(dwBuffSize);
  3164. if (pWideCounterPathElements != NULL) {
  3165. // populate the fields
  3166. wszNextString = (LPWSTR)&pWideCounterPathElements[1];
  3167. if (pCounterPathElements->szMachineName != NULL) {
  3168. dwDest = MultiByteToWideChar(_getmbcp(),
  3169. 0,
  3170. pCounterPathElements->szMachineName,
  3171. lstrlenA(pCounterPathElements->szMachineName),
  3172. wszNextString,
  3173. (lstrlenA(pCounterPathElements->szMachineName) + 1));
  3174. if (dwDest > 0) {
  3175. pWideCounterPathElements->szMachineName = wszNextString;
  3176. wszNextString += dwDest + 1;
  3177. }
  3178. else {
  3179. pWideCounterPathElements->szMachineName = NULL;
  3180. }
  3181. } else {
  3182. pWideCounterPathElements->szMachineName = NULL;
  3183. }
  3184. if (pCounterPathElements->szObjectName != NULL) {
  3185. pWideCounterPathElements->szObjectName = wszNextString;
  3186. dwDest = MultiByteToWideChar(_getmbcp(),
  3187. 0,
  3188. pCounterPathElements->szObjectName,
  3189. lstrlenA(pCounterPathElements->szObjectName),
  3190. wszNextString,
  3191. (lstrlenA(pCounterPathElements->szObjectName) + 1));
  3192. if (dwDest > 0) {
  3193. pWideCounterPathElements->szObjectName = wszNextString;
  3194. wszNextString += dwDest + 1;
  3195. }
  3196. else {
  3197. pWideCounterPathElements->szObjectName = NULL;
  3198. }
  3199. } else {
  3200. pWideCounterPathElements->szObjectName = NULL;
  3201. }
  3202. if (pCounterPathElements->szInstanceName != NULL) {
  3203. dwDest = MultiByteToWideChar(_getmbcp(),
  3204. 0,
  3205. pCounterPathElements->szInstanceName,
  3206. lstrlenA(pCounterPathElements->szInstanceName),
  3207. wszNextString,
  3208. (lstrlenA(pCounterPathElements->szInstanceName) + 1));
  3209. if (dwDest > 0) {
  3210. pWideCounterPathElements->szInstanceName = wszNextString;
  3211. wszNextString += dwDest + 1;
  3212. }
  3213. else {
  3214. pWideCounterPathElements->szInstanceName = NULL;
  3215. }
  3216. } else {
  3217. pWideCounterPathElements->szInstanceName = NULL;
  3218. }
  3219. if (pCounterPathElements->szParentInstance != NULL) {
  3220. dwDest = MultiByteToWideChar(_getmbcp(),
  3221. 0,
  3222. pCounterPathElements->szParentInstance,
  3223. lstrlenA(pCounterPathElements->szParentInstance),
  3224. wszNextString,
  3225. (lstrlenA(pCounterPathElements->szParentInstance) + 1));
  3226. if (dwDest > 0) {
  3227. pWideCounterPathElements->szParentInstance = wszNextString;
  3228. wszNextString += dwDest + 1;
  3229. }
  3230. else {
  3231. pWideCounterPathElements->szParentInstance = NULL;
  3232. }
  3233. } else {
  3234. pWideCounterPathElements->szParentInstance = NULL;
  3235. }
  3236. if (pCounterPathElements->szCounterName != NULL) {
  3237. dwDest = MultiByteToWideChar(_getmbcp(),
  3238. 0,
  3239. pCounterPathElements->szCounterName,
  3240. lstrlenA(pCounterPathElements->szCounterName),
  3241. wszNextString,
  3242. (lstrlenA(pCounterPathElements->szCounterName) + 1));
  3243. if (dwDest > 0) {
  3244. pWideCounterPathElements->szCounterName = wszNextString;
  3245. wszNextString += dwDest + 1;
  3246. }
  3247. else {
  3248. pWideCounterPathElements->szCounterName = NULL;
  3249. }
  3250. } else {
  3251. pWideCounterPathElements->szCounterName = NULL;
  3252. }
  3253. pWideCounterPathElements->dwInstanceIndex =
  3254. pCounterPathElements->dwInstanceIndex;
  3255. if (szFullPathBuffer != NULL) {
  3256. wszReturnBuffer = wszNextString;
  3257. } else {
  3258. wszReturnBuffer = NULL;
  3259. }
  3260. // call wide function
  3261. pdhStatus = PdhiEncodeWbemPathW (
  3262. pWideCounterPathElements,
  3263. wszReturnBuffer,
  3264. & dwcchBufferSize,
  3265. LangId,
  3266. dwFlags);
  3267. if ((pdhStatus == ERROR_SUCCESS) && (szFullPathBuffer != NULL)) {
  3268. // convert the wide path back to ANSI
  3269. pdhStatus = PdhiConvertUnicodeToAnsi(_getmbcp(),
  3270. wszReturnBuffer,
  3271. szFullPathBuffer,
  3272. pcchBufferSize);
  3273. }
  3274. G_FREE (pWideCounterPathElements);
  3275. } else {
  3276. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  3277. }
  3278. return pdhStatus;
  3279. }
  3280. PDH_FUNCTION
  3281. PdhiDecodeWbemPathW (
  3282. IN LPCWSTR szFullPathBuffer,
  3283. IN PDH_COUNTER_PATH_ELEMENTS_W *pCounterPathElements,
  3284. IN LPDWORD pdwBufferSize,
  3285. IN LANGID LangId,
  3286. IN DWORD dwFlags
  3287. )
  3288. {
  3289. PPDHI_COUNTER_PATH pLocalCounterPath;
  3290. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  3291. DWORD dwSize;
  3292. LPWSTR szString = NULL;
  3293. WCHAR wszTempBuffer[MAX_PATH];
  3294. LPWSTR szSrc = NULL;
  3295. PPDHI_WBEM_SERVER_DEF pThisServer = NULL;
  3296. IWbemClassObject *pThisClass = NULL;
  3297. DBG_UNREFERENCED_PARAMETER (LangId);
  3298. // CoInitialize() if we need to
  3299. BOOL fCoInitialized = PdhiCoInitialize();
  3300. // allocate a temporary work buffer
  3301. pLocalCounterPath = (PPDHI_COUNTER_PATH) G_ALLOC(
  3302. sizeof(PDHI_COUNTER_PATH) + sizeof(WCHAR) * 2 *
  3303. ( lstrlenW(szStaticLocalMachineName)
  3304. + lstrlenW(szFullPathBuffer) + 3));
  3305. if (pLocalCounterPath != NULL) {
  3306. dwSize = (DWORD)G_SIZE (pLocalCounterPath);
  3307. assert (dwSize != NULL);
  3308. if (pdhStatus == ERROR_SUCCESS) {
  3309. // get WBEM server since we'll probably need it later
  3310. if (ParseFullPathNameW (szFullPathBuffer,
  3311. &dwSize, pLocalCounterPath,
  3312. (dwFlags & PDH_PATH_WBEM_INPUT ? TRUE : FALSE))) {
  3313. // parsed successfully so load into user's buffer
  3314. if (*pdwBufferSize != 0) {
  3315. if (pCounterPathElements != NULL) {
  3316. // see if there's enough room
  3317. if (*pdwBufferSize >= dwSize) {
  3318. // there's room so copy / translate the data
  3319. szString = (LPWSTR)&pCounterPathElements[1];
  3320. if (pLocalCounterPath->szMachineName != NULL) {
  3321. pCounterPathElements->szMachineName = szString;
  3322. lstrcpyW (szString, pLocalCounterPath->szMachineName);
  3323. szString += lstrlenW (szString) + 1;
  3324. szString = (LPWSTR)ALIGN_ON_DWORD (szString);
  3325. } else {
  3326. pCounterPathElements->szMachineName = NULL;
  3327. }
  3328. dwSize = (DWORD)((LPBYTE)szString - (LPBYTE)pCounterPathElements);
  3329. }
  3330. // Now that we have the proper machine name,
  3331. // connect to the server if we need to
  3332. if (dwFlags != (PDH_PATH_WBEM_INPUT | PDH_PATH_WBEM_RESULT)) {
  3333. pdhStatus = PdhiConnectWbemServer (
  3334. pCounterPathElements->szMachineName, &pThisServer);
  3335. } else {
  3336. // this will just be a copy operation
  3337. pdhStatus = ERROR_SUCCESS;
  3338. }
  3339. if ( pdhStatus == ERROR_SUCCESS ) {
  3340. if (pLocalCounterPath->szObjectName != NULL) {
  3341. pCounterPathElements->szObjectName = szString;
  3342. if (dwFlags & PDH_PATH_WBEM_RESULT) {
  3343. if (dwFlags & PDH_PATH_WBEM_INPUT) {
  3344. // just copy
  3345. szSrc = pLocalCounterPath->szObjectName;
  3346. } else {
  3347. // interpret the display name to a class name
  3348. pdhStatus = PdhiWbemGetObjectClassName (
  3349. pThisServer,
  3350. pLocalCounterPath->szObjectName,
  3351. wszTempBuffer,
  3352. sizeof(wszTempBuffer) / sizeof(wszTempBuffer[0]),
  3353. &pThisClass);
  3354. if (pdhStatus == ERROR_SUCCESS) {
  3355. szSrc = wszTempBuffer;
  3356. }
  3357. }
  3358. } else {
  3359. if (dwFlags & PDH_PATH_WBEM_INPUT) {
  3360. // translate class name to a display name
  3361. pdhStatus = PdhiWbemGetClassDisplayName (
  3362. pThisServer, pLocalCounterPath->szObjectName,
  3363. wszTempBuffer,
  3364. sizeof(wszTempBuffer) / sizeof(wszTempBuffer[0]),
  3365. &pThisClass);
  3366. if (pdhStatus == ERROR_SUCCESS) {
  3367. szSrc = wszTempBuffer;
  3368. }
  3369. } else {
  3370. assert (dwFlags != 0); // this should be caught earlier
  3371. }
  3372. }
  3373. if (pdhStatus == ERROR_SUCCESS) {
  3374. dwSize += (lstrlenW(szSrc) +1) * sizeof(WCHAR);
  3375. if (*pdwBufferSize >= dwSize) {
  3376. lstrcpyW (szString, szSrc);
  3377. szString += lstrlenW (szString) + 1;
  3378. szString = (LPWSTR)ALIGN_ON_DWORD (szString);
  3379. dwSize = (DWORD)((LPBYTE)szString - (LPBYTE)pCounterPathElements);
  3380. } else {
  3381. // not enough room
  3382. pdhStatus = PDH_INSUFFICIENT_BUFFER;
  3383. }
  3384. }
  3385. } else {
  3386. pCounterPathElements->szObjectName = NULL;
  3387. }
  3388. if (pdhStatus == ERROR_SUCCESS) {
  3389. if (pLocalCounterPath->szInstanceName != NULL) {
  3390. pCounterPathElements->szInstanceName = szString;
  3391. szSrc = pLocalCounterPath->szInstanceName;
  3392. dwSize += (lstrlenW(szSrc) +1) * sizeof(WCHAR);
  3393. if (*pdwBufferSize >= dwSize) {
  3394. lstrcpyW (szString, szSrc);
  3395. szString += lstrlenW (szString) + 1;
  3396. szString = (LPWSTR)ALIGN_ON_DWORD (szString);
  3397. dwSize = (DWORD)((LPBYTE)szString - (LPBYTE)pCounterPathElements);
  3398. } else {
  3399. // not enough room
  3400. pdhStatus = PDH_INSUFFICIENT_BUFFER;
  3401. }
  3402. if (pLocalCounterPath->szParentName != NULL) {
  3403. pCounterPathElements->szParentInstance = szString;
  3404. szSrc = pLocalCounterPath->szParentName;
  3405. dwSize += (lstrlenW(szSrc) +1) * sizeof(WCHAR);
  3406. if (*pdwBufferSize >= dwSize) {
  3407. lstrcpyW (szString, szSrc);
  3408. szString += lstrlenW (szString) + 1;
  3409. szString = (LPWSTR)ALIGN_ON_DWORD (szString);
  3410. dwSize = (DWORD)((LPBYTE)szString - (LPBYTE)pCounterPathElements);
  3411. } else {
  3412. // not enough room
  3413. pdhStatus = PDH_INSUFFICIENT_BUFFER;
  3414. }
  3415. } else {
  3416. pCounterPathElements->szParentInstance = NULL;
  3417. }
  3418. pCounterPathElements->dwInstanceIndex =
  3419. pLocalCounterPath->dwIndex;
  3420. } else {
  3421. pCounterPathElements->szInstanceName = NULL;
  3422. pCounterPathElements->szParentInstance = NULL;
  3423. pCounterPathElements->dwInstanceIndex = (DWORD)-1;
  3424. }
  3425. }
  3426. if (pdhStatus == ERROR_SUCCESS) {
  3427. if (pLocalCounterPath->szCounterName != NULL) {
  3428. pCounterPathElements->szCounterName = szString;
  3429. if (dwFlags & PDH_PATH_WBEM_RESULT) {
  3430. if (dwFlags & PDH_PATH_WBEM_INPUT) {
  3431. // just copy
  3432. szSrc = pLocalCounterPath->szCounterName;
  3433. } else {
  3434. // interpret the display name to a property name
  3435. pdhStatus = PdhiWbemGetCounterPropertyName (
  3436. pThisClass,
  3437. pLocalCounterPath->szCounterName,
  3438. wszTempBuffer,
  3439. sizeof(wszTempBuffer) / sizeof(wszTempBuffer[0]));
  3440. if (pdhStatus == ERROR_SUCCESS) {
  3441. szSrc = wszTempBuffer;
  3442. }
  3443. }
  3444. } else {
  3445. if (dwFlags & PDH_PATH_WBEM_INPUT) {
  3446. // translate class name to a display name
  3447. pdhStatus = PdhiWbemGetCounterDisplayName (
  3448. pThisClass, pLocalCounterPath->szCounterName,
  3449. wszTempBuffer,
  3450. sizeof(wszTempBuffer) / sizeof(wszTempBuffer[0]));
  3451. if (pdhStatus == ERROR_SUCCESS) {
  3452. szSrc = wszTempBuffer;
  3453. }
  3454. } else {
  3455. assert (dwFlags != 0); // this should be caught earlier
  3456. }
  3457. }
  3458. dwSize += (lstrlenW(szSrc) +1) * sizeof(WCHAR);
  3459. if (*pdwBufferSize >= dwSize) {
  3460. lstrcpyW (szString, szSrc);
  3461. szString += lstrlenW (szString) + 1;
  3462. szString = (LPWSTR)ALIGN_ON_DWORD (szString);
  3463. dwSize = (DWORD)((LPBYTE)szString - (LPBYTE)pCounterPathElements);
  3464. } else {
  3465. // not enough room
  3466. pdhStatus = PDH_INSUFFICIENT_BUFFER;
  3467. }
  3468. } else {
  3469. pCounterPathElements->szCounterName = NULL;
  3470. }
  3471. }
  3472. } // If pdhStatus == ERROR_SUCCESS
  3473. if (pdhStatus == ERROR_SUCCESS) {
  3474. dwSize = (DWORD)((LPBYTE)szString - (LPBYTE)pCounterPathElements);
  3475. *pdwBufferSize = dwSize;
  3476. }
  3477. } else {
  3478. // a null buffer pointer was passed int
  3479. pdhStatus = PDH_INVALID_ARGUMENT;
  3480. }
  3481. } else {
  3482. // this is just a size check so return size required
  3483. *pdwBufferSize = dwSize * 2; // doubled to insure room for path expansions
  3484. pdhStatus = ERROR_SUCCESS;
  3485. }
  3486. } else {
  3487. // unable to read path
  3488. pdhStatus = PDH_INVALID_PATH;
  3489. }
  3490. // release class object if used
  3491. //if (pThisClass != NULL) pThisClass->Release();
  3492. // Cleanup pThisServer if used
  3493. if ( NULL != pThisServer )
  3494. {
  3495. if (pdhStatus == ERROR_SUCCESS) {
  3496. pdhStatus = PdhiDisconnectWbemServer (pThisServer);
  3497. } else {
  3498. // don't trash the return status
  3499. PdhiDisconnectWbemServer (pThisServer);
  3500. }
  3501. }
  3502. }
  3503. G_FREE (pLocalCounterPath);
  3504. } else {
  3505. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  3506. }
  3507. // CoUninitialize if necessary
  3508. if ( fCoInitialized )
  3509. {
  3510. PdhiCoUninitialize();
  3511. }
  3512. return pdhStatus;
  3513. }
  3514. PDH_FUNCTION
  3515. PdhiDecodeWbemPathA (
  3516. IN LPCSTR szFullPathBuffer,
  3517. IN PDH_COUNTER_PATH_ELEMENTS_A *pCounterPathElements,
  3518. IN LPDWORD pdwBufferSize,
  3519. IN LANGID LangId,
  3520. IN DWORD dwFlags
  3521. )
  3522. {
  3523. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  3524. LPWSTR wszWidePath = NULL;
  3525. PDH_COUNTER_PATH_ELEMENTS_W *pWideElements = NULL;
  3526. DWORD dwSize;
  3527. DWORD dwDest = 0;
  3528. LONG lSizeRemaining;
  3529. LPSTR szNextString;
  3530. wszWidePath = (LPWSTR)G_ALLOC((lstrlenA(szFullPathBuffer) + 1) * sizeof(WCHAR));
  3531. if (wszWidePath == NULL) {
  3532. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  3533. }
  3534. if (pdhStatus == ERROR_SUCCESS) {
  3535. // compute size of temp element buffer
  3536. lSizeRemaining = * pdwBufferSize - sizeof(PDH_COUNTER_PATH_ELEMENTS_A);
  3537. dwSize = * pdwBufferSize - sizeof(PDH_COUNTER_PATH_ELEMENTS_A);
  3538. // dwSize now has the size of the buffer AFTER the structure so
  3539. // adjust this for the longer char length to make it a fair comparison
  3540. dwSize *= sizeof(WCHAR)/sizeof(CHAR);
  3541. // and add back in the structure
  3542. dwSize += sizeof(PDH_COUNTER_PATH_ELEMENTS_W);
  3543. if (pCounterPathElements != NULL) {
  3544. pWideElements = (PDH_COUNTER_PATH_ELEMENTS_W *) G_ALLOC(dwSize);
  3545. if (pWideElements == NULL) {
  3546. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  3547. }
  3548. } else {
  3549. pWideElements = NULL;
  3550. pdhStatus = ERROR_SUCCESS;
  3551. }
  3552. }
  3553. if (pdhStatus == ERROR_SUCCESS) {
  3554. // convert path to Wide
  3555. MultiByteToWideChar(_getmbcp(),
  3556. 0,
  3557. szFullPathBuffer,
  3558. lstrlenA(szFullPathBuffer),
  3559. wszWidePath,
  3560. lstrlenA(szFullPathBuffer) + 1);
  3561. pdhStatus = PdhiDecodeWbemPathW (
  3562. wszWidePath,
  3563. pWideElements,
  3564. & dwSize,
  3565. LangId,
  3566. dwFlags);
  3567. if (pdhStatus == ERROR_SUCCESS) {
  3568. if (pCounterPathElements != NULL) {
  3569. // populate the fields of the caller's buffer
  3570. szNextString = (LPSTR)&pCounterPathElements[1];
  3571. if ( pWideElements->szMachineName != NULL
  3572. && lSizeRemaining > 0) {
  3573. dwDest = lSizeRemaining;
  3574. pdhStatus = PdhiConvertUnicodeToAnsi(_getmbcp(),
  3575. pWideElements->szMachineName,
  3576. szNextString,
  3577. & dwDest);
  3578. if (pdhStatus == ERROR_SUCCESS) {
  3579. pCounterPathElements->szMachineName = szNextString;
  3580. szNextString += dwDest + 1;
  3581. }
  3582. else {
  3583. pCounterPathElements->szMachineName = NULL;
  3584. }
  3585. lSizeRemaining -= dwDest + 1;
  3586. } else {
  3587. pCounterPathElements->szMachineName = NULL;
  3588. }
  3589. if ( pWideElements->szObjectName != NULL
  3590. && lSizeRemaining > 0) {
  3591. dwDest = lSizeRemaining;
  3592. pdhStatus = PdhiConvertUnicodeToAnsi(_getmbcp(),
  3593. pWideElements->szObjectName,
  3594. szNextString,
  3595. & dwDest);
  3596. if (pdhStatus == ERROR_SUCCESS) {
  3597. pCounterPathElements->szObjectName = szNextString;
  3598. szNextString += dwDest + 1;
  3599. }
  3600. else {
  3601. pCounterPathElements->szObjectName = NULL;
  3602. }
  3603. lSizeRemaining -= dwDest + 1;
  3604. } else {
  3605. pCounterPathElements->szObjectName = NULL;
  3606. }
  3607. if ( pWideElements->szInstanceName != NULL
  3608. && lSizeRemaining > 0) {
  3609. dwDest = lSizeRemaining;
  3610. pdhStatus = PdhiConvertUnicodeToAnsi(_getmbcp(),
  3611. pWideElements->szInstanceName,
  3612. szNextString,
  3613. & dwDest);
  3614. if (pdhStatus == ERROR_SUCCESS) {
  3615. pCounterPathElements->szInstanceName = szNextString;
  3616. szNextString += dwDest + 1;
  3617. }
  3618. else {
  3619. pCounterPathElements->szInstanceName = NULL;
  3620. }
  3621. lSizeRemaining -= dwDest + 1;
  3622. } else {
  3623. pCounterPathElements->szInstanceName = NULL;
  3624. }
  3625. if ( pWideElements->szParentInstance != NULL
  3626. && lSizeRemaining > 0) {
  3627. dwDest = lSizeRemaining;
  3628. pdhStatus = PdhiConvertUnicodeToAnsi(_getmbcp(),
  3629. pWideElements->szParentInstance,
  3630. szNextString,
  3631. & dwDest);
  3632. if (pdhStatus == ERROR_SUCCESS) {
  3633. pCounterPathElements->szParentInstance = szNextString;
  3634. szNextString += dwDest + 1;
  3635. }
  3636. else {
  3637. pCounterPathElements->szParentInstance = NULL;
  3638. }
  3639. lSizeRemaining -= dwDest + 1;
  3640. } else {
  3641. pCounterPathElements->szParentInstance = NULL;
  3642. }
  3643. if ( pWideElements->szCounterName != NULL
  3644. && lSizeRemaining > 0) {
  3645. dwDest = lSizeRemaining;
  3646. pdhStatus = PdhiConvertUnicodeToAnsi(_getmbcp(),
  3647. pWideElements->szObjectName,
  3648. szNextString,
  3649. & dwDest);
  3650. if (pdhStatus == ERROR_SUCCESS) {
  3651. pCounterPathElements->szCounterName = szNextString;
  3652. szNextString += dwDest + 1;
  3653. }
  3654. else {
  3655. pCounterPathElements->szCounterName = NULL;
  3656. }
  3657. lSizeRemaining -= dwDest + 1;
  3658. } else {
  3659. pCounterPathElements->szCounterName = NULL;
  3660. }
  3661. pCounterPathElements->dwInstanceIndex =
  3662. pWideElements->dwInstanceIndex;
  3663. *pdwBufferSize = (DWORD)((LPBYTE)szNextString - (LPBYTE)pCounterPathElements);
  3664. } else {
  3665. // just return the size required adjusted for wide/ansi characters
  3666. *pdwBufferSize = sizeof(PDH_COUNTER_PATH_ELEMENTS_A);
  3667. dwSize -= sizeof(PDH_COUNTER_PATH_ELEMENTS_W);
  3668. dwSize /= sizeof(WCHAR)/sizeof(CHAR);
  3669. *pdwBufferSize += dwSize;
  3670. }
  3671. } else {
  3672. // call to wide function failed so just return error
  3673. }
  3674. } else {
  3675. // memory allocation failed so return error
  3676. }
  3677. if (pWideElements != NULL) G_FREE(pWideElements);
  3678. if (wszWidePath != NULL) G_FREE(wszWidePath);
  3679. return pdhStatus;
  3680. }
  3681. BOOL
  3682. WbemInitCounter (
  3683. IN PPDHI_COUNTER pCounter
  3684. )
  3685. /*++
  3686. Routine Description:
  3687. Initialized the counter data structure by:
  3688. Allocating the memory block to contain the counter structure
  3689. and all the associated data fields. If this allocation
  3690. is successful, then the fields are initialized by
  3691. verifying the counter is valid.
  3692. Arguments:
  3693. IN PPDHI_COUNTER pCounter
  3694. pointer of the counter to initialize using the system data
  3695. Return Value:
  3696. TRUE if the counter was successfully initialized
  3697. FALSE if a problem was encountered
  3698. In either case, the CStatus field of the structure is updated to
  3699. indicate the status of the operation.
  3700. --*/
  3701. {
  3702. DWORD dwResult;
  3703. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  3704. PPDHI_WBEM_SERVER_DEF pWbemServer = NULL;
  3705. DWORD dwLastError = ERROR_SUCCESS;
  3706. HRESULT hRes = S_OK;
  3707. VARIANT vCountertype;
  3708. WCHAR szBasePropertyName[MAX_PATH];
  3709. WCHAR szFreqPropertyName[MAX_PATH];
  3710. WCHAR szWbemItemPath[MAX_PATH];
  3711. ULONGLONG llValue;
  3712. LONG lOffset;
  3713. PPDH_COUNTER_PATH_ELEMENTS_W pPathElem = NULL;
  3714. BOOL bReturn = TRUE;
  3715. DWORD dwBufferSize = 0;
  3716. BSTR bsPropName = NULL;
  3717. BSTR bsCountertype = NULL;
  3718. IWbemQualifierSet *pQualSet = NULL;
  3719. PPDHI_COUNTER pCounterInList = NULL;
  3720. PPDHI_COUNTER_PATH pPdhiCtrPath = NULL;
  3721. BOOL bMatchFound;
  3722. DWORD bDisconnectServer = FALSE;
  3723. // CoInitialize() if we need to
  3724. BOOL fCoInitialized = PdhiCoInitialize();
  3725. VariantInit (&vCountertype);
  3726. pCounter->dwFlags |= PDHIC_WBEM_COUNTER; // make sure WBEM flag is set
  3727. // make sure the query has a refresher started already
  3728. if (pCounter->pOwner->pRefresher == NULL) {
  3729. // it hasn't been started so start now
  3730. dwResult = CoCreateRefresher( &pCounter->pOwner->pRefresher );
  3731. if ((dwResult != S_OK) || (pCounter->pOwner->pRefresher == NULL)) {
  3732. pCounter->pOwner->pRefresher = NULL;
  3733. dwLastError = PDH_WBEM_ERROR;
  3734. bReturn = FALSE;
  3735. } else {
  3736. // open config interface
  3737. dwResult = pCounter->pOwner->pRefresher->QueryInterface (
  3738. IID_IWbemConfigureRefresher,
  3739. (LPVOID *)&pCounter->pOwner->pRefresherCfg);
  3740. if (dwResult != S_OK) {
  3741. pCounter->pOwner->pRefresherCfg = NULL;
  3742. pCounter->pOwner->pRefresher->Release();
  3743. pCounter->pOwner->pRefresher = NULL;
  3744. dwLastError = PDH_WBEM_ERROR;
  3745. bReturn = FALSE;
  3746. }
  3747. }
  3748. }
  3749. if (bReturn) {
  3750. // so far so good, now figure out the WBEM path to add it to the
  3751. // refresher
  3752. dwBufferSize = lstrlenW(pCounter->szFullName) * sizeof(WCHAR) * 10;
  3753. dwBufferSize += sizeof (PDH_COUNTER_PATH_ELEMENTS_W);
  3754. pPathElem = (PPDH_COUNTER_PATH_ELEMENTS_W) G_ALLOC (dwBufferSize);
  3755. // the path is display names, so convert to WBEM class names first
  3756. if (pPathElem == NULL) {
  3757. dwLastError = PDH_MEMORY_ALLOCATION_FAILURE;
  3758. bReturn = FALSE;
  3759. } else {
  3760. pdhStatus = PdhiDecodeWbemPathW (
  3761. pCounter->szFullName,
  3762. pPathElem,
  3763. &dwBufferSize,
  3764. pCounter->pOwner->LangID,
  3765. PDH_PATH_WBEM_RESULT);
  3766. if (pdhStatus == ERROR_SUCCESS) {
  3767. // continue
  3768. } else {
  3769. dwLastError = PDH_INVALID_PATH;
  3770. bReturn = FALSE;
  3771. }
  3772. }
  3773. }
  3774. if (bReturn) {
  3775. dwBufferSize *= 8; // just to be safe
  3776. pPdhiCtrPath = (PPDHI_COUNTER_PATH) G_ALLOC (dwBufferSize);
  3777. if (pPdhiCtrPath == NULL) {
  3778. dwLastError = PDH_MEMORY_ALLOCATION_FAILURE;
  3779. bReturn = FALSE;
  3780. } else {
  3781. // break path into display elements
  3782. bReturn = ParseFullPathNameW (
  3783. pCounter->szFullName,
  3784. &dwBufferSize,
  3785. pPdhiCtrPath,
  3786. FALSE);
  3787. if (bReturn) {
  3788. // realloc to use only the memory needed
  3789. pCounter->pCounterPath = (PPDHI_COUNTER_PATH)
  3790. G_REALLOC (pPdhiCtrPath, dwBufferSize);
  3791. if ((pPdhiCtrPath != pCounter->pCounterPath) &&
  3792. (pCounter->pCounterPath != NULL)){
  3793. // the memory block moved so
  3794. // correct addresses inside structure
  3795. lOffset = (LONG)((ULONG_PTR)pCounter->pCounterPath -
  3796. (ULONG_PTR)pPdhiCtrPath);
  3797. if (pCounter->pCounterPath->szMachineName) {
  3798. pCounter->pCounterPath->szMachineName = (LPWSTR)(
  3799. (LPBYTE)pCounter->pCounterPath->szMachineName + lOffset);
  3800. }
  3801. if (pCounter->pCounterPath->szObjectName) {
  3802. pCounter->pCounterPath->szObjectName = (LPWSTR)(
  3803. (LPBYTE)pCounter->pCounterPath->szObjectName + lOffset);
  3804. }
  3805. if (pCounter->pCounterPath->szInstanceName) {
  3806. pCounter->pCounterPath->szInstanceName = (LPWSTR)(
  3807. (LPBYTE)pCounter->pCounterPath->szInstanceName + lOffset);
  3808. }
  3809. if (pCounter->pCounterPath->szParentName) {
  3810. pCounter->pCounterPath->szParentName = (LPWSTR)(
  3811. (LPBYTE)pCounter->pCounterPath->szParentName + lOffset);
  3812. }
  3813. if (pCounter->pCounterPath->szCounterName) {
  3814. pCounter->pCounterPath->szCounterName = (LPWSTR)(
  3815. (LPBYTE)pCounter->pCounterPath->szCounterName + lOffset);
  3816. }
  3817. }
  3818. } else {
  3819. // free the buffer
  3820. G_FREE (pPdhiCtrPath);
  3821. dwLastError = PDH_WBEM_ERROR;
  3822. }
  3823. }
  3824. }
  3825. // connect to the WBEM Server on that machine
  3826. if (bReturn) {
  3827. pdhStatus = PdhiConnectWbemServer (
  3828. pCounter->pCounterPath->szMachineName,
  3829. &pWbemServer);
  3830. if (pdhStatus != ERROR_SUCCESS) {
  3831. dwLastError = pdhStatus;
  3832. bReturn = FALSE;
  3833. } else {
  3834. bDisconnectServer = TRUE;
  3835. }
  3836. }
  3837. if (bReturn) {
  3838. // make WBEM Instance path out of path elements
  3839. pdhStatus = PdhiMakeWbemInstancePath (
  3840. pPathElem,
  3841. szWbemItemPath,
  3842. TRUE);
  3843. // check for an object/class of this type that has already been added
  3844. // walk down counter list to find a matching:
  3845. // machine\namespace
  3846. // object
  3847. // instance name
  3848. if (pdhStatus != ERROR_SUCCESS) {
  3849. dwLastError = pdhStatus;
  3850. bReturn = FALSE;
  3851. }
  3852. }
  3853. if (bReturn) {
  3854. assert (pCounter->pWbemObject == NULL);
  3855. assert (pCounter->lWbemRefreshId == 0);
  3856. pCounterInList = pCounter->pOwner->pCounterListHead;
  3857. if (pCounterInList == NULL) {
  3858. // then there are no entries to search so continue
  3859. } else {
  3860. do {
  3861. // check for matching machine name
  3862. bMatchFound = FALSE;
  3863. if (lstrcmpiW(pCounterInList->pCounterPath->szMachineName,
  3864. pCounter->pCounterPath->szMachineName) == 0) {
  3865. // then the machine name matches
  3866. if (lstrcmpiW (pCounterInList->pCounterPath->szObjectName,
  3867. pCounter->pCounterPath->szObjectName) == 0) {
  3868. // then the object name matches
  3869. // see if the instance matches
  3870. if (lstrcmpiW (pCounterInList->pCounterPath->szInstanceName,
  3871. pCounter->pCounterPath->szInstanceName) == 0) {
  3872. if (pCounter->pCounterPath->szParentName != 0) {
  3873. if (lstrcmpiW (pCounterInList->pCounterPath->szParentName,
  3874. pCounter->pCounterPath->szParentName) == 0) {
  3875. // then this is a match
  3876. bMatchFound = TRUE;
  3877. } else {
  3878. // not a match
  3879. }
  3880. } else {
  3881. // this is a match
  3882. bMatchFound = TRUE;
  3883. }
  3884. if (bMatchFound) {
  3885. if ((pCounter->pCounterPath->szInstanceName != NULL) &&
  3886. (*pCounter->pCounterPath->szInstanceName == SPLAT_L)) {
  3887. // then this is a Wild Card or multiple instance path
  3888. // see if an enumerator for this object has already been created
  3889. // if so, then AddRef it
  3890. if (pCounterInList->pWbemEnum != NULL) {
  3891. pCounter->pWbemObject = pCounterInList->pWbemObject;
  3892. pCounter->pWbemEnum = pCounterInList->pWbemEnum;
  3893. // bump the ref counts on this object so it
  3894. // doesn't disapper from us
  3895. pCounter->pWbemObject->AddRef();
  3896. pCounter->pWbemEnum->AddRef();
  3897. pCounter->lWbemEnumId = pCounterInList->lWbemEnumId;
  3898. pCounter->dwFlags |= PDHIC_MULTI_INSTANCE;
  3899. }
  3900. // and exit loop
  3901. hRes = S_OK;
  3902. break;
  3903. } else {
  3904. // then it's a regular instance the instance name matches
  3905. // so get the Object pointer
  3906. pCounter->pWbemObject = pCounterInList->pWbemObject;
  3907. pCounter->pWbemAccess = pCounterInList->pWbemAccess;
  3908. // bump the ref counts on this object so it
  3909. // doesn't disapper from us
  3910. pCounter->pWbemObject->AddRef();
  3911. pCounter->pWbemAccess->AddRef();
  3912. pCounter->lWbemRefreshId = pCounterInList->lWbemRefreshId;
  3913. // and exit loop
  3914. hRes = S_OK;
  3915. break;
  3916. }
  3917. } else {
  3918. // no match so go to next one
  3919. }
  3920. } else {
  3921. // no match so go to next one
  3922. }
  3923. } else {
  3924. // no match so go to next one
  3925. }
  3926. } else {
  3927. // no match so go to next counter
  3928. }
  3929. pCounterInList = pCounterInList->next.flink;
  3930. } while (pCounterInList != pCounter->pOwner->pCounterListHead);
  3931. }
  3932. bDontRefresh = TRUE;
  3933. // determine if we should and an object or an enumerator
  3934. if ((pCounter->pCounterPath->szInstanceName != NULL) &&
  3935. (*pCounter->pCounterPath->szInstanceName == SPLAT_L)) {
  3936. // then this is an enum type so see if there's already one assigned
  3937. // if not, then create one
  3938. if (pCounter->pWbemEnum == NULL) {
  3939. if (pCounter->pOwner->pRefresherCfg != NULL) {
  3940. hRes = pCounter->pOwner->pRefresherCfg->AddEnum(
  3941. pWbemServer->pSvc,
  3942. pPathElem->szObjectName,
  3943. WBEM_FLAG_USE_AMENDED_QUALIFIERS, 0,
  3944. &pCounter->pWbemEnum,
  3945. &pCounter->lWbemEnumId);
  3946. } else {
  3947. hRes = WBEM_E_INITIALIZATION_FAILURE;
  3948. }
  3949. if (hRes != S_OK) {
  3950. bReturn = FALSE;
  3951. dwLastError = PDH_WBEM_ERROR;
  3952. } else {
  3953. pdhStatus = PdhiWbemGetClassObjectByName (
  3954. pWbemServer,
  3955. pPathElem->szObjectName,
  3956. &pCounter->pWbemObject);
  3957. }
  3958. // set multi instance flag
  3959. pCounter->dwFlags |= PDHIC_MULTI_INSTANCE;
  3960. } else {
  3961. // we must have copied another one so continue
  3962. }
  3963. } else {
  3964. // this is a single counter
  3965. if (pCounter->pWbemObject == NULL) {
  3966. // and it hasn't been added yet, so just add one object
  3967. if (pCounter->pOwner->pRefresherCfg != NULL) {
  3968. hRes = pCounter->pOwner->pRefresherCfg->AddObjectByPath (
  3969. pWbemServer->pSvc,
  3970. szWbemItemPath,
  3971. WBEM_FLAG_USE_AMENDED_QUALIFIERS, 0,
  3972. &pCounter->pWbemObject,
  3973. &pCounter->lWbemRefreshId);
  3974. } else {
  3975. hRes = WBEM_E_INITIALIZATION_FAILURE;
  3976. }
  3977. if (hRes != S_OK) {
  3978. bReturn = FALSE;
  3979. dwLastError = PDH_WBEM_ERROR;
  3980. }
  3981. } else {
  3982. // it must have been copied from another
  3983. }
  3984. }
  3985. if (hRes == S_OK) {
  3986. // get handles for subsequent data collection from this object
  3987. hRes = pCounter->pWbemObject->QueryInterface (IID_IWbemObjectAccess,
  3988. (LPVOID *)&pCounter->pWbemAccess);
  3989. if (hRes == S_OK) {
  3990. if (!PdhiIsSingletonClass (pCounter->pWbemObject)) {
  3991. CIMTYPE cimType = 0;
  3992. bsPropName = SysAllocString(cszName);
  3993. if (bsPropName) {
  3994. // get handle to the name property for this counter
  3995. hRes = pCounter->pWbemAccess->GetPropertyHandle (
  3996. bsPropName, &cimType,
  3997. &pCounter->lNameHandle);
  3998. if (hRes != S_OK) {
  3999. dwLastError = PDH_WBEM_ERROR;
  4000. }
  4001. assert (cimType == CIM_STRING);
  4002. } else {
  4003. dwLastError = PDH_MEMORY_ALLOCATION_FAILURE;
  4004. hRes = WBEM_E_OUT_OF_MEMORY;
  4005. }
  4006. } else {
  4007. pCounter->lNameHandle = -1;
  4008. }
  4009. if (hRes == S_OK) {
  4010. // get handle to the data property for this counter
  4011. hRes = pCounter->pWbemAccess->GetPropertyHandle (
  4012. pPathElem->szCounterName, &pCounter->lNumItemType,
  4013. &pCounter->lNumItemHandle);
  4014. assert (hRes == S_OK);
  4015. // get counter type field
  4016. // first get the property qualifiers
  4017. PdhiSysFreeString (&bsPropName);
  4018. bsPropName = SysAllocString (pPathElem->szCounterName);
  4019. if (bsPropName) {
  4020. hRes = pCounter->pWbemObject->GetPropertyQualifierSet (
  4021. bsPropName, &pQualSet);
  4022. } else {
  4023. hRes = WBEM_E_OUT_OF_MEMORY;
  4024. }
  4025. if (hRes == WBEM_NO_ERROR) {
  4026. // now get the specific value
  4027. VariantClear (&vCountertype);
  4028. bsCountertype = SysAllocString (cszCountertype);
  4029. if (bsCountertype) {
  4030. hRes = pQualSet->Get (bsCountertype, 0, &vCountertype, NULL);
  4031. if (hRes == WBEM_NO_ERROR) {
  4032. pCounter->plCounterInfo.dwCounterType = (DWORD)V_I4(&vCountertype);
  4033. } else {
  4034. pCounter->plCounterInfo.dwCounterType = 0;
  4035. }
  4036. PdhiSysFreeString (&bsCountertype);
  4037. } else {
  4038. hRes = WBEM_E_OUT_OF_MEMORY;
  4039. }
  4040. if (hRes == WBEM_NO_ERROR) {
  4041. // if this is a fraction counter that has a "base" value
  4042. // then look it up by appending the "base" string to the
  4043. // property name
  4044. if ((pCounter->plCounterInfo.dwCounterType == PERF_SAMPLE_FRACTION) ||
  4045. (pCounter->plCounterInfo.dwCounterType == PERF_AVERAGE_TIMER) ||
  4046. (pCounter->plCounterInfo.dwCounterType == PERF_AVERAGE_BULK) ||
  4047. (pCounter->plCounterInfo.dwCounterType == PERF_LARGE_RAW_FRACTION) ||
  4048. (pCounter->plCounterInfo.dwCounterType == PERF_RAW_FRACTION)) {
  4049. // make sure we have room for the "_Base" string
  4050. assert (lstrlenW(pPathElem->szCounterName) < (MAX_PATH - 6));
  4051. lstrcpyW (szBasePropertyName, pPathElem->szCounterName);
  4052. lstrcatW (szBasePropertyName, cszBaseSuffix);
  4053. // get the handle to the denominator
  4054. hRes = pCounter->pWbemAccess->GetPropertyHandle (
  4055. szBasePropertyName, &pCounter->lDenItemType,
  4056. &pCounter->lDenItemHandle);
  4057. assert (hRes == S_OK);
  4058. } else {
  4059. // the denominator is a time field
  4060. if ((pCounter->plCounterInfo.dwCounterType & PERF_TIMER_FIELD) == PERF_TIMER_TICK) {
  4061. // use the system perf time timestamp as the denominator
  4062. lstrcpyW (szBasePropertyName, cszTimestampPerfTime);
  4063. lstrcpyW (szFreqPropertyName, cszFrequencyPerfTime);
  4064. } else if ((pCounter->plCounterInfo.dwCounterType & PERF_TIMER_FIELD) == PERF_TIMER_100NS) {
  4065. lstrcpyW (szBasePropertyName, cszTimestampSys100Ns);
  4066. lstrcpyW (szFreqPropertyName, cszFrequencySys100Ns);
  4067. } else if ((pCounter->plCounterInfo.dwCounterType & PERF_TIMER_FIELD) == PERF_OBJECT_TIMER) {
  4068. lstrcpyW (szBasePropertyName, cszTimestampObject);
  4069. lstrcpyW (szFreqPropertyName, cszFrequencyObject);
  4070. } else {
  4071. assert (FALSE); // this should never happen
  4072. }
  4073. // get the handle to the denominator
  4074. hRes = pCounter->pWbemAccess->GetPropertyHandle (
  4075. szBasePropertyName, &pCounter->lDenItemType,
  4076. &pCounter->lDenItemHandle);
  4077. assert (hRes == S_OK);
  4078. // get the handle to the frequency
  4079. hRes = pCounter->pWbemAccess->GetPropertyHandle (
  4080. szFreqPropertyName, &pCounter->lFreqItemType,
  4081. &pCounter->lFreqItemHandle);
  4082. assert (hRes == S_OK);
  4083. }
  4084. // get the default scale value of this counter
  4085. VariantClear (&vCountertype);
  4086. PdhiSysFreeString (&bsCountertype);
  4087. bsCountertype = SysAllocString (cszDefaultscale);
  4088. if (bsCountertype) {
  4089. hRes = pQualSet->Get (bsCountertype, 0, &vCountertype, NULL);
  4090. if (hRes == WBEM_NO_ERROR) {
  4091. pCounter->lScale = 0;
  4092. pCounter->plCounterInfo.lDefaultScale = (DWORD)V_I4(&vCountertype);
  4093. } else {
  4094. pCounter->plCounterInfo.lDefaultScale = 0;
  4095. pCounter->lScale = 0;
  4096. }
  4097. // this may not be initialized but we try anyway
  4098. if ((pCounter->lFreqItemType == VT_I8) ||
  4099. (pCounter->lFreqItemType == VT_UI8)) {
  4100. pCounter->pWbemAccess->ReadQWORD (
  4101. pCounter->lFreqItemHandle, &llValue);
  4102. } else {
  4103. llValue = 0;
  4104. }
  4105. // the timebase is a 64 bit integer
  4106. pCounter->TimeBase = llValue;
  4107. } else {
  4108. hRes = WBEM_E_OUT_OF_MEMORY;
  4109. }
  4110. }
  4111. PdhiSysFreeString (&bsCountertype);
  4112. pQualSet->Release();
  4113. } else {
  4114. if (hRes == WBEM_E_OUT_OF_MEMORY) {
  4115. dwLastError = PDH_MEMORY_ALLOCATION_FAILURE;
  4116. } else {
  4117. dwLastError = PDH_WBEM_ERROR;
  4118. }
  4119. bReturn = FALSE;
  4120. }
  4121. } // else an error has ocurred
  4122. PdhiSysFreeString (&bsPropName);
  4123. } else {
  4124. dwLastError = PDH_WBEM_ERROR;
  4125. bReturn = FALSE;
  4126. }
  4127. } else {
  4128. dwLastError = PDH_WBEM_ERROR;
  4129. bReturn = FALSE;
  4130. }
  4131. if (bReturn) {
  4132. // clear the not init'd flag to say it's ok to use now
  4133. pCounter->dwFlags &= ~PDHIC_COUNTER_NOT_INIT;
  4134. }
  4135. bDontRefresh = FALSE;
  4136. }
  4137. if (bReturn) {
  4138. if (!AssignCalcFunction (
  4139. pCounter->plCounterInfo.dwCounterType,
  4140. &pCounter->CalcFunc,
  4141. &pCounter->StatFunc)) {
  4142. dwLastError = PDH_FUNCTION_NOT_FOUND;
  4143. bReturn = FALSE;
  4144. }
  4145. }
  4146. if (pPathElem != NULL) G_FREE(pPathElem);
  4147. VariantClear (&vCountertype);
  4148. if (bDisconnectServer) {
  4149. if (pdhStatus == ERROR_SUCCESS) {
  4150. pdhStatus = PdhiDisconnectWbemServer (pWbemServer);
  4151. } else {
  4152. // keep error code from function body
  4153. PdhiDisconnectWbemServer (pWbemServer);
  4154. }
  4155. }
  4156. if (!bReturn) SetLastError (dwLastError);
  4157. // CoUninitialize if necessary
  4158. if ( fCoInitialized )
  4159. {
  4160. PdhiCoUninitialize();
  4161. }
  4162. return bReturn;
  4163. }
  4164. BOOL
  4165. UpdateWbemCounterValue (
  4166. IN PPDHI_COUNTER pCounter,
  4167. IN FILETIME *pTimeStamp
  4168. )
  4169. {
  4170. DWORD LocalCStatus = 0;
  4171. DWORD LocalCType = 0;
  4172. ULONGLONG llValue;
  4173. DWORD dwValue;
  4174. BOOL bReturn = FALSE;
  4175. // move current value to last value buffer
  4176. pCounter->LastValue = pCounter->ThisValue;
  4177. // and clear the old value
  4178. pCounter->ThisValue.MultiCount = 1;
  4179. pCounter->ThisValue.FirstValue =
  4180. pCounter->ThisValue.SecondValue = 0;
  4181. pCounter->ThisValue.TimeStamp = *pTimeStamp;
  4182. // get the counter's machine status first. There's no point in
  4183. // contuning if the machine is offline
  4184. // UpdateWbemCounterValue() will be called only if WBEM refresher succeeds
  4185. // in GetQueryWbemData(); that is, all remote machines should be on-line
  4186. LocalCStatus = ERROR_SUCCESS;
  4187. if (IsSuccessSeverity(LocalCStatus)) {
  4188. // get the pointer to the counter data
  4189. LocalCType = pCounter->plCounterInfo.dwCounterType;
  4190. switch (LocalCType) {
  4191. //
  4192. // these counter types are loaded as:
  4193. // Numerator = Counter data from perf data block
  4194. // Denominator = Perf Time from perf data block
  4195. // (the time base is the PerfFreq)
  4196. //
  4197. case PERF_COUNTER_COUNTER:
  4198. case PERF_COUNTER_QUEUELEN_TYPE:
  4199. case PERF_SAMPLE_COUNTER:
  4200. // this should be a DWORD counter
  4201. assert ((pCounter->lNumItemType == VT_I4) ||
  4202. (pCounter->lNumItemType == VT_UI4));
  4203. pCounter->pWbemAccess->ReadDWORD (
  4204. pCounter->lNumItemHandle, &dwValue);
  4205. pCounter->ThisValue.FirstValue = (LONGLONG)(dwValue);
  4206. assert ((pCounter->lDenItemType == VT_I8) ||
  4207. (pCounter->lDenItemType == VT_UI8));
  4208. pCounter->pWbemAccess->ReadQWORD (
  4209. pCounter->lDenItemHandle, &llValue);
  4210. // the denominator should be a 64-bit timestamp
  4211. pCounter->ThisValue.SecondValue = llValue;
  4212. // look up the timebase freq if necessary
  4213. if (pCounter->TimeBase == 0) {
  4214. assert ((pCounter->lFreqItemType == VT_I8) ||
  4215. (pCounter->lFreqItemType == VT_UI8));
  4216. pCounter->pWbemAccess->ReadQWORD (
  4217. pCounter->lFreqItemHandle, &llValue);
  4218. // the timebase is a 64 bit integer
  4219. pCounter->TimeBase = llValue;
  4220. }
  4221. break;
  4222. case PERF_ELAPSED_TIME:
  4223. case PERF_100NSEC_TIMER:
  4224. case PERF_100NSEC_TIMER_INV:
  4225. case PERF_COUNTER_TIMER:
  4226. case PERF_COUNTER_TIMER_INV:
  4227. case PERF_COUNTER_BULK_COUNT:
  4228. case PERF_COUNTER_MULTI_TIMER:
  4229. case PERF_COUNTER_MULTI_TIMER_INV:
  4230. case PERF_COUNTER_LARGE_QUEUELEN_TYPE:
  4231. case PERF_OBJ_TIME_TIMER:
  4232. case PERF_COUNTER_100NS_QUEUELEN_TYPE:
  4233. case PERF_COUNTER_OBJ_TIME_QUEUELEN_TYPE:
  4234. case PERF_PRECISION_SYSTEM_TIMER:
  4235. case PERF_PRECISION_100NS_TIMER:
  4236. case PERF_PRECISION_OBJECT_TIMER:
  4237. // this should be a QWORD counter
  4238. assert ((pCounter->lNumItemType == VT_I8) ||
  4239. (pCounter->lNumItemType == VT_UI8));
  4240. pCounter->pWbemAccess->ReadQWORD (
  4241. pCounter->lNumItemHandle, &llValue);
  4242. pCounter->ThisValue.FirstValue = (LONGLONG)(llValue);
  4243. assert ((pCounter->lDenItemType == VT_I8) ||
  4244. (pCounter->lDenItemType == VT_UI8));
  4245. pCounter->pWbemAccess->ReadQWORD (
  4246. pCounter->lDenItemHandle, &llValue);
  4247. // the denominator should be a 64-bit timestamp
  4248. pCounter->ThisValue.SecondValue = llValue;
  4249. // look up the timebase freq if necessary
  4250. if (pCounter->TimeBase == 0) {
  4251. assert ((pCounter->lFreqItemType == VT_I8) ||
  4252. (pCounter->lFreqItemType == VT_UI8));
  4253. pCounter->pWbemAccess->ReadQWORD (
  4254. pCounter->lFreqItemHandle, &llValue);
  4255. // the timebase is a 64 bit integer
  4256. pCounter->TimeBase = llValue;
  4257. }
  4258. break;
  4259. //
  4260. // These counters do not use any time reference
  4261. //
  4262. case PERF_COUNTER_RAWCOUNT:
  4263. case PERF_COUNTER_RAWCOUNT_HEX:
  4264. case PERF_COUNTER_DELTA:
  4265. // this should be a DWORD counter
  4266. assert ((pCounter->lNumItemType == VT_I4) ||
  4267. (pCounter->lNumItemType == VT_UI4));
  4268. pCounter->pWbemAccess->ReadDWORD (
  4269. pCounter->lNumItemHandle, &dwValue);
  4270. pCounter->ThisValue.FirstValue = (LONGLONG)(dwValue);
  4271. pCounter->ThisValue.SecondValue = 0;
  4272. break;
  4273. case PERF_COUNTER_LARGE_RAWCOUNT:
  4274. case PERF_COUNTER_LARGE_RAWCOUNT_HEX:
  4275. case PERF_COUNTER_LARGE_DELTA:
  4276. // this should be a DWORD counter
  4277. assert ((pCounter->lNumItemType == VT_I8) ||
  4278. (pCounter->lNumItemType == VT_UI8));
  4279. pCounter->pWbemAccess->ReadQWORD (
  4280. pCounter->lNumItemHandle, &llValue);
  4281. pCounter->ThisValue.FirstValue = (LONGLONG)(llValue);
  4282. pCounter->ThisValue.SecondValue = 0;
  4283. break;
  4284. //
  4285. // These counters use two data points, the one pointed to by
  4286. // pData and the one immediately after
  4287. //
  4288. case PERF_SAMPLE_FRACTION:
  4289. case PERF_RAW_FRACTION:
  4290. // this should be a DWORD counter
  4291. assert ((pCounter->lNumItemType == VT_I4) ||
  4292. (pCounter->lNumItemType == VT_UI4));
  4293. pCounter->pWbemAccess->ReadDWORD (
  4294. pCounter->lNumItemHandle, &dwValue);
  4295. pCounter->ThisValue.FirstValue = (LONGLONG)dwValue;
  4296. assert ((pCounter->lDenItemType == VT_I4) ||
  4297. (pCounter->lDenItemType == VT_UI4));
  4298. pCounter->pWbemAccess->ReadDWORD (
  4299. pCounter->lDenItemHandle, &dwValue);
  4300. // the denominator should be a 32-bit value
  4301. pCounter->ThisValue.SecondValue = (LONGLONG)dwValue;
  4302. break;
  4303. case PERF_LARGE_RAW_FRACTION:
  4304. // this should be a DWORD counter
  4305. assert ((pCounter->lNumItemType == VT_I8) ||
  4306. (pCounter->lNumItemType == VT_UI8));
  4307. pCounter->pWbemAccess->ReadQWORD (
  4308. pCounter->lNumItemHandle, & llValue);
  4309. pCounter->ThisValue.FirstValue = (LONGLONG) llValue;
  4310. assert ((pCounter->lDenItemType == VT_I8) ||
  4311. (pCounter->lDenItemType == VT_UI8));
  4312. pCounter->pWbemAccess->ReadQWORD (
  4313. pCounter->lDenItemHandle, & llValue);
  4314. // the denominator should be a 32-bit value
  4315. pCounter->ThisValue.SecondValue = (LONGLONG) llValue;
  4316. break;
  4317. case PERF_AVERAGE_TIMER:
  4318. case PERF_AVERAGE_BULK:
  4319. // counter (numerator) is a LONGLONG, while the
  4320. // denominator is just a DWORD
  4321. // this should be a DWORD counter
  4322. assert ((pCounter->lNumItemType == VT_I8) ||
  4323. (pCounter->lNumItemType == VT_UI8));
  4324. pCounter->pWbemAccess->ReadQWORD (
  4325. pCounter->lNumItemHandle, &llValue);
  4326. pCounter->ThisValue.FirstValue = (LONGLONG)llValue;
  4327. assert ((pCounter->lDenItemType == VT_I4) ||
  4328. (pCounter->lDenItemType == VT_UI4));
  4329. pCounter->pWbemAccess->ReadDWORD (
  4330. pCounter->lDenItemHandle, &dwValue);
  4331. // the denominator should be a 32-bit value
  4332. pCounter->ThisValue.SecondValue = (LONGLONG)dwValue;
  4333. // look up the timebase freq if necessary
  4334. if (pCounter->TimeBase == 0) {
  4335. assert ((pCounter->lFreqItemType == VT_I8) ||
  4336. (pCounter->lFreqItemType == VT_UI8));
  4337. pCounter->pWbemAccess->ReadQWORD (
  4338. pCounter->lFreqItemHandle, &llValue);
  4339. // the timebase is a 64 bit integer
  4340. pCounter->TimeBase = llValue;
  4341. }
  4342. break;
  4343. //
  4344. // These counters are used as the part of another counter
  4345. // and as such should not be used, but in case they are
  4346. // they'll be handled here.
  4347. //
  4348. case PERF_SAMPLE_BASE:
  4349. case PERF_AVERAGE_BASE:
  4350. case PERF_COUNTER_MULTI_BASE:
  4351. case PERF_RAW_BASE:
  4352. case PERF_LARGE_RAW_BASE:
  4353. pCounter->ThisValue.FirstValue = 0;
  4354. pCounter->ThisValue.SecondValue = 0;
  4355. break;
  4356. //
  4357. // These counters are not supported by this function (yet)
  4358. //
  4359. case PERF_COUNTER_TEXT:
  4360. case PERF_COUNTER_NODATA:
  4361. case PERF_COUNTER_HISTOGRAM_TYPE:
  4362. pCounter->ThisValue.FirstValue = 0;
  4363. pCounter->ThisValue.SecondValue = 0;
  4364. break;
  4365. case PERF_100NSEC_MULTI_TIMER:
  4366. case PERF_100NSEC_MULTI_TIMER_INV:
  4367. default:
  4368. // an unidentified or unsupported
  4369. // counter was returned so
  4370. pCounter->ThisValue.FirstValue = 0;
  4371. pCounter->ThisValue.SecondValue = 0;
  4372. bReturn = FALSE;
  4373. break;
  4374. }
  4375. } else {
  4376. // else this counter is not valid so this value == 0
  4377. pCounter->ThisValue.CStatus = LocalCStatus;
  4378. pCounter->ThisValue.FirstValue = 0;
  4379. pCounter->ThisValue.SecondValue = 0;
  4380. bReturn = FALSE;
  4381. }
  4382. return bReturn;
  4383. }
  4384. BOOL
  4385. UpdateWbemMultiInstanceCounterValue (
  4386. IN PPDHI_COUNTER pCounter,
  4387. IN FILETIME *pTimestamp
  4388. )
  4389. {
  4390. IWbemObjectAccess *pWbemAccess;
  4391. HRESULT hRes;
  4392. DWORD LocalCStatus = 0;
  4393. DWORD LocalCType = 0;
  4394. DWORD dwValue;
  4395. ULONGLONG llValue;
  4396. DWORD dwSize;
  4397. DWORD dwFinalSize;
  4398. LONG lAvailableSize;
  4399. LONG lReturnSize;
  4400. LONG lThisInstanceIndex;
  4401. LONG lNumInstances;
  4402. LPWSTR szNextNameString;
  4403. PPDHI_RAW_COUNTER_ITEM pThisItem;
  4404. BOOL bReturn = FALSE;
  4405. if (pCounter->pThisRawItemList != NULL) {
  4406. // free old counter buffer list
  4407. G_FREE(pCounter->pLastRawItemList);
  4408. pCounter->pLastRawItemList =
  4409. pCounter->pThisRawItemList;
  4410. pCounter->pThisRawItemList = NULL;
  4411. }
  4412. // get the counter's machine status first. There's no point in
  4413. // contuning if the machine is offline
  4414. // UpdateWbemCounterValue() will be called only if WBEM refresher succeeds
  4415. // in GetQueryWbemData(); that is, all remote machines should be on-line
  4416. LocalCStatus = ERROR_SUCCESS;
  4417. if (IsSuccessSeverity(LocalCStatus)) {
  4418. IWbemObjectAccess **pWbemInstances = NULL;
  4419. // get count of instances in enumerator
  4420. assert (pCounter->pWbemEnum != NULL);
  4421. hRes = pCounter->pWbemEnum->GetObjects(0, 0, NULL, (LPDWORD)&lNumInstances);
  4422. if (hRes == WBEM_E_BUFFER_TOO_SMALL) {
  4423. // then we should know how many have been returned so allocate an
  4424. // array of pointers
  4425. pWbemInstances = new IWbemObjectAccess * [lNumInstances];
  4426. assert (pWbemInstances != NULL);
  4427. if (pWbemInstances == NULL) {
  4428. SetLastError(ERROR_OUTOFMEMORY);
  4429. hRes = ERROR_OUTOFMEMORY;
  4430. bReturn = FALSE;
  4431. }
  4432. else {
  4433. hRes = pCounter->pWbemEnum->GetObjects(0,
  4434. lNumInstances, pWbemInstances, (LPDWORD)&lNumInstances);
  4435. }
  4436. if (hRes == S_OK && lNumInstances > 0) {
  4437. // then we have a table of instances
  4438. // estimate the size required for the new data block
  4439. dwSize = sizeof (PDHI_RAW_COUNTER_ITEM_BLOCK) - sizeof (PDHI_RAW_COUNTER_ITEM);
  4440. dwSize += lNumInstances * (sizeof(PDH_RAW_COUNTER_ITEM_W) + (MAX_PATH * 2 * sizeof(WCHAR)));
  4441. pCounter->pThisRawItemList = (PPDHI_RAW_COUNTER_ITEM_BLOCK)G_ALLOC (dwSize);
  4442. if (pCounter->pThisRawItemList != NULL) {
  4443. dwFinalSize = lNumInstances * sizeof(PDH_RAW_COUNTER_ITEM_W);
  4444. szNextNameString = (LPWSTR)((PBYTE)pCounter->pThisRawItemList + dwFinalSize);
  4445. for (lThisInstanceIndex = 0;
  4446. lThisInstanceIndex < lNumInstances;
  4447. lThisInstanceIndex++) {
  4448. // get pointer to this raw data block in the array
  4449. pThisItem = &pCounter->pThisRawItemList->pItemArray[lThisInstanceIndex];
  4450. // get pointer to this IWbemObjectAccess pointer
  4451. pWbemAccess = pWbemInstances[lThisInstanceIndex];
  4452. // compute the remaining size of the buffer
  4453. lAvailableSize = (long)(dwSize - dwFinalSize);
  4454. assert (lAvailableSize > 0);
  4455. if (pCounter->lNameHandle != -1) {
  4456. hRes = pWbemAccess->ReadPropertyValue(
  4457. pCounter->lNameHandle,
  4458. lAvailableSize,
  4459. &lReturnSize,
  4460. (LPBYTE)szNextNameString);
  4461. assert(hRes == S_OK);
  4462. } else {
  4463. szNextNameString[0] = ATSIGN_L;
  4464. szNextNameString[1] = 0;
  4465. lReturnSize = 2;
  4466. }
  4467. pThisItem->szName = (DWORD)
  4468. ( ((LPBYTE) szNextNameString)
  4469. - ((LPBYTE) pCounter->pThisRawItemList));
  4470. szNextNameString = (LPWSTR)((LPBYTE)szNextNameString + lReturnSize);
  4471. dwFinalSize += lReturnSize;
  4472. dwFinalSize = DWORD_MULTIPLE(dwFinalSize);
  4473. LocalCType = pCounter->plCounterInfo.dwCounterType;
  4474. switch (LocalCType) {
  4475. //
  4476. // these counter types are loaded as:
  4477. // Numerator = Counter data from perf data block
  4478. // Denominator = Perf Time from perf data block
  4479. // (the time base is the PerfFreq)
  4480. //
  4481. case PERF_COUNTER_COUNTER:
  4482. case PERF_COUNTER_QUEUELEN_TYPE:
  4483. case PERF_SAMPLE_COUNTER:
  4484. // this should be a DWORD counter
  4485. assert ((pCounter->lNumItemType == VT_I4) ||
  4486. (pCounter->lNumItemType == VT_UI4));
  4487. pWbemAccess->ReadDWORD (
  4488. pCounter->lNumItemHandle, &dwValue);
  4489. pThisItem->FirstValue = (LONGLONG)(dwValue);
  4490. assert ((pCounter->lDenItemType == VT_I8) ||
  4491. (pCounter->lDenItemType == VT_UI8));
  4492. pWbemAccess->ReadQWORD (
  4493. pCounter->lDenItemHandle, &llValue);
  4494. // the denominator should be a 64-bit timestamp
  4495. pThisItem->SecondValue = llValue;
  4496. // look up the timebase freq if necessary
  4497. if (pCounter->TimeBase == 0) {
  4498. assert ((pCounter->lFreqItemType == VT_I8) ||
  4499. (pCounter->lFreqItemType == VT_UI8));
  4500. pWbemAccess->ReadQWORD (
  4501. pCounter->lFreqItemHandle, &llValue);
  4502. // the timebase is a 64 bit integer
  4503. pCounter->TimeBase = llValue;
  4504. }
  4505. break;
  4506. case PERF_ELAPSED_TIME:
  4507. case PERF_100NSEC_TIMER:
  4508. case PERF_100NSEC_TIMER_INV:
  4509. case PERF_COUNTER_TIMER:
  4510. case PERF_COUNTER_TIMER_INV:
  4511. case PERF_COUNTER_BULK_COUNT:
  4512. case PERF_COUNTER_MULTI_TIMER:
  4513. case PERF_COUNTER_MULTI_TIMER_INV:
  4514. case PERF_COUNTER_LARGE_QUEUELEN_TYPE:
  4515. case PERF_OBJ_TIME_TIMER:
  4516. case PERF_COUNTER_100NS_QUEUELEN_TYPE:
  4517. case PERF_COUNTER_OBJ_TIME_QUEUELEN_TYPE:
  4518. case PERF_PRECISION_SYSTEM_TIMER:
  4519. case PERF_PRECISION_100NS_TIMER:
  4520. case PERF_PRECISION_OBJECT_TIMER:
  4521. // this should be a QWORD counter
  4522. assert ((pCounter->lNumItemType == VT_I8) ||
  4523. (pCounter->lNumItemType == VT_UI8));
  4524. pWbemAccess->ReadQWORD (
  4525. pCounter->lNumItemHandle, &llValue);
  4526. pThisItem->FirstValue = (LONGLONG)(llValue);
  4527. assert ((pCounter->lDenItemType == VT_I8) ||
  4528. (pCounter->lDenItemType == VT_UI8));
  4529. pWbemAccess->ReadQWORD (
  4530. pCounter->lDenItemHandle, &llValue);
  4531. // the denominator should be a 64-bit timestamp
  4532. pThisItem->SecondValue = llValue;
  4533. // look up the timebase freq if necessary
  4534. if (pCounter->TimeBase == 0) {
  4535. assert ((pCounter->lFreqItemType == VT_I8) ||
  4536. (pCounter->lFreqItemType == VT_UI8));
  4537. pWbemAccess->ReadQWORD (
  4538. pCounter->lFreqItemHandle, &llValue);
  4539. // the timebase is a 64 bit integer
  4540. pCounter->TimeBase = llValue;
  4541. }
  4542. break;
  4543. //
  4544. // These counters do not use any time reference
  4545. //
  4546. case PERF_COUNTER_RAWCOUNT:
  4547. case PERF_COUNTER_RAWCOUNT_HEX:
  4548. case PERF_COUNTER_DELTA:
  4549. // this should be a DWORD counter
  4550. assert ((pCounter->lNumItemType == VT_I4) ||
  4551. (pCounter->lNumItemType == VT_UI4));
  4552. pWbemAccess->ReadDWORD (
  4553. pCounter->lNumItemHandle, &dwValue);
  4554. pThisItem->FirstValue = (LONGLONG)(dwValue);
  4555. pThisItem->SecondValue = 0;
  4556. break;
  4557. case PERF_COUNTER_LARGE_RAWCOUNT:
  4558. case PERF_COUNTER_LARGE_RAWCOUNT_HEX:
  4559. case PERF_COUNTER_LARGE_DELTA:
  4560. // this should be a DWORD counter
  4561. assert ((pCounter->lNumItemType == VT_I8) ||
  4562. (pCounter->lNumItemType == VT_UI8));
  4563. pWbemAccess->ReadQWORD (
  4564. pCounter->lNumItemHandle, &llValue);
  4565. pThisItem->FirstValue = (LONGLONG)(llValue);
  4566. pThisItem->SecondValue = 0;
  4567. break;
  4568. //
  4569. // These counters use two data points, the one pointed to by
  4570. // pData and the one immediately after
  4571. //
  4572. case PERF_SAMPLE_FRACTION:
  4573. case PERF_RAW_FRACTION:
  4574. // this should be a DWORD counter
  4575. assert ((pCounter->lNumItemType == VT_I4) ||
  4576. (pCounter->lNumItemType == VT_UI4));
  4577. pWbemAccess->ReadDWORD (
  4578. pCounter->lNumItemHandle, &dwValue);
  4579. pThisItem->FirstValue = (LONGLONG)dwValue;
  4580. assert ((pCounter->lDenItemType == VT_I4) ||
  4581. (pCounter->lDenItemType == VT_UI4));
  4582. pWbemAccess->ReadDWORD (
  4583. pCounter->lDenItemHandle, &dwValue);
  4584. // the denominator should be a 32-bit value
  4585. pThisItem->SecondValue = (LONGLONG)dwValue;
  4586. break;
  4587. case PERF_LARGE_RAW_FRACTION:
  4588. // this should be a DWORD counter
  4589. assert ((pCounter->lNumItemType == VT_I8) ||
  4590. (pCounter->lNumItemType == VT_UI8));
  4591. pCounter->pWbemAccess->ReadQWORD (
  4592. pCounter->lNumItemHandle, & llValue);
  4593. pCounter->ThisValue.FirstValue = (LONGLONG) llValue;
  4594. assert ((pCounter->lDenItemType == VT_I8) ||
  4595. (pCounter->lDenItemType == VT_UI8));
  4596. pCounter->pWbemAccess->ReadQWORD (
  4597. pCounter->lDenItemHandle, & llValue);
  4598. // the denominator should be a 32-bit value
  4599. pCounter->ThisValue.SecondValue = (LONGLONG) llValue;
  4600. break;
  4601. case PERF_AVERAGE_TIMER:
  4602. case PERF_AVERAGE_BULK:
  4603. // counter (numerator) is a LONGLONG, while the
  4604. // denominator is just a DWORD
  4605. // this should be a DWORD counter
  4606. assert ((pCounter->lNumItemType == VT_I8) ||
  4607. (pCounter->lNumItemType == VT_UI8));
  4608. pWbemAccess->ReadQWORD (
  4609. pCounter->lNumItemHandle, &llValue);
  4610. pThisItem->FirstValue = (LONGLONG)llValue;
  4611. assert ((pCounter->lDenItemType == VT_I4) ||
  4612. (pCounter->lDenItemType == VT_UI4));
  4613. pWbemAccess->ReadDWORD (
  4614. pCounter->lDenItemHandle, &dwValue);
  4615. // the denominator should be a 32-bit value
  4616. pThisItem->SecondValue = (LONGLONG)dwValue;
  4617. // look up the timebase freq if necessary
  4618. if (pCounter->TimeBase == 0) {
  4619. assert ((pCounter->lFreqItemType == VT_I8) ||
  4620. (pCounter->lFreqItemType == VT_UI8));
  4621. pWbemAccess->ReadQWORD (
  4622. pCounter->lFreqItemHandle, &llValue);
  4623. // the timebase is a 64 bit integer
  4624. pCounter->TimeBase = llValue;
  4625. }
  4626. break;
  4627. //
  4628. // These counters are used as the part of another counter
  4629. // and as such should not be used, but in case they are
  4630. // they'll be handled here.
  4631. //
  4632. case PERF_SAMPLE_BASE:
  4633. case PERF_AVERAGE_BASE:
  4634. case PERF_COUNTER_MULTI_BASE:
  4635. case PERF_RAW_BASE:
  4636. case PERF_LARGE_RAW_BASE:
  4637. pThisItem->FirstValue = 0;
  4638. pThisItem->SecondValue = 0;
  4639. break;
  4640. //
  4641. // These counters are not supported by this function (yet)
  4642. //
  4643. case PERF_COUNTER_TEXT:
  4644. case PERF_COUNTER_NODATA:
  4645. case PERF_COUNTER_HISTOGRAM_TYPE:
  4646. pThisItem->FirstValue = 0;
  4647. pThisItem->SecondValue = 0;
  4648. break;
  4649. case PERF_100NSEC_MULTI_TIMER:
  4650. case PERF_100NSEC_MULTI_TIMER_INV:
  4651. default:
  4652. // an unidentified or unsupported
  4653. // counter was returned so
  4654. pThisItem->FirstValue = 0;
  4655. pThisItem->SecondValue = 0;
  4656. bReturn = FALSE;
  4657. break;
  4658. }
  4659. // we're done with this one so release it
  4660. pWbemAccess->Release();
  4661. }
  4662. // measure the memory block used
  4663. assert (dwFinalSize == (DWORD)((LPBYTE)szNextNameString -
  4664. (LPBYTE)(pCounter->pThisRawItemList)));
  4665. pCounter->pThisRawItemList->dwLength = dwFinalSize;
  4666. pCounter->pThisRawItemList->dwItemCount = lNumInstances;
  4667. pCounter->pThisRawItemList->dwReserved = 0;
  4668. pCounter->pThisRawItemList->CStatus = ERROR_SUCCESS;
  4669. pCounter->pThisRawItemList->TimeStamp = *pTimestamp;
  4670. } else {
  4671. // unable to allocate a new buffer so return error
  4672. SetLastError (ERROR_OUTOFMEMORY);
  4673. bReturn = FALSE;
  4674. }
  4675. }
  4676. }
  4677. }
  4678. return bReturn;
  4679. }
  4680. LONG
  4681. GetQueryWbemData (
  4682. IN PPDHI_QUERY pQuery,
  4683. IN LONGLONG *pllTimeStamp
  4684. )
  4685. {
  4686. FILETIME GmtFileTime;
  4687. FILETIME LocFileTime;
  4688. LONGLONG llTimeStamp = 0;
  4689. HRESULT hRes;
  4690. LONG lRetStatus = ERROR_SUCCESS;\
  4691. PPDHI_COUNTER pCounter;
  4692. PDH_STATUS pdhStatus;
  4693. // refresh Wbem Refresher
  4694. if (bDontRefresh) return ERROR_BUSY;
  4695. if (pQuery->pRefresher != NULL) {
  4696. hRes = pQuery->pRefresher->Refresh(0);
  4697. } else {
  4698. hRes = WBEM_E_INITIALIZATION_FAILURE;
  4699. }
  4700. // If multiple objects are being refreshed, some objects may succeed and
  4701. // others may fail, in which case WBEM_S_PARTIAL_RESULTS is returned.
  4702. if ( FAILED( hRes ) ) {
  4703. SetLastError (hRes);
  4704. lRetStatus = PDH_WBEM_ERROR;
  4705. }
  4706. if (lRetStatus == ERROR_SUCCESS) {
  4707. // get timestamp for this counter
  4708. GetSystemTimeAsFileTime(& GmtFileTime);
  4709. FileTimeToLocalFileTime(& GmtFileTime, & LocFileTime);
  4710. llTimeStamp = MAKELONGLONG(LocFileTime.dwLowDateTime,
  4711. LocFileTime.dwHighDateTime);
  4712. // now update the counters using this new data
  4713. if ((pCounter = pQuery->pCounterListHead) != NULL) {
  4714. do {
  4715. if (pCounter->dwFlags & PDHIC_MULTI_INSTANCE) {
  4716. pdhStatus = UpdateWbemMultiInstanceCounterValue (
  4717. pCounter, (FILETIME *)&llTimeStamp);
  4718. } else {
  4719. // update single instance counter values
  4720. pdhStatus = UpdateWbemCounterValue (pCounter,
  4721. (FILETIME *)&llTimeStamp);
  4722. }
  4723. pCounter = pCounter->next.flink;
  4724. } while (pCounter != pQuery->pCounterListHead);
  4725. pdhStatus = ERROR_SUCCESS;
  4726. } else {
  4727. // no counters in the query (?!)
  4728. pdhStatus = PDH_NO_DATA;
  4729. }
  4730. lRetStatus = pdhStatus;
  4731. }
  4732. *pllTimeStamp = llTimeStamp;
  4733. return lRetStatus;
  4734. }
  4735. HRESULT WbemSetProxyBlanket(
  4736. IUnknown *pInterface,
  4737. DWORD dwAuthnSvc,
  4738. DWORD dwAuthzSvc,
  4739. OLECHAR *pServerPrincName,
  4740. DWORD dwAuthLevel,
  4741. DWORD dwImpLevel,
  4742. RPC_AUTH_IDENTITY_HANDLE pAuthInfo,
  4743. DWORD dwCapabilities )
  4744. {
  4745. // Security MUST be set on both the Proxy and it's IUnknown!
  4746. IUnknown * pUnk = NULL;
  4747. IClientSecurity * pCliSec = NULL;
  4748. HRESULT sc = pInterface->QueryInterface(IID_IUnknown, (void **) &pUnk);
  4749. if(sc != S_OK)
  4750. return sc;
  4751. sc = pInterface->QueryInterface(IID_IClientSecurity, (void **) &pCliSec);
  4752. if(sc != S_OK)
  4753. {
  4754. pUnk->Release();
  4755. return sc;
  4756. }
  4757. sc = pCliSec->SetBlanket(pInterface, dwAuthnSvc, dwAuthzSvc, pServerPrincName,
  4758. dwAuthLevel, dwImpLevel, pAuthInfo, dwCapabilities);
  4759. pCliSec->Release();
  4760. pCliSec = NULL;
  4761. sc = pUnk->QueryInterface(IID_IClientSecurity, (void **) &pCliSec);
  4762. if(sc == S_OK)
  4763. {
  4764. sc = pCliSec->SetBlanket(pUnk, dwAuthnSvc, dwAuthzSvc, pServerPrincName,
  4765. dwAuthLevel, dwImpLevel, pAuthInfo, dwCapabilities);
  4766. pCliSec->Release();
  4767. }
  4768. else if (sc == 0x80004002)
  4769. sc = S_OK;
  4770. pUnk->Release();
  4771. return sc;
  4772. }