[IMM32] Rewrite ImmGetContext (#3923)

- Add ValidateHwndNoErr and Imm32GetContextEx helper functions.
- Rewrite ImmGetContext function by using the helper functions.
CORE-11700
This commit is contained in:
Katayama Hirofumi MZ 2021-08-24 06:50:39 +09:00 committed by GitHub
parent 2ab858c125
commit a8d2cd4b9d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 78 additions and 34 deletions

View file

@ -61,6 +61,32 @@ SHAREDINFO g_SharedInfo = { NULL };
BYTE g_bClientRegd = FALSE;
HANDLE g_hImm32Heap = NULL;
static PWND FASTCALL ValidateHwndNoErr(HWND hwnd)
{
PCLIENTINFO ClientInfo = GetWin32ClientInfo();
INT index;
PUSER_HANDLE_TABLE ht;
WORD generation;
/* See if the window is cached */
if (hwnd == ClientInfo->CallbackWnd.hWnd)
return ClientInfo->CallbackWnd.pWnd;
if (!NtUserValidateHandleSecure(hwnd))
return NULL;
ht = g_SharedInfo.aheList; /* handle table */
index = (LOWORD(hwnd) - FIRST_USER_HANDLE) >> 1;
if (index < 0 || index >= ht->nb_handles || ht->handles[index].type != TYPE_WINDOW)
return NULL;
generation = HIWORD(hwnd);
if (generation != ht->handles[index].generation && generation && generation != 0xFFFF)
return NULL;
return (PWND)&ht->handles[index];
}
static BOOL APIENTRY Imm32InitInstance(HMODULE hMod)
{
NTSTATUS status;
@ -120,6 +146,12 @@ static inline BOOL Imm32IsCrossThreadAccess(HIMC hIMC)
return (dwImeThreadId != dwThreadId);
}
static BOOL Imm32IsCrossProcessAccess(HWND hWnd)
{
return (NtUserQueryWindow(hWnd, QUERY_WINDOW_UNIQUE_PROCESS_ID) !=
(DWORD_PTR)NtCurrentTeb()->ClientId.UniqueProcess);
}
static VOID APIENTRY Imm32FreeImeDpi(PIMEDPI pImeDpi, BOOL bDestroy)
{
if (pImeDpi->hInst == NULL)
@ -1862,6 +1894,40 @@ VOID WINAPI ImmUnlockClientImc(PCLIENTIMC pClientImc)
HeapFree(g_hImm32Heap, 0, pClientImc);
}
static HIMC APIENTRY Imm32GetContextEx(HWND hWnd, DWORD dwContextFlags)
{
HIMC hIMC;
PCLIENTIMC pClientImc;
PWND pWnd;
if (!g_psi || !(g_psi->dwSRVIFlags & SRVINFO_IMM32))
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;
}
static DWORD APIENTRY
CandidateListWideToAnsi(const CANDIDATELIST *pWideCL, LPCANDIDATELIST pAnsiCL, DWORD dwBufLen,
UINT uCodePage)
@ -2647,31 +2713,10 @@ BOOL WINAPI ImmGetCompositionWindow(HIMC hIMC, LPCOMPOSITIONFORM lpCompForm)
*/
HIMC WINAPI ImmGetContext(HWND hWnd)
{
HIMC rc;
TRACE("%p\n", hWnd);
if (!IsWindow(hWnd))
{
SetLastError(ERROR_INVALID_WINDOW_HANDLE);
TRACE("(%p)\n", hWnd);
if (hWnd == NULL)
return NULL;
}
rc = GetPropW(hWnd,szwWineIMCProperty);
if (rc == (HIMC)-1)
rc = NULL;
else if (rc == NULL)
rc = get_default_context( hWnd );
if (rc)
{
InputContextData *data = (InputContextData *)rc;
data->IMC.hWnd = hWnd;
}
TRACE("returning %p\n", rc);
return rc;
return Imm32GetContextEx(hWnd, 2);
}
/***********************************************************************
@ -2855,7 +2900,7 @@ UINT WINAPI ImmGetDescriptionA(
lpszDescription, uBufLen, NULL, NULL);
if (uBufLen)
lpszDescription[cch] = 0;
return cch;
return (UINT)cch;
}
/***********************************************************************
@ -3632,13 +3677,10 @@ Quit:
*/
BOOL WINAPI ImmReleaseContext(HWND hWnd, HIMC hIMC)
{
static BOOL shown = FALSE;
if (!shown) {
FIXME("(%p, %p): stub\n", hWnd, hIMC);
shown = TRUE;
}
return TRUE;
TRACE("(%p, %p)\n", hWnd, hIMC);
UNREFERENCED_PARAMETER(hWnd);
UNREFERENCED_PARAMETER(hIMC);
return TRUE; // Do nothing. This is correct.
}
/***********************************************************************
@ -3698,7 +3740,7 @@ BOOL WINAPI ImmSetCandidateWindow(
ImmUnlockIMC(hIMC);
Imm32NotifyAction(hIMC, hWnd, NI_CONTEXTUPDATED, 0, IMC_SETCANDIDATEPOS,
IMN_SETCANDIDATEPOS, (1 << lpCandidate->dwIndex));
IMN_SETCANDIDATEPOS, (1 << (BYTE)lpCandidate->dwIndex));
return TRUE;
}
@ -3721,7 +3763,7 @@ static VOID APIENTRY AnsiToWideLogFont(const LOGFONTA *plfA, LPLOGFONTW plfW)
RtlCopyMemory(plfW, plfA, offsetof(LOGFONTW, lfFaceName));
StringCchLengthA(plfA->lfFaceName, _countof(plfA->lfFaceName), &cchA);
cchW = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, plfA->lfFaceName, (INT)cchA,
plfW->lfFaceName, cchW);
plfW->lfFaceName, (INT)cchW);
if (cchW > _countof(plfW->lfFaceName) - 1)
cchW = _countof(plfW->lfFaceName) - 1;
plfW->lfFaceName[cchW] = 0;
@ -5106,6 +5148,7 @@ Quit:
UINT WINAPI ImmWINNLSGetIMEHotkey(HWND hwndIme)
{
TRACE("(%p)\n", hwndIme);
UNREFERENCED_PARAMETER(hwndIme);
return 0; /* This is correct. This function of Windows just returns zero. */
}

View file

@ -1311,6 +1311,7 @@ C_ASSERT(sizeof(CLIENTIMC) == 0x34);
/* flags for CLIENTIMC */
#define CLIENTIMC_WIDE 0x1
#define CLIENTIMC_UNKNOWN1 0x40
#define CLIENTIMC_UNKNOWN3 0x80
#define CLIENTIMC_UNKNOWN2 0x100
DWORD