632 lines
19 KiB
C
632 lines
19 KiB
C
|
/*++ BUILD Version: 0001 // Increment this if a change has global effects
|
||
|
|
||
|
Copyright (c) 1992-1994 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
perfname.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
This file returns the Counter names or help text.
|
||
|
|
||
|
|
||
|
|
||
|
Author:
|
||
|
|
||
|
HonWah Chan 10/12/93
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
|
||
|
|
||
|
--*/
|
||
|
#define UNICODE
|
||
|
#define _UNICODE
|
||
|
//
|
||
|
// Include files
|
||
|
//
|
||
|
#pragma warning(disable:4306)
|
||
|
#include <nt.h>
|
||
|
#include <ntrtl.h>
|
||
|
#include <nturtl.h>
|
||
|
#include <windows.h>
|
||
|
#include <string.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include "ntconreg.h"
|
||
|
#include "perflib.h"
|
||
|
#pragma warning(default:4306)
|
||
|
|
||
|
#define QUERY_GLOBAL 1
|
||
|
#define QUERY_ITEMS 2
|
||
|
#define QUERY_FOREIGN 3
|
||
|
#define QUERY_COSTLY 4
|
||
|
#define QUERY_COUNTER 5
|
||
|
#define QUERY_HELP 6
|
||
|
#define QUERY_ADDCOUNTER 7
|
||
|
#define QUERY_ADDHELP 8
|
||
|
|
||
|
#define tohexdigit(x) ((CHAR) (((x) < 10) ? ((x) + L'0') : ((x) + L'a' - 10)))
|
||
|
|
||
|
#define LANG_ID_START 25
|
||
|
WCHAR FileNameTemplate[] = L"\\SystemRoot\\system32\\perf0000.dat";
|
||
|
WCHAR SubFileNameTemplate[] = L"\\SystemRoot\\system32\\prf00000.dat";
|
||
|
WCHAR DefaultLangId[] = L"009";
|
||
|
|
||
|
extern WCHAR COUNTER_STRING[];
|
||
|
extern WCHAR HELP_STRING[];
|
||
|
extern WCHAR ADDCOUNTER_STRING[];
|
||
|
extern WCHAR ADDHELP_STRING[];
|
||
|
|
||
|
VOID Perflib004Update(LPWSTR pLangIdRequest);
|
||
|
LPWSTR PerflibCheckPerfFile(LPWSTR szLangId);
|
||
|
|
||
|
NTSTATUS
|
||
|
PerfGetNames (
|
||
|
IN DWORD QueryType,
|
||
|
IN PUNICODE_STRING lpValueName,
|
||
|
OUT LPBYTE lpData,
|
||
|
OUT LPDWORD lpcbData,
|
||
|
OUT LPDWORD lpcbLen OPTIONAL,
|
||
|
IN LPWSTR lpLanguageId OPTIONAL
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
PerfGetCounterName
|
||
|
|
||
|
Arguments - Get either counter names or help text for the given language.
|
||
|
If there is no language ID specified in the input, the default English
|
||
|
version is returned.
|
||
|
|
||
|
Inputs -
|
||
|
|
||
|
QueryType - Either QUERY_COUNTER or QUERY_HELP
|
||
|
or QUERY_ADDCOUNTER or QUERY_ADDHELP
|
||
|
|
||
|
lpValueName - Either "Counter ???" or "Explain ???"
|
||
|
or "Addcounter ???" or "Addexplain ???"
|
||
|
|
||
|
lpData - pointer to a buffer to receive the names
|
||
|
|
||
|
lpcbData - pointer to a variable containing the size in bytes of
|
||
|
the output buffer; on output, will receive the number
|
||
|
of bytes actually returned
|
||
|
|
||
|
lpcbLen - Return the number of bytes to transmit to
|
||
|
the client (used by RPC) (optional).
|
||
|
|
||
|
lpLanguageId - Input string for the language id desired.
|
||
|
|
||
|
Return Value -
|
||
|
|
||
|
error code indicating status of call or
|
||
|
ERROR_SUCCESS if all ok
|
||
|
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
UNICODE_STRING NtFileName;
|
||
|
NTSTATUS Status;
|
||
|
WCHAR Names[50], QueryChar;
|
||
|
ULONG NameLen, StartIndex;
|
||
|
|
||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
||
|
IO_STATUS_BLOCK IoStatus;
|
||
|
FILE_STANDARD_INFORMATION FileInformation;
|
||
|
HANDLE File;
|
||
|
LPWSTR pLangIdRequest;
|
||
|
LPWSTR pTmpLangId;
|
||
|
BOOL bAddNames, bSubLang;
|
||
|
|
||
|
// build the file name
|
||
|
RtlMoveMemory (Names, FileNameTemplate, sizeof(FileNameTemplate));
|
||
|
|
||
|
TRACE((WINPERF_DBG_TRACE_INFO),
|
||
|
(&PerflibGuid, __LINE__, PERF_GET_NAMES,
|
||
|
ARG_DEF(ARG_TYPE_WSTR, 2), 0,
|
||
|
&QueryType, sizeof(QueryType),
|
||
|
lpValueName->Buffer, WSTRSIZE(lpValueName->Buffer), NULL));
|
||
|
|
||
|
if (QueryType == QUERY_ADDCOUNTER || QueryType == QUERY_ADDHELP) {
|
||
|
bAddNames = TRUE;
|
||
|
} else {
|
||
|
bAddNames = FALSE;
|
||
|
}
|
||
|
|
||
|
if (QueryType == QUERY_COUNTER || QueryType == QUERY_ADDCOUNTER) {
|
||
|
QueryChar = L'c';
|
||
|
NameLen = (ULONG) wcslen(COUNTER_STRING);
|
||
|
} else {
|
||
|
NameLen = (ULONG) wcslen(HELP_STRING);
|
||
|
QueryChar = L'h';
|
||
|
}
|
||
|
|
||
|
if (lpLanguageId) {
|
||
|
pLangIdRequest = lpLanguageId;
|
||
|
} else {
|
||
|
// get the lang id from the input lpValueName
|
||
|
pLangIdRequest = lpValueName->Buffer + NameLen;
|
||
|
do {
|
||
|
if (lpValueName->Length < (NameLen + 3) * sizeof(WCHAR)) {
|
||
|
// lpValueName is too small to contain the lang id, use default
|
||
|
pLangIdRequest = DefaultLangId;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (*pLangIdRequest >= L'0' && *pLangIdRequest <= L'9') {
|
||
|
// found the first digit
|
||
|
break;
|
||
|
}
|
||
|
pLangIdRequest++;
|
||
|
NameLen++;
|
||
|
} while (NameLen > 0); // always TRUE
|
||
|
|
||
|
// Specially for 004 (CHT and CHS) if this is a Whistler upgrade.
|
||
|
// Need to copy perfc004.dat/perfh004.dat to prfc0?04.dat/prfh0?04.dat
|
||
|
// then rename perfc004.dat/perfh004.dat so that PERFLIB will not find
|
||
|
// them in the future.
|
||
|
// Currently this is a hack.
|
||
|
//
|
||
|
Perflib004Update(pLangIdRequest);
|
||
|
|
||
|
pTmpLangId = pLangIdRequest;
|
||
|
pLangIdRequest = PerflibCheckPerfFile(pTmpLangId);
|
||
|
if (pLangIdRequest == NULL) {
|
||
|
pLangIdRequest = pTmpLangId;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bSubLang = ((pLangIdRequest[3] >= L'0') && (pLangIdRequest[3] <= L'9'));
|
||
|
StartIndex = LANG_ID_START;
|
||
|
if (bSubLang) {
|
||
|
StartIndex = LANG_ID_START - 1;
|
||
|
RtlMoveMemory(Names, SubFileNameTemplate, sizeof(SubFileNameTemplate));
|
||
|
}
|
||
|
|
||
|
Names[StartIndex] = QueryChar;
|
||
|
Names[StartIndex + 1] = *pLangIdRequest++;
|
||
|
Names[StartIndex + 2] = *pLangIdRequest++;
|
||
|
Names[StartIndex + 3] = *pLangIdRequest++;
|
||
|
if (bSubLang) {
|
||
|
Names[StartIndex + 4] = *pLangIdRequest;
|
||
|
}
|
||
|
|
||
|
TRACE((WINPERF_DBG_TRACE_INFO),
|
||
|
(&PerflibGuid, __LINE__, PERF_GET_NAMES,
|
||
|
ARG_DEF(ARG_TYPE_WSTR, 1), 0,
|
||
|
Names, WSTRSIZE(Names), NULL));
|
||
|
|
||
|
RtlInitUnicodeString(&NtFileName, Names);
|
||
|
// open the file for info
|
||
|
InitializeObjectAttributes( &ObjectAttributes,
|
||
|
&NtFileName,
|
||
|
OBJ_CASE_INSENSITIVE,
|
||
|
(HANDLE)NULL,
|
||
|
NULL
|
||
|
);
|
||
|
if (bAddNames) {
|
||
|
// writing name to data file
|
||
|
|
||
|
LARGE_INTEGER ByteOffset;
|
||
|
|
||
|
ByteOffset.LowPart = ByteOffset.HighPart = 0;
|
||
|
Status = NtCreateFile( &File,
|
||
|
SYNCHRONIZE | GENERIC_WRITE,
|
||
|
&ObjectAttributes,
|
||
|
&IoStatus,
|
||
|
NULL, // no initial size
|
||
|
FILE_ATTRIBUTE_NORMAL,
|
||
|
FILE_SHARE_READ,
|
||
|
FILE_SUPERSEDE, // always create
|
||
|
FILE_SYNCHRONOUS_IO_NONALERT,
|
||
|
NULL, // no ea buffer
|
||
|
0 // no ea buffer
|
||
|
);
|
||
|
if (!NT_SUCCESS( Status )) {
|
||
|
TRACE((WINPERF_DBG_TRACE_INFO),
|
||
|
(&PerflibGuid, __LINE__, PERF_GET_NAMES, 0, Status, NULL));
|
||
|
return( Status );
|
||
|
}
|
||
|
Status = NtWriteFile( File,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
&IoStatus,
|
||
|
lpData,
|
||
|
*lpcbData,
|
||
|
&ByteOffset,
|
||
|
NULL
|
||
|
);
|
||
|
|
||
|
if (!NT_SUCCESS( Status )) {
|
||
|
TRACE((WINPERF_DBG_TRACE_INFO),
|
||
|
(&PerflibGuid, __LINE__, PERF_GET_NAMES, 0, Status, NULL));
|
||
|
NtClose( File );
|
||
|
return( Status );
|
||
|
}
|
||
|
} else {
|
||
|
// reading name from data file
|
||
|
Status = NtOpenFile( &File,
|
||
|
SYNCHRONIZE | GENERIC_READ,
|
||
|
&ObjectAttributes,
|
||
|
&IoStatus,
|
||
|
FILE_SHARE_DELETE |
|
||
|
FILE_SHARE_READ |
|
||
|
FILE_SHARE_WRITE,
|
||
|
FILE_SYNCHRONOUS_IO_NONALERT |
|
||
|
FILE_NON_DIRECTORY_FILE
|
||
|
);
|
||
|
|
||
|
if (!NT_SUCCESS( Status )) {
|
||
|
TRACE((WINPERF_DBG_TRACE_INFO),
|
||
|
(&PerflibGuid, __LINE__, PERF_GET_NAMES, 0, Status, NULL));
|
||
|
return( Status );
|
||
|
}
|
||
|
|
||
|
Status = NtQueryInformationFile( File,
|
||
|
&IoStatus,
|
||
|
(PVOID)&FileInformation,
|
||
|
sizeof( FileInformation ),
|
||
|
FileStandardInformation
|
||
|
);
|
||
|
|
||
|
if (NT_SUCCESS( Status )) {
|
||
|
if (FileInformation.EndOfFile.HighPart) {
|
||
|
Status = STATUS_BUFFER_OVERFLOW;
|
||
|
TRACE((WINPERF_DBG_TRACE_INFO),
|
||
|
(&PerflibGuid, __LINE__, PERF_GET_NAMES, 0, Status, NULL));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!NT_SUCCESS( Status )) {
|
||
|
TRACE((WINPERF_DBG_TRACE_INFO),
|
||
|
(&PerflibGuid, __LINE__, PERF_GET_NAMES, 0, Status, NULL));
|
||
|
NtClose( File );
|
||
|
return( Status );
|
||
|
}
|
||
|
|
||
|
if (!ARGUMENT_PRESENT (lpData) ||
|
||
|
*lpcbData < FileInformation.EndOfFile.LowPart) {
|
||
|
NtClose( File );
|
||
|
TRACE((WINPERF_DBG_TRACE_INFO),
|
||
|
(&PerflibGuid, __LINE__, PERF_GET_NAMES, 0, Status, NULL));
|
||
|
if (ARGUMENT_PRESENT (lpcbLen)) {
|
||
|
// no data yet for the rpc
|
||
|
*lpcbLen = 0;
|
||
|
}
|
||
|
*lpcbData = FileInformation.EndOfFile.LowPart;
|
||
|
if (ARGUMENT_PRESENT (lpData)) {
|
||
|
TRACE((WINPERF_DBG_TRACE_INFO),
|
||
|
(&PerflibGuid, __LINE__, PERF_GET_NAMES, 0, Status, NULL));
|
||
|
return (STATUS_BUFFER_OVERFLOW);
|
||
|
}
|
||
|
|
||
|
return(STATUS_SUCCESS);
|
||
|
}
|
||
|
|
||
|
|
||
|
Status = NtReadFile( File,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
&IoStatus,
|
||
|
lpData,
|
||
|
FileInformation.EndOfFile.LowPart,
|
||
|
NULL,
|
||
|
NULL
|
||
|
);
|
||
|
|
||
|
if (NT_SUCCESS( Status )) {
|
||
|
|
||
|
Status = IoStatus.Status;
|
||
|
|
||
|
if (NT_SUCCESS( Status )) {
|
||
|
if (IoStatus.Information != FileInformation.EndOfFile.LowPart) {
|
||
|
Status = STATUS_END_OF_FILE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
TRACE((WINPERF_DBG_TRACE_INFO),
|
||
|
(&PerflibGuid, __LINE__, PERF_GET_NAMES, 0, Status, NULL));
|
||
|
}
|
||
|
|
||
|
if (NT_SUCCESS( Status )) {
|
||
|
*lpcbData = FileInformation.EndOfFile.LowPart;
|
||
|
|
||
|
if (ARGUMENT_PRESENT (lpcbLen))
|
||
|
*lpcbLen = FileInformation.EndOfFile.LowPart;
|
||
|
}
|
||
|
} // end of reading names
|
||
|
|
||
|
NtClose (File);
|
||
|
return (Status);
|
||
|
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
PerfGetPrimaryLangId(
|
||
|
DWORD dwLangId,
|
||
|
WCHAR * PrimaryLangId
|
||
|
)
|
||
|
{
|
||
|
// build the native language id
|
||
|
WCHAR LangId;
|
||
|
WCHAR nDigit;
|
||
|
|
||
|
LangId = (WCHAR) PRIMARYLANGID(dwLangId);
|
||
|
|
||
|
nDigit = (WCHAR) (LangId >> 8);
|
||
|
PrimaryLangId[0] = tohexdigit(nDigit);
|
||
|
|
||
|
nDigit = (WCHAR) (LangId & 0XF0) >> 4;
|
||
|
PrimaryLangId[1] = tohexdigit(nDigit);
|
||
|
|
||
|
nDigit = (WCHAR) (LangId & 0xF);
|
||
|
PrimaryLangId[2] = tohexdigit(nDigit);
|
||
|
PrimaryLangId[3] = L'\0';
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
PerfGetLangId(
|
||
|
WCHAR *FullLangId
|
||
|
)
|
||
|
{
|
||
|
WCHAR LangId;
|
||
|
WCHAR nDigit;
|
||
|
|
||
|
LangId = (WCHAR) GetUserDefaultUILanguage();
|
||
|
|
||
|
nDigit = (LangId & 0xF000) >> 12;
|
||
|
FullLangId[0] = tohexdigit(nDigit);
|
||
|
|
||
|
nDigit = (LangId & 0x0F00) >> 8;
|
||
|
FullLangId[1] = tohexdigit(nDigit);
|
||
|
|
||
|
nDigit = (LangId & 0x00F0) >> 4;
|
||
|
FullLangId[2] = tohexdigit(nDigit);
|
||
|
|
||
|
nDigit = LangId & 0xF;
|
||
|
FullLangId[3] = tohexdigit(nDigit);
|
||
|
|
||
|
FullLangId[4] = L'\0';
|
||
|
}
|
||
|
|
||
|
DWORD
|
||
|
GetLangIdFromSzLang(
|
||
|
LPWSTR szLangId
|
||
|
)
|
||
|
{
|
||
|
DWORD dwLangId = 0;
|
||
|
DWORD dwLangLen = lstrlenW(szLangId);
|
||
|
DWORD i;
|
||
|
WCHAR wszDigit;
|
||
|
|
||
|
for (i = 0; i < dwLangLen; i ++) {
|
||
|
dwLangId <<= 4;
|
||
|
wszDigit = szLangId[i];
|
||
|
if (wszDigit >= L'0' && wszDigit <= L'9') {
|
||
|
dwLangId += (wszDigit - L'0');
|
||
|
}
|
||
|
else if (wszDigit >= L'a' && wszDigit <= 'f') {
|
||
|
dwLangId += (10 + wszDigit - L'a');
|
||
|
}
|
||
|
else if (wszDigit >= L'A' && wszDigit <= 'F') {
|
||
|
dwLangId += (10 + wszDigit - L'A');
|
||
|
}
|
||
|
else {
|
||
|
dwLangId = 0;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return dwLangId;
|
||
|
}
|
||
|
|
||
|
WCHAR szRtnLang[5];
|
||
|
WCHAR szSysDir[MAX_PATH];
|
||
|
WCHAR szSrchDir[MAX_PATH];
|
||
|
WCHAR szTmpFile[MAX_PATH];
|
||
|
LPCWSTR szCtrLangFile = L"perfc";
|
||
|
LPCWSTR szCtrSubLangFile = L"prfc";
|
||
|
LPCWSTR szHlpLangFile = L"perfh";
|
||
|
LPCWSTR szHlpSubLangFile = L"prfh";
|
||
|
LPCWSTR sz004CtrLangFile = L"perfc004.dat";
|
||
|
LPCWSTR sz004HlpLangFile = L"perfh004.dat";
|
||
|
LPCWSTR szFileExt = L".dat";
|
||
|
|
||
|
LPWSTR
|
||
|
PerflibFindCounterFile(
|
||
|
IN LPWSTR szFilePath,
|
||
|
IN BOOLEAN bCheckSubLang,
|
||
|
IN LPWSTR szLangId
|
||
|
)
|
||
|
{
|
||
|
WCHAR szThisLang[5];
|
||
|
WCHAR szPrimaryLang[5];
|
||
|
DWORD dwThisLang;
|
||
|
DWORD dwFileLen;
|
||
|
WIN32_FIND_DATAW FindFileData;
|
||
|
BOOLEAN bResult = FALSE;
|
||
|
HANDLE hFile = FindFirstFileExW(szFilePath,
|
||
|
FindExInfoStandard,
|
||
|
& FindFileData,
|
||
|
FindExSearchNameMatch,
|
||
|
NULL,
|
||
|
0);
|
||
|
RtlZeroMemory(szRtnLang, 5 * sizeof(WCHAR));
|
||
|
if (hFile != INVALID_HANDLE_VALUE) {
|
||
|
if (bCheckSubLang) {
|
||
|
do {
|
||
|
dwFileLen = lstrlenW(FindFileData.cFileName);
|
||
|
if (dwFileLen == 12) {
|
||
|
ZeroMemory(szThisLang, 5 * sizeof(WCHAR));
|
||
|
ZeroMemory(szPrimaryLang, 5 * sizeof(WCHAR));
|
||
|
lstrcpynW(szThisLang,
|
||
|
(LPWSTR) (FindFileData.cFileName + (dwFileLen - 8)),
|
||
|
5);
|
||
|
dwThisLang = GetLangIdFromSzLang(szThisLang);
|
||
|
if (dwThisLang != 0) {
|
||
|
PerfGetPrimaryLangId(dwThisLang, szPrimaryLang);
|
||
|
bResult = (lstrcmpiW(szPrimaryLang, szLangId) == 0);
|
||
|
if (bResult == TRUE) {
|
||
|
lstrcpyW(szRtnLang, szThisLang);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
while (FindNextFileW(hFile, & FindFileData));
|
||
|
}
|
||
|
else {
|
||
|
bResult = TRUE;
|
||
|
lstrcpyW(szRtnLang, szLangId);
|
||
|
}
|
||
|
FindClose(hFile);
|
||
|
}
|
||
|
return bResult ? szRtnLang : NULL;
|
||
|
}
|
||
|
|
||
|
LPWSTR
|
||
|
PerflibCheckPerfFile(
|
||
|
IN LPWSTR LangId
|
||
|
)
|
||
|
{
|
||
|
DWORD dwLangLen = lstrlenW(LangId);
|
||
|
DWORD dwLangId;
|
||
|
LPWSTR szRtnLang = NULL;
|
||
|
WCHAR szLang[5];
|
||
|
|
||
|
ZeroMemory(szSysDir, sizeof(WCHAR) * MAX_PATH);
|
||
|
GetSystemDirectoryW(szSysDir, MAX_PATH);
|
||
|
ZeroMemory(szSrchDir, sizeof(WCHAR) * MAX_PATH);
|
||
|
if (dwLangLen == 4) {
|
||
|
lstrcpyW(szSrchDir, szSysDir);
|
||
|
lstrcatW(szSrchDir, L"\\");
|
||
|
lstrcatW(szSrchDir, szCtrSubLangFile);
|
||
|
lstrcatW(szSrchDir, LangId);
|
||
|
lstrcatW(szSrchDir, szFileExt);
|
||
|
szRtnLang = PerflibFindCounterFile(szSrchDir, FALSE, LangId);
|
||
|
|
||
|
if (szRtnLang == NULL) {
|
||
|
dwLangId = GetLangIdFromSzLang(LangId);
|
||
|
if (dwLangId != 0) {
|
||
|
ZeroMemory(szLang, sizeof(WCHAR) * 5);
|
||
|
PerfGetPrimaryLangId(dwLangId, szLang);
|
||
|
ZeroMemory(szSrchDir, sizeof(WCHAR) * MAX_PATH);
|
||
|
lstrcpyW(szSrchDir, szSysDir);
|
||
|
lstrcatW(szSrchDir, L"\\");
|
||
|
lstrcatW(szSrchDir, szCtrLangFile);
|
||
|
lstrcatW(szSrchDir, szLang);
|
||
|
lstrcatW(szSrchDir, szFileExt);
|
||
|
szRtnLang = PerflibFindCounterFile(szSrchDir, FALSE, szLang);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
// dwLangId should be 3, this is primary UserDefaultUILanguage.
|
||
|
//
|
||
|
ZeroMemory(szSrchDir, sizeof(WCHAR) * MAX_PATH);
|
||
|
lstrcpyW(szSrchDir, szSysDir);
|
||
|
lstrcatW(szSrchDir, L"\\");
|
||
|
lstrcatW(szSrchDir, szCtrLangFile);
|
||
|
lstrcatW(szSrchDir, LangId);
|
||
|
lstrcatW(szSrchDir, szFileExt);
|
||
|
szRtnLang = PerflibFindCounterFile(szSrchDir, FALSE, LangId);
|
||
|
if (szRtnLang == NULL) {
|
||
|
ZeroMemory(szSrchDir, sizeof(WCHAR) * MAX_PATH);
|
||
|
lstrcpyW(szSrchDir, szSysDir);
|
||
|
lstrcatW(szSrchDir, L"\\");
|
||
|
lstrcatW(szSrchDir, szCtrSubLangFile);
|
||
|
lstrcatW(szSrchDir, L"??");
|
||
|
lstrcatW(szSrchDir, (LPWSTR) (LangId + 1));
|
||
|
lstrcatW(szSrchDir, szFileExt);
|
||
|
szRtnLang = PerflibFindCounterFile(szSrchDir, TRUE, LangId);
|
||
|
}
|
||
|
}
|
||
|
return szRtnLang;
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
PerflibRename004File(
|
||
|
IN LPWSTR szSysDir,
|
||
|
IN LPWSTR szLangId,
|
||
|
IN BOOLEAN bCounterFile
|
||
|
)
|
||
|
{
|
||
|
ZeroMemory(szSrchDir, sizeof(WCHAR) * MAX_PATH);
|
||
|
lstrcpyW(szSrchDir, szSysDir);
|
||
|
lstrcatW(szSrchDir, L"\\");
|
||
|
if (bCounterFile) {
|
||
|
lstrcatW(szSrchDir, sz004CtrLangFile);
|
||
|
}
|
||
|
else {
|
||
|
lstrcatW(szSrchDir, sz004HlpLangFile);
|
||
|
}
|
||
|
|
||
|
ZeroMemory(szTmpFile, sizeof(WCHAR) * MAX_PATH);
|
||
|
lstrcpyW(szTmpFile, szSysDir);
|
||
|
lstrcatW(szTmpFile, L"\\");
|
||
|
if (szLangId) {
|
||
|
if (bCounterFile) {
|
||
|
lstrcatW(szTmpFile, szCtrSubLangFile);
|
||
|
}
|
||
|
else {
|
||
|
lstrcatW(szTmpFile, szHlpSubLangFile);
|
||
|
}
|
||
|
lstrcatW(szTmpFile, szLangId);
|
||
|
lstrcatW(szTmpFile, szFileExt);
|
||
|
CopyFileW(szSrchDir, szTmpFile, FALSE);
|
||
|
}
|
||
|
else {
|
||
|
lstrcatW(szTmpFile, L"\\");
|
||
|
if (bCounterFile) {
|
||
|
lstrcatW(szTmpFile, sz004CtrLangFile);
|
||
|
}
|
||
|
else {
|
||
|
lstrcatW(szTmpFile, sz004HlpLangFile);
|
||
|
}
|
||
|
lstrcatW(szTmpFile, L".tmp");
|
||
|
DeleteFileW(szTmpFile);
|
||
|
MoveFileW(szSrchDir, szTmpFile);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
Perflib004Update(
|
||
|
IN LPWSTR pLangIdRequest
|
||
|
)
|
||
|
{
|
||
|
if (GetLangIdFromSzLang(pLangIdRequest) != LANG_CHINESE) goto Cleanup;
|
||
|
|
||
|
// Search whether PERFC004.DAT and PRFC0?04.DAT are in System32 directory
|
||
|
//
|
||
|
ZeroMemory(szSysDir, sizeof(WCHAR) * MAX_PATH);
|
||
|
GetSystemDirectoryW(szSysDir, MAX_PATH);
|
||
|
|
||
|
if (SearchPathW(szSysDir, sz004CtrLangFile, NULL, 0, NULL, NULL) == 0)
|
||
|
goto Cleanup;
|
||
|
|
||
|
ZeroMemory(szRtnLang, sizeof(WCHAR) * 5);
|
||
|
PerfGetLangId(szRtnLang);
|
||
|
ZeroMemory(szTmpFile, sizeof(WCHAR) * MAX_PATH);
|
||
|
lstrcpyW(szTmpFile, szCtrSubLangFile);
|
||
|
lstrcatW(szTmpFile, szRtnLang);
|
||
|
lstrcatW(szTmpFile, szFileExt);
|
||
|
|
||
|
if (SearchPathW(szSysDir, szTmpFile, NULL, 0, NULL, NULL) == 0)
|
||
|
goto Cleanup;
|
||
|
|
||
|
// Found PERFC004.DAT, assume that PERFH004.DAT is also there.
|
||
|
// Rename to PRFC0?04.DAT/PRFH0?04.DAT
|
||
|
//
|
||
|
PerflibRename004File(szSysDir, szRtnLang, TRUE);
|
||
|
PerflibRename004File(szSysDir, szRtnLang, FALSE);
|
||
|
PerflibRename004File(szSysDir, NULL, TRUE);
|
||
|
PerflibRename004File(szSysDir, NULL, FALSE);
|
||
|
|
||
|
Cleanup:
|
||
|
return;
|
||
|
}
|
||
|
|