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.
1641 lines
42 KiB
1641 lines
42 KiB
//
|
|
// Include Files.
|
|
//
|
|
|
|
#include "input.h"
|
|
#include <regstr.h>
|
|
#include "util.h"
|
|
#include "external.h"
|
|
#include "msctf.h"
|
|
#include "inputdlg.h"
|
|
|
|
|
|
#define CLSID_STRLEN 38
|
|
|
|
const TCHAR c_szSetupKey[] = TEXT("System\\Setup");
|
|
const TCHAR c_szSetupInProgress[] = TEXT("SystemSetupInProgress");
|
|
const TCHAR c_szLangBarSetting[] = TEXT("SOFTWARE\\Microsoft\\CTF\\LangBar");
|
|
const TCHAR c_szShowStatus[] = TEXT("ShowStatus");
|
|
const TCHAR c_szCtf[] = TEXT("SOFTWARE\\Microsoft\\CTF");
|
|
const TCHAR c_szCtfShared[] = TEXT("SOFTWARE\\Microsoft\\CTF\\SystemShared");
|
|
const TCHAR c_szDisableTim[] = TEXT("Disable Thread Input Manager");
|
|
const TCHAR c_szLangBarSetting_DefUser[] = TEXT(".DEFAULT\\SOFTWARE\\Microsoft\\CTF\\LangBar");
|
|
const TCHAR c_szLangGroup[] = TEXT("System\\CurrentControlSet\\Control\\Nls\\Language Groups");
|
|
const TCHAR c_szLangJPN[] = TEXT("7");
|
|
|
|
const TCHAR c_szLanguageProfile[] = TEXT("\\LanguageProfile");
|
|
|
|
//
|
|
// Cicero Unaware Application Support const strings.
|
|
//
|
|
const TCHAR c_szIMM[] = TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\IMM");
|
|
const TCHAR c_szLoadIMM[] = TEXT("LoadIMM");
|
|
const TCHAR c_szIMMFile[] = TEXT("IME File");
|
|
const TCHAR c_szIMMFileName[] = TEXT("msctfime.ime");
|
|
const TCHAR c_szCUAS[] = TEXT("CUAS");
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CLSIDToStringA
|
|
//
|
|
// Converts a CLSID to an mbcs string.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
static const BYTE GuidMap[] = {3, 2, 1, 0, '-', 5, 4, '-', 7, 6, '-',
|
|
8, 9, '-', 10, 11, 12, 13, 14, 15};
|
|
|
|
static const char szDigits[] = "0123456789ABCDEF";
|
|
|
|
|
|
BOOL CLSIDToStringA(REFGUID refGUID, char *pchA)
|
|
{
|
|
int i;
|
|
char *p = pchA;
|
|
|
|
const BYTE * pBytes = (const BYTE *) refGUID;
|
|
|
|
*p++ = '{';
|
|
for (i = 0; i < sizeof(GuidMap); i++)
|
|
{
|
|
if (GuidMap[i] == '-')
|
|
{
|
|
*p++ = '-';
|
|
}
|
|
else
|
|
{
|
|
*p++ = szDigits[ (pBytes[GuidMap[i]] & 0xF0) >> 4 ];
|
|
*p++ = szDigits[ (pBytes[GuidMap[i]] & 0x0F) ];
|
|
}
|
|
}
|
|
|
|
*p++ = '}';
|
|
*p = '\0';
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// TransNum
|
|
//
|
|
// Converts a number string to a dword value (in hex).
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
DWORD TransNum(
|
|
LPTSTR lpsz)
|
|
{
|
|
DWORD dw = 0L;
|
|
TCHAR c;
|
|
|
|
while (*lpsz)
|
|
{
|
|
c = *lpsz++;
|
|
|
|
if (c >= TEXT('A') && c <= TEXT('F'))
|
|
{
|
|
c -= TEXT('A') - 0xa;
|
|
}
|
|
else if (c >= TEXT('0') && c <= TEXT('9'))
|
|
{
|
|
c -= TEXT('0');
|
|
}
|
|
else if (c >= TEXT('a') && c <= TEXT('f'))
|
|
{
|
|
c -= TEXT('a') - 0xa;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
dw *= 0x10;
|
|
dw += c;
|
|
}
|
|
return (dw);
|
|
}
|
|
|
|
|
|
BOOL IsOSPlatform(DWORD dwOS)
|
|
{
|
|
BOOL bRet;
|
|
static OSVERSIONINFOA s_osvi;
|
|
static BOOL s_bVersionCached = FALSE;
|
|
|
|
if (!s_bVersionCached)
|
|
{
|
|
s_bVersionCached = TRUE;
|
|
|
|
s_osvi.dwOSVersionInfoSize = sizeof(s_osvi);
|
|
GetVersionExA(&s_osvi);
|
|
}
|
|
|
|
switch (dwOS)
|
|
{
|
|
case OS_WINDOWS:
|
|
bRet = (VER_PLATFORM_WIN32_WINDOWS == s_osvi.dwPlatformId);
|
|
break;
|
|
|
|
case OS_NT:
|
|
bRet = (VER_PLATFORM_WIN32_NT == s_osvi.dwPlatformId);
|
|
break;
|
|
|
|
case OS_WIN95:
|
|
bRet = (VER_PLATFORM_WIN32_WINDOWS == s_osvi.dwPlatformId &&
|
|
s_osvi.dwMajorVersion >= 4);
|
|
break;
|
|
|
|
case OS_NT4:
|
|
bRet = (VER_PLATFORM_WIN32_NT == s_osvi.dwPlatformId &&
|
|
(s_osvi.dwMajorVersion >= 4 && s_osvi.dwMajorVersion < 5));
|
|
break;
|
|
|
|
case OS_NT5:
|
|
bRet = (VER_PLATFORM_WIN32_NT == s_osvi.dwPlatformId &&
|
|
s_osvi.dwMajorVersion >= 5);
|
|
break;
|
|
|
|
case OS_NT51:
|
|
bRet = (VER_PLATFORM_WIN32_NT == s_osvi.dwPlatformId &&
|
|
s_osvi.dwMajorVersion >= 5 && s_osvi.dwMinorVersion >= 0x00000001);
|
|
break;
|
|
|
|
default:
|
|
bRet = FALSE;
|
|
break;
|
|
}
|
|
|
|
return bRet;
|
|
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// MirrorBitmapInDC
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void MirrorBitmapInDC(
|
|
HDC hdc,
|
|
HBITMAP hbmOrig)
|
|
{
|
|
HDC hdcMem;
|
|
HBITMAP hbm;
|
|
BITMAP bm;
|
|
|
|
if (!GetObject(hbmOrig, sizeof(BITMAP), &bm))
|
|
{
|
|
return;
|
|
}
|
|
|
|
hdcMem = CreateCompatibleDC(hdc);
|
|
if (!hdcMem)
|
|
{
|
|
return;
|
|
}
|
|
|
|
hbm = CreateCompatibleBitmap(hdc, bm.bmWidth, bm.bmHeight);
|
|
if (!hbm)
|
|
{
|
|
DeleteDC(hdcMem);
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Flip the bitmap.
|
|
//
|
|
SelectObject(hdcMem, hbm);
|
|
|
|
SetLayout(hdcMem, LAYOUT_RTL);
|
|
|
|
BitBlt(hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, hdc, 0, 0, SRCCOPY);
|
|
|
|
SetLayout(hdcMem, 0);
|
|
|
|
|
|
//
|
|
// The offset by 1 is to solve the off-by-one problem.
|
|
//
|
|
BitBlt(hdc, 0, 0, bm.bmWidth, bm.bmHeight, hdcMem, 1, 0, SRCCOPY);
|
|
|
|
DeleteDC(hdcMem);
|
|
DeleteObject(hbm);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IsSetupMode
|
|
//
|
|
// Look into the registry if we are currently in setup mode.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL IsSetupMode()
|
|
{
|
|
HKEY hKey;
|
|
DWORD cb;
|
|
DWORD fSystemSetupInProgress;
|
|
|
|
//
|
|
// Open the registry key used by setup
|
|
//
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
c_szSetupKey,
|
|
0,
|
|
KEY_READ,
|
|
&hKey) != ERROR_SUCCESS)
|
|
{
|
|
return (FALSE);
|
|
}
|
|
|
|
//
|
|
// Query for the value indicating that we are in setup.
|
|
//
|
|
cb = sizeof(fSystemSetupInProgress);
|
|
if (RegQueryValueEx(hKey,
|
|
c_szSetupInProgress,
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)&fSystemSetupInProgress,
|
|
&cb) != ERROR_SUCCESS)
|
|
{
|
|
RegCloseKey(hKey);
|
|
return (FALSE);
|
|
}
|
|
|
|
//
|
|
// Clean up
|
|
//
|
|
RegCloseKey(hKey);
|
|
|
|
//
|
|
// Check the value
|
|
//
|
|
if (fSystemSetupInProgress)
|
|
{
|
|
return (TRUE);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IsAdminPrivilegeUser
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL IsAdminPrivilegeUser()
|
|
{
|
|
BOOL bAdmin = FALSE;
|
|
BOOL bResult = FALSE;
|
|
BOOL fSIDCreated = FALSE;
|
|
HANDLE hToken = NULL;
|
|
PSID AdminSid;
|
|
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
|
|
|
|
fSIDCreated = AllocateAndInitializeSid(&NtAuthority,
|
|
2,
|
|
SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_ADMINS,
|
|
0, 0, 0, 0, 0, 0,
|
|
&AdminSid);
|
|
|
|
if (!fSIDCreated)
|
|
return FALSE;
|
|
|
|
bResult = OpenProcessToken(GetCurrentProcess(),
|
|
TOKEN_QUERY,
|
|
&hToken );
|
|
|
|
if (bResult)
|
|
{
|
|
DWORD dwSize = 0;
|
|
TOKEN_GROUPS *pTokenGrpInfo;
|
|
|
|
GetTokenInformation(hToken,
|
|
TokenGroups,
|
|
NULL,
|
|
dwSize,
|
|
&dwSize);
|
|
|
|
if (dwSize)
|
|
pTokenGrpInfo = (PTOKEN_GROUPS) LocalAlloc(LPTR, dwSize);
|
|
else
|
|
pTokenGrpInfo = NULL;
|
|
|
|
if (pTokenGrpInfo && GetTokenInformation(hToken,
|
|
TokenGroups,
|
|
pTokenGrpInfo,
|
|
dwSize,
|
|
&dwSize))
|
|
{
|
|
UINT i;
|
|
|
|
for (i = 0; i < pTokenGrpInfo->GroupCount; i++)
|
|
{
|
|
if (EqualSid(pTokenGrpInfo->Groups[i].Sid, AdminSid) &&
|
|
(pTokenGrpInfo->Groups[i].Attributes & SE_GROUP_ENABLED))
|
|
{
|
|
bAdmin = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pTokenGrpInfo)
|
|
LocalFree(pTokenGrpInfo);
|
|
}
|
|
|
|
if (hToken)
|
|
CloseHandle(hToken);
|
|
|
|
if (AdminSid)
|
|
FreeSid(AdminSid);
|
|
|
|
return bAdmin;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IsInteractiveUserLogon
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL IsInteractiveUserLogon()
|
|
{
|
|
PSID InteractiveSid;
|
|
BOOL bCheckSucceeded;
|
|
BOOL bAmInteractive = FALSE;
|
|
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
|
|
|
|
if (!AllocateAndInitializeSid(&NtAuthority,
|
|
1,
|
|
SECURITY_INTERACTIVE_RID,
|
|
0, 0, 0, 0, 0, 0, 0,
|
|
&InteractiveSid))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// This checking is for logged on user or not. So we can blcok running
|
|
// ctfmon.exe process from non-authorized user.
|
|
//
|
|
bCheckSucceeded = CheckTokenMembership(NULL,
|
|
InteractiveSid,
|
|
&bAmInteractive);
|
|
|
|
if (InteractiveSid)
|
|
FreeSid(InteractiveSid);
|
|
|
|
return (bCheckSucceeded && bAmInteractive);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IsValidLayout
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL IsValidLayout(
|
|
DWORD dwLayout)
|
|
{
|
|
HKEY hKey1, hKey2;
|
|
TCHAR szLayout[MAX_PATH];
|
|
|
|
//
|
|
// Get the layout id as a string.
|
|
//
|
|
StringCchPrintf(szLayout, ARRAYSIZE(szLayout), TEXT("%08x"), dwLayout);
|
|
|
|
//
|
|
// Open the Keyboard Layouts key.
|
|
//
|
|
if (RegOpenKey(HKEY_LOCAL_MACHINE, c_szLayoutPath, &hKey1) != ERROR_SUCCESS)
|
|
{
|
|
return (FALSE);
|
|
}
|
|
|
|
//
|
|
// Try to open the layout id key under the Keyboard Layouts key.
|
|
//
|
|
if (RegOpenKey(hKey1, szLayout, &hKey2) != ERROR_SUCCESS)
|
|
{
|
|
RegCloseKey(hKey1);
|
|
return (FALSE);
|
|
}
|
|
|
|
//
|
|
// Close the keys.
|
|
//
|
|
RegCloseKey(hKey1);
|
|
RegCloseKey(hKey2);
|
|
|
|
//
|
|
// Return success.
|
|
//
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// SetLangBarOption
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void SetLangBarOption(
|
|
DWORD dwShowStatus,
|
|
BOOL bDefUser)
|
|
{
|
|
DWORD cb;
|
|
HKEY hkeyLangBar;
|
|
|
|
if (bDefUser)
|
|
{
|
|
if (RegCreateKey(HKEY_USERS,
|
|
c_szLangBarSetting_DefUser,
|
|
&hkeyLangBar) != ERROR_SUCCESS)
|
|
{
|
|
hkeyLangBar = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (RegCreateKey(HKEY_CURRENT_USER,
|
|
c_szLangBarSetting,
|
|
&hkeyLangBar) != ERROR_SUCCESS)
|
|
{
|
|
hkeyLangBar = NULL;
|
|
}
|
|
}
|
|
|
|
if (hkeyLangBar)
|
|
{
|
|
cb = sizeof(DWORD);
|
|
|
|
RegSetValueEx(hkeyLangBar,
|
|
c_szShowStatus,
|
|
0,
|
|
REG_DWORD,
|
|
(LPBYTE)&dwShowStatus,
|
|
sizeof(DWORD) );
|
|
|
|
RegCloseKey(hkeyLangBar);
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// GetLangBarOption
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL GetLangBarOption(
|
|
DWORD *dwShowStatus,
|
|
BOOL bDefUser)
|
|
{
|
|
DWORD cb;
|
|
HKEY hkeyLangBar;
|
|
BOOL bRet = FALSE;
|
|
|
|
if (bDefUser)
|
|
{
|
|
if (RegCreateKey(HKEY_USERS,
|
|
c_szLangBarSetting_DefUser,
|
|
&hkeyLangBar) != ERROR_SUCCESS)
|
|
{
|
|
hkeyLangBar = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (RegCreateKey(HKEY_CURRENT_USER,
|
|
c_szLangBarSetting,
|
|
&hkeyLangBar) != ERROR_SUCCESS)
|
|
{
|
|
hkeyLangBar = NULL;
|
|
}
|
|
}
|
|
|
|
if (hkeyLangBar)
|
|
{
|
|
cb = sizeof(DWORD);
|
|
|
|
if (RegQueryValueEx(hkeyLangBar,
|
|
c_szShowStatus,
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)&dwShowStatus,
|
|
&cb) == ERROR_SUCCESS)
|
|
{
|
|
bRet = TRUE;
|
|
}
|
|
|
|
RegCloseKey(hkeyLangBar);
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CheckInternatModule
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void CheckInternatModule()
|
|
{
|
|
DWORD cb;
|
|
HKEY hkeyRun;
|
|
TCHAR szInternatName[MAX_PATH];
|
|
|
|
if (RegOpenKey(HKEY_CURRENT_USER,
|
|
REGSTR_PATH_RUN,
|
|
&hkeyRun) == ERROR_SUCCESS)
|
|
{
|
|
cb = sizeof(szInternatName);
|
|
|
|
if (RegQueryValueEx(hkeyRun,
|
|
c_szInternat,
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)szInternatName,
|
|
&cb) == ERROR_SUCCESS)
|
|
{
|
|
LCID SysLocale;
|
|
BOOL bMinLangBar = TRUE;
|
|
TCHAR szCTFMonPath[MAX_PATH];
|
|
|
|
SysLocale = GetSystemDefaultLCID();
|
|
|
|
if ((SysLocale == 0x0404) || (SysLocale == 0x0411) ||
|
|
(SysLocale == 0x0412) || (SysLocale == 0x0804))
|
|
{
|
|
//
|
|
// Show language bar in case of FE system as a default
|
|
//
|
|
bMinLangBar = FALSE;
|
|
}
|
|
|
|
if (bMinLangBar)
|
|
{
|
|
if (IsOSPlatform(OS_NT51))
|
|
{
|
|
SetLangBarOption(REG_LANGBAR_DESKBAND, FALSE);
|
|
|
|
//
|
|
// Update language band menu item to Taskbar
|
|
//
|
|
SetLanguageBandMenu(TRUE);
|
|
}
|
|
else
|
|
{
|
|
SetLangBarOption(REG_LANGBAR_MINIMIZED, FALSE);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Get Ctfmon full path string
|
|
//
|
|
if (GetCtfmonPath((LPTSTR) szCTFMonPath, ARRAYSIZE(szCTFMonPath)))
|
|
{
|
|
//
|
|
// Set "ctfmon.exe" instead of "internat.exe" module.
|
|
//
|
|
RegSetValueEx(hkeyRun,
|
|
c_szCTFMon,
|
|
0,
|
|
REG_SZ,
|
|
(LPBYTE)szCTFMonPath,
|
|
(lstrlen(szCTFMonPath) + 1) * sizeof(TCHAR));
|
|
}
|
|
}
|
|
|
|
RegCloseKey(hkeyRun);
|
|
}
|
|
}
|
|
|
|
|
|
#define MAX_REGKEY 10
|
|
|
|
DWORD
|
|
OpenUserKeyForWin9xUpgrade(
|
|
LPCTSTR pszUserKey,
|
|
HKEY *phKey
|
|
)
|
|
{
|
|
DWORD dwResult = ERROR_INVALID_PARAMETER;
|
|
|
|
if (NULL != pszUserKey && NULL != phKey)
|
|
{
|
|
typedef struct {
|
|
LPTSTR pszRoot;
|
|
HKEY hKeyRoot;
|
|
|
|
} REGISTRY_ROOTS, *PREGISTRY_ROOTS;
|
|
|
|
static REGISTRY_ROOTS rgRoots[] = {
|
|
{ TEXT("HKLM"), HKEY_LOCAL_MACHINE },
|
|
{ TEXT("HKEY_LOCAL_MACHINE"), HKEY_LOCAL_MACHINE },
|
|
{ TEXT("HKCC"), HKEY_CURRENT_CONFIG },
|
|
{ TEXT("HKEY_CURRENT_CONFIG"), HKEY_CURRENT_CONFIG },
|
|
{ TEXT("HKU"), HKEY_USERS },
|
|
{ TEXT("HKEY_USERS"), HKEY_USERS },
|
|
{ TEXT("HKCU"), HKEY_CURRENT_USER },
|
|
{ TEXT("HKEY_CURRENT_USER"), HKEY_CURRENT_USER },
|
|
{ TEXT("HKCR"), HKEY_CLASSES_ROOT },
|
|
{ TEXT("HKEY_CLASSES_ROOT"), HKEY_CLASSES_ROOT }
|
|
};
|
|
|
|
TCHAR szUserKey[MAX_PATH]; // For a local copy.
|
|
LPTSTR pszSubKey = szUserKey;
|
|
|
|
//
|
|
// Make a local copy that we can modify.
|
|
//
|
|
StringCchCopy(szUserKey, ARRAYSIZE(szUserKey), pszUserKey);
|
|
|
|
*phKey = NULL;
|
|
//
|
|
// Find the backslash.
|
|
//
|
|
while(*pszSubKey && TEXT('\\') != *pszSubKey)
|
|
pszSubKey++;
|
|
|
|
if (TEXT('\\') == *pszSubKey)
|
|
{
|
|
HKEY hkeyRoot = NULL;
|
|
int i;
|
|
//
|
|
// Replace backslash with nul to separate the root key and
|
|
// sub key strings in our local copy of the original argument
|
|
// string.
|
|
//
|
|
*pszSubKey++ = TEXT('\0');
|
|
//
|
|
// Now find the true root key in rgRoots[].
|
|
//
|
|
for (i = 0; i < MAX_REGKEY; i++)
|
|
{
|
|
if (0 == lstrcmpi(rgRoots[i].pszRoot, szUserKey))
|
|
{
|
|
hkeyRoot = rgRoots[i].hKeyRoot;
|
|
break;
|
|
}
|
|
}
|
|
if (NULL != hkeyRoot)
|
|
{
|
|
//
|
|
// Open the key.
|
|
//
|
|
dwResult = RegOpenKeyEx(hkeyRoot,
|
|
pszSubKey,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
phKey);
|
|
}
|
|
}
|
|
}
|
|
return dwResult;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// MigrateCtfmonFromWin9x
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
DWORD MigrateCtfmonFromWin9x(LPCTSTR pszUserKey)
|
|
{
|
|
DWORD cb;
|
|
LCID SysLocale;
|
|
HKEY hkeyRun = NULL;
|
|
HKEY hkeyUser = NULL;
|
|
HKEY hkeyPreload = NULL;
|
|
BOOL bAddCtfmon = FALSE;
|
|
TCHAR szInternatName[MAX_PATH];
|
|
DWORD dwResult = ERROR_INVALID_PARAMETER;
|
|
|
|
if (lstrlen(pszUserKey) >= MAX_PATH)
|
|
return 0;
|
|
|
|
SysLocale = GetSystemDefaultLCID();
|
|
|
|
if ((SysLocale == 0x0404) || (SysLocale == 0x0411) ||
|
|
(SysLocale == 0x0412) || (SysLocale == 0x0804))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
dwResult = OpenUserKeyForWin9xUpgrade(pszUserKey, &hkeyUser);
|
|
|
|
if (ERROR_SUCCESS != dwResult || hkeyUser == NULL)
|
|
{
|
|
return dwResult;
|
|
}
|
|
|
|
//
|
|
// Now read all of preload hkl from the registry.
|
|
//
|
|
if (RegOpenKeyEx(hkeyUser,
|
|
c_szKbdPreloadKey,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
&hkeyPreload) == ERROR_SUCCESS)
|
|
{
|
|
DWORD dwIndex;
|
|
DWORD cchValue, cbData;
|
|
TCHAR szValue[MAX_PATH]; // language id (number)
|
|
TCHAR szData[MAX_PATH]; // language name
|
|
|
|
dwIndex = 0;
|
|
cchValue = sizeof(szValue) / sizeof(TCHAR);
|
|
cbData = sizeof(szData);
|
|
|
|
dwResult = RegEnumValue(hkeyPreload,
|
|
dwIndex,
|
|
szValue,
|
|
&cchValue,
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)szData,
|
|
&cbData );
|
|
|
|
if (dwResult != ERROR_SUCCESS)
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
do
|
|
{
|
|
dwIndex++;
|
|
|
|
if (dwIndex >= 2)
|
|
{
|
|
bAddCtfmon = TRUE;
|
|
break;
|
|
}
|
|
cchValue = sizeof(szValue) / sizeof(TCHAR);
|
|
szValue[0] = TEXT('\0');
|
|
cbData = sizeof(szData);
|
|
szData[0] = TEXT('\0');
|
|
|
|
dwResult = RegEnumValue(hkeyPreload,
|
|
dwIndex,
|
|
szValue,
|
|
&cchValue,
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)szData,
|
|
&cbData );
|
|
|
|
} while (dwResult == ERROR_SUCCESS);
|
|
}
|
|
|
|
if (!bAddCtfmon)
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
if (RegOpenKeyEx(hkeyUser,
|
|
REGSTR_PATH_RUN,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
&hkeyRun) == ERROR_SUCCESS)
|
|
{
|
|
HKEY hkeyLangBar;
|
|
TCHAR szCTFMonPath[MAX_PATH];
|
|
|
|
if (RegCreateKey(hkeyUser,
|
|
c_szLangBarSetting,
|
|
&hkeyLangBar) == ERROR_SUCCESS)
|
|
{
|
|
DWORD dwShowStatus = REG_LANGBAR_DESKBAND;
|
|
cb = sizeof(DWORD);
|
|
|
|
RegSetValueEx(hkeyLangBar,
|
|
c_szShowStatus,
|
|
0,
|
|
REG_DWORD,
|
|
(LPBYTE)&dwShowStatus,
|
|
sizeof(DWORD) );
|
|
|
|
RegCloseKey(hkeyLangBar);
|
|
}
|
|
|
|
//
|
|
// Get Ctfmon full path string
|
|
//
|
|
if (GetCtfmonPath((LPTSTR) szCTFMonPath, ARRAYSIZE(szCTFMonPath)))
|
|
{
|
|
//
|
|
// Set "ctfmon.exe" instead of "internat.exe" module.
|
|
//
|
|
dwResult = RegSetValueEx(hkeyRun,
|
|
c_szCTFMon,
|
|
0,
|
|
REG_SZ,
|
|
(LPBYTE)szCTFMonPath,
|
|
(lstrlen(szCTFMonPath) + 1) * sizeof(TCHAR));
|
|
}
|
|
|
|
//
|
|
// Clean up the registry for internat.
|
|
//
|
|
RegDeleteValue(hkeyRun, c_szInternat);
|
|
}
|
|
|
|
Exit:
|
|
if (hkeyPreload)
|
|
RegCloseKey(hkeyPreload);
|
|
|
|
if (hkeyRun)
|
|
RegCloseKey(hkeyRun);
|
|
|
|
if (hkeyUser)
|
|
RegCloseKey(hkeyUser);
|
|
|
|
return dwResult;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IsDisableCtfmon
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL IsDisableCtfmon()
|
|
{
|
|
DWORD cb;
|
|
HKEY hkeyLangBar;
|
|
BOOL bRet = FALSE;
|
|
DWORD dwDisableCtfmon = 0;
|
|
|
|
|
|
if (RegOpenKey(HKEY_CURRENT_USER, c_szCtf, &hkeyLangBar) == ERROR_SUCCESS)
|
|
{
|
|
cb = sizeof(DWORD);
|
|
|
|
RegQueryValueEx(hkeyLangBar,
|
|
c_szDisableTim,
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)&dwDisableCtfmon,
|
|
&cb);
|
|
|
|
if (dwDisableCtfmon)
|
|
bRet = TRUE;
|
|
|
|
RegCloseKey(hkeyLangBar);
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// SetDisableCtfmon
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void SetDisalbeCtfmon(
|
|
DWORD dwDisableCtfmon)
|
|
{
|
|
DWORD cb;
|
|
HKEY hkeyLangBar;
|
|
|
|
if (RegCreateKey(HKEY_CURRENT_USER, c_szCtf, &hkeyLangBar) == ERROR_SUCCESS)
|
|
{
|
|
cb = sizeof(DWORD);
|
|
|
|
RegSetValueEx(hkeyLangBar,
|
|
c_szDisableTim,
|
|
0,
|
|
REG_DWORD,
|
|
(LPBYTE)&dwDisableCtfmon,
|
|
cb);
|
|
|
|
RegCloseKey(hkeyLangBar);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IsDisableCUAS
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL IsDisableCUAS()
|
|
{
|
|
DWORD cb;
|
|
HKEY hkeyCTF;
|
|
BOOL bRet = TRUE;
|
|
DWORD dwEnableCUAS = 0;
|
|
|
|
if (RegOpenKey(HKEY_LOCAL_MACHINE, c_szCtfShared, &hkeyCTF) == ERROR_SUCCESS)
|
|
{
|
|
cb = sizeof(DWORD);
|
|
|
|
RegQueryValueEx(hkeyCTF,
|
|
c_szCUAS,
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)&dwEnableCUAS,
|
|
&cb);
|
|
|
|
if (dwEnableCUAS)
|
|
bRet = FALSE;
|
|
|
|
RegCloseKey(hkeyCTF);
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// SetDisableCUAS
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void SetDisableCUAS(
|
|
BOOL bDisableCUAS)
|
|
{
|
|
HKEY hkeyIMM;
|
|
HKEY hkeyCTF;
|
|
DWORD cb = sizeof(DWORD);
|
|
DWORD dwIMM32, dwCUAS;
|
|
|
|
if (bDisableCUAS)
|
|
dwIMM32 = dwCUAS = 0;
|
|
else
|
|
dwIMM32 = dwCUAS = 1;
|
|
|
|
if (RegCreateKey(HKEY_LOCAL_MACHINE, c_szIMM, &hkeyIMM) != ERROR_SUCCESS)
|
|
{
|
|
hkeyIMM = NULL;
|
|
}
|
|
|
|
if (RegCreateKey(HKEY_LOCAL_MACHINE, c_szCtfShared, &hkeyCTF) != ERROR_SUCCESS)
|
|
{
|
|
hkeyCTF = NULL;
|
|
}
|
|
|
|
if (!bDisableCUAS)
|
|
{
|
|
//
|
|
// Turn on LoadIMM and CUAS flags
|
|
//
|
|
|
|
if (hkeyIMM)
|
|
{
|
|
RegSetValueEx(hkeyIMM,
|
|
c_szIMMFile,
|
|
0,
|
|
REG_SZ,
|
|
(LPBYTE)c_szIMMFileName,
|
|
(lstrlen(c_szIMMFileName) + 1) * sizeof(TCHAR));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Turn off LoadIMM and CUAS flags
|
|
//
|
|
|
|
BOOL bEALang = IsInstalledEALangPack();
|
|
|
|
if (bEALang)
|
|
{
|
|
dwIMM32 = 1;
|
|
}
|
|
}
|
|
|
|
if (hkeyIMM)
|
|
{
|
|
RegSetValueEx(hkeyIMM,
|
|
c_szLoadIMM,
|
|
0,
|
|
REG_DWORD,
|
|
(LPBYTE)&dwIMM32,
|
|
cb);
|
|
}
|
|
|
|
if (hkeyCTF)
|
|
{
|
|
RegSetValueEx(hkeyCTF,
|
|
c_szCUAS,
|
|
0,
|
|
REG_DWORD,
|
|
(LPBYTE)&dwCUAS,
|
|
cb);
|
|
}
|
|
|
|
if (hkeyIMM)
|
|
RegCloseKey(hkeyIMM);
|
|
|
|
if (hkeyCTF)
|
|
RegCloseKey(hkeyCTF);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// SetDisableCtfmon
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL SetLanguageBandMenu(
|
|
BOOL bLoad)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
HINSTANCE hMsutb = NULL;
|
|
FARPROC pfnSetRegisterLangBand = NULL;
|
|
|
|
//
|
|
// Load MSUTB.DLL to register deskband menu item to TaskBar.
|
|
//
|
|
hMsutb = LoadSystemLibrary(TEXT("msutb.dll"));
|
|
if (hMsutb)
|
|
{
|
|
//
|
|
// Get SetRegisterLangBand()
|
|
//
|
|
pfnSetRegisterLangBand = GetProcAddress(hMsutb,
|
|
(LPVOID)8);
|
|
}
|
|
else
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
//
|
|
// Call DllRegisterServer/DllUnregisterServer()
|
|
//
|
|
if (pfnSetRegisterLangBand)
|
|
{
|
|
pfnSetRegisterLangBand(bLoad);
|
|
bRet = TRUE;
|
|
}
|
|
|
|
if (hMsutb)
|
|
{
|
|
FreeLibrary(hMsutb);
|
|
}
|
|
|
|
Exit:
|
|
return bRet;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// RunCtfmonProcess
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL RunCtfmonProcess()
|
|
{
|
|
TCHAR szCtfmonPath[MAX_PATH + 1];
|
|
|
|
if (GetCtfmonPath(szCtfmonPath, ARRAYSIZE(szCtfmonPath)))
|
|
{
|
|
PROCESS_INFORMATION pi;
|
|
STARTUPINFO si = {0};
|
|
|
|
si.cb = sizeof(STARTUPINFO);
|
|
si.dwFlags = STARTF_USESHOWWINDOW;
|
|
si.wShowWindow = (WORD) SW_SHOWMINNOACTIVE;
|
|
|
|
if (CreateProcess(szCtfmonPath,
|
|
c_szCTFMon,
|
|
NULL,
|
|
NULL,
|
|
FALSE,
|
|
NORMAL_PRIORITY_CLASS,
|
|
NULL,
|
|
NULL,
|
|
&si,
|
|
&pi))
|
|
{
|
|
WaitForInputIdle(pi.hProcess, 2000) ;
|
|
return TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// GetCtfmonPath
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
UINT GetCtfmonPath(
|
|
LPTSTR lpCtfmonPath,
|
|
UINT uBuffLen)
|
|
{
|
|
UINT uSize = 0;
|
|
|
|
if (!lpCtfmonPath)
|
|
return uSize;
|
|
|
|
*lpCtfmonPath = TEXT('\0');
|
|
|
|
//
|
|
// Confirmed lpCtfmonPath has MAX_PATH buffer size.
|
|
//
|
|
if (uSize = GetSystemDirectory(lpCtfmonPath, uBuffLen))
|
|
{
|
|
if (*(lpCtfmonPath + uSize - 1) != TEXT('\\'))
|
|
{
|
|
*(lpCtfmonPath + uSize) = TEXT('\\');
|
|
uSize++;
|
|
}
|
|
|
|
if (uBuffLen - uSize > (UINT) lstrlen(c_szCTFMon))
|
|
{
|
|
lstrcpyn(lpCtfmonPath + uSize, c_szCTFMon, uBuffLen - uSize);
|
|
uSize += lstrlen(c_szCTFMon);
|
|
}
|
|
else
|
|
{
|
|
*(lpCtfmonPath) = TEXT('\0');
|
|
uSize = 0;
|
|
}
|
|
}
|
|
|
|
return uSize;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IsInstalledEALangPack
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL IsInstalledEALangPack()
|
|
{
|
|
BOOL bRet = FALSE;
|
|
HKEY hkeyLangGroup;
|
|
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
c_szLangGroup,
|
|
0,
|
|
KEY_READ,
|
|
&hkeyLangGroup) == ERROR_SUCCESS)
|
|
{
|
|
DWORD cb;
|
|
TCHAR szLangInstall[10];
|
|
|
|
cb = sizeof(szLangInstall);
|
|
|
|
//
|
|
// The checking of Japan Language is enough to know EA language pack
|
|
// installation.
|
|
//
|
|
if (RegQueryValueEx(hkeyLangGroup,
|
|
c_szLangJPN,
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)szLangInstall,
|
|
&cb) == ERROR_SUCCESS)
|
|
{
|
|
if (szLangInstall[0] != 0)
|
|
return TRUE;
|
|
}
|
|
|
|
RegCloseKey(hkeyLangGroup);
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IsTIPClsidEnabled
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL IsTIPClsidEnabled(
|
|
HKEY hkeyTop,
|
|
LPTSTR lpTipClsid,
|
|
BOOL *bExistEnable)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
HKEY hkeyTipLang;
|
|
HKEY hkeyTipLangid;
|
|
HKEY hkeyTipGuid;
|
|
UINT uIndex;
|
|
UINT uIndex2;
|
|
DWORD cb;
|
|
DWORD cchLangid;
|
|
DWORD cchGuid;
|
|
DWORD dwEnableTIP = 0;
|
|
LPTSTR pszGuid;
|
|
LPTSTR pszLangid;
|
|
TCHAR szTIPLangid[15];
|
|
TCHAR szTIPGuid[128];
|
|
TCHAR szTIPClsidLang[MAX_PATH];
|
|
FILETIME lwt;
|
|
UINT uLangidLen;
|
|
UINT uGuidLen;
|
|
|
|
if (lstrlen(lpTipClsid) != CLSID_STRLEN)
|
|
return bRet;
|
|
|
|
StringCchCopy(szTIPClsidLang, ARRAYSIZE(szTIPClsidLang), c_szCTFTipPath);
|
|
StringCchCat(szTIPClsidLang, ARRAYSIZE(szTIPClsidLang), lpTipClsid);
|
|
StringCchCat(szTIPClsidLang, ARRAYSIZE(szTIPClsidLang), c_szLanguageProfile);
|
|
|
|
pszLangid = szTIPClsidLang + lstrlen(szTIPClsidLang);
|
|
uLangidLen = ARRAYSIZE(szTIPClsidLang) - lstrlen(szTIPClsidLang);
|
|
|
|
if (RegOpenKeyEx(hkeyTop,
|
|
szTIPClsidLang, 0,
|
|
KEY_READ, &hkeyTipLang) != ERROR_SUCCESS)
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
for (uIndex = 0; bRet == FALSE; uIndex++)
|
|
{
|
|
cchLangid = sizeof(szTIPLangid) / sizeof(TCHAR);
|
|
|
|
if (RegEnumKeyEx(hkeyTipLang, uIndex,
|
|
szTIPLangid, &cchLangid,
|
|
NULL, NULL, NULL, &lwt) != ERROR_SUCCESS)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (cchLangid != 10)
|
|
{
|
|
// string langid subkeys should be like 0x00000409
|
|
continue;
|
|
}
|
|
|
|
if (uLangidLen > (cchLangid + 1))
|
|
{
|
|
StringCchCopy(pszLangid, uLangidLen, TEXT("\\"));
|
|
StringCchCat(pszLangid, uLangidLen, szTIPLangid);
|
|
}
|
|
|
|
if (RegOpenKeyEx(hkeyTop,
|
|
szTIPClsidLang, 0,
|
|
KEY_READ, &hkeyTipLangid) != ERROR_SUCCESS)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
pszGuid = szTIPClsidLang + lstrlen(szTIPClsidLang);
|
|
uGuidLen = ARRAYSIZE(szTIPClsidLang) - lstrlen(szTIPClsidLang);
|
|
|
|
for (uIndex2 = 0; bRet == FALSE; uIndex2++)
|
|
{
|
|
cchGuid = sizeof(szTIPGuid) / sizeof(TCHAR);
|
|
|
|
if (RegEnumKeyEx(hkeyTipLangid, uIndex2,
|
|
szTIPGuid, &cchGuid,
|
|
NULL, NULL, NULL, &lwt) != ERROR_SUCCESS)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (cchGuid != CLSID_STRLEN)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (uGuidLen > (cchGuid + 1))
|
|
{
|
|
StringCchCopy(pszGuid, uGuidLen, TEXT("\\"));
|
|
StringCchCat(szTIPClsidLang, ARRAYSIZE(szTIPClsidLang), szTIPGuid);
|
|
}
|
|
|
|
if (RegOpenKeyEx(hkeyTop,
|
|
szTIPClsidLang, 0,
|
|
KEY_READ, &hkeyTipGuid) == ERROR_SUCCESS)
|
|
{
|
|
cb = sizeof(DWORD);
|
|
|
|
if (RegQueryValueEx(hkeyTipGuid,
|
|
TEXT("Enable"),
|
|
NULL,
|
|
NULL,
|
|
(LPBYTE)&dwEnableTIP,
|
|
&cb) == ERROR_SUCCESS)
|
|
{
|
|
|
|
RegCloseKey(hkeyTipGuid);
|
|
|
|
*bExistEnable = TRUE;
|
|
|
|
if (dwEnableTIP)
|
|
{
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
else if (hkeyTop == HKEY_LOCAL_MACHINE)
|
|
{
|
|
// Default is the enabled status on HKLM
|
|
*bExistEnable = TRUE;
|
|
|
|
bRet = TRUE;
|
|
}
|
|
else
|
|
{
|
|
*bExistEnable = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
RegCloseKey(hkeyTipLangid);
|
|
}
|
|
|
|
RegCloseKey(hkeyTipLang);
|
|
|
|
Exit:
|
|
|
|
return bRet;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// IsTipInstalled
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
BOOL IsTipInstalled()
|
|
{
|
|
const CLSID CLSID_SapiLayr = {0xdcbd6fa8, 0x032f, 0x11d3, {0xb5, 0xb1, 0x00, 0xc0, 0x4f, 0xc3, 0x24, 0xa1}};
|
|
const CLSID CLSID_SoftkbdIMX = {0xf89e9e58, 0xbd2f, 0x4008, {0x9a, 0xc2, 0x0f, 0x81, 0x6c, 0x09, 0xf4, 0xee}};
|
|
|
|
static const TCHAR c_szSpeechRecognizersKey[] = TEXT("Software\\Microsoft\\Speech\\Recognizers\\Tokens");
|
|
static const TCHAR c_szCategory[] = TEXT("\\Category\\Category");
|
|
|
|
BOOL bRet = FALSE;
|
|
BOOL bExistEnable;
|
|
HKEY hkeyTip;
|
|
HKEY hkeyTipSub;
|
|
UINT uIndex;
|
|
DWORD dwSubKeys;
|
|
DWORD cchClsid;
|
|
CLSID clsidTip;
|
|
TCHAR szTipClsid[128];
|
|
TCHAR szTipClsidPath[MAX_PATH];
|
|
FILETIME lwt;
|
|
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
TEXT("Software\\Microsoft\\CTF\\TIP"),
|
|
0, KEY_READ, &hkeyTip) != ERROR_SUCCESS)
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// enum through all the TIP subkeys
|
|
for (uIndex = 0; TRUE; uIndex++)
|
|
{
|
|
bExistEnable = FALSE;
|
|
|
|
cchClsid = sizeof(szTipClsid) / sizeof(TCHAR);
|
|
|
|
if (RegEnumKeyEx(hkeyTip, uIndex,
|
|
szTipClsid, &cchClsid,
|
|
NULL, NULL, NULL, &lwt) != ERROR_SUCCESS)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (cchClsid != CLSID_STRLEN)
|
|
{
|
|
// string clsid subkeys should be like {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
|
|
continue;
|
|
}
|
|
|
|
StringCchCopy(szTipClsidPath, ARRAYSIZE(szTipClsidPath), szTipClsid);
|
|
|
|
// we want subkey\Language Profiles key
|
|
StringCchCat(szTipClsidPath, ARRAYSIZE(szTipClsidPath), c_szLanguageProfile);
|
|
|
|
// is this subkey a tip?
|
|
if (RegOpenKeyEx(hkeyTip,
|
|
szTipClsidPath, 0,
|
|
KEY_READ, &hkeyTipSub) == ERROR_SUCCESS)
|
|
{
|
|
RegCloseKey(hkeyTipSub);
|
|
|
|
// it's a tip, get the clsid
|
|
if (CLSIDFromString((LPOLESTR )szTipClsid, &clsidTip) != NOERROR)
|
|
continue;
|
|
|
|
// special case certain known tips
|
|
if (IsEqualGUID(&clsidTip, &CLSID_SapiLayr))
|
|
{
|
|
//
|
|
// This is SAPI TIP and need to handle it specially, since sptip has
|
|
// a default option as the enabled status.
|
|
//
|
|
if (!IsTIPClsidEnabled(HKEY_CURRENT_USER, szTipClsid, &bExistEnable))
|
|
{
|
|
//
|
|
// If SPTIP has enable registry setting on HKCU with the disabled
|
|
// speech tip, we assume user intentionally disable it.
|
|
//
|
|
if (bExistEnable)
|
|
continue;
|
|
}
|
|
|
|
// this is the sapi tip, which is always installed
|
|
// but it will not activate if sapi is not installed
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
c_szSpeechRecognizersKey, 0,
|
|
KEY_READ, &hkeyTipSub) != ERROR_SUCCESS)
|
|
{
|
|
continue; // this tip doesn't count
|
|
}
|
|
|
|
// need 1 or more subkeys for sapi to be truely installed...whistler has a Tokens with nothing underneath
|
|
if (RegQueryInfoKey(hkeyTipSub,
|
|
NULL, NULL, NULL, &dwSubKeys, NULL,
|
|
NULL, NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS)
|
|
{
|
|
dwSubKeys = 0; // assume no sub keys on failure
|
|
}
|
|
|
|
RegCloseKey(hkeyTipSub);
|
|
|
|
if (dwSubKeys != 0)
|
|
{
|
|
bRet = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
else if (IsEqualGUID(&clsidTip, &CLSID_SoftkbdIMX))
|
|
{
|
|
// don't count the softkbd, it is disabled until another tip
|
|
// enables it
|
|
continue;
|
|
}
|
|
else if(IsTIPClsidEnabled(HKEY_CURRENT_USER, szTipClsid, &bExistEnable))
|
|
{
|
|
bRet = TRUE;
|
|
break;
|
|
}
|
|
else if (!bExistEnable)
|
|
{
|
|
if(IsTIPClsidEnabled(HKEY_LOCAL_MACHINE, szTipClsid, &bExistEnable))
|
|
{
|
|
bRet = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
RegCloseKey(hkeyTip);
|
|
|
|
|
|
Exit:
|
|
|
|
return bRet;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// ResetImm32AndCtfImeFlag
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
void ResetImm32AndCtfIme()
|
|
{
|
|
BOOL bTipInstalled;
|
|
|
|
bTipInstalled = IsTipInstalled();
|
|
|
|
if (bTipInstalled)
|
|
{
|
|
//
|
|
// TIP is detected now, so automatically recover LoadImm
|
|
// and CUAS to "On" status
|
|
//
|
|
SetDisableCUAS(FALSE);
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// LoadSystemLibrary
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
HMODULE LoadSystemLibrary(
|
|
LPCTSTR lpModuleName)
|
|
{
|
|
UINT uRet = 0;
|
|
HINSTANCE hModule = NULL;
|
|
TCHAR szModulePath[MAX_PATH + 1];
|
|
|
|
szModulePath[0] = TEXT('\0');
|
|
|
|
uRet = GetSystemDirectory(szModulePath, ARRAYSIZE(szModulePath));
|
|
|
|
if (uRet >= ARRAYSIZE(szModulePath))
|
|
{
|
|
// we don't have a room to copy module name.
|
|
uRet = 0;
|
|
}
|
|
else if (uRet)
|
|
{
|
|
if (szModulePath[uRet - 1] != TEXT('\\'))
|
|
{
|
|
szModulePath[uRet] = TEXT('\\');
|
|
uRet++;
|
|
}
|
|
|
|
if (ARRAYSIZE(szModulePath) - uRet > (UINT) lstrlen(lpModuleName))
|
|
{
|
|
lstrcpyn(&szModulePath[uRet],
|
|
lpModuleName,
|
|
ARRAYSIZE(szModulePath) - uRet);
|
|
}
|
|
else
|
|
{
|
|
uRet = 0;
|
|
}
|
|
}
|
|
|
|
if (uRet)
|
|
{
|
|
hModule = LoadLibrary(szModulePath);
|
|
}
|
|
|
|
return hModule;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// LoadSystemLibraryEx
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
HMODULE LoadSystemLibraryEx(
|
|
LPCTSTR lpModuleName,
|
|
HANDLE hFile,
|
|
DWORD dwFlags)
|
|
{
|
|
UINT uRet = 0;
|
|
HINSTANCE hModule = NULL;
|
|
TCHAR szModulePath[MAX_PATH + 1];
|
|
|
|
szModulePath[0] = TEXT('\0');
|
|
|
|
uRet = GetSystemDirectory(szModulePath, ARRAYSIZE(szModulePath));
|
|
|
|
if (uRet >= ARRAYSIZE(szModulePath))
|
|
{
|
|
// we don't have a room to copy module name.
|
|
uRet = 0;
|
|
}
|
|
else if (uRet)
|
|
{
|
|
if (szModulePath[uRet - 1] != TEXT('\\'))
|
|
{
|
|
szModulePath[uRet] = TEXT('\\');
|
|
uRet++;
|
|
}
|
|
|
|
if (ARRAYSIZE(szModulePath) - uRet > (UINT) lstrlen(lpModuleName))
|
|
{
|
|
lstrcpyn(&szModulePath[uRet],
|
|
lpModuleName,
|
|
ARRAYSIZE(szModulePath) - uRet);
|
|
}
|
|
else
|
|
{
|
|
uRet = 0;
|
|
}
|
|
}
|
|
|
|
if (uRet)
|
|
{
|
|
hModule = LoadLibraryEx(szModulePath, hFile,dwFlags);
|
|
}
|
|
|
|
return hModule;
|
|
}
|