Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990/* * PROJECT: ReactOS msctfime.ime * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) * PURPOSE: Supporting IME interface of Text Input Processors (TIPs) * COPYRIGHT: Copyright 2023 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com> */
#include "msctfime.h"
WINE_DEFAULT_DEBUG_CHANNEL(msctfime);
HINSTANCE g_hInst = NULL; /* The instance of this module */BOOL g_bWinLogon = FALSE;UINT g_uACP = CP_ACP;DWORD g_dwOSInfo = 0;BOOL gfTFInitLib = FALSE;CRITICAL_SECTION g_csLock;CDispAttrPropCache *g_pPropCache = NULL;
/// Selects or unselects the input context./// @implementedstatic HRESULTInternalSelectEx( _In_ HIMC hIMC, _In_ BOOL fSelect, _In_ LANGID LangID){ CicIMCLock imcLock(hIMC); if (FAILED(imcLock.m_hr)) return imcLock.m_hr;
if (PRIMARYLANGID(LangID) == LANG_CHINESE) { imcLock.get().cfCandForm[0].dwStyle = 0; imcLock.get().cfCandForm[0].dwIndex = (DWORD)-1; }
if (!fSelect) { imcLock.get().fdwInit &= ~INIT_GUIDMAP; return imcLock.m_hr; }
if (!imcLock.ClearCand()) return imcLock.m_hr;
// Populate conversion mode if (!(imcLock.get().fdwInit & INIT_CONVERSION)) { DWORD dwConv = (imcLock.get().fdwConversion & IME_CMODE_SOFTKBD); if (LangID) { if (PRIMARYLANGID(LangID) == LANG_JAPANESE) { dwConv |= IME_CMODE_ROMAN | IME_CMODE_FULLSHAPE | IME_CMODE_NATIVE; } else if (PRIMARYLANGID(LangID) != LANG_KOREAN) { dwConv |= IME_CMODE_NATIVE; } } imcLock.get().fdwConversion |= dwConv; imcLock.get().fdwInit |= INIT_CONVERSION; }
// Populate sentence mode imcLock.get().fdwSentence |= IME_SMODE_PHRASEPREDICT;
// Populate LOGFONT if (!(imcLock.get().fdwInit & INIT_LOGFONT)) { // Get logical font LOGFONTW lf; HDC hDC = ::GetDC(imcLock.get().hWnd); HGDIOBJ hFont = ::GetCurrentObject(hDC, OBJ_FONT); ::GetObjectW(hFont, sizeof(LOGFONTW), &lf); ::ReleaseDC(imcLock.get().hWnd, hDC);
imcLock.get().lfFont.W = lf; imcLock.get().fdwInit |= INIT_LOGFONT; } imcLock.get().lfFont.W.lfCharSet = GetCharsetFromLangId(LangID);
imcLock.InitContext();
return imcLock.m_hr;}
/// Retrieves the IME information./// @implementedHRESULTInquire( _Out_ LPIMEINFO lpIMEInfo, _Out_ LPWSTR lpszWndClass, _In_ DWORD dwSystemInfoFlags, _In_ HKL hKL){ if (!lpIMEInfo) return E_OUTOFMEMORY;
StringCchCopyW(lpszWndClass, 64, L"MSCTFIME UI"); lpIMEInfo->dwPrivateDataSize = 0;
switch (LOWORD(hKL)) // Language ID { case MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT): // Japanese { lpIMEInfo->fdwProperty = IME_PROP_COMPLETE_ON_UNSELECT | IME_PROP_SPECIAL_UI | IME_PROP_AT_CARET | IME_PROP_NEED_ALTKEY | IME_PROP_KBD_CHAR_FIRST; lpIMEInfo->fdwConversionCaps = IME_CMODE_FULLSHAPE | IME_CMODE_KATAKANA | IME_CMODE_NATIVE; lpIMEInfo->fdwSentenceCaps = IME_SMODE_CONVERSATION | IME_SMODE_PLAURALCLAUSE; lpIMEInfo->fdwSelectCaps = SELECT_CAP_SENTENCE | SELECT_CAP_CONVERSION; lpIMEInfo->fdwSCSCaps = SCS_CAP_SETRECONVERTSTRING | SCS_CAP_MAKEREAD | SCS_CAP_COMPSTR; lpIMEInfo->fdwUICaps = UI_CAP_ROT90; break; } case MAKELANGID(LANG_KOREAN, SUBLANG_DEFAULT): // Korean { lpIMEInfo->fdwProperty = IME_PROP_COMPLETE_ON_UNSELECT | IME_PROP_SPECIAL_UI | IME_PROP_AT_CARET | IME_PROP_NEED_ALTKEY | IME_PROP_KBD_CHAR_FIRST; lpIMEInfo->fdwConversionCaps = IME_CMODE_FULLSHAPE | IME_CMODE_NATIVE; lpIMEInfo->fdwSentenceCaps = 0; lpIMEInfo->fdwSCSCaps = SCS_CAP_SETRECONVERTSTRING | SCS_CAP_COMPSTR; lpIMEInfo->fdwSelectCaps = SELECT_CAP_CONVERSION; lpIMEInfo->fdwUICaps = UI_CAP_ROT90; break; } case MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED): // Simplified Chinese case MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL): // Traditional Chinese { lpIMEInfo->fdwProperty = IME_PROP_SPECIAL_UI | IME_PROP_AT_CARET | IME_PROP_NEED_ALTKEY | IME_PROP_KBD_CHAR_FIRST; lpIMEInfo->fdwConversionCaps = IME_CMODE_FULLSHAPE | IME_CMODE_NATIVE; lpIMEInfo->fdwSentenceCaps = SELECT_CAP_CONVERSION; lpIMEInfo->fdwSelectCaps = 0; lpIMEInfo->fdwSCSCaps = SCS_CAP_SETRECONVERTSTRING | SCS_CAP_MAKEREAD | SCS_CAP_COMPSTR; lpIMEInfo->fdwUICaps = UI_CAP_ROT90; break; } default: // Otherwise { lpIMEInfo->fdwProperty = IME_PROP_UNICODE | IME_PROP_AT_CARET; lpIMEInfo->fdwConversionCaps = 0; lpIMEInfo->fdwSentenceCaps = 0; lpIMEInfo->fdwSCSCaps = 0; lpIMEInfo->fdwUICaps = 0; lpIMEInfo->fdwSelectCaps = 0; break; } }
return S_OK;}
/*********************************************************************** * ImeInquire (MSCTFIME.@) * * MSCTFIME's ImeInquire does nothing. * * @implemented * @see CtfImeInquireExW * @see https://katahiromz.web.fc2.com/colony3rd/imehackerz/en/ImeInquire.html */EXTERN_CBOOL WINAPIImeInquire( _Out_ LPIMEINFO lpIMEInfo, _Out_ LPWSTR lpszWndClass, _In_ DWORD dwSystemInfoFlags){ TRACE("(%p, %p, 0x%lX)\n", lpIMEInfo, lpszWndClass, dwSystemInfoFlags); return FALSE;}
/*********************************************************************** * ImeConversionList (MSCTFIME.@) * * MSCTFIME's ImeConversionList does nothing. * * @implemented * @see ImmGetConversionListW * @see https://katahiromz.web.fc2.com/colony3rd/imehackerz/en/ImeConversionList.html */EXTERN_C DWORD WINAPIImeConversionList( _In_ HIMC hIMC, _In_ LPCWSTR lpSrc, _Out_ LPCANDIDATELIST lpDst, _In_ DWORD dwBufLen, _In_ UINT uFlag){ TRACE("(%p, %s, %p, 0x%lX, %u)\n", hIMC, debugstr_w(lpSrc), lpDst, dwBufLen, uFlag); return 0;}
/*********************************************************************** * ImeRegisterWord (MSCTFIME.@) * * MSCTFIME's ImeRegisterWord does nothing. * * @implemented * @see ImeUnregisterWord * @see https://katahiromz.web.fc2.com/colony3rd/imehackerz/en/ImeRegisterWord.html */EXTERN_C BOOL WINAPIImeRegisterWord( _In_ LPCWSTR lpszReading, _In_ DWORD dwStyle, _In_ LPCWSTR lpszString){ TRACE("(%s, 0x%lX, %s)\n", debugstr_w(lpszReading), dwStyle, debugstr_w(lpszString)); return FALSE;}
/*********************************************************************** * ImeUnregisterWord (MSCTFIME.@) * * MSCTFIME's ImeUnregisterWord does nothing. * * @implemented * @see ImeRegisterWord * @see https://katahiromz.web.fc2.com/colony3rd/imehackerz/en/ImeUnregisterWord.html */EXTERN_C BOOL WINAPIImeUnregisterWord( _In_ LPCWSTR lpszReading, _In_ DWORD dwStyle, _In_ LPCWSTR lpszString){ TRACE("(%s, 0x%lX, %s)\n", debugstr_w(lpszReading), dwStyle, debugstr_w(lpszString)); return FALSE;}
/*********************************************************************** * ImeGetRegisterWordStyle (MSCTFIME.@) * * MSCTFIME's ImeGetRegisterWordStyle does nothing. * * @implemented * @see ImeRegisterWord * @see https://katahiromz.web.fc2.com/colony3rd/imehackerz/en/ImeGetRegisterWordStyle.html */EXTERN_C UINT WINAPIImeGetRegisterWordStyle( _In_ UINT nItem, _Out_ LPSTYLEBUFW lpStyleBuf){ TRACE("(%u, %p)\n", nItem, lpStyleBuf); return 0;}
/*********************************************************************** * ImeEnumRegisterWord (MSCTFIME.@) * * MSCTFIME's ImeEnumRegisterWord does nothing. * * @implemented * @see ImeRegisterWord * @see https://katahiromz.web.fc2.com/colony3rd/imehackerz/en/ImeEnumRegisterWord.html */EXTERN_C UINT WINAPIImeEnumRegisterWord( _In_ REGISTERWORDENUMPROCW lpfnEnumProc, _In_opt_ LPCWSTR lpszReading, _In_ DWORD dwStyle, _In_opt_ LPCWSTR lpszString, _In_opt_ LPVOID lpData){ TRACE("(%p, %s, %lu, %s, %p)\n", lpfnEnumProc, debugstr_w(lpszReading), dwStyle, debugstr_w(lpszString), lpData); return 0;}
/*********************************************************************** * ImeConfigure (MSCTFIME.@) * * @implemented * @see https://katahiromz.web.fc2.com/colony3rd/imehackerz/en/ImeConfigure.html */EXTERN_C BOOL WINAPIImeConfigure( _In_ HKL hKL, _In_ HWND hWnd, _In_ DWORD dwMode, _Inout_opt_ LPVOID lpData){ TRACE("(%p, %p, %lu, %p)\n", hKL, hWnd, dwMode, lpData);
TLS *pTLS = TLS::GetTLS(); if (!pTLS || !pTLS->m_pBridge || !pTLS->m_pThreadMgr) return FALSE;
auto pBridge = pTLS->m_pBridge; auto pThreadMgr = pTLS->m_pThreadMgr;
if (dwMode & 0x1) return (pBridge->ConfigureGeneral(pTLS, pThreadMgr, hKL, hWnd) == S_OK);
if (dwMode & 0x2) return (pBridge->ConfigureRegisterWord(pTLS, pThreadMgr, hKL, hWnd, lpData) == S_OK);
return FALSE;}
/*********************************************************************** * ImeDestroy (MSCTFIME.@) * * @implemented * @see https://katahiromz.web.fc2.com/colony3rd/imehackerz/en/ImeDestroy.html */EXTERN_C BOOL WINAPIImeDestroy( _In_ UINT uReserved){ TRACE("(%u)\n", uReserved);
TLS *pTLS = TLS::PeekTLS(); if (pTLS) return FALSE;
if (!pTLS->m_pBridge || !pTLS->m_pThreadMgr) return FALSE;
if (pTLS->m_dwSystemInfoFlags & IME_SYSINFO_WINLOGON) return TRUE;
if (pTLS->m_pBridge->DeactivateIMMX(pTLS, pTLS->m_pThreadMgr) != S_OK) return FALSE;
return pTLS->m_pBridge->UnInitIMMX(pTLS);}
/*********************************************************************** * ImeEscape (MSCTFIME.@) * * MSCTFIME's ImeEscape does nothing. * * @implemented * @see CtfImeEscapeEx * @see https://katahiromz.web.fc2.com/colony3rd/imehackerz/en/ImeEscape.html */EXTERN_C LRESULT WINAPIImeEscape( _In_ HIMC hIMC, _In_ UINT uEscape, _Inout_opt_ LPVOID lpData){ TRACE("(%p, %u, %p)\n", hIMC, uEscape, lpData); return 0;}
/*********************************************************************** * ImeProcessKey (MSCTFIME.@) * * @implemented * @see https://katahiromz.web.fc2.com/colony3rd/imehackerz/en/ImeProcessKey.html */EXTERN_C BOOL WINAPIImeProcessKey( _In_ HIMC hIMC, _In_ UINT uVirtKey, _In_ LPARAM lParam, _In_ CONST LPBYTE lpbKeyState){ TRACE("(%p, %u, %p, lpbKeyState)\n", hIMC, uVirtKey, lParam, lpbKeyState);
TLS *pTLS = TLS::GetTLS(); if (!pTLS) return FALSE;
auto pBridge = pTLS->m_pBridge; auto pThreadMgr = pTLS->m_pThreadMgr; if (!pBridge || !pThreadMgr) return FALSE;
if (pTLS->m_dwFlags1 & 0x1) { ITfDocumentMgr *pDocMgr = NULL; pThreadMgr->GetFocus(&pDocMgr); if (pDocMgr && !CicBridge::IsOwnDim(pDocMgr)) { pDocMgr->Release(); return FALSE; }
if (pDocMgr) pDocMgr->Release(); }
LANGID LangID = LOWORD(::GetKeyboardLayout(0)); if (((pTLS->m_dwFlags2 & 1) && MsimtfIsGuidMapEnable(hIMC, NULL)) || ((lParam & (KF_ALTDOWN << 16)) && (LangID == MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT)) && IsVKDBEKey(uVirtKey))) { return FALSE; }
INT nUnknown60 = 0; return pBridge->ProcessKey(pTLS, pThreadMgr, hIMC, uVirtKey, lParam, lpbKeyState, &nUnknown60);}
/*********************************************************************** * ImeSelect (MSCTFIME.@) * * MSCTFIME's ImeSelect does nothing. * * @implemented * @see CtfImeSelectEx * @see https://katahiromz.web.fc2.com/colony3rd/imehackerz/en/ImeSelect.html */EXTERN_C BOOL WINAPIImeSelect( _In_ HIMC hIMC, _In_ BOOL fSelect){ TRACE("(%p, %u)\n", hIMC, fSelect); return FALSE;}
/*********************************************************************** * ImeSetActiveContext (MSCTFIME.@) * * MSCTFIME's ImeSetActiveContext does nothing. * * @implemented * @see CtfImeSetActiveContextAlways * @see https://katahiromz.web.fc2.com/colony3rd/imehackerz/en/ImeSetActiveContext.html */EXTERN_C BOOL WINAPIImeSetActiveContext( _In_ HIMC hIMC, _In_ BOOL fFlag){ TRACE("(%p, %u)\n", hIMC, fFlag); return FALSE;}
/*********************************************************************** * ImeToAsciiEx (MSCTFIME.@) * * @implemented * @see https://katahiromz.web.fc2.com/colony3rd/imehackerz/en/ImeToAsciiEx.html */EXTERN_C UINT WINAPIImeToAsciiEx( _In_ UINT uVirtKey, _In_ UINT uScanCode, _In_ CONST LPBYTE lpbKeyState, _Out_ LPTRANSMSGLIST lpTransMsgList, _In_ UINT fuState, _In_ HIMC hIMC){ TRACE("(%u, %u, %p, %p, %u, %p)\n", uVirtKey, uScanCode, lpbKeyState, lpTransMsgList, fuState, hIMC);
TLS *pTLS = TLS::GetTLS(); if (!pTLS) return 0;
auto pBridge = pTLS->m_pBridge; auto pThreadMgr = pTLS->m_pThreadMgr; if (!pBridge || !pThreadMgr) return 0;
UINT ret = 0; HRESULT hr = pBridge->ToAsciiEx(pTLS, pThreadMgr, uVirtKey, uScanCode, lpbKeyState, lpTransMsgList, fuState, hIMC, &ret); return ((hr == S_OK) ? ret : 0);}
/*********************************************************************** * NotifyIME (MSCTFIME.@) * * @implemented * @see https://katahiromz.web.fc2.com/colony3rd/imehackerz/en/NotifyIME.html */EXTERN_C BOOL WINAPINotifyIME( _In_ HIMC hIMC, _In_ DWORD dwAction, _In_ DWORD dwIndex, _In_ DWORD_PTR dwValue){ TRACE("(%p, 0x%lX, 0x%lX, %p)\n", hIMC, dwAction, dwIndex, dwValue);
TLS *pTLS = TLS::GetTLS(); if (!pTLS) return FALSE;
auto pBridge = pTLS->m_pBridge; auto pThreadMgr = pTLS->m_pThreadMgr; if (!pBridge || !pThreadMgr) return FALSE;
HRESULT hr = pBridge->Notify(pTLS, pThreadMgr, hIMC, dwAction, dwIndex, dwValue); return (hr == S_OK);}
/*********************************************************************** * ImeSetCompositionString (MSCTFIME.@) * * @implemented * @see https://katahiromz.web.fc2.com/colony3rd/imehackerz/en/ImeSetCompositionString.html */EXTERN_C BOOL WINAPIImeSetCompositionString( _In_ HIMC hIMC, _In_ DWORD dwIndex, _In_opt_ LPCVOID lpComp, _In_ DWORD dwCompLen, _In_opt_ LPCVOID lpRead, _In_ DWORD dwReadLen){ TRACE("(%p, 0x%lX, %p, 0x%lX, %p, 0x%lX)\n", hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
TLS *pTLS = TLS::GetTLS(); if (!pTLS) return FALSE;
auto pBridge = pTLS->m_pBridge; auto pThreadMgr = pTLS->m_pThreadMgr; if (!pBridge || !pThreadMgr) return FALSE;
return pBridge->SetCompositionString(pTLS, pThreadMgr, hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);}
/*********************************************************************** * CtfImeInquireExW (MSCTFIME.@) * * @implemented */EXTERN_C HRESULT WINAPICtfImeInquireExW( _Out_ LPIMEINFO lpIMEInfo, _Out_ LPWSTR lpszWndClass, _In_ DWORD dwSystemInfoFlags, _In_ HKL hKL){ TRACE("(%p, %p, 0x%lX, %p)\n", lpIMEInfo, lpszWndClass, dwSystemInfoFlags, hKL);
TLS *pTLS = TLS::GetTLS(); if (!pTLS) return E_OUTOFMEMORY;
if (!IsInteractiveUserLogon()) { dwSystemInfoFlags |= IME_SYSINFO_WINLOGON; g_bWinLogon = TRUE; }
pTLS->m_dwSystemInfoFlags = dwSystemInfoFlags;
return Inquire(lpIMEInfo, lpszWndClass, dwSystemInfoFlags, hKL);}
/*********************************************************************** * CtfImeSelectEx (MSCTFIME.@) * * @implemented */EXTERN_C BOOL WINAPICtfImeSelectEx( _In_ HIMC hIMC, _In_ BOOL fSelect, _In_ HKL hKL){ TRACE("(%p, %d, %p)\n", hIMC, fSelect, hKL);
TLS *pTLS = TLS::PeekTLS(); if (!pTLS) return E_OUTOFMEMORY;
InternalSelectEx(hIMC, fSelect, LOWORD(hKL));
if (!pTLS->m_pBridge || !pTLS->m_pThreadMgr) return E_OUTOFMEMORY;
return pTLS->m_pBridge->SelectEx(pTLS, pTLS->m_pThreadMgr, hIMC, fSelect, hKL);}
/*********************************************************************** * CtfImeEscapeEx (MSCTFIME.@) * * @implemented */EXTERN_C LRESULT WINAPICtfImeEscapeEx( _In_ HIMC hIMC, _In_ UINT uSubFunc, _Inout_opt_ LPVOID lpData, _In_ HKL hKL){ TRACE("(%p, %u, %p, %p)\n", hIMC, uSubFunc, lpData, hKL);
if (LOWORD(hKL) != MAKELANGID(LANG_KOREAN, SUBLANG_DEFAULT)) return 0;
TLS *pTLS = TLS::GetTLS(); if (!pTLS || !pTLS->m_pBridge) return 0;
return pTLS->m_pBridge->EscapeKorean(pTLS, hIMC, uSubFunc, lpData);}
/*********************************************************************** * CtfImeGetGuidAtom (MSCTFIME.@) * * @implemented */EXTERN_C HRESULT WINAPICtfImeGetGuidAtom( _In_ HIMC hIMC, _In_ DWORD dwUnknown, _Out_opt_ LPDWORD pdwGuidAtom){ TRACE("(%p, 0x%lX, %p)\n", hIMC, dwUnknown, pdwGuidAtom);
CicIMCLock imcLock(hIMC); if (FAILED(imcLock.m_hr)) return imcLock.m_hr;
CicIMCCLock<CTFIMECONTEXT> imccLock(imcLock.get().hCtfImeContext); if (FAILED(imccLock.m_hr)) return imccLock.m_hr;
if (!imccLock.get().m_pCicIC) return E_OUTOFMEMORY;
return imccLock.get().m_pCicIC->GetGuidAtom(imcLock, dwUnknown, pdwGuidAtom);}
/*********************************************************************** * CtfImeIsGuidMapEnable (MSCTFIME.@) * * @implemented */EXTERN_C BOOL WINAPICtfImeIsGuidMapEnable( _In_ HIMC hIMC){ TRACE("(%p)\n", hIMC);
BOOL ret = FALSE; CicIMCLock imcLock(hIMC); if (SUCCEEDED(imcLock.m_hr)) ret = !!(imcLock.get().fdwInit & INIT_GUIDMAP);
return ret;}
/*********************************************************************** * CtfImeCreateThreadMgr (MSCTFIME.@) * * @implemented */EXTERN_C HRESULT WINAPICtfImeCreateThreadMgr(VOID){ TRACE("()\n");
TLS *pTLS = TLS::GetTLS(); if (!pTLS) return E_OUTOFMEMORY;
if (!pTLS->m_pBridge) { pTLS->m_pBridge = new(cicNoThrow) CicBridge(); if (!pTLS->m_pBridge) return E_OUTOFMEMORY; }
HRESULT hr = S_OK; if (!g_bWinLogon && !(pTLS->m_dwSystemInfoFlags & IME_SYSINFO_WINLOGON)) { hr = pTLS->m_pBridge->InitIMMX(pTLS); if (SUCCEEDED(hr)) { if (!pTLS->m_pThreadMgr) return E_OUTOFMEMORY;
hr = pTLS->m_pBridge->ActivateIMMX(pTLS, pTLS->m_pThreadMgr); if (FAILED(hr)) pTLS->m_pBridge->UnInitIMMX(pTLS); } }
return hr;}
/*********************************************************************** * CtfImeDestroyThreadMgr (MSCTFIME.@) * * @implemented */EXTERN_C HRESULT WINAPICtfImeDestroyThreadMgr(VOID){ TRACE("()\n");
TLS *pTLS = TLS::PeekTLS(); if (!pTLS) return E_OUTOFMEMORY;
if (pTLS->m_pBridge) { pTLS->m_pBridge = new(cicNoThrow) CicBridge(); if (!pTLS->m_pBridge) return E_OUTOFMEMORY; }
if (!pTLS->m_pThreadMgr) return E_OUTOFMEMORY;
if (pTLS->m_dwSystemInfoFlags & IME_SYSINFO_WINLOGON) return S_OK;
HRESULT hr = pTLS->m_pBridge->DeactivateIMMX(pTLS, pTLS->m_pThreadMgr); if (hr == S_OK) pTLS->m_pBridge->UnInitIMMX(pTLS);
return hr;}
/*********************************************************************** * CtfImeCreateInputContext (MSCTFIME.@) * * @implemented */EXTERN_C HRESULT WINAPICtfImeCreateInputContext( _In_ HIMC hIMC){ TRACE("(%p)\n", hIMC);
TLS *pTLS = TLS::GetTLS(); if (!pTLS || !pTLS->m_pBridge) return E_OUTOFMEMORY;
return pTLS->m_pBridge->CreateInputContext(pTLS, hIMC);}
/*********************************************************************** * CtfImeDestroyInputContext (MSCTFIME.@) * * @implemented */EXTERN_C HRESULT WINAPICtfImeDestroyInputContext( _In_ HIMC hIMC){ TRACE("(%p)\n", hIMC);
TLS *pTLS = TLS::PeekTLS(); if (!pTLS || !pTLS->m_pBridge) return E_OUTOFMEMORY;
return pTLS->m_pBridge->DestroyInputContext(pTLS, hIMC);}
/*********************************************************************** * CtfImeSetActiveContextAlways (MSCTFIME.@) * * @implemented */EXTERN_C HRESULT WINAPICtfImeSetActiveContextAlways( _In_ HIMC hIMC, _In_ BOOL fActive, _In_ HWND hWnd, _In_ HKL hKL){ TRACE("(%p, %d, %p, %p)\n", hIMC, fActive, hWnd, hKL);
TLS *pTLS = TLS::GetTLS(); if (!pTLS || !pTLS->m_pBridge) return E_OUTOFMEMORY; return pTLS->m_pBridge->SetActiveContextAlways(pTLS, hIMC, fActive, hWnd, hKL);}
/*********************************************************************** * CtfImeProcessCicHotkey (MSCTFIME.@) * * @implemented */EXTERN_C HRESULT WINAPICtfImeProcessCicHotkey( _In_ HIMC hIMC, _In_ UINT vKey, _In_ LPARAM lParam){ TRACE("(%p, %u, %p)\n", hIMC, vKey, lParam);
TLS *pTLS = TLS::GetTLS(); if (!pTLS) return S_OK;
HRESULT hr = S_OK; ITfThreadMgr *pThreadMgr = NULL; ITfThreadMgr_P *pThreadMgr_P = NULL; if ((TF_GetThreadMgr(&pThreadMgr) == S_OK) && (pThreadMgr->QueryInterface(IID_ITfThreadMgr_P, (void**)&pThreadMgr_P) == S_OK) && CtfImmIsCiceroStartedInThread()) { HRESULT hr2; if (SUCCEEDED(pThreadMgr_P->CallImm32HotkeyHandler(vKey, lParam, &hr2))) hr = hr2; }
if (pThreadMgr) pThreadMgr->Release(); if (pThreadMgr_P) pThreadMgr_P->Release();
return hr;}
/*********************************************************************** * CtfImeDispatchDefImeMessage (MSCTFIME.@) * * @implemented */EXTERN_C LRESULT WINAPICtfImeDispatchDefImeMessage( _In_ HWND hWnd, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam){ TRACE("(%p, %u, %p, %p)\n", hWnd, uMsg, wParam, lParam);
TLS *pTLS = TLS::GetTLS(); if (pTLS) { if (uMsg == WM_CREATE) ++pTLS->m_cWnds; else if (uMsg == WM_DESTROY) --pTLS->m_cWnds; }
if (!IsMsImeMessage(uMsg)) return 0;
HKL hKL = ::GetKeyboardLayout(0); if (IS_IME_HKL(hKL)) return 0;
HWND hImeWnd = (HWND)::SendMessageW(hWnd, WM_IME_NOTIFY, 0x17, 0); if (!IsWindow(hImeWnd)) return 0;
return ::SendMessageW(hImeWnd, uMsg, wParam, lParam);}
/*********************************************************************** * CtfImeIsIME (MSCTFIME.@) * * @implemented */EXTERN_C BOOL WINAPICtfImeIsIME( _In_ HKL hKL){ TRACE("(%p)\n", hKL);
if (IS_IME_HKL(hKL)) return TRUE;
TLS *pTLS = TLS::GetTLS(); if (!pTLS || !pTLS->m_pProfile) return FALSE;
// The return value of CicProfile::IsIME is brain-damaged return !pTLS->m_pProfile->IsIME(hKL);}
/*********************************************************************** * CtfImeThreadDetach (MSCTFIME.@) * * @implemented */EXTERN_C HRESULT WINAPICtfImeThreadDetach(VOID){ ImeDestroy(0); return S_OK;}
/// @implementedBOOL AttachIME(VOID){ return RegisterImeClass() && RegisterMSIMEMessage();}
/// @implementedVOID DetachIME(VOID){ UnregisterImeClass();}
EXTERN_C VOID TFUninitLib(VOID){ if (g_pPropCache) { delete g_pPropCache; g_pPropCache = NULL; }}
/// @implementedBOOL ProcessAttach(HINSTANCE hinstDLL){ g_hInst = hinstDLL;
::InitializeCriticalSectionAndSpinCount(&g_csLock, 0);
if (!TLS::Initialize()) return FALSE;
cicGetOSInfo(&g_uACP, &g_dwOSInfo);
cicInitUIFLib();
if (!TFInitLib()) return FALSE;
gfTFInitLib = TRUE; return AttachIME();}
/// @implementedVOID ProcessDetach(HINSTANCE hinstDLL){ TF_DllDetachInOther();
if (gfTFInitLib) { DetachIME(); TFUninitLib(); }
::DeleteCriticalSection(&g_csLock); TLS::InternalDestroyTLS(); TLS::Uninitialize(); cicDoneUIFLib();}
/// @implementedEXTERN_C BOOL WINAPIDllMain( _In_ HINSTANCE hinstDLL, _In_ DWORD dwReason, _Inout_opt_ LPVOID lpvReserved){ switch (dwReason) { case DLL_PROCESS_ATTACH: { TRACE("(%p, %lu, %p)\n", hinstDLL, dwReason, lpvReserved); if (!ProcessAttach(hinstDLL)) { ProcessDetach(hinstDLL); return FALSE; } break; } case DLL_PROCESS_DETACH: { ProcessDetach(hinstDLL); break; } case DLL_THREAD_DETACH: { TF_DllDetachInOther(); CtfImeThreadDetach(); TLS::InternalDestroyTLS(); break; } } return TRUE;}