Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670/* * PROJECT: ReactOS msctfime.ime * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) * PURPOSE: Miscellaneous of msctfime.ime * COPYRIGHT: Copyright 2024 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com> */
#include "msctfime.h"
WINE_DEFAULT_DEBUG_CHANNEL(msctfime);
/// East-Asian language?/// @implementedBOOL IsEALang(_In_opt_ LANGID LangID){ if (LangID == 0) { TLS *pTLS = TLS::GetTLS(); if (!pTLS || !pTLS->m_pProfile) return FALSE;
pTLS->m_pProfile->GetLangId(&LangID); }
switch (PRIMARYLANGID(LangID)) { case LANG_CHINESE: case LANG_JAPANESE: case LANG_KOREAN: return TRUE;
default: return FALSE; }}
typedef BOOLEAN (WINAPI *FN_DllShutdownInProgress)(VOID);
/// This function calls ntdll!RtlDllShutdownInProgress./// It can detect the system is shutting down or not./// @implementedBOOLEAN DllShutdownInProgress(VOID){ HMODULE hNTDLL; static FN_DllShutdownInProgress s_fnDllShutdownInProgress = NULL;
if (s_fnDllShutdownInProgress) return s_fnDllShutdownInProgress();
hNTDLL = cicGetSystemModuleHandle(L"ntdll.dll", FALSE); s_fnDllShutdownInProgress = (FN_DllShutdownInProgress)GetProcAddress(hNTDLL, "RtlDllShutdownInProgress"); if (!s_fnDllShutdownInProgress) return FALSE;
return s_fnDllShutdownInProgress();}
/// This function checks if the current user logon session is interactive./// @implementedBOOL IsInteractiveUserLogon(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;}
/// Gets the charset from a language ID./// @implementedBYTE GetCharsetFromLangId(_In_ DWORD dwValue){ CHARSETINFO info; if (!::TranslateCharsetInfo((DWORD*)(DWORD_PTR)dwValue, &info, TCI_SRCLOCALE)) return 0; return info.ciCharset;}
/// Get the active input context./// @implementedHIMC GetActiveContext(VOID){ HWND hwndFocus = ::GetFocus(); if (!hwndFocus) hwndFocus = ::GetActiveWindow(); return ::ImmGetContext(hwndFocus);}
// MSIMTF.dll!MsimtfIsGuidMapEnabletypedef BOOL (WINAPI *FN_MsimtfIsGuidMapEnable)(HIMC hIMC, LPBOOL pbValue);HINSTANCE g_hMSIMTF = NULL;
/// @implementedBOOL MsimtfIsGuidMapEnable(_In_ HIMC hIMC, _Out_opt_ LPBOOL pbValue){ static FN_MsimtfIsGuidMapEnable s_fn = NULL; if (!cicGetFN(g_hMSIMTF, s_fn, L"msimtf.dll", "MsimtfIsGuidMapEnable")) return FALSE; return s_fn(hIMC, pbValue);}
/// @implementedBOOL IsVKDBEKey(_In_ UINT uVirtKey){ switch (uVirtKey) { case VK_KANJI: case VK_CONVERT: return TRUE; default: return (VK_OEM_ATTN <= uVirtKey && uVirtKey <= VK_PA1); }}
/// @implementedITfCategoryMgr *GetUIMCat(PCIC_LIBTHREAD pLibThread){ if (!pLibThread) return NULL;
if (pLibThread->m_pCategoryMgr) return pLibThread->m_pCategoryMgr;
if (FAILED(cicCoCreateInstance(CLSID_TF_CategoryMgr, NULL, CLSCTX_INPROC_SERVER, IID_ITfCategoryMgr, (void **)&pLibThread->m_pCategoryMgr))) { return NULL; } return pLibThread->m_pCategoryMgr;}
/// @implementedstatic HRESULTLibEnumItemsInCategory(PCIC_LIBTHREAD pLibThread, REFGUID rguid, IEnumGUID **ppEnum){ ITfCategoryMgr *pCat = GetUIMCat(pLibThread); if (!pCat) return E_FAIL; return pCat->EnumItemsInCategory(rguid, ppEnum);}
/// @implementedHRESULT InitDisplayAttrbuteLib(PCIC_LIBTHREAD pLibThread){ if (!pLibThread) return E_FAIL;
if (pLibThread->m_pDisplayAttrMgr) { pLibThread->m_pDisplayAttrMgr->Release(); pLibThread->m_pDisplayAttrMgr = NULL; }
if (FAILED(cicCoCreateInstance(CLSID_TF_DisplayAttributeMgr, NULL, CLSCTX_INPROC_SERVER, IID_ITfDisplayAttributeMgr, (void **)&pLibThread->m_pDisplayAttrMgr))) { return E_FAIL; }
IEnumGUID *pEnumGuid; LibEnumItemsInCategory(pLibThread, GUID_TFCAT_DISPLAYATTRIBUTEPROPERTY, &pEnumGuid);
HRESULT hr = E_OUTOFMEMORY;
::EnterCriticalSection(&g_csLock); if (pEnumGuid && !g_pPropCache) { g_pPropCache = new(cicNoThrow) CDispAttrPropCache(); if (g_pPropCache) { g_pPropCache->Add(GUID_PROP_ATTRIBUTE); GUID guid; while (pEnumGuid->Next(1, &guid, NULL) == S_OK) { if (!IsEqualGUID(guid, GUID_PROP_ATTRIBUTE)) g_pPropCache->Add(guid); } hr = S_OK; } } ::LeaveCriticalSection(&g_csLock);
return hr;}
/// @implementedHRESULT UninitDisplayAttrbuteLib(PCIC_LIBTHREAD pLibThread){ if (!pLibThread) return E_FAIL;
if (pLibThread->m_pDisplayAttrMgr) { pLibThread->m_pDisplayAttrMgr->Release(); pLibThread->m_pDisplayAttrMgr = NULL; }
return S_OK;}
/***********************************************************************/
/// @implementedHRESULTGetCompartment( IUnknown *pUnknown, REFGUID rguid, ITfCompartment **ppComp, BOOL bThread){ *ppComp = NULL;
ITfThreadMgr *pThreadMgr = NULL; ITfCompartmentMgr *pCompMgr = NULL;
HRESULT hr; if (bThread) { hr = pUnknown->QueryInterface(IID_ITfThreadMgr, (void **)&pThreadMgr); if (FAILED(hr)) return hr;
hr = pThreadMgr->GetGlobalCompartment(&pCompMgr); } else { hr = pUnknown->QueryInterface(IID_ITfCompartmentMgr, (void **)&pCompMgr); }
if (SUCCEEDED(hr)) { hr = E_FAIL; if (pCompMgr) { hr = pCompMgr->GetCompartment(rguid, ppComp); pCompMgr->Release(); } }
if (pThreadMgr) pThreadMgr->Release();
return hr;}
/// @implementedHRESULTSetCompartmentDWORD( TfEditCookie cookie, IUnknown *pUnknown, REFGUID rguid, DWORD dwValue, BOOL bThread){ ITfCompartment *pComp = NULL; HRESULT hr = GetCompartment(pUnknown, rguid, &pComp, bThread); if (FAILED(hr)) return hr;
VARIANT vari; V_I4(&vari) = dwValue; V_VT(&vari) = VT_I4; hr = pComp->SetValue(cookie, &vari);
pComp->Release(); return hr;}
/// @implementedHRESULTGetCompartmentDWORD( IUnknown *pUnknown, REFGUID rguid, LPDWORD pdwValue, BOOL bThread){ *pdwValue = 0;
ITfCompartment *pComp = NULL; HRESULT hr = GetCompartment(pUnknown, rguid, &pComp, bThread); if (FAILED(hr)) return hr;
VARIANT vari; hr = pComp->GetValue(&vari); if (hr == S_OK) *pdwValue = V_I4(&vari);
pComp->Release(); return hr;}
/// @implementedHRESULTSetCompartmentUnknown( TfEditCookie cookie, IUnknown *pUnknown, REFGUID rguid, IUnknown *punkValue){ ITfCompartment *pComp = NULL; HRESULT hr = GetCompartment(pUnknown, rguid, &pComp, FALSE); if (FAILED(hr)) return hr;
VARIANT vari; V_UNKNOWN(&vari) = punkValue; V_VT(&vari) = VT_UNKNOWN; hr = pComp->SetValue(cookie, &vari);
pComp->Release(); return hr;}
/// @implementedHRESULTClearCompartment( TfClientId tid, IUnknown *pUnknown, REFGUID rguid, BOOL bThread){ ITfCompartmentMgr *pCompMgr = NULL; ITfThreadMgr *pThreadMgr = NULL;
HRESULT hr; if (bThread) { hr = pUnknown->QueryInterface(IID_ITfThreadMgr, (void **)&pThreadMgr); if (FAILED(hr)) return hr;
hr = pThreadMgr->GetGlobalCompartment(&pCompMgr); } else { hr = pUnknown->QueryInterface(IID_ITfCompartmentMgr, (void **)&pCompMgr); }
if (SUCCEEDED(hr)) { hr = E_FAIL; if (pCompMgr) { hr = pCompMgr->ClearCompartment(tid, rguid); pCompMgr->Release(); } }
if (pThreadMgr) pThreadMgr->Release();
return hr;}
/***********************************************************************/
struct MODEBIAS{ REFGUID m_guid; LONG m_bias;};
static const MODEBIAS g_ModeBiasMap[] ={ { GUID_MODEBIAS_FILENAME, 0x00000001 }, { GUID_MODEBIAS_NUMERIC, 0x00000004 }, { GUID_MODEBIAS_URLHISTORY, 0x00010000 }, { GUID_MODEBIAS_DEFAULT, 0x00000000 }, { GUID_MODEBIAS_NONE, 0x00000000 },};
/// @implementedvoid CModeBias::SetModeBias(REFGUID rguid){ m_guid = rguid;}
/// @implementedGUID CModeBias::ConvertModeBias(LONG bias){ const GUID *pguid = &GUID_NULL; for (auto& item : g_ModeBiasMap) { if (item.m_bias == bias) { pguid = &item.m_guid; break; } }
return *pguid;}
/// @implementedLONG CModeBias::ConvertModeBias(REFGUID guid){ for (auto& item : g_ModeBiasMap) { if (IsEqualGUID(guid, item.m_guid)) return item.m_bias; } return 0;}
/***********************************************************************/
/// @implementedCFunctionProviderBase::CFunctionProviderBase(_In_ TfClientId clientId){ m_clientId = clientId; m_guid = GUID_NULL; m_bstr = NULL; m_cRefs = 1;}
/// @implementedCFunctionProviderBase::~CFunctionProviderBase(){ if (!DllShutdownInProgress()) ::SysFreeString(m_bstr);}
/// @implementedBOOLCFunctionProviderBase::Init( _In_ REFGUID rguid, _In_ LPCWSTR psz){ m_bstr = ::SysAllocString(psz); m_guid = rguid; return (m_bstr != NULL);}
/// @implementedSTDMETHODIMPCFunctionProviderBase::QueryInterface( _In_ REFIID riid, _Out_ LPVOID* ppvObj){ static const QITAB c_tab[] = { QITABENT(CFunctionProviderBase, ITfFunctionProvider), { NULL } }; return ::QISearch(this, c_tab, riid, ppvObj);}
/// @implementedSTDMETHODIMP_(ULONG) CFunctionProviderBase::AddRef(){ return ::InterlockedIncrement(&m_cRefs);}
/// @implementedSTDMETHODIMP_(ULONG) CFunctionProviderBase::Release(){ if (::InterlockedDecrement(&m_cRefs) == 0) { delete this; return 0; } return m_cRefs;}
/// @implementedSTDMETHODIMP CFunctionProviderBase::GetType(_Out_ GUID *guid){ *guid = m_guid; return S_OK;}
/// @implementedSTDMETHODIMP CFunctionProviderBase::GetDescription(_Out_ BSTR *desc){ *desc = ::SysAllocString(m_bstr); return (*desc ? S_OK : E_OUTOFMEMORY);}
/***********************************************************************/
/// @implementedCFunctionProvider::CFunctionProvider(_In_ TfClientId clientId) : CFunctionProviderBase(clientId){ Init(CLSID_CAImmLayer, L"MSCTFIME::Function Provider");}
/// @implementedSTDMETHODIMPCFunctionProvider::GetFunction( _In_ REFGUID guid, _In_ REFIID riid, _Out_ IUnknown **func){ *func = NULL;
if (IsEqualGUID(guid, GUID_NULL) && IsEqualIID(riid, IID_IAImmFnDocFeed)) { *func = new(cicNoThrow) CFnDocFeed(); if (*func) return S_OK; }
return E_NOINTERFACE;}
/***********************************************************************/
CFnDocFeed::CFnDocFeed(){ m_cRefs = 1;}
CFnDocFeed::~CFnDocFeed(){}
/// @implementedSTDMETHODIMP CFnDocFeed::QueryInterface(_In_ REFIID riid, _Out_ LPVOID* ppvObj){ static const QITAB c_tab[] = { QITABENT(CFnDocFeed, IAImmFnDocFeed), { NULL } }; return ::QISearch(this, c_tab, riid, ppvObj);}
/// @implementedSTDMETHODIMP_(ULONG) CFnDocFeed::AddRef(){ return ::InterlockedIncrement(&m_cRefs);}
/// @implementedSTDMETHODIMP_(ULONG) CFnDocFeed::Release(){ if (::InterlockedDecrement(&m_cRefs) == 0) { delete this; return 0; } return m_cRefs;}
/// @implementedSTDMETHODIMP CFnDocFeed::DocFeed(){ TLS *pTLS = TLS::GetTLS(); if (!pTLS) return E_OUTOFMEMORY;
HIMC hIMC = GetActiveContext(); CicIMCLock imcLock(hIMC); if (FAILED(imcLock.m_hr)) return imcLock.m_hr;
CicIMCCLock<CTFIMECONTEXT> imeContext(imcLock.get().hCtfImeContext); if (FAILED(imeContext.m_hr)) return imeContext.m_hr; CicInputContext *pCicIC = imeContext.get().m_pCicIC; if (!pCicIC) return E_FAIL;
UINT uCodePage = CP_ACP; pTLS->m_pProfile->GetCodePageA(&uCodePage); pCicIC->SetupDocFeedString(imcLock, uCodePage); return S_OK;}
/// @implementedSTDMETHODIMP CFnDocFeed::ClearDocFeedBuffer(){ if (!TLS::GetTLS()) return E_OUTOFMEMORY;
HIMC hIMC = GetActiveContext(); CicIMCLock imcLock(hIMC); if (FAILED(imcLock.m_hr)) return imcLock.m_hr;
CicIMCCLock<CTFIMECONTEXT> imeContext(imcLock.get().hCtfImeContext); if (FAILED(imeContext.m_hr)) return imeContext.m_hr;
CicInputContext *pCicIC = imeContext.get().m_pCicIC; if (!pCicIC) return E_FAIL;
pCicIC->EscbClearDocFeedBuffer(imcLock, TRUE); return S_OK;}
/// @unimplementedSTDMETHODIMP CFnDocFeed::StartReconvert(){ TLS *pTLS = TLS::GetTLS(); if (!pTLS) return E_OUTOFMEMORY; auto *pThreadMgr = pTLS->m_pThreadMgr; if (!pThreadMgr) return E_OUTOFMEMORY;
HIMC hIMC = GetActiveContext(); CicIMCLock imcLock(hIMC); if (FAILED(imcLock.m_hr)) return imcLock.m_hr;
CicIMCCLock<CTFIMECONTEXT> imeContext(imcLock.get().hCtfImeContext); if (FAILED(imeContext.m_hr)) return imeContext.m_hr; CicInputContext *pCicIC = imeContext.get().m_pCicIC; if (!pCicIC) return E_FAIL;
UINT uCodePage = CP_ACP; pTLS->m_pProfile->GetCodePageA(&uCodePage);
pCicIC->m_bReconverting = TRUE; pCicIC->SetupReconvertString(imcLock, pThreadMgr, uCodePage, 0, 0); pCicIC->EndReconvertString(imcLock); pCicIC->m_bReconverting = FALSE; return S_OK;}
/// @implementedSTDMETHODIMP CFnDocFeed::StartUndoCompositionString(){ TLS *pTLS = TLS::GetTLS(); if (!pTLS) return E_OUTOFMEMORY; auto *pThreadMgr = pTLS->m_pThreadMgr; if (!pThreadMgr) return E_OUTOFMEMORY;
HIMC hIMC = GetActiveContext(); CicIMCLock imcLock(hIMC); if (FAILED(imcLock.m_hr)) return imcLock.m_hr;
CicIMCCLock<CTFIMECONTEXT> imeContext(imcLock.get().hCtfImeContext); if (FAILED(imeContext.m_hr)) return imeContext.m_hr; CicInputContext *pCicIC = imeContext.get().m_pCicIC; if (!pCicIC) return E_FAIL;
UINT uCodePage = CP_ACP; pTLS->m_pProfile->GetCodePageA(&uCodePage);
pCicIC->SetupReconvertString(imcLock, pThreadMgr, uCodePage, 0, TRUE); pCicIC->EndReconvertString(imcLock); return S_OK;}