2005-12-12 20:59:55 +00:00
|
|
|
/*
|
2021-08-17 23:42:12 +00:00
|
|
|
* PROJECT: ReactOS IMM32
|
|
|
|
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
|
|
|
|
* PURPOSE: Implementing Far-Eastern languages input
|
|
|
|
* COPYRIGHT: Copyright 1998 Patrik Stridvall
|
|
|
|
* Copyright 2002, 2003, 2007 CodeWeavers, Aric Stewart
|
|
|
|
* Copyright 2017 James Tabor <james.tabor@reactos.org>
|
|
|
|
* Copyright 2018 Amine Khaldi <amine.khaldi@reactos.org>
|
|
|
|
* Copyright 2020 Oleg Dubinskiy <oleg.dubinskij2013@yandex.ua>
|
|
|
|
* Copyright 2020-2021 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
|
2005-12-12 20:59:55 +00:00
|
|
|
*/
|
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
#include "precomp.h"
|
2005-12-12 20:59:55 +00:00
|
|
|
|
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(imm);
|
|
|
|
|
2021-08-04 00:41:59 +00:00
|
|
|
HMODULE g_hImm32Inst = NULL;
|
2021-07-28 14:25:10 +00:00
|
|
|
PSERVERINFO g_psi = NULL;
|
2021-08-04 00:41:59 +00:00
|
|
|
SHAREDINFO g_SharedInfo = { NULL };
|
|
|
|
BYTE g_bClientRegd = FALSE;
|
2021-08-23 21:50:39 +00:00
|
|
|
|
2021-08-04 00:41:59 +00:00
|
|
|
static BOOL APIENTRY Imm32InitInstance(HMODULE hMod)
|
|
|
|
{
|
|
|
|
NTSTATUS status;
|
|
|
|
|
|
|
|
if (hMod)
|
|
|
|
g_hImm32Inst = hMod;
|
|
|
|
|
|
|
|
if (g_bClientRegd)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
status = RtlInitializeCriticalSection(&g_csImeDpi);
|
|
|
|
if (NT_ERROR(status))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
g_bClientRegd = TRUE;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2021-08-14 01:38:06 +00:00
|
|
|
/***********************************************************************
|
2021-09-10 14:39:15 +00:00
|
|
|
* ImmRegisterClient(IMM32.@)
|
|
|
|
* ( Undocumented, called from user32.dll )
|
2021-08-14 01:38:06 +00:00
|
|
|
*/
|
2021-09-10 14:39:15 +00:00
|
|
|
BOOL WINAPI ImmRegisterClient(PSHAREDINFO ptr, HINSTANCE hMod)
|
2021-08-09 23:08:23 +00:00
|
|
|
{
|
2021-09-10 14:39:15 +00:00
|
|
|
g_SharedInfo = *ptr;
|
|
|
|
g_psi = g_SharedInfo.psi;
|
|
|
|
return Imm32InitInstance(hMod);
|
2021-08-09 23:08:23 +00:00
|
|
|
}
|
|
|
|
|
2021-08-14 01:38:06 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* ImmLoadLayout (IMM32.@)
|
|
|
|
*/
|
2021-07-28 14:25:10 +00:00
|
|
|
HKL WINAPI ImmLoadLayout(HKL hKL, PIMEINFOEX pImeInfoEx)
|
|
|
|
{
|
|
|
|
DWORD cbData;
|
|
|
|
UNICODE_STRING UnicodeString;
|
|
|
|
HKEY hLayoutKey = NULL, hLayoutsKey = NULL;
|
|
|
|
LONG error;
|
|
|
|
NTSTATUS Status;
|
|
|
|
WCHAR szLayout[MAX_PATH];
|
|
|
|
|
2021-08-04 00:49:41 +00:00
|
|
|
TRACE("(%p, %p)\n", hKL, pImeInfoEx);
|
2021-07-28 14:25:10 +00:00
|
|
|
|
2021-09-24 13:06:29 +00:00
|
|
|
if (IS_IME_HKL(hKL) || !Imm32IsCiceroMode() || Imm32Is16BitMode())
|
2021-07-28 14:25:10 +00:00
|
|
|
{
|
|
|
|
UnicodeString.Buffer = szLayout;
|
|
|
|
UnicodeString.MaximumLength = sizeof(szLayout);
|
|
|
|
Status = RtlIntegerToUnicodeString((DWORD_PTR)hKL, 16, &UnicodeString);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
error = RegOpenKeyW(HKEY_LOCAL_MACHINE, REGKEY_KEYBOARD_LAYOUTS, &hLayoutsKey);
|
|
|
|
if (error)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
error = RegOpenKeyW(hLayoutsKey, szLayout, &hLayoutKey);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
error = RegOpenKeyW(HKEY_LOCAL_MACHINE, REGKEY_IMM, &hLayoutKey);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (error)
|
|
|
|
{
|
|
|
|
ERR("RegOpenKeyW error: 0x%08lX\n", error);
|
|
|
|
hKL = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
cbData = sizeof(pImeInfoEx->wszImeFile);
|
|
|
|
error = RegQueryValueExW(hLayoutKey, L"Ime File", 0, 0,
|
|
|
|
(LPBYTE)pImeInfoEx->wszImeFile, &cbData);
|
|
|
|
if (error)
|
|
|
|
hKL = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
RegCloseKey(hLayoutKey);
|
|
|
|
if (hLayoutsKey)
|
|
|
|
RegCloseKey(hLayoutsKey);
|
|
|
|
return hKL;
|
|
|
|
}
|
|
|
|
|
2021-09-30 18:10:26 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* ImmFreeLayout (IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmFreeLayout(DWORD dwUnknown)
|
|
|
|
{
|
|
|
|
WCHAR szKBD[9];
|
|
|
|
UINT iKL, cKLs;
|
|
|
|
HKL hOldKL, hNewKL, *pList;
|
|
|
|
PIMEDPI pImeDpi;
|
|
|
|
LANGID LangID;
|
|
|
|
|
|
|
|
TRACE("(0x%lX)\n", dwUnknown);
|
|
|
|
|
|
|
|
hOldKL = GetKeyboardLayout(0);
|
|
|
|
|
|
|
|
if (dwUnknown == 1)
|
|
|
|
{
|
|
|
|
if (!IS_IME_HKL(hOldKL))
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
LangID = LANGIDFROMLCID(GetSystemDefaultLCID());
|
|
|
|
|
|
|
|
cKLs = GetKeyboardLayoutList(0, NULL);
|
|
|
|
if (cKLs)
|
|
|
|
{
|
|
|
|
pList = Imm32HeapAlloc(0, cKLs * sizeof(HKL));
|
|
|
|
if (pList == NULL)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
cKLs = GetKeyboardLayoutList(cKLs, pList);
|
|
|
|
for (iKL = 0; iKL < cKLs; ++iKL)
|
|
|
|
{
|
|
|
|
if (!IS_IME_HKL(pList[iKL]))
|
|
|
|
{
|
|
|
|
LangID = LOWORD(pList[iKL]);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Imm32HeapFree(pList);
|
|
|
|
}
|
|
|
|
|
|
|
|
StringCchPrintfW(szKBD, _countof(szKBD), L"%08X", LangID);
|
|
|
|
if (!LoadKeyboardLayoutW(szKBD, KLF_ACTIVATE))
|
|
|
|
LoadKeyboardLayoutW(L"00000409", KLF_ACTIVATE | 0x200);
|
|
|
|
}
|
|
|
|
else if (dwUnknown == 2)
|
|
|
|
{
|
|
|
|
RtlEnterCriticalSection(&g_csImeDpi);
|
|
|
|
Retry:
|
|
|
|
for (pImeDpi = g_pImeDpiList; pImeDpi; pImeDpi = pImeDpi->pNext)
|
|
|
|
{
|
|
|
|
if (Imm32ReleaseIME(pImeDpi->hKL))
|
|
|
|
goto Retry;
|
|
|
|
}
|
|
|
|
RtlLeaveCriticalSection(&g_csImeDpi);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
hNewKL = (HKL)(DWORD_PTR)dwUnknown;
|
|
|
|
if (IS_IME_HKL(hNewKL) && hNewKL != hOldKL)
|
|
|
|
Imm32ReleaseIME(hNewKL);
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
typedef struct _tagImmHkl
|
|
|
|
{
|
2008-04-04 13:20:27 +00:00
|
|
|
struct list entry;
|
|
|
|
HKL hkl;
|
|
|
|
HMODULE hIME;
|
|
|
|
IMEINFO imeInfo;
|
|
|
|
WCHAR imeClassName[17]; /* 16 character max */
|
|
|
|
ULONG uSelected;
|
2013-02-03 20:58:12 +00:00
|
|
|
HWND UIWnd;
|
2008-04-04 13:20:27 +00:00
|
|
|
|
|
|
|
/* Function Pointers */
|
2018-10-01 11:53:21 +00:00
|
|
|
BOOL (WINAPI *pImeInquire)(IMEINFO *, WCHAR *, const WCHAR *);
|
|
|
|
BOOL (WINAPI *pImeConfigure)(HKL, HWND, DWORD, void *);
|
|
|
|
BOOL (WINAPI *pImeDestroy)(UINT);
|
|
|
|
LRESULT (WINAPI *pImeEscape)(HIMC, UINT, void *);
|
|
|
|
BOOL (WINAPI *pImeSelect)(HIMC, BOOL);
|
|
|
|
BOOL (WINAPI *pImeSetActiveContext)(HIMC, BOOL);
|
|
|
|
UINT (WINAPI *pImeToAsciiEx)(UINT, UINT, const BYTE *, DWORD *, UINT, HIMC);
|
|
|
|
BOOL (WINAPI *pNotifyIME)(HIMC, DWORD, DWORD, DWORD);
|
|
|
|
BOOL (WINAPI *pImeRegisterWord)(const WCHAR *, DWORD, const WCHAR *);
|
|
|
|
BOOL (WINAPI *pImeUnregisterWord)(const WCHAR *, DWORD, const WCHAR *);
|
|
|
|
UINT (WINAPI *pImeEnumRegisterWord)(REGISTERWORDENUMPROCW, const WCHAR *, DWORD, const WCHAR *, void *);
|
|
|
|
BOOL (WINAPI *pImeSetCompositionString)(HIMC, DWORD, const void *, DWORD, const void *, DWORD);
|
|
|
|
DWORD (WINAPI *pImeConversionList)(HIMC, const WCHAR *, CANDIDATELIST *, DWORD, UINT);
|
|
|
|
BOOL (WINAPI *pImeProcessKey)(HIMC, UINT, LPARAM, const BYTE *);
|
|
|
|
UINT (WINAPI *pImeGetRegisterWordStyle)(UINT, STYLEBUFW *);
|
|
|
|
DWORD (WINAPI *pImeGetImeMenuItems)(HIMC, DWORD, DWORD, IMEMENUITEMINFOW *, IMEMENUITEMINFOW *, DWORD);
|
2008-04-04 13:20:27 +00:00
|
|
|
} ImmHkl;
|
|
|
|
|
2005-12-12 20:59:55 +00:00
|
|
|
typedef struct tagInputContextData
|
|
|
|
{
|
2021-09-10 14:39:15 +00:00
|
|
|
DWORD dwLock;
|
|
|
|
INPUTCONTEXT IMC;
|
|
|
|
DWORD threadID;
|
|
|
|
|
|
|
|
ImmHkl *immKbd;
|
|
|
|
UINT lastVK;
|
|
|
|
BOOL threadDefault;
|
|
|
|
DWORD magic;
|
2005-12-12 20:59:55 +00:00
|
|
|
} InputContextData;
|
|
|
|
|
2014-09-28 18:27:58 +00:00
|
|
|
#define WINE_IMC_VALID_MAGIC 0x56434D49
|
|
|
|
|
2008-04-04 13:20:27 +00:00
|
|
|
static const WCHAR szwWineIMCProperty[] = {'W','i','n','e','I','m','m','H','I','M','C','P','r','o','p','e','r','t','y',0};
|
2010-03-07 11:27:14 +00:00
|
|
|
static const WCHAR szImeFileW[] = {'I','m','e',' ','F','i','l','e',0};
|
|
|
|
static const WCHAR szLayoutTextW[] = {'L','a','y','o','u','t',' ','T','e','x','t',0};
|
|
|
|
static const WCHAR szImeRegFmt[] = {'S','y','s','t','e','m','\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\','C','o','n','t','r','o','l','\\','K','e','y','b','o','a','r','d',' ','L','a','y','o','u','t','s','\\','%','0','8','l','x',0};
|
|
|
|
|
2019-11-02 17:34:15 +00:00
|
|
|
static inline BOOL is_himc_ime_unicode(const InputContextData *data)
|
|
|
|
{
|
|
|
|
return !!(data->immKbd->imeInfo.fdwProperty & IME_PROP_UNICODE);
|
|
|
|
}
|
|
|
|
|
2014-09-28 18:27:58 +00:00
|
|
|
static InputContextData* get_imc_data(HIMC hIMC)
|
|
|
|
{
|
2021-08-16 06:33:51 +00:00
|
|
|
InputContextData *data = (InputContextData *)hIMC;
|
2014-09-28 18:27:58 +00:00
|
|
|
|
|
|
|
if (hIMC == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if(IsBadReadPtr(data, sizeof(InputContextData)) || data->magic != WINE_IMC_VALID_MAGIC)
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
2021-09-30 18:02:56 +00:00
|
|
|
static VOID APIENTRY Imm32CiceroSetActiveContext(HIMC hIMC, BOOL fActive, HWND hWnd, HKL hKL)
|
|
|
|
{
|
|
|
|
FIXME("We have to do something\n");
|
|
|
|
}
|
|
|
|
|
2005-12-12 20:59:55 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* ImmAssociateContext (IMM32.@)
|
|
|
|
*/
|
|
|
|
HIMC WINAPI ImmAssociateContext(HWND hWnd, HIMC hIMC)
|
|
|
|
{
|
2021-09-28 13:03:25 +00:00
|
|
|
PWND pWnd;
|
|
|
|
HWND hwndFocus;
|
|
|
|
DWORD dwValue;
|
|
|
|
HIMC hOldIMC;
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2021-09-28 13:03:25 +00:00
|
|
|
TRACE("(%p, %p)\n", hWnd, hIMC);
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2021-09-28 13:03:25 +00:00
|
|
|
if (!Imm32IsImmMode())
|
2014-09-28 18:27:58 +00:00
|
|
|
return NULL;
|
|
|
|
|
2021-09-28 13:03:25 +00:00
|
|
|
pWnd = ValidateHwndNoErr(hWnd);
|
|
|
|
if (!pWnd)
|
|
|
|
return NULL;
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2021-09-28 13:03:25 +00:00
|
|
|
if (hIMC && Imm32IsCrossThreadAccess(hIMC))
|
2017-12-08 03:14:21 +00:00
|
|
|
return NULL;
|
|
|
|
|
2021-09-28 13:03:25 +00:00
|
|
|
hOldIMC = pWnd->hImc;
|
|
|
|
if (hOldIMC == hIMC)
|
|
|
|
return hIMC;
|
2008-04-04 13:20:27 +00:00
|
|
|
|
2021-09-28 13:03:25 +00:00
|
|
|
dwValue = NtUserAssociateInputContext(hWnd, hIMC, 0);
|
|
|
|
if (dwValue == 0)
|
|
|
|
return hOldIMC;
|
|
|
|
if (dwValue != 1)
|
|
|
|
return NULL;
|
2008-04-04 13:20:27 +00:00
|
|
|
|
2021-09-28 13:03:25 +00:00
|
|
|
hwndFocus = (HWND)NtUserQueryWindow(hWnd, QUERY_WINDOW_FOCUS);
|
|
|
|
if (hwndFocus == hWnd)
|
2019-01-26 12:10:01 +00:00
|
|
|
{
|
2021-09-28 13:03:25 +00:00
|
|
|
ImmSetActiveContext(hWnd, hOldIMC, FALSE);
|
|
|
|
ImmSetActiveContext(hWnd, hIMC, TRUE);
|
2019-01-26 12:10:01 +00:00
|
|
|
}
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2021-09-28 13:03:25 +00:00
|
|
|
return hOldIMC;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmAssociateContextEx (IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmAssociateContextEx(HWND hWnd, HIMC hIMC, DWORD dwFlags)
|
|
|
|
{
|
2021-09-16 10:29:49 +00:00
|
|
|
HWND hwndFocus;
|
|
|
|
PWND pFocusWnd;
|
|
|
|
HIMC hOldIMC = NULL;
|
|
|
|
DWORD dwValue;
|
|
|
|
|
|
|
|
TRACE("(%p, %p, 0x%lX)\n", hWnd, hIMC, dwFlags);
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2021-09-24 13:06:29 +00:00
|
|
|
if (!Imm32IsImmMode())
|
2017-12-08 03:14:21 +00:00
|
|
|
return FALSE;
|
Sync avifil, credui, crypt32, cryptdlg, cryptui, dnsapi, gdiplus, hhctrl, hnetcfg, iccvid, imaadp32, imm32, jscript, localspl, localui, mapi32, mciavi32, mcicda, mciqtz32, mciseq, mciwave, mshtml, msrle32, msvfw32, msvidc32, msxml3, oleacc, oleaut32 to Wine 1.2rc5 (Samuel Serapion, small changes by me)
Remove Esperanto and Walon languages from comctl32, comdlg32, mpr, msi, shlwapi, wininet
svn path=/trunk/; revision=47920
2010-07-01 11:09:47 +00:00
|
|
|
|
2021-09-16 10:29:49 +00:00
|
|
|
if (hIMC && !(dwFlags & IACE_DEFAULT) && Imm32IsCrossThreadAccess(hIMC))
|
2010-03-07 11:27:14 +00:00
|
|
|
return FALSE;
|
2021-09-16 10:29:49 +00:00
|
|
|
|
|
|
|
hwndFocus = (HWND)NtUserQueryWindow(hWnd, QUERY_WINDOW_FOCUS);
|
|
|
|
pFocusWnd = ValidateHwndNoErr(hwndFocus);
|
|
|
|
if (pFocusWnd)
|
|
|
|
hOldIMC = pFocusWnd->hImc;
|
|
|
|
|
|
|
|
dwValue = NtUserAssociateInputContext(hWnd, hIMC, dwFlags);
|
|
|
|
switch (dwValue)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
pFocusWnd = ValidateHwndNoErr(hwndFocus);
|
|
|
|
if (pFocusWnd)
|
|
|
|
{
|
|
|
|
hIMC = pFocusWnd->hImc;
|
|
|
|
if (hIMC != hOldIMC)
|
|
|
|
{
|
|
|
|
ImmSetActiveContext(hwndFocus, hOldIMC, FALSE);
|
|
|
|
ImmSetActiveContext(hwndFocus, hIMC, TRUE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return FALSE;
|
2010-03-07 11:27:14 +00:00
|
|
|
}
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmCreateContext (IMM32.@)
|
|
|
|
*/
|
|
|
|
HIMC WINAPI ImmCreateContext(void)
|
|
|
|
{
|
2021-08-04 00:41:59 +00:00
|
|
|
PCLIENTIMC pClientImc;
|
|
|
|
HIMC hIMC;
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2021-08-04 00:49:41 +00:00
|
|
|
TRACE("()\n");
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2021-09-24 13:06:29 +00:00
|
|
|
if (!Imm32IsImmMode())
|
2021-08-04 00:41:59 +00:00
|
|
|
return NULL;
|
2008-04-04 13:20:27 +00:00
|
|
|
|
2021-08-04 00:41:59 +00:00
|
|
|
pClientImc = Imm32HeapAlloc(HEAP_ZERO_MEMORY, sizeof(CLIENTIMC));
|
|
|
|
if (pClientImc == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
2021-08-16 06:45:11 +00:00
|
|
|
hIMC = NtUserCreateInputContext(pClientImc);
|
2021-08-04 00:41:59 +00:00
|
|
|
if (hIMC == NULL)
|
2010-03-07 11:27:14 +00:00
|
|
|
{
|
2021-09-18 16:52:05 +00:00
|
|
|
Imm32HeapFree(pClientImc);
|
2021-08-04 00:41:59 +00:00
|
|
|
return NULL;
|
2010-03-07 11:27:14 +00:00
|
|
|
}
|
2008-04-04 13:20:27 +00:00
|
|
|
|
2021-08-04 00:41:59 +00:00
|
|
|
RtlInitializeCriticalSection(&pClientImc->cs);
|
2021-08-17 23:42:12 +00:00
|
|
|
|
|
|
|
// FIXME: NtUserGetThreadState and enum ThreadStateRoutines are broken.
|
|
|
|
pClientImc->unknown = NtUserGetThreadState(13);
|
|
|
|
|
2021-08-04 00:41:59 +00:00
|
|
|
return hIMC;
|
|
|
|
}
|
2008-04-04 13:20:27 +00:00
|
|
|
|
2021-08-04 00:41:59 +00:00
|
|
|
static VOID APIENTRY Imm32CleanupContextExtra(LPINPUTCONTEXT pIC)
|
|
|
|
{
|
|
|
|
FIXME("We have to do something do here");
|
|
|
|
}
|
2014-09-28 18:27:58 +00:00
|
|
|
|
2021-08-04 00:41:59 +00:00
|
|
|
BOOL APIENTRY Imm32CleanupContext(HIMC hIMC, HKL hKL, BOOL bKeep)
|
|
|
|
{
|
|
|
|
PIMEDPI pImeDpi;
|
|
|
|
LPINPUTCONTEXT pIC;
|
|
|
|
PCLIENTIMC pClientImc;
|
2021-09-27 00:31:16 +00:00
|
|
|
PIMC pIMC;
|
2014-09-28 18:27:58 +00:00
|
|
|
|
2021-09-24 13:06:29 +00:00
|
|
|
if (!Imm32IsImmMode() || hIMC == NULL)
|
2021-08-04 00:41:59 +00:00
|
|
|
return FALSE;
|
|
|
|
|
2021-09-27 00:31:16 +00:00
|
|
|
pIMC = ValidateHandleNoErr(hIMC, TYPE_INPUTCONTEXT);
|
|
|
|
if (!pIMC || pIMC->head.pti != NtCurrentTeb()->Win32ThreadInfo)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
pClientImc = (PCLIENTIMC)pIMC->dwClientImcData;
|
2021-08-04 00:41:59 +00:00
|
|
|
if (!pClientImc)
|
|
|
|
return FALSE;
|
|
|
|
|
2021-09-27 00:32:24 +00:00
|
|
|
if (pClientImc->hInputContext == NULL)
|
2008-04-04 13:20:27 +00:00
|
|
|
{
|
2021-08-04 00:41:59 +00:00
|
|
|
pClientImc->dwFlags |= CLIENTIMC_UNKNOWN1;
|
|
|
|
ImmUnlockClientImc(pClientImc);
|
|
|
|
if (!bKeep)
|
2021-08-16 06:45:11 +00:00
|
|
|
return NtUserDestroyInputContext(hIMC);
|
2021-08-04 00:41:59 +00:00
|
|
|
return TRUE;
|
2008-04-04 13:20:27 +00:00
|
|
|
}
|
|
|
|
|
2021-08-04 00:41:59 +00:00
|
|
|
pIC = ImmLockIMC(hIMC);
|
|
|
|
if (pIC == NULL)
|
|
|
|
{
|
|
|
|
ImmUnlockClientImc(pClientImc);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2008-04-04 13:20:27 +00:00
|
|
|
|
2021-08-04 00:41:59 +00:00
|
|
|
FIXME("We have do something to do here\n");
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2021-08-04 00:41:59 +00:00
|
|
|
if (pClientImc->hKL == hKL)
|
|
|
|
{
|
|
|
|
pImeDpi = ImmLockImeDpi(hKL);
|
|
|
|
if (pImeDpi != NULL)
|
|
|
|
{
|
|
|
|
if (IS_IME_HKL(hKL))
|
|
|
|
{
|
|
|
|
pImeDpi->ImeSelect(hIMC, FALSE);
|
|
|
|
}
|
2021-09-24 13:06:29 +00:00
|
|
|
else if (Imm32IsCiceroMode() && pImeDpi->CtfImeSelectEx)
|
2021-08-04 00:41:59 +00:00
|
|
|
{
|
2021-09-24 13:06:29 +00:00
|
|
|
pImeDpi->CtfImeSelectEx(hIMC, FALSE, hKL);
|
2021-08-04 00:41:59 +00:00
|
|
|
}
|
|
|
|
ImmUnlockImeDpi(pImeDpi);
|
|
|
|
}
|
|
|
|
pClientImc->hKL = NULL;
|
|
|
|
}
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2021-09-27 00:32:24 +00:00
|
|
|
pIC->hPrivate = ImmDestroyIMCC(pIC->hPrivate);
|
|
|
|
pIC->hMsgBuf = ImmDestroyIMCC(pIC->hMsgBuf);
|
|
|
|
pIC->hGuideLine = ImmDestroyIMCC(pIC->hGuideLine);
|
|
|
|
pIC->hCandInfo = ImmDestroyIMCC(pIC->hCandInfo);
|
|
|
|
pIC->hCompStr = ImmDestroyIMCC(pIC->hCompStr);
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2021-08-04 00:41:59 +00:00
|
|
|
Imm32CleanupContextExtra(pIC);
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2021-08-04 00:41:59 +00:00
|
|
|
ImmUnlockIMC(hIMC);
|
2014-09-28 18:27:58 +00:00
|
|
|
|
2021-08-04 00:41:59 +00:00
|
|
|
pClientImc->dwFlags |= CLIENTIMC_UNKNOWN1;
|
|
|
|
ImmUnlockClientImc(pClientImc);
|
2014-09-28 18:27:58 +00:00
|
|
|
|
2021-08-04 00:41:59 +00:00
|
|
|
if (!bKeep)
|
2021-08-16 06:45:11 +00:00
|
|
|
return NtUserDestroyInputContext(hIMC);
|
2005-12-12 20:59:55 +00:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2021-09-27 00:32:24 +00:00
|
|
|
BOOL APIENTRY
|
|
|
|
Imm32InitContext(HIMC hIMC, LPINPUTCONTEXT pIC, PCLIENTIMC pClientImc, HKL hKL, BOOL fSelect)
|
|
|
|
{
|
|
|
|
DWORD dwIndex, cbPrivate;
|
|
|
|
PIMEDPI pImeDpi = NULL;
|
|
|
|
LPCOMPOSITIONSTRING pCS;
|
|
|
|
LPCANDIDATEINFO pCI;
|
|
|
|
LPGUIDELINE pGL;
|
|
|
|
/* NOTE: Windows does recursive call ImmLockIMC here but we don't do so. */
|
|
|
|
|
|
|
|
/* Create IC components */
|
|
|
|
pIC->hCompStr = ImmCreateIMCC(sizeof(COMPOSITIONSTRING));
|
|
|
|
pIC->hCandInfo = ImmCreateIMCC(sizeof(CANDIDATEINFO));
|
|
|
|
pIC->hGuideLine = ImmCreateIMCC(sizeof(GUIDELINE));
|
|
|
|
pIC->hMsgBuf = ImmCreateIMCC(sizeof(UINT));
|
|
|
|
if (!pIC->hCompStr || !pIC->hCandInfo || !pIC->hGuideLine || !pIC->hMsgBuf)
|
|
|
|
goto Fail;
|
|
|
|
|
|
|
|
/* Initialize IC components */
|
|
|
|
pCS = ImmLockIMCC(pIC->hCompStr);
|
|
|
|
if (!pCS)
|
|
|
|
goto Fail;
|
|
|
|
pCS->dwSize = sizeof(COMPOSITIONSTRING);
|
|
|
|
ImmUnlockIMCC(pIC->hCompStr);
|
|
|
|
|
|
|
|
pCI = ImmLockIMCC(pIC->hCandInfo);
|
|
|
|
if (!pCI)
|
|
|
|
goto Fail;
|
|
|
|
pCI->dwSize = sizeof(CANDIDATEINFO);
|
|
|
|
ImmUnlockIMCC(pIC->hCandInfo);
|
|
|
|
|
|
|
|
pGL = ImmLockIMCC(pIC->hGuideLine);
|
|
|
|
if (!pGL)
|
|
|
|
goto Fail;
|
|
|
|
pGL->dwSize = sizeof(GUIDELINE);
|
|
|
|
ImmUnlockIMCC(pIC->hGuideLine);
|
|
|
|
|
|
|
|
pIC->dwNumMsgBuf = 0;
|
|
|
|
pIC->fOpen = FALSE;
|
|
|
|
pIC->fdwConversion = pIC->fdwSentence = 0;
|
|
|
|
|
|
|
|
for (dwIndex = 0; dwIndex < MAX_CANDIDATEFORM; ++dwIndex)
|
|
|
|
pIC->cfCandForm[dwIndex].dwIndex = IMM_INVALID_CANDFORM;
|
|
|
|
|
|
|
|
/* Get private data size */
|
|
|
|
pImeDpi = ImmLockImeDpi(hKL);
|
|
|
|
if (!pImeDpi)
|
|
|
|
{
|
|
|
|
cbPrivate = sizeof(DWORD);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Update CLIENTIMC */
|
|
|
|
pClientImc->uCodePage = pImeDpi->uCodePage;
|
|
|
|
if (ImeDpi_IsUnicode(pImeDpi))
|
|
|
|
pClientImc->dwFlags |= CLIENTIMC_WIDE;
|
|
|
|
|
|
|
|
cbPrivate = pImeDpi->ImeInfo.dwPrivateDataSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Create private data */
|
|
|
|
pIC->hPrivate = ImmCreateIMCC(cbPrivate);
|
|
|
|
if (!pIC->hPrivate)
|
|
|
|
goto Fail;
|
|
|
|
|
|
|
|
if (pImeDpi)
|
|
|
|
{
|
|
|
|
/* Select the IME */
|
|
|
|
if (fSelect)
|
|
|
|
{
|
|
|
|
if (IS_IME_HKL(hKL))
|
|
|
|
pImeDpi->ImeSelect(hIMC, TRUE);
|
|
|
|
else if (Imm32IsCiceroMode() && !Imm32Is16BitMode() && pImeDpi->CtfImeSelectEx)
|
|
|
|
pImeDpi->CtfImeSelectEx(hIMC, TRUE, hKL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set HKL */
|
|
|
|
pClientImc->hKL = hKL;
|
|
|
|
|
|
|
|
ImmUnlockImeDpi(pImeDpi);
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
Fail:
|
|
|
|
if (pImeDpi)
|
|
|
|
ImmUnlockImeDpi(pImeDpi);
|
|
|
|
|
|
|
|
pIC->hMsgBuf = ImmDestroyIMCC(pIC->hMsgBuf);
|
|
|
|
pIC->hGuideLine = ImmDestroyIMCC(pIC->hGuideLine);
|
|
|
|
pIC->hCandInfo = ImmDestroyIMCC(pIC->hCandInfo);
|
|
|
|
pIC->hCompStr = ImmDestroyIMCC(pIC->hCompStr);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
LPINPUTCONTEXT APIENTRY Imm32LockIMCEx(HIMC hIMC, BOOL fSelect)
|
|
|
|
{
|
|
|
|
HANDLE hIC;
|
|
|
|
LPINPUTCONTEXT pIC = NULL;
|
|
|
|
PCLIENTIMC pClientImc;
|
|
|
|
WORD Word;
|
|
|
|
DWORD dwThreadId;
|
|
|
|
HKL hKL, hNewKL;
|
|
|
|
PIMEDPI pImeDpi = NULL;
|
|
|
|
BOOL bInited;
|
|
|
|
|
|
|
|
pClientImc = ImmLockClientImc(hIMC);
|
|
|
|
if (!pClientImc)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
RtlEnterCriticalSection(&pClientImc->cs);
|
|
|
|
|
|
|
|
if (!pClientImc->hInputContext)
|
|
|
|
{
|
|
|
|
dwThreadId = (DWORD)NtUserQueryInputContext(hIMC, 1);
|
|
|
|
|
|
|
|
if (dwThreadId == GetCurrentThreadId() && Imm32IsCiceroMode() && !Imm32Is16BitMode())
|
|
|
|
{
|
|
|
|
hKL = GetKeyboardLayout(0);
|
|
|
|
Word = LOWORD(hKL);
|
|
|
|
hNewKL = (HKL)(DWORD_PTR)MAKELONG(Word, Word);
|
|
|
|
|
|
|
|
pImeDpi = ImmLockOrLoadImeDpi(hNewKL);
|
|
|
|
if (pImeDpi)
|
|
|
|
{
|
|
|
|
FIXME("We have to do something here\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!NtUserQueryInputContext(hIMC, 2))
|
|
|
|
{
|
|
|
|
RtlLeaveCriticalSection(&pClientImc->cs);
|
|
|
|
goto Quit;
|
|
|
|
}
|
|
|
|
|
|
|
|
hIC = LocalAlloc(LHND, sizeof(INPUTCONTEXTDX));
|
|
|
|
if (!hIC)
|
|
|
|
{
|
|
|
|
RtlLeaveCriticalSection(&pClientImc->cs);
|
|
|
|
goto Quit;
|
|
|
|
}
|
|
|
|
pClientImc->hInputContext = hIC;
|
|
|
|
|
|
|
|
pIC = LocalLock(pClientImc->hInputContext);
|
|
|
|
if (!pIC)
|
|
|
|
{
|
|
|
|
pClientImc->hInputContext = LocalFree(pClientImc->hInputContext);
|
|
|
|
RtlLeaveCriticalSection(&pClientImc->cs);
|
|
|
|
goto Quit;
|
|
|
|
}
|
|
|
|
|
|
|
|
hKL = GetKeyboardLayout(dwThreadId);
|
|
|
|
// bInited = Imm32InitContext(hIMC, hKL, fSelect);
|
|
|
|
bInited = Imm32InitContext(hIMC, pIC, pClientImc, hKL, fSelect);
|
|
|
|
LocalUnlock(pClientImc->hInputContext);
|
|
|
|
|
|
|
|
if (!bInited)
|
|
|
|
{
|
|
|
|
pIC = NULL;
|
|
|
|
pClientImc->hInputContext = LocalFree(pClientImc->hInputContext);
|
|
|
|
RtlLeaveCriticalSection(&pClientImc->cs);
|
|
|
|
goto Quit;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
FIXME("We have to do something here\n");
|
|
|
|
|
|
|
|
RtlLeaveCriticalSection(&pClientImc->cs);
|
|
|
|
pIC = LocalLock(pClientImc->hInputContext);
|
|
|
|
InterlockedIncrement(&pClientImc->cLockObj);
|
|
|
|
|
|
|
|
Quit:
|
|
|
|
ImmUnlockClientImc(pClientImc);
|
|
|
|
return pIC;
|
|
|
|
}
|
|
|
|
|
2010-03-07 11:27:14 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* ImmDestroyContext (IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmDestroyContext(HIMC hIMC)
|
|
|
|
{
|
2021-08-04 00:41:59 +00:00
|
|
|
HKL hKL;
|
|
|
|
|
2021-08-04 00:49:41 +00:00
|
|
|
TRACE("(%p)\n", hIMC);
|
2021-08-04 00:41:59 +00:00
|
|
|
|
2021-09-24 13:06:29 +00:00
|
|
|
if (!Imm32IsImmMode())
|
2010-03-07 11:27:14 +00:00
|
|
|
return FALSE;
|
2021-08-04 00:41:59 +00:00
|
|
|
|
2021-08-14 01:38:06 +00:00
|
|
|
if (Imm32IsCrossThreadAccess(hIMC))
|
2021-08-04 00:41:59 +00:00
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
hKL = GetKeyboardLayout(0);
|
|
|
|
return Imm32CleanupContext(hIMC, hKL, FALSE);
|
2010-03-07 11:27:14 +00:00
|
|
|
}
|
|
|
|
|
2021-08-14 01:38:06 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* ImmLockClientImc (IMM32.@)
|
|
|
|
*/
|
2021-07-11 00:48:15 +00:00
|
|
|
PCLIENTIMC WINAPI ImmLockClientImc(HIMC hImc)
|
|
|
|
{
|
2021-09-27 00:31:16 +00:00
|
|
|
PIMC pIMC;
|
2021-07-11 00:48:15 +00:00
|
|
|
PCLIENTIMC pClientImc;
|
|
|
|
|
2021-08-04 00:49:41 +00:00
|
|
|
TRACE("(%p)\n", hImc);
|
2021-07-11 00:48:15 +00:00
|
|
|
|
|
|
|
if (hImc == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
2021-09-27 00:31:16 +00:00
|
|
|
pIMC = ValidateHandleNoErr(hImc, TYPE_INPUTCONTEXT);
|
|
|
|
if (pIMC == NULL || !Imm32CheckImcProcess(pIMC))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
pClientImc = (PCLIENTIMC)pIMC->dwClientImcData;
|
2021-07-11 00:48:15 +00:00
|
|
|
if (!pClientImc)
|
|
|
|
{
|
|
|
|
pClientImc = Imm32HeapAlloc(HEAP_ZERO_MEMORY, sizeof(CLIENTIMC));
|
|
|
|
if (!pClientImc)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
RtlInitializeCriticalSection(&pClientImc->cs);
|
2021-08-17 23:42:12 +00:00
|
|
|
|
|
|
|
// FIXME: NtUserGetThreadState and enum ThreadStateRoutines are broken.
|
|
|
|
pClientImc->unknown = NtUserGetThreadState(13);
|
2021-07-11 00:48:15 +00:00
|
|
|
|
2021-08-16 06:45:11 +00:00
|
|
|
if (!NtUserUpdateInputContext(hImc, 0, pClientImc))
|
2021-07-11 00:48:15 +00:00
|
|
|
{
|
2021-09-18 16:52:05 +00:00
|
|
|
Imm32HeapFree(pClientImc);
|
2021-07-11 00:48:15 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
pClientImc->dwFlags |= CLIENTIMC_UNKNOWN2;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-07-25 02:55:03 +00:00
|
|
|
if (pClientImc->dwFlags & CLIENTIMC_UNKNOWN1)
|
2021-07-11 00:48:15 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
InterlockedIncrement(&pClientImc->cLockObj);
|
|
|
|
return pClientImc;
|
|
|
|
}
|
|
|
|
|
2021-08-14 01:38:06 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* ImmUnlockClientImc (IMM32.@)
|
|
|
|
*/
|
2021-07-11 00:48:15 +00:00
|
|
|
VOID WINAPI ImmUnlockClientImc(PCLIENTIMC pClientImc)
|
|
|
|
{
|
|
|
|
LONG cLocks;
|
2021-09-27 00:32:24 +00:00
|
|
|
HANDLE hInputContext;
|
2021-07-11 00:48:15 +00:00
|
|
|
|
2021-08-04 00:49:41 +00:00
|
|
|
TRACE("(%p)\n", pClientImc);
|
2021-07-11 00:48:15 +00:00
|
|
|
|
|
|
|
cLocks = InterlockedDecrement(&pClientImc->cLockObj);
|
2021-07-25 02:55:03 +00:00
|
|
|
if (cLocks != 0 || !(pClientImc->dwFlags & CLIENTIMC_UNKNOWN1))
|
2021-07-11 00:48:15 +00:00
|
|
|
return;
|
|
|
|
|
2021-09-27 00:32:24 +00:00
|
|
|
hInputContext = pClientImc->hInputContext;
|
|
|
|
if (hInputContext)
|
|
|
|
LocalFree(hInputContext);
|
2021-07-11 00:48:15 +00:00
|
|
|
|
|
|
|
RtlDeleteCriticalSection(&pClientImc->cs);
|
2021-09-18 16:52:05 +00:00
|
|
|
Imm32HeapFree(pClientImc);
|
2021-07-11 00:48:15 +00:00
|
|
|
}
|
|
|
|
|
2021-08-23 21:50:39 +00:00
|
|
|
static HIMC APIENTRY Imm32GetContextEx(HWND hWnd, DWORD dwContextFlags)
|
|
|
|
{
|
|
|
|
HIMC hIMC;
|
|
|
|
PCLIENTIMC pClientImc;
|
|
|
|
PWND pWnd;
|
|
|
|
|
2021-09-24 13:06:29 +00:00
|
|
|
if (!Imm32IsImmMode())
|
2021-08-23 21:50:39 +00:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (!hWnd)
|
|
|
|
{
|
|
|
|
// FIXME: NtUserGetThreadState and enum ThreadStateRoutines are broken.
|
|
|
|
hIMC = (HIMC)NtUserGetThreadState(4);
|
|
|
|
goto Quit;
|
|
|
|
}
|
|
|
|
|
|
|
|
pWnd = ValidateHwndNoErr(hWnd);
|
|
|
|
if (!pWnd || Imm32IsCrossProcessAccess(hWnd))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
hIMC = pWnd->hImc;
|
|
|
|
if (!hIMC && (dwContextFlags & 1))
|
|
|
|
hIMC = (HIMC)NtUserQueryWindow(hWnd, QUERY_WINDOW_DEFAULT_ICONTEXT);
|
|
|
|
|
|
|
|
Quit:
|
|
|
|
pClientImc = ImmLockClientImc(hIMC);
|
|
|
|
if (pClientImc == NULL)
|
|
|
|
return NULL;
|
|
|
|
if ((dwContextFlags & 2) && (pClientImc->dwFlags & CLIENTIMC_UNKNOWN3))
|
|
|
|
hIMC = NULL;
|
|
|
|
ImmUnlockClientImc(pClientImc);
|
|
|
|
return hIMC;
|
|
|
|
}
|
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
|
|
|
|
/* Helpers for the GetCompositionString functions */
|
|
|
|
|
|
|
|
/* Source encoding is defined by context, source length is always given in respective characters. Destination buffer
|
|
|
|
length is always in bytes. */
|
|
|
|
static INT
|
|
|
|
CopyCompStringIMEtoClient(const InputContextData *data, const void *src, INT src_len, void *dst,
|
|
|
|
INT dst_len, BOOL unicode)
|
2021-07-11 00:48:15 +00:00
|
|
|
{
|
2021-09-10 14:39:15 +00:00
|
|
|
int char_size = unicode ? sizeof(WCHAR) : sizeof(char);
|
|
|
|
INT ret;
|
|
|
|
|
|
|
|
if (is_himc_ime_unicode(data) ^ unicode)
|
2021-07-11 00:48:15 +00:00
|
|
|
{
|
2021-09-10 14:39:15 +00:00
|
|
|
if (unicode)
|
|
|
|
ret = MultiByteToWideChar(CP_ACP, 0, src, src_len, dst, dst_len / sizeof(WCHAR));
|
|
|
|
else
|
|
|
|
ret = WideCharToMultiByte(CP_ACP, 0, src, src_len, dst, dst_len, NULL, NULL);
|
|
|
|
ret *= char_size;
|
2021-07-11 00:48:15 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-09-10 14:39:15 +00:00
|
|
|
if (dst_len)
|
|
|
|
{
|
|
|
|
ret = min(src_len * char_size, dst_len);
|
|
|
|
memcpy(dst, src, ret);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
ret = src_len * char_size;
|
2021-07-11 00:48:15 +00:00
|
|
|
}
|
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
return ret;
|
|
|
|
}
|
2021-07-11 00:48:15 +00:00
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
/* Composition string encoding is defined by context, returned attributes correspond to string, converted according to
|
|
|
|
passed mode. String length is in characters, attributes are in byte arrays. */
|
|
|
|
static INT
|
|
|
|
CopyCompAttrIMEtoClient(const InputContextData *data, const BYTE *src, INT src_len, const void *comp_string,
|
|
|
|
INT str_len, BYTE *dst, INT dst_len, BOOL unicode)
|
|
|
|
{
|
|
|
|
union
|
2021-07-11 00:48:15 +00:00
|
|
|
{
|
2021-09-10 14:39:15 +00:00
|
|
|
const void *str;
|
|
|
|
const WCHAR *strW;
|
|
|
|
const char *strA;
|
|
|
|
} string;
|
|
|
|
INT rc;
|
2021-07-11 00:48:15 +00:00
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
string.str = comp_string;
|
2021-07-11 00:48:15 +00:00
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
if (is_himc_ime_unicode(data) && !unicode)
|
2021-07-11 00:48:15 +00:00
|
|
|
{
|
2021-09-10 14:39:15 +00:00
|
|
|
rc = WideCharToMultiByte(CP_ACP, 0, string.strW, str_len, NULL, 0, NULL, NULL);
|
|
|
|
if (dst_len)
|
|
|
|
{
|
|
|
|
int i, j = 0, k = 0;
|
2021-07-11 00:48:15 +00:00
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
if (rc < dst_len)
|
|
|
|
dst_len = rc;
|
|
|
|
for (i = 0; i < str_len; ++i)
|
|
|
|
{
|
|
|
|
int len;
|
2021-07-11 00:48:15 +00:00
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
len = WideCharToMultiByte(CP_ACP, 0, string.strW + i, 1, NULL, 0, NULL, NULL);
|
|
|
|
for (; len > 0; --len)
|
|
|
|
{
|
|
|
|
dst[j++] = src[k];
|
2021-07-11 00:48:15 +00:00
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
if (j >= dst_len)
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
++k;
|
|
|
|
}
|
|
|
|
end:
|
|
|
|
rc = j;
|
2021-07-11 00:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
2021-09-10 14:39:15 +00:00
|
|
|
else if (!is_himc_ime_unicode(data) && unicode)
|
2021-07-11 00:48:15 +00:00
|
|
|
{
|
2021-09-10 14:39:15 +00:00
|
|
|
rc = MultiByteToWideChar(CP_ACP, 0, string.strA, str_len, NULL, 0);
|
|
|
|
if (dst_len)
|
2021-07-11 00:48:15 +00:00
|
|
|
{
|
2021-09-10 14:39:15 +00:00
|
|
|
int i, j = 0;
|
|
|
|
|
|
|
|
if (rc < dst_len)
|
|
|
|
dst_len = rc;
|
|
|
|
for (i = 0; i < str_len; ++i)
|
|
|
|
{
|
|
|
|
if (IsDBCSLeadByte(string.strA[i]))
|
|
|
|
continue;
|
2021-07-11 00:48:15 +00:00
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
dst[j++] = src[i];
|
2021-07-11 00:48:15 +00:00
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
if (j >= dst_len)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
rc = j;
|
2021-07-11 00:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-09-10 14:39:15 +00:00
|
|
|
memcpy(dst, src, min(src_len, dst_len));
|
|
|
|
rc = src_len;
|
2021-07-11 00:48:15 +00:00
|
|
|
}
|
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
return rc;
|
2021-07-11 00:48:15 +00:00
|
|
|
}
|
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
static INT
|
|
|
|
CopyCompClauseIMEtoClient(InputContextData *data, LPBYTE source, INT slen, LPBYTE ssource,
|
|
|
|
LPBYTE target, INT tlen, BOOL unicode )
|
2005-12-12 20:59:55 +00:00
|
|
|
{
|
2021-09-10 14:39:15 +00:00
|
|
|
INT rc;
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
if (is_himc_ime_unicode(data) && !unicode)
|
2021-07-11 00:48:15 +00:00
|
|
|
{
|
2021-09-10 14:39:15 +00:00
|
|
|
if (tlen)
|
2021-07-11 00:48:15 +00:00
|
|
|
{
|
2021-09-10 14:39:15 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
if (slen < tlen)
|
|
|
|
tlen = slen;
|
|
|
|
tlen /= sizeof (DWORD);
|
|
|
|
for (i = 0; i < tlen; ++i)
|
|
|
|
{
|
|
|
|
((DWORD *)target)[i] = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource,
|
|
|
|
((DWORD *)source)[i],
|
|
|
|
NULL, 0,
|
|
|
|
NULL, NULL);
|
|
|
|
}
|
|
|
|
rc = sizeof (DWORD) * i;
|
2021-07-11 00:48:15 +00:00
|
|
|
}
|
|
|
|
else
|
2021-09-10 14:39:15 +00:00
|
|
|
rc = slen;
|
2021-07-13 11:17:17 +00:00
|
|
|
}
|
2021-09-10 14:39:15 +00:00
|
|
|
else if (!is_himc_ime_unicode(data) && unicode)
|
2021-07-13 11:17:17 +00:00
|
|
|
{
|
2021-09-10 14:39:15 +00:00
|
|
|
if (tlen)
|
2021-07-13 11:17:17 +00:00
|
|
|
{
|
2021-09-10 14:39:15 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
if (slen < tlen)
|
|
|
|
tlen = slen;
|
|
|
|
tlen /= sizeof (DWORD);
|
|
|
|
for (i = 0; i < tlen; ++i)
|
2021-07-13 11:17:17 +00:00
|
|
|
{
|
2021-09-10 14:39:15 +00:00
|
|
|
((DWORD *)target)[i] = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource,
|
|
|
|
((DWORD *)source)[i],
|
|
|
|
NULL, 0);
|
2021-07-13 11:17:17 +00:00
|
|
|
}
|
2021-09-10 14:39:15 +00:00
|
|
|
rc = sizeof (DWORD) * i;
|
2021-07-13 11:17:17 +00:00
|
|
|
}
|
|
|
|
else
|
2021-09-10 14:39:15 +00:00
|
|
|
rc = slen;
|
2021-07-13 11:17:17 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2021-09-10 14:39:15 +00:00
|
|
|
memcpy( target, source, min(slen,tlen));
|
|
|
|
rc = slen;
|
2021-07-13 11:17:17 +00:00
|
|
|
}
|
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
return rc;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
static INT
|
|
|
|
CopyCompOffsetIMEtoClient(InputContextData *data, DWORD offset, LPBYTE ssource, BOOL unicode)
|
2005-12-12 20:59:55 +00:00
|
|
|
{
|
2021-09-10 14:39:15 +00:00
|
|
|
int rc;
|
2014-09-28 18:27:58 +00:00
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
if (is_himc_ime_unicode(data) && !unicode)
|
2021-07-15 18:04:00 +00:00
|
|
|
{
|
2021-09-10 14:39:15 +00:00
|
|
|
rc = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)ssource, offset, NULL, 0, NULL, NULL);
|
2021-07-15 18:04:00 +00:00
|
|
|
}
|
2021-09-10 14:39:15 +00:00
|
|
|
else if (!is_himc_ime_unicode(data) && unicode)
|
|
|
|
{
|
|
|
|
rc = MultiByteToWideChar(CP_ACP, 0, (LPSTR)ssource, offset, NULL, 0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
rc = offset;
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
return rc;
|
2021-07-13 11:51:28 +00:00
|
|
|
}
|
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
static LONG
|
|
|
|
ImmGetCompositionStringT(HIMC hIMC, DWORD dwIndex, LPVOID lpBuf,
|
|
|
|
DWORD dwBufLen, BOOL unicode)
|
2005-12-12 20:59:55 +00:00
|
|
|
{
|
2021-09-10 14:39:15 +00:00
|
|
|
LONG rc = 0;
|
|
|
|
InputContextData *data = get_imc_data(hIMC);
|
|
|
|
LPCOMPOSITIONSTRING compstr;
|
|
|
|
LPBYTE compdata;
|
2008-04-04 13:20:27 +00:00
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
TRACE("(%p, 0x%x, %p, %d)\n", hIMC, dwIndex, lpBuf, dwBufLen);
|
2008-04-04 13:20:27 +00:00
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
if (!data)
|
|
|
|
return FALSE;
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
if (!data->IMC.hCompStr)
|
|
|
|
return FALSE;
|
2021-07-13 11:51:28 +00:00
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
compdata = ImmLockIMCC(data->IMC.hCompStr);
|
|
|
|
compstr = (LPCOMPOSITIONSTRING)compdata;
|
2021-07-13 11:51:28 +00:00
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
switch (dwIndex)
|
2010-03-07 11:27:14 +00:00
|
|
|
{
|
|
|
|
case GCS_RESULTSTR:
|
|
|
|
TRACE("GCS_RESULTSTR\n");
|
|
|
|
rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwResultStrOffset, compstr->dwResultStrLen, lpBuf, dwBufLen, unicode);
|
|
|
|
break;
|
|
|
|
case GCS_COMPSTR:
|
|
|
|
TRACE("GCS_COMPSTR\n");
|
|
|
|
rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwCompStrOffset, compstr->dwCompStrLen, lpBuf, dwBufLen, unicode);
|
|
|
|
break;
|
|
|
|
case GCS_COMPATTR:
|
|
|
|
TRACE("GCS_COMPATTR\n");
|
|
|
|
rc = CopyCompAttrIMEtoClient(data, compdata + compstr->dwCompAttrOffset, compstr->dwCompAttrLen,
|
|
|
|
compdata + compstr->dwCompStrOffset, compstr->dwCompStrLen,
|
|
|
|
lpBuf, dwBufLen, unicode);
|
|
|
|
break;
|
|
|
|
case GCS_COMPCLAUSE:
|
|
|
|
TRACE("GCS_COMPCLAUSE\n");
|
|
|
|
rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwCompClauseOffset,compstr->dwCompClauseLen,
|
2011-12-15 00:40:35 +00:00
|
|
|
compdata + compstr->dwCompStrOffset,
|
2010-03-07 11:27:14 +00:00
|
|
|
lpBuf, dwBufLen, unicode);
|
|
|
|
break;
|
|
|
|
case GCS_RESULTCLAUSE:
|
|
|
|
TRACE("GCS_RESULTCLAUSE\n");
|
|
|
|
rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwResultClauseOffset,compstr->dwResultClauseLen,
|
2011-12-15 00:40:35 +00:00
|
|
|
compdata + compstr->dwResultStrOffset,
|
2010-03-07 11:27:14 +00:00
|
|
|
lpBuf, dwBufLen, unicode);
|
|
|
|
break;
|
|
|
|
case GCS_RESULTREADSTR:
|
|
|
|
TRACE("GCS_RESULTREADSTR\n");
|
|
|
|
rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwResultReadStrOffset, compstr->dwResultReadStrLen, lpBuf, dwBufLen, unicode);
|
|
|
|
break;
|
|
|
|
case GCS_RESULTREADCLAUSE:
|
|
|
|
TRACE("GCS_RESULTREADCLAUSE\n");
|
|
|
|
rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwResultReadClauseOffset,compstr->dwResultReadClauseLen,
|
2011-12-15 00:40:35 +00:00
|
|
|
compdata + compstr->dwResultStrOffset,
|
2010-03-07 11:27:14 +00:00
|
|
|
lpBuf, dwBufLen, unicode);
|
|
|
|
break;
|
|
|
|
case GCS_COMPREADSTR:
|
|
|
|
TRACE("GCS_COMPREADSTR\n");
|
|
|
|
rc = CopyCompStringIMEtoClient(data, compdata + compstr->dwCompReadStrOffset, compstr->dwCompReadStrLen, lpBuf, dwBufLen, unicode);
|
|
|
|
break;
|
|
|
|
case GCS_COMPREADATTR:
|
|
|
|
TRACE("GCS_COMPREADATTR\n");
|
|
|
|
rc = CopyCompAttrIMEtoClient(data, compdata + compstr->dwCompReadAttrOffset, compstr->dwCompReadAttrLen,
|
|
|
|
compdata + compstr->dwCompReadStrOffset, compstr->dwCompReadStrLen,
|
|
|
|
lpBuf, dwBufLen, unicode);
|
|
|
|
break;
|
|
|
|
case GCS_COMPREADCLAUSE:
|
|
|
|
TRACE("GCS_COMPREADCLAUSE\n");
|
|
|
|
rc = CopyCompClauseIMEtoClient(data, compdata + compstr->dwCompReadClauseOffset,compstr->dwCompReadClauseLen,
|
2011-12-15 00:40:35 +00:00
|
|
|
compdata + compstr->dwCompStrOffset,
|
2010-03-07 11:27:14 +00:00
|
|
|
lpBuf, dwBufLen, unicode);
|
|
|
|
break;
|
|
|
|
case GCS_CURSORPOS:
|
|
|
|
TRACE("GCS_CURSORPOS\n");
|
|
|
|
rc = CopyCompOffsetIMEtoClient(data, compstr->dwCursorPos, compdata + compstr->dwCompStrOffset, unicode);
|
|
|
|
break;
|
|
|
|
case GCS_DELTASTART:
|
2007-09-14 08:03:04 +00:00
|
|
|
TRACE("GCS_DELTASTART\n");
|
2010-03-07 11:27:14 +00:00
|
|
|
rc = CopyCompOffsetIMEtoClient(data, compstr->dwDeltaStart, compdata + compstr->dwCompStrOffset, unicode);
|
|
|
|
break;
|
|
|
|
default:
|
2006-11-26 21:05:00 +00:00
|
|
|
FIXME("Unhandled index 0x%x\n",dwIndex);
|
2010-03-07 11:27:14 +00:00
|
|
|
break;
|
|
|
|
}
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2007-09-14 08:03:04 +00:00
|
|
|
ImmUnlockIMCC(data->IMC.hCompStr);
|
|
|
|
|
2005-12-12 20:59:55 +00:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2010-03-07 11:27:14 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* ImmGetCompositionStringA (IMM32.@)
|
|
|
|
*/
|
2021-09-10 14:39:15 +00:00
|
|
|
LONG WINAPI ImmGetCompositionStringA(HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen)
|
2010-03-07 11:27:14 +00:00
|
|
|
{
|
|
|
|
return ImmGetCompositionStringT(hIMC, dwIndex, lpBuf, dwBufLen, FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmGetCompositionStringW (IMM32.@)
|
|
|
|
*/
|
2021-09-10 14:39:15 +00:00
|
|
|
LONG WINAPI ImmGetCompositionStringW(HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen)
|
2010-03-07 11:27:14 +00:00
|
|
|
{
|
|
|
|
return ImmGetCompositionStringT(hIMC, dwIndex, lpBuf, dwBufLen, TRUE);
|
|
|
|
}
|
|
|
|
|
2005-12-12 20:59:55 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* ImmGetContext (IMM32.@)
|
|
|
|
*/
|
|
|
|
HIMC WINAPI ImmGetContext(HWND hWnd)
|
|
|
|
{
|
2021-08-23 21:50:39 +00:00
|
|
|
TRACE("(%p)\n", hWnd);
|
|
|
|
if (hWnd == NULL)
|
2011-12-15 00:40:35 +00:00
|
|
|
return NULL;
|
2021-08-23 21:50:39 +00:00
|
|
|
return Imm32GetContextEx(hWnd, 2);
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
2021-09-10 14:39:15 +00:00
|
|
|
* CtfImmIsCiceroEnabled (IMM32.@)
|
2005-12-12 20:59:55 +00:00
|
|
|
*/
|
2021-09-10 14:39:15 +00:00
|
|
|
BOOL WINAPI CtfImmIsCiceroEnabled(VOID)
|
2005-12-12 20:59:55 +00:00
|
|
|
{
|
2021-09-24 13:06:29 +00:00
|
|
|
return Imm32IsCiceroMode();
|
2021-09-10 14:39:15 +00:00
|
|
|
}
|
2021-08-12 03:32:02 +00:00
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* ImmInstallIMEA (IMM32.@)
|
|
|
|
*/
|
|
|
|
HKL WINAPI ImmInstallIMEA(LPCSTR lpszIMEFileName, LPCSTR lpszLayoutText)
|
|
|
|
{
|
|
|
|
HKL hKL = NULL;
|
|
|
|
LPWSTR pszFileNameW = NULL, pszLayoutTextW = NULL;
|
2021-08-12 03:32:02 +00:00
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
TRACE("(%s, %s)\n", debugstr_a(lpszIMEFileName), debugstr_a(lpszLayoutText));
|
2021-08-12 03:32:02 +00:00
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
pszFileNameW = Imm32WideFromAnsi(lpszIMEFileName);
|
|
|
|
if (pszFileNameW == NULL)
|
2021-08-12 03:32:02 +00:00
|
|
|
goto Quit;
|
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
pszLayoutTextW = Imm32WideFromAnsi(lpszLayoutText);
|
|
|
|
if (pszLayoutTextW == NULL)
|
2021-08-12 03:32:02 +00:00
|
|
|
goto Quit;
|
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
hKL = ImmInstallIMEW(pszFileNameW, pszLayoutTextW);
|
2021-08-12 03:30:13 +00:00
|
|
|
|
|
|
|
Quit:
|
2021-09-18 16:52:05 +00:00
|
|
|
Imm32HeapFree(pszFileNameW);
|
|
|
|
Imm32HeapFree(pszLayoutTextW);
|
2021-09-10 14:39:15 +00:00
|
|
|
return hKL;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
2021-09-10 14:39:15 +00:00
|
|
|
* ImmInstallIMEW (IMM32.@)
|
2005-12-12 20:59:55 +00:00
|
|
|
*/
|
2021-09-10 14:39:15 +00:00
|
|
|
HKL WINAPI ImmInstallIMEW(LPCWSTR lpszIMEFileName, LPCWSTR lpszLayoutText)
|
2005-12-12 20:59:55 +00:00
|
|
|
{
|
2021-09-10 14:39:15 +00:00
|
|
|
INT lcid = GetUserDefaultLCID();
|
|
|
|
INT count;
|
|
|
|
HKL hkl;
|
|
|
|
DWORD rc;
|
|
|
|
HKEY hkey;
|
|
|
|
WCHAR regKey[ARRAY_SIZE(szImeRegFmt)+8];
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
TRACE ("(%s, %s):\n", debugstr_w(lpszIMEFileName),
|
|
|
|
debugstr_w(lpszLayoutText));
|
2014-09-28 18:27:58 +00:00
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
/* Start with 2. e001 will be blank and so default to the wine internal IME */
|
|
|
|
count = 2;
|
2014-09-28 18:27:58 +00:00
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
while (count < 0xfff)
|
2010-03-07 11:27:14 +00:00
|
|
|
{
|
2021-09-10 14:39:15 +00:00
|
|
|
DWORD disposition = 0;
|
2010-03-07 11:27:14 +00:00
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
hkl = (HKL)MAKELPARAM( lcid, 0xe000 | count );
|
|
|
|
wsprintfW( regKey, szImeRegFmt, (ULONG_PTR)hkl);
|
2007-03-14 14:34:47 +00:00
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
rc = RegCreateKeyExW(HKEY_LOCAL_MACHINE, regKey, 0, NULL, 0, KEY_WRITE, NULL, &hkey, &disposition);
|
|
|
|
if (rc == ERROR_SUCCESS && disposition == REG_CREATED_NEW_KEY)
|
|
|
|
break;
|
|
|
|
else if (rc == ERROR_SUCCESS)
|
|
|
|
RegCloseKey(hkey);
|
2014-09-28 18:27:58 +00:00
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
count++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (count == 0xfff)
|
2014-09-28 18:27:58 +00:00
|
|
|
{
|
2021-09-10 14:39:15 +00:00
|
|
|
WARN("Unable to find slot to install IME\n");
|
2014-09-28 18:27:58 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
if (rc == ERROR_SUCCESS)
|
2010-03-07 11:27:14 +00:00
|
|
|
{
|
2021-09-10 14:39:15 +00:00
|
|
|
rc = RegSetValueExW(hkey, szImeFileW, 0, REG_SZ, (const BYTE*)lpszIMEFileName,
|
|
|
|
(lstrlenW(lpszIMEFileName) + 1) * sizeof(WCHAR));
|
|
|
|
if (rc == ERROR_SUCCESS)
|
|
|
|
rc = RegSetValueExW(hkey, szLayoutTextW, 0, REG_SZ, (const BYTE*)lpszLayoutText,
|
|
|
|
(lstrlenW(lpszLayoutText) + 1) * sizeof(WCHAR));
|
|
|
|
RegCloseKey(hkey);
|
|
|
|
return hkl;
|
2010-03-07 11:27:14 +00:00
|
|
|
}
|
|
|
|
else
|
2021-09-10 14:39:15 +00:00
|
|
|
{
|
|
|
|
WARN("Unable to set IME registry values\n");
|
2010-03-07 11:27:14 +00:00
|
|
|
return 0;
|
2021-09-10 14:39:15 +00:00
|
|
|
}
|
2007-03-14 14:34:47 +00:00
|
|
|
}
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2007-09-14 08:03:04 +00:00
|
|
|
/***********************************************************************
|
2021-09-27 00:32:24 +00:00
|
|
|
* ImmLockIMC(IMM32.@)
|
|
|
|
*
|
|
|
|
* NOTE: This is not ImmLockIMCC. Don't confuse.
|
|
|
|
*/
|
2007-09-14 08:03:04 +00:00
|
|
|
LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC hIMC)
|
|
|
|
{
|
2021-09-27 00:32:24 +00:00
|
|
|
TRACE("(%p)\n", hIMC);
|
|
|
|
return Imm32LockIMCEx(hIMC, TRUE);
|
2007-09-14 08:03:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmUnlockIMC(IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmUnlockIMC(HIMC hIMC)
|
|
|
|
{
|
2021-07-13 11:17:17 +00:00
|
|
|
PCLIENTIMC pClientImc;
|
2014-09-28 18:27:58 +00:00
|
|
|
|
2021-07-13 11:17:17 +00:00
|
|
|
pClientImc = ImmLockClientImc(hIMC);
|
|
|
|
if (pClientImc == NULL)
|
2014-09-28 18:27:58 +00:00
|
|
|
return FALSE;
|
2021-07-11 00:48:15 +00:00
|
|
|
|
2021-09-27 00:32:24 +00:00
|
|
|
if (pClientImc->hInputContext)
|
|
|
|
LocalUnlock(pClientImc->hInputContext);
|
2021-07-11 00:48:15 +00:00
|
|
|
|
2021-07-13 11:17:17 +00:00
|
|
|
InterlockedDecrement(&pClientImc->cLockObj);
|
|
|
|
ImmUnlockClientImc(pClientImc);
|
2013-12-01 15:57:34 +00:00
|
|
|
return TRUE;
|
2007-09-14 08:03:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
2021-09-10 14:39:15 +00:00
|
|
|
* ImmRequestMessageA(IMM32.@)
|
|
|
|
*/
|
|
|
|
LRESULT WINAPI ImmRequestMessageA(HIMC hIMC, WPARAM wParam, LPARAM lParam)
|
2007-09-14 08:03:04 +00:00
|
|
|
{
|
2021-09-10 14:39:15 +00:00
|
|
|
InputContextData *data = get_imc_data(hIMC);
|
2021-07-11 00:48:15 +00:00
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
TRACE("%p %ld %ld\n", hIMC, wParam, wParam);
|
2007-09-14 08:03:04 +00:00
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
if (data) return SendMessageA(data->IMC.hWnd, WM_IME_REQUEST, wParam, lParam);
|
2007-09-14 08:03:04 +00:00
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
|
|
return 0;
|
2007-09-14 08:03:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
2021-09-10 14:39:15 +00:00
|
|
|
* ImmRequestMessageW(IMM32.@)
|
|
|
|
*/
|
|
|
|
LRESULT WINAPI ImmRequestMessageW(HIMC hIMC, WPARAM wParam, LPARAM lParam)
|
2007-09-14 08:03:04 +00:00
|
|
|
{
|
2021-09-10 14:39:15 +00:00
|
|
|
InputContextData *data = get_imc_data(hIMC);
|
2007-09-14 08:03:04 +00:00
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
TRACE("%p %ld %ld\n", hIMC, wParam, wParam);
|
2007-09-14 08:03:04 +00:00
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
if (data) return SendMessageW(data->IMC.hWnd, WM_IME_REQUEST, wParam, lParam);
|
2007-09-14 08:03:04 +00:00
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
|
|
return 0;
|
2007-09-14 08:03:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
2021-09-10 14:39:15 +00:00
|
|
|
* ImmReleaseContext (IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmReleaseContext(HWND hWnd, HIMC hIMC)
|
2007-09-14 08:03:04 +00:00
|
|
|
{
|
2021-09-10 14:39:15 +00:00
|
|
|
TRACE("(%p, %p)\n", hWnd, hIMC);
|
|
|
|
UNREFERENCED_PARAMETER(hWnd);
|
|
|
|
UNREFERENCED_PARAMETER(hIMC);
|
|
|
|
return TRUE; // Do nothing. This is correct.
|
2007-09-14 08:03:04 +00:00
|
|
|
}
|
|
|
|
|
2008-04-04 13:20:27 +00:00
|
|
|
/***********************************************************************
|
2021-09-10 14:39:15 +00:00
|
|
|
* ImmSetCompositionStringA (IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI
|
|
|
|
ImmSetCompositionStringA(HIMC hIMC, DWORD dwIndex,
|
|
|
|
LPCVOID lpComp, DWORD dwCompLen,
|
|
|
|
LPCVOID lpRead, DWORD dwReadLen)
|
2008-04-04 13:20:27 +00:00
|
|
|
{
|
2021-09-10 14:39:15 +00:00
|
|
|
DWORD comp_len;
|
|
|
|
DWORD read_len;
|
|
|
|
WCHAR *CompBuffer = NULL;
|
|
|
|
WCHAR *ReadBuffer = NULL;
|
|
|
|
BOOL rc;
|
|
|
|
InputContextData *data = get_imc_data(hIMC);
|
2021-08-17 23:42:12 +00:00
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
TRACE("(%p, %d, %p, %d, %p, %d):\n",
|
|
|
|
hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
|
2021-08-17 23:42:12 +00:00
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
if (!data)
|
2021-08-17 23:42:12 +00:00
|
|
|
return FALSE;
|
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
if (!(dwIndex == SCS_SETSTR ||
|
|
|
|
dwIndex == SCS_CHANGEATTR ||
|
|
|
|
dwIndex == SCS_CHANGECLAUSE ||
|
|
|
|
dwIndex == SCS_SETRECONVERTSTRING ||
|
|
|
|
dwIndex == SCS_QUERYRECONVERTSTRING))
|
2014-09-28 18:27:58 +00:00
|
|
|
return FALSE;
|
2021-08-17 23:42:12 +00:00
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
if (!is_himc_ime_unicode(data))
|
|
|
|
return data->immKbd->pImeSetCompositionString(hIMC, dwIndex, lpComp,
|
|
|
|
dwCompLen, lpRead, dwReadLen);
|
2008-05-08 16:03:10 +00:00
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
comp_len = MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, NULL, 0);
|
|
|
|
if (comp_len)
|
2010-03-07 11:27:14 +00:00
|
|
|
{
|
2021-09-10 14:39:15 +00:00
|
|
|
CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len * sizeof(WCHAR));
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len);
|
2008-05-06 09:16:21 +00:00
|
|
|
}
|
2007-09-14 08:03:04 +00:00
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
read_len = MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, NULL, 0);
|
|
|
|
if (read_len)
|
2021-08-17 23:42:12 +00:00
|
|
|
{
|
2021-09-10 14:39:15 +00:00
|
|
|
ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len * sizeof(WCHAR));
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len);
|
2010-03-07 11:27:14 +00:00
|
|
|
}
|
2008-05-08 16:03:10 +00:00
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
rc = ImmSetCompositionStringW(hIMC, dwIndex, CompBuffer, comp_len,
|
|
|
|
ReadBuffer, read_len);
|
2007-09-14 08:03:04 +00:00
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
HeapFree(GetProcessHeap(), 0, CompBuffer);
|
|
|
|
HeapFree(GetProcessHeap(), 0, ReadBuffer);
|
|
|
|
|
|
|
|
return rc;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
|
|
|
|
2010-03-07 11:27:14 +00:00
|
|
|
/***********************************************************************
|
2021-09-10 14:39:15 +00:00
|
|
|
* ImmSetCompositionStringW (IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI
|
|
|
|
ImmSetCompositionStringW(HIMC hIMC, DWORD dwIndex,
|
|
|
|
LPCVOID lpComp, DWORD dwCompLen,
|
|
|
|
LPCVOID lpRead, DWORD dwReadLen)
|
2005-12-12 20:59:55 +00:00
|
|
|
{
|
2021-09-10 14:39:15 +00:00
|
|
|
DWORD comp_len;
|
|
|
|
DWORD read_len;
|
|
|
|
CHAR *CompBuffer = NULL;
|
|
|
|
CHAR *ReadBuffer = NULL;
|
|
|
|
BOOL rc;
|
|
|
|
InputContextData *data = get_imc_data(hIMC);
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
TRACE("(%p, %d, %p, %d, %p, %d):\n",
|
|
|
|
hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
|
2021-08-20 22:22:43 +00:00
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
if (!data)
|
|
|
|
return FALSE;
|
2021-08-20 22:22:43 +00:00
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
if (!(dwIndex == SCS_SETSTR ||
|
|
|
|
dwIndex == SCS_CHANGEATTR ||
|
|
|
|
dwIndex == SCS_CHANGECLAUSE ||
|
|
|
|
dwIndex == SCS_SETRECONVERTSTRING ||
|
|
|
|
dwIndex == SCS_QUERYRECONVERTSTRING))
|
|
|
|
return FALSE;
|
2021-08-20 22:22:43 +00:00
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
if (is_himc_ime_unicode(data))
|
|
|
|
return data->immKbd->pImeSetCompositionString(hIMC, dwIndex, lpComp,
|
|
|
|
dwCompLen, lpRead, dwReadLen);
|
2017-12-08 03:14:21 +00:00
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
comp_len = WideCharToMultiByte(CP_ACP, 0, lpComp, dwCompLen, NULL, 0, NULL,
|
|
|
|
NULL);
|
|
|
|
if (comp_len)
|
2021-08-20 22:22:43 +00:00
|
|
|
{
|
2021-09-10 14:39:15 +00:00
|
|
|
CompBuffer = HeapAlloc(GetProcessHeap(),0,comp_len);
|
|
|
|
WideCharToMultiByte(CP_ACP, 0, lpComp, dwCompLen, CompBuffer, comp_len,
|
|
|
|
NULL, NULL);
|
2021-08-20 22:22:43 +00:00
|
|
|
}
|
2008-05-08 16:03:10 +00:00
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
read_len = WideCharToMultiByte(CP_ACP, 0, lpRead, dwReadLen, NULL, 0, NULL,
|
|
|
|
NULL);
|
|
|
|
if (read_len)
|
2008-05-08 16:03:10 +00:00
|
|
|
{
|
2021-09-10 14:39:15 +00:00
|
|
|
ReadBuffer = HeapAlloc(GetProcessHeap(),0,read_len);
|
|
|
|
WideCharToMultiByte(CP_ACP, 0, lpRead, dwReadLen, ReadBuffer, read_len,
|
|
|
|
NULL, NULL);
|
2008-05-08 16:03:10 +00:00
|
|
|
}
|
2005-12-12 20:59:55 +00:00
|
|
|
|
2021-09-10 14:39:15 +00:00
|
|
|
rc = ImmSetCompositionStringA(hIMC, dwIndex, CompBuffer, comp_len,
|
|
|
|
ReadBuffer, read_len);
|
|
|
|
|
|
|
|
HeapFree(GetProcessHeap(), 0, CompBuffer);
|
|
|
|
HeapFree(GetProcessHeap(), 0, ReadBuffer);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmCreateSoftKeyboard(IMM32.@)
|
|
|
|
*/
|
|
|
|
HWND WINAPI ImmCreateSoftKeyboard(UINT uType, UINT hOwner, int x, int y)
|
|
|
|
{
|
|
|
|
FIXME("(%d, %d, %d, %d): stub\n", uType, hOwner, x, y);
|
|
|
|
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmDestroySoftKeyboard(IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmDestroySoftKeyboard(HWND hSoftWnd)
|
|
|
|
{
|
|
|
|
TRACE("(%p)\n", hSoftWnd);
|
|
|
|
return DestroyWindow(hSoftWnd);
|
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmShowSoftKeyboard(IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmShowSoftKeyboard(HWND hSoftWnd, int nCmdShow)
|
|
|
|
{
|
|
|
|
TRACE("(%p, %d)\n", hSoftWnd, nCmdShow);
|
|
|
|
if (hSoftWnd)
|
|
|
|
return ShowWindow(hSoftWnd, nCmdShow);
|
|
|
|
return FALSE;
|
2010-03-07 11:27:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmDisableTextFrameService(IMM32.@)
|
|
|
|
*/
|
2021-07-28 23:21:33 +00:00
|
|
|
BOOL WINAPI ImmDisableTextFrameService(DWORD dwThreadId)
|
2010-03-07 11:27:14 +00:00
|
|
|
{
|
|
|
|
FIXME("Stub\n");
|
|
|
|
return FALSE;
|
2005-12-12 20:59:55 +00:00
|
|
|
}
|
2011-12-15 00:40:35 +00:00
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmEnumInputContext(IMM32.@)
|
|
|
|
*/
|
2021-07-28 23:21:33 +00:00
|
|
|
BOOL WINAPI ImmEnumInputContext(DWORD dwThreadId, IMCENUMPROC lpfn, LPARAM lParam)
|
2011-12-15 00:40:35 +00:00
|
|
|
{
|
2021-07-31 06:45:07 +00:00
|
|
|
HIMC *phList;
|
|
|
|
DWORD dwIndex, dwCount;
|
|
|
|
BOOL ret = TRUE;
|
|
|
|
HIMC hIMC;
|
|
|
|
|
2021-08-04 00:49:41 +00:00
|
|
|
TRACE("(%lu, %p, %p)\n", dwThreadId, lpfn, lParam);
|
2021-07-31 06:45:07 +00:00
|
|
|
|
|
|
|
dwCount = Imm32AllocAndBuildHimcList(dwThreadId, &phList);
|
|
|
|
if (!dwCount)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
for (dwIndex = 0; dwIndex < dwCount; ++dwIndex)
|
|
|
|
{
|
|
|
|
hIMC = phList[dwIndex];
|
|
|
|
ret = (*lpfn)(hIMC, lParam);
|
|
|
|
if (!ret)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2021-09-18 16:52:05 +00:00
|
|
|
Imm32HeapFree(phList);
|
2021-07-31 06:45:07 +00:00
|
|
|
return ret;
|
2011-12-15 00:40:35 +00:00
|
|
|
}
|
2012-03-15 21:42:01 +00:00
|
|
|
|
2020-08-08 00:46:13 +00:00
|
|
|
/***********************************************************************
|
|
|
|
* ImmSetActiveContext(IMM32.@)
|
|
|
|
*/
|
2021-09-30 18:02:56 +00:00
|
|
|
BOOL WINAPI ImmSetActiveContext(HWND hWnd, HIMC hIMC, BOOL fActive)
|
2020-08-08 00:46:13 +00:00
|
|
|
{
|
2021-09-30 18:02:56 +00:00
|
|
|
PCLIENTIMC pClientImc;
|
|
|
|
LPINPUTCONTEXTDX pIC;
|
|
|
|
PIMEDPI pImeDpi;
|
|
|
|
HKL hKL;
|
|
|
|
BOOL fOpen = FALSE;
|
|
|
|
DWORD dwConversion = 0, iShow = ISC_SHOWUIALL;
|
|
|
|
HWND hwndDefIME;
|
|
|
|
|
|
|
|
TRACE("(%p, %p, %d)\n", hWnd, hIMC, fActive);
|
|
|
|
|
|
|
|
if (!Imm32IsImmMode())
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
pClientImc = ImmLockClientImc(hIMC);
|
|
|
|
|
|
|
|
if (!fActive)
|
|
|
|
{
|
|
|
|
if (pClientImc)
|
|
|
|
pClientImc->dwFlags &= ~CLIENTIMC_UNKNOWN4;
|
|
|
|
}
|
|
|
|
else if (hIMC)
|
|
|
|
{
|
|
|
|
if (!pClientImc)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
pIC = (LPINPUTCONTEXTDX)ImmLockIMC(hIMC);
|
|
|
|
if (!pIC)
|
|
|
|
{
|
|
|
|
ImmUnlockClientImc(pClientImc);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
pIC->hWnd = hWnd;
|
|
|
|
pClientImc->dwFlags |= CLIENTIMC_UNKNOWN5;
|
|
|
|
|
|
|
|
if (pIC->dwUIFlags & 2)
|
|
|
|
iShow = (ISC_SHOWUIGUIDELINE | ISC_SHOWUIALLCANDIDATEWINDOW);
|
|
|
|
|
|
|
|
fOpen = pIC->fOpen;
|
|
|
|
dwConversion = pIC->fdwConversion;
|
|
|
|
|
|
|
|
ImmUnlockIMC(hIMC);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
hIMC = Imm32GetContextEx(hWnd, TRUE);
|
|
|
|
pIC = (LPINPUTCONTEXTDX)ImmLockIMC(hIMC);
|
|
|
|
if (pIC)
|
|
|
|
{
|
|
|
|
pIC->hWnd = hWnd;
|
|
|
|
ImmUnlockIMC(hIMC);
|
|
|
|
}
|
|
|
|
hIMC = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
hKL = GetKeyboardLayout(0);
|
|
|
|
|
|
|
|
if (Imm32IsCiceroMode() && !Imm32Is16BitMode())
|
|
|
|
{
|
|
|
|
Imm32CiceroSetActiveContext(hIMC, fActive, hWnd, hKL);
|
|
|
|
hKL = GetKeyboardLayout(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
pImeDpi = ImmLockImeDpi(hKL);
|
|
|
|
if (pImeDpi)
|
|
|
|
{
|
|
|
|
if (IS_IME_HKL(hKL))
|
|
|
|
pImeDpi->ImeSetActiveContext(hIMC, fActive);
|
|
|
|
ImmUnlockImeDpi(pImeDpi);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (IsWindow(hWnd))
|
|
|
|
{
|
|
|
|
SendMessageW(hWnd, WM_IME_SETCONTEXT, fActive, iShow);
|
|
|
|
if (fActive)
|
|
|
|
NtUserNotifyIMEStatus(hWnd, fOpen, dwConversion);
|
|
|
|
}
|
|
|
|
else if (!fActive)
|
|
|
|
{
|
|
|
|
hwndDefIME = ImmGetDefaultIMEWnd(NULL);
|
|
|
|
if (hwndDefIME)
|
|
|
|
SendMessageW(hwndDefIME, WM_IME_SETCONTEXT, 0, iShow);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pClientImc)
|
|
|
|
ImmUnlockClientImc(pClientImc);
|
|
|
|
|
|
|
|
return TRUE;
|
2020-08-08 00:46:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ImmSetActiveContextConsoleIME(IMM32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ImmSetActiveContextConsoleIME(HWND hwnd, BOOL fFlag)
|
|
|
|
{
|
2020-08-09 13:42:17 +00:00
|
|
|
HIMC hIMC;
|
|
|
|
TRACE("(%p, %d)\n", hwnd, fFlag);
|
|
|
|
|
|
|
|
hIMC = ImmGetContext(hwnd);
|
2020-08-08 00:46:13 +00:00
|
|
|
if (hIMC)
|
|
|
|
return ImmSetActiveContext(hwnd, hIMC, fFlag);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2020-08-09 13:49:00 +00:00
|
|
|
|
2021-08-04 00:41:59 +00:00
|
|
|
BOOL WINAPI User32InitializeImmEntryTable(DWORD);
|
|
|
|
|
|
|
|
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
|
|
|
|
{
|
|
|
|
HKL hKL;
|
2021-08-16 06:33:51 +00:00
|
|
|
HIMC hIMC;
|
2021-08-04 00:41:59 +00:00
|
|
|
PTEB pTeb;
|
|
|
|
|
2021-08-04 00:49:41 +00:00
|
|
|
TRACE("(%p, 0x%X, %p)\n", hinstDLL, fdwReason, lpReserved);
|
2021-08-04 00:41:59 +00:00
|
|
|
|
|
|
|
switch (fdwReason)
|
|
|
|
{
|
|
|
|
case DLL_PROCESS_ATTACH:
|
|
|
|
if (!Imm32InitInstance(hinstDLL))
|
|
|
|
{
|
|
|
|
ERR("Imm32InitInstance failed\n");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
if (!User32InitializeImmEntryTable(IMM_INIT_MAGIC))
|
|
|
|
{
|
|
|
|
ERR("User32InitializeImmEntryTable failed\n");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DLL_THREAD_ATTACH:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DLL_THREAD_DETACH:
|
2021-09-24 13:06:29 +00:00
|
|
|
if (!Imm32IsImmMode())
|
2021-08-04 00:41:59 +00:00
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
pTeb = NtCurrentTeb();
|
|
|
|
if (pTeb->Win32ThreadInfo == NULL)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
hKL = GetKeyboardLayout(0);
|
2021-08-16 06:33:51 +00:00
|
|
|
// FIXME: NtUserGetThreadState and enum ThreadStateRoutines are broken.
|
2021-08-16 06:45:11 +00:00
|
|
|
hIMC = (HIMC)NtUserGetThreadState(4);
|
2021-08-16 06:33:51 +00:00
|
|
|
Imm32CleanupContext(hIMC, hKL, TRUE);
|
2021-08-04 00:41:59 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DLL_PROCESS_DETACH:
|
|
|
|
RtlDeleteCriticalSection(&g_csImeDpi);
|
2021-08-23 07:25:21 +00:00
|
|
|
TRACE("imm32.dll is unloaded\n");
|
2021-08-04 00:41:59 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|