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.

2662 lines
70 KiB

  1. #include "private.h"
  2. #include "globals.h"
  3. #include "regsvr.h"
  4. #include "catutil.h"
  5. #include "cregkey.h"
  6. #include "assembly.h"
  7. #include "immxutil.h"
  8. #include "osver.h"
  9. #include "internat.h"
  10. #include "cicmutex.h"
  11. #include "imelist.h"
  12. #include "tim.h"
  13. extern CCicMutex g_mutexAsm;
  14. extern char g_szAsmListCache[];
  15. extern HRESULT g_EnumItemsInCategory(REFGUID rcatid, IEnumGUID **ppEnum);
  16. //+---------------------------------------------------------------------------
  17. //
  18. // TF_GetLangIcon
  19. //
  20. //+---------------------------------------------------------------------------
  21. HICON WINAPI TF_GetLangIcon(WORD langid , WCHAR *psz, UINT cchMax)
  22. {
  23. if (psz)
  24. {
  25. SYSTHREAD *psfn = GetSYSTHREAD();
  26. CAssemblyList *pAsmList;
  27. *psz = L'\0';
  28. if (psfn && (pAsmList = EnsureAssemblyList(psfn)))
  29. {
  30. CAssembly *pAsm = pAsmList->FindAssemblyByLangId(langid);
  31. if (pAsm)
  32. {
  33. StringCchCopyW(psz, cchMax, pAsm->GetLangName());
  34. }
  35. }
  36. }
  37. return InatCreateIcon(langid);
  38. }
  39. //----------------------------------------------------------------------------
  40. //
  41. // GetSubstituteHKLfromKey
  42. //
  43. //----------------------------------------------------------------------------
  44. HKL GetSubstituteHKLfromKey(CMyRegKey *pkey, LANGID langid)
  45. {
  46. char sz[16];
  47. if (pkey->QueryValueCch(sz, c_szSubstitutehKL, ARRAYSIZE(sz)) != S_OK)
  48. return NULL;
  49. HKL hkl = NULL;
  50. if ((sz[0] == '0') && ((sz[1] == 'X') || (sz[1] == 'x')))
  51. {
  52. hkl = (HKL)IntToPtr(AsciiToNum(&sz[2]));
  53. if (LOWORD(HandleToLong(hkl)) != langid)
  54. {
  55. //
  56. // bad substitution.
  57. //
  58. Assert(0);
  59. hkl = 0;
  60. }
  61. }
  62. return hkl;
  63. }
  64. //////////////////////////////////////////////////////////////////////////////
  65. //
  66. // CAssembly
  67. //
  68. //////////////////////////////////////////////////////////////////////////////
  69. //+---------------------------------------------------------------------------
  70. //
  71. // ctor
  72. //
  73. //----------------------------------------------------------------------------
  74. CAssembly::CAssembly(LANGID langid)
  75. {
  76. _langid = langid;
  77. if (IsOnNT())
  78. {
  79. if (!GetLocaleInfoW(MAKELCID(langid, SORT_DEFAULT),
  80. LOCALE_SLANGUAGE,
  81. _szLangName,
  82. ARRAYSIZE(_szLangName)))
  83. {
  84. StringCchCopyW(_szLangName, ARRAYSIZE(_szLangName), L"Unknown Language");
  85. }
  86. else
  87. {
  88. _szLangName[ARRAYSIZE(_szLangName)-1] = 0; // in case GetLocaleInfoW truncates
  89. }
  90. }
  91. else
  92. {
  93. char szLangName[64];
  94. if (GetLocaleInfo(MAKELCID(langid, SORT_DEFAULT),
  95. LOCALE_SLANGUAGE,
  96. szLangName,
  97. sizeof(szLangName)))
  98. {
  99. szLangName[ARRAYSIZE(szLangName)-1] = 0; // in case GetLocaleInfoW truncates
  100. StringCchCopyW(_szLangName, ARRAYSIZE(_szLangName), AtoW(szLangName));
  101. }
  102. else
  103. {
  104. StringCchCopyW(_szLangName, ARRAYSIZE(_szLangName), L"Unknown Language");
  105. }
  106. }
  107. }
  108. //+---------------------------------------------------------------------------
  109. //
  110. // dtor
  111. //
  112. //----------------------------------------------------------------------------
  113. CAssembly::~CAssembly()
  114. {
  115. }
  116. //+---------------------------------------------------------------------------
  117. //
  118. // IsFEIMEActive()
  119. //
  120. //----------------------------------------------------------------------------
  121. BOOL CAssembly::IsFEIMEActive()
  122. {
  123. int i;
  124. if (IsFELangId(GetLangId()))
  125. {
  126. for (i = 0; i < Count(); i++)
  127. {
  128. ASSEMBLYITEM *pItem = GetItem(i);
  129. if (pItem->fActive && IsPureIMEHKL(pItem->hkl))
  130. {
  131. Assert(IsEqualGUID(pItem->clsid, GUID_NULL));
  132. return TRUE;
  133. }
  134. }
  135. }
  136. #ifdef CHECKFEIMESELECTED
  137. if (_fUnknownFEIMESelected)
  138. return TRUE;
  139. #endif CHECKFEIMESELECTED
  140. return FALSE;
  141. }
  142. //+---------------------------------------------------------------------------
  143. //
  144. // FindItemByCategory
  145. //
  146. //----------------------------------------------------------------------------
  147. ASSEMBLYITEM *CAssembly::FindItemByCategory(REFGUID catid)
  148. {
  149. int nCnt = _rgAsmItem.Count();
  150. int i;
  151. if (IsEqualGUID(catid, GUID_NULL))
  152. return NULL;
  153. for (i = 0; i < nCnt; i++)
  154. {
  155. ASSEMBLYITEM *pItemTmp;
  156. pItemTmp = _rgAsmItem.GetPtr(i);
  157. if (IsEqualGUID(pItemTmp->catid, catid))
  158. return pItemTmp;
  159. }
  160. return NULL;
  161. }
  162. //+---------------------------------------------------------------------------
  163. //
  164. // FindActiveKeyboardItem
  165. //
  166. // Why do you call this if there is no FocusDIM? You should not do.
  167. // fActive is not reliable if there is no FocusDIM.
  168. // Ser SetFocusDIMForAssembly(BOOL fSetFocus) in profiles.cpp. we don't
  169. // change fActive but switch hKL when the focus moves to non DIM control.
  170. //
  171. //----------------------------------------------------------------------------
  172. ASSEMBLYITEM *CAssembly::FindActiveKeyboardItem()
  173. {
  174. int nCnt = _rgAsmItem.Count();
  175. int i;
  176. for (i = 0; i < nCnt; i++)
  177. {
  178. ASSEMBLYITEM *pItemTmp;
  179. pItemTmp = _rgAsmItem.GetPtr(i);
  180. if (!pItemTmp->fEnabled)
  181. continue;
  182. if (!pItemTmp->fActive)
  183. continue;
  184. if (IsEqualGUID(pItemTmp->catid, GUID_TFCAT_TIP_KEYBOARD))
  185. return pItemTmp;
  186. }
  187. return NULL;
  188. }
  189. //+---------------------------------------------------------------------------
  190. //
  191. // FindKeyboardLayoutItem
  192. //
  193. //----------------------------------------------------------------------------
  194. ASSEMBLYITEM *CAssembly::FindKeyboardLayoutItem(HKL hkl)
  195. {
  196. int nCnt = _rgAsmItem.Count();
  197. int i;
  198. for (i = 0; i < nCnt; i++)
  199. {
  200. ASSEMBLYITEM *pItemTmp;
  201. pItemTmp = _rgAsmItem.GetPtr(i);
  202. if (!IsEqualGUID(pItemTmp->clsid, GUID_NULL))
  203. continue;
  204. if (IsEqualGUID(pItemTmp->catid, GUID_TFCAT_TIP_KEYBOARD) &&
  205. (pItemTmp->hkl == hkl))
  206. {
  207. return pItemTmp;
  208. }
  209. }
  210. return NULL;
  211. }
  212. //+---------------------------------------------------------------------------
  213. //
  214. // FindItemByCategory2
  215. //
  216. //----------------------------------------------------------------------------
  217. BOOL CAssembly::IsEnabledItemByCategory(REFGUID catid)
  218. {
  219. int nCnt = _rgAsmItem.Count();
  220. int i;
  221. if (IsEqualGUID(catid, GUID_NULL))
  222. return FALSE;
  223. for (i = 0; i < nCnt; i++)
  224. {
  225. ASSEMBLYITEM *pItemTmp;
  226. pItemTmp = _rgAsmItem.GetPtr(i);
  227. if (!IsEqualGUID(pItemTmp->catid, catid) && pItemTmp->fEnabled)
  228. return TRUE;
  229. }
  230. return FALSE;
  231. }
  232. //+---------------------------------------------------------------------------
  233. //
  234. // IsEnabledItem
  235. //
  236. //----------------------------------------------------------------------------
  237. BOOL CAssembly::IsEnabledItem()
  238. {
  239. int nCnt = _rgAsmItem.Count();
  240. int i;
  241. for (i = 0; i < nCnt; i++)
  242. {
  243. ASSEMBLYITEM *pItemTmp;
  244. pItemTmp = _rgAsmItem.GetPtr(i);
  245. if (pItemTmp->fEnabled)
  246. return TRUE;
  247. }
  248. return FALSE;
  249. }
  250. //+---------------------------------------------------------------------------
  251. //
  252. // FindPureKbdTipItem
  253. //
  254. //----------------------------------------------------------------------------
  255. ASSEMBLYITEM *CAssembly::FindPureKbdTipItem()
  256. {
  257. int nCnt = _rgAsmItem.Count();
  258. int i;
  259. for (i = 0; i < nCnt; i++)
  260. {
  261. ASSEMBLYITEM *pItemTmp;
  262. pItemTmp = _rgAsmItem.GetPtr(i);
  263. if (IsEqualGUID(pItemTmp->catid, GUID_TFCAT_TIP_KEYBOARD) && !IsPureIMEHKL(pItemTmp->hkl))
  264. return pItemTmp;
  265. }
  266. return NULL;
  267. }
  268. //+---------------------------------------------------------------------------
  269. //
  270. // IsNonCiceroItem
  271. //
  272. //----------------------------------------------------------------------------
  273. BOOL CAssembly::IsNonCiceroItem()
  274. {
  275. int nCnt = _rgAsmItem.Count();
  276. int i;
  277. BOOL fFound = FALSE;
  278. for (i = 0; i < nCnt; i++)
  279. {
  280. ASSEMBLYITEM *pItemTmp;
  281. pItemTmp = _rgAsmItem.GetPtr(i);
  282. if (!pItemTmp->fEnabled)
  283. continue;
  284. if (!IsEqualGUID(pItemTmp->catid, GUID_TFCAT_TIP_KEYBOARD))
  285. continue;
  286. if (IsEqualGUID(pItemTmp->clsid, GUID_NULL))
  287. {
  288. if (IsFELangId(LOWORD((DWORD)(LONG_PTR)(HKL)pItemTmp->hkl)))
  289. {
  290. if (!IsPureIMEHKL(pItemTmp->hkl))
  291. {
  292. // Assert(0);
  293. continue;
  294. }
  295. }
  296. return TRUE;
  297. }
  298. }
  299. return FALSE;
  300. }
  301. //+---------------------------------------------------------------------------
  302. //
  303. // IsEnabled
  304. //
  305. //----------------------------------------------------------------------------
  306. BOOL CAssembly::IsEnabled(SYSTHREAD *psfn)
  307. {
  308. CThreadInputMgr *ptim;
  309. ptim = CThreadInputMgr::_GetThisFromSYSTHREAD(psfn);
  310. if (!ptim || !ptim->_GetFocusDocInputMgr())
  311. return IsNonCiceroItem() ? TRUE : FALSE;
  312. return IsEnabledKeyboardItem(psfn);
  313. }
  314. //+---------------------------------------------------------------------------
  315. //
  316. // IsEnabledKeyboardItem
  317. //
  318. //----------------------------------------------------------------------------
  319. BOOL CAssembly::IsEnabledKeyboardItem(SYSTHREAD *psfn)
  320. {
  321. int nCnt = _rgAsmItem.Count();
  322. int i;
  323. BOOL fFound = FALSE;
  324. for (i = 0; i < nCnt; i++)
  325. {
  326. ASSEMBLYITEM *pItemTmp;
  327. pItemTmp = _rgAsmItem.GetPtr(i);
  328. if (!pItemTmp->fEnabled)
  329. continue;
  330. if (!IsEqualGUID(pItemTmp->catid, GUID_TFCAT_TIP_KEYBOARD))
  331. continue;
  332. fFound = TRUE;
  333. break;
  334. }
  335. return fFound;
  336. }
  337. //+---------------------------------------------------------------------------
  338. //
  339. // RebuildSubstitutedHKLList
  340. //
  341. //----------------------------------------------------------------------------
  342. void CAssembly::RebuildSubstitutedHKLList()
  343. {
  344. int i;
  345. _rghklSubstituted.Clear();
  346. for (i = 0; i < Count(); i++)
  347. {
  348. ASSEMBLYITEM *pItem = GetItem(i);
  349. if (!pItem->fEnabled)
  350. continue;
  351. if (!pItem->hklSubstitute)
  352. continue;
  353. if (IsEqualGUID(pItem->catid, GUID_TFCAT_TIP_KEYBOARD) &&
  354. !IsEqualGUID(pItem->clsid, GUID_NULL))
  355. {
  356. HKL *phkl = _rghklSubstituted.Append(1);
  357. if (phkl)
  358. *phkl = pItem->hklSubstitute;
  359. }
  360. }
  361. }
  362. //+---------------------------------------------------------------------------
  363. //
  364. // IsSubstitutedHKL
  365. //
  366. //----------------------------------------------------------------------------
  367. BOOL CAssembly::IsSubstitutedHKL(HKL hkl)
  368. {
  369. int nCnt = _rghklSubstituted.Count();
  370. int i;
  371. for (i = 0; i < nCnt; i++)
  372. {
  373. HKL *phkl = _rghklSubstituted.GetPtr(i);
  374. if (*phkl == hkl)
  375. return TRUE;
  376. }
  377. return FALSE;
  378. }
  379. //+---------------------------------------------------------------------------
  380. //
  381. // GetSubstituteItem
  382. //
  383. //----------------------------------------------------------------------------
  384. ASSEMBLYITEM *CAssembly::GetSubstituteItem(HKL hKL)
  385. {
  386. int i;
  387. BOOL fCheckActive = TRUE;
  388. TryAgain:
  389. for (i = 0; i < Count(); i++)
  390. {
  391. ASSEMBLYITEM *pItem = GetItem(i);
  392. if (!pItem->fEnabled)
  393. continue;
  394. if (!pItem->hklSubstitute)
  395. continue;
  396. if (fCheckActive)
  397. {
  398. if (!pItem->fActive)
  399. continue;
  400. }
  401. if (IsEqualGUID(pItem->catid, GUID_TFCAT_TIP_KEYBOARD) &&
  402. !IsEqualGUID(pItem->clsid, GUID_NULL))
  403. {
  404. if (hKL == pItem->hklSubstitute)
  405. {
  406. return pItem;
  407. }
  408. }
  409. }
  410. if (fCheckActive)
  411. {
  412. fCheckActive = FALSE;
  413. goto TryAgain;
  414. }
  415. return NULL;
  416. }
  417. //////////////////////////////////////////////////////////////////////////////
  418. //
  419. // CDefaultProfiles
  420. //
  421. // This class is a database for the default profiles and this database is
  422. // created from HKCU\Software\Microsoft\CTF\TIP
  423. //
  424. // however we need to respect the system default hKL setting. If the keyboard
  425. // tip's profile has a substitute hKL and this is not the system default hKL
  426. // we use the system default hKL as a default profile.
  427. //
  428. //////////////////////////////////////////////////////////////////////////////
  429. class CDefaultProfiles
  430. {
  431. public:
  432. CDefaultProfiles(LANGID langid)
  433. {
  434. _langid = langid;
  435. }
  436. ~CDefaultProfiles()
  437. {
  438. _rgDefProfiles.Clear();
  439. }
  440. BOOL Init(HKL *phkl);
  441. BOOL FilterProfiles(CAssembly *pAsm);
  442. typedef struct tag_DEFAULTPROFILE
  443. {
  444. GUID catid;
  445. CLSID clsid;
  446. GUID guidProfile;
  447. HKL hkl;
  448. } DEFAULTPROFILE;
  449. BOOL GetDefaultProfile(GUID catid, GUID *pclsid, GUID *pguidProfile, HKL *phkl);
  450. BOOL Append(GUID catid, CLSID clsid, GUID guidProfile, HKL hkl)
  451. {
  452. DEFAULTPROFILE defpro;
  453. DEFAULTPROFILE *pdefpro;
  454. int i;
  455. for (i = 0; i < _rgDefProfiles.Count(); i++)
  456. {
  457. pdefpro = _rgDefProfiles.GetPtr(i);
  458. if (!pdefpro)
  459. {
  460. Assert(0);
  461. return FALSE;
  462. }
  463. if (IsEqualGUID(catid, pdefpro->catid))
  464. return FALSE;
  465. }
  466. defpro.catid = catid;
  467. defpro.clsid = clsid;
  468. defpro.guidProfile = guidProfile;
  469. defpro.hkl = hkl;
  470. pdefpro = _rgDefProfiles.Append(1);
  471. if (!pdefpro)
  472. return FALSE;
  473. memcpy(pdefpro, &defpro, sizeof(defpro));
  474. return TRUE;
  475. }
  476. private:
  477. BOOL GetSubstitutedItem(HKL hklSub, DEFAULTPROFILE *pdefpro);
  478. LANGID _langid;
  479. CStructArray<DEFAULTPROFILE> _rgDefProfiles;
  480. };
  481. //+---------------------------------------------------------------------------
  482. //
  483. // Init
  484. //
  485. //----------------------------------------------------------------------------
  486. BOOL CDefaultProfiles::Init(HKL *phkl)
  487. {
  488. CMyRegKey key;
  489. DWORD dw;
  490. char szKey[256];
  491. char szName[CLSID_STRLEN + 1];
  492. HKL hklDef = GetSystemDefaultHKL();
  493. BOOL fFoundKeyboardIteminDefLang = FALSE;
  494. DEFAULTPROFILE defpro;
  495. DEFAULTPROFILE *pdefpro;
  496. DWORD dwIndex;
  497. StringCopyArray(szKey, c_szAsmKey);
  498. StringCatArray(szKey, "\\");
  499. StringCchPrintf(szKey + lstrlen(szKey), ARRAYSIZE(szKey)-lstrlen(szKey), "0x%08x", _langid);
  500. if (key.Open(HKEY_CURRENT_USER, szKey, KEY_READ) != S_OK)
  501. goto Exit;
  502. dwIndex = 0;
  503. while (key.EnumKey(dwIndex, szKey, ARRAYSIZE(szKey)) == S_OK)
  504. {
  505. CMyRegKey subkey;
  506. if (subkey.Open(key, szKey, KEY_READ) != S_OK)
  507. goto Next;
  508. StringAToCLSID(szKey, &defpro.catid);
  509. //
  510. // retreive tip clsid.
  511. //
  512. if (subkey.QueryValueCch(szName, c_szDefault, ARRAYSIZE(szName)) != S_OK)
  513. goto Next;
  514. StringAToCLSID(szName, &defpro.clsid);
  515. //
  516. // retreive guid profile
  517. //
  518. if (subkey.QueryValueCch(szName, c_szProfile, ARRAYSIZE(szName)) != S_OK)
  519. goto Next;
  520. StringAToCLSID(szName, &defpro.guidProfile);
  521. if (subkey.QueryValue(dw, c_szKeyboardLayout) != S_OK)
  522. goto Next;
  523. //
  524. // check the hkl from registry is valid or not.
  525. //
  526. defpro.hkl = (HKL)IntToPtr(dw);
  527. if (defpro.hkl)
  528. {
  529. int i = 0;
  530. BOOL fFound = FALSE;
  531. while(phkl[i])
  532. {
  533. if (defpro.hkl == phkl[i])
  534. {
  535. fFound = TRUE;
  536. break;
  537. }
  538. i++;
  539. }
  540. if (!fFound)
  541. goto Next;
  542. }
  543. //
  544. // if the system default hKL does not matched with
  545. // the substite hKL of this profile, this profile can not be
  546. // default profile. Instead the system default hKL became a
  547. // default profile item.
  548. //
  549. if ((LOWORD(HandleToLong(hklDef)) == _langid) &&
  550. IsEqualGUID(defpro.catid, GUID_TFCAT_TIP_KEYBOARD))
  551. {
  552. char szTmp[256];
  553. HKL hklSubstitute = NULL;
  554. fFoundKeyboardIteminDefLang = TRUE;
  555. if (InitProfileRegKeyStr(szTmp,
  556. ARRAYSIZE(szTmp),
  557. defpro.clsid,
  558. _langid,
  559. defpro.guidProfile))
  560. {
  561. CMyRegKey keySubstitute;
  562. if (keySubstitute.Open(HKEY_LOCAL_MACHINE, szTmp, KEY_READ) == S_OK)
  563. {
  564. hklSubstitute = GetSubstituteHKLfromKey(&keySubstitute, _langid);
  565. }
  566. }
  567. // Removed Chinese specific code for bug#427476
  568. if (IsEqualGUID(defpro.clsid, GUID_NULL) ||
  569. (hklSubstitute && (hklSubstitute != hklDef)))
  570. {
  571. defpro.clsid = CLSID_NULL;
  572. defpro.guidProfile = GUID_NULL;
  573. defpro.hkl = hklDef;
  574. }
  575. }
  576. pdefpro = _rgDefProfiles.Append(1);
  577. if (!pdefpro)
  578. return FALSE;
  579. memcpy(pdefpro, &defpro, sizeof(defpro));
  580. #ifdef DEBUG
  581. {
  582. char szDbgCatid[CLSID_STRLEN + 1];
  583. char szDbgClsid[CLSID_STRLEN + 1];
  584. char szDbgguidProfile[CLSID_STRLEN + 1];
  585. CLSIDToStringA(defpro.catid, szDbgCatid);
  586. CLSIDToStringA(defpro.clsid, szDbgClsid);
  587. CLSIDToStringA(defpro.guidProfile, szDbgguidProfile);
  588. TraceMsg(TF_GENERAL, "CDefaultProfiles:: langid %08x", _langid);
  589. TraceMsg(TF_GENERAL, " catid %s", szDbgCatid);
  590. TraceMsg(TF_GENERAL, " clsid %s", szDbgClsid);
  591. TraceMsg(TF_GENERAL, " guidProfile %s", szDbgguidProfile);
  592. TraceMsg(TF_GENERAL, " hkl %08x", (DWORD)HandleToLong(defpro.hkl));
  593. }
  594. #endif
  595. Next:
  596. dwIndex++;
  597. }
  598. Exit:
  599. if (LOWORD(HandleToLong(hklDef)) == _langid)
  600. {
  601. if (!fFoundKeyboardIteminDefLang)
  602. {
  603. //
  604. // Check if the default hkl is a substitute hKL of a TIP's
  605. // profile.
  606. //
  607. if (!GetSubstitutedItem(hklDef, &defpro))
  608. {
  609. //
  610. // we could not find TIP profile. Use this hkl as a default
  611. // item.
  612. //
  613. defpro.catid = GUID_TFCAT_TIP_KEYBOARD;
  614. defpro.clsid = CLSID_NULL;
  615. defpro.guidProfile = GUID_NULL;
  616. defpro.hkl = hklDef;
  617. }
  618. pdefpro = _rgDefProfiles.Append(1);
  619. if (!pdefpro)
  620. return FALSE;
  621. memcpy(pdefpro, &defpro, sizeof(defpro));
  622. }
  623. }
  624. return TRUE;
  625. }
  626. //+---------------------------------------------------------------------------
  627. //
  628. // GetSubstitutedItem
  629. //
  630. // this function walks HKLM\Software\Microsoft\CTF\TIPs to find the
  631. // TIP profile that uses hklSub as its substitute hKL.
  632. //
  633. //----------------------------------------------------------------------------
  634. BOOL CDefaultProfiles::GetSubstitutedItem(HKL hklSub, DEFAULTPROFILE *pdefpro)
  635. {
  636. CMyRegKey key;
  637. DWORD dwIndex;
  638. TCHAR szKey[256];
  639. TCHAR szSubKey[256];
  640. TCHAR szLangKey[256];
  641. TCHAR szValue[256];
  642. StringCopyArray(szKey, c_szCTFTIPKey);
  643. if (key.Open(HKEY_LOCAL_MACHINE, szKey, KEY_READ) != S_OK)
  644. {
  645. return FALSE;
  646. }
  647. // get all profiles from LanguageProfile registry.
  648. //
  649. dwIndex = 0;
  650. while (key.EnumKey(dwIndex, szSubKey, ARRAYSIZE(szSubKey)) == S_OK)
  651. {
  652. CMyRegKey subkey;
  653. CLSID clsid;
  654. StringAToCLSID(szSubKey, &clsid);
  655. if (StringCchPrintf(szSubKey + lstrlen(szSubKey), ARRAYSIZE(szSubKey), "\\%s", c_szLanguageProfileKey) != S_OK)
  656. goto Next0;
  657. if (subkey.Open(key, szSubKey, KEY_READ) != S_OK)
  658. goto Next0;
  659. DWORD dwIndexLang = 0;
  660. while (subkey.EnumKey(dwIndexLang, szLangKey, ARRAYSIZE(szLangKey)) == S_OK)
  661. {
  662. CMyRegKey langkey;
  663. LANGID langid;
  664. if ((szLangKey[0] != '0') ||
  665. ((szLangKey[1] != 'X') && (szLangKey[1] != 'x')))
  666. goto Next1;
  667. langid = (LANGID)AsciiToNum(&szLangKey[2]);
  668. //
  669. // The language ID does not meet the given hklSub.
  670. //
  671. if (langid != LANGIDFROMHKL(hklSub))
  672. goto Next1;
  673. if (langkey.Open(subkey, szLangKey, KEY_READ) != S_OK)
  674. goto Next1;
  675. DWORD dwProfileIndex = 0;
  676. while (langkey.EnumKey(dwProfileIndex, szValue, ARRAYSIZE(szValue)) == S_OK)
  677. {
  678. GUID guidProfile;
  679. CRegKeyMUI keyProfile;
  680. if (!StringAToCLSID(szValue, &guidProfile))
  681. goto Next2;
  682. if (keyProfile.Open(langkey, szValue, KEY_READ) == S_OK)
  683. {
  684. if (hklSub == GetSubstituteHKLfromKey(&keyProfile, langid))
  685. {
  686. //
  687. // ok, we found it. Assume it is Keyboard category.
  688. //
  689. pdefpro->catid = GUID_TFCAT_TIP_KEYBOARD;
  690. pdefpro->clsid = clsid;
  691. pdefpro->guidProfile = guidProfile;
  692. pdefpro->hkl = 0;
  693. return TRUE;
  694. }
  695. }
  696. Next2:
  697. dwProfileIndex++;
  698. }
  699. Next1:
  700. dwIndexLang++;
  701. }
  702. Next0:
  703. dwIndex++;
  704. }
  705. return FALSE;
  706. }
  707. //+---------------------------------------------------------------------------
  708. //
  709. // FilterProfiles
  710. //
  711. //----------------------------------------------------------------------------
  712. BOOL CDefaultProfiles::FilterProfiles(CAssembly *pAsm)
  713. {
  714. int i;
  715. int j;
  716. Assert(_langid == pAsm->GetLangId());
  717. for (i = _rgDefProfiles.Count() - 1; i >= 0 ; i--)
  718. {
  719. DEFAULTPROFILE *pdefpro = _rgDefProfiles.GetPtr(i);
  720. if (!pdefpro)
  721. {
  722. Assert(0);
  723. return FALSE;
  724. }
  725. BOOL fFound = FALSE;
  726. for (j = 0; j < pAsm->Count(); j++)
  727. {
  728. ASSEMBLYITEM *pItem = pAsm->GetItem(j);
  729. if (IsEqualGUID(pItem->catid, pdefpro->catid) &&
  730. IsEqualGUID(pItem->clsid, pdefpro->clsid) &&
  731. IsEqualGUID(pItem->guidProfile, pdefpro->guidProfile))
  732. {
  733. fFound = pItem->fEnabled ? TRUE : FALSE;
  734. break;
  735. }
  736. }
  737. if (!fFound)
  738. {
  739. _rgDefProfiles.Remove(i, 1);
  740. }
  741. }
  742. return TRUE;
  743. }
  744. //+---------------------------------------------------------------------------
  745. //
  746. // GetDefaultProfile
  747. //
  748. //----------------------------------------------------------------------------
  749. BOOL CDefaultProfiles::GetDefaultProfile(GUID catid, GUID *pclsid, GUID *pguidProfile, HKL *phkl)
  750. {
  751. int i;
  752. for (i = 0; i < _rgDefProfiles.Count(); i++)
  753. {
  754. DEFAULTPROFILE *pdefpro = _rgDefProfiles.GetPtr(i);
  755. if (!pdefpro)
  756. {
  757. Assert(0);
  758. return FALSE;
  759. }
  760. if (IsEqualGUID(catid, pdefpro->catid))
  761. {
  762. *pclsid = pdefpro->clsid;
  763. *pguidProfile = pdefpro->guidProfile;
  764. *phkl = pdefpro->hkl;
  765. return TRUE;
  766. }
  767. }
  768. return FALSE;
  769. }
  770. //////////////////////////////////////////////////////////////////////////////
  771. //
  772. // CAssemblyList
  773. //
  774. //////////////////////////////////////////////////////////////////////////////
  775. //+---------------------------------------------------------------------------
  776. //
  777. // ctor
  778. //
  779. //----------------------------------------------------------------------------
  780. CAssemblyList::CAssemblyList()
  781. {
  782. }
  783. //+---------------------------------------------------------------------------
  784. //
  785. // dtor
  786. //
  787. //----------------------------------------------------------------------------
  788. CAssemblyList::~CAssemblyList()
  789. {
  790. ClearAsms();
  791. }
  792. //+---------------------------------------------------------------------------
  793. //
  794. // ClearAsms
  795. //
  796. //----------------------------------------------------------------------------
  797. void CAssemblyList::ClearAsms()
  798. {
  799. int i = 0;
  800. while (i < _rgAsm.Count())
  801. {
  802. CAssembly *pAsm = _rgAsm.Get(i);
  803. delete pAsm;
  804. i++;
  805. }
  806. _rgAsm.Clear();
  807. }
  808. //+---------------------------------------------------------------------------
  809. //
  810. // FindAndCreateNewAssembly
  811. //
  812. //----------------------------------------------------------------------------
  813. extern INATSYMBOL symInatSymbols[];
  814. CAssembly *CAssemblyList::FindAndCreateNewAssembly(CPtrArray<CAssembly> *prgAsm, CPtrArray<CAssembly> *prgNutralAsm, LANGID langid)
  815. {
  816. CPtrArray<CAssembly> *prg;
  817. if (langid == 0xffff)
  818. prg = prgNutralAsm;
  819. else
  820. prg = (langid & 0xfc00) ? prgAsm : prgNutralAsm;
  821. //
  822. // do we already have pAsm?
  823. //
  824. CAssembly *pAsm = FindAssemblyByLangIdInArray(prg, langid);
  825. if (pAsm == NULL)
  826. {
  827. pAsm = new CAssembly(langid);
  828. if (pAsm)
  829. {
  830. CAssembly **ppAsm;
  831. ppAsm = prg->Append(1);
  832. if (ppAsm)
  833. {
  834. *ppAsm = pAsm;
  835. }
  836. else
  837. {
  838. delete pAsm;
  839. pAsm = NULL;
  840. }
  841. }
  842. }
  843. return pAsm;
  844. }
  845. //+---------------------------------------------------------------------------
  846. //
  847. // AttachOriginalAssembly
  848. //
  849. //----------------------------------------------------------------------------
  850. void CAssemblyList::AttachOriginalAssembly(CPtrArray<CAssembly> *prgAsmOrg)
  851. {
  852. int i;
  853. int j;
  854. SYSTHREAD *psfn = GetSYSTHREAD();
  855. CAssembly *pAsm = FindAssemblyByLangId(GetCurrentAssemblyLangId(psfn));
  856. if (!pAsm)
  857. return;
  858. for (i = 0; i < prgAsmOrg->Count(); i++)
  859. {
  860. CAssembly *pAsmOrg = prgAsmOrg->Get(i);
  861. if (pAsm->GetLangId() == pAsmOrg->GetLangId())
  862. {
  863. for (j = 0; j < pAsm->Count(); j++)
  864. {
  865. int nId;
  866. ASSEMBLYITEM *pItem = pAsm->GetItem(j);
  867. if (!pItem)
  868. continue;
  869. nId = pAsmOrg->Find(pItem);
  870. if (nId >= 0)
  871. {
  872. ASSEMBLYITEM *pItemOrg;
  873. pItemOrg = pAsmOrg->GetItem(nId);
  874. BOOL fPrevActive = pItem->fActive;
  875. if (pItemOrg && (pItemOrg->fActive))
  876. {
  877. pItem->fActive = pItemOrg->fActive;
  878. //
  879. // we need to deactivate all other item in the
  880. // category.
  881. //
  882. if (!fPrevActive && pItem->fActive)
  883. {
  884. for (int k = 0; k < pAsm->Count(); k++)
  885. {
  886. ASSEMBLYITEM *pItemTemp = pAsm->GetItem(k);
  887. if (pItemTemp == pItem)
  888. continue;
  889. if (IsEqualGUID(pItemTemp->catid, pItem->catid))
  890. pItemTemp->fActive = FALSE;
  891. }
  892. }
  893. }
  894. }
  895. }
  896. break;
  897. }
  898. }
  899. }
  900. //+---------------------------------------------------------------------------
  901. //
  902. // Load
  903. //
  904. //----------------------------------------------------------------------------
  905. extern INATSYMBOL symInatSymbols[];
  906. HRESULT CAssemblyList::Load()
  907. {
  908. CMyRegKey key;
  909. CMyRegKey key2;
  910. int nhkl;
  911. HKL *lphkl = NULL;
  912. HKL hklList[2];
  913. LANGID langid;
  914. int i;
  915. ASSEMBLYITEM ai;
  916. DWORD dwIndex;
  917. CAssembly *pAsm = NULL;
  918. BOOL fFoundActiveNoCic = FALSE;
  919. CPtrArray<CAssembly> *prgNutralAsm = NULL;
  920. IEnumGUID *pEnumCat = NULL;
  921. HRESULT hr;
  922. int nAsmCnt;
  923. CPtrArray<CAssembly> rgAsmOrg;
  924. TCHAR szKey[256];
  925. TCHAR szSubKey[256];
  926. TCHAR szLangKey[256];
  927. TCHAR szValue[256];
  928. //
  929. // backup original assembly in rgAsmOrg;
  930. //
  931. for (i = 0; i < _rgAsm.Count(); i++)
  932. {
  933. pAsm = _rgAsm.Get(i);
  934. if (pAsm)
  935. {
  936. CAssembly **ppAsm = rgAsmOrg.Append(1);
  937. if (ppAsm)
  938. *ppAsm = pAsm;
  939. }
  940. }
  941. _rgAsm.Clear();
  942. #ifdef PROFILE_UPDATE_REGISTRY // old code for tip setup.
  943. if (IsUpdated())
  944. {
  945. ClearUpdatedFlag();
  946. }
  947. else
  948. #endif
  949. {
  950. if (LoadFromCache())
  951. {
  952. AttachOriginalAssembly(&rgAsmOrg);
  953. hr = S_OK;
  954. goto Exit;
  955. }
  956. }
  957. prgNutralAsm = new CPtrArray<CAssembly>;
  958. if (!prgNutralAsm)
  959. {
  960. hr = E_OUTOFMEMORY;
  961. goto Exit;
  962. }
  963. StringCopyArray(szKey, c_szCTFTIPKey);
  964. if (key.Open(HKEY_LOCAL_MACHINE, szKey, KEY_READ) != S_OK)
  965. {
  966. hr = E_FAIL;
  967. goto Exit;
  968. }
  969. nhkl = GetKeyboardLayoutList(0, NULL);
  970. if (nhkl)
  971. {
  972. lphkl = (HKL *)cicMemAllocClear(sizeof(HKL) * (nhkl + 1));
  973. GetKeyboardLayoutList(nhkl, lphkl);
  974. }
  975. else
  976. {
  977. hklList[0] = GetKeyboardLayout(NULL);
  978. hklList[1] = NULL;
  979. lphkl = hklList;
  980. }
  981. //
  982. // clear Category cache
  983. //
  984. CCategoryMgr::FreeCatCache();
  985. hr = g_EnumItemsInCategory(GUID_TFCAT_CATEGORY_OF_TIP, &pEnumCat);
  986. if (FAILED(hr))
  987. {
  988. goto Exit;
  989. }
  990. //
  991. // Check all TIP CLSID under HKCU is valid TIP CLSIDs.
  992. //
  993. StringCopyArray(szKey, c_szCTFTIPKey);
  994. if (key2.Open(HKEY_CURRENT_USER, szKey, KEY_ALL_ACCESS) == S_OK)
  995. {
  996. dwIndex = 0;
  997. while (key2.EnumKey(dwIndex, szSubKey, ARRAYSIZE(szSubKey)) == S_OK)
  998. {
  999. CMyRegKey subkey;
  1000. dwIndex++;
  1001. //
  1002. // if we could not open the subkey (CLSID key) in HKLM,
  1003. // HKCU should not have the subkey.
  1004. //
  1005. if (subkey.Open(key, szSubKey, KEY_READ) != S_OK)
  1006. {
  1007. if (key2.RecurseDeleteKey(szSubKey) == S_OK)
  1008. dwIndex--;
  1009. }
  1010. }
  1011. }
  1012. //
  1013. // get all profiles from LanguageProfile registry.
  1014. //
  1015. dwIndex = 0;
  1016. while (key.EnumKey(dwIndex++, szSubKey, ARRAYSIZE(szSubKey)) == S_OK)
  1017. {
  1018. CMyRegKey subkey;
  1019. CLSID clsid;
  1020. StringAToCLSID(szSubKey, &clsid);
  1021. if (StringCchPrintf(szSubKey + lstrlen(szSubKey), ARRAYSIZE(szSubKey), "\\%s", c_szLanguageProfileKey) != S_OK)
  1022. continue;
  1023. if (subkey.Open(key, szSubKey, KEY_READ) == S_OK)
  1024. {
  1025. DWORD dwIndexLang = 0;
  1026. while (subkey.EnumKey(dwIndexLang, szLangKey, ARRAYSIZE(szLangKey)) == S_OK)
  1027. {
  1028. CMyRegKey langkey;
  1029. if ((szLangKey[0] != '0') ||
  1030. ((szLangKey[1] != 'X') && (szLangKey[1] != 'x')))
  1031. goto Next;
  1032. langid = (LANGID)AsciiToNum(&szLangKey[2]);
  1033. //
  1034. // do we already have pAsm?
  1035. //
  1036. pAsm = FindAndCreateNewAssembly(&_rgAsm, prgNutralAsm, langid);
  1037. if (pAsm == NULL)
  1038. {
  1039. hr = E_OUTOFMEMORY;
  1040. goto Exit;
  1041. }
  1042. if (langkey.Open(subkey, szLangKey, KEY_READ) == S_OK)
  1043. {
  1044. DWORD dwProfileIndex = 0;
  1045. while (langkey.EnumKey(dwProfileIndex, szValue, ARRAYSIZE(szValue)) == S_OK)
  1046. {
  1047. GUID guidProfile;
  1048. CRegKeyMUI keyProfile;
  1049. if (!StringAToCLSID(szValue, &guidProfile))
  1050. goto NextKey;
  1051. memset(&ai, 0, ai.GetAlignSize());
  1052. ai.InitIconIndex();
  1053. ai.clsid = clsid;
  1054. ai.fActive = FALSE;
  1055. GetTIPCategory(clsid, &ai.catid, pEnumCat);
  1056. ai.guidProfile = guidProfile;
  1057. ai.fEnabled = FALSE;
  1058. // we will assign proper hKL later.
  1059. ai.hkl = NULL;
  1060. hr = keyProfile.Open(langkey, szValue, KEY_READ);
  1061. if (hr == S_OK)
  1062. {
  1063. ai.hklSubstitute = GetSubstituteHKLfromKey(&keyProfile, langid);
  1064. hr = keyProfile.QueryMUIValueW(ai.szProfile,
  1065. c_szDescriptionW,
  1066. c_szMUIDescriptionW,
  1067. ARRAYSIZE(ai.szProfile));
  1068. DWORD dw;
  1069. if ((keyProfile.QueryValue(dw, c_szDisabledOnTransitory) == S_OK) && dw)
  1070. ai.fDisabledOnTransitory = TRUE;
  1071. }
  1072. if (hr == S_OK)
  1073. pAsm->Add(&ai);
  1074. NextKey:
  1075. dwProfileIndex++;
  1076. }
  1077. }
  1078. Next:
  1079. dwIndexLang++;
  1080. }
  1081. }
  1082. }
  1083. //
  1084. // check all assembly has KEYBOARD category.
  1085. // If not, we load keyboard layout for the assembly.
  1086. //
  1087. nAsmCnt = _rgAsm.Count();
  1088. for (i = 0; i < nAsmCnt; i++)
  1089. {
  1090. BOOL bLoaded;
  1091. int j;
  1092. CAssembly *pAsmTmp = _rgAsm.Get(i);
  1093. if (pAsmTmp->FindItemByCategory(GUID_TFCAT_TIP_KEYBOARD))
  1094. continue;
  1095. LANGID langidTmp = pAsmTmp->GetLangId();
  1096. //
  1097. // we can not use IsEnabledItem() here. We have not updated
  1098. // the enbaled status of Items yet.
  1099. //
  1100. // if (!pAsmTmp->IsEnabledItem())
  1101. // continue;
  1102. //
  1103. BOOL fFound = FALSE;
  1104. for (j = 0; j < pAsmTmp->Count(); j++)
  1105. {
  1106. ASSEMBLYITEM *pItem = pAsmTmp->GetItem(j);
  1107. if (pItem->fEnabled ||
  1108. IsEnabledLanguageProfileFromReg(pItem->clsid,
  1109. pAsmTmp->_langid,
  1110. pItem->guidProfile))
  1111. {
  1112. fFound = TRUE;
  1113. break;
  1114. }
  1115. }
  1116. if (!fFound)
  1117. continue;
  1118. //
  1119. // Load a proper keyboard layout....
  1120. //
  1121. GetProperHKL(langidTmp, lphkl, &bLoaded);
  1122. if (bLoaded)
  1123. {
  1124. //
  1125. // re-create the keyboard layout list.
  1126. //
  1127. nhkl = GetKeyboardLayoutList(0, NULL);
  1128. if (nhkl)
  1129. {
  1130. if (lphkl && (lphkl != hklList))
  1131. cicMemFree(lphkl);
  1132. lphkl = (HKL *)cicMemAllocClear(sizeof(HKL) * (nhkl + 1));
  1133. GetKeyboardLayoutList(nhkl, lphkl);
  1134. }
  1135. else
  1136. {
  1137. hklList[0] = GetKeyboardLayout(NULL);
  1138. hklList[1] = NULL;
  1139. lphkl = hklList;
  1140. }
  1141. }
  1142. }
  1143. //
  1144. // get all hKLs.
  1145. //
  1146. if (lphkl)
  1147. {
  1148. HKL *lphklCur = lphkl;
  1149. DWORD *pdwPreload = NULL;
  1150. UINT uPreloadCnt;
  1151. //
  1152. // load preload layouts infomation.
  1153. //
  1154. uPreloadCnt = GetPreloadListForNT(NULL, 0);
  1155. if (uPreloadCnt)
  1156. {
  1157. Assert(IsOnNT());
  1158. pdwPreload = new DWORD[uPreloadCnt];
  1159. if (pdwPreload)
  1160. GetPreloadListForNT(pdwPreload, uPreloadCnt);
  1161. }
  1162. while (*lphklCur)
  1163. {
  1164. BOOL fIsDefaultHKLinPreload = FALSE;
  1165. WORD wLayout = HIWORD((DWORD)(LONG_PTR)(*lphklCur));
  1166. langid = (LANGID)((DWORD)(LONG_PTR)(*lphklCur) & 0x0000ffff);
  1167. //
  1168. // do we already have pAsm?
  1169. //
  1170. pAsm = FindAndCreateNewAssembly(&_rgAsm, prgNutralAsm, langid);
  1171. if (pAsm == NULL)
  1172. {
  1173. hr = E_OUTOFMEMORY;
  1174. goto Exit;
  1175. }
  1176. //
  1177. // See Preload to check if this default hKL is real dummy or not.
  1178. // The default FE layout is not a dummy hKL if it is in Preload
  1179. // list.
  1180. //
  1181. if (IsFELangId(langid))
  1182. {
  1183. if (wLayout == (WORD)langid)
  1184. {
  1185. UINT uCur;
  1186. for (uCur = 0; uCur < uPreloadCnt; uCur++)
  1187. {
  1188. //
  1189. // check if we have 0x00000411 in preload.
  1190. //
  1191. if (pdwPreload[uCur] == (DWORD)(wLayout))
  1192. {
  1193. fIsDefaultHKLinPreload = TRUE;
  1194. break;
  1195. }
  1196. }
  1197. }
  1198. else if ((wLayout & 0xf000) != 0xe000)
  1199. {
  1200. fIsDefaultHKLinPreload = TRUE;
  1201. }
  1202. }
  1203. //
  1204. // we skip dummy FE hKL.
  1205. //
  1206. if (!IsFELangId(langid) ||
  1207. IsPureIMEHKL(*lphklCur) ||
  1208. fIsDefaultHKLinPreload ||
  1209. !pAsm->FindPureKbdTipItem())
  1210. {
  1211. TF_InitMlngInfo();
  1212. MLNGINFO mlInfo;
  1213. if (pAsm == NULL)
  1214. pAsm = new CAssembly(langid);
  1215. memset(&ai, 0, ai.GetAlignSize());
  1216. ai.InitIconIndex();
  1217. ai.hkl = *lphklCur;
  1218. ai.clsid = GUID_NULL;
  1219. ai.catid = GUID_TFCAT_TIP_KEYBOARD;
  1220. ai.fActive = FALSE;
  1221. ai.fEnabled = TRUE;
  1222. if (GetMlngInfoByhKL(ai.hkl, &mlInfo) == -1)
  1223. mlInfo.SetDesc(L"");
  1224. ai.guidProfile = GUID_NULL;
  1225. StringCopyArrayW(ai.szProfile, mlInfo.GetDesc());
  1226. pAsm->Add(&ai);
  1227. }
  1228. lphklCur++;
  1229. }
  1230. if (pdwPreload)
  1231. delete pdwPreload;
  1232. }
  1233. //
  1234. // filter neutral langiage assembly
  1235. //
  1236. while (prgNutralAsm->Count())
  1237. {
  1238. pAsm = prgNutralAsm->Get(0);
  1239. langid = pAsm->GetLangId();
  1240. Assert((langid == 0xffff) || !(langid & 0xFC00));
  1241. //
  1242. // find valid langid ang merge there.
  1243. //
  1244. for (i = 0; i < _rgAsm.Count(); i++)
  1245. {
  1246. CAssembly *pAsmDst = _rgAsm.Get(i);
  1247. LANGID langidDst = pAsmDst->GetLangId();
  1248. Assert(langidDst & 0xFC00);
  1249. //
  1250. // we found a valid langid.
  1251. //
  1252. if ((langid == 0xffff) ||
  1253. (PRIMARYLANGID(langid) == PRIMARYLANGID(langidDst)))
  1254. {
  1255. int j;
  1256. for (j = 0; j < pAsm->Count(); j++)
  1257. {
  1258. ASSEMBLYITEM *pItem = pAsm->GetItem(j);
  1259. pItem->fActive = FALSE;
  1260. pItem->fActiveNoCic = FALSE;
  1261. // we will assign proper hKL later.
  1262. pItem->hkl = NULL;
  1263. pAsmDst->Add(pItem);
  1264. }
  1265. }
  1266. }
  1267. //
  1268. // we don't need a neutral lang assembly.
  1269. //
  1270. prgNutralAsm->Remove(0, 1);
  1271. delete pAsm;
  1272. }
  1273. //
  1274. // It is time to decide this profile should be activated by default.
  1275. //
  1276. for (i = 0; i < _rgAsm.Count(); i++)
  1277. {
  1278. int j;
  1279. pAsm = _rgAsm.Get(i);
  1280. CDefaultProfiles defProfiles(pAsm->_langid);
  1281. defProfiles.Init(lphkl);
  1282. //
  1283. // update Enable status.
  1284. //
  1285. // this must be done before filtering the default profiles.
  1286. // disabled item should not be the default proble.
  1287. //
  1288. for (j = 0; j < pAsm->Count(); j++)
  1289. {
  1290. ASSEMBLYITEM *pItem = pAsm->GetItem(j);
  1291. if (!pItem->fEnabled)
  1292. pItem->fEnabled = IsEnabledLanguageProfileFromReg(pItem->clsid,
  1293. pAsm->_langid,
  1294. pItem->guidProfile);
  1295. }
  1296. //
  1297. // check if the default profile is enabled.
  1298. //
  1299. defProfiles.FilterProfiles(pAsm);
  1300. for (j = 0; j < pAsm->Count(); j++)
  1301. {
  1302. ASSEMBLYITEM *pItem = pAsm->GetItem(j);
  1303. CLSID clsid;
  1304. GUID guidProfile;
  1305. HKL hkl;
  1306. //
  1307. // If the item is not categoried, we activate it.
  1308. //
  1309. if (IsEqualGUID(pItem->catid, GUID_NULL))
  1310. {
  1311. pItem->fActive = TRUE;
  1312. continue;
  1313. }
  1314. //
  1315. // if this item is enabled, load proper hkl.
  1316. //
  1317. if (pItem->fEnabled &&
  1318. IsEqualGUID(pItem->catid, GUID_TFCAT_TIP_KEYBOARD) &&
  1319. !pItem->hkl)
  1320. pItem->hkl = GetProperHKL(pAsm->_langid, lphkl, NULL);
  1321. //
  1322. // init fActivate to false by default.
  1323. //
  1324. pItem->fActive = FALSE;
  1325. if (pItem->fEnabled)
  1326. {
  1327. //
  1328. // GetDefaultProfile() may return NULL in hkl if someone calls
  1329. // ITfInputProcessorProfiles::SetDefaultLanguageProfile() method
  1330. // from outside. We should not check hkl value then.
  1331. //
  1332. if (defProfiles.GetDefaultProfile(pItem->catid,
  1333. &clsid,
  1334. &guidProfile,
  1335. &hkl))
  1336. {
  1337. //
  1338. // ok this item is not default profile.
  1339. //
  1340. if (!IsEqualCLSID(pItem->clsid, clsid) ||
  1341. !IsEqualCLSID(pItem->guidProfile, guidProfile) ||
  1342. (hkl && (pItem->hkl != hkl)))
  1343. continue;
  1344. pItem->fActive = TRUE;
  1345. }
  1346. else if (defProfiles.Append(pItem->catid,
  1347. pItem->clsid,
  1348. pItem->guidProfile,
  1349. pItem->hkl))
  1350. {
  1351. pItem->fActive = TRUE;
  1352. }
  1353. }
  1354. }
  1355. #ifdef DEBUG
  1356. for (j = 0; j < pAsm->Count(); j++)
  1357. {
  1358. ASSEMBLYITEM *pItem = pAsm->GetItem(j);
  1359. int k;
  1360. if (!pItem->fActive)
  1361. {
  1362. UINT uCnt = 0;
  1363. for (k = 0; k < pAsm->Count(); k++)
  1364. {
  1365. ASSEMBLYITEM *pItemTemp = pAsm->GetItem(k);
  1366. if (IsEqualGUID(pItemTemp->catid, pItem->catid))
  1367. uCnt += (pItemTemp->fActive) ? 1 : 0;
  1368. }
  1369. Assert(uCnt <= 1);
  1370. }
  1371. }
  1372. #endif
  1373. }
  1374. //
  1375. // we should create cache before attaching the original assembly active
  1376. // status.
  1377. // AttachOriginalAssembly() is just for the current thread.
  1378. //
  1379. if (IsAsmCache())
  1380. CreateCache();
  1381. if (rgAsmOrg.Count())
  1382. AttachOriginalAssembly(&rgAsmOrg);
  1383. hr = S_OK;
  1384. Exit:
  1385. if (lphkl && (lphkl != hklList))
  1386. cicMemFree(lphkl);
  1387. if (prgNutralAsm)
  1388. {
  1389. Assert(!prgNutralAsm->Count())
  1390. delete prgNutralAsm;
  1391. }
  1392. if (pEnumCat)
  1393. pEnumCat->Release();
  1394. //
  1395. // clean up original assemblies.
  1396. //
  1397. for (i = 0; i < rgAsmOrg.Count(); i++)
  1398. {
  1399. pAsm = rgAsmOrg.Get(i);
  1400. delete pAsm;
  1401. }
  1402. rgAsmOrg.Clear();
  1403. return hr;
  1404. }
  1405. //+---------------------------------------------------------------------------
  1406. //
  1407. // GetDefaultAssembly
  1408. //
  1409. //----------------------------------------------------------------------------
  1410. CAssembly *CAssemblyList::GetDefaultAssembly()
  1411. {
  1412. CAssembly *pAsm = NULL;
  1413. int nAsmCnt = _rgAsm.Count();
  1414. DWORD langid;
  1415. if (!nAsmCnt)
  1416. return NULL;
  1417. langid = (LANGID)LOWORD(HandleToLong(GetSystemDefaultHKL()));
  1418. if (!langid)
  1419. return _rgAsm.Get(0);
  1420. int nCurAsm = 0;
  1421. while (nCurAsm < nAsmCnt)
  1422. {
  1423. CAssembly *pAsmTmp = _rgAsm.Get(nCurAsm);
  1424. if (pAsmTmp->_langid == langid)
  1425. {
  1426. pAsm = pAsmTmp;
  1427. break;
  1428. }
  1429. nCurAsm++;
  1430. }
  1431. if (!pAsm)
  1432. pAsm = _rgAsm.Get(0);
  1433. return pAsm;
  1434. }
  1435. //+---------------------------------------------------------------------------
  1436. //
  1437. // CreateCache
  1438. //
  1439. //----------------------------------------------------------------------------
  1440. typedef struct tag_ASSEMBLY_ROOT
  1441. {
  1442. DWORD dwAssemblyCount;
  1443. // ASSEMBLYHDR[]
  1444. static size_t GetAlignSize() { return Align(sizeof(struct tag_ASSEMBLY_ROOT)); }
  1445. } ASSEMBLY_ROOT;
  1446. typedef struct tag_ASSEMBLYHDR
  1447. {
  1448. DWORD dwCnt;
  1449. LANGID langid;
  1450. // ASSEMBLYITEM[]
  1451. static size_t GetAlignSize() { return Align(sizeof(struct tag_ASSEMBLYHDR)); }
  1452. } ASSEMBLYHDR;
  1453. CCicFileMapping *g_pcfmAsmCache = NULL;
  1454. BOOL EnsureAsmCacheFileMap()
  1455. {
  1456. if (!g_pcfmAsmCache)
  1457. g_pcfmAsmCache = new CCicFileMapping();
  1458. return g_pcfmAsmCache ? TRUE : FALSE;
  1459. }
  1460. BOOL UninitAsmCacheFileMap()
  1461. {
  1462. if (g_pcfmAsmCache)
  1463. {
  1464. delete g_pcfmAsmCache;
  1465. g_pcfmAsmCache = NULL;
  1466. }
  1467. return TRUE;
  1468. }
  1469. BOOL IsAsmCache()
  1470. {
  1471. return g_pcfmAsmCache ? TRUE : FALSE;
  1472. }
  1473. //+---------------------------------------------------------------------------
  1474. //
  1475. // CreateCache
  1476. //
  1477. //----------------------------------------------------------------------------
  1478. BOOL CAssemblyList::CreateCache()
  1479. {
  1480. int nAsmCnt = _rgAsm.Count();
  1481. int nCurAsm = 0;
  1482. HANDLE hfm = NULL;
  1483. DWORD cbSize = 0;
  1484. BYTE *pv;
  1485. BOOL bRet = FALSE;
  1486. CCicSecAttr sa;
  1487. if (!g_pcfmAsmCache)
  1488. return TRUE;
  1489. if (!g_pcfmAsmCache->Enter())
  1490. return FALSE;
  1491. g_pcfmAsmCache->Close();
  1492. g_pcfmAsmCache->Init(g_szAsmListCache, &g_mutexAsm);
  1493. //
  1494. // ASSEMBLY_ROOT, ASSEMBLYHDR and ASSEMBLYITEM
  1495. //
  1496. // When calc next data struc pointer, should not use sizeof()
  1497. // because need adjust data alignment for 64/32bit on IA64.
  1498. // Please use GetAlignSize() method instead of sizeof().
  1499. //
  1500. cbSize += ASSEMBLY_ROOT::GetAlignSize();
  1501. while (nCurAsm < nAsmCnt)
  1502. {
  1503. CAssembly *pAsm = _rgAsm.Get(nCurAsm);
  1504. cbSize += ASSEMBLYHDR::GetAlignSize();
  1505. cbSize += (pAsm->Count() * ASSEMBLYITEM::GetAlignSize());
  1506. nCurAsm++;
  1507. }
  1508. pv = (BYTE *)g_pcfmAsmCache->Create(sa, cbSize, NULL);
  1509. if (!pv)
  1510. goto Exit;
  1511. ASSEMBLY_ROOT* pasm_root = (ASSEMBLY_ROOT*) pv;
  1512. pasm_root->dwAssemblyCount = nAsmCnt;
  1513. pv += ASSEMBLY_ROOT::GetAlignSize();
  1514. nCurAsm = 0;
  1515. while (nCurAsm < nAsmCnt)
  1516. {
  1517. ASSEMBLYHDR *pAsmHdr;
  1518. CAssembly *pAsm = _rgAsm.Get(nCurAsm);
  1519. pAsmHdr = (ASSEMBLYHDR *)pv;
  1520. pAsmHdr->dwCnt = pAsm->Count();
  1521. pAsmHdr->langid = pAsm->GetLangId();
  1522. pv += ASSEMBLYHDR::GetAlignSize();
  1523. int nItemCnt = pAsm->Count();
  1524. int nCurItem = 0;
  1525. while (nCurItem < nItemCnt)
  1526. {
  1527. ASSEMBLYITEM *pItem = pAsm->GetItem(nCurItem);
  1528. memcpy(pv, pItem, ASSEMBLYITEM::GetAlignSize());
  1529. pv += ASSEMBLYITEM::GetAlignSize();
  1530. nCurItem++;
  1531. }
  1532. nCurAsm++;
  1533. }
  1534. bRet = TRUE;
  1535. Exit:
  1536. g_pcfmAsmCache->Leave();
  1537. return bRet;
  1538. }
  1539. //+---------------------------------------------------------------------------
  1540. //
  1541. // LoadFromCache
  1542. //
  1543. //----------------------------------------------------------------------------
  1544. BOOL CAssemblyList::LoadFromCache()
  1545. {
  1546. HANDLE hfm = NULL;
  1547. BYTE *pv;
  1548. int nAsmCnt;
  1549. int nCurAsm = 0;
  1550. BOOL bRet = FALSE;
  1551. CCicFileMapping cfm(g_szAsmListCache, &g_mutexAsm);
  1552. if (!cfm.Enter())
  1553. return FALSE;
  1554. pv = (BYTE *)cfm.Open();
  1555. if (!pv)
  1556. goto Exit;
  1557. //
  1558. // ASSEMBLY_ROOT, ASSEMBLYHDR and ASSEMBLYITEM
  1559. //
  1560. // When calc next data struc pointer, should not use sizeof()
  1561. // because need adjust data alignment for 64/32bit on IA64.
  1562. // Please use GetAlignSize() method instead of sizeof().
  1563. //
  1564. cfm.Flush(ASSEMBLY_ROOT::GetAlignSize());
  1565. ASSEMBLY_ROOT* pasm_root = (ASSEMBLY_ROOT*) pv;
  1566. nAsmCnt = pasm_root->dwAssemblyCount;
  1567. pv += ASSEMBLY_ROOT::GetAlignSize();
  1568. if (!nAsmCnt)
  1569. goto Exit;
  1570. while (nCurAsm < nAsmCnt)
  1571. {
  1572. ASSEMBLYHDR *pAsmHdr;
  1573. CAssembly *pAsm;
  1574. int nItemCnt;
  1575. int nCurItem = 0;
  1576. pAsmHdr = (ASSEMBLYHDR *)pv;
  1577. nItemCnt = pAsmHdr->dwCnt;
  1578. pAsm = new CAssembly(pAsmHdr->langid);
  1579. pv += ASSEMBLYHDR::GetAlignSize();
  1580. while (nCurItem < nItemCnt)
  1581. {
  1582. ASSEMBLYITEM *pItem = (ASSEMBLYITEM *)pv;
  1583. pItem->InitIconIndex();
  1584. if (pAsm)
  1585. pAsm->Add(pItem);
  1586. pv += ASSEMBLYITEM::GetAlignSize();
  1587. nCurItem++;
  1588. }
  1589. if (pAsm)
  1590. {
  1591. CAssembly **ppAsm;
  1592. ppAsm = _rgAsm.Append(1);
  1593. if (ppAsm)
  1594. {
  1595. *ppAsm = pAsm;
  1596. }
  1597. else
  1598. {
  1599. delete pAsm;
  1600. }
  1601. }
  1602. nCurAsm++;
  1603. }
  1604. bRet = TRUE;
  1605. Exit:
  1606. cfm.Leave();
  1607. return bRet;
  1608. }
  1609. //+---------------------------------------------------------------------------
  1610. //
  1611. // InvalidCache
  1612. //
  1613. //----------------------------------------------------------------------------
  1614. BOOL CAssemblyList::InvalidCache()
  1615. {
  1616. HANDLE hfm = NULL;
  1617. DWORD *pv;
  1618. BOOL bRet = FALSE;
  1619. CCicFileMapping cfm(g_szAsmListCache, &g_mutexAsm);
  1620. if (!cfm.Enter())
  1621. return FALSE;
  1622. pv = (DWORD *)cfm.Open();
  1623. if (!pv)
  1624. goto Exit;
  1625. //
  1626. // ASSEMBLY_ROOT, ASSEMBLYHDR and ASSEMBLYITEM
  1627. //
  1628. // When calc next data struc pointer, should not use sizeof()
  1629. // because need adjust data alignment for 64/32bit on IA64.
  1630. // Please use GetAlignSize() method instead of sizeof().
  1631. //
  1632. if (pv)
  1633. {
  1634. ASSEMBLY_ROOT* pasm_root = (ASSEMBLY_ROOT*) pv;
  1635. pasm_root->dwAssemblyCount = 0;
  1636. cfm.Flush(ASSEMBLY_ROOT::GetAlignSize());
  1637. bRet = TRUE;
  1638. }
  1639. Exit:
  1640. cfm.Leave();
  1641. return bRet;
  1642. }
  1643. //+---------------------------------------------------------------------------
  1644. //
  1645. // SetDefaultTIPInAssemblyForCache
  1646. //
  1647. //----------------------------------------------------------------------------
  1648. BOOL CAssemblyList::SetDefaultTIPInAssemblyForCache(LANGID langid, REFGUID catid, REFCLSID clsid, HKL hKL, REFGUID guidProfile)
  1649. {
  1650. BYTE *pv;
  1651. int nAsmCnt;
  1652. int nCurAsm = 0;
  1653. BOOL bRet = FALSE;
  1654. CCicFileMapping cfm(g_szAsmListCache, &g_mutexAsm);
  1655. if (!cfm.Enter())
  1656. return FALSE;
  1657. pv = (BYTE *)cfm.Open();
  1658. if (!pv)
  1659. goto Exit;
  1660. //
  1661. // ASSEMBLY_ROOT, ASSEMBLYHDR and ASSEMBLYITEM
  1662. //
  1663. // When calc next data struc pointer, should not use sizeof()
  1664. // because need adjust data alignment for 64/32bit on IA64.
  1665. // Please use GetAlignSize() method instead of sizeof().
  1666. //
  1667. ASSEMBLY_ROOT* pasm_root = (ASSEMBLY_ROOT*) pv;
  1668. nAsmCnt = pasm_root->dwAssemblyCount;
  1669. pv += ASSEMBLY_ROOT::GetAlignSize();
  1670. if (!nAsmCnt)
  1671. goto Exit;
  1672. while (nCurAsm < nAsmCnt)
  1673. {
  1674. ASSEMBLYHDR *pAsmHdr;
  1675. int nItemCnt;
  1676. int nCurItem = 0;
  1677. pAsmHdr = (ASSEMBLYHDR *)pv;
  1678. BOOL fTargetLang = (pAsmHdr->langid == langid) ? TRUE : FALSE;
  1679. nItemCnt = pAsmHdr->dwCnt;
  1680. pv += ASSEMBLYHDR::GetAlignSize();
  1681. while (nCurItem < nItemCnt)
  1682. {
  1683. if (fTargetLang)
  1684. {
  1685. ASSEMBLYITEM *pItem = (ASSEMBLYITEM *)pv;
  1686. if (IsEqualGUID(pItem->catid, catid))
  1687. {
  1688. if (IsEqualGUID(pItem->clsid, clsid) &&
  1689. IsEqualGUID(pItem->guidProfile, guidProfile) &&
  1690. (!hKL || (hKL == pItem->hkl)))
  1691. {
  1692. pItem->fActive = TRUE;
  1693. }
  1694. else
  1695. {
  1696. pItem->fActive = FALSE;
  1697. }
  1698. }
  1699. }
  1700. pv += ASSEMBLYITEM::GetAlignSize();
  1701. nCurItem++;
  1702. }
  1703. if (fTargetLang)
  1704. break;
  1705. nCurAsm++;
  1706. }
  1707. bRet = TRUE;
  1708. Exit:
  1709. cfm.Leave();
  1710. return bRet;
  1711. }
  1712. #ifdef PROFILE_UPDATE_REGISTRY // old code for tip setup.
  1713. //+---------------------------------------------------------------------------
  1714. //
  1715. // IsUpdated
  1716. //
  1717. //----------------------------------------------------------------------------
  1718. BOOL CAssemblyList::IsUpdated()
  1719. {
  1720. CMyRegKey key;
  1721. if (key.Open(HKEY_LOCAL_MACHINE, c_szCTFKey, KEY_READ) != S_OK)
  1722. return FALSE;
  1723. char szName[16];
  1724. DWORD dwCnt = sizeof(szName);
  1725. if (key.QueryValue(szName, c_szUpdateProfile, &dwCnt) != S_OK)
  1726. return FALSE;
  1727. return (szName[0] == '1') ? TRUE : FALSE;
  1728. }
  1729. //+---------------------------------------------------------------------------
  1730. //
  1731. // ClearUpdatedFlag
  1732. //
  1733. //----------------------------------------------------------------------------
  1734. BOOL CAssemblyList::ClearUpdatedFlag()
  1735. {
  1736. CMyRegKey key;
  1737. if (key.Open(HKEY_LOCAL_MACHINE, c_szCTFKey) != S_OK)
  1738. return FALSE;
  1739. if (key.DeleteValue(c_szUpdateProfile) != S_OK)
  1740. return FALSE;
  1741. return TRUE;
  1742. }
  1743. #endif
  1744. //+---------------------------------------------------------------------------
  1745. //
  1746. // CheckLangSupport
  1747. //
  1748. //----------------------------------------------------------------------------
  1749. BOOL CAssemblyList::CheckLangSupport(REFCLSID rclsid, LANGID langid)
  1750. {
  1751. CMyRegKey key;
  1752. TCHAR szKey[256];
  1753. TCHAR szLang[256];
  1754. int i = 0;
  1755. StringCopyArray(szKey, c_szCTFTIPKey);
  1756. CLSIDToStringA(rclsid, szKey + lstrlen(szKey));
  1757. StringCatArray(szKey, "\\");
  1758. StringCatArray(szKey, c_szLanguageProfileKey);
  1759. if (key.Open(HKEY_LOCAL_MACHINE, szKey, KEY_READ) == S_OK)
  1760. {
  1761. CMyRegKey subkey;
  1762. //
  1763. // Check a valid language id.
  1764. //
  1765. StringCchPrintf(szLang, ARRAYSIZE(szLang), "0x%08x", LOWORD(langid));
  1766. StringCopyArray(szKey, szLang);
  1767. if (subkey.Open(key, szKey, KEY_READ) == S_OK)
  1768. return TRUE;
  1769. //
  1770. // Check a primary language id.
  1771. //
  1772. StringCchPrintf(szLang, ARRAYSIZE(szLang), "0x%08x", LOWORD(PRIMARYLANGID(langid)));
  1773. StringCopyArray(szKey, szLang);
  1774. if (subkey.Open(key, szKey, KEY_READ) == S_OK)
  1775. return TRUE;
  1776. //
  1777. // Check a neutral language id.
  1778. //
  1779. StringCchPrintf(szLang, ARRAYSIZE(szLang), "0x0000ffff");
  1780. StringCopyArray(szKey, szLang);
  1781. if (subkey.Open(key, szKey, KEY_READ) == S_OK)
  1782. return TRUE;
  1783. }
  1784. return FALSE;
  1785. }
  1786. //+---------------------------------------------------------------------------
  1787. //
  1788. // GetTIPCategory
  1789. //
  1790. //----------------------------------------------------------------------------
  1791. BOOL CAssemblyList::GetTIPCategory(REFCLSID clsid, GUID *pcatid, IEnumGUID *pEnumCat)
  1792. {
  1793. HRESULT hr;
  1794. BOOL fFound = FALSE;
  1795. *pcatid = GUID_NULL;
  1796. hr = pEnumCat->Reset();
  1797. if (SUCCEEDED(hr))
  1798. {
  1799. GUID guidCat;
  1800. while (!fFound && (pEnumCat->Next(1, &guidCat, NULL) == S_OK))
  1801. {
  1802. IEnumGUID *pEnumTip;
  1803. hr = g_EnumItemsInCategory(guidCat, &pEnumTip);
  1804. if (SUCCEEDED(hr) && pEnumTip)
  1805. {
  1806. GUID guidTip;
  1807. while (!fFound && (pEnumTip->Next(1, &guidTip, NULL) == S_OK))
  1808. {
  1809. if (IsEqualGUID(clsid, guidTip))
  1810. {
  1811. *pcatid = guidCat;
  1812. fFound = TRUE;
  1813. }
  1814. }
  1815. pEnumTip->Release();
  1816. }
  1817. }
  1818. }
  1819. return fFound;
  1820. }
  1821. //+---------------------------------------------------------------------------
  1822. //
  1823. // GetDefaultTIPInAssembly
  1824. //
  1825. //----------------------------------------------------------------------------
  1826. BOOL CAssemblyList::GetDefaultTIPInAssembly(LANGID langid, REFGUID catid, CLSID *pclsid, HKL *phKL, GUID *pguidProfile)
  1827. {
  1828. CMyRegKey key;
  1829. DWORD dw;
  1830. char szKey[256];
  1831. char szName[CLSID_STRLEN + 1];
  1832. StringCopyArray(szKey, c_szAsmKey);
  1833. StringCatArray(szKey, "\\");
  1834. StringCchPrintf(szKey + lstrlen(szKey), ARRAYSIZE(szKey) - lstrlen(szKey), "0x%08x", langid);
  1835. StringCatArray(szKey, "\\");
  1836. CLSIDToStringA(catid, szKey + lstrlen(szKey));
  1837. *pclsid = GUID_NULL;
  1838. if (key.Open(HKEY_CURRENT_USER, szKey, KEY_READ) != S_OK)
  1839. return FALSE;
  1840. if (key.QueryValueCch(szName, c_szDefault, ARRAYSIZE(szName)) != S_OK)
  1841. return FALSE;
  1842. StringAToCLSID(szName, pclsid);
  1843. if (key.QueryValueCch(szName, c_szProfile, ARRAYSIZE(szName)) != S_OK)
  1844. return FALSE;
  1845. StringAToCLSID(szName, pguidProfile);
  1846. if (phKL)
  1847. {
  1848. *phKL = NULL;
  1849. if (key.QueryValue(dw, c_szKeyboardLayout) != S_OK)
  1850. return FALSE;
  1851. *phKL = (HKL)IntToPtr(dw);
  1852. }
  1853. return TRUE;
  1854. }
  1855. //+---------------------------------------------------------------------------
  1856. //
  1857. // SetDefaultTIPInAssemblyInternal
  1858. //
  1859. //----------------------------------------------------------------------------
  1860. BOOL CAssemblyList::SetDefaultTIPInAssemblyInternal(CAssembly *pAsm, ASSEMBLYITEM *pItem, BOOL fChangeDefault)
  1861. {
  1862. ASSEMBLYITEM *pItemSub = NULL;
  1863. BOOL bRet = FALSE;
  1864. Assert(!pItem->hkl || (pAsm->GetLangId() == LOWORD((DWORD)(LONG_PTR)(HKL)pItem->hkl)));
  1865. //
  1866. // If given hKL is substituted hKL, we set the original TIP as a default.
  1867. //
  1868. if (IsEqualGUID(pItem->catid, GUID_TFCAT_TIP_KEYBOARD))
  1869. {
  1870. #if 0
  1871. //
  1872. // Chienese platform special. We don't set the new default keyboard.
  1873. //
  1874. if (IsChinesePlatform())
  1875. {
  1876. return TRUE;
  1877. }
  1878. pItemSub = pAsm->GetSubstituteItem(pItem->hkl);
  1879. if (fChangeDefault)
  1880. {
  1881. //
  1882. // try to change the system default hKL.
  1883. //
  1884. // When TIP that has substitute HKL is selected.
  1885. // if the language of the system default hKL is same,
  1886. // set the hKL.
  1887. //
  1888. // When IME is selected.
  1889. // if the language of the system default hKL is same, set it.
  1890. //
  1891. HKL hklNewDef = IsPureIMEHKL(pItem->hkl) ? pItem->hkl : (IsPureIMEHKL(pItem->hklSubstitute) ? pItem->hklSubstitute : pItem->hkl);
  1892. if (!IsFELangId(LOWORD((WORD)(LONG_PTR)(HKL)pItem->hkl)) || hklNewDef)
  1893. {
  1894. HKL hklDef = GetSystemDefaultHKL();
  1895. if ((hklDef != hklNewDef) &&
  1896. (LOWORD((WORD)(LONG_PTR)hklDef) == LOWORD((WORD)(LONG_PTR)hklNewDef)))
  1897. {
  1898. SetSystemDefaultHKL(hklNewDef);
  1899. }
  1900. }
  1901. }
  1902. #else
  1903. HKL hklDef = GetSystemDefaultHKL();
  1904. if (pAsm->GetLangId() == LANGIDFROMHKL(hklDef))
  1905. {
  1906. //
  1907. // Now we can set the default layout directly from CPL instead of
  1908. // just set language(bug#353989)
  1909. //
  1910. return TRUE;
  1911. }
  1912. pItemSub = pAsm->GetSubstituteItem(pItem->hkl);
  1913. #endif
  1914. }
  1915. if (pItemSub)
  1916. {
  1917. bRet = SetDefaultTIPInAssembly(pAsm->GetLangId(),
  1918. pItemSub->catid,
  1919. pItemSub->clsid,
  1920. pItemSub->hkl,
  1921. pItemSub->guidProfile);
  1922. }
  1923. else
  1924. {
  1925. bRet = SetDefaultTIPInAssembly(pAsm->GetLangId(),
  1926. pItem->catid,
  1927. pItem->clsid,
  1928. pItem->hkl,
  1929. pItem->guidProfile);
  1930. }
  1931. return bRet;
  1932. }
  1933. //+---------------------------------------------------------------------------
  1934. //
  1935. // SetDefaultTIPInAssembly
  1936. //
  1937. //----------------------------------------------------------------------------
  1938. BOOL CAssemblyList::SetDefaultTIPInAssembly(LANGID langid, REFGUID catid, REFCLSID clsid, HKL hKL, REFGUID guidProfile)
  1939. {
  1940. CMyRegKey key;
  1941. char szKey[256];
  1942. char szName[256];
  1943. StringCopyArray(szKey, c_szAsmKey);
  1944. StringCatArray(szKey, "\\");
  1945. StringCchPrintf(szKey + lstrlen(szKey), ARRAYSIZE(szKey) - lstrlen(szKey), "0x%08x", langid);
  1946. StringCatArray(szKey, "\\");
  1947. CLSIDToStringA(catid, szKey + lstrlen(szKey));
  1948. if (key.Create(HKEY_CURRENT_USER, szKey) != S_OK)
  1949. return FALSE;
  1950. CLSIDToStringA(clsid, szName);
  1951. if (key.SetValue(szName, c_szDefault) != S_OK)
  1952. return FALSE;
  1953. CLSIDToStringA(guidProfile, szName);
  1954. if (key.SetValue(szName, c_szProfile) != S_OK)
  1955. return FALSE;
  1956. if (key.SetValue((DWORD)(ULONG_PTR)hKL, c_szKeyboardLayout) != S_OK)
  1957. return FALSE;
  1958. return TRUE;
  1959. }
  1960. //+---------------------------------------------------------------------------
  1961. //
  1962. // IsFEDummyKL
  1963. //
  1964. //----------------------------------------------------------------------------
  1965. BOOL CAssemblyList::IsFEDummyKL(HKL hkl)
  1966. {
  1967. char szProfile[256];
  1968. char szDummyProfile[256];
  1969. static HKL hkl411Dummy = 0;
  1970. static HKL hkl404Dummy = 0;
  1971. static HKL hkl412Dummy = 0;
  1972. static HKL hkl804Dummy = 0;
  1973. HKL *phklDummy = NULL;
  1974. BOOL bRet = FALSE;
  1975. //
  1976. // we don't use DummyHKL under NT.
  1977. //
  1978. if (IsOnNT())
  1979. return FALSE;
  1980. switch (LANGIDFROMLCID(hkl))
  1981. {
  1982. case 0x411: phklDummy = &hkl411Dummy; break;
  1983. case 0x412: phklDummy = &hkl412Dummy; break;
  1984. case 0x404: phklDummy = &hkl404Dummy; break;
  1985. case 0x804: phklDummy = &hkl804Dummy; break;
  1986. default:
  1987. return FALSE;
  1988. }
  1989. if (!ImmGetDescription(hkl, szProfile, ARRAYSIZE(szProfile)))
  1990. {
  1991. return FALSE;
  1992. }
  1993. CicEnterCriticalSection(g_cs);
  1994. if (*phklDummy)
  1995. {
  1996. bRet = (*phklDummy == hkl) ? TRUE : FALSE;
  1997. }
  1998. else
  1999. {
  2000. StringCchPrintf(szDummyProfile, ARRAYSIZE(szDummyProfile), "hkl%04x", LOWORD((DWORD)(UINT_PTR)hkl));
  2001. if (!lstrcmp(szDummyProfile, szProfile))
  2002. {
  2003. *phklDummy = hkl;
  2004. bRet = TRUE;
  2005. }
  2006. }
  2007. CicLeaveCriticalSection(g_cs);
  2008. return bRet;
  2009. }
  2010. //+---------------------------------------------------------------------------
  2011. //
  2012. // CheckKeyboardLayoutReg
  2013. //
  2014. //
  2015. // Hack for IMM32 hard code for "kbdjp.kbd" for Japanese hKL.
  2016. // If ImmInstallIME() fails, we try it after patching registry key.
  2017. //
  2018. //----------------------------------------------------------------------------
  2019. HKL CheckKeyboardLayoutReg(LANGID langid)
  2020. {
  2021. CMyRegKey key;
  2022. DWORD dwIndex;
  2023. TCHAR szValue[MAX_PATH];
  2024. //
  2025. // This is just for Win9x Kor,CHT,CHS
  2026. //
  2027. if (IsOnNT())
  2028. return NULL;
  2029. if ((g_uACP != 936) && (g_uACP != 949) && (g_uACP != 950))
  2030. return NULL;
  2031. //
  2032. // This is for HKL0411 only.
  2033. //
  2034. if (langid != 0x0411)
  2035. return NULL;
  2036. if (key.Open(HKEY_LOCAL_MACHINE, c_szKeyboardLayoutKey, KEY_READ) != S_OK)
  2037. return NULL;
  2038. dwIndex = 0;
  2039. while (key.EnumKey(dwIndex, szValue, ARRAYSIZE(szValue)) == S_OK)
  2040. {
  2041. CMyRegKey keyHKL;
  2042. TCHAR szName[13];
  2043. if (keyHKL.Open(key, szValue, KEY_ALL_ACCESS) != S_OK)
  2044. goto Next;
  2045. if (keyHKL.QueryValueCch(szName, c_szIMEFile, ARRAYSIZE(szName)) != S_OK)
  2046. goto Next;
  2047. if (!lstrcmpi(szName, "hkl0411.dll"))
  2048. {
  2049. //
  2050. // patch LayoutFile to kbdus.kbd and load the keyboard layout.
  2051. //
  2052. if (keyHKL.SetValue(c_szKbdUSName, c_szLayoutFile) != S_OK)
  2053. return NULL;
  2054. return LoadKeyboardLayout(szValue, KLF_NOTELLSHELL);
  2055. }
  2056. Next:
  2057. dwIndex++;
  2058. }
  2059. return NULL;
  2060. }
  2061. //+---------------------------------------------------------------------------
  2062. //
  2063. // GetProperHKL
  2064. //
  2065. //----------------------------------------------------------------------------
  2066. HKL CAssemblyList::GetProperHKL(LANGID langid, HKL *lphkl, BOOL *pfLoaded)
  2067. {
  2068. char szhkl[16];
  2069. HKL hkl = NULL;
  2070. BOOL fFELang = IsFELangId(langid) ? TRUE : FALSE;
  2071. if (pfLoaded)
  2072. *pfLoaded = FALSE;
  2073. if (lphkl)
  2074. {
  2075. while (*lphkl)
  2076. {
  2077. if (langid == (LANGID)((DWORD)(UINT_PTR)(*lphkl) & 0x0000ffff))
  2078. {
  2079. //
  2080. // Under FE language, we have a specialcase.
  2081. //
  2082. if (fFELang)
  2083. {
  2084. //
  2085. // Dummy HKL should be used.
  2086. //
  2087. if (IsIMEHKL(*lphkl))
  2088. {
  2089. if (IsFEDummyKL(*lphkl))
  2090. {
  2091. hkl = *lphkl;
  2092. break;
  2093. }
  2094. goto Next;
  2095. }
  2096. //
  2097. // We strongly want to use a primary hKL for FE.
  2098. //
  2099. if ((HIWORD((DWORD)(UINT_PTR)*lphkl) != langid))
  2100. goto Next;
  2101. }
  2102. hkl = *lphkl;
  2103. break;
  2104. }
  2105. Next:
  2106. lphkl++;
  2107. }
  2108. }
  2109. //
  2110. // if we could find any, return.
  2111. //
  2112. if (hkl)
  2113. return hkl;
  2114. if (!IsOnNT() && IsOnFE() && IsFELangId(langid))
  2115. {
  2116. char szSys[MAX_PATH];
  2117. char szDll[MAX_PATH];
  2118. char szLayout[16];
  2119. GetSystemDirectory(szSys, sizeof(szSys));
  2120. StringCchPrintf(szDll, ARRAYSIZE(szDll),"%s\\hkl%04x.dll", szSys, langid);
  2121. StringCchPrintf(szLayout, ARRAYSIZE(szLayout),"hkl%04x", langid);
  2122. hkl = ImmInstallIME(szDll, szLayout);
  2123. if (!hkl)
  2124. {
  2125. hkl = CheckKeyboardLayoutReg(langid);
  2126. if (hkl)
  2127. {
  2128. #if 0
  2129. RemoveFEDummyHKLFromPreloadReg(hkl);
  2130. #endif
  2131. goto Exit;
  2132. }
  2133. //
  2134. // error to load Dummy hKL.
  2135. // we just use a primary English language.
  2136. //
  2137. StringCchPrintf(szhkl, ARRAYSIZE(szhkl),"%08x", 0x0409);
  2138. hkl = LoadKeyboardLayout(szhkl, KLF_NOTELLSHELL);
  2139. }
  2140. #if 0
  2141. else
  2142. {
  2143. //
  2144. // check the dummy HKL from Preload section of registry and remove
  2145. // it since ImmInstallIME automatically add hkl to Preload section.
  2146. //
  2147. RemoveFEDummyHKLFromPreloadReg(hkl);
  2148. }
  2149. #endif
  2150. goto Exit;
  2151. }
  2152. StringCchPrintf(szhkl, ARRAYSIZE(szhkl),"%08x", langid);
  2153. hkl = LoadKeyboardLayout(szhkl, KLF_NOTELLSHELL);
  2154. //
  2155. // if we fail to create a hKL for langid, check this registry entry.
  2156. //
  2157. // HKLM\SYSTEM\CurrentControlSet\Control\Keyboard Layouts\[langid]
  2158. //
  2159. // without the key, it fails to create a default keyboard layout.
  2160. //
  2161. Assert(LOWORD(hkl) == langid);
  2162. //
  2163. // if hkl has NULL value and the current langid is FE, then we try to add
  2164. // the default keyboard layout in the system.
  2165. //
  2166. if (IsFELangId(langid) && ((LOWORD(hkl) != langid) || IsPureIMEHKL(hkl)))
  2167. {
  2168. char szKey[256];
  2169. CMyRegKey key;
  2170. if (IsOn98orNT5())
  2171. StringCopyArray(szKey, c_szLocaleInfo);
  2172. else
  2173. StringCopyArray(szKey, c_szLocaleInfoNT4);
  2174. //
  2175. // see if the user has Administrative privileges by checking for
  2176. // write permission to the registry key(NLS path).
  2177. //
  2178. if (key.Open(HKEY_LOCAL_MACHINE, szKey, KEY_WRITE) != S_OK)
  2179. goto Exit;
  2180. else
  2181. {
  2182. StringCopyArray(szKey, c_szKeyboardLayoutKey);
  2183. StringCchPrintf(szhkl, ARRAYSIZE(szhkl), "%08x", langid);
  2184. StringCatArray(szKey, szhkl);
  2185. //
  2186. // create new keyboard layout registry key and value.
  2187. //
  2188. if (key.Create(HKEY_LOCAL_MACHINE, szKey) == S_OK)
  2189. {
  2190. char szKbdName[256];
  2191. if (IsOnNT())
  2192. StringCopyArray(szKbdName, c_szKbdUSNameNT);
  2193. else
  2194. StringCopyArray(szKbdName, c_szKbdUSName);
  2195. if (key.SetValue(szKbdName, c_szLayoutFile) == S_OK)
  2196. {
  2197. //
  2198. // now try to reload keyboard layout again.
  2199. //
  2200. hkl = LoadKeyboardLayout(szhkl, KLF_NOTELLSHELL);
  2201. }
  2202. }
  2203. }
  2204. }
  2205. Exit:
  2206. if (hkl && pfLoaded)
  2207. *pfLoaded = TRUE;
  2208. return hkl;
  2209. }