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.

3845 lines
120 KiB

  1. /**************************************************************************\
  2. * Module Name: ctxtinfo.c
  3. *
  4. * Copyright (c) 1985 - 1999, Microsoft Corporation
  5. *
  6. * Get/set routines of various Input context information for imm32.dll
  7. *
  8. * History:
  9. * 26-Feb-1996 wkwok
  10. \**************************************************************************/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. // Helper function:
  14. // Converts RECONVERTSTRING structure between ANSI and UNICODE.
  15. extern DWORD ImmReconversionWorker(LPRECONVERTSTRING lpRecTo, LPRECONVERTSTRING lpRecFrom, BOOL bToAnsi, DWORD dwCodePage);
  16. int UnicodeToMultiByteSize(DWORD dwCodePage, LPCWSTR pwstr)
  17. {
  18. char dummy[2], *lpszDummy = dummy;
  19. return WCSToMBEx((WORD)dwCodePage, pwstr, 1, &lpszDummy, sizeof(WCHAR), FALSE);
  20. }
  21. /***************************************************************************\
  22. * ImmGetCompositionStringA
  23. *
  24. * Query composition string information specified by dwIndex.
  25. *
  26. * History:
  27. * 28-Feb-1995 wkwok Created
  28. \***************************************************************************/
  29. LONG WINAPI ImmGetCompositionStringA(
  30. HIMC hImc,
  31. DWORD dwIndex,
  32. LPVOID lpBuf,
  33. DWORD dwBufLen)
  34. {
  35. PCLIENTIMC pClientImc;
  36. PINPUTCONTEXT pInputContext;
  37. PCOMPOSITIONSTRING pCompStr;
  38. BOOL fAnsi;
  39. LONG lRet = 0;
  40. DWORD dwCodePage;
  41. if (dwBufLen != 0 && lpBuf == NULL) {
  42. RIPMSG0(RIP_WARNING, "ImmGetCompositionStringW: NULL lpBuf.");
  43. return lRet;
  44. }
  45. pClientImc = ImmLockClientImc(hImc);
  46. if (pClientImc == NULL) {
  47. RIPMSG1(RIP_WARNING,
  48. "ImmGetCompositionStringA: Invalid hImc %lx.", hImc);
  49. return lRet;
  50. }
  51. fAnsi = !TestICF(pClientImc, IMCF_UNICODE);
  52. dwCodePage = CImcCodePage(pClientImc);
  53. ImmUnlockClientImc(pClientImc);
  54. pInputContext = ImmLockIMC(hImc);
  55. if (pInputContext == NULL) {
  56. RIPMSG1(RIP_WARNING, "ImmGetCompositionStringA: Lock hImc %lx failed.", hImc);
  57. return lRet;
  58. }
  59. pCompStr = (PCOMPOSITIONSTRING)ImmLockIMCC(pInputContext->hCompStr);
  60. if (pCompStr == NULL) {
  61. RIPMSG1(RIP_WARNING, "ImmGetCompositionStringA: Lock hCompStr %x failed",
  62. pInputContext->hCompStr);
  63. ImmUnlockIMC(hImc);
  64. return lRet;
  65. }
  66. #if !defined(CUAS_ENABLE)
  67. lRet = InternalGetCompositionStringA(pCompStr, dwIndex,
  68. lpBuf, dwBufLen, fAnsi, dwCodePage);
  69. #else
  70. lRet = InternalGetCompositionStringA(hImc, pCompStr, dwIndex,
  71. lpBuf, dwBufLen, fAnsi, dwCodePage);
  72. #endif
  73. ImmUnlockIMCC(pInputContext->hCompStr);
  74. ImmUnlockIMC(hImc);
  75. return lRet;
  76. }
  77. /***************************************************************************\
  78. * ImmGetCompositionStringA
  79. *
  80. * Query composition string information specified by dwIndex.
  81. *
  82. * History:
  83. * 28-Feb-1995 wkwok Created
  84. \***************************************************************************/
  85. LONG WINAPI ImmGetCompositionStringW(
  86. HIMC hImc,
  87. DWORD dwIndex,
  88. LPVOID lpBuf,
  89. DWORD dwBufLen)
  90. {
  91. PCLIENTIMC pClientImc;
  92. PINPUTCONTEXT pInputContext;
  93. PCOMPOSITIONSTRING pCompStr;
  94. BOOL fAnsi;
  95. LONG lRet = 0;
  96. DWORD dwCodePage;
  97. if (dwBufLen != 0 && lpBuf == NULL) {
  98. RIPMSG0(RIP_WARNING, "ImmGetCompositionStringW: NULL lpBuf.");
  99. return lRet;
  100. }
  101. pClientImc = ImmLockClientImc(hImc);
  102. if (pClientImc == NULL) {
  103. RIPMSG1(RIP_WARNING,
  104. "ImmGetCompositionStringW: Invalid hImc %lx.", hImc);
  105. return lRet;
  106. }
  107. fAnsi = !TestICF(pClientImc, IMCF_UNICODE);
  108. dwCodePage = CImcCodePage(pClientImc);
  109. ImmUnlockClientImc(pClientImc);
  110. pInputContext = ImmLockIMC(hImc);
  111. if (pInputContext == NULL) {
  112. RIPMSG1(RIP_WARNING, "ImmGetCompositionStringW: Lock hImc %lx failed.", hImc);
  113. return lRet;
  114. }
  115. pCompStr = (PCOMPOSITIONSTRING)ImmLockIMCC(pInputContext->hCompStr);
  116. if (pCompStr == NULL) {
  117. RIPMSG1(RIP_WARNING, "ImmGetCompositionStringA: Lock hCompStr %x failed",
  118. pInputContext->hCompStr);
  119. ImmUnlockIMC(hImc);
  120. return lRet;
  121. }
  122. #if !defined(CUAS_ENABLE)
  123. lRet = InternalGetCompositionStringW(pCompStr, dwIndex,
  124. lpBuf, dwBufLen, fAnsi, dwCodePage);
  125. #else
  126. lRet = InternalGetCompositionStringW(hImc, pCompStr, dwIndex,
  127. lpBuf, dwBufLen, fAnsi, dwCodePage);
  128. #endif
  129. ImmUnlockIMCC(pInputContext->hCompStr);
  130. ImmUnlockIMC(hImc);
  131. return lRet;
  132. }
  133. /***************************************************************************\
  134. * ImmSetCompositionStringA
  135. *
  136. * Set composition string information specified by dwIndex.
  137. *
  138. * History:
  139. * 28-Feb-1995 wkwok Created
  140. \***************************************************************************/
  141. BOOL WINAPI ImmSetCompositionStringA(
  142. HIMC hImc,
  143. DWORD dwIndex,
  144. LPVOID lpComp,
  145. DWORD dwCompLen,
  146. LPVOID lpRead,
  147. DWORD dwReadLen)
  148. {
  149. return ImmSetCompositionStringWorker(hImc, dwIndex, lpComp,
  150. dwCompLen, lpRead, dwReadLen, TRUE);
  151. }
  152. /***************************************************************************\
  153. * ImmSetCompositionStringW
  154. *
  155. * Set composition string information specified by dwIndex.
  156. *
  157. * History:
  158. * 28-Feb-1995 wkwok Created
  159. \***************************************************************************/
  160. BOOL WINAPI ImmSetCompositionStringW(
  161. HIMC hImc,
  162. DWORD dwIndex,
  163. LPVOID lpComp,
  164. DWORD dwCompLen,
  165. LPVOID lpRead,
  166. DWORD dwReadLen)
  167. {
  168. return ImmSetCompositionStringWorker(hImc, dwIndex, lpComp,
  169. dwCompLen, lpRead, dwReadLen, FALSE);
  170. }
  171. LONG CompositionString(
  172. HIMC hImc,
  173. PINPUTCONTEXT *ppInputContext,
  174. PCOMPOSITIONSTRING *ppCompStr,
  175. BOOL fCheckSize)
  176. {
  177. PINPUTCONTEXT pInputContext;
  178. PCOMPOSITIONSTRING pCompStr;
  179. pInputContext = ImmLockIMC(hImc);
  180. if (!pInputContext) {
  181. RIPMSG1(RIP_WARNING, "CompositionString: Lock hImc %lx failed.", hImc);
  182. return (LONG)IMM_ERROR_GENERAL;
  183. }
  184. if (!pInputContext->hCompStr) {
  185. ImmUnlockIMC(hImc);
  186. return (LONG)IMM_ERROR_NODATA;
  187. }
  188. pCompStr = (PCOMPOSITIONSTRING)ImmLockIMCC(pInputContext->hCompStr);
  189. if (!pCompStr) {
  190. RIPMSG1(RIP_WARNING,
  191. "CompositionString: Lock hCompStr %lx failed.", pInputContext->hCompStr);
  192. ImmUnlockIMC(hImc);
  193. return (LONG)IMM_ERROR_GENERAL;
  194. }
  195. if (fCheckSize && pCompStr->dwSize < sizeof(COMPOSITIONSTRING)) {
  196. RIPMSG0(RIP_WARNING, "CompositionString: no composition string.");
  197. ImmUnlockIMCC(pInputContext->hCompStr);
  198. ImmUnlockIMC(hImc);
  199. return (LONG)IMM_ERROR_NODATA;
  200. }
  201. *ppInputContext = pInputContext;
  202. *ppCompStr = pCompStr;
  203. return (1);
  204. }
  205. BOOL CheckAttribute(
  206. LPBYTE lpComp, // the attr from apps
  207. DWORD dwCompLen, // the attr length from apps
  208. LPBYTE lpAttr, // the attr from IMC
  209. DWORD dwAttrLen, // the attr length from IMC
  210. LPDWORD lpClause, // the clause from IMC
  211. DWORD dwClauseLen) // the clause length from IMC
  212. {
  213. DWORD dwCnt;
  214. DWORD dwBound;
  215. BYTE bAttr;
  216. UNREFERENCED_PARAMETER(dwClauseLen);
  217. if (!lpClause) {
  218. RIPMSG0(RIP_WARNING, "CheckAttribute: no Clause. Pass it to IME.");
  219. return (TRUE);
  220. }
  221. if (!lpAttr) {
  222. RIPMSG0(RIP_WARNING, "CheckAttribute: no Attr. Not pass it to IME.");
  223. return (FALSE);
  224. }
  225. if (dwCompLen != dwAttrLen) {
  226. RIPMSG0(RIP_WARNING, "CheckAttribute: wrong length. Not pass it to IME.");
  227. return (FALSE);
  228. }
  229. /*
  230. * The attr. of chars of one clause have to be same.
  231. */
  232. while (*lpClause < dwCompLen) {
  233. dwBound = *(lpClause+1) - *lpClause;
  234. bAttr = *lpComp++;
  235. for (dwCnt = 1; dwCnt < dwBound; dwCnt++)
  236. if (bAttr != *lpComp++) {
  237. RIPMSG0(RIP_WARNING,
  238. "CheckAttribute: mismatch clause att. Not Pass it to IME");
  239. return (FALSE);
  240. }
  241. lpClause++;
  242. }
  243. return (TRUE);
  244. }
  245. BOOL CheckClause(
  246. LPDWORD lpComp, // the clause from apps
  247. DWORD dwCompLen, // the clause length from apps
  248. LPDWORD lpClause, // the clause from IMC
  249. DWORD dwClauseLen) // the clause length from IMC
  250. {
  251. UINT nCnt;
  252. INT diff = 0;
  253. if (!dwClauseLen || !dwCompLen) {
  254. RIPMSG0(RIP_WARNING, "CheckClause: no Clause. Not Pass it to IME.");
  255. return (FALSE);
  256. }
  257. if (*lpComp || *lpClause) {
  258. RIPMSG0(RIP_WARNING, "CheckClause: lpClause[0] have to be ZERO.");
  259. return (FALSE);
  260. }
  261. for (nCnt = 0; nCnt < (UINT)(dwClauseLen/4); nCnt++)
  262. {
  263. if (*lpComp++ != *lpClause++)
  264. {
  265. diff++;
  266. if (dwCompLen > dwClauseLen)
  267. lpClause--;
  268. if (dwCompLen < dwClauseLen)
  269. lpComp--;
  270. }
  271. if (diff > 1)
  272. return (FALSE);
  273. }
  274. return (TRUE);
  275. }
  276. LPBYTE InternalSCS_SETSTR(
  277. LPCVOID lpCompRead,
  278. DWORD dwCompReadLen,
  279. LPVOID *lplpNewCompRead,
  280. DWORD *lpdwNewCompReadLen,
  281. BOOL fAnsi,
  282. DWORD dwCodePage)
  283. {
  284. LPBYTE lpBufRet;
  285. DWORD dwBufSize;
  286. LPSTR lpBufA;
  287. LPWSTR lpBufW;
  288. INT i;
  289. BOOL bUDC;
  290. if (lpCompRead == NULL || dwCompReadLen == 0)
  291. return NULL;
  292. dwBufSize = dwCompReadLen * sizeof(WCHAR) * 2;
  293. lpBufRet = ImmLocalAlloc(0, dwBufSize);
  294. if (lpBufRet == NULL) {
  295. RIPMSG0(RIP_WARNING, "InternalSCS_SETSTR: memory failure.");
  296. return NULL;
  297. }
  298. lpBufW = (LPWSTR)lpBufRet;
  299. lpBufA = (LPSTR)(lpBufW + dwCompReadLen);
  300. if (fAnsi) {
  301. RtlCopyMemory(lpBufA, lpCompRead, dwCompReadLen);
  302. i = MultiByteToWideChar(dwCodePage,
  303. (DWORD)MB_PRECOMPOSED,
  304. (LPSTR)lpBufA, // src
  305. (INT)dwCompReadLen,
  306. (LPWSTR)lpBufW, // dest
  307. (INT)dwCompReadLen);
  308. *lplpNewCompRead = lpBufW;
  309. *lpdwNewCompReadLen = (DWORD)(i * sizeof(WCHAR));
  310. }
  311. else {
  312. RtlCopyMemory(lpBufW, lpCompRead, dwCompReadLen);
  313. i = WideCharToMultiByte(dwCodePage,
  314. (DWORD)0,
  315. lpBufW, // src
  316. (INT)dwCompReadLen/sizeof(WCHAR),
  317. (LPSTR)lpBufA, // dest
  318. (INT)dwCompReadLen,
  319. (LPSTR)NULL,
  320. (LPBOOL)&bUDC);
  321. *lplpNewCompRead = lpBufA;
  322. *lpdwNewCompReadLen = (DWORD)(i * sizeof(CHAR));
  323. }
  324. return lpBufRet;
  325. }
  326. LPBYTE InternalSCS_CHANGEATTR(
  327. HIMC hImc,
  328. LPCVOID lpCompRead,
  329. DWORD dwCompReadLen,
  330. DWORD dwIndex,
  331. LPVOID *lplpNewCompRead,
  332. DWORD *lpdwNewCompReadLen,
  333. BOOL fAnsi,
  334. DWORD dwCodePage)
  335. {
  336. LPBYTE lpBufRet;
  337. LPBYTE lpAttr, lpAttrA, lpAttrW;
  338. DWORD dwBufLenA, dwBufLenW;
  339. LPSTR lpStrBufA, lpBufA;
  340. LPWSTR lpStrBufW, lpBufW;
  341. CHAR c;
  342. WCHAR wc;
  343. ULONG MultiByteSize;
  344. if (lpCompRead == NULL || dwCompReadLen == 0)
  345. return NULL;
  346. if (fAnsi) {
  347. dwBufLenA = ImmGetCompositionStringA(hImc, dwIndex, NULL, 0);
  348. lpStrBufA = ImmLocalAlloc(0, dwBufLenA);
  349. if (lpStrBufA == NULL) {
  350. RIPMSG0(RIP_WARNING, "InternalSCS_CHANGEATTR: memory failure.");
  351. return NULL;
  352. }
  353. ImmGetCompositionStringA(hImc, dwIndex, lpStrBufA, dwBufLenA);
  354. lpBufRet = ImmLocalAlloc(0, dwBufLenA);
  355. if (lpBufRet == NULL) {
  356. RIPMSG0(RIP_WARNING, "InternalSCS_CHANGEATTR: memory failure.");
  357. ImmLocalFree(lpStrBufA);
  358. return NULL;
  359. }
  360. lpBufA = lpStrBufA;
  361. lpAttrA = (LPBYTE)lpCompRead;
  362. lpAttr = lpBufRet;
  363. while (dwBufLenA != 0 && (c=*lpBufA++) != 0) {
  364. if (IsDBCSLeadByteEx(dwCodePage, c)) {
  365. if (dwBufLenA >= 2) {
  366. *lpAttr++ = *lpAttrA++;
  367. dwBufLenA--;
  368. } else {
  369. *lpAttr++ = *lpAttrA;
  370. }
  371. lpBufA++;
  372. } else {
  373. *lpAttr++ = *lpAttrA;
  374. }
  375. lpAttrA++;
  376. dwBufLenA--;
  377. }
  378. ImmLocalFree(lpStrBufA);
  379. }
  380. else {
  381. dwBufLenW = ImmGetCompositionStringW(hImc, dwIndex, NULL, 0);
  382. lpStrBufW = ImmLocalAlloc(0, dwBufLenW);
  383. if (lpStrBufW == NULL) {
  384. RIPMSG0(RIP_WARNING, "InternalSCS_CHANGEATTR: memory failure.");
  385. return NULL;
  386. }
  387. ImmGetCompositionStringW(hImc, dwIndex, lpStrBufW, dwBufLenW);
  388. lpBufRet = ImmLocalAlloc(0, dwBufLenW);
  389. if (lpBufRet == NULL) {
  390. RIPMSG0(RIP_WARNING, "InternalSCS_CHANGEATTR: memory failure.");
  391. ImmLocalFree(lpStrBufW);
  392. return NULL;
  393. }
  394. lpBufW = lpStrBufW;
  395. lpAttrW = (LPBYTE)lpCompRead;
  396. lpAttr = lpBufRet;
  397. while (dwBufLenW != 0 && (wc=*lpBufW++) != L'\0') {
  398. MultiByteSize = UnicodeToMultiByteSize(dwCodePage, &wc);
  399. if (MultiByteSize == 2) {
  400. *lpAttr++ = *lpAttrW;
  401. }
  402. *lpAttr++ = *lpAttrW++;
  403. dwBufLenW -= sizeof(WCHAR);
  404. }
  405. ImmLocalFree(lpStrBufW);
  406. }
  407. *lplpNewCompRead = lpBufRet;
  408. *lpdwNewCompReadLen = (DWORD)(lpAttr - (PBYTE)lpBufRet);
  409. return lpBufRet;
  410. }
  411. LPBYTE InternalSCS_CHANGECLAUSE(
  412. HIMC hImc,
  413. LPCVOID lpCompRead,
  414. DWORD dwCompReadLen,
  415. DWORD dwIndex,
  416. LPDWORD *lplpNewCompRead,
  417. DWORD *lpdwNewCompReadLen,
  418. BOOL fAnsi,
  419. DWORD dwCodePage)
  420. {
  421. LPDWORD lpdw, lpNewdw, lpBufRet;
  422. DWORD dwBufLenA, dwBufLenW;
  423. LPSTR lpStrBufA = NULL;
  424. LPWSTR lpStrBufW = NULL;
  425. INT i;
  426. if (lpCompRead == NULL || dwCompReadLen == 0)
  427. return NULL;
  428. lpdw = (LPDWORD)lpCompRead;
  429. lpBufRet = ImmLocalAlloc(0, dwCompReadLen);
  430. if (lpBufRet == NULL) {
  431. RIPMSG0(RIP_WARNING, "InternalSCS_CHANGECLAUSE: memory failure.");
  432. return NULL;
  433. }
  434. if (fAnsi) {
  435. dwBufLenA = ImmGetCompositionStringA(hImc, dwIndex, NULL, 0);
  436. lpStrBufA = ImmLocalAlloc(0, dwBufLenA);
  437. if (lpStrBufA == NULL) {
  438. RIPMSG0(RIP_WARNING, "InternalSCS_CHANGECLAUSE: memory failure.");
  439. ImmLocalFree(lpBufRet);
  440. return NULL;
  441. }
  442. ImmGetCompositionStringA(hImc, dwIndex, lpStrBufA, dwBufLenA);
  443. }
  444. else {
  445. dwBufLenW = ImmGetCompositionStringW(hImc, dwIndex, NULL, 0);
  446. lpStrBufW = ImmLocalAlloc(0, dwBufLenW);
  447. if (lpStrBufW == NULL) {
  448. RIPMSG0(RIP_WARNING, "InternalSCS_CHANGECLAUSE: memory failure.");
  449. ImmLocalFree(lpBufRet);
  450. return NULL;
  451. }
  452. ImmGetCompositionStringW(hImc, dwIndex, lpStrBufW, dwBufLenW);
  453. }
  454. *lplpNewCompRead = lpNewdw = lpBufRet;
  455. *lpdwNewCompReadLen = dwCompReadLen;
  456. for (i = 0; i < (INT)(dwCompReadLen / sizeof(DWORD)); i++) {
  457. *lpNewdw++ = fAnsi ? CalcCharacterPositionAtoW(*lpdw++, lpStrBufA, dwCodePage)
  458. : CalcCharacterPositionWtoA(*lpdw++, lpStrBufW, dwCodePage);
  459. }
  460. if (lpStrBufA) {
  461. ImmLocalFree(lpStrBufA);
  462. UserAssert(lpStrBufW == NULL);
  463. } else {
  464. UserAssert(lpStrBufW);
  465. ImmLocalFree(lpStrBufW);
  466. }
  467. return (LPBYTE)lpBufRet;
  468. }
  469. LPBYTE InternalSCS_RECONVERTSTRING(
  470. LPRECONVERTSTRING lpReconv,
  471. DWORD dwReconvLen,
  472. LPRECONVERTSTRING *lplpNewReconv,
  473. DWORD *lpdwNewReconvLen,
  474. BOOL fAnsi,
  475. DWORD dwCodePage)
  476. {
  477. LPRECONVERTSTRING lpNewReconv;
  478. DWORD dwBufSize;
  479. if (lpReconv == NULL || dwReconvLen == 0)
  480. return NULL;
  481. if (fAnsi) {
  482. // AtoW
  483. dwBufSize = (lpReconv->dwSize - sizeof *lpReconv + 1) * sizeof(WCHAR) + sizeof *lpReconv;
  484. }
  485. else {
  486. dwBufSize = lpReconv->dwSize + sizeof(BYTE);
  487. }
  488. lpNewReconv = ImmLocalAlloc(0, dwBufSize);
  489. if (lpNewReconv == NULL) {
  490. RIPMSG0(RIP_WARNING, "InternalSCS_RECONVERTSTRING: memory failure.");
  491. return NULL;
  492. }
  493. lpNewReconv->dwVersion = 0;
  494. lpNewReconv->dwSize= dwBufSize;
  495. lpNewReconv->dwSize = ImmReconversionWorker(lpNewReconv, lpReconv, !fAnsi, dwCodePage);
  496. if (lpNewReconv->dwSize == 0) {
  497. ImmLocalFree(lpNewReconv);
  498. return NULL;;
  499. }
  500. *lpdwNewReconvLen = lpNewReconv->dwSize;
  501. *lplpNewReconv = lpNewReconv;
  502. return (LPBYTE)lpNewReconv;
  503. }
  504. /***************************************************************************\
  505. * ImmSetCompositionStringWorker
  506. *
  507. * Worker function of ImmSetCompositionStringA/ImmSetCompositionStringW
  508. *
  509. * History:
  510. * 28-Feb-1995 wkwok Created
  511. \***************************************************************************/
  512. BOOL ImmSetCompositionStringWorker(
  513. HIMC hImc,
  514. DWORD dwIndex,
  515. LPVOID lpComp,
  516. DWORD dwCompLen,
  517. LPVOID lpRead,
  518. DWORD dwReadLen,
  519. BOOL fAnsi)
  520. {
  521. PINPUTCONTEXT pInputContext;
  522. PCOMPOSITIONSTRING pCompStr;
  523. DWORD dwThreadId;
  524. PIMEDPI pImeDpi;
  525. LPBYTE lpCompBuf, lpReadBuf;
  526. LPBYTE lpNewComp = NULL, lpNewRead = NULL;
  527. DWORD dwNewCompLen, dwNewReadLen;
  528. BOOL fRet = FALSE;
  529. BOOL fCheckSize = TRUE;
  530. BOOL fNeedAWConversion;
  531. LPBYTE lpOrgComp, lpOrgRead;
  532. DWORD dwOrgCompLen, dwOrgReadLen;
  533. dwThreadId = GetInputContextThread(hImc);
  534. if (dwThreadId != GetCurrentThreadId()) {
  535. RIPMSG1(RIP_WARNING,
  536. "ImmSetCompositionString: Invalid input context access %lx.", hImc);
  537. return FALSE;
  538. }
  539. pImeDpi = ImmLockImeDpi(GetKeyboardLayout(dwThreadId));
  540. if (pImeDpi == NULL)
  541. return FALSE;
  542. lpCompBuf = lpReadBuf = NULL;
  543. // Backup original pointers to copyback for QUERY.
  544. lpOrgComp = lpComp;
  545. lpOrgRead = lpRead;
  546. dwOrgCompLen = dwCompLen;
  547. dwOrgReadLen = dwReadLen;
  548. /*
  549. * Check if we need ANSI/Unicode conversion
  550. */
  551. if (( fAnsi && !(pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE)) ||
  552. (!fAnsi && (pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE))) {
  553. /*
  554. * No A/W conversion needed.
  555. */
  556. fNeedAWConversion = FALSE;
  557. goto start_scs;
  558. }
  559. fNeedAWConversion = TRUE;
  560. switch (dwIndex) {
  561. case SCS_SETSTR:
  562. if ( lpComp &&
  563. (lpCompBuf = InternalSCS_SETSTR(lpComp, dwCompLen,
  564. &lpNewComp, &dwNewCompLen, fAnsi, IMECodePage(pImeDpi))) == NULL)
  565. goto callime_scs;
  566. if ( lpRead &&
  567. (lpReadBuf = InternalSCS_SETSTR(lpRead, dwReadLen,
  568. &lpNewRead, &dwNewReadLen, fAnsi, IMECodePage(pImeDpi))) == NULL)
  569. goto callime_scs;
  570. fCheckSize = FALSE;
  571. break;
  572. case SCS_CHANGEATTR:
  573. if ( lpComp &&
  574. (lpCompBuf = InternalSCS_CHANGEATTR(
  575. hImc, lpComp, dwCompLen, GCS_COMPSTR,
  576. &lpNewComp, &dwNewCompLen, fAnsi, IMECodePage(pImeDpi))) == NULL)
  577. goto callime_scs;
  578. if ( lpRead &&
  579. (lpReadBuf = InternalSCS_CHANGEATTR(
  580. hImc, lpRead, dwReadLen, GCS_COMPREADSTR,
  581. &lpNewRead, &dwNewReadLen, fAnsi, IMECodePage(pImeDpi))) == NULL)
  582. goto callime_scs;
  583. break;
  584. case SCS_CHANGECLAUSE:
  585. if ( lpComp &&
  586. (lpCompBuf = InternalSCS_CHANGECLAUSE(
  587. hImc, lpComp, dwCompLen, GCS_COMPSTR,
  588. (LPDWORD *)&lpNewComp, &dwNewCompLen, fAnsi, IMECodePage(pImeDpi))) == NULL)
  589. goto callime_scs;
  590. if ( lpRead &&
  591. (lpReadBuf = InternalSCS_CHANGECLAUSE(
  592. hImc, lpRead, dwReadLen, GCS_COMPREADSTR,
  593. (LPDWORD *)&lpNewRead, &dwNewReadLen, fAnsi, IMECodePage(pImeDpi))) == NULL)
  594. goto callime_scs;
  595. break;
  596. case SCS_SETRECONVERTSTRING:
  597. case SCS_QUERYRECONVERTSTRING:
  598. if (lpComp &&
  599. (lpCompBuf = InternalSCS_RECONVERTSTRING((LPRECONVERTSTRING)lpComp, dwCompLen,
  600. (LPRECONVERTSTRING *)&lpNewComp, &dwNewCompLen,
  601. fAnsi, IMECodePage(pImeDpi))) == NULL)
  602. goto callime_scs;
  603. if (lpRead &&
  604. (lpReadBuf = InternalSCS_RECONVERTSTRING((LPRECONVERTSTRING)lpRead, dwReadLen,
  605. (LPRECONVERTSTRING *)&lpNewRead, &dwNewReadLen,
  606. fAnsi, IMECodePage(pImeDpi))) == NULL)
  607. goto callime_scs;
  608. fCheckSize = FALSE;
  609. break;
  610. default:
  611. goto callime_scs;
  612. }
  613. if (lpCompBuf != NULL) {
  614. lpComp = lpNewComp;
  615. dwCompLen = dwNewCompLen;
  616. }
  617. if (lpReadBuf != NULL) {
  618. lpRead = lpNewRead;
  619. dwReadLen = dwNewReadLen;
  620. }
  621. start_scs:
  622. if (CompositionString(hImc, &pInputContext, &pCompStr, fCheckSize) <= 0)
  623. goto callime_scs;
  624. switch (dwIndex)
  625. {
  626. case SCS_SETSTR:
  627. fRet = TRUE;
  628. break;
  629. case SCS_CHANGEATTR:
  630. if ( lpComp &&
  631. !CheckAttribute((LPBYTE)lpComp, dwCompLen,
  632. (LPBYTE)((LPBYTE)pCompStr + pCompStr->dwCompAttrOffset),
  633. pCompStr->dwCompAttrLen,
  634. (LPDWORD)((LPBYTE)pCompStr + pCompStr->dwCompClauseOffset),
  635. pCompStr->dwCompClauseLen)) break;
  636. if ( lpRead &&
  637. !CheckAttribute((LPBYTE)lpRead, dwReadLen,
  638. (LPBYTE)((LPBYTE)pCompStr + pCompStr->dwCompReadAttrOffset),
  639. pCompStr->dwCompReadAttrLen,
  640. (LPDWORD)((LPBYTE)pCompStr + pCompStr->dwCompReadClauseOffset),
  641. pCompStr->dwCompReadClauseLen)) break;
  642. fRet = TRUE;
  643. break;
  644. case SCS_CHANGECLAUSE:
  645. if ( lpComp &&
  646. !CheckClause((LPDWORD)lpComp, dwCompLen,
  647. (LPDWORD)((LPBYTE)pCompStr + pCompStr->dwCompClauseOffset),
  648. pCompStr->dwCompClauseLen)) break;
  649. if ( lpRead &&
  650. !CheckClause((LPDWORD)lpRead, dwReadLen,
  651. (LPDWORD)((LPBYTE)pCompStr + pCompStr->dwCompReadClauseOffset),
  652. pCompStr->dwCompReadClauseLen)) break;
  653. fRet = TRUE;
  654. break;
  655. case SCS_SETRECONVERTSTRING:
  656. case SCS_QUERYRECONVERTSTRING:
  657. if (pImeDpi->ImeInfo.fdwSCSCaps & SCS_CAP_SETRECONVERTSTRING) {
  658. fRet = TRUE;
  659. }
  660. break;
  661. default:
  662. break;
  663. }
  664. ImmUnlockIMCC(pInputContext->hCompStr);
  665. ImmUnlockIMC(hImc);
  666. callime_scs:
  667. if (fRet) {
  668. fRet = (*pImeDpi->pfn.ImeSetCompositionString)(hImc, dwIndex,
  669. lpComp, dwCompLen, lpRead, dwReadLen);
  670. }
  671. /*
  672. * Check if we need ANSI/Unicode back conversion
  673. */
  674. if (fNeedAWConversion) {
  675. LPBYTE lpCompBufBack = NULL, lpReadBufBack = NULL;
  676. /*
  677. * A/W back conversion needed.
  678. */
  679. switch (dwIndex) {
  680. case SCS_QUERYRECONVERTSTRING:
  681. if (lpOrgComp &&
  682. (lpCompBufBack = InternalSCS_RECONVERTSTRING((LPRECONVERTSTRING)lpComp, dwCompLen,
  683. (LPRECONVERTSTRING *)&lpNewComp, &dwNewCompLen,
  684. !fAnsi, IMECodePage(pImeDpi)))) {
  685. if (dwOrgCompLen < dwNewCompLen) {
  686. // lpOrgComp buffer length is too small.
  687. fRet = FALSE;
  688. }
  689. else {
  690. RtlCopyMemory(lpOrgComp, lpNewComp, dwNewCompLen);
  691. }
  692. }
  693. if (lpOrgRead &&
  694. (lpReadBufBack = InternalSCS_RECONVERTSTRING(
  695. (LPRECONVERTSTRING)lpRead, dwReadLen,
  696. (LPRECONVERTSTRING *)&lpNewRead, &dwNewReadLen,
  697. !fAnsi, IMECodePage(pImeDpi)))) {
  698. if (dwOrgReadLen < dwNewReadLen) {
  699. // lpOrgRead buffer length is too small.
  700. fRet = FALSE;
  701. }
  702. else {
  703. RtlCopyMemory(lpOrgRead, lpNewRead, dwNewReadLen);
  704. }
  705. }
  706. }
  707. if (lpCompBufBack != NULL)
  708. LocalFree(lpCompBufBack);
  709. if (lpReadBufBack != NULL)
  710. LocalFree(lpReadBufBack);
  711. }
  712. if (lpCompBuf != NULL)
  713. ImmLocalFree(lpCompBuf);
  714. if (lpReadBuf != NULL)
  715. ImmLocalFree(lpReadBuf);
  716. ImmUnlockImeDpi(pImeDpi);
  717. return fRet;
  718. }
  719. /***************************************************************************\
  720. * ImmGetCandidateListCountA
  721. *
  722. * Query the byte count and list count to receive all candidate list.
  723. *
  724. * History:
  725. * 27-Feb-1995 wkwok Created
  726. \***************************************************************************/
  727. DWORD WINAPI ImmGetCandidateListCountA(
  728. HIMC hImc,
  729. LPDWORD lpdwListCount) // the buffer pointer for list count
  730. {
  731. return ImmGetCandidateListCountWorker(hImc, lpdwListCount, TRUE);
  732. }
  733. /***************************************************************************\
  734. * ImmGetCandidateListCountW
  735. *
  736. * Query the byte count and list count to receive all candidate list.
  737. *
  738. * History:
  739. * 27-Feb-1995 wkwok Created
  740. \***************************************************************************/
  741. DWORD WINAPI ImmGetCandidateListCountW(
  742. HIMC hImc,
  743. LPDWORD lpdwListCount) // the buffer pointer for list count
  744. {
  745. return ImmGetCandidateListCountWorker(hImc, lpdwListCount, FALSE);
  746. }
  747. /***************************************************************************\
  748. * ImmGetCandidateListCountWorker
  749. *
  750. * Worker function of ImmGetCandidateListCountA/ImmGetCandidateListCountW.
  751. *
  752. * History:
  753. * 27-Feb-1995 wkwok Created
  754. \***************************************************************************/
  755. DWORD ImmGetCandidateListCountWorker(
  756. HIMC hImc,
  757. LPDWORD lpdwListCount,
  758. BOOL fAnsi)
  759. {
  760. PCLIENTIMC pClientImc;
  761. PINPUTCONTEXT pInputContext;
  762. LPCANDIDATEINFO lpCandInfo;
  763. DWORD dwRet = 0;
  764. INT i;
  765. DWORD dwCodePage;
  766. if (lpdwListCount) {
  767. *lpdwListCount = 0;
  768. } else {
  769. RIPMSG0(RIP_WARNING, "ImmGetCandidateListCount: NULL lpdwListCount.");
  770. return dwRet;
  771. }
  772. pClientImc = ImmLockClientImc(hImc);
  773. if (pClientImc == NULL) {
  774. RIPMSG1(RIP_WARNING, "ImmGetCandidateListCount: Invalid hImc %lx.", hImc);
  775. goto GetCandListCntExit;
  776. }
  777. dwCodePage = CImcCodePage(pClientImc);
  778. pInputContext = ImmLockIMC(hImc);
  779. if (pInputContext == NULL) {
  780. RIPMSG1(RIP_WARNING, "ImmGetCandidateListCount: Lock hImc %lx failed.", hImc);
  781. goto GetCandListCntUnlockClientImc;
  782. }
  783. lpCandInfo = (LPCANDIDATEINFO)ImmLockIMCC(pInputContext->hCandInfo);
  784. if (!lpCandInfo) {
  785. RIPMSG1(RIP_WARNING,
  786. "ImmGetCandidateListCount: Lock hCandInfo %x failed.",
  787. pInputContext->hCandInfo);
  788. goto GetCandListCntUnlockIMC;
  789. }
  790. if (lpCandInfo->dwSize < sizeof(CANDIDATEINFO)) {
  791. RIPMSG0(RIP_WARNING, "ImmGetCandidateListCount: no candidate list.");
  792. goto GetCandListCntUnlockIMC;
  793. }
  794. *lpdwListCount = lpCandInfo->dwCount;
  795. if (fAnsi && TestICF(pClientImc, IMCF_UNICODE)) {
  796. LPCANDIDATELIST lpCandListW;
  797. dwRet = DWORD_ALIGN(sizeof(CANDIDATEINFO))
  798. + DWORD_ALIGN(lpCandInfo->dwPrivateSize);
  799. for (i = 0; i < (INT)lpCandInfo->dwCount; i++) {
  800. lpCandListW = (LPCANDIDATELIST)((LPBYTE)lpCandInfo + lpCandInfo->dwOffset[i]);
  801. dwRet += InternalGetCandidateListWtoA(lpCandListW, NULL, 0, dwCodePage);
  802. }
  803. }
  804. else if (!fAnsi && !TestICF(pClientImc, IMCF_UNICODE)) {
  805. LPCANDIDATELIST lpCandListA;
  806. dwRet = DWORD_ALIGN(sizeof(CANDIDATEINFO))
  807. + DWORD_ALIGN(lpCandInfo->dwPrivateSize);
  808. for (i = 0; i < (INT)lpCandInfo->dwCount; i++) {
  809. lpCandListA = (LPCANDIDATELIST)((LPBYTE)lpCandInfo + lpCandInfo->dwOffset[i]);
  810. dwRet += InternalGetCandidateListAtoW(lpCandListA, NULL, 0, dwCodePage);
  811. }
  812. }
  813. else {
  814. dwRet = lpCandInfo->dwSize;
  815. }
  816. ImmUnlockIMCC(pInputContext->hCandInfo);
  817. GetCandListCntUnlockIMC:
  818. ImmUnlockIMC(hImc);
  819. GetCandListCntUnlockClientImc:
  820. ImmUnlockClientImc(pClientImc);
  821. GetCandListCntExit:
  822. return dwRet;
  823. }
  824. /***************************************************************************\
  825. * ImmGetCandidateListA
  826. *
  827. * Gets the candidate list information specified by dwIndex.
  828. *
  829. * History:
  830. * 27-Feb-1995 wkwok Created
  831. \***************************************************************************/
  832. DWORD WINAPI ImmGetCandidateListA(
  833. HIMC hImc,
  834. DWORD dwIndex,
  835. LPCANDIDATELIST lpCandList,
  836. DWORD dwBufLen)
  837. {
  838. return ImmGetCandidateListWorker(hImc, dwIndex,
  839. lpCandList, dwBufLen, TRUE);
  840. }
  841. /***************************************************************************\
  842. * ImmGetCandidateListW
  843. *
  844. * Gets the candidate list information specified by dwIndex.
  845. *
  846. * History:
  847. * 27-Feb-1995 wkwok Created
  848. \***************************************************************************/
  849. DWORD WINAPI ImmGetCandidateListW(
  850. HIMC hImc,
  851. DWORD dwIndex,
  852. LPCANDIDATELIST lpCandList,
  853. DWORD dwBufLen)
  854. {
  855. return ImmGetCandidateListWorker(hImc, dwIndex,
  856. lpCandList, dwBufLen, FALSE);
  857. }
  858. /***************************************************************************\
  859. * ImmGetCandidateListWorker
  860. *
  861. * Worker function of ImmGetCandidateListA/ImmGetCandidateListW.
  862. *
  863. * History:
  864. * 27-Feb-1995 wkwok Created
  865. \***************************************************************************/
  866. DWORD ImmGetCandidateListWorker(
  867. HIMC hImc,
  868. DWORD dwIndex,
  869. LPCANDIDATELIST lpCandList,
  870. DWORD dwBufLen,
  871. BOOL fAnsi)
  872. {
  873. PCLIENTIMC pClientImc;
  874. PINPUTCONTEXT pInputContext;
  875. LPCANDIDATEINFO lpCandInfo;
  876. LPCANDIDATELIST lpCandListTemp;
  877. DWORD dwBufLenTemp;
  878. DWORD dwRet = 0;
  879. DWORD dwCodePage;
  880. pClientImc = ImmLockClientImc(hImc);
  881. if (pClientImc == NULL) {
  882. RIPMSG1(RIP_WARNING, "ImmGetCandidateList: Invalid hImc %lx.", hImc);
  883. goto GetCandListExit;
  884. }
  885. dwCodePage = CImcCodePage(pClientImc);
  886. pInputContext = ImmLockIMC(hImc);
  887. if (pInputContext == NULL) {
  888. RIPMSG1(RIP_WARNING, "ImmGetCandidateList: Lock hImc %lx failed.", hImc);
  889. goto GetCandListUnlockClientImc;
  890. }
  891. lpCandInfo = (LPCANDIDATEINFO)ImmLockIMCC(pInputContext->hCandInfo);
  892. if (!lpCandInfo) {
  893. RIPMSG1(RIP_WARNING, "ImmGetCandidateList: Lock hCandInfo %x failed",
  894. pInputContext->hCandInfo);
  895. goto GetCandListUnlockIMC;
  896. }
  897. if (lpCandInfo->dwSize < sizeof(CANDIDATEINFO)) {
  898. RIPMSG0(RIP_WARNING, "ImmGetCandidateList: no candidate list.");
  899. goto GetCandListUnlockIMCC;
  900. }
  901. /*
  902. * invalid access
  903. */
  904. if (dwIndex >= lpCandInfo->dwCount) {
  905. RIPMSG0(RIP_WARNING, "ImmGetCandidateList: dwIndex >= lpCandInfo->dwCount.");
  906. goto GetCandListUnlockIMCC;
  907. }
  908. lpCandListTemp = (LPCANDIDATELIST)((LPBYTE)lpCandInfo + lpCandInfo->dwOffset[dwIndex]);
  909. if (fAnsi && TestICF(pClientImc, IMCF_UNICODE)) {
  910. /*
  911. * ANSI Caller with an Unicode hImc.
  912. */
  913. dwBufLenTemp = InternalGetCandidateListWtoA(lpCandListTemp, NULL, 0, dwCodePage);
  914. }
  915. else if (!fAnsi && !TestICF(pClientImc, IMCF_UNICODE)) {
  916. /*
  917. * Unicode Caller with an ANSI hImc.
  918. */
  919. dwBufLenTemp = InternalGetCandidateListAtoW(lpCandListTemp, NULL, 0, dwCodePage);
  920. }
  921. else {
  922. /*
  923. * No conversion required.
  924. */
  925. dwBufLenTemp = lpCandListTemp->dwSize;
  926. }
  927. /*
  928. * Query buffer size or early exit on error
  929. */
  930. if (dwBufLen == 0 || dwBufLenTemp == 0) {
  931. dwRet = dwBufLenTemp;
  932. }
  933. else if (!lpCandList) {
  934. RIPMSG0(RIP_WARNING, "ImmGetCandidateList: Null lpCandList.");
  935. }
  936. else if (dwBufLen < dwBufLenTemp) {
  937. RIPMSG2(RIP_WARNING, "ImmGetCandidateList: dwBufLen = %d too small, require = %d.",
  938. dwBufLen, dwBufLenTemp);
  939. } else {
  940. if (fAnsi && TestICF(pClientImc, IMCF_UNICODE)) {
  941. dwRet = InternalGetCandidateListWtoA(lpCandListTemp, lpCandList, dwBufLenTemp, dwCodePage);
  942. }
  943. else if (!fAnsi && !TestICF(pClientImc, IMCF_UNICODE)) {
  944. dwRet = InternalGetCandidateListAtoW(lpCandListTemp, lpCandList, dwBufLenTemp, dwCodePage);
  945. }
  946. else {
  947. RtlCopyMemory((LPBYTE)lpCandList, (LPBYTE)lpCandListTemp, dwBufLenTemp);
  948. dwRet = dwBufLenTemp;
  949. }
  950. }
  951. GetCandListUnlockIMCC:
  952. ImmUnlockIMCC(pInputContext->hCandInfo);
  953. GetCandListUnlockIMC:
  954. ImmUnlockIMC(hImc);
  955. GetCandListUnlockClientImc:
  956. ImmUnlockClientImc(pClientImc);
  957. GetCandListExit:
  958. return dwRet;
  959. }
  960. /***************************************************************************\
  961. * ImmGetGuideLineA
  962. *
  963. * Gets the guide line information reported by the IME.
  964. *
  965. * History:
  966. * 26-Feb-1995 wkwok Created
  967. \***************************************************************************/
  968. DWORD WINAPI ImmGetGuideLineA(
  969. HIMC hImc,
  970. DWORD dwIndex,
  971. LPSTR lpszBuf,
  972. DWORD dwBufLen)
  973. {
  974. return ImmGetGuideLineWorker(hImc, dwIndex,
  975. (LPBYTE)lpszBuf, dwBufLen, TRUE);
  976. }
  977. /***************************************************************************\
  978. * ImmGetGuideLineW
  979. *
  980. * Gets the guide line information reported by the IME.
  981. *
  982. * History:
  983. * 26-Feb-1995 wkwok Created
  984. \***************************************************************************/
  985. DWORD WINAPI ImmGetGuideLineW(
  986. HIMC hImc,
  987. DWORD dwIndex,
  988. LPWSTR lpwszBuf,
  989. DWORD dwBufLen)
  990. {
  991. return ImmGetGuideLineWorker(hImc, dwIndex,
  992. (LPBYTE)lpwszBuf, dwBufLen, FALSE);
  993. }
  994. /***************************************************************************\
  995. * ImmGetGuideLineWorker
  996. *
  997. * Worker function of ImmGetGuideLineA/ImmGetGuideLineW.
  998. *
  999. * History:
  1000. * 26-Feb-1995 wkwok Created
  1001. \***************************************************************************/
  1002. DWORD ImmGetGuideLineWorker(
  1003. HIMC hImc,
  1004. DWORD dwIndex,
  1005. LPBYTE lpBuf,
  1006. DWORD dwBufLen,
  1007. BOOL fAnsi)
  1008. {
  1009. PCLIENTIMC pClientImc;
  1010. PINPUTCONTEXT pInputContext;
  1011. LPGUIDELINE lpGuideLine;
  1012. LPBYTE lpBufTemp;
  1013. DWORD dwRet = 0;
  1014. DWORD dwBufLenNeeded;
  1015. BOOL bUDC;
  1016. DWORD dwCodePage;
  1017. pClientImc = ImmLockClientImc(hImc);
  1018. if (pClientImc == NULL) {
  1019. RIPMSG1(RIP_WARNING, "ImmGetGuideLine: Invalid hImc %lx.", hImc);
  1020. goto GetGuideLineExit;
  1021. }
  1022. dwCodePage = CImcCodePage(pClientImc);
  1023. pInputContext = ImmLockIMC(hImc);
  1024. if (pInputContext == NULL) {
  1025. RIPMSG1(RIP_WARNING, "ImmGetGuideLine: Lock hImc %lx failed.", hImc);
  1026. goto GetGuideLineUnlockClientImc;
  1027. }
  1028. lpGuideLine = (LPGUIDELINE)ImmLockIMCC(pInputContext->hGuideLine);
  1029. if (!lpGuideLine) {
  1030. RIPMSG1(RIP_WARNING, "ImmGetGuideLine: Lock hGuideLine %lx failed.",
  1031. pInputContext->hGuideLine);
  1032. goto GetGuideLineUnlockIMC;
  1033. }
  1034. switch (dwIndex) {
  1035. case GGL_LEVEL:
  1036. dwRet = lpGuideLine->dwLevel;
  1037. break;
  1038. case GGL_INDEX:
  1039. dwRet = lpGuideLine->dwIndex;
  1040. break;
  1041. case GGL_STRING:
  1042. lpBufTemp = (LPBYTE)lpGuideLine + lpGuideLine->dwStrOffset;
  1043. /*
  1044. * Calculate the required buffer length.
  1045. */
  1046. if (fAnsi && TestICF(pClientImc, IMCF_UNICODE)) {
  1047. dwBufLenNeeded = WideCharToMultiByte(dwCodePage,
  1048. (DWORD)0,
  1049. (LPWSTR)lpBufTemp,
  1050. (INT)lpGuideLine->dwStrLen,
  1051. (LPSTR)NULL,
  1052. (INT)0,
  1053. (LPSTR)NULL,
  1054. (LPBOOL)&bUDC);
  1055. }
  1056. else if (!fAnsi && !TestICF(pClientImc, IMCF_UNICODE)) {
  1057. dwBufLenNeeded = MultiByteToWideChar(dwCodePage,
  1058. (DWORD)MB_PRECOMPOSED,
  1059. (LPSTR)lpBufTemp,
  1060. (INT)lpGuideLine->dwStrLen,
  1061. (LPWSTR)NULL,
  1062. (INT)0);
  1063. dwBufLenNeeded *= sizeof(WCHAR);
  1064. }
  1065. else {
  1066. dwBufLenNeeded = lpGuideLine->dwStrLen;
  1067. /*
  1068. * The dwStrLen records the strlen and not the byte count.
  1069. */
  1070. if (TestICF(pClientImc, IMCF_UNICODE))
  1071. dwBufLenNeeded *= sizeof(WCHAR);
  1072. }
  1073. /*
  1074. * Query GuideLine string size only or early exit on error
  1075. */
  1076. if (dwBufLen == 0 || dwBufLenNeeded == 0) {
  1077. dwRet = dwBufLenNeeded;
  1078. goto GetGuideLineUnlockIMCC;
  1079. }
  1080. if (lpBuf == NULL || dwBufLen < dwBufLenNeeded)
  1081. goto GetGuideLineUnlockIMCC;
  1082. if (fAnsi && TestICF(pClientImc, IMCF_UNICODE)) {
  1083. dwRet = WideCharToMultiByte(dwCodePage,
  1084. (DWORD)0,
  1085. (LPWSTR)lpBufTemp,
  1086. (INT)lpGuideLine->dwStrLen,
  1087. (LPSTR)lpBuf,
  1088. (INT)dwBufLen,
  1089. (LPSTR)NULL,
  1090. (LPBOOL)&bUDC);
  1091. }
  1092. else if (!fAnsi && !TestICF(pClientImc, IMCF_UNICODE)) {
  1093. dwRet = MultiByteToWideChar(dwCodePage,
  1094. (DWORD)MB_PRECOMPOSED,
  1095. (LPSTR)lpBufTemp,
  1096. (INT)lpGuideLine->dwStrLen,
  1097. (LPWSTR)lpBuf,
  1098. (INT)dwBufLen/sizeof(WCHAR));
  1099. dwRet *= sizeof(WCHAR);
  1100. }
  1101. else {
  1102. RtlCopyMemory(lpBuf, lpBufTemp, dwBufLenNeeded);
  1103. dwRet = dwBufLenNeeded;
  1104. }
  1105. break;
  1106. case GGL_PRIVATE:
  1107. lpBufTemp = (LPBYTE)lpGuideLine + lpGuideLine->dwPrivateOffset;
  1108. /*
  1109. * The dwPrivateOffset is an offset to a CANDIDATELIST when
  1110. * lpGuideLine->dwIndex == GL_ID_REVERSECONVERSION. Do conversion
  1111. * for this case only.
  1112. */
  1113. if (fAnsi && TestICF(pClientImc, IMCF_UNICODE) &&
  1114. lpGuideLine->dwIndex == GL_ID_REVERSECONVERSION) {
  1115. dwBufLenNeeded = InternalGetCandidateListWtoA(
  1116. (LPCANDIDATELIST)lpBufTemp, (LPCANDIDATELIST)NULL, 0, dwCodePage);
  1117. }
  1118. else if (!fAnsi && !TestICF(pClientImc, IMCF_UNICODE) &&
  1119. lpGuideLine->dwIndex == GL_ID_REVERSECONVERSION) {
  1120. dwBufLenNeeded = InternalGetCandidateListAtoW(
  1121. (LPCANDIDATELIST)lpBufTemp, (LPCANDIDATELIST)NULL, 0, dwCodePage);
  1122. }
  1123. else {
  1124. dwBufLenNeeded = lpGuideLine->dwPrivateSize;
  1125. }
  1126. /*
  1127. * Query dwPrivateSize size only or early exit on error
  1128. */
  1129. if (dwBufLen == 0 || dwBufLenNeeded == 0) {
  1130. dwRet = dwBufLenNeeded;
  1131. goto GetGuideLineUnlockIMCC;
  1132. }
  1133. if (lpBuf == NULL || dwBufLen < dwBufLenNeeded)
  1134. goto GetGuideLineUnlockIMCC;
  1135. if (fAnsi && TestICF(pClientImc, IMCF_UNICODE) &&
  1136. lpGuideLine->dwIndex == GL_ID_REVERSECONVERSION) {
  1137. dwRet = InternalGetCandidateListWtoA(
  1138. (LPCANDIDATELIST)lpBufTemp, (LPCANDIDATELIST)lpBuf, dwBufLenNeeded, dwCodePage);
  1139. }
  1140. else if (!fAnsi && !TestICF(pClientImc, IMCF_UNICODE) &&
  1141. lpGuideLine->dwIndex == GL_ID_REVERSECONVERSION) {
  1142. dwRet = InternalGetCandidateListAtoW(
  1143. (LPCANDIDATELIST)lpBufTemp, (LPCANDIDATELIST)lpBuf, dwBufLenNeeded, dwCodePage);
  1144. }
  1145. else {
  1146. RtlCopyMemory(lpBuf, lpBufTemp, dwBufLenNeeded);
  1147. dwRet = dwBufLenNeeded;
  1148. }
  1149. break;
  1150. default:
  1151. break;
  1152. }
  1153. GetGuideLineUnlockIMCC:
  1154. ImmUnlockIMCC(pInputContext->hGuideLine);
  1155. GetGuideLineUnlockIMC:
  1156. ImmUnlockIMC(hImc);
  1157. GetGuideLineUnlockClientImc:
  1158. ImmUnlockClientImc(pClientImc);
  1159. GetGuideLineExit:
  1160. return dwRet;
  1161. }
  1162. /***************************************************************************\
  1163. * ImmGetConversionStatus
  1164. *
  1165. * Gets current conversion status.
  1166. *
  1167. * History:
  1168. * 26-Feb-1995 wkwok Created
  1169. \***************************************************************************/
  1170. BOOL WINAPI ImmGetConversionStatus( // Get the conversion status
  1171. HIMC hImc,
  1172. LPDWORD lpfdwConversion,
  1173. LPDWORD lpfdwSentence)
  1174. {
  1175. PINPUTCONTEXT pInputContext;
  1176. pInputContext = ImmLockIMC(hImc);
  1177. if (pInputContext == NULL) {
  1178. RIPMSG1(RIP_WARNING, "ImmGetConversionStatus: Lock hImc %lx failed", hImc);
  1179. return FALSE;
  1180. }
  1181. if (lpfdwConversion != NULL)
  1182. *lpfdwConversion = pInputContext->fdwConversion;
  1183. if (lpfdwSentence != NULL)
  1184. *lpfdwSentence = pInputContext->fdwSentence;
  1185. ImmUnlockIMC(hImc);
  1186. return TRUE;
  1187. }
  1188. /***************************************************************************\
  1189. * ImmSetConversionStatus
  1190. *
  1191. * Sets current conversion status.
  1192. *
  1193. * History:
  1194. * 26-Feb-1995 wkwok Created
  1195. \***************************************************************************/
  1196. BOOL WINAPI ImmSetConversionStatus(
  1197. HIMC hImc,
  1198. DWORD fdwConversion,
  1199. DWORD fdwSentence)
  1200. {
  1201. PINPUTCONTEXT pInputContext;
  1202. DWORD fdwOldConversion;
  1203. DWORD fdwOldSentence;
  1204. BOOL fConvModeChg;
  1205. BOOL fSentenceChg;
  1206. HWND hWnd;
  1207. DWORD dwOpenStatus;
  1208. DWORD dwConversion;
  1209. #if defined(CUAS_ENABLE)
  1210. BOOL fMakeNotifyAlways = FALSE;
  1211. HKL hKL = GetKeyboardLayout(0);
  1212. if (!IS_IME_KBDLAYOUT(hKL) && IS_CICERO_ENABLED_AND_NOT16BIT())
  1213. fMakeNotifyAlways = TRUE;
  1214. #endif
  1215. if (GetInputContextThread(hImc) != GetCurrentThreadId()) {
  1216. RIPMSG1(RIP_WARNING,
  1217. "ImmSetConversionStatus: Invalid input context access %lx.", hImc);
  1218. return FALSE;
  1219. }
  1220. pInputContext = ImmLockIMC(hImc);
  1221. if (pInputContext == NULL) {
  1222. RIPMSG1(RIP_WARNING,
  1223. "ImmSetConversionStatus: Lock hImc %lx failed", hImc);
  1224. return FALSE;
  1225. }
  1226. fConvModeChg = FALSE;
  1227. fSentenceChg = FALSE;
  1228. if (pInputContext->fdwConversion != fdwConversion) {
  1229. if ((fdwConversion & IME_CMODE_LANGUAGE) == IME_CMODE_KATAKANA) {
  1230. RIPMSG0(RIP_WARNING, "ImmSetConversionStatus: wrong fdwConversion");
  1231. }
  1232. fdwOldConversion = pInputContext->fdwConversion;
  1233. pInputContext->fdwConversion = fdwConversion;
  1234. fConvModeChg = TRUE;
  1235. }
  1236. if (pInputContext->fdwSentence != fdwSentence) {
  1237. fdwOldSentence = pInputContext->fdwSentence;
  1238. pInputContext->fdwSentence = fdwSentence;
  1239. fSentenceChg = TRUE;
  1240. }
  1241. hWnd = pInputContext->hWnd;
  1242. if ( fConvModeChg ) {
  1243. dwOpenStatus = (DWORD)pInputContext->fOpen;
  1244. dwConversion = pInputContext->fdwConversion;
  1245. }
  1246. ImmUnlockIMC(hImc);
  1247. #ifdef LATER
  1248. // Do uNumLangVKey and uNumVKey checking later.
  1249. #endif
  1250. /*
  1251. * inform IME and UI about the conversion mode changes.
  1252. */
  1253. #if !defined(CUAS_ENABLE)
  1254. if (fConvModeChg)
  1255. #else
  1256. if (fConvModeChg || fMakeNotifyAlways)
  1257. #endif
  1258. {
  1259. MakeIMENotify(hImc, hWnd, NI_CONTEXTUPDATED, fdwOldConversion,
  1260. IMC_SETCONVERSIONMODE, IMN_SETCONVERSIONMODE, 0L);
  1261. /*
  1262. * notify shell and keyboard the conversion mode change
  1263. */
  1264. #if defined(CUAS_ENABLE)
  1265. if (fConvModeChg)
  1266. #endif
  1267. NtUserNotifyIMEStatus( hWnd, dwOpenStatus, dwConversion );
  1268. }
  1269. /*
  1270. * inform IME and UI about the sentence mode changes.
  1271. */
  1272. #if !defined(CUAS_ENABLE)
  1273. if (fSentenceChg)
  1274. #else
  1275. if (fSentenceChg || fMakeNotifyAlways)
  1276. #endif
  1277. {
  1278. MakeIMENotify(hImc, hWnd, NI_CONTEXTUPDATED, fdwOldSentence,
  1279. IMC_SETSENTENCEMODE, IMN_SETSENTENCEMODE, 0L);
  1280. }
  1281. return TRUE;
  1282. }
  1283. /***************************************************************************\
  1284. * ImmGetOpenStatus
  1285. *
  1286. * Gets the open or close status of the IME.
  1287. *
  1288. * History:
  1289. * 26-Feb-1995 wkwok Created
  1290. \***************************************************************************/
  1291. BOOL WINAPI ImmGetOpenStatus(
  1292. HIMC hImc)
  1293. {
  1294. PINPUTCONTEXT pInputContext;
  1295. BOOL fOpen;
  1296. if (hImc == NULL_HIMC)
  1297. return FALSE;
  1298. pInputContext = ImmLockIMC(hImc);
  1299. if (!pInputContext) {
  1300. RIPMSG1(RIP_WARNING, "ImmGetOpenStatus: Lock hImc %lx failed", hImc);
  1301. return FALSE;
  1302. }
  1303. fOpen = pInputContext->fOpen;
  1304. ImmUnlockIMC(hImc);
  1305. return (fOpen);
  1306. }
  1307. /***************************************************************************\
  1308. * ImmSetOpenStatus
  1309. *
  1310. * Opens or closes the IME.
  1311. *
  1312. * History:
  1313. * 26-Feb-1995 wkwok Created
  1314. \***************************************************************************/
  1315. BOOL WINAPI ImmSetOpenStatus(
  1316. HIMC hImc,
  1317. BOOL fOpen)
  1318. {
  1319. PINPUTCONTEXT pInputContext;
  1320. HWND hWnd;
  1321. DWORD dwOpenStatus;
  1322. DWORD dwConversion;
  1323. BOOL fOpenChg = FALSE;
  1324. if (GetInputContextThread(hImc) != GetCurrentThreadId()) {
  1325. RIPMSG1(RIP_WARNING,
  1326. "ImmSetOpenStatus: Invalid input context access %lx.", hImc);
  1327. return FALSE;
  1328. }
  1329. pInputContext = ImmLockIMC(hImc);
  1330. if (!pInputContext) {
  1331. RIPMSG1(RIP_WARNING, "ImmSetOpenStatus: Lock hImc %lx failed", hImc);
  1332. return FALSE;
  1333. }
  1334. if (pInputContext->fOpen != fOpen) {
  1335. fOpenChg = TRUE;
  1336. pInputContext->fOpen = fOpen;
  1337. }
  1338. if ( fOpenChg ) {
  1339. hWnd = (HWND)pInputContext->hWnd;
  1340. dwOpenStatus = (DWORD)pInputContext->fOpen;
  1341. dwConversion = (DWORD)pInputContext->fdwConversion;
  1342. }
  1343. ImmUnlockIMC(hImc);
  1344. /*
  1345. * inform IME and UI about the conversion mode changes.
  1346. */
  1347. if (fOpenChg) {
  1348. MakeIMENotify(hImc, hWnd, NI_CONTEXTUPDATED, (DWORD)0,
  1349. IMC_SETOPENSTATUS, IMN_SETOPENSTATUS, 0L);
  1350. NtUserNotifyIMEStatus( hWnd, dwOpenStatus, dwConversion );
  1351. }
  1352. return TRUE;
  1353. }
  1354. /***************************************************************************\
  1355. * ImmGetCompositionFontA
  1356. *
  1357. * Opens or closes the IME.
  1358. *
  1359. * History:
  1360. * 27-Feb-1995 wkwok Created
  1361. \***************************************************************************/
  1362. BOOL WINAPI ImmGetCompositionFontA(
  1363. HIMC hImc,
  1364. LPLOGFONTA lpLogFontA)
  1365. {
  1366. PCLIENTIMC pClientImc;
  1367. PINPUTCONTEXT pInputContext;
  1368. LOGFONTW LogFontW;
  1369. BOOL fUnicode, fRet;
  1370. pClientImc = ImmLockClientImc(hImc);
  1371. if (pClientImc == NULL) {
  1372. RIPMSG1(RIP_WARNING, "ImmGetCompositionFontA: Invalid hImc %lx.", hImc);
  1373. return FALSE;
  1374. }
  1375. fUnicode = TestICF(pClientImc, IMCF_UNICODE);
  1376. ImmUnlockClientImc(pClientImc);
  1377. pInputContext = ImmLockIMC(hImc);
  1378. if (pInputContext == NULL) {
  1379. RIPMSG1(RIP_WARNING, "ImmGetCompositionFontA: Lock hImc %lx failed.", hImc);
  1380. return FALSE;
  1381. }
  1382. if (fUnicode) {
  1383. ImmUnlockIMC(hImc);
  1384. if (ImmGetCompositionFontW(hImc, &LogFontW)) {
  1385. LFontWtoLFontA(&LogFontW, lpLogFontA);
  1386. return (TRUE);
  1387. }
  1388. return FALSE;
  1389. }
  1390. if ((pInputContext->fdwInit & INIT_LOGFONT) == INIT_LOGFONT) {
  1391. *lpLogFontA = pInputContext->lfFont.A;
  1392. fRet = TRUE;
  1393. }
  1394. else {
  1395. fRet = FALSE;
  1396. }
  1397. ImmUnlockIMC(hImc);
  1398. return fRet;
  1399. }
  1400. /***************************************************************************\
  1401. * ImmGetCompositionFontW
  1402. *
  1403. * Opens or closes the IME.
  1404. *
  1405. * History:
  1406. * 27-Feb-1995 wkwok Created
  1407. \***************************************************************************/
  1408. BOOL WINAPI ImmGetCompositionFontW(
  1409. HIMC hImc,
  1410. LPLOGFONTW lpLogFontW)
  1411. {
  1412. PCLIENTIMC pClientImc;
  1413. PINPUTCONTEXT pInputContext;
  1414. LOGFONTA LogFontA;
  1415. BOOL fUnicode, fRet;
  1416. pClientImc = ImmLockClientImc(hImc);
  1417. if (pClientImc == NULL) {
  1418. RIPMSG1(RIP_WARNING, "ImmGetCompositionFontW: Invalid hImc %lx.", hImc);
  1419. return FALSE;
  1420. }
  1421. fUnicode = TestICF(pClientImc, IMCF_UNICODE);
  1422. ImmUnlockClientImc(pClientImc);
  1423. pInputContext = ImmLockIMC(hImc);
  1424. if (!pInputContext) {
  1425. RIPMSG1(RIP_WARNING, "ImmGetCompositionFontW: Lock hImc %lx failed.", hImc);
  1426. return (FALSE);
  1427. }
  1428. if (!fUnicode) {
  1429. ImmUnlockIMC(hImc);
  1430. if (ImmGetCompositionFontA(hImc, &LogFontA)) {
  1431. LFontAtoLFontW(&LogFontA, lpLogFontW);
  1432. return (TRUE);
  1433. }
  1434. return FALSE;
  1435. }
  1436. if ((pInputContext->fdwInit & INIT_LOGFONT) == INIT_LOGFONT) {
  1437. *lpLogFontW = pInputContext->lfFont.W;
  1438. fRet = TRUE;
  1439. }
  1440. else {
  1441. fRet = FALSE;
  1442. }
  1443. ImmUnlockIMC(hImc);
  1444. return fRet;
  1445. }
  1446. BOOL WINAPI ImmSetCompositionFontA(
  1447. HIMC hImc,
  1448. LPLOGFONTA lpLogFontA)
  1449. {
  1450. PCLIENTIMC pClientImc;
  1451. PINPUTCONTEXT pInputContext;
  1452. LOGFONTW LogFontW;
  1453. HWND hWnd;
  1454. BOOL fUnicode;
  1455. if (GetInputContextThread(hImc) != GetCurrentThreadId()) {
  1456. RIPMSG1(RIP_WARNING,
  1457. "ImmSetCompositionFontA: Invalid input context access %lx.", hImc);
  1458. return FALSE;
  1459. }
  1460. pClientImc = ImmLockClientImc(hImc);
  1461. if (pClientImc == NULL) {
  1462. RIPMSG1(RIP_WARNING, "ImmSetCompositionFontA: Invalid hImc %lx.", hImc);
  1463. return FALSE;
  1464. }
  1465. fUnicode = TestICF(pClientImc, IMCF_UNICODE);
  1466. ImmUnlockClientImc(pClientImc);
  1467. pInputContext = ImmLockIMC(hImc);
  1468. if (!pInputContext) {
  1469. RIPMSG1(RIP_WARNING, "ImmSetCompositionFontA: Lock hImc %lx failed.", hImc);
  1470. return (FALSE);
  1471. }
  1472. if (fUnicode) {
  1473. ImmUnlockIMC(hImc);
  1474. LFontAtoLFontW(lpLogFontA, &LogFontW);
  1475. return ImmSetCompositionFontW(hImc, &LogFontW);
  1476. }
  1477. /*
  1478. * Japanese 3.x applications need to receive 3.x compatible notification message.
  1479. *
  1480. */
  1481. if ( (GetClientInfo()->dwExpWinVer < VER40) &&
  1482. (PRIMARYLANGID(LANGIDFROMLCID(GetSystemDefaultLCID())) == LANG_JAPANESE) &&
  1483. ! (pInputContext->fdw31Compat & F31COMPAT_MCWHIDDEN) &&
  1484. (pInputContext->cfCompForm.dwStyle != CFS_DEFAULT) ) {
  1485. PostMessageA( pInputContext->hWnd, WM_IME_REPORT, IR_CHANGECONVERT, (LPARAM)NULL);
  1486. }
  1487. pInputContext->lfFont.A = *lpLogFontA;
  1488. pInputContext->fdwInit |= INIT_LOGFONT;
  1489. hWnd = pInputContext->hWnd;
  1490. ImmUnlockIMC(hImc);
  1491. /*
  1492. * inform IME and UI about the change of composition font.
  1493. */
  1494. MakeIMENotify(hImc, hWnd, NI_CONTEXTUPDATED, 0L,
  1495. IMC_SETCOMPOSITIONFONT, IMN_SETCOMPOSITIONFONT, 0L);
  1496. return TRUE;
  1497. }
  1498. BOOL WINAPI ImmSetCompositionFontW(
  1499. HIMC hImc,
  1500. LPLOGFONTW lpLogFontW)
  1501. {
  1502. PCLIENTIMC pClientImc;
  1503. PINPUTCONTEXT pInputContext;
  1504. LOGFONTA LogFontA;
  1505. HWND hWnd;
  1506. BOOL fUnicode;
  1507. if (GetInputContextThread(hImc) != GetCurrentThreadId()) {
  1508. RIPMSG1(RIP_WARNING,
  1509. "ImmSetCompositionFontW: Invalid input context access %lx.", hImc);
  1510. return FALSE;
  1511. }
  1512. pClientImc = ImmLockClientImc(hImc);
  1513. if (pClientImc == NULL) {
  1514. RIPMSG1(RIP_WARNING, "ImmSetCompositionFontW: Invalid hImc %lx.", hImc);
  1515. return (FALSE);
  1516. }
  1517. fUnicode = TestICF(pClientImc, IMCF_UNICODE);
  1518. ImmUnlockClientImc(pClientImc);
  1519. pInputContext = ImmLockIMC(hImc);
  1520. if (!pInputContext) {
  1521. RIPMSG1(RIP_WARNING, "ImmSetCompositionFontW: Lock hImc %lx failed.", hImc);
  1522. return (FALSE);
  1523. }
  1524. if (!fUnicode) {
  1525. ImmUnlockIMC(hImc);
  1526. LFontWtoLFontA(lpLogFontW, &LogFontA);
  1527. return ImmSetCompositionFontA(hImc, &LogFontA);
  1528. }
  1529. /*
  1530. * Japanese 3.x applications need to receive 3.x compatible notification message.
  1531. *
  1532. */
  1533. if ( (GetClientInfo()->dwExpWinVer < VER40) &&
  1534. (PRIMARYLANGID(LANGIDFROMLCID(GetSystemDefaultLCID())) == LANG_JAPANESE) &&
  1535. ! (pInputContext->fdw31Compat & F31COMPAT_MCWHIDDEN) &&
  1536. (pInputContext->cfCompForm.dwStyle != CFS_DEFAULT) ) {
  1537. PostMessageW( pInputContext->hWnd, WM_IME_REPORT, IR_CHANGECONVERT, (LPARAM)NULL);
  1538. }
  1539. pInputContext->lfFont.W = *lpLogFontW;
  1540. pInputContext->fdwInit |= INIT_LOGFONT;
  1541. hWnd = pInputContext->hWnd;
  1542. ImmUnlockIMC(hImc);
  1543. /*
  1544. * inform IME and UI about the change of composition font.
  1545. */
  1546. MakeIMENotify(hImc, hWnd, NI_CONTEXTUPDATED, 0L,
  1547. IMC_SETCOMPOSITIONFONT, IMN_SETCOMPOSITIONFONT, 0L);
  1548. return TRUE;
  1549. }
  1550. /***************************************************************************\
  1551. * ImmGetConversionListA
  1552. *
  1553. * Obtains the list of FE character or word from one character or word.
  1554. *
  1555. * History:
  1556. * 27-Feb-1995 wkwok Created
  1557. \***************************************************************************/
  1558. DWORD WINAPI ImmGetConversionListA(
  1559. HKL hKL,
  1560. HIMC hImc,
  1561. LPCSTR lpszSrc,
  1562. LPCANDIDATELIST lpCandListA,
  1563. DWORD dwBufLen,
  1564. UINT uFlag)
  1565. {
  1566. PIMEDPI pImeDpi;
  1567. DWORD dwRet;
  1568. LPWSTR lpwszSrc;
  1569. DWORD dwBufTemp;
  1570. LPCANDIDATELIST lpCandListW;
  1571. INT i;
  1572. DWORD dwCodePage;
  1573. pImeDpi = FindOrLoadImeDpi(hKL);
  1574. if (pImeDpi == NULL) {
  1575. RIPMSG1(RIP_WARNING,
  1576. "ImmGetConversionListA: cannot find DPI entry for hkl=%lx", hKL);
  1577. return (0);
  1578. }
  1579. dwCodePage = IMECodePage(pImeDpi);
  1580. if (!(pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE)) {
  1581. /*
  1582. * This is an ANSI call to an ANSI IME.
  1583. */
  1584. dwRet = (*pImeDpi->pfn.ImeConversionList.a)(hImc, lpszSrc,
  1585. lpCandListA, dwBufLen, uFlag);
  1586. ImmUnlockImeDpi(pImeDpi);
  1587. return dwRet;
  1588. }
  1589. ImmUnlockImeDpi(pImeDpi);
  1590. /*
  1591. * This is an ANSI call to an Unicode IME.
  1592. */
  1593. if (lpszSrc != NULL) {
  1594. dwBufTemp = (strlen(lpszSrc) + 1) * sizeof(WCHAR);
  1595. lpwszSrc = ImmLocalAlloc(0, dwBufTemp);
  1596. if (lpwszSrc == NULL)
  1597. return (0);
  1598. i = MultiByteToWideChar(dwCodePage,
  1599. (DWORD)MB_PRECOMPOSED,
  1600. (LPSTR)lpszSrc, // src
  1601. (INT)strlen(lpszSrc),
  1602. (LPWSTR)lpwszSrc, // dest
  1603. (INT)dwBufTemp/sizeof(WCHAR));
  1604. lpwszSrc[i] = '\0';
  1605. }
  1606. else {
  1607. lpwszSrc = NULL;
  1608. }
  1609. /*
  1610. * Query the CandidateListW size required.
  1611. */
  1612. dwBufTemp = ImmGetConversionListW(hKL, hImc, lpwszSrc, NULL, 0, uFlag);
  1613. if (dwBufTemp == 0 || (lpCandListW = ImmLocalAlloc(0, dwBufTemp)) == NULL) {
  1614. if (lpwszSrc)
  1615. ImmLocalFree(lpwszSrc);
  1616. return (0);
  1617. }
  1618. /*
  1619. * Now get the actual CandidateListW.
  1620. */
  1621. dwBufTemp = ImmGetConversionListW(hKL, hImc, lpwszSrc,
  1622. lpCandListW, dwBufTemp, uFlag);
  1623. /*
  1624. * Query the CandidateListA size required.
  1625. */
  1626. if (dwBufTemp != 0) {
  1627. dwBufTemp = InternalGetCandidateListWtoA(lpCandListW, NULL, 0, dwCodePage);
  1628. }
  1629. if (dwBufLen == 0 || dwBufTemp == 0) {
  1630. /*
  1631. * Query required buffer size or error has happened.
  1632. */
  1633. dwRet = dwBufTemp;
  1634. }
  1635. else if (dwBufLen < dwBufTemp) {
  1636. /*
  1637. * Not enough buffer area.
  1638. */
  1639. dwRet = 0;
  1640. }
  1641. else {
  1642. /*
  1643. * Get the actual CandidateListA
  1644. */
  1645. dwRet = InternalGetCandidateListWtoA(lpCandListW, lpCandListA, dwBufLen, dwCodePage);
  1646. }
  1647. if (lpwszSrc)
  1648. ImmLocalFree(lpwszSrc);
  1649. ImmLocalFree(lpCandListW);
  1650. return dwRet;
  1651. }
  1652. /***************************************************************************\
  1653. * ImmGetConversionListW
  1654. *
  1655. * Obtains the list of FE character or word from one character or word.
  1656. *
  1657. * History:
  1658. * 27-Feb-1995 wkwok Created
  1659. \***************************************************************************/
  1660. DWORD WINAPI ImmGetConversionListW(
  1661. HKL hKL,
  1662. HIMC hImc,
  1663. LPCWSTR lpwszSrc,
  1664. LPCANDIDATELIST lpCandListW,
  1665. DWORD dwBufLen,
  1666. UINT uFlag)
  1667. {
  1668. PIMEDPI pImeDpi;
  1669. DWORD dwRet;
  1670. LPSTR lpszSrc;
  1671. DWORD dwBufTemp;
  1672. LPCANDIDATELIST lpCandListA;
  1673. BOOL bUDC;
  1674. INT i;
  1675. DWORD dwCodePage;
  1676. pImeDpi = FindOrLoadImeDpi(hKL);
  1677. if (pImeDpi == NULL) {
  1678. RIPMSG1(RIP_WARNING,
  1679. "ImmGetConversionListW: cannot find DPI entry for hkl=%lx", hKL);
  1680. return (0);
  1681. }
  1682. dwCodePage = IMECodePage(pImeDpi);
  1683. if (pImeDpi->ImeInfo.fdwProperty & IME_PROP_UNICODE) {
  1684. /*
  1685. * This is an Unicode call to an Unicode IME.
  1686. */
  1687. dwRet = (*pImeDpi->pfn.ImeConversionList.w)(hImc, lpwszSrc,
  1688. lpCandListW, dwBufLen, uFlag);
  1689. ImmUnlockImeDpi(pImeDpi);
  1690. return dwRet;
  1691. }
  1692. ImmUnlockImeDpi(pImeDpi);
  1693. /*
  1694. * This is an Unicode call to an ANSI IME.
  1695. */
  1696. if (lpwszSrc != NULL) {
  1697. dwBufTemp = (wcslen(lpwszSrc) + 1) * sizeof(WCHAR);
  1698. lpszSrc = ImmLocalAlloc(0, dwBufTemp);
  1699. if (lpszSrc == NULL)
  1700. return (0);
  1701. i = WideCharToMultiByte(dwCodePage,
  1702. (DWORD)0,
  1703. lpwszSrc,
  1704. (INT)wcslen(lpwszSrc),
  1705. (LPSTR)lpszSrc,
  1706. (INT)dwBufTemp,
  1707. (LPSTR)NULL,
  1708. (LPBOOL)&bUDC);
  1709. lpszSrc[i] = '\0';
  1710. }
  1711. else {
  1712. lpszSrc = NULL;
  1713. }
  1714. /*
  1715. * Query the CandidateListA size required.
  1716. */
  1717. dwBufTemp = ImmGetConversionListA(hKL, hImc, lpszSrc, NULL, 0, uFlag);
  1718. if (dwBufTemp == 0 || (lpCandListA = ImmLocalAlloc(0, dwBufTemp)) == NULL) {
  1719. if (lpszSrc)
  1720. ImmLocalFree(lpszSrc);
  1721. return (0);
  1722. }
  1723. /*
  1724. * Now get the actual CandidateListA.
  1725. */
  1726. dwBufTemp = ImmGetConversionListA(hKL, hImc, lpszSrc,
  1727. lpCandListA, dwBufTemp, uFlag);
  1728. /*
  1729. * Query the CandidateListW size required.
  1730. */
  1731. if (dwBufTemp != 0) {
  1732. dwBufTemp = InternalGetCandidateListAtoW(lpCandListA, NULL, 0, dwCodePage);
  1733. }
  1734. if (dwBufLen == 0 || dwBufTemp == 0) {
  1735. /*
  1736. * Query required buffer size or error has happened.
  1737. */
  1738. dwRet = dwBufTemp;
  1739. }
  1740. else if (dwBufLen < dwBufTemp) {
  1741. /*
  1742. * Not enough buffer area.
  1743. */
  1744. dwRet = 0;
  1745. }
  1746. else {
  1747. /*
  1748. * Get the actual CandidateListW
  1749. */
  1750. dwRet = InternalGetCandidateListAtoW(lpCandListA, lpCandListW, dwBufLen, dwCodePage);
  1751. }
  1752. if (lpszSrc)
  1753. ImmLocalFree(lpszSrc);
  1754. ImmLocalFree(lpCandListA);
  1755. return dwRet;
  1756. }
  1757. /***************************************************************************\
  1758. * ImmGetStatusWindowPos
  1759. *
  1760. * Gets the position, in screen coordinates, of the status window.
  1761. *
  1762. * History:
  1763. * 27-Feb-1995 wkwok Created
  1764. \***************************************************************************/
  1765. BOOL WINAPI ImmGetStatusWindowPos(
  1766. HIMC hImc,
  1767. LPPOINT lpptPos)
  1768. {
  1769. PINPUTCONTEXT pInputContext;
  1770. BOOL fStatusWndPosInited;
  1771. pInputContext = ImmLockIMC(hImc);
  1772. if (!pInputContext) {
  1773. RIPMSG1(RIP_WARNING, "ImmGetStatusWindowPos: Lock hImc %lx failed", hImc);
  1774. return FALSE;
  1775. }
  1776. fStatusWndPosInited = ((pInputContext->fdwInit & INIT_STATUSWNDPOS) == INIT_STATUSWNDPOS);
  1777. ImmUnlockIMC(hImc);
  1778. if (fStatusWndPosInited) {
  1779. *lpptPos = pInputContext->ptStatusWndPos;
  1780. return TRUE;
  1781. }
  1782. return FALSE;
  1783. }
  1784. BOOL WINAPI ImmSetStatusWindowPos(
  1785. HIMC hImc,
  1786. LPPOINT lpptPos)
  1787. {
  1788. PINPUTCONTEXT pInputContext;
  1789. HWND hWnd;
  1790. if (GetInputContextThread(hImc) != GetCurrentThreadId()) {
  1791. RIPMSG1(RIP_WARNING,
  1792. "ImmSetStatusWindowPos: Invalid input context access %lx.", hImc);
  1793. return FALSE;
  1794. }
  1795. pInputContext = ImmLockIMC(hImc);
  1796. if (!pInputContext) {
  1797. RIPMSG1(RIP_WARNING, "ImmSetStatusWindowPos: Lock hImc %lx failed", hImc);
  1798. return (FALSE);
  1799. }
  1800. pInputContext->ptStatusWndPos = *lpptPos;
  1801. pInputContext->fdwInit |= INIT_STATUSWNDPOS;
  1802. hWnd = pInputContext->hWnd;
  1803. ImmUnlockIMC(hImc);
  1804. /*
  1805. * inform IME and UI about the change of composition font.
  1806. */
  1807. MakeIMENotify(hImc, hWnd, NI_CONTEXTUPDATED, 0L,
  1808. IMC_SETSTATUSWINDOWPOS, IMN_SETSTATUSWINDOWPOS, 0L);
  1809. return TRUE;
  1810. }
  1811. /***************************************************************************\
  1812. * ImmGetCompositionWindow
  1813. *
  1814. * Gets the information of the composition window.
  1815. *
  1816. * History:
  1817. * 27-Feb-1995 wkwok Created
  1818. \***************************************************************************/
  1819. BOOL WINAPI ImmGetCompositionWindow(
  1820. HIMC hImc,
  1821. LPCOMPOSITIONFORM lpCompForm)
  1822. {
  1823. PINPUTCONTEXT pInputContext;
  1824. BOOL fCompFormInited;
  1825. pInputContext = ImmLockIMC(hImc);
  1826. if (!pInputContext) {
  1827. RIPMSG1(RIP_WARNING, "ImmGetCompositionWindow: Lock hImc %lx failed", hImc);
  1828. return FALSE;
  1829. }
  1830. fCompFormInited = ((pInputContext->fdwInit & INIT_COMPFORM) == INIT_COMPFORM);
  1831. ImmUnlockIMC(hImc);
  1832. if (fCompFormInited) {
  1833. *lpCompForm = pInputContext->cfCompForm;
  1834. return TRUE;
  1835. }
  1836. return FALSE;
  1837. }
  1838. BOOL WINAPI ImmSetCompositionWindow(
  1839. HIMC hImc,
  1840. LPCOMPOSITIONFORM lpCompForm)
  1841. {
  1842. PINPUTCONTEXT pInputContext;
  1843. HWND hWnd;
  1844. if (GetInputContextThread(hImc) != GetCurrentThreadId()) {
  1845. RIPMSG1(RIP_WARNING,
  1846. "ImmSetCompositionWindow: Invalid input context access %lx.", hImc);
  1847. return FALSE;
  1848. }
  1849. pInputContext = ImmLockIMC(hImc);
  1850. if (!pInputContext) {
  1851. RIPMSG1(RIP_WARNING, "ImmSetCompositionWindow: Lock hImc %lx failed", hImc);
  1852. return FALSE;
  1853. }
  1854. pInputContext->cfCompForm = *lpCompForm;
  1855. pInputContext->fdwInit |= INIT_COMPFORM;
  1856. /*
  1857. * Only WINNLS.DLL set F31COMPAT_MCWHIDDEN.
  1858. * When the apps or edit control calls this API, we need to remove
  1859. * F31COMPAT_MCWHIDDEN.
  1860. */
  1861. if (pInputContext->fdw31Compat & F31COMPAT_CALLFROMWINNLS)
  1862. pInputContext->fdw31Compat &= ~F31COMPAT_CALLFROMWINNLS;
  1863. else
  1864. pInputContext->fdw31Compat &= ~F31COMPAT_MCWHIDDEN;
  1865. hWnd = pInputContext->hWnd;
  1866. ImmUnlockIMC(hImc);
  1867. /*
  1868. * inform IME and UI about the change of composition window.
  1869. */
  1870. MakeIMENotify(hImc, hWnd, NI_CONTEXTUPDATED, 0L,
  1871. IMC_SETCOMPOSITIONWINDOW, IMN_SETCOMPOSITIONWINDOW, 0L);
  1872. return TRUE;
  1873. }
  1874. /***************************************************************************\
  1875. * ImmGetCandidateWindow
  1876. *
  1877. * Gets the information of the candidate window specified by dwIndex.
  1878. *
  1879. * History:
  1880. * 27-Feb-1995 wkwok Created
  1881. \***************************************************************************/
  1882. BOOL WINAPI ImmGetCandidateWindow(
  1883. HIMC hImc,
  1884. DWORD dwIndex,
  1885. LPCANDIDATEFORM lpCandForm)
  1886. {
  1887. PINPUTCONTEXT pInputContext;
  1888. pInputContext = ImmLockIMC(hImc);
  1889. if (!pInputContext) {
  1890. RIPMSG1(RIP_WARNING, "ImmGetCandidateWindow: Lock hImc %lx failed", hImc);
  1891. return FALSE;
  1892. }
  1893. if (pInputContext->cfCandForm[dwIndex].dwIndex == -1) {
  1894. ImmUnlockIMC(hImc);
  1895. return (FALSE);
  1896. }
  1897. *lpCandForm = pInputContext->cfCandForm[dwIndex];
  1898. ImmUnlockIMC(hImc);
  1899. return TRUE;
  1900. }
  1901. BOOL WINAPI ImmSetCandidateWindow(
  1902. HIMC hImc,
  1903. LPCANDIDATEFORM lpCandForm)
  1904. {
  1905. PINPUTCONTEXT pInputContext;
  1906. HWND hWnd;
  1907. if (lpCandForm->dwIndex >= 4) // over flow candidate index
  1908. return (FALSE);
  1909. if (GetInputContextThread(hImc) != GetCurrentThreadId()) {
  1910. RIPMSG1(RIP_WARNING,
  1911. "ImmSetCandidateWindow: Invalid input context access %lx.", hImc);
  1912. return FALSE;
  1913. }
  1914. pInputContext = ImmLockIMC(hImc);
  1915. if (!pInputContext) {
  1916. RIPMSG1(RIP_WARNING, "ImmSetCandidateWindow: Lock hImc %lx failed", hImc);
  1917. return FALSE;
  1918. }
  1919. pInputContext->cfCandForm[lpCandForm->dwIndex] = *lpCandForm;
  1920. hWnd = pInputContext->hWnd;
  1921. ImmUnlockIMC(hImc);
  1922. /*
  1923. * inform IME and UI about the change of composition window.
  1924. */
  1925. MakeIMENotify(hImc, hWnd, NI_CONTEXTUPDATED, 0L, IMC_SETCANDIDATEPOS,
  1926. IMN_SETCANDIDATEPOS, (LPARAM)(0x01 << lpCandForm->dwIndex));
  1927. return TRUE;
  1928. }
  1929. #define GetCompInfoA(Component) \
  1930. if (!dwBufLen) { /* query required buffer size */ \
  1931. /* not include \0 */ \
  1932. dwBufLen = pCompStr->dw ## Component ## Len * sizeof(CHAR); \
  1933. } else { \
  1934. if (dwBufLen > pCompStr->dw ## Component ## Len * sizeof(CHAR)) { \
  1935. dwBufLen = pCompStr->dw ## Component ## Len * sizeof(CHAR); \
  1936. } \
  1937. /* don't copy \0, maybe there is actually none */ \
  1938. RtlCopyMemory((LPBYTE)lpBuf, (LPBYTE)pCompStr + \
  1939. pCompStr->dw ## Component ## Offset, dwBufLen); \
  1940. }
  1941. #define GetCompInfoW(Component) \
  1942. if (!dwBufLen) { /* query required buffer size */ \
  1943. /* not include \0 */ \
  1944. dwBufLen = pCompStr->dw ## Component ## Len * sizeof(WCHAR); \
  1945. } else { \
  1946. if (dwBufLen > pCompStr->dw ## Component ## Len * sizeof(WCHAR)) { \
  1947. dwBufLen = pCompStr->dw ## Component ## Len * sizeof(WCHAR); \
  1948. } \
  1949. /* don't copy \0, maybe there is actually none */ \
  1950. RtlCopyMemory((LPBYTE)lpBuf, (LPBYTE)pCompStr + \
  1951. pCompStr->dw ## Component ## Offset, dwBufLen); \
  1952. }
  1953. #ifdef CUAS_ENABLE
  1954. #define GetPrivInfoA(pv, Component) \
  1955. if (!dwBufLen) { /* query required buffer size */ \
  1956. /* not include \0 */ \
  1957. dwBufLen = ## pv ## ->dw ## Component ## Len * sizeof(CHAR); \
  1958. } else { \
  1959. if (dwBufLen > ## pv ## ->dw ## Component ## Len * sizeof(CHAR)) { \
  1960. dwBufLen = ## pv ## ->dw ## Component ## Len * sizeof(CHAR); \
  1961. } \
  1962. /* don't copy \0, maybe there is actually none */ \
  1963. RtlCopyMemory((LPBYTE)lpBuf, (LPBYTE) ## pv ## + \
  1964. ## pv ## ->dw ## Component ## Offset, dwBufLen); \
  1965. }
  1966. #define GetPrivInfoW(pv, Component) \
  1967. if (!dwBufLen) { /* query required buffer size */ \
  1968. /* not include \0 */ \
  1969. dwBufLen = ## pv ## ->dw ## Component ## Len * sizeof(WCHAR); \
  1970. } else { \
  1971. if (dwBufLen > ## pv ## ->dw ## Component ## Len * sizeof(WCHAR)) {\
  1972. dwBufLen = ## pv ## ->dw ## Component ## Len * sizeof(WCHAR); \
  1973. } \
  1974. /* don't copy \0, maybe there is actually none */ \
  1975. RtlCopyMemory((LPBYTE)lpBuf, (LPBYTE) ## pv ## + \
  1976. ## pv ## ->dw ## Component ## Offset, dwBufLen); \
  1977. }
  1978. #endif // CUAS_ENABLE
  1979. /***************************************************************************\
  1980. * InternalGetCompositionStringA
  1981. *
  1982. * Internal version of ImmGetCompositionStringA.
  1983. *
  1984. * History:
  1985. * 28-Feb-1995 wkwok Created
  1986. \***************************************************************************/
  1987. LONG InternalGetCompositionStringA(
  1988. #ifdef CUAS_ENABLE
  1989. HIMC hImc,
  1990. #endif // CUAS_ENABLE
  1991. PCOMPOSITIONSTRING pCompStr,
  1992. DWORD dwIndex,
  1993. LPVOID lpBuf,
  1994. DWORD dwBufLen,
  1995. BOOL fAnsiImc,
  1996. DWORD dwCodePage)
  1997. {
  1998. if (fAnsiImc) {
  1999. /*
  2000. * Composition string in input context is of ANSI style.
  2001. */
  2002. switch (dwIndex) {
  2003. case GCS_COMPSTR:
  2004. GetCompInfoA(CompStr);
  2005. break;
  2006. case GCS_COMPATTR:
  2007. GetCompInfoA(CompAttr);
  2008. break;
  2009. case GCS_COMPREADSTR:
  2010. GetCompInfoA(CompReadStr);
  2011. break;
  2012. case GCS_COMPREADATTR:
  2013. GetCompInfoA(CompReadAttr);
  2014. break;
  2015. case GCS_COMPREADCLAUSE:
  2016. GetCompInfoA(CompReadClause);
  2017. break;
  2018. case GCS_CURSORPOS:
  2019. dwBufLen = (LONG)pCompStr->dwCursorPos;
  2020. break;
  2021. case GCS_DELTASTART:
  2022. dwBufLen = (LONG)pCompStr->dwDeltaStart;
  2023. break;
  2024. case GCS_RESULTSTR:
  2025. GetCompInfoA(ResultStr);
  2026. break;
  2027. case GCS_RESULTCLAUSE:
  2028. GetCompInfoA(ResultClause);
  2029. break;
  2030. case GCS_RESULTREADSTR:
  2031. GetCompInfoA(ResultReadStr);
  2032. break;
  2033. case GCS_RESULTREADCLAUSE:
  2034. GetCompInfoA(ResultReadClause);
  2035. break;
  2036. case GCS_COMPCLAUSE:
  2037. GetCompInfoA(CompClause);
  2038. break;
  2039. #ifdef CUAS_ENABLE
  2040. case GCS_COMPGUIDATTR:
  2041. if (CtfImmIsGuidMapEnable(hImc) && (pCompStr->dwPrivateSize >= sizeof(GUIDMAPATTRIBUTE)))
  2042. {
  2043. PGUIDMAPATTRIBUTE pGuidMap = (PGUIDMAPATTRIBUTE)((PBYTE)pCompStr + pCompStr->dwPrivateOffset);
  2044. if (pGuidMap != NULL)
  2045. {
  2046. GetPrivInfoA(pGuidMap, GuidMapAttr);
  2047. }
  2048. else
  2049. {
  2050. dwBufLen = (DWORD)(LONG)IMM_ERROR_GENERAL;
  2051. }
  2052. }
  2053. else
  2054. {
  2055. dwBufLen = (DWORD)(LONG)IMM_ERROR_GENERAL;
  2056. }
  2057. break;
  2058. #endif // CUAS_ENABLE
  2059. default:
  2060. dwBufLen = (DWORD)(LONG)IMM_ERROR_GENERAL;
  2061. break;
  2062. }
  2063. return (LONG)dwBufLen;
  2064. }
  2065. /*
  2066. * ANSI caller, Unicode input context/composition string.
  2067. */
  2068. switch (dwIndex) {
  2069. case GCS_COMPSTR:
  2070. case GCS_COMPREADSTR:
  2071. case GCS_RESULTSTR:
  2072. case GCS_RESULTREADSTR:
  2073. {
  2074. DWORD dwStrSize;
  2075. LPWSTR lpStrW;
  2076. BOOL bUDC;
  2077. /*
  2078. * Get ANSI string from Unicode composition string.
  2079. */
  2080. #if !defined(CUAS_ENABLE)
  2081. dwStrSize = InternalGetCompositionStringW(pCompStr, dwIndex,
  2082. NULL, 0, fAnsiImc, dwCodePage);
  2083. #else
  2084. dwStrSize = InternalGetCompositionStringW(hImc, pCompStr, dwIndex,
  2085. NULL, 0, fAnsiImc, dwCodePage);
  2086. #endif
  2087. lpStrW = ImmLocalAlloc(HEAP_ZERO_MEMORY, dwStrSize + sizeof(WCHAR));
  2088. if (lpStrW == NULL) {
  2089. RIPMSG0(RIP_WARNING, "InternalGetCompositionStringA: memory failure.");
  2090. return (LONG)IMM_ERROR_GENERAL;
  2091. }
  2092. #if !defined(CUAS_ENABLE)
  2093. dwStrSize = InternalGetCompositionStringW(pCompStr, dwIndex,
  2094. lpStrW, dwStrSize, fAnsiImc, dwCodePage);
  2095. #else
  2096. dwStrSize = InternalGetCompositionStringW(hImc, pCompStr, dwIndex,
  2097. lpStrW, dwStrSize, fAnsiImc, dwCodePage);
  2098. #endif
  2099. dwBufLen = WideCharToMultiByte(dwCodePage,
  2100. (DWORD)0,
  2101. lpStrW, // src
  2102. wcslen(lpStrW),
  2103. (LPSTR)lpBuf, // dest
  2104. dwBufLen,
  2105. (LPSTR)NULL,
  2106. (LPBOOL)&bUDC);
  2107. ImmLocalFree(lpStrW);
  2108. break;
  2109. }
  2110. case GCS_COMPATTR:
  2111. case GCS_COMPREADATTR:
  2112. #ifdef CUAS_ENABLE
  2113. case GCS_COMPGUIDATTR:
  2114. #endif // CUAS_ENABLE
  2115. {
  2116. DWORD dwAttrLenW, dwIndexStr, dwStrSize;
  2117. PBYTE lpAttrA, lpAttrW;
  2118. LPSTR lpStrA, lpStrT;
  2119. CHAR c;
  2120. /*
  2121. * Get ANSI attribute from Unicode composition attribute.
  2122. */
  2123. switch (dwIndex) {
  2124. case GCS_COMPATTR:
  2125. lpAttrW = (PBYTE)pCompStr + pCompStr->dwCompAttrOffset;
  2126. dwAttrLenW = pCompStr->dwCompAttrLen;
  2127. dwIndexStr = GCS_COMPSTR;
  2128. break;
  2129. case GCS_COMPREADATTR:
  2130. lpAttrW = (PBYTE)pCompStr + pCompStr->dwCompReadAttrOffset;
  2131. dwAttrLenW = pCompStr->dwCompReadAttrLen;
  2132. dwIndexStr = GCS_COMPREADSTR;
  2133. break;
  2134. #ifdef CUAS_ENABLE
  2135. case GCS_COMPGUIDATTR:
  2136. if (CtfImmIsGuidMapEnable(hImc) && (pCompStr->dwPrivateSize >= sizeof(GUIDMAPATTRIBUTE)))
  2137. {
  2138. PGUIDMAPATTRIBUTE pGuidMap = (PGUIDMAPATTRIBUTE)((PBYTE)pCompStr + pCompStr->dwPrivateOffset);
  2139. if (pGuidMap != NULL)
  2140. {
  2141. lpAttrW = (PBYTE)pGuidMap + pGuidMap->dwGuidMapAttrOffset;
  2142. dwAttrLenW = pGuidMap->dwGuidMapAttrLen;
  2143. dwIndexStr = GCS_COMPSTR;
  2144. break;
  2145. }
  2146. else
  2147. {
  2148. return (DWORD)(LONG)IMM_ERROR_GENERAL;
  2149. }
  2150. }
  2151. else
  2152. {
  2153. return (DWORD)(LONG)IMM_ERROR_GENERAL;
  2154. }
  2155. break;
  2156. #endif // CUAS_ENABLE
  2157. }
  2158. if (dwAttrLenW == 0) {
  2159. /*
  2160. * No CompAttr or CompReadAttr exists, do nothing.
  2161. */
  2162. return 0;
  2163. }
  2164. #if !defined(CUAS_ENABLE)
  2165. dwStrSize = InternalGetCompositionStringA(pCompStr,
  2166. dwIndexStr, NULL, 0, fAnsiImc, dwCodePage);
  2167. #else
  2168. dwStrSize = InternalGetCompositionStringA(hImc, pCompStr,
  2169. dwIndexStr, NULL, 0, fAnsiImc, dwCodePage);
  2170. #endif
  2171. if (dwStrSize == (DWORD)(LONG)IMM_ERROR_GENERAL) {
  2172. RIPMSG0(RIP_WARNING, "InternalGetCompositionStringA: IMM_ERROR_GENERAL.");
  2173. return (LONG)IMM_ERROR_GENERAL;
  2174. }
  2175. /*
  2176. * Query required size or early exit on error.
  2177. */
  2178. if (dwBufLen == 0 || dwStrSize == 0)
  2179. return dwStrSize;
  2180. lpStrA = ImmLocalAlloc(HEAP_ZERO_MEMORY, dwStrSize + sizeof(CHAR));
  2181. if (lpStrA == NULL) {
  2182. RIPMSG0(RIP_WARNING, "InternalGetCompositionStringA: memory failure.");
  2183. return (LONG)IMM_ERROR_GENERAL;
  2184. }
  2185. #if !defined(CUAS_ENABLE)
  2186. dwStrSize = InternalGetCompositionStringA(pCompStr,
  2187. dwIndexStr, lpStrA, dwStrSize, fAnsiImc, dwCodePage);
  2188. #else
  2189. dwStrSize = InternalGetCompositionStringA(hImc, pCompStr,
  2190. dwIndexStr, lpStrA, dwStrSize, fAnsiImc, dwCodePage);
  2191. #endif
  2192. if (dwStrSize == (LONG)IMM_ERROR_GENERAL) {
  2193. RIPMSG0(RIP_WARNING, "InternalGetCompositionStringA: IMM_ERROR_GENERAL.");
  2194. ImmLocalFree(lpStrA);
  2195. return (LONG)IMM_ERROR_GENERAL;
  2196. }
  2197. lpStrT = lpStrA;
  2198. lpAttrA = (PBYTE)lpBuf;
  2199. while ((c=*lpStrT++) != '\0' && dwBufLen != 0 && dwAttrLenW-- != 0) {
  2200. if (IsDBCSLeadByteEx(dwCodePage, c)) {
  2201. if (dwBufLen >= 2) {
  2202. *lpAttrA++ = *lpAttrW;
  2203. *lpAttrA++ = *lpAttrW;
  2204. dwBufLen--;
  2205. }
  2206. else {
  2207. *lpAttrA++ = *lpAttrW;
  2208. }
  2209. lpStrT++;
  2210. }
  2211. else {
  2212. *lpAttrA++ = *lpAttrW;
  2213. }
  2214. lpAttrW++;
  2215. dwBufLen--;
  2216. }
  2217. dwBufLen = (DWORD)(lpAttrA - (PBYTE)lpBuf);
  2218. ImmLocalFree(lpStrA);
  2219. break;
  2220. }
  2221. case GCS_COMPCLAUSE:
  2222. case GCS_COMPREADCLAUSE:
  2223. case GCS_RESULTCLAUSE:
  2224. case GCS_RESULTREADCLAUSE:
  2225. {
  2226. LPWSTR lpStrW;
  2227. DWORD dwClauseLen, dwBufLenA;
  2228. LPDWORD lpdwSrc, lpdwDst;
  2229. UINT i;
  2230. /*
  2231. * Get ANSI clause from Unicode composition clause.
  2232. */
  2233. switch (dwIndex) {
  2234. case GCS_COMPCLAUSE:
  2235. lpStrW = (LPWSTR)((PBYTE)pCompStr + pCompStr->dwCompStrOffset);
  2236. lpdwSrc = (LPDWORD)((PBYTE)pCompStr + pCompStr->dwCompClauseOffset);
  2237. dwClauseLen = pCompStr->dwCompClauseLen;
  2238. break;
  2239. case GCS_COMPREADCLAUSE:
  2240. lpStrW = (LPWSTR)((PBYTE)pCompStr + pCompStr->dwCompReadStrOffset);
  2241. lpdwSrc = (LPDWORD)((PBYTE)pCompStr + pCompStr->dwCompReadClauseOffset);
  2242. dwClauseLen = pCompStr->dwCompReadClauseLen;
  2243. break;
  2244. case GCS_RESULTCLAUSE:
  2245. lpStrW = (LPWSTR)((PBYTE)pCompStr + pCompStr->dwResultStrOffset);
  2246. lpdwSrc = (LPDWORD)((PBYTE)pCompStr + pCompStr->dwResultClauseOffset);
  2247. dwClauseLen = pCompStr->dwResultClauseLen;
  2248. break;
  2249. case GCS_RESULTREADCLAUSE:
  2250. lpStrW = (LPWSTR)((PBYTE)pCompStr + pCompStr->dwResultReadStrOffset);
  2251. lpdwSrc = (LPDWORD)((PBYTE)pCompStr + pCompStr->dwResultReadClauseOffset);
  2252. dwClauseLen = pCompStr->dwResultReadClauseLen;
  2253. break;
  2254. }
  2255. /*
  2256. * Query clause length or early exit on error.
  2257. */
  2258. if (dwBufLen == 0 || (LONG)dwClauseLen < 0) {
  2259. dwBufLen = dwClauseLen;
  2260. break;
  2261. }
  2262. lpdwDst = (LPDWORD)lpBuf;
  2263. dwBufLenA = dwBufLen / sizeof(DWORD);
  2264. for (i = 0; i < dwClauseLen / sizeof(DWORD) && dwBufLenA != 0; i++) {
  2265. *lpdwDst++ = CalcCharacterPositionWtoA(*lpdwSrc++, lpStrW, dwCodePage);
  2266. dwBufLenA--;
  2267. }
  2268. dwBufLen = i * sizeof(DWORD);
  2269. break;
  2270. }
  2271. case GCS_CURSORPOS:
  2272. case GCS_DELTASTART:
  2273. /*
  2274. * Get ANSI cursor/delta start position from Unicode composition string.
  2275. */
  2276. switch (dwIndex) {
  2277. case GCS_CURSORPOS:
  2278. dwBufLen = pCompStr->dwCursorPos;
  2279. break;
  2280. case GCS_DELTASTART:
  2281. dwBufLen = pCompStr->dwDeltaStart;
  2282. break;
  2283. }
  2284. if ((LONG)dwBufLen > 0) {
  2285. dwBufLen = CalcCharacterPositionWtoA(dwBufLen,
  2286. (LPWSTR)((PBYTE)pCompStr + pCompStr->dwCompStrOffset),
  2287. dwCodePage);
  2288. }
  2289. break;
  2290. default:
  2291. dwBufLen = (DWORD)(LONG)IMM_ERROR_GENERAL;
  2292. }
  2293. return (LONG)dwBufLen;
  2294. }
  2295. /***************************************************************************\
  2296. * InternalGetCompositionStringW
  2297. *
  2298. * Internal version of ImmGetCompositionStringW.
  2299. *
  2300. * History:
  2301. * 28-Feb-1995 wkwok Created
  2302. \***************************************************************************/
  2303. LONG InternalGetCompositionStringW(
  2304. #ifdef CUAS_ENABLE
  2305. HIMC hImc,
  2306. #endif // CUAS_ENABLE
  2307. PCOMPOSITIONSTRING pCompStr,
  2308. DWORD dwIndex,
  2309. LPVOID lpBuf,
  2310. DWORD dwBufLen,
  2311. BOOL fAnsiImc,
  2312. DWORD dwCodePage)
  2313. {
  2314. if (!fAnsiImc) {
  2315. /*
  2316. * Composition string in input context is of Unicode style.
  2317. */
  2318. switch (dwIndex) {
  2319. case GCS_COMPSTR:
  2320. GetCompInfoW(CompStr);
  2321. break;
  2322. case GCS_COMPATTR: // ANSI-only
  2323. GetCompInfoA(CompAttr);
  2324. break;
  2325. case GCS_COMPREADSTR:
  2326. GetCompInfoW(CompReadStr);
  2327. break;
  2328. case GCS_COMPREADATTR: // ANSI-only
  2329. GetCompInfoA(CompReadAttr);
  2330. break;
  2331. case GCS_COMPREADCLAUSE: // ANSI-only
  2332. GetCompInfoA(CompReadClause);
  2333. break;
  2334. case GCS_CURSORPOS:
  2335. dwBufLen = (LONG)pCompStr->dwCursorPos;
  2336. break;
  2337. case GCS_DELTASTART:
  2338. dwBufLen = (LONG)pCompStr->dwDeltaStart;
  2339. break;
  2340. case GCS_RESULTSTR:
  2341. GetCompInfoW(ResultStr);
  2342. break;
  2343. case GCS_RESULTCLAUSE: // ANSI-only
  2344. GetCompInfoA(ResultClause);
  2345. break;
  2346. case GCS_RESULTREADSTR:
  2347. GetCompInfoW(ResultReadStr);
  2348. break;
  2349. case GCS_RESULTREADCLAUSE: // ANSI-only
  2350. GetCompInfoA(ResultReadClause);
  2351. break;
  2352. case GCS_COMPCLAUSE: // ANSI-only
  2353. GetCompInfoA(CompClause);
  2354. break;
  2355. #ifdef CUAS_ENABLE
  2356. case GCS_COMPGUIDATTR: // ANSI-only
  2357. if (CtfImmIsGuidMapEnable(hImc) && (pCompStr->dwPrivateSize >= sizeof(GUIDMAPATTRIBUTE)))
  2358. {
  2359. PGUIDMAPATTRIBUTE pGuidMap = (PGUIDMAPATTRIBUTE)((PBYTE)pCompStr + pCompStr->dwPrivateOffset);
  2360. if (pGuidMap != NULL)
  2361. {
  2362. GetPrivInfoA(pGuidMap, GuidMapAttr);
  2363. }
  2364. else
  2365. {
  2366. dwBufLen = (DWORD)(LONG)IMM_ERROR_GENERAL;
  2367. }
  2368. }
  2369. else
  2370. {
  2371. dwBufLen = (DWORD)(LONG)IMM_ERROR_GENERAL;
  2372. }
  2373. break;
  2374. #endif // CUAS_ENABLE
  2375. default:
  2376. dwBufLen = (DWORD)IMM_ERROR_GENERAL;
  2377. break;
  2378. }
  2379. return (LONG)dwBufLen;
  2380. }
  2381. /*
  2382. * Unicode caller, ANSI input context/composition string.
  2383. */
  2384. switch (dwIndex) {
  2385. case GCS_COMPSTR:
  2386. case GCS_COMPREADSTR:
  2387. case GCS_RESULTSTR:
  2388. case GCS_RESULTREADSTR:
  2389. {
  2390. DWORD dwStrSize;
  2391. LPSTR lpStrA;
  2392. /*
  2393. * Get Unicode string from ANSI composition string.
  2394. */
  2395. #if !defined(CUAS_ENABLE)
  2396. dwStrSize = InternalGetCompositionStringA(pCompStr, dwIndex,
  2397. NULL, 0, fAnsiImc, dwCodePage);
  2398. #else
  2399. dwStrSize = InternalGetCompositionStringA(hImc, pCompStr, dwIndex,
  2400. NULL, 0, fAnsiImc, dwCodePage);
  2401. #endif
  2402. lpStrA = ImmLocalAlloc(HEAP_ZERO_MEMORY, dwStrSize + sizeof(CHAR));
  2403. if (lpStrA == NULL) {
  2404. RIPMSG0(RIP_WARNING, "InternalGetCompositionStringW: memory failure.");
  2405. return (LONG)IMM_ERROR_GENERAL;
  2406. }
  2407. #if !defined(CUAS_ENABLE)
  2408. dwStrSize = InternalGetCompositionStringA(pCompStr, dwIndex,
  2409. lpStrA, dwStrSize, fAnsiImc, dwCodePage);
  2410. #else
  2411. dwStrSize = InternalGetCompositionStringA(hImc, pCompStr, dwIndex,
  2412. lpStrA, dwStrSize, fAnsiImc, dwCodePage);
  2413. #endif
  2414. dwBufLen = MultiByteToWideChar(dwCodePage,
  2415. (DWORD)MB_PRECOMPOSED,
  2416. lpStrA, // src
  2417. strlen(lpStrA),
  2418. (LPWSTR)lpBuf, // dest
  2419. (INT)dwBufLen);
  2420. dwBufLen *= sizeof(WCHAR); // return number of bytes required.
  2421. ImmLocalFree(lpStrA);
  2422. break;
  2423. }
  2424. case GCS_COMPATTR:
  2425. case GCS_COMPREADATTR:
  2426. #ifdef CUAS_ENABLE
  2427. case GCS_COMPGUIDATTR:
  2428. #endif // CUAS_ENABLE
  2429. {
  2430. DWORD dwAttrLenA, dwIndexStr, dwStrSize;
  2431. PBYTE lpAttrA, lpAttrW;
  2432. LPWSTR lpStrW, lpStrT;
  2433. ULONG MultiByteSize;
  2434. WCHAR wc;
  2435. /*
  2436. * Get Unicode attribute from ANSI composition attribute.
  2437. */
  2438. switch (dwIndex) {
  2439. case GCS_COMPATTR:
  2440. lpAttrA = (PBYTE)pCompStr + pCompStr->dwCompAttrOffset;
  2441. dwAttrLenA = pCompStr->dwCompAttrLen;
  2442. dwIndexStr = GCS_COMPSTR;
  2443. break;
  2444. case GCS_COMPREADATTR:
  2445. lpAttrA = (PBYTE)pCompStr + pCompStr->dwCompReadAttrOffset;
  2446. dwAttrLenA = pCompStr->dwCompReadAttrLen;
  2447. dwIndexStr = GCS_COMPREADSTR;
  2448. break;
  2449. #ifdef CUAS_ENABLE
  2450. case GCS_COMPGUIDATTR:
  2451. if (CtfImmIsGuidMapEnable(hImc) && (pCompStr->dwPrivateSize >= sizeof(GUIDMAPATTRIBUTE)))
  2452. {
  2453. PGUIDMAPATTRIBUTE pGuidMap = (PGUIDMAPATTRIBUTE)((PBYTE)pCompStr + pCompStr->dwPrivateOffset);
  2454. if (pGuidMap != NULL)
  2455. {
  2456. lpAttrA = (PBYTE)pGuidMap + pGuidMap->dwGuidMapAttrOffset;
  2457. dwAttrLenA = pGuidMap->dwGuidMapAttrLen;
  2458. dwIndexStr = GCS_COMPSTR;
  2459. break;
  2460. }
  2461. else
  2462. {
  2463. return (DWORD)(LONG)IMM_ERROR_GENERAL;
  2464. }
  2465. }
  2466. else
  2467. {
  2468. return (DWORD)(LONG)IMM_ERROR_GENERAL;
  2469. }
  2470. break;
  2471. #endif // CUAS_ENABLE
  2472. }
  2473. if (dwAttrLenA == 0) {
  2474. /*
  2475. * No CompAttr or CompReadAttr exists, do nothing.
  2476. */
  2477. return 0;
  2478. }
  2479. #if !defined(CUAS_ENABLE)
  2480. dwStrSize = InternalGetCompositionStringW(pCompStr,
  2481. dwIndexStr, NULL, 0, fAnsiImc, dwCodePage);
  2482. #else
  2483. dwStrSize = InternalGetCompositionStringW(hImc, pCompStr,
  2484. dwIndexStr, NULL, 0, fAnsiImc, dwCodePage);
  2485. #endif
  2486. if (dwStrSize == (DWORD)(LONG)IMM_ERROR_GENERAL) {
  2487. RIPMSG0(RIP_WARNING, "InternalGetCompositionStringA: IMM_ERROR_GENERAL.");
  2488. return (LONG)IMM_ERROR_GENERAL;
  2489. }
  2490. /*
  2491. * Query required size or early exit on error.
  2492. */
  2493. if (dwBufLen == 0 || dwStrSize == 0)
  2494. return dwStrSize / sizeof(WCHAR);
  2495. lpStrW = ImmLocalAlloc(HEAP_ZERO_MEMORY, dwStrSize + sizeof(WCHAR));
  2496. if (lpStrW == NULL) {
  2497. RIPMSG0(RIP_WARNING, "InternalGetCompositionStringW: memory failure.");
  2498. return (LONG)IMM_ERROR_GENERAL;
  2499. }
  2500. #if !defined(CUAS_ENABLE)
  2501. dwStrSize = InternalGetCompositionStringW(pCompStr,
  2502. dwIndexStr, lpStrW, dwStrSize, fAnsiImc, dwCodePage);
  2503. #else
  2504. dwStrSize = InternalGetCompositionStringW(hImc, pCompStr,
  2505. dwIndexStr, lpStrW, dwStrSize, fAnsiImc, dwCodePage);
  2506. #endif
  2507. if (dwStrSize == (LONG)IMM_ERROR_GENERAL) {
  2508. RIPMSG0(RIP_WARNING, "InternalGetCompositionStringA: IMM_ERROR_GENERAL.");
  2509. ImmLocalFree(lpStrW);
  2510. return (LONG)IMM_ERROR_GENERAL;
  2511. }
  2512. lpStrT = lpStrW;
  2513. lpAttrW = (PBYTE)lpBuf;
  2514. while ((wc=*lpStrT++) != L'\0' && dwBufLen != 0 && dwAttrLenA-- != 0) {
  2515. MultiByteSize = UnicodeToMultiByteSize(dwCodePage, &wc);
  2516. if (MultiByteSize == 2 && dwAttrLenA != 0) {
  2517. *lpAttrW++ = *lpAttrA++;
  2518. dwAttrLenA--;
  2519. }
  2520. else {
  2521. *lpAttrW++ = *lpAttrA;
  2522. }
  2523. lpAttrA++;
  2524. dwBufLen--;
  2525. }
  2526. dwBufLen = (DWORD)(lpAttrW - (PBYTE)lpBuf);
  2527. ImmLocalFree(lpStrW);
  2528. break;
  2529. }
  2530. case GCS_COMPCLAUSE:
  2531. case GCS_COMPREADCLAUSE:
  2532. case GCS_RESULTCLAUSE:
  2533. case GCS_RESULTREADCLAUSE:
  2534. {
  2535. LPSTR lpStrA;
  2536. DWORD dwClauseLen, dwBufLenW;
  2537. LPDWORD lpdwSrc, lpdwDst;
  2538. UINT i;
  2539. /*
  2540. * Get Unicode clause from ANSI composition clause.
  2541. */
  2542. switch (dwIndex) {
  2543. case GCS_COMPCLAUSE:
  2544. lpStrA = (LPSTR)((PBYTE)pCompStr + pCompStr->dwCompStrOffset);
  2545. lpdwSrc = (LPDWORD)((PBYTE)pCompStr + pCompStr->dwCompClauseOffset);
  2546. dwClauseLen = pCompStr->dwCompClauseLen;
  2547. break;
  2548. case GCS_COMPREADCLAUSE:
  2549. lpStrA = (LPSTR)((PBYTE)pCompStr + pCompStr->dwCompReadStrOffset);
  2550. lpdwSrc = (LPDWORD)((PBYTE)pCompStr + pCompStr->dwCompReadClauseOffset);
  2551. dwClauseLen = pCompStr->dwCompReadClauseLen;
  2552. break;
  2553. case GCS_RESULTCLAUSE:
  2554. lpStrA = (LPSTR)((PBYTE)pCompStr + pCompStr->dwResultStrOffset);
  2555. lpdwSrc = (LPDWORD)((PBYTE)pCompStr + pCompStr->dwResultClauseOffset);
  2556. dwClauseLen = pCompStr->dwResultClauseLen;
  2557. break;
  2558. case GCS_RESULTREADCLAUSE:
  2559. lpStrA = (LPSTR)((PBYTE)pCompStr + pCompStr->dwResultReadStrOffset);
  2560. lpdwSrc = (LPDWORD)((PBYTE)pCompStr + pCompStr->dwResultReadClauseOffset);
  2561. dwClauseLen = pCompStr->dwResultReadClauseLen;
  2562. break;
  2563. }
  2564. /*
  2565. * Query clause length or early exit on error.
  2566. */
  2567. if (dwBufLen == 0 || (LONG)dwClauseLen < 0) {
  2568. dwBufLen = dwClauseLen;
  2569. break;
  2570. }
  2571. lpdwDst = (LPDWORD)lpBuf;
  2572. dwBufLenW = dwBufLen / sizeof(DWORD);
  2573. for (i = 0; i < dwClauseLen / sizeof(DWORD) && dwBufLenW != 0; i++) {
  2574. *lpdwDst++ = CalcCharacterPositionAtoW(*lpdwSrc++, lpStrA, dwCodePage);
  2575. dwBufLenW--;
  2576. }
  2577. dwBufLen = i * sizeof(DWORD);
  2578. break;
  2579. }
  2580. case GCS_CURSORPOS:
  2581. case GCS_DELTASTART:
  2582. /*
  2583. * Get Unicode cursor/delta start position from ANSI composition string.
  2584. */
  2585. switch (dwIndex) {
  2586. case GCS_CURSORPOS:
  2587. dwBufLen = pCompStr->dwCursorPos;
  2588. break;
  2589. case GCS_DELTASTART:
  2590. dwBufLen = pCompStr->dwDeltaStart;
  2591. break;
  2592. }
  2593. if ((LONG)dwBufLen > 0) {
  2594. dwBufLen = CalcCharacterPositionAtoW(dwBufLen,
  2595. (LPSTR)((PBYTE)pCompStr + pCompStr->dwCompStrOffset),
  2596. dwCodePage);
  2597. }
  2598. break;
  2599. default:
  2600. dwBufLen = (DWORD)(LONG)IMM_ERROR_GENERAL;
  2601. }
  2602. return (LONG)dwBufLen;
  2603. }
  2604. DWORD InternalGetCandidateListAtoW(
  2605. LPCANDIDATELIST lpCandListA,
  2606. LPCANDIDATELIST lpCandListW,
  2607. DWORD dwBufLen,
  2608. DWORD dwCodePage)
  2609. {
  2610. LPWSTR lpCandStrW;
  2611. LPSTR lpCandStrA;
  2612. INT i, j;
  2613. DWORD dwCandListLen;
  2614. dwCandListLen = sizeof(CANDIDATELIST);
  2615. /*
  2616. * CANDIDATELIST has already contained the dwOffset[0]
  2617. */
  2618. if (lpCandListA->dwCount > 0)
  2619. dwCandListLen += sizeof(DWORD) * (lpCandListA->dwCount - 1);
  2620. for (i = 0; i < (INT)lpCandListA->dwCount; i++) {
  2621. lpCandStrA = (LPSTR)((LPBYTE)lpCandListA + lpCandListA->dwOffset[i]);
  2622. j = MultiByteToWideChar(dwCodePage,
  2623. (DWORD)MB_PRECOMPOSED,
  2624. lpCandStrA,
  2625. -1,
  2626. (LPWSTR)NULL,
  2627. 0);
  2628. dwCandListLen += (j * sizeof(WCHAR));
  2629. }
  2630. dwCandListLen = DWORD_ALIGN(dwCandListLen);
  2631. if (dwBufLen == 0)
  2632. return dwCandListLen;
  2633. if (dwBufLen < dwCandListLen) {
  2634. RIPMSG0(RIP_WARNING, "InternalGetCandidateListAtoW: dwBufLen too small.");
  2635. return 0;
  2636. }
  2637. lpCandListW->dwSize = dwBufLen;
  2638. lpCandListW->dwStyle = lpCandListA->dwStyle;
  2639. lpCandListW->dwCount = lpCandListA->dwCount;
  2640. lpCandListW->dwSelection = lpCandListA->dwSelection;
  2641. lpCandListW->dwPageStart = lpCandListA->dwPageStart;
  2642. lpCandListW->dwPageSize = lpCandListA->dwPageSize;
  2643. lpCandListW->dwOffset[0] = sizeof(CANDIDATELIST);
  2644. if (lpCandListW->dwCount > 0)
  2645. lpCandListW->dwOffset[0] += sizeof(DWORD) * (lpCandListW->dwCount - 1);
  2646. dwCandListLen = dwBufLen - lpCandListW->dwOffset[0];
  2647. for (i = 0; i < (INT)lpCandListW->dwCount; i++) {
  2648. lpCandStrA = (LPSTR) ((LPBYTE)lpCandListA + lpCandListA->dwOffset[i]);
  2649. lpCandStrW = (LPWSTR)((LPBYTE)lpCandListW + lpCandListW->dwOffset[i]);
  2650. j = MultiByteToWideChar(dwCodePage,
  2651. (DWORD)MB_PRECOMPOSED,
  2652. lpCandStrA,
  2653. -1,
  2654. lpCandStrW,
  2655. (INT)dwCandListLen/sizeof(WCHAR));
  2656. dwCandListLen -= (j * sizeof(WCHAR));
  2657. if (i < (INT)lpCandListW->dwCount - 1)
  2658. lpCandListW->dwOffset[i+1] = lpCandListW->dwOffset[i] + j * sizeof(WCHAR);
  2659. }
  2660. return dwBufLen;
  2661. }
  2662. DWORD InternalGetCandidateListWtoA(
  2663. LPCANDIDATELIST lpCandListW,
  2664. LPCANDIDATELIST lpCandListA,
  2665. DWORD dwBufLen,
  2666. DWORD dwCodePage)
  2667. {
  2668. LPWSTR lpCandStrW;
  2669. LPSTR lpCandStrA;
  2670. INT i, j;
  2671. DWORD dwCandListLen;
  2672. BOOL bUDC;
  2673. dwCandListLen = sizeof(CANDIDATELIST);
  2674. /*
  2675. * CANDIDATELIST has already contained the dwOffset[0]
  2676. */
  2677. if (lpCandListW->dwCount > 0)
  2678. dwCandListLen += sizeof(DWORD) * (lpCandListW->dwCount - 1);
  2679. for (i = 0; i < (INT)lpCandListW->dwCount; i++) {
  2680. lpCandStrW = (LPWSTR)((LPBYTE)lpCandListW + lpCandListW->dwOffset[i]);
  2681. j = WideCharToMultiByte(dwCodePage,
  2682. (DWORD)0,
  2683. lpCandStrW,
  2684. -1,
  2685. (LPSTR)NULL,
  2686. (INT)0,
  2687. (LPSTR)NULL,
  2688. (LPBOOL)&bUDC);
  2689. dwCandListLen += (j * sizeof(CHAR));
  2690. }
  2691. dwCandListLen = DWORD_ALIGN(dwCandListLen);
  2692. if (dwBufLen == 0)
  2693. return dwCandListLen;
  2694. if (dwBufLen < dwCandListLen) {
  2695. RIPMSG0(RIP_WARNING, "InternalGetCandidateListWtoA: dwBufLen too small.");
  2696. return 0;
  2697. }
  2698. lpCandListA->dwSize = dwBufLen;
  2699. lpCandListA->dwStyle = lpCandListW->dwStyle;
  2700. lpCandListA->dwCount = lpCandListW->dwCount;
  2701. lpCandListA->dwSelection = lpCandListW->dwSelection;
  2702. lpCandListA->dwPageStart = lpCandListW->dwPageStart;
  2703. lpCandListA->dwPageSize = lpCandListW->dwPageSize;
  2704. lpCandListA->dwOffset[0] = sizeof(CANDIDATELIST);
  2705. if (lpCandListA->dwCount > 0)
  2706. lpCandListA->dwOffset[0] += sizeof(DWORD) * (lpCandListA->dwCount - 1);
  2707. dwCandListLen = dwBufLen - lpCandListA->dwOffset[0];
  2708. for (i = 0; i < (INT)lpCandListA->dwCount; i++) {
  2709. lpCandStrA = (LPSTR) ((LPBYTE)lpCandListA + lpCandListA->dwOffset[i]);
  2710. lpCandStrW = (LPWSTR)((LPBYTE)lpCandListW + lpCandListW->dwOffset[i]);
  2711. j = WideCharToMultiByte(dwCodePage,
  2712. (DWORD)0,
  2713. lpCandStrW,
  2714. -1,
  2715. (LPSTR)lpCandStrA,
  2716. (INT)dwCandListLen,
  2717. (LPSTR)NULL,
  2718. (LPBOOL)&bUDC);
  2719. dwCandListLen -= (j * sizeof(CHAR));
  2720. if (i < (INT)lpCandListA->dwCount - 1)
  2721. lpCandListA->dwOffset[i+1] = lpCandListA->dwOffset[i] + j * sizeof(CHAR);
  2722. }
  2723. return dwBufLen;
  2724. }
  2725. /***************************************************************************\
  2726. * CalcCharacterPositionAtoW
  2727. *
  2728. * Calculate Unicode character position to ANSI character position.
  2729. *
  2730. * History:
  2731. * 28-Feb-1995 wkwok Created
  2732. \***************************************************************************/
  2733. DWORD CalcCharacterPositionAtoW(
  2734. DWORD dwCharPosA,
  2735. LPSTR lpszCharStr,
  2736. DWORD dwCodePage)
  2737. {
  2738. DWORD dwCharPosW = 0;
  2739. while (dwCharPosA != 0) {
  2740. if (IsDBCSLeadByteEx(dwCodePage, *lpszCharStr)) {
  2741. if (dwCharPosA >= 2) {
  2742. dwCharPosA -= 2;
  2743. }
  2744. else {
  2745. dwCharPosA--;
  2746. }
  2747. lpszCharStr += 2;
  2748. }
  2749. else {
  2750. dwCharPosA--;
  2751. lpszCharStr++;
  2752. }
  2753. dwCharPosW++;
  2754. }
  2755. return dwCharPosW;
  2756. }
  2757. /***************************************************************************\
  2758. * CalcCharacterPositionWtoA
  2759. *
  2760. * Calculate ANSI character position to Unicode character position.
  2761. *
  2762. * History:
  2763. * 28-Feb-1995 wkwok Created
  2764. \***************************************************************************/
  2765. DWORD CalcCharacterPositionWtoA(
  2766. DWORD dwCharPosW,
  2767. LPWSTR lpwszCharStr,
  2768. DWORD dwCodePage)
  2769. {
  2770. DWORD dwCharPosA = 0;
  2771. ULONG MultiByteSize;
  2772. while (dwCharPosW != 0) {
  2773. MultiByteSize = UnicodeToMultiByteSize(dwCodePage, lpwszCharStr);
  2774. if (MultiByteSize == 2) {
  2775. dwCharPosA += 2;
  2776. }
  2777. else {
  2778. dwCharPosA++;
  2779. }
  2780. dwCharPosW--;
  2781. lpwszCharStr++;
  2782. }
  2783. return dwCharPosA;
  2784. }
  2785. VOID LFontAtoLFontW(
  2786. LPLOGFONTA lpLogFontA,
  2787. LPLOGFONTW lpLogFontW)
  2788. {
  2789. INT i;
  2790. RtlCopyMemory(lpLogFontW, lpLogFontA, sizeof(LOGFONTA)-LF_FACESIZE);
  2791. i = MultiByteToWideChar(CP_ACP, // Note: font face name should use ACP for A/W conversion.
  2792. MB_PRECOMPOSED,
  2793. lpLogFontA->lfFaceName,
  2794. strlen(lpLogFontA->lfFaceName),
  2795. lpLogFontW->lfFaceName,
  2796. LF_FACESIZE);
  2797. lpLogFontW->lfFaceName[i] = L'\0';
  2798. return;
  2799. }
  2800. VOID LFontWtoLFontA(
  2801. LPLOGFONTW lpLogFontW,
  2802. LPLOGFONTA lpLogFontA)
  2803. {
  2804. INT i;
  2805. BOOL bUDC;
  2806. RtlCopyMemory(lpLogFontA, lpLogFontW, sizeof(LOGFONTA)-LF_FACESIZE);
  2807. i = WideCharToMultiByte(CP_ACP, // Note: font face name should use ACP for A/W conversion.
  2808. 0,
  2809. lpLogFontW->lfFaceName,
  2810. wcslen(lpLogFontW->lfFaceName),
  2811. lpLogFontA->lfFaceName,
  2812. LF_FACESIZE,
  2813. (LPSTR)NULL,
  2814. &bUDC);
  2815. lpLogFontA->lfFaceName[i] = '\0';
  2816. return;
  2817. }
  2818. BOOL MakeIMENotify(
  2819. HIMC hImc,
  2820. HWND hWnd,
  2821. DWORD dwAction,
  2822. DWORD dwIndex,
  2823. DWORD dwValue,
  2824. WPARAM wParam,
  2825. LPARAM lParam)
  2826. {
  2827. PIMEDPI pImeDpi;
  2828. DWORD dwThreadId;
  2829. #ifdef LATER
  2830. // implement MakeIMENotifyEvent() later
  2831. #endif
  2832. if (dwAction != 0 && (dwThreadId = GetInputContextThread(hImc)) != 0) {
  2833. pImeDpi = ImmLockImeDpi(GetKeyboardLayout(dwThreadId));
  2834. if (pImeDpi != NULL) {
  2835. (*pImeDpi->pfn.NotifyIME)(hImc, dwAction, dwIndex, dwValue);
  2836. ImmUnlockImeDpi(pImeDpi);
  2837. }
  2838. }
  2839. if (hWnd != NULL && wParam != 0)
  2840. SendMessage(hWnd, WM_IME_NOTIFY, wParam, lParam);
  2841. return TRUE;
  2842. }
  2843. //////////////////////////////////////////////////////////////////////
  2844. // Reconversion support
  2845. //////////////////////////////////////////////////////////////////////
  2846. typedef enum {FROM_IME, FROM_APP} REQ_CALLER;
  2847. ///////////////////////////////////////////////////////////////////////////////////
  2848. // ImmGetReconvertTotalSize
  2849. //
  2850. // calculate the appropriate size of the buffer, based on caller/ansi information
  2851. //
  2852. // History:
  2853. // 28-Feb-1997 hiroyama Created
  2854. ///////////////////////////////////////////////////////////////////////////////////
  2855. DWORD ImmGetReconvertTotalSize(DWORD dwSize, REQ_CALLER eCaller, BOOL bAnsiTarget)
  2856. {
  2857. if (dwSize < sizeof(RECONVERTSTRING)) {
  2858. return 0;
  2859. }
  2860. if (bAnsiTarget) {
  2861. dwSize -= sizeof(RECONVERTSTRING);
  2862. if (eCaller == FROM_IME) {
  2863. dwSize /= 2;
  2864. } else {
  2865. dwSize *= 2;
  2866. }
  2867. dwSize += sizeof(RECONVERTSTRING);
  2868. }
  2869. return dwSize;
  2870. }
  2871. DWORD ImmReconversionWorker(
  2872. LPRECONVERTSTRING lpRecTo,
  2873. LPRECONVERTSTRING lpRecFrom,
  2874. BOOL bToAnsi,
  2875. DWORD dwCodePage)
  2876. {
  2877. INT i;
  2878. DWORD dwSize = 0;
  2879. UserAssert(lpRecTo);
  2880. UserAssert(lpRecFrom);
  2881. if (lpRecFrom->dwVersion != 0 || lpRecTo->dwVersion != 0) {
  2882. RIPMSG0(RIP_WARNING, "ImmReconversionWorker: dwVersion in lpRecTo or lpRecFrom is incorrect.");
  2883. return 0;
  2884. }
  2885. // Note:
  2886. // In any IME related structures, use the following principal.
  2887. // 1) xxxStrOffset is an actual offset, i.e. byte count.
  2888. // 2) xxxStrLen is a number of characters, i.e. TCHAR count.
  2889. //
  2890. // CalcCharacterPositionXtoY() takes TCHAR count so that we
  2891. // need to adjust xxxStrOffset if it's being converted. But you
  2892. // should be careful, because the actual position of the string
  2893. // is always at something like (LPBYTE)lpStruc + lpStruc->dwStrOffset.
  2894. //
  2895. if (bToAnsi) {
  2896. // Convert W to A
  2897. lpRecTo->dwStrOffset = sizeof *lpRecTo;
  2898. i = WideCharToMultiByte(dwCodePage,
  2899. (DWORD)0,
  2900. (LPWSTR)((LPSTR)lpRecFrom + lpRecFrom->dwStrOffset), // src
  2901. (INT)lpRecFrom->dwStrLen,
  2902. (LPSTR)lpRecTo + lpRecTo->dwStrOffset, // dest
  2903. (INT)lpRecFrom->dwStrLen * DBCS_CHARSIZE,
  2904. (LPSTR)NULL,
  2905. (LPBOOL)NULL);
  2906. lpRecTo->dwCompStrOffset =
  2907. CalcCharacterPositionWtoA(lpRecFrom->dwCompStrOffset / sizeof(WCHAR),
  2908. (LPWSTR)((LPBYTE)lpRecFrom + lpRecFrom->dwStrOffset),
  2909. dwCodePage)
  2910. * sizeof(CHAR);
  2911. lpRecTo->dwCompStrLen =
  2912. (CalcCharacterPositionWtoA(lpRecFrom->dwCompStrOffset / sizeof(WCHAR) +
  2913. lpRecFrom->dwCompStrLen,
  2914. (LPWSTR)((LPBYTE)lpRecFrom + lpRecFrom->dwStrOffset),
  2915. dwCodePage)
  2916. * sizeof(CHAR))
  2917. - lpRecTo->dwCompStrOffset;
  2918. lpRecTo->dwTargetStrOffset =
  2919. CalcCharacterPositionWtoA(lpRecFrom->dwTargetStrOffset / sizeof(WCHAR),
  2920. (LPWSTR)((LPBYTE)lpRecFrom +
  2921. lpRecFrom->dwStrOffset),
  2922. dwCodePage)
  2923. * sizeof(CHAR);
  2924. lpRecTo->dwTargetStrLen =
  2925. (CalcCharacterPositionWtoA(lpRecFrom->dwTargetStrOffset / sizeof(WCHAR) +
  2926. lpRecFrom->dwTargetStrLen,
  2927. (LPWSTR)((LPBYTE)lpRecFrom + lpRecFrom->dwStrOffset),
  2928. dwCodePage)
  2929. * sizeof(CHAR))
  2930. - lpRecTo->dwTargetStrOffset;
  2931. ((LPSTR)lpRecTo)[lpRecTo->dwStrOffset + i] = '\0';
  2932. lpRecTo->dwStrLen = i * sizeof(CHAR);
  2933. dwSize = sizeof(RECONVERTSTRING) + ((i + 1) * sizeof(CHAR));
  2934. } else {
  2935. // AtoW
  2936. lpRecTo->dwStrOffset = sizeof *lpRecTo;
  2937. i = MultiByteToWideChar(dwCodePage,
  2938. (DWORD)MB_PRECOMPOSED,
  2939. (LPSTR)lpRecFrom + lpRecFrom->dwStrOffset, // src
  2940. (INT)lpRecFrom->dwStrLen,
  2941. (LPWSTR)((LPSTR)lpRecTo + lpRecTo->dwStrOffset), // dest
  2942. (INT)lpRecFrom->dwStrLen);
  2943. lpRecTo->dwCompStrOffset =
  2944. CalcCharacterPositionAtoW(lpRecFrom->dwCompStrOffset,
  2945. (LPSTR)lpRecFrom + lpRecFrom->dwStrOffset,
  2946. dwCodePage) * sizeof(WCHAR);
  2947. lpRecTo->dwCompStrLen =
  2948. ((CalcCharacterPositionAtoW(lpRecFrom->dwCompStrOffset +
  2949. lpRecFrom->dwCompStrLen,
  2950. (LPSTR)lpRecFrom + lpRecFrom->dwStrOffset,
  2951. dwCodePage) * sizeof(WCHAR))
  2952. - lpRecTo->dwCompStrOffset) / sizeof(WCHAR);
  2953. lpRecTo->dwTargetStrOffset =
  2954. CalcCharacterPositionAtoW(lpRecFrom->dwTargetStrOffset,
  2955. (LPSTR)lpRecFrom + lpRecFrom->dwStrOffset,
  2956. dwCodePage) * sizeof(WCHAR);
  2957. lpRecTo->dwTargetStrLen =
  2958. ((CalcCharacterPositionAtoW(lpRecFrom->dwTargetStrOffset +
  2959. lpRecFrom->dwTargetStrLen,
  2960. (LPSTR)lpRecFrom + lpRecFrom->dwStrOffset,
  2961. dwCodePage) * sizeof(WCHAR))
  2962. - lpRecTo->dwTargetStrOffset) / sizeof(WCHAR);
  2963. lpRecTo->dwStrLen = i; // Length is TCHAR count.
  2964. if (lpRecTo->dwSize >= (DWORD)(lpRecTo->dwStrOffset + (i + 1)* sizeof(WCHAR))) {
  2965. LPWSTR lpW = (LPWSTR)((LPSTR)lpRecTo + lpRecTo->dwStrOffset);
  2966. lpW[i] = L'\0';
  2967. }
  2968. dwSize = sizeof(RECONVERTSTRING) + ((i + 1) * sizeof(WCHAR));
  2969. }
  2970. return dwSize;
  2971. }
  2972. ///////////////////////////////////////////////////////////////////////////////////
  2973. // ImmRequestMessageWorker
  2974. //
  2975. // worker function for WM_IME_REQUEST message
  2976. //
  2977. // History:
  2978. // 30-Mar-1997 hiroyama Created
  2979. ///////////////////////////////////////////////////////////////////////////////////
  2980. LRESULT ImmRequestMessageWorker(HIMC hIMC, PWND pwnd, WPARAM wParam, LPARAM lParam, BOOL bAnsiOrigin)
  2981. {
  2982. // the (least) size of the structure given in lParam: for valid pointer checking
  2983. static CONST int nReqBufSize[][7] = {
  2984. { // sizes if IME is UNICODE
  2985. sizeof(COMPOSITIONFORM), // IMR_COMPOSITIONWINDOW
  2986. sizeof(CANDIDATEFORM), // IMR_CANDIDATEWINDOW
  2987. sizeof(LOGFONTW), // IMR_COMPOSITIONFONT
  2988. sizeof(RECONVERTSTRING), // IMR_RECONVERTSTRING
  2989. sizeof(RECONVERTSTRING), // IMR_CONFIRMRECONVERTSTRING
  2990. sizeof(IMECHARPOSITION), // IMR_QUERYCHARPOSITION
  2991. sizeof(RECONVERTSTRING), // IMR_DOCUMENTFEED
  2992. },
  2993. { // sizes if IME is ANSI
  2994. sizeof(COMPOSITIONFORM), // IMR_COMPOSITIONWINDOW
  2995. sizeof(CANDIDATEFORM), // IMR_CANDIDATEWINDOW
  2996. sizeof(LOGFONTA), // IMR_COMPOSITIONFONT
  2997. sizeof(RECONVERTSTRING), // IMR_RECONVERTSTRING
  2998. sizeof(RECONVERTSTRING), // IMR_CONFIRMRECONVERTSTRING
  2999. sizeof(IMECHARPOSITION), // IMR_QUERYCHARPOSITION
  3000. sizeof(RECONVERTSTRING), // IMR_DOCUMENTFEED
  3001. }
  3002. };
  3003. LRESULT lRet = 0L;
  3004. CONST BOOLEAN bAnsiTarget = !!TestWF(pwnd, WFANSIPROC); // TRUE if the target Window Proc is ANSI
  3005. LPBYTE lpReq = (LPBYTE)lParam; // return buffer (maybe allocated buffer)
  3006. LPBYTE lpNew = NULL; // buffer allocated within this function
  3007. DWORD dwSaveCharPos;
  3008. PCLIENTIMC pClientImc;
  3009. DWORD dwCodePage;
  3010. #define SEND_MESSAGE(bAnsi) ((bAnsi) ? SendMessageA : SendMessageW)
  3011. //////////////////////////////////////////////
  3012. // Parameter checking
  3013. // check wParam as sub messages
  3014. if (wParam == 0 || wParam > IMR_DOCUMENTFEED) { // wParam is not a proper sub message
  3015. RIPMSG1(RIP_WARNING, "ImmRequestMessageWorker: wParam(%lx) out of range.", wParam);
  3016. return 0L;
  3017. }
  3018. // Check if the pointer which is given through lParam points the proper memory block.
  3019. UserAssert(bAnsiOrigin == 0 || bAnsiOrigin == 1); // we'll use bAnsiOrigin as an index
  3020. // The first sub message IMR_COMPOSITIONWINDOW is 1, so substract 1 from wParam
  3021. if (lpReq && IsBadWritePtr(lpReq, nReqBufSize[bAnsiOrigin][wParam - 1])) {
  3022. RIPMSG0(RIP_WARNING, "ImmRequestMessageWorker: Bad pointer passed from IME to write");
  3023. return 0L;
  3024. }
  3025. // check the lpReq(==lParam): the spec does not allow lParam as NULL
  3026. // except IMR_RECONVERTSTRING and IMR_DOCUMENTFEED
  3027. if (wParam == IMR_RECONVERTSTRING || wParam == IMR_DOCUMENTFEED) {
  3028. //
  3029. // check version number
  3030. //
  3031. if (lpReq != NULL) {
  3032. LPRECONVERTSTRING lpReconv = (LPRECONVERTSTRING)lParam;
  3033. if (lpReconv->dwVersion != 0) {
  3034. RIPERR1(ERROR_INVALID_PARAMETER, RIP_WARNING, "Invalid version number: %d",
  3035. lpReconv->dwVersion);
  3036. return 0L;
  3037. }
  3038. if (lpReconv->dwSize < sizeof(RECONVERTSTRING)) {
  3039. RIPERR1(ERROR_INVALID_PARAMETER, RIP_WARNING, "Invalid dwSize: %d",
  3040. lpReconv->dwSize);
  3041. return 0L;
  3042. }
  3043. }
  3044. } else if (wParam == IMR_CONFIRMRECONVERTSTRING) {
  3045. // check if lParam is not NULL, and version of the structure is correct.
  3046. if (lpReq == NULL || ((LPRECONVERTSTRING)lpReq)->dwVersion != 0) {
  3047. RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "Invalid argument or invalid version number");
  3048. return 0L;
  3049. }
  3050. } else if (lpReq == NULL) {
  3051. RIPERR1(ERROR_INVALID_PARAMETER, RIP_WARNING,
  3052. "ImmRequestMessageWorker: lParam should not be NULL with this wParam(%lx).",
  3053. wParam);
  3054. return 0L;
  3055. }
  3056. // end parameter checking
  3057. ////////////////////////////////////////////
  3058. pClientImc = ImmLockClientImc(hIMC);
  3059. if (pClientImc != NULL) {
  3060. dwCodePage = CImcCodePage(pClientImc);
  3061. ImmUnlockClientImc(pClientImc);
  3062. }
  3063. else {
  3064. dwCodePage = CP_ACP;
  3065. }
  3066. // allocate and prepare required buffer if we need A/W conversion
  3067. switch (wParam) {
  3068. case IMR_CONFIRMRECONVERTSTRING:
  3069. case IMR_RECONVERTSTRING:
  3070. case IMR_DOCUMENTFEED:
  3071. if (bAnsiOrigin != bAnsiTarget) {
  3072. if (lpReq != NULL) {
  3073. // IME wants not only the buffer size but the real reconversion information
  3074. DWORD dwSize = ImmGetReconvertTotalSize(((LPRECONVERTSTRING)lpReq)->dwSize, FROM_IME, bAnsiTarget);
  3075. LPRECONVERTSTRING lpReconv;
  3076. lpNew = ImmLocalAlloc(0, dwSize + sizeof(WCHAR));
  3077. if (lpNew == NULL) {
  3078. RIPMSG0(RIP_WARNING, "ImmRequestMessageWorker: failed to allocate a buffer for reconversion.");
  3079. return 0L;
  3080. }
  3081. lpReconv = (LPRECONVERTSTRING)lpNew;
  3082. // setup the information in the allocated structure
  3083. lpReconv->dwVersion = 0;
  3084. lpReconv->dwSize = dwSize;
  3085. //
  3086. // if it's confirmation message, we need to translate the contents
  3087. //
  3088. if (wParam == IMR_CONFIRMRECONVERTSTRING) {
  3089. ImmReconversionWorker(lpReconv, (LPRECONVERTSTRING)lParam, bAnsiTarget, dwCodePage);
  3090. }
  3091. }
  3092. }
  3093. break;
  3094. case IMR_COMPOSITIONFONT:
  3095. UserAssert(lpReq != NULL); // has been checked so far
  3096. if (bAnsiOrigin != bAnsiTarget) {
  3097. if (bAnsiTarget) {
  3098. lpNew = ImmLocalAlloc(0, sizeof(LOGFONTA));
  3099. } else {
  3100. lpNew = ImmLocalAlloc(0, sizeof(LOGFONTW));
  3101. }
  3102. if (lpNew == NULL) {
  3103. RIPMSG0(RIP_WARNING, "ImmRequestMessageWorker: IMR_COMPOSITIONFONT: failed to allocate memory for A/W conversion.");
  3104. return 0L;
  3105. }
  3106. }
  3107. break;
  3108. case IMR_QUERYCHARPOSITION:
  3109. UserAssert(lpReq != NULL);
  3110. if (bAnsiOrigin != bAnsiTarget) {
  3111. #define lpIMEPOS ((LPIMECHARPOSITION)lParam)
  3112. LPVOID lpstr;
  3113. DWORD dwLen;
  3114. dwSaveCharPos = lpIMEPOS->dwCharPos;
  3115. dwLen = (!bAnsiOrigin ? ImmGetCompositionStringW : ImmGetCompositionStringA)(hIMC, GCS_COMPSTR, 0, 0);
  3116. if (dwLen == 0) {
  3117. RIPMSG0(RIP_WARNING, "ImmRequestMessageWorker: IMR_QUERYCHARPOSITION no compositiong string.");
  3118. return 0L;
  3119. }
  3120. lpstr = ImmLocalAlloc(0, (dwLen + 1) * (!bAnsiOrigin ? sizeof(WCHAR) : sizeof(CHAR)));
  3121. if (lpstr == NULL) {
  3122. RIPMSG0(RIP_WARNING, "ImmRequestMessageWorker: IMR_QUERYCHARPOSITION: failed to allocate memory for A/W conversion.");
  3123. return 0L;
  3124. }
  3125. (!bAnsiOrigin ? ImmGetCompositionStringW : ImmGetCompositionStringA)(hIMC, GCS_COMPSTR, lpstr, dwLen);
  3126. if (bAnsiTarget) {
  3127. lpIMEPOS->dwCharPos = CalcCharacterPositionWtoA(lpIMEPOS->dwCharPos, lpstr, dwCodePage);
  3128. } else {
  3129. lpIMEPOS->dwCharPos = CalcCharacterPositionAtoW(lpIMEPOS->dwCharPos, lpstr, dwCodePage);
  3130. }
  3131. ImmLocalFree(lpstr);
  3132. }
  3133. break;
  3134. default:
  3135. UserAssert(lpReq != NULL); // has been checked so far
  3136. break;
  3137. }
  3138. if (lpNew) {
  3139. // if we allocated the buffer, let lpReq point it; lpNew is used later to free memory
  3140. lpReq = lpNew;
  3141. }
  3142. //////////////////////////////////
  3143. lRet = SEND_MESSAGE(bAnsiTarget)(HW(pwnd), WM_IME_REQUEST, wParam, (LPARAM)lpReq);
  3144. //////////////////////////////////
  3145. // copy back the results from WinProc to IME's buffer (only if conversion is needed)
  3146. if (bAnsiOrigin != bAnsiTarget) {
  3147. switch (wParam) {
  3148. case IMR_RECONVERTSTRING:
  3149. case IMR_DOCUMENTFEED:
  3150. // Note: by definition, we don't have to do back-conversion for IMR_CONFIRMRECONVERTSTRING
  3151. if (lRet != 0) {
  3152. // IME wants the buffer size
  3153. lRet = ImmGetReconvertTotalSize((DWORD)lRet, FROM_APP, bAnsiTarget);
  3154. if (lRet < sizeof(RECONVERTSTRING)) {
  3155. RIPMSG1(RIP_WARNING, "ImmRequestMessageWorker: return value from application %d is invalid.", lRet);
  3156. lRet = 0;
  3157. } else if (lpReq) {
  3158. // We need to perform the A/W conversion of the contents
  3159. if (!ImmReconversionWorker((LPRECONVERTSTRING)lParam, (LPRECONVERTSTRING)lpReq, bAnsiOrigin, dwCodePage)) {
  3160. lRet = 0; // Error !
  3161. }
  3162. }
  3163. }
  3164. break;
  3165. case IMR_COMPOSITIONFONT:
  3166. if (bAnsiOrigin) {
  3167. LFontWtoLFontA((LPLOGFONTW)lpNew, (LPLOGFONTA)lParam);
  3168. } else {
  3169. LFontAtoLFontW((LPLOGFONTA)lpNew, (LPLOGFONTW)lParam);
  3170. }
  3171. break;
  3172. case IMR_QUERYCHARPOSITION:
  3173. UserAssert((LPVOID)lParam != NULL);
  3174. lpIMEPOS->dwCharPos = dwSaveCharPos;
  3175. #undef lpIMEPOS
  3176. break;
  3177. default:
  3178. break;
  3179. }
  3180. }
  3181. if (lpNew) {
  3182. // buffer has been allocated, free it before returning
  3183. ImmLocalFree(lpNew);
  3184. }
  3185. return lRet;
  3186. }
  3187. /**************************************************************************\
  3188. * ImmRequestMessage: Send WM_IME_REQUEST message to the given HIMC window
  3189. *
  3190. * IME function
  3191. *
  3192. * 27-Feb-1997 hiroyama Created
  3193. \**************************************************************************/
  3194. LRESULT ImmRequestMessageAorW(HIMC hIMC, WPARAM wParam, LPARAM lParam, BOOL bAnsiOrigin)
  3195. {
  3196. LPINPUTCONTEXT lpInputContext;
  3197. PWND pwnd;
  3198. LRESULT lRet = 0L;
  3199. DWORD dwThreadId = GetInputContextThread(hIMC);
  3200. if (dwThreadId != GetCurrentThreadId()) {
  3201. RIPMSG1(RIP_WARNING,
  3202. "ImmRequestMessageAorW:: Invalid input context access %lx.", hIMC);
  3203. return lRet;
  3204. }
  3205. if (hIMC == NULL || (lpInputContext = ImmLockIMC(hIMC)) == NULL) {
  3206. RIPMSG1(RIP_WARNING, "ImmRequestMessage: Invalid hImc %lx.", hIMC);
  3207. return 0L;
  3208. }
  3209. // check if the window of the input context is valid
  3210. if ((pwnd = ValidateHwnd(lpInputContext->hWnd)) == NULL) {
  3211. RIPMSG1(RIP_WARNING, "ImmRequestMessage: Invalid hWnd %lx.", lpInputContext->hWnd);
  3212. } else {
  3213. // check if the message is being sent inter thread
  3214. if (PtiCurrent() != GETPTI(pwnd)) {
  3215. RIPMSG0(RIP_WARNING, "ImmRequestMessage: IME Attempt to send IMR_ message to different thread.");
  3216. } else {
  3217. lRet = ImmRequestMessageWorker(hIMC, pwnd, wParam, lParam, bAnsiOrigin);
  3218. }
  3219. }
  3220. ImmUnlockIMC(hIMC);
  3221. return lRet;
  3222. }
  3223. LRESULT WINAPI ImmRequestMessageA(HIMC hIMC, WPARAM wParam, LPARAM lParam)
  3224. {
  3225. return ImmRequestMessageAorW(hIMC, wParam, lParam, TRUE /* ANSI */);
  3226. }
  3227. LRESULT WINAPI ImmRequestMessageW(HIMC hIMC, WPARAM wParam, LPARAM lParam)
  3228. {
  3229. return ImmRequestMessageAorW(hIMC, wParam, lParam, FALSE /* not ANSI */);
  3230. }