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

894 lines
30 KiB

  1. /*++
  2. Copyright (C) 1995-1999 Microsoft Corporation
  3. Module Name:
  4. vbfuncs.c
  5. Abstract:
  6. Visual Basic interface functions exposed in pdh.dll
  7. --*/
  8. #include <windows.h>
  9. #include "strsafe.h"
  10. #include <winperf.h>
  11. #include <pdh.h>
  12. #include "pdhidef.h"
  13. #include "pdhmsg.h"
  14. #include "strings.h"
  15. #define INITIAL_VB_LIST_SIZE (4096 * 4)
  16. #define EXTEND_VB_LIST_SIZE (4096 * 2)
  17. typedef struct _VB_STRING_LIST {
  18. LPSTR mszList; // pointer to buffer containing strings
  19. LPSTR szTermChar; // pointer to "next" char to use
  20. DWORD dwNumEntries; // number of strings
  21. DWORD dwSize; // max size (in chars) of buffer
  22. DWORD dwRemaining; // # of chars left
  23. DWORD dwLastEntryRead; // index of last string read indicating index of....
  24. DWORD dwLastItemLength; // length of last item read
  25. LPSTR szLastItemRead; // pointer to START of last item read
  26. } VB_STRING_LIST, FAR * LPVB_STRING_LIST;
  27. VB_STRING_LIST PdhivbList = { NULL, NULL, 0, 0, 0};
  28. BOOL
  29. PdhiAddStringToVbList(
  30. LPSTR szString
  31. )
  32. {
  33. DWORD dwSize1, dwSize2;
  34. VB_STRING_LIST * pVbList;
  35. BOOL bReturn = FALSE;
  36. if (WAIT_FOR_AND_LOCK_MUTEX(hPdhDataMutex) == ERROR_SUCCESS) {
  37. dwSize1 = lstrlenA(szString) + 1;
  38. pVbList = & PdhivbList;
  39. if (dwSize1 > pVbList->dwRemaining) {
  40. LPSTR lpTmp = pVbList->mszList;
  41. dwSize2 = (DWORD) (pVbList->szTermChar - pVbList->mszList);
  42. pVbList->dwSize += EXTEND_VB_LIST_SIZE;
  43. pVbList->mszList = G_REALLOC(lpTmp, pVbList->dwSize);
  44. if (pVbList->mszList == NULL) {
  45. G_FREE(lpTmp);
  46. ZeroMemory(pVbList, sizeof(VB_STRING_LIST));
  47. RELEASE_MUTEX(hPdhDataMutex);
  48. goto Cleanup;
  49. }
  50. else {
  51. // update values
  52. pVbList->szLastItemRead = pVbList->mszList;
  53. pVbList->szTermChar = pVbList->mszList + dwSize2;
  54. pVbList->dwRemaining += EXTEND_VB_LIST_SIZE;
  55. }
  56. }
  57. // copy new string
  58. StringCchCopyA(pVbList->szTermChar, pVbList->dwSize, szString);
  59. pVbList->dwNumEntries ++;
  60. pVbList->szTermChar += dwSize1;
  61. pVbList->dwRemaining -= dwSize1;
  62. RELEASE_MUTEX(hPdhDataMutex);
  63. bReturn = TRUE;
  64. }
  65. Cleanup:
  66. return bReturn;
  67. }
  68. void
  69. PdhiDialogCallBack(
  70. DWORD_PTR dwArg
  71. )
  72. {
  73. // add strings in buffer to list boxpfdh
  74. LPTSTR NewCounterName;
  75. LPTSTR NewCounterName2;
  76. LPTSTR szExpandedPath;
  77. DWORD dwSize1, dwSize2;
  78. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  79. PPDH_BROWSE_DLG_CONFIG pDlgConfig;
  80. pDlgConfig = (PPDH_BROWSE_DLG_CONFIG)dwArg;
  81. if (pDlgConfig->CallBackStatus == PDH_MORE_DATA) {
  82. // transfer buffer is too small for selection so extend it and
  83. // try again.
  84. if (pDlgConfig->szReturnPathBuffer != NULL) {
  85. G_FREE (pDlgConfig->szReturnPathBuffer);
  86. }
  87. pDlgConfig->cchReturnPathLength += EXTEND_VB_LIST_SIZE;
  88. pDlgConfig->szReturnPathBuffer =
  89. G_ALLOC ((pDlgConfig->cchReturnPathLength * sizeof (CHAR)));
  90. if (pDlgConfig->szReturnPathBuffer != NULL) {
  91. pdhStatus = PDH_RETRY;
  92. } else {
  93. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  94. }
  95. } else {
  96. for (NewCounterName = pDlgConfig->szReturnPathBuffer;
  97. (*NewCounterName != 0) && (pdhStatus == ERROR_SUCCESS);
  98. NewCounterName += (lstrlen(NewCounterName) + 1)) {
  99. if (strstr (NewCounterName, caszSplat) == NULL) {
  100. // this is a regular path entry so add it to the VB List
  101. if (!PdhiAddStringToVbList (NewCounterName)) {
  102. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  103. }
  104. } else {
  105. szExpandedPath = G_ALLOC (INITIAL_VB_LIST_SIZE);
  106. if (szExpandedPath != NULL) {
  107. // there's a wild card path character so expand it then enter them
  108. // clear the list buffer
  109. *(LPDWORD)szExpandedPath = 0;
  110. dwSize1 = dwSize2 = INITIAL_VB_LIST_SIZE;
  111. PdhExpandCounterPath (NewCounterName, szExpandedPath, &dwSize2);
  112. if (dwSize2 < dwSize1) {
  113. // then the returned buffer fit
  114. for (NewCounterName2 = szExpandedPath;
  115. *NewCounterName2 != 0;
  116. NewCounterName2 += (lstrlen(NewCounterName2) + 1)) {
  117. if (!PdhiAddStringToVbList (NewCounterName2)) {
  118. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  119. break; //out of loop
  120. }
  121. }
  122. } else {
  123. pdhStatus = PDH_INSUFFICIENT_BUFFER;
  124. }
  125. G_FREE (szExpandedPath);
  126. } else {
  127. SetLastError (PDH_MEMORY_ALLOCATION_FAILURE);
  128. }
  129. }
  130. }
  131. // clear buffer
  132. ZeroMemory(pDlgConfig->szReturnPathBuffer,
  133. (pDlgConfig->cchReturnPathLength * sizeof(CHAR)));
  134. }
  135. pDlgConfig->CallBackStatus = pdhStatus;
  136. return;
  137. }
  138. double
  139. PdhVbGetDoubleCounterValue(
  140. IN PDH_HCOUNTER hCounter,
  141. IN LPDWORD pdwCounterStatus
  142. )
  143. /*++
  144. Routine Description:
  145. retrieves the current value of the specified counter and returns the
  146. formatted version to the caller.
  147. Arguments:
  148. IN HCOUNTER hCounter
  149. pointer to the counter to get the data for
  150. IN LPDWORD pdwCounterStatus
  151. status value of this counter. This value should be checked to
  152. insure the data is valid. If the status is not successful, then
  153. the data returned cannot be trusted and should not be used
  154. Return Value:
  155. a double precesion floating point value of the current counter value
  156. formatted and computed as required by the counter type.
  157. --*/
  158. {
  159. PDH_STATUS pdhStatus;
  160. PDH_FMT_COUNTERVALUE pdhValue;
  161. DWORD dwCounterType;
  162. double dReturn;
  163. pdhStatus = PdhGetFormattedCounterValue (
  164. hCounter, PDH_FMT_DOUBLE | PDH_FMT_NOCAP100, &dwCounterType, &pdhValue);
  165. if (pdhStatus == ERROR_SUCCESS) {
  166. // the function was successful so return the counter status
  167. // and the returned value
  168. pdhStatus = pdhValue.CStatus;
  169. dReturn = pdhValue.doubleValue;
  170. } else {
  171. // the function returned an error so return the
  172. // error in the status field & 0.0 for a value
  173. dReturn = 0.0f;
  174. }
  175. if (pdwCounterStatus != NULL) {
  176. __try {
  177. *pdwCounterStatus = pdhStatus;
  178. } __except (EXCEPTION_EXECUTE_HANDLER) {
  179. // unable to write to status variable
  180. // don't worry about it, since it's optional and there's not much
  181. // we can do here anyway.
  182. }
  183. }
  184. return dReturn;
  185. }
  186. DWORD
  187. PdhVbGetOneCounterPath(
  188. IN LPSTR szPathBuffer,
  189. IN DWORD cchBufferLength,
  190. IN DWORD dwDetailLevel,
  191. IN LPCSTR szCaption
  192. )
  193. /*++
  194. Routine Description:
  195. Retrieves one path string from the buffer of stored counter paths
  196. assembled by the most recent call to PdhVbCreateCounterPathList
  197. Arguments:
  198. LPSTR szPathBuffer
  199. string buffer to return selected counter path in
  200. DWORD cchBufferLength
  201. size of string buffer in characters
  202. DWORD dwDetailLevel
  203. detail level to filter the counters by
  204. LPCSTR szCaption
  205. string to display in the caption bar
  206. Return Value:
  207. returns the length of the path string in characters returned
  208. to the caller.
  209. --*/
  210. {
  211. PDH_BROWSE_DLG_CONFIG_A BrowseConfig;
  212. PDH_STATUS PdhStatus = ERROR_SUCCESS;
  213. DWORD dwReturn = 0;
  214. // test access to caller supplied buffer
  215. __try {
  216. CHAR cChar;
  217. if ((cchBufferLength > 0) && (szPathBuffer != NULL)) {
  218. cChar = szPathBuffer[0];
  219. szPathBuffer[0] = '\0';
  220. szPathBuffer[0] = cChar;
  221. cChar = szPathBuffer[cchBufferLength - 1];
  222. szPathBuffer[cchBufferLength - 1] = '\0';
  223. szPathBuffer[cchBufferLength - 1] = cChar;
  224. }
  225. else {
  226. PdhStatus = PDH_INVALID_ARGUMENT;
  227. }
  228. if (szCaption != NULL) {
  229. cChar = * ((CHAR volatile *) szCaption);
  230. }
  231. }
  232. __except (EXCEPTION_EXECUTE_HANDLER) {
  233. PdhStatus = PDH_INVALID_ARGUMENT;
  234. }
  235. if (PdhStatus == ERROR_SUCCESS) {
  236. ZeroMemory(& BrowseConfig, sizeof(PDH_BROWSE_DLG_CONFIG_A));
  237. BrowseConfig.bIncludeInstanceIndex = FALSE;
  238. BrowseConfig.bSingleCounterPerAdd = TRUE;
  239. BrowseConfig.bSingleCounterPerDialog = TRUE;
  240. BrowseConfig.bLocalCountersOnly = FALSE;
  241. BrowseConfig.bWildCardInstances = FALSE;
  242. BrowseConfig.bDisableMachineSelection = FALSE;
  243. BrowseConfig.bHideDetailBox = (dwDetailLevel > 0 ? TRUE : FALSE);
  244. BrowseConfig.hWndOwner = NULL; // there should be some way to get this
  245. BrowseConfig.szReturnPathBuffer = szPathBuffer;
  246. BrowseConfig.cchReturnPathLength = cchBufferLength;
  247. BrowseConfig.pCallBack = NULL;
  248. BrowseConfig.dwCallBackArg = 0;
  249. // default is to show ALL counters
  250. BrowseConfig.dwDefaultDetailLevel = (dwDetailLevel > 0 ? dwDetailLevel : PERF_DETAIL_WIZARD);
  251. BrowseConfig.szDialogBoxCaption = (LPSTR) szCaption;
  252. PdhStatus = PdhBrowseCountersA(& BrowseConfig);
  253. }
  254. if (PdhStatus == ERROR_SUCCESS) {
  255. dwReturn = lstrlenA(szPathBuffer);
  256. }
  257. else {
  258. dwReturn = 0;
  259. }
  260. return dwReturn;
  261. }
  262. DWORD
  263. PdhVbCreateCounterPathList(
  264. IN DWORD dwDetailLevel,
  265. IN LPCSTR szCaption
  266. )
  267. /*++
  268. Routine Description:
  269. Displays the counter browsing dialog box and allows the user to select
  270. multiple counter paths. As the paths are selected, they are stored
  271. in an internal buffer for later retrieval by the caller.
  272. NOTE, that calling this function will clear any previous selections.
  273. Arguments:
  274. DWORD dwDetailLevel
  275. detail level to filter the counters by
  276. LPCSTR szCaption
  277. string to display in the caption bar
  278. Return Value:
  279. returns the number of path strings selected by the user that must
  280. be retrieved by the caller.
  281. --*/
  282. {
  283. PDH_STATUS PdhStatus = ERROR_SUCCESS;
  284. PDH_BROWSE_DLG_CONFIG_A BrowseConfig;
  285. DWORD dwReturn = 0;
  286. // test access to caller supplied buffer
  287. __try {
  288. CHAR cChar;
  289. if (szCaption != NULL) {
  290. cChar = * ((CHAR volatile *) szCaption);
  291. }
  292. }
  293. __except (EXCEPTION_EXECUTE_HANDLER) {
  294. PdhStatus = PDH_INVALID_ARGUMENT;
  295. }
  296. if (PdhStatus == ERROR_SUCCESS) {
  297. PdhStatus = WAIT_FOR_AND_LOCK_MUTEX(hPdhDataMutex);
  298. if (PdhStatus == ERROR_SUCCESS) {
  299. if (PdhivbList.mszList != NULL) {
  300. G_FREE(PdhivbList.mszList);
  301. ZeroMemory((LPVOID) & PdhivbList, sizeof(VB_STRING_LIST));
  302. }
  303. PdhivbList.mszList = G_ALLOC(INITIAL_VB_LIST_SIZE);
  304. if (PdhivbList.mszList != NULL) {
  305. PdhivbList.szLastItemRead = PdhivbList.mszList;
  306. PdhivbList.szTermChar = PdhivbList.mszList;
  307. PdhivbList.dwRemaining = INITIAL_VB_LIST_SIZE;
  308. PdhivbList.dwSize = INITIAL_VB_LIST_SIZE;
  309. PdhivbList.dwLastEntryRead = 0;
  310. PdhivbList.dwLastItemLength = 0;
  311. }
  312. else {
  313. PdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  314. }
  315. RELEASE_MUTEX(hPdhDataMutex);
  316. }
  317. }
  318. if (PdhStatus == ERROR_SUCCESS) {
  319. ZeroMemory(& BrowseConfig, sizeof(PDH_BROWSE_DLG_CONFIG_A));
  320. BrowseConfig.bIncludeInstanceIndex = FALSE;
  321. BrowseConfig.bSingleCounterPerAdd = FALSE;
  322. BrowseConfig.bSingleCounterPerDialog = FALSE;
  323. BrowseConfig.bLocalCountersOnly = FALSE;
  324. BrowseConfig.bWildCardInstances = FALSE;
  325. BrowseConfig.bDisableMachineSelection = FALSE;
  326. BrowseConfig.bHideDetailBox = (dwDetailLevel > 0 ? TRUE : FALSE);
  327. BrowseConfig.hWndOwner = NULL; // there should be some way to get this
  328. BrowseConfig.szReturnPathBuffer = G_ALLOC (INITIAL_VB_LIST_SIZE);
  329. if (BrowseConfig.szReturnPathBuffer != NULL) {
  330. BrowseConfig.cchReturnPathLength = (BrowseConfig.szReturnPathBuffer != NULL ? INITIAL_VB_LIST_SIZE : 0);
  331. BrowseConfig.pCallBack = (CounterPathCallBack) PdhiDialogCallBack;
  332. BrowseConfig.dwCallBackArg = (DWORD_PTR) & BrowseConfig;
  333. // default is to show ALL counters
  334. BrowseConfig.dwDefaultDetailLevel = (dwDetailLevel > 0 ? dwDetailLevel : PERF_DETAIL_WIZARD);
  335. BrowseConfig.szDialogBoxCaption = (LPSTR)szCaption;
  336. PdhStatus = PdhBrowseCountersA(& BrowseConfig);
  337. if (BrowseConfig.szReturnPathBuffer != NULL) {
  338. G_FREE(BrowseConfig.szReturnPathBuffer);
  339. }
  340. dwReturn = PdhivbList.dwNumEntries;
  341. }
  342. else {
  343. SetLastError(PDH_MEMORY_ALLOCATION_FAILURE);
  344. dwReturn = 0;
  345. }
  346. }
  347. return dwReturn;
  348. }
  349. DWORD
  350. PdhVbGetCounterPathFromList(
  351. IN DWORD dwIndex, // starting at 1 for VB types
  352. IN LPSTR szBuffer, // return buffer
  353. IN DWORD dwBufferSize // size in chars of buffer
  354. )
  355. /*++
  356. Routine Description:
  357. Displays the counter browsing dialog box and allows the user to select
  358. multiple counter paths. As the paths are selected, they are stored
  359. in an internal buffer for later retrieval by the caller.
  360. NOTE, that calling this function will clear any previous selections.
  361. Arguments:
  362. DWORD dwIndex
  363. The "1-based" index of the counter path to retrieve from
  364. the list of selected counter paths generated by the previous
  365. call to PdhVbCreateCounterPathList.
  366. LPSTR szBuffer
  367. string buffer to return the selected string in
  368. DWORD dwBufferSize
  369. size of the szBuffer in characters
  370. Return Value:
  371. Returns the number of characters copied to the calling function
  372. --*/
  373. {
  374. DWORD dwBuffIndex; // 0-based index for "c"
  375. DWORD dwThisIndex;
  376. DWORD dwCharsCopied; // size of string not counting term NULL
  377. BOOL bContinue = TRUE;
  378. dwBuffIndex = dwIndex - 1;
  379. dwCharsCopied = 0;
  380. // validate the arguments
  381. __try {
  382. if (dwBufferSize > 0) {
  383. // try writing to ouput buffer
  384. szBuffer[0] = '\0';
  385. szBuffer[dwBufferSize - 1] = '\0';
  386. }
  387. else {
  388. bContinue = FALSE;
  389. }
  390. if (dwBuffIndex >= PdhivbList.dwNumEntries) {
  391. bContinue = FALSE;
  392. }
  393. }
  394. __except (EXCEPTION_EXECUTE_HANDLER) {
  395. bContinue = FALSE;
  396. }
  397. if (WAIT_FOR_AND_LOCK_MUTEX(hPdhDataMutex) == ERROR_SUCCESS) {
  398. if (bContinue) {
  399. if (PdhivbList.szLastItemRead == NULL) {
  400. PdhivbList.szLastItemRead = PdhivbList.mszList;
  401. PdhivbList.dwLastEntryRead = 0;
  402. PdhivbList.dwLastItemLength = 0;
  403. }
  404. if (PdhivbList.szLastItemRead != NULL) {
  405. if (PdhivbList.dwLastItemLength == 0) {
  406. PdhivbList.dwLastItemLength = lstrlen(PdhivbList.szLastItemRead) + 1;
  407. }
  408. }
  409. else {
  410. bContinue = FALSE;
  411. }
  412. }
  413. if (bContinue) {
  414. // see if this is the next entry
  415. if (dwBuffIndex == (PdhivbList.dwLastEntryRead + 1)) {
  416. PdhivbList.szLastItemRead += PdhivbList.dwLastItemLength;
  417. PdhivbList.dwLastItemLength = lstrlen(PdhivbList.szLastItemRead) + 1;
  418. PdhivbList.dwLastEntryRead ++;
  419. if (PdhivbList.dwLastItemLength < dwBufferSize) {
  420. StringCchCopyA(szBuffer, dwBufferSize, PdhivbList.szLastItemRead);
  421. dwCharsCopied = PdhivbList.dwLastItemLength - 1;
  422. }
  423. }
  424. else if (dwBuffIndex == PdhivbList.dwLastEntryRead) {
  425. // it's this one (again)
  426. if (PdhivbList.dwLastItemLength < dwBufferSize) {
  427. StringCchCopyA(szBuffer, dwBufferSize, PdhivbList.szLastItemRead);
  428. dwCharsCopied = PdhivbList.dwLastItemLength - 1;
  429. }
  430. }
  431. else {
  432. // walk the list to the desired entry (ugh!)
  433. PdhivbList.szLastItemRead = PdhivbList.mszList;
  434. for (dwThisIndex = 0; dwThisIndex < dwBuffIndex; dwThisIndex++) {
  435. PdhivbList.szLastItemRead += lstrlen(PdhivbList.szLastItemRead) + 1;
  436. }
  437. PdhivbList.dwLastItemLength = lstrlen(PdhivbList.szLastItemRead) + 1;
  438. PdhivbList.dwLastEntryRead = dwThisIndex;
  439. if (PdhivbList.dwLastItemLength < dwBufferSize) {
  440. StringCchCopyA(szBuffer, dwBufferSize, PdhivbList.szLastItemRead);
  441. dwCharsCopied = PdhivbList.dwLastItemLength - 1;
  442. }
  443. }
  444. }
  445. RELEASE_MUTEX(hPdhDataMutex);
  446. }
  447. return dwCharsCopied;
  448. }
  449. DWORD
  450. PdhVbGetCounterPathElements(
  451. IN LPCSTR szPathString,
  452. IN LPSTR szMachineName,
  453. IN LPSTR szObjectName,
  454. IN LPSTR szInstanceName,
  455. IN LPSTR szParentInstance,
  456. IN LPSTR szCounterName,
  457. IN DWORD dwBufferSize
  458. )
  459. /*++
  460. Routine Description:
  461. breaks the counter path provided in the szPathString argument and
  462. returns the components in the buffers provided by the caller.
  463. The buffers must be at least "dwBufferSize" in length.
  464. Arguments:
  465. LPCSTR szPathString
  466. pointer to the full counter path that is to be parsed into
  467. component strings
  468. LPSTR szMachineName
  469. caller supplied buffer that is to receive the machine name.
  470. The buffer must be at least dwBufferSize in length.
  471. LPSTR szObjectName
  472. caller supplied buffer that is to receive the object name.
  473. The buffer must be at least dwBufferSize in length.
  474. LPSTR szInstanceName
  475. caller supplied buffer that is to receive the Instance name.
  476. The buffer must be at least dwBufferSize in length.
  477. LPSTR szParentInstance
  478. caller supplied buffer that is to receive the parent instance name.
  479. The buffer must be at least dwBufferSize in length.
  480. LPSTR szCounterName
  481. caller supplied buffer that is to receive the counter name.
  482. The buffer must be at least dwBufferSize in length.
  483. DWORD dwBufferSize
  484. The buffer size of the caller supplied string buffers in characters
  485. Return Value:
  486. ERROR_SUCCESS if the counter string is successfully parsed, otherwise
  487. a PDH error if not.
  488. PDH_INVALID_ARGUMENT if one or more of the string buffers is not
  489. the correct size
  490. PDH_INSUFFICIENT_BUFFER if one or more of the counter path elements
  491. is too large for the return buffer length.
  492. PDH_MEMORY_ALLOCATION_FAILURE if a temporary memory buffer could not
  493. be allocated.
  494. --*/
  495. {
  496. PPDH_COUNTER_PATH_ELEMENTS_A pInfo;
  497. PDH_STATUS pdhStatus = ERROR_SUCCESS;
  498. DWORD dwSize;
  499. // validate the return arguments
  500. __try {
  501. CHAR cChar;
  502. if (szPathString != NULL) {
  503. cChar = * ((CHAR volatile *) szPathString);
  504. if (cChar == 0) {
  505. pdhStatus = PDH_INVALID_ARGUMENT;
  506. }
  507. }
  508. else {
  509. pdhStatus = PDH_INVALID_ARGUMENT;
  510. }
  511. if (pdhStatus == ERROR_SUCCESS){
  512. if (szMachineName != NULL) {
  513. szMachineName[0] = '\0';
  514. szMachineName[dwBufferSize - 1] = '\0';
  515. }
  516. else {
  517. pdhStatus = PDH_INVALID_ARGUMENT;
  518. }
  519. }
  520. if (pdhStatus == ERROR_SUCCESS){
  521. if (szObjectName != NULL) {
  522. szObjectName[0] = '\0';
  523. szObjectName[dwBufferSize - 1] = '\0';
  524. }
  525. else {
  526. pdhStatus = PDH_INVALID_ARGUMENT;
  527. }
  528. }
  529. if (pdhStatus == ERROR_SUCCESS){
  530. if (szInstanceName != NULL) {
  531. szInstanceName[0] = '\0';
  532. szInstanceName[dwBufferSize - 1] = '\0';
  533. }
  534. else {
  535. pdhStatus = PDH_INVALID_ARGUMENT;
  536. }
  537. }
  538. if (pdhStatus == ERROR_SUCCESS){
  539. if (szParentInstance != NULL) {
  540. szParentInstance[0] = '\0';
  541. szParentInstance[dwBufferSize - 1] = '\0';
  542. }
  543. else {
  544. pdhStatus = PDH_INVALID_ARGUMENT;
  545. }
  546. }
  547. if (pdhStatus == ERROR_SUCCESS){
  548. if (szCounterName != NULL) {
  549. szCounterName[0] = '\0';
  550. szCounterName[dwBufferSize - 1] = '\0';
  551. } else {
  552. pdhStatus = PDH_INVALID_ARGUMENT;
  553. }
  554. }
  555. }
  556. __except (EXCEPTION_EXECUTE_HANDLER) {
  557. pdhStatus = PDH_INVALID_ARGUMENT;
  558. }
  559. if (pdhStatus == ERROR_SUCCESS) {
  560. // allocate temp buffer for component strings
  561. dwSize = (5 * dwBufferSize) + sizeof(PDH_COUNTER_INFO_A);
  562. pInfo = G_ALLOC (dwSize);
  563. if (pInfo != NULL) {
  564. pdhStatus = PdhParseCounterPathA(szPathString, pInfo, & dwSize, 0);
  565. if (pdhStatus == ERROR_SUCCESS) {
  566. // move from local structure to user args if the strings will fit
  567. if (pInfo->szMachineName != NULL) {
  568. if (FAILED(StringCchCopyA(szMachineName, dwBufferSize, pInfo->szMachineName))) {
  569. pdhStatus = PDH_INSUFFICIENT_BUFFER;
  570. }
  571. }
  572. if (pInfo->szObjectName != NULL) {
  573. if (FAILED(StringCchCopyA(szObjectName, dwBufferSize, pInfo->szObjectName))) {
  574. pdhStatus = PDH_INSUFFICIENT_BUFFER;
  575. }
  576. }
  577. if (pInfo->szInstanceName != NULL) {
  578. if (FAILED(StringCchCopyA(szInstanceName, dwBufferSize, pInfo->szInstanceName))) {
  579. pdhStatus = PDH_INSUFFICIENT_BUFFER;
  580. }
  581. }
  582. if (pInfo->szParentInstance != NULL) {
  583. if (FAILED(StringCchCopyA(szParentInstance, dwBufferSize, pInfo->szParentInstance))) {
  584. pdhStatus = PDH_INSUFFICIENT_BUFFER;
  585. }
  586. }
  587. if (pInfo->szCounterName != NULL) {
  588. if (FAILED(StringCchCopyA(szCounterName, dwBufferSize, pInfo->szCounterName))) {
  589. pdhStatus = PDH_INSUFFICIENT_BUFFER;
  590. }
  591. }
  592. } // else pass error to caller
  593. G_FREE (pInfo);
  594. }
  595. else {
  596. pdhStatus = PDH_MEMORY_ALLOCATION_FAILURE;
  597. }
  598. } // else pass error to caller
  599. return pdhStatus;
  600. }
  601. DWORD
  602. PdhVbAddCounter(
  603. IN PDH_HQUERY hQuery,
  604. IN LPCSTR szFullCounterPath,
  605. IN PDH_HCOUNTER * hCounter
  606. )
  607. /*++
  608. Routine Description:
  609. Creates and initializes a counter structure and attaches it to the
  610. specified query by calling the C function.
  611. Arguments:
  612. IN HQUERY hQuery
  613. handle of the query to attach this counter to once the counter
  614. entry has been successfully created.
  615. IN LPCSTR szFullCounterPath
  616. pointer to the path string that describes the counter to add to
  617. the query referenced above. This string must specify a single
  618. counter. Wildcard path strings are not permitted.
  619. IN HCOUNTER *phCounter
  620. pointer to the buffer that will get the handle value of the
  621. successfully created counter entry.
  622. Return Value:
  623. Returns ERROR_SUCCESS if a new query was created and initialized,
  624. and a PDH_ error value if not.
  625. PDH_INVALID_ARGUMENT is returned when one or more of the arguements
  626. is invalid or incorrect.
  627. PDH_MEMORY_ALLOCATION_FAILURE is returned when a memory buffer could
  628. not be allocated.
  629. PDH_INVALID_HANDLE is returned if the query handle is not valid.
  630. PDH_CSTATUS_NO_COUNTER is returned if the specified counter was
  631. not found
  632. PDH_CSTATUS_NO_OBJECT is returned if the specified object could
  633. not be found
  634. PDH_CSTATUS_NO_MACHINE is returned if a machine entry could not
  635. be created.
  636. PDH_CSTATUS_BAD_COUNTERNAME is returned if the counter name path
  637. string could not be parsed or interpreted
  638. PDH_CSTATUS_NO_COUNTERNAME is returned if an empty counter name
  639. path string is passed in
  640. PDH_FUNCTION_NOT_FOUND is returned if the calculation function
  641. for this counter could not be determined.
  642. --*/
  643. {
  644. DWORD dwReturn = ERROR_SUCCESS;
  645. PDH_HCOUNTER hLocalCounter = NULL;
  646. if ((hCounter == NULL) || (szFullCounterPath == NULL)) {
  647. dwReturn = PDH_INVALID_ARGUMENT;
  648. }
  649. else {
  650. dwReturn = PdhAddCounterA(hQuery, szFullCounterPath, 0, & hLocalCounter);
  651. }
  652. if (dwReturn == ERROR_SUCCESS) {
  653. __try {
  654. * hCounter = hLocalCounter;
  655. }
  656. __except (EXCEPTION_EXECUTE_HANDLER) {
  657. dwReturn = PDH_INVALID_ARGUMENT;
  658. }
  659. }
  660. return dwReturn;
  661. }
  662. DWORD
  663. PdhVbOpenQuery(
  664. IN PDH_HQUERY * phQuery
  665. )
  666. /*++
  667. Routine Description:
  668. allocates a new query structure for a VB app by calling the "C"
  669. function with the rest of the arguments supplied
  670. Arguments:
  671. IN HQUERY *phQuery
  672. pointer to the buffer that will receive the query handle opened.
  673. Return Value:
  674. Returns ERROR_SUCCESS if a new query was created and initialized,
  675. and a PDH_ error value if not.
  676. PDH_INVALID_ARGUMENT is returned when one or more of the arguements
  677. is invalid or incorrect.
  678. PDH_MEMORY_ALLOCATION_FAILURE is returned when a memory buffer could
  679. not be allocated.
  680. --*/
  681. {
  682. DWORD dwReturn = ERROR_SUCCESS;
  683. PDH_HQUERY hLocalQuery = NULL;
  684. if (phQuery == NULL) {
  685. dwReturn = PDH_INVALID_ARGUMENT;
  686. }
  687. else {
  688. dwReturn = PdhOpenQuery(NULL, 0, & hLocalQuery);
  689. }
  690. if (dwReturn == ERROR_SUCCESS) {
  691. __try {
  692. * phQuery = hLocalQuery;
  693. }
  694. __except (EXCEPTION_EXECUTE_HANDLER) {
  695. dwReturn = PDH_INVALID_ARGUMENT;
  696. }
  697. }
  698. return dwReturn;
  699. }
  700. DWORD
  701. PdhVbIsGoodStatus(
  702. IN LONG lStatus
  703. )
  704. /*++
  705. Routine Description:
  706. Checks the status severity of the PDH status value
  707. passed into the function as a binary Good (TRUE)/Bad (FALSE)
  708. value.
  709. Arguments:
  710. IN LONG lStatus
  711. Status code to test
  712. Return Value:
  713. TRUE if the status code is Success or Informational severity
  714. FALSE if the status code is Error or Warning severity
  715. --*/
  716. {
  717. BOOL bReturn;
  718. if (lStatus == ERROR_SUCCESS) {
  719. bReturn = TRUE;
  720. }
  721. else if (IsSuccessSeverity(lStatus)) {
  722. bReturn = TRUE;
  723. }
  724. else if (IsInformationalSeverity(lStatus)) {
  725. bReturn = TRUE;
  726. }
  727. else {
  728. bReturn = FALSE;
  729. }
  730. return (DWORD) bReturn;
  731. }
  732. DWORD
  733. PdhVbOpenLog(
  734. IN LPCSTR szLogFileName,
  735. IN DWORD dwAccessFlags,
  736. IN LPDWORD lpdwLogType,
  737. IN HQUERY hQuery,
  738. IN DWORD dwMaxSize,
  739. IN LPCSTR szUserCaption,
  740. IN PDH_HLOG * phLog
  741. )
  742. /*++
  743. Routine Description:
  744. Arguments:
  745. IN LPCSTR szLogFileName,
  746. IN DWORD dwAccessFlags,
  747. IN LPDWORD lpdwLogType,
  748. IN HQUERY hQuery,
  749. IN DWORD dwMaxSize,
  750. IN LPCSTR szUserCaption,
  751. IN HLOG * phLog
  752. Return Value:
  753. TRUE if the status code is Success or Informational severity
  754. FALSE if the status code is Error or Warning severity
  755. --*/
  756. {
  757. return PdhOpenLogA(szLogFileName, dwAccessFlags, lpdwLogType, hQuery, dwMaxSize, szUserCaption, phLog);
  758. }
  759. DWORD
  760. PdhVbUpdateLog(
  761. IN PDH_HLOG hLog,
  762. IN LPCSTR szUserString
  763. )
  764. /*++
  765. Routine Description:
  766. Arguments:
  767. IN HLOG hLog,
  768. IN LPCWSTR szUserString
  769. Return Value:
  770. TRUE if the status code is Success or Informational severity
  771. FALSE if the status code is Error or Warning severity
  772. --*/
  773. {
  774. return PdhUpdateLogA(hLog, szUserString);
  775. }
  776. DWORD
  777. PdhVbGetLogFileSize(
  778. IN PDH_HLOG hLog,
  779. IN LONG * lSize
  780. )
  781. /*++
  782. Routine Description:
  783. Arguments:
  784. IN HLOG hLog,
  785. IN LONGLONG * llSize
  786. Return Value:
  787. TRUE if the status code is Success or Informational severity
  788. FALSE if the status code is Error or Warning severity
  789. --*/
  790. {
  791. PDH_STATUS pdhStatus;
  792. LONGLONG llTemp;
  793. pdhStatus = PdhGetLogFileSize(hLog, & llTemp);
  794. if (pdhStatus == ERROR_SUCCESS) {
  795. if (llTemp > 0x0000000080000000) {
  796. // file size is larger than a long value
  797. pdhStatus = PDH_INSUFFICIENT_BUFFER;
  798. }
  799. else {
  800. __try {
  801. * lSize = (LONG) (llTemp & 0x000000007FFFFFFF);
  802. }
  803. __except (EXCEPTION_EXECUTE_HANDLER) {
  804. pdhStatus = PDH_INVALID_ARGUMENT;
  805. }
  806. }
  807. }
  808. return pdhStatus;
  809. }