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.

423 lines
15 KiB

  1. #include <windows.h>
  2. #include <winperf.h>
  3. #include <stdlib.h>
  4. #include <strsafe.h>
  5. #include "showperf.h"
  6. #include "perfdata.h"
  7. LPCWSTR NamesKey = L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib";
  8. LPCWSTR DefaultLangId = L"009";
  9. LPCWSTR Counters = L"Counters";
  10. LPCWSTR Help = L"Help";
  11. LPCWSTR LastHelp = L"Last Help";
  12. LPCWSTR LastCounter = L"Last Counter";
  13. LPCWSTR Slash = L"\\";
  14. // the following strings are for getting texts from perflib
  15. #define OLD_VERSION 0x010000
  16. LPCWSTR VersionName = L"Version";
  17. LPCWSTR CounterName = L"Counter ";
  18. LPCWSTR HelpName = L"Explain ";
  19. LPWSTR
  20. * BuildNameTable(
  21. LPWSTR szComputerName, // computer to query names from
  22. LPWSTR lpszLangId, // unicode value of Language subkey
  23. PDWORD pdwLastItem // size of array in elements
  24. )
  25. /*++
  26. BuildNameTable
  27. Arguments:
  28. hKeyRegistry
  29. Handle to an open registry (this can be local or remote.) and
  30. is the value returned by RegConnectRegistry or a default key.
  31. lpszLangId
  32. The unicode id of the language to look up. (default is 409)
  33. Return Value:
  34. pointer to an allocated table. (the caller must free it when finished!)
  35. the table is an array of pointers to zero terminated strings. NULL is
  36. returned if an error occured.
  37. --*/
  38. {
  39. LPWSTR * lpReturnValue = NULL;
  40. LPWSTR * lpCounterId;
  41. LPWSTR lpCounterNames;
  42. LPWSTR lpHelpText;
  43. LPWSTR lpThisName;
  44. LONG lWin32Status;
  45. DWORD dwLastError;
  46. DWORD dwValueType;
  47. DWORD dwArraySize;
  48. DWORD dwBufferSize;
  49. DWORD dwCounterSize;
  50. DWORD dwHelpSize;
  51. DWORD dwThisCounter;
  52. DWORD dwSystemVersion;
  53. DWORD dwLastId;
  54. DWORD dwLastHelpId;
  55. HKEY hKeyRegistry = NULL;
  56. HKEY hKeyValue = NULL;
  57. HKEY hKeyNames = NULL;
  58. LPWSTR lpValueNameString = NULL; //initialize to NULL
  59. WCHAR CounterNameBuffer[50];
  60. WCHAR HelpNameBuffer[50];
  61. HRESULT hError;
  62. if (szComputerName == NULL) {
  63. // use local machine
  64. hKeyRegistry = HKEY_LOCAL_MACHINE;
  65. }
  66. else {
  67. lWin32Status = RegConnectRegistryW(szComputerName, HKEY_LOCAL_MACHINE, & hKeyRegistry);
  68. if (lWin32Status != ERROR_SUCCESS) {
  69. // unable to connect to registry
  70. goto BNT_BAILOUT;
  71. }
  72. }
  73. // check for null arguments and insert defaults if necessary
  74. if (lpszLangId == NULL) {
  75. lpszLangId = (LPWSTR) DefaultLangId;
  76. }
  77. // open registry to get number of items for computing array size
  78. lWin32Status = RegOpenKeyExW(hKeyRegistry, NamesKey, RESERVED, KEY_READ, & hKeyValue);
  79. if (lWin32Status != ERROR_SUCCESS) {
  80. goto BNT_BAILOUT;
  81. }
  82. // get number of items
  83. dwBufferSize = sizeof(dwLastHelpId);
  84. lWin32Status = RegQueryValueExW(
  85. hKeyValue, LastHelp, RESERVED, & dwValueType, (LPBYTE) & dwLastHelpId, & dwBufferSize);
  86. if ((lWin32Status != ERROR_SUCCESS) || (dwValueType != REG_DWORD)) {
  87. if (lWin32Status == ERROR_SUCCESS) lWin32Status = ERROR_INVALID_DATA;
  88. goto BNT_BAILOUT;
  89. }
  90. // get number of items
  91. dwBufferSize = sizeof(dwLastId);
  92. lWin32Status = RegQueryValueExW(
  93. hKeyValue, LastCounter, RESERVED, & dwValueType, (LPBYTE) & dwLastId, & dwBufferSize);
  94. if ((lWin32Status != ERROR_SUCCESS) || (dwValueType != REG_DWORD)) {
  95. if (lWin32Status == ERROR_SUCCESS) lWin32Status = ERROR_INVALID_DATA;
  96. goto BNT_BAILOUT;
  97. }
  98. if (dwLastId < dwLastHelpId) dwLastId = dwLastHelpId;
  99. dwArraySize = dwLastId * sizeof(LPWSTR);
  100. // get Perflib system version
  101. dwBufferSize = sizeof(dwSystemVersion);
  102. lWin32Status = RegQueryValueExW(
  103. hKeyValue, VersionName, RESERVED, & dwValueType, (LPBYTE) & dwSystemVersion, & dwBufferSize);
  104. if ((lWin32Status != ERROR_SUCCESS) || (dwValueType != REG_DWORD)) {
  105. dwSystemVersion = OLD_VERSION;
  106. }
  107. if (dwSystemVersion == OLD_VERSION) {
  108. // get names from registry
  109. lpValueNameString = MemoryAllocate(
  110. (lstrlenW(NamesKey) + lstrlenW(Slash) + lstrlenW(lpszLangId) + 1) * sizeof (WCHAR));
  111. if (lpValueNameString == NULL) {
  112. lWin32Status = ERROR_OUTOFMEMORY;
  113. goto BNT_BAILOUT;
  114. }
  115. hError = StringCbPrintfW(lpValueNameString, MemorySize(lpValueNameString), L"%ws%ws%ws",
  116. NamesKey, Slash, lpszLangId);
  117. if (SUCCEEDED(hError)) {
  118. lWin32Status = RegOpenKeyExW(hKeyRegistry, lpValueNameString, RESERVED, KEY_READ, & hKeyNames);
  119. }
  120. else {
  121. lWin32Status = HRESULT_CODE(hError);
  122. }
  123. MemoryFree(lpValueNameString);
  124. }
  125. else {
  126. if (szComputerName == NULL) {
  127. hKeyNames = HKEY_PERFORMANCE_DATA;
  128. }
  129. else {
  130. lWin32Status = RegConnectRegistryW(szComputerName, HKEY_PERFORMANCE_DATA, & hKeyNames);
  131. if (lWin32Status != ERROR_SUCCESS) {
  132. goto BNT_BAILOUT;
  133. }
  134. }
  135. hError = StringCchPrintfW(CounterNameBuffer, RTL_NUMBER_OF(CounterNameBuffer), L"%ws%ws",
  136. CounterName, lpszLangId);
  137. if (SUCCEEDED(hError)) {
  138. hError = StringCchPrintfW(HelpNameBuffer, RTL_NUMBER_OF(HelpNameBuffer), L"%ws%ws", HelpName, lpszLangId);
  139. if (FAILED(hError)) lWin32Status = HRESULT_CODE(hError);
  140. }
  141. else {
  142. lWin32Status = HRESULT_CODE(hError);
  143. }
  144. }
  145. if (lWin32Status != ERROR_SUCCESS) goto BNT_BAILOUT;
  146. // get size of counter names and add that to the arrays
  147. dwBufferSize = 0;
  148. lWin32Status = RegQueryValueExW(hKeyNames,
  149. dwSystemVersion == OLD_VERSION ? Counters : CounterNameBuffer,
  150. RESERVED,
  151. & dwValueType,
  152. NULL,
  153. & dwBufferSize);
  154. if (lWin32Status != ERROR_SUCCESS) goto BNT_BAILOUT;
  155. dwCounterSize = dwBufferSize;
  156. // get size of counter names and add that to the arrays
  157. if (lWin32Status != ERROR_SUCCESS) goto BNT_BAILOUT;
  158. dwBufferSize = 0;
  159. lWin32Status = RegQueryValueExW(hKeyNames,
  160. dwSystemVersion == OLD_VERSION ? Help : HelpNameBuffer,
  161. RESERVED,
  162. & dwValueType,
  163. NULL,
  164. & dwBufferSize);
  165. if (lWin32Status != ERROR_SUCCESS) goto BNT_BAILOUT;
  166. dwHelpSize = dwBufferSize;
  167. lpReturnValue = MemoryAllocate(dwArraySize + dwCounterSize + dwHelpSize);
  168. if (lpReturnValue == NULL) {
  169. lWin32Status = ERROR_OUTOFMEMORY;
  170. goto BNT_BAILOUT;
  171. }
  172. // initialize pointers into buffer
  173. lpCounterId = lpReturnValue;
  174. lpCounterNames = (LPWSTR) ((LPBYTE) lpCounterId + dwArraySize);
  175. lpHelpText = (LPWSTR) ((LPBYTE) lpCounterNames + dwCounterSize);
  176. // read counters into memory
  177. dwBufferSize = dwCounterSize;
  178. lWin32Status = RegQueryValueExW(hKeyNames,
  179. dwSystemVersion == OLD_VERSION ? Counters : CounterNameBuffer,
  180. RESERVED,
  181. & dwValueType,
  182. (LPVOID) lpCounterNames,
  183. & dwBufferSize);
  184. if (lWin32Status != ERROR_SUCCESS) goto BNT_BAILOUT;
  185. dwBufferSize = dwHelpSize;
  186. lWin32Status = RegQueryValueExW(hKeyNames,
  187. dwSystemVersion == OLD_VERSION ? Help : HelpNameBuffer,
  188. RESERVED,
  189. & dwValueType,
  190. (LPVOID) lpHelpText,
  191. & dwBufferSize);
  192. if (lWin32Status != ERROR_SUCCESS) goto BNT_BAILOUT;
  193. // load counter array items
  194. for (lpThisName = lpCounterNames; * lpThisName != L'\0'; lpThisName += (lstrlenW(lpThisName) + 1)) {
  195. // first string should be an integer (in decimal unicode digits)
  196. dwThisCounter = wcstoul(lpThisName, NULL, 10);
  197. if (dwThisCounter > 0 && dwThisCounter < dwLastId) {
  198. // point to corresponding counter name
  199. lpThisName += (lstrlenW(lpThisName) + 1);
  200. // and load array element;
  201. lpCounterId[dwThisCounter] = lpThisName;
  202. }
  203. }
  204. for (lpThisName = lpHelpText; * lpThisName != L'\0'; lpThisName += (lstrlenW(lpThisName) + 1)) {
  205. // first string should be an integer (in decimal unicode digits)
  206. dwThisCounter = wcstoul(lpThisName, NULL, 10);
  207. if (dwThisCounter > 0 && dwThisCounter < dwLastId) {
  208. // point to corresponding counter name
  209. lpThisName += (lstrlenW(lpThisName) + 1);
  210. // and load array element;
  211. lpCounterId[dwThisCounter] = lpThisName;
  212. }
  213. }
  214. if (pdwLastItem) * pdwLastItem = dwLastId;
  215. BNT_BAILOUT:
  216. if (lWin32Status != ERROR_SUCCESS) {
  217. MemoryFree(lpReturnValue);
  218. dwLastError = GetLastError();
  219. lpReturnValue = NULL;
  220. }
  221. if (hKeyValue != NULL) RegCloseKey(hKeyValue);
  222. if (hKeyNames != NULL && hKeyNames != HKEY_PERFORMANCE_DATA) RegCloseKey(hKeyNames);
  223. if (hKeyRegistry != NULL) RegCloseKey(hKeyRegistry);
  224. return lpReturnValue;
  225. }
  226. PPERF_OBJECT_TYPE
  227. FirstObject(
  228. PPERF_DATA_BLOCK pPerfData
  229. )
  230. {
  231. return ((PPERF_OBJECT_TYPE) ((PBYTE) pPerfData + pPerfData->HeaderLength));
  232. }
  233. PPERF_OBJECT_TYPE
  234. NextObject(
  235. PPERF_OBJECT_TYPE pObject
  236. )
  237. { // NextObject
  238. DWORD dwOffset = pObject->TotalByteLength;
  239. return (dwOffset != 0) ? ((PPERF_OBJECT_TYPE) (((LPBYTE) pObject) + dwOffset)) : (NULL);
  240. } // NextObject
  241. PPERF_OBJECT_TYPE
  242. GetObjectDefByTitleIndex(
  243. PPERF_DATA_BLOCK pDataBlock,
  244. DWORD ObjectTypeTitleIndex
  245. )
  246. {
  247. DWORD NumTypeDef;
  248. PPERF_OBJECT_TYPE pObjectDef;
  249. PPERF_OBJECT_TYPE pRtnObject = NULL;
  250. if (pDataBlock != NULL) {
  251. pObjectDef = FirstObject(pDataBlock);
  252. for (NumTypeDef = 0; pRtnObject == NULL && NumTypeDef < pDataBlock->NumObjectTypes; NumTypeDef ++) {
  253. if (pObjectDef->ObjectNameTitleIndex == ObjectTypeTitleIndex ) {
  254. pRtnObject = pObjectDef;
  255. break;
  256. }
  257. else {
  258. pObjectDef = NextObject(pObjectDef);
  259. }
  260. }
  261. }
  262. return pRtnObject;
  263. }
  264. PPERF_INSTANCE_DEFINITION
  265. FirstInstance(
  266. PPERF_OBJECT_TYPE pObjectDef
  267. )
  268. {
  269. return (PPERF_INSTANCE_DEFINITION) ((LPBYTE) pObjectDef + pObjectDef->DefinitionLength);
  270. }
  271. PPERF_INSTANCE_DEFINITION
  272. NextInstance(
  273. PPERF_INSTANCE_DEFINITION pInstDef
  274. )
  275. {
  276. PPERF_COUNTER_BLOCK pCounterBlock = (PPERF_COUNTER_BLOCK) ((LPBYTE) pInstDef + pInstDef->ByteLength);
  277. return (PPERF_INSTANCE_DEFINITION) ((LPBYTE) pCounterBlock + pCounterBlock->ByteLength);
  278. }
  279. PPERF_INSTANCE_DEFINITION
  280. GetInstance(
  281. PPERF_OBJECT_TYPE pObjectDef,
  282. LONG InstanceNumber
  283. )
  284. {
  285. PPERF_INSTANCE_DEFINITION pRtnInstance = NULL;
  286. PPERF_INSTANCE_DEFINITION pInstanceDef;
  287. LONG NumInstance;
  288. if (pObjectDef != NULL) {
  289. pInstanceDef = FirstInstance(pObjectDef);
  290. for (NumInstance = 0; pRtnInstance == NULL && NumInstance < pObjectDef->NumInstances; NumInstance ++) {
  291. if (InstanceNumber == NumInstance) {
  292. pRtnInstance = pInstanceDef;
  293. break;
  294. }
  295. else {
  296. pInstanceDef = NextInstance(pInstanceDef);
  297. }
  298. }
  299. }
  300. return pRtnInstance;
  301. }
  302. PPERF_COUNTER_DEFINITION
  303. FirstCounter(
  304. PPERF_OBJECT_TYPE pObjectDef
  305. )
  306. {
  307. return (PPERF_COUNTER_DEFINITION) ((LPBYTE) pObjectDef + pObjectDef->HeaderLength);
  308. }
  309. PPERF_COUNTER_DEFINITION
  310. NextCounter(
  311. PPERF_COUNTER_DEFINITION pCounterDef
  312. )
  313. {
  314. DWORD dwOffset = pCounterDef->ByteLength;
  315. return (dwOffset != 0) ? ((PPERF_COUNTER_DEFINITION) (((LPBYTE) pCounterDef) + dwOffset)) : (NULL);
  316. }
  317. LONG
  318. GetSystemPerfData(
  319. HKEY hKeySystem,
  320. PPERF_DATA_BLOCK * pPerfData,
  321. DWORD dwIndex // 0 = Global, 1 = Costly
  322. )
  323. { // GetSystemPerfData
  324. LONG lError = ERROR_SUCCESS;
  325. BOOL bAlloc = FALSE;
  326. DWORD Size;
  327. DWORD Type;
  328. if (dwIndex >= 2) {
  329. lError = ! ERROR_SUCCESS;
  330. }
  331. else {
  332. if (* pPerfData == NULL) {
  333. * pPerfData = MemoryAllocate(INITIAL_SIZE);
  334. bAlloc = TRUE;
  335. if (* pPerfData == NULL) {
  336. lError = ERROR_OUTOFMEMORY;
  337. }
  338. }
  339. if (lError == ERROR_SUCCESS) {
  340. lError = ERROR_MORE_DATA;
  341. while (lError == ERROR_MORE_DATA) {
  342. Size = MemorySize(* pPerfData);
  343. lError = RegQueryValueExW(hKeySystem,
  344. dwIndex == 0 ? L"Global" : L"Costly",
  345. RESERVED,
  346. & Type,
  347. (LPBYTE) * pPerfData,
  348. & Size);
  349. if (lError == ERROR_MORE_DATA) {
  350. PPERF_DATA_BLOCK pTmpBlock = * pPerfData;
  351. * pPerfData = MemoryResize(* pPerfData, MemorySize(* pPerfData) + INITIAL_SIZE);
  352. bAlloc = TRUE;
  353. if (* pPerfData == NULL) {
  354. MemoryFree(pTmpBlock);
  355. lError = ERROR_OUTOFMEMORY;
  356. }
  357. }
  358. else if ((lError == ERROR_SUCCESS) && (Size > 0)
  359. && ((* pPerfData)->Signature[0] == L'P')
  360. && ((* pPerfData)->Signature[1] == L'E')
  361. && ((* pPerfData)->Signature[2] == L'R')
  362. && ((* pPerfData)->Signature[3] == L'F')) {
  363. // does nothing, will break out while loop and return;
  364. }
  365. else if (lError == ERROR_SUCCESS) {
  366. // RegQueryValueEx() return bogus counter datablock, bail out.
  367. lError = ERROR_INVALID_DATA;
  368. }
  369. }
  370. }
  371. }
  372. if (lError != ERROR_SUCCESS) {
  373. if (bAlloc = TRUE && * pPerfData != NULL) {
  374. MemoryFree(* pPerfData);
  375. * pPerfData = NULL;
  376. }
  377. }
  378. return (lError);
  379. } // GetSystemPerfData