2023-12-18 10:11:17 +00:00
|
|
|
/*
|
|
|
|
* 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"
|
2024-01-01 07:36:49 +00:00
|
|
|
#include <ndk/ldrfuncs.h> /* for RtlDllShutdownInProgress */
|
2023-12-18 10:11:17 +00:00
|
|
|
|
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(msctfime);
|
|
|
|
|
2024-02-20 05:36:24 +00:00
|
|
|
typedef CicArray<GUID> CDispAttrPropCache;
|
|
|
|
|
2023-12-18 10:11:17 +00:00
|
|
|
HINSTANCE g_hInst = NULL; /* The instance of this module */
|
|
|
|
BOOL g_bWinLogon = FALSE;
|
2023-12-22 02:52:06 +00:00
|
|
|
UINT g_uACP = CP_ACP;
|
2023-12-18 10:11:17 +00:00
|
|
|
DWORD g_dwOSInfo = 0;
|
|
|
|
BOOL gfTFInitLib = FALSE;
|
|
|
|
CRITICAL_SECTION g_csLock;
|
2024-02-20 05:36:24 +00:00
|
|
|
CDispAttrPropCache *g_pPropCache = NULL;
|
2023-12-18 10:11:17 +00:00
|
|
|
|
2023-12-21 07:23:23 +00:00
|
|
|
EXTERN_C void __cxa_pure_virtual(void)
|
|
|
|
{
|
|
|
|
ERR("__cxa_pure_virtual\n");
|
|
|
|
}
|
|
|
|
|
2024-02-20 12:11:08 +00:00
|
|
|
typedef BOOLEAN (WINAPI *FN_DllShutdownInProgress)(VOID);
|
2023-12-18 10:11:17 +00:00
|
|
|
|
2024-01-05 09:36:30 +00:00
|
|
|
/// This function calls ntdll!RtlDllShutdownInProgress.
|
|
|
|
/// It can detect the system is shutting down or not.
|
|
|
|
/// @implemented
|
2024-02-20 12:11:08 +00:00
|
|
|
EXTERN_C BOOLEAN WINAPI DllShutdownInProgress(VOID)
|
2023-12-18 10:11:17 +00:00
|
|
|
{
|
|
|
|
HMODULE hNTDLL;
|
2024-02-20 12:11:08 +00:00
|
|
|
static FN_DllShutdownInProgress s_fnDllShutdownInProgress = NULL;
|
2023-12-18 10:11:17 +00:00
|
|
|
|
2024-02-20 12:11:08 +00:00
|
|
|
if (s_fnDllShutdownInProgress)
|
|
|
|
return s_fnDllShutdownInProgress();
|
2023-12-18 10:11:17 +00:00
|
|
|
|
2023-12-21 10:05:33 +00:00
|
|
|
hNTDLL = cicGetSystemModuleHandle(L"ntdll.dll", FALSE);
|
2024-02-20 12:11:08 +00:00
|
|
|
s_fnDllShutdownInProgress =
|
|
|
|
(FN_DllShutdownInProgress)GetProcAddress(hNTDLL, "RtlDllShutdownInProgress");
|
|
|
|
if (!s_fnDllShutdownInProgress)
|
2023-12-18 10:11:17 +00:00
|
|
|
return FALSE;
|
|
|
|
|
2024-02-20 12:11:08 +00:00
|
|
|
return s_fnDllShutdownInProgress();
|
2023-12-18 10:11:17 +00:00
|
|
|
}
|
|
|
|
|
2024-01-05 09:36:30 +00:00
|
|
|
/// This function checks if the current user logon session is interactive.
|
|
|
|
/// @implemented
|
2023-12-18 10:11:17 +00:00
|
|
|
static BOOL
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2024-02-20 05:36:24 +00:00
|
|
|
/// @implemented
|
|
|
|
ITfCategoryMgr *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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// @implemented
|
|
|
|
HRESULT LibEnumItemsInCategory(PCIC_LIBTHREAD pLibThread, REFGUID rguid, IEnumGUID **ppEnum)
|
|
|
|
{
|
|
|
|
ITfCategoryMgr *pCat = GetUIMCat(pLibThread);
|
|
|
|
if (!pCat)
|
|
|
|
return E_FAIL;
|
|
|
|
return pCat->EnumItemsInCategory(rguid, ppEnum);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// @implemented
|
2023-12-23 00:34:41 +00:00
|
|
|
HRESULT InitDisplayAttrbuteLib(PCIC_LIBTHREAD pLibThread)
|
2023-12-20 07:12:57 +00:00
|
|
|
{
|
|
|
|
if (!pLibThread)
|
|
|
|
return E_FAIL;
|
|
|
|
|
|
|
|
if (pLibThread->m_pDisplayAttrMgr)
|
|
|
|
{
|
|
|
|
pLibThread->m_pDisplayAttrMgr->Release();
|
|
|
|
pLibThread->m_pDisplayAttrMgr = NULL;
|
|
|
|
}
|
|
|
|
|
2024-02-20 05:36:24 +00:00
|
|
|
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;
|
|
|
|
}
|
2024-02-20 12:11:08 +00:00
|
|
|
}
|
|
|
|
::LeaveCriticalSection(&g_csLock);
|
2023-12-18 12:56:21 +00:00
|
|
|
|
2024-02-20 12:11:08 +00:00
|
|
|
return hr;
|
2023-12-18 12:56:21 +00:00
|
|
|
}
|
|
|
|
|
2024-01-05 09:36:30 +00:00
|
|
|
/// @implemented
|
2024-02-20 12:11:08 +00:00
|
|
|
HRESULT UninitDisplayAttrbuteLib(PCIC_LIBTHREAD pLibThread)
|
2023-12-18 12:56:21 +00:00
|
|
|
{
|
2024-02-20 12:11:08 +00:00
|
|
|
if (!pLibThread)
|
|
|
|
return E_FAIL;
|
2023-12-18 12:56:21 +00:00
|
|
|
|
2024-02-20 12:11:08 +00:00
|
|
|
if (pLibThread->m_pDisplayAttrMgr)
|
2023-12-21 01:42:06 +00:00
|
|
|
{
|
2024-02-20 12:11:08 +00:00
|
|
|
pLibThread->m_pDisplayAttrMgr->Release();
|
|
|
|
pLibThread->m_pDisplayAttrMgr = NULL;
|
2023-12-21 01:42:06 +00:00
|
|
|
}
|
2024-02-20 12:11:08 +00:00
|
|
|
|
|
|
|
return S_OK;
|
2023-12-21 01:42:06 +00:00
|
|
|
}
|
|
|
|
|
2024-02-20 12:11:08 +00:00
|
|
|
/// Gets the charset from a language ID.
|
2024-01-05 09:36:30 +00:00
|
|
|
/// @implemented
|
2024-02-20 12:11:08 +00:00
|
|
|
BYTE GetCharsetFromLangId(_In_ DWORD dwValue)
|
2023-12-19 10:23:52 +00:00
|
|
|
{
|
2024-02-20 12:11:08 +00:00
|
|
|
CHARSETINFO info;
|
|
|
|
if (!::TranslateCharsetInfo((DWORD*)(DWORD_PTR)dwValue, &info, TCI_SRCLOCALE))
|
|
|
|
return 0;
|
|
|
|
return info.ciCharset;
|
2023-12-19 10:23:52 +00:00
|
|
|
}
|
|
|
|
|
2024-02-20 12:11:08 +00:00
|
|
|
/// Selects or unselects the input context.
|
2024-01-05 09:36:30 +00:00
|
|
|
/// @implemented
|
2023-12-19 10:23:52 +00:00
|
|
|
HRESULT
|
2024-02-20 12:11:08 +00:00
|
|
|
InternalSelectEx(
|
|
|
|
_In_ HIMC hIMC,
|
|
|
|
_In_ BOOL fSelect,
|
|
|
|
_In_ LANGID LangID)
|
2023-12-19 10:23:52 +00:00
|
|
|
{
|
2024-02-20 12:11:08 +00:00
|
|
|
CicIMCLock imcLock(hIMC);
|
|
|
|
if (FAILED(imcLock.m_hr))
|
|
|
|
return imcLock.m_hr;
|
2023-12-19 10:23:52 +00:00
|
|
|
|
2024-02-20 12:11:08 +00:00
|
|
|
if (PRIMARYLANGID(LangID) == LANG_CHINESE)
|
|
|
|
{
|
|
|
|
imcLock.get().cfCandForm[0].dwStyle = 0;
|
|
|
|
imcLock.get().cfCandForm[0].dwIndex = (DWORD)-1;
|
|
|
|
}
|
2023-12-19 10:23:52 +00:00
|
|
|
|
2024-02-20 12:11:08 +00:00
|
|
|
if (!fSelect)
|
2023-12-19 10:23:52 +00:00
|
|
|
{
|
2024-02-20 12:11:08 +00:00
|
|
|
imcLock.get().fdwInit &= ~INIT_GUIDMAP;
|
|
|
|
return imcLock.m_hr;
|
2023-12-19 10:23:52 +00:00
|
|
|
}
|
|
|
|
|
2024-02-20 12:11:08 +00:00
|
|
|
if (!imcLock.ClearCand())
|
|
|
|
return imcLock.m_hr;
|
|
|
|
|
|
|
|
// Populate conversion mode
|
|
|
|
if (!(imcLock.get().fdwInit & INIT_CONVERSION))
|
2023-12-19 10:23:52 +00:00
|
|
|
{
|
2024-02-20 12:11:08 +00:00
|
|
|
DWORD dwConv = (imcLock.get().fdwConversion & IME_CMODE_SOFTKBD);
|
|
|
|
if (LangID)
|
2023-12-19 10:23:52 +00:00
|
|
|
{
|
2024-02-20 12:11:08 +00:00
|
|
|
if (PRIMARYLANGID(LangID) == LANG_JAPANESE)
|
2023-12-19 10:23:52 +00:00
|
|
|
{
|
2024-02-20 12:11:08 +00:00
|
|
|
dwConv |= IME_CMODE_ROMAN | IME_CMODE_FULLSHAPE | IME_CMODE_NATIVE;
|
|
|
|
}
|
|
|
|
else if (PRIMARYLANGID(LangID) != LANG_KOREAN)
|
|
|
|
{
|
|
|
|
dwConv |= IME_CMODE_NATIVE;
|
2023-12-19 10:23:52 +00:00
|
|
|
}
|
|
|
|
}
|
2024-02-20 12:11:08 +00:00
|
|
|
imcLock.get().fdwConversion |= dwConv;
|
|
|
|
imcLock.get().fdwInit |= INIT_CONVERSION;
|
2023-12-19 10:23:52 +00:00
|
|
|
}
|
|
|
|
|
2024-02-20 12:11:08 +00:00
|
|
|
// Populate sentence mode
|
|
|
|
imcLock.get().fdwSentence |= IME_SMODE_PHRASEPREDICT;
|
2023-12-19 10:23:52 +00:00
|
|
|
|
2024-02-20 12:11:08 +00:00
|
|
|
// 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);
|
2023-12-19 10:23:52 +00:00
|
|
|
|
2024-02-20 12:11:08 +00:00
|
|
|
imcLock.get().lfFont.W = lf;
|
|
|
|
imcLock.get().fdwInit |= INIT_LOGFONT;
|
|
|
|
}
|
|
|
|
imcLock.get().lfFont.W.lfCharSet = GetCharsetFromLangId(LangID);
|
|
|
|
|
|
|
|
imcLock.InitContext();
|
|
|
|
|
|
|
|
return imcLock.m_hr;
|
2023-12-19 10:23:52 +00:00
|
|
|
}
|
|
|
|
|
2024-02-20 12:11:08 +00:00
|
|
|
class TLS;
|
|
|
|
|
2023-12-18 10:11:17 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* ImeInquire (MSCTFIME.@)
|
|
|
|
*
|
|
|
|
* MSCTFIME's ImeInquire does nothing.
|
|
|
|
*
|
|
|
|
* @implemented
|
|
|
|
* @see CtfImeInquireExW
|
|
|
|
*/
|
|
|
|
EXTERN_C
|
|
|
|
BOOL WINAPI
|
|
|
|
ImeInquire(
|
|
|
|
_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
|
|
|
|
*/
|
|
|
|
EXTERN_C DWORD WINAPI
|
|
|
|
ImeConversionList(
|
|
|
|
_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
|
|
|
|
*/
|
|
|
|
EXTERN_C BOOL WINAPI
|
|
|
|
ImeRegisterWord(
|
|
|
|
_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
|
|
|
|
*/
|
|
|
|
EXTERN_C BOOL WINAPI
|
|
|
|
ImeUnregisterWord(
|
|
|
|
_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
|
|
|
|
*/
|
|
|
|
EXTERN_C UINT WINAPI
|
|
|
|
ImeGetRegisterWordStyle(
|
|
|
|
_In_ UINT nItem,
|
|
|
|
_Out_ LPSTYLEBUFW lpStyleBuf)
|
|
|
|
{
|
|
|
|
TRACE("(%u, %p)\n", nItem, lpStyleBuf);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImeEnumRegisterWord (MSCTFIME.@)
|
|
|
|
*
|
|
|
|
* MSCTFIME's ImeEnumRegisterWord does nothing.
|
|
|
|
*
|
|
|
|
* @implemented
|
|
|
|
* @see ImeRegisterWord
|
|
|
|
*/
|
|
|
|
EXTERN_C UINT WINAPI
|
|
|
|
ImeEnumRegisterWord(
|
|
|
|
_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;
|
|
|
|
}
|
|
|
|
|
|
|
|
EXTERN_C BOOL WINAPI
|
|
|
|
ImeConfigure(
|
|
|
|
_In_ HKL hKL,
|
|
|
|
_In_ HWND hWnd,
|
|
|
|
_In_ DWORD dwMode,
|
|
|
|
_Inout_opt_ LPVOID lpData)
|
|
|
|
{
|
2023-12-19 10:23:52 +00:00
|
|
|
TRACE("(%p, %p, %lu, %p)\n", hKL, hWnd, dwMode, lpData);
|
|
|
|
|
|
|
|
TLS *pTLS = TLS::GetTLS();
|
|
|
|
if (!pTLS || !pTLS->m_pBridge || !pTLS->m_pThreadMgr)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
CicBridge *pBridge = pTLS->m_pBridge;
|
|
|
|
ITfThreadMgr *pThreadMgr = pTLS->m_pThreadMgr;
|
|
|
|
|
|
|
|
if (dwMode & 1)
|
|
|
|
return (pBridge->ConfigureGeneral(pTLS, pThreadMgr, hKL, hWnd) == S_OK);
|
|
|
|
|
|
|
|
if (dwMode & 2)
|
|
|
|
return (pBridge->ConfigureRegisterWord(pTLS, pThreadMgr, hKL, hWnd, lpData) == S_OK);
|
|
|
|
|
2023-12-18 10:11:17 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2023-12-18 12:56:21 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* ImeDestroy (MSCTFIME.@)
|
|
|
|
*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2023-12-18 10:11:17 +00:00
|
|
|
EXTERN_C BOOL WINAPI
|
|
|
|
ImeDestroy(
|
|
|
|
_In_ UINT uReserved)
|
|
|
|
{
|
2023-12-18 12:56:21 +00:00
|
|
|
TRACE("(%u)\n", uReserved);
|
|
|
|
|
2023-12-19 09:34:08 +00:00
|
|
|
TLS *pTLS = TLS::PeekTLS();
|
2023-12-18 12:56:21 +00:00
|
|
|
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);
|
2023-12-18 10:11:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImeEscape (MSCTFIME.@)
|
|
|
|
*
|
|
|
|
* MSCTFIME's ImeEscape does nothing.
|
|
|
|
*
|
|
|
|
* @implemented
|
|
|
|
* @see CtfImeEscapeEx
|
|
|
|
*/
|
|
|
|
EXTERN_C LRESULT WINAPI
|
|
|
|
ImeEscape(
|
|
|
|
_In_ HIMC hIMC,
|
|
|
|
_In_ UINT uEscape,
|
|
|
|
_Inout_opt_ LPVOID lpData)
|
|
|
|
{
|
|
|
|
TRACE("(%p, %u, %p)\n", hIMC, uEscape, lpData);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
EXTERN_C BOOL WINAPI
|
|
|
|
ImeProcessKey(
|
|
|
|
_In_ HIMC hIMC,
|
|
|
|
_In_ UINT uVirKey,
|
|
|
|
_In_ LPARAM lParam,
|
|
|
|
_In_ CONST LPBYTE lpbKeyState)
|
|
|
|
{
|
|
|
|
FIXME("stub:(%p, %u, %p, lpbKeyState)\n", hIMC, uVirKey, lParam, lpbKeyState);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImeSelect (MSCTFIME.@)
|
|
|
|
*
|
|
|
|
* MSCTFIME's ImeSelect does nothing.
|
|
|
|
*
|
|
|
|
* @implemented
|
|
|
|
* @see CtfImeSelectEx
|
|
|
|
*/
|
|
|
|
EXTERN_C BOOL WINAPI
|
|
|
|
ImeSelect(
|
|
|
|
_In_ HIMC hIMC,
|
|
|
|
_In_ BOOL fSelect)
|
|
|
|
{
|
|
|
|
TRACE("(%p, %u)\n", hIMC, fSelect);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImeSetActiveContext (MSCTFIME.@)
|
|
|
|
*
|
|
|
|
* MSCTFIME's ImeSetActiveContext does nothing.
|
|
|
|
*
|
|
|
|
* @implemented
|
|
|
|
* @see CtfImeSetActiveContextAlways
|
|
|
|
*/
|
|
|
|
EXTERN_C BOOL WINAPI
|
|
|
|
ImeSetActiveContext(
|
|
|
|
_In_ HIMC hIMC,
|
|
|
|
_In_ BOOL fFlag)
|
|
|
|
{
|
|
|
|
TRACE("(%p, %u)\n", hIMC, fFlag);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
EXTERN_C UINT WINAPI
|
|
|
|
ImeToAsciiEx(
|
|
|
|
_In_ UINT uVirKey,
|
|
|
|
_In_ UINT uScanCode,
|
|
|
|
_In_ CONST LPBYTE lpbKeyState,
|
|
|
|
_Out_ LPTRANSMSGLIST lpTransMsgList,
|
|
|
|
_In_ UINT fuState,
|
|
|
|
_In_ HIMC hIMC)
|
|
|
|
{
|
|
|
|
FIXME("stub:(%u, %u, %p, %p, %u, %p)\n", uVirKey, uScanCode, lpbKeyState, lpTransMsgList,
|
|
|
|
fuState, hIMC);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
EXTERN_C BOOL WINAPI
|
|
|
|
NotifyIME(
|
|
|
|
_In_ HIMC hIMC,
|
|
|
|
_In_ DWORD dwAction,
|
|
|
|
_In_ DWORD dwIndex,
|
|
|
|
_In_ DWORD_PTR dwValue)
|
|
|
|
{
|
|
|
|
FIXME("stub:(%p, 0x%lX, 0x%lX, %p)\n", hIMC, dwAction, dwIndex, dwValue);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
EXTERN_C BOOL WINAPI
|
|
|
|
ImeSetCompositionString(
|
|
|
|
_In_ HIMC hIMC,
|
|
|
|
_In_ DWORD dwIndex,
|
|
|
|
_In_opt_ LPCVOID lpComp,
|
|
|
|
_In_ DWORD dwCompLen,
|
|
|
|
_In_opt_ LPCVOID lpRead,
|
|
|
|
_In_ DWORD dwReadLen)
|
|
|
|
{
|
|
|
|
FIXME("stub:(%p, 0x%lX, %p, 0x%lX, %p, 0x%lX)\n", hIMC, dwIndex, lpComp, dwCompLen,
|
|
|
|
lpRead, dwReadLen);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
EXTERN_C DWORD WINAPI
|
|
|
|
ImeGetImeMenuItems(
|
|
|
|
_In_ HIMC hIMC,
|
|
|
|
_In_ DWORD dwFlags,
|
|
|
|
_In_ DWORD dwType,
|
|
|
|
_Inout_opt_ LPIMEMENUITEMINFOW lpImeParentMenu,
|
|
|
|
_Inout_opt_ LPIMEMENUITEMINFOW lpImeMenu,
|
|
|
|
_In_ DWORD dwSize)
|
|
|
|
{
|
|
|
|
FIXME("stub:(%p, 0x%lX, 0x%lX, %p, %p, 0x%lX)\n", hIMC, dwFlags, dwType, lpImeParentMenu,
|
|
|
|
lpImeMenu, dwSize);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* CtfImeInquireExW (MSCTFIME.@)
|
|
|
|
*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
EXTERN_C HRESULT WINAPI
|
|
|
|
CtfImeInquireExW(
|
|
|
|
_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);
|
|
|
|
}
|
|
|
|
|
2023-12-27 11:29:02 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* CtfImeSelectEx (MSCTFIME.@)
|
|
|
|
*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2023-12-18 10:11:17 +00:00
|
|
|
EXTERN_C BOOL WINAPI
|
|
|
|
CtfImeSelectEx(
|
|
|
|
_In_ HIMC hIMC,
|
|
|
|
_In_ BOOL fSelect,
|
|
|
|
_In_ HKL hKL)
|
|
|
|
{
|
2023-12-27 11:29:02 +00:00
|
|
|
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);
|
2023-12-18 10:11:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
EXTERN_C LRESULT WINAPI
|
|
|
|
CtfImeEscapeEx(
|
|
|
|
_In_ HIMC hIMC,
|
|
|
|
_In_ UINT uSubFunc,
|
|
|
|
_Inout_opt_ LPVOID lpData,
|
|
|
|
_In_ HKL hKL)
|
|
|
|
{
|
|
|
|
FIXME("stub:(%p, %u, %p, %p)\n", hIMC, uSubFunc, lpData, hKL);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2023-12-19 06:46:13 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* CtfImeGetGuidAtom (MSCTFIME.@)
|
|
|
|
*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2023-12-18 10:11:17 +00:00
|
|
|
EXTERN_C HRESULT WINAPI
|
|
|
|
CtfImeGetGuidAtom(
|
|
|
|
_In_ HIMC hIMC,
|
|
|
|
_In_ DWORD dwUnknown,
|
|
|
|
_Out_opt_ LPDWORD pdwGuidAtom)
|
|
|
|
{
|
2023-12-19 06:46:13 +00:00
|
|
|
TRACE("(%p, 0x%lX, %p)\n", hIMC, dwUnknown, pdwGuidAtom);
|
|
|
|
|
2023-12-22 05:52:49 +00:00
|
|
|
CicIMCLock imcLock(hIMC);
|
2024-02-22 06:46:05 +00:00
|
|
|
if (FAILED(imcLock.m_hr))
|
|
|
|
return imcLock.m_hr;
|
2023-12-19 06:46:13 +00:00
|
|
|
|
2023-12-22 05:52:49 +00:00
|
|
|
CicIMCCLock<CTFIMECONTEXT> imccLock(imcLock.get().hCtfImeContext);
|
2024-02-22 06:46:05 +00:00
|
|
|
if (FAILED(imccLock.m_hr))
|
|
|
|
return imccLock.m_hr;
|
2023-12-19 06:46:13 +00:00
|
|
|
|
2023-12-19 07:12:12 +00:00
|
|
|
if (!imccLock.get().m_pCicIC)
|
2023-12-19 06:46:13 +00:00
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
|
2024-02-22 06:46:05 +00:00
|
|
|
return imccLock.get().m_pCicIC->GetGuidAtom(imcLock, dwUnknown, pdwGuidAtom);
|
2023-12-18 10:11:17 +00:00
|
|
|
}
|
|
|
|
|
2023-12-19 06:23:12 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* CtfImeIsGuidMapEnable (MSCTFIME.@)
|
|
|
|
*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2023-12-18 10:11:17 +00:00
|
|
|
EXTERN_C BOOL WINAPI
|
|
|
|
CtfImeIsGuidMapEnable(
|
|
|
|
_In_ HIMC hIMC)
|
|
|
|
{
|
2023-12-19 06:23:12 +00:00
|
|
|
TRACE("(%p)\n", hIMC);
|
|
|
|
|
|
|
|
BOOL ret = FALSE;
|
2023-12-22 05:52:49 +00:00
|
|
|
CicIMCLock imcLock(hIMC);
|
2024-02-22 06:46:05 +00:00
|
|
|
if (SUCCEEDED(imcLock.m_hr))
|
2023-12-19 07:12:12 +00:00
|
|
|
ret = !!(imcLock.get().fdwInit & INIT_GUIDMAP);
|
2023-12-19 06:23:12 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
2023-12-18 12:56:21 +00:00
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* CtfImeCreateThreadMgr (MSCTFIME.@)
|
|
|
|
*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2023-12-18 10:11:17 +00:00
|
|
|
EXTERN_C HRESULT WINAPI
|
|
|
|
CtfImeCreateThreadMgr(VOID)
|
|
|
|
{
|
2023-12-18 12:56:21 +00:00
|
|
|
TRACE("()\n");
|
|
|
|
|
|
|
|
TLS *pTLS = TLS::GetTLS();
|
|
|
|
if (!pTLS)
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
|
|
|
|
if (!pTLS->m_pBridge)
|
|
|
|
{
|
2024-01-03 07:45:23 +00:00
|
|
|
pTLS->m_pBridge = new(cicNoThrow) CicBridge();
|
2023-12-18 12:56:21 +00:00
|
|
|
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;
|
2023-12-18 10:11:17 +00:00
|
|
|
}
|
|
|
|
|
2023-12-18 12:56:21 +00:00
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* CtfImeDestroyThreadMgr (MSCTFIME.@)
|
|
|
|
*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2023-12-18 10:11:17 +00:00
|
|
|
EXTERN_C HRESULT WINAPI
|
|
|
|
CtfImeDestroyThreadMgr(VOID)
|
|
|
|
{
|
2023-12-18 12:56:21 +00:00
|
|
|
TRACE("()\n");
|
|
|
|
|
2023-12-19 09:34:08 +00:00
|
|
|
TLS *pTLS = TLS::PeekTLS();
|
2023-12-18 12:56:21 +00:00
|
|
|
if (!pTLS)
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
|
|
|
|
if (pTLS->m_pBridge)
|
|
|
|
{
|
2024-01-03 07:45:23 +00:00
|
|
|
pTLS->m_pBridge = new(cicNoThrow) CicBridge();
|
2023-12-18 12:56:21 +00:00
|
|
|
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;
|
2023-12-18 10:11:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
EXTERN_C HRESULT WINAPI
|
|
|
|
CtfImeCreateInputContext(
|
|
|
|
_In_ HIMC hIMC)
|
|
|
|
{
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
2023-12-19 07:40:03 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* CtfImeDestroyInputContext (MSCTFIME.@)
|
|
|
|
*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2023-12-18 10:11:17 +00:00
|
|
|
EXTERN_C HRESULT WINAPI
|
|
|
|
CtfImeDestroyInputContext(
|
|
|
|
_In_ HIMC hIMC)
|
|
|
|
{
|
2023-12-19 07:40:03 +00:00
|
|
|
TRACE("(%p)\n", hIMC);
|
|
|
|
|
2023-12-19 09:34:08 +00:00
|
|
|
TLS *pTLS = TLS::PeekTLS();
|
2023-12-19 07:40:03 +00:00
|
|
|
if (!pTLS || !pTLS->m_pBridge)
|
|
|
|
return E_OUTOFMEMORY;
|
|
|
|
|
|
|
|
return pTLS->m_pBridge->DestroyInputContext(pTLS, hIMC);
|
2023-12-18 10:11:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
EXTERN_C HRESULT WINAPI
|
|
|
|
CtfImeSetActiveContextAlways(
|
|
|
|
_In_ HIMC hIMC,
|
|
|
|
_In_ BOOL fActive,
|
|
|
|
_In_ HWND hWnd,
|
|
|
|
_In_ HKL hKL)
|
|
|
|
{
|
|
|
|
FIXME("stub:(%p, %d, %p, %p)\n", hIMC, fActive, hWnd, hKL);
|
|
|
|
return E_NOTIMPL;
|
|
|
|
}
|
|
|
|
|
2023-12-27 06:08:17 +00:00
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* CtfImeProcessCicHotkey (MSCTFIME.@)
|
|
|
|
*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2023-12-18 10:11:17 +00:00
|
|
|
EXTERN_C HRESULT WINAPI
|
|
|
|
CtfImeProcessCicHotkey(
|
|
|
|
_In_ HIMC hIMC,
|
|
|
|
_In_ UINT vKey,
|
|
|
|
_In_ LPARAM lParam)
|
|
|
|
{
|
2023-12-27 06:08:17 +00:00
|
|
|
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;
|
2023-12-18 10:11:17 +00:00
|
|
|
}
|
|
|
|
|
2023-12-19 05:24:48 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* CtfImeDispatchDefImeMessage (MSCTFIME.@)
|
|
|
|
*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2023-12-18 10:11:17 +00:00
|
|
|
EXTERN_C LRESULT WINAPI
|
|
|
|
CtfImeDispatchDefImeMessage(
|
|
|
|
_In_ HWND hWnd,
|
|
|
|
_In_ UINT uMsg,
|
|
|
|
_In_ WPARAM wParam,
|
|
|
|
_In_ LPARAM lParam)
|
|
|
|
{
|
2023-12-19 05:24:48 +00:00
|
|
|
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);
|
2023-12-18 10:11:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
EXTERN_C BOOL WINAPI
|
|
|
|
CtfImeIsIME(
|
|
|
|
_In_ HKL hKL)
|
|
|
|
{
|
|
|
|
FIXME("stub:(%p)\n", hKL);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2024-01-01 02:05:49 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* CtfImeThreadDetach (MSCTFIME.@)
|
|
|
|
*
|
2023-12-18 10:11:17 +00:00
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
EXTERN_C HRESULT WINAPI
|
|
|
|
CtfImeThreadDetach(VOID)
|
|
|
|
{
|
|
|
|
ImeDestroy(0);
|
|
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|
2024-01-05 09:36:30 +00:00
|
|
|
/// @implemented
|
2023-12-18 10:11:17 +00:00
|
|
|
BOOL AttachIME(VOID)
|
|
|
|
{
|
|
|
|
return RegisterImeClass() && RegisterMSIMEMessage();
|
|
|
|
}
|
|
|
|
|
2024-01-05 09:36:30 +00:00
|
|
|
/// @implemented
|
2023-12-18 10:11:17 +00:00
|
|
|
VOID DetachIME(VOID)
|
|
|
|
{
|
|
|
|
UnregisterImeClass();
|
|
|
|
}
|
|
|
|
|
2024-02-20 05:36:24 +00:00
|
|
|
EXTERN_C VOID TFUninitLib(VOID)
|
|
|
|
{
|
|
|
|
if (g_pPropCache)
|
|
|
|
{
|
|
|
|
delete g_pPropCache;
|
|
|
|
g_pPropCache = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-05 09:36:30 +00:00
|
|
|
/// @implemented
|
2023-12-18 10:11:17 +00:00
|
|
|
BOOL ProcessAttach(HINSTANCE hinstDLL)
|
|
|
|
{
|
|
|
|
g_hInst = hinstDLL;
|
|
|
|
|
|
|
|
InitializeCriticalSectionAndSpinCount(&g_csLock, 0);
|
|
|
|
|
|
|
|
if (!TLS::Initialize())
|
|
|
|
return FALSE;
|
|
|
|
|
2023-12-22 02:52:06 +00:00
|
|
|
cicGetOSInfo(&g_uACP, &g_dwOSInfo);
|
2023-12-18 10:11:17 +00:00
|
|
|
|
2024-01-06 10:21:37 +00:00
|
|
|
cicInitUIFLib();
|
2023-12-23 00:34:41 +00:00
|
|
|
|
|
|
|
if (!TFInitLib())
|
|
|
|
return FALSE;
|
2023-12-18 10:11:17 +00:00
|
|
|
|
|
|
|
gfTFInitLib = TRUE;
|
|
|
|
return AttachIME();
|
|
|
|
}
|
|
|
|
|
2024-02-20 05:36:24 +00:00
|
|
|
/// @implemented
|
2023-12-18 10:11:17 +00:00
|
|
|
VOID ProcessDetach(HINSTANCE hinstDLL)
|
|
|
|
{
|
2023-12-23 00:34:41 +00:00
|
|
|
TF_DllDetachInOther();
|
|
|
|
|
2023-12-18 10:11:17 +00:00
|
|
|
if (gfTFInitLib)
|
2023-12-23 00:34:41 +00:00
|
|
|
{
|
2023-12-18 10:11:17 +00:00
|
|
|
DetachIME();
|
2023-12-23 00:34:41 +00:00
|
|
|
TFUninitLib();
|
|
|
|
}
|
2023-12-18 10:11:17 +00:00
|
|
|
|
|
|
|
DeleteCriticalSection(&g_csLock);
|
|
|
|
TLS::InternalDestroyTLS();
|
|
|
|
TLS::Uninitialize();
|
2024-01-06 10:21:37 +00:00
|
|
|
cicDoneUIFLib();
|
2023-12-18 10:11:17 +00:00
|
|
|
}
|
|
|
|
|
2024-01-05 09:36:30 +00:00
|
|
|
/// @implemented
|
2023-12-18 10:11:17 +00:00
|
|
|
EXTERN_C BOOL WINAPI
|
|
|
|
DllMain(
|
|
|
|
_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:
|
|
|
|
{
|
2023-12-20 08:51:37 +00:00
|
|
|
TF_DllDetachInOther();
|
2023-12-18 10:11:17 +00:00
|
|
|
CtfImeThreadDetach();
|
|
|
|
TLS::InternalDestroyTLS();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|