[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
This commit is contained in:
Katayama Hirofumi MZ 2023-10-31 22:45:28 +09:00 committed by GitHub
parent 25b7447818
commit b3194e320c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 335 additions and 32 deletions

View file

@ -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@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))

View file

@ -2,7 +2,7 @@
* PROJECT: ReactOS IMM32 * PROJECT: ReactOS IMM32
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
* PURPOSE: Implementing the IMM32 Cicero-aware Text Framework (CTF) * PURPOSE: Implementing the IMM32 Cicero-aware Text Framework (CTF)
* COPYRIGHT: Copyright 2022 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com> * COPYRIGHT: Copyright 2022-2023 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
*/ */
#include "precomp.h" #include "precomp.h"
@ -17,62 +17,326 @@ WINE_DEFAULT_DEBUG_CHANNEL(imm);
* https://googleprojectzero.blogspot.com/2019/08/down-rabbit-hole.html * 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()) if (!Imm32LoadCtfIme())
return E_FAIL; return E_FAIL;
#if 1 return CTF_IME_FN(CtfImeCreateThreadMgr)();
FIXME("(%p)\n", hIMC);
return E_NOTIMPL;
#else
return g_pfnCtfImeDestroyInputContext(hIMC);
#endif
} }
// Win: CtfImmTIMDestroyInputContext /***********************************************************************
HRESULT APIENTRY CtfImmTIMDestroyInputContext(HIMC hIMC) * 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 */
}
/***********************************************************************
* This function calls CtfImeDestroyInputContext if possible.
*/
HRESULT
CtfImmTIMDestroyInputContext(
_In_ HIMC hIMC)
{ {
if (!IS_CICERO_MODE() || (GetWin32ClientInfo()->dwCompatFlags2 & 2)) if (!IS_CICERO_MODE() || (GetWin32ClientInfo()->dwCompatFlags2 & 2))
return E_NOINTERFACE; return E_NOINTERFACE;
return Imm32CtfImeDestroyInputContext(hIMC); return CtfImeDestroyInputContext(hIMC);
} }
// Win: CtfImmTIMCreateInputContext HRESULT
HRESULT APIENTRY CtfImmTIMCreateInputContext(HIMC hIMC) CtfImmTIMCreateInputContext(
_In_ HIMC hIMC)
{ {
TRACE("(%p)\n", hIMC); TRACE("(%p)\n", hIMC);
return E_NOTIMPL; return E_NOTIMPL;
} }
/*********************************************************************** /***********************************************************************
* CtfImmIsCiceroEnabled (IMM32.@) * CtfAImmActivate (IMM32.@)
*
* This function activates "Active IMM" (AIMM) and TSF.
*/ */
BOOL WINAPI CtfImmIsCiceroEnabled(VOID) 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)
{ {
return IS_CICERO_MODE(); return IS_CICERO_MODE();
} }
/*********************************************************************** /***********************************************************************
* CtfImmIsTextFrameServiceDisabled(IMM32.@) * 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.@) * CtfImmTIMActivate(IMM32.@)
*/ */
HRESULT WINAPI CtfImmTIMActivate(HKL hKL) HRESULT WINAPI
CtfImmTIMActivate(_In_ HKL hKL)
{ {
FIXME("(%p)\n", hKL); FIXME("(%p)\n", hKL);
return E_NOTIMPL; return E_NOTIMPL;
@ -81,7 +345,8 @@ HRESULT WINAPI CtfImmTIMActivate(HKL hKL)
/*********************************************************************** /***********************************************************************
* CtfImmRestoreToolbarWnd(IMM32.@) * CtfImmRestoreToolbarWnd(IMM32.@)
*/ */
VOID WINAPI CtfImmRestoreToolbarWnd(DWORD dwStatus) VOID WINAPI
CtfImmRestoreToolbarWnd(_In_ DWORD dwStatus)
{ {
FIXME("(0x%lx)\n", dwStatus); FIXME("(0x%lx)\n", dwStatus);
} }
@ -89,7 +354,8 @@ VOID WINAPI CtfImmRestoreToolbarWnd(DWORD dwStatus)
/*********************************************************************** /***********************************************************************
* CtfImmHideToolbarWnd(IMM32.@) * CtfImmHideToolbarWnd(IMM32.@)
*/ */
DWORD WINAPI CtfImmHideToolbarWnd(VOID) DWORD WINAPI
CtfImmHideToolbarWnd(VOID)
{ {
FIXME("()\n"); FIXME("()\n");
return 0; return 0;
@ -98,7 +364,12 @@ DWORD WINAPI CtfImmHideToolbarWnd(VOID)
/*********************************************************************** /***********************************************************************
* CtfImmDispatchDefImeMessage(IMM32.@) * 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); */ /* FIXME("(%p, %u, %p, %p)\n", hWnd, uMsg, wParam, lParam); */
return 0; return 0;
@ -107,7 +378,9 @@ LRESULT WINAPI CtfImmDispatchDefImeMessage(HWND hWnd, UINT uMsg, WPARAM wParam,
/*********************************************************************** /***********************************************************************
* CtfImmIsGuidMapEnable(IMM32.@) * CtfImmIsGuidMapEnable(IMM32.@)
*/ */
BOOL WINAPI CtfImmIsGuidMapEnable(HIMC hIMC) BOOL WINAPI
CtfImmIsGuidMapEnable(
_In_ HIMC hIMC)
{ {
DWORD dwThreadId; DWORD dwThreadId;
HKL hKL; HKL hKL;
@ -138,7 +411,11 @@ BOOL WINAPI CtfImmIsGuidMapEnable(HIMC hIMC)
/*********************************************************************** /***********************************************************************
* CtfImmGetGuidAtom(IMM32.@) * 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; HRESULT hr = E_FAIL;
PIMEDPI pImeDpi; PIMEDPI pImeDpi;

View file

@ -1,3 +1,5 @@
@ stdcall CtfAImmActivate(ptr)
@ stdcall CtfAImmDeactivate(long)
@ stdcall CtfImmIsCiceroEnabled() @ stdcall CtfImmIsCiceroEnabled()
@ stdcall CtfImmIsTextFrameServiceDisabled() @ stdcall CtfImmIsTextFrameServiceDisabled()
@ stdcall CtfImmTIMActivate(ptr) @ stdcall CtfImmTIMActivate(ptr)

View file

@ -143,7 +143,6 @@ BOOL WINAPI Imm32IsImcAnsi(HIMC hIMC);
#define IS_CROSS_THREAD_HIMC(hIMC) IS_TRUE_UNEXPECTEDLY(Imm32IsCrossThreadAccess(hIMC)) #define IS_CROSS_THREAD_HIMC(hIMC) IS_TRUE_UNEXPECTEDLY(Imm32IsCrossThreadAccess(hIMC))
#define IS_CROSS_PROCESS_HWND(hWnd) IS_TRUE_UNEXPECTEDLY(Imm32IsCrossProcessAccess(hWnd)) #define IS_CROSS_PROCESS_HWND(hWnd) IS_TRUE_UNEXPECTEDLY(Imm32IsCrossProcessAccess(hWnd))
#define ImeDpi_IsUnicode(pImeDpi) ((pImeDpi)->ImeInfo.fdwProperty & IME_PROP_UNICODE) #define ImeDpi_IsUnicode(pImeDpi) ((pImeDpi)->ImeInfo.fdwProperty & IME_PROP_UNICODE)
#define IS_16BIT_MODE() (GetWin32ClientInfo()->dwTIFlags & TIF_16BIT)
DWORD APIENTRY DWORD APIENTRY
CandidateListWideToAnsi(const CANDIDATELIST *pWideCL, LPCANDIDATELIST pAnsiCL, DWORD dwBufLen, CandidateListWideToAnsi(const CANDIDATELIST *pWideCL, LPCANDIDATELIST pAnsiCL, DWORD dwBufLen,
@ -189,3 +188,6 @@ PTHREADINFO FASTCALL Imm32CurrentPti(VOID);
HBITMAP Imm32LoadBitmapFromBytes(const BYTE *pb); HBITMAP Imm32LoadBitmapFromBytes(const BYTE *pb);
BOOL Imm32StoreBitmapToBytes(HBITMAP hbm, LPBYTE pbData, DWORD cbDataMax); BOOL Imm32StoreBitmapToBytes(HBITMAP hbm, LPBYTE pbData, DWORD cbDataMax);
HRESULT CtfImmTIMCreateInputContext(_In_ HIMC hIMC);
HRESULT CtfImmTIMDestroyInputContext(_In_ HIMC hIMC);

View file

@ -14,14 +14,16 @@ extern "C" {
BOOL WINAPI BOOL WINAPI
ImmGetImeInfoEx(PIMEINFOEX pImeInfoEx, IMEINFOEXCLASS SearchType, PVOID pvSearchKey); ImmGetImeInfoEx(PIMEINFOEX pImeInfoEx, IMEINFOEXCLASS SearchType, PVOID pvSearchKey);
BOOL WINAPI ImmLoadLayout(HKL hKL, PIMEINFOEX pImeInfoEx);
PCLIENTIMC WINAPI ImmLockClientImc(HIMC hImc); PCLIENTIMC WINAPI ImmLockClientImc(HIMC hImc);
VOID WINAPI ImmUnlockClientImc(PCLIENTIMC pClientImc); VOID WINAPI ImmUnlockClientImc(PCLIENTIMC pClientImc);
PIMEDPI WINAPI ImmLockImeDpi(HKL hKL); PIMEDPI WINAPI ImmLockImeDpi(HKL hKL);
VOID WINAPI ImmUnlockImeDpi(PIMEDPI pImeDpi); VOID WINAPI ImmUnlockImeDpi(PIMEDPI pImeDpi);
HRESULT APIENTRY CtfImmTIMCreateInputContext(HIMC hIMC);
HRESULT APIENTRY CtfImmTIMDestroyInputContext(HIMC hIMC);
HRESULT WINAPI CtfImmTIMActivate(HKL hKL); HRESULT WINAPI CtfImmTIMActivate(HKL hKL);
HRESULT WINAPI CtfAImmActivate(_Out_opt_ HINSTANCE *phinstCtfIme);
HRESULT WINAPI CtfAImmDeactivate(_In_ BOOL bDestroy);
#ifdef __cplusplus #ifdef __cplusplus
} // extern "C" } // extern "C"
#endif #endif

View file

@ -302,8 +302,9 @@ typedef struct _CALLBACKWND
#define CI_INITTHREAD 0x00000008 #define CI_INITTHREAD 0x00000008
#define CI_CURTHPRHOOK 0x00000010 #define CI_CURTHPRHOOK 0x00000010
#define CI_CLASSESREGISTERED 0x00000020 #define CI_CLASSESREGISTERED 0x00000020
#define CI_IMMACTIVATE 0x00000040 #define CI_IMMACTIVATE 0x00000040 /* IMM/IME (Asian input) */
#define CI_TFSDISABLED 0x00000400 #define CI_TSFDISABLED 0x00000400 /* TSF (Text Services Framework a.k.a. Cicero) */
#define CI_AIMMACTIVATED 0x00000800 /* Active IMM (AIMM) */
/* /*
* CLIENTINFO structure. * CLIENTINFO structure.
@ -1231,6 +1232,7 @@ typedef enum IMEINFOEXCLASS
#define IS_IME_HKL(hkl) ((((ULONG_PTR)(hkl)) & 0xF0000000) == 0xE0000000) #define IS_IME_HKL(hkl) ((((ULONG_PTR)(hkl)) & 0xF0000000) == 0xE0000000)
#define IS_IMM_MODE() (gpsi && (gpsi->dwSRVIFlags & SRVINFO_IMM32)) #define IS_IMM_MODE() (gpsi && (gpsi->dwSRVIFlags & SRVINFO_IMM32))
#define IS_CICERO_MODE() (gpsi && (gpsi->dwSRVIFlags & SRVINFO_CICERO_ENABLED)) #define IS_CICERO_MODE() (gpsi && (gpsi->dwSRVIFlags & SRVINFO_CICERO_ENABLED))
#define IS_16BIT_MODE() (GetWin32ClientInfo()->dwTIFlags & TIF_16BIT)
typedef struct tagIMEUI typedef struct tagIMEUI
{ {