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.
 
 
 
 
 
 

1870 lines
49 KiB

/*++
Copyright (c) 2001, Microsoft Corporation
Module Name:
com.c
Abstract:
This file implements the COM entry.
Author:
Revision History:
Notes:
--*/
#include "precomp.h"
#define COBJMACROS
#include "msctf.h"
#include "tlapi.h"
#include "apcompat.h"
#ifdef CUAS_ENABLE
#ifndef RtlIsThreadWithinLoaderCallout
BOOLEAN NTAPI RtlIsThreadWithinLoaderCallout (VOID);
#endif
HRESULT CtfAImmCreateInputContext(HIMC himc);
HRESULT ActivateOrDeactivateTIM( BOOL fActivate);
DWORD GetCoInitCountSkip();
DWORD IncCoInitCountSkip();
DWORD DecCoInitCountSkip();
HRESULT Internal_CoInitializeEx(void* pv, DWORD dw);
//+---------------------------------------------------------------------------
//
// For InitializeSpy
//
//----------------------------------------------------------------------------
typedef struct _IMMISPY
{
IInitializeSpy;
ULONG cref;
} IMMISPY;
//+---------------------------------------------------------------------------
//
// CTFIMMTLS
//
//----------------------------------------------------------------------------
typedef struct _CTFIMMTLS
{
IMMISPY *pimmispy;
ULARGE_INTEGER uliISpyCookie;
DWORD dwInRefCountSkipMode;
DWORD dwRefCountSkip;
BOOL fInCtfImmCoUninitialize;
} CTFIMMTLS;
CTFIMMTLS* GetTLS();
IMMISPY *AllocIMMISPY();
void DeleteIMMISPY(IMMISPY *pimmispy);
//+---------------------------------------------------------------------------
//
// _InsideLoaderLock()
//
//----------------------------------------------------------------------------
BOOL _InsideLoaderLock()
{
return (NtCurrentTeb()->ClientId.UniqueThread ==
((PRTL_CRITICAL_SECTION)(NtCurrentPeb()->LoaderLock))->OwningThread);
}
//+---------------------------------------------------------------------------
//
// PImmISpyFromPISpy
//
//----------------------------------------------------------------------------
IMMISPY *PImmISpyFromPISpy(IInitializeSpy *pispy)
{
return (IMMISPY *)pispy;
}
//+---------------------------------------------------------------------------
//
// ISPY_AddRef
//
//----------------------------------------------------------------------------
ULONG ISPY_AddRef(IInitializeSpy *pispy)
{
IMMISPY *pimmispy = PImmISpyFromPISpy(pispy);
pimmispy->cref++;
return pimmispy->cref;
}
//+---------------------------------------------------------------------------
//
// ISPY_Release
//
//----------------------------------------------------------------------------
ULONG ISPY_Release(IInitializeSpy *pispy)
{
IMMISPY *pimmispy = PImmISpyFromPISpy(pispy);
pimmispy->cref--;
if (!pimmispy->cref)
{
DeleteIMMISPY(pimmispy);
return 0;
}
return pimmispy->cref;
}
//+---------------------------------------------------------------------------
//
// ISPY_QueryInterface
//
//----------------------------------------------------------------------------
HRESULT ISPY_QueryInterface(IInitializeSpy *pispy,
REFIID riid,
void **ppvObject)
{
if (!ppvObject)
return E_INVALIDARG;
*ppvObject = NULL;
if (IsEqualIID(riid, &IID_IUnknown) ||
IsEqualIID(riid, &IID_IInitializeSpy))
{
ISPY_AddRef(pispy);
*ppvObject = pispy;
return S_OK;
}
return E_NOINTERFACE;
}
//+---------------------------------------------------------------------------
//
// ISPY_PreInitialize
//
//----------------------------------------------------------------------------
HRESULT ISPY_PreInitialize(IInitializeSpy * pispy,
DWORD dwCoInit,
DWORD dwCurThreadAptRefs)
{
DWORD dwRet = IncCoInitCountSkip();
UNREFERENCED_PARAMETER(pispy);
//
// If we already initialize com and a 2nd initialization is MT,
// we should disable CUAS. So the CoInit(MT) from caller will work.
//
if (GetClientInfo()->CI_flags & CI_CUAS_COINIT_CALLED)
{
if ((dwCurThreadAptRefs == (dwRet + 1)) &&
(dwCoInit == COINIT_MULTITHREADED))
{
ActivateOrDeactivateTIM(FALSE);
CtfImmCoUninitialize();
}
}
return S_OK;
}
//+---------------------------------------------------------------------------
//
// ISPY_PostInitialize
//
//----------------------------------------------------------------------------
HRESULT ISPY_PostInitialize(IInitializeSpy * pispy,
HRESULT hrCoInit,
DWORD dwCoInit,
DWORD dwNewThreadAptRefs)
{
DWORD dwRet = GetCoInitCountSkip();
UNREFERENCED_PARAMETER(pispy);
UNREFERENCED_PARAMETER(dwCoInit);
//
// If we already initialize com and got a 2nd initialization,
// change the return value to S_OK. So the caller think
// that it is the first initialization.
//
if (GetClientInfo()->CI_flags & CI_CUAS_COINIT_CALLED)
{
if ((hrCoInit == S_FALSE) && (dwNewThreadAptRefs == (dwRet + 2)))
{
return S_OK;
}
}
return hrCoInit;
}
//+---------------------------------------------------------------------------
//
// ISPY_PreUninitialize
//
//----------------------------------------------------------------------------
HRESULT ISPY_PreUninitialize(IInitializeSpy * pispy,
DWORD dwCurThreadAptRefs)
{
UNREFERENCED_PARAMETER(pispy);
UNREFERENCED_PARAMETER(dwCurThreadAptRefs);
//
// #607467
//
// Norton Systemworks setup calls CoUninitialize() without calling
// CoInitialize(). So we got under ref problem.
// If the last ref count is ours, we recover it by calling
// CoInitializeEx().
//
if (dwCurThreadAptRefs == 1)
{
if (!RtlDllShutdownInProgress() &&
!_InsideLoaderLock() &&
(GetClientInfo()->CI_flags & CI_CUAS_COINIT_CALLED))
{
CTFIMMTLS* ptls = GetTLS();
if (ptls && !ptls->fInCtfImmCoUninitialize)
{
Internal_CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
}
}
}
return S_OK;
}
//+---------------------------------------------------------------------------
//
// ISPY_PostUninitialize
//
//----------------------------------------------------------------------------
HRESULT ISPY_PostUninitialize(IInitializeSpy * pispy,
DWORD dwNewThreadAptRefs)
{
UNREFERENCED_PARAMETER(pispy);
UNREFERENCED_PARAMETER(dwNewThreadAptRefs);
DecCoInitCountSkip();
return S_OK;
}
//+---------------------------------------------------------------------------
//
// g_vtbnlISPY
//
//----------------------------------------------------------------------------
IInitializeSpyVtbl g_vtblISPY = {
ISPY_QueryInterface,
ISPY_AddRef,
ISPY_Release,
ISPY_PreInitialize,
ISPY_PostInitialize,
ISPY_PreUninitialize,
ISPY_PostUninitialize,
};
//+---------------------------------------------------------------------------
//
// AllocIMMISPY
//
//----------------------------------------------------------------------------
IMMISPY *AllocIMMISPY()
{
IMMISPY *pimmispy = ImmLocalAlloc(0, sizeof(IMMISPY));
if (!pimmispy)
return NULL;
pimmispy->lpVtbl = &g_vtblISPY;
pimmispy->cref = 1;
return pimmispy;
}
//+---------------------------------------------------------------------------
//
// DeletIMMISPY
//
//----------------------------------------------------------------------------
void DeleteIMMISPY(IMMISPY *pimmispy)
{
ImmLocalFree(pimmispy);
}
//////////////////////////////////////////////////////////////////////////////
//
// TLS
//
//////////////////////////////////////////////////////////////////////////////
DWORD g_dwTLSIndex = (DWORD)-1;
//+---------------------------------------------------------------------------
//
// InitTLS
//
//----------------------------------------------------------------------------
void InitTLS()
{
RtlEnterCriticalSection(&gcsImeDpi);
if (g_dwTLSIndex == (DWORD)-1)
g_dwTLSIndex = TlsAlloc();
RtlLeaveCriticalSection(&gcsImeDpi);
}
//+---------------------------------------------------------------------------
//
// InternalAllocateTLS
//
//----------------------------------------------------------------------------
CTFIMMTLS* InternalAllocateTLS()
{
CTFIMMTLS* ptls;
if (g_dwTLSIndex == (DWORD)-1)
return NULL;
ptls = (CTFIMMTLS*)TlsGetValue(g_dwTLSIndex);
if (ptls == NULL)
{
if ((ptls = (CTFIMMTLS*)ImmLocalAlloc(HEAP_ZERO_MEMORY,
sizeof(CTFIMMTLS))) == NULL)
return NULL;
if (!TlsSetValue(g_dwTLSIndex, ptls))
{
ImmLocalFree(ptls);
return NULL;
}
}
return ptls;
}
//+---------------------------------------------------------------------------
//
// GetTLS
//
//----------------------------------------------------------------------------
CTFIMMTLS* GetTLS()
{
if (g_dwTLSIndex == (DWORD)-1)
return NULL;
return (CTFIMMTLS*)TlsGetValue(g_dwTLSIndex);
}
//+---------------------------------------------------------------------------
//
// CtfImmEnterCoInitCountSkipMode
//
//----------------------------------------------------------------------------
BOOL WINAPI CtfImmEnterCoInitCountSkipMode()
{
CTFIMMTLS* ptls = GetTLS();
if (!ptls)
return FALSE;
ptls->dwInRefCountSkipMode++;
return TRUE;
}
//+---------------------------------------------------------------------------
//
// CtfImmLeaveCoInitCountSkip
//
//----------------------------------------------------------------------------
BOOL WINAPI CtfImmLeaveCoInitCountSkipMode()
{
CTFIMMTLS* ptls = GetTLS();
if (!ptls)
return FALSE;
if (ptls->dwInRefCountSkipMode < 1)
{
UserAssert(0);
return FALSE;
}
ptls->dwInRefCountSkipMode--;
return TRUE;
}
//+---------------------------------------------------------------------------
//
// GetCoInitCountSkip
//
//----------------------------------------------------------------------------
DWORD GetCoInitCountSkip()
{
CTFIMMTLS* ptls = GetTLS();
if (!ptls)
return 0;
return ptls->dwRefCountSkip;
}
//+---------------------------------------------------------------------------
//
// IncCoInitCountSkip
//
//----------------------------------------------------------------------------
DWORD IncCoInitCountSkip()
{
DWORD dwRet = 0;
CTFIMMTLS* ptls = GetTLS();
if (!ptls)
return dwRet;
dwRet = ptls->dwRefCountSkip;
if (ptls->dwInRefCountSkipMode)
ptls->dwRefCountSkip++;
return dwRet;
}
//+---------------------------------------------------------------------------
//
// DecCoInitCountSkip
//
//----------------------------------------------------------------------------
DWORD DecCoInitCountSkip()
{
DWORD dwRet = 0;
CTFIMMTLS* ptls = GetTLS();
if (!ptls)
return dwRet;
dwRet = ptls->dwRefCountSkip;
if (ptls->dwInRefCountSkipMode)
{
if (ptls->dwRefCountSkip < 1)
{
UserAssert(0);
return dwRet;
}
ptls->dwRefCountSkip--;
}
return dwRet;
}
//+---------------------------------------------------------------------------
//
// InternalDestroyTLS
//
//----------------------------------------------------------------------------
BOOL InternalDestroyTLS()
{
CTFIMMTLS* ptls;
ptls = (CTFIMMTLS*)TlsGetValue(g_dwTLSIndex);
if (ptls != NULL)
{
ImmLocalFree(ptls);
TlsSetValue(g_dwTLSIndex, NULL);
return TRUE;
}
return FALSE;
}
/*
* Text frame service processing is disabled for all the thread in the current process
*/
BOOL g_disable_CUAS_flag = FALSE;
//+---------------------------------------------------------------------------
//
// delay load
//
//----------------------------------------------------------------------------
FARPROC GetFn(HINSTANCE *phInst, TCHAR *pchLib, char *pchFunc)
{
if (*phInst == NULL)
{
*phInst = LoadLibrary(pchLib);
if (*phInst == NULL)
{
UserAssert(0);
return NULL;
}
}
return GetProcAddress(*phInst, pchFunc);
}
HINSTANCE g_hOle32 = NULL;
HRESULT Internal_CoInitializeEx(void* pv, DWORD dw)
{
static FARPROC pfn = NULL;
if (pfn == NULL || g_hOle32 == NULL) {
pfn = GetFn(&g_hOle32, L"ole32.dll", "CoInitializeEx");
if (pfn == NULL) {
UserAssert(0);
return E_FAIL;
}
}
return (HRESULT)(*pfn)(pv, dw);
}
void Internal_CoUninitialize()
{
static FARPROC pfn = NULL;
if (pfn == NULL || g_hOle32 == NULL) {
pfn = GetFn(&g_hOle32, L"ole32.dll", "CoUninitialize");
if (pfn == NULL) {
UserAssert(0);
return;
}
}
(*pfn)();
}
HRESULT Internal_CoRegisterInitializeSpy(LPINITIALIZESPY pSpy,
ULARGE_INTEGER *puliCookie)
{
static FARPROC pfn = NULL;
if (pfn == NULL || g_hOle32 == NULL) {
pfn = GetFn(&g_hOle32, L"ole32.dll", "CoRegisterInitializeSpy");
if (pfn == NULL) {
UserAssert(0);
return E_FAIL;
}
}
return (HRESULT)(*pfn)(pSpy, puliCookie);
}
HRESULT Internal_CoRevokeInitializeSpy(ULARGE_INTEGER uliCookie)
{
static FARPROC pfn = NULL;
if (pfn == NULL || g_hOle32 == NULL) {
pfn = GetFn(&g_hOle32, L"ole32.dll", "CoRevokeInitializeSpy");
if (pfn == NULL) {
UserAssert(0);
return E_FAIL;
}
}
return (HRESULT)(*pfn)(uliCookie);
}
HINSTANCE g_hMsctf = NULL;
HRESULT Internal_TF_CreateLangBarMgr(ITfLangBarMgr** pv)
{
static FARPROC pfn = NULL;
if (pfn == NULL || g_hMsctf == NULL) {
pfn = GetFn(&g_hMsctf, L"msctf.dll", "TF_CreateLangBarMgr");
if (pfn == NULL) {
UserAssert(0);
return E_FAIL;
}
}
return (HRESULT)(*pfn)(pv);
}
DWORD Internal_TF_CicNotify(int nCode, WPARAM wParam, LPARAM lParam)
{
static FARPROC pfn = NULL;
if (pfn == NULL || g_hMsctf == NULL) {
pfn = GetFn(&g_hMsctf, L"msctf.dll", "TF_CicNotify");
if (pfn == NULL) {
UserAssert(0);
return E_FAIL;
}
}
return (DWORD)(*pfn)(nCode, wParam, lParam);
}
#if 0
HINSTANCE g_hNtdll = NULL;
BOOLEAN Internal_RtlIsThreadWithinLoaderCallout(VOID)
{
static FARPROC pfn = NULL;
if (pfn == NULL || g_hNtdll == NULL) {
pfn = GetFn(&g_hNtdll, L"ntdll.dll", "RtlIsThreadWithinLoaderCallout");
if (pfn == NULL) {
UserAssert(0);
return FALSE;
}
}
return (BOOLEAN)(*pfn)();
}
#endif
//+---------------------------------------------------------------------------
//
// CtfImmCoInitialize
//
//----------------------------------------------------------------------------
HRESULT
CtfImmCoInitialize()
{
//
// CoInitializeEx
//
HRESULT hr = E_NOINTERFACE;
//
// Check CI flag
//
if (GetClientInfo()->CI_flags & CI_CUAS_COINIT_CALLED)
return S_OK;
hr = Internal_CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if (SUCCEEDED(hr))
{
RIPMSG0(RIP_VERBOSE, "CtfImmCoInitialize succeeded.");
//
// Set CI flag
//
GetClientInfo()->CI_flags |= CI_CUAS_COINIT_CALLED;
{
CTFIMMTLS* ptls;
//
// Initialize CoInitSpy.
//
InitTLS();
ptls = InternalAllocateTLS();
if (ptls && !ptls->pimmispy)
{
ptls->pimmispy = AllocIMMISPY();
if (ptls->pimmispy)
{
HRESULT hrTemp;
hrTemp = Internal_CoRegisterInitializeSpy((LPINITIALIZESPY)ptls->pimmispy,
&(ptls->uliISpyCookie));
if (FAILED(hrTemp))
{
DeleteIMMISPY(ptls->pimmispy);
ptls->pimmispy = NULL;
memset(&ptls->uliISpyCookie, 0, sizeof(ULARGE_INTEGER));
}
}
}
}
hr = S_OK;
}
else
{
RIPMSG1(RIP_WARNING, "CtfImmCoInitialize failed. err=%x", hr);
}
return hr;
}
//+---------------------------------------------------------------------------
//
// CtfImmCoUninitialize
//
//----------------------------------------------------------------------------
void WINAPI
CtfImmCoUninitialize()
{
if (GetClientInfo()->CI_flags & CI_CUAS_COINIT_CALLED)
{
CTFIMMTLS* ptls = GetTLS();
if (ptls)
{
ptls->fInCtfImmCoUninitialize = TRUE;
Internal_CoUninitialize();
ptls->fInCtfImmCoUninitialize = FALSE;
GetClientInfo()->CI_flags &= ~CI_CUAS_COINIT_CALLED;
}
{
CTFIMMTLS* ptls;
//
// revoke initialize spy
//
ptls = InternalAllocateTLS();
if (ptls && ptls->pimmispy)
{
Internal_CoRevokeInitializeSpy(ptls->uliISpyCookie);
ISPY_Release((IInitializeSpy *)ptls->pimmispy);
ptls->pimmispy = NULL;
memset(&ptls->uliISpyCookie, 0, sizeof(ULARGE_INTEGER));
}
}
}
}
//+---------------------------------------------------------------------------
//
// CtfImmTIMActivate
//
//----------------------------------------------------------------------------
HRESULT
CtfImmTIMActivate(
HKL hKL)
{
HRESULT hr = S_OK;
/*
* Text frame service processing is disabled for all the thread in the current process
*/
if (g_disable_CUAS_flag) {
RIPMSG0(RIP_VERBOSE, "CtfImmTIMActivate: g_disable_CUAS_flag is ON.");
/*
* set client info flag.
*/
GetClientInfo()->CI_flags |= CI_CUAS_DISABLE;
return hr;
}
/*
* Check client info flag.
*/
if (GetClientInfo()->CI_flags & CI_CUAS_DISABLE) {
RIPMSG0(RIP_VERBOSE, "CtfImmTIMActivate: CI_CUAS_DISABLE is ON.");
return hr;
}
/*
* Check Disable Advanced Text Services switch.
* If it is On, doesn't activate TIM.
*/
if (IsDisabledTextServices()) {
/*
* set client info flag.
*/
GetClientInfo()->CI_flags |= CI_CUAS_DISABLE;
RIPMSG0(RIP_VERBOSE, "CtfImmTIMActivate: Disabled Text Services.");
return hr;
}
/*
* Check a interactive user logon.
*/
if (!IsInteractiveUserLogon() || IsRunningInMsoobe()) {
RIPMSG0(RIP_VERBOSE, "CtfImmTIMActivate: Not a interactive user logon. or MSOOBE mode");
return hr;
}
/*
* Check CUAS switch. If CUAS is OFF, doesn't activate TIM.
*/
if (! IsCUASEnabled()) {
/*
* If AIMM enabled, then return S_OK;
*/
DWORD dwImeCompatFlags = ImmGetAppCompatFlags(NULL);
if (dwImeCompatFlags & (IMECOMPAT_AIMM12 | IMECOMPAT_AIMM_LEGACY_CLSID | IMECOMPAT_AIMM12_TRIDENT)) {
return S_OK;
}
/*
* set client info flag.
*/
GetClientInfo()->CI_flags |= CI_CUAS_DISABLE;
RIPMSG0(RIP_VERBOSE, "CtfImmTIMActivate: CUAS switch is OFF.");
return hr;
}
/*
*
* KACF_DISABLECICERO is already defined in private/Lab06_DEV
* we will use this flag later.
*
* APPCOMPATFLAG(KACF_DISABLECICERO)
* KACF_DISABLECICERO is 0x100
*/
#ifndef KACF_DISABLECICERO
#define KACF_DISABLECICERO 0x00000100 // If set. Cicero support for the current process
// is disabled.
#endif
if (APPCOMPATFLAG(KACF_DISABLECICERO)) {
/*
* set client info flag.
*/
GetClientInfo()->CI_flags |= CI_CUAS_DISABLE;
RIPMSG0(RIP_VERBOSE, "CtfImmTIMActivate: KACF_DISABLECICERO app compatiblity flag is ON.");
return hr;
}
if (RtlIsThreadWithinLoaderCallout())
{
RIPMSG0(RIP_VERBOSE, "CtfImmTIMActivate: we're in DllMain().");
return hr;
}
if (_InsideLoaderLock()) {
RIPMSG0(RIP_VERBOSE, "CtfImmTIMActivate: we're in DllMain.");
return hr;
}
if (IS_CICERO_ENABLED_AND_NOT16BIT()) {
HINSTANCE hCtf = NULL;
if (IS_IME_KBDLAYOUT(hKL)) {
LANGID lg = LOWORD(HandleToUlong(hKL));
hKL = (HKL)LongToHandle( MAKELONG(lg, lg) );
}
if (!ImmLoadIME(hKL)) {
//
RIPMSG1(RIP_VERBOSE, "CtfImmTIMActivate: ImmLoadIME=%lx fail.", hKL);
//
// Cicero keyboard layout doesn't loaded yet.
// MSCTF ! TF_InvalidAssemblyListCacheIfExist load Cicero assembly.
//
hCtf = LoadLibrary(TEXT("msctf.dll"));
if (hCtf) {
typedef BOOL (WINAPI* PFNINVALIDASSEMBLY)();
PFNINVALIDASSEMBLY pfn;
pfn = (PFNINVALIDASSEMBLY)GetProcAddress(hCtf, "TF_InvalidAssemblyListCacheIfExist");
if (pfn) {
pfn();
}
}
}
/*
* Initialize COM for Cicero IME.
*/
CtfImmCoInitialize();
if ( (GetClientInfo()->CI_flags & CI_CUAS_COINIT_CALLED) &&
! (GetClientInfo()->CI_flags & CI_CUAS_TIM_ACTIVATED)) {
/*
* Create and Activate TIM
*/
hr = Internal_CtfImeCreateThreadMgr();
if (SUCCEEDED(hr)) {
GetClientInfo()->CI_flags |= CI_CUAS_TIM_ACTIVATED;
RIPMSG0(RIP_VERBOSE, "CtfImmTIMActivate: Succeeded CtfImeCreateThreadMgr.");
}
else {
RIPMSG0(RIP_WARNING, "CtfImmTIMActivate: Fail CtfImeCreateThreadMgr.");
}
}
if (hCtf) {
FreeLibrary(hCtf);
}
}
return hr;
}
//+---------------------------------------------------------------------------
//
// CtfImmTIMCreateInputContext
//
//----------------------------------------------------------------------------
HRESULT
CtfImmTIMCreateInputContext(
HIMC hImc)
{
PCLIENTIMC pClientImc;
HRESULT hr = S_FALSE;
DWORD dwThreadId;
if (GetClientInfo()->CI_flags & CI_CUAS_AIMM12ACTIVATED)
{
if ((pClientImc = ImmLockClientImc(hImc)) == NULL)
return E_FAIL;
/*
* check fCtfImeContext first
*/
if (pClientImc->fCtfImeContext)
goto Exit;
pClientImc->fCtfImeContext = TRUE;
hr = CtfAImmCreateInputContext(hImc);
if (SUCCEEDED(hr)) {
RIPMSG0(RIP_VERBOSE, "CtfImmTIMCreateInputContext: Succeeded CtfImeCreateInputContext.");
}
else {
pClientImc->fCtfImeContext = FALSE;
RIPMSG0(RIP_WARNING, "CtfImmTIMCreateInputContext: Fail CtfImeCreateInputContext.");
}
goto Exit;
}
if (!(GetClientInfo()->CI_flags & CI_CUAS_TIM_ACTIVATED))
{
//
// Tim is not activated. We don't have to create the InputContext.
//
return S_OK;
}
if ((pClientImc = ImmLockClientImc(hImc)) == NULL)
return E_FAIL;
/*
* check fCtfImeContext first
*/
if (pClientImc->fCtfImeContext)
goto Exit;
dwThreadId = GetInputContextThread(hImc);
if (dwThreadId != GetCurrentThreadId())
goto Exit;
if (IS_CICERO_ENABLED_AND_NOT16BIT()) {
/*
* Set fCtfImeContext before calling ctfime to avoid recursion
* call.
*/
pClientImc->fCtfImeContext = TRUE;
/*
* Create Input Context
*/
hr = Internal_CtfImeCreateInputContext(hImc);
if (SUCCEEDED(hr)) {
RIPMSG0(RIP_VERBOSE, "CtfImmTIMCreateInputContext: Succeeded CtfImeCreateInputContext.");
}
else {
pClientImc->fCtfImeContext = FALSE;
RIPMSG0(RIP_WARNING, "CtfImmTIMCreateInputContext: Fail CtfImeCreateInputContext.");
}
}
Exit:
ImmUnlockClientImc(pClientImc);
return hr;
}
//+---------------------------------------------------------------------------
//
// CtfImmTIMDestroyInputContext
//
//----------------------------------------------------------------------------
HRESULT
CtfImmTIMDestroyInputContext(
HIMC hImc)
{
HRESULT hr = E_NOINTERFACE;
if (IS_CICERO_ENABLED_AND_NOT16BIT()) {
/*
* Destroy Input Context.
*/
hr = Internal_CtfImeDestroyInputContext(hImc);
if (SUCCEEDED(hr)) {
RIPMSG0(RIP_VERBOSE, "CtfImmTIMDestroyInputContext: Succeeded CtfImeDestroyInputContext.");
}
else {
RIPMSG0(RIP_WARNING, "CtfImmTIMDestroyInputContext: Fail CtfImeDestroyInputContext.");
}
}
return hr;
}
//+---------------------------------------------------------------------------
//
// CtfImmRestoreToolbarWnd
//
//----------------------------------------------------------------------------
void
CtfImmRestoreToolbarWnd(
DWORD dwStatus)
{
ITfLangBarMgr* plbm;
if (SUCCEEDED(Internal_TF_CreateLangBarMgr(&plbm)))
{
if (dwStatus)
{
ITfLangBarMgr_ShowFloating(plbm, dwStatus);
}
ITfLangBarMgr_Release(plbm);
}
return;
}
//+---------------------------------------------------------------------------
//
// CtfImmHideToolbarWnd
//
//----------------------------------------------------------------------------
DWORD
CtfImmHideToolbarWnd()
{
ITfLangBarMgr* plbm;
DWORD _dwPrev = 0;
if (SUCCEEDED(Internal_TF_CreateLangBarMgr(&plbm)))
{
if (SUCCEEDED(ITfLangBarMgr_GetShowFloatingStatus(plbm, &_dwPrev)))
{
BOOL fHide = TRUE;
if (_dwPrev & TF_SFT_DESKBAND)
fHide = FALSE;
//
// mask for show/hide
//
_dwPrev &= (TF_SFT_SHOWNORMAL |
TF_SFT_DOCK |
TF_SFT_MINIMIZED |
TF_SFT_HIDDEN);
if (fHide)
ITfLangBarMgr_ShowFloating(plbm, TF_SFT_HIDDEN);
}
ITfLangBarMgr_Release(plbm);
}
return _dwPrev;
}
//+---------------------------------------------------------------------------
//
// CtfImmGetGuidAtom
//
//----------------------------------------------------------------------------
HRESULT
CtfImmGetGuidAtom(HIMC hImc, BYTE bAttr, DWORD* pGuidAtom)
{
HRESULT hr = E_FAIL;
*pGuidAtom = 0;
if (IS_CICERO_ENABLED_AND_NOT16BIT()) {
PIMEDPI pImeDpi;
DWORD dwImcThreadId = (DWORD)NtUserQueryInputContext(hImc, InputContextThread);
HKL hKL = GetKeyboardLayout(dwImcThreadId);
if (IS_IME_KBDLAYOUT(hKL)) {
RIPMSG1(RIP_WARNING, "CtfImmGetGuidAtom: hKL=%lx.", hKL);
return FALSE;
}
pImeDpi = FindOrLoadImeDpi(hKL);
if (pImeDpi == NULL) {
RIPMSG0(RIP_WARNING, "CtfImmGetGuidAtom: no pImeDpi entry.");
}
else {
/*
* Get GUID atom value
*/
hr = (*pImeDpi->pfn.CtfImeGetGuidAtom)(hImc, bAttr, pGuidAtom);
if (SUCCEEDED(hr)) {
RIPMSG0(RIP_VERBOSE, "CtfImmGetGuidAtom: Succeeded CtfImeGetGuidAtom.");
}
else {
RIPMSG0(RIP_WARNING, "CtfImmGetGuidAtom: Fail CtfImeGetGuidAtom.");
}
ImmUnlockImeDpi(pImeDpi);
}
}
return hr;
}
//+---------------------------------------------------------------------------
//
// CtfImmIsGuidMapEnable
//
//----------------------------------------------------------------------------
BOOL
CtfImmIsGuidMapEnable(HIMC hImc)
{
BOOL ret = FALSE;
if (IS_CICERO_ENABLED_AND_NOT16BIT()) {
PIMEDPI pImeDpi;
DWORD dwImcThreadId = (DWORD)NtUserQueryInputContext(hImc, InputContextThread);
HKL hKL = GetKeyboardLayout(dwImcThreadId);
if (IS_IME_KBDLAYOUT(hKL)) {
RIPMSG1(RIP_WARNING, "CtfImmIsGuidMapEnable: hKL=%lx.", hKL);
return FALSE;
}
pImeDpi = FindOrLoadImeDpi(hKL);
if (pImeDpi == NULL) {
RIPMSG0(RIP_WARNING, "CtfImmIsGuidMapEnable: no pImeDpi entry.");
}
else {
/*
* Get GUID atom value
*/
ret = (*pImeDpi->pfn.CtfImeIsGuidMapEnable)(hImc);
ImmUnlockImeDpi(pImeDpi);
}
}
return ret;
}
//+---------------------------------------------------------------------------
//
// CtfImmSetAppCompatFlags
//
//----------------------------------------------------------------------------
DWORD g_aimm_compat_flags = 0;
VOID
CtfImmSetAppCompatFlags(
DWORD dwFlag)
{
if (dwFlag & ~(IMECOMPAT_AIMM_LEGACY_CLSID |
IMECOMPAT_AIMM_TRIDENT55 |
IMECOMPAT_AIMM12_TRIDENT |
IMECOMPAT_AIMM12))
{
return;
}
g_aimm_compat_flags = dwFlag;
}
//+---------------------------------------------------------------------------
//
// ActivateOrDeactivateTIM
//
//----------------------------------------------------------------------------
HRESULT
ActivateOrDeactivateTIM(
BOOL fActivate)
{
HRESULT hr = S_OK;
if (IS_CICERO_ENABLED_AND_NOT16BIT()) {
if (GetClientInfo()->CI_flags & CI_CUAS_COINIT_CALLED) {
if (! fActivate) {
/*
* Deactivate TIM
*/
if (GetClientInfo()->CI_flags & CI_CUAS_TIM_ACTIVATED) {
hr = Internal_CtfImeDestroyThreadMgr();
if (SUCCEEDED(hr)) {
GetClientInfo()->CI_flags &= ~CI_CUAS_TIM_ACTIVATED;
RIPMSG0(RIP_VERBOSE, "CtfImmLastEnabledWndDestroy: Succeeded CtfImeDestroyThreadMgr.");
}
else {
RIPMSG0(RIP_WARNING, "CtfImmLastEnabledWndDestroy: Fail CtfImeDestroyThreadMgr.");
}
}
}
else {
/*
* Activate TIM
*/
if (! (GetClientInfo()->CI_flags & CI_CUAS_TIM_ACTIVATED)) {
hr = Internal_CtfImeCreateThreadMgr();
if (SUCCEEDED(hr)) {
GetClientInfo()->CI_flags |= CI_CUAS_TIM_ACTIVATED;
RIPMSG0(RIP_VERBOSE, "CtfImmLastEnabledWndDestroy: Succeeded CtfImeDestroyThreadMgr.");
}
else {
RIPMSG0(RIP_WARNING, "CtfImmLastEnabledWndDestroy: Fail CtfImeDestroyThreadMgr.");
}
}
}
}
}
return hr;
}
//+---------------------------------------------------------------------------
//
// CtfImmLastEnabledWndDestroy
// LPARAM 0 = Deactivate TIM.
// ! 0 = Activate TIM.
//
//----------------------------------------------------------------------------
HRESULT
CtfImmLastEnabledWndDestroy(
LPARAM lParam)
{
return ActivateOrDeactivateTIM(lParam ? TRUE : FALSE);
}
//+---------------------------------------------------------------------------
//
// ImmSetLangBand
//
//----------------------------------------------------------------------------
// TM_LANGUAGEBAND is defined in "shell\inc\trayp.h"
#define TM_LANGUAGEBAND WM_USER+0x105
typedef struct _LANG_BAND {
HWND hwndTray;
BOOL fLangBand;
} LANG_BAND;
DWORD
DelaySetLangBand(
LANG_BAND* langband)
{
HWND hwndIME;
//
// Delay 3000msec.
// If this delay value is not enough, Explorer takes CPU power 100%.
// printui!CTrayNotify::_ResetAll
//
Sleep(3000);
hwndIME = ImmGetDefaultIMEWnd(langband->hwndTray);
if (hwndIME) {
DWORD_PTR dwResult;
LRESULT lResult = (LRESULT)0;
lResult = SendMessageTimeout(hwndIME,
WM_IME_SYSTEM,
langband->fLangBand ? IMS_SETLANGBAND : IMS_RESETLANGBAND,
(LPARAM)langband->hwndTray,
SMTO_ABORTIFHUNG | SMTO_BLOCK,
5000,
&dwResult);
//
// Checking the language band setting fail case
//
if (!lResult || dwResult != langband->fLangBand)
{
// UserAssert(0);
}
}
ImmLocalFree(langband);
return 0;
}
LRESULT
CtfImmSetLangBand(
HWND hwndTray,
BOOL fLangBand)
{
DWORD_PTR dwResult = 0;
PWND pwnd;
// check if the window of the Explorer Tray is valid
if ((pwnd = ValidateHwnd(hwndTray)) == NULL) {
RIPMSG1(RIP_WARNING, "CtfImmSetLangBand: Invalid hwndTray %lx.", hwndTray);
} else {
if (TestWF(pwnd, WFISINITIALIZED)) { // TRUE if the Explorer Tray is initialized
LRESULT lResult = (LRESULT)0;
lResult = SendMessageTimeout(hwndTray,
TM_LANGUAGEBAND,
0,
fLangBand,
SMTO_ABORTIFHUNG | SMTO_BLOCK,
5000,
&dwResult);
//
// Checking the language band setting fail case
//
if (!lResult || dwResult != fLangBand)
{
// UserAssert(0);
}
}
else {
LANG_BAND* langband = (LANG_BAND*) ImmLocalAlloc(0, sizeof(LANG_BAND));
if (langband != NULL) {
HANDLE hThread;
DWORD ThreadId;
langband->hwndTray = hwndTray;
langband->fLangBand = fLangBand;
hThread = CreateThread(NULL,
0,
DelaySetLangBand,
langband,
0,
&ThreadId);
if (hThread) {
CloseHandle(hThread);
}
}
}
}
return dwResult;
}
BOOL
CtfImmIsCiceroEnabled()
{
return IS_CICERO_ENABLED();
}
BOOL
CtfImmIsCiceroStartedInThread()
{
return (GetClientInfo()->CI_flags & CI_CUAS_MSCTF_RUNNING) ? TRUE : FALSE;
}
HRESULT
CtfImmSetCiceroStartInThread(BOOL fSet)
{
if (fSet)
GetClientInfo()->CI_flags |= CI_CUAS_MSCTF_RUNNING;
else
GetClientInfo()->CI_flags &= ~CI_CUAS_MSCTF_RUNNING;
return S_OK;
}
BOOL
IsCUASEnabled()
{
LONG lRet;
HKEY hKeyCtf;
DWORD dwType;
DWORD dwCUAS;
DWORD dwTmp;
lRet = RegOpenKey(HKEY_LOCAL_MACHINE, gszRegCtfShared, &hKeyCtf);
if ( lRet != ERROR_SUCCESS ) {
return FALSE;
}
dwType = 0;
dwCUAS = 0;
dwTmp = sizeof(DWORD);
lRet = RegQueryValueEx(hKeyCtf,
gszValCUASEnable,
NULL,
&dwType,
(LPBYTE)&dwCUAS,
&dwTmp);
RegCloseKey(hKeyCtf);
if ( lRet != ERROR_SUCCESS || dwType != REG_DWORD) {
return FALSE;
}
return (BOOL)dwCUAS;
}
//+---------------------------------------------------------------------------
//
// ImmDisableTextFrameService
//
//----------------------------------------------------------------------------
BOOL
ImmDisableTextFrameService(DWORD idThread)
{
HRESULT hr = S_OK;
if (idThread == -1)
{
// Text frame service processing is disabled for all the thread in the current process
g_disable_CUAS_flag = TRUE;
}
if ((idThread == 0 || g_disable_CUAS_flag) &&
(! (GetClientInfo()->CI_flags & CI_CUAS_DISABLE)))
{
/*
* set client info flag.
*/
GetClientInfo()->CI_flags |= CI_CUAS_DISABLE;
if (IS_CICERO_ENABLED_AND_NOT16BIT()) {
if (GetClientInfo()->CI_flags & CI_CUAS_COINIT_CALLED) {
/*
* Deactivate TIM
*/
if (GetClientInfo()->CI_flags & CI_CUAS_TIM_ACTIVATED) {
hr = Internal_CtfImeDestroyThreadMgr();
if (SUCCEEDED(hr)) {
GetClientInfo()->CI_flags &= ~CI_CUAS_TIM_ACTIVATED;
RIPMSG0(RIP_VERBOSE, "ImmDisableTextFrameService: Succeeded CtfImeDestroyThreadMgr.");
}
else {
RIPMSG0(RIP_WARNING, "ImmDisableTextFrameService: Fail CtfImeDestroyThreadMgr.");
}
if (SUCCEEDED(hr)) {
/*
* CoUninitialize
*/
CtfImmCoUninitialize();
}
}
}
}
}
return hr == S_OK ? TRUE : FALSE;
}
BOOL
CtfImmIsTextFrameServiceDisabled()
{
return (GetClientInfo()->CI_flags & CI_CUAS_DISABLE) ? TRUE : FALSE;
}
BOOL
IsDisabledTextServices()
{
static const TCHAR c_szCTFKey[] = TEXT("SOFTWARE\\Microsoft\\CTF");
static const TCHAR c_szDiableTim[] = TEXT("Disable Thread Input Manager");
HKEY hKey;
if (RegOpenKey(HKEY_CURRENT_USER, c_szCTFKey, &hKey) == ERROR_SUCCESS)
{
DWORD cb;
DWORD dwDisableTim = 0;
cb = sizeof(DWORD);
RegQueryValueEx(hKey,
c_szDiableTim,
NULL,
NULL,
(LPBYTE)&dwDisableTim,
&cb);
RegCloseKey(hKey);
//
// Ctfmon disabling flag is set.
//
if (dwDisableTim)
return TRUE;
}
return FALSE;
}
BOOL
IsInteractiveUserLogon()
{
PSID InteractiveSid;
BOOL bCheckSucceeded;
BOOL bAmInteractive = FALSE;
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
if (!AllocateAndInitializeSid(&NtAuthority,
1,
SECURITY_INTERACTIVE_RID,
0, 0, 0, 0, 0, 0, 0,
&InteractiveSid))
{
return FALSE;
}
//
// This checking is for logged on user or not. So we can blcok running
// ctfmon.exe process from non-authorized user.
//
bCheckSucceeded = CheckTokenMembership(NULL,
InteractiveSid,
&bAmInteractive);
if (InteractiveSid)
FreeSid(InteractiveSid);
return (bCheckSucceeded && bAmInteractive);
}
//+---------------------------------------------------------------------------
//
// IsRunningInMsoobe()
//
//----------------------------------------------------------------------------
BOOL IsRunningInMsoobe()
{
static const TCHAR c_szMsoobeModule[] = TEXT("msoobe.exe");
TCHAR szFileName[MAX_PATH];
TCHAR szModuleName[MAX_PATH];
LPTSTR pszFilePart = NULL;
if (GetModuleFileName(NULL, szFileName, sizeof(szFileName)/sizeof(szFileName[0])) == 0)
return FALSE;
GetFullPathName(szFileName,
sizeof(szFileName)/sizeof(szFileName[0]),
szModuleName,
&pszFilePart);
if (pszFilePart == NULL)
return FALSE;
if (lstrcmpiW(pszFilePart, c_szMsoobeModule) == 0)
return TRUE;
return FALSE;
}
//+---------------------------------------------------------------------------
//
// LoadCtfIme
//
//----------------------------------------------------------------------------
BOOL CheckAndApplyAppCompat(LPWSTR wszImeFile);
typedef HRESULT (CALLBACK* PFNCREATETHREADMGR)();
typedef HRESULT (CALLBACK* PFNDESTROYTHREADMGR)();
typedef HRESULT (CALLBACK* PFNCREATEINPUTCONTEXT)(HIMC);
typedef HRESULT (CALLBACK* PFNDESTROYINPUTCONTEXT)(HIMC);
typedef HRESULT (CALLBACK* PFNSETACTIVECONTEXTALWAYS)(HIMC, BOOL, HWND, HKL);
typedef BOOL (CALLBACK* PFNPROCESSCICHOTKEY)(HIMC, UINT, LPARAM);
typedef LRESULT (CALLBACK* PFNDISPATCHDEFIMEMESSAGE)(HWND, UINT, WPARAM, LPARAM);
typedef BOOL (CALLBACK* PFNIMEISIME)(HKL);
PFNCREATETHREADMGR g_pfnCtfImeCreateThreadMgr = NULL;
PFNDESTROYTHREADMGR g_pfnCtfImeDestroyThreadMgr = NULL;
PFNCREATEINPUTCONTEXT g_pfnCtfImeCreateInputContext = NULL;
PFNDESTROYINPUTCONTEXT g_pfnCtfImeDestroyInputContext= NULL;
PFNSETACTIVECONTEXTALWAYS g_pfnCtfImeSetActiveContextAlways= NULL;
PFNPROCESSCICHOTKEY g_pfnCtfImeProcessCicHotkey = NULL;
PFNDISPATCHDEFIMEMESSAGE g_pfnCtfImeDispatchDefImeMessage = NULL;
PFNIMEISIME g_pfnCtfImeIsIME = NULL;
#define GET_CTFIMEPROC(x) \
if (!(g_pfn##x = (PVOID) GetProcAddress(g_hCtfIme, #x))) { \
RIPMSG0(RIP_WARNING, "LoadCtfIme: " #x " not supported"); \
goto LoadCtfIme_ErrOut; }
HMODULE g_hCtfIme = NULL;
HMODULE LoadCtfIme()
{
IMEINFOEX iiex;
RtlEnterCriticalSection(&gcsImeDpi);
if (g_hCtfIme)
goto Exit;
if (ImmLoadLayout((HKL)0x04090409, &iiex)) {
WCHAR wszImeFile[MAX_PATH];
GetSystemPathName(wszImeFile, iiex.wszImeFile, MAX_PATH);
if (!CheckAndApplyAppCompat(wszImeFile)) {
RIPMSG1(RIP_WARNING, "LoadCtfIme: IME (%ws) blocked by appcompat", wszImeFile);
}
else {
g_hCtfIme = LoadLibraryW(wszImeFile);
if (g_hCtfIme) {
GET_CTFIMEPROC(CtfImeCreateThreadMgr);
GET_CTFIMEPROC(CtfImeDestroyThreadMgr);
GET_CTFIMEPROC(CtfImeCreateInputContext);
GET_CTFIMEPROC(CtfImeDestroyInputContext);
GET_CTFIMEPROC(CtfImeSetActiveContextAlways);
GET_CTFIMEPROC(CtfImeProcessCicHotkey);
GET_CTFIMEPROC(CtfImeDispatchDefImeMessage);
GET_CTFIMEPROC(CtfImeIsIME);
}
}
}
goto Exit;
LoadCtfIme_ErrOut:
if (g_hCtfIme) {
FreeLibrary(g_hCtfIme);
g_hCtfIme = NULL;
}
Exit:
RtlLeaveCriticalSection(&gcsImeDpi);
return g_hCtfIme;
}
//+---------------------------------------------------------------------------
//
// CtfAImmCreateInputContext
//
//----------------------------------------------------------------------------
HRESULT CtfAImmCreateInputContext(HIMC himc)
{
return Internal_CtfImeCreateInputContext(himc);
}
//+---------------------------------------------------------------------------
//
// EnumIMC
//
//----------------------------------------------------------------------------
BOOL EnumIMC(HIMC hIMC, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
CtfAImmCreateInputContext(hIMC);
return TRUE;
}
//+---------------------------------------------------------------------------
//
// CtfAImmActivate
//
//----------------------------------------------------------------------------
HRESULT CtfAImmActivate(HMODULE* phMod)
{
HRESULT hr = E_FAIL;
HMODULE hCtfIme = LoadCtfIme();
hr = Internal_CtfImeCreateThreadMgr();
if (hr == S_OK)
{
GetClientInfo()->CI_flags |= CI_CUAS_AIMM12ACTIVATED;
/*
* reset client info flag.
* Bug#525583 - Reset CU_CUAS_DISABLE flag before create
* the input context.
*/
GetClientInfo()->CI_flags &= ~CI_CUAS_DISABLE;
ImmEnumInputContext(0, EnumIMC, 0);
}
if (phMod)
*phMod = hCtfIme;
return hr;
}
//+---------------------------------------------------------------------------
//
// CtfAImmDectivate
//
//----------------------------------------------------------------------------
HRESULT CtfAImmDeactivate(HMODULE hMod)
{
HRESULT hr = E_FAIL;
//
// Load CTFIME and destroy TIM.
//
if (hMod)
{
hr = Internal_CtfImeDestroyThreadMgr();
if (hr == S_OK)
{
GetClientInfo()->CI_flags &= ~CI_CUAS_AIMM12ACTIVATED;
/*
* set client info flag.
*/
GetClientInfo()->CI_flags |= CI_CUAS_DISABLE;
}
//
// Win BUG: 611569
//
// Don't call FreeLibrary because LoadCtfIme() hold CTFIME module handle in global.
//
// FreeLibrary(hMod);
}
return hr;
}
//+---------------------------------------------------------------------------
//
// CtfAImmIsIME
//
//----------------------------------------------------------------------------
BOOL CtfAImmIsIME(HKL hkl)
{
if (LoadCtfIme())
return (g_pfnCtfImeIsIME)(hkl);
return ImmIsIME(hkl);
}
//+---------------------------------------------------------------------------
//
// CtfImmDispatchDefImeMessage
//
//----------------------------------------------------------------------------
LRESULT CtfImmDispatchDefImeMessage(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (RtlDllShutdownInProgress() || _InsideLoaderLock())
return 0;
if (LoadCtfIme())
{
return (g_pfnCtfImeDispatchDefImeMessage)(hwnd, message, wParam, lParam);
}
return 0;
}
//+---------------------------------------------------------------------------
//
// Internal_CtfImeCreateThreadMgr
//
//----------------------------------------------------------------------------
HRESULT Internal_CtfImeCreateThreadMgr()
{
if (!LoadCtfIme())
return E_FAIL;
return (g_pfnCtfImeCreateThreadMgr)();
}
//+---------------------------------------------------------------------------
//
// Internal_CtfImeDestroyThreadMgr
//
//----------------------------------------------------------------------------
HRESULT Internal_CtfImeDestroyThreadMgr()
{
if (!LoadCtfIme())
return E_FAIL;
return (g_pfnCtfImeDestroyThreadMgr)();
}
//+---------------------------------------------------------------------------
//
// Internal_CtfImeProcessCicHotkey
//
//----------------------------------------------------------------------------
BOOL Internal_CtfImeProcessCicHotkey(HIMC hIMC, UINT uVKey, LPARAM lParam)
{
if (!LoadCtfIme())
return FALSE;
return (g_pfnCtfImeProcessCicHotkey)(hIMC, uVKey, lParam);
}
//+---------------------------------------------------------------------------
//
// Internal_CtfImeCreateInputContext
//
//----------------------------------------------------------------------------
HRESULT Internal_CtfImeCreateInputContext(HIMC himc)
{
if (!LoadCtfIme())
return E_FAIL;
return (g_pfnCtfImeCreateInputContext)(himc);
}
//+---------------------------------------------------------------------------
//
// Internal_CtfImeDestroyInputContext
//
//----------------------------------------------------------------------------
HRESULT Internal_CtfImeDestroyInputContext(HIMC himc)
{
if (!LoadCtfIme())
return E_FAIL;
return (g_pfnCtfImeDestroyInputContext)(himc);
}
//+---------------------------------------------------------------------------
//
// Internal_CtfImeSetActiveContextAlways
//
//----------------------------------------------------------------------------
HRESULT Internal_CtfImeSetActiveContextAlways(HIMC himc, BOOL fActive, HWND hwnd, HKL hkl)
{
if (!LoadCtfIme())
return E_FAIL;
return (g_pfnCtfImeSetActiveContextAlways)(himc, fActive, hwnd, hkl);
}
#else
void CtfImmGetGuidAtom() { }
void CtfImmHideToolbarWnd() { }
void CtfImmIsGuidMapEnable() { }
void CtfImmRestoreToolbarWnd() { }
void CtfImmSetAppCompatFlags() { }
void CtfImmTIMActivate() { }
void CtfImmIsCiceroEnabled() { }
void CtfImmDispatchDefImeMessage() { }
#endif // CUAS_ENABLE