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.

908 lines
23 KiB

  1. /**************************************************************************\
  2. * Module Name: layout.c (corresponds to Win95 ime.c)
  3. *
  4. * Copyright (c) 1985 - 1999, Microsoft Corporation
  5. *
  6. * IME Keyboard Layout related functionality
  7. *
  8. * History:
  9. * 03-Jan-1996 wkwok Created
  10. \**************************************************************************/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. /*
  14. * Local Defines.
  15. */
  16. #define szLZOpenFileW "LZOpenFileW"
  17. #define szLZCopy "LZCopy"
  18. #define szLZClose "LZClose"
  19. typedef HFILE (WINAPI *LPFNLZOPENFILEW)(LPTSTR, LPOFSTRUCT, WORD);
  20. typedef LONG (WINAPI *LPFNLZCOPY)(INT, INT);
  21. typedef VOID (WINAPI *LPFNLZCLOSE)(INT);
  22. /*
  23. * Local Routines.
  24. */
  25. UINT StrToUInt(LPWSTR);
  26. VOID UIntToStr(UINT, ULONG, LPWSTR, USHORT);
  27. BOOL CopyImeFile(LPWSTR, LPCWSTR);
  28. INT GetImeLayout(PIMELAYOUT, INT);
  29. BOOL WriteImeLayout(HKL, LPCWSTR, LPCWSTR);
  30. HKL AssignNewLayout(INT, PIMELAYOUT, HKL);
  31. /***************************************************************************\
  32. * ImmGetIMEFileNameW
  33. *
  34. * Gets the description of the IME with the specified HKL.
  35. *
  36. * History:
  37. * 28-Feb-1995 wkwok Created
  38. \***************************************************************************/
  39. UINT WINAPI ImmGetDescriptionW(
  40. HKL hKL,
  41. LPWSTR lpwszDescription,
  42. UINT uBufLen)
  43. {
  44. IMEINFOEX iiex;
  45. UINT uRet;
  46. if (!ImmGetImeInfoEx(&iiex, ImeInfoExKeyboardLayout, &hKL))
  47. return 0;
  48. #if defined(CUAS_ENABLE)
  49. if (!IS_IME_KBDLAYOUT(hKL))
  50. return 0;
  51. #endif
  52. uRet = wcslen(iiex.wszImeDescription);
  53. /*
  54. * ask buffer length
  55. */
  56. if (uBufLen == 0)
  57. return uRet;
  58. if (uBufLen > uRet) {
  59. wcscpy(lpwszDescription, iiex.wszImeDescription);
  60. }
  61. else {
  62. uRet = uBufLen - 1;
  63. wcsncpy(lpwszDescription, iiex.wszImeDescription, uRet);
  64. lpwszDescription[uRet] = L'\0';
  65. }
  66. return uRet;
  67. }
  68. /***************************************************************************\
  69. * ImmGetIMEFileNameA
  70. *
  71. * Gets the description of the IME with the specified HKL.
  72. *
  73. * History:
  74. * 28-Feb-1995 wkwok Created
  75. \***************************************************************************/
  76. UINT WINAPI ImmGetDescriptionA(
  77. HKL hKL,
  78. LPSTR lpszDescription,
  79. UINT uBufLen)
  80. {
  81. IMEINFOEX iiex;
  82. INT i;
  83. BOOL bUDC;
  84. if (!ImmGetImeInfoEx(&iiex, ImeInfoExKeyboardLayout, &hKL))
  85. return 0;
  86. #if defined(CUAS_ENABLE)
  87. if (!IS_IME_KBDLAYOUT(hKL))
  88. return 0;
  89. #endif
  90. i = WideCharToMultiByte(CP_ACP,
  91. (DWORD)0,
  92. (LPWSTR)iiex.wszImeDescription, // src
  93. wcslen(iiex.wszImeDescription),
  94. lpszDescription, // dest
  95. uBufLen,
  96. (LPSTR)NULL,
  97. (LPBOOL)&bUDC);
  98. if (uBufLen != 0)
  99. lpszDescription[i] = '\0';
  100. return (UINT)i;
  101. }
  102. /***************************************************************************\
  103. * ImmGetIMEFileNameW
  104. *
  105. * Gets the file name of the IME with the specified HKL.
  106. *
  107. * History:
  108. * 28-Feb-1995 wkwok Created
  109. \***************************************************************************/
  110. UINT WINAPI ImmGetIMEFileNameW(
  111. HKL hKL,
  112. LPWSTR lpwszFile,
  113. UINT uBufLen)
  114. {
  115. IMEINFOEX iiex;
  116. UINT uRet;
  117. if (!ImmGetImeInfoEx(&iiex, ImeInfoExKeyboardLayout, &hKL))
  118. return 0;
  119. #if defined(CUAS_ENABLE)
  120. if (!IS_IME_KBDLAYOUT(hKL))
  121. {
  122. //
  123. // #602631
  124. //
  125. // Ichitaro12 ATOKLIB.DLL does not check the return value of
  126. // ImmGetIMEFileName()
  127. //
  128. if (uBufLen)
  129. *lpwszFile = L'\0';
  130. return 0;
  131. }
  132. #endif
  133. uRet = wcslen(iiex.wszImeFile);
  134. /*
  135. * ask buffer length
  136. */
  137. if (uBufLen == 0)
  138. return uRet;
  139. if (uBufLen > uRet) {
  140. wcscpy(lpwszFile, iiex.wszImeFile);
  141. }
  142. else {
  143. uRet = uBufLen - 1;
  144. wcsncpy(lpwszFile, iiex.wszImeFile, uRet);
  145. lpwszFile[uRet] = L'\0';
  146. }
  147. return uRet;
  148. }
  149. /***************************************************************************\
  150. * ImmGetIMEFileNameA
  151. *
  152. * Gets the file name of the IME with the specified HKL.
  153. *
  154. * History:
  155. * 28-Feb-1995 wkwok Created
  156. \***************************************************************************/
  157. UINT WINAPI ImmGetIMEFileNameA(
  158. HKL hKL,
  159. LPSTR lpszFile,
  160. UINT uBufLen)
  161. {
  162. IMEINFOEX iiex;
  163. INT i;
  164. BOOL bUDC;
  165. if (!ImmGetImeInfoEx(&iiex, ImeInfoExKeyboardLayout, &hKL))
  166. return 0;
  167. #if defined(CUAS_ENABLE)
  168. if (!IS_IME_KBDLAYOUT(hKL))
  169. {
  170. //
  171. // #602631
  172. //
  173. // Ichitaro12 ATOKLIB.DLL does not check the return value of
  174. // ImmGetIMEFileName()
  175. //
  176. if (uBufLen)
  177. *lpszFile = '\0';
  178. return 0;
  179. }
  180. #endif
  181. i = WideCharToMultiByte(CP_ACP,
  182. (DWORD)0,
  183. (LPWSTR)iiex.wszImeFile, // src
  184. wcslen(iiex.wszImeFile),
  185. lpszFile, // dest
  186. uBufLen,
  187. (LPSTR)NULL,
  188. (LPBOOL)&bUDC);
  189. if (uBufLen != 0)
  190. lpszFile[i] = '\0';
  191. return i;
  192. }
  193. /***************************************************************************\
  194. * ImmGetProperty
  195. *
  196. * Gets the property and capability of the IME with the specified HKL.
  197. *
  198. * History:
  199. * 28-Feb-1995 wkwok Created
  200. \***************************************************************************/
  201. DWORD WINAPI ImmGetProperty(
  202. HKL hKL,
  203. DWORD dwIndex)
  204. {
  205. IMEINFOEX iiex;
  206. PIMEDPI pImeDpi = NULL;
  207. PIMEINFO pImeInfo;
  208. DWORD dwRet;
  209. if (!ImmGetImeInfoEx(&iiex, ImeInfoExKeyboardLayout, &hKL))
  210. return 0;
  211. if (dwIndex == IGP_GETIMEVERSION)
  212. return iiex.dwImeWinVersion;
  213. if (iiex.fLoadFlag != IMEF_LOADED) {
  214. pImeDpi = FindOrLoadImeDpi(hKL);
  215. if (pImeDpi == NULL) {
  216. RIPMSG0(RIP_WARNING, "ImmGetProperty: load IME failure.");
  217. return 0;
  218. }
  219. pImeInfo = &pImeDpi->ImeInfo;
  220. }
  221. else {
  222. pImeInfo = &iiex.ImeInfo;
  223. }
  224. switch (dwIndex) {
  225. case IGP_PROPERTY:
  226. dwRet = pImeInfo->fdwProperty;
  227. break;
  228. case IGP_CONVERSION:
  229. dwRet = pImeInfo->fdwConversionCaps;
  230. break;
  231. case IGP_SENTENCE:
  232. dwRet = pImeInfo->fdwSentenceCaps;
  233. break;
  234. case IGP_UI:
  235. dwRet = pImeInfo->fdwUICaps;
  236. break;
  237. case IGP_SETCOMPSTR:
  238. dwRet = pImeInfo->fdwSCSCaps;
  239. break;
  240. case IGP_SELECT:
  241. dwRet = pImeInfo->fdwSelectCaps;
  242. break;
  243. default:
  244. RIPMSG1(RIP_WARNING, "ImmGetProperty: wrong index %lx.", dwIndex);
  245. dwRet = 0;
  246. break;
  247. }
  248. ImmUnlockImeDpi(pImeDpi);
  249. return dwRet;
  250. }
  251. HKL WINAPI ImmInstallIMEW(
  252. LPCWSTR lpszIMEFileName,
  253. LPCWSTR lpszLayoutText)
  254. {
  255. LPWSTR lpwszImeFileName;
  256. LPWSTR lpwszImeFilePart;
  257. LPWSTR lpwszImeCopiedPath;
  258. int i, nIMEs;
  259. PIMELAYOUT pImeLayout = NULL;
  260. HKL hImeKL, hLangKL;
  261. WCHAR szKeyName[HEX_ASCII_SIZE];
  262. IMEINFOEX iiex;
  263. lpwszImeFileName = ImmLocalAlloc(0, (MAX_PATH+1) * sizeof(WCHAR));
  264. if (lpwszImeFileName == NULL)
  265. return (HKL)0;
  266. lpwszImeCopiedPath = ImmLocalAlloc(0, (MAX_PATH+1) * sizeof(WCHAR));
  267. if (lpwszImeCopiedPath == NULL) {
  268. ImmLocalFree(lpwszImeFileName);
  269. return (HKL)0;
  270. }
  271. /*
  272. * Get the file name only into lpwszImeFilePart
  273. */
  274. GetFullPathNameW(lpszIMEFileName, MAX_PATH,
  275. lpwszImeFileName, &lpwszImeFilePart);
  276. CharUpper(lpwszImeFileName);
  277. if (lpwszImeFilePart == NULL) {
  278. ImmLocalFree(lpwszImeFileName);
  279. ImmLocalFree(lpwszImeCopiedPath);
  280. return (HKL)0;
  281. }
  282. hImeKL = hLangKL = iiex.hkl = (HKL)0;
  283. wcsncpy(iiex.wszImeFile, lpwszImeFilePart, IM_FILE_SIZE-1);
  284. iiex.wszImeFile[IM_FILE_SIZE - 1] = L'\0';
  285. if (LoadVersionInfo(&iiex) && iiex.hkl != (HKL)0) {
  286. hLangKL = iiex.hkl;
  287. }
  288. else {
  289. ImmLocalFree(lpwszImeFileName);
  290. ImmLocalFree(lpwszImeCopiedPath);
  291. return (HKL)0;
  292. }
  293. nIMEs = GetImeLayout(NULL, 0);
  294. if (nIMEs != 0) {
  295. pImeLayout = (PIMELAYOUT)ImmLocalAlloc(0, nIMEs * sizeof(IMELAYOUT));
  296. if (pImeLayout == NULL) {
  297. ImmLocalFree(lpwszImeFileName);
  298. ImmLocalFree(lpwszImeCopiedPath);
  299. return (HKL)0;
  300. }
  301. GetImeLayout(pImeLayout, nIMEs);
  302. for (i=0; i < nIMEs; i++) {
  303. if (_wcsicmp(pImeLayout[i].szImeName, lpwszImeFilePart) == 0) {
  304. /*
  305. * We got the same IME name, ISV wants to upgrade.
  306. */
  307. if (LOWORD(HandleToUlong(hLangKL)) != LOWORD(HandleToUlong(pImeLayout[i].hImeKL))) {
  308. /*
  309. * IME name conflict, blow out!
  310. */
  311. RIPMSG0(RIP_WARNING, "ImmInstallIME: different language!");
  312. goto ImmInstallIMEWFailed;
  313. }
  314. hImeKL = pImeLayout[i].hImeKL;
  315. break;
  316. }
  317. }
  318. }
  319. if (ImmGetImeInfoEx(&iiex, ImeInfoExImeFileName, lpwszImeFilePart)) {
  320. /*
  321. * The specified IME has been activated. Unload it first.
  322. */
  323. if (!UnloadKeyboardLayout(iiex.hkl)) {
  324. hImeKL = (HKL)0;
  325. goto ImmInstallIMEWFailed;
  326. }
  327. }
  328. /*
  329. * We will copy to system directory
  330. */
  331. #if 0
  332. i = (INT)GetSystemDirectory(lpwszImeCopiedPath, MAX_PATH);
  333. lpwszImeCopiedPath[i] = L'\0';
  334. AddBackslash(lpwszImeCopiedPath);
  335. wcscat(lpwszImeCopiedPath, lpwszImeFilePart);
  336. #else
  337. GetSystemPathName(lpwszImeCopiedPath, lpwszImeFilePart, MAX_PATH);
  338. #endif
  339. CharUpper(lpwszImeCopiedPath);
  340. if (_wcsicmp(lpwszImeFileName, lpwszImeCopiedPath) != 0) {
  341. /*
  342. * path is different, need to copy into system directory
  343. */
  344. if (!CopyImeFile(lpwszImeFileName, lpwszImeCopiedPath)) {
  345. hImeKL = (HKL)0;
  346. goto ImmInstallIMEWFailed;
  347. }
  348. }
  349. if (hImeKL == 0) {
  350. hImeKL = AssignNewLayout(nIMEs, pImeLayout, hLangKL);
  351. }
  352. if (hImeKL != 0) {
  353. /*
  354. * Write HKL under "keyboard layouts"
  355. */
  356. if (WriteImeLayout(hImeKL, lpwszImeFilePart, lpszLayoutText)) {
  357. UIntToStr(HandleToUlong(hImeKL), 16, szKeyName, sizeof(szKeyName));
  358. hImeKL = LoadKeyboardLayout(szKeyName, KLF_REPLACELANG);
  359. }
  360. else {
  361. hImeKL = (HKL)0;
  362. }
  363. }
  364. ImmInstallIMEWFailed:
  365. if (pImeLayout != NULL)
  366. ImmLocalFree(pImeLayout);
  367. ImmLocalFree(lpwszImeFileName);
  368. ImmLocalFree(lpwszImeCopiedPath);
  369. return (HKL)hImeKL;
  370. }
  371. HKL WINAPI ImmInstallIMEA(
  372. LPCSTR lpszIMEFileName,
  373. LPCSTR lpszLayoutText)
  374. {
  375. HKL hKL;
  376. LPWSTR lpwszIMEFileName;
  377. LPWSTR lpwszLayoutText;
  378. DWORD cbIMEFileName;
  379. DWORD cbLayoutText;
  380. INT i;
  381. cbIMEFileName = strlen(lpszIMEFileName) + sizeof(CHAR);
  382. cbLayoutText = strlen(lpszLayoutText) + sizeof(CHAR);
  383. lpwszIMEFileName = ImmLocalAlloc(0, cbIMEFileName * sizeof(WCHAR));
  384. if (lpwszIMEFileName == NULL) {
  385. RIPMSG0(RIP_WARNING, "ImmInstallIMEA: memory failure!");
  386. return (HKL)0;
  387. }
  388. lpwszLayoutText = ImmLocalAlloc(0, cbLayoutText * sizeof(WCHAR));
  389. if (lpwszLayoutText == NULL) {
  390. RIPMSG0(RIP_WARNING, "ImmInstallIMEA: memory failure!");
  391. ImmLocalFree(lpwszIMEFileName);
  392. return (HKL)0;
  393. }
  394. i = MultiByteToWideChar(CP_ACP,
  395. (DWORD)MB_PRECOMPOSED,
  396. (LPSTR)lpszIMEFileName, // src
  397. (INT)strlen(lpszIMEFileName),
  398. (LPWSTR)lpwszIMEFileName, // dest
  399. (INT)cbIMEFileName);
  400. lpwszIMEFileName[i] = L'\0';
  401. i = MultiByteToWideChar(CP_ACP,
  402. (DWORD)MB_PRECOMPOSED,
  403. (LPSTR)lpszLayoutText, // src
  404. (INT)strlen(lpszLayoutText),
  405. (LPWSTR)lpwszLayoutText, // dest
  406. (INT)cbLayoutText);
  407. lpwszLayoutText[i] = L'\0';
  408. hKL = ImmInstallIMEW(lpwszIMEFileName, lpwszLayoutText);
  409. ImmLocalFree(lpwszLayoutText);
  410. ImmLocalFree(lpwszIMEFileName);
  411. return hKL;
  412. }
  413. /***************************************************************************\
  414. * ImmIsIME
  415. *
  416. * Checks whether the specified hKL is a HKL of an IME or not.
  417. *
  418. * History:
  419. * 28-Feb-1995 wkwok Created
  420. \***************************************************************************/
  421. BOOL WINAPI ImmIsIME(
  422. HKL hKL)
  423. {
  424. IMEINFOEX iiex;
  425. #if !defined(CUAS_ENABLE)
  426. if (!ImmGetImeInfoEx(&iiex, ImeInfoExKeyboardLayout, &hKL))
  427. return FALSE;
  428. #else
  429. if (!ImmGetImeInfoEx(&iiex, ImeInfoExKeyboardLayoutWithCUAS, &hKL))
  430. return FALSE;
  431. #endif
  432. return TRUE;
  433. }
  434. UINT StrToUInt(
  435. LPWSTR lpsz)
  436. {
  437. UNICODE_STRING Value;
  438. UINT ReturnValue;
  439. Value.Length = wcslen(lpsz) * sizeof(WCHAR);
  440. Value.Buffer = lpsz;
  441. /*
  442. * Convert string to int.
  443. */
  444. RtlUnicodeStringToInteger(&Value, 16, &ReturnValue);
  445. return(ReturnValue);
  446. }
  447. VOID UIntToStr(
  448. UINT Value,
  449. ULONG Base,
  450. LPWSTR lpsz,
  451. USHORT dwBufLen)
  452. {
  453. UNICODE_STRING String;
  454. String.Length = dwBufLen;
  455. String.MaximumLength = dwBufLen;
  456. String.Buffer = lpsz;
  457. /*
  458. * Convert int to string.
  459. */
  460. RtlIntegerToUnicodeString(Value, Base, &String);
  461. }
  462. BOOL CopyImeFile(
  463. LPWSTR lpwszImeFileName,
  464. LPCWSTR lpwszImeCopiedPath)
  465. {
  466. HMODULE hLzExpandDll;
  467. BOOL fUnloadExpandDll;
  468. LPFNLZOPENFILEW lpfnLZOpenFileW;
  469. LPFNLZCOPY lpfnLZCopy;
  470. LPFNLZCLOSE lpfnLZClose;
  471. OFSTRUCT ofStruc;
  472. HFILE hfSource, hfDest;
  473. LPSTR lpszImeCopiedPath;
  474. INT i, cbBuffer;
  475. BOOL fRet = FALSE;
  476. hLzExpandDll = GetModuleHandle(L"LZ32");
  477. if (hLzExpandDll) {
  478. fUnloadExpandDll = FALSE;
  479. } else {
  480. WCHAR szLzExpand[MAX_PATH];
  481. GetSystemPathName(szLzExpand, L"LZ32", MAX_PATH);
  482. hLzExpandDll = LoadLibrary(szLzExpand);
  483. if (!hLzExpandDll) {
  484. return FALSE;
  485. }
  486. fUnloadExpandDll = TRUE;
  487. }
  488. #define GET_PROC(x) \
  489. if (!(lpfn##x = (PVOID) GetProcAddress(hLzExpandDll, sz##x))) { \
  490. goto CopyImeFileFailed; }
  491. GET_PROC(LZOpenFileW);
  492. GET_PROC(LZCopy);
  493. GET_PROC(LZClose);
  494. #undef GET_PROC
  495. cbBuffer = (wcslen(lpwszImeCopiedPath) + 1) * sizeof(WCHAR);
  496. if ((lpszImeCopiedPath = ImmLocalAlloc(0, cbBuffer)) == NULL)
  497. goto CopyImeFileFailed;
  498. i = WideCharToMultiByte(CP_ACP,
  499. (DWORD)0,
  500. lpwszImeCopiedPath, // src
  501. wcslen(lpwszImeCopiedPath),
  502. lpszImeCopiedPath, // dest
  503. cbBuffer,
  504. (LPSTR)NULL,
  505. (LPBOOL)NULL);
  506. if (i == 0) {
  507. ImmLocalFree(lpszImeCopiedPath);
  508. goto CopyImeFileFailed;
  509. }
  510. lpszImeCopiedPath[i] = '\0';
  511. hfSource = (*lpfnLZOpenFileW)(lpwszImeFileName, &ofStruc, OF_READ);
  512. if (hfSource < 0) {
  513. ImmLocalFree(lpszImeCopiedPath);
  514. goto CopyImeFileFailed;
  515. }
  516. hfDest = OpenFile(lpszImeCopiedPath, &ofStruc, OF_CREATE);
  517. if (hfDest != HFILE_ERROR) {
  518. if ((*lpfnLZCopy)(hfSource, hfDest) >= 0) {
  519. fRet = TRUE;
  520. }
  521. _lclose(hfDest);
  522. }
  523. (*lpfnLZClose)(hfSource);
  524. ImmLocalFree(lpszImeCopiedPath);
  525. CopyImeFileFailed:
  526. if (fUnloadExpandDll)
  527. FreeLibrary(hLzExpandDll);
  528. return fRet;
  529. }
  530. INT GetImeLayout(
  531. PIMELAYOUT pImeLayout,
  532. INT cEntery)
  533. {
  534. int i, nIMEs;
  535. HKEY hKeyKbdLayout;
  536. HKEY hKeyOneIME;
  537. WCHAR szKeyName[HEX_ASCII_SIZE];
  538. WCHAR szImeFileName[IM_FILE_SIZE];
  539. CONST DWORD dwKeyNameSize = ARRAY_SIZE(szKeyName);
  540. DWORD dwTmp;
  541. RegOpenKey(HKEY_LOCAL_MACHINE, gszRegKbdLayout, &hKeyKbdLayout);
  542. for (i = 0, nIMEs = 0;
  543. RegEnumKey(hKeyKbdLayout, i, szKeyName, dwKeyNameSize) == ERROR_SUCCESS;
  544. i++)
  545. {
  546. if (szKeyName[0] != L'E' && szKeyName[0] != L'e')
  547. continue; // this is not an IME based keyboard layout.
  548. if (pImeLayout != NULL) {
  549. if (nIMEs >= cEntery)
  550. break;
  551. RegOpenKey(hKeyKbdLayout, szKeyName, &hKeyOneIME);
  552. dwTmp = IM_FILE_SIZE;
  553. RegQueryValueEx(hKeyOneIME,
  554. gszValImeFile,
  555. NULL,
  556. NULL,
  557. (LPBYTE)szImeFileName,
  558. &dwTmp);
  559. // avoid length problem
  560. szImeFileName[IM_FILE_SIZE - 1] = L'\0';
  561. RegCloseKey(hKeyOneIME);
  562. CharUpper(szImeFileName);
  563. pImeLayout[nIMEs].hImeKL = (HKL)IntToPtr( StrToUInt(szKeyName) );
  564. wcscpy(pImeLayout[nIMEs].szKeyName, szKeyName);
  565. wcscpy(pImeLayout[nIMEs].szImeName, szImeFileName);
  566. }
  567. nIMEs++;
  568. }
  569. RegCloseKey(hKeyKbdLayout);
  570. return nIMEs;
  571. }
  572. BOOL WriteImeLayout(
  573. HKL hImeKL,
  574. LPCWSTR lpwszImeFilePart,
  575. LPCWSTR lpszLayoutText)
  576. {
  577. int i;
  578. HKEY hKeyKbdLayout;
  579. HKEY hKeyOneIME;
  580. HKEY hKeyKbdOrder;
  581. WCHAR szKeyName[HEX_ASCII_SIZE];
  582. WCHAR szImeFileName[IM_FILE_SIZE];
  583. WCHAR szOrderNum[HEX_ASCII_SIZE];
  584. WCHAR szOrderKeyName[HEX_ASCII_SIZE];
  585. DWORD dwTmp;
  586. if (RegOpenKey(HKEY_LOCAL_MACHINE,
  587. gszRegKbdLayout,
  588. &hKeyKbdLayout) != ERROR_SUCCESS) {
  589. RIPMSG0(RIP_WARNING, "WriteImeLayout: RegOpenKey() failed!");
  590. return FALSE;
  591. }
  592. UIntToStr(HandleToUlong(hImeKL), 16, szKeyName, sizeof(szKeyName));
  593. if (RegCreateKey(hKeyKbdLayout,
  594. szKeyName,
  595. &hKeyOneIME) != ERROR_SUCCESS) {
  596. RIPMSG0(RIP_WARNING, "WriteImeLayout: RegCreateKey() failed!");
  597. RegCloseKey(hKeyKbdLayout);
  598. return FALSE;
  599. }
  600. if (RegSetValueExW(hKeyOneIME,
  601. gszValImeFile,
  602. 0,
  603. REG_SZ,
  604. (CONST BYTE*)lpwszImeFilePart,
  605. (wcslen(lpwszImeFilePart) + 1) * sizeof(WCHAR)) != ERROR_SUCCESS) {
  606. goto WriteImeLayoutFail;
  607. }
  608. if (RegSetValueExW(hKeyOneIME,
  609. gszValLayoutText,
  610. 0,
  611. REG_SZ,
  612. (CONST BYTE*)lpszLayoutText,
  613. (wcslen(lpszLayoutText) + 1) * sizeof(WCHAR)) != ERROR_SUCCESS) {
  614. goto WriteImeLayoutFail;
  615. }
  616. switch (LANGIDFROMHKL(hImeKL)) {
  617. case LANG_JAPANESE:
  618. wcscpy(szImeFileName, L"kbdjpn.dll");
  619. break;
  620. case LANG_KOREAN:
  621. wcscpy(szImeFileName, L"kbdkor.dll");
  622. break;
  623. case LANG_CHINESE:
  624. default:
  625. wcscpy(szImeFileName, L"kbdus.dll");
  626. break;
  627. }
  628. if (RegSetValueExW(hKeyOneIME,
  629. gszValLayoutFile,
  630. 0,
  631. REG_SZ,
  632. (CONST BYTE*)szImeFileName,
  633. (wcslen(szImeFileName) + 1) * sizeof(WCHAR)) != ERROR_SUCCESS) {
  634. goto WriteImeLayoutFail;
  635. }
  636. RegCloseKey(hKeyOneIME);
  637. RegCloseKey(hKeyKbdLayout);
  638. /*
  639. * Update CurrentUser's preload keyboard layout setting
  640. */
  641. RegCreateKey(HKEY_CURRENT_USER, gszRegKbdOrder, &hKeyKbdOrder);
  642. for (i = 1; i < 1024; i++) {
  643. UIntToStr(i, 10, szOrderNum, sizeof(szOrderNum));
  644. dwTmp = sizeof(szOrderKeyName);
  645. if (RegQueryValueEx(hKeyKbdOrder,
  646. szOrderNum,
  647. NULL,
  648. NULL,
  649. (LPBYTE)szOrderKeyName,
  650. &dwTmp) != ERROR_SUCCESS) {
  651. break;
  652. }
  653. if (_wcsicmp(szKeyName, szOrderKeyName) == 0) {
  654. /*
  655. * We have the same value in the preload!
  656. * OK, ISV is developing their IMEs
  657. * so even it is in preload, but it can not be loaded
  658. */
  659. break;
  660. }
  661. }
  662. if (i < 1024) {
  663. /*
  664. * Write a subkey under "preload"
  665. */
  666. RegSetValueExW(hKeyKbdOrder,
  667. szOrderNum,
  668. 0,
  669. REG_SZ,
  670. (CONST BYTE*)szKeyName,
  671. (lstrlen(szKeyName) + 1) * sizeof(WCHAR));
  672. RegCloseKey(hKeyKbdOrder);
  673. }
  674. else {
  675. RegCloseKey(hKeyKbdOrder);
  676. return FALSE;
  677. }
  678. return TRUE;
  679. WriteImeLayoutFail:
  680. RegCloseKey(hKeyOneIME);
  681. RegDeleteKey(hKeyKbdLayout, szKeyName);
  682. RegCloseKey(hKeyKbdLayout);
  683. return FALSE;
  684. }
  685. #define IMELANGID(hkl) \
  686. LOWORD(HandleToUlong(hkl))
  687. #define IMELAYOUTID(hkl) \
  688. HIWORD(HandleToUlong(hkl))
  689. HKL AssignNewLayout(
  690. INT nIMEs,
  691. PIMELAYOUT pImeLayout,
  692. HKL hLangKL)
  693. {
  694. DWORD dwNewId = 0;
  695. DWORD dwHighId = 0xE01F;
  696. DWORD dwLowId = 0xE0FF;
  697. INT i;
  698. /*
  699. * We prefer the value higher than E01F for ISVs, we will use
  700. * E001 ~ E01F in Microsoft .INF file
  701. */
  702. /*
  703. * Find out the high and low one
  704. */
  705. for (i = 0; i < nIMEs; ++i) {
  706. /*
  707. * Let's try to keep the previous behavior, not to
  708. * have the duplicated hiword in hkl.
  709. */
  710. if (IMELAYOUTID(pImeLayout[i].hImeKL) > dwHighId) {
  711. dwHighId = IMELAYOUTID(pImeLayout[i].hImeKL);
  712. }
  713. if (IMELAYOUTID(pImeLayout[i].hImeKL) < dwLowId) {
  714. dwLowId = IMELAYOUTID(pImeLayout[i].hImeKL);
  715. }
  716. }
  717. if (dwHighId < 0xE0FF) {
  718. dwNewId = dwHighId + 1;
  719. } else if (dwLowId > 0xE001) {
  720. dwNewId = dwLowId - 1;
  721. } else {
  722. /*
  723. * Need to find out unused hKL using full search.
  724. * Find it one by one.
  725. */
  726. DWORD dwId;
  727. for (dwId = 0xE020; dwId < 0xE100; ++dwId) {
  728. for (i = 0; i < nIMEs; ++i) {
  729. if (IMELAYOUTID(pImeLayout[i].hImeKL) == dwId &&
  730. IMELANGID(pImeLayout[i].hImeKL) == IMELANGID(hLangKL)) {
  731. // conflicts with existing IME, try the next dwLowId
  732. break;
  733. }
  734. }
  735. if (i >= nIMEs) {
  736. break;
  737. }
  738. }
  739. if (dwId < 0xE100) {
  740. dwNewId = dwId;
  741. }
  742. }
  743. if (dwNewId == 0) {
  744. return NULL;
  745. }
  746. return (HKL)UIntToPtr(MAKELONG(IMELANGID(hLangKL), dwNewId));
  747. }