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.

1026 lines
38 KiB

  1. /*++
  2. Copyright (C) 1995-1999 Microsoft Corporation
  3. Module Name:
  4. wildcard.c
  5. Abstract:
  6. counter name wild card expansion functions
  7. --*/
  8. #include <windows.h>
  9. #include <winperf.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <stdio.h>
  13. #include <tchar.h>
  14. #include "mbctype.h"
  15. #include "pdhidef.h"
  16. #include "pdhdlgs.h"
  17. #include "pdh.h"
  18. #include "pdhui.h"
  19. #include "perftype.h"
  20. #include "perfdata.h"
  21. #pragma warning ( disable : 4213)
  22. #define PDHI_COUNTER_PATH_BUFFER_SIZE (DWORD)(sizeof(PDHI_COUNTER_PATH) + (5 * MAX_PATH))
  23. DWORD DataSourceTypeA(LPCSTR szDataSource);
  24. DWORD DataSourceTypeW(LPCWSTR szDataSource);
  25. STATIC_BOOL
  26. WildStringMatchW (
  27. LPWSTR szWildString,
  28. LPWSTR szMatchString
  29. )
  30. {
  31. BOOL bReturn;
  32. if (szWildString == NULL) {
  33. // every thing matches a null wild card string
  34. bReturn = TRUE;
  35. } else if (*szWildString == SPLAT_L) {
  36. // every thing matches this
  37. bReturn = TRUE;
  38. } else {
  39. // for now just do a case insensitive comparison.
  40. // later, this can be made more selective to support
  41. // partial wildcard string matches
  42. bReturn = (BOOL)(lstrcmpiW(szWildString, szMatchString) == 0);
  43. }
  44. return bReturn;
  45. }
  46. STATIC_PDH_FUNCTION
  47. PdhiExpandWildcardPath (
  48. IN HLOG hDataSource,
  49. IN LPCWSTR szWildCardPath,
  50. IN LPVOID pExpandedPathList,
  51. IN LPDWORD pcchPathListLength,
  52. IN DWORD dwFlags,
  53. IN BOOL bUnicode
  54. )
  55. /*
  56. Flags:
  57. NoExpandCounters
  58. NoExpandInstances
  59. CheckCostlyCounters
  60. */
  61. {
  62. PDH_COUNTER_PATH_ELEMENTS_W pPathElem;
  63. PPDHI_COUNTER_PATH pWildCounterPath = NULL;
  64. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  65. DWORD dwDetailLevel = PERF_DETAIL_WIZARD;
  66. DWORD dwBufferRemaining = 0;
  67. LPVOID szNextUserString = NULL;
  68. DWORD dwSize;
  69. DWORD dwSizeReturned = 0;
  70. DWORD dwRetry;
  71. LPWSTR mszObjectList = NULL;
  72. DWORD dwObjectListSize = 0;
  73. LPWSTR szThisObject;
  74. LPWSTR mszCounterList = NULL;
  75. DWORD dwCounterListSize = 0;
  76. LPWSTR szThisCounter;
  77. LPWSTR mszInstanceList = NULL;
  78. DWORD dwInstanceListSize = 0;
  79. LPWSTR szThisInstance;
  80. WCHAR szTempPathBuffer[MAX_PATH * 2];
  81. DWORD szTempPathBufferSize;
  82. BOOL bMoreData = FALSE;
  83. BOOL bNoInstances = FALSE;\
  84. LIST_ENTRY InstList;
  85. PLIST_ENTRY pHead;
  86. PLIST_ENTRY pNext;
  87. PPDHI_INSTANCE pInst;
  88. // allocate buffers
  89. pWildCounterPath = G_ALLOC (PDHI_COUNTER_PATH_BUFFER_SIZE);
  90. if (pWildCounterPath == NULL) {
  91. // unable to allocate memory so bail out
  92. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  93. } else {
  94. __try {
  95. dwBufferRemaining = *pcchPathListLength;
  96. szNextUserString = pExpandedPathList;
  97. } __except (EXCEPTION_EXECUTE_HANDLER) {
  98. pdhStatus = PDH_INVALID_ARGUMENT;
  99. }
  100. }
  101. if (pdhStatus == ERROR_SUCCESS) {
  102. // Parse wild card Path
  103. dwSize = (DWORD)G_SIZE (pWildCounterPath);
  104. if (ParseFullPathNameW (szWildCardPath, &dwSize, pWildCounterPath, FALSE)) {
  105. if (pWildCounterPath->szObjectName == NULL) {
  106. pdhStatus = PDH_INVALID_PATH;
  107. } else if (*pWildCounterPath->szObjectName == SPLAT_L) {
  108. //then the object is wild so get the list
  109. // of objects supported by this machine
  110. dwObjectListSize = 2048; // starting buffer size
  111. dwRetry = 10;
  112. do {
  113. if (mszObjectList != NULL) G_FREE(mszObjectList);
  114. mszObjectList = G_ALLOC (dwObjectListSize * sizeof(WCHAR));
  115. if (mszObjectList != NULL) {
  116. pdhStatus = PdhEnumObjectsHW (
  117. hDataSource,
  118. pWildCounterPath->szMachineName,
  119. mszObjectList,
  120. &dwObjectListSize,
  121. dwDetailLevel,
  122. TRUE);
  123. dwRetry--;
  124. } else {
  125. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  126. }
  127. } while ( (dwRetry)
  128. && ( pdhStatus == PDH_MORE_DATA
  129. || pdhStatus == PDH_INSUFFICIENT_BUFFER));
  130. } else {
  131. dwObjectListSize = lstrlenW(pWildCounterPath->szObjectName) + 2;
  132. mszObjectList = G_ALLOC(dwObjectListSize * sizeof (WCHAR));
  133. if (mszObjectList != NULL) {
  134. lstrcpyW (mszObjectList, pWildCounterPath->szObjectName);
  135. // add the MSZ terminator
  136. mszObjectList[dwObjectListSize-1] = 0;
  137. pdhStatus = ERROR_SUCCESS;
  138. } else {
  139. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  140. }
  141. }
  142. } else {
  143. pdhStatus = PDH_INVALID_PATH;
  144. }
  145. }
  146. if (pdhStatus == ERROR_SUCCESS) {
  147. pPathElem.szMachineName = pWildCounterPath->szMachineName;
  148. // for each object
  149. for (szThisObject = mszObjectList;
  150. *szThisObject != 0;
  151. szThisObject += lstrlenW(szThisObject) + 1) {
  152. dwCounterListSize = 8192; // starting buffer size
  153. dwInstanceListSize = 16384; // starting buffer size
  154. dwRetry = 10;
  155. do {
  156. if (mszCounterList != NULL) G_FREE(mszCounterList);
  157. if (mszInstanceList != NULL) G_FREE(mszInstanceList);
  158. mszCounterList = G_ALLOC ((dwCounterListSize * sizeof(WCHAR)));
  159. if (mszCounterList != NULL) {
  160. mszInstanceList = G_ALLOC (dwInstanceListSize * sizeof(WCHAR));
  161. if (mszInstanceList != NULL) {
  162. pdhStatus = PdhEnumObjectItemsHW (
  163. hDataSource,
  164. pWildCounterPath->szMachineName,
  165. szThisObject,
  166. mszCounterList,
  167. &dwCounterListSize,
  168. mszInstanceList,
  169. &dwInstanceListSize,
  170. dwDetailLevel,
  171. 0);
  172. dwRetry--;
  173. } else {
  174. G_FREE (mszCounterList);
  175. mszCounterList = NULL;
  176. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  177. }
  178. } else {
  179. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  180. }
  181. } while ( (dwRetry)
  182. && ( pdhStatus == PDH_MORE_DATA
  183. || pdhStatus == PDH_INSUFFICIENT_BUFFER));
  184. pPathElem.szObjectName = szThisObject;
  185. if (pdhStatus == ERROR_SUCCESS) {
  186. if (pWildCounterPath->szCounterName == NULL) {
  187. pdhStatus = PDH_INVALID_PATH;
  188. } else if ((*pWildCounterPath->szCounterName != SPLAT_L) || (dwFlags & PDH_NOEXPANDCOUNTERS)) {
  189. if (mszCounterList != NULL) G_FREE(mszCounterList);
  190. dwCounterListSize = lstrlenW(pWildCounterPath->szCounterName) + 2;
  191. mszCounterList = G_ALLOC (dwCounterListSize * sizeof(WCHAR));
  192. if (mszCounterList != NULL) {
  193. lstrcpyW (mszCounterList, pWildCounterPath->szCounterName);
  194. mszCounterList[dwCounterListSize-1] = 0;
  195. } else {
  196. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  197. }
  198. } else {
  199. // enum wild counters
  200. }
  201. if ((pWildCounterPath->szInstanceName == NULL) && (pdhStatus == ERROR_SUCCESS)){
  202. bNoInstances = TRUE;
  203. dwInstanceListSize = 2;
  204. mszInstanceList = G_ALLOC (dwInstanceListSize * sizeof(WCHAR));
  205. if (mszInstanceList != NULL) {
  206. mszInstanceList [0] =0;
  207. mszInstanceList [dwInstanceListSize-1] = 0;
  208. } else {
  209. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  210. }
  211. } else if ((*pWildCounterPath->szInstanceName != SPLAT_L) || (dwFlags & PDH_NOEXPANDINSTANCES)) {
  212. if (mszInstanceList != NULL) G_FREE(mszInstanceList);
  213. dwInstanceListSize = lstrlenW(pWildCounterPath->szInstanceName) + 2;
  214. mszInstanceList = G_ALLOC (dwInstanceListSize * sizeof(WCHAR));
  215. if (mszInstanceList != NULL) {
  216. lstrcpyW (mszInstanceList, pWildCounterPath->szInstanceName);
  217. mszInstanceList [dwInstanceListSize-1] = 0;
  218. } else {
  219. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  220. }
  221. } else {
  222. // enum wild instance
  223. }
  224. }
  225. if (mszInstanceList != NULL) {
  226. InitializeListHead(& InstList);
  227. szThisInstance = mszInstanceList;
  228. do {
  229. PdhiFindInstance(& InstList, szThisInstance, TRUE, &pInst);
  230. szThisInstance += lstrlenW(szThisInstance) + 1;
  231. } while (* szThisInstance != 0);
  232. szThisInstance = mszInstanceList;
  233. do {
  234. if (bNoInstances) {
  235. pPathElem.szInstanceName = NULL;
  236. } else {
  237. pPathElem.szInstanceName = szThisInstance;
  238. }
  239. pPathElem.szParentInstance = NULL; // included in the instance name
  240. pInst = NULL;
  241. PdhiFindInstance(
  242. & InstList, szThisInstance, FALSE, & pInst);
  243. if (pInst == NULL || pInst->dwTotal == 1
  244. || pInst->dwCount <= 1) {
  245. pPathElem.dwInstanceIndex = (DWORD) -1; // included in the instance name
  246. }
  247. else {
  248. pInst->dwCount --;
  249. pPathElem.dwInstanceIndex = pInst->dwCount;
  250. }
  251. for (szThisCounter = mszCounterList;
  252. *szThisCounter != 0;
  253. szThisCounter += lstrlenW(szThisCounter) +1) {
  254. pPathElem.szCounterName = szThisCounter;
  255. //make path string and add to list if it will fit
  256. szTempPathBufferSize = sizeof (szTempPathBuffer) / sizeof (szTempPathBuffer[0]);
  257. pdhStatus = PdhMakeCounterPathW (
  258. &pPathElem,
  259. szTempPathBuffer,
  260. &szTempPathBufferSize,
  261. 0);
  262. if (pdhStatus == ERROR_SUCCESS) {
  263. // add the string if it will fit
  264. if (bUnicode) {
  265. dwSize = lstrlenW((LPWSTR) szTempPathBuffer) + 1;
  266. if (!bMoreData && (dwSize <= dwBufferRemaining)) {
  267. lstrcpyW ((LPWSTR)szNextUserString, szTempPathBuffer);
  268. (LPBYTE) szNextUserString += dwSize * sizeof(WCHAR);
  269. dwBufferRemaining -= dwSize;
  270. }
  271. else {
  272. dwBufferRemaining = 0;
  273. bMoreData = TRUE;
  274. }
  275. }
  276. else {
  277. dwSize = dwBufferRemaining;
  278. if (PdhiConvertUnicodeToAnsi(_getmbcp(),
  279. szTempPathBuffer,
  280. szNextUserString,
  281. & dwSize) == ERROR_SUCCESS) {
  282. (LPBYTE)szNextUserString += dwSize * sizeof(CHAR);
  283. dwBufferRemaining -= dwSize;
  284. }
  285. else {
  286. dwBufferRemaining = 0;
  287. bMoreData = TRUE;
  288. }
  289. }
  290. dwSizeReturned += dwSize;
  291. } // end if path created OK
  292. } // end for each counter
  293. szThisInstance += lstrlenW(szThisInstance) +1;
  294. } while (*szThisInstance != 0);
  295. if (! IsListEmpty(& InstList)) {
  296. pHead = & InstList;
  297. pNext = pHead->Flink;
  298. while (pNext != pHead) {
  299. pInst = CONTAINING_RECORD(pNext, PDHI_INSTANCE, Entry);
  300. pNext = pNext->Flink;
  301. RemoveEntryList(& pInst->Entry);
  302. G_FREE(pInst);
  303. }
  304. }
  305. } // else no instances to do
  306. } // end for each object found
  307. } // end if object enumeration successful
  308. if ((dwSizeReturned > 0) && (dwBufferRemaining >= 1)) {
  309. dwSize = 1;
  310. if (szNextUserString) {
  311. if (bUnicode) {
  312. * (LPWSTR) szNextUserString = 0;
  313. (LPBYTE) szNextUserString += dwSize * sizeof(WCHAR);
  314. } else {
  315. * (LPSTR) szNextUserString = 0;
  316. (LPBYTE) szNextUserString += dwSize * sizeof(CHAR);
  317. }
  318. }
  319. dwSizeReturned += dwSize;
  320. dwBufferRemaining -= dwSize;
  321. }
  322. *pcchPathListLength = dwSizeReturned;
  323. if (mszCounterList != NULL) G_FREE(mszCounterList);
  324. if (mszInstanceList != NULL) G_FREE(mszInstanceList);
  325. if (mszObjectList != NULL) G_FREE(mszObjectList);
  326. if (pWildCounterPath != NULL) G_FREE(pWildCounterPath);
  327. if (bMoreData) pdhStatus = PDH_MORE_DATA;
  328. return (pdhStatus);
  329. }
  330. STATIC_PDH_FUNCTION
  331. PdhiExpandCounterPath (
  332. IN LPCWSTR szWildCardPath,
  333. IN LPVOID pExpandedPathList,
  334. IN LPDWORD pcchPathListLength,
  335. IN BOOL bUnicode
  336. )
  337. {
  338. PPERF_MACHINE pMachine;
  339. PPDHI_COUNTER_PATH pWildCounterPath = NULL;
  340. WCHAR szWorkBuffer[MAX_PATH];
  341. WCHAR szCounterName[MAX_PATH];
  342. WCHAR szInstanceName[MAX_PATH];
  343. LPWSTR szEndOfObjectString;
  344. LPWSTR szInstanceString;
  345. LPWSTR szCounterString;
  346. LPVOID szNextUserString = NULL;
  347. PERF_OBJECT_TYPE *pObjectDef;
  348. PERF_OBJECT_TYPE *pParentObjectDef;
  349. PERF_COUNTER_DEFINITION *pCounterDef;
  350. PERF_INSTANCE_DEFINITION *pInstanceDef;
  351. PERF_INSTANCE_DEFINITION *pParentInstanceDef;
  352. DWORD dwLocalPathLength = 0;
  353. DWORD dwBufferRemaining = 0;
  354. DWORD dwSize;
  355. DWORD dwSizeReturned = 0;
  356. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  357. DWORD dwCtrNdx, dwInstNdx;
  358. BOOL bMoreData = FALSE;
  359. if ((szWildCardPath == NULL) ||
  360. (pExpandedPathList == NULL) ||
  361. (pcchPathListLength == NULL)) {
  362. pdhStatus = PDH_INVALID_ARGUMENT;
  363. } else {
  364. // allocate buffers
  365. pWildCounterPath = G_ALLOC (PDHI_COUNTER_PATH_BUFFER_SIZE);
  366. if (pWildCounterPath == NULL) {
  367. // unable to allocate memory so bail out
  368. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  369. } else {
  370. __try {
  371. dwLocalPathLength = *pcchPathListLength;
  372. dwBufferRemaining = dwLocalPathLength;
  373. szNextUserString = pExpandedPathList;
  374. } __except (EXCEPTION_EXECUTE_HANDLER) {
  375. pdhStatus = PDH_INVALID_ARGUMENT;
  376. }
  377. }
  378. }
  379. if (pdhStatus == ERROR_SUCCESS) {
  380. pdhStatus = WAIT_FOR_AND_LOCK_MUTEX (hPdhDataMutex);
  381. }
  382. if (pdhStatus == ERROR_SUCCESS) {
  383. // Parse wild card Path
  384. dwSize = (DWORD)G_SIZE (pWildCounterPath);
  385. if (ParseFullPathNameW (szWildCardPath, &dwSize, pWildCounterPath, FALSE)) {
  386. // get the machine referenced in the path
  387. pMachine = GetMachine (pWildCounterPath->szMachineName, 0);
  388. if (pMachine != NULL) {
  389. if (wcsncmp (cszDoubleBackSlash, szWildCardPath, 2) == 0) {
  390. // the caller wants the machine name in the path so
  391. // copy it to the work buffer
  392. lstrcpyW (szWorkBuffer, pWildCounterPath->szMachineName);
  393. } else {
  394. *szWorkBuffer = 0;
  395. }
  396. // append the object name (since wild card objects are not
  397. // currently supported.
  398. lstrcatW (szWorkBuffer, cszBackSlash);
  399. lstrcatW (szWorkBuffer, pWildCounterPath->szObjectName);
  400. szEndOfObjectString = &szWorkBuffer[lstrlenW(szWorkBuffer)];
  401. if (pMachine->dwStatus == ERROR_SUCCESS) {
  402. // get object pointer (since objects are not wild)
  403. pObjectDef = GetObjectDefByName (
  404. pMachine->pSystemPerfData,
  405. pMachine->dwLastPerfString,
  406. pMachine->szPerfStrings,
  407. pWildCounterPath->szObjectName);
  408. } else {
  409. pObjectDef = NULL;
  410. }
  411. if (pObjectDef != NULL) {
  412. // for each counters and identify matches
  413. pCounterDef = FirstCounter (pObjectDef);
  414. for (dwCtrNdx = 0; dwCtrNdx < pObjectDef->NumCounters; dwCtrNdx++) {
  415. // for each counter check instances (if supported)
  416. // and keep matches
  417. if ((pCounterDef->CounterNameTitleIndex > 0) &&
  418. (pCounterDef->CounterNameTitleIndex < pMachine->dwLastPerfString ) &&
  419. (!((pCounterDef->CounterType & PERF_DISPLAY_NOSHOW) &&
  420. // this is a hack because this type is not defined correctly
  421. (pCounterDef->CounterType != PERF_AVERAGE_BULK)))) {
  422. // look up name of each object & store size
  423. lstrcpyW (szCounterName,
  424. PdhiLookupPerfNameByIndex (
  425. pMachine,
  426. pCounterDef->CounterNameTitleIndex));
  427. if (WildStringMatchW(pWildCounterPath->szCounterName, szCounterName)) {
  428. // if this object has instances, then walk down
  429. // the instance list and save any matches
  430. if (pObjectDef->NumInstances != PERF_NO_INSTANCES) {
  431. // then walk instances to find matches
  432. pInstanceDef = FirstInstance (pObjectDef);
  433. if (pObjectDef->NumInstances > 0) {
  434. for (dwInstNdx = 0;
  435. dwInstNdx < (DWORD)pObjectDef->NumInstances;
  436. dwInstNdx++) {
  437. szInstanceString = szEndOfObjectString;
  438. if (pInstanceDef->ParentObjectTitleIndex > 0) {
  439. // then add in parent instance name
  440. pParentObjectDef = GetObjectDefByTitleIndex (
  441. pMachine->pSystemPerfData,
  442. pInstanceDef->ParentObjectTitleIndex);
  443. if (pParentObjectDef != NULL) {
  444. pParentInstanceDef = GetInstance (
  445. pParentObjectDef,
  446. pInstanceDef->ParentObjectInstance);
  447. if (pParentInstanceDef != NULL) {
  448. GetInstanceNameStr (pParentInstanceDef,
  449. szInstanceName,
  450. pObjectDef->CodePage);
  451. if (WildStringMatchW (pWildCounterPath->szParentName, szInstanceName)) {
  452. // add this string
  453. szInstanceString = szEndOfObjectString;
  454. lstrcpyW (szInstanceString, cszLeftParen);
  455. lstrcatW (szInstanceString, szInstanceName);
  456. lstrcatW (szInstanceString, cszSlash);
  457. } else {
  458. // get next instance and continue
  459. pInstanceDef = NextInstance(pInstanceDef);
  460. continue;
  461. }
  462. } else {
  463. // unable to locate parent instance
  464. // so cancel this one, then
  465. // get next instance and continue
  466. pInstanceDef = NextInstance(pInstanceDef);
  467. continue;
  468. }
  469. } else {
  470. // unable to locate parent object
  471. // so cancel this one, then
  472. // get next instance and continue
  473. pInstanceDef = NextInstance(pInstanceDef);
  474. continue;
  475. }
  476. } else {
  477. // no parent name so continue
  478. szInstanceString = szEndOfObjectString;
  479. lstrcpyW (szInstanceString, cszLeftParen);
  480. }
  481. GetInstanceNameStr (pInstanceDef,
  482. szInstanceName,
  483. pObjectDef->CodePage);
  484. // if this instance name matches, then keep it
  485. if (WildStringMatchW (pWildCounterPath->szInstanceName, szInstanceName)) {
  486. lstrcatW (szInstanceString, szInstanceName);
  487. lstrcatW (szInstanceString, cszRightParenBackSlash);
  488. // now append this counter name
  489. lstrcatW (szInstanceString, szCounterName);
  490. // add it to the user's buffer if there's room
  491. if (bUnicode) {
  492. dwSize = lstrlenW(szWorkBuffer) + 1;
  493. if (!bMoreData && (dwSize <= dwBufferRemaining)) {
  494. lstrcpyW ((LPWSTR)szNextUserString, szWorkBuffer);
  495. (LPBYTE)szNextUserString += dwSize * sizeof(WCHAR);
  496. }
  497. else {
  498. bMoreData = TRUE;
  499. }
  500. } else {
  501. dwSize = dwBufferRemaining;
  502. if (PdhiConvertUnicodeToAnsi(_getmbcp(),
  503. szWorkBuffer, szNextUserString, & dwSize)
  504. == ERROR_SUCCESS) {
  505. (LPBYTE)szNextUserString += dwSize * sizeof(CHAR);
  506. }
  507. else {
  508. bMoreData = TRUE;
  509. }
  510. }
  511. dwSizeReturned += dwSize;
  512. if (! bMoreData) {
  513. dwBufferRemaining -= dwSize;
  514. }
  515. } else {
  516. // they don't want this instance so skip it
  517. }
  518. pInstanceDef = NextInstance (pInstanceDef);
  519. } // end for each instance in object
  520. } else {
  521. // this object supports instances,
  522. // but doesn't currently have any
  523. // so do nothing.
  524. }
  525. } else {
  526. // this object does not use instances so copy this
  527. // counter to the caller's buffer.
  528. szCounterString = szEndOfObjectString;
  529. lstrcpyW (szCounterString, cszBackSlash);
  530. lstrcatW (szCounterString, szCounterName);
  531. if (bUnicode) {
  532. dwSize = lstrlenW(szWorkBuffer) + 1;
  533. if (!bMoreData && (dwSize < dwBufferRemaining)) {
  534. lstrcpyW ((LPWSTR)szNextUserString, szWorkBuffer);
  535. (LPBYTE)szNextUserString += dwSize * sizeof(WCHAR);
  536. }
  537. else {
  538. bMoreData = TRUE;
  539. }
  540. } else {
  541. dwSize = dwBufferRemaining;
  542. if (PdhiConvertUnicodeToAnsi(_getmbcp(),
  543. szWorkBuffer, szNextUserString, & dwSize)
  544. == ERROR_SUCCESS) {
  545. (LPBYTE)szNextUserString += dwSize * sizeof(CHAR);
  546. }
  547. else {
  548. bMoreData = TRUE;
  549. }
  550. }
  551. dwSizeReturned += dwSize;
  552. if (! bMoreData) {
  553. dwBufferRemaining -= dwSize;
  554. }
  555. }
  556. } else {
  557. // this counter doesn't match so skip it
  558. }
  559. } else {
  560. // this counter string is not available
  561. }
  562. pCounterDef = NextCounter(pCounterDef);
  563. } // end for each counter in this object
  564. if (bUnicode) {
  565. *(LPWSTR)szNextUserString = 0; // MSZ terminator
  566. } else {
  567. *(LPSTR)szNextUserString = 0; // MSZ terminator
  568. }
  569. dwLocalPathLength = dwSizeReturned;
  570. if (bMoreData) {
  571. pdhStatus = PDH_MORE_DATA;
  572. } else {
  573. pdhStatus = ERROR_SUCCESS;
  574. }
  575. } else {
  576. // unable to find object
  577. pdhStatus = PDH_INVALID_PATH;
  578. }
  579. pMachine->dwRefCount--;
  580. RELEASE_MUTEX (pMachine->hMutex);
  581. } else {
  582. // unable to connect to machine.
  583. pdhStatus = GetLastError();
  584. }
  585. } else {
  586. // unable to read input path string
  587. pdhStatus = PDH_INVALID_PATH;
  588. }
  589. RELEASE_MUTEX (hPdhDataMutex);
  590. __try {
  591. *pcchPathListLength = dwLocalPathLength;
  592. } __except (EXCEPTION_EXECUTE_HANDLER) {
  593. pdhStatus = PDH_INVALID_ARGUMENT;
  594. }
  595. }
  596. if (pWildCounterPath != NULL) G_FREE (pWildCounterPath);
  597. return pdhStatus;
  598. }
  599. PDH_FUNCTION
  600. PdhExpandCounterPathW (
  601. IN LPCWSTR szWildCardPath,
  602. IN LPWSTR mszExpandedPathList,
  603. IN LPDWORD pcchPathListLength
  604. )
  605. /*++
  606. Expands any wild card characters in the following fields of the
  607. counter path string in the szWildCardPath argument and returns the
  608. matching counter paths in the buffer referenced by the
  609. mszExpandedPathList argument
  610. The input path is defined as one of the following formats:
  611. \\machine\object(parent/instance#index)\counter
  612. \\machine\object(parent/instance)\counter
  613. \\machine\object(instance#index)\counter
  614. \\machine\object(instance)\counter
  615. \\machine\object\counter
  616. \object(parent/instance#index)\counter
  617. \object(parent/instance)\counter
  618. \object(instance#index)\counter
  619. \object(instance)\counter
  620. \object\counter
  621. Input paths that include the machine will be expanded to also
  622. include the machine and use the specified machine to resolve the
  623. wild card matches. Input paths that do not contain a machine name
  624. will use the local machine to resolve wild card matches.
  625. The following fields may contain either a valid name or a wild card
  626. character ("*"). Partial string matches (e.g. "pro*") are not
  627. supported.
  628. parent returns all instances of the specified object that
  629. match the other specified fields
  630. instance returns all instances of the specified object and
  631. parent object if specified
  632. index returns all duplicate matching instance names
  633. counter returns all counters of the specified object
  634. --*/
  635. {
  636. return PdhiExpandCounterPath (
  637. szWildCardPath,
  638. (LPVOID)mszExpandedPathList,
  639. pcchPathListLength,
  640. TRUE);
  641. }
  642. PDH_FUNCTION
  643. PdhExpandCounterPathA (
  644. IN LPCSTR szWildCardPath,
  645. IN LPSTR mszExpandedPathList,
  646. IN LPDWORD pcchPathListLength
  647. )
  648. {
  649. LPWSTR szWideWildCardPath = NULL;
  650. DWORD dwSize;
  651. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  652. DWORD dwLocalListSize = 0;
  653. if ((szWildCardPath == NULL) || (pcchPathListLength == NULL)) {
  654. pdhStatus = PDH_INVALID_ARGUMENT;
  655. }
  656. else if (* szWildCardPath == '\0') {
  657. pdhStatus = PDH_INVALID_ARGUMENT;
  658. } else {
  659. __try {
  660. dwLocalListSize = *pcchPathListLength;
  661. dwSize = lstrlenA (szWildCardPath);
  662. szWideWildCardPath = G_ALLOC (((dwSize+1) * sizeof (WCHAR)));
  663. if (szWideWildCardPath == NULL) {
  664. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  665. } else {
  666. MultiByteToWideChar(_getmbcp(),
  667. 0,
  668. szWildCardPath,
  669. dwSize,
  670. (LPWSTR) szWideWildCardPath,
  671. dwSize + 1);
  672. }
  673. } __except (EXCEPTION_EXECUTE_HANDLER) {
  674. pdhStatus = PDH_INVALID_ARGUMENT;
  675. }
  676. }
  677. if (pdhStatus == ERROR_SUCCESS && szWideWildCardPath != NULL) {
  678. pdhStatus = PdhiExpandCounterPath (
  679. szWideWildCardPath,
  680. (LPVOID)mszExpandedPathList,
  681. &dwLocalListSize,
  682. FALSE);
  683. __try {
  684. * pcchPathListLength = dwLocalListSize;
  685. } __except (EXCEPTION_EXECUTE_HANDLER) {
  686. pdhStatus = PDH_INVALID_ARGUMENT;
  687. }
  688. }
  689. if (szWideWildCardPath != NULL) G_FREE (szWideWildCardPath);
  690. return pdhStatus;
  691. }
  692. PDH_FUNCTION
  693. PdhExpandWildCardPathHW (
  694. IN HLOG hDataSource,
  695. IN LPCWSTR szWildCardPath,
  696. IN LPWSTR mszExpandedPathList,
  697. IN LPDWORD pcchPathListLength,
  698. IN DWORD dwFlags
  699. )
  700. {
  701. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  702. DWORD dwLocalBufferSize;
  703. if ((szWildCardPath == NULL) || (pcchPathListLength == NULL)) {
  704. pdhStatus = PDH_INVALID_ARGUMENT;
  705. }
  706. else {
  707. __try {
  708. dwLocalBufferSize = * pcchPathListLength;
  709. } __except (EXCEPTION_EXECUTE_HANDLER) {
  710. pdhStatus = PDH_INVALID_ARGUMENT;
  711. }
  712. }
  713. if (pdhStatus == ERROR_SUCCESS) {
  714. pdhStatus = PdhiExpandWildcardPath (
  715. hDataSource,
  716. szWildCardPath,
  717. (LPVOID) mszExpandedPathList,
  718. & dwLocalBufferSize,
  719. dwFlags,
  720. TRUE);
  721. __try {
  722. * pcchPathListLength = dwLocalBufferSize;
  723. }
  724. __except (EXCEPTION_EXECUTE_HANDLER) {
  725. pdhStatus = PDH_INVALID_ARGUMENT;
  726. }
  727. }
  728. return pdhStatus;
  729. }
  730. PDH_FUNCTION
  731. PdhExpandWildCardPathW (
  732. IN LPCWSTR szDataSource,
  733. IN LPCWSTR szWildCardPath,
  734. IN LPWSTR mszExpandedPathList,
  735. IN LPDWORD pcchPathListLength,
  736. IN DWORD dwFlags
  737. )
  738. /*++
  739. Expands any wild card characters in the following fields of the
  740. counter path string in the szWildCardPath argument and returns the
  741. matching counter paths in the buffer referenced by the
  742. mszExpandedPathList argument
  743. The input path is defined as one of the following formats:
  744. \\machine\object(parent/instance#index)\counter
  745. \\machine\object(parent/instance)\counter
  746. \\machine\object(instance#index)\counter
  747. \\machine\object(instance)\counter
  748. \\machine\object\counter
  749. \object(parent/instance#index)\counter
  750. \object(parent/instance)\counter
  751. \object(instance#index)\counter
  752. \object(instance)\counter
  753. \object\counter
  754. Input paths that include the machine will be expanded to also
  755. include the machine and use the specified machine to resolve the
  756. wild card matches. Input paths that do not contain a machine name
  757. will use the local machine to resolve wild card matches.
  758. The following fields may contain either a valid name or a wild card
  759. character ("*"). Partial string matches (e.g. "pro*") are not
  760. supported.
  761. parent returns all instances of the specified object that
  762. match the other specified fields
  763. instance returns all instances of the specified object and
  764. parent object if specified
  765. index returns all duplicate matching instance names
  766. counter returns all counters of the specified object
  767. --*/
  768. {
  769. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  770. DWORD dwLocalBufferSize;
  771. DWORD dwDataSource = 0;
  772. HLOG hDataSource = H_REALTIME_DATASOURCE;
  773. __try {
  774. if (szDataSource != NULL) {
  775. // test for read access to the name
  776. if (* szDataSource == 0) {
  777. pdhStatus = PDH_INVALID_ARGUMENT;
  778. }
  779. } // else NULL is a valid arg
  780. if (pdhStatus == ERROR_SUCCESS) {
  781. dwDataSource = DataSourceTypeW(szDataSource);
  782. dwLocalBufferSize = * pcchPathListLength;
  783. }
  784. } __except (EXCEPTION_EXECUTE_HANDLER) {
  785. pdhStatus = PDH_INVALID_ARGUMENT;
  786. }
  787. if (pdhStatus == ERROR_SUCCESS) {
  788. if (dwDataSource == DATA_SOURCE_WBEM) {
  789. hDataSource = H_WBEM_DATASOURCE;
  790. }
  791. else if (dwDataSource == DATA_SOURCE_LOGFILE) {
  792. DWORD dwLogType = 0;
  793. pdhStatus = PdhOpenLogW(
  794. szDataSource,
  795. PDH_LOG_READ_ACCESS | PDH_LOG_OPEN_EXISTING,
  796. & dwLogType,
  797. NULL,
  798. 0,
  799. NULL,
  800. & hDataSource);
  801. }
  802. if (pdhStatus == ERROR_SUCCESS) {
  803. pdhStatus = PdhExpandWildCardPathHW (
  804. hDataSource,
  805. szWildCardPath,
  806. mszExpandedPathList,
  807. pcchPathListLength,
  808. dwFlags);
  809. if (dwDataSource == DATA_SOURCE_LOGFILE) {
  810. PdhCloseLog(hDataSource, 0);
  811. }
  812. }
  813. }
  814. return pdhStatus;
  815. }
  816. PDH_FUNCTION
  817. PdhExpandWildCardPathHA (
  818. IN HLOG hDataSource,
  819. IN LPCSTR szWildCardPath,
  820. IN LPSTR mszExpandedPathList,
  821. IN LPDWORD pcchPathListLength,
  822. IN DWORD dwFlags
  823. )
  824. {
  825. LPWSTR szWideWildCardPath = NULL;
  826. DWORD dwSize;
  827. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  828. DWORD dwLocalBufferSize;
  829. if ((szWildCardPath == NULL) || (pcchPathListLength == NULL)) {
  830. pdhStatus = PDH_INVALID_ARGUMENT;
  831. }
  832. else if (* szWildCardPath == '\0') {
  833. pdhStatus = PDH_INVALID_ARGUMENT;
  834. }
  835. else {
  836. __try {
  837. dwSize = lstrlenA(szWildCardPath);
  838. szWideWildCardPath = G_ALLOC(((dwSize + 1) * sizeof(WCHAR)));
  839. if (szWideWildCardPath == NULL) {
  840. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  841. }
  842. else {
  843. MultiByteToWideChar(_getmbcp(),
  844. 0,
  845. szWildCardPath,
  846. dwSize,
  847. (LPWSTR) szWideWildCardPath,
  848. dwSize + 1);
  849. }
  850. dwLocalBufferSize = * pcchPathListLength;
  851. }
  852. __except (EXCEPTION_EXECUTE_HANDLER) {
  853. pdhStatus = PDH_INVALID_ARGUMENT;
  854. }
  855. }
  856. if (pdhStatus == ERROR_SUCCESS) {
  857. pdhStatus = PdhiExpandWildcardPath (
  858. hDataSource,
  859. szWideWildCardPath,
  860. (LPVOID) mszExpandedPathList,
  861. & dwLocalBufferSize,
  862. dwFlags,
  863. FALSE);
  864. __try {
  865. * pcchPathListLength = dwLocalBufferSize;
  866. }
  867. __except (EXCEPTION_EXECUTE_HANDLER) {
  868. pdhStatus = PDH_INVALID_ARGUMENT;
  869. }
  870. }
  871. if (szWideWildCardPath != NULL) G_FREE(szWideWildCardPath);
  872. return pdhStatus;
  873. }
  874. PDH_FUNCTION
  875. PdhExpandWildCardPathA (
  876. IN LPCSTR szDataSource,
  877. IN LPCSTR szWildCardPath,
  878. IN LPSTR mszExpandedPathList,
  879. IN LPDWORD pcchPathListLength,
  880. IN DWORD dwFlags
  881. )
  882. {
  883. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  884. HLOG hDataSource = H_REALTIME_DATASOURCE;
  885. DWORD dwDataSource = 0;
  886. __try {
  887. if (szDataSource != NULL) {
  888. // test for read access to the name
  889. if (* szDataSource == 0) {
  890. pdhStatus = PDH_INVALID_ARGUMENT;
  891. }
  892. } // else NULL is a valid arg
  893. if (pdhStatus == ERROR_SUCCESS) {
  894. dwDataSource = DataSourceTypeA(szDataSource);
  895. }
  896. }
  897. __except (EXCEPTION_EXECUTE_HANDLER) {
  898. pdhStatus = PDH_INVALID_ARGUMENT;
  899. }
  900. if (pdhStatus == ERROR_SUCCESS) {
  901. if (dwDataSource == DATA_SOURCE_WBEM) {
  902. hDataSource = H_WBEM_DATASOURCE;
  903. }
  904. else if (dwDataSource == DATA_SOURCE_LOGFILE) {
  905. DWORD dwLogType = 0;
  906. pdhStatus = PdhOpenLogA(
  907. szDataSource,
  908. PDH_LOG_READ_ACCESS | PDH_LOG_OPEN_EXISTING,
  909. & dwLogType,
  910. NULL,
  911. 0,
  912. NULL,
  913. & hDataSource);
  914. }
  915. if (pdhStatus == ERROR_SUCCESS) {
  916. pdhStatus = PdhExpandWildCardPathHA (
  917. hDataSource,
  918. szWildCardPath,
  919. mszExpandedPathList,
  920. pcchPathListLength,
  921. dwFlags);
  922. if (dwDataSource == DATA_SOURCE_LOGFILE) {
  923. PdhCloseLog(hDataSource, 0);
  924. }
  925. }
  926. }
  927. return pdhStatus;
  928. }