https://git.reactos.org/?p=reactos.git;a=commitdiff;h=b3382d8d24ac7f9e098ed7...
commit b3382d8d24ac7f9e098ed77ec1ce1f2f42d167a8 Author: Katayama Hirofumi MZ katayama.hirofumi.mz@gmail.com AuthorDate: Mon Sep 27 09:32:24 2021 +0900 Commit: GitHub noreply@github.com CommitDate: Mon Sep 27 09:32:24 2021 +0900
[IMM32] Rewrite ImmLockIMC (#3975)
- Add Imm32InitContext and Imm32LockIMCEx helper functions. - Re-implement ImmLockIMC function. - Modify CLIENTIMC and INPUTCONTEXTDX structures. CORE-11700 --- dll/win32/imm32/imm.c | 216 +++++++++++++++++++++++++--- dll/win32/imm32/utils.c | 8 +- modules/rostests/apitests/imm32/clientimc.c | 8 +- sdk/include/reactos/wine/ddk/imm.h | 10 +- win32ss/include/ntuser.h | 7 +- 5 files changed, 212 insertions(+), 37 deletions(-)
diff --git a/dll/win32/imm32/imm.c b/dll/win32/imm32/imm.c index 9fecb94c183..383a395f15e 100644 --- a/dll/win32/imm32/imm.c +++ b/dll/win32/imm32/imm.c @@ -354,7 +354,7 @@ BOOL APIENTRY Imm32CleanupContext(HIMC hIMC, HKL hKL, BOOL bKeep) if (!pClientImc) return FALSE;
- if (pClientImc->hImc == NULL) + if (pClientImc->hInputContext == NULL) { pClientImc->dwFlags |= CLIENTIMC_UNKNOWN1; ImmUnlockClientImc(pClientImc); @@ -390,11 +390,11 @@ BOOL APIENTRY Imm32CleanupContext(HIMC hIMC, HKL hKL, BOOL bKeep) pClientImc->hKL = NULL; }
- ImmDestroyIMCC(pIC->hPrivate); - ImmDestroyIMCC(pIC->hMsgBuf); - ImmDestroyIMCC(pIC->hGuideLine); - ImmDestroyIMCC(pIC->hCandInfo); - ImmDestroyIMCC(pIC->hCompStr); + 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);
Imm32CleanupContextExtra(pIC);
@@ -409,6 +409,182 @@ BOOL APIENTRY Imm32CleanupContext(HIMC hIMC, HKL hKL, BOOL bKeep) return TRUE; }
+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; +} + /*********************************************************************** * ImmDestroyContext (IMM32.@) */ @@ -481,7 +657,7 @@ PCLIENTIMC WINAPI ImmLockClientImc(HIMC hImc) VOID WINAPI ImmUnlockClientImc(PCLIENTIMC pClientImc) { LONG cLocks; - HIMC hImc; + HANDLE hInputContext;
TRACE("(%p)\n", pClientImc);
@@ -489,9 +665,9 @@ VOID WINAPI ImmUnlockClientImc(PCLIENTIMC pClientImc) if (cLocks != 0 || !(pClientImc->dwFlags & CLIENTIMC_UNKNOWN1)) return;
- hImc = pClientImc->hImc; - if (hImc) - LocalFree(hImc); + hInputContext = pClientImc->hInputContext; + if (hInputContext) + LocalFree(hInputContext);
RtlDeleteCriticalSection(&pClientImc->cs); Imm32HeapFree(pClientImc); @@ -925,16 +1101,14 @@ HKL WINAPI ImmInstallIMEW(LPCWSTR lpszIMEFileName, LPCWSTR lpszLayoutText) }
/*********************************************************************** -* ImmLockIMC(IMM32.@) -*/ + * ImmLockIMC(IMM32.@) + * + * NOTE: This is not ImmLockIMCC. Don't confuse. + */ LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC hIMC) { - InputContextData *data = get_imc_data(hIMC); - - if (!data) - return NULL; - data->dwLock++; - return &data->IMC; + TRACE("(%p)\n", hIMC); + return Imm32LockIMCEx(hIMC, TRUE); }
/*********************************************************************** @@ -943,15 +1117,13 @@ LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC hIMC) BOOL WINAPI ImmUnlockIMC(HIMC hIMC) { PCLIENTIMC pClientImc; - HIMC hClientImc;
pClientImc = ImmLockClientImc(hIMC); if (pClientImc == NULL) return FALSE;
- hClientImc = pClientImc->hImc; - if (hClientImc) - LocalUnlock(hClientImc); + if (pClientImc->hInputContext) + LocalUnlock(pClientImc->hInputContext);
InterlockedDecrement(&pClientImc->cLockObj); ImmUnlockClientImc(pClientImc); diff --git a/dll/win32/imm32/utils.c b/dll/win32/imm32/utils.c index 17a7efb5179..64bd3d158be 100644 --- a/dll/win32/imm32/utils.c +++ b/dll/win32/imm32/utils.c @@ -276,7 +276,7 @@ DWORD WINAPI ImmGetIMCCSize(HIMCC imcc) DWORD WINAPI ImmGetIMCLockCount(HIMC hIMC) { DWORD ret; - HIMC hClientImc; + HANDLE hInputContext; PCLIENTIMC pClientImc;
pClientImc = ImmLockClientImc(hIMC); @@ -284,9 +284,9 @@ DWORD WINAPI ImmGetIMCLockCount(HIMC hIMC) return 0;
ret = 0; - hClientImc = pClientImc->hImc; - if (hClientImc) - ret = (LocalFlags(hClientImc) & LMEM_LOCKCOUNT); + hInputContext = pClientImc->hInputContext; + if (hInputContext) + ret = (LocalFlags(hInputContext) & LMEM_LOCKCOUNT);
ImmUnlockClientImc(pClientImc); return ret; diff --git a/modules/rostests/apitests/imm32/clientimc.c b/modules/rostests/apitests/imm32/clientimc.c index 0f43024efd0..f0080c8112e 100644 --- a/modules/rostests/apitests/imm32/clientimc.c +++ b/modules/rostests/apitests/imm32/clientimc.c @@ -24,15 +24,15 @@ START_TEST(clientimc) DWORD dwCode; CLIENTIMC *pClientImc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CLIENTIMC));
- pClientImc->hImc = (HIMC)ImmCreateIMCC(4); + pClientImc->hInputContext = (HANDLE)ImmCreateIMCC(4); pClientImc->cLockObj = 2; pClientImc->dwFlags = 0x40; RtlInitializeCriticalSection(&pClientImc->cs); - ok_long(ImmGetIMCCSize((HIMCC)pClientImc->hImc), 4); + ok_long(ImmGetIMCCSize((HIMCC)pClientImc->hInputContext), 4);
ImmUnlockClientImc(pClientImc); ok_long(pClientImc->cLockObj, 1); - ok_long(ImmGetIMCCSize((HIMCC)pClientImc->hImc), 4); + ok_long(ImmGetIMCCSize((HIMCC)pClientImc->hInputContext), 4);
dwCode = 0; _SEH2_TRY @@ -47,7 +47,7 @@ START_TEST(clientimc) ok_long(dwCode, STATUS_ACCESS_VIOLATION);
ok_long(pClientImc->cLockObj, 0); - ok_long(ImmGetIMCCSize((HIMCC)pClientImc->hImc), 0); + ok_long(ImmGetIMCCSize((HIMCC)pClientImc->hInputContext), 0);
HeapFree(GetProcessHeap(), 0, pClientImc); } diff --git a/sdk/include/reactos/wine/ddk/imm.h b/sdk/include/reactos/wine/ddk/imm.h index f5b45fc6d1a..842c7cac015 100644 --- a/sdk/include/reactos/wine/ddk/imm.h +++ b/sdk/include/reactos/wine/ddk/imm.h @@ -92,17 +92,19 @@ typedef struct INPUTCONTEXTDX /* unconfirmed */ INPUTCONTEXT; UINT nVKey; BOOL bNeedsTrans; - DWORD dwUnknownCat; + DWORD dwUnknown1; DWORD dwUIFlags; - DWORD dwUnknownDog; - void *pUnknownFox; - /* ... */ + DWORD dwUnknown2; + void *pUnknown3; + DWORD dwUnknown4; + DWORD dwUnknown5; } INPUTCONTEXTDX, *LPINPUTCONTEXTDX;
#ifndef _WIN64 C_ASSERT(offsetof(INPUTCONTEXTDX, nVKey) == 0x140); C_ASSERT(offsetof(INPUTCONTEXTDX, bNeedsTrans) == 0x144); C_ASSERT(offsetof(INPUTCONTEXTDX, dwUIFlags) == 0x14c); +C_ASSERT(sizeof(INPUTCONTEXTDX) == 0x160); #endif
// bits of fdwInit of INPUTCONTEXT diff --git a/win32ss/include/ntuser.h b/win32ss/include/ntuser.h index 6d463ddb69a..482ea232926 100644 --- a/win32ss/include/ntuser.h +++ b/win32ss/include/ntuser.h @@ -1290,21 +1290,22 @@ C_ASSERT(sizeof(IMEDPI) == 0xa8); /* unconfirmed */ typedef struct tagCLIENTIMC { - HIMC hImc; + HANDLE hInputContext; /* LocalAlloc'ed LHND */ LONG cLockObj; DWORD dwFlags; DWORD unknown; RTL_CRITICAL_SECTION cs; - DWORD unknown2; + UINT uCodePage; HKL hKL; BOOL bUnknown4; } CLIENTIMC, *PCLIENTIMC;
#ifndef _WIN64 -C_ASSERT(offsetof(CLIENTIMC, hImc) == 0x0); +C_ASSERT(offsetof(CLIENTIMC, hInputContext) == 0x0); C_ASSERT(offsetof(CLIENTIMC, cLockObj) == 0x4); C_ASSERT(offsetof(CLIENTIMC, dwFlags) == 0x8); C_ASSERT(offsetof(CLIENTIMC, cs) == 0x10); +C_ASSERT(offsetof(CLIENTIMC, uCodePage) == 0x28); C_ASSERT(offsetof(CLIENTIMC, hKL) == 0x2c); C_ASSERT(sizeof(CLIENTIMC) == 0x34); #endif