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.

626 lines
21 KiB

  1. /*++ BUILD Version: 0001 // Increment this if a change has global effects
  2. Copyright (c) 1992-1994 Microsoft Corporation
  3. Module Name:
  4. perfname.c
  5. Abstract:
  6. This file returns the Counter names or help text.
  7. Author:
  8. HonWah Chan 10/12/93
  9. Revision History:
  10. --*/
  11. #define UNICODE
  12. #define _UNICODE
  13. //
  14. // Include files
  15. //
  16. #pragma warning(disable:4306)
  17. #include <nt.h>
  18. #include <ntrtl.h>
  19. #include <nturtl.h>
  20. #include <windows.h>
  21. #include <string.h>
  22. #include <strsafe.h>
  23. #include "ntconreg.h"
  24. #include "perflib.h"
  25. #pragma warning(default:4306)
  26. #define QUERY_GLOBAL 1
  27. #define QUERY_ITEMS 2
  28. #define QUERY_FOREIGN 3
  29. #define QUERY_COSTLY 4
  30. #define QUERY_COUNTER 5
  31. #define QUERY_HELP 6
  32. #define QUERY_ADDCOUNTER 7
  33. #define QUERY_ADDHELP 8
  34. #define tohexdigit(x) ((CHAR) (((x) < 10) ? ((x) + L'0') : ((x) + L'a' - 10)))
  35. #define LANG_ID_START 25
  36. const WCHAR FileNameTemplate[] = L"\\SystemRoot\\system32\\perf0000.dat";
  37. const WCHAR SubFileNameTemplate[] = L"\\SystemRoot\\system32\\prf00000.dat";
  38. const WCHAR DefaultLangId[] = L"009";
  39. extern WCHAR COUNTER_STRING[];
  40. extern WCHAR HELP_STRING[];
  41. extern WCHAR ADDCOUNTER_STRING[];
  42. extern WCHAR ADDHELP_STRING[];
  43. DWORD GetLangIdFromSzLang(LPWSTR szLangId);
  44. VOID Perflib004Update(LPWSTR pLangIdRequest);
  45. LPWSTR PerflibCheckPerfFile(LPWSTR szLangId, LPWSTR szRtnLang, DWORD dwRtnLang);
  46. NTSTATUS
  47. PerfGetNames(
  48. IN DWORD QueryType,
  49. IN PUNICODE_STRING lpValueName,
  50. OUT LPBYTE lpData,
  51. OUT LPDWORD lpcbData,
  52. OUT LPDWORD lpcbLen OPTIONAL,
  53. IN LPWSTR lpLanguageId OPTIONAL
  54. )
  55. /*++
  56. PerfGetCounterName
  57. Arguments - Get either counter names or help text for the given language.
  58. If there is no language ID specified in the input, the default English
  59. version is returned.
  60. Inputs -
  61. QueryType - Either QUERY_COUNTER or QUERY_HELP
  62. or QUERY_ADDCOUNTER or QUERY_ADDHELP
  63. lpValueName - Either "Counter ???" or "Explain ???"
  64. or "Addcounter ???" or "Addexplain ???"
  65. lpData - pointer to a buffer to receive the names
  66. lpcbData - pointer to a variable containing the size in bytes of
  67. the output buffer; on output, will receive the number
  68. of bytes actually returned
  69. lpcbLen - Return the number of bytes to transmit to
  70. the client (used by RPC) (optional).
  71. lpLanguageId - Input string for the language id desired.
  72. Return Value -
  73. error code indicating status of call or
  74. ERROR_SUCCESS if all ok
  75. --*/
  76. {
  77. UNICODE_STRING NtFileName;
  78. NTSTATUS Status;
  79. WCHAR Names[50], QueryChar;
  80. WCHAR szRtnLang[5];
  81. ULONG NameLen, StartIndex;
  82. OBJECT_ATTRIBUTES ObjectAttributes;
  83. IO_STATUS_BLOCK IoStatus;
  84. FILE_STANDARD_INFORMATION FileInformation;
  85. HANDLE File;
  86. LPWSTR pLangIdRequest;
  87. LPWSTR pTmpLangId;
  88. BOOL bAddNames, bSubLang;
  89. HRESULT hError;
  90. // build the file name
  91. hError = StringCchCopyW(Names, 50, FileNameTemplate);
  92. TRACE((WINPERF_DBG_TRACE_INFO),
  93. (&PerflibGuid, __LINE__, PERF_GET_NAMES,
  94. ARG_DEF(ARG_TYPE_WSTR, 2), 0,
  95. &QueryType, sizeof(QueryType),
  96. lpValueName->Buffer, WSTRSIZE(lpValueName->Buffer), NULL));
  97. if (QueryType == QUERY_ADDCOUNTER || QueryType == QUERY_ADDHELP) {
  98. bAddNames = TRUE;
  99. } else {
  100. bAddNames = FALSE;
  101. }
  102. if (QueryType == QUERY_COUNTER || QueryType == QUERY_ADDCOUNTER) {
  103. QueryChar = L'c';
  104. NameLen = (ULONG) wcslen(COUNTER_STRING);
  105. } else {
  106. NameLen = (ULONG) wcslen(HELP_STRING);
  107. QueryChar = L'h';
  108. }
  109. if (lpLanguageId) {
  110. DWORD dwLangId = PRIMARYLANGID(GetLangIdFromSzLang(lpLanguageId));
  111. if (dwLangId == 0x004) {
  112. pLangIdRequest = lpLanguageId;
  113. }
  114. else {
  115. pLangIdRequest = PerflibCheckPerfFile(lpLanguageId, szRtnLang, 5);
  116. if (pLangIdRequest == NULL) {
  117. // It is possible that no PERFCxx.DAT and PERFHxxx.DAT files are present.
  118. // Restore pLangIdRequest to original value if PerflibCheckPerfFile() returns
  119. // NULL.
  120. //
  121. pLangIdRequest = lpLanguageId;
  122. }
  123. }
  124. } else {
  125. // get the lang id from the input lpValueName
  126. pLangIdRequest = lpValueName->Buffer + NameLen;
  127. do {
  128. if (lpValueName->Length < (NameLen + 3) * sizeof(WCHAR)) {
  129. // lpValueName is too small to contain the lang id, use default
  130. pLangIdRequest = (LPWSTR) DefaultLangId;
  131. break;
  132. }
  133. if (*pLangIdRequest >= L'0' && *pLangIdRequest <= L'9') {
  134. // found the first digit
  135. break;
  136. }
  137. pLangIdRequest++;
  138. NameLen++;
  139. } while (NameLen > 0); // always TRUE
  140. // Specially for 004 (CHT and CHS) if this is a Whistler upgrade.
  141. // Need to copy perfc004.dat/perfh004.dat to prfc0?04.dat/prfh0?04.dat
  142. // then rename perfc004.dat/perfh004.dat so that PERFLIB will not find
  143. // them in the future.
  144. // Currently this is a hack.
  145. //
  146. Perflib004Update(pLangIdRequest);
  147. pTmpLangId = pLangIdRequest;
  148. pLangIdRequest = PerflibCheckPerfFile(pTmpLangId, szRtnLang, 5);
  149. if (pLangIdRequest == NULL) {
  150. pLangIdRequest = pTmpLangId;
  151. }
  152. }
  153. bSubLang = ((pLangIdRequest[3] >= L'0') && (pLangIdRequest[3] <= L'9'));
  154. StartIndex = LANG_ID_START;
  155. if (bSubLang) {
  156. StartIndex = LANG_ID_START - 1;
  157. hError = StringCchCopyW(Names, 50, SubFileNameTemplate);
  158. }
  159. Names[StartIndex] = QueryChar;
  160. Names[StartIndex + 1] = *pLangIdRequest++;
  161. Names[StartIndex + 2] = *pLangIdRequest++;
  162. Names[StartIndex + 3] = *pLangIdRequest++;
  163. if (bSubLang) {
  164. Names[StartIndex + 4] = *pLangIdRequest;
  165. }
  166. TRACE((WINPERF_DBG_TRACE_INFO),
  167. (&PerflibGuid, __LINE__, PERF_GET_NAMES,
  168. ARG_DEF(ARG_TYPE_WSTR, 1), 0,
  169. Names, WSTRSIZE(Names), NULL));
  170. RtlInitUnicodeString(& NtFileName, Names);
  171. // open the file for info
  172. InitializeObjectAttributes( &ObjectAttributes,
  173. &NtFileName,
  174. OBJ_CASE_INSENSITIVE,
  175. (HANDLE)NULL,
  176. NULL
  177. );
  178. if (bAddNames) {
  179. // writing name to data file
  180. LARGE_INTEGER ByteOffset;
  181. ByteOffset.LowPart = ByteOffset.HighPart = 0;
  182. Status = NtCreateFile( &File,
  183. SYNCHRONIZE | GENERIC_WRITE,
  184. &ObjectAttributes,
  185. &IoStatus,
  186. NULL, // no initial size
  187. FILE_ATTRIBUTE_NORMAL,
  188. FILE_SHARE_READ,
  189. FILE_SUPERSEDE, // always create
  190. FILE_SYNCHRONOUS_IO_NONALERT,
  191. NULL, // no ea buffer
  192. 0 // no ea buffer
  193. );
  194. if (!NT_SUCCESS( Status )) {
  195. TRACE((WINPERF_DBG_TRACE_INFO),
  196. (&PerflibGuid, __LINE__, PERF_GET_NAMES, 0, Status, NULL));
  197. return( Status );
  198. }
  199. if (ARGUMENT_PRESENT(lpData) && ARGUMENT_PRESENT(lpcbData)) {
  200. Status = NtWriteFile( File,
  201. NULL,
  202. NULL,
  203. NULL,
  204. &IoStatus,
  205. lpData,
  206. *lpcbData,
  207. &ByteOffset,
  208. NULL
  209. );
  210. }
  211. else {
  212. Status = ERROR_INVALID_PARAMETER;
  213. }
  214. if (!NT_SUCCESS( Status )) {
  215. TRACE((WINPERF_DBG_TRACE_INFO),
  216. (&PerflibGuid, __LINE__, PERF_GET_NAMES, 0, Status, NULL));
  217. NtClose( File );
  218. return( Status );
  219. }
  220. } else {
  221. // reading name from data file
  222. Status = NtOpenFile( &File,
  223. SYNCHRONIZE | GENERIC_READ,
  224. &ObjectAttributes,
  225. &IoStatus,
  226. FILE_SHARE_DELETE |
  227. FILE_SHARE_READ |
  228. FILE_SHARE_WRITE,
  229. FILE_SYNCHRONOUS_IO_NONALERT |
  230. FILE_NON_DIRECTORY_FILE
  231. );
  232. if (!NT_SUCCESS( Status )) {
  233. TRACE((WINPERF_DBG_TRACE_INFO),
  234. (&PerflibGuid, __LINE__, PERF_GET_NAMES, 0, Status, NULL));
  235. return( Status );
  236. }
  237. Status = NtQueryInformationFile( File,
  238. &IoStatus,
  239. (PVOID)&FileInformation,
  240. sizeof( FileInformation ),
  241. FileStandardInformation
  242. );
  243. if (NT_SUCCESS( Status )) {
  244. if (FileInformation.EndOfFile.HighPart) {
  245. Status = STATUS_BUFFER_OVERFLOW;
  246. TRACE((WINPERF_DBG_TRACE_INFO),
  247. (&PerflibGuid, __LINE__, PERF_GET_NAMES, 0, Status, NULL));
  248. }
  249. }
  250. if (!NT_SUCCESS( Status )) {
  251. TRACE((WINPERF_DBG_TRACE_INFO),
  252. (&PerflibGuid, __LINE__, PERF_GET_NAMES, 0, Status, NULL));
  253. NtClose( File );
  254. return( Status );
  255. }
  256. if (! ARGUMENT_PRESENT(lpData) || ! ARGUMENT_PRESENT(lpcbData) ||
  257. * lpcbData < FileInformation.EndOfFile.LowPart) {
  258. NtClose( File );
  259. TRACE((WINPERF_DBG_TRACE_INFO),
  260. (&PerflibGuid, __LINE__, PERF_GET_NAMES, 0, Status, NULL));
  261. if (ARGUMENT_PRESENT (lpcbLen)) {
  262. // no data yet for the rpc
  263. *lpcbLen = 0;
  264. }
  265. if (ARGUMENT_PRESENT(lpcbData)) {
  266. *lpcbData = FileInformation.EndOfFile.LowPart;
  267. }
  268. if (ARGUMENT_PRESENT (lpData)) {
  269. TRACE((WINPERF_DBG_TRACE_INFO),
  270. (&PerflibGuid, __LINE__, PERF_GET_NAMES, 0, Status, NULL));
  271. return (STATUS_BUFFER_OVERFLOW);
  272. }
  273. return(STATUS_SUCCESS);
  274. }
  275. Status = NtReadFile( File,
  276. NULL,
  277. NULL,
  278. NULL,
  279. &IoStatus,
  280. lpData,
  281. FileInformation.EndOfFile.LowPart,
  282. NULL,
  283. NULL
  284. );
  285. if (NT_SUCCESS( Status )) {
  286. Status = IoStatus.Status;
  287. if (NT_SUCCESS( Status )) {
  288. if (IoStatus.Information != FileInformation.EndOfFile.LowPart) {
  289. Status = STATUS_END_OF_FILE;
  290. }
  291. }
  292. }
  293. else {
  294. TRACE((WINPERF_DBG_TRACE_INFO),
  295. (&PerflibGuid, __LINE__, PERF_GET_NAMES, 0, Status, NULL));
  296. }
  297. if (NT_SUCCESS( Status )) {
  298. if (ARGUMENT_PRESENT(lpcbData)) {
  299. *lpcbData = FileInformation.EndOfFile.LowPart;
  300. }
  301. if (ARGUMENT_PRESENT(lpcbLen)) {
  302. *lpcbLen = FileInformation.EndOfFile.LowPart;
  303. }
  304. }
  305. } // end of reading names
  306. NtClose (File);
  307. return (Status);
  308. }
  309. VOID
  310. PerfGetPrimaryLangId(
  311. DWORD dwLangId,
  312. WCHAR * PrimaryLangId
  313. )
  314. {
  315. // build the native language id
  316. WCHAR LangId;
  317. WCHAR nDigit;
  318. LangId = (WCHAR) PRIMARYLANGID(dwLangId);
  319. nDigit = (WCHAR) (LangId >> 8);
  320. PrimaryLangId[0] = tohexdigit(nDigit);
  321. nDigit = (WCHAR) (LangId & 0XF0) >> 4;
  322. PrimaryLangId[1] = tohexdigit(nDigit);
  323. nDigit = (WCHAR) (LangId & 0xF);
  324. PrimaryLangId[2] = tohexdigit(nDigit);
  325. PrimaryLangId[3] = L'\0';
  326. }
  327. VOID
  328. PerfGetLangId(
  329. WCHAR * FullLangId
  330. )
  331. {
  332. WCHAR LangId;
  333. WCHAR nDigit;
  334. LangId = (WCHAR) GetUserDefaultUILanguage();
  335. nDigit = (LangId & 0xF000) >> 12;
  336. FullLangId[0] = tohexdigit(nDigit);
  337. nDigit = (LangId & 0x0F00) >> 8;
  338. FullLangId[1] = tohexdigit(nDigit);
  339. nDigit = (LangId & 0x00F0) >> 4;
  340. FullLangId[2] = tohexdigit(nDigit);
  341. nDigit = LangId & 0xF;
  342. FullLangId[3] = tohexdigit(nDigit);
  343. FullLangId[4] = L'\0';
  344. }
  345. DWORD
  346. GetLangIdFromSzLang(
  347. LPWSTR szLangId
  348. )
  349. {
  350. DWORD dwLangId = 0;
  351. DWORD dwLangLen = lstrlenW(szLangId);
  352. DWORD i;
  353. WCHAR wszDigit;
  354. for (i = 0; i < dwLangLen; i ++) {
  355. dwLangId <<= 4;
  356. wszDigit = szLangId[i];
  357. if (wszDigit >= L'0' && wszDigit <= L'9') {
  358. dwLangId += (wszDigit - L'0');
  359. }
  360. else if (wszDigit >= L'a' && wszDigit <= 'f') {
  361. dwLangId += (10 + wszDigit - L'a');
  362. }
  363. else if (wszDigit >= L'A' && wszDigit <= 'F') {
  364. dwLangId += (10 + wszDigit - L'A');
  365. }
  366. else {
  367. dwLangId = 0;
  368. break;
  369. }
  370. }
  371. return dwLangId;
  372. }
  373. LPCWSTR szCtrLangFile = L"perfc";
  374. LPCWSTR szCtrSubLangFile = L"prfc";
  375. LPCWSTR szHlpLangFile = L"perfh";
  376. LPCWSTR szHlpSubLangFile = L"prfh";
  377. LPCWSTR sz004CtrLangFile = L"perfc004.dat";
  378. LPCWSTR sz004HlpLangFile = L"perfh004.dat";
  379. LPCWSTR szFileExt = L".dat";
  380. LPWSTR
  381. PerflibFindCounterFile(
  382. IN LPWSTR szFilePath,
  383. IN BOOLEAN bCheckSubLang,
  384. IN LPWSTR szLangId,
  385. OUT LPWSTR szRtnLang,
  386. IN DWORD dwRtnLang
  387. )
  388. {
  389. WCHAR szThisLang[5];
  390. WCHAR szPrimaryLang[5];
  391. DWORD dwThisLang;
  392. DWORD dwFileLen;
  393. WIN32_FIND_DATAW FindFileData;
  394. DWORD bResult = FALSE;
  395. HANDLE hFile = NULL;
  396. HRESULT hError;
  397. hFile = FindFirstFileExW(szFilePath, FindExInfoStandard, & FindFileData, FindExSearchNameMatch, NULL, 0);
  398. RtlZeroMemory(szRtnLang, dwRtnLang * sizeof(WCHAR));
  399. if (hFile != INVALID_HANDLE_VALUE) {
  400. if (bCheckSubLang) {
  401. do {
  402. dwFileLen = lstrlenW(FindFileData.cFileName);
  403. if (dwFileLen == 12) {
  404. ZeroMemory(szThisLang, 5 * sizeof(WCHAR));
  405. ZeroMemory(szPrimaryLang, 5 * sizeof(WCHAR));
  406. hError = StringCchCopyW(szThisLang, 5, (LPWSTR) (FindFileData.cFileName + (dwFileLen - 8)));
  407. dwThisLang = GetLangIdFromSzLang(szThisLang);
  408. if (dwThisLang != 0) {
  409. PerfGetPrimaryLangId(dwThisLang, szPrimaryLang);
  410. bResult = (lstrcmpiW(szPrimaryLang, szLangId) == 0);
  411. if (bResult == TRUE) {
  412. hError = StringCchCopyW(szRtnLang, dwRtnLang, szThisLang);
  413. }
  414. }
  415. }
  416. }
  417. while (FindNextFileW(hFile, & FindFileData));
  418. }
  419. else {
  420. bResult = TRUE;
  421. hError = StringCchCopyW(szRtnLang, dwRtnLang, szLangId);
  422. }
  423. FindClose(hFile);
  424. }
  425. return bResult ? szRtnLang : NULL;
  426. }
  427. LPWSTR
  428. PerflibCheckPerfFile(
  429. IN LPWSTR LangId,
  430. OUT LPWSTR szRtnLang,
  431. IN DWORD dwRtnLang
  432. )
  433. {
  434. DWORD dwSysDir = GetSystemDirectoryW(NULL, 0);
  435. DWORD dwSrchDir;
  436. DWORD dwLangLen = lstrlenW(LangId);
  437. DWORD dwLangId;
  438. LPWSTR szLangId = NULL;
  439. WCHAR szLang[5];
  440. LPWSTR szSysDir = NULL;
  441. LPWSTR szSrchDir = NULL;
  442. HRESULT hError;
  443. if (dwSysDir == 0) goto Cleanup;
  444. dwSrchDir = lstrlenW(szCtrSubLangFile) + lstrlenW(LangId) + lstrlenW(szFileExt) + 1;
  445. if (dwSrchDir < 13) dwSrchDir = 13; // "8.3" filename format with NULL
  446. dwSrchDir += dwSysDir + 1;
  447. szSysDir = (LPWSTR) ALLOCMEM(sizeof(WCHAR) * (dwSysDir + 1 + dwSrchDir));
  448. if (szSysDir == NULL) goto Cleanup;
  449. else if (GetSystemDirectoryW(szSysDir, dwSysDir + 1) == 0) goto Cleanup;
  450. szSrchDir = szSysDir + dwSysDir + 1;
  451. if (dwLangLen == 4) {
  452. hError = StringCchPrintfW(szSrchDir, dwSrchDir, L"%ws\\%ws%ws%ws",
  453. szSysDir, szCtrSubLangFile, LangId, szFileExt);
  454. szLangId = PerflibFindCounterFile(szSrchDir, FALSE, LangId, szRtnLang, dwRtnLang);
  455. if (szLangId == NULL) {
  456. dwLangId = GetLangIdFromSzLang(LangId);
  457. if (dwLangId != 0) {
  458. ZeroMemory(szLang, sizeof(WCHAR) * 5);
  459. PerfGetPrimaryLangId(dwLangId, szLang);
  460. ZeroMemory(szSrchDir, sizeof(WCHAR) * dwSrchDir);
  461. hError = StringCchPrintfW(szSrchDir, dwSrchDir, L"%ws\\%ws%ws%ws",
  462. szSysDir, szCtrLangFile, szLang, szFileExt);
  463. szLangId = PerflibFindCounterFile(szSrchDir, FALSE, szLang, szRtnLang, dwRtnLang);
  464. }
  465. }
  466. }
  467. else {
  468. // dwLangId should be 3, this is primary UserDefaultUILanguage.
  469. //
  470. hError = StringCchPrintfW(szSrchDir, dwSrchDir, L"%ws\\%ws%ws%ws",
  471. szSysDir, szCtrLangFile, LangId, szFileExt);
  472. szLangId = PerflibFindCounterFile(szSrchDir, FALSE, LangId, szRtnLang, dwRtnLang);
  473. if (szLangId == NULL) {
  474. ZeroMemory(szSrchDir, sizeof(WCHAR) * dwSrchDir);
  475. hError = StringCchPrintfW(szSrchDir, dwSrchDir, L"%ws\\%ws??%ws%ws",
  476. szSysDir, szCtrSubLangFile, (LPWSTR) (LangId + 1), szFileExt);
  477. szLangId = PerflibFindCounterFile(szSrchDir, TRUE, LangId, szRtnLang, dwRtnLang);
  478. }
  479. }
  480. Cleanup:
  481. FREEMEM(szSysDir);
  482. return szLangId;
  483. }
  484. VOID
  485. PerflibRename004File(
  486. IN LPWSTR szSysDir,
  487. IN LPWSTR szLangId,
  488. IN BOOLEAN bCounterFile
  489. )
  490. {
  491. DWORD dwSrchDir = lstrlenW(szSysDir) + 2 + 13 + 4; // 13 is for "8.3" filename with NULL; 4 is for ".tmp"
  492. LPWSTR szTmpFile = NULL;
  493. LPWSTR szSrchDir = NULL;
  494. LPWSTR szName;
  495. HRESULT hError;
  496. szSrchDir = ALLOCMEM(2 * sizeof(WCHAR) * dwSrchDir);
  497. if (szSrchDir == NULL) goto Cleanup;
  498. szTmpFile = szSrchDir + dwSrchDir;
  499. szName = (LPWSTR) ((bCounterFile) ? (sz004CtrLangFile) : (sz004HlpLangFile));
  500. hError = StringCchPrintfW(szSrchDir, dwSrchDir, L"%ws\\%ws", szSysDir, szName);
  501. if (szLangId) {
  502. szName = (LPWSTR) ((bCounterFile) ? (szCtrSubLangFile) : (szHlpSubLangFile));
  503. hError = StringCchPrintfW(szTmpFile, dwSrchDir, L"%ws\\%ws%ws%ws", szSysDir, szName, szLangId, szFileExt);
  504. CopyFileW(szSrchDir, szTmpFile, FALSE);
  505. }
  506. else {
  507. szName = (LPWSTR) ((bCounterFile) ? (sz004CtrLangFile) : (sz004HlpLangFile));
  508. hError = StringCchPrintfW(szTmpFile, dwSrchDir, L"%ws\\%ws.tmp", szSysDir, szName);
  509. DeleteFileW(szTmpFile);
  510. MoveFileW(szSrchDir, szTmpFile);
  511. }
  512. Cleanup:
  513. FREEMEM(szSrchDir);
  514. }
  515. VOID
  516. Perflib004Update(
  517. IN LPWSTR pLangIdRequest
  518. )
  519. {
  520. LPWSTR szSysDir = NULL;
  521. LPWSTR szTmpFile = NULL;
  522. LPWSTR szRtnLang = NULL;
  523. DWORD dwSysDir;
  524. DWORD dwTmpDir;
  525. HRESULT hError;
  526. if (GetLangIdFromSzLang(pLangIdRequest) != LANG_CHINESE) goto Cleanup;
  527. dwSysDir = GetSystemDirectoryW(NULL, 0);
  528. dwTmpDir = lstrlenW(szCtrSubLangFile) + 5 + lstrlenW(szFileExt) + 1; // 5 is for LangId
  529. if (dwSysDir == 0) goto Cleanup;
  530. szSysDir = (LPWSTR) ALLOCMEM(sizeof(WCHAR) * (dwSysDir + 1 + dwTmpDir + 5));
  531. if (szSysDir == NULL) goto Cleanup;
  532. szRtnLang = szSysDir + dwSysDir + 1;
  533. szTmpFile = szRtnLang + 5;
  534. // Search whether PERFC004.DAT and PRFC0?04.DAT are in System32 directory
  535. //
  536. if (GetSystemDirectoryW(szSysDir, dwSysDir + 1) == 0)
  537. goto Cleanup;
  538. if (SearchPathW(szSysDir, sz004CtrLangFile, NULL, 0, NULL, NULL) == 0)
  539. goto Cleanup;
  540. PerfGetLangId(szRtnLang);
  541. hError = StringCchPrintfW(szTmpFile, dwTmpDir, L"%ws%ws%ws", szCtrSubLangFile, szRtnLang, szFileExt);
  542. if (SearchPathW(szSysDir, szTmpFile, NULL, 0, NULL, NULL) == 0)
  543. goto Cleanup;
  544. // Found PERFC004.DAT, assume that PERFH004.DAT is also there.
  545. // Rename to PRFC0?04.DAT/PRFH0?04.DAT
  546. //
  547. PerflibRename004File(szSysDir, szRtnLang, TRUE);
  548. PerflibRename004File(szSysDir, szRtnLang, FALSE);
  549. PerflibRename004File(szSysDir, NULL, TRUE);
  550. PerflibRename004File(szSysDir, NULL, FALSE);
  551. Cleanup:
  552. FREEMEM(szSysDir);
  553. return;
  554. }