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.
 
 
 
 
 
 

776 lines
22 KiB

/****************************** Module Header ******************************\
* Module Name: femgrate.c
*
* Copyright (c) 1985 - 1999, Microsoft Corporation
*
* FEMGRATE, main functions
*
\***************************************************************************/
#include "femgrate.h"
#include <tchar.h>
FUNC_DIR FuncDir[FUNC_NumofFunctions] = {
{'l',FUNC_PatchInLogon},
{'s',FUNC_PatchInSetup},
{'u',FUNC_PatchFEUIFont},
{'p',FUNC_PatchPreload},
{'t',FUNC_PatchTest},
{'c',FUNC_PatchCHSAnsiEMB}
};
HINSTANCE ghInst=NULL;
//
// Function Declaration
//
//
// Max size of a value's data
//
//
// Max number of Functions NO_FUNCTION - 1
//
UINT GetFunctions(
int *pCmdList,
int nNum)
{
int i,j;
int nMaxNum;
int nCommands;
if ((__argc <=1) || nNum < 2)
return 0;
//
// reserved one cell for terminiator
//
nMaxNum = (__argc-1 > nNum-1) ? nNum-1 : __argc-1;
for (nCommands = 0,i=1; i <= nMaxNum; i++) {
if (__argv[i][0] != '-') {
continue;
}
for (j=0; j<FUNC_NumofFunctions ; j++) {
if (FuncDir[j].cFunc == __argv[i][1]) {
pCmdList[nCommands++] = FuncDir[j].nID;
}
}
}
pCmdList[nCommands] = NO_FUNCTION;
return nCommands;
}
//
// In 3.51/4.0, the time zone name displaying on date/time applets was in English
//
// we want to change it back to localization string
//
BOOL FixTimeZone(UINT nLocale)
{
DWORD dwErr,dwType,dwSize;
HKEY hSysKey,hSftKey;
BOOL bOK = FALSE;
TCHAR szStdName[MAX_PATH];
TCHAR szTimeZoneLookup[MAX_PATH];
dwErr = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
TEXT("System\\CurrentControlSet\\Control\\TimeZoneInformation"),
0,
KEY_READ | KEY_WRITE,
&hSysKey );
if (dwErr != ERROR_SUCCESS) {
DebugMsg((DM_VERBOSE,TEXT("[FixTimeZone] Open System\\CurrentControlSet\\Control\\TimeZoneInformation failed !\n")));
goto Err0;
}
dwSize = sizeof(szStdName);
dwErr = RegQueryValueEx(hSysKey,
TEXT("StandardName"),
NULL,
&dwType,
(LPBYTE) szStdName,
&dwSize);
if (dwErr != ERROR_SUCCESS) {
DebugMsg((DM_VERBOSE,TEXT("[FixTimeZone] StandardName doesn't exist !\n")));
bOK = TRUE;
goto Err1;
}
//
// KOR 3.51 used "Japanese Standard Time". It is necessary to change it to "Seul Standard time"
//
// check if system locale is KOR and the length of szStdName is non-zero
//
DebugMsg((DM_VERBOSE,TEXT("[FixTimeZone] locale = %X, dwSize = %d !\n"),nLocale,dwSize));
if ((nLocale == LOCALE_KOR) && dwSize) {
if (lstrcmpi(szStdName,TEXT("Tokyo Standard Time"))== 0) {
lstrcpy(szStdName,TEXT("Korea Standard Time"));
}
}
wsprintf(szTimeZoneLookup,TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones\\%s"),szStdName);
DebugMsg((DM_VERBOSE,TEXT("[FixTimeZone] Open %s !\n"),szTimeZoneLookup));
dwErr = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
szTimeZoneLookup,
0,
KEY_READ,
&hSftKey );
if (dwErr != ERROR_SUCCESS) {
DebugMsg((DM_VERBOSE,TEXT("[FixTimeZone] %s doesn't exist !\n"),szTimeZoneLookup));
bOK = TRUE;
goto Err1;
}
dwSize = sizeof(szStdName);
dwErr = RegQueryValueEx(hSftKey,
TEXT("Std"),
NULL,
&dwType,
(LPBYTE) szStdName,
&dwSize);
if (dwErr != ERROR_SUCCESS) {
DebugMsg((DM_VERBOSE,TEXT("[FixTimeZone] Query Std failed, abornomal !\n")));
goto Err2;
}
dwErr = RegSetValueEx(hSysKey,
TEXT("StandardName"),
0,
REG_SZ,
(LPBYTE) szStdName,
(lstrlen(szStdName)+1)*sizeof(TCHAR));
if (dwErr != ERROR_SUCCESS) {
DebugMsg((DM_VERBOSE,TEXT("[FixTimeZone] Set Standardname failed !\n")));
goto Err2;
}
dwSize = sizeof(szStdName);
dwErr = RegQueryValueEx(hSftKey,
TEXT("Dlt"),
NULL,
&dwType,
(LPBYTE) szStdName,
&dwSize);
if (dwErr != ERROR_SUCCESS) {
DebugMsg((DM_VERBOSE,TEXT("[FixTimeZone] Query Dlt failed, abornomal !\n")));
bOK = TRUE;
goto Err2;
}
dwErr = RegSetValueEx(hSysKey,
TEXT("DaylightName"),
0,
REG_SZ,
(LPBYTE) szStdName,
(lstrlen(szStdName)+1)*sizeof(TCHAR));
if (dwErr != ERROR_SUCCESS) {
DebugMsg((DM_VERBOSE,TEXT("[FixTimeZone] Set DaylightName failed !\n")));
goto Err2;
}
bOK = TRUE;
Err2:
RegCloseKey(hSftKey);
Err1:
RegCloseKey(hSysKey);
Err0:
return bOK;
}
//
// Patch CHT/CHS 3.51 bug
// 1. length of Preload Values is 8, patch to 9
// 2. replace 00000409 with default lang ID
// 3. if default lang ID existed, we don't replace anything
//
BOOL PatchPreloadKeyboard(
BOOL bReplaceDefaultLCID) //if TRUE will replace 409 with default LCID
{
HKEY hkLayoutPreload;
LONG lResult;
int i;
BOOL bFoundDefaultLocale = FALSE;
int nFound0409 = -1;
TCHAR szDefaultLocaleID[KL_NAMELENGTH];
TCHAR szPreloadID[4*sizeof(TCHAR)]; // 3 digits + NULL
TCHAR szLayoutID[KL_NAMELENGTH]; // 9
DWORD dwValueSize;
wsprintf(szDefaultLocaleID,TEXT("%08X"),GetSystemDefaultLCID());
lResult = RegOpenKeyEx(HKEY_CURRENT_USER,
TEXT("keyboard layout\\preload"),
0,
KEY_READ | KEY_WRITE,
&hkLayoutPreload);
if (lResult != ERROR_SUCCESS) {
return FALSE;
}
for (i=1; i<=999;i++) { // size allows up to 999 preloaded!!!!!
wsprintf(szPreloadID,TEXT("%d"),i);
dwValueSize = 0;
RegQueryValueEx(hkLayoutPreload,
szPreloadID,
NULL,
NULL,
NULL,
&dwValueSize);
if (dwValueSize == 0)
break;
lResult = RegQueryValueEx(hkLayoutPreload,
szPreloadID,
NULL,
NULL,
(LPBYTE) szLayoutID,
&dwValueSize);
//
// First, fix missing NULL terminator
//
if (dwValueSize == (KL_NAMELENGTH - 1)* sizeof(TCHAR)) {
//
// this case is what we want to fix
//
szLayoutID[KL_NAMELENGTH-1] = (TCHAR) 0;
lResult = RegSetValueEx(hkLayoutPreload,
szPreloadID,
0,
REG_SZ,
(LPBYTE) szLayoutID,
sizeof(TCHAR) * KL_NAMELENGTH);
if (lResult != ERROR_SUCCESS) {
DebugMsg((DM_VERBOSE,TEXT("IMECONV: Failed to set %s = %s \n"),szPreloadID,szLayoutID));
}
}
//
// FOR CHS/CHT, we need check and replace
//
if (bReplaceDefaultLCID) {
//
// Second, fix wrong locale, rule:
// if Default Locale existed (e.q. 00000404 for CHT), do nothing
// else found 00000409, replace it with Default Locale
//
if ((dwValueSize < (KL_NAMELENGTH - 1) * sizeof(TCHAR)) ||
(dwValueSize > (KL_NAMELENGTH) * sizeof(TCHAR))) {
//
// wrong data, ignore it
//
continue;
}
if (bFoundDefaultLocale) {
continue;
}
// if (_tcsncmp(szDefaultLocaleID,szLayoutID,KL_NAMELENGTH-1)==0) {
if (_tcsncmp(L"123",L"123",KL_NAMELENGTH-1)==0) {
bFoundDefaultLocale = TRUE;
continue;
}
if (_tcsncmp(szLayoutID,TEXT("00000409"),KL_NAMELENGTH-1)==0) {
nFound0409 = i;
}
}
}
if (bReplaceDefaultLCID) {
if (!bFoundDefaultLocale) {
if (nFound0409 != -1 ) {
wsprintf(szPreloadID,TEXT("%d"),nFound0409);
lResult = RegSetValueEx(hkLayoutPreload,
szPreloadID,
0,
REG_SZ,
(LPBYTE) szDefaultLocaleID,
sizeof(TCHAR) * KL_NAMELENGTH);
if (lResult != ERROR_SUCCESS) {
DebugMsg((DM_VERBOSE,TEXT("IMECONV: Failed to set %s = %s \n"),szPreloadID,szLayoutID));
}
}
}
}
RegCloseKey (hkLayoutPreload);
if (i > 999)
return FALSE;
else
return TRUE;
}
const TCHAR g_szCaptionFont[] = TEXT("CaptionFont");
const TCHAR g_szSmCaptionFont[] = TEXT("SmCaptionFont");
const TCHAR g_szMenuFont[] = TEXT("MenuFont");
const TCHAR g_szStatusFont[] = TEXT("StatusFont");
const TCHAR g_szMessageFont[] = TEXT("MessageFont");
const TCHAR g_szIconFont[] = TEXT("IconFont");
const LPCTSTR g_rgpszFontMetrics[] = { g_szCaptionFont,
g_szSmCaptionFont,
g_szMenuFont,
g_szStatusFont,
g_szMessageFont,
g_szIconFont};
BOOL FixIncorrectCharSet(LOGFONT *plf)
{
struct NameCharSet {
char szFaceName[LF_FACESIZE*2];
BYTE bCharSet;
} Pairs[] = {
{"\x74\xad\xbc\xb9\x00\x00",0x81},
{"\xb0\x65\x30\x7d\x0e\x66\xd4\x9a\x00\x00",0x88},
{"\x8b\x5b\x53\x4f\x00\x00",0x86}
};
int i;
for (i=0; i<ARRAYSIZE(Pairs); i++) {
if (lstrcmp(plf->lfFaceName,(LPTSTR)(Pairs[i].szFaceName)) == 0) {
if (plf->lfCharSet != Pairs[i].bCharSet) {
plf->lfCharSet = Pairs[i].bCharSet;
DebugMsg((DM_VERBOSE,TEXT("FixIncorrectCharSet, we found and we fixed. [%X]\n"),Pairs[i].bCharSet));
return TRUE;
}
}
}
DebugMsg((DM_VERBOSE,TEXT("FixIncorrectCharSet, Input %s, %d, no fix needed !\n"),plf->lfFaceName,plf->lfCharSet));
return TRUE;
}
BOOL FixMSPGothic(LOGFONT *plf)
{
int i;
char szMSPGothic[LF_FACESIZE*2] = "\x2D\xFF\x33\xFF\x20\x00\x30\xFF\xB4\x30\xB7\x30\xC3\x30\xAF\x30\x00\x00";
DebugMsg((DM_VERBOSE,TEXT("FixMSPGothic, [%s] == [%s] ?\n"),plf->lfFaceName,szMSPGothic));
if (lstrcmp(plf->lfFaceName,(LPTSTR)szMSPGothic) == 0) {
lstrcpy(plf->lfFaceName,TEXT("MS UI Gothic"));
DebugMsg((DM_VERBOSE,TEXT("FixMSPGothic, we found and we fixed. [%s]\n"),plf->lfFaceName));
return TRUE;
}
return TRUE;
}
BOOL
UpdateUIFont(
BOOL bJapan,
HKEY hkeyMetrics,
LPCTSTR pszValueName,
LOGFONT *plf
)
{
DWORD dwResult = ERROR_SUCCESS;
LOGFONT lfCopy;
BOOL bOkToUpdate = FALSE;
DebugMsg((DM_VERBOSE,TEXT("UpdateUIFont, Starting ...\n")));
//
// First see if this face name should be updated.
//
if (bJapan) {
bOkToUpdate = FixMSPGothic(plf);
} else {
bOkToUpdate = FixIncorrectCharSet(plf);
}
if (bOkToUpdate) {
//
// Yep. Update the face name string in the logfont.
// Also make sure that the point size is 8 or greater
// if we're updating the icon font.
//
DebugMsg((DM_VERBOSE,TEXT("UpdateUIFont, update %s 's charset %X\n"),
plf->lfFaceName, plf->lfCharSet));
dwResult = RegSetValueEx(hkeyMetrics,
pszValueName,
0,
REG_BINARY,
(const LPBYTE)plf,
sizeof(*plf));
if (ERROR_SUCCESS != dwResult) {
DebugMsg((DM_VERBOSE,TEXT("Error %d setting NC font data for \"%s\"\n"),
dwResult, pszValueName));
return FALSE;
}
}
return TRUE;
}
void FixCurrentSchemeName(HINF hInf)
{
HKEY hkeyAppearance;
TCHAR szCurrentSchemeName[MAX_PATH];
DWORD cbValue;
DWORD dwType;
INFCONTEXT InfContext;
UINT LineCount,LineNo;
LPCTSTR szSectionName = TEXT("CurrentScheme");
LPCTSTR pszStandard;
LPCTSTR pszClassic;
DWORD dwResult = ERROR_SUCCESS;
if(hInf == INVALID_HANDLE_VALUE) {
DebugMsg((DM_VERBOSE,TEXT("[FixCurrentSchemeName] Open femgrate.inf failed !\n")));
goto Exit1;
}
LineCount = (UINT)SetupGetLineCount(hInf,szSectionName);
if((LONG)LineCount <= 0) {
DebugMsg((DM_VERBOSE,TEXT("[FixCurrentSchemeName] line count == 0 !\n")));
goto Exit1;
}
dwResult = RegOpenKeyEx(HKEY_CURRENT_USER,
TEXT("Control Panel\\Appearance"),
0,
KEY_ALL_ACCESS,
&hkeyAppearance);
if (ERROR_SUCCESS != dwResult ) {
DebugMsg((DM_VERBOSE,TEXT("[FixCurrentSchemeName] Key Control Panel\\Appearance doesn't exist\r\n")));
goto Exit1;
}
cbValue = sizeof(szCurrentSchemeName) * sizeof(TCHAR);
dwResult = RegQueryValueEx(hkeyAppearance,
TEXT("Current"),
NULL,
&dwType,
(LPBYTE)szCurrentSchemeName,
&cbValue);
if (ERROR_SUCCESS != dwResult) {
DebugMsg((DM_VERBOSE,TEXT("[FixCurrentSchemeName] No Current value, not an error !\r\n")));
goto Exit2;
}
for(LineNo=0; LineNo<LineCount; LineNo++) {
if (SetupGetLineByIndex(hInf,szSectionName,LineNo,&InfContext)
&& (pszStandard = pSetupGetField(&InfContext,1))
&& (pszClassic = pSetupGetField(&InfContext,2))) {
if (lstrcmp(pszStandard,szCurrentSchemeName) == 0) {
lstrcpy(szCurrentSchemeName,pszClassic);
break;
}
}
}
dwResult = RegSetValueEx(hkeyAppearance,
TEXT("Current"),
0,
REG_SZ,
(LPBYTE)szCurrentSchemeName,
(lstrlen(szCurrentSchemeName)+1) * sizeof(TCHAR));
Exit2:
RegCloseKey(hkeyAppearance);
Exit1:
return;
}
BOOL FixCurrentSchemeData(BOOL bJapan)
{
DWORD dwResult = ERROR_SUCCESS;
HKEY hkeyMetrics;
DebugMsg((DM_VERBOSE,TEXT("DoPatchUIFont, Starting ... \n")));
dwResult = RegOpenKeyEx(HKEY_CURRENT_USER,
TEXT("Control Panel\\Desktop\\WindowMetrics"),
0,
KEY_ALL_ACCESS,
&hkeyMetrics);
if (ERROR_SUCCESS == dwResult)
{
DWORD cbValue;
DWORD dwType;
LOGFONT lf;
int i;
for (i = 0; i < ARRAYSIZE(g_rgpszFontMetrics); i++)
{
LPCTSTR pszValueName = g_rgpszFontMetrics[i];
//
LOGFONT *plf = NULL;
cbValue = sizeof(lf);
dwResult = RegQueryValueEx(hkeyMetrics,
pszValueName,
NULL,
&dwType,
(LPBYTE)&lf,
&cbValue);
if (ERROR_SUCCESS == dwResult)
{
if (REG_BINARY == dwType)
{
plf = &lf;
if (!UpdateUIFont(bJapan,hkeyMetrics, pszValueName, plf)) {
DebugMsg((DM_VERBOSE,TEXT("DoPatchUIFont,UpdateUIFont failed \n")));
}
} else {
DebugMsg((DM_VERBOSE,TEXT("DoPatchUIFont,not binary format \n")));
}
}
}
DebugMsg((DM_VERBOSE,TEXT("DoPatchUIFont, colsing ... \n")));
RegCloseKey(hkeyMetrics);
}
else if (ERROR_FILE_NOT_FOUND == dwResult)
{
//
// Some keys under HKEY_USERS don't have WindowMetric information.
// Such cases are not processed but are still considered successful.
//
DebugMsg((DM_VERBOSE,TEXT("DoPatchUIFont,Some keys under HKEY_USERS don't have WindowMetric information \n")));
dwResult = ERROR_SUCCESS;
}
else
{
DebugMsg((DM_VERBOSE,TEXT("DoPatchUIFont,Error %d opening key \n"), dwResult));
}
return (TRUE);
}
BOOL FixSchemeProblem(BOOL bJapan, HINF hInf)
{
FixCurrentSchemeData(bJapan);
FixCurrentSchemeName(hInf);
return TRUE;
}
BOOL RenameRegValueName(HINF hInf, BOOL PerUser)
{
LPCTSTR RegRoot,RegPath;
LPCTSTR RegOldVal,RegNewVal;
LONG LineCount,LineNo;
DWORD dwSize,dwType;
INFCONTEXT InfContext;
HKEY Key,KeyRoot;
BOOL bOK;
LPBYTE RegData;
LONG lResult;
TCHAR SectionName[MAX_PATH];
if (PerUser) {
lstrcpy(SectionName,TEXT("RenameRegValueName.PerUser"));
} else {
lstrcpy(SectionName,TEXT("RenameRegValueName.PerSystem"));
}
if(hInf == INVALID_HANDLE_VALUE) {
DebugMsg((DM_VERBOSE,TEXT("[ReplaceRegValueName] Open femgrate.inf failed !\n")));
return FALSE;
}
LineCount = (UINT)SetupGetLineCount(hInf,SectionName);
if((LONG)LineCount <= 0) {
DebugMsg((DM_VERBOSE,TEXT("[ReplaceRegValueName] line count == 0 !\n")));
return FALSE;
}
for(LineNo = 0; LineNo < LineCount; LineNo++) {
if (SetupGetLineByIndex(hInf,SectionName,LineNo,&InfContext)
&& (RegRoot = pSetupGetField(&InfContext,1))
&& (RegPath = pSetupGetField(&InfContext,2))
&& (RegOldVal = pSetupGetField(&InfContext,3))
&& (RegNewVal = pSetupGetField(&InfContext,4))) {
if (!LookUpStringInTable(InfRegSpecTohKey,RegRoot,(PUINT)&KeyRoot)) {
continue;
}
lResult = RegOpenKeyEx( KeyRoot,
RegPath,
0,
KEY_READ | KEY_WRITE,
&Key);
if (lResult != ERROR_SUCCESS) {
continue;
}
dwSize = 0;
lResult = RegQueryValueEx (Key,
RegOldVal,
NULL,
&dwType,
NULL,
&dwSize);
if (lResult != ERROR_SUCCESS) {
goto Err1;
}
RegData = (BYTE *) malloc(dwSize+1);
if (!RegData) {
goto Err1;
}
lResult = RegQueryValueEx (Key,
RegOldVal,
NULL,
&dwType,
RegData,
&dwSize);
lResult = RegSetValueEx (Key,
RegNewVal,
0,
dwType,
RegData,
dwSize);
if (lResult != ERROR_SUCCESS) {
goto Err2;
}
RegDeleteValue(Key,
RegOldVal);
Err2:
free(RegData);
Err1:
RegCloseKey(Key);
}
}
return TRUE;
}
int WINAPI WinMainFE(
LPSTR lpCmdLine,
UINT uLocale)
{
int Cmds[FUNC_NumofFunctions + 1];
int i;
HINF hMigrateInf;
#ifdef DEBUGLOG
SetupOpenLog (FALSE);
#endif
if (GetFunctions(Cmds,FUNC_NumofFunctions+1) == 0) {
DebugMsg((DM_VERBOSE,TEXT("FEGRPCV: There are no valid commands. \n")));
return (1);
}
hMigrateInf = SetupOpenInfFile(
TEXT("femgrate.inf"),
NULL,
INF_STYLE_WIN4,
NULL);
if(hMigrateInf == INVALID_HANDLE_VALUE) {
DebugMsg((DM_VERBOSE,TEXT("[FixCommon] Open femgrate.inf failed !\n")));
return 0;
}
for (i=0; Cmds[i] != NO_FUNCTION && i < FUNC_NumofFunctions+1; i++) {
switch (uLocale) {
case 0x404:
WinMainCHT(Cmds[i],hMigrateInf);
break;
case 0x411:
WinMainJPN(Cmds[i],hMigrateInf);
break;
case 0x412:
WinMainKOR(Cmds[i],hMigrateInf);
break;
case 0x804:
WinMainCHS(Cmds[i],hMigrateInf);
break;
default:
break;
}
}
SetupCloseInfFile(hMigrateInf);
#ifdef DEBUGLOG
SetupCloseLog();
#endif
return (0);
}
int WINAPI WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
DebugMsg((DM_VERBOSE,TEXT("FEGRPCV: Start Executing....\n")));
ghInst = hInstance;
//
// In order to share the code for CHT/CHS/KOR, fork here
//
if ((GetInstallLocale() == 0x0412) ||
(GetInstallLocale() == 0x0404) ||
(GetInstallLocale() == 0x0804) ||
(GetInstallLocale() == 0x0411)) {
DebugMsg((DM_VERBOSE,TEXT("FEGRPCV: calling WinMainFE %X....\n"),GetInstallLocale()));
return (WinMainFE(lpCmdLine,GetInstallLocale()));
} else {
DebugMsg((DM_VERBOSE,TEXT("FEGRPCV: Not valid locale....\n")));
return 0;
}
}