Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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