|
|
//
// regwatch.cpp
//
#include "private.h"
#include "regwatch.h"
#include "indicml.h"
#include "tfpriv.h"
#include "ctffunc.h"
#include "tlapi.h"
#include "immxutil.h"
extern "C" HRESULT WINAPI TF_InvalidAssemblyListCache(); extern "C" HRESULT WINAPI TF_PostAllThreadMsg(WPARAM wParam, DWORD dwFlags);
static const char c_szKbdLayout[] = "keyboard layout"; static const char c_szKbdToggleKey[] = "Keyboard Layout\\Toggle"; static const char c_szKbdPreload[] = "keyboard layout\\Preload"; static const char c_szRun[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Run"; static const char c_szSpeechKey[] = "Software\\Microsoft\\Speech"; static const char c_szCPLAppearance[] = "Control Panel\\Appearance"; static const char c_szCPLColors[] = "Control Panel\\Colors"; static const char c_szCPLMetrics[] = "Control Panel\\Desktop\\WindowMetrics"; static const TCHAR c_szCTFTIPKey[] = TEXT("SOFTWARE\\Microsoft\\CTF\\TIP\\"); static const TCHAR c_szCTFAssemblies[] = TEXT("SOFTWARE\\Microsoft\\CTF\\Assemblies\\");
REGWATCH CRegWatcher::_rgRegWatch[NUM_REG_WATCH] = { { HKEY_CURRENT_USER, c_szKbdToggleKey, 0 }, { HKEY_LOCAL_MACHINE, c_szCTFTIPKey, 0 }, { HKEY_CURRENT_USER, c_szKbdPreload, 0 }, { HKEY_CURRENT_USER, c_szRun, 0 }, { HKEY_CURRENT_USER, c_szCTFTIPKey, 0 }, { HKEY_CURRENT_USER, c_szSpeechKey, 0 }, { HKEY_CURRENT_USER, c_szCPLAppearance, 0 }, { HKEY_CURRENT_USER, c_szCPLColors, 0 }, { HKEY_CURRENT_USER, c_szCPLMetrics, 0 }, { HKEY_LOCAL_MACHINE, c_szSpeechKey, 0 }, { HKEY_CURRENT_USER, c_szKbdLayout, 0 }, { HKEY_CURRENT_USER, c_szCTFAssemblies, 0 }, };
HANDLE CRegWatcher::_rgEvent[NUM_REG_WATCH] = { 0 };
typedef LONG (STDAPICALLTYPE* PFNREGNOTIFYCHANGEKEYVALUE) ( HKEY, BOOL, DWORD, HANDLE, BOOL);
typedef HRESULT (STDAPICALLTYPE* PFNCREATELANGPROFILEUTIL) (ITfFnLangProfileUtil **);
PFNREGNOTIFYCHANGEKEYVALUE g_pfnRegNotifyChangeKeyValue = NULL;
//////////////////////////////////////////////////////////////////////////////
//
// CRegWatcher
//
//////////////////////////////////////////////////////////////////////////////
//--------------------------------------------------------------------------
//
// Init
//
//--------------------------------------------------------------------------
BOOL CRegWatcher::Init() { int i; BOOL bRet = FALSE;
if (!IsOnNT()) { _rgRegWatch[REG_WATCH_RUN].hKeyRoot = HKEY_LOCAL_MACHINE; }
HMODULE hMod = LoadSystemLibrary("advapi32.dll"); // Issue: why no release?
g_pfnRegNotifyChangeKeyValue = (PFNREGNOTIFYCHANGEKEYVALUE)GetProcAddress(hMod, "RegNotifyChangeKeyValue");
if (!g_pfnRegNotifyChangeKeyValue) { Assert(0); goto Exit; }
for (i = 0; i < NUM_REG_WATCH; i++) { if ((_rgEvent[i] = CreateEvent(NULL, TRUE, FALSE, NULL)) != 0) { InitEvent(i); } }
KillInternat();
UpdateSpTip();
bRet = TRUE;
Exit: return bRet; }
//--------------------------------------------------------------------------
//
// Uninit
//
//--------------------------------------------------------------------------
void CRegWatcher::Uninit() { int i;
for (i = 0; i < NUM_REG_WATCH; i++) { RegCloseKey(_rgRegWatch[i].hKey); if (_rgEvent[i]) { CloseHandle(_rgEvent[i]); } } }
//--------------------------------------------------------------------------
//
// RegImxTimerProc
//
//--------------------------------------------------------------------------
UINT_PTR CRegWatcher::nRegImxTimerId = 0;
void CRegWatcher::RegImxTimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) { KillTimer(NULL, nRegImxTimerId); nRegImxTimerId = 0;
TF_InvalidAssemblyListCache(); TF_PostAllThreadMsg(TFPRIV_UPDATE_REG_IMX, TLF_LBIMGR); }
//--------------------------------------------------------------------------
//
// SysColorTimerProc
//
//--------------------------------------------------------------------------
UINT_PTR CRegWatcher::nSysColorTimerId = 0;
void CRegWatcher::SysColorTimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) { KillTimer(NULL, nSysColorTimerId); nSysColorTimerId = 0;
TF_PostAllThreadMsg(TFPRIV_SYSCOLORCHANGED, TLF_LBIMGR); }
//--------------------------------------------------------------------------
//
// KbdToggleTimerProc
//
//--------------------------------------------------------------------------
UINT_PTR CRegWatcher::nKbdToggleTimerId = 0;
void CRegWatcher::KbdToggleTimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) { KillTimer(NULL, nKbdToggleTimerId); nKbdToggleTimerId = 0;
TF_PostAllThreadMsg(TFPRIV_UPDATE_REG_KBDTOGGLE, TLF_LBIMGR); }
//--------------------------------------------------------------------------
//
// OnEvent
//
//--------------------------------------------------------------------------
void CRegWatcher::OnEvent(DWORD dwEventId) { Assert(dwEventId < NUM_REG_WATCH); // bogus event?
InitEvent(dwEventId, TRUE);
switch (dwEventId) { case REG_WATCH_KBDTOGGLE: if (nKbdToggleTimerId) { KillTimer(NULL, nKbdToggleTimerId); nKbdToggleTimerId = 0; }
nKbdToggleTimerId = SetTimer(NULL, 0, 500, KbdToggleTimerProc); break;
case REG_WATCH_KBDLAYOUT: case REG_WATCH_KBDPRELOAD: case REG_WATCH_HKLM_IMX: case REG_WATCH_HKCU_IMX: case REG_WATCH_HKCU_ASSEMBLIES: if (nRegImxTimerId) { KillTimer(NULL, nRegImxTimerId); nRegImxTimerId = 0; }
nRegImxTimerId = SetTimer(NULL, 0, 200, RegImxTimerProc); break;
case REG_WATCH_RUN: KillInternat(); break;
case REG_WATCH_HKCU_SPEECH: case REG_WATCH_HKLM_SPEECH: UpdateSpTip();
// Forcelly update assembly list
// fix bug 4871
if (nRegImxTimerId) { KillTimer(NULL, nRegImxTimerId); nRegImxTimerId = 0; }
nRegImxTimerId = SetTimer(NULL, 0, 200, RegImxTimerProc);
break;
case REG_WATCH_HKCU_CPL_APPEARANCE: case REG_WATCH_HKCU_CPL_COLORS: case REG_WATCH_HKCU_CPL_METRICS: StartSysColorChangeTimer(); break;
} }
//--------------------------------------------------------------------------
//
// StartSysColorChangeTimer
//
//--------------------------------------------------------------------------
void CRegWatcher::StartSysColorChangeTimer() { if (nSysColorTimerId) { KillTimer(NULL, nSysColorTimerId); nSysColorTimerId = 0; }
nSysColorTimerId = SetTimer(NULL, 0, 500, SysColorTimerProc); }
//--------------------------------------------------------------------------
//
// InitEvent
//
//--------------------------------------------------------------------------
BOOL CRegWatcher::InitEvent(int nId, BOOL fReset) { LONG lErrorCode;
if (fReset) ::ResetEvent(_rgEvent[nId]);
RegCloseKey(_rgRegWatch[nId].hKey);
if (RegOpenKeyEx(_rgRegWatch[nId].hKeyRoot, _rgRegWatch[nId].pszKey, 0, KEY_READ, &_rgRegWatch[nId].hKey) == S_OK || RegCreateKeyEx(_rgRegWatch[nId].hKeyRoot, _rgRegWatch[nId].pszKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &_rgRegWatch[nId].hKey, NULL) == S_OK) { Assert(g_pfnRegNotifyChangeKeyValue); lErrorCode = g_pfnRegNotifyChangeKeyValue(_rgRegWatch[nId].hKey, TRUE, REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_CHANGE_LAST_SET, _rgEvent[nId], TRUE);
if (lErrorCode != ERROR_SUCCESS) { Assert(0); return FALSE; }
return TRUE; }
return FALSE; }
//--------------------------------------------------------------------------
//
// KillInternat
//
//--------------------------------------------------------------------------
void CRegWatcher::KillInternat() { HKEY hKey;
if (RegOpenKeyEx(_rgRegWatch[REG_WATCH_RUN].hKeyRoot, _rgRegWatch[REG_WATCH_RUN].pszKey, 0, KEY_ALL_ACCESS, &hKey) == S_OK) { RegDeleteValue(hKey, "internat.exe"); RegCloseKey(hKey); }
HWND hwndIndic = FindWindow(INDICATOR_CLASS, NULL); if (hwndIndic) { PostMessage(hwndIndic, WM_CLOSE, 0, 0); } }
//--------------------------------------------------------------------------
//
// UpdateSpTip
//
//--------------------------------------------------------------------------
#define WM_PRIV_SPEECHOPTION WM_APP+2
const char c_szWorkerWndClass[] = "SapiTipWorkerClass"; const TCHAR c_szSapilayrKey[] = TEXT("SOFTWARE\\Microsoft\\CTF\\Sapilayr\\"); const TCHAR c_szProfileInit[] = TEXT("ProfileInitialized"); const TCHAR c_szSpTipFile[] = TEXT("\\IME\\sptip.dll"); const TCHAR c_szTFCreateLangPropUtil[] = TEXT("TF_CreateLangProfileUtil");
extern "C" HRESULT WINAPI TF_InvalidAssemblyListCacheIfExist();
void CRegWatcher::UpdateSpTip() { EnumWindows( EnumWndProc, NULL);
// clear the key that states "we've init'ed profiles"
//
// 03/27/01 - for bug#4818, we re-enabled this piece of code for HKCU value
// instead of HKLM
//
HKEY hKey; if (RegOpenKeyEx(HKEY_CURRENT_USER, c_szSapilayrKey, 0, KEY_WRITE, &hKey) == ERROR_SUCCESS) { DWORD dw = 0; RegSetValueEx(hKey, c_szProfileInit, NULL, REG_DWORD, (const BYTE *)&dw, sizeof(dw)); RegCloseKey(hKey); }
//
// ..then call into sptip's ITfFnLangProfileUtil to update sptip's profile
// we probably don't need to do this at the moment app starts
// if we don't need to register profiles at app boot, we also don't need
// the code above to reset 'ProfileInit' - actually we need to remove this
// code to fix bug 2801 or 3479 (not to access HKLM)
//
PFNCREATELANGPROFILEUTIL pfnCreateLangProfUtil = NULL; ITfFnLangProfileUtil *pFnLangUtil = NULL; TCHAR szPathSpTip[MAX_PATH]; HMODULE hSpTip = NULL;
UINT uLength = GetSystemWindowsDirectory(szPathSpTip, ARRAYSIZE(szPathSpTip)); if (uLength && (ARRAYSIZE(szPathSpTip) > (uLength + ARRAYSIZE(c_szSpTipFile)))) { _tcscat(szPathSpTip, c_szSpTipFile); hSpTip = LoadLibrary(szPathSpTip); // Issue: why no release?
} if (hSpTip != NULL) { pfnCreateLangProfUtil = (PFNCREATELANGPROFILEUTIL)GetProcAddress(hSpTip, c_szTFCreateLangPropUtil); }
HRESULT hr = E_FAIL; if (pfnCreateLangProfUtil != NULL) { hr = pfnCreateLangProfUtil(&pFnLangUtil); }
if (S_OK == hr) { if (S_OK == pFnLangUtil->RegisterActiveProfiles()) TF_InvalidAssemblyListCacheIfExist(); }
if (pFnLangUtil) pFnLangUtil->Release();
if (hSpTip != NULL) { FreeLibrary(hSpTip); } }
BOOL CALLBACK CRegWatcher::EnumWndProc(HWND hwnd, LPARAM lparam) { char szCls[MAX_PATH]; if (GetClassNameA(hwnd, szCls, ARRAYSIZE(szCls)) > 0) { if ( 0 == lstrcmpiA(szCls, c_szWorkerWndClass) ) { PostMessage(hwnd, WM_PRIV_SPEECHOPTION, 0, 0); } } return TRUE; }
|