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.

408 lines
12 KiB

  1. //
  2. // regwatch.cpp
  3. //
  4. #include "private.h"
  5. #include "regwatch.h"
  6. #include "indicml.h"
  7. #include "tfpriv.h"
  8. #include "ctffunc.h"
  9. #include "tlapi.h"
  10. #include "immxutil.h"
  11. extern "C" HRESULT WINAPI TF_InvalidAssemblyListCache();
  12. extern "C" HRESULT WINAPI TF_PostAllThreadMsg(WPARAM wParam, DWORD dwFlags);
  13. static const char c_szKbdLayout[] = "keyboard layout";
  14. static const char c_szKbdToggleKey[] = "Keyboard Layout\\Toggle";
  15. static const char c_szKbdPreload[] = "keyboard layout\\Preload";
  16. static const char c_szRun[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Run";
  17. static const char c_szSpeechKey[] = "Software\\Microsoft\\Speech";
  18. static const char c_szCPLAppearance[] = "Control Panel\\Appearance";
  19. static const char c_szCPLColors[] = "Control Panel\\Colors";
  20. static const char c_szCPLMetrics[] = "Control Panel\\Desktop\\WindowMetrics";
  21. static const TCHAR c_szCTFTIPKey[] = TEXT("SOFTWARE\\Microsoft\\CTF\\TIP\\");
  22. static const TCHAR c_szCTFAssemblies[] = TEXT("SOFTWARE\\Microsoft\\CTF\\Assemblies\\");
  23. REGWATCH CRegWatcher::_rgRegWatch[NUM_REG_WATCH] =
  24. {
  25. { HKEY_CURRENT_USER, c_szKbdToggleKey, 0 },
  26. { HKEY_LOCAL_MACHINE, c_szCTFTIPKey, 0 },
  27. { HKEY_CURRENT_USER, c_szKbdPreload, 0 },
  28. { HKEY_CURRENT_USER, c_szRun, 0 },
  29. { HKEY_CURRENT_USER, c_szCTFTIPKey, 0 },
  30. { HKEY_CURRENT_USER, c_szSpeechKey, 0 },
  31. { HKEY_CURRENT_USER, c_szCPLAppearance, 0 },
  32. { HKEY_CURRENT_USER, c_szCPLColors, 0 },
  33. { HKEY_CURRENT_USER, c_szCPLMetrics, 0 },
  34. { HKEY_LOCAL_MACHINE, c_szSpeechKey, 0 },
  35. { HKEY_CURRENT_USER, c_szKbdLayout, 0 },
  36. { HKEY_CURRENT_USER, c_szCTFAssemblies, 0 },
  37. };
  38. HANDLE CRegWatcher::_rgEvent[NUM_REG_WATCH] = { 0 };
  39. typedef LONG (STDAPICALLTYPE* PFNREGNOTIFYCHANGEKEYVALUE) ( HKEY,
  40. BOOL,
  41. DWORD,
  42. HANDLE,
  43. BOOL);
  44. typedef HRESULT (STDAPICALLTYPE* PFNCREATELANGPROFILEUTIL) (ITfFnLangProfileUtil **);
  45. PFNREGNOTIFYCHANGEKEYVALUE g_pfnRegNotifyChangeKeyValue = NULL;
  46. //////////////////////////////////////////////////////////////////////////////
  47. //
  48. // CRegWatcher
  49. //
  50. //////////////////////////////////////////////////////////////////////////////
  51. //--------------------------------------------------------------------------
  52. //
  53. // Init
  54. //
  55. //--------------------------------------------------------------------------
  56. BOOL CRegWatcher::Init()
  57. {
  58. int i;
  59. BOOL bRet = FALSE;
  60. if (!IsOnNT())
  61. {
  62. _rgRegWatch[REG_WATCH_RUN].hKeyRoot = HKEY_LOCAL_MACHINE;
  63. }
  64. HMODULE hMod = LoadSystemLibrary("advapi32.dll"); // Issue: why no release?
  65. g_pfnRegNotifyChangeKeyValue = (PFNREGNOTIFYCHANGEKEYVALUE)GetProcAddress(hMod, "RegNotifyChangeKeyValue");
  66. if (!g_pfnRegNotifyChangeKeyValue)
  67. {
  68. Assert(0);
  69. goto Exit;
  70. }
  71. for (i = 0; i < NUM_REG_WATCH; i++)
  72. {
  73. if ((_rgEvent[i] = CreateEvent(NULL, TRUE, FALSE, NULL)) != 0)
  74. {
  75. InitEvent(i);
  76. }
  77. }
  78. KillInternat();
  79. UpdateSpTip();
  80. bRet = TRUE;
  81. Exit:
  82. return bRet;
  83. }
  84. //--------------------------------------------------------------------------
  85. //
  86. // Uninit
  87. //
  88. //--------------------------------------------------------------------------
  89. void CRegWatcher::Uninit()
  90. {
  91. int i;
  92. for (i = 0; i < NUM_REG_WATCH; i++)
  93. {
  94. RegCloseKey(_rgRegWatch[i].hKey);
  95. if (_rgEvent[i])
  96. {
  97. CloseHandle(_rgEvent[i]);
  98. }
  99. }
  100. }
  101. //--------------------------------------------------------------------------
  102. //
  103. // RegImxTimerProc
  104. //
  105. //--------------------------------------------------------------------------
  106. UINT_PTR CRegWatcher::nRegImxTimerId = 0;
  107. void CRegWatcher::RegImxTimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
  108. {
  109. KillTimer(NULL, nRegImxTimerId);
  110. nRegImxTimerId = 0;
  111. TF_InvalidAssemblyListCache();
  112. TF_PostAllThreadMsg(TFPRIV_UPDATE_REG_IMX, TLF_LBIMGR);
  113. }
  114. //--------------------------------------------------------------------------
  115. //
  116. // SysColorTimerProc
  117. //
  118. //--------------------------------------------------------------------------
  119. UINT_PTR CRegWatcher::nSysColorTimerId = 0;
  120. void CRegWatcher::SysColorTimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
  121. {
  122. KillTimer(NULL, nSysColorTimerId);
  123. nSysColorTimerId = 0;
  124. TF_PostAllThreadMsg(TFPRIV_SYSCOLORCHANGED, TLF_LBIMGR);
  125. }
  126. //--------------------------------------------------------------------------
  127. //
  128. // KbdToggleTimerProc
  129. //
  130. //--------------------------------------------------------------------------
  131. UINT_PTR CRegWatcher::nKbdToggleTimerId = 0;
  132. void CRegWatcher::KbdToggleTimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
  133. {
  134. KillTimer(NULL, nKbdToggleTimerId);
  135. nKbdToggleTimerId = 0;
  136. TF_PostAllThreadMsg(TFPRIV_UPDATE_REG_KBDTOGGLE, TLF_LBIMGR);
  137. }
  138. //--------------------------------------------------------------------------
  139. //
  140. // OnEvent
  141. //
  142. //--------------------------------------------------------------------------
  143. void CRegWatcher::OnEvent(DWORD dwEventId)
  144. {
  145. Assert(dwEventId < NUM_REG_WATCH); // bogus event?
  146. InitEvent(dwEventId, TRUE);
  147. switch (dwEventId)
  148. {
  149. case REG_WATCH_KBDTOGGLE:
  150. if (nKbdToggleTimerId)
  151. {
  152. KillTimer(NULL, nKbdToggleTimerId);
  153. nKbdToggleTimerId = 0;
  154. }
  155. nKbdToggleTimerId = SetTimer(NULL, 0, 500, KbdToggleTimerProc);
  156. break;
  157. case REG_WATCH_KBDLAYOUT:
  158. case REG_WATCH_KBDPRELOAD:
  159. case REG_WATCH_HKLM_IMX:
  160. case REG_WATCH_HKCU_IMX:
  161. case REG_WATCH_HKCU_ASSEMBLIES:
  162. if (nRegImxTimerId)
  163. {
  164. KillTimer(NULL, nRegImxTimerId);
  165. nRegImxTimerId = 0;
  166. }
  167. nRegImxTimerId = SetTimer(NULL, 0, 200, RegImxTimerProc);
  168. break;
  169. case REG_WATCH_RUN:
  170. KillInternat();
  171. break;
  172. case REG_WATCH_HKCU_SPEECH:
  173. case REG_WATCH_HKLM_SPEECH:
  174. UpdateSpTip();
  175. // Forcelly update assembly list
  176. // fix bug 4871
  177. if (nRegImxTimerId)
  178. {
  179. KillTimer(NULL, nRegImxTimerId);
  180. nRegImxTimerId = 0;
  181. }
  182. nRegImxTimerId = SetTimer(NULL, 0, 200, RegImxTimerProc);
  183. break;
  184. case REG_WATCH_HKCU_CPL_APPEARANCE:
  185. case REG_WATCH_HKCU_CPL_COLORS:
  186. case REG_WATCH_HKCU_CPL_METRICS:
  187. StartSysColorChangeTimer();
  188. break;
  189. }
  190. }
  191. //--------------------------------------------------------------------------
  192. //
  193. // StartSysColorChangeTimer
  194. //
  195. //--------------------------------------------------------------------------
  196. void CRegWatcher::StartSysColorChangeTimer()
  197. {
  198. if (nSysColorTimerId)
  199. {
  200. KillTimer(NULL, nSysColorTimerId);
  201. nSysColorTimerId = 0;
  202. }
  203. nSysColorTimerId = SetTimer(NULL, 0, 500, SysColorTimerProc);
  204. }
  205. //--------------------------------------------------------------------------
  206. //
  207. // InitEvent
  208. //
  209. //--------------------------------------------------------------------------
  210. BOOL CRegWatcher::InitEvent(int nId, BOOL fReset)
  211. {
  212. LONG lErrorCode;
  213. if (fReset)
  214. ::ResetEvent(_rgEvent[nId]);
  215. RegCloseKey(_rgRegWatch[nId].hKey);
  216. if (RegOpenKeyEx(_rgRegWatch[nId].hKeyRoot, _rgRegWatch[nId].pszKey, 0, KEY_READ, &_rgRegWatch[nId].hKey) == S_OK ||
  217. RegCreateKeyEx(_rgRegWatch[nId].hKeyRoot, _rgRegWatch[nId].pszKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &_rgRegWatch[nId].hKey, NULL) == S_OK)
  218. {
  219. Assert(g_pfnRegNotifyChangeKeyValue);
  220. lErrorCode = g_pfnRegNotifyChangeKeyValue(_rgRegWatch[nId].hKey,
  221. TRUE,
  222. REG_NOTIFY_CHANGE_NAME |
  223. REG_NOTIFY_CHANGE_LAST_SET,
  224. _rgEvent[nId],
  225. TRUE);
  226. if (lErrorCode != ERROR_SUCCESS)
  227. {
  228. Assert(0);
  229. return FALSE;
  230. }
  231. return TRUE;
  232. }
  233. return FALSE;
  234. }
  235. //--------------------------------------------------------------------------
  236. //
  237. // KillInternat
  238. //
  239. //--------------------------------------------------------------------------
  240. void CRegWatcher::KillInternat()
  241. {
  242. HKEY hKey;
  243. if (RegOpenKeyEx(_rgRegWatch[REG_WATCH_RUN].hKeyRoot, _rgRegWatch[REG_WATCH_RUN].pszKey, 0, KEY_ALL_ACCESS, &hKey) == S_OK)
  244. {
  245. RegDeleteValue(hKey, "internat.exe");
  246. RegCloseKey(hKey);
  247. }
  248. HWND hwndIndic = FindWindow(INDICATOR_CLASS, NULL);
  249. if (hwndIndic)
  250. {
  251. PostMessage(hwndIndic, WM_CLOSE, 0, 0);
  252. }
  253. }
  254. //--------------------------------------------------------------------------
  255. //
  256. // UpdateSpTip
  257. //
  258. //--------------------------------------------------------------------------
  259. #define WM_PRIV_SPEECHOPTION WM_APP+2
  260. const char c_szWorkerWndClass[] = "SapiTipWorkerClass";
  261. const TCHAR c_szSapilayrKey[] = TEXT("SOFTWARE\\Microsoft\\CTF\\Sapilayr\\");
  262. const TCHAR c_szProfileInit[] = TEXT("ProfileInitialized");
  263. const TCHAR c_szSpTipFile[] = TEXT("\\IME\\sptip.dll");
  264. const TCHAR c_szTFCreateLangPropUtil[] = TEXT("TF_CreateLangProfileUtil");
  265. extern "C" HRESULT WINAPI TF_InvalidAssemblyListCacheIfExist();
  266. void CRegWatcher::UpdateSpTip()
  267. {
  268. EnumWindows( EnumWndProc, NULL);
  269. // clear the key that states "we've init'ed profiles"
  270. //
  271. // 03/27/01 - for bug#4818, we re-enabled this piece of code for HKCU value
  272. // instead of HKLM
  273. //
  274. HKEY hKey;
  275. if (RegOpenKeyEx(HKEY_CURRENT_USER, c_szSapilayrKey, 0, KEY_WRITE, &hKey) == ERROR_SUCCESS)
  276. {
  277. DWORD dw = 0;
  278. RegSetValueEx(hKey, c_szProfileInit, NULL, REG_DWORD, (const BYTE *)&dw, sizeof(dw));
  279. RegCloseKey(hKey);
  280. }
  281. //
  282. // ..then call into sptip's ITfFnLangProfileUtil to update sptip's profile
  283. // we probably don't need to do this at the moment app starts
  284. // if we don't need to register profiles at app boot, we also don't need
  285. // the code above to reset 'ProfileInit' - actually we need to remove this
  286. // code to fix bug 2801 or 3479 (not to access HKLM)
  287. //
  288. PFNCREATELANGPROFILEUTIL pfnCreateLangProfUtil = NULL;
  289. ITfFnLangProfileUtil *pFnLangUtil = NULL;
  290. TCHAR szPathSpTip[MAX_PATH];
  291. HMODULE hSpTip = NULL;
  292. UINT uLength = GetSystemWindowsDirectory(szPathSpTip, ARRAYSIZE(szPathSpTip));
  293. if (uLength &&
  294. (ARRAYSIZE(szPathSpTip) > (uLength + ARRAYSIZE(c_szSpTipFile))))
  295. {
  296. _tcscat(szPathSpTip, c_szSpTipFile);
  297. hSpTip = LoadLibrary(szPathSpTip); // Issue: why no release?
  298. }
  299. if (hSpTip != NULL)
  300. {
  301. pfnCreateLangProfUtil = (PFNCREATELANGPROFILEUTIL)GetProcAddress(hSpTip, c_szTFCreateLangPropUtil);
  302. }
  303. HRESULT hr = E_FAIL;
  304. if (pfnCreateLangProfUtil != NULL)
  305. {
  306. hr = pfnCreateLangProfUtil(&pFnLangUtil);
  307. }
  308. if (S_OK == hr)
  309. {
  310. if (S_OK == pFnLangUtil->RegisterActiveProfiles())
  311. TF_InvalidAssemblyListCacheIfExist();
  312. }
  313. if (pFnLangUtil)
  314. pFnLangUtil->Release();
  315. if (hSpTip != NULL)
  316. {
  317. FreeLibrary(hSpTip);
  318. }
  319. }
  320. BOOL CALLBACK CRegWatcher::EnumWndProc(HWND hwnd, LPARAM lparam)
  321. {
  322. char szCls[MAX_PATH];
  323. if (GetClassNameA(hwnd, szCls, ARRAYSIZE(szCls)) > 0)
  324. {
  325. if ( 0 == lstrcmpiA(szCls, c_szWorkerWndClass) )
  326. {
  327. PostMessage(hwnd, WM_PRIV_SPEECHOPTION, 0, 0);
  328. }
  329. }
  330. return TRUE;
  331. }