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.

331 lines
7.9 KiB

  1. /******************************************************************************
  2. P E R F O R M A N C E D A T A
  3. Name: perfdata.c
  4. Description:
  5. This module together with objdata.c, instdata.c, and cntrdata.c
  6. access the performance data.
  7. ******************************************************************************/
  8. #include <windows.h>
  9. #include <winperf.h>
  10. #include "perfdata.h"
  11. #include <stdlib.h>
  12. LPTSTR *gPerfTitleSz;
  13. LPTSTR TitleData;
  14. //*********************************************************************
  15. //
  16. // GetPerfData
  17. //
  18. // Get a new set of performance data.
  19. //
  20. // *ppData should be NULL initially.
  21. // This function will allocate a buffer big enough to hold the
  22. // data requested by szObjectIndex.
  23. //
  24. // *pDataSize specifies the initial buffer size. If the size is
  25. // too small, the function will increase it until it is big enough
  26. // then return the size through *pDataSize. Caller should
  27. // deallocate *ppData if it is no longer being used.
  28. //
  29. // Returns ERROR_SUCCESS if no error occurs.
  30. //
  31. // Note: the trial and error loop is quite different from the normal
  32. // registry operation. Normally if the buffer is too small,
  33. // RegQueryValueEx returns the required size. In this case,
  34. // the perflib, since the data is dynamic, a buffer big enough
  35. // for the moment may not be enough for the next. Therefor,
  36. // the required size is not returned.
  37. //
  38. // One should start with a resonable size to avoid the overhead
  39. // of reallocation of memory.
  40. //
  41. DWORD GetPerfData (HKEY hPerfKey,
  42. LPTSTR szObjectIndex,
  43. PPERF_DATA *ppData,
  44. DWORD *pDataSize)
  45. {
  46. DWORD DataSize;
  47. DWORD dwR;
  48. DWORD Type;
  49. if (!*ppData)
  50. *ppData = (PPERF_DATA) LocalAlloc (LMEM_FIXED, *pDataSize);
  51. do {
  52. DataSize = *pDataSize;
  53. dwR = RegQueryValueEx (hPerfKey,
  54. szObjectIndex,
  55. NULL,
  56. &Type,
  57. (BYTE *)*ppData,
  58. &DataSize);
  59. if (dwR == ERROR_MORE_DATA)
  60. {
  61. LocalFree (*ppData);
  62. *pDataSize += 1024;
  63. *ppData = (PPERF_DATA) LocalAlloc (LMEM_FIXED, *pDataSize);
  64. }
  65. if (!*ppData)
  66. {
  67. LocalFree (*ppData);
  68. return ERROR_NOT_ENOUGH_MEMORY;
  69. }
  70. } while (dwR == ERROR_MORE_DATA);
  71. return dwR;
  72. }
  73. #ifdef UNICODE
  74. #define atoi atoiW
  75. //*********************************************************************
  76. //
  77. // atoiW
  78. //
  79. // Unicode version of atoi.
  80. //
  81. INT atoiW (LPTSTR s)
  82. {
  83. INT i = 0;
  84. while (iswdigit (*s))
  85. {
  86. i = i*10 + (BYTE)*s - L'0';
  87. s++;
  88. }
  89. return i;
  90. }
  91. #endif
  92. //*********************************************************************
  93. //
  94. // GetPerfTitleSz
  95. //
  96. // Retrieves the performance data title strings.
  97. //
  98. // This call retrieves english version of the title strings.
  99. //
  100. // For NT 1.0, the counter names are stored in the "Counters" value
  101. // in the ...\perflib\009 key. For 1.0a and later, the 009 key is no
  102. // longer used. The counter names should be retrieved from "Counter 009"
  103. // value of HKEY_PERFORMANCE_KEY.
  104. //
  105. // Caller should provide two pointers, one for buffering the title
  106. // strings the other for indexing the title strings. This function will
  107. // allocate memory for the TitleBuffer and TitleSz. To get the title
  108. // string for a particular title index one would just index the TitleSz.
  109. // *TitleLastIdx returns the highest index can be used. If TitleSz[N] is
  110. // NULL then there is no Title for index N.
  111. //
  112. // Example: TitleSz[20] points to titile string for title index 20.
  113. //
  114. // When done with the TitleSz, caller should LocalFree(*TitleBuffer).
  115. //
  116. // This function returns ERROR_SUCCESS if no error.
  117. //
  118. DWORD GetPerfTitleSz (HKEY hKeyMachine,
  119. HKEY hKeyPerf,
  120. LPTSTR *TitleBuffer,
  121. LPTSTR *TitleSz[],
  122. DWORD *TitleLastIdx)
  123. {
  124. HKEY hKey1;
  125. HKEY hKey2;
  126. DWORD Type;
  127. DWORD DataSize;
  128. DWORD dwR;
  129. DWORD Len;
  130. DWORD Index;
  131. DWORD dwTemp;
  132. BOOL bNT10;
  133. LPTSTR szCounterValueName;
  134. LPTSTR szTitle;
  135. // Initialize
  136. //
  137. hKey1 = NULL;
  138. hKey2 = NULL;
  139. *TitleBuffer = NULL;
  140. *TitleSz = NULL;
  141. // Open the perflib key to find out the last counter's index and system version.
  142. //
  143. dwR = RegOpenKeyEx (hKeyMachine,
  144. TEXT("software\\microsoft\\windows nt\\currentversion\\perflib"),
  145. 0,
  146. KEY_READ,
  147. &hKey1);
  148. if (dwR != ERROR_SUCCESS)
  149. goto done;
  150. // Get the last counter's index so we know how much memory to allocate for TitleSz
  151. //
  152. DataSize = sizeof (DWORD);
  153. dwR = RegQueryValueEx (hKey1, TEXT("Last Counter"), 0, &Type, (LPBYTE)TitleLastIdx, &DataSize);
  154. if (dwR != ERROR_SUCCESS)
  155. goto done;
  156. // Find system version, for system earlier than 1.0a, there's no version value.
  157. //
  158. dwR = RegQueryValueEx (hKey1, TEXT("Version"), 0, &Type, (LPBYTE)&dwTemp, &DataSize);
  159. if (dwR != ERROR_SUCCESS)
  160. // unable to read the value, assume NT 1.0
  161. bNT10 = TRUE;
  162. else
  163. // found the value, so, NT 1.0a or later
  164. bNT10 = FALSE;
  165. // Now, get ready for the counter names and indexes.
  166. //
  167. if (bNT10)
  168. {
  169. // NT 1.0, so make hKey2 point to ...\perflib\009 and get
  170. // the counters from value "Counters"
  171. //
  172. szCounterValueName = TEXT("Counters");
  173. dwR = RegOpenKeyEx (hKeyMachine,
  174. TEXT("software\\microsoft\\windows nt\\currentversion\\perflib\\009"),
  175. 0,
  176. KEY_READ,
  177. &hKey2);
  178. if (dwR != ERROR_SUCCESS)
  179. goto done;
  180. }
  181. else
  182. {
  183. // NT 1.0a or later. Get the counters in key HKEY_PERFORMANCE_KEY
  184. // and from value "Counter 009"
  185. //
  186. szCounterValueName = TEXT("Counter 009");
  187. hKey2 = hKeyPerf;
  188. }
  189. // Find out the size of the data.
  190. //
  191. dwR = RegQueryValueEx (hKey2, szCounterValueName, 0, &Type, 0, &DataSize);
  192. if (dwR != ERROR_SUCCESS)
  193. goto done;
  194. // Allocate memory
  195. //
  196. *TitleBuffer = (LPTSTR)LocalAlloc (LMEM_FIXED, DataSize);
  197. if (!*TitleBuffer)
  198. {
  199. dwR = ERROR_NOT_ENOUGH_MEMORY;
  200. goto done;
  201. }
  202. *TitleSz = (LPTSTR *)LocalAlloc (LPTR, (*TitleLastIdx+1) * sizeof (LPTSTR));
  203. if (!*TitleSz)
  204. {
  205. dwR = ERROR_NOT_ENOUGH_MEMORY;
  206. goto done;
  207. }
  208. // Query the data
  209. //
  210. dwR = RegQueryValueEx (hKey2, szCounterValueName, 0, &Type, (BYTE *)*TitleBuffer, &DataSize);
  211. if (dwR != ERROR_SUCCESS)
  212. goto done;
  213. // Setup the TitleSz array of pointers to point to beginning of each title string.
  214. // TitleBuffer is type REG_MULTI_SZ.
  215. //
  216. szTitle = *TitleBuffer;
  217. while (Len = lstrlen (szTitle))
  218. {
  219. Index = atoi (szTitle);
  220. szTitle = szTitle + Len +1;
  221. if (Index <= *TitleLastIdx)
  222. (*TitleSz)[Index] = szTitle;
  223. szTitle = szTitle + lstrlen (szTitle) +1;
  224. }
  225. done:
  226. // Done. Now cleanup!
  227. //
  228. if (dwR != ERROR_SUCCESS)
  229. {
  230. // There was an error, free the allocated memory
  231. //
  232. if (*TitleBuffer) LocalFree (*TitleBuffer);
  233. if (*TitleSz) LocalFree (*TitleSz);
  234. }
  235. // Close the hKeys.
  236. //
  237. if (hKey1) RegCloseKey (hKey1);
  238. if (hKey2 && hKey2 != hKeyPerf) RegCloseKey (hKey2);
  239. return dwR;
  240. }