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
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;
|
|
}
|