2 * PROJECT: ReactOS IMM32
3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4 * PURPOSE: Implementing Far-Eastern languages input
5 * COPYRIGHT: Copyright 1998 Patrik Stridvall
6 * Copyright 2002, 2003, 2007 CodeWeavers, Aric Stewart
7 * Copyright 2017 James Tabor <james.tabor@reactos.org>
8 * Copyright 2018 Amine Khaldi <amine.khaldi@reactos.org>
9 * Copyright 2020-2022 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
14 WINE_DEFAULT_DEBUG_CHANNEL(imm
);
16 HMODULE ghImm32Inst
= NULL
; // Win: ghInst
17 PSERVERINFO gpsi
= NULL
; // Win: gpsi
18 SHAREDINFO gSharedInfo
= { NULL
}; // Win: gSharedInfo
19 BYTE gfImmInitialized
= FALSE
; // Win: gfInitialized
21 // Win: ImmInitializeGlobals
22 static BOOL APIENTRY
ImmInitializeGlobals(HMODULE hMod
)
32 status
= RtlInitializeCriticalSection(&gcsImeDpi
);
36 gfImmInitialized
= TRUE
;
40 /***********************************************************************
41 * ImmRegisterClient(IMM32.@)
42 * ( Undocumented, called from user32.dll )
44 BOOL WINAPI
ImmRegisterClient(PSHAREDINFO ptr
, HINSTANCE hMod
)
47 gpsi
= gSharedInfo
.psi
;
48 return ImmInitializeGlobals(hMod
);
51 /***********************************************************************
52 * ImmLoadLayout (IMM32.@)
54 BOOL WINAPI
ImmLoadLayout(HKL hKL
, PIMEINFOEX pImeInfoEx
)
57 HKEY hLayoutKey
= NULL
, hLayoutsKey
= NULL
;
59 WCHAR szLayout
[MAX_PATH
];
61 TRACE("(%p, %p)\n", hKL
, pImeInfoEx
);
63 if (IS_IME_HKL(hKL
) || !Imm32IsCiceroMode() || Imm32Is16BitMode())
65 Imm32UIntToStr((DWORD
)(DWORD_PTR
)hKL
, 16, szLayout
, _countof(szLayout
));
67 error
= RegOpenKeyW(HKEY_LOCAL_MACHINE
, REGKEY_KEYBOARD_LAYOUTS
, &hLayoutsKey
);
70 ERR("RegOpenKeyW: 0x%08lX\n", error
);
74 error
= RegOpenKeyW(hLayoutsKey
, szLayout
, &hLayoutKey
);
77 ERR("RegOpenKeyW: 0x%08lX\n", error
);
78 RegCloseKey(hLayoutsKey
);
84 error
= RegOpenKeyW(HKEY_LOCAL_MACHINE
, REGKEY_IMM
, &hLayoutKey
);
87 ERR("RegOpenKeyW: 0x%08lX\n", error
);
92 cbData
= sizeof(pImeInfoEx
->wszImeFile
);
93 error
= RegQueryValueExW(hLayoutKey
, L
"Ime File", 0, 0,
94 (LPBYTE
)pImeInfoEx
->wszImeFile
, &cbData
);
95 pImeInfoEx
->wszImeFile
[_countof(pImeInfoEx
->wszImeFile
) - 1] = 0;
97 RegCloseKey(hLayoutKey
);
99 RegCloseKey(hLayoutsKey
);
101 pImeInfoEx
->fLoadFlag
= 0;
105 ERR("RegQueryValueExW: 0x%08lX\n", error
);
106 pImeInfoEx
->hkl
= NULL
;
110 pImeInfoEx
->hkl
= hKL
;
111 return Imm32LoadImeVerInfo(pImeInfoEx
);
114 /***********************************************************************
115 * ImmFreeLayout (IMM32.@)
117 BOOL WINAPI
ImmFreeLayout(DWORD dwUnknown
)
121 HKL hOldKL
, hNewKL
, *pList
;
125 TRACE("(0x%lX)\n", dwUnknown
);
127 hOldKL
= GetKeyboardLayout(0);
131 if (!IS_IME_HKL(hOldKL
))
134 LangID
= LANGIDFROMLCID(GetSystemDefaultLCID());
136 cKLs
= GetKeyboardLayoutList(0, NULL
);
139 pList
= ImmLocalAlloc(0, cKLs
* sizeof(HKL
));
143 cKLs
= GetKeyboardLayoutList(cKLs
, pList
);
144 for (iKL
= 0; iKL
< cKLs
; ++iKL
)
146 if (!IS_IME_HKL(pList
[iKL
]))
148 LangID
= LOWORD(pList
[iKL
]);
156 StringCchPrintfW(szKBD
, _countof(szKBD
), L
"%08X", LangID
);
157 if (!LoadKeyboardLayoutW(szKBD
, KLF_ACTIVATE
))
158 LoadKeyboardLayoutW(L
"00000409", KLF_ACTIVATE
| 0x200);
160 else if (dwUnknown
== 2)
162 RtlEnterCriticalSection(&gcsImeDpi
);
164 for (pImeDpi
= gpImeDpiList
; pImeDpi
; pImeDpi
= pImeDpi
->pNext
)
166 if (Imm32ReleaseIME(pImeDpi
->hKL
))
169 RtlLeaveCriticalSection(&gcsImeDpi
);
173 hNewKL
= (HKL
)(DWORD_PTR
)dwUnknown
;
174 if (IS_IME_HKL(hNewKL
) && hNewKL
!= hOldKL
)
175 Imm32ReleaseIME(hNewKL
);
181 // Win: SelectInputContext
182 VOID APIENTRY
Imm32SelectInputContext(HKL hNewKL
, HKL hOldKL
, HIMC hIMC
)
184 PCLIENTIMC pClientImc
;
185 LPINPUTCONTEXTDX pIC
;
188 LPCOMPOSITIONSTRING pCS
;
191 BOOL fOpen
, bIsNewHKLIme
= TRUE
, bIsOldHKLIme
= TRUE
, bClientWide
, bNewDpiWide
;
192 DWORD cbNewPrivate
= 0, cbOldPrivate
= 0, dwConversion
, dwSentence
, dwSize
, dwNewSize
;
193 PIMEDPI pNewImeDpi
= NULL
, pOldImeDpi
= NULL
;
195 PIME_STATE pNewState
= NULL
, pOldState
= NULL
;
197 pClientImc
= ImmLockClientImc(hIMC
);
201 pNewImeDpi
= ImmLockImeDpi(hNewKL
);
203 if (hNewKL
!= hOldKL
)
204 pOldImeDpi
= ImmLockImeDpi(hOldKL
);
208 cbNewPrivate
= pNewImeDpi
->ImeInfo
.dwPrivateDataSize
;
209 pClientImc
->uCodePage
= pNewImeDpi
->uCodePage
;
213 pClientImc
->uCodePage
= CP_ACP
;
216 if (cbNewPrivate
< sizeof(DWORD
))
217 cbNewPrivate
= sizeof(DWORD
);
220 cbOldPrivate
= pOldImeDpi
->ImeInfo
.dwPrivateDataSize
;
222 if (cbOldPrivate
< sizeof(DWORD
))
223 cbOldPrivate
= sizeof(DWORD
);
225 if (pClientImc
->hKL
== hOldKL
)
229 if (IS_IME_HKL(hOldKL
))
230 pOldImeDpi
->ImeSelect(hIMC
, FALSE
);
231 else if (Imm32IsCiceroMode() && !Imm32Is16BitMode() && pOldImeDpi
->CtfImeSelectEx
)
232 pOldImeDpi
->CtfImeSelectEx(hIMC
, FALSE
, hOldKL
);
234 pClientImc
->hKL
= NULL
;
237 if (CtfImmIsTextFrameServiceDisabled())
239 if (IS_IMM_MODE() && !Imm32IsCiceroMode())
241 bIsNewHKLIme
= IS_IME_HKL(hNewKL
);
242 bIsOldHKLIme
= IS_IME_HKL(hOldKL
);
246 pIC
= (LPINPUTCONTEXTDX
)Imm32InternalLockIMC(hIMC
, FALSE
);
251 if (IS_IME_HKL(hNewKL
))
252 pNewImeDpi
->ImeSelect(hIMC
, TRUE
);
253 else if (Imm32IsCiceroMode() && !Imm32Is16BitMode() && pNewImeDpi
->CtfImeSelectEx
)
254 pNewImeDpi
->CtfImeSelectEx(hIMC
, TRUE
, hNewKL
);
256 pClientImc
->hKL
= hNewKL
;
261 dwConversion
= pIC
->fdwConversion
;
262 dwSentence
= pIC
->fdwSentence
;
267 bClientWide
= (pClientImc
->dwFlags
& CLIENTIMC_WIDE
);
268 bNewDpiWide
= ImeDpi_IsUnicode(pNewImeDpi
);
269 if (bClientWide
&& !bNewDpiWide
)
271 if (pIC
->fdwInit
& INIT_LOGFONT
)
273 LogFontWideToAnsi(&pIC
->lfFont
.W
, &LogFontA
);
274 pIC
->lfFont
.A
= LogFontA
;
276 pClientImc
->dwFlags
&= ~CLIENTIMC_WIDE
;
278 else if (!bClientWide
&& bNewDpiWide
)
280 if (pIC
->fdwInit
& INIT_LOGFONT
)
282 LogFontAnsiToWide(&pIC
->lfFont
.A
, &LogFontW
);
283 pIC
->lfFont
.W
= LogFontW
;
285 pClientImc
->dwFlags
|= CLIENTIMC_WIDE
;
289 if (cbOldPrivate
!= cbNewPrivate
)
291 hPrivate
= ImmReSizeIMCC(pIC
->hPrivate
, cbNewPrivate
);
294 ImmDestroyIMCC(pIC
->hPrivate
);
295 hPrivate
= ImmCreateIMCC(cbNewPrivate
);
297 pIC
->hPrivate
= hPrivate
;
300 #define MAX_IMCC_SIZE 0x1000
301 dwSize
= ImmGetIMCCSize(pIC
->hMsgBuf
);
302 if (ImmGetIMCCLockCount(pIC
->hMsgBuf
) || dwSize
> MAX_IMCC_SIZE
)
304 ImmDestroyIMCC(pIC
->hMsgBuf
);
305 pIC
->hMsgBuf
= ImmCreateIMCC(sizeof(UINT
));
306 pIC
->dwNumMsgBuf
= 0;
309 dwSize
= ImmGetIMCCSize(pIC
->hGuideLine
);
310 dwNewSize
= sizeof(GUIDELINE
);
311 if (ImmGetIMCCLockCount(pIC
->hGuideLine
) ||
312 dwSize
< dwNewSize
|| dwSize
> MAX_IMCC_SIZE
)
314 ImmDestroyIMCC(pIC
->hGuideLine
);
315 pIC
->hGuideLine
= ImmCreateIMCC(dwNewSize
);
316 pGL
= ImmLockIMCC(pIC
->hGuideLine
);
319 pGL
->dwSize
= dwNewSize
;
320 ImmUnlockIMCC(pIC
->hGuideLine
);
324 dwSize
= ImmGetIMCCSize(pIC
->hCandInfo
);
325 dwNewSize
= sizeof(CANDIDATEINFO
);
326 if (ImmGetIMCCLockCount(pIC
->hCandInfo
) ||
327 dwSize
< dwNewSize
|| dwSize
> MAX_IMCC_SIZE
)
329 ImmDestroyIMCC(pIC
->hCandInfo
);
330 pIC
->hCandInfo
= ImmCreateIMCC(dwNewSize
);
331 pCI
= ImmLockIMCC(pIC
->hCandInfo
);
334 pCI
->dwSize
= dwNewSize
;
335 ImmUnlockIMCC(pIC
->hCandInfo
);
339 dwSize
= ImmGetIMCCSize(pIC
->hCompStr
);
340 dwNewSize
= sizeof(COMPOSITIONSTRING
);
341 if (ImmGetIMCCLockCount(pIC
->hCompStr
) ||
342 dwSize
< dwNewSize
|| dwSize
> MAX_IMCC_SIZE
)
344 ImmDestroyIMCC(pIC
->hCompStr
);
345 pIC
->hCompStr
= ImmCreateIMCC(dwNewSize
);
346 pCS
= ImmLockIMCC(pIC
->hCompStr
);
349 pCS
->dwSize
= dwNewSize
;
350 ImmUnlockIMCC(pIC
->hCompStr
);
355 if (pOldImeDpi
&& bIsOldHKLIme
)
357 pOldState
= Imm32FetchImeState(pIC
, hOldKL
);
359 Imm32SaveImeStateSentence(pIC
, pOldState
, hOldKL
);
362 if (pNewImeDpi
&& bIsNewHKLIme
)
363 pNewState
= Imm32FetchImeState(pIC
, hNewKL
);
365 if (pOldState
!= pNewState
)
369 pOldState
->fOpen
= !!pIC
->fOpen
;
370 pOldState
->dwConversion
= (pIC
->fdwConversion
& ~IME_CMODE_EUDC
);
371 pOldState
->dwSentence
= pIC
->fdwSentence
;
372 pOldState
->dwInit
= pIC
->fdwInit
;
377 if (pIC
->dwChange
& INPUTCONTEXTDX_CHANGE_FORCE_OPEN
)
379 pIC
->dwChange
&= ~INPUTCONTEXTDX_CHANGE_FORCE_OPEN
;
384 pIC
->fOpen
= pNewState
->fOpen
;
387 pIC
->fdwConversion
= (pNewState
->dwConversion
& ~IME_CMODE_EUDC
);
388 pIC
->fdwSentence
= pNewState
->dwSentence
;
389 pIC
->fdwInit
= pNewState
->dwInit
;
394 Imm32LoadImeStateSentence(pIC
, pNewState
, hNewKL
);
398 if (IS_IME_HKL(hNewKL
))
399 pNewImeDpi
->ImeSelect(hIMC
, TRUE
);
400 else if (Imm32IsCiceroMode() && !Imm32Is16BitMode() && pNewImeDpi
->CtfImeSelectEx
)
401 pNewImeDpi
->CtfImeSelectEx(hIMC
, TRUE
, hNewKL
);
403 pClientImc
->hKL
= hNewKL
;
407 if (pIC
->fOpen
!= fOpen
)
408 pIC
->dwChange
|= INPUTCONTEXTDX_CHANGE_OPEN
;
409 if (pIC
->fdwConversion
!= dwConversion
)
410 pIC
->dwChange
|= INPUTCONTEXTDX_CHANGE_CONVERSION
;
411 if (pIC
->fdwSentence
!= dwSentence
)
412 pIC
->dwChange
|= INPUTCONTEXTDX_CHANGE_SENTENCE
;
417 ImmUnlockImeDpi(pOldImeDpi
);
418 ImmUnlockImeDpi(pNewImeDpi
);
419 ImmUnlockClientImc(pClientImc
);
422 typedef struct SELECT_LAYOUT
426 } SELECT_LAYOUT
, *LPSELECT_LAYOUT
;
428 // Win: SelectContextProc
429 static BOOL CALLBACK
Imm32SelectContextProc(HIMC hIMC
, LPARAM lParam
)
431 LPSELECT_LAYOUT pSelect
= (LPSELECT_LAYOUT
)lParam
;
432 Imm32SelectInputContext(pSelect
->hNewKL
, pSelect
->hOldKL
, hIMC
);
436 // Win: NotifyIMEProc
437 static BOOL CALLBACK
Imm32NotifyIMEProc(HIMC hIMC
, LPARAM lParam
)
439 ImmNotifyIME(hIMC
, NI_COMPOSITIONSTR
, (DWORD
)lParam
, 0);
443 /***********************************************************************
444 * ImmActivateLayout (IMM32.@)
446 BOOL WINAPI
ImmActivateLayout(HKL hKL
)
451 HWND hwndDefIME
= NULL
;
452 SELECT_LAYOUT SelectLayout
;
454 hOldKL
= GetKeyboardLayout(0);
456 if (hOldKL
== hKL
&& !(GetWin32ClientInfo()->CI_flags
& CI_IMMACTIVATE
))
463 pImeDpi
= ImmLockImeDpi(hOldKL
);
466 if (pImeDpi
->ImeInfo
.fdwProperty
& IME_PROP_COMPLETE_ON_UNSELECT
)
467 lParam
= CPS_COMPLETE
;
470 ImmUnlockImeDpi(pImeDpi
);
472 ImmEnumInputContext(0, Imm32NotifyIMEProc
, lParam
);
475 hwndDefIME
= ImmGetDefaultIMEWnd(NULL
);
476 if (IsWindow(hwndDefIME
))
477 SendMessageW(hwndDefIME
, WM_IME_SELECT
, FALSE
, (LPARAM
)hOldKL
);
479 NtUserSetThreadLayoutHandles(hKL
, hOldKL
);
482 SelectLayout
.hNewKL
= hKL
;
483 SelectLayout
.hOldKL
= hOldKL
;
484 ImmEnumInputContext(0, Imm32SelectContextProc
, (LPARAM
)&SelectLayout
);
486 if (IsWindow(hwndDefIME
))
487 SendMessageW(hwndDefIME
, WM_IME_SELECT
, TRUE
, (LPARAM
)hKL
);
492 static VOID APIENTRY
Imm32CiceroSetActiveContext(HIMC hIMC
, BOOL fActive
, HWND hWnd
, HKL hKL
)
494 TRACE("We have to do something\n");
497 /***********************************************************************
498 * ImmAssociateContext (IMM32.@)
500 HIMC WINAPI
ImmAssociateContext(HWND hWnd
, HIMC hIMC
)
507 TRACE("(%p, %p)\n", hWnd
, hIMC
);
512 pWnd
= ValidateHwnd(hWnd
);
516 if (hIMC
&& Imm32IsCrossThreadAccess(hIMC
))
519 hOldIMC
= pWnd
->hImc
;
523 dwValue
= NtUserAssociateInputContext(hWnd
, hIMC
, 0);
529 hwndFocus
= (HWND
)NtUserQueryWindow(hWnd
, QUERY_WINDOW_FOCUS
);
530 if (hwndFocus
== hWnd
)
532 ImmSetActiveContext(hWnd
, hOldIMC
, FALSE
);
533 ImmSetActiveContext(hWnd
, hIMC
, TRUE
);
539 /***********************************************************************
540 * ImmAssociateContextEx (IMM32.@)
542 BOOL WINAPI
ImmAssociateContextEx(HWND hWnd
, HIMC hIMC
, DWORD dwFlags
)
549 TRACE("(%p, %p, 0x%lX)\n", hWnd
, hIMC
, dwFlags
);
554 if (hIMC
&& !(dwFlags
& IACE_DEFAULT
) && Imm32IsCrossThreadAccess(hIMC
))
557 hwndFocus
= (HWND
)NtUserQueryWindow(hWnd
, QUERY_WINDOW_FOCUS
);
558 pFocusWnd
= ValidateHwnd(hwndFocus
);
560 hOldIMC
= pFocusWnd
->hImc
;
562 dwValue
= NtUserAssociateInputContext(hWnd
, hIMC
, dwFlags
);
569 pFocusWnd
= ValidateHwnd(hwndFocus
);
572 hIMC
= pFocusWnd
->hImc
;
575 ImmSetActiveContext(hwndFocus
, hOldIMC
, FALSE
);
576 ImmSetActiveContext(hwndFocus
, hIMC
, TRUE
);
586 /***********************************************************************
587 * ImmCreateContext (IMM32.@)
589 HIMC WINAPI
ImmCreateContext(void)
591 PCLIENTIMC pClientImc
;
599 pClientImc
= ImmLocalAlloc(HEAP_ZERO_MEMORY
, sizeof(CLIENTIMC
));
600 if (pClientImc
== NULL
)
603 hIMC
= NtUserCreateInputContext((ULONG_PTR
)pClientImc
);
606 ImmLocalFree(pClientImc
);
610 RtlInitializeCriticalSection(&pClientImc
->cs
);
612 pClientImc
->dwCompatFlags
= (DWORD
)NtUserGetThreadState(THREADSTATE_IMECOMPATFLAGS
);
617 // Win: DestroyImeModeSaver
618 static VOID APIENTRY
Imm32DestroyImeModeSaver(LPINPUTCONTEXTDX pIC
)
620 PIME_STATE pState
, pNext
;
621 PIME_SUBSTATE pSubState
, pSubNext
;
623 for (pState
= pIC
->pState
; pState
; pState
= pNext
)
625 pNext
= pState
->pNext
;
627 for (pSubState
= pState
->pSubState
; pSubState
; pSubState
= pSubNext
)
629 pSubNext
= pSubState
->pNext
;
630 ImmLocalFree(pSubState
);
633 ImmLocalFree(pState
);
639 // Win: DestroyInputContext
640 BOOL APIENTRY
Imm32DestroyInputContext(HIMC hIMC
, HKL hKL
, BOOL bKeep
)
643 LPINPUTCONTEXTDX pIC
;
644 PCLIENTIMC pClientImc
;
647 if (!hIMC
|| !IS_IMM_MODE())
650 pIMC
= ValidateHandle(hIMC
, TYPE_INPUTCONTEXT
);
651 if (!pIMC
|| pIMC
->head
.pti
!= Imm32CurrentPti())
653 ERR("invalid pIMC: %p\n", pIMC
);
657 pClientImc
= (PCLIENTIMC
)pIMC
->dwClientImcData
;
661 if ((pClientImc
->dwFlags
& CLIENTIMC_UNKNOWN2
) && !bKeep
)
663 ERR("CLIENTIMC_UNKNOWN2\n");
667 if (pClientImc
->dwFlags
& CLIENTIMC_DESTROY
)
670 InterlockedIncrement(&pClientImc
->cLockObj
);
672 if (!pClientImc
->hInputContext
)
675 pIC
= (LPINPUTCONTEXTDX
)ImmLockIMC(hIMC
);
678 ImmUnlockClientImc(pClientImc
);
683 CtfImmTIMDestroyInputContext(hIMC
);
685 if (pClientImc
->hKL
== hKL
)
687 pImeDpi
= ImmLockImeDpi(hKL
);
691 pImeDpi
->ImeSelect(hIMC
, FALSE
);
692 else if (Imm32IsCiceroMode() && !Imm32Is16BitMode())
693 pImeDpi
->CtfImeSelectEx(hIMC
, FALSE
, hKL
);
695 ImmUnlockImeDpi(pImeDpi
);
698 pClientImc
->hKL
= NULL
;
701 ImmDestroyIMCC(pIC
->hPrivate
);
702 ImmDestroyIMCC(pIC
->hMsgBuf
);
703 ImmDestroyIMCC(pIC
->hGuideLine
);
704 ImmDestroyIMCC(pIC
->hCandInfo
);
705 ImmDestroyIMCC(pIC
->hCompStr
);
706 Imm32DestroyImeModeSaver(pIC
);
710 pClientImc
->dwFlags
|= CLIENTIMC_DESTROY
;
711 ImmUnlockClientImc(pClientImc
);
716 return NtUserDestroyInputContext(hIMC
);
719 // NOTE: Windows does recursive call ImmLockIMC here but we don't do so.
720 // Win: BOOL CreateInputContext(HIMC hIMC, HKL hKL, BOOL fSelect)
722 Imm32CreateInputContext(HIMC hIMC
, LPINPUTCONTEXT pIC
, PCLIENTIMC pClientImc
, HKL hKL
, BOOL fSelect
)
724 DWORD dwIndex
, cbPrivate
;
725 PIMEDPI pImeDpi
= NULL
;
726 LPCOMPOSITIONSTRING pCS
;
730 /* Create IC components */
731 pIC
->hCompStr
= ImmCreateIMCC(sizeof(COMPOSITIONSTRING
));
732 pIC
->hCandInfo
= ImmCreateIMCC(sizeof(CANDIDATEINFO
));
733 pIC
->hGuideLine
= ImmCreateIMCC(sizeof(GUIDELINE
));
734 pIC
->hMsgBuf
= ImmCreateIMCC(sizeof(UINT
));
735 if (!pIC
->hCompStr
|| !pIC
->hCandInfo
|| !pIC
->hGuideLine
|| !pIC
->hMsgBuf
)
738 /* Initialize IC components */
739 pCS
= ImmLockIMCC(pIC
->hCompStr
);
742 pCS
->dwSize
= sizeof(COMPOSITIONSTRING
);
743 ImmUnlockIMCC(pIC
->hCompStr
);
745 pCI
= ImmLockIMCC(pIC
->hCandInfo
);
748 pCI
->dwSize
= sizeof(CANDIDATEINFO
);
749 ImmUnlockIMCC(pIC
->hCandInfo
);
751 pGL
= ImmLockIMCC(pIC
->hGuideLine
);
754 pGL
->dwSize
= sizeof(GUIDELINE
);
755 ImmUnlockIMCC(pIC
->hGuideLine
);
757 pIC
->dwNumMsgBuf
= 0;
759 pIC
->fdwConversion
= pIC
->fdwSentence
= 0;
761 for (dwIndex
= 0; dwIndex
< MAX_CANDIDATEFORM
; ++dwIndex
)
762 pIC
->cfCandForm
[dwIndex
].dwIndex
= IMM_INVALID_CANDFORM
;
764 /* Get private data size */
765 pImeDpi
= ImmLockImeDpi(hKL
);
768 cbPrivate
= sizeof(DWORD
);
772 /* Update CLIENTIMC */
773 pClientImc
->uCodePage
= pImeDpi
->uCodePage
;
774 if (ImeDpi_IsUnicode(pImeDpi
))
775 pClientImc
->dwFlags
|= CLIENTIMC_WIDE
;
777 cbPrivate
= pImeDpi
->ImeInfo
.dwPrivateDataSize
;
780 /* Create private data */
781 pIC
->hPrivate
= ImmCreateIMCC(cbPrivate
);
791 pImeDpi
->ImeSelect(hIMC
, TRUE
);
792 else if (Imm32IsCiceroMode() && !Imm32Is16BitMode() && pImeDpi
->CtfImeSelectEx
)
793 pImeDpi
->CtfImeSelectEx(hIMC
, TRUE
, hKL
);
797 pClientImc
->hKL
= hKL
;
799 ImmUnlockImeDpi(pImeDpi
);
806 ImmUnlockImeDpi(pImeDpi
);
808 pIC
->hMsgBuf
= ImmDestroyIMCC(pIC
->hMsgBuf
);
809 pIC
->hGuideLine
= ImmDestroyIMCC(pIC
->hGuideLine
);
810 pIC
->hCandInfo
= ImmDestroyIMCC(pIC
->hCandInfo
);
811 pIC
->hCompStr
= ImmDestroyIMCC(pIC
->hCompStr
);
815 // Win: InternalImmLockIMC
816 LPINPUTCONTEXT APIENTRY
Imm32InternalLockIMC(HIMC hIMC
, BOOL fSelect
)
819 LPINPUTCONTEXT pIC
= NULL
;
820 PCLIENTIMC pClientImc
;
824 PIMEDPI pImeDpi
= NULL
;
826 pClientImc
= ImmLockClientImc(hIMC
);
830 RtlEnterCriticalSection(&pClientImc
->cs
);
832 if (pClientImc
->hInputContext
)
834 pIC
= LocalLock(pClientImc
->hInputContext
);
841 dwThreadId
= (DWORD
)NtUserQueryInputContext(hIMC
, QIC_INPUTTHREADID
);
842 if (dwThreadId
== GetCurrentThreadId() && Imm32IsCiceroMode() && !Imm32Is16BitMode())
844 hOldKL
= GetKeyboardLayout(0);
845 LangID
= LOWORD(hOldKL
);
846 hNewKL
= (HKL
)(DWORD_PTR
)MAKELONG(LangID
, LangID
);
848 pImeDpi
= Imm32FindOrLoadImeDpi(hNewKL
);
851 CtfImmTIMActivate(hNewKL
);
855 if (!NtUserQueryInputContext(hIMC
, QIC_DEFAULTWINDOWIME
))
858 hIC
= LocalAlloc(LHND
, sizeof(INPUTCONTEXTDX
));
859 pIC
= LocalLock(hIC
);
865 pClientImc
->hInputContext
= hIC
;
867 hNewKL
= GetKeyboardLayout(dwThreadId
);
868 if (!Imm32CreateInputContext(hIMC
, pIC
, pClientImc
, hNewKL
, fSelect
))
870 pClientImc
->hInputContext
= LocalFree(pClientImc
->hInputContext
);
875 CtfImmTIMCreateInputContext(hIMC
);
876 RtlLeaveCriticalSection(&pClientImc
->cs
);
877 InterlockedIncrement(&pClientImc
->cLockObj
);
878 ImmUnlockClientImc(pClientImc
);
882 RtlLeaveCriticalSection(&pClientImc
->cs
);
883 ImmUnlockClientImc(pClientImc
);
887 /***********************************************************************
888 * ImmDestroyContext (IMM32.@)
890 BOOL WINAPI
ImmDestroyContext(HIMC hIMC
)
894 TRACE("(%p)\n", hIMC
);
899 if (Imm32IsCrossThreadAccess(hIMC
))
902 hKL
= GetKeyboardLayout(0);
903 return Imm32DestroyInputContext(hIMC
, hKL
, FALSE
);
906 /***********************************************************************
907 * ImmLockClientImc (IMM32.@)
909 PCLIENTIMC WINAPI
ImmLockClientImc(HIMC hImc
)
912 PCLIENTIMC pClientImc
;
914 TRACE("(%p)\n", hImc
);
919 pIMC
= ValidateHandle(hImc
, TYPE_INPUTCONTEXT
);
920 if (!pIMC
|| !Imm32CheckImcProcess(pIMC
))
923 pClientImc
= (PCLIENTIMC
)pIMC
->dwClientImcData
;
926 if (pClientImc
->dwFlags
& CLIENTIMC_DESTROY
)
931 pClientImc
= ImmLocalAlloc(HEAP_ZERO_MEMORY
, sizeof(CLIENTIMC
));
935 RtlInitializeCriticalSection(&pClientImc
->cs
);
936 pClientImc
->dwCompatFlags
= (DWORD
)NtUserGetThreadState(THREADSTATE_IMECOMPATFLAGS
);
938 if (!NtUserUpdateInputContext(hImc
, UIC_CLIENTIMCDATA
, (DWORD_PTR
)pClientImc
))
940 ImmLocalFree(pClientImc
);
944 pClientImc
->dwFlags
|= CLIENTIMC_UNKNOWN2
;
947 InterlockedIncrement(&pClientImc
->cLockObj
);
951 /***********************************************************************
952 * ImmUnlockClientImc (IMM32.@)
954 VOID WINAPI
ImmUnlockClientImc(PCLIENTIMC pClientImc
)
957 HANDLE hInputContext
;
959 TRACE("(%p)\n", pClientImc
);
961 cLocks
= InterlockedDecrement(&pClientImc
->cLockObj
);
962 if (cLocks
!= 0 || !(pClientImc
->dwFlags
& CLIENTIMC_DESTROY
))
965 hInputContext
= pClientImc
->hInputContext
;
967 LocalFree(hInputContext
);
969 RtlDeleteCriticalSection(&pClientImc
->cs
);
970 ImmLocalFree(pClientImc
);
973 // Win: ImmGetSaveContext
974 static HIMC APIENTRY
ImmGetSaveContext(HWND hWnd
, DWORD dwContextFlags
)
977 PCLIENTIMC pClientImc
;
985 hIMC
= (HIMC
)NtUserGetThreadState(THREADSTATE_DEFAULTINPUTCONTEXT
);
989 pWnd
= ValidateHwnd(hWnd
);
990 if (!pWnd
|| Imm32IsCrossProcessAccess(hWnd
))
994 if (!hIMC
&& (dwContextFlags
& 1))
995 hIMC
= (HIMC
)NtUserQueryWindow(hWnd
, QUERY_WINDOW_DEFAULT_ICONTEXT
);
998 pClientImc
= ImmLockClientImc(hIMC
);
999 if (pClientImc
== NULL
)
1001 if ((dwContextFlags
& 2) && (pClientImc
->dwFlags
& CLIENTIMC_UNKNOWN3
))
1003 ImmUnlockClientImc(pClientImc
);
1007 /***********************************************************************
1008 * ImmGetContext (IMM32.@)
1010 HIMC WINAPI
ImmGetContext(HWND hWnd
)
1012 TRACE("(%p)\n", hWnd
);
1015 return ImmGetSaveContext(hWnd
, 2);
1018 /***********************************************************************
1019 * ImmLockIMC(IMM32.@)
1021 * NOTE: This is not ImmLockIMCC. Don't confuse.
1023 LPINPUTCONTEXT WINAPI
ImmLockIMC(HIMC hIMC
)
1025 TRACE("(%p)\n", hIMC
);
1026 return Imm32InternalLockIMC(hIMC
, TRUE
);
1029 /***********************************************************************
1030 * ImmUnlockIMC(IMM32.@)
1032 BOOL WINAPI
ImmUnlockIMC(HIMC hIMC
)
1034 PCLIENTIMC pClientImc
;
1036 pClientImc
= ImmLockClientImc(hIMC
);
1037 if (pClientImc
== NULL
)
1040 if (pClientImc
->hInputContext
)
1041 LocalUnlock(pClientImc
->hInputContext
);
1043 InterlockedDecrement(&pClientImc
->cLockObj
);
1044 ImmUnlockClientImc(pClientImc
);
1048 /***********************************************************************
1049 * ImmReleaseContext (IMM32.@)
1051 BOOL WINAPI
ImmReleaseContext(HWND hWnd
, HIMC hIMC
)
1053 TRACE("(%p, %p)\n", hWnd
, hIMC
);
1054 UNREFERENCED_PARAMETER(hWnd
);
1055 UNREFERENCED_PARAMETER(hIMC
);
1056 return TRUE
; // Do nothing. This is correct.
1059 /***********************************************************************
1060 * ImmCreateSoftKeyboard(IMM32.@)
1062 HWND WINAPI
ImmCreateSoftKeyboard(UINT uType
, UINT hOwner
, int x
, int y
)
1064 FIXME("(%d, %d, %d, %d): stub\n", uType
, hOwner
, x
, y
);
1065 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1069 /***********************************************************************
1070 * ImmDestroySoftKeyboard(IMM32.@)
1072 BOOL WINAPI
ImmDestroySoftKeyboard(HWND hSoftWnd
)
1074 TRACE("(%p)\n", hSoftWnd
);
1075 return DestroyWindow(hSoftWnd
);
1078 /***********************************************************************
1079 * ImmShowSoftKeyboard(IMM32.@)
1081 BOOL WINAPI
ImmShowSoftKeyboard(HWND hSoftWnd
, int nCmdShow
)
1083 TRACE("(%p, %d)\n", hSoftWnd
, nCmdShow
);
1085 return ShowWindow(hSoftWnd
, nCmdShow
);
1089 /***********************************************************************
1090 * ImmDisableTextFrameService(IMM32.@)
1092 BOOL WINAPI
ImmDisableTextFrameService(DWORD dwThreadId
)
1098 /***********************************************************************
1099 * ImmEnumInputContext(IMM32.@)
1101 BOOL WINAPI
ImmEnumInputContext(DWORD dwThreadId
, IMCENUMPROC lpfn
, LPARAM lParam
)
1104 DWORD dwIndex
, dwCount
;
1108 TRACE("(%lu, %p, %p)\n", dwThreadId
, lpfn
, lParam
);
1110 dwCount
= Imm32BuildHimcList(dwThreadId
, &phList
);
1114 for (dwIndex
= 0; dwIndex
< dwCount
; ++dwIndex
)
1116 hIMC
= phList
[dwIndex
];
1117 ret
= (*lpfn
)(hIMC
, lParam
);
1122 ImmLocalFree(phList
);
1126 /***********************************************************************
1127 * ImmSetActiveContext(IMM32.@)
1129 BOOL WINAPI
ImmSetActiveContext(HWND hWnd
, HIMC hIMC
, BOOL fActive
)
1131 PCLIENTIMC pClientImc
;
1132 LPINPUTCONTEXTDX pIC
;
1136 DWORD dwConversion
= 0, iShow
= ISC_SHOWUIALL
;
1139 TRACE("(%p, %p, %d)\n", hWnd
, hIMC
, fActive
);
1144 pClientImc
= ImmLockClientImc(hIMC
);
1149 pClientImc
->dwFlags
&= ~CLIENTIMC_UNKNOWN4
;
1156 pIC
= (LPINPUTCONTEXTDX
)ImmLockIMC(hIMC
);
1159 ImmUnlockClientImc(pClientImc
);
1164 pClientImc
->dwFlags
|= CLIENTIMC_UNKNOWN5
;
1166 if (pIC
->dwUIFlags
& 2)
1167 iShow
= (ISC_SHOWUIGUIDELINE
| ISC_SHOWUIALLCANDIDATEWINDOW
);
1170 dwConversion
= pIC
->fdwConversion
;
1176 hIMC
= ImmGetSaveContext(hWnd
, 1);
1177 pIC
= (LPINPUTCONTEXTDX
)ImmLockIMC(hIMC
);
1186 hKL
= GetKeyboardLayout(0);
1188 if (Imm32IsCiceroMode() && !Imm32Is16BitMode())
1190 Imm32CiceroSetActiveContext(hIMC
, fActive
, hWnd
, hKL
);
1191 hKL
= GetKeyboardLayout(0);
1194 pImeDpi
= ImmLockImeDpi(hKL
);
1197 if (IS_IME_HKL(hKL
))
1198 pImeDpi
->ImeSetActiveContext(hIMC
, fActive
);
1199 ImmUnlockImeDpi(pImeDpi
);
1204 SendMessageW(hWnd
, WM_IME_SETCONTEXT
, fActive
, iShow
);
1206 NtUserNotifyIMEStatus(hWnd
, fOpen
, dwConversion
);
1210 hwndDefIME
= ImmGetDefaultIMEWnd(NULL
);
1212 SendMessageW(hwndDefIME
, WM_IME_SETCONTEXT
, 0, iShow
);
1216 ImmUnlockClientImc(pClientImc
);
1221 /***********************************************************************
1222 * ImmWINNLSGetEnableStatus (IMM32.@)
1225 BOOL WINAPI
ImmWINNLSGetEnableStatus(HWND hWnd
)
1227 if (!Imm32IsSystemJapaneseOrKorean())
1229 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1233 return !!ImmGetSaveContext(hWnd
, 2);
1236 /***********************************************************************
1237 * ImmSetActiveContextConsoleIME(IMM32.@)
1239 BOOL WINAPI
ImmSetActiveContextConsoleIME(HWND hwnd
, BOOL fFlag
)
1242 TRACE("(%p, %d)\n", hwnd
, fFlag
);
1244 hIMC
= ImmGetContext(hwnd
);
1246 return ImmSetActiveContext(hwnd
, hIMC
, fFlag
);
1250 BOOL WINAPI
User32InitializeImmEntryTable(DWORD
);
1252 // Win: ImmDllInitialize
1253 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpReserved
)
1258 TRACE("(%p, 0x%X, %p)\n", hinstDLL
, fdwReason
, lpReserved
);
1262 case DLL_PROCESS_ATTACH
:
1263 if (!ImmInitializeGlobals(hinstDLL
))
1265 ERR("ImmInitializeGlobals failed\n");
1268 if (!User32InitializeImmEntryTable(IMM_INIT_MAGIC
))
1270 ERR("User32InitializeImmEntryTable failed\n");
1275 case DLL_THREAD_ATTACH
:
1278 case DLL_THREAD_DETACH
:
1279 if (!IS_IMM_MODE() || NtCurrentTeb()->Win32ThreadInfo
== NULL
)
1282 hKL
= GetKeyboardLayout(0);
1283 hIMC
= (HIMC
)NtUserGetThreadState(THREADSTATE_DEFAULTINPUTCONTEXT
);
1284 Imm32DestroyInputContext(hIMC
, hKL
, TRUE
);
1287 case DLL_PROCESS_DETACH
:
1288 RtlDeleteCriticalSection(&gcsImeDpi
);
1289 TRACE("imm32.dll is unloaded\n");