[IMM32] ImmCreateContext, ImmDestroyContext, DllMain etc. (#3867)

- Rewrite ImmCreateContext, ImmDestroyContext, and DllMain functions.
- Add g_hImm32Inst, g_bClientRegd, and g_SharedInfo global variables. Delete g_dwImm32Flags (that was g_psi->dwSRVIFlags).
- Implement ImmLoadIME and ImmRegisterClient functions.
- Modify CLIENTIMC and IMEDPI structures. Move CLIENTIMC definition into ntuser.h.
- Add file win32ss/include/imetable.h.
- Rename SRVINFO_METRICS macro as SRVINFO_CICERO_ENABLED.
CORE-11700
This commit is contained in:
Katayama Hirofumi MZ 2021-08-04 09:41:59 +09:00 committed by GitHub
parent c23ce9dfad
commit 692a30a84a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 586 additions and 296 deletions

View file

@ -15,5 +15,5 @@ list(APPEND SOURCE
add_library(imm32 MODULE ${SOURCE} version.rc)
set_module_type(imm32 win32dll)
target_link_libraries(imm32 wine win32ksys)
add_importlibs(imm32 advapi32 user32 msvcrt kernel32 ntdll)
add_importlibs(imm32 advapi32 user32 gdi32 msvcrt kernel32 ntdll)
add_cd_file(TARGET imm32 DESTINATION reactos/system32 FOR all)

View file

@ -57,11 +57,55 @@ WINE_DEFAULT_DEBUG_CHANNEL(imm);
#define REGKEY_IMM \
L"Software\\Microsoft\\Windows NT\\CurrentVersion\\IMM"
#define ROUNDUP4(n) (((n) + 3) & ~3) /* DWORD alignment */
HMODULE g_hImm32Inst = NULL;
RTL_CRITICAL_SECTION g_csImeDpi;
PIMEDPI g_pImeDpiList = NULL;
PSERVERINFO g_psi = NULL;
SHAREDINFO g_SharedInfo = { NULL };
BYTE g_bClientRegd = FALSE;
HANDLE g_hImm32Heap = NULL;
BOOL WINAPI User32InitializeImmEntryTable(DWORD);
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;
}
LPVOID APIENTRY Imm32HeapAlloc(DWORD dwFlags, DWORD dwBytes)
{
if (!g_hImm32Heap)
{
g_hImm32Heap = RtlGetProcessHeap();
if (g_hImm32Heap == NULL)
return NULL;
}
return HeapAlloc(g_hImm32Heap, dwFlags, dwBytes);
}
static DWORD_PTR APIENTRY Imm32QueryWindow(HWND hWnd, DWORD Index)
{
return NtUserQueryWindow(hWnd, Index);
}
static DWORD APIENTRY
Imm32UpdateInputContext(HIMC hIMC, DWORD Unknown1, PCLIENTIMC pClientImc)
{
return NtUserUpdateInputContext(hIMC, Unknown1, pClientImc);
}
static DWORD APIENTRY Imm32QueryInputContext(HIMC hIMC, DWORD dwUnknown2)
{
@ -73,6 +117,21 @@ static DWORD APIENTRY Imm32NotifyIMEStatus(HWND hwnd, HIMC hIMC, DWORD dwConvers
return NtUserNotifyIMEStatus(hwnd, hIMC, dwConversion);
}
static HIMC APIENTRY Imm32CreateInputContext(PCLIENTIMC pClientImc)
{
return NtUserCreateInputContext(pClientImc);
}
static BOOL APIENTRY Imm32DestroyInputContext(HIMC hIMC)
{
return NtUserDestroyInputContext(hIMC);
}
DWORD_PTR APIENTRY Imm32GetThreadState(DWORD Routine)
{
return NtUserGetThreadState(Routine);
}
static VOID APIENTRY Imm32FreeImeDpi(PIMEDPI pImeDpi, BOOL bDestroy)
{
if (pImeDpi->hInst == NULL)
@ -115,6 +174,269 @@ Imm32NotifyAction(HIMC hIMC, HWND hwnd, DWORD dwAction, DWORD_PTR dwIndex, DWORD
return TRUE;
}
static PIMEDPI APIENTRY Imm32FindImeDpi(HKL hKL)
{
PIMEDPI pImeDpi;
RtlEnterCriticalSection(&g_csImeDpi);
for (pImeDpi = g_pImeDpiList; pImeDpi != NULL; pImeDpi = pImeDpi->pNext)
{
if (pImeDpi->hKL == hKL)
break;
}
RtlLeaveCriticalSection(&g_csImeDpi);
return pImeDpi;
}
static BOOL Imm32GetSystemLibraryPath(LPWSTR pszPath, DWORD cchPath, LPCWSTR pszFileName)
{
if (!pszFileName[0] || !GetSystemDirectoryW(pszPath, cchPath))
return FALSE;
StringCchCatW(pszPath, cchPath, L"\\");
StringCchCatW(pszPath, cchPath, pszFileName);
return TRUE;
}
DWORD APIENTRY Imm32SetImeOwnerWindow(PIMEINFOEX pImeInfoEx, BOOL fFlag)
{
return NtUserSetImeOwnerWindow(pImeInfoEx, fFlag);
}
static BOOL APIENTRY Imm32InquireIme(PIMEDPI pImeDpi)
{
WCHAR szUIClass[64];
WNDCLASSW wcW;
DWORD dwSysInfoFlags = 0; // TODO: ???
LPIMEINFO pImeInfo = &pImeDpi->ImeInfo;
// TODO: Imm32GetThreadState(THREADSTATE_UNKNOWN16);
if (!IS_IME_HKL(pImeDpi->hKL))
{
if (g_psi && (g_psi->dwSRVIFlags & SRVINFO_CICERO_ENABLED) &&
pImeDpi->CtfImeInquireExW)
{
// TODO:
return FALSE;
}
}
if (!pImeDpi->ImeInquire(pImeInfo, szUIClass, dwSysInfoFlags))
return FALSE;
szUIClass[_countof(szUIClass) - 1] = 0;
if (pImeInfo->dwPrivateDataSize == 0)
pImeInfo->dwPrivateDataSize = 4;
#define VALID_IME_PROP (IME_PROP_AT_CARET | \
IME_PROP_SPECIAL_UI | \
IME_PROP_CANDLIST_START_FROM_1 | \
IME_PROP_UNICODE | \
IME_PROP_COMPLETE_ON_UNSELECT | \
IME_PROP_END_UNLOAD | \
IME_PROP_KBD_CHAR_FIRST | \
IME_PROP_IGNORE_UPKEYS | \
IME_PROP_NEED_ALTKEY | \
IME_PROP_NO_KEYS_ON_CLOSE | \
IME_PROP_ACCEPT_WIDE_VKEY)
#define VALID_CMODE_CAPS (IME_CMODE_ALPHANUMERIC | \
IME_CMODE_NATIVE | \
IME_CMODE_KATAKANA | \
IME_CMODE_LANGUAGE | \
IME_CMODE_FULLSHAPE | \
IME_CMODE_ROMAN | \
IME_CMODE_CHARCODE | \
IME_CMODE_HANJACONVERT | \
IME_CMODE_SOFTKBD | \
IME_CMODE_NOCONVERSION | \
IME_CMODE_EUDC | \
IME_CMODE_SYMBOL | \
IME_CMODE_FIXED)
#define VALID_SMODE_CAPS (IME_SMODE_NONE | \
IME_SMODE_PLAURALCLAUSE | \
IME_SMODE_SINGLECONVERT | \
IME_SMODE_AUTOMATIC | \
IME_SMODE_PHRASEPREDICT | \
IME_SMODE_CONVERSATION)
#define VALID_UI_CAPS (UI_CAP_2700 | \
UI_CAP_ROT90 | \
UI_CAP_ROTANY | \
UI_CAP_SOFTKBD)
#define VALID_SCS_CAPS (SCS_CAP_COMPSTR | \
SCS_CAP_MAKEREAD | \
SCS_CAP_SETRECONVERTSTRING)
#define VALID_SELECT_CAPS (SELECT_CAP_CONVERSION | SELECT_CAP_SENTENCE)
if (pImeInfo->fdwProperty & ~VALID_IME_PROP)
return FALSE;
if (pImeInfo->fdwConversionCaps & ~VALID_CMODE_CAPS)
return FALSE;
if (pImeInfo->fdwSentenceCaps & ~VALID_SMODE_CAPS)
return FALSE;
if (pImeInfo->fdwUICaps & ~VALID_UI_CAPS)
return FALSE;
if (pImeInfo->fdwSCSCaps & ~VALID_SCS_CAPS)
return FALSE;
if (pImeInfo->fdwSelectCaps & ~VALID_SELECT_CAPS)
return FALSE;
#undef VALID_IME_PROP
#undef VALID_CMODE_CAPS
#undef VALID_SMODE_CAPS
#undef VALID_UI_CAPS
#undef VALID_SCS_CAPS
#undef VALID_SELECT_CAPS
if (pImeInfo->fdwProperty & IME_PROP_UNICODE)
{
StringCchCopyW(pImeDpi->szUIClass, _countof(pImeDpi->szUIClass), szUIClass);
}
else
{
if (pImeDpi->uCodePage != GetACP() && pImeDpi->uCodePage)
return FALSE;
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, (LPSTR)szUIClass, -1,
pImeDpi->szUIClass, _countof(pImeDpi->szUIClass));
}
return GetClassInfoW(pImeDpi->hInst, pImeDpi->szUIClass, &wcW);
}
static BOOL APIENTRY Imm32LoadImeInfo(PIMEINFOEX pImeInfoEx, PIMEDPI pImeDpi)
{
WCHAR szPath[MAX_PATH];
HINSTANCE hIME;
FARPROC fn;
if (!Imm32GetSystemLibraryPath(szPath, _countof(szPath), pImeInfoEx->wszImeFile))
return FALSE;
hIME = GetModuleHandleW(szPath);
if (hIME == NULL)
{
hIME = LoadLibraryW(szPath);
if (hIME == NULL)
{
ERR("Imm32LoadImeInfo: LoadLibraryW(%S) failed\n", szPath);
return FALSE;
}
}
pImeDpi->hInst = hIME;
#define DEFINE_IME_ENTRY(type, name, params, extended) \
do { \
fn = GetProcAddress(hIME, #name); \
if (fn) pImeDpi->name = (FN_##name)fn; \
else if (!extended) goto Failed; \
} while (0);
#include "../../../win32ss/include/imetable.h"
#undef DEFINE_IME_ENTRY
if (!Imm32InquireIme(pImeDpi))
{
ERR("Imm32LoadImeInfo: Imm32InquireIme failed\n");
goto Failed;
}
if (pImeInfoEx->fLoadFlag)
return TRUE;
Imm32SetImeOwnerWindow(pImeInfoEx, TRUE);
return TRUE;
Failed:
FreeLibrary(pImeDpi->hInst);
pImeDpi->hInst = NULL;
return FALSE;
}
static PIMEDPI APIENTRY Ime32LoadImeDpi(HKL hKL, BOOL bLock)
{
IMEINFOEX ImeInfoEx;
CHARSETINFO ci;
PIMEDPI pImeDpiNew, pImeDpiFound;
UINT uCodePage;
LCID lcid;
if (!ImmGetImeInfoEx(&ImeInfoEx, ImeInfoExKeyboardLayout, &hKL) ||
ImeInfoEx.fLoadFlag == 1)
{
return NULL;
}
pImeDpiNew = Imm32HeapAlloc(HEAP_ZERO_MEMORY, sizeof(IMEDPI));
if (pImeDpiNew == NULL)
return NULL;
pImeDpiNew->hKL = hKL;
lcid = LOWORD(hKL);
if (TranslateCharsetInfo((LPDWORD)(DWORD_PTR)lcid, &ci, TCI_SRCLOCALE))
uCodePage = ci.ciACP;
else
uCodePage = CP_ACP;
pImeDpiNew->uCodePage = uCodePage;
if (!Imm32LoadImeInfo(&ImeInfoEx, pImeDpiNew))
{
HeapFree(g_hImm32Heap, 0, pImeDpiNew);
return FALSE;
}
RtlEnterCriticalSection(&g_csImeDpi);
pImeDpiFound = Imm32FindImeDpi(hKL);
if (pImeDpiFound)
{
if (!bLock)
pImeDpiFound->dwFlags &= ~IMEDPI_FLAG_LOCKED;
RtlLeaveCriticalSection(&g_csImeDpi);
Imm32FreeImeDpi(pImeDpiNew, FALSE);
HeapFree(g_hImm32Heap, 0, pImeDpiNew);
return pImeDpiFound;
}
else
{
if (bLock)
{
pImeDpiNew->dwFlags |= IMEDPI_FLAG_LOCKED;
pImeDpiNew->cLockObj = 1;
}
pImeDpiNew->pNext = g_pImeDpiList;
g_pImeDpiList = pImeDpiNew;
RtlLeaveCriticalSection(&g_csImeDpi);
return pImeDpiNew;
}
}
BOOL WINAPI ImmLoadIME(HKL hKL)
{
PW32CLIENTINFO pInfo;
PIMEDPI pImeDpi;
if (!IS_IME_HKL(hKL))
{
if (!g_psi || !(g_psi->dwSRVIFlags & SRVINFO_CICERO_ENABLED))
return FALSE;
pInfo = (PW32CLIENTINFO)(NtCurrentTeb()->Win32ClientInfo);
if ((pInfo->W32ClientInfo[0] & 2))
return FALSE;
}
pImeDpi = Imm32FindImeDpi(hKL);
if (pImeDpi == NULL)
pImeDpi = Ime32LoadImeDpi(hKL, FALSE);
return (pImeDpi != NULL);
}
HKL WINAPI ImmLoadLayout(HKL hKL, PIMEINFOEX pImeInfoEx)
{
DWORD cbData;
@ -127,7 +449,7 @@ HKL WINAPI ImmLoadLayout(HKL hKL, PIMEINFOEX pImeInfoEx)
TRACE("ImmLoadLayout(%p, %p)\n", hKL, pImeInfoEx);
if (IS_IME_HKL(hKL) ||
!g_psi || (g_psi->dwSRVIFlags & SRVINFO_METRICS) == 0 ||
!g_psi || !(g_psi->dwSRVIFlags & SRVINFO_CICERO_ENABLED) ||
((PW32CLIENTINFO)NtCurrentTeb()->Win32ClientInfo)->W32ClientInfo[0] & 2)
{
UnicodeString.Buffer = szLayout;
@ -256,7 +578,6 @@ static inline BOOL is_kbd_ime_unicode(const ImmHkl *hkl)
return !!(hkl->imeInfo.fdwProperty & IME_PROP_UNICODE);
}
static BOOL IMM_DestroyContext(HIMC hIMC);
static InputContextData* get_imc_data(HIMC hIMC);
static inline WCHAR *strdupAtoW( const char *str )
@ -393,36 +714,6 @@ static IMMThreadData *IMM_GetThreadData(HWND hwnd, DWORD thread)
return data;
}
static BOOL IMM_IsDefaultContext(HIMC imc)
{
InputContextData *data = get_imc_data(imc);
if (!data)
return FALSE;
return data->threadDefault;
}
static void IMM_FreeThreadData(void)
{
IMMThreadData *data;
EnterCriticalSection(&threaddata_cs);
LIST_FOR_EACH_ENTRY(data, &ImmThreadDataList, IMMThreadData, entry)
{
if (data->threadID == GetCurrentThreadId())
{
list_remove(&data->entry);
LeaveCriticalSection(&threaddata_cs);
IMM_DestroyContext(data->defaultContext);
HeapFree(GetProcessHeap(),0,data);
TRACE("Thread Data Destroyed\n");
return;
}
}
LeaveCriticalSection(&threaddata_cs);
}
static HMODULE load_graphics_driver(void)
{
static const WCHAR display_device_guid_propW[] = {
@ -531,49 +822,6 @@ HWND WINAPI __wine_get_ui_window(HKL hkl)
return immHkl->UIWnd;
}
static void IMM_FreeAllImmHkl(void)
{
ImmHkl *ptr,*cursor2;
LIST_FOR_EACH_ENTRY_SAFE(ptr, cursor2, &ImmHklList, ImmHkl, entry)
{
list_remove(&ptr->entry);
if (ptr->hIME)
{
ptr->pImeDestroy(1);
FreeLibrary(ptr->hIME);
}
if (ptr->UIWnd)
DestroyWindow(ptr->UIWnd);
HeapFree(GetProcessHeap(),0,ptr);
}
}
BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved)
{
TRACE("%p, %x, %p\n",hInstDLL,fdwReason,lpReserved);
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
if (!User32InitializeImmEntryTable(IMM_INIT_MAGIC))
{
return FALSE;
}
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
IMM_FreeThreadData();
break;
case DLL_PROCESS_DETACH:
if (lpReserved) break;
IMM_FreeThreadData();
IMM_FreeAllImmHkl();
break;
}
return TRUE;
}
/* for posting messages as the IME */
static void ImmInternalPostIMEMessage(InputContextData *data, UINT msg, WPARAM wParam, LPARAM lParam)
{
@ -607,18 +855,6 @@ static LRESULT ImmInternalSendIMENotify(InputContextData *data, WPARAM notify, L
return 0;
}
static HIMCC ImmCreateBlankCompStr(void)
{
HIMCC rc;
LPCOMPOSITIONSTRING ptr;
rc = ImmCreateIMCC(sizeof(COMPOSITIONSTRING));
ptr = ImmLockIMCC(rc);
memset(ptr,0,sizeof(COMPOSITIONSTRING));
ptr->dwSize = sizeof(COMPOSITIONSTRING);
ImmUnlockIMCC(rc);
return rc;
}
static InputContextData* get_imc_data(HIMC hIMC)
{
InputContextData *data = hIMC;
@ -636,43 +872,8 @@ static InputContextData* get_imc_data(HIMC hIMC)
static HIMC get_default_context( HWND hwnd )
{
HIMC ret;
IMMThreadData* thread_data = IMM_GetThreadData( hwnd, 0 );
if (!thread_data) return 0;
if (thread_data->defaultContext)
{
ret = thread_data->defaultContext;
LeaveCriticalSection(&threaddata_cs);
return ret;
}
/* can't create a default context in another thread */
if (thread_data->threadID != GetCurrentThreadId())
{
LeaveCriticalSection(&threaddata_cs);
return 0;
}
LeaveCriticalSection(&threaddata_cs);
ret = ImmCreateContext();
if (!ret) return 0;
((InputContextData*)ret)->threadDefault = TRUE;
/* thread_data is in the current thread so we can assume it's still valid */
EnterCriticalSection(&threaddata_cs);
if (thread_data->defaultContext) /* someone beat us */
{
IMM_DestroyContext( ret );
ret = thread_data->defaultContext;
}
else thread_data->defaultContext = ret;
LeaveCriticalSection(&threaddata_cs);
return ret;
FIXME("Don't use this function\n");
return FALSE;
}
static BOOL IMM_IsCrossThreadAccess(HWND hWnd, HIMC hIMC)
@ -873,83 +1074,106 @@ BOOL WINAPI ImmConfigureIMEW(
*/
HIMC WINAPI ImmCreateContext(void)
{
InputContextData *new_context;
LPGUIDELINE gl;
LPCANDIDATEINFO ci;
int i;
PCLIENTIMC pClientImc;
HIMC hIMC;
new_context = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(InputContextData));
TRACE("ImmCreateContext()\n");
/* Load the IME */
new_context->immKbd = IMM_GetImmHkl(GetKeyboardLayout(0));
if (g_psi == NULL || !(g_psi->dwSRVIFlags & SRVINFO_IMM32))
return NULL;
if (!new_context->immKbd->hIME)
pClientImc = Imm32HeapAlloc(HEAP_ZERO_MEMORY, sizeof(CLIENTIMC));
if (pClientImc == NULL)
return NULL;
hIMC = Imm32CreateInputContext(pClientImc);
if (hIMC == NULL)
{
TRACE("IME dll could not be loaded\n");
HeapFree(GetProcessHeap(),0,new_context);
return 0;
HeapFree(g_hImm32Heap, 0, pClientImc);
return NULL;
}
/* the HIMCCs are never NULL */
new_context->IMC.hCompStr = ImmCreateBlankCompStr();
new_context->IMC.hMsgBuf = ImmCreateIMCC(0);
new_context->IMC.hCandInfo = ImmCreateIMCC(sizeof(CANDIDATEINFO));
ci = ImmLockIMCC(new_context->IMC.hCandInfo);
memset(ci,0,sizeof(CANDIDATEINFO));
ci->dwSize = sizeof(CANDIDATEINFO);
ImmUnlockIMCC(new_context->IMC.hCandInfo);
new_context->IMC.hGuideLine = ImmCreateIMCC(sizeof(GUIDELINE));
gl = ImmLockIMCC(new_context->IMC.hGuideLine);
memset(gl,0,sizeof(GUIDELINE));
gl->dwSize = sizeof(GUIDELINE);
ImmUnlockIMCC(new_context->IMC.hGuideLine);
for (i = 0; i < ARRAY_SIZE(new_context->IMC.cfCandForm); i++)
new_context->IMC.cfCandForm[i].dwIndex = ~0u;
/* Initialize the IME Private */
new_context->IMC.hPrivate = ImmCreateIMCC(new_context->immKbd->imeInfo.dwPrivateDataSize);
new_context->IMC.fdwConversion = new_context->immKbd->imeInfo.fdwConversionCaps;
new_context->IMC.fdwSentence = new_context->immKbd->imeInfo.fdwSentenceCaps;
if (!new_context->immKbd->pImeSelect(new_context, TRUE))
{
TRACE("Selection of IME failed\n");
IMM_DestroyContext(new_context);
return 0;
}
new_context->threadID = GetCurrentThreadId();
SendMessageW(GetFocus(), WM_IME_SELECT, TRUE, (LPARAM)new_context->immKbd);
new_context->immKbd->uSelected++;
TRACE("Created context %p\n",new_context);
new_context->magic = WINE_IMC_VALID_MAGIC;
return new_context;
RtlInitializeCriticalSection(&pClientImc->cs);
pClientImc->unknown = Imm32GetThreadState(THREADSTATE_UNKNOWN13);
return hIMC;
}
static BOOL IMM_DestroyContext(HIMC hIMC)
static VOID APIENTRY Imm32CleanupContextExtra(LPINPUTCONTEXT pIC)
{
InputContextData *data = get_imc_data(hIMC);
FIXME("We have to do something do here");
}
TRACE("Destroying %p\n",hIMC);
static PCLIENTIMC APIENTRY Imm32FindClientImc(HIMC hIMC)
{
// FIXME
return NULL;
}
if (!data)
BOOL APIENTRY Imm32CleanupContext(HIMC hIMC, HKL hKL, BOOL bKeep)
{
PIMEDPI pImeDpi;
LPINPUTCONTEXT pIC;
PCLIENTIMC pClientImc;
if (g_psi == NULL || !(g_psi->dwSRVIFlags & SRVINFO_IMM32) || hIMC == NULL)
return FALSE;
data->immKbd->uSelected --;
data->immKbd->pImeSelect(hIMC, FALSE);
SendMessageW(data->IMC.hWnd, WM_IME_SELECT, FALSE, (LPARAM)data->immKbd);
FIXME("We have do something to do here\n");
pClientImc = Imm32FindClientImc(hIMC);
if (!pClientImc)
return FALSE;
ImmDestroyIMCC(data->IMC.hCompStr);
ImmDestroyIMCC(data->IMC.hCandInfo);
ImmDestroyIMCC(data->IMC.hGuideLine);
ImmDestroyIMCC(data->IMC.hPrivate);
ImmDestroyIMCC(data->IMC.hMsgBuf);
if (pClientImc->hImc == NULL)
{
pClientImc->dwFlags |= CLIENTIMC_UNKNOWN1;
ImmUnlockClientImc(pClientImc);
if (!bKeep)
return Imm32DestroyInputContext(hIMC);
return TRUE;
}
data->magic = 0;
HeapFree(GetProcessHeap(),0,data);
pIC = ImmLockIMC(hIMC);
if (pIC == NULL)
{
ImmUnlockClientImc(pClientImc);
return FALSE;
}
FIXME("We have do something to do here\n");
if (pClientImc->hKL == hKL)
{
pImeDpi = ImmLockImeDpi(hKL);
if (pImeDpi != NULL)
{
if (IS_IME_HKL(hKL))
{
pImeDpi->ImeSelect(hIMC, FALSE);
}
else if (g_psi && (g_psi->dwSRVIFlags & SRVINFO_CICERO_ENABLED))
{
FIXME("We have do something to do here\n");
}
ImmUnlockImeDpi(pImeDpi);
}
pClientImc->hKL = NULL;
}
ImmDestroyIMCC(pIC->hPrivate);
ImmDestroyIMCC(pIC->hMsgBuf);
ImmDestroyIMCC(pIC->hGuideLine);
ImmDestroyIMCC(pIC->hCandInfo);
ImmDestroyIMCC(pIC->hCompStr);
Imm32CleanupContextExtra(pIC);
ImmUnlockIMC(hIMC);
pClientImc->dwFlags |= CLIENTIMC_UNKNOWN1;
ImmUnlockClientImc(pClientImc);
if (!bKeep)
return Imm32DestroyInputContext(hIMC);
return TRUE;
}
@ -959,10 +1183,21 @@ static BOOL IMM_DestroyContext(HIMC hIMC)
*/
BOOL WINAPI ImmDestroyContext(HIMC hIMC)
{
if (!IMM_IsDefaultContext(hIMC) && !IMM_IsCrossThreadAccess(NULL, hIMC))
return IMM_DestroyContext(hIMC);
else
DWORD dwImeThreadId, dwThreadId;
HKL hKL;
TRACE("ImmDestroyContext(%p)\n", hIMC);
if (g_psi == NULL || !(g_psi->dwSRVIFlags & SRVINFO_IMM32))
return FALSE;
dwImeThreadId = Imm32QueryInputContext(hIMC, 1);
dwThreadId = GetCurrentThreadId();
if (dwImeThreadId != dwThreadId)
return FALSE;
hKL = GetKeyboardLayout(0);
return Imm32CleanupContext(hIMC, hKL, FALSE);
}
/***********************************************************************
@ -1122,43 +1357,6 @@ LRESULT WINAPI ImmEscapeW(
return 0;
}
#define ROUNDUP4(n) (((n) + 3) & ~3) /* DWORD alignment */
HANDLE g_hImm32Heap = NULL;
DWORD g_dwImm32Flags = 0;
/* flags for g_dwImm32Flags */
#define IMM32_FLAG_UNKNOWN 0x4
#define IMM32_FLAG_CICERO_ENABLED 0x20
LPVOID APIENTRY Imm32HeapAlloc(DWORD dwFlags, DWORD dwBytes)
{
if (!g_hImm32Heap)
{
g_hImm32Heap = RtlGetProcessHeap();
if (g_hImm32Heap == NULL)
return NULL;
}
return HeapAlloc(g_hImm32Heap, dwFlags, dwBytes);
}
static DWORD_PTR APIENTRY
Imm32GetThreadState(DWORD Routine)
{
return NtUserGetThreadState(Routine);
}
static DWORD_PTR APIENTRY Imm32QueryWindow(HWND hWnd, DWORD Index)
{
return NtUserQueryWindow(hWnd, Index);
}
static DWORD APIENTRY
Imm32UpdateInputContext(HIMC hIMC, DWORD Unknown1, PCLIENTIMC pClientImc)
{
return NtUserUpdateInputContext(hIMC, Unknown1, pClientImc);
}
static PCLIENTIMC APIENTRY Imm32GetClientImcCache(void)
{
// FIXME: Do something properly here
@ -2501,7 +2699,7 @@ void WINAPI __wine_unregister_window(HWND hwnd)
*/
HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
{
if (!(g_dwImm32Flags & IMM32_FLAG_UNKNOWN))
if (!g_psi || !(g_psi->dwSRVIFlags & SRVINFO_IMM32))
return NULL;
if (hWnd == NULL)
@ -2515,7 +2713,7 @@ HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
*/
BOOL WINAPI CtfImmIsCiceroEnabled(VOID)
{
return !!(g_dwImm32Flags & IMM32_FLAG_CICERO_ENABLED);
return (g_psi && (g_psi->dwSRVIFlags & SRVINFO_CICERO_ENABLED));
}
/***********************************************************************
@ -3401,8 +3599,8 @@ VOID WINAPI ImmUnlockImeDpi(PIMEDPI pImeDpi)
if ((pImeDpi->dwFlags & IMEDPI_FLAG_UNKNOWN) == 0)
{
if ((pImeDpi->dwFlags & IMEDPI_FLAG_UNKNOWN2) == 0 ||
(pImeDpi->dwUnknown1 & 1) == 0)
if ((pImeDpi->dwFlags & IMEDPI_FLAG_LOCKED) == 0 ||
(pImeDpi->ImeInfo.fdwProperty & IME_PROP_END_UNLOAD) == 0)
{
RtlLeaveCriticalSection(&g_csImeDpi);
return;
@ -4110,11 +4308,11 @@ BOOL WINAPI ImmSetActiveContextConsoleIME(HWND hwnd, BOOL fFlag)
* ImmRegisterClient(IMM32.@)
* ( Undocumented, called from user32.dll )
*/
BOOL WINAPI ImmRegisterClient(PVOID ptr, /* FIXME: should point to SHAREDINFO structure */
HINSTANCE hMod)
BOOL WINAPI ImmRegisterClient(PSHAREDINFO ptr, HINSTANCE hMod)
{
FIXME("Stub\n");
return TRUE;
g_SharedInfo = *ptr;
g_psi = g_SharedInfo.psi;
return Imm32InitInstance(hMod);
}
/***********************************************************************
@ -4167,7 +4365,7 @@ ImmGetImeInfoEx(PIMEINFOEX pImeInfoEx,
if (!IS_IME_HKL(hKL))
{
if (g_dwImm32Flags & IMM32_FLAG_CICERO_ENABLED)
if (g_psi && (g_psi->dwSRVIFlags & SRVINFO_CICERO_ENABLED))
{
pTeb = NtCurrentTeb();
if (((PW32CLIENTINFO)pTeb->Win32ClientInfo)->W32ClientInfo[0] & 2)
@ -4181,3 +4379,53 @@ ImmGetImeInfoEx(PIMEINFOEX pImeInfoEx,
Quit:
return Imm32GetImeInfoEx(pImeInfoEx, SearchType);
}
BOOL WINAPI User32InitializeImmEntryTable(DWORD);
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
{
HKL hKL;
HWND hWnd;
PTEB pTeb;
TRACE("DllMain(%p, 0x%X, %p)\n", hinstDLL, fdwReason, lpReserved);
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
//Imm32GenerateRandomSeed(hinstDLL, 1, lpReserved); // Non-sense
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:
if (g_psi == NULL || !(g_psi->dwSRVIFlags & SRVINFO_IMM32))
return TRUE;
pTeb = NtCurrentTeb();
if (pTeb->Win32ThreadInfo == NULL)
return TRUE;
hKL = GetKeyboardLayout(0);
hWnd = (HWND)Imm32GetThreadState(THREADSTATE_CAPTUREWINDOW);
Imm32CleanupContext(hWnd, hKL, TRUE);
break;
case DLL_PROCESS_DETACH:
RtlDeleteCriticalSection(&g_csImeDpi);
break;
}
return TRUE;
}

View file

@ -68,7 +68,7 @@
@ stdcall ImmIsIME(long)
@ stdcall ImmIsUIMessageA(long long long long)
@ stdcall ImmIsUIMessageW(long long long long)
@ stdcall -stub ImmLoadIME(long)
@ stdcall ImmLoadIME(ptr)
@ stdcall ImmLoadLayout(ptr ptr)
@ stdcall ImmLockClientImc(ptr)
@ stdcall ImmLockIMC(ptr)

View file

@ -215,6 +215,7 @@ typedef struct tagCANDIDATEINFO {
#define IME_PROP_IGNORE_UPKEYS 0x0004
#define IME_PROP_NEED_ALTKEY 0x0008
#define IME_PROP_NO_KEYS_ON_CLOSE 0x0010
#define IME_PROP_ACCEPT_WIDE_VKEY 0x0020
/* for NI_CONTEXTUPDATED */
#define IMC_SETCONVERSIONMODE 0x0002
@ -381,7 +382,6 @@ DWORD WINAPI ImeGetImeMenuItems(HIMC, DWORD, DWORD, LPIMEMENUITEMINFOW, LPIMEMEN
#define IMEVER_0310 0x0003000A
#define IMEVER_0400 0x00040000
/* IME property bits */
#define IME_PROP_AT_CARET 0x00010000
#define IME_PROP_SPECIAL_UI 0x00020000
@ -389,17 +389,17 @@ DWORD WINAPI ImeGetImeMenuItems(HIMC, DWORD, DWORD, LPIMEMENUITEMINFOW, LPIMEMEN
#define IME_PROP_UNICODE 0x00080000
#define IME_PROP_COMPLETE_ON_UNSELECT 0x00100000
/* IME UICapability bits */
#define UI_CAP_2700 0x00000001
#define UI_CAP_ROT90 0x00000002
#define UI_CAP_ROTANY 0x00000004
#define UI_CAP_SOFTKBD 0x00010000
/* ImmSetCompositionString Capability bits */
#define SCS_CAP_COMPSTR 0x00000001
#define SCS_CAP_MAKEREAD 0x00000002
#define SCS_CAP_SETRECONVERTSTRING 0x00000004
/* IME WM_IME_SELECT inheritance Capability bits */
#define SELECT_CAP_CONVERSION 0x00000001
#define SELECT_CAP_SENTENCE 0x00000002

View file

@ -7,24 +7,6 @@
#pragma once
/* unconfirmed */
typedef struct tagCLIENTIMC
{
HIMC hImc;
LONG cLockObj;
DWORD dwFlags;
DWORD unknown;
RTL_CRITICAL_SECTION cs;
DWORD unknown2;
DWORD unknown3;
BOOL bUnknown4;
} CLIENTIMC, *PCLIENTIMC;
/* flags for CLIENTIMC */
#define CLIENTIMC_WIDE 0x1
#define CLIENTIMC_UNKNOWN1 0x40
#define CLIENTIMC_UNKNOWN2 0x100
#ifdef __cplusplus
extern "C" {
#endif

View file

@ -0,0 +1,22 @@
/* DEFINE_IME_ENTRY(type, name, params, extended) */
DEFINE_IME_ENTRY(BOOL, ImeInquire, (LPIMEINFO lpIMEInfo, LPWSTR lpszWndClass, DWORD dwSystemInfoFlags), FALSE)
DEFINE_IME_ENTRY(DWORD, ImeConversionList, (HIMC hIMC, LPCWSTR lpSrc, LPCANDIDATELIST lpDst, DWORD dwBufLen, UINT uFlag), FALSE)
DEFINE_IME_ENTRY(BOOL, ImeRegisterWord, (LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszString), FALSE)
DEFINE_IME_ENTRY(BOOL, ImeUnregisterWord, (LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszString), FALSE)
DEFINE_IME_ENTRY(UINT, ImeGetRegisterWordStyle, (UINT nItem, LPSTYLEBUFW lpStyleBuf), FALSE)
DEFINE_IME_ENTRY(UINT, ImeEnumRegisterWord, (HKL hKL, REGISTERWORDENUMPROCW lpfnEnumProc, LPCWSTR lpszReading, DWORD dwStyle, LPCWSTR lpszString, LPVOID lpData), FALSE)
DEFINE_IME_ENTRY(BOOL, ImeConfigure, (HKL hKL, HWND hWnd, DWORD dwMode, LPVOID lpData), FALSE)
DEFINE_IME_ENTRY(BOOL, ImeDestroy, (UINT uReserved), FALSE)
DEFINE_IME_ENTRY(LRESULT, ImeEscape, (HIMC hIMC, UINT uEscape, LPVOID lpData), FALSE)
DEFINE_IME_ENTRY(BOOL, ImeSelect, (HIMC hIMC, BOOL fSelect), FALSE)
DEFINE_IME_ENTRY(BOOL, ImeProcessKey, (HIMC hIMC, UINT uVirKey, DWORD lParam, CONST LPBYTE lpbKeyState), FALSE)
DEFINE_IME_ENTRY(BOOL, ImeSetActiveContext, (HIMC hIMC, BOOL fFlag), FALSE)
DEFINE_IME_ENTRY(UINT, ImeToAsciiEx, (UINT uVirKey, UINT uScanCode, CONST LPBYTE lpbKeyState, /*FIXME: LPTRANSMSGLIST*/ LPVOID lpTransMsgList, UINT fuState, HIMC hIMC), FALSE)
DEFINE_IME_ENTRY(BOOL, NotifyIME, (HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue), FALSE)
DEFINE_IME_ENTRY(BOOL, ImeSetCompositionString, (HIMC hIMC, DWORD dwIndex, LPCVOID lpComp, DWORD dwCompLen, LPCVOID lpRead, DWORD dwReadLen), FALSE)
DEFINE_IME_ENTRY(DWORD, ImeGetImeMenuItems, (HIMC hIMC, DWORD dwFlags, DWORD dwType, LPIMEMENUITEMINFOW lpImeParentMenu, LPIMEMENUITEMINFOW lpImeMenu, DWORD dwSize), FALSE)
DEFINE_IME_ENTRY(DWORD, CtfImeInquireExW, (VOID /* FIXME: unknown */), TRUE)
DEFINE_IME_ENTRY(DWORD, CtfImeSelectEx, (VOID /* FIXME: unknown */), TRUE)
DEFINE_IME_ENTRY(DWORD, CtfImeEscapeEx, (VOID /* FIXME: unknown */), TRUE)
DEFINE_IME_ENTRY(DWORD, CtfImeGetGuidAtom, (VOID /* FIXME: unknown */), TRUE)
DEFINE_IME_ENTRY(DWORD, CtfImeIsGuidMapEnable, (VOID /* FIXME: unknown */), TRUE)

View file

@ -912,7 +912,7 @@ typedef LONG_PTR
#define SRVINFO_DBCSENABLED 0x0002
#define SRVINFO_IMM32 0x0004
#define SRVINFO_APIHOOK 0x0010
#define SRVINFO_METRICS 0x0020
#define SRVINFO_CICERO_ENABLED 0x0020
#define SRVINFO_KBDPREF 0x0080
#define NUM_SYSCOLORS 31
@ -1212,42 +1212,88 @@ typedef struct _IMEWND
PIMEUI pimeui;
} IMEWND, *PIMEWND;
typedef BOOL (WINAPI *FN_ImeDestroy)(UINT uReserved);
typedef LRESULT (WINAPI *FN_ImeEscape)(HIMC hIMC, UINT uEscape, LPVOID lpData);
typedef BOOL (WINAPI *FN_NotifyIME)(HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue);
#define DEFINE_IME_ENTRY(type, name, params, extended) typedef type (WINAPI *FN_##name) params;
#include "imetable.h"
#undef DEFINE_IME_ENTRY
typedef struct IMEDPI /* unconfirmed */
typedef struct IMEDPI
{
struct IMEDPI *pNext;
HINSTANCE hInst;
HKL hKL;
DWORD dwUnknown0;
DWORD dwUnknown1;
DWORD dwUnknown2[14];
IMEINFO ImeInfo;
UINT uCodePage;
WCHAR szUIClass[16];
DWORD cLockObj;
DWORD dwFlags;
DWORD dwUnknown3[7];
FN_ImeDestroy ImeDestroy;
FN_ImeEscape ImeEscape;
DWORD dwUnknown4[4];
FN_NotifyIME NotifyIME;
/* ... */
#define DEFINE_IME_ENTRY(type, name, params, extended) FN_##name name;
#include "imetable.h"
#undef DEFINE_IME_ENTRY
} IMEDPI, *PIMEDPI;
#ifndef _WIN64
C_ASSERT(offsetof(IMEDPI, pNext) == 0x0);
C_ASSERT(offsetof(IMEDPI, hInst) == 0x4);
C_ASSERT(offsetof(IMEDPI, hKL) == 0x8);
C_ASSERT(offsetof(IMEDPI, ImeInfo) == 0xc);
C_ASSERT(offsetof(IMEDPI, uCodePage) == 0x28);
C_ASSERT(offsetof(IMEDPI, szUIClass) == 0x2c);
C_ASSERT(offsetof(IMEDPI, cLockObj) == 0x4c);
C_ASSERT(offsetof(IMEDPI, dwFlags) == 0x50);
C_ASSERT(offsetof(IMEDPI, ImeInquire) == 0x54);
C_ASSERT(offsetof(IMEDPI, ImeConversionList) == 0x58);
C_ASSERT(offsetof(IMEDPI, ImeRegisterWord) == 0x5c);
C_ASSERT(offsetof(IMEDPI, ImeUnregisterWord) == 0x60);
C_ASSERT(offsetof(IMEDPI, ImeGetRegisterWordStyle) == 0x64);
C_ASSERT(offsetof(IMEDPI, ImeEnumRegisterWord) == 0x68);
C_ASSERT(offsetof(IMEDPI, ImeConfigure) == 0x6c);
C_ASSERT(offsetof(IMEDPI, ImeDestroy) == 0x70);
C_ASSERT(offsetof(IMEDPI, ImeEscape) == 0x74);
C_ASSERT(offsetof(IMEDPI, ImeSelect) == 0x78);
C_ASSERT(offsetof(IMEDPI, ImeProcessKey) == 0x7c);
C_ASSERT(offsetof(IMEDPI, ImeSetActiveContext) == 0x80);
C_ASSERT(offsetof(IMEDPI, ImeToAsciiEx) == 0x84);
C_ASSERT(offsetof(IMEDPI, NotifyIME) == 0x88);
C_ASSERT(offsetof(IMEDPI, ImeSetCompositionString) == 0x8c);
C_ASSERT(offsetof(IMEDPI, ImeGetImeMenuItems) == 0x90);
C_ASSERT(offsetof(IMEDPI, CtfImeInquireExW) == 0x94);
C_ASSERT(offsetof(IMEDPI, CtfImeSelectEx) == 0x98);
C_ASSERT(offsetof(IMEDPI, CtfImeEscapeEx) == 0x9c);
C_ASSERT(offsetof(IMEDPI, CtfImeGetGuidAtom) == 0xa0);
C_ASSERT(offsetof(IMEDPI, CtfImeIsGuidMapEnable) == 0xa4);
C_ASSERT(sizeof(IMEDPI) == 0xa8);
#endif
/* flags for IMEDPI.dwFlags */
#define IMEDPI_FLAG_UNKNOWN 1
#define IMEDPI_FLAG_UNKNOWN2 2
#define IMEDPI_FLAG_UNKNOWN 0x1
#define IMEDPI_FLAG_LOCKED 0x2
/* unconfirmed */
typedef struct tagCLIENTIMC
{
HIMC hImc;
LONG cLockObj;
DWORD dwFlags;
DWORD unknown;
RTL_CRITICAL_SECTION cs;
DWORD unknown2;
HKL hKL;
BOOL bUnknown4;
} CLIENTIMC, *PCLIENTIMC;
#ifndef _WIN64
C_ASSERT(offsetof(CLIENTIMC, hImc) == 0x0);
C_ASSERT(offsetof(CLIENTIMC, cLockObj) == 0x4);
C_ASSERT(offsetof(CLIENTIMC, dwFlags) == 0x8);
C_ASSERT(offsetof(CLIENTIMC, cs) == 0x10);
C_ASSERT(offsetof(CLIENTIMC, hKL) == 0x2c);
C_ASSERT(sizeof(CLIENTIMC) == 0x34);
#endif
/* flags for CLIENTIMC */
#define CLIENTIMC_WIDE 0x1
#define CLIENTIMC_UNKNOWN1 0x40
#define CLIENTIMC_UNKNOWN2 0x100
DWORD
NTAPI
@ -1869,10 +1915,9 @@ NtUserCreateDesktop(
DWORD dwFlags,
ACCESS_MASK dwDesiredAccess);
DWORD
HIMC
NTAPI
NtUserCreateInputContext(
DWORD dwUnknown1);
NtUserCreateInputContext(PCLIENTIMC pClientImc);
NTSTATUS
NTAPI
@ -1964,10 +2009,9 @@ NtUserDestroyCursor(
_In_ HANDLE Handle,
_In_ BOOL bForce);
DWORD
BOOL
NTAPI
NtUserDestroyInputContext(
DWORD dwUnknown1);
NtUserDestroyInputContext(HIMC hIMC);
BOOLEAN
NTAPI
@ -3130,9 +3174,7 @@ NtUserSetImeInfoEx(
DWORD
NTAPI
NtUserSetImeOwnerWindow(
DWORD Unknown0,
DWORD Unknown1);
NtUserSetImeOwnerWindow(PIMEINFOEX pImeInfoEx, BOOL fFlag);
DWORD
NTAPI

View file

@ -133,11 +133,9 @@ NtUserSetImeInfoEx(
}
DWORD APIENTRY
NtUserSetImeOwnerWindow(DWORD Unknown0,
DWORD Unknown1)
NtUserSetImeOwnerWindow(PIMEINFOEX pImeInfoEx, BOOL fFlag)
{
STUB
return 0;
}

View file

@ -169,7 +169,7 @@ InitMetrics(VOID)
piSysMet[90] = 0;
#endif
gpsi->dwSRVIFlags |= SRVINFO_METRICS;
gpsi->dwSRVIFlags |= SRVINFO_CICERO_ENABLED;
Setup = TRUE;
return TRUE;

View file

@ -419,22 +419,20 @@ NtUserYieldTask(VOID)
return 0;
}
DWORD
HIMC
APIENTRY
NtUserCreateInputContext(
DWORD dwUnknown1)
NtUserCreateInputContext(PCLIENTIMC pClientImc)
{
STUB;
return 0;
return NULL;
}
DWORD
BOOL
APIENTRY
NtUserDestroyInputContext(
DWORD dwUnknown1)
NtUserDestroyInputContext(HIMC hIMC)
{
STUB;
return 0;
return FALSE;
}
DWORD