https://git.reactos.org/?p=reactos.git;a=commitdiff;h=ecb0c0963d19ecb3cc465…
commit ecb0c0963d19ecb3cc46582500dddbbb452ce36b
Author: Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com>
AuthorDate: Sun Jul 25 11:57:57 2021 +0900
Commit: GitHub <noreply(a)github.com>
CommitDate: Sun Jul 25 11:57:57 2021 +0900
[IMM32] Imm(Lock|Unlock)ImeDpi and ImmSetOpenStatus (#3830)
- Add IMEDPI structure to ntuser.h.
- Implement ImmLockImeDpi/ImmUnlockImeDpi functions.
- Rewrite ImmSetOpenStatus function.
- Modify some NTUSER function prototypes.
- Modify imm32.spec.
CORE-11700
---
dll/win32/imm32/imm.c | 172 +++++++++++++++++++++++++++++++++-----
dll/win32/imm32/imm32.spec | 4 +-
sdk/include/reactos/imm32_undoc.h | 2 +
win32ss/include/ntuser.h | 42 +++++++++-
win32ss/user/ntuser/ime.c | 11 ++-
win32ss/user/ntuser/ntstubs.c | 4 +-
6 files changed, 202 insertions(+), 33 deletions(-)
diff --git a/dll/win32/imm32/imm.c b/dll/win32/imm32/imm.c
index 53c13d27d9f..66c740a925f 100644
--- a/dll/win32/imm32/imm.c
+++ b/dll/win32/imm32/imm.c
@@ -48,8 +48,63 @@ WINE_DEFAULT_DEBUG_CHANNEL(imm);
#define IMM_INIT_MAGIC 0x19650412
#define IMM_INVALID_CANDFORM ULONG_MAX
+RTL_CRITICAL_SECTION g_csImeDpi;
+PIMEDPI g_pImeDpiList = NULL;
+
BOOL WINAPI User32InitializeImmEntryTable(DWORD);
+static DWORD APIENTRY Imm32QueryInputContext(HIMC hIMC, DWORD dwUnknown2)
+{
+ return NtUserQueryInputContext(hIMC, dwUnknown2);
+}
+
+static DWORD APIENTRY Imm32NotifyIMEStatus(HWND hwnd, HIMC hIMC, DWORD dwConversion)
+{
+ return NtUserNotifyIMEStatus(hwnd, hIMC, dwConversion);
+}
+
+static VOID APIENTRY Imm32FreeImeDpi(PIMEDPI pImeDpi, BOOL bDestroy)
+{
+ if (pImeDpi->hInst == NULL)
+ return;
+ if (bDestroy)
+ pImeDpi->ImeDestroy(0);
+ FreeLibrary(pImeDpi->hInst);
+ pImeDpi->hInst = NULL;
+}
+
+static BOOL APIENTRY
+Imm32NotifyAction(HIMC hIMC, HWND hwnd, DWORD dwAction, DWORD_PTR dwIndex, DWORD_PTR
dwValue,
+ DWORD_PTR dwCommand, DWORD_PTR dwData)
+{
+ DWORD dwLayout;
+ HKL hKL;
+ PIMEDPI pImeDpi;
+
+ if (dwAction)
+ {
+ dwLayout = Imm32QueryInputContext(hIMC, 1);
+ if (dwLayout)
+ {
+ /* find keyboard layout and lock it */
+ hKL = GetKeyboardLayout(dwLayout);
+ pImeDpi = ImmLockImeDpi(hKL);
+ if (pImeDpi)
+ {
+ /* do notify */
+ pImeDpi->NotifyIME(hIMC, dwAction, dwIndex, dwValue);
+
+ ImmUnlockImeDpi(pImeDpi); /* unlock */
+ }
+ }
+ }
+
+ if (hwnd && dwCommand)
+ SendMessageW(hwnd, WM_IME_NOTIFY, dwCommand, dwData);
+
+ return TRUE;
+}
+
typedef struct _tagImmHkl{
struct list entry;
HKL hkl;
@@ -2951,40 +3006,119 @@ BOOL WINAPI ImmSetConversionStatus(
return TRUE;
}
+/***********************************************************************
+ * ImmLockImeDpi (IMM32.@)
+ */
+PIMEDPI WINAPI ImmLockImeDpi(HKL hKL)
+{
+ PIMEDPI pImeDpi = NULL;
+
+ TRACE("ImmLockImeDpi(%p)\n", hKL);
+
+ RtlEnterCriticalSection(&g_csImeDpi);
+
+ /* Find by hKL */
+ for (pImeDpi = g_pImeDpiList; pImeDpi; pImeDpi = pImeDpi->pNext)
+ {
+ if (pImeDpi->hKL == hKL) /* found */
+ {
+ /* lock if possible */
+ if (pImeDpi->dwFlags & IMEDPI_FLAG_UNKNOWN)
+ pImeDpi = NULL;
+ else
+ ++(pImeDpi->cLockObj);
+ break;
+ }
+ }
+
+ RtlLeaveCriticalSection(&g_csImeDpi);
+ return pImeDpi;
+}
+
+/***********************************************************************
+ * ImmUnlockImeDpi (IMM32.@)
+ */
+VOID WINAPI ImmUnlockImeDpi(PIMEDPI pImeDpi)
+{
+ PIMEDPI *ppEntry;
+
+ TRACE("ImmUnlockImeDpi(%p)\n", pImeDpi);
+
+ if (pImeDpi == NULL)
+ return;
+
+ RtlEnterCriticalSection(&g_csImeDpi);
+
+ /* unlock */
+ --(pImeDpi->cLockObj);
+ if (pImeDpi->cLockObj != 0)
+ {
+ RtlLeaveCriticalSection(&g_csImeDpi);
+ return;
+ }
+
+ if ((pImeDpi->dwFlags & IMEDPI_FLAG_UNKNOWN) == 0)
+ {
+ if ((pImeDpi->dwFlags & IMEDPI_FLAG_UNKNOWN2) == 0 ||
+ (pImeDpi->dwUnknown1 & 1) == 0)
+ {
+ RtlLeaveCriticalSection(&g_csImeDpi);
+ return;
+ }
+ }
+
+ /* Remove from list */
+ for (ppEntry = &g_pImeDpiList; *ppEntry; ppEntry = &((*ppEntry)->pNext))
+ {
+ if (*ppEntry == pImeDpi) /* found */
+ {
+ *ppEntry = pImeDpi->pNext;
+ break;
+ }
+ }
+
+ Imm32FreeImeDpi(pImeDpi, TRUE);
+ HeapFree(g_hImm32Heap, 0, pImeDpi);
+
+ RtlLeaveCriticalSection(&g_csImeDpi);
+}
+
/***********************************************************************
* ImmSetOpenStatus (IMM32.@)
*/
BOOL WINAPI ImmSetOpenStatus(HIMC hIMC, BOOL fOpen)
{
- InputContextData *data = get_imc_data(hIMC);
+ DWORD idImeThread, idThread, dwConversion;
+ LPINPUTCONTEXT pIC;
+ HWND hWnd;
+ BOOL bHasChange = FALSE;
- TRACE("%p %d\n", hIMC, fOpen);
+ TRACE("ImmSetOpenStatus(%p, %d)\n", hIMC, fOpen);
- if (!data)
- {
- SetLastError(ERROR_INVALID_HANDLE);
+ idImeThread = Imm32QueryInputContext(hIMC, 1);
+ idThread = GetCurrentThreadId();
+ if (idImeThread != idThread)
return FALSE;
- }
- if (IMM_IsCrossThreadAccess(NULL, hIMC))
+ pIC = ImmLockIMC(hIMC);
+ if (pIC == NULL)
return FALSE;
- if (data->immKbd->UIWnd == NULL)
+ if (pIC->fOpen != fOpen)
{
- /* create the ime window */
- data->immKbd->UIWnd = CreateWindowExW( WS_EX_TOOLWINDOW,
- data->immKbd->imeClassName, NULL, WS_POPUP, 0, 0, 1, 1, 0,
- 0, data->immKbd->hIME, 0);
- SetWindowLongPtrW(data->immKbd->UIWnd, IMMGWL_IMC, (LONG_PTR)data);
+ pIC->fOpen = fOpen;
+ hWnd = pIC->hWnd;
+ dwConversion = pIC->fdwConversion;
+ bHasChange = TRUE;
}
- else if (fOpen)
- SetWindowLongPtrW(data->immKbd->UIWnd, IMMGWL_IMC, (LONG_PTR)data);
- if (!fOpen != !data->IMC.fOpen)
+ ImmUnlockIMC(hIMC);
+
+ if (bHasChange)
{
- data->IMC.fOpen = fOpen;
- ImmNotifyIME( hIMC, NI_CONTEXTUPDATED, 0, IMC_SETOPENSTATUS);
- ImmInternalSendIMENotify(data, IMN_SETOPENSTATUS, 0);
+ Imm32NotifyAction(hIMC, hWnd, NI_CONTEXTUPDATED, 0,
+ IMC_SETOPENSTATUS, IMN_SETOPENSTATUS, 0);
+ Imm32NotifyIMEStatus(hWnd, hIMC, dwConversion);
}
return TRUE;
diff --git a/dll/win32/imm32/imm32.spec b/dll/win32/imm32/imm32.spec
index 3c950672c35..365d6726122 100644
--- a/dll/win32/imm32/imm32.spec
+++ b/dll/win32/imm32/imm32.spec
@@ -73,7 +73,7 @@
@ stdcall ImmLockClientImc(ptr)
@ stdcall ImmLockIMC(ptr)
@ stdcall ImmLockIMCC(ptr)
-@ stdcall -stub ImmLockImeDpi(long)
+@ stdcall ImmLockImeDpi(ptr)
@ stdcall ImmNotifyIME(ptr long long long)
@ stub ImmPenAuxInput
@ stdcall ImmProcessKey(ptr long long long long)
@@ -107,7 +107,7 @@
@ stdcall ImmUnlockClientImc(ptr)
@ stdcall ImmUnlockIMC(ptr)
@ stdcall ImmUnlockIMCC(ptr)
-@ stdcall -stub ImmUnlockImeDpi(ptr)
+@ stdcall ImmUnlockImeDpi(ptr)
@ stdcall ImmUnregisterWordA(long str long str)
@ stdcall ImmUnregisterWordW(long wstr long wstr)
@ stdcall -stub ImmWINNLSEnableIME(ptr long)
diff --git a/sdk/include/reactos/imm32_undoc.h b/sdk/include/reactos/imm32_undoc.h
index a2b068fb058..a9a20c49b18 100644
--- a/sdk/include/reactos/imm32_undoc.h
+++ b/sdk/include/reactos/imm32_undoc.h
@@ -34,6 +34,8 @@ ImmGetImeInfoEx(PIMEINFOEX pImeInfoEx, IMEINFOEXCLASS SearchType, PVOID
pvSearch
PCLIENTIMC WINAPI ImmLockClientImc(HIMC hImc);
VOID WINAPI ImmUnlockClientImc(PCLIENTIMC pClientImc);
+PIMEDPI WINAPI ImmLockImeDpi(HKL hKL);
+VOID WINAPI ImmUnlockImeDpi(PIMEDPI pImeDpi);
#ifdef __cplusplus
} // extern "C"
diff --git a/win32ss/include/ntuser.h b/win32ss/include/ntuser.h
index cc454ba1e2c..7c30a21d54d 100644
--- a/win32ss/include/ntuser.h
+++ b/win32ss/include/ntuser.h
@@ -1212,6 +1212,40 @@ typedef struct _IMEWND
PIMEUI pimeui;
} IMEWND, *PIMEWND;
+typedef BOOL (WINAPI *FN_ImeDestroy)(UINT uReserved);
+typedef BOOL (WINAPI *FN_NotifyIME)(HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD
dwValue);
+
+typedef struct IMEDPI /* unconfirmed */
+{
+ struct IMEDPI *pNext;
+ HINSTANCE hInst;
+ HKL hKL;
+ DWORD dwUnknown0;
+ DWORD dwUnknown1;
+ DWORD dwUnknown2[14];
+ DWORD cLockObj;
+ DWORD dwFlags;
+ DWORD dwUnknown3[7];
+ FN_ImeDestroy ImeDestroy;
+ DWORD dwUnknown4[5];
+ FN_NotifyIME NotifyIME;
+ /* ... */
+} 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, cLockObj) == 0x4c);
+C_ASSERT(offsetof(IMEDPI, dwFlags) == 0x50);
+C_ASSERT(offsetof(IMEDPI, ImeDestroy) == 0x70);
+C_ASSERT(offsetof(IMEDPI, NotifyIME) == 0x88);
+#endif
+
+/* flags for IMEDPI.dwFlags */
+#define IMEDPI_FLAG_UNKNOWN 1
+#define IMEDPI_FLAG_UNKNOWN2 2
+
DWORD
NTAPI
NtUserAssociateInputContext(
@@ -2676,9 +2710,9 @@ NtUserMoveWindow(
DWORD
NTAPI
NtUserNotifyIMEStatus(
- DWORD Unknown0,
- DWORD Unknown1,
- DWORD Unknown2);
+ HWND hwnd,
+ HIMC hIMC,
+ DWORD dwConversion);
BOOL
NTAPI
@@ -2787,7 +2821,7 @@ NtUserQueryInformationThread(
DWORD
NTAPI
NtUserQueryInputContext(
- DWORD dwUnknown1,
+ HIMC hIMC,
DWORD dwUnknown2);
DWORD
diff --git a/win32ss/user/ntuser/ime.c b/win32ss/user/ntuser/ime.c
index 4b587667e4e..dd5ccbc874a 100644
--- a/win32ss/user/ntuser/ime.c
+++ b/win32ss/user/ntuser/ime.c
@@ -50,13 +50,12 @@ NtUserGetImeHotKey(IN DWORD dwHotKey,
DWORD
APIENTRY
NtUserNotifyIMEStatus(
- DWORD Unknown0,
- DWORD Unknown1,
- DWORD Unknown2)
+ HWND hwnd,
+ HIMC hIMC,
+ DWORD dwConversion)
{
- STUB
-
- return 0;
+ TRACE("NtUserNotifyIMEStatus(%p, %p, 0x%lX)\n", hwnd, hIMC, dwConversion);
+ return 0;
}
diff --git a/win32ss/user/ntuser/ntstubs.c b/win32ss/user/ntuser/ntstubs.c
index 87d2c3ed11a..5ebde8bb41c 100644
--- a/win32ss/user/ntuser/ntstubs.c
+++ b/win32ss/user/ntuser/ntstubs.c
@@ -630,10 +630,10 @@ Quit:
DWORD
APIENTRY
NtUserQueryInputContext(
- DWORD dwUnknown1,
+ HIMC hIMC,
DWORD dwUnknown2)
{
- STUB;
+ TRACE("NtUserQueryInputContext(%p, 0x%lX)\n", hIMC, dwUnknown2);
return 0;
}