diff --git a/sdk/include/ddk/immdev.h b/sdk/include/ddk/immdev.h index 7780487da59..97a5e9cb4cd 100644 --- a/sdk/include/ddk/immdev.h +++ b/sdk/include/ddk/immdev.h @@ -110,6 +110,7 @@ typedef struct tagGUIDELINE { #define IMS_IMEDEACTIVATE 0x18 #define IMS_ACTIVATELAYOUT 0x19 #define IMS_GETIMEMENU 0x1C +#define IMS_IMEMENUITEMSELECTED 0x1D #define IMS_GETCONTEXT 0x1E #define IMS_SENDNOTIFICATION 0x1F #define IMS_COMPLETECOMPSTR 0x20 diff --git a/win32ss/user/imm32/imemenu.c b/win32ss/user/imm32/imemenu.c index 966b37af4ca..dbea140cb9c 100644 --- a/win32ss/user/imm32/imemenu.c +++ b/win32ss/user/imm32/imemenu.c @@ -610,12 +610,15 @@ ImmGetImeMenuItemsAW( /* Get IME menu items from the IME */ ret = pImeDpi->ImeGetImeMenuItems(hIMC, dwFlags, dwType, pNewParent, pNewItems, dwSize); - if (!ret || !lpImeMenuItems) + if (!ret) { - ERR("%d, %p\n", ret, lpImeMenuItems); + ERR("ImeGetImeMenuItems failed\n"); goto Quit; } + if (!lpImeMenuItems) + goto Quit; + if (bImcIsAnsi != bTargetIsAnsi) /* Are text types different? */ { if (bTargetIsAnsi) diff --git a/win32ss/user/user32/include/user32p.h b/win32ss/user/user32/include/user32p.h index 06e02f8c158..5ce137a850a 100644 --- a/win32ss/user/user32/include/user32p.h +++ b/win32ss/user/user32/include/user32p.h @@ -128,7 +128,7 @@ VOID DeleteFrameBrushes(VOID); BOOL WINAPI GdiValidateHandle(HGDIOBJ); HANDLE FASTCALL UserGetProp(HWND hWnd, ATOM Atom, BOOLEAN SystemProp); BOOL WINAPI InitializeImmEntryTable(VOID); -HRESULT User32GetImmFileName(_Out_ LPWSTR lpBuffer, _In_ size_t cchBuffer); +HRESULT User32GetSystemFilePath(_Out_writes_(cchBuffer) PWSTR lpBuffer, _In_ SIZE_T cchBuffer, _In_ PCWSTR pszFileName); BOOL WINAPI UpdatePerUserImmEnabling(VOID); VOID APIENTRY CliImmInitializeHotKeys(DWORD dwAction, HKL hKL); VOID IntLoadPreloadKeyboardLayouts(VOID); diff --git a/win32ss/user/user32/misc/dllmain.c b/win32ss/user/user32/misc/dllmain.c index c3c8451985a..d9cc8c96cd4 100644 --- a/win32ss/user/user32/misc/dllmain.c +++ b/win32ss/user/user32/misc/dllmain.c @@ -537,7 +537,7 @@ DllMain( { WCHAR szImmFile[MAX_PATH]; InitializeImmEntryTable(); - User32GetImmFileName(szImmFile, _countof(szImmFile)); + User32GetSystemFilePath(szImmFile, _countof(szImmFile), L"imm32.dll"); hImm32 = GetModuleHandleW(szImmFile); } diff --git a/win32ss/user/user32/misc/imm.c b/win32ss/user/user32/misc/imm.c index c9e24c2fd25..44c88d52c4e 100644 --- a/win32ss/user/user32/misc/imm.c +++ b/win32ss/user/user32/misc/imm.c @@ -1,10 +1,9 @@ /* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS user32.dll - * FILE: win32ss/user/user32/misc/imm.c - * PURPOSE: User32.dll Imm functions - * PROGRAMMERS: Dmitry Chapyshev (dmitry@reactos.org) - * Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com) + * PROJECT: ReactOS user32.dll + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) + * PURPOSE: User32.dll Imm functions + * COPYRIGHT: Copyright Dmitry Chapyshev (dmitry@reactos.org) + * Copyright Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com) */ #include @@ -17,11 +16,11 @@ WINE_DEFAULT_DEBUG_CHANNEL(user32); #define MAX_CANDIDATEFORM 4 /* Is != NULL when we have loaded the IMM ourselves */ -HINSTANCE ghImm32 = NULL; // Win: ghImm32 +HINSTANCE ghImm32 = NULL; -BOOL gbImmInitializing = FALSE; // Win: bImmInitializing +BOOL gbImmInitializing = FALSE; -INT gfConIme = -1; // Win: gfConIme +INT gfConIme = -1; HWND FASTCALL IntGetTopLevelWindow(HWND hWnd) { @@ -43,7 +42,6 @@ HWND FASTCALL IntGetTopLevelWindow(HWND hWnd) static type WINAPI IMMSTUB_##name params { IMM_RETURN_##retkind((type)retval); } #include "immtable.h" -// Win: gImmApiEntries Imm32ApiTable gImmApiEntries = { /* initialize by stubs */ #undef DEFINE_IMM_ENTRY @@ -52,21 +50,25 @@ Imm32ApiTable gImmApiEntries = { #include "immtable.h" }; -// Win: GetImmFileName HRESULT -User32GetImmFileName(_Out_ LPWSTR lpBuffer, _In_ size_t cchBuffer) +User32GetSystemFilePath( + _Out_writes_(cchBuffer) PWSTR lpBuffer, + _In_ SIZE_T cchBuffer, + _In_ PCWSTR pszFileName) { UINT length = GetSystemDirectoryW(lpBuffer, cchBuffer); if (length && length < cchBuffer) { StringCchCatW(lpBuffer, cchBuffer, L"\\"); - return StringCchCatW(lpBuffer, cchBuffer, L"imm32.dll"); + return StringCchCatW(lpBuffer, cchBuffer, pszFileName); } - return StringCchCopyW(lpBuffer, cchBuffer, L"imm32.dll"); + DWORD dwError = GetLastError(); + ERR("GetSystemDirectoryW failed (error %lu)\n", dwError); + StringCchCopyW(lpBuffer, cchBuffer, pszFileName); + return HRESULT_FROM_WIN32(dwError); } // @unimplemented -// Win: _InitializeImmEntryTable static BOOL IntInitializeImmEntryTable(VOID) { WCHAR ImmFile[MAX_PATH]; @@ -76,8 +78,8 @@ static BOOL IntInitializeImmEntryTable(VOID) if (IMM_FN(ImmWINNLSEnableIME) != IMMSTUB_ImmWINNLSEnableIME) return TRUE; - User32GetImmFileName(ImmFile, _countof(ImmFile)); - TRACE("File %S\n", ImmFile); + User32GetSystemFilePath(ImmFile, _countof(ImmFile), L"imm32.dll"); + TRACE("File %s\n", debugstr_w(ImmFile)); /* If IMM32 is already loaded, use it without increasing reference count. */ if (imm32 == NULL) @@ -115,14 +117,12 @@ static BOOL IntInitializeImmEntryTable(VOID) return TRUE; } -// Win: InitializeImmEntryTable BOOL WINAPI InitializeImmEntryTable(VOID) { gbImmInitializing = TRUE; return IntInitializeImmEntryTable(); } -// Win: User32InitializeImmEntryTable BOOL WINAPI User32InitializeImmEntryTable(DWORD magic) { TRACE("Imm (%x)\n", magic); @@ -139,7 +139,7 @@ BOOL WINAPI User32InitializeImmEntryTable(DWORD magic) if (ghImm32 == NULL && !gbImmInitializing) { WCHAR ImmFile[MAX_PATH]; - User32GetImmFileName(ImmFile, _countof(ImmFile)); + User32GetSystemFilePath(ImmFile, _countof(ImmFile), L"imm32.dll"); ghImm32 = LoadLibraryW(ImmFile); if (ghImm32 == NULL) { @@ -151,21 +151,18 @@ BOOL WINAPI User32InitializeImmEntryTable(DWORD magic) return IMM_FN(ImmRegisterClient)(&gSharedInfo, ghImm32); } -// Win: ImeIsUsableContext static BOOL User32CanSetImeWindowToImc(HIMC hIMC, HWND hImeWnd) { PIMC pIMC = ValidateHandle(hIMC, TYPE_INPUTCONTEXT); return pIMC && (!pIMC->hImeWnd || pIMC->hImeWnd == hImeWnd || !ValidateHwnd(pIMC->hImeWnd)); } -// Win: GetIMEShowStatus static BOOL User32GetImeShowStatus(VOID) { return (BOOL)NtUserCallNoParam(NOPARAM_ROUTINE_GETIMESHOWSTATUS); } /* Sends a message to the IME UI window. */ -/* Win: SendMessageToUI(pimeui, uMsg, wParam, lParam, !unicode) */ static LRESULT User32SendImeUIMessage(PIMEUI pimeui, UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL unicode) { @@ -195,7 +192,6 @@ User32SendImeUIMessage(PIMEUI pimeui, UINT uMsg, WPARAM wParam, LPARAM lParam, B return ret; } -// Win: SendOpenStatusNotify static VOID User32NotifyOpenStatus(PIMEUI pimeui, HWND hwndIMC, BOOL bOpen) { WPARAM wParam = (bOpen ? IMN_OPENSTATUSWINDOW : IMN_CLOSESTATUSWINDOW); @@ -210,7 +206,6 @@ static VOID User32NotifyOpenStatus(PIMEUI pimeui, HWND hwndIMC, BOOL bOpen) User32SendImeUIMessage(pimeui, WM_IME_NOTIFY, wParam, 0, TRUE); } -// Win: ImeMarkUsedContext static VOID User32SetImeWindowOfImc(HIMC hIMC, HWND hImeWnd) { PIMC pIMC = ValidateHandle(hIMC, TYPE_INPUTCONTEXT); @@ -220,7 +215,6 @@ static VOID User32SetImeWindowOfImc(HIMC hIMC, HWND hImeWnd) NtUserUpdateInputContext(hIMC, UIC_IMEWINDOW, (ULONG_PTR)hImeWnd); } -// Win: ImeSetImc static VOID User32UpdateImcOfImeUI(PIMEUI pimeui, HIMC hNewIMC) { HWND hImeWnd; @@ -242,7 +236,6 @@ static VOID User32UpdateImcOfImeUI(PIMEUI pimeui, HIMC hNewIMC) } /* Handles WM_IME_NOTIFY message of the default IME window. */ -/* Win: ImeNotifyHandler */ static LRESULT ImeWnd_OnImeNotify(PIMEUI pimeui, WPARAM wParam, LPARAM lParam) { LRESULT ret = 0; @@ -293,7 +286,6 @@ static LRESULT ImeWnd_OnImeNotify(PIMEUI pimeui, WPARAM wParam, LPARAM lParam) } /* Creates the IME UI window. */ -/* Win: CreateIMEUI */ static HWND User32CreateImeUIWindow(PIMEUI pimeui, HKL hKL) { IMEINFOEX ImeInfoEx; @@ -339,7 +331,6 @@ Quit: } /* Initializes the default IME window. */ -/* Win: ImeWndCreateHandler */ static INT ImeWnd_OnCreate(PIMEUI pimeui, LPCREATESTRUCT lpCS) { PWND pParentWnd, pWnd = pimeui->spwnd; @@ -371,7 +362,6 @@ static INT ImeWnd_OnCreate(PIMEUI pimeui, LPCREATESTRUCT lpCS) } /* Destroys the IME UI window. */ -/* Win: DestroyIMEUI */ static VOID User32DestroyImeUIWindow(PIMEUI pimeui) { HWND hwndUI = pimeui->hwndUI; @@ -387,7 +377,6 @@ static VOID User32DestroyImeUIWindow(PIMEUI pimeui) } /* Handles WM_IME_SELECT message of the default IME window. */ -/* Win: ImeSelectHandler */ static VOID ImeWnd_OnImeSelect(PIMEUI pimeui, WPARAM wParam, LPARAM lParam) { HKL hKL; @@ -422,7 +411,6 @@ static VOID ImeWnd_OnImeSelect(PIMEUI pimeui, WPARAM wParam, LPARAM lParam) } /* Handles WM_IME_CONTROL message of the default IME window. */ -/* Win: ImeControlHandler(pimeui, wParam, lParam, !unicode) */ static LRESULT ImeWnd_OnImeControl(PIMEUI pimeui, WPARAM wParam, LPARAM lParam, BOOL unicode) { @@ -558,7 +546,6 @@ ImeWnd_OnImeControl(PIMEUI pimeui, WPARAM wParam, LPARAM lParam, BOOL unicode) } /* Modify the IME activation status. */ -/* Win: FocusSetIMCContext */ static VOID FASTCALL User32SetImeActivenessOfWindow(HWND hWnd, BOOL bActive) { HIMC hIMC; @@ -574,7 +561,6 @@ static VOID FASTCALL User32SetImeActivenessOfWindow(HWND hWnd, BOOL bActive) IMM_FN(ImmReleaseContext)(hWnd, hIMC); } -/* Win: CtfLoadThreadLayout */ VOID FASTCALL CtfLoadThreadLayout(PIMEUI pimeui) { IMM_FN(CtfImmTIMActivate)(pimeui->hKL); @@ -636,6 +622,59 @@ ImeWnd_SwitchSoftKbdProc(_In_ HIMC hIMC, _In_ LPARAM lParam) return TRUE; } +// indicdll!12 +typedef VOID (CALLBACK *FN_GetPenMenuData)(PUINT pnID, PDWORD_PTR pdwMenuData); +static FN_GetPenMenuData s_pGetPenMenuData = NULL; +#define IFN_GetPenMenuData 12 + +static BOOL CALLBACK +User32GetPenMenuData(_Out_ PUINT pnID, _Out_ PDWORD_PTR pdwMenuData) +{ + if (!s_pGetPenMenuData) + { + WCHAR szPath[MAX_PATH]; + HMODULE hIndicDll = GetModuleHandleW(L"indicdll.dll"); + if (!hIndicDll) + { + User32GetSystemFilePath(szPath, _countof(szPath), L"indicdll.dll"); + hIndicDll = LoadLibraryW(szPath); + } + if (!hIndicDll) + { + ERR("indicdll.dll not loaded: %s\n", debugstr_w(szPath)); + return FALSE; + } + + s_pGetPenMenuData = + (FN_GetPenMenuData)GetProcAddress(hIndicDll, MAKEINTRESOURCEA(IFN_GetPenMenuData)); + } + + if (!s_pGetPenMenuData) + return FALSE; + + s_pGetPenMenuData(pnID, pdwMenuData); + return TRUE; +} + +// IMS_IMEMENUITEMSELECTED +static VOID +User32ImeMenuItemSelected(HWND hwndTarget) +{ + if (!IsWindow(hwndTarget)) + return; + + HIMC hIMC = IMM_FN(ImmGetContext)(hwndTarget); + if (!hIMC) + return; + + UINT nID = 0; + DWORD_PTR dwMenuData = 0; + if (User32GetPenMenuData(&nID, &dwMenuData)) + IMM_FN(ImmNotifyIME)(hIMC, NI_IMEMENUSELECTED, nID, dwMenuData); + + IMM_FN(ImmReleaseContext)(hwndTarget, hIMC); +} + /* Handles WM_IME_SYSTEM message of the default IME window. */ static LRESULT ImeWnd_OnImeSystem(PIMEUI pimeui, WPARAM wParam, LPARAM lParam) { @@ -765,8 +804,8 @@ static LRESULT ImeWnd_OnImeSystem(PIMEUI pimeui, WPARAM wParam, LPARAM lParam) ret = IMM_FN(ImmPutImeMenuItemsIntoMappedFile)((HIMC)lParam); break; - case 0x1D: - FIXME("\n"); + case IMS_IMEMENUITEMSELECTED: + User32ImeMenuItemSelected((HWND)lParam); break; case IMS_GETCONTEXT: @@ -792,7 +831,6 @@ static LRESULT ImeWnd_OnImeSystem(PIMEUI pimeui, WPARAM wParam, LPARAM lParam) } /* Handles WM_IME_SETCONTEXT message of the default IME window. */ -/* Win: ImeSetContextHandler */ LRESULT ImeWnd_OnImeSetContext(PIMEUI pimeui, WPARAM wParam, LPARAM lParam) { LRESULT ret; @@ -947,7 +985,6 @@ LRESULT ImeWnd_OnImeSetContext(PIMEUI pimeui, WPARAM wParam, LPARAM lParam) } /* The window procedure of the default IME window */ -/* Win: ImeWndProcWorker(pWnd, msg, wParam, lParam, !unicode) */ LRESULT WINAPI ImeWndProc_common(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, BOOL unicode) // ReactOS { @@ -1103,19 +1140,16 @@ Finish: return DefWindowProcA(hwnd, msg, wParam, lParam); } -// Win: ImeWndProcA LRESULT WINAPI ImeWndProcA( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ) { return ImeWndProc_common(hwnd, msg, wParam, lParam, FALSE); } -// Win: ImeWndProcW LRESULT WINAPI ImeWndProcW( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ) { return ImeWndProc_common(hwnd, msg, wParam, lParam, TRUE); } -// Win: UpdatePerUserImmEnabling BOOL WINAPI UpdatePerUserImmEnabling(VOID) { HMODULE imm32;