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.
 
 
 
 
 
 

1604 lines
45 KiB

//
// Include Files.
//
#include "input.h"
#include <regstr.h>
#include <shlapip.h>
#include "external.h"
#include "inputdlg.h"
#include "util.h"
#include "msctf.h"
// TM_LANGUAGEBAND is defined in "shell\inc\trayp.h"
#define TM_LANGUAGEBAND WM_USER+0x105
typedef BOOL (WINAPI *PFNINVALIDASMCACHE)();
static const char c_szTF_InvalidAssemblyListCahgeIdExist[] = "TF_InvalidAssemblyListCacheIfExist";
void InvalidAssemblyListCacheIfExist()
{
HINSTANCE hModCtf = LoadSystemLibrary(TEXT("msctf.dll"));
PFNINVALIDASMCACHE pfn;
if (!hModCtf)
return;
pfn = (PFNINVALIDASMCACHE)GetProcAddress(hModCtf,
c_szTF_InvalidAssemblyListCahgeIdExist);
if (pfn)
pfn();
FreeLibrary(hModCtf);
}
////////////////////////////////////////////////////////////////////////////
//
// LoadCtfmon
//
////////////////////////////////////////////////////////////////////////////
void LoadCtfmon(
BOOL bLoad,
LCID SysLocale,
BOOL bDefUser)
{
HWND hwndCTFMon;
HKEY hkeyCtfmon;
BOOL bMinLangBar = TRUE;
//
// Get default system locale
//
if (!SysLocale)
SysLocale = GetSystemDefaultLCID();
if ((SysLocale == 0x0404) || (SysLocale == 0x0411) ||
(SysLocale == 0x0412) || (SysLocale == 0x0804))
{
//
// Show language bar in case of FE system as a default
//
bMinLangBar = FALSE;
}
//
// Find language tool bar module(CTFMON.EXE)
//
hwndCTFMon = FindWindow(c_szCTFMonClass, NULL);
if (!bDefUser)
{
if (RegCreateKey( HKEY_CURRENT_USER,
REGSTR_PATH_RUN,
&hkeyCtfmon ) != ERROR_SUCCESS)
{
hkeyCtfmon = NULL;
}
}
else
{
if (RegCreateKey( HKEY_USERS,
c_szRunPath_DefUser,
&hkeyCtfmon ) != ERROR_SUCCESS)
{
hkeyCtfmon = NULL;
}
}
//
// Update language band menu item to Taskbar
//
SetLanguageBandMenu(bLoad);
if (bLoad)
{
BOOL bOSNT51 = IsOSPlatform(OS_NT51);
if (IsSetupMode() || bDefUser)
{
DWORD dwShowStatus;
if (!GetLangBarOption(&dwShowStatus, bDefUser))
{
if (bMinLangBar)
{
if (bOSNT51)
SetLangBarOption(REG_LANGBAR_DESKBAND, bDefUser);
else
SetLangBarOption(REG_LANGBAR_MINIMIZED, bDefUser);
}
else
{
SetLangBarOption(REG_LANGBAR_SHOWNORMAL, bDefUser);
}
}
}
if (!IsSetupMode() && IsInteractiveUserLogon() && !bDefUser)
{
HRESULT hr;
DWORD dwTBFlag = 0;
ITfLangBarMgr *pLangBar = NULL;
//
// Minimize language bar as a default setting.
//
hr = CoCreateInstance(&CLSID_TF_LangBarMgr,
NULL,
CLSCTX_INPROC_SERVER,
&IID_ITfLangBarMgr,
(LPVOID *) &pLangBar);
if (SUCCEEDED(hr))
{
pLangBar->lpVtbl->GetShowFloatingStatus(pLangBar, &dwTBFlag);
//
// Bug#519662 - Tablet PC set Language Bar UI as hidden status with
// running ctfmon.exe module. So we want to show Language Bar UI again
// if the current show status is hidden.
//
if (!IsWindow(hwndCTFMon) || (dwTBFlag & TF_SFT_HIDDEN))
{
if (bMinLangBar)
{
if (bOSNT51)
pLangBar->lpVtbl->ShowFloating(pLangBar, TF_SFT_DESKBAND);
else
pLangBar->lpVtbl->ShowFloating(pLangBar, TF_SFT_MINIMIZED);
}
else
{
pLangBar->lpVtbl->ShowFloating(pLangBar, TF_SFT_SHOWNORMAL);
}
}
else if (dwTBFlag & TF_SFT_DESKBAND)
{
pLangBar->lpVtbl->ShowFloating(pLangBar, dwTBFlag);
}
}
if (pLangBar)
pLangBar->lpVtbl->Release(pLangBar);
//
// Invalid Assembly Cahce before starting ctfmon.exe
//
InvalidAssemblyListCacheIfExist();
//
// Run ctfmon.exe process
//
RunCtfmonProcess();
}
if (hkeyCtfmon)
{
TCHAR szCTFMonPath[MAX_PATH];
GetCtfmonPath((LPTSTR) szCTFMonPath, ARRAYSIZE(szCTFMonPath));
RegSetValueEx(hkeyCtfmon,
c_szCTFMon,
0,
REG_SZ,
(LPBYTE)szCTFMonPath,
(lstrlen(szCTFMonPath) + 1) * sizeof(TCHAR));
//
// Clean up the registry for internat.
//
RegDeleteValue(hkeyCtfmon, c_szInternat);
}
}
else
{
if (!bDefUser)
{
HRESULT hr;
DWORD dwTBFlag = 0;
ITfLangBarMgr *pLangBar = NULL;
//
// Minimize language bar as a default setting.
//
hr = CoCreateInstance(&CLSID_TF_LangBarMgr,
NULL,
CLSCTX_INPROC_SERVER,
&IID_ITfLangBarMgr,
(LPVOID *) &pLangBar);
if (SUCCEEDED(hr))
{
pLangBar->lpVtbl->GetShowFloatingStatus(pLangBar, &dwTBFlag);
if (dwTBFlag & TF_SFT_DESKBAND)
{
#if 0
HWND hwndTray = NULL;
//
// Notify to shell to remove the language band from taskbar.
//
hwndTray = FindWindow(TEXT(WNDCLASS_TRAYNOTIFY), NULL);
if (hwndTray)
{
DWORD_PTR dwResult;
LRESULT lResult = (LRESULT)0;
lResult = SendMessageTimeout(hwndTray,
TM_LANGUAGEBAND,
0,
0, // Remove band
SMTO_ABORTIFHUNG | SMTO_BLOCK,
5000,
&dwResult);
}
#else
pLangBar->lpVtbl->ShowFloating(pLangBar, TF_SFT_SHOWNORMAL);
//
// Change back DeskBand setting into the registry
//
SetLangBarOption(REG_LANGBAR_DESKBAND, bDefUser);
#endif
}
}
if (pLangBar)
pLangBar->lpVtbl->Release(pLangBar);
if (hwndCTFMon && IsWindow(hwndCTFMon))
{
//
// It's on, turn off the language tool bar.
//
PostMessage(hwndCTFMon, WM_CLOSE, 0L, 0L);
}
}
if (hkeyCtfmon)
RegDeleteValue(hkeyCtfmon, c_szCTFMon);
}
if (hkeyCtfmon)
{
RegCloseKey(hkeyCtfmon);
}
}
////////////////////////////////////////////////////////////////////////////
//
// UpdateDefaultHotkey
//
////////////////////////////////////////////////////////////////////////////
void UpdateDefaultHotkey(
LCID SysLocale,
BOOL bThai,
BOOL bDefaultUserCase)
{
HKEY hKey;
TCHAR szData[MAX_PATH];
DWORD cbData;
BOOL bHotKey = FALSE;
BOOL bChinese = FALSE;
BOOL bMe = FALSE;
DWORD dwPrimLangID;
dwPrimLangID = PRIMARYLANGID(LANGIDFROMLCID(SysLocale));
if (PRIMARYLANGID(dwPrimLangID) == LANG_CHINESE)
{
bChinese = TRUE;
}
else if (dwPrimLangID == LANG_ARABIC || dwPrimLangID == LANG_HEBREW)
{
bMe = TRUE;
}
//
// Try to open the registry key
//
if (!bDefaultUserCase)
{
if (RegOpenKey( HKEY_CURRENT_USER,
c_szKbdToggleKey,
&hKey ) == ERROR_SUCCESS)
{
bHotKey = TRUE;
}
}
else
{
if (RegOpenKey( HKEY_USERS,
c_szKbdToggleKey_DefUser,
&hKey ) == ERROR_SUCCESS)
{
bHotKey = TRUE;
}
}
//
// If there is no hotkey switch, set it to Ctrl+Shift. Otherwise, the
// user cannot switch to an IME without setting the value first.
//
szData[0] = TEXT('\0');
if (bHotKey)
{
cbData = sizeof(szData);
RegQueryValueEx( hKey,
TEXT("Hotkey"),
NULL,
NULL,
(LPBYTE)szData,
&cbData );
switch (szData[0])
{
case TEXT('1'):
{
//
// Currently ALT/SHIFT or CTRL/SHIFT. Do not change.
//
break;
}
case TEXT('2'):
{
//
// Change to 1 if Chinese.
//
if (bChinese)
{
szData[0] = TEXT('1');
szData[1] = TEXT('\0');
RegSetValueEx( hKey,
TEXT("Hotkey"),
0,
REG_SZ,
(LPBYTE)szData,
(DWORD)(lstrlen(szData) + 1) * sizeof(TCHAR) );
}
break;
}
case TEXT('3'):
{
//
// Default hotkey for FE locale switch.
//
szData[0] = bThai ? TEXT('4') : TEXT('1');
szData[1] = TEXT('\0');
RegSetValueEx( hKey,
TEXT("Hotkey"),
0,
REG_SZ,
(LPBYTE)szData,
(DWORD)(lstrlen(szData) + 1) * sizeof(TCHAR) );
break;
}
case TEXT('4'):
{
//
// Currently Grave. Change to 1 if not Thai.
//
if (!bThai)
{
szData[0] = TEXT('1');
szData[1] = TEXT('\0');
RegSetValueEx( hKey,
TEXT("Hotkey"),
0,
REG_SZ,
(LPBYTE)szData,
(DWORD)(lstrlen(szData) + 1) * sizeof(TCHAR) );
}
break;
}
}
RegFlushKey(hKey);
//
// Get updated hotkey value and copy the value to language hotkey
//
szData[0] = TEXT('\0');
cbData = sizeof(szData);
RegQueryValueEx( hKey,
TEXT("Hotkey"),
NULL,
NULL,
(LPBYTE)szData,
&cbData );
if (szData[0])
{
RegSetValueEx( hKey,
TEXT("Language Hotkey"),
0,
REG_SZ,
(LPBYTE)szData,
(DWORD)(lstrlen(szData) + 1) * sizeof(TCHAR) );
//
// Set Layout Hotkey
//
switch (szData[0])
{
case TEXT('1'):
case TEXT('4'):
{
szData[0] = bMe ? TEXT('3') : TEXT('2');
szData[1] = TEXT('\0');
break;
}
case TEXT('2'):
{
szData[0] = TEXT('1');
szData[1] = TEXT('\0');
break;
}
case TEXT('3'):
{
szData[0] = TEXT('3');
szData[1] = TEXT('\0');
break;
}
}
RegSetValueEx( hKey,
TEXT("Layout Hotkey"),
0,
REG_SZ,
(LPBYTE)szData,
(DWORD)(lstrlen(szData) + 1) * sizeof(TCHAR) );
}
RegCloseKey(hKey);
}
else
{
BOOL bKeyCreated = FALSE;
//
// Create the registry key
//
if (!bDefaultUserCase)
{
if (RegCreateKey( HKEY_CURRENT_USER,
c_szKbdToggleKey,
&hKey ) == ERROR_SUCCESS)
{
bKeyCreated = TRUE;
}
}
else
{
if (RegCreateKey( HKEY_USERS,
c_szKbdToggleKey_DefUser,
&hKey ) == ERROR_SUCCESS)
{
bKeyCreated = TRUE;
}
}
//
// We don't have a Toggle key yet. Create one and set the
// correct value.
//
if (bKeyCreated)
{
szData[0] = bThai ? TEXT('4') : TEXT('1');
szData[1] = 0;
RegSetValueEx( hKey,
TEXT("Hotkey"),
0,
REG_SZ,
(LPBYTE)szData,
(DWORD)(lstrlen(szData) + 1) * sizeof(TCHAR) );
RegSetValueEx( hKey,
TEXT("Language Hotkey"),
0,
REG_SZ,
(LPBYTE)szData,
(DWORD)(lstrlen(szData) + 1) * sizeof(TCHAR) );
szData[0] = bMe ? TEXT('3') : TEXT('2');
szData[1] = 0;
RegSetValueEx( hKey,
TEXT("Layout Hotkey"),
0,
REG_SZ,
(LPBYTE)szData,
(DWORD)(lstrlen(szData) + 1) * sizeof(TCHAR) );
RegFlushKey(hKey);
RegCloseKey(hKey);
}
}
}
////////////////////////////////////////////////////////////////////////////
//
// ClearHotkey
//
////////////////////////////////////////////////////////////////////////////
void ClearHotKey(
BOOL bDefaultUserCase)
{
HKEY hKey;
DWORD cbData;
TCHAR szData[MAX_PATH];
BOOL bKeyCreated = FALSE;
//
// Create the registry key
//
if (!bDefaultUserCase)
{
if (RegCreateKey( HKEY_CURRENT_USER,
c_szKbdToggleKey,
&hKey ) == ERROR_SUCCESS)
{
bKeyCreated = TRUE;
}
}
else
{
if (RegCreateKey( HKEY_USERS,
c_szKbdToggleKey_DefUser,
&hKey ) == ERROR_SUCCESS)
{
bKeyCreated = TRUE;
}
}
if (bKeyCreated)
{
szData[0] = TEXT('3');
szData[1] = 0;
RegSetValueEx( hKey,
TEXT("Hotkey"),
0,
REG_SZ,
(LPBYTE)szData,
(DWORD)(lstrlen(szData) + 1) * sizeof(TCHAR) );
RegSetValueEx( hKey,
TEXT("Language Hotkey"),
0,
REG_SZ,
(LPBYTE)szData,
(DWORD)(lstrlen(szData) + 1) * sizeof(TCHAR) );
RegSetValueEx( hKey,
TEXT("Layout Hotkey"),
0,
REG_SZ,
(LPBYTE)szData,
(DWORD)(lstrlen(szData) + 1) * sizeof(TCHAR) );
RegFlushKey(hKey);
RegCloseKey(hKey);
}
}
////////////////////////////////////////////////////////////////////////////
//
// ActivateDefaultKeyboardLayout
//
// Sets the default input layout on the system, and broadcast to all
// running apps about this change.
//
////////////////////////////////////////////////////////////////////////////
BOOL ActivateDefaultKeyboardLayout(
DWORD dwLocale,
DWORD dwLayout,
HKL hkl)
{
BOOL bRet = FALSE;
if (hkl)
{
if (SystemParametersInfo( SPI_SETDEFAULTINPUTLANG,
0,
(LPVOID)((LPDWORD) &hkl),
0 ))
{
DWORD dwRecipients = BSM_APPLICATIONS | BSM_ALLDESKTOPS;
BroadcastSystemMessage( BSF_POSTMESSAGE,
&dwRecipients,
WM_INPUTLANGCHANGEREQUEST,
1,
(LPARAM) hkl );
bRet = TRUE;
}
}
return bRet;
}
////////////////////////////////////////////////////////////////////////////
//
// SetSystemDefautLayout
//
////////////////////////////////////////////////////////////////////////////
BOOL SetSystemDefautLayout(
LCID Locale,
DWORD dwLayout,
HKL hklDefault,
BOOL bDefaultUserCase )
{
LONG rc;
int iPreloadInx;
BOOL bRet = FALSE;
HKEY hKeyPreload,hKeySubst;
TCHAR szSubValue[MAX_PATH];
TCHAR szSubData[MAX_PATH];
TCHAR szPreload[MAX_PATH];
TCHAR szPreloadInx[MAX_PATH];
DWORD dwLocale, dwIndex, cchSubValue, cbData;
dwLocale = Locale;
if (dwLayout == 0)
{
return (FALSE);
}
//
// Open the HKCU\Keyboard Layout\Preload key.
//
if (!bDefaultUserCase)
{
if (RegOpenKeyEx(HKEY_CURRENT_USER,
c_szKbdPreloadKey,
0,
KEY_ALL_ACCESS,
&hKeyPreload) != ERROR_SUCCESS)
{
return (FALSE);
}
}
else
{
if (RegOpenKeyEx(HKEY_USERS,
c_szKbdPreloadKey_DefUser,
0,
KEY_ALL_ACCESS,
&hKeyPreload) != ERROR_SUCCESS)
{
return (FALSE);
}
}
//
// Open the HKCU\Keyboard Layout\Substitutes key.
//
if (!bDefaultUserCase)
{
if (RegOpenKeyEx(HKEY_CURRENT_USER,
c_szKbdSubstKey,
0,
KEY_ALL_ACCESS,
&hKeySubst) != ERROR_SUCCESS)
{
RegCloseKey(hKeyPreload);
return (FALSE);
}
}
else
{
if (RegOpenKeyEx(HKEY_USERS,
c_szKbdSubstKey_DefUser,
0,
KEY_ALL_ACCESS,
&hKeySubst) != ERROR_SUCCESS)
{
RegCloseKey(hKeyPreload);
return (FALSE);
}
}
//
// Enumerate the values in the Preload key.
//
dwIndex = 0;
cchSubValue = sizeof(szSubValue) / sizeof(TCHAR);
cbData = sizeof(szSubData);
rc = RegEnumValue( hKeySubst,
dwIndex,
szSubValue,
&cchSubValue,
NULL,
NULL,
(LPBYTE)szSubData,
&cbData );
while (rc == ERROR_SUCCESS)
{
DWORD dwSubLayout;
dwSubLayout = TransNum(szSubData);
if (dwLayout == dwSubLayout)
{
dwLayout = TransNum(szSubValue);
break;
}
//
// Get the next enum value.
//
dwIndex++;
cchSubValue = sizeof(szSubValue) / sizeof(TCHAR);
cbData = sizeof(szSubData);
rc = RegEnumValue( hKeySubst,
dwIndex,
szSubValue,
&cchSubValue,
NULL,
NULL,
(LPBYTE)szSubData,
&cbData );
}
//
// Set default layout into preload section
//
iPreloadInx = 1;
while(1)
{
DWORD dwCurLayout;
DWORD dwFirstLayout;
//
// See if there is a substitute value.
//
StringCchPrintf(szPreloadInx, ARRAYSIZE(szPreloadInx), TEXT("%d"), iPreloadInx);
cbData = sizeof(szPreload);
if (RegQueryValueEx(hKeyPreload,
szPreloadInx,
NULL,
NULL,
(LPBYTE)szPreload,
&cbData ) == ERROR_SUCCESS)
{
dwCurLayout = TransNum(szPreload);
}
else
{
break;
}
if (!dwCurLayout)
break;
if (iPreloadInx == 1)
dwFirstLayout = dwCurLayout;
if (dwCurLayout == dwLayout)
{
bRet = TRUE;
if (iPreloadInx != 1)
{
//
// Set new default keyboard layout
//
StringCchPrintf(szPreloadInx, ARRAYSIZE(szPreloadInx), TEXT("%d"), 1);
StringCchPrintf(szPreload, ARRAYSIZE(szPreload), TEXT("%08x"), dwCurLayout);
RegSetValueEx( hKeyPreload,
szPreloadInx,
0,
REG_SZ,
(LPBYTE)szPreload,
(DWORD)(lstrlen(szPreload) + 1) * sizeof(TCHAR) );
//
// Set old default keyboard layout
//
StringCchPrintf(szPreloadInx, ARRAYSIZE(szPreloadInx), TEXT("%d"), iPreloadInx);
StringCchPrintf(szPreload, ARRAYSIZE(szPreload), TEXT("%08x"), dwFirstLayout);
RegSetValueEx( hKeyPreload,
szPreloadInx,
0,
REG_SZ,
(LPBYTE)szPreload,
(DWORD)(lstrlen(szPreload) + 1) * sizeof(TCHAR) );
}
//
// Activate new default keyboard layout
//
ActivateDefaultKeyboardLayout(dwLocale, dwLayout, hklDefault);
break;
}
iPreloadInx++;
}
//
// Refresh Preload section and close key.
//
RegFlushKey(hKeyPreload);
RegCloseKey(hKeyPreload);
RegCloseKey(hKeySubst);
//
// Return success.
//
return (bRet);
}
////////////////////////////////////////////////////////////////////////////
//
// SetFETipStatus
//
////////////////////////////////////////////////////////////////////////////
BOOL SetFETipStatus(
DWORD dwLayout,
BOOL bEnable)
{
HRESULT hr;
BOOL bReturn = FALSE;
BOOL bFound = FALSE;
IEnumTfLanguageProfiles *pEnum;
ITfInputProcessorProfiles *pProfiles = NULL;
//
// load Assembly list
//
hr = CoCreateInstance(&CLSID_TF_InputProcessorProfiles,
NULL,
CLSCTX_INPROC_SERVER,
&IID_ITfInputProcessorProfiles,
(LPVOID *) &pProfiles);
if (FAILED(hr))
return bReturn;
//
// Enum all available languages
//
if (SUCCEEDED(pProfiles->lpVtbl->EnumLanguageProfiles(pProfiles, 0, &pEnum)))
{
TF_LANGUAGEPROFILE tflp;
while (pEnum->lpVtbl->Next(pEnum, 1, &tflp, NULL) == S_OK)
{
HKL hklSub;
if (!IsEqualGUID(&tflp.catid, &GUID_TFCAT_TIP_KEYBOARD))
{
continue;
}
hklSub = GetSubstituteHKL(&tflp.clsid,
tflp.langid,
&tflp.guidProfile);
if (hklSub == IntToPtr(dwLayout))
{
hr = pProfiles->lpVtbl->EnableLanguageProfile(
pProfiles,
&tflp.clsid,
tflp.langid,
&tflp.guidProfile,
bEnable);
if (FAILED(hr))
goto Exit;
bFound = TRUE;
}
}
if (bFound)
bReturn = TRUE;
Exit:
pEnum->lpVtbl->Release(pEnum);
}
if (pProfiles)
pProfiles->lpVtbl->Release(pProfiles);
return bReturn;
}
////////////////////////////////////////////////////////////////////////////
//
// InstallInputLayout
//
////////////////////////////////////////////////////////////////////////////
BOOL InstallInputLayout(
LCID lcid,
DWORD dwLayout,
BOOL bDefLayout,
HKL hklDefault,
BOOL bDefUser,
BOOL bSysLocale)
{
LONG rc;
LCID SysLocale;
HKEY hKeySubst;
HKEY hKeyPreload;
BOOL bRet = FALSE;
BOOL bThai = FALSE;
BOOL bHasIME = FALSE;
DWORD dwPreloadNum = 0;
TCHAR szValue[MAX_PATH];
TCHAR szData[MAX_PATH];
TCHAR szData2[MAX_PATH];
LPLAYOUTLIST pLayoutList = NULL;
DWORD dwIndex, cchValue, cbData, cbData2;
DWORD dwValue, dwData, dwData2, dwCtr, dwCtr2;
DWORD dwNum = 1; // Only support 1 layout installing
HKL hklNew = 0;
//
// Create the array to store the list of input locales.
//
pLayoutList = (LPLAYOUTLIST)LocalAlloc(LPTR, sizeof(LAYOUTLIST) * dwNum + 1);
if (pLayoutList == NULL)
{
goto Exit;
}
//
// Currently support only one install layout list
//
pLayoutList[0].dwLocale = lcid;
pLayoutList[0].dwLayout = dwLayout;
if ((HIWORD(pLayoutList[0].dwLayout) & 0xf000) == 0xe000)
{
pLayoutList[0].bIME = TRUE;
}
//
// Open the HKCU\Keyboard Layout\Preload key.
//
if (!bDefUser)
{
if (RegOpenKeyEx( HKEY_CURRENT_USER,
c_szKbdPreloadKey,
0,
KEY_ALL_ACCESS,
&hKeyPreload ) != ERROR_SUCCESS)
{
goto Exit;
}
}
else
{
if (RegOpenKeyEx( HKEY_USERS,
c_szKbdPreloadKey_DefUser,
0,
KEY_ALL_ACCESS,
&hKeyPreload ) != ERROR_SUCCESS)
{
goto Exit;
}
}
//
// Open the HKCU\Keyboard Layout\Substitutes key.
//
if (!bDefUser)
{
if (RegOpenKeyEx( HKEY_CURRENT_USER,
c_szKbdSubstKey,
0,
KEY_ALL_ACCESS,
&hKeySubst ) != ERROR_SUCCESS)
{
RegCloseKey(hKeyPreload);
goto Exit;
}
}
else
{
if (RegOpenKeyEx( HKEY_USERS,
c_szKbdSubstKey_DefUser,
0,
KEY_ALL_ACCESS,
&hKeySubst ) != ERROR_SUCCESS)
{
RegCloseKey(hKeyPreload);
goto Exit;
}
}
//
// Enumerate the values in the Preload key.
//
dwIndex = 0;
cchValue = sizeof(szValue) / sizeof(TCHAR);
cbData = sizeof(szData);
rc = RegEnumValue( hKeyPreload,
dwIndex,
szValue,
&cchValue,
NULL,
NULL,
(LPBYTE)szData,
&cbData );
while (rc == ERROR_SUCCESS)
{
//
// Save the preload number if it's higher than the highest one
// found so far.
//
dwValue = TransNum(szValue);
if (dwValue > dwPreloadNum)
{
dwPreloadNum = dwValue;
}
//
// Save the preload data - input locale.
//
dwValue = TransNum(szData);
if (PRIMARYLANGID(LOWORD(dwValue)) == LANG_THAI)
{
bThai = TRUE;
}
//
// See if there is a substitute value.
//
dwData = 0;
cbData2 = sizeof(szData2);
if (RegQueryValueEx( hKeySubst,
szData,
NULL,
NULL,
(LPBYTE)szData2,
&cbData2 ) == ERROR_SUCCESS)
{
dwData = TransNum(szData2);
}
//
// Go through each of the requested input locales and make sure
// they don't already exist.
//
for (dwCtr = 0; dwCtr < dwNum; dwCtr++)
{
if (LOWORD(pLayoutList[dwCtr].dwLocale) == LOWORD(dwValue))
{
if (dwData)
{
if (pLayoutList[dwCtr].dwLayout == dwData)
{
pLayoutList[dwCtr].bLoaded = TRUE;
}
}
else if (pLayoutList[dwCtr].dwLayout == dwValue)
{
pLayoutList[dwCtr].bLoaded = TRUE;
}
//
// Save the highest 0xd000 value for this input locale.
//
if (pLayoutList[dwCtr].bIME == FALSE)
{
dwData2 = (DWORD)(HIWORD(dwValue));
if (((dwData2 & 0xf000) != 0xe000) &&
(pLayoutList[dwCtr].dwSubst <= dwData2))
{
if (dwData2 == 0)
{
pLayoutList[dwCtr].dwSubst = 0xd000;
}
else if ((dwData2 & 0xf000) == 0xd000)
{
pLayoutList[dwCtr].dwSubst = dwData2 + 1;
}
}
}
}
}
//
// Get the next enum value.
//
dwIndex++;
cchValue = sizeof(szValue) / sizeof(TCHAR);
szValue[0] = TEXT('\0');
cbData = sizeof(szData);
szData[0] = TEXT('\0');
rc = RegEnumValue( hKeyPreload,
dwIndex,
szValue,
&cchValue,
NULL,
NULL,
(LPBYTE)szData,
&cbData );
}
//
// Increase the maximum preload value by one so that it represents the
// next available value to use.
//
dwPreloadNum++;
//
// Go through the list of layouts and add them.
//
for (dwCtr = 0; dwCtr < dwNum; dwCtr++)
{
if ((pLayoutList[dwCtr].bLoaded == FALSE) &&
(IsValidLocale(pLayoutList[dwCtr].dwLocale, LCID_INSTALLED)) &&
(IsValidLayout(pLayoutList[dwCtr].dwLayout)))
{
//
// Save the preload number as a string so that it can be
// written into the registry.
//
StringCchPrintf(szValue, ARRAYSIZE(szValue), TEXT("%d"), dwPreloadNum);
if (PRIMARYLANGID(LOWORD(pLayoutList[dwCtr].dwLocale)) == LANG_THAI)
{
bThai = TRUE;
}
//
// Save the locale id as a string so that it can be written
// into the registry.
//
if (pLayoutList[dwCtr].bIME == TRUE)
{
StringCchPrintf(szData, ARRAYSIZE(szData), TEXT("%08x"), pLayoutList[dwCtr].dwLayout);
bHasIME = TRUE;
}
else
{
//
// Get the 0xd000 value, if necessary.
//
if (dwCtr != 0)
{
dwCtr2 = dwCtr;
do
{
dwCtr2--;
if ((pLayoutList[dwCtr2].bLoaded == FALSE) &&
(pLayoutList[dwCtr].dwLocale ==
pLayoutList[dwCtr2].dwLocale) &&
(pLayoutList[dwCtr2].bIME == FALSE))
{
dwData2 = pLayoutList[dwCtr2].dwSubst;
if (dwData2 == 0)
{
pLayoutList[dwCtr].dwSubst = 0xd000;
}
else
{
pLayoutList[dwCtr].dwSubst = dwData2 + 1;
}
break;
}
} while (dwCtr2 != 0);
}
//
// Save the locale id as a string.
//
dwData2 = pLayoutList[dwCtr].dwLocale;
dwData2 |= (DWORD)(pLayoutList[dwCtr].dwSubst << 16);
StringCchPrintf(szData, ARRAYSIZE(szData), TEXT("%08x"), dwData2);
}
//
// Set the value in the Preload section of the registry.
//
RegSetValueEx( hKeyPreload,
szValue,
0,
REG_SZ,
(LPBYTE)szData,
(DWORD)(lstrlen(szData) + 1) * sizeof(TCHAR) );
//
// Increment the preload value.
//
dwPreloadNum++;
//
// See if we need to add a substitute for this input locale.
//
if (((pLayoutList[dwCtr].dwLocale != pLayoutList[dwCtr].dwLayout) ||
(pLayoutList[dwCtr].dwSubst != 0)) &&
(pLayoutList[dwCtr].bIME == FALSE))
{
StringCchPrintf(szData2, ARRAYSIZE(szData2), TEXT("%08x"), pLayoutList[dwCtr].dwLayout);
RegSetValueEx( hKeySubst,
szData,
0,
REG_SZ,
(LPBYTE)szData2,
(DWORD)(lstrlen(szData) + 1) * sizeof(TCHAR) );
}
//
// Make sure all of the changes are written to disk.
//
RegFlushKey(hKeySubst);
RegFlushKey(hKeyPreload);
//
// Load the keyboard layout.
// If it fails, there isn't much we can do at this point.
//
hklNew = LoadKeyboardLayout(szData, KLF_SUBSTITUTE_OK | KLF_NOTELLSHELL);
}
}
//
// Add FE TIPs if the current requested keyboard layout is the substitute
// keyboard layout of TIP.
//
if (((HIWORD(dwLayout) & 0xf000) == 0xe000) &&
(PRIMARYLANGID(LOWORD(dwLayout)) != LANG_CHINESE))
{
BOOL bEnable = TRUE;
SetFETipStatus(dwLayout, bEnable);
}
//
// Get default system locale
//
if (bSysLocale)
SysLocale = lcid;
else
SysLocale = GetSystemDefaultLCID();
//
// If there is an IME and there is no hotkey switch, set it to
// Ctrl+Shift. Otherwise, the user cannot switch to an IME without
// setting the value first.
//
if (bHasIME || (dwPreloadNum > 2))
{
UpdateDefaultHotkey(
SysLocale,
(PRIMARYLANGID(LANGIDFROMLCID(SysLocale)) == LANG_THAI)
&& bThai,
bDefUser);
}
//
// Update the taskbar indicator.
//
if (!IsDisableCtfmon() && dwPreloadNum > 2)
{
LoadCtfmon(TRUE, SysLocale, bDefUser);
}
//
// Close the registry keys.
//
RegCloseKey(hKeyPreload);
RegCloseKey(hKeySubst);
bRet = TRUE;
//
// Update preload section with new default keyboard layout
//
if (bDefLayout)
{
TCHAR szDefLayout[MAX_PATH];
StringCchPrintf(szDefLayout, ARRAYSIZE(szDefLayout), TEXT("%08x"), dwLayout);
hklNew = LoadKeyboardLayout(szDefLayout, KLF_SUBSTITUTE_OK |
KLF_REPLACELANG |
KLF_NOTELLSHELL);
if (hklNew)
bRet = SetSystemDefautLayout(lcid, dwLayout, hklNew, bDefUser);
}
Exit:
if (pLayoutList)
LocalFree(pLayoutList);
return bRet;
}
////////////////////////////////////////////////////////////////////////////
//
// UnInstallInputLayout
//
////////////////////////////////////////////////////////////////////////////
BOOL UnInstallInputLayout(
LCID lcid,
DWORD dwLayout,
BOOL bDefUser)
{
LCID SysLocale;
HKEY hKeySubst;
HKEY hKeyPreload;
BOOL bHasSubst;
DWORD cbData;
DWORD dwCurLayout;
UINT uMatch = 0;
UINT uPreloadNum;
UINT uPreloadInx = 1;
BOOL bRet = FALSE;
BOOL fReset = FALSE;
BOOL bRemoveAllLang = FALSE;
TCHAR szSubst[MAX_PATH];
TCHAR szPreload[MAX_PATH];
TCHAR szPreloadInx[MAX_PATH];
//
// Remove all language layouts from system
//
if (lcid && dwLayout == 0)
{
bRemoveAllLang = TRUE;
dwLayout = PRIMARYLANGID(LANGIDFROMLCID(lcid));
}
//
// Open the HKCU\Keyboard Layout\Preload key.
//
if (!bDefUser)
{
if (RegOpenKeyEx( HKEY_CURRENT_USER,
c_szKbdPreloadKey,
0,
KEY_ALL_ACCESS,
&hKeyPreload ) != ERROR_SUCCESS)
{
goto Exit;
}
}
else
{
if (RegOpenKeyEx( HKEY_USERS,
c_szKbdPreloadKey_DefUser,
0,
KEY_ALL_ACCESS,
&hKeyPreload ) != ERROR_SUCCESS)
{
goto Exit;
}
}
//
// Open the HKCU\Keyboard Layout\Substitutes key.
//
if (!bDefUser)
{
if (RegOpenKeyEx( HKEY_CURRENT_USER,
c_szKbdSubstKey,
0,
KEY_ALL_ACCESS,
&hKeySubst ) != ERROR_SUCCESS)
{
RegCloseKey(hKeyPreload);
goto Exit;
}
}
else
{
if (RegOpenKeyEx( HKEY_USERS,
c_szKbdSubstKey_DefUser,
0,
KEY_ALL_ACCESS,
&hKeySubst ) != ERROR_SUCCESS)
{
RegCloseKey(hKeyPreload);
goto Exit;
}
}
uPreloadInx = 1;
//
// See if there is a substitute value.
//
StringCchPrintf(szPreloadInx, ARRAYSIZE(szPreloadInx), TEXT("%d"), uPreloadInx);
cbData = sizeof(szPreload);
while (RegQueryValueEx(hKeyPreload,
szPreloadInx,
NULL,
NULL,
(LPBYTE)szPreload,
&cbData ) == ERROR_SUCCESS)
{
dwCurLayout = TransNum(szPreload);
//
// See if there is a substitute value.
//
bHasSubst = FALSE;
cbData = sizeof(szSubst);
if (RegQueryValueEx(hKeySubst,
szPreload,
NULL,
NULL,
(LPBYTE)szSubst,
&cbData) == ERROR_SUCCESS)
{
dwCurLayout = TransNum(szSubst);
bHasSubst = TRUE;
}
if ((dwCurLayout == dwLayout) ||
(bRemoveAllLang &&
(PRIMARYLANGID(LANGIDFROMLCID(dwCurLayout)) == dwLayout)))
{
uPreloadInx++;
StringCchPrintf(szPreloadInx, ARRAYSIZE(szPreloadInx), TEXT("%d"), uPreloadInx);
uMatch++;
fReset = TRUE;
if (bHasSubst)
{
RegDeleteValue(hKeySubst, szPreload);
}
continue;
}
if (fReset && uMatch)
{
if (uPreloadInx <= uMatch)
{
goto Exit;
}
//
// Reordering the preload keyboard layouts
//
StringCchPrintf(szPreloadInx, ARRAYSIZE(szPreloadInx), TEXT("%d"), uPreloadInx - uMatch);
StringCchPrintf(szPreload, ARRAYSIZE(szPreload), TEXT("%08x"), dwCurLayout);
RegSetValueEx(hKeyPreload,
szPreloadInx,
0,
REG_SZ,
(LPBYTE)szPreload,
(DWORD)(lstrlen(szPreload) + 1) * sizeof(TCHAR));
}
uPreloadInx++;
StringCchPrintf(szPreloadInx, ARRAYSIZE(szPreloadInx), TEXT("%d"), uPreloadInx);
}
uPreloadNum = uPreloadInx - uMatch;
while (fReset && uMatch && uPreloadInx)
{
if (uPreloadInx <= uMatch || (uPreloadInx - uMatch) <= 1)
goto Exit;
//
// Uninstall the specified keyboard layout
//
StringCchPrintf(szPreloadInx, ARRAYSIZE(szPreloadInx), TEXT("%d"), uPreloadInx - uMatch);
RegDeleteValue(hKeyPreload, szPreloadInx);
uMatch--;
}
//
// Close the registry keys.
//
RegCloseKey(hKeyPreload);
RegCloseKey(hKeySubst);
#if 0
if (hklUnload)
{
//
// Get the active keyboard layout list from the system.
//
if (!SystemParametersInfo(SPI_GETDEFAULTINPUTLANG,
0,
&hklDefault,
0 ))
{
hklDefault = GetKeyboardLayout(0);
}
if (hklUnload == hklDefault)
{
if (!SystemParametersInfo( SPI_SETDEFAULTINPUTLANG,
0,
(LPVOID)((LPDWORD)&hklNewDefault),
0 ))
{
goto Exit;
}
else
{
DWORD dwRecipients = BSM_APPLICATIONS | BSM_ALLDESKTOPS;
BroadcastSystemMessage( BSF_POSTMESSAGE,
&dwRecipients,
WM_INPUTLANGCHANGEREQUEST,
1,
(LPARAM)hklNewDefault );
}
}
UnloadKeyboardLayout(hklUnload);
}
#endif
//
// Add FE TIPs if the current requested keyboard layout is the substitute
// keyboard layout of TIP.
//
if (((HIWORD(dwLayout) & 0xf000) == 0xe000) &&
(PRIMARYLANGID(LOWORD(dwLayout)) != LANG_CHINESE))
{
BOOL bEnable = FALSE;
SetFETipStatus(dwLayout, bEnable);
}
//
// Get default system locale
//
SysLocale = GetSystemDefaultLCID();
//
// Update the taskbar indicator.
//
if (uPreloadNum <= 2)
{
LoadCtfmon(FALSE, SysLocale, bDefUser);
ClearHotKey(bDefUser);
}
bRet = TRUE;
Exit:
return bRet;
}