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.

1143 lines
30 KiB

  1. /**************************************************************************\
  2. * Module Name: misc.c
  3. *
  4. * Copyright (c) 1985 - 1999, Microsoft Corporation
  5. *
  6. *
  7. * History:
  8. * 03-Jan-1996 wkwok Created
  9. \**************************************************************************/
  10. #include "precomp.h"
  11. #pragma hdrstop
  12. #ifdef HIRO_DEBUG
  13. #define D(x) x
  14. #else
  15. #define D(x)
  16. #endif
  17. /**************************************************************************\
  18. * ImmGetDefaultIMEWnd
  19. *
  20. * 03-Jan-1996 wkwok Created
  21. \**************************************************************************/
  22. HWND WINAPI ImmGetDefaultIMEWnd(
  23. HWND hWnd)
  24. {
  25. if (!IS_IME_ENABLED()) {
  26. return NULL;
  27. }
  28. if (hWnd == NULL) {
  29. /*
  30. * Query default IME window of current thread.
  31. */
  32. return (HWND)NtUserGetThreadState(UserThreadStateDefaultImeWindow);
  33. }
  34. return (HWND)NtUserQueryWindow(hWnd, WindowDefaultImeWindow);
  35. }
  36. /**************************************************************************\
  37. * ImmDisableIME
  38. *
  39. * 13-Sep-1996 wkwok Created
  40. \**************************************************************************/
  41. BOOL WINAPI ImmDisableIME(DWORD dwThreadId)
  42. {
  43. #ifdef LATER // hiro
  44. if (dwThreadId == -1) {
  45. // Unload all IMEs
  46. RtlEnterCriticalSection(&gcsImeDpi);
  47. while (gpImeDpi) {
  48. PIMEDPI pImeDpi = gpImeDpi;
  49. gpImeDpi = gpImeDpi->pNext;
  50. UnloadIME(pImeDpi, TRUE);
  51. ImmLocalFree(pImeDpi);
  52. }
  53. RtlLeaveCriticalSection(&gcsImeDpi);
  54. }
  55. #endif
  56. return (BOOL)NtUserDisableThreadIme(dwThreadId);
  57. }
  58. /**************************************************************************\
  59. * ImmIsUIMessageA
  60. *
  61. * Filter messages needed for IME window.
  62. *
  63. * 03-Jan-1996 wkwok Created
  64. \**************************************************************************/
  65. BOOL WINAPI ImmIsUIMessageA(
  66. HWND hIMEWnd,
  67. UINT message,
  68. WPARAM wParam,
  69. LPARAM lParam)
  70. {
  71. return ImmIsUIMessageWorker(hIMEWnd, message, wParam, lParam, TRUE);
  72. }
  73. /**************************************************************************\
  74. * ImmIsUIMessageW
  75. *
  76. * Filter messages needed for IME window.
  77. *
  78. * 29-Feb-1996 wkwok Created
  79. \**************************************************************************/
  80. BOOL WINAPI ImmIsUIMessageW(
  81. HWND hIMEWnd,
  82. UINT message,
  83. WPARAM wParam,
  84. LPARAM lParam)
  85. {
  86. return ImmIsUIMessageWorker(hIMEWnd, message, wParam, lParam, FALSE);
  87. }
  88. /**************************************************************************\
  89. * ImmIsUIMessageWorker
  90. *
  91. * Worker function of ImmIsUIMessageA/ImmIsUIMessageW.
  92. *
  93. * Return: True if message is processed by IME UI.
  94. * False otherwise.
  95. *
  96. * 29-Feb-1996 wkwok Created
  97. \**************************************************************************/
  98. BOOL ImmIsUIMessageWorker(
  99. HWND hIMEWnd,
  100. UINT message,
  101. WPARAM wParam,
  102. LPARAM lParam,
  103. BOOL fAnsi)
  104. {
  105. D(DbgPrint("ImmIsUIMessageWorker(wnd[%08X], msg[%04X], wp[%08X], lp[%08X], Ansi[%d]\n",
  106. hIMEWnd, message, wParam, lParam, fAnsi));
  107. switch (message) {
  108. case WM_IME_STARTCOMPOSITION:
  109. case WM_IME_ENDCOMPOSITION:
  110. case WM_IME_COMPOSITION:
  111. case WM_IME_SETCONTEXT:
  112. case WM_IME_COMPOSITIONFULL:
  113. case WM_IME_SELECT:
  114. case WM_IME_NOTIFY:
  115. case WM_IME_SYSTEM:
  116. if (!hIMEWnd)
  117. return TRUE;
  118. #if DBG
  119. if (!IsWindow(hIMEWnd)) {
  120. RIPMSG1(RIP_WARNING,
  121. "ImmIsUIMessage: Invalid window handle %x", hIMEWnd);
  122. return FALSE;
  123. }
  124. #endif
  125. if (fAnsi) {
  126. SendMessageA(hIMEWnd, message, wParam, lParam);
  127. }
  128. else {
  129. SendMessageW(hIMEWnd, message, wParam, lParam);
  130. }
  131. return TRUE;
  132. default:
  133. break;
  134. }
  135. return FALSE;
  136. }
  137. /**************************************************************************\
  138. * ImmGenerateMessage
  139. *
  140. * Sends message(s) that are stored in hMsgBuf of hImc to hWnd of hImc.
  141. *
  142. * 29-Feb-1996 wkwok Created
  143. \**************************************************************************/
  144. BOOL WINAPI ImmGenerateMessage(
  145. HIMC hImc)
  146. {
  147. PCLIENTIMC pClientImc;
  148. PINPUTCONTEXT pInputContext;
  149. PTRANSMSG pTransMsg;
  150. INT iNum;
  151. INT i;
  152. BOOL fUnicodeImc;
  153. if (GetInputContextThread(hImc) != GetCurrentThreadId()) {
  154. RIPMSG1(RIP_WARNING,
  155. "ImmGenerateMessage: Invalid input context access %lx.", hImc);
  156. return FALSE;
  157. }
  158. pClientImc = ImmLockClientImc(hImc);
  159. if (pClientImc == NULL)
  160. return FALSE;
  161. fUnicodeImc = TestICF(pClientImc, IMCF_UNICODE);
  162. ImmUnlockClientImc(pClientImc);
  163. pInputContext = ImmLockIMC(hImc);
  164. if (!pInputContext) {
  165. RIPMSG1(RIP_WARNING, "ImmGenerateMessage: Lock hImc %lx failed.", hImc);
  166. return FALSE;
  167. }
  168. iNum = (int)pInputContext->dwNumMsgBuf;
  169. if (iNum && (pTransMsg = (PTRANSMSG)ImmLockIMCC(pInputContext->hMsgBuf))) {
  170. PTRANSMSG pTransMsgBuf, pTransMsgTemp;
  171. pTransMsgBuf = (PTRANSMSG)ImmLocalAlloc(0, iNum * sizeof(TRANSMSG));
  172. if (pTransMsgBuf != NULL) {
  173. RtlCopyMemory(pTransMsgBuf, pTransMsg, iNum * sizeof(TRANSMSG));
  174. if (GetClientInfo()->dwExpWinVer < VER40) {
  175. /*
  176. * translate messages for those applications that expect
  177. * old style IME messages.
  178. */
  179. DWORD dwLangId;
  180. dwLangId = PRIMARYLANGID(LANGIDFROMLCID(GetSystemDefaultLCID()));
  181. if ( (dwLangId == LANG_KOREAN && TransGetLevel(pInputContext->hWnd) == 3) ||
  182. (dwLangId == LANG_JAPANESE) ) {
  183. iNum = WINNLSTranslateMessage(iNum,
  184. pTransMsgBuf,
  185. hImc,
  186. !fUnicodeImc,
  187. dwLangId );
  188. }
  189. }
  190. pTransMsgTemp = pTransMsgBuf;
  191. for (i = 0; i < iNum; i++) {
  192. if (fUnicodeImc) {
  193. SendMessageW( pInputContext->hWnd,
  194. pTransMsgTemp->message,
  195. pTransMsgTemp->wParam,
  196. pTransMsgTemp->lParam );
  197. } else {
  198. SendMessageW( pInputContext->hWnd,
  199. pTransMsgTemp->message,
  200. pTransMsgTemp->wParam,
  201. pTransMsgTemp->lParam );
  202. }
  203. pTransMsgTemp++;
  204. }
  205. ImmLocalFree(pTransMsgBuf);
  206. }
  207. ImmUnlockIMCC(pInputContext->hMsgBuf);
  208. }
  209. /*
  210. * We should not reallocate the message buffer
  211. */
  212. pInputContext->dwNumMsgBuf = 0L;
  213. ImmUnlockIMC(hImc);
  214. return TRUE;
  215. }
  216. #ifdef CUAS_ENABLE
  217. BOOL WINAPI CtfImmGenerateMessage(
  218. HIMC hImc,
  219. BOOL fSendMsg)
  220. {
  221. PCLIENTIMC pClientImc;
  222. PINPUTCONTEXT pInputContext;
  223. PTRANSMSG pTransMsg;
  224. INT iNum;
  225. INT i;
  226. BOOL fUnicodeImc;
  227. if (GetInputContextThread(hImc) != GetCurrentThreadId()) {
  228. RIPMSG1(RIP_WARNING,
  229. "ImmGenerateMessage: Invalid input context access %lx.", hImc);
  230. return FALSE;
  231. }
  232. pClientImc = ImmLockClientImc(hImc);
  233. if (pClientImc == NULL)
  234. return FALSE;
  235. fUnicodeImc = TestICF(pClientImc, IMCF_UNICODE);
  236. ImmUnlockClientImc(pClientImc);
  237. pInputContext = ImmLockIMC(hImc);
  238. if (!pInputContext) {
  239. RIPMSG1(RIP_WARNING, "ImmGenerateMessage: Lock hImc %lx failed.", hImc);
  240. return FALSE;
  241. }
  242. iNum = (int)pInputContext->dwNumMsgBuf;
  243. if (iNum && (pTransMsg = (PTRANSMSG)ImmLockIMCC(pInputContext->hMsgBuf))) {
  244. PTRANSMSG pTransMsgBuf, pTransMsgTemp;
  245. pTransMsgBuf = (PTRANSMSG)ImmLocalAlloc(0, iNum * sizeof(TRANSMSG));
  246. if (pTransMsgBuf != NULL) {
  247. RtlCopyMemory(pTransMsgBuf, pTransMsg, iNum * sizeof(TRANSMSG));
  248. pTransMsgTemp = pTransMsgBuf;
  249. for (i = 0; i < iNum; i++) {
  250. if (fSendMsg)
  251. {
  252. if (fUnicodeImc) {
  253. SendMessageW( pInputContext->hWnd,
  254. pTransMsgTemp->message,
  255. pTransMsgTemp->wParam,
  256. pTransMsgTemp->lParam );
  257. } else {
  258. SendMessageA( pInputContext->hWnd,
  259. pTransMsgTemp->message,
  260. pTransMsgTemp->wParam,
  261. pTransMsgTemp->lParam );
  262. }
  263. }
  264. else
  265. {
  266. if (fUnicodeImc) {
  267. PostMessageW( pInputContext->hWnd,
  268. pTransMsgTemp->message,
  269. pTransMsgTemp->wParam,
  270. pTransMsgTemp->lParam );
  271. } else {
  272. PostMessageA( pInputContext->hWnd,
  273. pTransMsgTemp->message,
  274. pTransMsgTemp->wParam,
  275. pTransMsgTemp->lParam );
  276. }
  277. }
  278. pTransMsgTemp++;
  279. }
  280. ImmLocalFree(pTransMsgBuf);
  281. }
  282. ImmUnlockIMCC(pInputContext->hMsgBuf);
  283. }
  284. /*
  285. * We should not reallocate the message buffer
  286. */
  287. pInputContext->dwNumMsgBuf = 0L;
  288. ImmUnlockIMC(hImc);
  289. return TRUE;
  290. }
  291. #endif // CUAS_ENABLE
  292. /**************************************************************************\
  293. * ImmGetVirtualKey
  294. *
  295. * Gets the actual virtual key which is preprocessed by an IME.
  296. *
  297. * 03-Jan-1996 wkwok Created
  298. \**************************************************************************/
  299. UINT WINAPI ImmGetVirtualKey(
  300. HWND hWnd)
  301. {
  302. HIMC hImc;
  303. PINPUTCONTEXT pInputContext;
  304. UINT uVirtKey;
  305. hImc = ImmGetContext(hWnd);
  306. pInputContext = ImmLockIMC(hImc);
  307. if (!pInputContext) {
  308. RIPMSG1(RIP_WARNING, "ImmGetVirtualKey: lock IMC %x failure", hImc);
  309. return (VK_PROCESSKEY);
  310. }
  311. if (pInputContext->fChgMsg) {
  312. uVirtKey = pInputContext->uSavedVKey;
  313. } else {
  314. uVirtKey = VK_PROCESSKEY;
  315. }
  316. ImmUnlockIMC(hImc);
  317. return (uVirtKey);
  318. }
  319. /**************************************************************************\
  320. * ImmLockIMC
  321. *
  322. * 03-Jan-1996 wkwok Created
  323. \**************************************************************************/
  324. PINPUTCONTEXT WINAPI InternalImmLockIMC(
  325. HIMC hImc,
  326. BOOL fCanCallImeSelect)
  327. {
  328. PCLIENTIMC pClientImc;
  329. PINPUTCONTEXT pInputContext;
  330. DWORD dwImcThreadId;
  331. if ((pClientImc = ImmLockClientImc(hImc)) == NULL)
  332. return NULL;
  333. EnterImcCrit(pClientImc);
  334. if (pClientImc->hInputContext == NULL) {
  335. #ifdef CUAS_ENABLE
  336. dwImcThreadId = (DWORD)NtUserQueryInputContext(hImc, InputContextThread);
  337. #endif // CUAS_ENABLE
  338. #ifdef CUAS_ENABLE
  339. if (dwImcThreadId == GetCurrentThreadId() &&
  340. IS_CICERO_ENABLED_AND_NOT16BIT()) {
  341. /*
  342. * Cicero IME. Activate Thread Input Manager.
  343. */
  344. PIMEDPI pImeDpi;
  345. LANGID lg = LOWORD(HandleToUlong(GetKeyboardLayout(0)));
  346. DWORD dwKL = MAKELONG(lg, lg);
  347. pImeDpi = FindOrLoadImeDpi(UlongToHandle(dwKL));
  348. if (pImeDpi == NULL) {
  349. RIPMSG0(RIP_WARNING, "InternalImmLockIMC: no pImeDpi entry.");
  350. }
  351. else
  352. {
  353. /*
  354. * Activate TIM
  355. * For this call, CTFIME's tim->Activate retreive TfClientId value
  356. * when user32!LoadThreadLayout calls ImmTIMActivate with non-IME hKL.
  357. * Because tim->Activate calls keyboard layout change and it occurred
  358. * InternalImmLockIMC via IMS_ACTIVATETHREADLAYOUT.
  359. * Also this hIMC is used at first time.
  360. * In this case, this code block calls ImmTIMCreateInputContext and
  361. * create IC by dim->CreateContext(TfClientId).
  362. * If this code is disabled, TfClientId is not yet ready and
  363. * doesn't create IC.
  364. */
  365. CtfImmTIMActivate(UlongToHandle(dwKL));
  366. }
  367. }
  368. #endif // CUAS_ENABLE
  369. /*
  370. * If the owner thread of this hImc does not have
  371. * default IME window, don't bother to create the
  372. * INPUTCONTEXT. It could happen when some other
  373. * thread which call ImmGetContext() to retrieve
  374. * the associate hImc before the default IME window
  375. * is created.
  376. */
  377. if ((HWND)NtUserQueryInputContext(hImc,
  378. InputContextDefaultImeWindow) == NULL) {
  379. LeaveImcCrit(pClientImc);
  380. ImmUnlockClientImc(pClientImc);
  381. return NULL;
  382. }
  383. /*
  384. * This is a delay creation of INPUTCONTEXT structure. Create
  385. * it now for this hImc.
  386. */
  387. pClientImc->hInputContext = LocalAlloc(LHND, sizeof(INPUTCONTEXT));
  388. if (pClientImc->hInputContext == NULL) {
  389. LeaveImcCrit(pClientImc);
  390. ImmUnlockClientImc(pClientImc);
  391. return NULL;
  392. }
  393. #ifndef CUAS_ENABLE
  394. dwImcThreadId = (DWORD)NtUserQueryInputContext(hImc, InputContextThread);
  395. #endif // CUAS_ENABLE
  396. if (!CreateInputContext(hImc, GetKeyboardLayout(dwImcThreadId), fCanCallImeSelect)) {
  397. RIPMSG0(RIP_WARNING, "ImmLockIMC: CreateInputContext failed");
  398. LocalFree(pClientImc->hInputContext);
  399. pClientImc->hInputContext = NULL;
  400. LeaveImcCrit(pClientImc);
  401. ImmUnlockClientImc(pClientImc);
  402. return NULL;
  403. }
  404. }
  405. #ifdef CUAS_ENABLE
  406. /*
  407. * Create Cicero Input Context.
  408. */
  409. CtfImmTIMCreateInputContext(hImc);
  410. #endif // CUAS_ENABLE
  411. LeaveImcCrit(pClientImc);
  412. pInputContext = (PINPUTCONTEXT)LocalLock(pClientImc->hInputContext);
  413. /*
  414. * Increment lock count so that the ImmUnlockClientImc() won't
  415. * free up the pClientImc->hInputContext.
  416. */
  417. InterlockedIncrement(&pClientImc->cLockObj);
  418. ImmUnlockClientImc(pClientImc);
  419. return pInputContext;
  420. }
  421. PINPUTCONTEXT WINAPI ImmLockIMC(
  422. HIMC hImc)
  423. {
  424. return InternalImmLockIMC(hImc, TRUE);
  425. }
  426. /**************************************************************************\
  427. * ImmUnlockIMC
  428. *
  429. * 03-Jan-1996 wkwok Created
  430. \**************************************************************************/
  431. BOOL WINAPI ImmUnlockIMC(
  432. HIMC hImc)
  433. {
  434. PCLIENTIMC pClientImc;
  435. if ((pClientImc = ImmLockClientImc(hImc)) == NULL)
  436. return FALSE;
  437. if (pClientImc->hInputContext != NULL)
  438. LocalUnlock(pClientImc->hInputContext);
  439. /*
  440. * Decrement lock count so that the ImmUnlockClientImc() can
  441. * free up the pClientImc->hInputContext if required.
  442. */
  443. InterlockedDecrement(&pClientImc->cLockObj);
  444. ImmUnlockClientImc(pClientImc);
  445. return TRUE;
  446. }
  447. /**************************************************************************\
  448. * ImmGetIMCLockCount
  449. *
  450. * 03-Jan-1996 wkwok Created
  451. \**************************************************************************/
  452. DWORD WINAPI ImmGetIMCLockCount(
  453. HIMC hImc)
  454. {
  455. PCLIENTIMC pClientImc;
  456. DWORD dwRet = 0;
  457. if ((pClientImc = ImmLockClientImc(hImc)) == NULL)
  458. return dwRet;
  459. if (pClientImc->hInputContext != NULL)
  460. dwRet = (DWORD)(LocalFlags(pClientImc->hInputContext) & LMEM_LOCKCOUNT);
  461. ImmUnlockClientImc(pClientImc);
  462. return dwRet;
  463. }
  464. /**************************************************************************\
  465. * ImmCreateIMCC
  466. *
  467. * 03-Jan-1996 wkwok Created
  468. \**************************************************************************/
  469. HIMCC WINAPI ImmCreateIMCC(
  470. DWORD dwSize)
  471. {
  472. // At least size should be DWORD.
  473. if (dwSize < sizeof(DWORD)) {
  474. dwSize = sizeof(DWORD);
  475. }
  476. return (HIMCC)LocalAlloc(LHND, dwSize);
  477. }
  478. /**************************************************************************\
  479. * ImmDestroyIMCC
  480. *
  481. * 03-Jan-1996 wkwok Created
  482. \**************************************************************************/
  483. HIMCC WINAPI ImmDestroyIMCC(
  484. HIMCC hIMCC)
  485. {
  486. if (hIMCC == NULL) {
  487. return NULL;
  488. }
  489. return (HIMCC)LocalFree(hIMCC);
  490. }
  491. /**************************************************************************\
  492. * ImmLockIMCC
  493. *
  494. * 03-Jan-1996 wkwok Created
  495. \**************************************************************************/
  496. LPVOID WINAPI ImmLockIMCC(
  497. HIMCC hIMCC)
  498. {
  499. if (hIMCC == NULL) {
  500. return NULL;
  501. }
  502. return LocalLock(hIMCC);
  503. }
  504. /**************************************************************************\
  505. * ImmUnlockIMCC
  506. *
  507. * 03-Jan-1996 wkwok Created
  508. \**************************************************************************/
  509. BOOL WINAPI ImmUnlockIMCC(
  510. HIMCC hIMCC)
  511. {
  512. if (hIMCC == NULL) {
  513. return FALSE;
  514. }
  515. return LocalUnlock(hIMCC);
  516. }
  517. /**************************************************************************\
  518. * ImmGetIMCCLockCount
  519. *
  520. * 03-Jan-1996 wkwok Created
  521. \**************************************************************************/
  522. DWORD WINAPI ImmGetIMCCLockCount(
  523. HIMCC hIMCC)
  524. {
  525. if (hIMCC == NULL) {
  526. return 0;
  527. }
  528. return (DWORD)(LocalFlags(hIMCC) & LMEM_LOCKCOUNT);
  529. }
  530. /**************************************************************************\
  531. * ImmReSizeIMCC
  532. *
  533. * 03-Jan-1996 wkwok Created
  534. \**************************************************************************/
  535. HIMCC WINAPI ImmReSizeIMCC(
  536. HIMCC hIMCC,
  537. DWORD dwSize)
  538. {
  539. if (hIMCC == NULL) {
  540. return NULL;
  541. }
  542. return (HIMCC)LocalReAlloc(hIMCC, dwSize, LHND);
  543. }
  544. /**************************************************************************\
  545. * ImmGetIMCCSize
  546. *
  547. * 03-Jan-1996 wkwok Created
  548. \**************************************************************************/
  549. DWORD WINAPI ImmGetIMCCSize(
  550. HIMCC hIMCC)
  551. {
  552. if (hIMCC == NULL) {
  553. return 0;
  554. }
  555. return (DWORD)LocalSize(hIMCC);
  556. }
  557. /**************************************************************************\
  558. * ImmLocalAlloc
  559. *
  560. * 18-Jun-1996 wkwok Created
  561. \**************************************************************************/
  562. LPVOID ImmLocalAlloc(
  563. DWORD uFlag,
  564. DWORD uBytes)
  565. {
  566. if (pImmHeap == NULL) {
  567. pImmHeap = RtlProcessHeap();
  568. if (pImmHeap == NULL) {
  569. RIPMSG0(RIP_WARNING, "ImmLocalAlloc: NULL pImmHeap!");
  570. return NULL;
  571. }
  572. }
  573. return HeapAlloc(pImmHeap, uFlag, uBytes);
  574. }
  575. /***************************************************************************\
  576. * PtiCurrent
  577. *
  578. * Returns the THREADINFO structure for the current thread.
  579. * LATER: Get DLL_THREAD_ATTACH initialization working right and we won't
  580. * need this connect code.
  581. *
  582. * History:
  583. * 10-28-90 DavidPe Created.
  584. * 02-21-96 wkwok Copied from USER32.DLL
  585. \***************************************************************************/
  586. PTHREADINFO PtiCurrent(VOID)
  587. {
  588. ConnectIfNecessary(0);
  589. return (PTHREADINFO)NtCurrentTebShared()->Win32ThreadInfo;
  590. }
  591. /**************************************************************************\
  592. * TestInputContextProcess
  593. *
  594. * 02-21-96 wkwok Created
  595. \**************************************************************************/
  596. BOOL TestInputContextProcess(
  597. PIMC pImc)
  598. {
  599. /*
  600. * If the threads are the same, don't bother going to the kernel
  601. * to get the input context's process id.
  602. */
  603. if (GETPTI(pImc) == PtiCurrent()) {
  604. return TRUE;
  605. }
  606. return (GetInputContextProcess(PtoH(pImc)) == GETPROCESSID());
  607. }
  608. /**************************************************************************\
  609. * TestWindowProcess
  610. *
  611. * 11-14-94 JimA Created.
  612. * 02-29-96 wkwok Copied from USER32.DLL
  613. \**************************************************************************/
  614. BOOL TestWindowProcess(
  615. PWND pwnd)
  616. {
  617. /*
  618. * If the threads are the same, don't bother going to the kernel
  619. * to get the window's process id.
  620. */
  621. if (GETPTI(pwnd) == PtiCurrent()) {
  622. return TRUE;
  623. }
  624. return (GetWindowProcess(HW(pwnd)) == GETPROCESSID());
  625. }
  626. /**************************************************************************\
  627. * GetKeyboardLayoutCP
  628. *
  629. * 12-Mar-1996 wkwok Created
  630. \**************************************************************************/
  631. static LCID CachedLCID = 0;
  632. static UINT CachedCP = CP_ACP;
  633. UINT GetKeyboardLayoutCP(
  634. HKL hKL)
  635. {
  636. #define LOCALE_CPDATA 7
  637. WCHAR wszCodePage[LOCALE_CPDATA];
  638. LCID lcid;
  639. lcid = MAKELCID(LOWORD(HandleToUlong(hKL)), SORT_DEFAULT);
  640. if (lcid == CachedLCID)
  641. return CachedCP;
  642. if (!GetLocaleInfoW(lcid, LOCALE_IDEFAULTANSICODEPAGE,
  643. wszCodePage, LOCALE_CPDATA))
  644. return CP_ACP;
  645. CachedLCID = lcid;
  646. CachedCP = (UINT)wcstol(wszCodePage, NULL, 10);
  647. return CachedCP;
  648. }
  649. /**************************************************************************\
  650. * GetKeyboardLayoutCP
  651. *
  652. * 12-Mar-1996 wkwok Created
  653. \**************************************************************************/
  654. UINT GetThreadKeyboardLayoutCP(
  655. DWORD dwThreadId)
  656. {
  657. HKL hKL;
  658. hKL = GetKeyboardLayout(dwThreadId);
  659. return GetKeyboardLayoutCP(hKL);
  660. }
  661. /**************************************************************************\
  662. * ImmLockClientImc
  663. *
  664. * 13-Mar-1996 wkwok Created
  665. \**************************************************************************/
  666. PCLIENTIMC WINAPI ImmLockClientImc(
  667. HIMC hImc)
  668. {
  669. PIMC pImc;
  670. PCLIENTIMC pClientImc;
  671. if (hImc == NULL_HIMC)
  672. return NULL;
  673. pImc = HMValidateHandle((HANDLE)hImc, TYPE_INPUTCONTEXT);
  674. /*
  675. * Cannot access input context from other process.
  676. */
  677. if (pImc == NULL || !TestInputContextProcess(pImc))
  678. return NULL;
  679. pClientImc = (PCLIENTIMC)pImc->dwClientImcData;
  680. if (pClientImc == NULL) {
  681. /*
  682. * We delay the creation of client side per-thread default Imc.
  683. * Now, this is the time to create it.
  684. */
  685. pClientImc = ImmLocalAlloc(HEAP_ZERO_MEMORY, sizeof(CLIENTIMC));
  686. if (pClientImc == NULL)
  687. return NULL;
  688. InitImcCrit(pClientImc);
  689. pClientImc->dwImeCompatFlags = (DWORD)NtUserGetThreadState(UserThreadStateImeCompatFlags);
  690. /*
  691. * Update the kernel side input context.
  692. */
  693. if (!NtUserUpdateInputContext(hImc,
  694. UpdateClientInputContext, (ULONG_PTR)pClientImc)) {
  695. ImmLocalFree(pClientImc);
  696. return NULL;
  697. }
  698. /*
  699. * Marks with default input context signature.
  700. */
  701. SetICF(pClientImc, IMCF_DEFAULTIMC);
  702. }
  703. else if (TestICF(pClientImc, IMCF_INDESTROY)) {
  704. /*
  705. * Cannot access destroyed input context.
  706. */
  707. return NULL;
  708. }
  709. InterlockedIncrement(&pClientImc->cLockObj);
  710. return pClientImc;
  711. }
  712. VOID WINAPI ImmUnlockClientImc(
  713. PCLIENTIMC pClientImc)
  714. {
  715. if (InterlockedDecrement(&pClientImc->cLockObj) == 0) {
  716. if (TestICF(pClientImc, IMCF_INDESTROY)) {
  717. if (pClientImc->hInputContext != NULL)
  718. LocalFree(pClientImc->hInputContext);
  719. DeleteImcCrit(pClientImc);
  720. ImmLocalFree(pClientImc);
  721. }
  722. }
  723. return;
  724. }
  725. /**************************************************************************\
  726. * ImmGetImeDpi
  727. *
  728. * 08-Jan-1996 wkwok Created
  729. \**************************************************************************/
  730. PIMEDPI WINAPI ImmGetImeDpi(
  731. HKL hKL)
  732. {
  733. PIMEDPI pImeDpi;
  734. RtlEnterCriticalSection(&gcsImeDpi);
  735. pImeDpi = gpImeDpi;
  736. while (pImeDpi != NULL && pImeDpi->hKL != hKL)
  737. pImeDpi = pImeDpi->pNext;
  738. RtlLeaveCriticalSection(&gcsImeDpi);
  739. return (PIMEDPI)pImeDpi;
  740. }
  741. /**************************************************************************\
  742. * ImmLockImeDpi
  743. *
  744. * 08-Jan-1996 wkwok Created
  745. \**************************************************************************/
  746. PIMEDPI WINAPI ImmLockImeDpi(
  747. HKL hKL)
  748. {
  749. PIMEDPI pImeDpi;
  750. RtlEnterCriticalSection(&gcsImeDpi);
  751. pImeDpi = gpImeDpi;
  752. while (pImeDpi != NULL && pImeDpi->hKL != hKL)
  753. pImeDpi = pImeDpi->pNext;
  754. if (pImeDpi != NULL) {
  755. if (pImeDpi->dwFlag & IMEDPI_UNLOADED)
  756. pImeDpi = NULL;
  757. else
  758. pImeDpi->cLock++;
  759. }
  760. RtlLeaveCriticalSection(&gcsImeDpi);
  761. return (PIMEDPI)pImeDpi;
  762. }
  763. /**************************************************************************\
  764. * ImmUnlockImeDpi
  765. *
  766. * 03-Jan-1996 wkwok Created
  767. \**************************************************************************/
  768. VOID WINAPI ImmUnlockImeDpi(
  769. PIMEDPI pImeDpi)
  770. {
  771. PIMEDPI pImeDpiT;
  772. if (pImeDpi == NULL)
  773. return;
  774. RtlEnterCriticalSection(&gcsImeDpi);
  775. if (--pImeDpi->cLock == 0) {
  776. if ((pImeDpi->dwFlag & IMEDPI_UNLOADED) ||
  777. ((pImeDpi->dwFlag & IMEDPI_UNLOCKUNLOAD) &&
  778. (pImeDpi->ImeInfo.fdwProperty & IME_PROP_END_UNLOAD)))
  779. {
  780. /*
  781. * Unlink it.
  782. */
  783. if (gpImeDpi == pImeDpi) {
  784. gpImeDpi = pImeDpi->pNext;
  785. }
  786. else {
  787. pImeDpiT = gpImeDpi;
  788. while (pImeDpiT != NULL && pImeDpiT->pNext != pImeDpi)
  789. pImeDpiT = pImeDpiT->pNext;
  790. if (pImeDpiT != NULL)
  791. pImeDpiT->pNext = pImeDpi->pNext;
  792. }
  793. /*
  794. * Unload the IME DLL.
  795. */
  796. UnloadIME(pImeDpi, TRUE);
  797. ImmLocalFree(pImeDpi);
  798. }
  799. }
  800. RtlLeaveCriticalSection(&gcsImeDpi);
  801. return;
  802. }
  803. /**************************************************************************\
  804. * ImmGetImeInfoEx
  805. *
  806. * 03-Jan-1996 wkwok Created
  807. \**************************************************************************/
  808. BOOL WINAPI ImmGetImeInfoEx(
  809. PIMEINFOEX piiex,
  810. IMEINFOEXCLASS SearchType,
  811. PVOID pvSearchKey)
  812. {
  813. #if defined(CUAS_ENABLE)
  814. BOOL fCUAS_OFF = FALSE;
  815. #endif
  816. ImmAssert(piiex != NULL && pvSearchKey != NULL);
  817. switch (SearchType) {
  818. #if defined(CUAS_ENABLE)
  819. case ImeInfoExKeyboardLayoutWithCUAS:
  820. fCUAS_OFF = CtfImmIsTextFrameServiceDisabled();
  821. SearchType = ImeInfoExKeyboardLayout;
  822. #endif
  823. case ImeInfoExKeyboardLayout:
  824. piiex->hkl = *((HKL *)pvSearchKey);
  825. /*
  826. * Quick return for non-IME based keyboard layout
  827. */
  828. #if !defined(CUAS_ENABLE)
  829. if (!IS_IME_KBDLAYOUT(piiex->hkl))
  830. return FALSE;
  831. #else
  832. if (! IS_IME_KBDLAYOUT(piiex->hkl) &&
  833. (! IS_CICERO_ENABLED_AND_NOT16BIT() || fCUAS_OFF))
  834. return FALSE;
  835. #endif
  836. break;
  837. case ImeInfoExImeFileName:
  838. wcsncpy(piiex->wszImeFile, (PWSTR)pvSearchKey, IM_FILE_SIZE-1);
  839. piiex->wszImeFile[IM_FILE_SIZE - 1] = L'\0';
  840. break;
  841. default:
  842. return FALSE;
  843. }
  844. return NtUserGetImeInfoEx(piiex, SearchType);
  845. }
  846. /**************************************************************************\
  847. * ImmGetAppCompatFlags
  848. *
  849. * private function
  850. * returns Win95 compatible IME Compatibility flags
  851. *
  852. * 02-July-1996 takaok Created
  853. \**************************************************************************/
  854. DWORD ImmGetAppCompatFlags( HIMC hImc )
  855. {
  856. PCLIENTIMC pClientImc;
  857. DWORD dwImeCompat = 0;
  858. pClientImc = ImmLockClientImc( hImc );
  859. if ( pClientImc != NULL ) {
  860. dwImeCompat = pClientImc->dwImeCompatFlags;
  861. ImmUnlockClientImc( pClientImc );
  862. }
  863. #ifdef CUAS_ENABLE
  864. dwImeCompat |= g_aimm_compat_flags;
  865. #endif // CUAS_ENABLE
  866. return dwImeCompat;
  867. }
  868. /**************************************************************************\
  869. * ImmPtInRect
  870. *
  871. * private function
  872. *
  873. * 02-July-1997 hiroyama Created
  874. \**************************************************************************/
  875. BOOL ImmPtInRect(
  876. int left,
  877. int top,
  878. int width,
  879. int height,
  880. LPPOINT lppt)
  881. {
  882. return (lppt->x >= left && lppt->x < (left + width) &&
  883. lppt->y >= top && lppt->y < (top + height));
  884. }
  885. /**************************************************************************\
  886. * ImmSystemHandler
  887. *
  888. * private function
  889. *
  890. * IMM bulk helper to handle WM_IME_SYSTEM message
  891. *
  892. * 02-July-1997 hiroyama Created
  893. \**************************************************************************/
  894. LRESULT ImmSystemHandler(
  895. HIMC hImc,
  896. WPARAM wParam,
  897. LPARAM lParam)
  898. {
  899. LRESULT lRet = 0;
  900. switch (wParam) {
  901. case IMS_SENDNOTIFICATION:
  902. ImmSendNotification((BOOL)lParam);
  903. break;
  904. case IMS_FINALIZE_COMPSTR:
  905. ImmNotifyIME(hImc, NI_COMPOSITIONSTR, CPS_COMPLETE, 0);
  906. break;
  907. #ifdef CUAS_ENABLE
  908. case IMS_SETLANGBAND:
  909. case IMS_RESETLANGBAND:
  910. lRet = CtfImmSetLangBand((HWND)lParam, wParam == IMS_SETLANGBAND ? TRUE : FALSE);
  911. break;
  912. #endif // CUAS_ENABLE
  913. }
  914. return lRet;
  915. }