https://git.reactos.org/?p=reactos.git;a=commitdiff;h=b3194e320cfd143fa7f3a…
commit b3194e320cfd143fa7f3ad4183f8b3305a113b07
Author: Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com>
AuthorDate: Tue Oct 31 22:45:28 2023 +0900
Commit: GitHub <noreply(a)github.com>
CommitDate: Tue Oct 31 22:45:28 2023 +0900
[IMM32][SDK] Add CtfAImmActivate/Deactivate functions (#5835)
- Add dll/win32/imm32/CtfImeTable.h for CTF
IME functions.
- Implementing Imm32CheckAndApplyAppCompat,
Imm32LoadCtfIme, and
Imm32EnumCreateCtfICProc helper functions.
- Add CtfAImmActivate and CtfAImmDeactivate
functions.
- s/CI_TFSDISABLED/CI_TSFDISABLED/
CORE-19268
---
dll/win32/imm32/CtfImeTable.h | 18 +++
dll/win32/imm32/ctf.c | 329 +++++++++++++++++++++++++++++++++++---
dll/win32/imm32/imm32.spec | 2 +
dll/win32/imm32/precomp.h | 4 +-
sdk/include/reactos/imm32_undoc.h | 6 +-
win32ss/include/ntuser.h | 6 +-
6 files changed, 334 insertions(+), 31 deletions(-)
diff --git a/dll/win32/imm32/CtfImeTable.h b/dll/win32/imm32/CtfImeTable.h
new file mode 100644
index 00000000000..14f701b6c46
--- /dev/null
+++ b/dll/win32/imm32/CtfImeTable.h
@@ -0,0 +1,18 @@
+/*
+ * PROJECT: ReactOS IMM32
+ * LICENSE: LGPL-2.1-or-later (
https://spdx.org/licenses/LGPL-2.1-or-later)
+ * PURPOSE: Defining the CTF IME file interface
+ * COPYRIGHT: Copyright 2023 Katayama Hirofumi MZ
<katayama.hirofumi.mz(a)gmail.com>
+ */
+
+/* The valid CTF IME file contains the following functions: */
+
+/* DEFINE_CTF_IME_FN(func_name, ret_type, params) */
+DEFINE_CTF_IME_FN(CtfImeCreateThreadMgr, HRESULT, (VOID))
+DEFINE_CTF_IME_FN(CtfImeDestroyThreadMgr, HRESULT, (VOID))
+DEFINE_CTF_IME_FN(CtfImeCreateInputContext, HRESULT, (HIMC hIMC))
+DEFINE_CTF_IME_FN(CtfImeDestroyInputContext, HRESULT, (HIMC hIMC))
+DEFINE_CTF_IME_FN(CtfImeSetActiveContextAlways, HRESULT, (DWORD dwFIXME1, DWORD dwFIXME2,
DWORD dwFIXME3, DWORD dwFIXME4))
+DEFINE_CTF_IME_FN(CtfImeProcessCicHotkey, HRESULT, (DWORD dwFIXME1, DWORD dwFIXME2, DWORD
dwFIXME3))
+DEFINE_CTF_IME_FN(CtfImeDispatchDefImeMessage, LRESULT, (HWND hWnd, UINT uMsg, WPARAM
wParam, LPARAM lParam))
+DEFINE_CTF_IME_FN(CtfImeIsIME, BOOL, (HKL hKL))
diff --git a/dll/win32/imm32/ctf.c b/dll/win32/imm32/ctf.c
index 8495725ed0f..eeeae62b588 100644
--- a/dll/win32/imm32/ctf.c
+++ b/dll/win32/imm32/ctf.c
@@ -2,7 +2,7 @@
* PROJECT: ReactOS IMM32
* LICENSE: LGPL-2.1-or-later (
https://spdx.org/licenses/LGPL-2.1-or-later)
* PURPOSE: Implementing the IMM32 Cicero-aware Text Framework (CTF)
- * COPYRIGHT: Copyright 2022 Katayama Hirofumi MZ
<katayama.hirofumi.mz(a)gmail.com>
+ * COPYRIGHT: Copyright 2022-2023 Katayama Hirofumi MZ
<katayama.hirofumi.mz(a)gmail.com>
*/
#include "precomp.h"
@@ -17,62 +17,326 @@ WINE_DEFAULT_DEBUG_CHANNEL(imm);
*
https://googleprojectzero.blogspot.com/2019/08/down-rabbit-hole.html
*/
-// Win: LoadCtfIme
-HMODULE APIENTRY Imm32LoadCtfIme(VOID)
+/*
+ * TSF stands for "Text Services Framework". "Cicero" is the code
name of TSF.
+ * CTF stands for "Cicero-aware Text Framework".
+ *
+ * Comparing with old-style IMM IME, the combination of CTF IME and TSF provides
+ * new-style and high-level input method.
+ *
+ * The CTF IME file is a DLL file that the software developer distributes.
+ * The export functions of the CTF IME file are defined in "CtfImeTable.h" of
+ * this folder.
+ */
+
+/* The instance of the CTF IME file */
+HINSTANCE g_hCtfIme = NULL;
+
+/* Define the function types (FN_...) for CTF IME functions */
+#undef DEFINE_CTF_IME_FN
+#define DEFINE_CTF_IME_FN(func_name, ret_type, params) \
+ typedef ret_type (WINAPI *FN_##func_name)params;
+#include "CtfImeTable.h"
+
+/* Define the global variables (g_pfn...) for CTF IME functions */
+#undef DEFINE_CTF_IME_FN
+#define DEFINE_CTF_IME_FN(func_name, ret_type, params) \
+ FN_##func_name g_pfn##func_name = NULL;
+#include "CtfImeTable.h"
+
+/* The macro that gets the variable name from the CTF IME function name */
+#define CTF_IME_FN(func_name) g_pfn##func_name
+
+/* The type of ApphelpCheckIME function in apphelp.dll */
+typedef BOOL (WINAPI *FN_ApphelpCheckIME)(_In_z_ LPCWSTR AppName);
+
+/* FIXME: This is kernel32 function. We have to declare this in some header. */
+BOOL WINAPI
+BaseCheckAppcompatCache(_In_z_ LPCWSTR ApplicationName,
+ _In_ HANDLE FileHandle,
+ _In_opt_z_ LPCWSTR Environment,
+ _Out_ PULONG pdwReason);
+
+/***********************************************************************
+ * This function checks whether the app's IME is disabled by application
+ * compatibility patcher.
+ */
+BOOL
+Imm32CheckAndApplyAppCompat(
+ _In_ ULONG dwReason,
+ _In_z_ LPCWSTR pszAppName)
{
- return NULL;
+ HINSTANCE hinstApphelp;
+ FN_ApphelpCheckIME pApphelpCheckIME;
+
+ /* Query the application compatibility patcher */
+ if (BaseCheckAppcompatCache(pszAppName, INVALID_HANDLE_VALUE, NULL, &dwReason))
+ return TRUE; /* The app's IME is not disabled */
+
+ /* Load apphelp.dll if necessary */
+ hinstApphelp = GetModuleHandleW(L"apphelp.dll");
+ if (!hinstApphelp)
+ {
+ hinstApphelp = LoadLibraryW(L"apphelp.dll");
+ if (!hinstApphelp)
+ return TRUE; /* There is no apphelp.dll. The app's IME is not disabled
*/
+ }
+
+ /* Is ApphelpCheckIME implemented? */
+ pApphelpCheckIME = (FN_ApphelpCheckIME)GetProcAddress(hinstApphelp,
"ApphelpCheckIME");
+ if (!pApphelpCheckIME)
+ return TRUE; /* Not implemented. The app's IME is not disabled */
+
+ /* Is the app's IME disabled or not? */
+ return pApphelpCheckIME(pszAppName);
}
-// Win: Internal_CtfImeDestroyInputContext
-HRESULT APIENTRY Imm32CtfImeDestroyInputContext(HIMC hIMC)
+/***********************************************************************
+ * This function loads the CTF IME file if necessary and establishes
+ * communication with the CTF IME.
+ */
+HINSTANCE
+Imm32LoadCtfIme(VOID)
+{
+ BOOL bSuccess = FALSE;
+ IMEINFOEX ImeInfoEx;
+ WCHAR szImeFile[MAX_PATH];
+
+ /* Lock the IME interface */
+ RtlEnterCriticalSection(&gcsImeDpi);
+
+ do
+ {
+ if (g_hCtfIme) /* Already loaded? */
+ {
+ bSuccess = TRUE;
+ break;
+ }
+
+ /*
+ * NOTE: (HKL)0x04090409 is English US keyboard (default).
+ * The Cicero keyboard logically uses English US keyboard.
+ */
+ if (!ImmLoadLayout((HKL)ULongToHandle(0x04090409), &ImeInfoEx))
+ break;
+
+ /* Build a path string in system32. The installed IME file must be in system32.
*/
+ Imm32GetSystemLibraryPath(szImeFile, _countof(szImeFile), ImeInfoEx.wszImeFile);
+
+ /* Is the CTF IME disabled by app compatibility patcher? */
+ if (!Imm32CheckAndApplyAppCompat(0, szImeFile))
+ break; /* This IME is disabled */
+
+ /* Load a CTF IME file */
+ g_hCtfIme = LoadLibraryW(szImeFile);
+ if (!g_hCtfIme)
+ break;
+
+ /* Assume success */
+ bSuccess = TRUE;
+
+ /* Retrieve the CTF IME functions */
+#undef DEFINE_CTF_IME_FN
+#define DEFINE_CTF_IME_FN(func_name, ret_type, params) \
+ CTF_IME_FN(func_name) = (FN_##func_name)GetProcAddress(g_hCtfIme, #func_name); \
+ if (!CTF_IME_FN(func_name)) \
+ { \
+ bSuccess = FALSE; /* Failed */ \
+ break; \
+ }
+#include "CtfImeTable.h"
+ } while (0);
+
+ /* Unload the CTF IME if failed */
+ if (!bSuccess)
+ {
+ /* Set NULL to the function pointers */
+#undef DEFINE_CTF_IME_FN
+#define DEFINE_CTF_IME_FN(func_name, ret_type, params) CTF_IME_FN(func_name) = NULL;
+#include "CtfImeTable.h"
+
+ if (g_hCtfIme)
+ {
+ FreeLibrary(g_hCtfIme);
+ g_hCtfIme = NULL;
+ }
+ }
+
+ /* Unlock the IME interface */
+ RtlLeaveCriticalSection(&gcsImeDpi);
+
+ return g_hCtfIme;
+}
+
+/***********************************************************************
+ * This function calls the same name function of the CTF IME side.
+ */
+HRESULT
+CtfImeCreateThreadMgr(VOID)
{
if (!Imm32LoadCtfIme())
return E_FAIL;
-#if 1
- FIXME("(%p)\n", hIMC);
- return E_NOTIMPL;
-#else
- return g_pfnCtfImeDestroyInputContext(hIMC);
-#endif
+ return CTF_IME_FN(CtfImeCreateThreadMgr)();
+}
+
+/***********************************************************************
+ * This function calls the same name function of the CTF IME side.
+ */
+HRESULT
+CtfImeDestroyThreadMgr(VOID)
+{
+ if (!Imm32LoadCtfIme())
+ return E_FAIL;
+
+ return CTF_IME_FN(CtfImeDestroyThreadMgr)();
+}
+
+/***********************************************************************
+ * This function calls the same name function of the CTF IME side.
+ */
+HRESULT
+CtfImeCreateInputContext(
+ _In_ HIMC hIMC)
+{
+ if (!Imm32LoadCtfIme())
+ return E_FAIL;
+
+ return CTF_IME_FN(CtfImeCreateInputContext)(hIMC);
+}
+
+/***********************************************************************
+ * This function calls the same name function of the CTF IME side.
+ */
+HRESULT
+CtfImeDestroyInputContext(_In_ HIMC hIMC)
+{
+ if (!Imm32LoadCtfIme())
+ return E_FAIL;
+
+ return CTF_IME_FN(CtfImeDestroyInputContext)(hIMC);
+}
+
+/***********************************************************************
+ * The callback function to activate CTF IMEs. Used in CtfAImmActivate.
+ */
+static BOOL CALLBACK
+Imm32EnumCreateCtfICProc(
+ _In_ HIMC hIMC,
+ _In_ LPARAM lParam)
+{
+ UNREFERENCED_PARAMETER(lParam);
+ CtfImeCreateInputContext(hIMC);
+ return TRUE; /* Continue */
}
-// Win: CtfImmTIMDestroyInputContext
-HRESULT APIENTRY CtfImmTIMDestroyInputContext(HIMC hIMC)
+/***********************************************************************
+ * This function calls CtfImeDestroyInputContext if possible.
+ */
+HRESULT
+CtfImmTIMDestroyInputContext(
+ _In_ HIMC hIMC)
{
if (!IS_CICERO_MODE() || (GetWin32ClientInfo()->dwCompatFlags2 & 2))
return E_NOINTERFACE;
- return Imm32CtfImeDestroyInputContext(hIMC);
+ return CtfImeDestroyInputContext(hIMC);
}
-// Win: CtfImmTIMCreateInputContext
-HRESULT APIENTRY CtfImmTIMCreateInputContext(HIMC hIMC)
+HRESULT
+CtfImmTIMCreateInputContext(
+ _In_ HIMC hIMC)
{
TRACE("(%p)\n", hIMC);
return E_NOTIMPL;
}
+/***********************************************************************
+ * CtfAImmActivate (IMM32.@)
+ *
+ * This function activates "Active IMM" (AIMM) and TSF.
+ */
+HRESULT WINAPI
+CtfAImmActivate(
+ _Out_opt_ HINSTANCE *phinstCtfIme)
+{
+ HRESULT hr;
+ HINSTANCE hinstCtfIme;
+
+ TRACE("(%p)\n", phinstCtfIme);
+
+ /* Load a CTF IME file if necessary */
+ hinstCtfIme = Imm32LoadCtfIme();
+
+ /* Create a thread manager of the CTF IME */
+ hr = CtfImeCreateThreadMgr();
+ if (hr == S_OK)
+ {
+ /* Update CI_... flags of the thread client info */
+ GetWin32ClientInfo()->CI_flags |= CI_AIMMACTIVATED; /* Activate AIMM */
+ GetWin32ClientInfo()->CI_flags &= ~CI_TSFDISABLED; /* Enable TSF */
+
+ /* Create the CTF input contexts */
+ ImmEnumInputContext(0, Imm32EnumCreateCtfICProc, 0);
+ }
+
+ if (phinstCtfIme)
+ *phinstCtfIme = hinstCtfIme;
+
+ return hr;
+}
+
+/***********************************************************************
+ * CtfAImmDeactivate (IMM32.@)
+ *
+ * This function de-activates "Active IMM" (AIMM) and TSF.
+ */
+HRESULT WINAPI
+CtfAImmDeactivate(
+ _In_ BOOL bDestroy)
+{
+ HRESULT hr;
+
+ if (!bDestroy)
+ return E_FAIL;
+
+ hr = CtfImeDestroyThreadMgr();
+ if (hr == S_OK)
+ {
+ GetWin32ClientInfo()->CI_flags &= ~CI_AIMMACTIVATED; /* Deactivate AIMM
*/
+ GetWin32ClientInfo()->CI_flags |= CI_TSFDISABLED; /* Disable TSF */
+ }
+
+ return hr;
+}
+
/***********************************************************************
* CtfImmIsCiceroEnabled (IMM32.@)
+ *
+ * @return TRUE if Cicero is enabled.
*/
-BOOL WINAPI CtfImmIsCiceroEnabled(VOID)
+BOOL WINAPI
+CtfImmIsCiceroEnabled(VOID)
{
return IS_CICERO_MODE();
}
/***********************************************************************
* CtfImmIsTextFrameServiceDisabled(IMM32.@)
+ *
+ * @return TRUE if TSF is disabled.
*/
-BOOL WINAPI CtfImmIsTextFrameServiceDisabled(VOID)
+BOOL WINAPI
+CtfImmIsTextFrameServiceDisabled(VOID)
{
- return !!(GetWin32ClientInfo()->CI_flags & CI_TFSDISABLED);
+ return !!(GetWin32ClientInfo()->CI_flags & CI_TSFDISABLED);
}
/***********************************************************************
* CtfImmTIMActivate(IMM32.@)
*/
-HRESULT WINAPI CtfImmTIMActivate(HKL hKL)
+HRESULT WINAPI
+CtfImmTIMActivate(_In_ HKL hKL)
{
FIXME("(%p)\n", hKL);
return E_NOTIMPL;
@@ -81,7 +345,8 @@ HRESULT WINAPI CtfImmTIMActivate(HKL hKL)
/***********************************************************************
* CtfImmRestoreToolbarWnd(IMM32.@)
*/
-VOID WINAPI CtfImmRestoreToolbarWnd(DWORD dwStatus)
+VOID WINAPI
+CtfImmRestoreToolbarWnd(_In_ DWORD dwStatus)
{
FIXME("(0x%lx)\n", dwStatus);
}
@@ -89,7 +354,8 @@ VOID WINAPI CtfImmRestoreToolbarWnd(DWORD dwStatus)
/***********************************************************************
* CtfImmHideToolbarWnd(IMM32.@)
*/
-DWORD WINAPI CtfImmHideToolbarWnd(VOID)
+DWORD WINAPI
+CtfImmHideToolbarWnd(VOID)
{
FIXME("()\n");
return 0;
@@ -98,7 +364,12 @@ DWORD WINAPI CtfImmHideToolbarWnd(VOID)
/***********************************************************************
* CtfImmDispatchDefImeMessage(IMM32.@)
*/
-LRESULT WINAPI CtfImmDispatchDefImeMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM
lParam)
+LRESULT WINAPI
+CtfImmDispatchDefImeMessage(
+ _In_ HWND hWnd,
+ _In_ UINT uMsg,
+ _In_ WPARAM wParam,
+ _In_ LPARAM lParam)
{
/* FIXME("(%p, %u, %p, %p)\n", hWnd, uMsg, wParam, lParam); */
return 0;
@@ -107,7 +378,9 @@ LRESULT WINAPI CtfImmDispatchDefImeMessage(HWND hWnd, UINT uMsg,
WPARAM wParam,
/***********************************************************************
* CtfImmIsGuidMapEnable(IMM32.@)
*/
-BOOL WINAPI CtfImmIsGuidMapEnable(HIMC hIMC)
+BOOL WINAPI
+CtfImmIsGuidMapEnable(
+ _In_ HIMC hIMC)
{
DWORD dwThreadId;
HKL hKL;
@@ -138,7 +411,11 @@ BOOL WINAPI CtfImmIsGuidMapEnable(HIMC hIMC)
/***********************************************************************
* CtfImmGetGuidAtom(IMM32.@)
*/
-HRESULT WINAPI CtfImmGetGuidAtom(HIMC hIMC, DWORD dwUnknown, LPDWORD pdwGuidAtom)
+HRESULT WINAPI
+CtfImmGetGuidAtom(
+ _In_ HIMC hIMC,
+ _In_ DWORD dwUnknown,
+ _Out_ LPDWORD pdwGuidAtom)
{
HRESULT hr = E_FAIL;
PIMEDPI pImeDpi;
diff --git a/dll/win32/imm32/imm32.spec b/dll/win32/imm32/imm32.spec
index 92ac837fffd..eec7202482a 100644
--- a/dll/win32/imm32/imm32.spec
+++ b/dll/win32/imm32/imm32.spec
@@ -1,3 +1,5 @@
+@ stdcall CtfAImmActivate(ptr)
+@ stdcall CtfAImmDeactivate(long)
@ stdcall CtfImmIsCiceroEnabled()
@ stdcall CtfImmIsTextFrameServiceDisabled()
@ stdcall CtfImmTIMActivate(ptr)
diff --git a/dll/win32/imm32/precomp.h b/dll/win32/imm32/precomp.h
index 6db1f8d6e4d..6e0512af409 100644
--- a/dll/win32/imm32/precomp.h
+++ b/dll/win32/imm32/precomp.h
@@ -143,7 +143,6 @@ BOOL WINAPI Imm32IsImcAnsi(HIMC hIMC);
#define IS_CROSS_THREAD_HIMC(hIMC)
IS_TRUE_UNEXPECTEDLY(Imm32IsCrossThreadAccess(hIMC))
#define IS_CROSS_PROCESS_HWND(hWnd)
IS_TRUE_UNEXPECTEDLY(Imm32IsCrossProcessAccess(hWnd))
#define ImeDpi_IsUnicode(pImeDpi) ((pImeDpi)->ImeInfo.fdwProperty &
IME_PROP_UNICODE)
-#define IS_16BIT_MODE() (GetWin32ClientInfo()->dwTIFlags &
TIF_16BIT)
DWORD APIENTRY
CandidateListWideToAnsi(const CANDIDATELIST *pWideCL, LPCANDIDATELIST pAnsiCL, DWORD
dwBufLen,
@@ -189,3 +188,6 @@ PTHREADINFO FASTCALL Imm32CurrentPti(VOID);
HBITMAP Imm32LoadBitmapFromBytes(const BYTE *pb);
BOOL Imm32StoreBitmapToBytes(HBITMAP hbm, LPBYTE pbData, DWORD cbDataMax);
+
+HRESULT CtfImmTIMCreateInputContext(_In_ HIMC hIMC);
+HRESULT CtfImmTIMDestroyInputContext(_In_ HIMC hIMC);
diff --git a/sdk/include/reactos/imm32_undoc.h b/sdk/include/reactos/imm32_undoc.h
index dadff68b031..49cb047182a 100644
--- a/sdk/include/reactos/imm32_undoc.h
+++ b/sdk/include/reactos/imm32_undoc.h
@@ -14,14 +14,16 @@ extern "C" {
BOOL WINAPI
ImmGetImeInfoEx(PIMEINFOEX pImeInfoEx, IMEINFOEXCLASS SearchType, PVOID pvSearchKey);
+BOOL WINAPI ImmLoadLayout(HKL hKL, PIMEINFOEX pImeInfoEx);
PCLIENTIMC WINAPI ImmLockClientImc(HIMC hImc);
VOID WINAPI ImmUnlockClientImc(PCLIENTIMC pClientImc);
PIMEDPI WINAPI ImmLockImeDpi(HKL hKL);
VOID WINAPI ImmUnlockImeDpi(PIMEDPI pImeDpi);
-HRESULT APIENTRY CtfImmTIMCreateInputContext(HIMC hIMC);
-HRESULT APIENTRY CtfImmTIMDestroyInputContext(HIMC hIMC);
HRESULT WINAPI CtfImmTIMActivate(HKL hKL);
+HRESULT WINAPI CtfAImmActivate(_Out_opt_ HINSTANCE *phinstCtfIme);
+HRESULT WINAPI CtfAImmDeactivate(_In_ BOOL bDestroy);
+
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/win32ss/include/ntuser.h b/win32ss/include/ntuser.h
index e1a3ee9788a..1cb0fb2db4c 100644
--- a/win32ss/include/ntuser.h
+++ b/win32ss/include/ntuser.h
@@ -302,8 +302,9 @@ typedef struct _CALLBACKWND
#define CI_INITTHREAD 0x00000008
#define CI_CURTHPRHOOK 0x00000010
#define CI_CLASSESREGISTERED 0x00000020
-#define CI_IMMACTIVATE 0x00000040
-#define CI_TFSDISABLED 0x00000400
+#define CI_IMMACTIVATE 0x00000040 /* IMM/IME (Asian input) */
+#define CI_TSFDISABLED 0x00000400 /* TSF (Text Services Framework a.k.a. Cicero)
*/
+#define CI_AIMMACTIVATED 0x00000800 /* Active IMM (AIMM) */
/*
* CLIENTINFO structure.
@@ -1231,6 +1232,7 @@ typedef enum IMEINFOEXCLASS
#define IS_IME_HKL(hkl) ((((ULONG_PTR)(hkl)) & 0xF0000000) == 0xE0000000)
#define IS_IMM_MODE() (gpsi && (gpsi->dwSRVIFlags & SRVINFO_IMM32))
#define IS_CICERO_MODE() (gpsi && (gpsi->dwSRVIFlags &
SRVINFO_CICERO_ENABLED))
+#define IS_16BIT_MODE() (GetWin32ClientInfo()->dwTIFlags & TIF_16BIT)
typedef struct tagIMEUI
{