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.

1180 lines
40 KiB

  1. /*++
  2. Copyright (c) 1991-1999 Microsoft Corporation
  3. Module Name:
  4. dumpload.c
  5. Abstract:
  6. functions to dump and load the contents of the performance related registry
  7. entries
  8. Author:
  9. Bob Watson (bobw) 13 Jun 99
  10. Revision History:
  11. --*/
  12. #ifndef UNICODE
  13. #define UNICODE 1
  14. #endif
  15. #ifndef _UNICODE
  16. #define _UNICODE 1
  17. #endif
  18. //
  19. // "C" Include files
  20. //
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <malloc.h>
  25. //
  26. // Windows Include files
  27. //
  28. #include <windows.h>
  29. #include <winperf.h>
  30. #include <loadperf.h>
  31. #include "wmistr.h"
  32. #include "evntrace.h"
  33. //
  34. // application include files
  35. //
  36. #include "winperfp.h"
  37. #include "common.h"
  38. #include "ldprfmsg.h"
  39. static const WCHAR cszServiceKeyName[] = {L"SYSTEM\\CurrentControlSet\\Services"};
  40. static const WCHAR cszPerflibKeyName[] = {L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib"};
  41. static const WCHAR cszLastCounter[] = {L"Last Counter"};
  42. static const WCHAR cszFirstHelp[] = {L"First Help"};
  43. static const WCHAR cszLastHelp[] = {L"Last Help"};
  44. static const WCHAR cszBaseIndex[] = {L"Base Index"};
  45. static const WCHAR cszPerformance[] = {L"\\Performance"};
  46. static const WCHAR cszDisablePerformanceCounters[] = {L"Disable Performance Counters"};
  47. // headings in save file
  48. static const WCHAR cszFmtSectionHeader[] = {L"\r\n\r\n[%s]"};
  49. static const WCHAR cszFmtServiceSectionHeader[] = {L"\r\n\r\n[PERF_%s]"};
  50. static const WCHAR cszFmtServiceSectionName[] = {L"PERF_%s"};
  51. static const WCHAR cszFmtStringSectionHeader[] = {L"\r\n\r\n[PerfStrings_%s]"};
  52. static const WCHAR cszFmtExtCtrString[] = {L"\r\n%d=%s"};
  53. static const WCHAR cszFmtDecimalParam[] = {L"\r\n%s=%d"};
  54. static const WCHAR cszFmtNoParam[] = {L"\r\n%s="};
  55. static const WCHAR cszExtensiblePerfStrings[] = {L"Strings"};
  56. static const WCHAR cszPerfCounterServices[] = {L"PerfCounterServices"};
  57. static const WCHAR cszNoPerfCounterServices[] = {L"NoPerfCounterServices"};
  58. static const WCHAR cszPerflib[] = {L"Perflib"};
  59. // external forward definitions
  60. LPWSTR
  61. *BuildNameTable(
  62. HKEY hKeyRegistry, // handle to registry db with counter names
  63. LPWSTR lpszLangId, // unicode value of Language subkey
  64. PDWORD pdwLastItem // size of array in elements
  65. );
  66. DWORD
  67. UpdatePerfNameFilesX (
  68. IN LPCWSTR szNewCtrFilePath, // data file with new base counter strings
  69. IN LPCWSTR szNewHlpFilePath, // data file with new base counter strings
  70. IN LPWSTR szLanguageID, // Lang ID to update
  71. IN ULONG_PTR dwFlags // flags
  72. );
  73. DWORD
  74. static
  75. DumpNameTable (
  76. IN HANDLE hOutputFile,
  77. IN LPCWSTR szLangId,
  78. IN LPCWSTR *pszNameTable,
  79. IN DWORD dwStartIndex,
  80. IN DWORD dwLastIndex
  81. )
  82. {
  83. DWORD ndx;
  84. WCHAR szOutputBuffer[4096];
  85. DWORD dwSize, dwSizeWritten;
  86. dwSize = swprintf (szOutputBuffer, cszFmtStringSectionHeader, szLangId);
  87. dwSize *= sizeof (WCHAR);
  88. WriteFile (hOutputFile, szOutputBuffer, dwSize, &dwSizeWritten, NULL);
  89. for (ndx = dwStartIndex; ndx <= dwLastIndex; ndx++) {
  90. if (pszNameTable[ndx] != NULL) {
  91. dwSize = swprintf (szOutputBuffer, cszFmtExtCtrString, ndx, pszNameTable[ndx] );
  92. dwSize *= sizeof (WCHAR);
  93. WriteFile (hOutputFile, szOutputBuffer, dwSize, &dwSizeWritten, NULL);
  94. }
  95. }
  96. return ERROR_SUCCESS;
  97. }
  98. DWORD
  99. static
  100. DumpPerfServiceEntries (
  101. IN HANDLE hOutputFile,
  102. IN LPCWSTR szServiceName
  103. )
  104. {
  105. LONG lStatus = ERROR_SUCCESS;
  106. WCHAR szPerfSubKeyName[MAX_PATH+20];
  107. HKEY hKeyPerformance;
  108. HKEY hKeyServices = NULL;
  109. DWORD dwItemSize, dwType, dwValue;
  110. DWORD dwRegAccessMask;
  111. DWORD dwRetStatus = ERROR_SUCCESS;
  112. DWORD dwSize, dwSizeWritten;
  113. WCHAR szOutputBuffer[4096];
  114. // try read-only then
  115. dwRegAccessMask = KEY_READ;
  116. lStatus = RegOpenKeyExW (HKEY_LOCAL_MACHINE,
  117. cszServiceKeyName,
  118. 0L,
  119. dwRegAccessMask,
  120. &hKeyServices);
  121. if (lStatus == ERROR_SUCCESS) {
  122. //try to open the perfkey under this key.
  123. lstrcpy (szPerfSubKeyName, szServiceName);
  124. lstrcat (szPerfSubKeyName, cszPerformance);
  125. lStatus = RegOpenKeyExW (
  126. hKeyServices,
  127. szPerfSubKeyName,
  128. 0L,
  129. dwRegAccessMask,
  130. &hKeyPerformance);
  131. if (lStatus == ERROR_SUCCESS) {
  132. // key found so service has perf data
  133. dwSize = swprintf (szOutputBuffer, cszFmtServiceSectionHeader, szServiceName);
  134. dwSize *= sizeof (WCHAR);
  135. WriteFile (hOutputFile, szOutputBuffer, dwSize, &dwSizeWritten, NULL);
  136. // now check to see if the strings have been loaded
  137. dwType = dwValue = 0;
  138. dwItemSize = sizeof (dwValue);
  139. lStatus = RegQueryValueExW (
  140. hKeyPerformance,
  141. cszFirstCounter,
  142. NULL,
  143. &dwType,
  144. (LPBYTE)&dwValue,
  145. &dwItemSize);
  146. TRACE((WINPERF_DBG_TRACE_INFO),
  147. (& LoadPerfGuid,
  148. __LINE__,
  149. LOADPERF_DUMPPERFSERVICEENTRIES,
  150. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  151. lStatus,
  152. TRACE_WSTR(szServiceName),
  153. TRACE_WSTR(cszFirstCounter),
  154. TRACE_DWORD(dwValue),
  155. NULL));
  156. if ((lStatus == ERROR_SUCCESS) &&
  157. ((dwType == REG_DWORD) || dwType == REG_BINARY)) {
  158. dwSize = swprintf (szOutputBuffer, cszFmtDecimalParam, cszFirstCounter, dwValue);
  159. dwSize *= sizeof (WCHAR);
  160. WriteFile (hOutputFile, szOutputBuffer, dwSize, &dwSizeWritten, NULL);
  161. }
  162. dwType = dwValue = 0;
  163. dwItemSize = sizeof (dwValue);
  164. lStatus = RegQueryValueExW (
  165. hKeyPerformance,
  166. cszFirstHelp,
  167. NULL,
  168. &dwType,
  169. (LPBYTE)&dwValue,
  170. &dwItemSize);
  171. TRACE((WINPERF_DBG_TRACE_INFO),
  172. (& LoadPerfGuid,
  173. __LINE__,
  174. LOADPERF_DUMPPERFSERVICEENTRIES,
  175. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  176. lStatus,
  177. TRACE_WSTR(szServiceName),
  178. TRACE_WSTR(cszFirstHelp),
  179. TRACE_DWORD(dwValue),
  180. NULL));
  181. if ((lStatus == ERROR_SUCCESS) &&
  182. ((dwType == REG_DWORD) || dwType == REG_BINARY)) {
  183. dwSize = swprintf (szOutputBuffer, cszFmtDecimalParam, cszFirstHelp, dwValue);
  184. dwSize *= sizeof (WCHAR);
  185. WriteFile (hOutputFile, szOutputBuffer, dwSize, &dwSizeWritten, NULL);
  186. }
  187. dwType = dwValue = 0;
  188. dwItemSize = sizeof (dwValue);
  189. lStatus = RegQueryValueExW (
  190. hKeyPerformance,
  191. cszLastCounter,
  192. NULL,
  193. &dwType,
  194. (LPBYTE)&dwValue,
  195. &dwItemSize);
  196. TRACE((WINPERF_DBG_TRACE_INFO),
  197. (& LoadPerfGuid,
  198. __LINE__,
  199. LOADPERF_DUMPPERFSERVICEENTRIES,
  200. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  201. lStatus,
  202. TRACE_WSTR(szServiceName),
  203. TRACE_WSTR(cszLastCounter),
  204. TRACE_DWORD(dwValue),
  205. NULL));
  206. if ((lStatus == ERROR_SUCCESS) &&
  207. ((dwType == REG_DWORD) || dwType == REG_BINARY)) {
  208. dwSize = swprintf (szOutputBuffer, cszFmtDecimalParam, cszLastCounter, dwValue);
  209. dwSize *= sizeof (WCHAR);
  210. WriteFile (hOutputFile, szOutputBuffer, dwSize, &dwSizeWritten, NULL);
  211. }
  212. dwType = dwValue = 0;
  213. dwItemSize = sizeof (dwValue);
  214. lStatus = RegQueryValueExW (
  215. hKeyPerformance,
  216. cszLastHelp,
  217. NULL,
  218. &dwType,
  219. (LPBYTE)&dwValue,
  220. &dwItemSize);
  221. TRACE((WINPERF_DBG_TRACE_INFO),
  222. (& LoadPerfGuid,
  223. __LINE__,
  224. LOADPERF_DUMPPERFSERVICEENTRIES,
  225. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  226. lStatus,
  227. TRACE_WSTR(szServiceName),
  228. TRACE_WSTR(cszLastHelp),
  229. TRACE_DWORD(dwValue),
  230. NULL));
  231. if ((lStatus == ERROR_SUCCESS) &&
  232. ((dwType == REG_DWORD) || dwType == REG_BINARY)) {
  233. dwSize = swprintf (szOutputBuffer, cszFmtDecimalParam, cszLastHelp, dwValue);
  234. dwSize *= sizeof (WCHAR);
  235. WriteFile (hOutputFile, szOutputBuffer, dwSize, &dwSizeWritten, NULL);
  236. }
  237. dwType = dwValue = 0;
  238. dwItemSize = sizeof (dwValue);
  239. lStatus = RegQueryValueExW (
  240. hKeyPerformance,
  241. cszDisablePerformanceCounters,
  242. NULL,
  243. &dwType,
  244. (LPBYTE)&dwValue,
  245. &dwItemSize);
  246. TRACE((WINPERF_DBG_TRACE_INFO),
  247. (& LoadPerfGuid,
  248. __LINE__,
  249. LOADPERF_DUMPPERFSERVICEENTRIES,
  250. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  251. lStatus,
  252. TRACE_WSTR(szServiceName),
  253. TRACE_WSTR(cszDisablePerformanceCounters),
  254. TRACE_DWORD(dwValue),
  255. NULL));
  256. if ((lStatus == ERROR_SUCCESS) &&
  257. ((dwType == REG_DWORD) || dwType == REG_BINARY)) {
  258. dwSize = swprintf (szOutputBuffer, cszFmtDecimalParam, cszDisablePerformanceCounters, dwValue);
  259. dwSize *= sizeof (WCHAR);
  260. WriteFile (hOutputFile, szOutputBuffer, dwSize, &dwSizeWritten, NULL);
  261. }
  262. RegCloseKey (hKeyPerformance);
  263. } else {
  264. dwRetStatus = lStatus;
  265. TRACE((WINPERF_DBG_TRACE_ERROR),
  266. (& LoadPerfGuid,
  267. __LINE__,
  268. LOADPERF_DUMPPERFSERVICEENTRIES,
  269. ARG_DEF(ARG_TYPE_WSTR, 1),
  270. lStatus,
  271. TRACE_WSTR(szServiceName),
  272. NULL));
  273. }
  274. RegCloseKey (hKeyServices);
  275. }
  276. else {
  277. dwRetStatus = lStatus;
  278. TRACE((WINPERF_DBG_TRACE_ERROR),
  279. (& LoadPerfGuid,
  280. __LINE__,
  281. LOADPERF_DUMPPERFSERVICEENTRIES,
  282. ARG_DEF(ARG_TYPE_WSTR, 1),
  283. lStatus,
  284. TRACE_WSTR(cszServiceKeyName),
  285. NULL));
  286. }
  287. return dwRetStatus;
  288. }
  289. DWORD
  290. static
  291. DumpPerflibEntries (
  292. IN HANDLE hOutputFile,
  293. IN LPDWORD pdwFirstExtCtrIndex
  294. )
  295. {
  296. HKEY hKeyPerflib = NULL;
  297. DWORD dwStatus;
  298. DWORD dwItemSize, dwType, dwValue;
  299. DWORD dwSize, dwSizeWritten;
  300. WCHAR szOutputBuffer[4096];
  301. dwStatus = RegOpenKeyExW (HKEY_LOCAL_MACHINE,
  302. cszPerflibKeyName,
  303. 0L,
  304. KEY_READ,
  305. &hKeyPerflib);
  306. if (dwStatus == ERROR_SUCCESS) {
  307. dwSize = swprintf (szOutputBuffer, cszFmtSectionHeader, cszPerflib);
  308. dwSize *= sizeof (WCHAR);
  309. WriteFile (hOutputFile, szOutputBuffer, dwSize, &dwSizeWritten, NULL);
  310. }
  311. else {
  312. TRACE((WINPERF_DBG_TRACE_ERROR),
  313. (& LoadPerfGuid,
  314. __LINE__,
  315. LOADPERF_DUMPPERFLIBENTRIES,
  316. ARG_DEF(ARG_TYPE_WSTR, 1),
  317. dwStatus,
  318. TRACE_WSTR(cszPerflibKeyName),
  319. NULL));
  320. }
  321. if (dwStatus == ERROR_SUCCESS) {
  322. dwType = dwValue = 0;
  323. dwItemSize = sizeof (dwValue);
  324. dwStatus = RegQueryValueEx (
  325. hKeyPerflib,
  326. cszBaseIndex,
  327. NULL,
  328. &dwType,
  329. (LPBYTE)&dwValue,
  330. &dwItemSize);
  331. TRACE((WINPERF_DBG_TRACE_INFO),
  332. (& LoadPerfGuid,
  333. __LINE__,
  334. LOADPERF_DUMPPERFLIBENTRIES,
  335. ARG_DEF(ARG_TYPE_WSTR, 1),
  336. dwStatus,
  337. TRACE_WSTR(cszBaseIndex),
  338. TRACE_DWORD(dwValue),
  339. NULL));
  340. if ((dwStatus == ERROR_SUCCESS) && (dwType == REG_DWORD)) {
  341. dwSize = swprintf (szOutputBuffer, cszFmtDecimalParam, cszBaseIndex, dwValue);
  342. dwSize *= sizeof (WCHAR);
  343. WriteFile (hOutputFile, szOutputBuffer, dwSize, &dwSizeWritten, NULL);
  344. *pdwFirstExtCtrIndex = dwValue + 1;
  345. }
  346. }
  347. if (dwStatus == ERROR_SUCCESS) {
  348. dwType = dwValue = 0;
  349. dwItemSize = sizeof (dwValue);
  350. dwStatus = RegQueryValueEx (
  351. hKeyPerflib,
  352. cszLastCounter,
  353. NULL,
  354. &dwType,
  355. (LPBYTE)&dwValue,
  356. &dwItemSize);
  357. TRACE((WINPERF_DBG_TRACE_INFO),
  358. (& LoadPerfGuid,
  359. __LINE__,
  360. LOADPERF_DUMPPERFLIBENTRIES,
  361. ARG_DEF(ARG_TYPE_WSTR, 1),
  362. dwStatus,
  363. TRACE_WSTR(cszLastCounter),
  364. TRACE_DWORD(dwValue),
  365. NULL));
  366. if ((dwStatus == ERROR_SUCCESS) && (dwType == REG_DWORD)) {
  367. dwSize = swprintf (szOutputBuffer, cszFmtDecimalParam, cszLastCounter, dwValue);
  368. dwSize *= sizeof (WCHAR);
  369. WriteFile (hOutputFile, szOutputBuffer, dwSize, &dwSizeWritten, NULL);
  370. }
  371. }
  372. if (dwStatus == ERROR_SUCCESS) {
  373. dwType = dwValue = 0;
  374. dwItemSize = sizeof (dwValue);
  375. dwStatus = RegQueryValueEx (
  376. hKeyPerflib,
  377. cszLastHelp,
  378. NULL,
  379. &dwType,
  380. (LPBYTE)&dwValue,
  381. &dwItemSize);
  382. TRACE((WINPERF_DBG_TRACE_INFO),
  383. (& LoadPerfGuid,
  384. __LINE__,
  385. LOADPERF_DUMPPERFLIBENTRIES,
  386. ARG_DEF(ARG_TYPE_WSTR, 1),
  387. dwStatus,
  388. TRACE_WSTR(cszLastHelp),
  389. TRACE_DWORD(dwValue),
  390. NULL));
  391. if ((dwStatus == ERROR_SUCCESS) && (dwType == REG_DWORD)) {
  392. dwSize = swprintf (szOutputBuffer, cszFmtDecimalParam, cszLastHelp, dwValue);
  393. dwSize *= sizeof (WCHAR);
  394. WriteFile (hOutputFile, szOutputBuffer, dwSize, &dwSizeWritten, NULL);
  395. }
  396. }
  397. if (hKeyPerflib != NULL) RegCloseKey (hKeyPerflib);
  398. return dwStatus;
  399. }
  400. DWORD
  401. static
  402. BuildServiceLists (
  403. IN LPWSTR mszPerfServiceList,
  404. IN LPDWORD pcchPerfServiceListSize,
  405. IN LPWSTR mszNoPerfServiceList,
  406. IN LPDWORD pcchNoPerfServiceListSize
  407. )
  408. {
  409. LONG lStatus = ERROR_SUCCESS;
  410. LONG lEnumStatus = ERROR_SUCCESS;
  411. DWORD dwServiceIndex = 0;
  412. WCHAR szServiceSubKeyName[MAX_PATH];
  413. WCHAR szPerfSubKeyName[MAX_PATH+20];
  414. DWORD dwNameSize = MAX_PATH;
  415. HKEY hKeyPerformance;
  416. HKEY hKeyServices = NULL;
  417. DWORD dwItemSize, dwType, dwValue;
  418. DWORD dwRegAccessMask;
  419. DWORD bServiceHasPerfCounters;
  420. DWORD dwRetStatus = ERROR_SUCCESS;
  421. LPWSTR szNextNoPerfChar, szNextPerfChar;
  422. DWORD dwNoPerfSizeRem, dwPerfSizeRem;
  423. DWORD dwPerfSizeUsed = 0, dwNoPerfSizeUsed = 0;
  424. // try read-only then
  425. dwRegAccessMask = KEY_READ;
  426. lStatus = RegOpenKeyExW (HKEY_LOCAL_MACHINE,
  427. cszServiceKeyName,
  428. 0L,
  429. dwRegAccessMask,
  430. &hKeyServices);
  431. if (lStatus == ERROR_SUCCESS) {
  432. szNextNoPerfChar = mszNoPerfServiceList;
  433. szNextPerfChar = mszPerfServiceList;
  434. dwNoPerfSizeRem = *pcchPerfServiceListSize;
  435. dwPerfSizeRem = *pcchNoPerfServiceListSize;
  436. dwPerfSizeUsed = 0;
  437. dwNoPerfSizeUsed = 0;
  438. while ((lEnumStatus = RegEnumKeyExW (
  439. hKeyServices,
  440. dwServiceIndex,
  441. szServiceSubKeyName,
  442. &dwNameSize,
  443. NULL,
  444. NULL,
  445. NULL,
  446. NULL)) == ERROR_SUCCESS) {
  447. //try to open the perfkey under this key.
  448. lstrcpy (szPerfSubKeyName, szServiceSubKeyName);
  449. lstrcat (szPerfSubKeyName, cszPerformance);
  450. lStatus = RegOpenKeyExW (
  451. hKeyServices,
  452. szPerfSubKeyName,
  453. 0L,
  454. dwRegAccessMask,
  455. &hKeyPerformance);
  456. if (lStatus == ERROR_SUCCESS) {
  457. // key found so service has perf data
  458. // now check to see if the strings have been loaded
  459. dwType = dwValue = 0;
  460. dwItemSize = sizeof (dwValue);
  461. lStatus = RegQueryValueExW (
  462. hKeyPerformance,
  463. cszFirstCounter,
  464. NULL,
  465. &dwType,
  466. (LPBYTE)&dwValue,
  467. &dwItemSize);
  468. if ((lStatus == ERROR_SUCCESS) &&
  469. ((dwType == REG_DWORD) || dwType == REG_BINARY)) {
  470. bServiceHasPerfCounters = TRUE;
  471. } else {
  472. bServiceHasPerfCounters = FALSE;
  473. }
  474. RegCloseKey (hKeyPerformance);
  475. } else {
  476. // key not found so service doesn't have perfdata
  477. bServiceHasPerfCounters = FALSE;
  478. }
  479. TRACE((WINPERF_DBG_TRACE_INFO),
  480. (& LoadPerfGuid,
  481. __LINE__,
  482. LOADPERF_BUILDSERVICELISTS,
  483. ARG_DEF(ARG_TYPE_WSTR, 1),
  484. lStatus,
  485. TRACE_WSTR(szServiceSubKeyName),
  486. TRACE_DWORD(bServiceHasPerfCounters),
  487. NULL));
  488. if (bServiceHasPerfCounters != FALSE) {
  489. // add to the perf service list
  490. if ((dwNameSize + 1)< dwPerfSizeRem) {
  491. // add to list
  492. lstrcpyW (szNextPerfChar, szServiceSubKeyName);
  493. szNextPerfChar += dwNameSize;
  494. *szNextPerfChar = 0;
  495. szNextPerfChar++;
  496. dwPerfSizeRem -= dwNameSize + 1;
  497. } else {
  498. dwRetStatus = ERROR_MORE_DATA;
  499. }
  500. dwPerfSizeUsed += dwNameSize + 1;
  501. } else {
  502. // add to the no perf list
  503. if ((dwNameSize + 1) < dwNoPerfSizeRem) {
  504. // add to list
  505. lstrcpyW (szNextNoPerfChar, szServiceSubKeyName);
  506. szNextNoPerfChar += dwNameSize;
  507. *szNextNoPerfChar = 0;
  508. szNextNoPerfChar++;
  509. dwNoPerfSizeRem -= dwNameSize + 1;
  510. } else {
  511. dwRetStatus = ERROR_MORE_DATA;
  512. }
  513. dwNoPerfSizeUsed += dwNameSize + 1;
  514. }
  515. // reset for next loop
  516. dwServiceIndex++;
  517. dwNameSize = MAX_PATH;
  518. }
  519. // zero term the MSZ
  520. if (1 < dwPerfSizeRem) {
  521. *szNextPerfChar = 0;
  522. szNextPerfChar++;
  523. dwPerfSizeRem -= 1;
  524. } else {
  525. dwRetStatus = ERROR_MORE_DATA;
  526. }
  527. dwPerfSizeUsed += 1;
  528. // zero term the no perf list
  529. if (1 < dwNoPerfSizeRem) {
  530. // add to list
  531. *szNextNoPerfChar = 0;
  532. szNextNoPerfChar++;
  533. dwNoPerfSizeRem -= 1;
  534. } else {
  535. dwRetStatus = ERROR_MORE_DATA;
  536. }
  537. dwNoPerfSizeUsed += 1;
  538. }
  539. else {
  540. TRACE((WINPERF_DBG_TRACE_ERROR),
  541. (& LoadPerfGuid,
  542. __LINE__,
  543. LOADPERF_BUILDSERVICELISTS,
  544. ARG_DEF(ARG_TYPE_WSTR, 1),
  545. lStatus,
  546. TRACE_WSTR(cszServiceKeyName),
  547. NULL));
  548. }
  549. if (hKeyServices != NULL) RegCloseKey (hKeyServices);
  550. *pcchPerfServiceListSize = dwPerfSizeUsed;
  551. *pcchNoPerfServiceListSize = dwNoPerfSizeUsed;
  552. return dwRetStatus;
  553. }
  554. DWORD
  555. BackupPerfRegistryToFileW (
  556. IN LPCWSTR szFileName,
  557. IN LPCWSTR szCommentString
  558. )
  559. {
  560. HANDLE hOutFile;
  561. DWORD dwStatus = ERROR_SUCCESS;
  562. LPWSTR szNewFileName = NULL;
  563. DWORD dwNewFileNameLen;
  564. DWORD dwOrigFileNameLen;
  565. DWORD dwFileNameSN;
  566. LPWSTR mszPerfServiceList = NULL;
  567. DWORD dwPerfServiceListSize = 0;
  568. LPWSTR mszNoPerfServiceList = NULL;
  569. DWORD dwNoPerfServiceListSize = 0;
  570. LPWSTR *lpCounterText = NULL;
  571. DWORD dwLastElement = 0;
  572. DWORD dwFirstExtCtrIndex = 0;
  573. LPWSTR szThisServiceName;
  574. LPWSTR szLangId = (LPWSTR)L"009";
  575. DBG_UNREFERENCED_PARAMETER (szCommentString);
  576. WinPerfStartTrace(NULL);
  577. // open output file
  578. hOutFile = CreateFileW (
  579. szFileName,
  580. GENERIC_WRITE,
  581. 0, // no sharing
  582. NULL, // default security
  583. CREATE_NEW,
  584. FILE_ATTRIBUTE_NORMAL,
  585. NULL);
  586. // if the file open failed
  587. if (hOutFile == INVALID_HANDLE_VALUE) {
  588. // see if it's because the file already exists
  589. dwStatus = GetLastError();
  590. if (dwStatus == ERROR_FILE_EXISTS) {
  591. // then try appending a serial number to the name
  592. dwOrigFileNameLen = lstrlenW (szFileName);
  593. dwNewFileNameLen = dwOrigFileNameLen + 4;
  594. szNewFileName = HeapAlloc (
  595. GetProcessHeap(),
  596. HEAP_ZERO_MEMORY,
  597. (dwNewFileNameLen +1) * sizeof(WCHAR));
  598. if (szNewFileName != NULL) {
  599. lstrcpyW (szNewFileName, szFileName);
  600. for (dwFileNameSN = 1; dwFileNameSN < 1000; dwFileNameSN++) {
  601. swprintf (&szNewFileName[dwOrigFileNameLen],
  602. (LPCWSTR)L"_%3.3d", dwFileNameSN);
  603. hOutFile = CreateFileW (
  604. szNewFileName,
  605. GENERIC_WRITE,
  606. 0, // no sharing
  607. NULL, // default security
  608. CREATE_NEW,
  609. FILE_ATTRIBUTE_NORMAL,
  610. NULL);
  611. // if the file open failed
  612. if (hOutFile == INVALID_HANDLE_VALUE) {
  613. dwStatus = GetLastError();
  614. if (dwStatus != ERROR_FILE_EXISTS) {
  615. // some other error occurred so bail out
  616. break;
  617. } else {
  618. continue; // with the next try
  619. }
  620. } else {
  621. // found one not in use so continue on
  622. dwStatus = ERROR_SUCCESS;
  623. break;
  624. }
  625. }
  626. } else {
  627. dwStatus = ERROR_OUTOFMEMORY;
  628. }
  629. }
  630. } else {
  631. // file opened so continue
  632. dwStatus = ERROR_SUCCESS;
  633. }
  634. if (dwStatus == ERROR_SUCCESS) {
  635. // dump perflib key entires
  636. dwStatus = DumpPerflibEntries (hOutFile, &dwFirstExtCtrIndex);
  637. }
  638. if (dwStatus == ERROR_SUCCESS) {
  639. do {
  640. if (mszPerfServiceList != NULL) {
  641. HeapFree (GetProcessHeap(), 0, mszPerfServiceList);
  642. mszPerfServiceList = NULL;
  643. }
  644. if (mszNoPerfServiceList != NULL) {
  645. HeapFree (GetProcessHeap(), 0, mszNoPerfServiceList);
  646. mszNoPerfServiceList = NULL;
  647. }
  648. // build service lists
  649. dwPerfServiceListSize += 32768;
  650. dwNoPerfServiceListSize += 65536;
  651. mszPerfServiceList = HeapAlloc (
  652. GetProcessHeap(),
  653. HEAP_ZERO_MEMORY,
  654. (dwPerfServiceListSize) * sizeof(WCHAR));
  655. mszNoPerfServiceList = HeapAlloc (
  656. GetProcessHeap(),
  657. HEAP_ZERO_MEMORY,
  658. (dwNoPerfServiceListSize) * sizeof(WCHAR));
  659. if ((mszNoPerfServiceList == NULL) || (mszPerfServiceList == NULL)) {
  660. dwStatus = ERROR_OUTOFMEMORY;
  661. break;
  662. }
  663. if (dwStatus == ERROR_SUCCESS) {
  664. dwStatus = BuildServiceLists (
  665. mszPerfServiceList,
  666. &dwPerfServiceListSize,
  667. mszNoPerfServiceList,
  668. &dwNoPerfServiceListSize);
  669. if (dwStatus == ERROR_SUCCESS) break; // and continue on
  670. }
  671. } while (dwPerfServiceListSize < 4194304);
  672. }
  673. // dump service entries for those services with perf counters
  674. if (dwStatus == ERROR_SUCCESS) {
  675. for (szThisServiceName = mszPerfServiceList;
  676. *szThisServiceName != 0;
  677. szThisServiceName += lstrlenW(szThisServiceName)+1) {
  678. dwStatus = DumpPerfServiceEntries (
  679. hOutFile,
  680. szThisServiceName);
  681. if (dwStatus != ERROR_SUCCESS) break;
  682. }
  683. }
  684. // dump perf string entries
  685. if (dwStatus == ERROR_SUCCESS) {
  686. // build Name table
  687. // get ENGLISH string list
  688. lpCounterText = BuildNameTable (
  689. HKEY_LOCAL_MACHINE, // use only local machine
  690. (LPWSTR)szLangId,
  691. &dwLastElement);
  692. if (lpCounterText != NULL) {
  693. dwStatus = DumpNameTable (
  694. hOutFile,
  695. szLangId,
  696. lpCounterText,
  697. 0, // dump the entire table for complete restore
  698. dwLastElement
  699. );
  700. } else {
  701. dwStatus = GetLastError();
  702. }
  703. }
  704. // free buffers
  705. if (lpCounterText != NULL) {
  706. HeapFree (GetProcessHeap(), 0, lpCounterText);
  707. lpCounterText = NULL;
  708. }
  709. if (mszNoPerfServiceList != NULL) {
  710. HeapFree (GetProcessHeap(), 0, mszNoPerfServiceList);
  711. mszNoPerfServiceList = NULL;
  712. }
  713. if (mszPerfServiceList != NULL) {
  714. HeapFree (GetProcessHeap(), 0, mszPerfServiceList);
  715. mszPerfServiceList = NULL;
  716. }
  717. if (szNewFileName != NULL) {
  718. HeapFree (GetProcessHeap(), 0, szNewFileName);
  719. szNewFileName = NULL;
  720. }
  721. // close file handles
  722. if (hOutFile != INVALID_HANDLE_VALUE) {
  723. CloseHandle (hOutFile);
  724. }
  725. return dwStatus;
  726. }
  727. DWORD
  728. RestorePerfRegistryFromFileW (
  729. IN LPCWSTR szFileName,
  730. IN LPCWSTR szLangId
  731. )
  732. {
  733. LONG lStatus = ERROR_SUCCESS;
  734. LONG lEnumStatus = ERROR_SUCCESS;
  735. DWORD dwServiceIndex = 0;
  736. WCHAR szServiceSubKeyName[MAX_PATH];
  737. WCHAR szPerfSubKeyName[MAX_PATH+20];
  738. DWORD dwNameSize = MAX_PATH;
  739. HKEY hKeyPerformance;
  740. HKEY hKeyServices = NULL;
  741. HKEY hKeyPerflib = NULL;
  742. DWORD dwItemSize;
  743. DWORD dwRegAccessMask;
  744. DWORD dwRetStatus = ERROR_SUCCESS;
  745. UINT nValue;
  746. DWORD dwnValue;
  747. BOOL bServiceRegistryOk = TRUE;
  748. WCHAR wPerfSection[MAX_PATH * 2];
  749. LPWSTR szLocalLangId;
  750. WinPerfStartTrace(NULL);
  751. if (szLangId == NULL) {
  752. szLocalLangId = (LPWSTR)L"009";
  753. } else {
  754. szLocalLangId = (LPWSTR)szLangId;
  755. }
  756. lStatus = RegOpenKeyExW (HKEY_LOCAL_MACHINE,
  757. cszServiceKeyName,
  758. 0L,
  759. KEY_READ,
  760. &hKeyServices);
  761. if (lStatus == ERROR_SUCCESS) {
  762. // enum service list
  763. while ((lEnumStatus = RegEnumKeyExW (
  764. hKeyServices,
  765. dwServiceIndex,
  766. szServiceSubKeyName,
  767. &dwNameSize,
  768. NULL,
  769. NULL,
  770. NULL,
  771. NULL)) == ERROR_SUCCESS) {
  772. //try to open the perfkey under this key.
  773. lstrcpy (szPerfSubKeyName, szServiceSubKeyName);
  774. lstrcat (szPerfSubKeyName, cszPerformance);
  775. bServiceRegistryOk = TRUE;
  776. dwRegAccessMask = KEY_READ | KEY_WRITE;
  777. // look for a performance subkey
  778. lStatus = RegOpenKeyExW (
  779. hKeyServices,
  780. szPerfSubKeyName,
  781. 0L,
  782. dwRegAccessMask,
  783. &hKeyPerformance);
  784. if (lStatus == ERROR_SUCCESS) {
  785. // key found so service has perf data
  786. // if performance subkey then
  787. dwItemSize = swprintf (wPerfSection,
  788. cszFmtServiceSectionName, szServiceSubKeyName);
  789. // look into the file for a perf entry for this service
  790. nValue = GetPrivateProfileIntW (
  791. wPerfSection,
  792. cszFirstCounter,
  793. -1,
  794. szFileName);
  795. if (nValue != (UINT) -1) {
  796. // if found in file then update registry with values from file
  797. lStatus = RegSetValueExW (hKeyPerformance,
  798. cszFirstCounter,
  799. 0L,
  800. REG_DWORD,
  801. (const BYTE *) & nValue,
  802. sizeof(nValue));
  803. dwnValue = nValue;
  804. TRACE((WINPERF_DBG_TRACE_INFO),
  805. (& LoadPerfGuid,
  806. __LINE__,
  807. LOADPERF_RESTOREPERFREGISTRYFROMFILEW,
  808. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  809. lStatus,
  810. TRACE_WSTR(szServiceSubKeyName),
  811. TRACE_WSTR(cszFirstCounter),
  812. TRACE_DWORD(dwnValue),
  813. NULL));
  814. // now read the other values
  815. } else {
  816. // there's one or more missing entries so
  817. // remove the whole entry
  818. bServiceRegistryOk = FALSE;
  819. }
  820. // look into the file for a perf entry for this service
  821. nValue = GetPrivateProfileIntW (
  822. wPerfSection,
  823. cszFirstHelp,
  824. -1,
  825. szFileName);
  826. if (nValue != (UINT)-1) {
  827. // if found in file then update registry with values from file
  828. lStatus = RegSetValueExW (hKeyPerformance,
  829. cszFirstHelp,
  830. 0L,
  831. REG_DWORD,
  832. (const BYTE *)&nValue,
  833. sizeof(nValue));
  834. dwnValue = nValue;
  835. TRACE((WINPERF_DBG_TRACE_INFO),
  836. (& LoadPerfGuid,
  837. __LINE__,
  838. LOADPERF_RESTOREPERFREGISTRYFROMFILEW,
  839. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  840. lStatus,
  841. TRACE_WSTR(szServiceSubKeyName),
  842. TRACE_WSTR(cszFirstHelp),
  843. TRACE_DWORD(dwnValue),
  844. NULL));
  845. // now read the other values
  846. } else {
  847. // there's one or more missing entries so
  848. // remove the whole entry
  849. bServiceRegistryOk = FALSE;
  850. }
  851. // look into the file for a perf entry for this service
  852. nValue = GetPrivateProfileIntW (
  853. wPerfSection,
  854. cszLastCounter,
  855. -1,
  856. szFileName);
  857. if (nValue != (UINT)-1) {
  858. // if found in file then update registry with values from file
  859. lStatus = RegSetValueExW (hKeyPerformance,
  860. cszLastCounter,
  861. 0L,
  862. REG_DWORD,
  863. (const BYTE *)&nValue,
  864. sizeof(nValue));
  865. dwnValue = nValue;
  866. TRACE((WINPERF_DBG_TRACE_INFO),
  867. (& LoadPerfGuid,
  868. __LINE__,
  869. LOADPERF_RESTOREPERFREGISTRYFROMFILEW,
  870. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  871. lStatus,
  872. TRACE_WSTR(szServiceSubKeyName),
  873. TRACE_WSTR(cszLastCounter),
  874. TRACE_DWORD(dwnValue),
  875. NULL));
  876. // now read the other values
  877. } else {
  878. // there's one or more missing entries so
  879. // remove the whole entry
  880. bServiceRegistryOk = FALSE;
  881. }
  882. // look into the file for a perf entry for this service
  883. nValue = GetPrivateProfileIntW (
  884. wPerfSection,
  885. cszLastHelp,
  886. -1,
  887. szFileName);
  888. if (nValue != (UINT)-1) {
  889. // if found in file then update registry with values from file
  890. lStatus = RegSetValueExW (hKeyPerformance,
  891. cszLastHelp,
  892. 0L,
  893. REG_DWORD,
  894. (const BYTE *)&nValue,
  895. sizeof(nValue));
  896. dwnValue = nValue;
  897. TRACE((WINPERF_DBG_TRACE_INFO),
  898. (& LoadPerfGuid,
  899. __LINE__,
  900. LOADPERF_RESTOREPERFREGISTRYFROMFILEW,
  901. ARG_DEF(ARG_TYPE_WSTR, 1) | ARG_DEF(ARG_TYPE_WSTR, 2),
  902. lStatus,
  903. TRACE_WSTR(szServiceSubKeyName),
  904. TRACE_WSTR(cszLastHelp),
  905. TRACE_DWORD(dwnValue),
  906. NULL));
  907. // now read the other values
  908. } else {
  909. // there's one or more missing entries so
  910. // remove the whole entry
  911. bServiceRegistryOk = FALSE;
  912. }
  913. if (!bServiceRegistryOk) {
  914. // an error occurred so delete the first/last counter/help values
  915. RegDeleteValue (hKeyPerformance, cszFirstCounter);
  916. RegDeleteValue (hKeyPerformance, cszFirstHelp);
  917. RegDeleteValue (hKeyPerformance, cszLastCounter);
  918. RegDeleteValue (hKeyPerformance, cszLastHelp);
  919. } // else continiue
  920. RegCloseKey (hKeyPerformance);
  921. } // else this service has no perf data so skip
  922. else {
  923. TRACE((WINPERF_DBG_TRACE_ERROR),
  924. (& LoadPerfGuid,
  925. __LINE__,
  926. LOADPERF_RESTOREPERFREGISTRYFROMFILEW,
  927. ARG_DEF(ARG_TYPE_WSTR, 1),
  928. lStatus,
  929. TRACE_WSTR(szServiceSubKeyName),
  930. NULL));
  931. }
  932. // reset for next loop
  933. dwServiceIndex++;
  934. dwNameSize = MAX_PATH;
  935. } // end enum service list
  936. }
  937. else {
  938. TRACE((WINPERF_DBG_TRACE_ERROR),
  939. (& LoadPerfGuid,
  940. __LINE__,
  941. LOADPERF_RESTOREPERFREGISTRYFROMFILEW,
  942. ARG_DEF(ARG_TYPE_WSTR, 1),
  943. lStatus,
  944. TRACE_WSTR(cszServiceKeyName),
  945. NULL));
  946. }
  947. if (hKeyServices != NULL) RegCloseKey (hKeyServices);
  948. if (dwRetStatus == ERROR_SUCCESS) {
  949. // merge registry string values:
  950. dwRetStatus = UpdatePerfNameFilesX (
  951. szFileName, NULL,
  952. szLocalLangId,
  953. LODCTR_UPNF_RESTORE);
  954. if (dwRetStatus == ERROR_SUCCESS) {
  955. // update the keys in the registry
  956. lStatus = RegOpenKeyExW (HKEY_LOCAL_MACHINE,
  957. cszPerflibKeyName,
  958. 0L,
  959. KEY_ALL_ACCESS,
  960. &hKeyPerflib);
  961. if (lStatus != ERROR_SUCCESS) {
  962. TRACE((WINPERF_DBG_TRACE_ERROR),
  963. (& LoadPerfGuid,
  964. __LINE__,
  965. LOADPERF_RESTOREPERFREGISTRYFROMFILEW,
  966. ARG_DEF(ARG_TYPE_WSTR, 1),
  967. lStatus,
  968. TRACE_WSTR(cszPerflibKeyName),
  969. NULL));
  970. }
  971. if (lStatus == ERROR_SUCCESS) {
  972. nValue = GetPrivateProfileIntW (
  973. cszPerflib,
  974. cszLastCounter,
  975. -1,
  976. szFileName);
  977. if (nValue != (UINT)-1) {
  978. // if found in file then update registry with values from file
  979. lStatus = RegSetValueExW (hKeyPerflib,
  980. cszLastCounter,
  981. 0L,
  982. REG_DWORD,
  983. (const BYTE *)&nValue,
  984. sizeof(nValue));
  985. dwnValue = nValue;
  986. TRACE((WINPERF_DBG_TRACE_INFO),
  987. (& LoadPerfGuid,
  988. __LINE__,
  989. LOADPERF_RESTOREPERFREGISTRYFROMFILEW,
  990. ARG_DEF(ARG_TYPE_WSTR, 1),
  991. lStatus,
  992. TRACE_WSTR(cszLastCounter),
  993. TRACE_DWORD(dwnValue),
  994. NULL));
  995. }
  996. }
  997. if (lStatus == ERROR_SUCCESS) {
  998. // look into the file for a perf entry for this service
  999. nValue = GetPrivateProfileIntW (
  1000. cszPerflib,
  1001. cszLastHelp,
  1002. -1,
  1003. szFileName);
  1004. if (nValue != (UINT)-1) {
  1005. // if found in file then update registry with values from file
  1006. lStatus = RegSetValueExW (hKeyPerflib,
  1007. cszLastHelp,
  1008. 0L,
  1009. REG_DWORD,
  1010. (const BYTE *)&nValue,
  1011. sizeof(nValue));
  1012. dwnValue = nValue;
  1013. TRACE((WINPERF_DBG_TRACE_INFO),
  1014. (& LoadPerfGuid,
  1015. __LINE__,
  1016. LOADPERF_RESTOREPERFREGISTRYFROMFILEW,
  1017. ARG_DEF(ARG_TYPE_WSTR, 1),
  1018. lStatus,
  1019. TRACE_WSTR(cszLastHelp),
  1020. TRACE_DWORD(dwnValue),
  1021. NULL));
  1022. }
  1023. }
  1024. if (lStatus == ERROR_SUCCESS) {
  1025. // look into the file for a perf entry for this service
  1026. nValue = GetPrivateProfileIntW (
  1027. cszPerflib,
  1028. cszBaseIndex,
  1029. -1,
  1030. szFileName);
  1031. if (nValue != (UINT)-1) {
  1032. // if found in file then update registry with values from file
  1033. lStatus = RegSetValueExW (hKeyPerflib,
  1034. cszBaseIndex,
  1035. 0L,
  1036. REG_DWORD,
  1037. (const BYTE *)&nValue,
  1038. sizeof(nValue));
  1039. dwnValue = nValue;
  1040. TRACE((WINPERF_DBG_TRACE_INFO),
  1041. (& LoadPerfGuid,
  1042. __LINE__,
  1043. LOADPERF_RESTOREPERFREGISTRYFROMFILEW,
  1044. ARG_DEF(ARG_TYPE_WSTR, 1),
  1045. lStatus,
  1046. TRACE_WSTR(cszBaseIndex),
  1047. TRACE_DWORD(dwnValue),
  1048. NULL));
  1049. }
  1050. }
  1051. if (hKeyPerflib != NULL) RegCloseKey (hKeyPerflib);
  1052. }
  1053. dwRetStatus = lStatus;
  1054. }
  1055. return dwRetStatus;
  1056. }