windows-nt/Source/XPSP1/NT/windows/feime/fe/chimemig/common.c

1231 lines
35 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
#include <windows.h>
#include <setupapi.h>
#include <tchar.h>
#include <malloc.h>
#include "resource.h"
#include "common.h"
TCHAR szMsgBuf[MAX_PATH];
#pragma pack(push, USERDIC, 1 )
//
// Cht/Chs EUDC IME table Header Format
//
typedef struct tagUSRDICIMHDR {
WORD uHeaderSize; // 0x00
BYTE idUserCharInfoSign[8]; // 0x02
BYTE idMajor; // 0x0A
BYTE idMinor; // 0x0B
DWORD ulTableCount; // 0x0C
WORD cMethodKeySize; // 0x10
BYTE uchBankID; // 0x12
WORD idInternalBankID; // 0x13
BYTE achCMEXReserved1[43]; // 0x15
WORD uInfoSize; // 0x40
BYTE chCmdKey; // 0x42
BYTE idStlnUpd; // 0x43
BYTE cbField; // 0x44
WORD idCP; // 0x45
BYTE achMethodName[6]; // 0x47
BYTE achCSIReserved2[51]; // 0x4D
BYTE achCopyRightMsg[128]; // 0x80
} USRDICIMHDR;
typedef struct tagWinAR30EUDC95 {
WORD ID;
WORD Code;
BYTE Seq[4];
} WinAR30EUDC95;
typedef struct tagWinAR30EUDCNT {
WORD ID;
WORD Code;
BYTE Seq[5];
} WinAR30EUDCNT;
#pragma pack(pop, USERDIC)
typedef struct tagTABLIST {
UINT nResID;
TCHAR szIMEName[MAX_PATH];
} TABLELIST,*LPTABLELIST;
BYTE WinAR30MapTable[] = {0x00, 0x00 ,
0x3F, 0x3F ,
0x1E, 0x01 ,
0x1B, 0x02 ,
0x1C, 0x03 ,
0x1D, 0x04 ,
0x3E, 0x3E ,
0x01, 0x05 ,
0x02, 0x06 ,
0x03, 0x07 ,
0x04, 0x08 ,
0x05, 0x09 ,
0x06, 0x0a ,
0x07, 0x0b ,
0x08, 0x0c ,
0x09, 0x0d ,
0x0A, 0x0e ,
0x0B, 0x0f ,
0x0C, 0x10 ,
0x0D, 0x11 ,
0x0E, 0x12 ,
0x0F, 0x13 ,
0x10, 0x14 ,
0x11, 0x15 ,
0x12, 0x16 ,
0x13, 0x17 ,
0x14, 0x18 ,
0x15, 0x19 ,
0x16, 0x1a ,
0x17, 0x1b ,
0x18, 0x1c ,
0x19, 0x1d ,
0x1A, 0x1e };
// ----------------------------------------------------------------------------
// An EUDC IME table comprises a Header and lots of records, the number of
// records is ulTableCount, and every record has following format:
//
// <WORD1> <WORD2> <SEQCODES>
//
// <WORD1>: Identical between Win95 and NT.
// WORD2 stands for internal code, Win95 is ANSI code, NT is Unicode code.
// Seqcodes: bytes number is cMethodKeySize. identical between Win95 and NT
//
//
// Following fields in CHTUSRDICIMHDR need to convert from Win95 to NT 5.0
//
// idCp: from CHT 950 to 1200. ( stands for Unicode )
// CHS 936 to 1200.
// achMethodName[6]: converted from DBCS to Unicode.
//
//
// Every IME EUDC table file names can be got from following registry Key/Value
//
// Key:Registry\Current_User\Software\Microsoft\Windows\CurrentVersion\<IMEName>
// Value: User Dictionary: REG_SZ:
//
// ---------------------------------------------------------------------------
/******************************Public*Routine******************************\
* ImeEudcConvert
*
* Convert CHT/CHS Win95 EUDC IME table to NT 5.0
*
* Arguments:
*
* UCHAR * EudcTblFile - IME Eudc tbl file name.
*
* Return Value:
*
* BOOL: Success -TRUE. Fail - FALSE;
*
\**************************************************************************/
BOOL ImeEudcConvert( LPCSTR EudcTblFile)
{
HANDLE hTblFile, hTblMap;
LPBYTE lpTblFile, lpStart, lpTmp;
DWORD dwCharNums, i;
USRDICIMHDR *lpEudcHeader;
BYTE DBCSChar[2];
WORD wUnicodeChar, wImeName[3];
UINT uCodePage;
DebugMsg(("ImeEudcConvert,EudcTblFile = %s !\r\n",EudcTblFile));
hTblFile = CreateFile(EudcTblFile, // ptr to name of file
GENERIC_READ | GENERIC_WRITE, // access(read-write)mode
FILE_SHARE_READ | FILE_SHARE_WRITE, // share mode
NULL, // ptr to security attr
OPEN_EXISTING, // how to create
FILE_ATTRIBUTE_NORMAL, // file attributes
NULL);
if (hTblFile == INVALID_HANDLE_VALUE) {
DebugMsg(("ImeEudcConvert,hTblFile == INVALID_HANDLE_VALUE !\r\n"));
return FALSE;
}
hTblMap = CreateFileMapping(hTblFile, // handle to file to map
NULL, // optional security attributes
PAGE_READWRITE,// protection for mapping object
0, // high-order 32 bits of object size
0, // low-order 32 bits of object size
NULL); // name of file-mapping object);
if ( !hTblMap ) {
DebugMsg(("ImeEudcConvert,CreateFileMapping failed !\r\n"));
CloseHandle(hTblFile);
return FALSE;
}
lpTblFile = (LPBYTE) MapViewOfFile(hTblMap, FILE_MAP_WRITE, 0, 0, 0);
if ( !lpTblFile ) {
DebugMsg(("ImeEudcConvert,MapViewOfFile failed !\r\n"));
CloseHandle(hTblMap);
CloseHandle(hTblFile);
return FALSE;
}
lpEudcHeader = (USRDICIMHDR *)lpTblFile;
// get the current Code Page.
uCodePage = lpEudcHeader->idCP;
//
// if CodePage == 1200, it means this table has already been
// unicode format
//
if (uCodePage == 1200) {
DebugMsg(("ImeEudcConvert,[%s] Codepage is already 1200 !\r\n",EudcTblFile));
CloseHandle(hTblMap);
CloseHandle(hTblFile);
return FALSE;
}
// change the codepage from 950 (CHT) or 936 (CHS) to 1200
lpEudcHeader->idCP = 1200; // Unicode Native Code Page.
// change the IME name from DBCS to Unicode.
MultiByteToWideChar(uCodePage, // code page
0, // character-type options
lpEudcHeader->achMethodName, // address of string to map
6, // number of bytes in string
wImeName, // addr of wide-char buf
3); // size of buffer
lpTmp = (LPBYTE)wImeName;
for (i=0; i<6; i++)
lpEudcHeader->achMethodName[i] = lpTmp[i];
// Now we will convert every record for EUDC char.
lpStart = lpTblFile + lpEudcHeader->uHeaderSize;
dwCharNums = lpEudcHeader->ulTableCount;
for (i=0; i<dwCharNums; i++) {
lpTmp = lpStart + sizeof(WORD);
// swap the leader Byte and tail Byte of the DBCS Code.
DBCSChar[0] = *(lpTmp+1);
DBCSChar[1] = *lpTmp;
MultiByteToWideChar(uCodePage, // code page
0, // character-type options
DBCSChar, // address of string to map
2, // number of bytes in string
&wUnicodeChar, // addr of wide-char buf
1); // size of buffer
*lpTmp = (BYTE)(wUnicodeChar & 0x00ff);
*(lpTmp+1) = (BYTE)((wUnicodeChar >> 8) & 0x00ff);
lpStart += sizeof(WORD) + sizeof(WORD) + lpEudcHeader->cMethodKeySize;
}
UnmapViewOfFile(lpTblFile);
CloseHandle(hTblMap);
CloseHandle(hTblFile);
return TRUE;
}
BOOL GetEUDCHeader(
LPCTSTR EudcFileName,
USRDICIMHDR *EudcHeader)
{
BOOL Result = FALSE;
HANDLE EudcFileHandle, EudcMappingHandle;
LPBYTE EudcPtr;
EudcFileHandle = CreateFile(EudcFileName,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (EudcFileHandle == INVALID_HANDLE_VALUE) {
DebugMsg(("GetEUDCHeader, EudcFileHandle == INVALID_HANDLE_VALUE !\r\n"));
goto Exit1;
}
EudcMappingHandle = CreateFileMapping(EudcFileHandle,
NULL,
PAGE_READONLY,
0,
0,
NULL);
if ( !EudcMappingHandle ) {
DebugMsg(("GetEUDCHeader, EudcMappingHandle == INVALID_HANDLE_VALUE !\r\n"));
goto Exit2;
}
EudcPtr = (LPBYTE) MapViewOfFile(EudcMappingHandle, FILE_MAP_READ, 0, 0, 0);
if ( ! EudcPtr ) {
DebugMsg(("GetEUDCHeader, ! EudcPtr !\r\n"));
goto Exit3;
}
CopyMemory(EudcHeader,EudcPtr,sizeof(USRDICIMHDR));
Result = TRUE;
UnmapViewOfFile(EudcPtr);
Exit3:
CloseHandle(EudcMappingHandle);
Exit2:
CloseHandle(EudcFileHandle);
Exit1:
return Result;
}
BYTE WinAR30SeqMapTable(BYTE SeqCode)
{
INT i;
INT NumOfKey = sizeof(WinAR30MapTable) / (sizeof (BYTE) * 2);
for (i = 0; i < NumOfKey; i++) {
if (WinAR30MapTable[i * 2] == SeqCode) {
return WinAR30MapTable[i * 2+1];
}
}
return 0;
}
BOOL WinAR30ConvertWorker(
LPBYTE EudcPtr)
{
USRDICIMHDR *EudcHeader;
WinAR30EUDC95 *EudcDataPtr95;
WinAR30EUDCNT *EudcDataPtrNT;
INT i;
DebugMsg(("WinAR30ConvertWorker, ! Start !\r\n"));
if (! EudcPtr) {
DebugMsg(("WinAR30ConvertWorker, ! EudcPtr !\r\n"));
return FALSE;
}
EudcHeader = (USRDICIMHDR *) EudcPtr;
EudcHeader->cMethodKeySize = 5;
EudcDataPtr95 = (WinAR30EUDC95 *) (EudcPtr + EudcHeader->uHeaderSize);
EudcDataPtrNT = (WinAR30EUDCNT *) (EudcPtr + EudcHeader->uHeaderSize);
DebugMsg(("Sizeof WinAR30EUDC95 = %d WinAR30EUDCNT = %d ! \r\n",sizeof(WinAR30EUDC95),sizeof(WinAR30EUDCNT)));
for (i=(INT)(EudcHeader->ulTableCount -1) ; i >= 0 ; i--) {
EudcDataPtrNT[i].Seq[4] = 0;
EudcDataPtrNT[i].Seq[3] = WinAR30SeqMapTable(EudcDataPtr95[i].Seq[3]);
EudcDataPtrNT[i].Seq[2] = WinAR30SeqMapTable(EudcDataPtr95[i].Seq[2]);
EudcDataPtrNT[i].Seq[1] = WinAR30SeqMapTable(EudcDataPtr95[i].Seq[1]);
EudcDataPtrNT[i].Seq[0] = WinAR30SeqMapTable(EudcDataPtr95[i].Seq[0]);
EudcDataPtrNT[i].Code = EudcDataPtr95[i].Code;
EudcDataPtrNT[i].ID = EudcDataPtr95[i].ID;
}
return TRUE;
}
BOOL
WinAR30Convert(
LPCTSTR EudcFileName,
USRDICIMHDR *EudcHeader)
{
INT NewFileSize;
HANDLE EudcFileHandle, EudcMappingHandle;
LPBYTE EudcPtr;
BOOL Result = FALSE;
if (! EudcHeader) {
goto Exit1;
}
NewFileSize = EudcHeader->uHeaderSize + EudcHeader->ulTableCount * sizeof(WinAR30EUDCNT);
EudcFileHandle = CreateFile(EudcFileName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (EudcFileHandle == INVALID_HANDLE_VALUE) {
DebugMsg(("WinAR30Convert, EudcFileHandle == INVALID_HANDLE_VALUE !\r\n"));
goto Exit1;
}
EudcMappingHandle = CreateFileMapping(EudcFileHandle,
NULL,
PAGE_READWRITE,
0,
NewFileSize,
NULL);
if ( !EudcMappingHandle ) {
DebugMsg(("WinAR30Convert, EudcMappingHandle == INVALID_HANDLE_VALUE !\r\n"));
goto Exit2;
}
EudcPtr = (LPBYTE) MapViewOfFile(EudcMappingHandle, FILE_MAP_WRITE, 0, 0, 0);
if ( !EudcPtr ) {
DebugMsg(("GetEUDCHeader, ! EudcPtr !\r\n"));
goto Exit3;
}
Result = WinAR30ConvertWorker(EudcPtr);
UnmapViewOfFile(EudcPtr);
Exit3:
CloseHandle(EudcMappingHandle);
Exit2:
CloseHandle(EudcFileHandle);
Exit1:
return Result;
}
BOOL FixWinAR30EUDCTable(
LPCTSTR EudcFileName)
/*
Main function to fix WinAR30 EUDC table
Input : Eudc File Name (include path)
*/
{
USRDICIMHDR EudcHeader;
BOOL Result = FALSE;
if (! GetEUDCHeader(EudcFileName,&EudcHeader)) {
DebugMsg(("FixWinAR30EUDCTable,GetEUDCHeader(%s,..) failed!\r\n",EudcFileName));
goto Exit1;
} else {
DebugMsg(("FixWinAR30EUDCTable,GetEUDCHeader(%s,..) OK!\r\n",EudcFileName));
}
DebugMsg(("FixWinAR30EUDCTable,EudcHeader.cMethodKeySize = (%d)!\r\n",EudcHeader.cMethodKeySize));
if (EudcHeader.cMethodKeySize != 4) {
goto Exit1;
}
DebugMsg(("FixWinAR30EUDCTable,EudcHeader.ulTableCount = (%d) !\r\n",EudcHeader.ulTableCount));
if (EudcHeader.ulTableCount == 0) {
goto Exit1;
}
Result = WinAR30Convert(EudcFileName, &EudcHeader);
Exit1:
return Result;
}
BOOL GetEUDCPathInRegistry(
HKEY UserRegKey,
LPCTSTR EUDCName,
LPCTSTR EUDCPathValueName,
LPTSTR EUDCFileName)
{
HKEY hKey;
TCHAR IMERegPath[MAX_PATH] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\");
LONG RetVal;
LONG SizeOfFileName;
if (! EUDCName || ! EUDCFileName) {
return FALSE;
}
ConcatenatePaths(IMERegPath,EUDCName,MAX_PATH);
RetVal = RegOpenKey(UserRegKey,
IMERegPath,
&hKey);
if (RetVal != ERROR_SUCCESS) {
//
// it's ok, not every IME has created eudc table
//
DebugMsg(("ImeEudcConvert::GetEUDCPathInRegistry,No table in %s !\r\n",EUDCName));
return FALSE;
}
SizeOfFileName = MAX_PATH;
RetVal = RegQueryValueEx(hKey,
EUDCPathValueName,
NULL,
NULL,
(LPBYTE) EUDCFileName,
&SizeOfFileName);
if (RetVal == ERROR_SUCCESS) {
DebugMsg(("ImeEudcConvert::GetEUDCPathInRegistry,IME Table path = %s !\r\n",EUDCFileName));
} else {
DebugMsg(("ImeEudcConvert::GetEUDCPathInRegistry,No IME table path %s !\r\n",EUDCName));
}
return (RetVal == ERROR_SUCCESS);
}
UINT CreateNestedDirectory(LPCTSTR lpDirectory, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
{
TCHAR szDirectory[2*MAX_PATH];
LPTSTR lpEnd;
//
// Check for NULL pointer
//
if (!lpDirectory || !(*lpDirectory)) {
return 0;
}
//
// First, see if we can create the directory without having
// to build parent directories.
//
if (CreateDirectory (lpDirectory, lpSecurityAttributes)) {
return 1;
}
//
// If this directory exists already, this is OK too.
//
if (GetLastError() == ERROR_ALREADY_EXISTS) {
return ERROR_ALREADY_EXISTS;
}
//
// No luck, copy the string to a buffer we can munge
//
lstrcpy (szDirectory, lpDirectory);
//
// Find the first subdirectory name
//
lpEnd = szDirectory;
if (szDirectory[1] == TEXT(':')) {
lpEnd += 3;
} else if (szDirectory[1] == TEXT('\\')) {
lpEnd += 2;
while (*lpEnd && *lpEnd != TEXT('\\')) {
lpEnd++;
}
if (!(*lpEnd)) {
return 0;
}
lpEnd++;
while (*lpEnd && *lpEnd != TEXT('\\')) {
lpEnd++;
}
if (!(*lpEnd)) {
return 0;
}
lpEnd++;
} else if (szDirectory[0] == TEXT('\\')) {
lpEnd++;
}
while (*lpEnd) {
while (*lpEnd && *lpEnd != TEXT('\\')) {
lpEnd++;
}
if (*lpEnd == TEXT('\\')) {
*lpEnd = TEXT('\0');
if (!CreateDirectory (szDirectory, NULL)) {
if (GetLastError() != ERROR_ALREADY_EXISTS) {
DebugMsg((TEXT("CreateNestedDirectory: CreateDirectory failed with %d."), GetLastError()));
return 0;
}
}
*lpEnd = TEXT('\\');
lpEnd++;
}
}
if (CreateDirectory (szDirectory, lpSecurityAttributes)) {
return 1;
}
if (GetLastError() == ERROR_ALREADY_EXISTS) {
return ERROR_ALREADY_EXISTS;
}
DebugMsg((TEXT("CreateNestedDirectory: Failed to create the directory with error %d."), GetLastError()));
return 0;
}
BOOL
ConcatenatePaths(
LPTSTR Target,
LPCTSTR Path,
UINT TargetBufferSize
)
{
UINT TargetLength,PathLength;
BOOL TrailingBackslash,LeadingBackslash;
UINT EndingLength;
TargetLength = lstrlen(Target);
PathLength = lstrlen(Path);
//
// See whether the target has a trailing backslash.
//
if(TargetLength && (Target[TargetLength-1] == TEXT('\\'))) {
TrailingBackslash = TRUE;
TargetLength--;
} else {
TrailingBackslash = FALSE;
}
//
// See whether the path has a leading backshash.
//
if(Path[0] == TEXT('\\')) {
LeadingBackslash = TRUE;
PathLength--;
} else {
LeadingBackslash = FALSE;
}
//
// Calculate the ending length, which is equal to the sum of
// the length of the two strings modulo leading/trailing
// backslashes, plus one path separator, plus a nul.
//
EndingLength = TargetLength + PathLength + 2;
if(!LeadingBackslash && (TargetLength < TargetBufferSize)) {
Target[TargetLength++] = TEXT('\\');
}
if(TargetBufferSize > TargetLength) {
lstrcpyn(Target+TargetLength,Path,TargetBufferSize-TargetLength);
}
//
// Make sure the buffer is nul terminated in all cases.
//
if (TargetBufferSize) {
Target[TargetBufferSize-1] = 0;
}
return(EndingLength <= TargetBufferSize);
}
#define CSIDL_APPDATA 0x001a
BOOL (* MYSHGetSpecialFolderPathA) (HWND , LPTSTR , int , BOOL );
BOOL GetApplicationFolderPath(LPTSTR lpszFolder,UINT nLen)
{
HINSTANCE hDll;
BOOL bGotPath = FALSE;
hDll = LoadLibrary(TEXT("shell32.dll"));
if (hDll) {
(FARPROC) MYSHGetSpecialFolderPathA = GetProcAddress(hDll,"SHGetSpecialFolderPathA");
if (MYSHGetSpecialFolderPathA) {
if (MYSHGetSpecialFolderPathA(NULL, lpszFolder, CSIDL_APPDATA , FALSE)){
DebugMsg((TEXT("[GetApplicationFolder] SHGetSpecialFolderPath %s !\n"),lpszFolder));
bGotPath = TRUE;
} else {
DebugMsg((TEXT("[GetApplicationFolder] SHGetSpecialFolderPath failed !\n")));
}
} else {
DebugMsg((TEXT("[GetApplicationFolder] GetProc of SHGetSpecialFolderPath failed !\n")));
}
FreeLibrary(hDll);
} else {
DebugMsg((TEXT("[GetApplicationFolder] Load shell32.dll failed ! %d\n"),GetLastError()));
}
if (! bGotPath) {
ExpandEnvironmentStrings(TEXT("%userprofile%"),lpszFolder,nLen);
lstrcat(lpszFolder,TEXT("\\Application data"));
}
return TRUE;
}
BOOL GetNewPath(
LPTSTR lpszNewPath,
LPCTSTR lpszFileName,
LPCTSTR lpszClass)
/*
OUT lpszNewPath : e.q. \winnt\profiles\administrator\application data\Micorsoft\ime\chajei
IN lpszFileName : e.q. \winnt\chajei.tbl
IN lpszClass : e.q. Micorsoft\ime\chajei\chajei.tbl
lpszFileName (e.q. \winnt\phon.tbl) -> get base name (e.q. phon.tbl) ->
get Application folder (e.q. \winnt\profiles\administrator\application data) ->
create directory -> concat lpszClass (e.q. Micorsoft\ime\chajei)
Then we get lpszNewPath = \winnt\profiles\administrator\application data\Micorsoft\ime\chajei
*/
{
BOOL bRet = FALSE;
LPTSTR lpszBaseName;
DebugMsg((TEXT("[GetNewPath>>>] Param lpszFileName = %s !\n"),lpszFileName));
DebugMsg((TEXT("[GetNewPath>>>] Param lpszClass = %s !\n"),lpszClass));
GetApplicationFolderPath(lpszNewPath,MAX_PATH);
ConcatenatePaths(lpszNewPath, lpszClass,MAX_PATH);
if (! CreateNestedDirectory(lpszNewPath,NULL)) {
DebugMsg((TEXT("[GetNewPath] CreateDirectory %s ! %X\n"),lpszNewPath,GetLastError()));
}
if ((lpszBaseName = _tcsrchr(lpszFileName,TEXT('\\'))) != NULL) {
ConcatenatePaths(lpszNewPath,lpszBaseName,MAX_PATH);
} else {
ConcatenatePaths(lpszNewPath,lpszFileName,MAX_PATH);
DebugMsg((TEXT("[GetNewPath] can't find \\ in %s !\n"),lpszFileName));
}
DebugMsg((TEXT("[GetNewPath] return %s !\n"),lpszNewPath));
bRet = TRUE;
return bRet;
}
BOOL MigrateImeEUDCTables(HKEY UserRegKey)
{
LONG returnCode = ERROR_SUCCESS;
UINT uACP;
UINT uNumOfTables;
UINT i;
LPTABLELIST lpTableList;
TCHAR szIMERegPath[MAX_PATH] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\");
LPTSTR lpszEnd;
TCHAR szPathBuf[MAX_PATH];
LONG lPathBuf;
TCHAR szEudcRegValName[MAX_PATH];
HKEY hKey;
LONG lRetVal;
TABLELIST IMETableListCHT[] = {
{IDS_CHT_TABLE1,TEXT("")},
{IDS_CHT_TABLE2,TEXT("")},
{IDS_CHT_TABLE3,TEXT("")},
{IDS_CHT_TABLE4,TEXT("")},
{IDS_CHT_TABLE5,TEXT("")}
};
TABLELIST IMETableListCHS[] = {
{IDS_CHS_TABLE1,TEXT("")},
{IDS_CHS_TABLE2,TEXT("")},
{IDS_CHS_TABLE3,TEXT("")},
// {IDS_CHS_TABLE4,TEXT("")},
{IDS_CHS_TABLE5,TEXT("")},
{IDS_CHS_TABLE6,TEXT("")},
{IDS_CHS_TABLE7,TEXT("")}
// {IDS_CHS_TABLE8,TEXT("")}
};
if (!UserRegKey) {
return FALSE;
}
//
// 1. Decide which language and prepare IME table list
//
uACP = GetACP();
switch(uACP) {
case CP_CHINESE_GB: // Simplied Chinese
lpTableList = IMETableListCHS;
uNumOfTables = sizeof(IMETableListCHS) / sizeof(TABLELIST);
lstrcpy(szEudcRegValName,TEXT("EUDCDictName"));
break;
case CP_CHINESE_BIG5: // Traditional Chinese
lpTableList = IMETableListCHT;
uNumOfTables = sizeof(IMETableListCHT) / sizeof(TABLELIST);
lstrcpy(szEudcRegValName,TEXT("User Dictionary"));
break;
default:
DebugMsg(("MigrateImeEUDCTables::MigrateImeEUDCTables failed, wrong system code page !\r\n"));
return FALSE;
}
//
// 2. load IME name from resource
//
for (i=0; i<uNumOfTables; i++) {
if (!LoadString(g_hInstance,lpTableList[i].nResID,lpTableList[i].szIMEName,MAX_PATH)) {
DebugMsg(("MigrateImeEUDCTables failed, MigrateImeEUDCTables, load string failed !\r\n"));
return FALSE;
}
else {
DebugMsg(("MigrateImeEUDCTables , MigrateImeEUDCTables, load string [%s] !\r\n",lpTableList[i].szIMEName));
}
}
//
// 3. Read eudc table locaion from registry
//
lpszEnd = &szIMERegPath[lstrlen(szIMERegPath)];
for (i=0; i<uNumOfTables; i++) {
*lpszEnd = TEXT('\0');
lstrcat(szIMERegPath,lpTableList[i].szIMEName);
DebugMsg(("MigrateImeEUDCTables , Open registry, szIMERegPath [%s] !\r\n",szIMERegPath));
lRetVal = RegOpenKey(UserRegKey,
szIMERegPath,
&hKey);
if (lRetVal != ERROR_SUCCESS) {
//
// it's ok, not every IME has created eudc table
//
DebugMsg(("MigrateImeEUDCTables,No table in %s ! But it's fine\r\n",szIMERegPath));
continue;
}
lPathBuf = sizeof(szPathBuf);
lRetVal = RegQueryValueEx(hKey,
szEudcRegValName,
NULL,
NULL,
(LPBYTE) szPathBuf,
&lPathBuf);
if (lRetVal == ERROR_SUCCESS) {
if (! ImeEudcConvert(szPathBuf)) {
DebugMsg(("MigrateImeEUDCTables,call ImeEudcConvert(%s) failed !\r\n",szPathBuf));
}
else {
DebugMsg(("MigrateImeEUDCTables,call ImeEudcConvert(%s) OK !\r\n",szPathBuf));
}
}
else {
DebugMsg(("MigrateImeEUDCTables,RegQueryValue for %s failed !\r\n",szEudcRegValName));
}
if (uACP == CP_CHINESE_BIG5) {
DebugMsg(("MigrateImeEUDCTables,Test WINAR30 WINAR30 == %s !\r\n",lpTableList[i].szIMEName));
if (lstrcmpi(lpTableList[i].szIMEName,TEXT("WINAR30")) == 0) {
if (FixWinAR30EUDCTable(szPathBuf)) {
DebugMsg(("MigrateImeEUDCTables,FixWinAR30EUDCTable OK !\r\n"));
} else {
DebugMsg(("MigrateImeEUDCTables,FixWinAR30EUDCTable Failed !\r\n"));
}
}
}
//
// CHS's memory map file use "\" which cause bug
//
// replace "\" with "_"
//
if (uACP == CP_CHINESE_GB) {
lRetVal = RegQueryValueEx(hKey,
TEXT("EUDCMapFileName"),
NULL,
NULL,
(LPBYTE) szPathBuf,
&lPathBuf);
if (lRetVal == ERROR_SUCCESS) {
DebugMsg(("MigrateImeEUDCTables,Org MemMap = %s !\r\n",szPathBuf));
for (i=0; i<(UINT) lPathBuf; i++) {
if (szPathBuf[i] == '\\') {
szPathBuf[i] = '-';
}
}
DebugMsg(("MigrateImeEUDCTables,fixed MemMap = %s !\r\n",szPathBuf));
lRetVal = RegSetValueEx(hKey,
TEXT("EUDCMapFileName"),
0,
REG_SZ,
(LPBYTE) szPathBuf,
(lstrlen(szPathBuf)+1)*sizeof(TCHAR));
if (lRetVal != ERROR_SUCCESS) {
DebugMsg(("MigrateImeEUDCTables,fix CHS MemMap [%s]reg,SetReg failed [%d]!\r\n",szPathBuf,lRetVal));
} else {
DebugMsg(("MigrateImeEUDCTables,fix CHS MemMap [%s] reg,SetReg OK !\r\n",szPathBuf));
}
} else {
DebugMsg(("MigrateImeEUDCTables,MemMap, QuwryValue EUDCMapFileName failed [%d]!\r\n",lRetVal));
}
}
RegCloseKey(hKey);
}
DebugMsg(("MigrateImeEUDCTables , Finished !\r\n"));
return TRUE;
}
LPPATHPAIR g_RememberedPath = NULL;
UINT g_NumofRememberedPath = 0;
BOOL RememberPath(LPCTSTR szDstFile,LPCTSTR szSrcFile)
{
//
// only single thread executes this function, skip synchronization protection
//
BOOL bRet = FALSE;
if (g_NumofRememberedPath == 0) {
g_RememberedPath = (LPPATHPAIR) malloc(sizeof(PATHPAIR));
if (! g_RememberedPath) {
DebugMsg(("RememberPath , alloc memory failed !\r\n"));
goto Exit1;
}
} else {
g_RememberedPath = (LPPATHPAIR) realloc(g_RememberedPath,(g_NumofRememberedPath + 1) * sizeof(PATHPAIR));
if (! g_RememberedPath) {
DebugMsg(("RememberPath , alloc memory failed !\r\n"));
goto Exit1;
}
}
lstrcpy(g_RememberedPath[g_NumofRememberedPath].szSrcFile,szSrcFile);
lstrcpy(g_RememberedPath[g_NumofRememberedPath].szDstFile,szDstFile);
g_NumofRememberedPath++;
bRet = TRUE;
Exit1:
return bRet;
}
BOOL MigrateImeEUDCTables2(HKEY UserRegKey)
/*++
CHS : if xxx.emb exist, it needs to be duplicated to each user's AP directory
CHT : only move emb files that specified in user's "User Dictionary" Reg value
--*/
{
LONG returnCode = ERROR_SUCCESS;
UINT uACP;
UINT uNumOfTables;
UINT i;
LPTABLELIST lpTableList;
TCHAR szIMERegPath[MAX_PATH] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\");
LPTSTR lpszEnd;
TCHAR szOldDataFile[MAX_PATH];
LONG lPathBuf;
TCHAR szEudcRegValName[MAX_PATH];
HKEY hKey;
LONG lRetVal;
TCHAR szNewDataFile[MAX_PATH];
TCHAR szClassPath[MAX_PATH];
TABLELIST IMETableListCHT[] = {
{IDS_CHT_TABLE1,TEXT("")},
{IDS_CHT_TABLE2,TEXT("")},
{IDS_CHT_TABLE3,TEXT("")},
{IDS_CHT_TABLE4,TEXT("")},
{IDS_CHT_TABLE5,TEXT("")}
};
TABLELIST IMETableListCHS[] = {
{IDS_CHS_TABLE1,TEXT("")},
{IDS_CHS_TABLE2,TEXT("")},
{IDS_CHS_TABLE3,TEXT("")}
};
TABLELIST IMETableListCHSENG[] = {
{IDS_CHS_ENG_TABLE1,TEXT("")},
{IDS_CHS_ENG_TABLE2,TEXT("")},
{IDS_CHS_ENG_TABLE3,TEXT("")}
};
if (!UserRegKey) {
return FALSE;
}
//
// 1. Decide which language and prepare IME table list
//
uACP = GetACP();
switch(uACP) {
case CP_CHINESE_GB: // Simplied Chinese
lpTableList = IMETableListCHS;
uNumOfTables = sizeof(IMETableListCHS) / sizeof(TABLELIST);
lstrcpy(szEudcRegValName,TEXT("EUDCDictName"));
break;
case CP_CHINESE_BIG5: // Traditional Chinese
lpTableList = IMETableListCHT;
uNumOfTables = sizeof(IMETableListCHT) / sizeof(TABLELIST);
lstrcpy(szEudcRegValName,TEXT("User Dictionary"));
break;
default:
DebugMsg(("MigrateImeEUDCTables2 failed, wrong system code page !\r\n"));
return FALSE;
}
//
// 2. load IME name from resource
//
for (i=0; i<uNumOfTables; i++) {
if (!LoadString(g_hInstance,lpTableList[i].nResID,lpTableList[i].szIMEName,MAX_PATH)) {
DebugMsg(("MigrateImeEUDCTables2 failed, MigrateImeEUDCTables, load string failed !\r\n"));
return FALSE;
}
else {
DebugMsg(("MigrateImeEUDCTables2 , MigrateImeEUDCTables, load string [%s] !\r\n",lpTableList[i].szIMEName));
}
if (uACP == CP_CHINESE_GB) {
if (!LoadString(g_hInstance,IMETableListCHSENG[i].nResID,IMETableListCHSENG[i].szIMEName,MAX_PATH)) {
DebugMsg(("MigrateImeEUDCTables2 failed, MigrateImeEUDCTables, load string failed !\r\n"));
return FALSE;
}
else {
DebugMsg(("MigrateImeEUDCTables2 , MigrateImeEUDCTables, load string [%s] !\r\n",lpTableList[i].szIMEName));
}
}
}
//
// 3. Read eudc table locaion from registry
//
lpszEnd = &szIMERegPath[lstrlen(szIMERegPath)];
for (i=0; i<uNumOfTables; i++) {
if (uACP == CP_CHINESE_GB) {
TCHAR szEMBName[MAX_PATH];
lstrcpy(szEMBName,IMETableListCHSENG[i].szIMEName);
lstrcat(szEMBName,TEXT(".emb"));
lstrcpy(szOldDataFile,ImeDataDirectory);
ConcatenatePaths(szOldDataFile,szEMBName,sizeof(szOldDataFile));
if (GetFileAttributes(szOldDataFile) == 0xFFFFFFFF) {
DebugMsg(("MigrateImeEUDCTables2 , No %s EMB, continue next !\r\n",szOldDataFile));
continue;
}
lstrcpy(szClassPath,TEXT("Microsoft\\IME\\"));
lstrcat(szClassPath,IMETableListCHSENG[i].szIMEName);
GetSystemDirectory(szOldDataFile, sizeof(szOldDataFile));
ConcatenatePaths(szOldDataFile,szEMBName,sizeof(szOldDataFile));
if (GetNewPath(szNewDataFile,
szOldDataFile,
szClassPath)) {
RememberPath(szNewDataFile,szOldDataFile);
}
}
*lpszEnd = TEXT('\0');
lstrcat(szIMERegPath,lpTableList[i].szIMEName);
DebugMsg(("MigrateImeEUDCTables2 , Open registry, szIMERegPath [%s] !\r\n",szIMERegPath));
lRetVal = RegOpenKey(UserRegKey,
szIMERegPath,
&hKey);
if (lRetVal != ERROR_SUCCESS) {
//
// it's ok, not every IME has created eudc table
//
DebugMsg(("MigrateImeEUDCTables2,No table in %s ! But it's fine\r\n",szIMERegPath));
continue;
}
lPathBuf = sizeof(szOldDataFile);
lRetVal = RegQueryValueEx(hKey,
szEudcRegValName,
NULL,
NULL,
(LPBYTE) szOldDataFile,
&lPathBuf);
if (lRetVal == ERROR_SUCCESS) {
if (uACP == CP_CHINESE_BIG5) {
lstrcpy(szClassPath,TEXT("Microsoft\\IME\\"));
lstrcat(szClassPath,lpTableList[i].szIMEName);
if (GetNewPath(szNewDataFile,
szOldDataFile,
szClassPath)) {
RememberPath(szNewDataFile,szOldDataFile);
}
}
//
// at this step, both CHT's and CHS's szNewDataFile is ready
//
lRetVal = RegSetValueEx(hKey,
szEudcRegValName,
0,
REG_SZ,
(LPBYTE) szNewDataFile,
(lstrlen(szNewDataFile)+1) * sizeof (TCHAR));
if (lRetVal != ERROR_SUCCESS) {
DebugMsg(("MigrateImeEUDCTables2,RegSetValueEx %s,%x ! \r\n",szNewDataFile,GetLastError()));
}
}
else {
DebugMsg(("MigrateImeEUDCTables2,RegQueryValue for %s failed !\r\n",szEudcRegValName));
}
RegCloseKey(hKey);
}
DebugMsg(("MigrateImeEUDCTables2 , Finished !\r\n"));
return TRUE;
}
BOOL MovePerUserIMEData()
{
UINT i;
for (i=0; i< g_NumofRememberedPath; i++) {
if (CopyFile(g_RememberedPath[i].szSrcFile,g_RememberedPath[i].szDstFile,FALSE)) {
DebugMsg(("MovePerUserIMEData , Copy %s to %s OK !\r\n",g_RememberedPath[i].szSrcFile,g_RememberedPath[i].szDstFile));
} else {
DebugMsg(("MovePerUserIMEData , Copy %s to %s failed !\r\n",g_RememberedPath[i].szSrcFile,g_RememberedPath[i].szDstFile));
}
}
if (g_RememberedPath) {
free (g_RememberedPath);
g_RememberedPath = NULL;
g_NumofRememberedPath = 0;
}
return TRUE;
}