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); - return FALSE; - } - - if (IMM_IsCrossThreadAccess(NULL, hIMC)) + idImeThread = Imm32QueryInputContext(hIMC, 1); + idThread = GetCurrentThreadId(); + if (idImeThread != idThread) return FALSE; - if (data->immKbd->UIWnd == NULL) - { - /* 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); - } - else if (fOpen) - SetWindowLongPtrW(data->immKbd->UIWnd, IMMGWL_IMC, (LONG_PTR)data); + pIC = ImmLockIMC(hIMC); + if (pIC == NULL) + return FALSE; - if (!fOpen != !data->IMC.fOpen) + if (pIC->fOpen != fOpen) { - data->IMC.fOpen = fOpen; - ImmNotifyIME( hIMC, NI_CONTEXTUPDATED, 0, IMC_SETOPENSTATUS); - ImmInternalSendIMENotify(data, IMN_SETOPENSTATUS, 0); + pIC->fOpen = fOpen; + hWnd = pIC->hWnd; + dwConversion = pIC->fdwConversion; + bHasChange = TRUE; + } + + ImmUnlockIMC(hIMC); + + if (bHasChange) + { + 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; }