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