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.

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