mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 16:36:33 +00:00
[IMM32][SDK][NTUSER] Implement CtfImmTIMActivate (#6041)
- Add Imm32InitTLS, Imm32AllocateTLS, Imm32GetTLS, Imm32GetCoInitCountSkip, Imm32IncCoInitCountSkip, and Imm32DecCoInitCountSkip helper functions to control the TLS data. - Introduce "CoInitialize Spy" (ISPY) to manage COM initialization status. - Implement CtfImmCoInitialize and CtfImmCoUninitialize. - Implement CtfImmEnterCoInitCountSkipMode and CtfImmLeaveCoInitCountSkipMode. - Implement CtfImmLastEnabledWndDestroy, ImmDisableTextFrameService, and CtfImmTIMActivate. CORE-19268
This commit is contained in:
parent
01a8288d28
commit
931224fbe1
8 changed files with 683 additions and 46 deletions
|
@ -45,6 +45,6 @@ list(APPEND imm32_rc_deps
|
|||
add_library(imm32 MODULE ${SOURCE} imm32.rc)
|
||||
set_module_type(imm32 win32dll UNICODE ENTRYPOINT ImmDllInitialize 12)
|
||||
set_source_files_properties(imm32.rc PROPERTIES OBJECT_DEPENDS "${imm32_rc_deps}")
|
||||
target_link_libraries(imm32 wine win32ksys)
|
||||
target_link_libraries(imm32 wine win32ksys uuid)
|
||||
add_importlibs(imm32 advapi32 user32 gdi32 kernel32 ntdll)
|
||||
add_cd_file(TARGET imm32 DESTINATION reactos/system32 FOR all)
|
||||
|
|
|
@ -6,11 +6,83 @@
|
|||
*/
|
||||
|
||||
#include "precomp.h"
|
||||
#include <msctf.h>
|
||||
#include <ctfutb.h>
|
||||
#include <msctf.h> /* for ITfLangBarMgr */
|
||||
#include <objidl.h> /* for IInitializeSpy */
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(imm);
|
||||
|
||||
/* FIXME: Use RTL */
|
||||
static BOOL WINAPI RtlDllShutdownInProgress(VOID)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOL Imm32InsideLoaderLock(VOID)
|
||||
{
|
||||
return NtCurrentTeb()->ProcessEnvironmentBlock->LoaderLock->OwningThread ==
|
||||
NtCurrentTeb()->ClientId.UniqueThread;
|
||||
}
|
||||
|
||||
static BOOL
|
||||
Imm32IsInteractiveUserLogon(VOID)
|
||||
{
|
||||
BOOL bOK, IsMember = FALSE;
|
||||
PSID pSid;
|
||||
SID_IDENTIFIER_AUTHORITY IdentAuth = { SECURITY_NT_AUTHORITY };
|
||||
|
||||
if (!AllocateAndInitializeSid(&IdentAuth, 1, SECURITY_INTERACTIVE_RID,
|
||||
0, 0, 0, 0, 0, 0, 0, &pSid))
|
||||
{
|
||||
ERR("Error: %ld\n", GetLastError());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bOK = CheckTokenMembership(NULL, pSid, &IsMember);
|
||||
|
||||
if (pSid)
|
||||
FreeSid(pSid);
|
||||
|
||||
return bOK && IsMember;
|
||||
}
|
||||
|
||||
static BOOL
|
||||
Imm32IsRunningInMsoobe(VOID)
|
||||
{
|
||||
LPWSTR pchFilePart = NULL;
|
||||
WCHAR Buffer[MAX_PATH], FileName[MAX_PATH];
|
||||
|
||||
if (!GetModuleFileNameW(NULL, FileName, _countof(FileName)))
|
||||
return FALSE;
|
||||
|
||||
GetFullPathNameW(FileName, _countof(Buffer), Buffer, &pchFilePart);
|
||||
if (!pchFilePart)
|
||||
return FALSE;
|
||||
|
||||
return lstrcmpiW(pchFilePart, L"msoobe.exe") == 0;
|
||||
}
|
||||
|
||||
static BOOL
|
||||
Imm32IsCUASEnabledInRegistry(VOID)
|
||||
{
|
||||
HKEY hKey;
|
||||
LSTATUS error;
|
||||
DWORD dwType, dwData, cbData;
|
||||
|
||||
error = RegOpenKeyW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\CTF\\SystemShared", &hKey);
|
||||
if (error != ERROR_SUCCESS)
|
||||
return FALSE;
|
||||
|
||||
dwData = 0;
|
||||
cbData = sizeof(dwData);
|
||||
error = RegQueryValueExW(hKey, L"CUAS", NULL, &dwType, (LPBYTE)&dwData, &cbData);
|
||||
RegCloseKey(hKey);
|
||||
|
||||
if (error != ERROR_SUCCESS || dwType != REG_DWORD)
|
||||
return FALSE;
|
||||
|
||||
return !!dwData;
|
||||
}
|
||||
|
||||
BOOL
|
||||
Imm32GetFn(
|
||||
_Inout_opt_ FARPROC *ppfn,
|
||||
|
@ -110,6 +182,8 @@ FN_TF_InvalidAssemblyListCacheIfExist MSCTF_FN(TF_InvalidAssemblyListCacheIfExis
|
|||
|
||||
HRESULT Imm32TF_CreateLangBarMgr(_Inout_ ITfLangBarMgr **ppBarMgr)
|
||||
{
|
||||
TRACE("TF_CreateLangBarMgr(%p)\n", ppBarMgr);
|
||||
|
||||
if (!Imm32GetMsctfFn(TF_CreateLangBarMgr))
|
||||
return E_FAIL;
|
||||
|
||||
|
@ -118,6 +192,8 @@ HRESULT Imm32TF_CreateLangBarMgr(_Inout_ ITfLangBarMgr **ppBarMgr)
|
|||
|
||||
VOID Imm32TF_InvalidAssemblyListCacheIfExist(VOID)
|
||||
{
|
||||
TRACE("TF_InvalidAssemblyListCacheIfExist()\n");
|
||||
|
||||
if (!Imm32GetMsctfFn(TF_InvalidAssemblyListCacheIfExist))
|
||||
return;
|
||||
|
||||
|
@ -141,6 +217,9 @@ VOID Imm32TF_InvalidAssemblyListCacheIfExist(VOID)
|
|||
/* "Active IMM" compatibility flags */
|
||||
DWORD g_aimm_compat_flags = 0;
|
||||
|
||||
/* Disable CUAS? */
|
||||
BOOL g_disable_CUAS_flag = FALSE;
|
||||
|
||||
/* The instance of the CTF IME file */
|
||||
HINSTANCE g_hCtfIme = NULL;
|
||||
|
||||
|
@ -203,6 +282,384 @@ Imm32CheckAndApplyAppCompat(
|
|||
return pApphelpCheckIME(pszAppName);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* TLS (Thread-Local Storage)
|
||||
*
|
||||
* See: TlsAlloc
|
||||
*/
|
||||
|
||||
DWORD g_dwTLSIndex = -1;
|
||||
|
||||
/* IMM Thread-Local Storage (TLS) data */
|
||||
typedef struct IMMTLSDATA
|
||||
{
|
||||
IInitializeSpy *pSpy; /* CoInitialize Spy */
|
||||
DWORD dwUnknown1;
|
||||
ULARGE_INTEGER uliCookie; /* Spy requires a cookie for revoking */
|
||||
BOOL bDoCount; /* Is it counting? */
|
||||
DWORD dwSkipCount; /* The skipped count */
|
||||
BOOL bUninitializing; /* Is it uninitializing? */
|
||||
DWORD dwUnknown2;
|
||||
} IMMTLSDATA, *PIMMTLSDATA;
|
||||
|
||||
static VOID
|
||||
Imm32InitTLS(VOID)
|
||||
{
|
||||
RtlEnterCriticalSection(&gcsImeDpi);
|
||||
|
||||
if (g_dwTLSIndex == -1)
|
||||
g_dwTLSIndex = TlsAlloc();
|
||||
|
||||
RtlLeaveCriticalSection(&gcsImeDpi);
|
||||
}
|
||||
|
||||
static IMMTLSDATA*
|
||||
Imm32AllocateTLS(VOID)
|
||||
{
|
||||
IMMTLSDATA *pData;
|
||||
|
||||
if (g_dwTLSIndex == -1)
|
||||
return NULL;
|
||||
|
||||
pData = (IMMTLSDATA*)TlsGetValue(g_dwTLSIndex);
|
||||
if (pData)
|
||||
return pData;
|
||||
|
||||
pData = (IMMTLSDATA*)ImmLocalAlloc(HEAP_ZERO_MEMORY, sizeof(IMMTLSDATA));
|
||||
if (IS_NULL_UNEXPECTEDLY(pData))
|
||||
return NULL;
|
||||
|
||||
if (IS_FALSE_UNEXPECTEDLY(TlsSetValue(g_dwTLSIndex, pData)))
|
||||
{
|
||||
ImmLocalFree(pData);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pData;
|
||||
}
|
||||
|
||||
static IMMTLSDATA*
|
||||
Imm32GetTLS(VOID)
|
||||
{
|
||||
if (g_dwTLSIndex == -1)
|
||||
return NULL;
|
||||
|
||||
return (IMMTLSDATA*)TlsGetValue(g_dwTLSIndex);
|
||||
}
|
||||
|
||||
/* Get */
|
||||
static DWORD
|
||||
Imm32GetCoInitCountSkip(VOID)
|
||||
{
|
||||
IMMTLSDATA *pData = Imm32GetTLS();
|
||||
if (!pData)
|
||||
return 0;
|
||||
return pData->dwSkipCount;
|
||||
}
|
||||
|
||||
/* Increment */
|
||||
static DWORD
|
||||
Imm32IncCoInitCountSkip(VOID)
|
||||
{
|
||||
IMMTLSDATA *pData;
|
||||
DWORD dwOldSkipCount;
|
||||
|
||||
pData = Imm32GetTLS();
|
||||
if (!pData)
|
||||
return 0;
|
||||
|
||||
dwOldSkipCount = pData->dwSkipCount;
|
||||
if (pData->bDoCount)
|
||||
pData->dwSkipCount = dwOldSkipCount + 1;
|
||||
|
||||
return dwOldSkipCount;
|
||||
}
|
||||
|
||||
/* Decrement */
|
||||
static DWORD
|
||||
Imm32DecCoInitCountSkip(VOID)
|
||||
{
|
||||
DWORD dwSkipCount;
|
||||
IMMTLSDATA *pData;
|
||||
|
||||
pData = Imm32GetTLS();;
|
||||
if (!pData)
|
||||
return 0;
|
||||
|
||||
dwSkipCount = pData->dwSkipCount;
|
||||
if (pData->bDoCount)
|
||||
{
|
||||
if (dwSkipCount)
|
||||
pData->dwSkipCount = dwSkipCount - 1;
|
||||
}
|
||||
|
||||
return dwSkipCount;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* CtfImmEnterCoInitCountSkipMode (IMM32.@)
|
||||
*/
|
||||
VOID WINAPI CtfImmEnterCoInitCountSkipMode(VOID)
|
||||
{
|
||||
IMMTLSDATA *pData;
|
||||
|
||||
TRACE("()\n");
|
||||
|
||||
pData = Imm32GetTLS();
|
||||
if (pData)
|
||||
++(pData->bDoCount);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* CtfImmLeaveCoInitCountSkipMode (IMM32.@)
|
||||
*/
|
||||
BOOL WINAPI CtfImmLeaveCoInitCountSkipMode(VOID)
|
||||
{
|
||||
IMMTLSDATA *pData;
|
||||
|
||||
TRACE("()\n");
|
||||
|
||||
pData = Imm32GetTLS();
|
||||
if (!pData || !pData->bDoCount)
|
||||
return FALSE;
|
||||
|
||||
--(pData->bDoCount);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ISPY (I am not spy!)
|
||||
*
|
||||
* ISPY watches CoInitialize[Ex] / CoUninitialize to manage COM initialization status.
|
||||
*/
|
||||
|
||||
typedef struct ISPY
|
||||
{
|
||||
const IInitializeSpyVtbl *m_pSpyVtbl;
|
||||
LONG m_cRefs;
|
||||
} ISPY, *PISPY;
|
||||
|
||||
static STDMETHODIMP
|
||||
ISPY_QueryInterface(
|
||||
_Inout_ IInitializeSpy *pThis,
|
||||
_In_ REFIID riid,
|
||||
_Inout_ LPVOID *ppvObj)
|
||||
{
|
||||
ISPY *pSpy = (ISPY*)pThis;
|
||||
|
||||
if (!ppvObj)
|
||||
return E_INVALIDARG;
|
||||
|
||||
*ppvObj = NULL;
|
||||
|
||||
if (!IsEqualIID(riid, &IID_IUnknown) && !IsEqualIID(riid, &IID_IInitializeSpy))
|
||||
return E_NOINTERFACE;
|
||||
|
||||
++(pSpy->m_cRefs);
|
||||
*ppvObj = pSpy;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static STDMETHODIMP_(ULONG)
|
||||
ISPY_AddRef(
|
||||
_Inout_ IInitializeSpy *pThis)
|
||||
{
|
||||
ISPY *pSpy = (ISPY*)pThis;
|
||||
return ++pSpy->m_cRefs;
|
||||
}
|
||||
|
||||
static STDMETHODIMP_(ULONG)
|
||||
ISPY_Release(
|
||||
_Inout_ IInitializeSpy *pThis)
|
||||
{
|
||||
ISPY *pSpy = (ISPY*)pThis;
|
||||
if (--pSpy->m_cRefs == 0)
|
||||
{
|
||||
ImmLocalFree(pSpy);
|
||||
return 0;
|
||||
}
|
||||
return pSpy->m_cRefs;
|
||||
}
|
||||
|
||||
/*
|
||||
* (Pre/Post)(Initialize/Uninitialize) will be automatically called from OLE32
|
||||
* as the results of watching.
|
||||
*/
|
||||
|
||||
static STDMETHODIMP
|
||||
ISPY_PreInitialize(
|
||||
_Inout_ IInitializeSpy *pThis,
|
||||
_In_ DWORD dwCoInit,
|
||||
_In_ DWORD dwCurThreadAptRefs)
|
||||
{
|
||||
DWORD cCount;
|
||||
|
||||
UNREFERENCED_PARAMETER(pThis);
|
||||
|
||||
cCount = Imm32IncCoInitCountSkip();
|
||||
if (!dwCoInit &&
|
||||
(dwCurThreadAptRefs == cCount + 1) &&
|
||||
(GetWin32ClientInfo()->CI_flags & CI_CTFCOINIT))
|
||||
{
|
||||
Imm32ActivateOrDeactivateTIM(FALSE);
|
||||
CtfImmCoUninitialize();
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static STDMETHODIMP
|
||||
ISPY_PostInitialize(
|
||||
_Inout_ IInitializeSpy *pThis,
|
||||
_In_ HRESULT hrCoInit,
|
||||
_In_ DWORD dwCoInit,
|
||||
_In_ DWORD dwNewThreadAptRefs)
|
||||
{
|
||||
DWORD CoInitCountSkip;
|
||||
|
||||
UNREFERENCED_PARAMETER(pThis);
|
||||
UNREFERENCED_PARAMETER(dwCoInit);
|
||||
|
||||
CoInitCountSkip = Imm32GetCoInitCountSkip();
|
||||
|
||||
if ((hrCoInit != S_FALSE) ||
|
||||
(dwNewThreadAptRefs != CoInitCountSkip + 2) ||
|
||||
!(GetWin32ClientInfo()->CI_flags & CI_CTFCOINIT))
|
||||
{
|
||||
return hrCoInit;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static STDMETHODIMP
|
||||
ISPY_PreUninitialize(
|
||||
_Inout_ IInitializeSpy *pThis,
|
||||
_In_ DWORD dwCurThreadAptRefs)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(pThis);
|
||||
|
||||
if (dwCurThreadAptRefs == 1 &&
|
||||
!RtlDllShutdownInProgress() &&
|
||||
!Imm32InsideLoaderLock() &&
|
||||
(GetWin32ClientInfo()->CI_flags & CI_CTFCOINIT))
|
||||
{
|
||||
IMMTLSDATA *pData = Imm32GetTLS();
|
||||
if (pData && !pData->bUninitializing)
|
||||
Imm32CoInitializeEx();
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static STDMETHODIMP
|
||||
ISPY_PostUninitialize(
|
||||
_In_ IInitializeSpy *pThis,
|
||||
_In_ DWORD dwNewThreadAptRefs)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(pThis);
|
||||
UNREFERENCED_PARAMETER(dwNewThreadAptRefs);
|
||||
Imm32DecCoInitCountSkip();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static const IInitializeSpyVtbl g_vtblISPY =
|
||||
{
|
||||
ISPY_QueryInterface,
|
||||
ISPY_AddRef,
|
||||
ISPY_Release,
|
||||
ISPY_PreInitialize,
|
||||
ISPY_PostInitialize,
|
||||
ISPY_PreUninitialize,
|
||||
ISPY_PostUninitialize,
|
||||
};
|
||||
|
||||
static ISPY*
|
||||
Imm32AllocIMMISPY(VOID)
|
||||
{
|
||||
ISPY *pSpy = (ISPY*)ImmLocalAlloc(0, sizeof(ISPY));
|
||||
if (!pSpy)
|
||||
return NULL;
|
||||
|
||||
pSpy->m_pSpyVtbl = &g_vtblISPY;
|
||||
pSpy->m_cRefs = 1;
|
||||
return pSpy;
|
||||
}
|
||||
|
||||
#define Imm32DeleteIMMISPY(pSpy) ImmLocalFree(pSpy)
|
||||
|
||||
/***********************************************************************
|
||||
* CtfImmCoInitialize (Not exported)
|
||||
*/
|
||||
HRESULT
|
||||
CtfImmCoInitialize(VOID)
|
||||
{
|
||||
HRESULT hr;
|
||||
IMMTLSDATA *pData;
|
||||
ISPY *pSpy;
|
||||
|
||||
if (GetWin32ClientInfo()->CI_flags & CI_CTFCOINIT)
|
||||
return S_OK; /* Already initialized */
|
||||
|
||||
hr = Imm32CoInitializeEx();
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return hr; /* CoInitializeEx failed */
|
||||
|
||||
GetWin32ClientInfo()->CI_flags |= CI_CTFCOINIT;
|
||||
Imm32InitTLS();
|
||||
|
||||
pData = Imm32AllocateTLS();
|
||||
if (!pData || pData->pSpy)
|
||||
return S_OK; /* Cannot allocate or already it has a spy */
|
||||
|
||||
pSpy = Imm32AllocIMMISPY();
|
||||
pData->pSpy = (IInitializeSpy*)pSpy;
|
||||
if (IS_NULL_UNEXPECTEDLY(pSpy))
|
||||
return S_OK; /* Cannot allocate a spy */
|
||||
|
||||
if (FAILED_UNEXPECTEDLY(Imm32CoRegisterInitializeSpy(pData->pSpy, &pData->uliCookie)))
|
||||
{
|
||||
/* Failed to register the spy */
|
||||
Imm32DeleteIMMISPY(pData->pSpy);
|
||||
pData->pSpy = NULL;
|
||||
pData->uliCookie.QuadPart = 0;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* CtfImmCoUninitialize (IMM32.@)
|
||||
*/
|
||||
VOID WINAPI
|
||||
CtfImmCoUninitialize(VOID)
|
||||
{
|
||||
IMMTLSDATA *pData;
|
||||
|
||||
if (!(GetWin32ClientInfo()->CI_flags & CI_CTFCOINIT))
|
||||
return; /* Not CoInitialize'd */
|
||||
|
||||
pData = Imm32GetTLS();
|
||||
if (pData)
|
||||
{
|
||||
pData->bUninitializing = TRUE;
|
||||
Imm32CoUninitialize(); /* Do CoUninitialize */
|
||||
pData->bUninitializing = FALSE;
|
||||
|
||||
GetWin32ClientInfo()->CI_flags &= ~CI_CTFCOINIT;
|
||||
}
|
||||
|
||||
pData = Imm32AllocateTLS();
|
||||
if (!pData || !pData->pSpy)
|
||||
return; /* There were no spy */
|
||||
|
||||
/* Our work is done. We don't need spies like you anymore. */
|
||||
Imm32CoRevokeInitializeSpy(pData->uliCookie);
|
||||
ISPY_Release(pData->pSpy);
|
||||
pData->pSpy = NULL;
|
||||
pData->uliCookie.QuadPart = 0;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* This function loads the CTF IME file if necessary and establishes
|
||||
* communication with the CTF IME.
|
||||
|
@ -286,6 +743,8 @@ Imm32LoadCtfIme(VOID)
|
|||
HRESULT
|
||||
CtfImeCreateThreadMgr(VOID)
|
||||
{
|
||||
TRACE("()\n");
|
||||
|
||||
if (!Imm32LoadCtfIme())
|
||||
return E_FAIL;
|
||||
|
||||
|
@ -298,6 +757,8 @@ CtfImeCreateThreadMgr(VOID)
|
|||
HRESULT
|
||||
CtfImeDestroyThreadMgr(VOID)
|
||||
{
|
||||
TRACE("()\n");
|
||||
|
||||
if (!Imm32LoadCtfIme())
|
||||
return E_FAIL;
|
||||
|
||||
|
@ -362,6 +823,8 @@ HRESULT
|
|||
CtfImeCreateInputContext(
|
||||
_In_ HIMC hIMC)
|
||||
{
|
||||
TRACE("(%p)\n", hIMC);
|
||||
|
||||
if (!Imm32LoadCtfIme())
|
||||
return E_FAIL;
|
||||
|
||||
|
@ -374,6 +837,8 @@ CtfImeCreateInputContext(
|
|||
HRESULT
|
||||
CtfImeDestroyInputContext(_In_ HIMC hIMC)
|
||||
{
|
||||
TRACE("(%p)\n", hIMC);
|
||||
|
||||
if (!Imm32LoadCtfIme())
|
||||
return E_FAIL;
|
||||
|
||||
|
@ -394,8 +859,61 @@ Imm32EnumCreateCtfICProc(
|
|||
}
|
||||
|
||||
/***********************************************************************
|
||||
* This function calls CtfImeDestroyInputContext if possible.
|
||||
* Thread Input Manager (TIM)
|
||||
*/
|
||||
|
||||
static BOOL
|
||||
Imm32IsTIMDisabledInRegistry(VOID)
|
||||
{
|
||||
DWORD dwData, cbData;
|
||||
HKEY hKey;
|
||||
LSTATUS error;
|
||||
|
||||
error = RegOpenKeyW(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\CTF", &hKey);
|
||||
if (error != ERROR_SUCCESS)
|
||||
return FALSE;
|
||||
|
||||
dwData = 0;
|
||||
cbData = sizeof(dwData);
|
||||
RegQueryValueExW(hKey, L"Disable Thread Input Manager", NULL, NULL, (LPBYTE)&dwData, &cbData);
|
||||
RegCloseKey(hKey);
|
||||
return !!dwData;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
Imm32ActivateOrDeactivateTIM(
|
||||
_In_ BOOL bCreate)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
if (!IS_CICERO_MODE() || IS_16BIT_MODE() ||
|
||||
!(GetWin32ClientInfo()->CI_flags & CI_CTFCOINIT))
|
||||
{
|
||||
return S_OK; /* No need to activate/de-activate TIM */
|
||||
}
|
||||
|
||||
if (bCreate)
|
||||
{
|
||||
if (!(GetWin32ClientInfo()->CI_flags & CI_CTFTIM))
|
||||
{
|
||||
hr = CtfImeCreateThreadMgr();
|
||||
if (SUCCEEDED(hr))
|
||||
GetWin32ClientInfo()->CI_flags |= CI_CTFTIM;
|
||||
}
|
||||
}
|
||||
else /* Destroy */
|
||||
{
|
||||
if (GetWin32ClientInfo()->CI_flags & CI_CTFTIM)
|
||||
{
|
||||
hr = CtfImeDestroyThreadMgr();
|
||||
if (SUCCEEDED(hr))
|
||||
GetWin32ClientInfo()->CI_flags &= ~CI_CTFTIM;
|
||||
}
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
CtfImmTIMDestroyInputContext(
|
||||
_In_ HIMC hIMC)
|
||||
|
@ -422,34 +940,34 @@ CtfImmTIMCreateInputContext(
|
|||
|
||||
if (GetWin32ClientInfo()->CI_flags & CI_AIMMACTIVATED)
|
||||
{
|
||||
if (!pClientImc->bUnknown4)
|
||||
if (!pClientImc->bCtfIme)
|
||||
{
|
||||
dwImeThreadId = NtUserQueryInputContext(hIMC, QIC_INPUTTHREADID);
|
||||
dwCurrentThreadId = GetCurrentThreadId();
|
||||
if (dwImeThreadId == dwCurrentThreadId)
|
||||
{
|
||||
pClientImc->bUnknown4 = 1;
|
||||
pClientImc->bCtfIme = TRUE;
|
||||
hr = CtfImeCreateInputContext(hIMC);
|
||||
if (FAILED(hr))
|
||||
pClientImc->bUnknown4 = 0;
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
pClientImc->bCtfIme = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(GetWin32ClientInfo()->CI_flags & 0x100))
|
||||
if (!(GetWin32ClientInfo()->CI_flags & CI_CTFTIM))
|
||||
return S_OK;
|
||||
|
||||
if (!pClientImc->bUnknown4)
|
||||
if (!pClientImc->bCtfIme)
|
||||
{
|
||||
dwImeThreadId = NtUserQueryInputContext(hIMC, QIC_INPUTTHREADID);
|
||||
dwCurrentThreadId = GetCurrentThreadId();
|
||||
if ((dwImeThreadId == dwCurrentThreadId) && IS_CICERO_MODE() && !IS_16BIT_MODE())
|
||||
{
|
||||
pClientImc->bUnknown4 = 1;
|
||||
pClientImc->bCtfIme = TRUE;
|
||||
hr = CtfImeCreateInputContext(hIMC);
|
||||
if (FAILED(hr))
|
||||
pClientImc->bUnknown4 = 0;
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
pClientImc->bCtfIme = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -458,6 +976,19 @@ CtfImmTIMCreateInputContext(
|
|||
return hr;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* CtfImmLastEnabledWndDestroy (IMM32.@)
|
||||
*
|
||||
* Same as Imm32ActivateOrDeactivateTIM but its naming is improper.
|
||||
*/
|
||||
HRESULT WINAPI
|
||||
CtfImmLastEnabledWndDestroy(
|
||||
_In_ BOOL bCreate)
|
||||
{
|
||||
TRACE("(%d)\n", bCreate);
|
||||
return Imm32ActivateOrDeactivateTIM(bCreate);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* CtfAImmActivate (IMM32.@)
|
||||
*
|
||||
|
@ -529,7 +1060,7 @@ CtfImmIsCiceroEnabled(VOID)
|
|||
}
|
||||
|
||||
/***********************************************************************
|
||||
* CtfImmIsTextFrameServiceDisabled(IMM32.@)
|
||||
* CtfImmIsTextFrameServiceDisabled (IMM32.@)
|
||||
*
|
||||
* @return TRUE if TSF is disabled.
|
||||
*/
|
||||
|
@ -540,17 +1071,123 @@ CtfImmIsTextFrameServiceDisabled(VOID)
|
|||
}
|
||||
|
||||
/***********************************************************************
|
||||
* CtfImmTIMActivate(IMM32.@)
|
||||
* ImmDisableTextFrameService (IMM32.@)
|
||||
*/
|
||||
BOOL WINAPI
|
||||
ImmDisableTextFrameService(_In_ DWORD dwThreadId)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
TRACE("(0x%lX)\n", dwThreadId);
|
||||
|
||||
if (dwThreadId == -1)
|
||||
g_disable_CUAS_flag = TRUE;
|
||||
|
||||
if ((dwThreadId && !g_disable_CUAS_flag) || (GetWin32ClientInfo()->CI_flags & CI_TSFDISABLED))
|
||||
return TRUE;
|
||||
|
||||
GetWin32ClientInfo()->CI_flags |= CI_TSFDISABLED;
|
||||
|
||||
if (IS_CICERO_MODE() && !IS_16BIT_MODE() &&
|
||||
(GetWin32ClientInfo()->CI_flags & CI_CTFCOINIT) &&
|
||||
(GetWin32ClientInfo()->CI_flags & CI_CTFTIM))
|
||||
{
|
||||
hr = CtfImeDestroyThreadMgr();
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
GetWin32ClientInfo()->CI_flags &= ~CI_CTFTIM;
|
||||
CtfImmCoUninitialize();
|
||||
}
|
||||
}
|
||||
|
||||
return hr == S_OK;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* CtfImmTIMActivate (IMM32.@)
|
||||
*
|
||||
* Activates Thread Input Manager (TIM) in the thread.
|
||||
*/
|
||||
HRESULT WINAPI
|
||||
CtfImmTIMActivate(_In_ HKL hKL)
|
||||
{
|
||||
FIXME("(%p)\n", hKL);
|
||||
return E_NOTIMPL;
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
TRACE("(%p)\n", hKL);
|
||||
|
||||
if (g_disable_CUAS_flag)
|
||||
{
|
||||
TRACE("g_disable_CUAS_flag\n");
|
||||
GetWin32ClientInfo()->CI_flags |= CI_TSFDISABLED;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (GetWin32ClientInfo()->CI_flags & CI_TSFDISABLED)
|
||||
{
|
||||
TRACE("CI_TSFDISABLED\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (Imm32IsTIMDisabledInRegistry())
|
||||
{
|
||||
TRACE("TIM is disabled in registry\n");
|
||||
GetWin32ClientInfo()->CI_flags |= CI_TSFDISABLED;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!Imm32IsInteractiveUserLogon() || Imm32IsRunningInMsoobe())
|
||||
{
|
||||
TRACE("TIM is disabled due to LOGON or MSOBE\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!Imm32IsCUASEnabledInRegistry())
|
||||
{
|
||||
TRACE("CUAS is disabled in registry\n");
|
||||
GetWin32ClientInfo()->CI_flags |= CI_TSFDISABLED;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (NtCurrentTeb()->ProcessEnvironmentBlock->AppCompatFlags.LowPart & 0x100)
|
||||
{
|
||||
TRACE("CUAS is disabled by AppCompatFlags\n");
|
||||
GetWin32ClientInfo()->CI_flags |= CI_TSFDISABLED;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (RtlIsThreadWithinLoaderCallout() || Imm32InsideLoaderLock())
|
||||
{
|
||||
TRACE("TIM is disabled by Loader\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!IS_CICERO_MODE() || IS_16BIT_MODE())
|
||||
{
|
||||
TRACE("TIM is disabled because CICERO mode is unset\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (IS_IME_HKL(hKL))
|
||||
hKL = (HKL)UlongToHandle(MAKELONG(LOWORD(hKL), LOWORD(hKL)));
|
||||
|
||||
if (!ImmLoadIME(hKL))
|
||||
Imm32TF_InvalidAssemblyListCacheIfExist();
|
||||
|
||||
CtfImmCoInitialize();
|
||||
|
||||
if ((GetWin32ClientInfo()->CI_flags & CI_CTFCOINIT) &&
|
||||
!(GetWin32ClientInfo()->CI_flags & CI_CTFTIM))
|
||||
{
|
||||
hr = CtfImeCreateThreadMgr();
|
||||
if (SUCCEEDED(hr))
|
||||
GetWin32ClientInfo()->CI_flags |= CI_CTFTIM;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* CtfImmGenerateMessage(IMM32.@)
|
||||
* CtfImmGenerateMessage (IMM32.@)
|
||||
*/
|
||||
BOOL WINAPI
|
||||
CtfImmGenerateMessage(
|
||||
|
@ -638,7 +1275,7 @@ CtfImmGenerateMessage(
|
|||
}
|
||||
|
||||
/***********************************************************************
|
||||
* CtfImmHideToolbarWnd(IMM32.@)
|
||||
* CtfImmHideToolbarWnd (IMM32.@)
|
||||
*
|
||||
* Used with CtfImmRestoreToolbarWnd.
|
||||
*/
|
||||
|
@ -667,7 +1304,7 @@ CtfImmHideToolbarWnd(VOID)
|
|||
}
|
||||
|
||||
/***********************************************************************
|
||||
* CtfImmRestoreToolbarWnd(IMM32.@)
|
||||
* CtfImmRestoreToolbarWnd (IMM32.@)
|
||||
*
|
||||
* Used with CtfImmHideToolbarWnd.
|
||||
*/
|
||||
|
@ -684,7 +1321,7 @@ CtfImmRestoreToolbarWnd(
|
|||
TRACE("(%p, 0x%X)\n", pUnused, dwShowFlags);
|
||||
|
||||
hr = Imm32TF_CreateLangBarMgr(&pBarMgr);
|
||||
if (FAILED(hr))
|
||||
if (FAILED_UNEXPECTEDLY(hr))
|
||||
return;
|
||||
|
||||
if (dwShowFlags)
|
||||
|
@ -693,20 +1330,8 @@ CtfImmRestoreToolbarWnd(
|
|||
pBarMgr->lpVtbl->Release(pBarMgr);
|
||||
}
|
||||
|
||||
BOOL Imm32InsideLoaderLock(VOID)
|
||||
{
|
||||
return (NtCurrentTeb()->ProcessEnvironmentBlock->LoaderLock->OwningThread ==
|
||||
NtCurrentTeb()->ClientId.UniqueThread);
|
||||
}
|
||||
|
||||
/* FIXME: Use RTL */
|
||||
BOOL WINAPI RtlDllShutdownInProgress(VOID)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* CtfImmDispatchDefImeMessage(IMM32.@)
|
||||
* CtfImmDispatchDefImeMessage (IMM32.@)
|
||||
*/
|
||||
LRESULT WINAPI
|
||||
CtfImmDispatchDefImeMessage(
|
||||
|
@ -724,7 +1349,7 @@ CtfImmDispatchDefImeMessage(
|
|||
}
|
||||
|
||||
/***********************************************************************
|
||||
* CtfImmIsGuidMapEnable(IMM32.@)
|
||||
* CtfImmIsGuidMapEnable (IMM32.@)
|
||||
*/
|
||||
BOOL WINAPI
|
||||
CtfImmIsGuidMapEnable(
|
||||
|
@ -757,7 +1382,7 @@ CtfImmIsGuidMapEnable(
|
|||
}
|
||||
|
||||
/***********************************************************************
|
||||
* CtfImmGetGuidAtom(IMM32.@)
|
||||
* CtfImmGetGuidAtom (IMM32.@)
|
||||
*/
|
||||
HRESULT WINAPI
|
||||
CtfImmGetGuidAtom(
|
||||
|
|
|
@ -1103,15 +1103,6 @@ BOOL WINAPI ImmReleaseContext(HWND hWnd, HIMC hIMC)
|
|||
return TRUE; // Do nothing. This is correct.
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ImmDisableTextFrameService(IMM32.@)
|
||||
*/
|
||||
BOOL WINAPI ImmDisableTextFrameService(DWORD dwThreadId)
|
||||
{
|
||||
FIXME("Stub\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ImmEnumInputContext(IMM32.@)
|
||||
*/
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
@ stdcall CtfAImmActivate(ptr)
|
||||
@ stdcall CtfAImmDeactivate(long)
|
||||
@ stdcall CtfAImmIsIME(ptr)
|
||||
@ stdcall CtfImmCoUninitialize()
|
||||
@ stdcall CtfImmDispatchDefImeMessage(ptr long ptr ptr)
|
||||
@ stdcall CtfImmEnterCoInitCountSkipMode()
|
||||
@ stdcall CtfImmGenerateMessage(ptr long)
|
||||
@ stdcall CtfImmGetGuidAtom(ptr long ptr)
|
||||
@ stdcall CtfImmHideToolbarWnd()
|
||||
|
@ -9,6 +11,8 @@
|
|||
@ stdcall CtfImmIsCiceroStartedInThread()
|
||||
@ stdcall CtfImmIsGuidMapEnable(ptr)
|
||||
@ stdcall CtfImmIsTextFrameServiceDisabled()
|
||||
@ stdcall CtfImmLastEnabledWndDestroy(long)
|
||||
@ stdcall CtfImmLeaveCoInitCountSkipMode()
|
||||
@ stdcall CtfImmRestoreToolbarWnd(ptr long)
|
||||
@ stdcall CtfImmSetAppCompatFlags(long)
|
||||
@ stdcall CtfImmSetCiceroStartInThread(long)
|
||||
|
|
|
@ -112,12 +112,17 @@ BOOL WINAPI Imm32IsImcAnsi(HIMC hIMC);
|
|||
* --- Examine the condition, and then generate trace log if necessary.
|
||||
*/
|
||||
#ifdef NDEBUG /* on Release */
|
||||
#define FAILED_UNEXPECTEDLY(hr) (FAILED(hr))
|
||||
#define IS_NULL_UNEXPECTEDLY(p) (!(p))
|
||||
#define IS_ZERO_UNEXPECTEDLY(p) (!(p))
|
||||
#define IS_TRUE_UNEXPECTEDLY(x) (x)
|
||||
#define IS_FALSE_UNEXPECTEDLY(x) (!(x))
|
||||
#define IS_ERROR_UNEXPECTEDLY(x) (!(x))
|
||||
#else /* on Debug */
|
||||
#define FAILED_UNEXPECTEDLY(hr) \
|
||||
(FAILED(hr) ? (ros_dbg_log(__WINE_DBCL_ERR, __wine_dbch___default, \
|
||||
__FILE__, __FUNCTION__, __LINE__, "FAILED(%s)\n", #hr), UNEXPECTED(), TRUE) \
|
||||
: FALSE)
|
||||
#define IS_NULL_UNEXPECTEDLY(p) \
|
||||
(!(p) ? (ros_dbg_log(__WINE_DBCL_ERR, __wine_dbch___default, \
|
||||
__FILE__, __FUNCTION__, __LINE__, "%s was NULL\n", #p), UNEXPECTED(), TRUE) \
|
||||
|
@ -192,3 +197,7 @@ BOOL Imm32StoreBitmapToBytes(HBITMAP hbm, LPBYTE pbData, DWORD cbDataMax);
|
|||
|
||||
HRESULT CtfImmTIMCreateInputContext(_In_ HIMC hIMC);
|
||||
HRESULT CtfImmTIMDestroyInputContext(_In_ HIMC hIMC);
|
||||
HRESULT CtfImmCoInitialize(VOID);
|
||||
HRESULT CtfImeCreateThreadMgr(VOID);
|
||||
HRESULT CtfImeDestroyThreadMgr(VOID);
|
||||
HRESULT Imm32ActivateOrDeactivateTIM(_In_ BOOL bCreate);
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
BOOL WINAPI ImmDisableTextFrameService(_In_ DWORD dwThreadId);
|
||||
|
||||
typedef struct tagSOFTKBDDATA
|
||||
{
|
||||
UINT uCount;
|
||||
|
@ -317,7 +319,7 @@ typedef struct tagCLIENTIMC
|
|||
RTL_CRITICAL_SECTION cs;
|
||||
UINT uCodePage;
|
||||
HKL hKL;
|
||||
BOOL bUnknown4;
|
||||
BOOL bCtfIme;
|
||||
} CLIENTIMC, *PCLIENTIMC;
|
||||
|
||||
#ifndef _WIN64
|
||||
|
|
|
@ -31,6 +31,10 @@ VOID WINAPI CtfImmSetAppCompatFlags(_In_ DWORD dwFlags);
|
|||
DWORD WINAPI CtfImmHideToolbarWnd(VOID);
|
||||
VOID WINAPI CtfImmRestoreToolbarWnd(_In_ LPVOID pUnused, _In_ DWORD dwShowFlags);
|
||||
BOOL WINAPI CtfImmGenerateMessage(_In_ HIMC hIMC, _In_ BOOL bSend);
|
||||
VOID WINAPI CtfImmCoUninitialize(VOID);
|
||||
VOID WINAPI CtfImmEnterCoInitCountSkipMode(VOID);
|
||||
BOOL WINAPI CtfImmLeaveCoInitCountSkipMode(VOID);
|
||||
HRESULT WINAPI CtfImmLastEnabledWndDestroy(_In_ BOOL bCreate);
|
||||
|
||||
LRESULT WINAPI
|
||||
CtfImmDispatchDefImeMessage(
|
||||
|
|
|
@ -303,6 +303,8 @@ typedef struct _CALLBACKWND
|
|||
#define CI_CURTHPRHOOK 0x00000010
|
||||
#define CI_CLASSESREGISTERED 0x00000020
|
||||
#define CI_IMMACTIVATE 0x00000040 /* IMM/IME (Asian input) */
|
||||
#define CI_CTFCOINIT 0x00000080 /* Did CTF CoInitialize? */
|
||||
#define CI_CTFTIM 0x00000100 /* CTF Thread Input Manager (TIM) */
|
||||
#define CI_TSFDISABLED 0x00000400 /* TSF (Text Services Framework a.k.a. Cicero) */
|
||||
#define CI_AIMMACTIVATED 0x00000800 /* Active IMM (AIMM) */
|
||||
|
||||
|
|
Loading…
Reference in a new issue