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.
 
 
 
 
 
 

1926 lines
47 KiB

#include "private.h"
#include "globals.h"
#include "internat.h"
#include "strary.h"
#include "xstring.h"
#include "immxutil.h"
#include "cregkey.h"
#include "cmydc.h"
#include "assembly.h"
CStructArray<MLNGINFO> *g_pMlngInfo = NULL;
const TCHAR c_szDefaultUserPreload[] = TEXT(".DEFAULT\\Keyboard Layout\\Preload");
const TCHAR c_szPreload[] = TEXT("Keyboard Layout\\Preload");
const TCHAR c_szSubst[] = TEXT("Keyboard Layout\\Substitutes");
//////////////////////////////////////////////////////////////////////////////
//
// CStaticIconList
//
//////////////////////////////////////////////////////////////////////////////
class CStaticIconList
{
public:
void Init(int cx, int cy);
void RemoveAll(BOOL fInUninit);
BOOL IsInited()
{
return _cx != 0;
}
int AddIcon(HICON hicon);
HICON ExtractIcon(int i);
void GetIconSize(int *cx, int *cy);
int GetImageCount();
private:
static int _cx;
static int _cy;
static CStructArray<HICON> *_prgIcons;
};
CStaticIconList g_IconList;
int CStaticIconList::_cx = 0;
int CStaticIconList::_cy = 0;
CStructArray<HICON> *CStaticIconList::_prgIcons = NULL;
//+---------------------------------------------------------------------------
//
// Init
//
//----------------------------------------------------------------------------
inline void CStaticIconList::Init(int cx, int cy)
{
CicEnterCriticalSection(g_cs);
_cx = cx;
_cy = cy;
CicLeaveCriticalSection(g_cs);
}
//+---------------------------------------------------------------------------
//
// RemoveAll
//
//----------------------------------------------------------------------------
void CStaticIconList::RemoveAll(BOOL fInUninit)
{
int i;
//
// don't have to enter g_cs if we're in DllMain(PROCESS_DETATCH).
//
if (!fInUninit)
CicEnterCriticalSection(g_cs);
if (_prgIcons == NULL)
goto Exit;
for (i=0; i<_prgIcons->Count(); i++)
{
DestroyIcon(*_prgIcons->GetPtr(i));
}
delete _prgIcons;
_prgIcons = NULL;
Exit:
if (!fInUninit)
CicLeaveCriticalSection(g_cs);
}
//+---------------------------------------------------------------------------
//
// AddIcon
//
//----------------------------------------------------------------------------
inline int CStaticIconList::AddIcon(HICON hicon)
{
HICON hIconCopy;
HICON *pIconDst;
int nRet = -1;
CicEnterCriticalSection(g_cs);
if (!_prgIcons)
_prgIcons = new CStructArray<HICON>;
if (!_prgIcons)
goto Exit;
if ((pIconDst = _prgIcons->Append(1)) == NULL)
goto Exit;
if ((hIconCopy = CopyIcon(hicon)) == 0)
{
_prgIcons->Remove(_prgIcons->Count()-1, 1);
goto Exit;
}
*pIconDst = hIconCopy;
nRet = _prgIcons->Count()-1;
Exit:
CicLeaveCriticalSection(g_cs);
return nRet;
}
//+---------------------------------------------------------------------------
//
// ExtractIcon
//
//----------------------------------------------------------------------------
inline HICON CStaticIconList::ExtractIcon(int i)
{
HICON hIcon = NULL;
CicEnterCriticalSection(g_cs);
if (!_prgIcons)
goto Exit;
if (i >= _prgIcons->Count() || i < 0)
goto Exit;
hIcon = CopyIcon(*_prgIcons->GetPtr(i));
Exit:
CicLeaveCriticalSection(g_cs);
return hIcon;
}
//+---------------------------------------------------------------------------
//
// GetIconSize
//
//----------------------------------------------------------------------------
inline void CStaticIconList::GetIconSize(int *cx, int *cy)
{
CicEnterCriticalSection(g_cs);
*cx = _cx;
*cy = _cy;
CicLeaveCriticalSection(g_cs);
}
//+---------------------------------------------------------------------------
//
// GetImageCount
//
//----------------------------------------------------------------------------
inline int CStaticIconList::GetImageCount()
{
int nRet = 0;
CicEnterCriticalSection(g_cs);
if (_prgIcons == NULL)
goto Exit;
nRet = _prgIcons->Count();
Exit:
CicLeaveCriticalSection(g_cs);
return nRet;
}
//////////////////////////////////////////////////////////////////////////////
//
// UninitINAT
//
//////////////////////////////////////////////////////////////////////////////
void UninitINAT()
{
g_IconList.RemoveAll(TRUE);
if (g_pMlngInfo)
{
delete g_pMlngInfo;
g_pMlngInfo = NULL;
}
}
//////////////////////////////////////////////////////////////////////////////
//
// InterNAT icon APIs
//
//////////////////////////////////////////////////////////////////////////////
#if 0
//
// ISO 639:1988 Code.
//
//
// Under NT, we use GetLocaleInfoNTString(). It returns ISO 3166.
//
INATSYMBOL symInatSymbols[] =
{
{0x0436, "AF"}, // Afrikaans
{0x041c, "SQ"}, // Albanian
{0x0401, "AR"}, // Arabic
{0x042d, "EU"}, // Basque
{0x0423, "BE"}, // Byelorus
{0x0402, "BG"}, // Bulgaria
{0x0403, "CA"}, // Catalan
{0x0404, "CH"}, // China #1
{0x0804, "CH"}, // China #2
//#ifdef WINDOWS_PE
#if 1
{0x041a, "HR"}, // Croatian
#else
{0x041a, "SH"}, // Croatian
#endif
{0x0405, "CZ"}, // Czech
{0x0406, "DA"}, // Danish
{0x0413, "NL"}, // Dutch
{0x0813, "NL"}, // Dutch
{0x0409, "EN"}, // English
{0x0809, "EN"}, // English
{0x0c09, "EN"}, // English
{0x1009, "EN"}, // English
{0x1409, "EN"}, // English
{0x1809, "EN"}, // English
{0x0425, "ET"}, // Estonian
{0x0429, "FA"}, // Farsi
{0x040b, "FI"}, // Finnish
{0x040c, "FR"}, // French
{0x080c, "FR"}, // French
{0x0c0c, "FR"}, // French
{0x0407, "DE"}, // German
{0x0807, "DE"}, // German
{0x0c07, "DE"}, // German
{0x1007, "DE"}, // German
{0x1407, "DE"}, // German
{0x0408, "GR"}, // Greek
{0x040d, "HE"}, // Hebrew
{0x040e, "HU"}, // Hungary
{0x040f, "IS"}, // Iceland
{0x0421, "BA"}, // Indonesia
{0x0410, "IT"}, // Italy
{0x0810, "IT"}, // Italy
{0x0411, "JA"}, // Japan
{0x0412, "KO"}, // Korea
{0x0426, "LV"}, // Latvian
{0x0427, "LT"}, // Lithuanian
{0x042f, "MK"}, // Former Yugoslav Republic of Macedonia
{0x0414, "NO"}, // Norway
{0x0814, "NO"}, // Norway
{0x0415, "PL"}, // Poland
{0x0416, "PT"}, // Portugal
{0x0816, "PT"}, // Portugal
{0x0417, "RM"}, // Rhaeto
{0x0418, "RO"}, // Romanian
{0x0818, "RO"}, // Romanian
{0x0419, "RU"}, // Russian
{0x0819, "RU"}, // Russian
{0x081a, "SR"}, // Serbian
//#ifdef WINDOWS_PE
#if 1
{0x0c1a, "SR"}, // Serbian
#endif
{0x041b, "SK"}, // Slovakian
{0x0424, "SL"}, // Slovenian
{0x042e, "SB"}, // Sorbian
{0x040a, "ES"}, // Spanish
{0x080a, "ES"}, // Spanish
{0x0c0a, "ES"}, // Spanish
{0x041d, "SV"}, // Swedish
{0x041e, "TH"}, // Thai
{0x041f, "TR"}, // Turkish
{0x0422, "UK"}, // Ukranian
{0x0420, "UR"}, // Urdu
{0x0033, "VE"}, // Venda
{0x042a, "VN"}, // Vietnamese
{0x0034, "XH"}, // Xhosa
{0x0035, "ZU"}, // Zulu
{0x002b, "ST"}, // Sutu
{0x002e, "TS"}, // Tsona
{0x002f, "TN"}, // Tswana
{0x0000, "??"}
} ;
#define NSYMBOLS ((sizeof(symInatSymbols) / sizeof(INATSYMBOL))-1)
#endif
static const TCHAR c_szLayoutPath[] = TEXT("SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts");
static const TCHAR c_szLayoutText[] = TEXT("layout text");
static const TCHAR c_szLayoutID[] = TEXT("layout id");
static const WCHAR c_szMUILayoutTextW[] = L"Layout Display Name";
static const WCHAR c_szLayoutTextW[] = L"layout text";
static const char c_szNamesPath[] = "system\\currentcontrolset\\control\\nls\\Locale";
//+---------------------------------------------------------------------------
//
// GetLocaleInfoString
//
// this is not a general wrapper for GetLocaleInfo!
// LCTYPE must be LOCALE_SABBREVLANGNAME or LOCALE_SLANGUAGE.
//
//----------------------------------------------------------------------------
int GetLocaleInfoString(LCID lcid, LCTYPE lcType, char *psz, int cch)
{
WCHAR achW[64];
Assert((lcType & LOCALE_SLANGUAGE) || (lcType & LOCALE_SABBREVLANGNAME));
if (IsOnNT())
{
if (GetLocaleInfoW(lcid, lcType, achW, ARRAYSIZE(achW)))
{
return WideCharToMultiByte(CP_ACP, 0, achW, -1, psz, cch, NULL, NULL);
}
}
else
{
return GetLocaleInfo(lcid, lcType, psz, cch);
}
return 0;
}
//+---------------------------------------------------------------------------
//
// InatCreateIcon
//
//+---------------------------------------------------------------------------
HICON InatCreateIcon(WORD langID)
{
LOGFONT lf;
UINT cxSmIcon;
UINT cySmIcon;
cxSmIcon = GetSystemMetrics( SM_CXSMICON );
cySmIcon = GetSystemMetrics( SM_CYSMICON );
if( !SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(LOGFONT), &lf, 0))
return NULL;
if (cySmIcon < GetPhysicalFontHeight(lf))
{
lf.lfHeight = 0 - ((int)cySmIcon * 7 / 10);
lf.lfWidth = 0;
}
return InatCreateIconBySize(langID, cxSmIcon, cySmIcon, &lf);
}
//+---------------------------------------------------------------------------
//
// InatCreateIconBySize
//
//+---------------------------------------------------------------------------
HICON InatCreateIconBySize(WORD langID, int cxSmIcon, int cySmIcon, LOGFONT *plf)
{
HBITMAP hbmColour;
HBITMAP hbmMono;
HBITMAP hbmOld;
HICON hicon = NULL;
ICONINFO ii;
RECT rc;
DWORD rgbText;
DWORD rgbBk = 0;
HDC hdc;
HDC hdcScreen;
HFONT hfont;
HFONT hfontOld;
TCHAR szData[20];
//
// Get the indicator by using the first 2 characters of the
// abbreviated language name.
//
if (GetLocaleInfoString( MAKELCID(langID, SORT_DEFAULT),
LOCALE_SABBREVLANGNAME | LOCALE_NOUSEROVERRIDE,
szData,
sizeof(szData) / sizeof(TCHAR) ))
{
//
// Make Uppercase
//
if (!IsOnNT())
{
szData[0] -= 0x20;
szData[1] -= 0x20;
}
//
// Only use the first two characters.
//
szData[2] = TEXT('\0');
}
else
{
//
// Id wasn't found. Use question marks.
//
szData[0] = TEXT('?');
szData[1] = TEXT('?');
szData[2] = TEXT('\0');
}
if( (hfont = CreateFontIndirect(plf)) )
{
hdcScreen = GetDC(NULL);
hdc = CreateCompatibleDC(hdcScreen);
hbmColour = CreateCompatibleBitmap(hdcScreen, cxSmIcon, cySmIcon);
ReleaseDC( NULL, hdcScreen);
if (hbmColour && hdc)
{
hbmMono = CreateBitmap(cxSmIcon, cySmIcon, 1, 1, NULL);
if (hbmMono)
{
hbmOld = (HBITMAP)SelectObject( hdc, hbmColour);
rc.left = 0;
rc.top = 0;
rc.right = cxSmIcon;
rc.bottom = cySmIcon;
rgbBk = SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
rgbText = SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
ExtTextOut( hdc, rc.left, rc.top, ETO_OPAQUE, &rc, "", 0, NULL);
hfontOld = (HFONT)SelectObject( hdc, hfont);
DrawText(hdc,
szData,
2,
&rc,
DT_CENTER | DT_VCENTER | DT_SINGLELINE);
SelectObject( hdc, hbmMono);
PatBlt(hdc, 0, 0, cxSmIcon, cySmIcon, BLACKNESS);
ii.fIcon = TRUE;
ii.xHotspot = 0;
ii.yHotspot = 0;
ii.hbmColor = hbmColour;
ii.hbmMask = hbmMono;
hicon = CreateIconIndirect(&ii);
SelectObject(hdc, hbmOld);
DeleteObject(hbmMono);
SelectObject(hdc, hfontOld);
}
}
DeleteObject(hbmColour);
DeleteDC(hdc);
DeleteObject(hfont);
}
return hicon;
}
//+---------------------------------------------------------------------------
//
// GetIconFromFile
//
//+---------------------------------------------------------------------------
HICON GetIconFromFile(int cx, int cy, WCHAR *lpszFileName, UINT uIconIndex)
{
return GetIconFromFileA(cx, cy, WtoA(lpszFileName), uIconIndex);
}
//+---------------------------------------------------------------------------
//
// GetIconFromFileA
//
//+---------------------------------------------------------------------------
HICON GetIconFromFileA(int cx, int cy, char *lpszFileName, UINT uIconIndex)
{
HICON hicon = NULL;
if (cx > GetSystemMetrics(SM_CXSMICON))
{
ExtractIconEx(lpszFileName, uIconIndex, &hicon, NULL, 1);
}
else
{
ExtractIconEx(lpszFileName, uIconIndex, NULL, &hicon, 1);
}
return hicon;
}
//+---------------------------------------------------------------------------
//
// CLayoutsSharedMem
//
//+---------------------------------------------------------------------------
extern CCicMutex g_mutexLayouts;
extern char g_szLayoutsCache[];
class CLayoutsSharedMem : public CCicFileMappingStatic
{
public:
void Init()
{
CCicFileMappingStatic::Init(g_szLayoutsCache, &g_mutexLayouts);
}
BOOL Start(UINT nNum)
{
BOOL fAlreadyExists;
CCicSecAttr sa;
if (Create(sa, sizeof(LAYOUT) * nNum, &fAlreadyExists) == NULL)
return FALSE;
return TRUE;
}
LAYOUT *GetPtr() { return (LAYOUT *)_pv; }
};
CLayoutsSharedMem g_smLayouts;
//+---------------------------------------------------------------------------
//
// UninitLayoutMappedFile();
//
//----------------------------------------------------------------------------
void UninitLayoutMappedFile()
{
g_smLayouts.Uninit();
}
//+---------------------------------------------------------------------------
//
// LoadKeyboardLayouts
//
//----------------------------------------------------------------------------
BOOL LoadKeyboardLayouts()
{
CMyRegKey key;
DWORD dwIndex;
BOOL bRet = FALSE;
TCHAR szValue[MAX_PATH]; // language id (number)
WCHAR szValueW[MAX_PATH];
TCHAR szData[MAX_PATH]; // language name
CStructArray<LAYOUT> *pLayouts = NULL;
LAYOUT *pLayout;
BOOL bLoadedLayout;
pLayouts = new CStructArray<LAYOUT>;
if (!pLayouts)
return FALSE;
//
// Now read all the locales from the registry.
//
if (key.Open(HKEY_LOCAL_MACHINE, c_szLayoutPath, KEY_READ) != ERROR_SUCCESS)
{
goto Exit;
}
dwIndex = 0;
szValue[0] = TEXT('\0');
while (key.EnumKey(dwIndex, szValue, ARRAYSIZE(szValue)) == ERROR_SUCCESS)
{
CRegKeyMUI key1;
pLayout = pLayouts->Append(1);
if (!pLayout)
goto Exit;
pLayout->dwID = AsciiToNum(szValue);
if (StringCchPrintf(szData, ARRAYSIZE(szData), "%s\\%s", c_szLayoutPath, szValue) != S_OK)
goto Next;
if (key1.Open(HKEY_LOCAL_MACHINE, szData, KEY_READ) == S_OK)
{
//
// Get the layout name.
//
szValue[0] = TEXT('\0');
bLoadedLayout = FALSE;
if (IsOnNT())
{
szValueW[0] = 0;
if (key1.QueryValueCchW(szValueW,
c_szMUILayoutTextW,
ARRAYSIZE(szValueW)) == S_OK)
{
bLoadedLayout = TRUE;
}
else if (key1.QueryValueCchW(szValueW,
c_szLayoutTextW,
ARRAYSIZE(szValueW)) == S_OK)
{
bLoadedLayout = TRUE;
}
if (bLoadedLayout)
{
wcsncpy(pLayout->wszText,
szValueW,
ARRAYSIZE(pLayout->wszText));
}
}
else
{
if (key1.QueryValueCch(szValue,
c_szLayoutText,
ARRAYSIZE(szValue)) == S_OK)
{
wcsncpy(pLayout->wszText,
AtoW(szValue),
ARRAYSIZE(pLayout->wszText));
bLoadedLayout = TRUE;
}
}
if (bLoadedLayout)
{
szValue[0] = TEXT('\0');
pLayout->iSpecialID = 0;
if (key1.QueryValueCch(szValue,
c_szLayoutID,
ARRAYSIZE(szValue)) == S_OK)
{
//
// This may not exist!
//
pLayout->iSpecialID = (UINT)AsciiToNum(szValue);
}
}
}
Next:
dwIndex++;
szValue[0] = TEXT('\0');
}
pLayout = pLayouts->Append(1);
if (!pLayout)
goto Exit;
memset(pLayout, 0, sizeof(LAYOUT));
if (!g_smLayouts.Enter())
goto Exit;
g_smLayouts.Close();
if (g_smLayouts.Start(pLayouts->Count()))
{
if (g_smLayouts.GetPtr())
{
memcpy(g_smLayouts.GetPtr(),
pLayouts->GetPtr(0),
pLayouts->Count() * sizeof(LAYOUT));
bRet = TRUE;
}
}
g_smLayouts.Leave();
Exit:
if (pLayouts)
delete pLayouts;
return bRet;
}
//+---------------------------------------------------------------------------
//
// FindLayoutEntry
//
// Gets the name of the given layout.
//
//+---------------------------------------------------------------------------
UINT FindLayoutEntry( LAYOUT *pLayout, DWORD dwLayout )
{
UINT ctr = 0;
UINT id;
WORD wLayout = HIWORD(dwLayout);
BOOL bIsIME = ((HIWORD(dwLayout) & 0xf000) == 0xe000) ? TRUE : FALSE;
//
// Find the layout in the global structure.
//
if ((wLayout & 0xf000) == 0xf000)
{
//
// Layout is special, need to search for the ID
// number.
//
id = wLayout & 0x0fff;
ctr = 0;
while (pLayout[ctr].dwID)
{
if (id == pLayout[ctr].iSpecialID)
{
break;
}
ctr++;
}
}
else
{
ctr = 0;
while (pLayout[ctr].dwID)
{
//
// If it is IME, needs to be DWORD comparison.
//
if (IsOnFE() && bIsIME && (dwLayout == pLayout[ctr].dwID))
{
break;
}
else if (wLayout == LOWORD(pLayout[ctr].dwID))
{
break;
}
ctr++;
}
}
return ctr;
}
//+---------------------------------------------------------------------------
//
// GetKbdLayoutName
//
// Gets the name of the given layout.
//
//+---------------------------------------------------------------------------
void GetKbdLayoutName( DWORD dwLayout, WCHAR *pBuffer, int nBufSize)
{
UINT ctr;
LAYOUT *pLayout;
*pBuffer = L'\0';
if (!g_smLayouts.Enter())
return;
g_smLayouts.Close();
g_smLayouts.Init();
if (!g_smLayouts.Open())
{
if (!LoadKeyboardLayouts())
{
Assert(0);
}
}
pLayout = g_smLayouts.GetPtr();
if (!pLayout)
goto Exit;
ctr = FindLayoutEntry( pLayout, dwLayout );
//
// Make sure there is a match. If not, then simply return without
// copying anything.
//
if (pLayout[ctr].dwID)
{
//
// Separate the Input Locale name and the Layout name with " - ".
//
#ifdef ATTACH_LAYOUTNAME
pBuffer[0] = L' ';
pBuffer[1] = L'-';
pBuffer[2] = L' ';
wcsncpy(pBuffer + 3, pLayout[ctr].wszText, nBufSize - 3);
#else
wcsncpy(pBuffer, pLayout[ctr].wszText, nBufSize);
#endif
}
Exit:
g_smLayouts.Leave();
}
//+---------------------------------------------------------------------------
//
// GetKbdLayoutId
//
// Gets the name of the given layout.
//
//+---------------------------------------------------------------------------
DWORD GetKbdLayoutId( DWORD dwLayout)
{
UINT ctr;
DWORD dwId = 0;
LAYOUT *pLayout;
if (!g_smLayouts.Enter())
return 0;
g_smLayouts.Close();
g_smLayouts.Init();
if (!g_smLayouts.Open())
LoadKeyboardLayouts();
pLayout = g_smLayouts.GetPtr();
if (!pLayout)
goto Exit;
ctr = FindLayoutEntry( pLayout, dwLayout );
//
// Make sure there is a match. If not, then simply return without
// copying anything.
//
dwId = pLayout[ctr].dwID;
Exit:
g_smLayouts.Leave();
return dwId;
}
//+---------------------------------------------------------------------------
//
// GetLocaleInfoString
//
// this is not a general wrapper for GetLocaleInfo!
// LCTYPE must be LOCALE_SABBREVLANGNAME or LOCALE_SLANGUAGE.
//
//----------------------------------------------------------------------------
ULONG GetLocaleInfoString(HKL hKL, WCHAR *pszRegText, int nSize)
{
ULONG cb = 0;
DWORD dwRegValue = (DWORD)((LONG_PTR)(hKL) & 0x0000FFFF);
*pszRegText = L'\0';
if (IsOnNT())
{
if (!GetLocaleInfoW(dwRegValue, LOCALE_SLANGUAGE, pszRegText, nSize))
{
*pszRegText = L'\0';
}
//
// Attach the Layout name if it's not the default.
//
if (HIWORD(hKL) != LOWORD(hKL))
{
#ifdef ATTACH_LAYOUTNAME
WCHAR *pszRT = pszRegText + wcslen(pszRegText);
//
// Pass DWORD value for IME.
//
GetKbdLayoutName((DWORD)(LONG_PTR)hKL,
pszRT,
nSize - (DWORD)(pszRT - pszRegText));
#else
GetKbdLayoutName((DWORD)(LONG_PTR)hKL, pszRegText, nSize);
#endif
}
}
else
{
CMyRegKey key;
char szRegKey[128];
char szRegText[128];
StringCchPrintf(szRegKey, ARRAYSIZE(szRegKey),"%8.8lx", (DWORD)dwRegValue);
*pszRegText = '\0';
if(key.Open(HKEY_LOCAL_MACHINE,c_szNamesPath, KEY_READ)==ERROR_SUCCESS)
{
if(key.QueryValueCch(szRegText, szRegKey, ARRAYSIZE(szRegText)) == ERROR_SUCCESS)
{
DWORD dwLen = MultiByteToWideChar(CP_ACP,
MB_ERR_INVALID_CHARS,
szRegText,
lstrlen(szRegText),
pszRegText,
nSize-1);
pszRegText[dwLen] = L'\0';
}
}
}
return wcslen(pszRegText);
}
//+---------------------------------------------------------------------------
//
// GetHKLDescription
//
//
//----------------------------------------------------------------------------
int GetHKLDesctription(HKL hKL, WCHAR *pszDesc, int cchDesc, WCHAR *pszIMEFile, int cchIMEFile)
{
DWORD dwIMEDesc = 0;
if (IsIMEHKL(hKL))
{
HKEY hkey;
DWORD dwIMELayout;
TCHAR szIMELayout[MAX_PATH];
TCHAR szIMELayoutPath[MAX_PATH];
dwIMELayout = GetSubstitute(hKL);
StringCchPrintf(szIMELayout, ARRAYSIZE(szIMELayout), "%8.8lx", dwIMELayout);
StringCopyArray(szIMELayoutPath, c_szLayoutPath);
StringCatArray(szIMELayoutPath, TEXT("\\"));
StringCatArray(szIMELayoutPath, szIMELayout);
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szIMELayoutPath, 0, KEY_READ, &hkey)
== ERROR_SUCCESS)
{
if (SHLoadRegUIStringW(hkey,
c_szMUILayoutTextW,
pszDesc, cchDesc) == S_OK)
{
dwIMEDesc = wcslen(pszDesc);
}
RegCloseKey(hkey);
}
if (!dwIMEDesc)
{
dwIMEDesc = ImmGetDescriptionW(hKL,pszDesc,cchDesc);
if (!dwIMEDesc)
pszDesc[0] = L'\0';
}
}
if (dwIMEDesc == 0)
{
GetLocaleInfoString(hKL, pszDesc, cchDesc);
pszIMEFile[0] = L'\0';
}
else
{
if (!ImmGetIMEFileNameW(hKL, pszIMEFile, cchIMEFile))
pszIMEFile[0] = L'\0';
}
return wcslen(pszDesc);
}
//////////////////////////////////////////////////////////////////////////////
//
// MLNGINFO List
//
//////////////////////////////////////////////////////////////////////////////
//---------------------------------------------------------------------------
//
// MlngInfoCount()
//
//---------------------------------------------------------------------------
int WINAPI TF_MlngInfoCount()
{
if (!g_pMlngInfo)
return 0;
return g_pMlngInfo->Count();
}
//---------------------------------------------------------------------------
//
// GetMlngInfo()
//
//---------------------------------------------------------------------------
BOOL GetMlngInfo(int n, MLNGINFO *pmlInfo)
{
BOOL bRet = FALSE;
MLNGINFO *pml;
if (!g_pMlngInfo)
return FALSE;
CicEnterCriticalSection(g_cs);
Assert(g_pMlngInfo);
if (n >= g_pMlngInfo->Count())
goto Exit;
pml = g_pMlngInfo->GetPtr(n);
if (!pml)
goto Exit;
*pmlInfo = *pml;
bRet = TRUE;
Exit:
CicLeaveCriticalSection(g_cs);
return bRet;
}
//---------------------------------------------------------------------------
//
// GetMlngInfoByhKL()
//
//---------------------------------------------------------------------------
int GetMlngInfoByhKL(HKL hKL, MLNGINFO *pmlInfo)
{
int nRet = -1;
MLNGINFO *pml;
if (!g_pMlngInfo)
return 0;
CicEnterCriticalSection(g_cs);
int nCnt = g_pMlngInfo->Count();
int i;
for (i = 0; i < nCnt; i++)
{
pml = g_pMlngInfo->GetPtr(i);
if (pml->hKL == hKL)
{
*pmlInfo = *pml;
nRet = i;
break;
}
}
CicLeaveCriticalSection(g_cs);
return nRet;
}
//+---------------------------------------------------------------------------
//
// CheckMlngInfo
//
// return TRUE, if MlangInfo needs to be updated.
//
//----------------------------------------------------------------------------
BOOL CheckMlngInfo()
{
int iLangs;
BOOL bRet = FALSE;
HKL *pLanguages = NULL;
if (!g_pMlngInfo)
return TRUE;
iLangs = GetKeyboardLayoutList((UINT)0, (HKL FAR *)NULL);
if (iLangs != TF_MlngInfoCount())
return TRUE;
if (iLangs)
{
int i;
pLanguages = (HKL *)cicMemAlloc(iLangs * sizeof(HKL));
if (!pLanguages)
goto Exit;
GetKeyboardLayoutList(iLangs, (HKL FAR *)pLanguages);
for (i = 0; i < iLangs; i++)
{
MLNGINFO *pMlngInfo = g_pMlngInfo->GetPtr(i);
if (pMlngInfo->hKL != pLanguages[i])
{
bRet = TRUE;
goto Exit;
}
}
}
Exit:
if (pLanguages)
cicMemFree(pLanguages);
return bRet;
}
//---------------------------------------------------------------------------
//
// void DestroyMlngInfo()
//
//---------------------------------------------------------------------------
void DestroyMlngInfo()
{
if (g_pMlngInfo)
{
while (g_pMlngInfo->Count())
{
g_pMlngInfo->Remove(0, 1);
}
delete g_pMlngInfo;
g_pMlngInfo = NULL;
}
}
//---------------------------------------------------------------------------
//
// void CreateMLlngInfo()
//
//---------------------------------------------------------------------------
void CreateMlngInfo()
{
HKL *pLanguages;
UINT uCount;
UINT uLangs;
MLNGINFO *pMlngInfo;
BOOL fNeedInd = FALSE;
uLangs = GetKeyboardLayoutList((UINT)0, (HKL FAR *)NULL);
if (!g_pMlngInfo)
g_pMlngInfo = new CStructArray<MLNGINFO>;
if (!g_pMlngInfo)
return;
if (!EnsureIconImageList())
{
return;
}
pLanguages = (HKL *)cicMemAllocClear(uLangs * sizeof(HKL));
if (!pLanguages)
return;
GetKeyboardLayoutList(uLangs, (HKL FAR *)pLanguages);
//
// pLanguages contains all the HKLs in the system
// Put everything together in the DPA and Image List
//
for (uCount = 0; uCount < uLangs; uCount++)
{
pMlngInfo = g_pMlngInfo->Append(1);
if (pMlngInfo)
{
pMlngInfo->hKL = pLanguages[uCount];
pMlngInfo->fInitIcon = FALSE;
pMlngInfo->fInitDesc = FALSE;
}
}
cicMemFree(pLanguages);
}
//---------------------------------------------------------------------------
//
// void InitDesc
//
//---------------------------------------------------------------------------
void MLNGINFO::InitDesc()
{
MLNGINFO *pml;
if (fInitDesc)
return;
WCHAR szRegText[256];
WCHAR szIMEFile[256];
GetHKLDesctription(hKL,
szRegText, ARRAYSIZE(szRegText),
szIMEFile, ARRAYSIZE(szIMEFile));
fInitDesc = TRUE;
SetDesc(szRegText);
CicEnterCriticalSection(g_cs);
Assert(g_pMlngInfo);
int nCnt = g_pMlngInfo->Count();
int i;
for (i = 0; i < nCnt; i++)
{
pml = g_pMlngInfo->GetPtr(i);
if (pml->hKL == hKL)
{
pml->fInitDesc = TRUE;
pml->SetDesc(szRegText);
break;
}
}
CicLeaveCriticalSection(g_cs);
return;
}
//---------------------------------------------------------------------------
//
// void InitIcon
//
//---------------------------------------------------------------------------
void MLNGINFO::InitIcon()
{
HICON hIcon;
if (fInitIcon)
return;
WCHAR szRegText[256];
WCHAR szIMEFile[256];
GetHKLDesctription(hKL,
szRegText, ARRAYSIZE(szRegText),
szIMEFile, ARRAYSIZE(szIMEFile));
fInitDesc = TRUE;
SetDesc(szRegText);
if (wcslen(szIMEFile))
{
int cx, cy;
InatGetIconSize(&cx, &cy);
if ((hIcon = GetIconFromFile(cx, cy, szIMEFile, 0)) == 0)
{
goto GetLangIcon;
}
}
else // for non-ime layout
{
GetLangIcon:
hIcon = InatCreateIcon(LOWORD((DWORD)(UINT_PTR)hKL));
}
if (hIcon)
{
nIconIndex = InatAddIcon(hIcon);
DestroyIcon(hIcon);
}
MLNGINFO *pml;
CicEnterCriticalSection(g_cs);
Assert(g_pMlngInfo);
int nCnt = g_pMlngInfo->Count();
int i;
for (i = 0; i < nCnt; i++)
{
pml = g_pMlngInfo->GetPtr(i);
if (pml->hKL == hKL)
{
pml->fInitDesc = TRUE;
pml->fInitIcon = TRUE;
pml->nIconIndex = nIconIndex;
pml->SetDesc(szRegText);
break;
}
}
CicLeaveCriticalSection(g_cs);
return;
}
//---------------------------------------------------------------------------
//
// void TF_InitMLlngInfo()
//
//---------------------------------------------------------------------------
void WINAPI TF_InitMlngInfo()
{
CicEnterCriticalSection(g_cs);
if (CheckMlngInfo())
{
DestroyMlngInfo();
CreateMlngInfo();
}
CicLeaveCriticalSection(g_cs);
}
//---------------------------------------------------------------------------
//
// void TF_InitMLlngHKL()
//
//---------------------------------------------------------------------------
BOOL TF_GetMlngHKL(int nId, HKL *phkl, WCHAR *psz, UINT cch)
{
BOOL bRet = FALSE;
MLNGINFO *pml;
CicEnterCriticalSection(g_cs);
Assert(g_pMlngInfo);
if (nId >= g_pMlngInfo->Count())
goto Exit;
pml = g_pMlngInfo->GetPtr(nId);
if (!pml)
goto Exit;
if (phkl)
*phkl = pml->hKL;
if (psz)
wcsncpy(psz, pml->GetDesc(), cch);
bRet = TRUE;
Exit:
CicLeaveCriticalSection(g_cs);
return bRet;
}
//---------------------------------------------------------------------------
//
// void TF_GetMlngIconIndex()
//
//---------------------------------------------------------------------------
UINT WINAPI TF_GetMlngIconIndex(int nId)
{
UINT uIconIndex = (UINT)-1;
MLNGINFO *pml;
CicEnterCriticalSection(g_cs);
Assert(g_pMlngInfo);
if (nId >= g_pMlngInfo->Count())
goto Exit;
pml = g_pMlngInfo->GetPtr(nId);
if (!pml)
goto Exit;
uIconIndex = pml->GetIconIndex();
Exit:
CicLeaveCriticalSection(g_cs);
return uIconIndex;
}
//---------------------------------------------------------------------------
//
// void ClearMlngIconIndex()
//
//---------------------------------------------------------------------------
void ClearMlngIconIndex()
{
int i;
CicEnterCriticalSection(g_cs);
Assert(g_pMlngInfo);
for (i = 0; i < g_pMlngInfo->Count(); i++)
{
MLNGINFO *pml;
pml = g_pMlngInfo->GetPtr(i);
if (!pml)
goto Exit;
pml->ClearIconIndex();
}
Exit:
CicLeaveCriticalSection(g_cs);
return;
}
//////////////////////////////////////////////////////////////////////////////
//
// IconImageList
//
//////////////////////////////////////////////////////////////////////////////
//---------------------------------------------------------------------------
//
// EnsureIconImageList
//
//---------------------------------------------------------------------------
BOOL EnsureIconImageList()
{
if (g_IconList.IsInited())
return TRUE;
g_IconList.Init(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON));
return TRUE;
}
//---------------------------------------------------------------------------
//
// InatAddIcon
//
//---------------------------------------------------------------------------
UINT InatAddIcon(HICON hIcon)
{
if (!EnsureIconImageList())
return -1;
return g_IconList.AddIcon(hIcon);
}
//---------------------------------------------------------------------------
//
// InatExtractIcon
//
//---------------------------------------------------------------------------
HICON WINAPI TF_InatExtractIcon(UINT uId)
{
return g_IconList.ExtractIcon(uId);
}
//---------------------------------------------------------------------------
//
// InatGetIconSize
//
//---------------------------------------------------------------------------
BOOL InatGetIconSize(int *pcx, int *pcy)
{
g_IconList.GetIconSize(pcx, pcy);
return TRUE;
}
//---------------------------------------------------------------------------
//
// InatGetImageCount
//
//---------------------------------------------------------------------------
BOOL InatGetImageCount()
{
return g_IconList.GetImageCount();
}
//---------------------------------------------------------------------------
//
// InatRemoveAll
//
//---------------------------------------------------------------------------
void InatRemoveAll()
{
if (!g_IconList.IsInited())
return;
g_IconList.RemoveAll(FALSE);
return;
}
//////////////////////////////////////////////////////////////////////////////
//
// HKL API
//
//////////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
//
// CPreloadRegKey
//
//-----------------------------------------------------------------------------
class CPreloadRegKey : public CMyRegKey
{
public:
HRESULT Open(BOOL fDefaultUser = FALSE)
{
if (fDefaultUser)
return CMyRegKey::Open(HKEY_USERS, c_szDefaultUserPreload, KEY_ALL_ACCESS);
else
return CMyRegKey::Open(HKEY_CURRENT_USER, c_szPreload, KEY_ALL_ACCESS);
}
HKL Get(int n)
{
char szValue[16];
char szValueName[16];
StringCchPrintf(szValueName, ARRAYSIZE(szValueName), "%d", n);
if (IsOnNT())
{
if (QueryValueCch(szValue, szValueName, ARRAYSIZE(szValue)) != S_OK)
return NULL;
}
else
{
CMyRegKey keySub;
if (keySub.Open(m_hKey, szValueName, KEY_READ) != S_OK)
return NULL;
if (keySub.QueryValueCch(szValue, NULL, ARRAYSIZE(szValue)) != S_OK)
return NULL;
}
return (HKL)(LONG_PTR)AsciiToNum(szValue);
}
void Set(int n, HKL hkl)
{
char szValue[16];
char szValueName[16];
StringCchPrintf(szValueName, ARRAYSIZE(szValueName), "%d", n);
NumToA((DWORD)(LONG_PTR)hkl, szValue);
if (IsOnNT())
{
SetValue(szValue, szValueName);
}
else
{
CMyRegKey keySub;
if (keySub.Open(m_hKey, szValueName, KEY_ALL_ACCESS) == S_OK)
keySub.SetValue(szValue, (LPSTR)NULL);
}
return;
}
void Delete(int n)
{
char szValueName[16];
StringCchPrintf(szValueName, ARRAYSIZE(szValueName), "%d", n);
if (IsOnNT())
{
DeleteValue(szValueName);
}
else
{
DeleteSubKey(szValueName);
}
return;
}
};
//+---------------------------------------------------------------------------
//
// GetSubstitute
//
//----------------------------------------------------------------------------
DWORD GetSubstitute(HKL hKL)
{
CMyRegKey key;
DWORD dwIndex = 0;
TCHAR szValue[16];
TCHAR szValueName[64];
DWORD dwLayout = HandleToLong(hKL);
//
// it's IME.
//
if ((dwLayout & 0xf0000000) == 0xe0000000)
return dwLayout;
//
// it's default layout.
//
if (HIWORD(dwLayout) == LOWORD(dwLayout))
dwLayout &= 0x0000FFFF;
else if ((dwLayout & 0xf0000000) == 0xf0000000)
dwLayout = GetKbdLayoutId(dwLayout);
if (key.Open(HKEY_CURRENT_USER, c_szSubst, KEY_READ) != S_OK)
return dwLayout;
if (IsOnNT())
{
while (key.EnumValue(dwIndex, szValueName, ARRAYSIZE(szValueName)) == S_OK)
{
if (key.QueryValueCch(szValue, szValueName, ARRAYSIZE(szValue)) == S_OK)
{
if ((dwLayout & 0x0FFFFFFF) == AsciiToNum(szValue))
{
return AsciiToNum(szValueName);
}
}
dwIndex++;
}
}
else
{
while (key.EnumKey(dwIndex, szValueName, ARRAYSIZE(szValueName)) == S_OK)
{
CMyRegKey keySub;
if (keySub.Open(key, szValueName, KEY_READ) == S_OK)
{
if (key.QueryValueCch(szValue, NULL, ARRAYSIZE(szValue)) == S_OK)
{
if ((dwLayout & 0x0FFFFFFF) == AsciiToNum(szValue))
{
return AsciiToNum(szValueName);
}
}
}
dwIndex++;
}
}
return dwLayout;
}
//+---------------------------------------------------------------------------
//
// SetSystemDefaultHKL
//
//----------------------------------------------------------------------------
BOOL SetSystemDefaultHKL(HKL hkl)
{
CPreloadRegKey key;
int n;
HKL hklFirst;
BOOL bRet = FALSE;
DWORD dwLayout;
if (key.Open() != S_OK)
return bRet;
dwLayout = GetSubstitute(hkl);
n = 1;
while(1)
{
HKL hklCur;
hklCur = key.Get(n);
if (!hklCur)
break;
if (n == 1)
hklFirst = hklCur;
if (hklCur == LongToHandle(dwLayout))
{
bRet = TRUE;
if (n != 1)
{
key.Set(n, hklFirst);
key.Set(1, hklCur);
}
bRet = SystemParametersInfo( SPI_SETDEFAULTINPUTLANG,
0,
(LPVOID)((LPDWORD)&hkl),
0 );
Assert(bRet);
break;
}
n++;
}
return bRet;
}
//+---------------------------------------------------------------------------
//
// GetPreloadListForNT()
//
//----------------------------------------------------------------------------
UINT GetPreloadListForNT(DWORD *pdw, UINT uBufSize)
{
CMyRegKey key;
CMyRegKey key1;
char szValue[16];
char szSubstValue[16];
char szName[16];
UINT uRet = 0;
//
// this function support only NT.
// win9x has different formation for Preload registry. Each layout is key.
//
if (!IsOnNT())
return 0;
if (key.Open(HKEY_CURRENT_USER, c_szPreload, KEY_READ) != S_OK)
return uRet;
key1.Open(HKEY_CURRENT_USER, c_szSubst, KEY_READ);
if (!pdw)
uBufSize = 1000;
while (uRet < uBufSize)
{
BOOL fUseSubst = FALSE;
StringCchPrintf(szName, ARRAYSIZE(szName), "%d", uRet + 1);
if (key.QueryValueCch(szValue, szName, ARRAYSIZE(szValue)) != S_OK)
return uRet;
if ((HKEY)key1)
{
if (key1.QueryValueCch(szSubstValue, szValue, ARRAYSIZE(szSubstValue)) == S_OK)
fUseSubst = TRUE;
}
if (pdw)
{
*pdw = AsciiToNum(fUseSubst ? szSubstValue : szValue);
pdw++;
}
uRet++;
}
return uRet;
}
#ifdef LATER_TO_CHECK_DUMMYHKL
//+---------------------------------------------------------------------------
//
// RemoveFEDummyHKLFromPreloadReg()
//
//----------------------------------------------------------------------------
void RemoveFEDummyHKLFromPreloadReg(HKL hkl, BOOL fDefaultUser)
{
CPreloadRegKey key;
BOOL fReset = FALSE;
UINT uCount;
UINT uMatch = 0;
if (key.Open(fDefaultUser) != S_OK)
return;
uCount = 1;
while(uCount < 1000)
{
HKL hklCur;
hklCur = key.Get(uCount);
if (!hklCur)
break;
if (hklCur == hkl)
{
uMatch++;
uCount++;
fReset = TRUE;
continue;
}
if (fReset && uMatch)
{
if (uCount <= uMatch)
{
Assert(0);
return;
}
//
// reset the hkl orders from preload section
//
key.Set(uCount-uMatch, hklCur);
}
uCount++;
}
while (fReset && uMatch && uCount)
{
if (uCount <= uMatch || (uCount - uMatch) <= 1)
{
Assert(0);
return;
}
//
// remove the dummy hkl from preload section
//
key.Delete(uCount - uMatch);
uMatch--;
}
return;
}
//+---------------------------------------------------------------------------
//
// RemoveFEDummyHKLs
//
// This function cleans up the FE Dummy HKLs that were added on Win9x.
// This is called during update setup to Whistler.
//
//----------------------------------------------------------------------------
void RemoveFEDummyHKLs()
{
CMyRegKey key;
DWORD dwIndex;
TCHAR szValue[MAX_PATH];
//
// Now read all the locales from the registry.
//
if (key.Open(HKEY_LOCAL_MACHINE, c_szLayoutPath) != ERROR_SUCCESS)
{
return;
}
dwIndex = 0;
szValue[0] = TEXT('\0');
while (key.EnumKey(dwIndex, szValue, ARRAYSIZE(szValue)) == ERROR_SUCCESS)
{
BOOL fDelete = FALSE;
CRegKeyMUI key1;
if ((szValue[0] != 'e') && (szValue[0] != 'E'))
goto Next;
if (key1.Open(key, szValue) == S_OK)
{
TCHAR szValueLayoutText[MAX_PATH];
//
// Get the layout text.
//
szValueLayoutText[0] = TEXT('\0');
if (key1.QueryValueCch(szValueLayoutText, c_szLayoutText, ARRAYSIZE(szValueLayoutText)) == S_OK)
{
char szDummyProfile[256];
DWORD dw = AsciiToNum(szValue);
StringCchPrintf(szDummyProfile, ARRAYSIZE(szDummyProfile), "hkl%04x", LOWORD(dw));
if (!lstrcmpi(szDummyProfile, szValueLayoutText))
{
fDelete = TRUE;
//
// Remove dummy HKL from Preload of HKCU and HKU\.DEFAULT.
// We may need to enum all users in HKU\.DEFAULT.
//
RemoveFEDummyHKLFromPreloadReg((HKL)LongToHandle(dw), TRUE);
RemoveFEDummyHKLFromPreloadReg((HKL)LongToHandle(dw), FALSE);
}
}
key1.Close();
}
if (fDelete)
{
key.RecurseDeleteKey(szValue);
}
else
{
Next:
dwIndex++;
}
szValue[0] = TEXT('\0');
}
return;
}
#endif LATER_TO_CHECK_DUMMYHKL