Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5754 lines
211 KiB

  1. /*++
  2. Copyright (C) 1996-1999 Microsoft Corporation
  3. Module Name:
  4. browser.c
  5. Abstract:
  6. counter name browsing functions exposed by the PDH.DLL
  7. --*/
  8. #include <windows.h>
  9. #include <pdh.h>
  10. #include <stdlib.h>
  11. #include <math.h>
  12. #include <mbctype.h>
  13. #include <assert.h>
  14. #include "pdhitype.h"
  15. #include "pdhidef.h"
  16. #include "pdhdlgs.h"
  17. #include "perfdata.h"
  18. #include "browsdlg.h"
  19. #include "pdhui.h"
  20. #pragma warning ( disable : 4213)
  21. #ifndef _USE_WBEM_ONLY
  22. #define _USE_WBEM_ONLY 0
  23. #endif
  24. #define DEFAULT_NULL_DATA_SOURCE DATA_SOURCE_REGISTRY
  25. PDH_FUNCTION
  26. PdhSetDefaultRealTimeDataSource (
  27. IN DWORD dwDataSourceId
  28. )
  29. {
  30. DWORD dwReturn = ERROR_SUCCESS;
  31. if (dwCurrentRealTimeDataSource <= 0) {
  32. switch (dwDataSourceId) {
  33. case DATA_SOURCE_WBEM:
  34. case DATA_SOURCE_REGISTRY:
  35. // this is OK so set local variable
  36. dwPdhiLocalDefaultDataSource = dwDataSourceId;
  37. break;
  38. case DATA_SOURCE_LOGFILE:
  39. default:
  40. // these are not OK so insert default
  41. dwReturn = PDH_INVALID_ARGUMENT;
  42. break;
  43. }
  44. } else {
  45. // a default realtime data source has already been defined
  46. dwReturn = PDH_CANNOT_SET_DEFAULT_REALTIME_DATASOURCE;
  47. }
  48. return dwReturn;
  49. }
  50. DWORD
  51. DataSourceTypeH(
  52. IN HLOG hDataSource
  53. )
  54. {
  55. if (hDataSource == H_REALTIME_DATASOURCE) {
  56. #if _USE_WBEM_ONLY
  57. return DATA_SOURCE_WBEM;
  58. #else
  59. return dwPdhiLocalDefaultDataSource;
  60. #endif
  61. }
  62. else if (hDataSource == H_WBEM_DATASOURCE) {
  63. return DATA_SOURCE_WBEM;
  64. }
  65. else {
  66. return DATA_SOURCE_LOGFILE;
  67. }
  68. }
  69. DWORD
  70. DataSourceTypeA (
  71. IN LPCSTR szDataSource
  72. )
  73. {
  74. if (szDataSource == NULL) {
  75. #if _USE_WBEM_ONLY
  76. return DATA_SOURCE_WBEM;
  77. #else
  78. //normal
  79. return dwPdhiLocalDefaultDataSource;
  80. #endif
  81. } else {
  82. // see if the prefix to the file name is "WBEM:"
  83. // indicating this is a WBEM name space instead of a
  84. // log file name
  85. // if the file name has a "WBEM:" in the front, then
  86. // set the flag appropriately
  87. if ( strncmp(szDataSource, caszWBEM, lstrlenA(caszWBEM)) != 0
  88. && strncmp(szDataSource, caszWMI, lstrlenA(caszWMI)) != 0) {
  89. return DATA_SOURCE_LOGFILE;
  90. }
  91. return DATA_SOURCE_WBEM;
  92. }
  93. }
  94. DWORD
  95. DataSourceTypeW (
  96. IN LPCWSTR szDataSource
  97. )
  98. {
  99. if (szDataSource == NULL) {
  100. #if _USE_WBEM_ONLY
  101. return DATA_SOURCE_WBEM;
  102. #else
  103. //normal
  104. return dwPdhiLocalDefaultDataSource;
  105. #endif
  106. } else {
  107. // see if the prefix to the file name is "WBEM:"
  108. // indicating this is a WBEM name space instead of a
  109. // log file name
  110. // if the file name has a "WBEM:" in the front, then
  111. // set the flag appropriately
  112. // Else check if it is "SQL:" prefixed
  113. if ( wcsncmp(szDataSource, cszWBEM, lstrlenW(cszWBEM)) != 0
  114. && wcsncmp(szDataSource, cszWMI, lstrlenW(cszWMI)) != 0) {
  115. return DATA_SOURCE_LOGFILE;
  116. }
  117. return DATA_SOURCE_LOGFILE;
  118. }
  119. }
  120. PDH_FUNCTION
  121. PdhConnectMachineW (
  122. IN LPCWSTR szMachineName
  123. )
  124. /*++
  125. Routine Description:
  126. Establishes a connection to the specified machine for reading perforamance
  127. data from the machine.
  128. Arguments:
  129. LPCWSTR szMachineName
  130. The name of the machine to connect to. If this argument is NULL,
  131. then the local machine is opened.
  132. Return Value:
  133. PDH Error status value
  134. ERROR_SUCCESS indicates the machine was successfully connected and the
  135. performance data from that machine was loaded.
  136. PDH_ error code indicates that the machine could not be located or opened.
  137. The status code indicates the problem.
  138. --*/
  139. {
  140. PPERF_MACHINE pMachine = NULL;
  141. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  142. DebugPrint((4, "PdhConnectMachineW BEGIN 0x%08X\n", szMachineName));
  143. if (szMachineName != NULL) {
  144. __try {
  145. WCHAR wChar;
  146. // test buffer access
  147. wChar = *szMachineName;
  148. if (wChar == 0) {
  149. pdhStatus = PDH_INVALID_ARGUMENT;
  150. }
  151. } __except (EXCEPTION_EXECUTE_HANDLER) {
  152. pdhStatus = PDH_INVALID_ARGUMENT;
  153. }
  154. }
  155. if (pdhStatus == ERROR_SUCCESS) {
  156. pMachine = GetMachine ((LPWSTR)szMachineName, 0);
  157. if (pMachine != NULL) {
  158. // then return the machine status
  159. pdhStatus = pMachine->dwStatus;
  160. pMachine->dwRefCount--;
  161. RELEASE_MUTEX (pMachine->hMutex);
  162. } else {
  163. // return the status from the GetMachine call
  164. pdhStatus = GetLastError();
  165. }
  166. } // else pass the status to the caller
  167. DebugPrint((4, "PdhConnectMachineW END status 0x%08X\n", pdhStatus));
  168. return pdhStatus;
  169. }
  170. PDH_FUNCTION
  171. PdhConnectMachineA (
  172. IN LPCSTR szMachineName
  173. )
  174. /*++
  175. Routine Description:
  176. Establishes a connection to the specified machine for reading perforamance
  177. data from the machine.
  178. Arguments:
  179. LPCSTR szMachineName
  180. The name of the machine to connect to. If this argument is NULL,
  181. then the local machine is opened.
  182. Return Value:
  183. PDH Error status value
  184. ERROR_SUCCESS indicates the machine was successfully connected and the
  185. performance data from that machine was loaded.
  186. PDH_ error code indicates that the machine could not be located or opened.
  187. The status code indicates the problem.
  188. --*/
  189. {
  190. LPWSTR szWideName = NULL;
  191. DWORD dwNameLength = 0;
  192. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  193. PPERF_MACHINE pMachine = NULL;
  194. DebugPrint((4, "PdhConnectMachineA BEGIN 0x%08X\n", szMachineName));
  195. if (szMachineName != NULL) {
  196. __try {
  197. WCHAR wChar;
  198. // test buffer access
  199. wChar = *szMachineName;
  200. if (wChar != 0) {
  201. if (pdhStatus == ERROR_SUCCESS) {
  202. dwNameLength = lstrlenA (szMachineName);
  203. } else {
  204. dwNameLength = 0;
  205. }
  206. } else {
  207. pdhStatus = PDH_INVALID_ARGUMENT;
  208. }
  209. } __except (EXCEPTION_EXECUTE_HANDLER) {
  210. pdhStatus = PDH_INVALID_ARGUMENT;
  211. }
  212. if (pdhStatus == ERROR_SUCCESS) {
  213. szWideName = G_ALLOC ((dwNameLength+1) * sizeof(WCHAR));
  214. if (szWideName == NULL) {
  215. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  216. } else {
  217. __try {
  218. MultiByteToWideChar(_getmbcp(),
  219. 0,
  220. szMachineName,
  221. dwNameLength,
  222. szWideName,
  223. dwNameLength + 1);
  224. } __except (EXCEPTION_EXECUTE_HANDLER) {
  225. pdhStatus = PDH_INVALID_ARGUMENT;
  226. }
  227. }
  228. }
  229. } else {
  230. szWideName = NULL;
  231. }
  232. if (pdhStatus == ERROR_SUCCESS) {
  233. pMachine = GetMachine (szWideName, 0);
  234. if (pMachine != NULL) {
  235. // then return the machine status
  236. pdhStatus = pMachine->dwStatus;
  237. pMachine->dwRefCount--;
  238. RELEASE_MUTEX (pMachine->hMutex);
  239. } else {
  240. // return the status from the GetMachine call
  241. pdhStatus = GetLastError();
  242. }
  243. }
  244. if (szWideName != NULL) G_FREE (szWideName);
  245. DebugPrint((4, "PdhConnectMachineA END status 0x%08X\n", pdhStatus));
  246. return pdhStatus;
  247. }
  248. STATIC_PDH_FUNCTION
  249. PdhiEnumConnectedMachines (
  250. IN LPVOID pMachineList,
  251. IN LPDWORD pcchBufferSize,
  252. IN BOOL bUnicode
  253. )
  254. /*++
  255. Routine Description:
  256. Builds a MSZ list of the machines currently known by the PDH. This
  257. list includes machines with open sessions as well as those that
  258. are off-line.
  259. Arguments:
  260. IN LPVOID pMachineList
  261. A pointer to the buffer to receive the enumerated machine list.
  262. The strings written to this buffer will contain the characters
  263. specified by the bUnicode argument
  264. IN LPVOID pMachineList
  265. A pointer to the buffer to receive the enumerated machine list.
  266. The strings written to this buffer will contain the characters
  267. specified by the bUnicode argument
  268. IN LPDWORD pcchBufferSize
  269. The size of the buffer referenced by pMachineList in characters
  270. IN BOOL bUnicode
  271. TRUE = UNICODE characters will be written to the pMachineList
  272. buffer
  273. FALSE = ANSI characters will be writtn to the pMachinList buffer
  274. Return Value:
  275. ERROR_SUCCESS if this the function completes successfully. a PDH error
  276. value if not.
  277. PDH_MORE_DATA some entries were returned, but there was not enough
  278. room in the buffer to store all entries.
  279. PDH_INSUFFICIENT_BUFFER there was not enough room in the buffer to
  280. store ANY data
  281. PDH_INVALID_ARGUMENT unable to write to the size buffers or the
  282. data buffer
  283. --*/
  284. {
  285. PPERF_MACHINE pThisMachine;
  286. DWORD dwRequiredLength = 0;
  287. DWORD dwMaximumLength;
  288. DWORD dwNameLength;
  289. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  290. LPVOID szNextName;
  291. DebugPrint((4, "PdhiEnumConnectedMachines BEGIN\n"));
  292. // reset the last error value
  293. SetLastError (ERROR_SUCCESS);
  294. // first walk down list to compute required length
  295. pThisMachine = pFirstMachine;
  296. __try {
  297. // get a local copy of the size and try writing to the variable
  298. // to test read & write access of args before continuing
  299. dwMaximumLength = *pcchBufferSize;
  300. *pcchBufferSize = 0;
  301. *pcchBufferSize = dwMaximumLength;
  302. // point to first machine entry in list
  303. szNextName = pMachineList;
  304. // walk around entire list
  305. if (pThisMachine != NULL) {
  306. do {
  307. if (bUnicode) {
  308. dwNameLength = lstrlenW(pThisMachine->szName) + 1;
  309. if ( szNextName != NULL
  310. && dwRequiredLength + dwNameLength <= dwMaximumLength) {
  311. lstrcpyW ((LPWSTR) szNextName, pThisMachine->szName);
  312. (LPBYTE) szNextName += sizeof(WCHAR) * (dwNameLength - 1);
  313. * ((LPWSTR) szNextName) ++ = 0;
  314. }
  315. else {
  316. pdhStatus = PDH_MORE_DATA;
  317. }
  318. }
  319. else {
  320. dwNameLength = (dwRequiredLength <= dwMaximumLength)
  321. ? (dwMaximumLength - dwRequiredLength) : (0);
  322. pdhStatus = PdhiConvertUnicodeToAnsi(_getmbcp(),
  323. pThisMachine->szName,
  324. (LPSTR) szNextName,
  325. & dwNameLength);
  326. if (pdhStatus == ERROR_SUCCESS) {
  327. (LPBYTE) szNextName += sizeof(CHAR) * dwNameLength;
  328. }
  329. }
  330. dwRequiredLength += dwNameLength;
  331. // go to next machine in list
  332. pThisMachine = pThisMachine->pNext;
  333. } while (pThisMachine != pFirstMachine);
  334. } else {
  335. // no machines in list, so insert an empty string
  336. if (++dwRequiredLength <= dwMaximumLength) {
  337. if (bUnicode) {
  338. *((LPWSTR)szNextName)++ = 0;
  339. } else {
  340. *((LPSTR)szNextName)++ = 0;
  341. }
  342. pdhStatus = ERROR_SUCCESS;
  343. } else if (dwMaximumLength != 0) {
  344. // then the buffer is too small
  345. pdhStatus = PDH_MORE_DATA;
  346. }
  347. }
  348. // all entries have been checked and /or copied
  349. // so terminate the MSZ or at least account for the required size
  350. dwRequiredLength ++;
  351. if (szNextName != NULL && dwRequiredLength <= dwMaximumLength) {
  352. if (bUnicode) {
  353. *((LPWSTR)szNextName)++ = 0;
  354. } else {
  355. *((LPSTR)szNextName)++ = 0;
  356. }
  357. pdhStatus = ERROR_SUCCESS;
  358. } else {
  359. // then the buffer is too small
  360. pdhStatus = PDH_MORE_DATA;
  361. }
  362. //return the required size or size used
  363. *pcchBufferSize = dwRequiredLength;
  364. } __except (EXCEPTION_EXECUTE_HANDLER) {
  365. pdhStatus = PDH_INVALID_ARGUMENT;
  366. }
  367. DebugPrint((4, "PdhiEnumConnectedMachines END status 0x%08X\n", pdhStatus));
  368. return pdhStatus;
  369. }
  370. PDH_FUNCTION
  371. PdhEnumMachinesHW (
  372. IN HLOG hDataSource,
  373. IN LPWSTR mszMachineList,
  374. IN LPDWORD pcchBufferSize
  375. )
  376. {
  377. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  378. DWORD dwBufferSize = 0;
  379. DWORD dwDataSource = 0;
  380. if (pcchBufferSize == NULL) {
  381. pdhStatus = PDH_INVALID_ARGUMENT;
  382. }
  383. else {
  384. __try {
  385. dwDataSource = DataSourceTypeH(hDataSource);
  386. if (pdhStatus == ERROR_SUCCESS) {
  387. dwBufferSize = *pcchBufferSize;
  388. }
  389. if ((dwBufferSize * sizeof(WCHAR)) >= sizeof(DWORD)) {
  390. // test writing to the buffers to make sure they are valid
  391. CLEAR_FIRST_FOUR_BYTES (mszMachineList);
  392. mszMachineList[dwBufferSize -1] = 0;
  393. } else if ((dwBufferSize * sizeof(WCHAR)) >= sizeof(WCHAR)) {
  394. // then just try the first byte
  395. *mszMachineList = 0;
  396. } else if (dwBufferSize != 0) {
  397. // it's smaller than a character so return if not 0
  398. pdhStatus = PDH_MORE_DATA;
  399. }
  400. }
  401. __except (EXCEPTION_EXECUTE_HANDLER) {
  402. pdhStatus = PDH_INVALID_ARGUMENT;
  403. }
  404. }
  405. if (pdhStatus == ERROR_SUCCESS) {
  406. pdhStatus = WAIT_FOR_AND_LOCK_MUTEX (hPdhDataMutex);
  407. }
  408. if (pdhStatus == ERROR_SUCCESS) {
  409. __try {
  410. switch (dwDataSource) {
  411. case DATA_SOURCE_REGISTRY:
  412. pdhStatus = PdhiEnumConnectedMachines (
  413. (LPVOID)mszMachineList,
  414. &dwBufferSize,
  415. TRUE);
  416. break;
  417. case DATA_SOURCE_WBEM:
  418. pdhStatus = PdhiEnumWbemMachines (
  419. (LPVOID)mszMachineList,
  420. &dwBufferSize,
  421. TRUE);
  422. break;
  423. case DATA_SOURCE_LOGFILE:
  424. pdhStatus = PdhiEnumLoggedMachines (
  425. hDataSource,
  426. (LPVOID) mszMachineList,
  427. & dwBufferSize,
  428. TRUE);
  429. break;
  430. default:
  431. assert (FALSE); // unknown data source type
  432. }
  433. }
  434. __except (EXCEPTION_EXECUTE_HANDLER) {
  435. pdhStatus = PDH_INVALID_ARGUMENT;
  436. }
  437. RELEASE_MUTEX (hPdhDataMutex);
  438. __try {
  439. *pcchBufferSize = dwBufferSize;
  440. }
  441. __except (EXCEPTION_EXECUTE_HANDLER) {
  442. pdhStatus = PDH_INVALID_ARGUMENT;
  443. }
  444. }
  445. return pdhStatus;
  446. }
  447. PDH_FUNCTION
  448. PdhEnumMachinesW (
  449. IN LPCWSTR szDataSource,
  450. IN LPWSTR mszMachineList,
  451. IN LPDWORD pcchBufferSize
  452. )
  453. /*++
  454. Routine Description:
  455. Builds a MSZ list of the machines currently known by the PDH. This
  456. list includes machines with open sessions as well as those that
  457. are off-line.
  458. Arguments:
  459. IN LPCWSTR szDataSource
  460. NULL for current real-time data or the name of a log file
  461. IN LPWSTR szMachineList
  462. A pointer to the buffer to receive the enumerated machine list.
  463. The strings written to this buffer will contain UNICODE chars
  464. IN LPDWORD pcchBufferSize
  465. The size of the buffer referenced by pMachineList in characters
  466. The value of the buffer referenced by this pointer may be 0
  467. if the required size is requested.
  468. Return Value:
  469. ERROR_SUCCESS if this the function completes successfully. a PDH error
  470. value if not.
  471. PDH_MORE_DATA some entries were returned, but there was not enough
  472. room in the buffer to store all entries.
  473. PDH_INSUFFICIENT_BUFFER there was not enough room in the buffer to
  474. store ANY data
  475. PDH_INVALID_ARGUMENT unable to write to the size buffers or the
  476. data buffer
  477. --*/
  478. {
  479. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  480. DWORD dwDataSource = 0;
  481. HLOG hDataSource = H_REALTIME_DATASOURCE;
  482. DebugPrint((4, "PdhEnumMachinesW BEGIN\n"));
  483. __try {
  484. if (szDataSource != NULL) {
  485. WCHAR TestChar;
  486. // test for read access to the name
  487. TestChar = *szDataSource;
  488. if (TestChar == 0) {
  489. pdhStatus = PDH_INVALID_ARGUMENT;
  490. }
  491. } // else NULL is a valid arg
  492. dwDataSource = DataSourceTypeW (szDataSource);
  493. } __except (EXCEPTION_EXECUTE_HANDLER) {
  494. pdhStatus = PDH_INVALID_ARGUMENT;
  495. }
  496. if (pdhStatus == ERROR_SUCCESS) {
  497. if (dwDataSource == DATA_SOURCE_WBEM) {
  498. hDataSource = H_WBEM_DATASOURCE;
  499. }
  500. else if (dwDataSource == DATA_SOURCE_LOGFILE) {
  501. DWORD dwLogType = 0;
  502. pdhStatus = PdhOpenLogW(
  503. szDataSource,
  504. PDH_LOG_READ_ACCESS | PDH_LOG_OPEN_EXISTING,
  505. & dwLogType,
  506. NULL,
  507. 0,
  508. NULL,
  509. & hDataSource);
  510. }
  511. }
  512. if (pdhStatus == ERROR_SUCCESS) {
  513. pdhStatus = PdhEnumMachinesHW(hDataSource,
  514. mszMachineList,
  515. pcchBufferSize);
  516. if (dwDataSource == DATA_SOURCE_LOGFILE) {
  517. PdhCloseLog(hDataSource, 0);
  518. }
  519. }
  520. DebugPrint((4, "PdhEnumMachinesW END status 0x%08X\n", pdhStatus));
  521. return pdhStatus;
  522. }
  523. PDH_FUNCTION
  524. PdhEnumMachinesHA (
  525. IN HLOG hDataSource,
  526. IN LPSTR mszMachineList,
  527. IN LPDWORD pcchBufferSize
  528. )
  529. {
  530. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  531. DWORD dwBufferSize = 0;
  532. DWORD dwDataSource = 0;
  533. if (pcchBufferSize == NULL) {
  534. pdhStatus = PDH_INVALID_ARGUMENT;
  535. }
  536. else {
  537. __try {
  538. dwDataSource = DataSourceTypeH(hDataSource);
  539. dwBufferSize = *pcchBufferSize;
  540. if (dwBufferSize >= sizeof (DWORD)) {
  541. // test writing to the buffers to make sure they are valid
  542. CLEAR_FIRST_FOUR_BYTES (mszMachineList);
  543. mszMachineList[dwBufferSize -1] = 0;
  544. } else if (dwBufferSize >= sizeof(CHAR)) {
  545. *mszMachineList = 0;
  546. }
  547. }
  548. __except (EXCEPTION_EXECUTE_HANDLER) {
  549. pdhStatus = PDH_INVALID_ARGUMENT;
  550. }
  551. }
  552. if (pdhStatus == ERROR_SUCCESS) {
  553. pdhStatus = WAIT_FOR_AND_LOCK_MUTEX (hPdhDataMutex);
  554. }
  555. if (pdhStatus == ERROR_SUCCESS) {
  556. __try {
  557. switch (dwDataSource) {
  558. case DATA_SOURCE_REGISTRY:
  559. pdhStatus = PdhiEnumConnectedMachines (
  560. (LPVOID)mszMachineList,
  561. &dwBufferSize,
  562. FALSE);
  563. break;
  564. case DATA_SOURCE_WBEM:
  565. pdhStatus = PdhiEnumWbemMachines (
  566. (LPVOID)mszMachineList,
  567. &dwBufferSize,
  568. FALSE);
  569. break;
  570. case DATA_SOURCE_LOGFILE:
  571. pdhStatus = PdhiEnumLoggedMachines (
  572. hDataSource,
  573. (LPVOID) mszMachineList,
  574. & dwBufferSize,
  575. FALSE);
  576. break;
  577. default:
  578. assert (FALSE);
  579. }
  580. }
  581. __except (EXCEPTION_EXECUTE_HANDLER) {
  582. pdhStatus = PDH_INVALID_ARGUMENT;
  583. }
  584. RELEASE_MUTEX (hPdhDataMutex);
  585. __try {
  586. *pcchBufferSize = dwBufferSize;
  587. }
  588. __except (EXCEPTION_EXECUTE_HANDLER) {
  589. pdhStatus = PDH_INVALID_ARGUMENT;
  590. }
  591. }
  592. return pdhStatus;
  593. }
  594. PDH_FUNCTION
  595. PdhEnumMachinesA (
  596. IN LPCSTR szDataSource,
  597. IN LPSTR mszMachineList,
  598. IN LPDWORD pcchBufferSize
  599. )
  600. /*++
  601. Routine Description:
  602. Builds a MSZ list of the machines currently known by the PDH. This
  603. list includes machines with open sessions as well as those that
  604. are off-line.
  605. Arguments:
  606. IN LPCSTR szDataSource
  607. NULL for current real-time data or the name of a log file
  608. IN LPWSTR szMachineList
  609. A pointer to the buffer to receive the enumerated machine list.
  610. The strings written to this buffer will contain UNICODE chars
  611. IN LPDWORD pcchBufferSize
  612. The size of the buffer referenced by pMachineList in characters
  613. The value of the buffer referenced by this pointer may be 0
  614. if the required size is requested.
  615. Return Value:
  616. ERROR_SUCCESS if this the function completes successfully. a PDH error
  617. value if not.
  618. PDH_MORE_DATA some entries were returned, but there was not enough
  619. room in the buffer to store all entries.
  620. PDH_INSUFFICIENT_BUFFER there was not enough room in the buffer to
  621. store ANY data
  622. PDH_INVALID_ARGUMENT unable to write to the size buffers or the
  623. data buffer
  624. --*/
  625. {
  626. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  627. DWORD dwDataSource = 0;
  628. HLOG hDataSource = H_REALTIME_DATASOURCE;
  629. DebugPrint((4, "PdhEnumMachinesA BEGIN\n"));
  630. __try {
  631. if (szDataSource != NULL) {
  632. CHAR TestChar;
  633. // test for read access to the name
  634. TestChar = *szDataSource;
  635. if (TestChar == 0) {
  636. pdhStatus = PDH_INVALID_ARGUMENT;
  637. }
  638. } // else NULL is a valid arg
  639. dwDataSource = DataSourceTypeA(szDataSource);
  640. }
  641. __except (EXCEPTION_EXECUTE_HANDLER) {
  642. pdhStatus = PDH_INVALID_ARGUMENT;
  643. }
  644. if (pdhStatus == ERROR_SUCCESS) {
  645. if (dwDataSource == DATA_SOURCE_WBEM) {
  646. hDataSource = H_WBEM_DATASOURCE;
  647. }
  648. else if (dwDataSource == DATA_SOURCE_LOGFILE) {
  649. DWORD dwLogType = 0;
  650. pdhStatus = PdhOpenLogA(
  651. szDataSource,
  652. PDH_LOG_READ_ACCESS | PDH_LOG_OPEN_EXISTING,
  653. & dwLogType,
  654. NULL,
  655. 0,
  656. NULL,
  657. & hDataSource);
  658. }
  659. }
  660. if (pdhStatus == ERROR_SUCCESS) {
  661. pdhStatus = PdhEnumMachinesHA(hDataSource,
  662. mszMachineList,
  663. pcchBufferSize);
  664. if (dwDataSource == DATA_SOURCE_LOGFILE) {
  665. PdhCloseLog(hDataSource, 0);
  666. }
  667. }
  668. DebugPrint((4, "PdhEnumMachinesA END status 0x%08X\n", pdhStatus));
  669. return pdhStatus;
  670. }
  671. #pragma warning ( disable : 4127 )
  672. PDH_FUNCTION
  673. PdhiEnumObjects (
  674. IN LPWSTR szMachineName,
  675. IN LPVOID mszObjectList,
  676. IN LPDWORD pcchBufferSize,
  677. IN DWORD dwDetailLevel,
  678. IN BOOL bRefresh,
  679. IN BOOL bUnicode
  680. )
  681. /*++
  682. Routine Description:
  683. Lists the performance objects found on the specified machine as
  684. a MSZ list.
  685. Arguments:
  686. IN LPWSTR szMachineName
  687. The machine to list objects from
  688. IN LPVOID mszObjectList
  689. a pointer to the buffer to receive the list of performance
  690. objects
  691. IN LPDWORD pcchBufferSize
  692. a pointer to the DWORD containing the size of the mszObjectList
  693. buffer in characters. The characters assumed are determined by
  694. the bUnicode argument.
  695. IN DWORD dwDetailLevel
  696. The detail level to use as a filter of objects. All objects
  697. with a detail level less than or equal to that specified
  698. by this argument will be returned.
  699. IN BOOL bRefresh
  700. TRUE = retrive a new perf. data buffer for this machine before
  701. listing the objects
  702. FALSE = use the currently cached perf data buffer for this
  703. machine to enumerate objects
  704. IN BOOL bUnicode
  705. TRUE = return the listed objects as UNICODE strings
  706. FALSE = return the listed objects as ANSI strings
  707. Return Value:
  708. ERROR_SUCCESS if the function completes successfully. Otherwise a
  709. PDH_ error status if not.
  710. PDH_MORE_DATA is returned when there are more entries available to
  711. return than there is room in the buffer. Some entries may be
  712. returned in the buffer though.
  713. PDH_INSUFFICIENT_BUFFER is returned when there is not enough
  714. room in the buffer for ANY data.
  715. PDH_CSTATUS_NO_MACHINE is returned when the specified machine
  716. is offline or unavailable.
  717. --*/
  718. {
  719. PPERF_MACHINE pMachine;
  720. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  721. DWORD NumTypeDef;
  722. PERF_OBJECT_TYPE *pObjectDef;
  723. PERF_OBJECT_TYPE *pEndOfBuffer;
  724. DWORD dwRequiredLength = 0;
  725. LPVOID szNextName;
  726. DWORD dwNameLength;
  727. DWORD dwMaximumLength;
  728. LPWSTR szObjNameString;
  729. WCHAR wszNumberString[32];
  730. DWORD dwGmFlags;
  731. DWORD dwLocalDetailLevel;
  732. DebugPrint((4, "PdhiEnumObjects BEGIN\n"));
  733. // connect to machine and update data if desired
  734. if (bRefresh) {
  735. dwGmFlags = PDH_GM_UPDATE_PERFDATA;
  736. dwGmFlags |= ((dwDetailLevel & PERF_DETAIL_COSTLY) == PERF_DETAIL_COSTLY) ?
  737. PDH_GM_READ_COSTLY_DATA : 0;
  738. } else {
  739. dwGmFlags = 0;
  740. }
  741. // connect to machine and update data if desired
  742. pMachine = GetMachine (szMachineName,
  743. (bRefresh ? PDH_GM_UPDATE_PERFDATA : 0));
  744. dwMaximumLength = *pcchBufferSize;
  745. if (pMachine != NULL) {
  746. if (pMachine->dwStatus == ERROR_SUCCESS) {
  747. if ((dwDetailLevel & PERF_DETAIL_COSTLY) &&
  748. !(pMachine->dwMachineFlags & PDHIPM_FLAGS_HAVE_COSTLY)) {
  749. // then get them
  750. dwGmFlags = PDH_GM_UPDATE_PERFDATA | PDH_GM_READ_COSTLY_DATA;
  751. pMachine = GetMachine (szMachineName, dwGmFlags);
  752. }
  753. }
  754. }
  755. if (pMachine != NULL) {
  756. // make sure the machine connection is valid
  757. if (pMachine->dwStatus == ERROR_SUCCESS) {
  758. dwRequiredLength = 0;
  759. szNextName = mszObjectList;
  760. // start walking object list
  761. pObjectDef = FirstObject(pMachine->pSystemPerfData);
  762. pEndOfBuffer = (PPERF_OBJECT_TYPE)
  763. ((DWORD_PTR)pMachine->pSystemPerfData +
  764. pMachine->pSystemPerfData->TotalByteLength);
  765. if ((pMachine->pSystemPerfData->NumObjectTypes > 0) &&
  766. (pObjectDef != NULL)) {
  767. // convert detail level to the PerfLib detail level
  768. dwLocalDetailLevel = dwDetailLevel & PERF_DETAIL_STANDARD;
  769. // build list
  770. NumTypeDef = 0;
  771. while (1) {
  772. // only look at entries matching the desired Detail Level
  773. if (pObjectDef->DetailLevel <= dwLocalDetailLevel) {
  774. if ( pObjectDef->ObjectNameTitleIndex < pMachine->dwLastPerfString ) {
  775. szObjNameString =
  776. (LPWSTR)PdhiLookupPerfNameByIndex (
  777. pMachine,
  778. pObjectDef->ObjectNameTitleIndex);
  779. } else {
  780. // no match since the index is larger that that found
  781. // in the data buffer
  782. szObjNameString = NULL;
  783. }
  784. if (szObjNameString == NULL) {
  785. // then this object has no string name so use
  786. // the object number
  787. _ltow (pObjectDef->ObjectNameTitleIndex,
  788. wszNumberString, 10);
  789. szObjNameString = &wszNumberString[0];
  790. }
  791. // compute length
  792. if (bUnicode) {
  793. dwNameLength = lstrlenW(szObjNameString) + 1;
  794. if ( szNextName != NULL
  795. && dwRequiredLength + dwNameLength <= dwMaximumLength) {
  796. lstrcpyW ((LPWSTR)szNextName, szObjNameString);
  797. (LPBYTE) szNextName += (dwNameLength - 1)
  798. * sizeof(WCHAR);
  799. * ((LPWSTR) szNextName) ++ = 0;
  800. }
  801. else {
  802. pdhStatus = PDH_MORE_DATA;
  803. }
  804. }
  805. else {
  806. dwNameLength = (dwRequiredLength <= dwMaximumLength)
  807. ? (dwMaximumLength - dwRequiredLength)
  808. : (0);
  809. pdhStatus = PdhiConvertUnicodeToAnsi(_getmbcp(),
  810. szObjNameString,
  811. (LPSTR) szNextName,
  812. & dwNameLength);
  813. if (pdhStatus == ERROR_SUCCESS) {
  814. (LPBYTE) szNextName += sizeof(CHAR) * dwNameLength;
  815. }
  816. }
  817. dwRequiredLength += dwNameLength;
  818. } else {
  819. // this entry is not correct detail level
  820. // so skip & continue
  821. }
  822. // go to next object in the data block
  823. NumTypeDef++;
  824. if (NumTypeDef >= pMachine->pSystemPerfData->NumObjectTypes) {
  825. // that's enough so break out of the loop
  826. break;
  827. } else {
  828. // goto the next one and make sure it's valid
  829. pObjectDef = NextObject(pObjectDef); // get next
  830. //make sure next object is legit
  831. if (pObjectDef != NULL) {
  832. if (pObjectDef->TotalByteLength > 0) {
  833. if (pObjectDef >= pEndOfBuffer) {
  834. // looks like we ran off the end of the data buffer
  835. assert (pObjectDef < pEndOfBuffer);
  836. break;
  837. }
  838. } else {
  839. // 0-length object buffer returned
  840. assert (pObjectDef->TotalByteLength > 0);
  841. break;
  842. }
  843. } else {
  844. // and continue
  845. assert (pObjectDef != NULL);
  846. break;
  847. }
  848. }
  849. }
  850. // add MSZ terminator to string
  851. ++dwRequiredLength; // add the size of the MSZ char
  852. if (pdhStatus == ERROR_SUCCESS) {
  853. if (dwRequiredLength <= dwMaximumLength) {
  854. if (bUnicode) {
  855. *((LPWSTR)szNextName)++ = 0;
  856. } else {
  857. *((LPSTR)szNextName)++ = 0;
  858. }
  859. // make sure pointers and lengths stay in sync
  860. } else if (dwMaximumLength > 0) {
  861. pdhStatus = PDH_MORE_DATA;
  862. }
  863. } else {
  864. // leave the current error value
  865. // but keep the size of the MSZ Null to the required length
  866. }
  867. } else {
  868. // no objects found for this machine
  869. dwRequiredLength = 2;
  870. if (dwMaximumLength > 0) {
  871. if (dwRequiredLength <= dwMaximumLength) {
  872. if (bUnicode) {
  873. *((LPWSTR)szNextName)++ = 0;
  874. *((LPWSTR)szNextName)++ = 0;
  875. } else {
  876. *((LPSTR)szNextName)++ = 0;
  877. *((LPSTR)szNextName)++ = 0;
  878. }
  879. // make sure pointers and lengths stay in sync
  880. } else {
  881. pdhStatus = ERROR_MORE_DATA;
  882. }
  883. } // else this is just a size request
  884. }
  885. // return length info
  886. *pcchBufferSize = dwRequiredLength;
  887. } else {
  888. pdhStatus = pMachine->dwStatus; // computer off line
  889. }
  890. pMachine->dwRefCount--;
  891. RELEASE_MUTEX (pMachine->hMutex);
  892. } else {
  893. pdhStatus = GetLastError(); // computer not found
  894. }
  895. DebugPrint((4, "PdhiEnumObjects END status 0x%08X\n", pdhStatus));
  896. return pdhStatus;
  897. }
  898. #pragma warning ( default : 4127 )
  899. PDH_FUNCTION
  900. PdhEnumObjectsHW (
  901. IN HLOG hDataSource,
  902. IN LPCWSTR szMachineName,
  903. IN LPWSTR mszObjectList,
  904. IN LPDWORD pcchBufferSize,
  905. IN DWORD dwDetailLevel,
  906. IN BOOL bRefresh
  907. )
  908. {
  909. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  910. DWORD dwBufferSize = 0;
  911. DWORD dwDataSource = 0;
  912. if (pcchBufferSize == NULL) {
  913. pdhStatus = PDH_INVALID_ARGUMENT;
  914. }
  915. else {
  916. __try {
  917. dwDataSource = DataSourceTypeH(hDataSource);
  918. if (szMachineName != NULL) {
  919. if (* szMachineName == 0) {
  920. pdhStatus = PDH_INVALID_ARGUMENT;
  921. }
  922. }
  923. else {
  924. // NULL is a valid value
  925. }
  926. if (pdhStatus == ERROR_SUCCESS) {
  927. dwBufferSize = * pcchBufferSize;
  928. }
  929. if (pdhStatus == ERROR_SUCCESS) {
  930. if ((dwBufferSize * sizeof(WCHAR)) >= sizeof(DWORD)) {
  931. // test writing to the buffers to make sure they are valid
  932. CLEAR_FIRST_FOUR_BYTES (mszObjectList);
  933. mszObjectList[dwBufferSize - 1] = 0;
  934. }
  935. else if ((dwBufferSize * sizeof(WCHAR)) >= sizeof(WCHAR)) {
  936. mszObjectList[0] = 0;
  937. }
  938. else if ((dwBufferSize * sizeof(WCHAR)) != 0) {
  939. // then the buffer is too small
  940. pdhStatus = PDH_MORE_DATA;
  941. }
  942. else {
  943. // buffer size of 0 is OK as a query for the required size
  944. }
  945. }
  946. }
  947. __except (EXCEPTION_EXECUTE_HANDLER) {
  948. pdhStatus = PDH_INVALID_ARGUMENT;
  949. }
  950. }
  951. if (pdhStatus == ERROR_SUCCESS) {
  952. pdhStatus = WAIT_FOR_AND_LOCK_MUTEX (hPdhDataMutex);
  953. }
  954. if (pdhStatus == ERROR_SUCCESS) {
  955. __try {
  956. switch (dwDataSource) {
  957. case DATA_SOURCE_REGISTRY:
  958. pdhStatus = PdhiEnumObjects (
  959. (LPWSTR)szMachineName,
  960. (LPVOID)mszObjectList,
  961. &dwBufferSize,
  962. dwDetailLevel,
  963. bRefresh,
  964. TRUE);
  965. break;
  966. case DATA_SOURCE_WBEM:
  967. pdhStatus = PdhiEnumWbemObjects (
  968. (LPWSTR)szMachineName,
  969. (LPVOID)mszObjectList,
  970. &dwBufferSize,
  971. dwDetailLevel, // not used
  972. bRefresh,
  973. TRUE);
  974. break;
  975. case DATA_SOURCE_LOGFILE:
  976. pdhStatus = PdhiEnumLoggedObjects (
  977. hDataSource,
  978. (LPWSTR) szMachineName,
  979. (LPVOID) mszObjectList,
  980. & dwBufferSize,
  981. dwDetailLevel,
  982. bRefresh,
  983. TRUE);
  984. break;
  985. default:
  986. assert (FALSE);
  987. }
  988. }
  989. __except (EXCEPTION_EXECUTE_HANDLER) {
  990. pdhStatus = PDH_INVALID_ARGUMENT;
  991. }
  992. RELEASE_MUTEX (hPdhDataMutex);
  993. __try {
  994. * pcchBufferSize = dwBufferSize;
  995. }
  996. __except (EXCEPTION_EXECUTE_HANDLER) {
  997. pdhStatus = PDH_INVALID_ARGUMENT;
  998. }
  999. }
  1000. return pdhStatus;
  1001. }
  1002. PDH_FUNCTION
  1003. PdhEnumObjectsW (
  1004. IN LPCWSTR szDataSource,
  1005. IN LPCWSTR szMachineName,
  1006. IN LPWSTR mszObjectList,
  1007. IN LPDWORD pcchBufferSize,
  1008. IN DWORD dwDetailLevel,
  1009. IN BOOL bRefresh
  1010. )
  1011. /*++
  1012. Routine Description:
  1013. Lists the performance objects found on the specified machine as
  1014. a MSZ UNICODE string list.
  1015. Arguments:
  1016. IN LPCWSTR szDataSource
  1017. NULL for current real-time data or the name of a log file
  1018. IN LPCWSTR szMachineName
  1019. The machine to list objects from
  1020. IN LPWSTR mszObjectList
  1021. a pointer to the buffer to receive the list of performance
  1022. objects
  1023. IN LPDWORD pcchBufferSize
  1024. a pointer to the DWORD containing the size of the mszObjectList
  1025. buffer in characters.
  1026. IN DWORD dwDetailLevel
  1027. The detail level to use as a filter of objects. All objects
  1028. with a detail level less than or equal to that specified
  1029. by this argument will be returned.
  1030. IN BOOL bRefresh
  1031. TRUE = retrive a new perf. data buffer for this machine before
  1032. listing the objects
  1033. FALSE = use the currently cached perf data buffer for this
  1034. machine to enumerate objects
  1035. Return Value:
  1036. ERROR_SUCCESS if the function completes successfully. Otherwise a
  1037. PDH_ error status if not.
  1038. PDH_MORE_DATA is returned when there are more entries available to
  1039. return than there is room in the buffer. Some entries may be
  1040. returned in the buffer though.
  1041. PDH_INSUFFICIENT_BUFFER is returned when there is not enough
  1042. room in the buffer for ANY data.
  1043. PDH_CSTATUS_NO_MACHINE is returned when the specified machine
  1044. is offline or unavailable.
  1045. PDH_INVALID_ARGUMENT is returned if a required argument is not provided
  1046. or a reserved argument is not NULL
  1047. --*/
  1048. {
  1049. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  1050. DWORD dwDataSource = 0;
  1051. HLOG hDataSource = H_REALTIME_DATASOURCE;
  1052. DebugPrint((4, "PdhEnumObjectsW BEGIN\n"));
  1053. __try {
  1054. if (szDataSource != NULL) {
  1055. // test for read access to the name
  1056. if (*szDataSource == 0) {
  1057. pdhStatus = PDH_INVALID_ARGUMENT;
  1058. }
  1059. } // else NULL is a valid arg
  1060. dwDataSource = DataSourceTypeW(szDataSource);
  1061. }
  1062. __except (EXCEPTION_EXECUTE_HANDLER) {
  1063. pdhStatus = PDH_INVALID_ARGUMENT;
  1064. }
  1065. if (pdhStatus == ERROR_SUCCESS) {
  1066. if (dwDataSource == DATA_SOURCE_WBEM) {
  1067. hDataSource = H_WBEM_DATASOURCE;
  1068. }
  1069. else if (dwDataSource == DATA_SOURCE_LOGFILE) {
  1070. DWORD dwLogType = 0;
  1071. pdhStatus = PdhOpenLogW(
  1072. szDataSource,
  1073. PDH_LOG_READ_ACCESS | PDH_LOG_OPEN_EXISTING,
  1074. & dwLogType,
  1075. NULL,
  1076. 0,
  1077. NULL,
  1078. & hDataSource);
  1079. }
  1080. }
  1081. if (pdhStatus == ERROR_SUCCESS) {
  1082. pdhStatus = PdhEnumObjectsHW(hDataSource,
  1083. szMachineName,
  1084. mszObjectList,
  1085. pcchBufferSize,
  1086. dwDetailLevel,
  1087. bRefresh);
  1088. if (dwDataSource == DATA_SOURCE_LOGFILE) {
  1089. PdhCloseLog(hDataSource, 0);
  1090. }
  1091. }
  1092. DebugPrint((4, "PdhEnumObjectsW END status 0x%08X\n", pdhStatus));
  1093. return pdhStatus;
  1094. }
  1095. PDH_FUNCTION
  1096. PdhEnumObjectsHA (
  1097. IN HLOG hDataSource,
  1098. IN LPCSTR szMachineName,
  1099. IN LPSTR mszObjectList,
  1100. IN LPDWORD pcchBufferSize,
  1101. IN DWORD dwDetailLevel,
  1102. IN BOOL bRefresh
  1103. )
  1104. {
  1105. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  1106. LPWSTR szWideName;
  1107. DWORD dwNameLength = 0;
  1108. DWORD dwDataSource = 0;
  1109. DWORD dwBufferSize = 0;
  1110. if (pcchBufferSize == NULL) {
  1111. pdhStatus = PDH_INVALID_ARGUMENT;
  1112. }
  1113. else {
  1114. __try {
  1115. dwDataSource = DataSourceTypeH(hDataSource);
  1116. if (szMachineName != NULL) {
  1117. // test buffer access
  1118. if (*szMachineName != 0) {
  1119. if (pdhStatus == ERROR_SUCCESS) {
  1120. dwNameLength = lstrlenA (szMachineName);
  1121. }
  1122. else {
  1123. dwNameLength = 0;
  1124. }
  1125. }
  1126. else {
  1127. // null machine names are not permitted
  1128. pdhStatus = PDH_INVALID_ARGUMENT;
  1129. }
  1130. }
  1131. else {
  1132. dwNameLength = 0;
  1133. }
  1134. if (pdhStatus == ERROR_SUCCESS) {
  1135. dwBufferSize = * pcchBufferSize;
  1136. }
  1137. if (pdhStatus == ERROR_SUCCESS) {
  1138. if (dwBufferSize >= sizeof (DWORD)) {
  1139. // test writing to the buffers to make sure they are valid
  1140. CLEAR_FIRST_FOUR_BYTES (mszObjectList);
  1141. mszObjectList[dwBufferSize-1] = 0;
  1142. }
  1143. else if (dwBufferSize >= sizeof(CHAR)) {
  1144. mszObjectList[0] = 0;
  1145. }
  1146. }
  1147. }
  1148. __except (EXCEPTION_EXECUTE_HANDLER) {
  1149. pdhStatus = PDH_INVALID_ARGUMENT;
  1150. }
  1151. }
  1152. if (pdhStatus == ERROR_SUCCESS) {
  1153. pdhStatus = WAIT_FOR_AND_LOCK_MUTEX (hPdhDataMutex);
  1154. }
  1155. if (pdhStatus == ERROR_SUCCESS) {
  1156. if (dwNameLength > 0) {
  1157. szWideName = G_ALLOC ((dwNameLength+1) * sizeof(WCHAR));
  1158. if (szWideName == NULL) {
  1159. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  1160. }
  1161. else {
  1162. __try {
  1163. MultiByteToWideChar(_getmbcp(),
  1164. 0,
  1165. szMachineName,
  1166. dwNameLength,
  1167. szWideName,
  1168. dwNameLength + 1);
  1169. }
  1170. __except (EXCEPTION_EXECUTE_HANDLER) {
  1171. pdhStatus = PDH_INVALID_ARGUMENT;
  1172. }
  1173. }
  1174. }
  1175. else {
  1176. szWideName = NULL;
  1177. }
  1178. if (pdhStatus == ERROR_SUCCESS) {
  1179. __try {
  1180. switch (dwDataSource) {
  1181. case DATA_SOURCE_REGISTRY:
  1182. pdhStatus = PdhiEnumObjects (
  1183. szWideName,
  1184. (LPVOID)mszObjectList,
  1185. &dwBufferSize,
  1186. dwDetailLevel,
  1187. bRefresh,
  1188. FALSE);
  1189. break;
  1190. case DATA_SOURCE_WBEM:
  1191. pdhStatus = PdhiEnumWbemObjects (
  1192. (LPWSTR)szWideName,
  1193. (LPVOID)mszObjectList,
  1194. &dwBufferSize,
  1195. dwDetailLevel, // not used
  1196. bRefresh,
  1197. FALSE);
  1198. break;
  1199. case DATA_SOURCE_LOGFILE:
  1200. pdhStatus = PdhiEnumLoggedObjects (
  1201. hDataSource,
  1202. (LPWSTR) szWideName,
  1203. (LPVOID) mszObjectList,
  1204. & dwBufferSize,
  1205. dwDetailLevel,
  1206. bRefresh,
  1207. FALSE);
  1208. break;
  1209. default:
  1210. assert (FALSE);
  1211. }
  1212. * pcchBufferSize = dwBufferSize;
  1213. }
  1214. __except (EXCEPTION_EXECUTE_HANDLER) {
  1215. pdhStatus = PDH_INVALID_ARGUMENT;
  1216. }
  1217. }
  1218. RELEASE_MUTEX (hPdhDataMutex);
  1219. if (szWideName != NULL) G_FREE (szWideName);
  1220. }
  1221. return pdhStatus;
  1222. }
  1223. PDH_FUNCTION
  1224. PdhEnumObjectsA (
  1225. IN LPCSTR szDataSource,
  1226. IN LPCSTR szMachineName,
  1227. IN LPSTR mszObjectList,
  1228. IN LPDWORD pcchBufferSize,
  1229. IN DWORD dwDetailLevel,
  1230. IN BOOL bRefresh
  1231. )
  1232. /*++
  1233. Routine Description:
  1234. Lists the performance objects found on the specified machine as
  1235. a MSZ ANSI string list.
  1236. Arguments:
  1237. IN LPCSTR szDataSource
  1238. NULL for current real-time data or the name of a log file
  1239. IN LPCSTR szMachineName
  1240. The machine to list objects from
  1241. IN LPSTR mszObjectList
  1242. a pointer to the buffer to receive the list of performance
  1243. objects
  1244. IN LPDWORD pcchBufferSize
  1245. a pointer to the DWORD containing the size of the mszObjectList
  1246. buffer in characters.
  1247. IN DWORD dwDetailLevel
  1248. The detail level to use as a filter of objects. All objects
  1249. with a detail level less than or equal to that specified
  1250. by this argument will be returned.
  1251. IN BOOL bRefresh
  1252. TRUE = retrive a new perf. data buffer for this machine before
  1253. listing the objects
  1254. FALSE = use the currently cached perf data buffer for this
  1255. machine to enumerate objects
  1256. Return Value:
  1257. ERROR_SUCCESS if the function completes successfully. Otherwise a
  1258. PDH_ error status if not.
  1259. PDH_MORE_DATA is returned when there are more entries available to
  1260. return than there is room in the buffer. Some entries may be
  1261. returned in the buffer though.
  1262. PDH_INSUFFICIENT_BUFFER is returned when there is not enough
  1263. room in the buffer for ANY data.
  1264. PDH_CSTATUS_NO_MACHINE is returned when the specified machine
  1265. is offline or unavailable.
  1266. PDH_INVALID_ARGUMENT is returned if a required argument is not provided
  1267. or a reserved argument is not NULL
  1268. --*/
  1269. {
  1270. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  1271. HLOG hDataSource = H_REALTIME_DATASOURCE;
  1272. DWORD dwDataSource = 0;
  1273. DebugPrint((4, "PdhEnumObjectsA BEGIN\n"));
  1274. __try {
  1275. if (szDataSource != NULL) {
  1276. // test for read access to the name
  1277. if (*szDataSource == 0) {
  1278. pdhStatus = PDH_INVALID_ARGUMENT;
  1279. }
  1280. } // else NULL is a valid arg
  1281. dwDataSource = DataSourceTypeA(szDataSource);
  1282. }
  1283. __except (EXCEPTION_EXECUTE_HANDLER) {
  1284. pdhStatus = PDH_INVALID_ARGUMENT;
  1285. }
  1286. if (pdhStatus == ERROR_SUCCESS) {
  1287. if (dwDataSource == DATA_SOURCE_WBEM) {
  1288. hDataSource = H_WBEM_DATASOURCE;
  1289. }
  1290. else if (dwDataSource == DATA_SOURCE_LOGFILE) {
  1291. DWORD dwLogType = 0;
  1292. pdhStatus = PdhOpenLogA(
  1293. szDataSource,
  1294. PDH_LOG_READ_ACCESS | PDH_LOG_OPEN_EXISTING,
  1295. & dwLogType,
  1296. NULL,
  1297. 0,
  1298. NULL,
  1299. & hDataSource);
  1300. }
  1301. }
  1302. if (pdhStatus == ERROR_SUCCESS) {
  1303. pdhStatus = PdhEnumObjectsHA(hDataSource,
  1304. szMachineName,
  1305. mszObjectList,
  1306. pcchBufferSize,
  1307. dwDetailLevel,
  1308. bRefresh);
  1309. if (dwDataSource == DATA_SOURCE_LOGFILE) {
  1310. PdhCloseLog(hDataSource, 0);
  1311. }
  1312. }
  1313. DebugPrint((4, "PdhEnumObjectsA END status 0x%08X\n", pdhStatus));
  1314. return pdhStatus;
  1315. }
  1316. STATIC_PDH_FUNCTION
  1317. PdhiEnumObjectItems (
  1318. IN LPCWSTR szMachineName,
  1319. IN LPCWSTR szObjectName,
  1320. IN LPVOID mszCounterList,
  1321. IN LPDWORD pcchCounterListLength,
  1322. IN LPVOID mszInstanceList,
  1323. IN LPDWORD pcchInstanceListLength,
  1324. IN DWORD dwDetailLevel,
  1325. IN DWORD dwFlags,
  1326. IN BOOL bUnicode
  1327. )
  1328. /*++
  1329. Routine Description:
  1330. Lists the items found in the specified performance object on the
  1331. specified machine. Thie includes the performance counters and,
  1332. if supported by the object, the object instances.
  1333. Arguments:
  1334. IN LPCWSTR szMachineName
  1335. The name of the machine to list the objects
  1336. IN LPCWSTR szObjectName
  1337. the name of the object to list items from
  1338. IN LPVOID mszCounterList
  1339. pointer to the buffer that will receive the list of counters
  1340. provided by this object. This argument may be NULL if
  1341. the value of pcchCounterLIstLength is 0.
  1342. IN LPDWORD pcchCounterListLength
  1343. pointer to a DWORD that contains the size in characters
  1344. of the buffer referenced by mszCounterList. The characters
  1345. assumed are defined by bUnicode.
  1346. IN LPVOID mszInstanceList
  1347. pointer to the buffer that will receive the list of instances
  1348. of the specified performance object. This argument may be
  1349. NULL if the value of pcchInstanceListLength is 0.
  1350. IN LPDWORD pcchInstanceListLength
  1351. pointer to the DWORD containing the size, in characters, of
  1352. the buffer referenced by the mszInstanceList argument. If the
  1353. value in this DWORD is 0, then no data will be written to the
  1354. buffer, only the required size will be returned.
  1355. If the value returned is 0, then this object does not
  1356. return instances, if the value returned is 2, then the
  1357. object supports instances, but does not currently have
  1358. any instances to return (2 = the size of an MSZ list in
  1359. characters)
  1360. IN DWORD dwDetailLevel
  1361. The detail level of the performance items to return. All items
  1362. that are of the specified detail level or less will be
  1363. returned.
  1364. IN DWORD dwFlags
  1365. Not Used, must be 0.
  1366. IN BOOL bUnicode
  1367. TRUE = UNICODE characters will be written to the pMachineList
  1368. buffer
  1369. FALSE = ANSI characters will be writtn to the pMachinList buffer
  1370. Return Value:
  1371. ERROR_SUCCESS if the function completes successfully. Otherwise a
  1372. PDH_ error status if not.
  1373. PDH_MORE_DATA is returned when there are more entries available to
  1374. return than there is room in the buffer. Some entries may be
  1375. returned in the buffer though.
  1376. PDH_INSUFFICIENT_BUFFER is returned when there is not enough
  1377. room in the buffer for ANY data.
  1378. PDH_CSTATUS_NO_MACHINE is returned when the specified machine
  1379. is offline or unavailable.
  1380. PDH_CSTATUS_NO_OBJECT is returned if the specified object could
  1381. not be found on the specified machine.
  1382. --*/
  1383. {
  1384. PPERF_MACHINE pMachine;
  1385. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  1386. PDH_STATUS pdhCtrStatus = ERROR_SUCCESS;
  1387. PDH_STATUS pdhInstStatus = ERROR_SUCCESS;
  1388. DWORD DefNdx;
  1389. PERF_OBJECT_TYPE *pObjectDef;
  1390. PERF_COUNTER_DEFINITION *pCounterDef;
  1391. PERF_INSTANCE_DEFINITION *pInstanceDef;
  1392. DWORD dwReqCounterLength = 0;
  1393. DWORD dwReqInstanceLength = 0;
  1394. LPVOID szNextName;
  1395. DWORD dwNameLength;
  1396. WCHAR szInstanceName[1024];
  1397. WCHAR szNumberString[32];
  1398. DWORD dwMaxInstanceLength;
  1399. DWORD dwMaxCounterLength;
  1400. LPWSTR szCounterName;
  1401. DWORD dwGmFlags;
  1402. DBG_UNREFERENCED_PARAMETER (dwFlags);
  1403. DebugPrint((4, "PdhiEnumObjectItems BEGIN\n"));
  1404. pMachine = GetMachine ((LPWSTR)szMachineName, 0);
  1405. if (pMachine != NULL) {
  1406. if ((dwDetailLevel & PERF_DETAIL_COSTLY) &&
  1407. !(pMachine->dwMachineFlags & PDHIPM_FLAGS_HAVE_COSTLY)) {
  1408. // then get them
  1409. dwGmFlags = PDH_GM_UPDATE_PERFDATA | PDH_GM_READ_COSTLY_DATA;
  1410. pMachine = GetMachine ((LPWSTR)szMachineName, dwGmFlags);
  1411. }
  1412. }
  1413. if (pMachine != NULL) {
  1414. dwMaxCounterLength = *pcchCounterListLength;
  1415. dwMaxInstanceLength = *pcchInstanceListLength;
  1416. // make sure the machine connection is valid
  1417. if (pMachine->dwStatus == ERROR_SUCCESS) {
  1418. pObjectDef = GetObjectDefByName (
  1419. pMachine->pSystemPerfData,
  1420. pMachine->dwLastPerfString,
  1421. pMachine->szPerfStrings,
  1422. szObjectName);
  1423. if (pObjectDef != NULL) {
  1424. // add up counter name sizes
  1425. pCounterDef = FirstCounter (pObjectDef);
  1426. szNextName = mszCounterList;
  1427. for (DefNdx = 0; DefNdx < pObjectDef->NumCounters; DefNdx++) {
  1428. if (!((pCounterDef->CounterType & PERF_DISPLAY_NOSHOW) &&
  1429. // this is a hack because this type is not defined correctly
  1430. (pCounterDef->CounterType != PERF_AVERAGE_BULK)) &&
  1431. (pCounterDef->DetailLevel <= dwDetailLevel)) {
  1432. // then this is a visible counter so get its name.
  1433. if ((pCounterDef->CounterNameTitleIndex > 0) &&
  1434. (pCounterDef->CounterNameTitleIndex < pMachine->dwLastPerfString)) {
  1435. // look up name of each object & store size
  1436. szCounterName =
  1437. (LPWSTR)PdhiLookupPerfNameByIndex (
  1438. pMachine,
  1439. pCounterDef->CounterNameTitleIndex);
  1440. } else {
  1441. // no matching string found for this index
  1442. szCounterName = NULL;
  1443. }
  1444. if (szCounterName == NULL) {
  1445. // then use the index numbe for lack of a better
  1446. // string to use
  1447. _ltow (pCounterDef->CounterNameTitleIndex,
  1448. szNumberString, 10);
  1449. szCounterName = &szNumberString[0];
  1450. }
  1451. if (bUnicode) {
  1452. dwNameLength = lstrlenW(szCounterName) + 1;
  1453. if ( szNextName != NULL
  1454. && dwReqCounterLength <= dwMaxCounterLength) {
  1455. lstrcpyW ((LPWSTR) szNextName, szCounterName);
  1456. (LPBYTE) szNextName += sizeof(WCHAR) * (dwNameLength - 1);
  1457. * ((LPWSTR) szNextName) ++ = 0;
  1458. }
  1459. else {
  1460. pdhCtrStatus = PDH_MORE_DATA;
  1461. }
  1462. }
  1463. else {
  1464. dwNameLength = (dwReqCounterLength <= dwMaxCounterLength)
  1465. ? (dwMaxCounterLength - dwReqCounterLength)
  1466. : (0);
  1467. pdhCtrStatus = PdhiConvertUnicodeToAnsi(_getmbcp(),
  1468. szCounterName,
  1469. (LPSTR) szNextName,
  1470. & dwNameLength);
  1471. if (pdhCtrStatus == ERROR_SUCCESS) {
  1472. (LPBYTE) szNextName += sizeof(CHAR) * dwNameLength;
  1473. }
  1474. }
  1475. dwReqCounterLength += dwNameLength;
  1476. } else {
  1477. // this counter is not displayed either because
  1478. // it's hidden (e.g. the 2nd part of a 2 part counter
  1479. // or it's the wrong detail level
  1480. }
  1481. pCounterDef = NextCounter(pCounterDef); // get next
  1482. }
  1483. if (DefNdx == 0) {
  1484. // no counters found so at least one NULL is required
  1485. dwReqCounterLength += 1;
  1486. // see if this string will fit
  1487. if (dwReqCounterLength <= dwMaxCounterLength) {
  1488. if (bUnicode) {
  1489. *((LPWSTR)szNextName)++ = 0;
  1490. } else {
  1491. *((LPSTR)szNextName)++ = 0;
  1492. }
  1493. } else {
  1494. // more space needed than was reported
  1495. pdhCtrStatus = PDH_MORE_DATA;
  1496. }
  1497. }
  1498. // add terminating NULL
  1499. dwReqCounterLength += 1;
  1500. // see if this string will fit
  1501. if (dwReqCounterLength <= dwMaxCounterLength) {
  1502. if (bUnicode) {
  1503. *((LPWSTR)szNextName)++ = 0;
  1504. } else {
  1505. *((LPSTR)szNextName)++ = 0;
  1506. }
  1507. } else {
  1508. // more space needed than was reported
  1509. pdhCtrStatus = PDH_MORE_DATA;
  1510. }
  1511. // do instances now.
  1512. szNextName = mszInstanceList;
  1513. // add up instance name sizes
  1514. if (pObjectDef->NumInstances != PERF_NO_INSTANCES) {
  1515. if ((pObjectDef->DetailLevel <= dwDetailLevel) &&
  1516. (pObjectDef->NumInstances > 0)) {
  1517. // the object HAS instances and is of the
  1518. // approrpriate detail level, so list them
  1519. pInstanceDef = FirstInstance (pObjectDef);
  1520. for (DefNdx = 0; DefNdx < (DWORD)pObjectDef->NumInstances; DefNdx++) {
  1521. dwNameLength = GetFullInstanceNameStr(
  1522. pMachine->pSystemPerfData,
  1523. pObjectDef, pInstanceDef,
  1524. szInstanceName);
  1525. if (dwNameLength > 0) {
  1526. if (bUnicode) {
  1527. // add length of this string + it's null
  1528. dwNameLength += 1;
  1529. if ( szNextName != NULL
  1530. && dwReqInstanceLength + dwNameLength <= dwMaxInstanceLength) {
  1531. lstrcpyW ((LPWSTR) szNextName, szInstanceName);
  1532. (LPBYTE) szNextName += sizeof(WCHAR) * (dwNameLength - 1);
  1533. * ((LPWSTR) szNextName) ++ = 0;
  1534. }
  1535. else {
  1536. pdhInstStatus = PDH_MORE_DATA;
  1537. }
  1538. }
  1539. else {
  1540. dwNameLength = (dwReqInstanceLength <= dwMaxInstanceLength)
  1541. ? (dwMaxInstanceLength - dwReqInstanceLength) : (0);
  1542. pdhInstStatus = PdhiConvertUnicodeToAnsi(_getmbcp(),
  1543. szInstanceName,
  1544. (LPSTR) szNextName,
  1545. & dwNameLength);
  1546. if (pdhInstStatus == ERROR_SUCCESS) {
  1547. (LPBYTE) szNextName += sizeof(CHAR) * dwNameLength;
  1548. }
  1549. }
  1550. dwReqInstanceLength += dwNameLength;
  1551. }
  1552. // go to next instance of this object
  1553. pInstanceDef = NextInstance(pInstanceDef); // get next
  1554. }
  1555. // add the terminating NULL char
  1556. dwReqInstanceLength += 1;
  1557. if (dwMaxInstanceLength > 0) {
  1558. // see if this string will fit
  1559. if (dwReqInstanceLength <= dwMaxInstanceLength) {
  1560. if (bUnicode) {
  1561. *((LPWSTR)szNextName)++ = 0;
  1562. } else {
  1563. *((LPSTR)szNextName)++ = 0;
  1564. }
  1565. } else {
  1566. // more space needed than was reported
  1567. pdhInstStatus = PDH_MORE_DATA;
  1568. }
  1569. }
  1570. } else {
  1571. // there are no instances present, but the object does
  1572. // support instances so return a zero length MSZ (which
  1573. // actually contains 2 NULL chars
  1574. dwReqInstanceLength = 2;
  1575. // see if this string will fit
  1576. if (dwReqInstanceLength <= dwMaxInstanceLength) {
  1577. if (bUnicode) {
  1578. *((LPWSTR)szNextName)++ = 0;
  1579. *((LPWSTR)szNextName)++ = 0;
  1580. } else {
  1581. *((LPSTR)szNextName)++ = 0;
  1582. *((LPSTR)szNextName)++ = 0;
  1583. }
  1584. } else {
  1585. // more space needed than was reported
  1586. pdhInstStatus = PDH_MORE_DATA;
  1587. }
  1588. }
  1589. } else {
  1590. // the object has no instances and never will
  1591. // so return a 0 length and NO string
  1592. dwReqInstanceLength = 0;
  1593. }
  1594. *pcchCounterListLength = dwReqCounterLength;
  1595. *pcchInstanceListLength = dwReqInstanceLength;
  1596. if (pdhStatus == ERROR_SUCCESS) {
  1597. pdhStatus = (pdhCtrStatus == ERROR_SUCCESS)
  1598. ? (pdhInstStatus) : (pdhCtrStatus);
  1599. }
  1600. } else {
  1601. // object not found on this machine
  1602. pdhStatus = PDH_CSTATUS_NO_OBJECT;
  1603. }
  1604. } else {
  1605. // machine is off line
  1606. pdhStatus = pMachine->dwStatus;
  1607. }
  1608. pMachine->dwRefCount--;
  1609. RELEASE_MUTEX (pMachine->hMutex);
  1610. } else {
  1611. pdhStatus = GetLastError();
  1612. }
  1613. DebugPrint((4, "PdhiEnumObjectItems END status 0x%08X\n", pdhStatus));
  1614. return pdhStatus;
  1615. }
  1616. PDH_FUNCTION
  1617. PdhEnumObjectItemsHW (
  1618. IN HLOG hDataSource,
  1619. IN LPCWSTR szMachineName,
  1620. IN LPCWSTR szObjectName,
  1621. IN LPWSTR mszCounterList,
  1622. IN LPDWORD pcchCounterListLength,
  1623. IN LPWSTR mszInstanceList,
  1624. IN LPDWORD pcchInstanceListLength,
  1625. IN DWORD dwDetailLevel,
  1626. IN DWORD dwFlags
  1627. )
  1628. {
  1629. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  1630. DWORD dwCBufferSize = 0;
  1631. DWORD dwIBufferSize = 0;
  1632. DWORD dwDataSource = 0;
  1633. if ((pcchCounterListLength == NULL) || (pcchInstanceListLength == NULL)) {
  1634. pdhStatus = PDH_INVALID_ARGUMENT;
  1635. }
  1636. else {
  1637. __try {
  1638. dwDataSource = DataSourceTypeH(hDataSource);
  1639. if (szMachineName != NULL) {
  1640. if (* szMachineName == 0) {
  1641. pdhStatus = PDH_INVALID_ARGUMENT;
  1642. }
  1643. }
  1644. if (pdhStatus == ERROR_SUCCESS) {
  1645. if (* szObjectName == 0) {
  1646. pdhStatus = PDH_INVALID_ARGUMENT;
  1647. }
  1648. }
  1649. if (pdhStatus == ERROR_SUCCESS) {
  1650. // test writing to the size buffers to make sure they are valid
  1651. dwCBufferSize = *pcchCounterListLength;
  1652. }
  1653. if (pdhStatus == ERROR_SUCCESS) {
  1654. if ((dwCBufferSize * sizeof(WCHAR)) >= sizeof (DWORD)) {
  1655. //then the buffer must be valid
  1656. CLEAR_FIRST_FOUR_BYTES (mszCounterList);
  1657. mszCounterList[dwCBufferSize -1] = 0;
  1658. }
  1659. else if ((dwCBufferSize * sizeof(WCHAR)) >= sizeof (WCHAR)) {
  1660. mszCounterList[0] = 0;
  1661. }
  1662. else if ((dwCBufferSize * sizeof(WCHAR)) != 0) {
  1663. // then the buffer is too small
  1664. pdhStatus = PDH_MORE_DATA;
  1665. }
  1666. }
  1667. if (pdhStatus == ERROR_SUCCESS) {
  1668. dwIBufferSize = *pcchInstanceListLength;
  1669. }
  1670. if (pdhStatus == ERROR_SUCCESS) {
  1671. if ((dwIBufferSize * sizeof(WCHAR)) >= sizeof (DWORD)) {
  1672. //then the buffer must be valid
  1673. CLEAR_FIRST_FOUR_BYTES (mszInstanceList);
  1674. mszInstanceList[dwIBufferSize -1] = 0;
  1675. }
  1676. else if ((dwIBufferSize * sizeof(WCHAR)) >= sizeof(WCHAR)) {
  1677. mszInstanceList[0] = 0;
  1678. }
  1679. else if ((dwIBufferSize * sizeof(WCHAR)) != 0) {
  1680. // then the buffer is too small
  1681. pdhStatus = PDH_MORE_DATA;
  1682. }
  1683. }
  1684. }
  1685. __except (EXCEPTION_EXECUTE_HANDLER) {
  1686. pdhStatus = PDH_INVALID_ARGUMENT;
  1687. }
  1688. }
  1689. if (dwFlags != 0L) {
  1690. pdhStatus = PDH_INVALID_ARGUMENT;
  1691. }
  1692. if (pdhStatus == ERROR_SUCCESS) {
  1693. pdhStatus = WAIT_FOR_AND_LOCK_MUTEX (hPdhDataMutex);
  1694. }
  1695. if (pdhStatus == ERROR_SUCCESS) {
  1696. __try {
  1697. switch (dwDataSource) {
  1698. case DATA_SOURCE_REGISTRY:
  1699. pdhStatus = PdhiEnumObjectItems (
  1700. (LPWSTR)szMachineName,
  1701. szObjectName,
  1702. (LPVOID)mszCounterList,
  1703. &dwCBufferSize,
  1704. (LPVOID)mszInstanceList,
  1705. &dwIBufferSize,
  1706. dwDetailLevel,
  1707. dwFlags,
  1708. TRUE);
  1709. break;
  1710. case DATA_SOURCE_WBEM:
  1711. pdhStatus = PdhiEnumWbemObjectItems (
  1712. (LPWSTR)szMachineName,
  1713. szObjectName,
  1714. (LPVOID)mszCounterList,
  1715. &dwCBufferSize,
  1716. (LPVOID)mszInstanceList,
  1717. &dwIBufferSize,
  1718. dwDetailLevel,
  1719. dwFlags,
  1720. TRUE);
  1721. break;
  1722. case DATA_SOURCE_LOGFILE:
  1723. pdhStatus = PdhiEnumLoggedObjectItems (
  1724. hDataSource,
  1725. (LPWSTR) szMachineName,
  1726. szObjectName,
  1727. (LPVOID) mszCounterList,
  1728. & dwCBufferSize,
  1729. (LPVOID) mszInstanceList,
  1730. & dwIBufferSize,
  1731. dwDetailLevel,
  1732. dwFlags,
  1733. TRUE);
  1734. break;
  1735. default:
  1736. assert (FALSE);
  1737. }
  1738. }
  1739. __except (EXCEPTION_EXECUTE_HANDLER) {
  1740. pdhStatus = PDH_INVALID_ARGUMENT;
  1741. }
  1742. RELEASE_MUTEX (hPdhDataMutex);
  1743. __try {
  1744. *pcchCounterListLength = dwCBufferSize;
  1745. *pcchInstanceListLength = dwIBufferSize;
  1746. }
  1747. __except (EXCEPTION_EXECUTE_HANDLER) {
  1748. pdhStatus = PDH_INVALID_ARGUMENT;
  1749. }
  1750. }
  1751. return pdhStatus;
  1752. }
  1753. PDH_FUNCTION
  1754. PdhEnumObjectItemsW (
  1755. IN LPCWSTR szDataSource,
  1756. IN LPCWSTR szMachineName,
  1757. IN LPCWSTR szObjectName,
  1758. IN LPWSTR mszCounterList,
  1759. IN LPDWORD pcchCounterListLength,
  1760. IN LPWSTR mszInstanceList,
  1761. IN LPDWORD pcchInstanceListLength,
  1762. IN DWORD dwDetailLevel,
  1763. IN DWORD dwFlags
  1764. )
  1765. /*++
  1766. Routine Description:
  1767. Lists the items found in the specified performance object on the
  1768. specified machine. Thie includes the performance counters and,
  1769. if supported by the object, the object instances.
  1770. Arguments:
  1771. IN LPCWSTR szDataSource
  1772. NULL for current real-time data or the name of a log file
  1773. IN LPCWSTR szMachineName
  1774. The name of the machine to list the objects
  1775. IN LPCWSTR szObjectName
  1776. the name of the object to list items from
  1777. IN LPWSTR mszCounterList
  1778. pointer to the buffer that will receive the list of counters
  1779. provided by this object. This argument may be NULL if
  1780. the value of pcchCounterLIstLength is 0.
  1781. IN LPDWORD pcchCounterListLength
  1782. pointer to a DWORD that contains the size in characters
  1783. of the buffer referenced by mszCounterList. The characters
  1784. assumed are defined by bUnicode.
  1785. IN LPWSTR mszInstanceList
  1786. pointer to the buffer that will receive the list of instances
  1787. of the specified performance object. This argument may be
  1788. NULL if the value of pcchInstanceListLength is 0.
  1789. IN LPDWORD pcchInstanceListLength
  1790. pointer to the DWORD containing the size, in characters, of
  1791. the buffer referenced by the mszInstanceList argument. If the
  1792. value in this DWORD is 0, then no data will be written to the
  1793. buffer, only the required size will be returned.
  1794. If the value returned is 0, then this object does not
  1795. return instances, if the value returned is 2, then the
  1796. object supports instances, but does not currently have
  1797. any instances to return (2 = the size of an MSZ list in
  1798. characters)
  1799. IN DWORD dwDetailLevel
  1800. The detail level of the performance items to return. All items
  1801. that are of the specified detail level or less will be
  1802. returned.
  1803. IN DWORD dwFlags
  1804. Not Used, must be 0.
  1805. Return Value:
  1806. ERROR_SUCCESS if the function completes successfully. Otherwise a
  1807. PDH_ error status if not.
  1808. PDH_MORE_DATA is returned when there are more entries available to
  1809. return than there is room in the buffer. Some entries may be
  1810. returned in the buffer though.
  1811. PDH_INSUFFICIENT_BUFFER is returned when there is not enough
  1812. room in the buffer for ANY data.
  1813. PDH_INVALID_ARGUMENT a required argument is not correct or reserved
  1814. argument is not 0 or NULL.
  1815. PDH_CSTATUS_NO_MACHINE is returned when the specified machine
  1816. is offline or unavailable.
  1817. PDH_CSTATUS_NO_OBJECT is returned if the specified object could
  1818. not be found on the specified machine.
  1819. --*/
  1820. {
  1821. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  1822. HLOG hDataSource = H_REALTIME_DATASOURCE;
  1823. DWORD dwDataSource = 0;
  1824. DebugPrint((4, "PdhEnumObjectItemsW BEGIN\n"));
  1825. __try {
  1826. if (szDataSource != NULL) {
  1827. // test for read access to the name
  1828. if (* szDataSource == 0) {
  1829. pdhStatus = PDH_INVALID_ARGUMENT;
  1830. }
  1831. } // else NULL is a valid arg
  1832. dwDataSource = DataSourceTypeW(szDataSource);
  1833. }
  1834. __except (EXCEPTION_EXECUTE_HANDLER) {
  1835. pdhStatus = PDH_INVALID_ARGUMENT;
  1836. }
  1837. if (pdhStatus == ERROR_SUCCESS) {
  1838. if (dwDataSource == DATA_SOURCE_WBEM) {
  1839. hDataSource = H_WBEM_DATASOURCE;
  1840. }
  1841. else if (dwDataSource == DATA_SOURCE_LOGFILE) {
  1842. DWORD dwLogType = 0;
  1843. pdhStatus = PdhOpenLogW(
  1844. szDataSource,
  1845. PDH_LOG_READ_ACCESS | PDH_LOG_OPEN_EXISTING,
  1846. & dwLogType,
  1847. NULL,
  1848. 0,
  1849. NULL,
  1850. & hDataSource);
  1851. }
  1852. }
  1853. if (pdhStatus == ERROR_SUCCESS) {
  1854. pdhStatus = PdhEnumObjectItemsHW(hDataSource,
  1855. szMachineName,
  1856. szObjectName,
  1857. mszCounterList,
  1858. pcchCounterListLength,
  1859. mszInstanceList,
  1860. pcchInstanceListLength,
  1861. dwDetailLevel,
  1862. dwFlags);
  1863. if (dwDataSource == DATA_SOURCE_LOGFILE) {
  1864. PdhCloseLog(hDataSource, 0);
  1865. }
  1866. }
  1867. DebugPrint((4, "PdhEnumObjectItemsW END status 0x%08X\n", pdhStatus));
  1868. return pdhStatus;
  1869. }
  1870. PDH_FUNCTION
  1871. PdhEnumObjectItemsHA (
  1872. IN HLOG hDataSource,
  1873. IN LPCSTR szMachineName,
  1874. IN LPCSTR szObjectName,
  1875. IN LPSTR mszCounterList,
  1876. IN LPDWORD pcchCounterListLength,
  1877. IN LPSTR mszInstanceList,
  1878. IN LPDWORD pcchInstanceListLength,
  1879. IN DWORD dwDetailLevel,
  1880. IN DWORD dwFlags
  1881. )
  1882. {
  1883. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  1884. DWORD dwMachineNameLength = 0;
  1885. DWORD dwObjectNameLength = 0;
  1886. LPWSTR szWideMachineName = NULL;
  1887. LPWSTR szWideObjectName = NULL;
  1888. DWORD dwDataSource = 0;
  1889. DWORD dwCBufferSize = 0;
  1890. DWORD dwIBufferSize = 0;
  1891. if ((pcchCounterListLength == NULL) || (pcchInstanceListLength == NULL)) {
  1892. pdhStatus = PDH_INVALID_ARGUMENT;
  1893. }
  1894. else {
  1895. __try {
  1896. dwDataSource = DataSourceTypeH(hDataSource);
  1897. if (szMachineName != NULL) {
  1898. if (* szMachineName == 0) {
  1899. pdhStatus = PDH_INVALID_ARGUMENT;
  1900. }
  1901. else {
  1902. dwMachineNameLength = lstrlenA(szMachineName);
  1903. }
  1904. }
  1905. else {
  1906. dwMachineNameLength = 0;
  1907. }
  1908. if (pdhStatus == ERROR_SUCCESS) {
  1909. if (szObjectName != NULL) {
  1910. if (* szObjectName == 0) {
  1911. pdhStatus = PDH_INVALID_ARGUMENT;
  1912. }
  1913. else {
  1914. dwObjectNameLength = lstrlenA(szObjectName);
  1915. }
  1916. }
  1917. else {
  1918. // object cannot be NULL
  1919. pdhStatus = PDH_INVALID_ARGUMENT;
  1920. }
  1921. }
  1922. if (pdhStatus == ERROR_SUCCESS) {
  1923. // test writing to the size buffers to make sure they are valid
  1924. dwCBufferSize = *pcchCounterListLength;
  1925. }
  1926. if (pdhStatus == ERROR_SUCCESS) {
  1927. if (dwCBufferSize >= sizeof(DWORD)) {
  1928. //then the buffer must be valid
  1929. CLEAR_FIRST_FOUR_BYTES (mszCounterList);
  1930. mszCounterList[dwCBufferSize - 1] = 0;
  1931. }
  1932. else if (dwCBufferSize >= sizeof(CHAR)) {
  1933. mszCounterList[0] = 0;
  1934. }
  1935. }
  1936. if (pdhStatus == ERROR_SUCCESS) {
  1937. dwIBufferSize = *pcchInstanceListLength;
  1938. }
  1939. if (pdhStatus == ERROR_SUCCESS) {
  1940. if (dwIBufferSize >= sizeof(DWORD)) {
  1941. //then the buffer must be valid
  1942. CLEAR_FIRST_FOUR_BYTES (mszInstanceList);
  1943. mszInstanceList[dwIBufferSize - 1] = 0;
  1944. }
  1945. else if (dwIBufferSize >= sizeof(CHAR)) {
  1946. mszInstanceList[0] = 0;
  1947. }
  1948. }
  1949. }
  1950. __except (EXCEPTION_EXECUTE_HANDLER) {
  1951. pdhStatus = PDH_INVALID_ARGUMENT;
  1952. }
  1953. }
  1954. if (dwFlags != 0L) {
  1955. pdhStatus = PDH_INVALID_ARGUMENT;
  1956. }
  1957. if (pdhStatus == ERROR_SUCCESS) {
  1958. pdhStatus = WAIT_FOR_AND_LOCK_MUTEX (hPdhDataMutex);
  1959. }
  1960. if (pdhStatus == ERROR_SUCCESS) {
  1961. __try {
  1962. if (dwMachineNameLength > 0) {
  1963. szWideMachineName = G_ALLOC( (dwMachineNameLength + 1)
  1964. * sizeof(WCHAR));
  1965. if (szWideMachineName != NULL) {
  1966. MultiByteToWideChar(_getmbcp(),
  1967. 0,
  1968. szMachineName,
  1969. dwMachineNameLength,
  1970. szWideMachineName,
  1971. dwMachineNameLength + 1);
  1972. }
  1973. else {
  1974. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  1975. }
  1976. }
  1977. else {
  1978. szWideMachineName = NULL;
  1979. }
  1980. if (dwObjectNameLength > 0) {
  1981. szWideObjectName = G_ALLOC( (dwObjectNameLength + 1)
  1982. * sizeof(WCHAR));
  1983. if (szWideObjectName != NULL) {
  1984. MultiByteToWideChar(_getmbcp(),
  1985. 0,
  1986. szObjectName,
  1987. dwObjectNameLength,
  1988. szWideObjectName,
  1989. dwObjectNameLength + 1);
  1990. }
  1991. else {
  1992. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  1993. }
  1994. }
  1995. else {
  1996. szWideObjectName = NULL;
  1997. }
  1998. if (pdhStatus == ERROR_SUCCESS) {
  1999. switch (dwDataSource) {
  2000. case DATA_SOURCE_REGISTRY:
  2001. pdhStatus = PdhiEnumObjectItems (
  2002. szWideMachineName,
  2003. szWideObjectName,
  2004. (LPVOID)mszCounterList,
  2005. &dwCBufferSize,
  2006. (LPVOID)mszInstanceList,
  2007. &dwIBufferSize,
  2008. dwDetailLevel,
  2009. dwFlags,
  2010. FALSE);
  2011. break;
  2012. case DATA_SOURCE_WBEM:
  2013. pdhStatus = PdhiEnumWbemObjectItems (
  2014. (LPWSTR)szWideMachineName,
  2015. szWideObjectName,
  2016. (LPVOID)mszCounterList,
  2017. &dwCBufferSize,
  2018. (LPVOID)mszInstanceList,
  2019. &dwIBufferSize,
  2020. dwDetailLevel,
  2021. dwFlags,
  2022. FALSE);
  2023. break;
  2024. case DATA_SOURCE_LOGFILE:
  2025. pdhStatus = PdhiEnumLoggedObjectItems (
  2026. hDataSource,
  2027. szWideMachineName,
  2028. szWideObjectName,
  2029. (LPVOID) mszCounterList,
  2030. & dwCBufferSize,
  2031. (LPVOID) mszInstanceList,
  2032. & dwIBufferSize,
  2033. dwDetailLevel,
  2034. dwFlags,
  2035. FALSE);
  2036. break;
  2037. default:
  2038. assert (FALSE);
  2039. }
  2040. }
  2041. }
  2042. __except (EXCEPTION_EXECUTE_HANDLER) {
  2043. pdhStatus = PDH_INVALID_ARGUMENT;
  2044. }
  2045. RELEASE_MUTEX (hPdhDataMutex);
  2046. if (szWideMachineName != NULL) G_FREE(szWideMachineName);
  2047. if (szWideObjectName != NULL) G_FREE(szWideObjectName);
  2048. __try {
  2049. * pcchCounterListLength = dwCBufferSize;
  2050. * pcchInstanceListLength = dwIBufferSize;
  2051. }
  2052. __except (EXCEPTION_EXECUTE_HANDLER) {
  2053. pdhStatus = PDH_INVALID_ARGUMENT;
  2054. }
  2055. }
  2056. return pdhStatus;
  2057. }
  2058. PDH_FUNCTION
  2059. PdhEnumObjectItemsA (
  2060. IN LPCSTR szDataSource,
  2061. IN LPCSTR szMachineName,
  2062. IN LPCSTR szObjectName,
  2063. IN LPSTR mszCounterList,
  2064. IN LPDWORD pcchCounterListLength,
  2065. IN LPSTR mszInstanceList,
  2066. IN LPDWORD pcchInstanceListLength,
  2067. IN DWORD dwDetailLevel,
  2068. IN DWORD dwFlags
  2069. )
  2070. /*++
  2071. Routine Description:
  2072. Lists the items found in the specified performance object on the
  2073. specified machine. Thie includes the performance counters and,
  2074. if supported by the object, the object instances.
  2075. Arguments:
  2076. IN LPCSTR szDataSource
  2077. NULL for current real-time data or the name of a log file
  2078. IN LPCSTR szMachineName
  2079. The name of the machine to list the objects
  2080. IN LPCSTR szObjectName
  2081. the name of the object to list items from
  2082. IN LPSTR mszCounterList
  2083. pointer to the buffer that will receive the list of counters
  2084. provided by this object. This argument may be NULL if
  2085. the value of pcchCounterLIstLength is 0.
  2086. IN LPDWORD pcchCounterListLength
  2087. pointer to a DWORD that contains the size in characters
  2088. of the buffer referenced by mszCounterList. The characters
  2089. assumed are defined by bUnicode.
  2090. IN LPSTR mszInstanceList
  2091. pointer to the buffer that will receive the list of instances
  2092. of the specified performance object. This argument may be
  2093. NULL if the value of pcchInstanceListLength is 0.
  2094. IN LPDWORD pcchInstanceListLength
  2095. pointer to the DWORD containing the size, in characters, of
  2096. the buffer referenced by the mszInstanceList argument. If the
  2097. value in this DWORD is 0, then no data will be written to the
  2098. buffer, only the required size will be returned.
  2099. If the value returned is 0, then this object does not
  2100. return instances, if the value returned is 2, then the
  2101. object supports instances, but does not currently have
  2102. any instances to return (2 = the size of an MSZ list in
  2103. characters)
  2104. IN DWORD dwDetailLevel
  2105. The detail level of the performance items to return. All items
  2106. that are of the specified detail level or less will be
  2107. returned.
  2108. IN DWORD dwFlags
  2109. Not Used, must be 0.
  2110. Return Value:
  2111. ERROR_SUCCESS if the function completes successfully. Otherwise a
  2112. PDH_ error status if not.
  2113. PDH_MORE_DATA is returned when there are more entries available to
  2114. return than there is room in the buffer. Some entries may be
  2115. returned in the buffer though.
  2116. PDH_INSUFFICIENT_BUFFER is returned when there is not enough
  2117. room in the buffer for ANY data.
  2118. PDH_INVALID_ARGUMENT a required argument is not correct or reserved
  2119. argument is not 0 or NULL.
  2120. PDH_MEMORY_ALLOCATION_FAILURE is returned when a required temporary
  2121. buffer could not be allocated.
  2122. PDH_CSTATUS_NO_MACHINE is returned when the specified machine
  2123. is offline or unavailable.
  2124. PDH_CSTATUS_NO_OBJECT is returned if the specified object could
  2125. not be found on the specified machine.
  2126. --*/
  2127. {
  2128. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  2129. HLOG hDataSource = H_REALTIME_DATASOURCE;
  2130. DWORD dwDataSource = 0;
  2131. DebugPrint((4, "PdhEnumObjectItemsA BEGIN\n"));
  2132. __try {
  2133. if (szDataSource != NULL) {
  2134. // test for read access to the name
  2135. if (* szDataSource == 0) {
  2136. pdhStatus = PDH_INVALID_ARGUMENT;
  2137. }
  2138. } // else NULL is a valid arg
  2139. dwDataSource = DataSourceTypeA(szDataSource);
  2140. }
  2141. __except (EXCEPTION_EXECUTE_HANDLER) {
  2142. pdhStatus = PDH_INVALID_ARGUMENT;
  2143. }
  2144. if (pdhStatus == ERROR_SUCCESS) {
  2145. if (dwDataSource == DATA_SOURCE_WBEM) {
  2146. hDataSource = H_WBEM_DATASOURCE;
  2147. }
  2148. else if (dwDataSource == DATA_SOURCE_LOGFILE) {
  2149. DWORD dwLogType = 0;
  2150. pdhStatus = PdhOpenLogA(
  2151. szDataSource,
  2152. PDH_LOG_READ_ACCESS | PDH_LOG_OPEN_EXISTING,
  2153. & dwLogType,
  2154. NULL,
  2155. 0,
  2156. NULL,
  2157. & hDataSource);
  2158. }
  2159. }
  2160. if (pdhStatus == ERROR_SUCCESS) {
  2161. pdhStatus = PdhEnumObjectItemsHA(hDataSource,
  2162. szMachineName,
  2163. szObjectName,
  2164. mszCounterList,
  2165. pcchCounterListLength,
  2166. mszInstanceList,
  2167. pcchInstanceListLength,
  2168. dwDetailLevel,
  2169. dwFlags);
  2170. if (dwDataSource == DATA_SOURCE_LOGFILE) {
  2171. PdhCloseLog(hDataSource, 0);
  2172. }
  2173. }
  2174. DebugPrint((4, "PdhEnumObjectItemsA END status 0x%08X\n", pdhStatus));
  2175. return pdhStatus;
  2176. }
  2177. PDH_FUNCTION
  2178. PdhMakeCounterPathW (
  2179. IN PDH_COUNTER_PATH_ELEMENTS_W *pCounterPathElements,
  2180. IN LPWSTR szFullPathBuffer,
  2181. IN LPDWORD pcchBufferSize,
  2182. IN DWORD dwFlags
  2183. )
  2184. /*++
  2185. Routine Description:
  2186. Constructs a counter path using the elemeents defined in the
  2187. pCounterPathElements structure and returns the path string
  2188. in the buffer provided by the caller. The resulting path
  2189. is not validated.
  2190. Arguments:
  2191. IN PDH_COUNTER_PATH_ELEMENTS_W *pCounterPathElements
  2192. The pointer to the structure containing the
  2193. individual counter path fields that are to be
  2194. assembled in to a path string
  2195. IN LPWSTR szFullPathBuffer
  2196. The buffer to receive the path string. This value
  2197. may be NULL if the value of the DWORD pointed to
  2198. by pcchBufferSize is 0 indicating this is just a
  2199. request for the required buffer size.
  2200. IN LPDWORD pcchBufferSize
  2201. The pointer to the DWORD containing the size
  2202. of the string buffer in characters. On return
  2203. it contains the size of the buffer used in
  2204. characters (including the terminating NULL char).
  2205. If the value is 0 on entry then no data will be
  2206. written to the buffer, but the required size will
  2207. still be returned.
  2208. IN DWORD dwFlags
  2209. if 0, then return the path as a REGISTRY path items
  2210. if PDH_PATH_WBEM_RESULT then return the items in WBEM format
  2211. if PDH_PATH_WBEM_INPUT then assume the input is in WBEM format
  2212. Return Value:
  2213. ERROR_SUCCESS if the function completes successfully, otherwise a
  2214. PDH error is returned.
  2215. PDH_INVALID_ARGUMENT is returned when one of the arguments passed
  2216. by the caller is incorrect or not accesible.
  2217. PDH_INSUFFICIENT_BUFFER is returned when the buffer provided is not
  2218. large enough for the path string.
  2219. --*/
  2220. {
  2221. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  2222. double dIndex;
  2223. double dLen;
  2224. DWORD dwSizeRequired = 0;
  2225. LPWSTR szNextChar;
  2226. DWORD dwMaxSize;
  2227. DWORD dwLocalBufferSize = 0;
  2228. if ((pCounterPathElements == NULL) || (pcchBufferSize == NULL)){
  2229. pdhStatus = PDH_INVALID_ARGUMENT;
  2230. } else {
  2231. __try {
  2232. // test access to the input structure
  2233. if (pCounterPathElements->szMachineName != NULL) {
  2234. WCHAR wChar;
  2235. wChar = *pCounterPathElements->szMachineName;
  2236. // then see if it's accessible
  2237. if (wChar == 0) {
  2238. pdhStatus = PDH_INVALID_ARGUMENT;
  2239. }
  2240. } else {
  2241. //NULL is ok for this field
  2242. }
  2243. if (pdhStatus == ERROR_SUCCESS) {
  2244. if (pCounterPathElements->szObjectName != NULL) {
  2245. WCHAR wChar;
  2246. wChar = *pCounterPathElements->szObjectName;
  2247. // then see if it's accessible
  2248. if (wChar == 0) {
  2249. pdhStatus = PDH_INVALID_ARGUMENT;
  2250. }
  2251. } else {
  2252. //NULL is NOT ok for this field
  2253. pdhStatus = PDH_INVALID_ARGUMENT;
  2254. }
  2255. }
  2256. if (pdhStatus == ERROR_SUCCESS) {
  2257. if (pCounterPathElements->szInstanceName != NULL) {
  2258. WCHAR wChar;
  2259. wChar = *pCounterPathElements->szInstanceName;
  2260. // then see if it's accessible
  2261. if (wChar == 0) {
  2262. pdhStatus = PDH_INVALID_ARGUMENT;
  2263. }
  2264. } else {
  2265. //NULL is ok for this field
  2266. }
  2267. }
  2268. if (pdhStatus == ERROR_SUCCESS) {
  2269. if (pCounterPathElements->szParentInstance != NULL) {
  2270. WCHAR wChar;
  2271. wChar = *pCounterPathElements->szParentInstance;
  2272. // then see if it's accessible
  2273. if (wChar == 0) {
  2274. pdhStatus = PDH_INVALID_ARGUMENT;
  2275. }
  2276. } else {
  2277. //NULL is ok for this field
  2278. }
  2279. }
  2280. if (pdhStatus == ERROR_SUCCESS) {
  2281. if (pCounterPathElements->szCounterName != NULL) {
  2282. WCHAR wChar;
  2283. wChar = *pCounterPathElements->szCounterName;
  2284. // then see if it's accessible
  2285. if (wChar == 0) {
  2286. pdhStatus = PDH_INVALID_ARGUMENT;
  2287. }
  2288. } else {
  2289. //NULL is NOT ok for this field
  2290. pdhStatus = PDH_INVALID_ARGUMENT;
  2291. }
  2292. }
  2293. // test the output buffers
  2294. if (pdhStatus == ERROR_SUCCESS) {
  2295. if (pcchBufferSize != NULL) {
  2296. dwLocalBufferSize = *pcchBufferSize;
  2297. } else {
  2298. // NULL is NOT OK
  2299. pdhStatus = PDH_INVALID_ARGUMENT;
  2300. }
  2301. }
  2302. if ( (pdhStatus == ERROR_SUCCESS)
  2303. && (szFullPathBuffer == NULL && dwLocalBufferSize > 0)) {
  2304. pdhStatus = PDH_INVALID_ARGUMENT;
  2305. }
  2306. if (pdhStatus == ERROR_SUCCESS) {
  2307. if ((szFullPathBuffer != NULL) && (dwLocalBufferSize > 0)) {
  2308. *szFullPathBuffer = 0;
  2309. szFullPathBuffer[dwLocalBufferSize - 1] = 0;
  2310. } else {
  2311. // NULL is OK
  2312. }
  2313. }
  2314. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2315. pdhStatus = PDH_INVALID_ARGUMENT;
  2316. }
  2317. }
  2318. if (pdhStatus == ERROR_SUCCESS) {
  2319. __try {
  2320. if (dwFlags == 0) {
  2321. // then process as:
  2322. // registry path elements in
  2323. // registry path out
  2324. dwMaxSize = dwLocalBufferSize;
  2325. if (pCounterPathElements->szMachineName != NULL) {
  2326. dwSizeRequired = lstrlenW (pCounterPathElements->szMachineName);
  2327. // compare the first two words of the machine name
  2328. // to see if the double backslash is already present in the string
  2329. if (*((LPDWORD)(pCounterPathElements->szMachineName)) !=
  2330. *((LPDWORD)(cszDoubleBackSlash))) {
  2331. // double backslash not found
  2332. dwSizeRequired += 2; // to include the backslashes
  2333. }
  2334. if (dwMaxSize > 0) {
  2335. if (dwSizeRequired < dwMaxSize) {
  2336. if (*((LPDWORD)(pCounterPathElements->szMachineName)) !=
  2337. *((LPDWORD)(cszDoubleBackSlash))) {
  2338. // double backslash not found
  2339. lstrcpyW (szFullPathBuffer, cszDoubleBackSlash);
  2340. } else {
  2341. *szFullPathBuffer = 0;
  2342. }
  2343. lstrcatW (szFullPathBuffer, pCounterPathElements->szMachineName);
  2344. assert ((DWORD)lstrlenW (szFullPathBuffer) == dwSizeRequired);
  2345. } else {
  2346. pdhStatus = PDH_MORE_DATA;
  2347. }
  2348. }
  2349. }
  2350. dwSizeRequired += 1; // for delimiting slash
  2351. dwSizeRequired += lstrlenW (pCounterPathElements->szObjectName);
  2352. if (dwMaxSize > 0) {
  2353. if (dwSizeRequired < dwMaxSize) {
  2354. lstrcatW (szFullPathBuffer, cszBackSlash);
  2355. lstrcatW (szFullPathBuffer, pCounterPathElements->szObjectName);
  2356. assert ((DWORD)lstrlenW (szFullPathBuffer) == dwSizeRequired);
  2357. } else {
  2358. pdhStatus = PDH_MORE_DATA;
  2359. }
  2360. }
  2361. if (pCounterPathElements->szInstanceName != NULL) {
  2362. dwSizeRequired += 1; // for delimiting left paren
  2363. if (dwMaxSize > 0) {
  2364. if (dwSizeRequired < dwMaxSize) {
  2365. lstrcatW (szFullPathBuffer, cszLeftParen);
  2366. assert ((DWORD)lstrlenW (szFullPathBuffer) == dwSizeRequired);
  2367. } else {
  2368. pdhStatus = PDH_MORE_DATA;
  2369. }
  2370. }
  2371. if ( lstrcmpiW(pCounterPathElements->szInstanceName, cszSplat) != 0
  2372. && pCounterPathElements->szParentInstance != NULL) {
  2373. dwSizeRequired += lstrlenW (pCounterPathElements->szParentInstance);
  2374. dwSizeRequired += 1; // for delimiting slash
  2375. if (dwMaxSize > 0) {
  2376. if (dwSizeRequired < dwMaxSize) {
  2377. lstrcatW (szFullPathBuffer,
  2378. pCounterPathElements->szParentInstance);
  2379. lstrcatW (szFullPathBuffer, cszSlash);
  2380. assert ((DWORD)lstrlenW (szFullPathBuffer) == dwSizeRequired);
  2381. } else {
  2382. pdhStatus = PDH_MORE_DATA;
  2383. }
  2384. }
  2385. }
  2386. dwSizeRequired += lstrlenW (pCounterPathElements->szInstanceName);
  2387. if (dwMaxSize > 0) {
  2388. if (dwSizeRequired < dwMaxSize) {
  2389. lstrcatW (szFullPathBuffer,
  2390. pCounterPathElements->szInstanceName);
  2391. assert ((DWORD)lstrlenW (szFullPathBuffer) == dwSizeRequired);
  2392. } else {
  2393. pdhStatus = PDH_MORE_DATA;
  2394. }
  2395. }
  2396. if ( lstrcmpiW(pCounterPathElements->szInstanceName, cszSplat) != 0
  2397. && pCounterPathElements->dwInstanceIndex != ((DWORD)-1)) {
  2398. // the length of the index is computed by getting the log of the number
  2399. // yielding the largest power of 10 less than or equal to the index.
  2400. // e.g. the power of 10 of an index value of 356 would 2.0 (which is the
  2401. // result of (floor(log10(index))). The actual number of characters in
  2402. // the string would always be 1 greate than that value so 1 is added.
  2403. // 1 more is added to include the delimiting character
  2404. dIndex = (double)pCounterPathElements->dwInstanceIndex; // cast to float
  2405. dLen = floor(log10(dIndex)); // get integer log
  2406. dwSizeRequired += (DWORD)dLen; // cast to integer
  2407. dwSizeRequired += 2; // increment
  2408. if (dwMaxSize > 0) {
  2409. if (dwSizeRequired < dwMaxSize) {
  2410. szNextChar = &szFullPathBuffer[lstrlenW(szFullPathBuffer)];
  2411. *szNextChar++ = POUNDSIGN_L;
  2412. _ltow ((long)pCounterPathElements->dwInstanceIndex, szNextChar, 10);
  2413. assert ((DWORD)lstrlenW (szFullPathBuffer) == dwSizeRequired);
  2414. } else {
  2415. pdhStatus = PDH_MORE_DATA;
  2416. }
  2417. }
  2418. }
  2419. dwSizeRequired += 1; // for delimiting parenthesis
  2420. if (dwMaxSize > 0) {
  2421. if (dwSizeRequired < dwMaxSize) {
  2422. lstrcatW (szFullPathBuffer, cszRightParen);
  2423. assert ((DWORD)lstrlenW (szFullPathBuffer) == dwSizeRequired);
  2424. } else {
  2425. pdhStatus = PDH_MORE_DATA;
  2426. }
  2427. }
  2428. }
  2429. dwSizeRequired++; // include delimiting Backslash
  2430. dwSizeRequired += lstrlenW(pCounterPathElements->szCounterName);
  2431. if (dwMaxSize > 0) {
  2432. if (dwSizeRequired < dwMaxSize) {
  2433. lstrcatW (szFullPathBuffer, cszBackSlash);
  2434. lstrcatW (szFullPathBuffer,
  2435. pCounterPathElements->szCounterName);
  2436. assert ((DWORD)lstrlenW (szFullPathBuffer) == dwSizeRequired);
  2437. } else {
  2438. pdhStatus = PDH_MORE_DATA;
  2439. }
  2440. }
  2441. dwSizeRequired++; // include trailing Null char
  2442. } else {
  2443. // there is some WBEM component involved so send to WBEM function
  2444. // to figure it out
  2445. pdhStatus = PdhiEncodeWbemPathW (
  2446. pCounterPathElements,
  2447. szFullPathBuffer,
  2448. &dwLocalBufferSize,
  2449. (LANGID)((dwFlags >> 16) & 0x0000FFFF),
  2450. (DWORD)(dwFlags & 0x0000FFFF));
  2451. }
  2452. if (pdhStatus == ERROR_SUCCESS && szFullPathBuffer == NULL
  2453. && * pcchBufferSize == 0) {
  2454. pdhStatus = PDH_MORE_DATA;
  2455. }
  2456. *pcchBufferSize = dwSizeRequired;
  2457. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2458. pdhStatus = PDH_INVALID_ARGUMENT;
  2459. }
  2460. }
  2461. return pdhStatus;
  2462. }
  2463. PDH_FUNCTION
  2464. PdhMakeCounterPathA (
  2465. IN PDH_COUNTER_PATH_ELEMENTS_A *pCounterPathElements,
  2466. IN LPSTR szFullPathBuffer,
  2467. IN LPDWORD pcchBufferSize,
  2468. IN DWORD dwFlags
  2469. )
  2470. /*++
  2471. Routine Description:
  2472. Constructs a counter path using the elemeents defined in the
  2473. pCounterPathElements structure and returns the path string
  2474. in the buffer provided by the caller. The resulting path
  2475. is not validated.
  2476. Arguments:
  2477. IN PDH_COUNTER_PATH_ELEMENTS_W *pCounterPathElements
  2478. The pointer to the structure containing the
  2479. individual counter path fields that are to be
  2480. assembled in to a path string
  2481. IN LPWSTR szFullPathBuffer
  2482. The buffer to receive the path string. This value
  2483. may be NULL if the value of the DWORD pointed to
  2484. by pcchBufferSize is 0 indicating this is just a
  2485. request for the required buffer size.
  2486. IN LPDWORD pcchBufferSize
  2487. The pointer to the DWORD containing the size
  2488. of the string buffer in characters. On return
  2489. it contains the size of the buffer used in
  2490. characters (including the terminating NULL char).
  2491. If the value is 0 on entry then no data will be
  2492. written to the buffer, but the required size will
  2493. still be returned.
  2494. IN DWORD dwFlags
  2495. if 0, then return the path as a REGISTRY path items
  2496. if PDH_PATH_WBEM_RESULT then return the items in WBEM format
  2497. if PDH_PATH_WBEM_INPUT then assume the input is in WBEM format
  2498. Return Value:
  2499. ERROR_SUCCESS if the function completes successfully, otherwise a
  2500. PDH error is returned.
  2501. PDH_INVALID_ARGUMENT is returned when one of the arguments passed
  2502. by the caller is incorrect or not accesible.
  2503. PDH_INSUFFICIENT_BUFFER is returned when the buffer provided is not
  2504. large enough for the path string.
  2505. --*/
  2506. {
  2507. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  2508. double dIndex;
  2509. double dLen;
  2510. DWORD dwSizeRequired = 0;
  2511. LPSTR szNextChar;
  2512. DWORD dwMaxSize;
  2513. DWORD dwLocalBufferSize = 0;
  2514. // TODO: Win2K.1 capture pCounterPathElements and szFullPathBuffer
  2515. if ((pCounterPathElements == NULL)|| (pcchBufferSize == NULL)){
  2516. pdhStatus = PDH_INVALID_ARGUMENT;
  2517. } else {
  2518. __try {
  2519. // test access to the input structure
  2520. if (pCounterPathElements->szMachineName != NULL) {
  2521. CHAR cChar;
  2522. cChar = *pCounterPathElements->szMachineName;
  2523. // then see if it's accessible
  2524. if (cChar == 0) {
  2525. pdhStatus = PDH_INVALID_ARGUMENT;
  2526. }
  2527. } else {
  2528. //NULL is ok for this field
  2529. }
  2530. if (pdhStatus == ERROR_SUCCESS) {
  2531. if (pCounterPathElements->szObjectName != NULL) {
  2532. CHAR cChar;
  2533. cChar = *pCounterPathElements->szObjectName;
  2534. // then see if it's accessible
  2535. if (cChar == 0) {
  2536. pdhStatus = PDH_INVALID_ARGUMENT;
  2537. }
  2538. } else {
  2539. //NULL is NOT ok for this field
  2540. pdhStatus = PDH_INVALID_ARGUMENT;
  2541. }
  2542. }
  2543. if (pdhStatus == ERROR_SUCCESS) {
  2544. if (pCounterPathElements->szInstanceName != NULL) {
  2545. CHAR cChar;
  2546. cChar = *pCounterPathElements->szInstanceName;
  2547. // then see if it's accessible
  2548. if (cChar == 0) {
  2549. pdhStatus = PDH_INVALID_ARGUMENT;
  2550. }
  2551. } else {
  2552. //NULL is ok for this field
  2553. }
  2554. }
  2555. if (pdhStatus == ERROR_SUCCESS) {
  2556. if (pCounterPathElements->szParentInstance != NULL) {
  2557. CHAR cChar;
  2558. cChar = *pCounterPathElements->szParentInstance;
  2559. // then see if it's accessible
  2560. if (cChar == 0) {
  2561. pdhStatus = PDH_INVALID_ARGUMENT;
  2562. }
  2563. } else {
  2564. //NULL is ok for this field
  2565. }
  2566. }
  2567. if (pdhStatus == ERROR_SUCCESS) {
  2568. if (pCounterPathElements->szCounterName != NULL) {
  2569. CHAR cChar;
  2570. cChar = *pCounterPathElements->szCounterName;
  2571. // then see if it's accessible
  2572. if (cChar == 0) {
  2573. pdhStatus = PDH_INVALID_ARGUMENT;
  2574. }
  2575. } else {
  2576. //NULL is NOT ok for this field
  2577. pdhStatus = PDH_INVALID_ARGUMENT;
  2578. }
  2579. }
  2580. // test the output buffers
  2581. if (pdhStatus == ERROR_SUCCESS) {
  2582. if (pcchBufferSize != NULL) {
  2583. dwLocalBufferSize = *pcchBufferSize;
  2584. } else {
  2585. // NULL is NOT OK
  2586. pdhStatus = PDH_INVALID_ARGUMENT;
  2587. }
  2588. }
  2589. if ( (pdhStatus == ERROR_SUCCESS)
  2590. && (szFullPathBuffer == NULL && dwLocalBufferSize > 0)) {
  2591. pdhStatus = PDH_INVALID_ARGUMENT;
  2592. }
  2593. if (pdhStatus == ERROR_SUCCESS) {
  2594. // write to both ends of the buffer if one was sent
  2595. if ((szFullPathBuffer != NULL) && (dwLocalBufferSize > 0)) {
  2596. *szFullPathBuffer = 0;
  2597. szFullPathBuffer[dwLocalBufferSize - 1] = 0;
  2598. } else {
  2599. // NULL is OK
  2600. }
  2601. }
  2602. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2603. pdhStatus = PDH_INVALID_ARGUMENT;
  2604. }
  2605. }
  2606. if (pdhStatus == ERROR_SUCCESS) {
  2607. __try {
  2608. if (dwFlags == 0) {
  2609. // this is a registry path in and out
  2610. dwMaxSize = dwLocalBufferSize;
  2611. if (pCounterPathElements->szMachineName != NULL) {
  2612. dwSizeRequired = lstrlenA (pCounterPathElements->szMachineName);
  2613. // compare the first two words of the machine name
  2614. // to see if the double backslash is already present in the string
  2615. if (*((LPWORD)(pCounterPathElements->szMachineName)) !=
  2616. *((LPWORD)(caszDoubleBackSlash))) {
  2617. // double backslash not found
  2618. dwSizeRequired += 2; // to include the backslashes
  2619. }
  2620. if (dwMaxSize > 0) {
  2621. if (dwSizeRequired < dwMaxSize) {
  2622. if (*((LPWORD)(pCounterPathElements->szMachineName)) !=
  2623. *((LPWORD)(caszDoubleBackSlash))) {
  2624. // double backslash not found
  2625. lstrcpyA (szFullPathBuffer, caszDoubleBackSlash);
  2626. } else {
  2627. *szFullPathBuffer = 0;
  2628. }
  2629. lstrcatA (szFullPathBuffer, pCounterPathElements->szMachineName);
  2630. assert ((DWORD)lstrlenA (szFullPathBuffer) == dwSizeRequired);
  2631. } else {
  2632. pdhStatus = PDH_MORE_DATA;
  2633. }
  2634. }
  2635. }
  2636. dwSizeRequired += 1; // for delimiting slash
  2637. dwSizeRequired += lstrlenA (pCounterPathElements->szObjectName);
  2638. if (dwMaxSize > 0) {
  2639. if (dwSizeRequired < dwMaxSize) {
  2640. lstrcatA (szFullPathBuffer, caszBackSlash);
  2641. lstrcatA (szFullPathBuffer, pCounterPathElements->szObjectName);
  2642. assert ((DWORD)lstrlenA (szFullPathBuffer) == dwSizeRequired);
  2643. } else {
  2644. pdhStatus = PDH_MORE_DATA;
  2645. }
  2646. }
  2647. if (pCounterPathElements->szInstanceName != NULL) {
  2648. dwSizeRequired += 1; // for delimiting left paren
  2649. if (dwMaxSize > 0) {
  2650. if (dwSizeRequired < dwMaxSize) {
  2651. lstrcatA (szFullPathBuffer, caszLeftParen);
  2652. assert ((DWORD)lstrlenA (szFullPathBuffer) == dwSizeRequired);
  2653. } else {
  2654. pdhStatus = PDH_MORE_DATA;
  2655. }
  2656. }
  2657. if (pCounterPathElements->szParentInstance != NULL) {
  2658. dwSizeRequired += lstrlenA (pCounterPathElements->szParentInstance);
  2659. dwSizeRequired += 1; // for delimiting slash
  2660. if (dwMaxSize > 0) {
  2661. if (dwSizeRequired < dwMaxSize) {
  2662. lstrcatA (szFullPathBuffer,
  2663. pCounterPathElements->szParentInstance);
  2664. lstrcatA (szFullPathBuffer, caszSlash);
  2665. assert ((DWORD)lstrlenA (szFullPathBuffer) == dwSizeRequired);
  2666. } else {
  2667. pdhStatus = PDH_MORE_DATA;
  2668. }
  2669. }
  2670. }
  2671. dwSizeRequired += lstrlenA (pCounterPathElements->szInstanceName);
  2672. if (dwMaxSize > 0) {
  2673. if (dwSizeRequired < dwMaxSize) {
  2674. lstrcatA (szFullPathBuffer,
  2675. pCounterPathElements->szInstanceName);
  2676. assert ((DWORD)lstrlenA (szFullPathBuffer) == dwSizeRequired);
  2677. } else {
  2678. pdhStatus = PDH_MORE_DATA;
  2679. }
  2680. }
  2681. if (pCounterPathElements->dwInstanceIndex != ((DWORD)-1)) {
  2682. // the length of the index is computed by getting the log of the number
  2683. // yielding the largest power of 10 less than or equal to the index.
  2684. // e.g. the power of 10 of an index value of 356 would 2.0 (which is the
  2685. // result of (floor(log10(index))). The actual number of characters in
  2686. // the string would always be 1 greate than that value so 1 is added.
  2687. // 1 more is added to include the delimiting character
  2688. dIndex = (double)pCounterPathElements->dwInstanceIndex; // cast to float
  2689. dLen = floor(log10(dIndex)); // get integer log
  2690. dwSizeRequired = (DWORD)dLen; // cast to integer
  2691. dwSizeRequired += 2; // increment
  2692. if (dwMaxSize > 0) {
  2693. if (dwSizeRequired < dwMaxSize) {
  2694. szNextChar = &szFullPathBuffer[lstrlenA(szFullPathBuffer)];
  2695. *szNextChar++ = POUNDSIGN_L;
  2696. _ltoa ((long)pCounterPathElements->dwInstanceIndex, szNextChar, 10);
  2697. assert ((DWORD)lstrlenA (szFullPathBuffer) == dwSizeRequired);
  2698. } else {
  2699. pdhStatus = PDH_MORE_DATA;
  2700. }
  2701. }
  2702. }
  2703. dwSizeRequired += 1; // for delimiting parenthesis
  2704. if (dwMaxSize > 0) {
  2705. if (dwSizeRequired < dwMaxSize) {
  2706. lstrcatA (szFullPathBuffer, caszRightParen);
  2707. assert ((DWORD)lstrlenA (szFullPathBuffer) == dwSizeRequired);
  2708. } else {
  2709. pdhStatus = PDH_MORE_DATA;
  2710. }
  2711. }
  2712. }
  2713. dwSizeRequired++; // include delimiting Backslash
  2714. dwSizeRequired += lstrlenA(pCounterPathElements->szCounterName);
  2715. if (szFullPathBuffer != NULL && dwMaxSize > 0) {
  2716. if (dwSizeRequired < dwMaxSize) {
  2717. lstrcatA (szFullPathBuffer, caszBackSlash);
  2718. lstrcatA (szFullPathBuffer,
  2719. pCounterPathElements->szCounterName);
  2720. assert ((DWORD)lstrlenA (szFullPathBuffer) == dwSizeRequired);
  2721. } else {
  2722. pdhStatus = PDH_MORE_DATA;
  2723. }
  2724. }
  2725. dwSizeRequired++; // include trailing Null char
  2726. } else {
  2727. // this is a WBEM path so have the WBEM function figure
  2728. // it out
  2729. // there is some WBEM component involved so send to WBEM function
  2730. // to figure it out
  2731. pdhStatus = PdhiEncodeWbemPathA (
  2732. pCounterPathElements,
  2733. szFullPathBuffer,
  2734. &dwLocalBufferSize,
  2735. (LANGID)((dwFlags >> 16) & 0x0000FFFF),
  2736. (DWORD)(dwFlags & 0x0000FFFF));
  2737. }
  2738. if (pdhStatus == ERROR_SUCCESS && szFullPathBuffer == NULL
  2739. && * pcchBufferSize == 0) {
  2740. pdhStatus = PDH_MORE_DATA;
  2741. }
  2742. *pcchBufferSize = dwSizeRequired;
  2743. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2744. pdhStatus = PDH_INVALID_ARGUMENT;
  2745. }
  2746. }
  2747. return pdhStatus;
  2748. }
  2749. PDH_FUNCTION
  2750. PdhParseCounterPathW (
  2751. IN LPCWSTR szFullPathBuffer,
  2752. IN PDH_COUNTER_PATH_ELEMENTS_W *pCounterPathElements,
  2753. IN LPDWORD pcchBufferSize,
  2754. IN DWORD dwFlags
  2755. )
  2756. /*++
  2757. Routine Description:
  2758. Reads a perf counter path string and parses out the
  2759. component fields, returning them in a buffer
  2760. supplied by the calling function.
  2761. Arguments:
  2762. IN LPCWSTR szFullPathBuffer
  2763. counter path string to parse.
  2764. IN PDH_COUNTER_PATH_ELEMENTS_W *pCounterPathElements
  2765. pointer to buffer supplied by the caller in
  2766. which the component fields will be written
  2767. This buffer is cast as a structure, however, the
  2768. string data is written to the space after
  2769. the buffer.
  2770. IN LPDWORD pcchBufferSize
  2771. the size of the buffer in BYTES. If specified size
  2772. is 0, then the size is estimated and returned
  2773. in this field and the buffer referenced by the
  2774. agrument above is ignored.
  2775. IN DWORD dwFlags
  2776. if 0, then return the path elements as REGISTRY path items
  2777. if PDH_PATH_WBEM_RESULT then return the items in WBEM format
  2778. if PDH_PATH_WBEM_INPUT then assume the input is in WBEM format
  2779. Return Value:
  2780. ERROR_SUCCESS if the function completes successfully, otherwise
  2781. a PDH error if not
  2782. PDH_INVALID_ARGUMENT is returned when an argument is inocrrect or
  2783. this function does not have the necessary access to that arg.
  2784. PDH_INSUFFICIENT_BUFFER is returned when the buffer supplied is not
  2785. large enough to accept the resulting data.
  2786. PDH_INVALID_PATH is returned when the path is not formatted correctly
  2787. and cannot be parsed.
  2788. PDH_MEMORY_ALLOCATION_FAILURE is returned when a temporary buffer
  2789. cannot be allocated
  2790. --*/
  2791. {
  2792. PPDHI_COUNTER_PATH pLocalCounterPath;
  2793. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  2794. DWORD dwSize;
  2795. LPWSTR szString;
  2796. DWORD dwLocalBufferSize;
  2797. // TODO: Win2K.1 capture pCounterPathElements and szFullPathBuffer
  2798. //validate incoming arguments
  2799. if ((szFullPathBuffer == NULL) || (pcchBufferSize == NULL)) {
  2800. return PDH_INVALID_ARGUMENT;
  2801. }
  2802. __try {
  2803. // string cannot be null
  2804. if (*szFullPathBuffer == 0) {
  2805. pdhStatus = PDH_INVALID_ARGUMENT;
  2806. }
  2807. dwLocalBufferSize = *pcchBufferSize;
  2808. if (pdhStatus == ERROR_SUCCESS) {
  2809. if (pCounterPathElements != NULL) {
  2810. if (dwLocalBufferSize > 0) {
  2811. // try both "ends" of the buffer to see if an AV occurs
  2812. *((LPBYTE)pCounterPathElements) = 0;
  2813. ((LPBYTE)pCounterPathElements)[dwLocalBufferSize - 1] = 0;
  2814. } else {
  2815. // a 0 length is OK for sizing
  2816. }
  2817. } // else NULL pointer, which is OK
  2818. }
  2819. if (dwFlags != 0) {
  2820. pdhStatus = PDH_INVALID_ARGUMENT;
  2821. }
  2822. if (pdhStatus == ERROR_SUCCESS) {
  2823. if (dwFlags == 0) {
  2824. // allocate a temporary work buffer
  2825. pLocalCounterPath = G_ALLOC (
  2826. (sizeof(PDHI_COUNTER_PATH) +
  2827. (2 * lstrlenW(szFullPathBuffer) + MAX_PATH) * sizeof (WCHAR)));
  2828. if (pLocalCounterPath != NULL) {
  2829. dwSize = (DWORD)G_SIZE (pLocalCounterPath);
  2830. if (ParseFullPathNameW (szFullPathBuffer,
  2831. &dwSize, pLocalCounterPath, FALSE)) {
  2832. // parsed successfully so load into user's buffer
  2833. if (dwLocalBufferSize != 0) {
  2834. // see if there's enough room
  2835. if (dwLocalBufferSize >= dwSize) {
  2836. // there's room so copy the data
  2837. szString = (LPWSTR)&pCounterPathElements[1];
  2838. if (pLocalCounterPath->szMachineName != NULL) {
  2839. pCounterPathElements->szMachineName = szString;
  2840. lstrcpyW (szString, pLocalCounterPath->szMachineName);
  2841. szString += lstrlenW (szString) + 1;
  2842. szString = ALIGN_ON_DWORD (szString);
  2843. } else {
  2844. pCounterPathElements->szMachineName = NULL;
  2845. }
  2846. if (pLocalCounterPath->szObjectName != NULL) {
  2847. pCounterPathElements->szObjectName = szString;
  2848. lstrcpyW (szString, pLocalCounterPath->szObjectName);
  2849. szString += lstrlenW (szString) + 1;
  2850. szString = ALIGN_ON_DWORD (szString);
  2851. } else {
  2852. pCounterPathElements->szObjectName = NULL;
  2853. }
  2854. if (pLocalCounterPath->szInstanceName != NULL) {
  2855. pCounterPathElements->szInstanceName = szString;
  2856. lstrcpyW (szString, pLocalCounterPath->szInstanceName);
  2857. szString += lstrlenW (szString) + 1;
  2858. szString = ALIGN_ON_DWORD (szString);
  2859. if (pLocalCounterPath->szParentName != NULL) {
  2860. pCounterPathElements->szParentInstance = szString;
  2861. lstrcpyW (szString, pLocalCounterPath->szParentName);
  2862. szString+= lstrlenW (szString) + 1;
  2863. szString = ALIGN_ON_DWORD (szString);
  2864. } else {
  2865. pCounterPathElements->szParentInstance = NULL;
  2866. }
  2867. pCounterPathElements->dwInstanceIndex =
  2868. pLocalCounterPath->dwIndex;
  2869. } else {
  2870. pCounterPathElements->szInstanceName = NULL;
  2871. pCounterPathElements->szParentInstance = NULL;
  2872. pCounterPathElements->dwInstanceIndex = (DWORD)-1;
  2873. }
  2874. if (pLocalCounterPath->szCounterName != NULL) {
  2875. pCounterPathElements->szCounterName = szString;
  2876. lstrcpyW (szString, pLocalCounterPath->szCounterName);
  2877. szString += lstrlenW (szString) + 1;
  2878. szString = ALIGN_ON_DWORD (szString);
  2879. } else {
  2880. pCounterPathElements->szCounterName = NULL;
  2881. }
  2882. assert ((DWORD)((LPBYTE)szString - (LPBYTE)pCounterPathElements) == dwSize);
  2883. dwLocalBufferSize = (DWORD)((LPBYTE)szString - (LPBYTE)pCounterPathElements);
  2884. pdhStatus = ERROR_SUCCESS;
  2885. } else {
  2886. // not enough room
  2887. pdhStatus = PDH_MORE_DATA;
  2888. }
  2889. } else {
  2890. // this is just a size check so return size required
  2891. dwLocalBufferSize = dwSize;
  2892. pdhStatus = PDH_MORE_DATA;
  2893. }
  2894. } else {
  2895. // unable to read path
  2896. pdhStatus = PDH_INVALID_PATH;
  2897. }
  2898. G_FREE (pLocalCounterPath);
  2899. } else {
  2900. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  2901. }
  2902. } else {
  2903. pdhStatus = PdhiDecodeWbemPathW (
  2904. szFullPathBuffer,
  2905. pCounterPathElements,
  2906. &dwLocalBufferSize,
  2907. (LANGID)((dwFlags >> 16) & 0x0000FFFF),
  2908. (DWORD)(dwFlags & 0x0000FFFF));
  2909. }
  2910. }
  2911. *pcchBufferSize = dwLocalBufferSize;
  2912. } __except (EXCEPTION_EXECUTE_HANDLER) {
  2913. pdhStatus = PDH_INVALID_ARGUMENT;
  2914. }
  2915. return pdhStatus;
  2916. }
  2917. PDH_FUNCTION
  2918. PdhParseCounterPathA (
  2919. IN LPCSTR szFullPathBuffer,
  2920. IN PDH_COUNTER_PATH_ELEMENTS_A *pCounterPathElements,
  2921. IN LPDWORD pcchBufferSize,
  2922. IN DWORD dwFlags
  2923. )
  2924. /*++
  2925. Routine Description:
  2926. Reads a perf counter path string and parses out the
  2927. component fields, returning them in a buffer
  2928. supplied by the calling function.
  2929. Arguments:
  2930. IN LPCSTR szFullPathBuffer
  2931. counter path string to parse.
  2932. IN PDH_COUNTER_PATH_ELEMENTS_W *pCounterPathElements
  2933. pointer to buffer supplied by the caller in
  2934. which the component fields will be written
  2935. This buffer is cast as a structure, however, the
  2936. string data is written to the space after
  2937. the buffer.
  2938. IN LPDWORD pcchBufferSize
  2939. the size of the buffer in BYTES. If specified size
  2940. is 0, then the size is estimated and returned
  2941. in this field and the buffer referenced by the
  2942. agrument above is ignored.
  2943. IN DWORD dwFlags
  2944. if 0, then return the path as a REGISTRY path items
  2945. if PDH_PATH_WBEM_RESULT then return the items in WBEM format
  2946. if PDH_PATH_WBEM_INPUT then assume the input is in WBEM format
  2947. Return Value:
  2948. ERROR_SUCCESS if the function completes successfully, otherwise
  2949. a PDH error if not
  2950. PDH_INVALID_ARGUMENT is returned when an argument is inocrrect or
  2951. this function does not have the necessary access to that arg.
  2952. PDH_INSUFFICIENT_BUFFER is returned when the buffer supplied is not
  2953. large enough to accept the resulting data.
  2954. PDH_INVALID_PATH is returned when the path is not formatted correctly
  2955. and cannot be parsed.
  2956. PDH_MEMORY_ALLOCATION_FAILURE is returned when a temporary buffer
  2957. cannot be allocated
  2958. --*/
  2959. {
  2960. PPDHI_COUNTER_PATH pLocalCounterPath = NULL;
  2961. LPWSTR wszFullPath = NULL;
  2962. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  2963. PDH_STATUS pdhStatus1 = ERROR_SUCCESS;
  2964. DWORD dwSize;
  2965. DWORD dwSizeUsed;
  2966. LPSTR szString;
  2967. DWORD dwSizeofFullPath;
  2968. DWORD dwSizeofLocalCounterPath;
  2969. DWORD dwLocalBufferSize;
  2970. // TODO: Win2K.1 capture pCounterPathElements and szFullPathBuffer
  2971. //validate incoming arguments
  2972. if ((szFullPathBuffer == NULL) || (pcchBufferSize == NULL)) {
  2973. return PDH_INVALID_ARGUMENT;
  2974. }
  2975. __try {
  2976. // the name must be non null
  2977. if (*szFullPathBuffer == 0) {
  2978. pdhStatus = PDH_INVALID_ARGUMENT;
  2979. }
  2980. // capture buffer size locally
  2981. dwLocalBufferSize = *pcchBufferSize;
  2982. if (pdhStatus == ERROR_SUCCESS) {
  2983. if (pCounterPathElements != NULL) {
  2984. if (dwLocalBufferSize > 0) {
  2985. // try both "ends" of the buffer to see if an AV occurs
  2986. *((LPBYTE)pCounterPathElements) = 0;
  2987. ((LPBYTE)pCounterPathElements)[dwLocalBufferSize - 1] = 0;
  2988. } else {
  2989. // a 0 length is OK for sizing
  2990. }
  2991. } // else NULL pointer, which is OK
  2992. }
  2993. if (dwFlags != 0) {
  2994. pdhStatus = PDH_INVALID_ARGUMENT;
  2995. }
  2996. if (pdhStatus == ERROR_SUCCESS) {
  2997. if (dwFlags == 0) {
  2998. dwSize = lstrlenA(szFullPathBuffer) * sizeof(WCHAR);
  2999. dwSizeofFullPath = dwSize + sizeof(WCHAR);
  3000. dwSizeofFullPath = QWORD_MULTIPLE(dwSizeofFullPath);
  3001. dwSizeofLocalCounterPath =
  3002. sizeof(PDHI_COUNTER_PATH) + // room for structure
  3003. (2 * dwSize * sizeof (WCHAR)) ; // room for string components
  3004. dwSizeofLocalCounterPath = QWORD_MULTIPLE (dwSizeofLocalCounterPath);
  3005. wszFullPath = G_ALLOC (dwSizeofFullPath + dwSizeofLocalCounterPath);
  3006. if (wszFullPath != NULL) {
  3007. pLocalCounterPath = (PPDHI_COUNTER_PATH)(
  3008. (LPBYTE)wszFullPath + dwSizeofFullPath);
  3009. MultiByteToWideChar(_getmbcp(),
  3010. 0,
  3011. szFullPathBuffer,
  3012. lstrlenA(szFullPathBuffer),
  3013. (LPWSTR) wszFullPath,
  3014. dwSizeofFullPath / sizeof(WCHAR));
  3015. dwSize = (DWORD) dwSizeofLocalCounterPath;
  3016. if (ParseFullPathNameW (wszFullPath,
  3017. &dwSize, pLocalCounterPath, FALSE)) {
  3018. // parsed successfully so load into user's buffer
  3019. // adjust dwSize to account for single-byte characters
  3020. // as they'll be packed in user's buffer.
  3021. // compute require size by adding:
  3022. // size of the text strings
  3023. dwSize = (dwSize - (sizeof(PDHI_COUNTER_PATH) - sizeof(DWORD))) / sizeof(WCHAR);
  3024. // + the size of the data structure
  3025. dwSize += sizeof(PDH_COUNTER_PATH_ELEMENTS_A);
  3026. // + the allowance for DWORD alignment padding
  3027. dwSize += (sizeof(DWORD) -1) * 4; // 5 string elements
  3028. dwSizeUsed = sizeof(PDH_COUNTER_PATH_ELEMENTS);
  3029. szString = (LPSTR) & pCounterPathElements[1];
  3030. if (pLocalCounterPath->szMachineName != NULL) {
  3031. dwSize = (dwLocalBufferSize >= dwSizeUsed)
  3032. ? (dwLocalBufferSize - dwSizeUsed) : (0);
  3033. pdhStatus1 = PdhiConvertUnicodeToAnsi(_getmbcp(),
  3034. pLocalCounterPath->szMachineName,
  3035. szString,
  3036. & dwSize);
  3037. if (dwSize % sizeof(DWORD) != 0) {
  3038. dwSize = sizeof(DWORD)
  3039. * ((dwSize / sizeof(DWORD)) + 1);
  3040. }
  3041. dwSizeUsed += dwSize;
  3042. if (pdhStatus1 == ERROR_SUCCESS) {
  3043. szString += dwSize;
  3044. //szString = ALIGN_ON_DWORD(szString);
  3045. }
  3046. else if (pdhStatus == ERROR_SUCCESS) {
  3047. pdhStatus = pdhStatus1;
  3048. }
  3049. }
  3050. if (pLocalCounterPath->szMachineName != NULL) {
  3051. dwSize = (dwLocalBufferSize >= dwSizeUsed)
  3052. ? (dwLocalBufferSize - dwSizeUsed) : (0);
  3053. pdhStatus1 = PdhiConvertUnicodeToAnsi(_getmbcp(),
  3054. pLocalCounterPath->szMachineName,
  3055. szString,
  3056. & dwSize);
  3057. if (dwSize % sizeof(DWORD) != 0) {
  3058. dwSize = sizeof(DWORD)
  3059. * ((dwSize / sizeof(DWORD)) + 1);
  3060. }
  3061. dwSizeUsed += dwSize;
  3062. if (pdhStatus1 == ERROR_SUCCESS) {
  3063. pCounterPathElements->szMachineName = szString;
  3064. szString += dwSize;
  3065. //szString = ALIGN_ON_DWORD(szString);
  3066. }
  3067. else if (pdhStatus == ERROR_SUCCESS) {
  3068. pdhStatus = pdhStatus1;
  3069. }
  3070. }
  3071. else if (pCounterPathElements != NULL) {
  3072. pCounterPathElements->szMachineName = NULL;
  3073. }
  3074. if (pLocalCounterPath->szObjectName != NULL) {
  3075. dwSize = (dwLocalBufferSize >= dwSizeUsed)
  3076. ? (dwLocalBufferSize - dwSizeUsed) : (0);
  3077. pdhStatus1 = PdhiConvertUnicodeToAnsi(_getmbcp(),
  3078. pLocalCounterPath->szObjectName,
  3079. szString,
  3080. & dwSize);
  3081. if (dwSize % sizeof(DWORD) != 0) {
  3082. dwSize = sizeof(DWORD)
  3083. * ((dwSize / sizeof(DWORD)) + 1);
  3084. }
  3085. dwSizeUsed += dwSize;
  3086. if (pdhStatus1 == ERROR_SUCCESS) {
  3087. pCounterPathElements->szObjectName = szString;
  3088. szString += dwSize;
  3089. //szString = ALIGN_ON_DWORD(szString);
  3090. }
  3091. else if (pdhStatus == ERROR_SUCCESS) {
  3092. pdhStatus = pdhStatus1;
  3093. }
  3094. }
  3095. else if (pCounterPathElements != NULL) {
  3096. pCounterPathElements->szObjectName = NULL;
  3097. }
  3098. if (pLocalCounterPath->szInstanceName != NULL) {
  3099. dwSize = (dwLocalBufferSize >= dwSizeUsed)
  3100. ? (dwLocalBufferSize - dwSizeUsed) : (0);
  3101. pdhStatus1 = PdhiConvertUnicodeToAnsi(_getmbcp(),
  3102. pLocalCounterPath->szInstanceName,
  3103. szString,
  3104. & dwSize);
  3105. if (dwSize % sizeof(DWORD) != 0) {
  3106. dwSize = sizeof(DWORD)
  3107. * ((dwSize / sizeof(DWORD)) + 1);
  3108. }
  3109. dwSizeUsed += dwSize;
  3110. if (pdhStatus1 == ERROR_SUCCESS) {
  3111. pCounterPathElements->szInstanceName = szString;
  3112. szString += dwSize;
  3113. //szString = ALIGN_ON_DWORD(szString);
  3114. }
  3115. else if (pdhStatus == ERROR_SUCCESS) {
  3116. pdhStatus = pdhStatus1;
  3117. }
  3118. if (pLocalCounterPath->szParentName != NULL) {
  3119. dwSize = (dwLocalBufferSize >= dwSizeUsed)
  3120. ? (dwLocalBufferSize - dwSizeUsed) : (0);
  3121. pdhStatus1 = PdhiConvertUnicodeToAnsi(_getmbcp(),
  3122. pLocalCounterPath->szParentName,
  3123. szString,
  3124. & dwSize);
  3125. if (dwSize % sizeof(DWORD) != 0) {
  3126. dwSize = sizeof(DWORD)
  3127. * ((dwSize / sizeof(DWORD)) + 1);
  3128. }
  3129. dwSizeUsed += dwSize;
  3130. if (pdhStatus1 == ERROR_SUCCESS) {
  3131. pCounterPathElements->szParentInstance = szString;
  3132. szString += dwSize;
  3133. //szString = ALIGN_ON_DWORD(szString);
  3134. }
  3135. else if (pdhStatus == ERROR_SUCCESS) {
  3136. pdhStatus = pdhStatus1;
  3137. }
  3138. }
  3139. else if (pCounterPathElements != NULL) {
  3140. pCounterPathElements->szParentInstance = NULL;
  3141. }
  3142. if (pCounterPathElements != NULL) {
  3143. pCounterPathElements->dwInstanceIndex =
  3144. pLocalCounterPath->dwIndex;
  3145. }
  3146. }
  3147. else if (pCounterPathElements != NULL) {
  3148. pCounterPathElements->szInstanceName = NULL;
  3149. pCounterPathElements->szParentInstance = NULL;
  3150. pCounterPathElements->dwInstanceIndex = 0;
  3151. }
  3152. if (pLocalCounterPath->szCounterName != NULL) {
  3153. dwSize = (dwLocalBufferSize >= dwSizeUsed)
  3154. ? (dwLocalBufferSize - dwSizeUsed) : (0);
  3155. pdhStatus1 = PdhiConvertUnicodeToAnsi(_getmbcp(),
  3156. pLocalCounterPath->szCounterName,
  3157. szString,
  3158. & dwSize);
  3159. if (dwSize % sizeof(DWORD) != 0) {
  3160. dwSize = sizeof(DWORD)
  3161. * ((dwSize / sizeof(DWORD)) + 1);
  3162. }
  3163. dwSizeUsed += dwSize;
  3164. if (pdhStatus1 == ERROR_SUCCESS) {
  3165. pCounterPathElements->szCounterName = szString;
  3166. szString += dwSize;
  3167. //szString = ALIGN_ON_DWORD(szString);
  3168. }
  3169. else if (pdhStatus == ERROR_SUCCESS) {
  3170. pdhStatus = pdhStatus1;
  3171. }
  3172. }
  3173. else if (pCounterPathElements != NULL) {
  3174. pCounterPathElements->szCounterName = NULL;
  3175. }
  3176. dwLocalBufferSize = dwSizeUsed;
  3177. } else {
  3178. pdhStatus = PDH_INVALID_PATH;
  3179. }
  3180. } else {
  3181. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  3182. }
  3183. if (wszFullPath != NULL) G_FREE(wszFullPath);
  3184. } else {
  3185. // this is a WBEM path so have the WBEM function figure
  3186. // it out
  3187. // there is some WBEM component involved so send to WBEM function
  3188. // to figure it out
  3189. pdhStatus = PdhiDecodeWbemPathA (
  3190. szFullPathBuffer,
  3191. pCounterPathElements,
  3192. &dwLocalBufferSize,
  3193. (LANGID)((dwFlags >> 16) & 0x0000FFFF),
  3194. (DWORD)(dwFlags & 0x0000FFFF));
  3195. }
  3196. }
  3197. *pcchBufferSize = dwLocalBufferSize;
  3198. } __except (EXCEPTION_EXECUTE_HANDLER) {
  3199. pdhStatus = PDH_INVALID_ARGUMENT;
  3200. }
  3201. return pdhStatus;
  3202. }
  3203. PDH_FUNCTION
  3204. PdhParseInstanceNameW (
  3205. IN LPCWSTR szInstanceString,
  3206. IN LPWSTR szInstanceName,
  3207. IN LPDWORD pcchInstanceNameLength,
  3208. IN LPWSTR szParentName,
  3209. IN LPDWORD pcchParentNameLength,
  3210. IN LPDWORD lpIndex
  3211. )
  3212. /*++
  3213. Routine Description:
  3214. parses the fields of an instance string and returns them in the
  3215. buffers supplied by the caller
  3216. Arguments:
  3217. szInstanceString
  3218. is the pointer to the string containing the instance substring
  3219. to parse into individual components. This string can contain the
  3220. following formats and less than MAX_PATH chars in length:
  3221. instance
  3222. instance#index
  3223. parent/instance
  3224. parent/instance#index
  3225. szInstanceName
  3226. is the pointer to the buffer that will receive the instance
  3227. name parsed from the instance string. This pointer can be
  3228. NULL if the DWORD referenced by the pcchInstanceNameLength
  3229. argument is 0.
  3230. pcchInstanceNameLength
  3231. is the pointer to the DWORD that contains the length of the
  3232. szInstanceName buffer. If the value of this DWORD is 0, then
  3233. the buffer size required to hold the instance name will be
  3234. returned.
  3235. szParentName
  3236. is the pointer to the buffer that will receive the name
  3237. of the parent index if one is specified. This argument can
  3238. be NULL if the value of the DWORD referenced by the
  3239. pcchParentNameLength argument is 0.
  3240. lpIndex
  3241. is the pointer to the DWORD that will receive the index
  3242. value of the instance. If an index entry is not present in
  3243. the string, then this value will be 0. This argument can
  3244. be NULL if this information is not needed.
  3245. Return Value:
  3246. ERROR_SUCCESS if the function completes successfully, otherwise
  3247. a PDH error is returned.
  3248. PDH_INVALID_ARGUMENT is returned when one or more of the
  3249. arguments is invalid or incorrect.
  3250. PDH_INVALID_INSTANCE is returned if the instance string is incorrectly
  3251. formatted and cannot be parsed
  3252. PDH_INSUFFICIENT_BUFFER is returned when one or both of the string
  3253. buffers supplied is not large enough for the strings to be
  3254. returned.
  3255. --*/
  3256. {
  3257. BOOL bReturn;
  3258. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  3259. DWORD dwSize;
  3260. DWORD dwLocalIndex;
  3261. WCHAR szLocalInstanceName[MAX_PATH];
  3262. WCHAR szLocalParentName[MAX_PATH];
  3263. DWORD dwLocalInstanceNameLength;
  3264. DWORD dwLocalParentNameLength;
  3265. // test access to arguments
  3266. if ((szInstanceString == NULL) ||
  3267. (pcchInstanceNameLength == NULL) ||
  3268. (pcchParentNameLength == NULL)) {
  3269. return PDH_INVALID_ARGUMENT;
  3270. }
  3271. __try {
  3272. if (*szInstanceString == 0) {
  3273. pdhStatus = PDH_INVALID_ARGUMENT;
  3274. }
  3275. dwLocalInstanceNameLength = *pcchInstanceNameLength;
  3276. if (szInstanceName != NULL) {
  3277. if (dwLocalInstanceNameLength > 0) {
  3278. WCHAR wChar = *szInstanceName;
  3279. *szInstanceName = 0;
  3280. *szInstanceName = wChar;
  3281. wChar =szInstanceName[dwLocalInstanceNameLength -1];
  3282. szInstanceName[dwLocalInstanceNameLength -1] = 0;
  3283. szInstanceName[dwLocalInstanceNameLength -1] = wChar;
  3284. } // else size only request
  3285. } // else size only request
  3286. dwLocalParentNameLength = *pcchParentNameLength;
  3287. if (szParentName != NULL) {
  3288. if (dwLocalParentNameLength > 0) {
  3289. WCHAR wChar = *szParentName;
  3290. *szParentName = 0;
  3291. *szParentName = wChar;
  3292. wChar = szParentName[dwLocalParentNameLength -1];
  3293. szParentName[dwLocalParentNameLength -1] = 0;
  3294. szParentName[dwLocalParentNameLength -1] = wChar;
  3295. } // else size only request
  3296. } // else size only request
  3297. if (pdhStatus == ERROR_SUCCESS) {
  3298. memset (&szLocalInstanceName[0], 0, sizeof(szLocalInstanceName));
  3299. memset (&szLocalParentName[0], 0, sizeof(szLocalParentName));
  3300. bReturn = ParseInstanceName (
  3301. szInstanceString,
  3302. szLocalInstanceName,
  3303. szLocalParentName,
  3304. &dwLocalIndex);
  3305. if (bReturn) {
  3306. dwSize = lstrlenW(szLocalInstanceName);
  3307. if ( szInstanceName != NULL
  3308. && dwLocalInstanceNameLength > 0) {
  3309. if (dwSize < dwLocalInstanceNameLength) {
  3310. lstrcpyW (szInstanceName, szLocalInstanceName);
  3311. } else {
  3312. pdhStatus = PDH_MORE_DATA;
  3313. }
  3314. }
  3315. else {
  3316. pdhStatus = PDH_MORE_DATA;
  3317. }
  3318. dwLocalInstanceNameLength = dwSize + 1; // include the trailing NULL
  3319. dwSize = lstrlenW(szLocalParentName);
  3320. if (szParentName != NULL && dwLocalParentNameLength > 0) {
  3321. if (dwSize < dwLocalParentNameLength) {
  3322. lstrcpyW (szParentName, szLocalParentName);
  3323. } else {
  3324. pdhStatus = PDH_MORE_DATA;
  3325. }
  3326. }
  3327. else {
  3328. pdhStatus = PDH_MORE_DATA;
  3329. }
  3330. dwLocalParentNameLength = dwSize + 1; // include the trailing NULL
  3331. __try {
  3332. *pcchInstanceNameLength = dwLocalInstanceNameLength;
  3333. *pcchParentNameLength = dwLocalParentNameLength;
  3334. if (lpIndex != NULL) {
  3335. *lpIndex = dwLocalIndex;
  3336. }
  3337. } __except (EXCEPTION_EXECUTE_HANDLER) {
  3338. pdhStatus = PDH_INVALID_ARGUMENT;
  3339. }
  3340. } else {
  3341. // unable to parse string
  3342. pdhStatus = PDH_INVALID_INSTANCE;
  3343. }
  3344. } // else pass the error through
  3345. } __except (EXCEPTION_EXECUTE_HANDLER) {
  3346. pdhStatus = PDH_INVALID_ARGUMENT;
  3347. }
  3348. return pdhStatus;
  3349. }
  3350. PDH_FUNCTION
  3351. PdhParseInstanceNameA (
  3352. IN LPCSTR szInstanceString,
  3353. IN LPSTR szInstanceName,
  3354. IN LPDWORD pcchInstanceNameLength,
  3355. IN LPSTR szParentName,
  3356. IN LPDWORD pcchParentNameLength,
  3357. IN LPDWORD lpIndex
  3358. )
  3359. /*++
  3360. Routine Description:
  3361. parses the fields of an instance string and returns them in the
  3362. buffers supplied by the caller
  3363. Arguments:
  3364. szInstanceString
  3365. is the pointer to the string containing the instance substring
  3366. to parse into individual components. This string can contain the
  3367. following formats and less than MAX_PATH chars in length:
  3368. instance
  3369. instance#index
  3370. parent/instance
  3371. parent/instance#index
  3372. szInstanceName
  3373. is the pointer to the buffer that will receive the instance
  3374. name parsed from the instance string. This pointer can be
  3375. NULL if the DWORD referenced by the pcchInstanceNameLength
  3376. argument is 0.
  3377. pcchInstanceNameLength
  3378. is the pointer to the DWORD that contains the length of the
  3379. szInstanceName buffer. If the value of this DWORD is 0, then
  3380. the buffer size required to hold the instance name will be
  3381. returned.
  3382. szParentName
  3383. is the pointer to the buffer that will receive the name
  3384. of the parent index if one is specified. This argument can
  3385. be NULL if the value of the DWORD referenced by the
  3386. pcchParentNameLength argument is 0.
  3387. lpIndex
  3388. is the pointer to the DWORD that will receive the index
  3389. value of the instance. If an index entry is not present in
  3390. the string, then this value will be 0. This argument can
  3391. be NULL if this information is not needed.
  3392. Return Value:
  3393. ERROR_SUCCESS if the function completes successfully, otherwise
  3394. a PDH error is returned.
  3395. PDH_INVALID_ARGUMENT is returned when one or more of the
  3396. arguments is invalid or incorrect.
  3397. PDH_INVALID_INSTANCE is returned if the instance string is incorrectly
  3398. formatted and cannot be parsed
  3399. PDH_INSUFFICIENT_BUFFER is returned when one or both of the string
  3400. buffers supplied is not large enough for the strings to be
  3401. returned.
  3402. --*/
  3403. {
  3404. BOOL bReturn;
  3405. LONG pdhStatus = ERROR_SUCCESS;
  3406. DWORD dwSize;
  3407. WCHAR wszInstanceString[MAX_PATH];
  3408. WCHAR wszLocalInstanceName[MAX_PATH];
  3409. WCHAR wszLocalParentName[MAX_PATH];
  3410. DWORD dwLocalIndex = 0;
  3411. DWORD dwLocalInstanceNameLength;
  3412. DWORD dwLocalParentNameLength;
  3413. // test access to arguments
  3414. if ((szInstanceString == NULL) ||
  3415. (pcchInstanceNameLength == NULL) ||
  3416. (pcchParentNameLength == NULL)) {
  3417. return PDH_INVALID_ARGUMENT;
  3418. }
  3419. __try {
  3420. if (*szInstanceString == 0) {
  3421. pdhStatus = PDH_INVALID_ARGUMENT;
  3422. }
  3423. dwLocalInstanceNameLength = *pcchInstanceNameLength;
  3424. if (szInstanceName != NULL) {
  3425. if (dwLocalInstanceNameLength > 0) {
  3426. CHAR cChar = *szInstanceName;
  3427. *szInstanceName = 0;
  3428. *szInstanceName = cChar;
  3429. cChar =szInstanceName[dwLocalInstanceNameLength -1];
  3430. szInstanceName[dwLocalInstanceNameLength -1] = 0;
  3431. szInstanceName[dwLocalInstanceNameLength -1] = cChar;
  3432. } // else size only request
  3433. } // else size only request
  3434. dwLocalParentNameLength = *pcchParentNameLength;
  3435. if (szParentName != NULL) {
  3436. if (dwLocalParentNameLength > 0) {
  3437. CHAR cChar = *szParentName;
  3438. *szParentName = 0;
  3439. *szParentName = cChar;
  3440. cChar = szParentName[dwLocalParentNameLength -1];
  3441. szParentName[dwLocalParentNameLength -1] = 0;
  3442. szParentName[dwLocalParentNameLength -1] = cChar;
  3443. } // else size only request
  3444. } // else size only request
  3445. if (pdhStatus == ERROR_SUCCESS) {
  3446. memset (&wszInstanceString[0], 0, sizeof(wszInstanceString));
  3447. memset (&wszLocalInstanceName[0], 0, sizeof(wszLocalInstanceName));
  3448. memset (&wszLocalParentName[0], 0, sizeof(wszLocalParentName));
  3449. dwSize = lstrlenA(szInstanceString) +1 ;
  3450. if (lstrlenA(szInstanceString) < MAX_PATH) {
  3451. MultiByteToWideChar(_getmbcp(),
  3452. 0,
  3453. szInstanceString,
  3454. lstrlenA(szInstanceString),
  3455. wszInstanceString,
  3456. dwSize);
  3457. bReturn = ParseInstanceName (
  3458. wszInstanceString,
  3459. wszLocalInstanceName,
  3460. wszLocalParentName,
  3461. &dwLocalIndex);
  3462. } else {
  3463. // instance string is too long
  3464. bReturn = FALSE;
  3465. pdhStatus = PDH_INVALID_INSTANCE;
  3466. }
  3467. if (bReturn) {
  3468. PDH_STATUS pdhInstStatus = ERROR_SUCCESS;
  3469. PDH_STATUS pdhParentStatus = ERROR_SUCCESS;
  3470. dwSize = dwLocalInstanceNameLength;
  3471. pdhInstStatus = PdhiConvertUnicodeToAnsi(_getmbcp(),
  3472. wszLocalInstanceName,
  3473. szInstanceName,
  3474. & dwSize);
  3475. dwLocalInstanceNameLength = dwSize;
  3476. dwSize = * pcchParentNameLength;
  3477. pdhParentStatus = PdhiConvertUnicodeToAnsi(_getmbcp(),
  3478. wszLocalParentName,
  3479. szParentName,
  3480. & dwSize);
  3481. if (pdhParentStatus == PDH_INVALID_ARGUMENT) {
  3482. pdhParentStatus = ERROR_SUCCESS;
  3483. }
  3484. dwLocalParentNameLength = dwSize + 1;
  3485. if (pdhInstStatus != ERROR_SUCCESS) {
  3486. pdhStatus = pdhInstStatus;
  3487. }
  3488. else {
  3489. pdhStatus = pdhParentStatus;
  3490. }
  3491. __try {
  3492. *pcchInstanceNameLength = dwLocalInstanceNameLength;
  3493. *pcchParentNameLength = dwLocalParentNameLength;
  3494. if (lpIndex != NULL) {
  3495. *lpIndex = dwLocalIndex;
  3496. }
  3497. } __except (EXCEPTION_EXECUTE_HANDLER) {
  3498. pdhStatus = PDH_INVALID_ARGUMENT;
  3499. }
  3500. } else {
  3501. // unable to parse string
  3502. pdhStatus = PDH_INVALID_INSTANCE;
  3503. }
  3504. } // else pass status through to caller
  3505. } __except (EXCEPTION_EXECUTE_HANDLER) {
  3506. pdhStatus = PDH_INVALID_ARGUMENT;
  3507. }
  3508. return pdhStatus;
  3509. }
  3510. PDH_FUNCTION
  3511. PdhValidatePathW (
  3512. IN LPCWSTR szFullPathBuffer
  3513. )
  3514. /*++
  3515. Routine Description:
  3516. breaks the specified path into its component parts and evaluates
  3517. each of the part to make sure the specified path represents
  3518. a valid and operational performance counter. The return value
  3519. indicates the pdhStatus of the counter defined in the path string.
  3520. Arguments:
  3521. IN LPCWSTR szFullPathBuffer
  3522. the full path string of the counter to validate.
  3523. Return Value:
  3524. ERROR_SUCCESS of the counter was successfully located otherwise
  3525. a PDH error.
  3526. PDH_CSTATUS_NO_INSTANCE is returned if the specified instance of
  3527. the performance object wasn't found
  3528. PDH_CSTATUS_NO_COUNTER is returned if the specified counter was not
  3529. found in the object.
  3530. PDH_CSTATUS_NO_OBJECT is returned if the specified object was not
  3531. found on the machine
  3532. PDH_CSTATUS_NO_MACHINE is returned if the specified machine could
  3533. not be found or connected to
  3534. PDH_CSTATUS_BAD_COUNTERNAME is returned when the counter path string
  3535. could not be parsed.
  3536. PDH_MEMORY_ALLOCATION_FAILURE is returned when the function is unable
  3537. to allocate a required temporary buffer
  3538. PDH_INVALID_ARGUMENT is returned when the counter path string argument
  3539. could not be accessed
  3540. --*/
  3541. {
  3542. PPERF_MACHINE pMachine;
  3543. PPDHI_COUNTER_PATH pLocalCounterPath;
  3544. DWORD dwSize;
  3545. PERF_OBJECT_TYPE *pPerfObjectDef = NULL;
  3546. PERF_INSTANCE_DEFINITION *pPerfInstanceDef;
  3547. PERF_COUNTER_DEFINITION *pPerfCounterDef;
  3548. PDH_STATUS CStatus = ERROR_SUCCESS;
  3549. DebugPrint((4, "PdhValidatePathW BEGIN\n"));
  3550. if (szFullPathBuffer != NULL) {
  3551. // validate access to arguments
  3552. __try {
  3553. // make sure the name isn't empty
  3554. if (*szFullPathBuffer == 0) {
  3555. CStatus = PDH_INVALID_ARGUMENT;
  3556. }
  3557. } __except (EXCEPTION_EXECUTE_HANDLER) {
  3558. CStatus = PDH_INVALID_ARGUMENT;
  3559. }
  3560. } else {
  3561. // cannot be null
  3562. CStatus = PDH_INVALID_ARGUMENT;
  3563. }
  3564. if (CStatus == ERROR_SUCCESS) {
  3565. CStatus = WAIT_FOR_AND_LOCK_MUTEX (hPdhDataMutex);
  3566. }
  3567. if (CStatus == ERROR_SUCCESS) {
  3568. __try {
  3569. pLocalCounterPath = G_ALLOC (
  3570. (sizeof(PDHI_COUNTER_PATH) +
  3571. 2 * lstrlenW(szFullPathBuffer) * sizeof (WCHAR)));
  3572. if (pLocalCounterPath != NULL) {
  3573. dwSize = (DWORD)G_SIZE (pLocalCounterPath);
  3574. if (ParseFullPathNameW (szFullPathBuffer,
  3575. &dwSize, pLocalCounterPath, FALSE)) {
  3576. // parsed successfully so try to connect to machine
  3577. // and get machine pointer
  3578. pMachine = GetMachine (pLocalCounterPath->szMachineName, 0);
  3579. if (pMachine != NULL) {
  3580. if (pMachine->dwStatus == ERROR_SUCCESS) {
  3581. // look up object name
  3582. pPerfObjectDef = GetObjectDefByName (
  3583. pMachine->pSystemPerfData,
  3584. pMachine->dwLastPerfString,
  3585. pMachine->szPerfStrings,
  3586. pLocalCounterPath->szObjectName);
  3587. } else {
  3588. pPerfObjectDef = NULL;
  3589. }
  3590. if (pPerfObjectDef != NULL) {
  3591. // look up instances if necessary
  3592. if (pPerfObjectDef->NumInstances != PERF_NO_INSTANCES) {
  3593. if (pLocalCounterPath->szInstanceName != NULL) {
  3594. if (*pLocalCounterPath->szInstanceName != SPLAT_L) {
  3595. pPerfInstanceDef = GetInstanceByName (
  3596. pMachine->pSystemPerfData,
  3597. pPerfObjectDef,
  3598. pLocalCounterPath->szInstanceName,
  3599. pLocalCounterPath->szParentName,
  3600. (pLocalCounterPath->dwIndex != (DWORD)-1 ?
  3601. pLocalCounterPath->dwIndex : 0));
  3602. if (pPerfInstanceDef == NULL) {
  3603. // unable to lookup instance
  3604. CStatus = PDH_CSTATUS_NO_INSTANCE;
  3605. } else {
  3606. // instance found and matched so continue
  3607. }
  3608. } else {
  3609. // wild card instances are OK IF multiple instances
  3610. // are supported!!!
  3611. }
  3612. } else {
  3613. // no instance was specified for a counter
  3614. // that should have an instance so this is
  3615. // an invalid path
  3616. CStatus = PDH_CSTATUS_NO_INSTANCE;
  3617. }
  3618. } else {
  3619. // no instances in this counter, see if one
  3620. // is defined
  3621. if ((pLocalCounterPath->szInstanceName != NULL) ||
  3622. (pLocalCounterPath->szParentName != NULL)) {
  3623. // unable to lookup instance
  3624. CStatus = PDH_CSTATUS_NO_INSTANCE;
  3625. }
  3626. }
  3627. if (CStatus == ERROR_SUCCESS) {
  3628. // and look up counter
  3629. pPerfCounterDef = GetCounterDefByName (
  3630. pPerfObjectDef,
  3631. pMachine->dwLastPerfString,
  3632. pMachine->szPerfStrings,
  3633. pLocalCounterPath->szCounterName);
  3634. if (pPerfCounterDef != NULL) {
  3635. // counter found so return TRUE & valid
  3636. CStatus = ERROR_SUCCESS;
  3637. } else {
  3638. // unable to lookup counter
  3639. CStatus = PDH_CSTATUS_NO_COUNTER;
  3640. }
  3641. }
  3642. } else {
  3643. // unable to lookup object
  3644. CStatus = PDH_CSTATUS_NO_OBJECT;
  3645. }
  3646. pMachine->dwRefCount--;
  3647. RELEASE_MUTEX (pMachine->hMutex);
  3648. } else {
  3649. // unable to find machine
  3650. CStatus = PDH_CSTATUS_NO_MACHINE;
  3651. }
  3652. } else {
  3653. // unable to parse counter name
  3654. CStatus = PDH_CSTATUS_BAD_COUNTERNAME;
  3655. }
  3656. G_FREE (pLocalCounterPath);
  3657. } else {
  3658. // unable to allocate memory
  3659. CStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  3660. }
  3661. } __except (EXCEPTION_EXECUTE_HANDLER) {
  3662. CStatus = PDH_INVALID_ARGUMENT;
  3663. }
  3664. RELEASE_MUTEX (hPdhDataMutex);
  3665. } // else pass error to caller
  3666. DebugPrint((4, "PdhValidatePathW END status 0x%08X\n", CStatus));
  3667. return CStatus;
  3668. }
  3669. PDH_FUNCTION
  3670. PdhValidatePathA (
  3671. IN LPCSTR szFullPathBuffer
  3672. )
  3673. /*++
  3674. Routine Description:
  3675. breaks the specified path into its component parts and evaluates
  3676. each of the part to make sure the specified path represents
  3677. a valid and operational performance counter. The return value
  3678. indicates the pdhStatus of the counter defined in the path string.
  3679. Arguments:
  3680. IN LPCSTR szFullPathBuffer
  3681. the full path string of the counter to validate.
  3682. Return Value:
  3683. ERROR_SUCCESS of the counter was successfully located otherwise
  3684. a PDH error.
  3685. PDH_CSTATUS_NO_INSTANCE is returned if the specified instance of
  3686. the performance object wasn't found
  3687. PDH_CSTATUS_NO_COUNTER is returned if the specified counter was not
  3688. found in the object.
  3689. PDH_CSTATUS_NO_OBJECT is returned if the specified object was not
  3690. found on the machine
  3691. PDH_CSTATUS_NO_MACHINE is returned if the specified machine could
  3692. not be found or connected to
  3693. PDH_CSTATUS_BAD_COUNTERNAME is returned when the counter path string
  3694. could not be parsed.
  3695. PDH_MEMORY_ALLOCATION_FAILURE is returned when the function is unable
  3696. to allocate a required temporary buffer
  3697. --*/
  3698. {
  3699. LPWSTR wszFullPath = NULL;
  3700. PDH_STATUS Status = ERROR_SUCCESS;
  3701. DWORD dwSize;
  3702. DebugPrint((4, "PdhValidatePathA BEGIN\n"));
  3703. if (szFullPathBuffer != NULL) {
  3704. __try {
  3705. // cannot be blank
  3706. if (*szFullPathBuffer == 0) {
  3707. Status = PDH_INVALID_ARGUMENT;
  3708. } else {
  3709. dwSize = lstrlenA(szFullPathBuffer);
  3710. wszFullPath = G_ALLOC ((dwSize + 1) * sizeof(WCHAR));
  3711. if (wszFullPath != NULL) {
  3712. MultiByteToWideChar(_getmbcp(),
  3713. 0,
  3714. szFullPathBuffer,
  3715. dwSize,
  3716. wszFullPath,
  3717. dwSize + 1);
  3718. }
  3719. }
  3720. } __except (EXCEPTION_EXECUTE_HANDLER) {
  3721. Status = PDH_INVALID_ARGUMENT;
  3722. }
  3723. } else {
  3724. // cannot be null
  3725. Status = PDH_INVALID_ARGUMENT;
  3726. }
  3727. if (Status == ERROR_SUCCESS) {
  3728. if (wszFullPath != NULL) {
  3729. Status = PdhValidatePathW (wszFullPath);
  3730. } else {
  3731. Status = PDH_MEMORY_ALLOCATION_FAILURE;
  3732. }
  3733. }
  3734. if (wszFullPath != NULL) G_FREE (wszFullPath);
  3735. DebugPrint((4, "PdhValidatePathA END status 0x%08X\n", Status));
  3736. return Status;
  3737. }
  3738. PDH_FUNCTION
  3739. PdhiGetDefaultPerfObjectW (
  3740. IN DWORD dwDataSource,
  3741. IN LPCWSTR szMachineName,
  3742. IN LPWSTR szDefaultObjectName,
  3743. IN LPDWORD pcchBufferSize
  3744. )
  3745. /*++
  3746. Routine Description:
  3747. Obtains the default performance object from the specified machine.
  3748. Arguments:
  3749. IN DWORD dwDataSourcetype
  3750. IN LPCWSTR szMachineName
  3751. NULL indicates the local machine, othewise this is the
  3752. name of the remote machine to query. If this machine is
  3753. not known to the PDH DLL, then it will be connected.
  3754. IN LPWSTR szDefaultObjectName
  3755. pointer to the buffer that will receive the default object
  3756. name. This pointer can be NULL if the value of the DWORD
  3757. referenced by bcchBufferSize is 0.
  3758. IN LPDWORD pcchBufferSize
  3759. pointer to a DWORD containing the size of the buffer, in
  3760. characters, referenced by the szDefaultObjectName argument.
  3761. If the value of this DWORD is 0, then no data will be written
  3762. to the szDefaultObjectNameBuffer, however the required
  3763. buffer size will be returned in the DWORD referenced by
  3764. this pointer.
  3765. Return Value:
  3766. ERROR_SUCCESS if this function completes normally otherwise a PDH error.
  3767. PDH_INVALID_ARGUMENT a required argument is not correct or reserved
  3768. argument is not 0 or NULL.
  3769. PDH_MEMORY_ALLOCATION_FAILURE is returned when a required temporary
  3770. buffer could not be allocated.
  3771. PDH_INSUFFICIENT_BUFFER is returned when the buffer supplied is
  3772. not large enough for the available data.
  3773. PDH_CSTATUS_NO_COUNTERNAME is returned when the default object
  3774. name cannot be read or found.
  3775. PDH_CSTATUS_NO_MACHINE is returned when the specified machine
  3776. is offline or unavailable.
  3777. --*/
  3778. {
  3779. PPERF_MACHINE pMachine;
  3780. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  3781. LONG lDefault;
  3782. DWORD dwStringLen;
  3783. DWORD dwLocalBufferSize = 0;
  3784. LPWSTR szDefault;
  3785. LPWSTR szThisMachine = NULL;
  3786. DebugPrint((4, "PdhiGetDefaultPerfObjectW BEGIN\n"));
  3787. if (pcchBufferSize == NULL) {
  3788. pdhStatus = PDH_INVALID_ARGUMENT;
  3789. } else {
  3790. // test the access the arguments
  3791. __try {
  3792. if (szMachineName != NULL) {
  3793. // if there's a machine name then it cannot be blank
  3794. if (*szMachineName == 0) {
  3795. pdhStatus = PDH_INVALID_ARGUMENT;
  3796. }
  3797. } // else NULL machine Name is OK
  3798. if (pdhStatus == ERROR_SUCCESS) {
  3799. dwLocalBufferSize = *pcchBufferSize;
  3800. if (dwLocalBufferSize > 0) {
  3801. // test both ends of the caller's buffer for
  3802. // write access
  3803. szDefaultObjectName[0] = 0;
  3804. szDefaultObjectName[dwLocalBufferSize -1] = 0;
  3805. } else {
  3806. // this is just a size request so the buffer will not be used
  3807. }
  3808. }
  3809. } __except (EXCEPTION_EXECUTE_HANDLER) {
  3810. pdhStatus = PDH_INVALID_ARGUMENT;
  3811. }
  3812. }
  3813. if (pdhStatus == ERROR_SUCCESS && szMachineName != NULL) {
  3814. DWORD dwMachineName = (* szMachineName == L'\\')
  3815. ? (lstrlenW(szMachineName) + 1)
  3816. : (lstrlenW(szMachineName) + 3);
  3817. dwMachineName *= sizeof(WCHAR);
  3818. szThisMachine = G_ALLOC(dwMachineName);
  3819. if (szThisMachine == NULL) {
  3820. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  3821. }
  3822. else if (* szMachineName == L'\\') {
  3823. lstrcpyW(szThisMachine, szMachineName);
  3824. }
  3825. else {
  3826. lstrcpyW(szThisMachine, cszDoubleBackSlash);
  3827. lstrcatW(szThisMachine, szMachineName);
  3828. }
  3829. }
  3830. if (pdhStatus == ERROR_SUCCESS) {
  3831. pdhStatus = WAIT_FOR_AND_LOCK_MUTEX (hPdhDataMutex);
  3832. }
  3833. if (pdhStatus == ERROR_SUCCESS) {
  3834. __try {
  3835. switch (dwDataSource) {
  3836. case DATA_SOURCE_REGISTRY:
  3837. pMachine = GetMachine ((LPWSTR)szThisMachine, 0);
  3838. if (pMachine == NULL) {
  3839. // unable to connect to machine so get pdhStatus
  3840. pdhStatus = GetLastError();
  3841. }
  3842. if (pMachine != NULL) {
  3843. if (pMachine->dwStatus == ERROR_SUCCESS) {
  3844. // only look at buffers from machines that are "on line"
  3845. lDefault = pMachine->pSystemPerfData->DefaultObject;
  3846. if ((lDefault > 0) && ((DWORD)lDefault < pMachine->dwLastPerfString)) {
  3847. // then there should be a string in the table
  3848. szDefault = (LPWSTR)PdhiLookupPerfNameByIndex (
  3849. pMachine, lDefault);
  3850. if (szDefault != NULL) {
  3851. // determine string buffer length including term. NULL char
  3852. dwStringLen = lstrlenW (szDefault) + 1;
  3853. if (dwLocalBufferSize > 0) {
  3854. if (dwStringLen <= dwLocalBufferSize) {
  3855. lstrcpyW (szDefaultObjectName, szDefault);
  3856. pdhStatus = ERROR_SUCCESS;
  3857. } else {
  3858. pdhStatus = PDH_MORE_DATA;
  3859. }
  3860. }
  3861. else {
  3862. pdhStatus = PDH_MORE_DATA;
  3863. }
  3864. } else {
  3865. // unable to find a matching counter name
  3866. pdhStatus = PDH_CSTATUS_NO_COUNTERNAME;
  3867. dwStringLen = 0;
  3868. }
  3869. } else {
  3870. // string not in table
  3871. pdhStatus = PDH_CSTATUS_NO_COUNTERNAME;
  3872. dwStringLen = 0;
  3873. }
  3874. dwLocalBufferSize = dwStringLen;
  3875. } else {
  3876. // machine is off line
  3877. pdhStatus = pMachine->dwStatus;
  3878. }
  3879. pMachine->dwRefCount--;
  3880. RELEASE_MUTEX (pMachine->hMutex);
  3881. } // else pass error pdhStatus on to the caller
  3882. break;
  3883. case DATA_SOURCE_WBEM:
  3884. pdhStatus = PdhiGetDefaultWbemObject (
  3885. szThisMachine,
  3886. (LPVOID)szDefaultObjectName,
  3887. &dwLocalBufferSize,
  3888. TRUE); // unicode function
  3889. break;
  3890. case DATA_SOURCE_LOGFILE:
  3891. // log files don't support this (for now)
  3892. // but this is still successful.
  3893. dwLocalBufferSize = 0;
  3894. *szDefaultObjectName = 0;
  3895. break;
  3896. default:
  3897. assert (FALSE);
  3898. }
  3899. } __except (EXCEPTION_EXECUTE_HANDLER) {
  3900. pdhStatus = PDH_INVALID_ARGUMENT;
  3901. }
  3902. RELEASE_MUTEX (hPdhDataMutex);
  3903. __try {
  3904. *pcchBufferSize = dwLocalBufferSize;
  3905. } __except (EXCEPTION_EXECUTE_HANDLER) {
  3906. pdhStatus = PDH_INVALID_ARGUMENT;
  3907. }
  3908. }
  3909. if (szThisMachine != NULL) {
  3910. G_FREE(szThisMachine);
  3911. }
  3912. DebugPrint((4, "PdhiGetDefaultPerfObjectW END status 0x%08X\n", pdhStatus));
  3913. return pdhStatus;
  3914. }
  3915. PDH_FUNCTION
  3916. PdhGetDefaultPerfObjectHW(
  3917. IN HLOG hDataSource,
  3918. IN LPCWSTR szMachineName,
  3919. IN LPWSTR szDefaultObjectName,
  3920. IN LPDWORD pcchBufferSize)
  3921. {
  3922. DWORD dwDataSourceType = 0;
  3923. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  3924. __try {
  3925. dwDataSourceType = DataSourceTypeH(hDataSource);
  3926. }
  3927. __except (EXCEPTION_EXECUTE_HANDLER) {
  3928. pdhStatus = PDH_INVALID_ARGUMENT;
  3929. }
  3930. if (pdhStatus == ERROR_SUCCESS) {
  3931. pdhStatus = PdhiGetDefaultPerfObjectW(dwDataSourceType,
  3932. szMachineName,
  3933. szDefaultObjectName,
  3934. pcchBufferSize);
  3935. }
  3936. return pdhStatus;
  3937. }
  3938. PDH_FUNCTION
  3939. PdhGetDefaultPerfObjectW(
  3940. IN LPCWSTR szDataSource,
  3941. IN LPCWSTR szMachineName,
  3942. IN LPWSTR szDefaultObjectName,
  3943. IN LPDWORD pcchBufferSize)
  3944. {
  3945. DWORD dwDataSourceType = 0;
  3946. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  3947. __try {
  3948. if (szDataSource != NULL) {
  3949. if (* szDataSource == 0) {
  3950. pdhStatus = PDH_INVALID_ARGUMENT;
  3951. }
  3952. }
  3953. dwDataSourceType = DataSourceTypeW(szDataSource);
  3954. }
  3955. __except (EXCEPTION_EXECUTE_HANDLER) {
  3956. pdhStatus = PDH_INVALID_ARGUMENT;
  3957. }
  3958. if (pdhStatus == ERROR_SUCCESS) {
  3959. pdhStatus = PdhiGetDefaultPerfObjectW(dwDataSourceType,
  3960. szMachineName,
  3961. szDefaultObjectName,
  3962. pcchBufferSize);
  3963. }
  3964. return pdhStatus;
  3965. }
  3966. PDH_FUNCTION
  3967. PdhiGetDefaultPerfObjectA (
  3968. IN DWORD dwDataSource,
  3969. IN LPCSTR szMachineName,
  3970. IN LPSTR szDefaultObjectName,
  3971. IN LPDWORD pcchBufferSize
  3972. )
  3973. /*++
  3974. Routine Description:
  3975. Obtains the default performance object from the specified machine.
  3976. Arguments:
  3977. IN DWORD dwDataSourceType
  3978. IN LPCSTR szMachineName
  3979. NULL indicates the local machine, othewise this is the
  3980. name of the remote machine to query. If this machine is
  3981. not known to the PDH DLL, then it will be connected.
  3982. IN LPSTR szDefaultObjectName
  3983. pointer to the buffer that will receive the default object
  3984. name. This pointer can be NULL if the value of the DWORD
  3985. referenced by bcchBufferSize is 0.
  3986. IN LPDWORD pcchBufferSize
  3987. pointer to a DWORD containing the size of the buffer, in
  3988. characters, referenced by the szDefaultObjectName argument.
  3989. If the value of this DWORD is 0, then no data will be written
  3990. to the szDefaultObjectNameBuffer, however the required
  3991. buffer size will be returned in the DWORD referenced by
  3992. this pointer.
  3993. Return Value:
  3994. ERROR_SUCCESS if this function completes normally otherwise a PDH error.
  3995. PDH_INVALID_ARGUMENT a required argument is not correct or reserved
  3996. argument is not 0 or NULL.
  3997. PDH_MEMORY_ALLOCATION_FAILURE is returned when a required temporary
  3998. buffer could not be allocated.
  3999. PDH_INSUFFICIENT_BUFFER is returned when the buffer supplied is
  4000. not large enough for the available data.
  4001. PDH_CSTATUS_NO_COUNTERNAME is returned when the default object
  4002. name cannot be read or found.
  4003. PDH_CSTATUS_NO_MACHINE is returned when the specified machine
  4004. is offline or unavailable.
  4005. --*/
  4006. {
  4007. LPWSTR szWideName = NULL;
  4008. DWORD dwNameLength;
  4009. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  4010. PPERF_MACHINE pMachine = NULL;
  4011. LONG lDefault;
  4012. DWORD dwStringLen;
  4013. DWORD dwLocalBufferSize = 0;
  4014. LPWSTR szDefault = NULL;
  4015. DebugPrint((4, "PdhiGetDefaultPerfObjectA BEGIN\n"));
  4016. if (pcchBufferSize == NULL) {
  4017. return PDH_INVALID_ARGUMENT;
  4018. }
  4019. // test the access the arguments
  4020. __try {
  4021. if (szMachineName != NULL) {
  4022. if (*szMachineName == 0) {
  4023. pdhStatus = PDH_INVALID_ARGUMENT;
  4024. }
  4025. } // else NULL machine Name is OK
  4026. if (pdhStatus == ERROR_SUCCESS) {
  4027. dwLocalBufferSize = *pcchBufferSize;
  4028. if (dwLocalBufferSize > 0) {
  4029. // test both ends of the caller's buffer for
  4030. // write access
  4031. szDefaultObjectName[0] = 0;
  4032. szDefaultObjectName[dwLocalBufferSize -1] = 0;
  4033. } else {
  4034. // this is just a size request so the buffer will not be used
  4035. }
  4036. }
  4037. } __except (EXCEPTION_EXECUTE_HANDLER) {
  4038. pdhStatus = PDH_INVALID_ARGUMENT;
  4039. }
  4040. if (pdhStatus == ERROR_SUCCESS && szMachineName != NULL) {
  4041. dwNameLength = (* szMachineName == '\\')
  4042. ? (lstrlenA(szMachineName) + 1)
  4043. : (lstrlenA(szMachineName) + 3);
  4044. szWideName = G_ALLOC (dwNameLength * sizeof(WCHAR));
  4045. if (szWideName == NULL) {
  4046. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  4047. }
  4048. else if (* szMachineName == '\\') {
  4049. MultiByteToWideChar(_getmbcp(),
  4050. 0,
  4051. szMachineName,
  4052. lstrlenA(szMachineName),
  4053. (LPWSTR) szWideName,
  4054. dwNameLength);
  4055. }
  4056. else {
  4057. LPWSTR szThisMachine = szWideName + 2;
  4058. lstrcpyW(szWideName, cszDoubleBackSlash);
  4059. MultiByteToWideChar(_getmbcp(),
  4060. 0,
  4061. szMachineName,
  4062. lstrlenA(szMachineName),
  4063. (LPWSTR) szThisMachine,
  4064. dwNameLength - 2);
  4065. }
  4066. }
  4067. if (pdhStatus == ERROR_SUCCESS) {
  4068. pdhStatus = WAIT_FOR_AND_LOCK_MUTEX (hPdhDataMutex);
  4069. }
  4070. if (pdhStatus == ERROR_SUCCESS) {
  4071. __try {
  4072. switch (dwDataSource) {
  4073. case DATA_SOURCE_REGISTRY:
  4074. if (pdhStatus == ERROR_SUCCESS) {
  4075. pMachine = GetMachine (szWideName, 0);
  4076. if (pMachine == NULL) {
  4077. // unable to connect to machine so get pdhStatus
  4078. pdhStatus = GetLastError();
  4079. } else {
  4080. pdhStatus = ERROR_SUCCESS;
  4081. }
  4082. }
  4083. if (pMachine != NULL) {
  4084. if (pMachine->dwStatus == ERROR_SUCCESS) {
  4085. // only look at buffers from machines that are "on line"
  4086. lDefault = pMachine->pSystemPerfData->DefaultObject;
  4087. if ((lDefault > 0) && ((DWORD)lDefault < pMachine->dwLastPerfString)) {
  4088. // then there should be a string in the table
  4089. szDefault = (LPWSTR)PdhiLookupPerfNameByIndex (
  4090. pMachine, lDefault);
  4091. if (szDefault != NULL) {
  4092. // determine string buffer length including term. NULL char
  4093. dwStringLen = dwLocalBufferSize;
  4094. pdhStatus = PdhiConvertUnicodeToAnsi(_getmbcp(),
  4095. szDefault,
  4096. szDefaultObjectName,
  4097. & dwStringLen);
  4098. } else {
  4099. // unable to find a matching counter name
  4100. pdhStatus = PDH_CSTATUS_NO_COUNTERNAME;
  4101. dwStringLen = 0;
  4102. }
  4103. } else {
  4104. // string not in table
  4105. pdhStatus = PDH_CSTATUS_NO_COUNTERNAME;
  4106. dwStringLen = 0;
  4107. }
  4108. dwLocalBufferSize = dwStringLen;
  4109. } else {
  4110. // machine is off line
  4111. pdhStatus = pMachine->dwStatus;
  4112. }
  4113. pMachine->dwRefCount--;
  4114. RELEASE_MUTEX (pMachine->hMutex);
  4115. } // else pass error pdhStatus on to the caller
  4116. break;
  4117. case DATA_SOURCE_WBEM:
  4118. case DATA_SOURCE_LOGFILE:
  4119. if ((pdhStatus == ERROR_SUCCESS) && (dwDataSource == DATA_SOURCE_WBEM)) {
  4120. pdhStatus = PdhiGetDefaultWbemObject (
  4121. szWideName,
  4122. (LPVOID)szDefaultObjectName,
  4123. &dwLocalBufferSize,
  4124. FALSE); // ANSI function
  4125. } else {
  4126. //log files don't support this (for now)
  4127. dwLocalBufferSize = 0;
  4128. *szDefaultObjectName = 0;
  4129. }
  4130. break;
  4131. default:
  4132. assert (FALSE);
  4133. }
  4134. } __except (EXCEPTION_EXECUTE_HANDLER) {
  4135. pdhStatus = PDH_INVALID_ARGUMENT;
  4136. }
  4137. RELEASE_MUTEX (hPdhDataMutex);
  4138. __try {
  4139. *pcchBufferSize = dwLocalBufferSize;
  4140. } __except (EXCEPTION_EXECUTE_HANDLER) {
  4141. pdhStatus = PDH_INVALID_ARGUMENT;
  4142. }
  4143. }
  4144. if (szWideName != NULL) G_FREE (szWideName);
  4145. DebugPrint((4, "PdhiGetDefaultPerfObjectA END status 0x%08X\n", pdhStatus));
  4146. return pdhStatus;
  4147. }
  4148. PDH_FUNCTION
  4149. PdhGetDefaultPerfObjectHA(
  4150. IN HLOG hDataSource,
  4151. IN LPCSTR szMachineName,
  4152. IN LPSTR szDefaultObjectName,
  4153. IN LPDWORD pcchBufferSize)
  4154. {
  4155. DWORD dwDataSourceType = 0;
  4156. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  4157. __try {
  4158. dwDataSourceType = DataSourceTypeH(hDataSource);
  4159. }
  4160. __except (EXCEPTION_EXECUTE_HANDLER) {
  4161. pdhStatus = PDH_INVALID_ARGUMENT;
  4162. }
  4163. if (pdhStatus == ERROR_SUCCESS) {
  4164. pdhStatus = PdhiGetDefaultPerfObjectA(dwDataSourceType,
  4165. szMachineName,
  4166. szDefaultObjectName,
  4167. pcchBufferSize);
  4168. }
  4169. return pdhStatus;
  4170. }
  4171. PDH_FUNCTION
  4172. PdhGetDefaultPerfObjectA(
  4173. IN LPCSTR szDataSource,
  4174. IN LPCSTR szMachineName,
  4175. IN LPSTR szDefaultObjectName,
  4176. IN LPDWORD pcchBufferSize)
  4177. {
  4178. DWORD dwDataSourceType = 0;
  4179. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  4180. __try {
  4181. if (szDataSource != NULL) {
  4182. if (* szDataSource == 0) {
  4183. pdhStatus = PDH_INVALID_ARGUMENT;
  4184. }
  4185. }
  4186. dwDataSourceType = DataSourceTypeA(szDataSource);
  4187. }
  4188. __except (EXCEPTION_EXECUTE_HANDLER) {
  4189. pdhStatus = PDH_INVALID_ARGUMENT;
  4190. }
  4191. if (pdhStatus == ERROR_SUCCESS) {
  4192. pdhStatus = PdhiGetDefaultPerfObjectA(dwDataSourceType,
  4193. szMachineName,
  4194. szDefaultObjectName,
  4195. pcchBufferSize);
  4196. }
  4197. return pdhStatus;
  4198. }
  4199. PDH_FUNCTION
  4200. PdhiGetDefaultPerfCounterW (
  4201. IN DWORD dwDataSource,
  4202. IN LPCWSTR szMachineName,
  4203. IN LPCWSTR szObjectName,
  4204. IN LPWSTR szDefaultCounterName,
  4205. IN LPDWORD pcchBufferSize
  4206. )
  4207. /*++
  4208. Routine Description:
  4209. Obtains the default performance counter from the specified object on
  4210. the specified machine.
  4211. Arguments:
  4212. IN DWORD dwDataSource
  4213. IN LPCWSTR szMachineName
  4214. NULL indicates the local machine, othewise this is the
  4215. name of the remote machine to query. If this machine is
  4216. not known to the PDH DLL, then it will be connected.
  4217. IN LPCWSTR szObjectName
  4218. a pointer to the buffer that contains the name of the object
  4219. on the machine to find the default counter for.
  4220. IN LPWSTR szDefaultCounterName
  4221. pointer to the buffer that will receive the default counter
  4222. name. This pointer can be NULL if the value of the DWORD
  4223. referenced by bcchBufferSize is 0.
  4224. IN LPDWORD pcchBufferSize
  4225. pointer to a DWORD containing the size of the buffer, in
  4226. characters, referenced by the szDefaultObjectName argument.
  4227. If the value of this DWORD is 0, then no data will be written
  4228. to the szDefaultObjectNameBuffer, however the required
  4229. buffer size will be returned in the DWORD referenced by
  4230. this pointer.
  4231. Return Value:
  4232. ERROR_SUCCESS if this function completes normally otherwise a PDH error.
  4233. PDH_INVALID_ARGUMENT a required argument is not correct or reserved
  4234. argument is not 0 or NULL.
  4235. PDH_MEMORY_ALLOCATION_FAILURE is returned when a required temporary
  4236. buffer could not be allocated.
  4237. PDH_INSUFFICIENT_BUFFER is returned when the buffer supplied is
  4238. not large enough for the available data.
  4239. PDH_CSTATUS_NO_COUNTERNAME is returned when the name string for the
  4240. default counter could not be found.
  4241. PDH_CSTATUS_NO_MACHINE is returned when the specified machine
  4242. is offline or unavailable.
  4243. PDH_CSTATUS_NO_OBJECT is returned when the specified object could
  4244. not be found on the specified computer.
  4245. PDH_CSTATUS_NO_COUNTER is returned when the default counter is not
  4246. found in the data buffer.
  4247. --*/
  4248. {
  4249. PPERF_MACHINE pMachine;
  4250. PERF_OBJECT_TYPE *pObjectDef;
  4251. PPERF_COUNTER_DEFINITION pCounterDef;
  4252. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  4253. LONG lDefault;
  4254. DWORD dwStringLen;
  4255. DWORD dwLocalBufferSize = 0;
  4256. LPWSTR szDefault;
  4257. LPWSTR szThisMachine = NULL;
  4258. DebugPrint((4, "PdhiGetDefaultPerfCounterW BEGIN\n"));
  4259. if ((szObjectName == NULL) ||
  4260. (pcchBufferSize == NULL)) {
  4261. pdhStatus = PDH_INVALID_ARGUMENT;
  4262. } else {
  4263. // test the access the arguments
  4264. __try {
  4265. if (szMachineName != NULL) {
  4266. if (*szMachineName == 0) {
  4267. pdhStatus = PDH_INVALID_ARGUMENT;
  4268. }
  4269. } // else NULL machine Name is OK
  4270. if (pdhStatus == ERROR_SUCCESS) {
  4271. if (szObjectName != NULL) {
  4272. if (*szObjectName == 0) {
  4273. pdhStatus = PDH_INVALID_ARGUMENT;
  4274. }
  4275. } else {
  4276. // Null Object is not allowed
  4277. pdhStatus = PDH_INVALID_ARGUMENT;
  4278. }
  4279. }
  4280. if (pdhStatus == ERROR_SUCCESS) {
  4281. dwLocalBufferSize = *pcchBufferSize;
  4282. if (dwLocalBufferSize > 0) {
  4283. // test both ends of the caller's buffer for
  4284. // write access
  4285. szDefaultCounterName[0] = 0;
  4286. szDefaultCounterName[dwLocalBufferSize -1] = 0;
  4287. } else {
  4288. // this is just a size request so the buffer will not be used
  4289. }
  4290. }
  4291. } __except (EXCEPTION_EXECUTE_HANDLER) {
  4292. pdhStatus = PDH_INVALID_ARGUMENT;
  4293. }
  4294. }
  4295. if (pdhStatus == ERROR_SUCCESS && szMachineName != NULL) {
  4296. DWORD dwMachineName = (* szMachineName == L'\\')
  4297. ? (lstrlenW(szMachineName) + 1)
  4298. : (lstrlenW(szMachineName) + 3);
  4299. dwMachineName *= sizeof(WCHAR);
  4300. szThisMachine = G_ALLOC(dwMachineName);
  4301. if (szThisMachine == NULL) {
  4302. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  4303. }
  4304. else if (* szMachineName == L'\\') {
  4305. lstrcpyW(szThisMachine, szMachineName);
  4306. }
  4307. else {
  4308. lstrcpyW(szThisMachine, cszDoubleBackSlash);
  4309. lstrcatW(szThisMachine, szMachineName);
  4310. }
  4311. }
  4312. if (pdhStatus == ERROR_SUCCESS) {
  4313. pdhStatus = WAIT_FOR_AND_LOCK_MUTEX (hPdhDataMutex);
  4314. }
  4315. if (pdhStatus == ERROR_SUCCESS) {
  4316. __try {
  4317. switch (dwDataSource) {
  4318. case DATA_SOURCE_REGISTRY:
  4319. pMachine = GetMachine ((LPWSTR)szThisMachine, 0);
  4320. if (pMachine == NULL) {
  4321. // unable to connect to machine so get pdhStatus
  4322. pdhStatus = GetLastError();
  4323. } else {
  4324. pdhStatus = pMachine->dwStatus;
  4325. }
  4326. if (pdhStatus == ERROR_SUCCESS) {
  4327. // get object pointer
  4328. pObjectDef = GetObjectDefByName (
  4329. pMachine->pSystemPerfData,
  4330. pMachine->dwLastPerfString,
  4331. pMachine->szPerfStrings,
  4332. szObjectName);
  4333. if (pObjectDef != NULL) {
  4334. // default counter reference is an index into the list
  4335. // of counter definition entries so walk down list of
  4336. // counters defs to find the default one
  4337. if (pObjectDef->DefaultCounter < (LONG)pObjectDef->NumCounters) {
  4338. // then the default index should be this buffer
  4339. lDefault = 0;
  4340. pCounterDef = FirstCounter (pObjectDef);
  4341. while ((lDefault < pObjectDef->DefaultCounter) &&
  4342. (lDefault < (LONG)pObjectDef->NumCounters)) {
  4343. pCounterDef = NextCounter (pCounterDef);
  4344. lDefault++;
  4345. }
  4346. lDefault = pCounterDef->CounterNameTitleIndex;
  4347. if ((lDefault > 0) && ((DWORD)lDefault < pMachine->dwLastPerfString)) {
  4348. // then there should be a string in the table
  4349. szDefault = (LPWSTR)PdhiLookupPerfNameByIndex (
  4350. pMachine, lDefault);
  4351. dwStringLen = lstrlenW (szDefault) + 1;
  4352. if (dwLocalBufferSize > 0) {
  4353. if (dwStringLen <= dwLocalBufferSize) {
  4354. lstrcpyW (szDefaultCounterName, szDefault);
  4355. pdhStatus = ERROR_SUCCESS;
  4356. } else {
  4357. pdhStatus = PDH_MORE_DATA;
  4358. }
  4359. }
  4360. else {
  4361. pdhStatus = PDH_MORE_DATA;
  4362. }
  4363. dwLocalBufferSize = dwStringLen;
  4364. } else {
  4365. // string index is not valid
  4366. dwLocalBufferSize = 0;
  4367. pdhStatus = PDH_CSTATUS_NO_COUNTER;
  4368. }
  4369. } else {
  4370. // the counter entry is not in the buffer
  4371. dwLocalBufferSize = 0;
  4372. pdhStatus = PDH_CSTATUS_NO_COUNTER;
  4373. }
  4374. } else {
  4375. // unable to find object
  4376. dwLocalBufferSize = 0;
  4377. pdhStatus = PDH_CSTATUS_NO_OBJECT;
  4378. }
  4379. pMachine->dwRefCount--;
  4380. RELEASE_MUTEX (pMachine->hMutex);
  4381. } // else pass pdhStatus value to caller
  4382. break;
  4383. case DATA_SOURCE_WBEM:
  4384. pdhStatus = PdhiGetDefaultWbemProperty (
  4385. szThisMachine,
  4386. szObjectName,
  4387. szDefaultCounterName,
  4388. &dwLocalBufferSize,
  4389. TRUE);
  4390. break;
  4391. case DATA_SOURCE_LOGFILE:
  4392. *szDefaultCounterName = 0;
  4393. dwLocalBufferSize = 0;
  4394. break;
  4395. default:
  4396. assert (FALSE);
  4397. }
  4398. } __except (EXCEPTION_EXECUTE_HANDLER) {
  4399. pdhStatus = PDH_INVALID_ARGUMENT;
  4400. }
  4401. RELEASE_MUTEX (hPdhDataMutex);
  4402. __try {
  4403. *pcchBufferSize = dwLocalBufferSize;
  4404. } __except (EXCEPTION_EXECUTE_HANDLER) {
  4405. pdhStatus = PDH_INVALID_ARGUMENT;
  4406. }
  4407. }
  4408. if (szThisMachine != NULL) G_FREE(szThisMachine);
  4409. DebugPrint((4, "PdhiGetDefaultPerfCounterW END status 0x%08X\n", pdhStatus));
  4410. return pdhStatus;
  4411. }
  4412. PDH_FUNCTION
  4413. PdhGetDefaultPerfCounterHW (
  4414. IN HLOG hDataSource,
  4415. IN LPCWSTR szMachineName,
  4416. IN LPCWSTR szObjectName,
  4417. IN LPWSTR szDefaultCounterName,
  4418. IN LPDWORD pcchBufferSize)
  4419. {
  4420. DWORD dwDataSourceType = 0;
  4421. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  4422. __try {
  4423. dwDataSourceType = DataSourceTypeH(hDataSource);
  4424. }
  4425. __except (EXCEPTION_EXECUTE_HANDLER) {
  4426. pdhStatus = PDH_INVALID_ARGUMENT;
  4427. }
  4428. if (pdhStatus == ERROR_SUCCESS) {
  4429. pdhStatus = PdhiGetDefaultPerfCounterW(dwDataSourceType,
  4430. szMachineName,
  4431. szObjectName,
  4432. szDefaultCounterName,
  4433. pcchBufferSize);
  4434. }
  4435. return pdhStatus;
  4436. }
  4437. PDH_FUNCTION
  4438. PdhGetDefaultPerfCounterW(
  4439. IN LPCWSTR szDataSource,
  4440. IN LPCWSTR szMachineName,
  4441. IN LPCWSTR szObjectName,
  4442. IN LPWSTR szDefaultCounterName,
  4443. IN LPDWORD pcchBufferSize)
  4444. {
  4445. DWORD dwDataSourceType = 0;
  4446. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  4447. __try {
  4448. if (szDataSource != NULL) {
  4449. if (* szDataSource == 0) {
  4450. pdhStatus = PDH_INVALID_ARGUMENT;
  4451. }
  4452. }
  4453. dwDataSourceType = DataSourceTypeW(szDataSource);
  4454. }
  4455. __except (EXCEPTION_EXECUTE_HANDLER) {
  4456. pdhStatus = PDH_INVALID_ARGUMENT;
  4457. }
  4458. if (pdhStatus == ERROR_SUCCESS) {
  4459. pdhStatus = PdhiGetDefaultPerfCounterW(dwDataSourceType,
  4460. szMachineName,
  4461. szObjectName,
  4462. szDefaultCounterName,
  4463. pcchBufferSize);
  4464. }
  4465. return pdhStatus;
  4466. }
  4467. PDH_FUNCTION
  4468. PdhiGetDefaultPerfCounterA (
  4469. IN DWORD dwDataSource,
  4470. IN LPCSTR szMachineName,
  4471. IN LPCSTR szObjectName,
  4472. IN LPSTR szDefaultCounterName,
  4473. IN LPDWORD pcchBufferSize
  4474. )
  4475. /*++
  4476. Routine Description:
  4477. Obtains the default performance counter from the specified object on
  4478. the specified machine.
  4479. Arguments:
  4480. IN DWORD dwDataSource
  4481. IN LPCSTR szMachineName
  4482. NULL indicates the local machine, othewise this is the
  4483. name of the remote machine to query. If this machine is
  4484. not known to the PDH DLL, then it will be connected.
  4485. IN LPCSTR szObjectName
  4486. a pointer to the buffer that contains the name of the object
  4487. on the machine to find the default counter for.
  4488. IN LPSTR szDefaultCounterName
  4489. pointer to the buffer that will receive the default counter
  4490. name. This pointer can be NULL if the value of the DWORD
  4491. referenced by bcchBufferSize is 0.
  4492. IN LPDWORD pcchBufferSize
  4493. pointer to a DWORD containing the size of the buffer, in
  4494. characters, referenced by the szDefaultObjectName argument.
  4495. If the value of this DWORD is 0, then no data will be written
  4496. to the szDefaultObjectNameBuffer, however the required
  4497. buffer size will be returned in the DWORD referenced by
  4498. this pointer.
  4499. Return Value:
  4500. ERROR_SUCCESS if this function completes normally otherwise a PDH error.
  4501. PDH_INVALID_ARGUMENT a required argument is not correct or reserved
  4502. argument is not 0 or NULL.
  4503. PDH_MEMORY_ALLOCATION_FAILURE is returned when a required temporary
  4504. buffer could not be allocated.
  4505. PDH_INSUFFICIENT_BUFFER is returned when the buffer supplied is
  4506. not large enough for the available data.
  4507. PDH_CSTATUS_NO_COUNTERNAME is returned when the name string for the
  4508. default counter could not be found.
  4509. PDH_CSTATUS_NO_MACHINE is returned when the specified machine
  4510. is offline or unavailable.
  4511. PDH_CSTATUS_NO_OBJECT is returned when the specified object could
  4512. not be found on the specified computer.
  4513. PDH_CSTATUS_NO_COUNTER is returned when the default counter is not
  4514. found in the data buffer.
  4515. --*/
  4516. {
  4517. LPWSTR szWideObject = NULL;
  4518. LPWSTR szWideName = NULL;
  4519. DWORD dwNameLength;
  4520. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  4521. PPERF_MACHINE pMachine = NULL;
  4522. PPERF_OBJECT_TYPE pObjectDef = NULL;
  4523. PPERF_COUNTER_DEFINITION pCounterDef;
  4524. LONG lDefault;
  4525. DWORD dwStringLen;
  4526. DWORD dwLocalBufferSize = 0;
  4527. LPWSTR szDefault;
  4528. DebugPrint((4, "PdhGetDefaultPerfCounterA BEGIN\n"));
  4529. if ((szObjectName == NULL) ||
  4530. (pcchBufferSize == NULL)) {
  4531. pdhStatus = PDH_INVALID_ARGUMENT;
  4532. } else {
  4533. // test the access the arguments
  4534. __try {
  4535. if (szMachineName != NULL) {
  4536. if (*szMachineName == 0) {
  4537. pdhStatus = PDH_INVALID_ARGUMENT;
  4538. }
  4539. } // else NULL machine Name is OK
  4540. if (pdhStatus == ERROR_SUCCESS) {
  4541. if (szObjectName != NULL) {
  4542. if (*szObjectName == 0) {
  4543. pdhStatus = PDH_INVALID_ARGUMENT;
  4544. }
  4545. } else {
  4546. // null objects are not allowed
  4547. pdhStatus = PDH_INVALID_ARGUMENT;
  4548. }
  4549. }
  4550. if (pdhStatus == ERROR_SUCCESS) {
  4551. dwLocalBufferSize = *pcchBufferSize;
  4552. if (dwLocalBufferSize > 0) {
  4553. // test both ends of the caller's buffer for
  4554. // write access
  4555. szDefaultCounterName[0] = 0;
  4556. szDefaultCounterName[dwLocalBufferSize -1] = 0;
  4557. } else {
  4558. // this is just a size request so the buffer will not be used
  4559. }
  4560. }
  4561. } __except (EXCEPTION_EXECUTE_HANDLER) {
  4562. pdhStatus = PDH_INVALID_ARGUMENT;
  4563. }
  4564. }
  4565. if (pdhStatus == ERROR_SUCCESS && szMachineName != NULL) {
  4566. dwNameLength = (* szMachineName == '\\')
  4567. ? (lstrlenA(szMachineName) + 1)
  4568. : (lstrlenA(szMachineName) + 3);
  4569. szWideName = G_ALLOC (dwNameLength * sizeof(WCHAR));
  4570. if (szWideName == NULL) {
  4571. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  4572. }
  4573. else if (* szMachineName == '\\') {
  4574. MultiByteToWideChar(_getmbcp(),
  4575. 0,
  4576. szMachineName,
  4577. lstrlenA(szMachineName),
  4578. (LPWSTR) szWideName,
  4579. dwNameLength);
  4580. }
  4581. else {
  4582. LPWSTR szThisMachine = szWideName + 2;
  4583. lstrcpyW(szWideName, cszDoubleBackSlash);
  4584. MultiByteToWideChar(_getmbcp(),
  4585. 0,
  4586. szMachineName,
  4587. lstrlenA(szMachineName),
  4588. (LPWSTR) szThisMachine,
  4589. dwNameLength - 2);
  4590. }
  4591. }
  4592. if (pdhStatus == ERROR_SUCCESS) {
  4593. pdhStatus = WAIT_FOR_AND_LOCK_MUTEX (hPdhDataMutex);
  4594. }
  4595. if (pdhStatus == ERROR_SUCCESS) {
  4596. __try {
  4597. switch (dwDataSource) {
  4598. case DATA_SOURCE_REGISTRY:
  4599. if (pdhStatus == ERROR_SUCCESS) {
  4600. pMachine = GetMachine (szWideName, 0);
  4601. if (pMachine == NULL) {
  4602. // unable to connect to machine so get pdhStatus
  4603. pdhStatus = GetLastError();
  4604. } else {
  4605. pdhStatus = ERROR_SUCCESS;
  4606. }
  4607. }
  4608. if (szWideName != NULL) {
  4609. G_FREE (szWideName);
  4610. szWideName = NULL;
  4611. }
  4612. if ((pdhStatus == ERROR_SUCCESS) && (pMachine != NULL)) {
  4613. // get selected object
  4614. dwNameLength = lstrlenA (szObjectName);
  4615. szWideName = G_ALLOC ((dwNameLength+1) * sizeof(WCHAR));
  4616. if (szWideName == NULL) {
  4617. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  4618. } else {
  4619. MultiByteToWideChar(_getmbcp(),
  4620. 0,
  4621. szObjectName,
  4622. dwNameLength,
  4623. szWideName,
  4624. dwNameLength + 1);
  4625. pObjectDef = GetObjectDefByName (
  4626. pMachine->pSystemPerfData,
  4627. pMachine->dwLastPerfString,
  4628. pMachine->szPerfStrings,
  4629. szWideName);
  4630. G_FREE (szWideName);
  4631. }
  4632. if (pObjectDef != NULL) {
  4633. // default counter reference is an index into the list
  4634. // of counter definition entries so walk down list of
  4635. // counters defs to find the default one
  4636. if (pObjectDef->DefaultCounter < (LONG)pObjectDef->NumCounters) {
  4637. // then the default index should be this buffer
  4638. lDefault = 0;
  4639. pCounterDef = FirstCounter (pObjectDef);
  4640. while ((lDefault < pObjectDef->DefaultCounter) &&
  4641. (lDefault < (LONG)pObjectDef->NumCounters)) {
  4642. pCounterDef = NextCounter (pCounterDef);
  4643. lDefault++;
  4644. }
  4645. lDefault = pCounterDef->CounterNameTitleIndex;
  4646. if ((lDefault > 0) && ((DWORD)lDefault < pMachine->dwLastPerfString)) {
  4647. // then there should be a string in the table
  4648. szDefault = (LPWSTR)PdhiLookupPerfNameByIndex (
  4649. pMachine, lDefault);
  4650. dwStringLen = dwLocalBufferSize;
  4651. pdhStatus = PdhiConvertUnicodeToAnsi(_getmbcp(),
  4652. szDefault,
  4653. szDefaultCounterName,
  4654. & dwStringLen);
  4655. dwLocalBufferSize = dwStringLen;
  4656. } else {
  4657. // string index is not valid
  4658. dwLocalBufferSize = 0;
  4659. pdhStatus = PDH_CSTATUS_NO_COUNTER;
  4660. }
  4661. } else {
  4662. // the counter entry is not in the buffer
  4663. dwLocalBufferSize = 0;
  4664. pdhStatus = PDH_CSTATUS_NO_COUNTER;
  4665. }
  4666. } else {
  4667. // unable to find object
  4668. dwLocalBufferSize = 0;
  4669. pdhStatus = PDH_CSTATUS_NO_OBJECT;
  4670. }
  4671. pMachine->dwRefCount--;
  4672. RELEASE_MUTEX (pMachine->hMutex);
  4673. } else {
  4674. // unable to find machine
  4675. pdhStatus = GetLastError();
  4676. }
  4677. break;
  4678. case DATA_SOURCE_WBEM:
  4679. case DATA_SOURCE_LOGFILE:
  4680. if ((pdhStatus == ERROR_SUCCESS) && (dwDataSource == DATA_SOURCE_WBEM)) {
  4681. dwNameLength = lstrlenA (szObjectName);
  4682. szWideObject = G_ALLOC ((dwNameLength + 1) * sizeof(WCHAR));
  4683. if (szWideObject == NULL) {
  4684. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  4685. } else {
  4686. MultiByteToWideChar(_getmbcp(),
  4687. 0,
  4688. szObjectName,
  4689. dwNameLength,
  4690. szWideObject,
  4691. dwNameLength + 1);
  4692. }
  4693. if (pdhStatus == ERROR_SUCCESS) {
  4694. pdhStatus = PdhiGetDefaultWbemProperty (
  4695. szWideName,
  4696. szWideObject,
  4697. (LPVOID)szDefaultCounterName,
  4698. &dwLocalBufferSize,
  4699. FALSE); // ANSI function
  4700. }
  4701. } else {
  4702. //log files don't support this (for now)
  4703. dwLocalBufferSize = 0;
  4704. *szDefaultCounterName = 0;
  4705. }
  4706. if (szWideName != NULL) G_FREE (szWideName);
  4707. if (szWideObject != NULL) G_FREE (szWideObject);
  4708. break;
  4709. default:
  4710. assert (FALSE);
  4711. }
  4712. } __except (EXCEPTION_EXECUTE_HANDLER) {
  4713. pdhStatus = PDH_INVALID_ARGUMENT;
  4714. }
  4715. RELEASE_MUTEX (hPdhDataMutex);
  4716. __try {
  4717. *pcchBufferSize = dwLocalBufferSize;
  4718. } __except (EXCEPTION_EXECUTE_HANDLER) {
  4719. pdhStatus = PDH_INVALID_ARGUMENT;
  4720. }
  4721. }
  4722. DebugPrint((4, "PdhGetDefaultPerfCounterA END status 0x%08X\n", pdhStatus));
  4723. return pdhStatus;
  4724. }
  4725. PDH_FUNCTION
  4726. PdhGetDefaultPerfCounterHA (
  4727. IN HLOG hDataSource,
  4728. IN LPCSTR szMachineName,
  4729. IN LPCSTR szObjectName,
  4730. IN LPSTR szDefaultCounterName,
  4731. IN LPDWORD pcchBufferSize)
  4732. {
  4733. DWORD dwDataSourceType = 0;
  4734. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  4735. __try {
  4736. dwDataSourceType = DataSourceTypeH(hDataSource);
  4737. }
  4738. __except (EXCEPTION_EXECUTE_HANDLER) {
  4739. pdhStatus = PDH_INVALID_ARGUMENT;
  4740. }
  4741. if (pdhStatus == ERROR_SUCCESS) {
  4742. pdhStatus = PdhiGetDefaultPerfCounterA(dwDataSourceType,
  4743. szMachineName,
  4744. szObjectName,
  4745. szDefaultCounterName,
  4746. pcchBufferSize);
  4747. }
  4748. return pdhStatus;
  4749. }
  4750. PDH_FUNCTION
  4751. PdhGetDefaultPerfCounterA(
  4752. IN LPCSTR szDataSource,
  4753. IN LPCSTR szMachineName,
  4754. IN LPCSTR szObjectName,
  4755. IN LPSTR szDefaultCounterName,
  4756. IN LPDWORD pcchBufferSize)
  4757. {
  4758. DWORD dwDataSourceType = 0;
  4759. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  4760. __try {
  4761. if (szDataSource != NULL) {
  4762. if (* szDataSource == 0) {
  4763. pdhStatus = PDH_INVALID_ARGUMENT;
  4764. }
  4765. }
  4766. dwDataSourceType = DataSourceTypeA(szDataSource);
  4767. }
  4768. __except (EXCEPTION_EXECUTE_HANDLER) {
  4769. pdhStatus = PDH_INVALID_ARGUMENT;
  4770. }
  4771. if (pdhStatus == ERROR_SUCCESS) {
  4772. pdhStatus = PdhiGetDefaultPerfCounterA(dwDataSourceType,
  4773. szMachineName,
  4774. szObjectName,
  4775. szDefaultCounterName,
  4776. pcchBufferSize);
  4777. }
  4778. return pdhStatus;
  4779. }
  4780. PDH_FUNCTION
  4781. PdhBrowseCountersHW (
  4782. IN PPDH_BROWSE_DLG_CONFIG_HW pBrowseDlgData)
  4783. {
  4784. PDHI_BROWSE_DLG_INFO pInfo;
  4785. LPWSTR szResource;
  4786. int nDlgReturn;
  4787. DWORD dwReturn = ERROR_SUCCESS;
  4788. pInfo.pWideStruct = (PPDH_BROWSE_DLG_CONFIG_W) pBrowseDlgData;
  4789. pInfo.pAnsiStruct = NULL;
  4790. if (pBrowseDlgData != NULL) {
  4791. __try {
  4792. // copy the data source since it wide characters already
  4793. pInfo.hDataSource = pBrowseDlgData->hDataSource;
  4794. szResource = MAKEINTRESOURCEW (
  4795. pBrowseDlgData->bShowObjectBrowser ?
  4796. IDD_BROWSE_OBJECTS :
  4797. pBrowseDlgData->bSingleCounterPerDialog ?
  4798. IDD_BROWSE_COUNTERS_SIM :
  4799. IDD_BROWSE_COUNTERS_EXT);
  4800. nDlgReturn = (int)DialogBoxParamW (ThisDLLHandle,
  4801. szResource,
  4802. pBrowseDlgData->hWndOwner,
  4803. BrowseCounterDlgProc,
  4804. (LPARAM)&pInfo);
  4805. if (nDlgReturn == -1) {
  4806. dwReturn = GetLastError();
  4807. } else {
  4808. dwReturn = (nDlgReturn == IDOK)
  4809. ? ERROR_SUCCESS : PDH_DIALOG_CANCELLED;
  4810. }
  4811. } __except (EXCEPTION_EXECUTE_HANDLER) {
  4812. dwReturn = PDH_INVALID_ARGUMENT;
  4813. }
  4814. } else {
  4815. dwReturn = PDH_INVALID_ARGUMENT;
  4816. }
  4817. return dwReturn;
  4818. }
  4819. PDH_FUNCTION
  4820. PdhBrowseCountersHA (
  4821. IN PPDH_BROWSE_DLG_CONFIG_HA pBrowseDlgData)
  4822. {
  4823. PDHI_BROWSE_DLG_INFO pInfo;
  4824. LPWSTR szResource;
  4825. int nDlgReturn;
  4826. DWORD dwReturn = ERROR_SUCCESS;
  4827. pInfo.pAnsiStruct = (PPDH_BROWSE_DLG_CONFIG_A) pBrowseDlgData;
  4828. pInfo.pWideStruct = NULL;
  4829. if (pBrowseDlgData != NULL) {
  4830. __try {
  4831. // copy the data source since it wide characters already
  4832. pInfo.hDataSource = pBrowseDlgData->hDataSource;
  4833. szResource = MAKEINTRESOURCEW (
  4834. pBrowseDlgData->bShowObjectBrowser ?
  4835. IDD_BROWSE_OBJECTS :
  4836. pBrowseDlgData->bSingleCounterPerDialog ?
  4837. IDD_BROWSE_COUNTERS_SIM :
  4838. IDD_BROWSE_COUNTERS_EXT);
  4839. nDlgReturn = (int)DialogBoxParamW (ThisDLLHandle,
  4840. szResource,
  4841. pBrowseDlgData->hWndOwner,
  4842. BrowseCounterDlgProc,
  4843. (LPARAM)&pInfo);
  4844. if (nDlgReturn == -1) {
  4845. dwReturn = GetLastError();
  4846. } else {
  4847. dwReturn = (nDlgReturn == IDOK)
  4848. ? ERROR_SUCCESS : PDH_DIALOG_CANCELLED;
  4849. }
  4850. } __except (EXCEPTION_EXECUTE_HANDLER) {
  4851. dwReturn = PDH_INVALID_ARGUMENT;
  4852. }
  4853. } else {
  4854. dwReturn = PDH_INVALID_ARGUMENT;
  4855. }
  4856. return dwReturn;
  4857. }
  4858. PDH_FUNCTION
  4859. PdhBrowseCountersW (
  4860. IN PPDH_BROWSE_DLG_CONFIG_W pBrowseDlgData
  4861. )
  4862. /*++
  4863. Routine Description:
  4864. Arguments:
  4865. Return Value:
  4866. --*/
  4867. {
  4868. PDHI_BROWSE_DLG_INFO pInfo;
  4869. LPWSTR szResource;
  4870. int nDlgReturn;
  4871. DWORD dwReturn = ERROR_SUCCESS;
  4872. pInfo.pWideStruct = pBrowseDlgData;
  4873. pInfo.pAnsiStruct = NULL;
  4874. if (pBrowseDlgData != NULL) {
  4875. __try {
  4876. DWORD dwDataSource = DataSourceTypeW (pBrowseDlgData->szDataSource);
  4877. if (dwDataSource == DATA_SOURCE_WBEM) {
  4878. pInfo.hDataSource = H_WBEM_DATASOURCE;
  4879. }
  4880. else if (dwDataSource == DATA_SOURCE_LOGFILE) {
  4881. DWORD dwLogType = 0;
  4882. dwReturn = PdhOpenLogW(
  4883. pBrowseDlgData->szDataSource,
  4884. PDH_LOG_READ_ACCESS | PDH_LOG_OPEN_EXISTING,
  4885. & dwLogType,
  4886. NULL,
  4887. 0,
  4888. NULL,
  4889. & pInfo.hDataSource);
  4890. }
  4891. else {
  4892. pInfo.hDataSource = H_REALTIME_DATASOURCE;
  4893. }
  4894. if (dwReturn == ERROR_SUCCESS) {
  4895. szResource = MAKEINTRESOURCEW (
  4896. pBrowseDlgData->bShowObjectBrowser ?
  4897. IDD_BROWSE_OBJECTS :
  4898. pBrowseDlgData->bSingleCounterPerDialog ?
  4899. IDD_BROWSE_COUNTERS_SIM :
  4900. IDD_BROWSE_COUNTERS_EXT);
  4901. nDlgReturn = (int)DialogBoxParamW (ThisDLLHandle,
  4902. szResource,
  4903. pBrowseDlgData->hWndOwner,
  4904. BrowseCounterDlgProc,
  4905. (LPARAM)&pInfo);
  4906. if (nDlgReturn == -1) {
  4907. dwReturn = GetLastError();
  4908. } else {
  4909. dwReturn = nDlgReturn == IDOK ? ERROR_SUCCESS : PDH_DIALOG_CANCELLED;
  4910. }
  4911. }
  4912. } __except (EXCEPTION_EXECUTE_HANDLER) {
  4913. dwReturn = PDH_INVALID_ARGUMENT;
  4914. }
  4915. } else {
  4916. dwReturn = PDH_INVALID_ARGUMENT;
  4917. }
  4918. return dwReturn;
  4919. }
  4920. PDH_FUNCTION
  4921. PdhBrowseCountersA (
  4922. IN PPDH_BROWSE_DLG_CONFIG_A pBrowseDlgData
  4923. )
  4924. /*++
  4925. Routine Description:
  4926. Arguments:
  4927. Return Value:
  4928. --*/
  4929. {
  4930. PDHI_BROWSE_DLG_INFO pInfo;
  4931. LPWSTR szResource;
  4932. int nDlgReturn;
  4933. DWORD dwReturn = ERROR_SUCCESS;
  4934. pInfo.pAnsiStruct = pBrowseDlgData;
  4935. pInfo.pWideStruct = NULL;
  4936. if (pBrowseDlgData != NULL) {
  4937. __try {
  4938. DWORD dwDataSource = DataSourceTypeA(pBrowseDlgData->szDataSource);
  4939. if (dwDataSource == DATA_SOURCE_WBEM) {
  4940. pInfo.hDataSource = H_WBEM_DATASOURCE;
  4941. }
  4942. else if (dwDataSource == DATA_SOURCE_LOGFILE) {
  4943. DWORD dwLogType = 0;
  4944. dwReturn = PdhOpenLogA(
  4945. pBrowseDlgData->szDataSource,
  4946. PDH_LOG_READ_ACCESS | PDH_LOG_OPEN_EXISTING,
  4947. & dwLogType,
  4948. NULL,
  4949. 0,
  4950. NULL,
  4951. & pInfo.hDataSource);
  4952. }
  4953. else {
  4954. pInfo.hDataSource = H_REALTIME_DATASOURCE;
  4955. }
  4956. if (dwReturn == ERROR_SUCCESS) {
  4957. szResource = MAKEINTRESOURCEW (
  4958. pBrowseDlgData->bShowObjectBrowser ?
  4959. IDD_BROWSE_OBJECTS :
  4960. pBrowseDlgData->bSingleCounterPerDialog ?
  4961. IDD_BROWSE_COUNTERS_SIM :
  4962. IDD_BROWSE_COUNTERS_EXT);
  4963. nDlgReturn = (int)DialogBoxParamW (ThisDLLHandle,
  4964. szResource,
  4965. pBrowseDlgData->hWndOwner,
  4966. BrowseCounterDlgProc,
  4967. (LPARAM)&pInfo);
  4968. if (nDlgReturn == -1) {
  4969. dwReturn = GetLastError();
  4970. } else {
  4971. dwReturn = nDlgReturn == IDOK ? ERROR_SUCCESS : PDH_DIALOG_CANCELLED;
  4972. }
  4973. }
  4974. } __except (EXCEPTION_EXECUTE_HANDLER) {
  4975. dwReturn = PDH_INVALID_ARGUMENT;
  4976. }
  4977. } else {
  4978. dwReturn = PDH_INVALID_ARGUMENT;
  4979. }
  4980. return dwReturn;
  4981. }
  4982. LPWSTR
  4983. PdhiGetExplainText (
  4984. IN LPCWSTR szMachineName,
  4985. IN LPCWSTR szObjectName,
  4986. IN LPCWSTR szCounterName
  4987. )
  4988. {
  4989. PPERF_MACHINE pMachine;
  4990. PERF_OBJECT_TYPE *pObjectDef;
  4991. PERF_COUNTER_DEFINITION *pCounterDef;
  4992. LPWSTR szReturnString = NULL;
  4993. pMachine = GetMachine ((LPWSTR)szMachineName, 0);
  4994. if (pMachine != NULL) {
  4995. // make sure the machine connection is valid
  4996. if (pMachine->dwStatus == ERROR_SUCCESS) {
  4997. pObjectDef = GetObjectDefByName (
  4998. pMachine->pSystemPerfData,
  4999. pMachine->dwLastPerfString,
  5000. pMachine->szPerfStrings,
  5001. szObjectName);
  5002. if (pObjectDef != NULL) {
  5003. if (szCounterName != NULL) {
  5004. pCounterDef = GetCounterDefByName (
  5005. pObjectDef,
  5006. pMachine->dwLastPerfString,
  5007. pMachine->szPerfStrings,
  5008. (LPWSTR)szCounterName);
  5009. if ((pCounterDef != NULL) &&
  5010. (pCounterDef->CounterHelpTitleIndex <= pMachine->dwLastPerfString)) {
  5011. // return string from array
  5012. szReturnString = pMachine->szPerfStrings[pCounterDef->CounterHelpTitleIndex];
  5013. } else {
  5014. // counter not found
  5015. }
  5016. }
  5017. else if (pObjectDef->ObjectHelpTitleIndex <= pMachine->dwLastPerfString) {
  5018. szReturnString = pMachine->szPerfStrings[pObjectDef->ObjectHelpTitleIndex];
  5019. }
  5020. } else {
  5021. // object not found
  5022. }
  5023. } else {
  5024. // machine not accessible
  5025. }
  5026. pMachine->dwRefCount--;
  5027. RELEASE_MUTEX (pMachine->hMutex);
  5028. } else {
  5029. // machine not found
  5030. }
  5031. return szReturnString;
  5032. }
  5033. BOOL
  5034. IsWbemDataSource (
  5035. IN LPCWSTR szDataSource
  5036. )
  5037. {
  5038. BOOL bReturn = FALSE;
  5039. __try {
  5040. if (DataSourceTypeW(szDataSource) == DATA_SOURCE_WBEM)
  5041. bReturn = TRUE;
  5042. } __except (EXCEPTION_EXECUTE_HANDLER) {
  5043. SetLastError (GetExceptionCode());
  5044. }
  5045. return bReturn;
  5046. }