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

  1. //
  2. // Include Files.
  3. //
  4. #include "input.h"
  5. #include <regstr.h>
  6. #include <shlapip.h>
  7. #include "external.h"
  8. #include "inputdlg.h"
  9. #include "util.h"
  10. #include "msctf.h"
  11. // TM_LANGUAGEBAND is defined in "shell\inc\trayp.h"
  12. #define TM_LANGUAGEBAND WM_USER+0x105
  13. typedef BOOL (WINAPI *PFNINVALIDASMCACHE)();
  14. static const char c_szTF_InvalidAssemblyListCahgeIdExist[] = "TF_InvalidAssemblyListCacheIfExist";
  15. void InvalidAssemblyListCacheIfExist()
  16. {
  17. HINSTANCE hModCtf = LoadSystemLibrary(TEXT("msctf.dll"));
  18. PFNINVALIDASMCACHE pfn;
  19. if (!hModCtf)
  20. return;
  21. pfn = (PFNINVALIDASMCACHE)GetProcAddress(hModCtf,
  22. c_szTF_InvalidAssemblyListCahgeIdExist);
  23. if (pfn)
  24. pfn();
  25. FreeLibrary(hModCtf);
  26. }
  27. ////////////////////////////////////////////////////////////////////////////
  28. //
  29. // LoadCtfmon
  30. //
  31. ////////////////////////////////////////////////////////////////////////////
  32. void LoadCtfmon(
  33. BOOL bLoad,
  34. LCID SysLocale,
  35. BOOL bDefUser)
  36. {
  37. HWND hwndCTFMon;
  38. HKEY hkeyCtfmon;
  39. BOOL bMinLangBar = TRUE;
  40. //
  41. // Get default system locale
  42. //
  43. if (!SysLocale)
  44. SysLocale = GetSystemDefaultLCID();
  45. if ((SysLocale == 0x0404) || (SysLocale == 0x0411) ||
  46. (SysLocale == 0x0412) || (SysLocale == 0x0804))
  47. {
  48. //
  49. // Show language bar in case of FE system as a default
  50. //
  51. bMinLangBar = FALSE;
  52. }
  53. //
  54. // Find language tool bar module(CTFMON.EXE)
  55. //
  56. hwndCTFMon = FindWindow(c_szCTFMonClass, NULL);
  57. if (!bDefUser)
  58. {
  59. if (RegCreateKey( HKEY_CURRENT_USER,
  60. REGSTR_PATH_RUN,
  61. &hkeyCtfmon ) != ERROR_SUCCESS)
  62. {
  63. hkeyCtfmon = NULL;
  64. }
  65. }
  66. else
  67. {
  68. if (RegCreateKey( HKEY_USERS,
  69. c_szRunPath_DefUser,
  70. &hkeyCtfmon ) != ERROR_SUCCESS)
  71. {
  72. hkeyCtfmon = NULL;
  73. }
  74. }
  75. //
  76. // Update language band menu item to Taskbar
  77. //
  78. SetLanguageBandMenu(bLoad);
  79. if (bLoad)
  80. {
  81. BOOL bOSNT51 = IsOSPlatform(OS_NT51);
  82. if (IsSetupMode() || bDefUser)
  83. {
  84. DWORD dwShowStatus;
  85. if (!GetLangBarOption(&dwShowStatus, bDefUser))
  86. {
  87. if (bMinLangBar)
  88. {
  89. if (bOSNT51)
  90. SetLangBarOption(REG_LANGBAR_DESKBAND, bDefUser);
  91. else
  92. SetLangBarOption(REG_LANGBAR_MINIMIZED, bDefUser);
  93. }
  94. else
  95. {
  96. SetLangBarOption(REG_LANGBAR_SHOWNORMAL, bDefUser);
  97. }
  98. }
  99. }
  100. if (!IsSetupMode() && IsInteractiveUserLogon() && !bDefUser)
  101. {
  102. HRESULT hr;
  103. DWORD dwTBFlag = 0;
  104. ITfLangBarMgr *pLangBar = NULL;
  105. //
  106. // Minimize language bar as a default setting.
  107. //
  108. hr = CoCreateInstance(&CLSID_TF_LangBarMgr,
  109. NULL,
  110. CLSCTX_INPROC_SERVER,
  111. &IID_ITfLangBarMgr,
  112. (LPVOID *) &pLangBar);
  113. if (SUCCEEDED(hr))
  114. {
  115. pLangBar->lpVtbl->GetShowFloatingStatus(pLangBar, &dwTBFlag);
  116. //
  117. // Bug#519662 - Tablet PC set Language Bar UI as hidden status with
  118. // running ctfmon.exe module. So we want to show Language Bar UI again
  119. // if the current show status is hidden.
  120. //
  121. if (!IsWindow(hwndCTFMon) || (dwTBFlag & TF_SFT_HIDDEN))
  122. {
  123. if (bMinLangBar)
  124. {
  125. if (bOSNT51)
  126. pLangBar->lpVtbl->ShowFloating(pLangBar, TF_SFT_DESKBAND);
  127. else
  128. pLangBar->lpVtbl->ShowFloating(pLangBar, TF_SFT_MINIMIZED);
  129. }
  130. else
  131. {
  132. pLangBar->lpVtbl->ShowFloating(pLangBar, TF_SFT_SHOWNORMAL);
  133. }
  134. }
  135. else if (dwTBFlag & TF_SFT_DESKBAND)
  136. {
  137. pLangBar->lpVtbl->ShowFloating(pLangBar, dwTBFlag);
  138. }
  139. }
  140. if (pLangBar)
  141. pLangBar->lpVtbl->Release(pLangBar);
  142. //
  143. // Invalid Assembly Cahce before starting ctfmon.exe
  144. //
  145. InvalidAssemblyListCacheIfExist();
  146. //
  147. // Run ctfmon.exe process
  148. //
  149. RunCtfmonProcess();
  150. }
  151. if (hkeyCtfmon)
  152. {
  153. TCHAR szCTFMonPath[MAX_PATH];
  154. GetCtfmonPath((LPTSTR) szCTFMonPath, ARRAYSIZE(szCTFMonPath));
  155. RegSetValueEx(hkeyCtfmon,
  156. c_szCTFMon,
  157. 0,
  158. REG_SZ,
  159. (LPBYTE)szCTFMonPath,
  160. (lstrlen(szCTFMonPath) + 1) * sizeof(TCHAR));
  161. //
  162. // Clean up the registry for internat.
  163. //
  164. RegDeleteValue(hkeyCtfmon, c_szInternat);
  165. }
  166. }
  167. else
  168. {
  169. if (!bDefUser)
  170. {
  171. HRESULT hr;
  172. DWORD dwTBFlag = 0;
  173. ITfLangBarMgr *pLangBar = NULL;
  174. //
  175. // Minimize language bar as a default setting.
  176. //
  177. hr = CoCreateInstance(&CLSID_TF_LangBarMgr,
  178. NULL,
  179. CLSCTX_INPROC_SERVER,
  180. &IID_ITfLangBarMgr,
  181. (LPVOID *) &pLangBar);
  182. if (SUCCEEDED(hr))
  183. {
  184. pLangBar->lpVtbl->GetShowFloatingStatus(pLangBar, &dwTBFlag);
  185. if (dwTBFlag & TF_SFT_DESKBAND)
  186. {
  187. #if 0
  188. HWND hwndTray = NULL;
  189. //
  190. // Notify to shell to remove the language band from taskbar.
  191. //
  192. hwndTray = FindWindow(TEXT(WNDCLASS_TRAYNOTIFY), NULL);
  193. if (hwndTray)
  194. {
  195. DWORD_PTR dwResult;
  196. LRESULT lResult = (LRESULT)0;
  197. lResult = SendMessageTimeout(hwndTray,
  198. TM_LANGUAGEBAND,
  199. 0,
  200. 0, // Remove band
  201. SMTO_ABORTIFHUNG | SMTO_BLOCK,
  202. 5000,
  203. &dwResult);
  204. }
  205. #else
  206. pLangBar->lpVtbl->ShowFloating(pLangBar, TF_SFT_SHOWNORMAL);
  207. //
  208. // Change back DeskBand setting into the registry
  209. //
  210. SetLangBarOption(REG_LANGBAR_DESKBAND, bDefUser);
  211. #endif
  212. }
  213. }
  214. if (pLangBar)
  215. pLangBar->lpVtbl->Release(pLangBar);
  216. if (hwndCTFMon && IsWindow(hwndCTFMon))
  217. {
  218. //
  219. // It's on, turn off the language tool bar.
  220. //
  221. PostMessage(hwndCTFMon, WM_CLOSE, 0L, 0L);
  222. }
  223. }
  224. if (hkeyCtfmon)
  225. RegDeleteValue(hkeyCtfmon, c_szCTFMon);
  226. }
  227. if (hkeyCtfmon)
  228. {
  229. RegCloseKey(hkeyCtfmon);
  230. }
  231. }
  232. ////////////////////////////////////////////////////////////////////////////
  233. //
  234. // UpdateDefaultHotkey
  235. //
  236. ////////////////////////////////////////////////////////////////////////////
  237. void UpdateDefaultHotkey(
  238. LCID SysLocale,
  239. BOOL bThai,
  240. BOOL bDefaultUserCase)
  241. {
  242. HKEY hKey;
  243. TCHAR szData[MAX_PATH];
  244. DWORD cbData;
  245. BOOL bHotKey = FALSE;
  246. BOOL bChinese = FALSE;
  247. BOOL bMe = FALSE;
  248. DWORD dwPrimLangID;
  249. dwPrimLangID = PRIMARYLANGID(LANGIDFROMLCID(SysLocale));
  250. if (PRIMARYLANGID(dwPrimLangID) == LANG_CHINESE)
  251. {
  252. bChinese = TRUE;
  253. }
  254. else if (dwPrimLangID == LANG_ARABIC || dwPrimLangID == LANG_HEBREW)
  255. {
  256. bMe = TRUE;
  257. }
  258. //
  259. // Try to open the registry key
  260. //
  261. if (!bDefaultUserCase)
  262. {
  263. if (RegOpenKey( HKEY_CURRENT_USER,
  264. c_szKbdToggleKey,
  265. &hKey ) == ERROR_SUCCESS)
  266. {
  267. bHotKey = TRUE;
  268. }
  269. }
  270. else
  271. {
  272. if (RegOpenKey( HKEY_USERS,
  273. c_szKbdToggleKey_DefUser,
  274. &hKey ) == ERROR_SUCCESS)
  275. {
  276. bHotKey = TRUE;
  277. }
  278. }
  279. //
  280. // If there is no hotkey switch, set it to Ctrl+Shift. Otherwise, the
  281. // user cannot switch to an IME without setting the value first.
  282. //
  283. szData[0] = TEXT('\0');
  284. if (bHotKey)
  285. {
  286. cbData = sizeof(szData);
  287. RegQueryValueEx( hKey,
  288. TEXT("Hotkey"),
  289. NULL,
  290. NULL,
  291. (LPBYTE)szData,
  292. &cbData );
  293. switch (szData[0])
  294. {
  295. case TEXT('1'):
  296. {
  297. //
  298. // Currently ALT/SHIFT or CTRL/SHIFT. Do not change.
  299. //
  300. break;
  301. }
  302. case TEXT('2'):
  303. {
  304. //
  305. // Change to 1 if Chinese.
  306. //
  307. if (bChinese)
  308. {
  309. szData[0] = TEXT('1');
  310. szData[1] = TEXT('\0');
  311. RegSetValueEx( hKey,
  312. TEXT("Hotkey"),
  313. 0,
  314. REG_SZ,
  315. (LPBYTE)szData,
  316. (DWORD)(lstrlen(szData) + 1) * sizeof(TCHAR) );
  317. }
  318. break;
  319. }
  320. case TEXT('3'):
  321. {
  322. //
  323. // Default hotkey for FE locale switch.
  324. //
  325. szData[0] = bThai ? TEXT('4') : TEXT('1');
  326. szData[1] = TEXT('\0');
  327. RegSetValueEx( hKey,
  328. TEXT("Hotkey"),
  329. 0,
  330. REG_SZ,
  331. (LPBYTE)szData,
  332. (DWORD)(lstrlen(szData) + 1) * sizeof(TCHAR) );
  333. break;
  334. }
  335. case TEXT('4'):
  336. {
  337. //
  338. // Currently Grave. Change to 1 if not Thai.
  339. //
  340. if (!bThai)
  341. {
  342. szData[0] = TEXT('1');
  343. szData[1] = TEXT('\0');
  344. RegSetValueEx( hKey,
  345. TEXT("Hotkey"),
  346. 0,
  347. REG_SZ,
  348. (LPBYTE)szData,
  349. (DWORD)(lstrlen(szData) + 1) * sizeof(TCHAR) );
  350. }
  351. break;
  352. }
  353. }
  354. RegFlushKey(hKey);
  355. //
  356. // Get updated hotkey value and copy the value to language hotkey
  357. //
  358. szData[0] = TEXT('\0');
  359. cbData = sizeof(szData);
  360. RegQueryValueEx( hKey,
  361. TEXT("Hotkey"),
  362. NULL,
  363. NULL,
  364. (LPBYTE)szData,
  365. &cbData );
  366. if (szData[0])
  367. {
  368. RegSetValueEx( hKey,
  369. TEXT("Language Hotkey"),
  370. 0,
  371. REG_SZ,
  372. (LPBYTE)szData,
  373. (DWORD)(lstrlen(szData) + 1) * sizeof(TCHAR) );
  374. //
  375. // Set Layout Hotkey
  376. //
  377. switch (szData[0])
  378. {
  379. case TEXT('1'):
  380. case TEXT('4'):
  381. {
  382. szData[0] = bMe ? TEXT('3') : TEXT('2');
  383. szData[1] = TEXT('\0');
  384. break;
  385. }
  386. case TEXT('2'):
  387. {
  388. szData[0] = TEXT('1');
  389. szData[1] = TEXT('\0');
  390. break;
  391. }
  392. case TEXT('3'):
  393. {
  394. szData[0] = TEXT('3');
  395. szData[1] = TEXT('\0');
  396. break;
  397. }
  398. }
  399. RegSetValueEx( hKey,
  400. TEXT("Layout Hotkey"),
  401. 0,
  402. REG_SZ,
  403. (LPBYTE)szData,
  404. (DWORD)(lstrlen(szData) + 1) * sizeof(TCHAR) );
  405. }
  406. RegCloseKey(hKey);
  407. }
  408. else
  409. {
  410. BOOL bKeyCreated = FALSE;
  411. //
  412. // Create the registry key
  413. //
  414. if (!bDefaultUserCase)
  415. {
  416. if (RegCreateKey( HKEY_CURRENT_USER,
  417. c_szKbdToggleKey,
  418. &hKey ) == ERROR_SUCCESS)
  419. {
  420. bKeyCreated = TRUE;
  421. }
  422. }
  423. else
  424. {
  425. if (RegCreateKey( HKEY_USERS,
  426. c_szKbdToggleKey_DefUser,
  427. &hKey ) == ERROR_SUCCESS)
  428. {
  429. bKeyCreated = TRUE;
  430. }
  431. }
  432. //
  433. // We don't have a Toggle key yet. Create one and set the
  434. // correct value.
  435. //
  436. if (bKeyCreated)
  437. {
  438. szData[0] = bThai ? TEXT('4') : TEXT('1');
  439. szData[1] = 0;
  440. RegSetValueEx( hKey,
  441. TEXT("Hotkey"),
  442. 0,
  443. REG_SZ,
  444. (LPBYTE)szData,
  445. (DWORD)(lstrlen(szData) + 1) * sizeof(TCHAR) );
  446. RegSetValueEx( hKey,
  447. TEXT("Language Hotkey"),
  448. 0,
  449. REG_SZ,
  450. (LPBYTE)szData,
  451. (DWORD)(lstrlen(szData) + 1) * sizeof(TCHAR) );
  452. szData[0] = bMe ? TEXT('3') : TEXT('2');
  453. szData[1] = 0;
  454. RegSetValueEx( hKey,
  455. TEXT("Layout Hotkey"),
  456. 0,
  457. REG_SZ,
  458. (LPBYTE)szData,
  459. (DWORD)(lstrlen(szData) + 1) * sizeof(TCHAR) );
  460. RegFlushKey(hKey);
  461. RegCloseKey(hKey);
  462. }
  463. }
  464. }
  465. ////////////////////////////////////////////////////////////////////////////
  466. //
  467. // ClearHotkey
  468. //
  469. ////////////////////////////////////////////////////////////////////////////
  470. void ClearHotKey(
  471. BOOL bDefaultUserCase)
  472. {
  473. HKEY hKey;
  474. DWORD cbData;
  475. TCHAR szData[MAX_PATH];
  476. BOOL bKeyCreated = FALSE;
  477. //
  478. // Create the registry key
  479. //
  480. if (!bDefaultUserCase)
  481. {
  482. if (RegCreateKey( HKEY_CURRENT_USER,
  483. c_szKbdToggleKey,
  484. &hKey ) == ERROR_SUCCESS)
  485. {
  486. bKeyCreated = TRUE;
  487. }
  488. }
  489. else
  490. {
  491. if (RegCreateKey( HKEY_USERS,
  492. c_szKbdToggleKey_DefUser,
  493. &hKey ) == ERROR_SUCCESS)
  494. {
  495. bKeyCreated = TRUE;
  496. }
  497. }
  498. if (bKeyCreated)
  499. {
  500. szData[0] = TEXT('3');
  501. szData[1] = 0;
  502. RegSetValueEx( hKey,
  503. TEXT("Hotkey"),
  504. 0,
  505. REG_SZ,
  506. (LPBYTE)szData,
  507. (DWORD)(lstrlen(szData) + 1) * sizeof(TCHAR) );
  508. RegSetValueEx( hKey,
  509. TEXT("Language Hotkey"),
  510. 0,
  511. REG_SZ,
  512. (LPBYTE)szData,
  513. (DWORD)(lstrlen(szData) + 1) * sizeof(TCHAR) );
  514. RegSetValueEx( hKey,
  515. TEXT("Layout Hotkey"),
  516. 0,
  517. REG_SZ,
  518. (LPBYTE)szData,
  519. (DWORD)(lstrlen(szData) + 1) * sizeof(TCHAR) );
  520. RegFlushKey(hKey);
  521. RegCloseKey(hKey);
  522. }
  523. }
  524. ////////////////////////////////////////////////////////////////////////////
  525. //
  526. // ActivateDefaultKeyboardLayout
  527. //
  528. // Sets the default input layout on the system, and broadcast to all
  529. // running apps about this change.
  530. //
  531. ////////////////////////////////////////////////////////////////////////////
  532. BOOL ActivateDefaultKeyboardLayout(
  533. DWORD dwLocale,
  534. DWORD dwLayout,
  535. HKL hkl)
  536. {
  537. BOOL bRet = FALSE;
  538. if (hkl)
  539. {
  540. if (SystemParametersInfo( SPI_SETDEFAULTINPUTLANG,
  541. 0,
  542. (LPVOID)((LPDWORD) &hkl),
  543. 0 ))
  544. {
  545. DWORD dwRecipients = BSM_APPLICATIONS | BSM_ALLDESKTOPS;
  546. BroadcastSystemMessage( BSF_POSTMESSAGE,
  547. &dwRecipients,
  548. WM_INPUTLANGCHANGEREQUEST,
  549. 1,
  550. (LPARAM) hkl );
  551. bRet = TRUE;
  552. }
  553. }
  554. return bRet;
  555. }
  556. ////////////////////////////////////////////////////////////////////////////
  557. //
  558. // SetSystemDefautLayout
  559. //
  560. ////////////////////////////////////////////////////////////////////////////
  561. BOOL SetSystemDefautLayout(
  562. LCID Locale,
  563. DWORD dwLayout,
  564. HKL hklDefault,
  565. BOOL bDefaultUserCase )
  566. {
  567. LONG rc;
  568. int iPreloadInx;
  569. BOOL bRet = FALSE;
  570. HKEY hKeyPreload,hKeySubst;
  571. TCHAR szSubValue[MAX_PATH];
  572. TCHAR szSubData[MAX_PATH];
  573. TCHAR szPreload[MAX_PATH];
  574. TCHAR szPreloadInx[MAX_PATH];
  575. DWORD dwLocale, dwIndex, cchSubValue, cbData;
  576. dwLocale = Locale;
  577. if (dwLayout == 0)
  578. {
  579. return (FALSE);
  580. }
  581. //
  582. // Open the HKCU\Keyboard Layout\Preload key.
  583. //
  584. if (!bDefaultUserCase)
  585. {
  586. if (RegOpenKeyEx(HKEY_CURRENT_USER,
  587. c_szKbdPreloadKey,
  588. 0,
  589. KEY_ALL_ACCESS,
  590. &hKeyPreload) != ERROR_SUCCESS)
  591. {
  592. return (FALSE);
  593. }
  594. }
  595. else
  596. {
  597. if (RegOpenKeyEx(HKEY_USERS,
  598. c_szKbdPreloadKey_DefUser,
  599. 0,
  600. KEY_ALL_ACCESS,
  601. &hKeyPreload) != ERROR_SUCCESS)
  602. {
  603. return (FALSE);
  604. }
  605. }
  606. //
  607. // Open the HKCU\Keyboard Layout\Substitutes key.
  608. //
  609. if (!bDefaultUserCase)
  610. {
  611. if (RegOpenKeyEx(HKEY_CURRENT_USER,
  612. c_szKbdSubstKey,
  613. 0,
  614. KEY_ALL_ACCESS,
  615. &hKeySubst) != ERROR_SUCCESS)
  616. {
  617. RegCloseKey(hKeyPreload);
  618. return (FALSE);
  619. }
  620. }
  621. else
  622. {
  623. if (RegOpenKeyEx(HKEY_USERS,
  624. c_szKbdSubstKey_DefUser,
  625. 0,
  626. KEY_ALL_ACCESS,
  627. &hKeySubst) != ERROR_SUCCESS)
  628. {
  629. RegCloseKey(hKeyPreload);
  630. return (FALSE);
  631. }
  632. }
  633. //
  634. // Enumerate the values in the Preload key.
  635. //
  636. dwIndex = 0;
  637. cchSubValue = sizeof(szSubValue) / sizeof(TCHAR);
  638. cbData = sizeof(szSubData);
  639. rc = RegEnumValue( hKeySubst,
  640. dwIndex,
  641. szSubValue,
  642. &cchSubValue,
  643. NULL,
  644. NULL,
  645. (LPBYTE)szSubData,
  646. &cbData );
  647. while (rc == ERROR_SUCCESS)
  648. {
  649. DWORD dwSubLayout;
  650. dwSubLayout = TransNum(szSubData);
  651. if (dwLayout == dwSubLayout)
  652. {
  653. dwLayout = TransNum(szSubValue);
  654. break;
  655. }
  656. //
  657. // Get the next enum value.
  658. //
  659. dwIndex++;
  660. cchSubValue = sizeof(szSubValue) / sizeof(TCHAR);
  661. cbData = sizeof(szSubData);
  662. rc = RegEnumValue( hKeySubst,
  663. dwIndex,
  664. szSubValue,
  665. &cchSubValue,
  666. NULL,
  667. NULL,
  668. (LPBYTE)szSubData,
  669. &cbData );
  670. }
  671. //
  672. // Set default layout into preload section
  673. //
  674. iPreloadInx = 1;
  675. while(1)
  676. {
  677. DWORD dwCurLayout;
  678. DWORD dwFirstLayout;
  679. //
  680. // See if there is a substitute value.
  681. //
  682. StringCchPrintf(szPreloadInx, ARRAYSIZE(szPreloadInx), TEXT("%d"), iPreloadInx);
  683. cbData = sizeof(szPreload);
  684. if (RegQueryValueEx(hKeyPreload,
  685. szPreloadInx,
  686. NULL,
  687. NULL,
  688. (LPBYTE)szPreload,
  689. &cbData ) == ERROR_SUCCESS)
  690. {
  691. dwCurLayout = TransNum(szPreload);
  692. }
  693. else
  694. {
  695. break;
  696. }
  697. if (!dwCurLayout)
  698. break;
  699. if (iPreloadInx == 1)
  700. dwFirstLayout = dwCurLayout;
  701. if (dwCurLayout == dwLayout)
  702. {
  703. bRet = TRUE;
  704. if (iPreloadInx != 1)
  705. {
  706. //
  707. // Set new default keyboard layout
  708. //
  709. StringCchPrintf(szPreloadInx, ARRAYSIZE(szPreloadInx), TEXT("%d"), 1);
  710. StringCchPrintf(szPreload, ARRAYSIZE(szPreload), TEXT("%08x"), dwCurLayout);
  711. RegSetValueEx( hKeyPreload,
  712. szPreloadInx,
  713. 0,
  714. REG_SZ,
  715. (LPBYTE)szPreload,
  716. (DWORD)(lstrlen(szPreload) + 1) * sizeof(TCHAR) );
  717. //
  718. // Set old default keyboard layout
  719. //
  720. StringCchPrintf(szPreloadInx, ARRAYSIZE(szPreloadInx), TEXT("%d"), iPreloadInx);
  721. StringCchPrintf(szPreload, ARRAYSIZE(szPreload), TEXT("%08x"), dwFirstLayout);
  722. RegSetValueEx( hKeyPreload,
  723. szPreloadInx,
  724. 0,
  725. REG_SZ,
  726. (LPBYTE)szPreload,
  727. (DWORD)(lstrlen(szPreload) + 1) * sizeof(TCHAR) );
  728. }
  729. //
  730. // Activate new default keyboard layout
  731. //
  732. ActivateDefaultKeyboardLayout(dwLocale, dwLayout, hklDefault);
  733. break;
  734. }
  735. iPreloadInx++;
  736. }
  737. //
  738. // Refresh Preload section and close key.
  739. //
  740. RegFlushKey(hKeyPreload);
  741. RegCloseKey(hKeyPreload);
  742. RegCloseKey(hKeySubst);
  743. //
  744. // Return success.
  745. //
  746. return (bRet);
  747. }
  748. ////////////////////////////////////////////////////////////////////////////
  749. //
  750. // SetFETipStatus
  751. //
  752. ////////////////////////////////////////////////////////////////////////////
  753. BOOL SetFETipStatus(
  754. DWORD dwLayout,
  755. BOOL bEnable)
  756. {
  757. HRESULT hr;
  758. BOOL bReturn = FALSE;
  759. BOOL bFound = FALSE;
  760. IEnumTfLanguageProfiles *pEnum;
  761. ITfInputProcessorProfiles *pProfiles = NULL;
  762. //
  763. // load Assembly list
  764. //
  765. hr = CoCreateInstance(&CLSID_TF_InputProcessorProfiles,
  766. NULL,
  767. CLSCTX_INPROC_SERVER,
  768. &IID_ITfInputProcessorProfiles,
  769. (LPVOID *) &pProfiles);
  770. if (FAILED(hr))
  771. return bReturn;
  772. //
  773. // Enum all available languages
  774. //
  775. if (SUCCEEDED(pProfiles->lpVtbl->EnumLanguageProfiles(pProfiles, 0, &pEnum)))
  776. {
  777. TF_LANGUAGEPROFILE tflp;
  778. while (pEnum->lpVtbl->Next(pEnum, 1, &tflp, NULL) == S_OK)
  779. {
  780. HKL hklSub;
  781. if (!IsEqualGUID(&tflp.catid, &GUID_TFCAT_TIP_KEYBOARD))
  782. {
  783. continue;
  784. }
  785. hklSub = GetSubstituteHKL(&tflp.clsid,
  786. tflp.langid,
  787. &tflp.guidProfile);
  788. if (hklSub == IntToPtr(dwLayout))
  789. {
  790. hr = pProfiles->lpVtbl->EnableLanguageProfile(
  791. pProfiles,
  792. &tflp.clsid,
  793. tflp.langid,
  794. &tflp.guidProfile,
  795. bEnable);
  796. if (FAILED(hr))
  797. goto Exit;
  798. bFound = TRUE;
  799. }
  800. }
  801. if (bFound)
  802. bReturn = TRUE;
  803. Exit:
  804. pEnum->lpVtbl->Release(pEnum);
  805. }
  806. if (pProfiles)
  807. pProfiles->lpVtbl->Release(pProfiles);
  808. return bReturn;
  809. }
  810. ////////////////////////////////////////////////////////////////////////////
  811. //
  812. // InstallInputLayout
  813. //
  814. ////////////////////////////////////////////////////////////////////////////
  815. BOOL InstallInputLayout(
  816. LCID lcid,
  817. DWORD dwLayout,
  818. BOOL bDefLayout,
  819. HKL hklDefault,
  820. BOOL bDefUser,
  821. BOOL bSysLocale)
  822. {
  823. LONG rc;
  824. LCID SysLocale;
  825. HKEY hKeySubst;
  826. HKEY hKeyPreload;
  827. BOOL bRet = FALSE;
  828. BOOL bThai = FALSE;
  829. BOOL bHasIME = FALSE;
  830. DWORD dwPreloadNum = 0;
  831. TCHAR szValue[MAX_PATH];
  832. TCHAR szData[MAX_PATH];
  833. TCHAR szData2[MAX_PATH];
  834. LPLAYOUTLIST pLayoutList = NULL;
  835. DWORD dwIndex, cchValue, cbData, cbData2;
  836. DWORD dwValue, dwData, dwData2, dwCtr, dwCtr2;
  837. DWORD dwNum = 1; // Only support 1 layout installing
  838. HKL hklNew = 0;
  839. //
  840. // Create the array to store the list of input locales.
  841. //
  842. pLayoutList = (LPLAYOUTLIST)LocalAlloc(LPTR, sizeof(LAYOUTLIST) * dwNum + 1);
  843. if (pLayoutList == NULL)
  844. {
  845. goto Exit;
  846. }
  847. //
  848. // Currently support only one install layout list
  849. //
  850. pLayoutList[0].dwLocale = lcid;
  851. pLayoutList[0].dwLayout = dwLayout;
  852. if ((HIWORD(pLayoutList[0].dwLayout) & 0xf000) == 0xe000)
  853. {
  854. pLayoutList[0].bIME = TRUE;
  855. }
  856. //
  857. // Open the HKCU\Keyboard Layout\Preload key.
  858. //
  859. if (!bDefUser)
  860. {
  861. if (RegOpenKeyEx( HKEY_CURRENT_USER,
  862. c_szKbdPreloadKey,
  863. 0,
  864. KEY_ALL_ACCESS,
  865. &hKeyPreload ) != ERROR_SUCCESS)
  866. {
  867. goto Exit;
  868. }
  869. }
  870. else
  871. {
  872. if (RegOpenKeyEx( HKEY_USERS,
  873. c_szKbdPreloadKey_DefUser,
  874. 0,
  875. KEY_ALL_ACCESS,
  876. &hKeyPreload ) != ERROR_SUCCESS)
  877. {
  878. goto Exit;
  879. }
  880. }
  881. //
  882. // Open the HKCU\Keyboard Layout\Substitutes key.
  883. //
  884. if (!bDefUser)
  885. {
  886. if (RegOpenKeyEx( HKEY_CURRENT_USER,
  887. c_szKbdSubstKey,
  888. 0,
  889. KEY_ALL_ACCESS,
  890. &hKeySubst ) != ERROR_SUCCESS)
  891. {
  892. RegCloseKey(hKeyPreload);
  893. goto Exit;
  894. }
  895. }
  896. else
  897. {
  898. if (RegOpenKeyEx( HKEY_USERS,
  899. c_szKbdSubstKey_DefUser,
  900. 0,
  901. KEY_ALL_ACCESS,
  902. &hKeySubst ) != ERROR_SUCCESS)
  903. {
  904. RegCloseKey(hKeyPreload);
  905. goto Exit;
  906. }
  907. }
  908. //
  909. // Enumerate the values in the Preload key.
  910. //
  911. dwIndex = 0;
  912. cchValue = sizeof(szValue) / sizeof(TCHAR);
  913. cbData = sizeof(szData);
  914. rc = RegEnumValue( hKeyPreload,
  915. dwIndex,
  916. szValue,
  917. &cchValue,
  918. NULL,
  919. NULL,
  920. (LPBYTE)szData,
  921. &cbData );
  922. while (rc == ERROR_SUCCESS)
  923. {
  924. //
  925. // Save the preload number if it's higher than the highest one
  926. // found so far.
  927. //
  928. dwValue = TransNum(szValue);
  929. if (dwValue > dwPreloadNum)
  930. {
  931. dwPreloadNum = dwValue;
  932. }
  933. //
  934. // Save the preload data - input locale.
  935. //
  936. dwValue = TransNum(szData);
  937. if (PRIMARYLANGID(LOWORD(dwValue)) == LANG_THAI)
  938. {
  939. bThai = TRUE;
  940. }
  941. //
  942. // See if there is a substitute value.
  943. //
  944. dwData = 0;
  945. cbData2 = sizeof(szData2);
  946. if (RegQueryValueEx( hKeySubst,
  947. szData,
  948. NULL,
  949. NULL,
  950. (LPBYTE)szData2,
  951. &cbData2 ) == ERROR_SUCCESS)
  952. {
  953. dwData = TransNum(szData2);
  954. }
  955. //
  956. // Go through each of the requested input locales and make sure
  957. // they don't already exist.
  958. //
  959. for (dwCtr = 0; dwCtr < dwNum; dwCtr++)
  960. {
  961. if (LOWORD(pLayoutList[dwCtr].dwLocale) == LOWORD(dwValue))
  962. {
  963. if (dwData)
  964. {
  965. if (pLayoutList[dwCtr].dwLayout == dwData)
  966. {
  967. pLayoutList[dwCtr].bLoaded = TRUE;
  968. }
  969. }
  970. else if (pLayoutList[dwCtr].dwLayout == dwValue)
  971. {
  972. pLayoutList[dwCtr].bLoaded = TRUE;
  973. }
  974. //
  975. // Save the highest 0xd000 value for this input locale.
  976. //
  977. if (pLayoutList[dwCtr].bIME == FALSE)
  978. {
  979. dwData2 = (DWORD)(HIWORD(dwValue));
  980. if (((dwData2 & 0xf000) != 0xe000) &&
  981. (pLayoutList[dwCtr].dwSubst <= dwData2))
  982. {
  983. if (dwData2 == 0)
  984. {
  985. pLayoutList[dwCtr].dwSubst = 0xd000;
  986. }
  987. else if ((dwData2 & 0xf000) == 0xd000)
  988. {
  989. pLayoutList[dwCtr].dwSubst = dwData2 + 1;
  990. }
  991. }
  992. }
  993. }
  994. }
  995. //
  996. // Get the next enum value.
  997. //
  998. dwIndex++;
  999. cchValue = sizeof(szValue) / sizeof(TCHAR);
  1000. szValue[0] = TEXT('\0');
  1001. cbData = sizeof(szData);
  1002. szData[0] = TEXT('\0');
  1003. rc = RegEnumValue( hKeyPreload,
  1004. dwIndex,
  1005. szValue,
  1006. &cchValue,
  1007. NULL,
  1008. NULL,
  1009. (LPBYTE)szData,
  1010. &cbData );
  1011. }
  1012. //
  1013. // Increase the maximum preload value by one so that it represents the
  1014. // next available value to use.
  1015. //
  1016. dwPreloadNum++;
  1017. //
  1018. // Go through the list of layouts and add them.
  1019. //
  1020. for (dwCtr = 0; dwCtr < dwNum; dwCtr++)
  1021. {
  1022. if ((pLayoutList[dwCtr].bLoaded == FALSE) &&
  1023. (IsValidLocale(pLayoutList[dwCtr].dwLocale, LCID_INSTALLED)) &&
  1024. (IsValidLayout(pLayoutList[dwCtr].dwLayout)))
  1025. {
  1026. //
  1027. // Save the preload number as a string so that it can be
  1028. // written into the registry.
  1029. //
  1030. StringCchPrintf(szValue, ARRAYSIZE(szValue), TEXT("%d"), dwPreloadNum);
  1031. if (PRIMARYLANGID(LOWORD(pLayoutList[dwCtr].dwLocale)) == LANG_THAI)
  1032. {
  1033. bThai = TRUE;
  1034. }
  1035. //
  1036. // Save the locale id as a string so that it can be written
  1037. // into the registry.
  1038. //
  1039. if (pLayoutList[dwCtr].bIME == TRUE)
  1040. {
  1041. StringCchPrintf(szData, ARRAYSIZE(szData), TEXT("%08x"), pLayoutList[dwCtr].dwLayout);
  1042. bHasIME = TRUE;
  1043. }
  1044. else
  1045. {
  1046. //
  1047. // Get the 0xd000 value, if necessary.
  1048. //
  1049. if (dwCtr != 0)
  1050. {
  1051. dwCtr2 = dwCtr;
  1052. do
  1053. {
  1054. dwCtr2--;
  1055. if ((pLayoutList[dwCtr2].bLoaded == FALSE) &&
  1056. (pLayoutList[dwCtr].dwLocale ==
  1057. pLayoutList[dwCtr2].dwLocale) &&
  1058. (pLayoutList[dwCtr2].bIME == FALSE))
  1059. {
  1060. dwData2 = pLayoutList[dwCtr2].dwSubst;
  1061. if (dwData2 == 0)
  1062. {
  1063. pLayoutList[dwCtr].dwSubst = 0xd000;
  1064. }
  1065. else
  1066. {
  1067. pLayoutList[dwCtr].dwSubst = dwData2 + 1;
  1068. }
  1069. break;
  1070. }
  1071. } while (dwCtr2 != 0);
  1072. }
  1073. //
  1074. // Save the locale id as a string.
  1075. //
  1076. dwData2 = pLayoutList[dwCtr].dwLocale;
  1077. dwData2 |= (DWORD)(pLayoutList[dwCtr].dwSubst << 16);
  1078. StringCchPrintf(szData, ARRAYSIZE(szData), TEXT("%08x"), dwData2);
  1079. }
  1080. //
  1081. // Set the value in the Preload section of the registry.
  1082. //
  1083. RegSetValueEx( hKeyPreload,
  1084. szValue,
  1085. 0,
  1086. REG_SZ,
  1087. (LPBYTE)szData,
  1088. (DWORD)(lstrlen(szData) + 1) * sizeof(TCHAR) );
  1089. //
  1090. // Increment the preload value.
  1091. //
  1092. dwPreloadNum++;
  1093. //
  1094. // See if we need to add a substitute for this input locale.
  1095. //
  1096. if (((pLayoutList[dwCtr].dwLocale != pLayoutList[dwCtr].dwLayout) ||
  1097. (pLayoutList[dwCtr].dwSubst != 0)) &&
  1098. (pLayoutList[dwCtr].bIME == FALSE))
  1099. {
  1100. StringCchPrintf(szData2, ARRAYSIZE(szData2), TEXT("%08x"), pLayoutList[dwCtr].dwLayout);
  1101. RegSetValueEx( hKeySubst,
  1102. szData,
  1103. 0,
  1104. REG_SZ,
  1105. (LPBYTE)szData2,
  1106. (DWORD)(lstrlen(szData) + 1) * sizeof(TCHAR) );
  1107. }
  1108. //
  1109. // Make sure all of the changes are written to disk.
  1110. //
  1111. RegFlushKey(hKeySubst);
  1112. RegFlushKey(hKeyPreload);
  1113. //
  1114. // Load the keyboard layout.
  1115. // If it fails, there isn't much we can do at this point.
  1116. //
  1117. hklNew = LoadKeyboardLayout(szData, KLF_SUBSTITUTE_OK | KLF_NOTELLSHELL);
  1118. }
  1119. }
  1120. //
  1121. // Add FE TIPs if the current requested keyboard layout is the substitute
  1122. // keyboard layout of TIP.
  1123. //
  1124. if (((HIWORD(dwLayout) & 0xf000) == 0xe000) &&
  1125. (PRIMARYLANGID(LOWORD(dwLayout)) != LANG_CHINESE))
  1126. {
  1127. BOOL bEnable = TRUE;
  1128. SetFETipStatus(dwLayout, bEnable);
  1129. }
  1130. //
  1131. // Get default system locale
  1132. //
  1133. if (bSysLocale)
  1134. SysLocale = lcid;
  1135. else
  1136. SysLocale = GetSystemDefaultLCID();
  1137. //
  1138. // If there is an IME and there is no hotkey switch, set it to
  1139. // Ctrl+Shift. Otherwise, the user cannot switch to an IME without
  1140. // setting the value first.
  1141. //
  1142. if (bHasIME || (dwPreloadNum > 2))
  1143. {
  1144. UpdateDefaultHotkey(
  1145. SysLocale,
  1146. (PRIMARYLANGID(LANGIDFROMLCID(SysLocale)) == LANG_THAI)
  1147. && bThai,
  1148. bDefUser);
  1149. }
  1150. //
  1151. // Update the taskbar indicator.
  1152. //
  1153. if (!IsDisableCtfmon() && dwPreloadNum > 2)
  1154. {
  1155. LoadCtfmon(TRUE, SysLocale, bDefUser);
  1156. }
  1157. //
  1158. // Close the registry keys.
  1159. //
  1160. RegCloseKey(hKeyPreload);
  1161. RegCloseKey(hKeySubst);
  1162. bRet = TRUE;
  1163. //
  1164. // Update preload section with new default keyboard layout
  1165. //
  1166. if (bDefLayout)
  1167. {
  1168. TCHAR szDefLayout[MAX_PATH];
  1169. StringCchPrintf(szDefLayout, ARRAYSIZE(szDefLayout), TEXT("%08x"), dwLayout);
  1170. hklNew = LoadKeyboardLayout(szDefLayout, KLF_SUBSTITUTE_OK |
  1171. KLF_REPLACELANG |
  1172. KLF_NOTELLSHELL);
  1173. if (hklNew)
  1174. bRet = SetSystemDefautLayout(lcid, dwLayout, hklNew, bDefUser);
  1175. }
  1176. Exit:
  1177. if (pLayoutList)
  1178. LocalFree(pLayoutList);
  1179. return bRet;
  1180. }
  1181. ////////////////////////////////////////////////////////////////////////////
  1182. //
  1183. // UnInstallInputLayout
  1184. //
  1185. ////////////////////////////////////////////////////////////////////////////
  1186. BOOL UnInstallInputLayout(
  1187. LCID lcid,
  1188. DWORD dwLayout,
  1189. BOOL bDefUser)
  1190. {
  1191. LCID SysLocale;
  1192. HKEY hKeySubst;
  1193. HKEY hKeyPreload;
  1194. BOOL bHasSubst;
  1195. DWORD cbData;
  1196. DWORD dwCurLayout;
  1197. UINT uMatch = 0;
  1198. UINT uPreloadNum;
  1199. UINT uPreloadInx = 1;
  1200. BOOL bRet = FALSE;
  1201. BOOL fReset = FALSE;
  1202. BOOL bRemoveAllLang = FALSE;
  1203. TCHAR szSubst[MAX_PATH];
  1204. TCHAR szPreload[MAX_PATH];
  1205. TCHAR szPreloadInx[MAX_PATH];
  1206. //
  1207. // Remove all language layouts from system
  1208. //
  1209. if (lcid && dwLayout == 0)
  1210. {
  1211. bRemoveAllLang = TRUE;
  1212. dwLayout = PRIMARYLANGID(LANGIDFROMLCID(lcid));
  1213. }
  1214. //
  1215. // Open the HKCU\Keyboard Layout\Preload key.
  1216. //
  1217. if (!bDefUser)
  1218. {
  1219. if (RegOpenKeyEx( HKEY_CURRENT_USER,
  1220. c_szKbdPreloadKey,
  1221. 0,
  1222. KEY_ALL_ACCESS,
  1223. &hKeyPreload ) != ERROR_SUCCESS)
  1224. {
  1225. goto Exit;
  1226. }
  1227. }
  1228. else
  1229. {
  1230. if (RegOpenKeyEx( HKEY_USERS,
  1231. c_szKbdPreloadKey_DefUser,
  1232. 0,
  1233. KEY_ALL_ACCESS,
  1234. &hKeyPreload ) != ERROR_SUCCESS)
  1235. {
  1236. goto Exit;
  1237. }
  1238. }
  1239. //
  1240. // Open the HKCU\Keyboard Layout\Substitutes key.
  1241. //
  1242. if (!bDefUser)
  1243. {
  1244. if (RegOpenKeyEx( HKEY_CURRENT_USER,
  1245. c_szKbdSubstKey,
  1246. 0,
  1247. KEY_ALL_ACCESS,
  1248. &hKeySubst ) != ERROR_SUCCESS)
  1249. {
  1250. RegCloseKey(hKeyPreload);
  1251. goto Exit;
  1252. }
  1253. }
  1254. else
  1255. {
  1256. if (RegOpenKeyEx( HKEY_USERS,
  1257. c_szKbdSubstKey_DefUser,
  1258. 0,
  1259. KEY_ALL_ACCESS,
  1260. &hKeySubst ) != ERROR_SUCCESS)
  1261. {
  1262. RegCloseKey(hKeyPreload);
  1263. goto Exit;
  1264. }
  1265. }
  1266. uPreloadInx = 1;
  1267. //
  1268. // See if there is a substitute value.
  1269. //
  1270. StringCchPrintf(szPreloadInx, ARRAYSIZE(szPreloadInx), TEXT("%d"), uPreloadInx);
  1271. cbData = sizeof(szPreload);
  1272. while (RegQueryValueEx(hKeyPreload,
  1273. szPreloadInx,
  1274. NULL,
  1275. NULL,
  1276. (LPBYTE)szPreload,
  1277. &cbData ) == ERROR_SUCCESS)
  1278. {
  1279. dwCurLayout = TransNum(szPreload);
  1280. //
  1281. // See if there is a substitute value.
  1282. //
  1283. bHasSubst = FALSE;
  1284. cbData = sizeof(szSubst);
  1285. if (RegQueryValueEx(hKeySubst,
  1286. szPreload,
  1287. NULL,
  1288. NULL,
  1289. (LPBYTE)szSubst,
  1290. &cbData) == ERROR_SUCCESS)
  1291. {
  1292. dwCurLayout = TransNum(szSubst);
  1293. bHasSubst = TRUE;
  1294. }
  1295. if ((dwCurLayout == dwLayout) ||
  1296. (bRemoveAllLang &&
  1297. (PRIMARYLANGID(LANGIDFROMLCID(dwCurLayout)) == dwLayout)))
  1298. {
  1299. uPreloadInx++;
  1300. StringCchPrintf(szPreloadInx, ARRAYSIZE(szPreloadInx), TEXT("%d"), uPreloadInx);
  1301. uMatch++;
  1302. fReset = TRUE;
  1303. if (bHasSubst)
  1304. {
  1305. RegDeleteValue(hKeySubst, szPreload);
  1306. }
  1307. continue;
  1308. }
  1309. if (fReset && uMatch)
  1310. {
  1311. if (uPreloadInx <= uMatch)
  1312. {
  1313. goto Exit;
  1314. }
  1315. //
  1316. // Reordering the preload keyboard layouts
  1317. //
  1318. StringCchPrintf(szPreloadInx, ARRAYSIZE(szPreloadInx), TEXT("%d"), uPreloadInx - uMatch);
  1319. StringCchPrintf(szPreload, ARRAYSIZE(szPreload), TEXT("%08x"), dwCurLayout);
  1320. RegSetValueEx(hKeyPreload,
  1321. szPreloadInx,
  1322. 0,
  1323. REG_SZ,
  1324. (LPBYTE)szPreload,
  1325. (DWORD)(lstrlen(szPreload) + 1) * sizeof(TCHAR));
  1326. }
  1327. uPreloadInx++;
  1328. StringCchPrintf(szPreloadInx, ARRAYSIZE(szPreloadInx), TEXT("%d"), uPreloadInx);
  1329. }
  1330. uPreloadNum = uPreloadInx - uMatch;
  1331. while (fReset && uMatch && uPreloadInx)
  1332. {
  1333. if (uPreloadInx <= uMatch || (uPreloadInx - uMatch) <= 1)
  1334. goto Exit;
  1335. //
  1336. // Uninstall the specified keyboard layout
  1337. //
  1338. StringCchPrintf(szPreloadInx, ARRAYSIZE(szPreloadInx), TEXT("%d"), uPreloadInx - uMatch);
  1339. RegDeleteValue(hKeyPreload, szPreloadInx);
  1340. uMatch--;
  1341. }
  1342. //
  1343. // Close the registry keys.
  1344. //
  1345. RegCloseKey(hKeyPreload);
  1346. RegCloseKey(hKeySubst);
  1347. #if 0
  1348. if (hklUnload)
  1349. {
  1350. //
  1351. // Get the active keyboard layout list from the system.
  1352. //
  1353. if (!SystemParametersInfo(SPI_GETDEFAULTINPUTLANG,
  1354. 0,
  1355. &hklDefault,
  1356. 0 ))
  1357. {
  1358. hklDefault = GetKeyboardLayout(0);
  1359. }
  1360. if (hklUnload == hklDefault)
  1361. {
  1362. if (!SystemParametersInfo( SPI_SETDEFAULTINPUTLANG,
  1363. 0,
  1364. (LPVOID)((LPDWORD)&hklNewDefault),
  1365. 0 ))
  1366. {
  1367. goto Exit;
  1368. }
  1369. else
  1370. {
  1371. DWORD dwRecipients = BSM_APPLICATIONS | BSM_ALLDESKTOPS;
  1372. BroadcastSystemMessage( BSF_POSTMESSAGE,
  1373. &dwRecipients,
  1374. WM_INPUTLANGCHANGEREQUEST,
  1375. 1,
  1376. (LPARAM)hklNewDefault );
  1377. }
  1378. }
  1379. UnloadKeyboardLayout(hklUnload);
  1380. }
  1381. #endif
  1382. //
  1383. // Add FE TIPs if the current requested keyboard layout is the substitute
  1384. // keyboard layout of TIP.
  1385. //
  1386. if (((HIWORD(dwLayout) & 0xf000) == 0xe000) &&
  1387. (PRIMARYLANGID(LOWORD(dwLayout)) != LANG_CHINESE))
  1388. {
  1389. BOOL bEnable = FALSE;
  1390. SetFETipStatus(dwLayout, bEnable);
  1391. }
  1392. //
  1393. // Get default system locale
  1394. //
  1395. SysLocale = GetSystemDefaultLCID();
  1396. //
  1397. // Update the taskbar indicator.
  1398. //
  1399. if (uPreloadNum <= 2)
  1400. {
  1401. LoadCtfmon(FALSE, SysLocale, bDefUser);
  1402. ClearHotKey(bDefUser);
  1403. }
  1404. bRet = TRUE;
  1405. Exit:
  1406. return bRet;
  1407. }