From 2ab858c125a6c01c03c99ace13a880fca60f5c19 Mon Sep 17 00:00:00 2001 From: Katayama Hirofumi MZ Date: Mon, 23 Aug 2021 16:25:21 +0900 Subject: [PATCH] [USER32][IMM32] Improve User32InitializeImmEntryTable (#3918) - Improve User32InitializeImmEntryTable function and related. - Complete win32ss/user/user32/include/immtable.h table. - Delete a hack in user32.DllMain and apply my magical tricks. This will fix some access violations in IMM32. - Add some stubs into IMM32. CORE-11700 --- dll/win32/imm32/imm.c | 1 + dll/win32/imm32/imm32.spec | 4 ++ win32ss/user/user32/include/immtable.h | 4 ++ win32ss/user/user32/include/user32.h | 4 ++ win32ss/user/user32/misc/dllmain.c | 26 +++++---- win32ss/user/user32/misc/imm.c | 80 +++++++++++++++----------- 6 files changed, 73 insertions(+), 46 deletions(-) diff --git a/dll/win32/imm32/imm.c b/dll/win32/imm32/imm.c index 675f4d0c648..87097af5ad2 100644 --- a/dll/win32/imm32/imm.c +++ b/dll/win32/imm32/imm.c @@ -5154,6 +5154,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) case DLL_PROCESS_DETACH: RtlDeleteCriticalSection(&g_csImeDpi); + TRACE("imm32.dll is unloaded\n"); break; } diff --git a/dll/win32/imm32/imm32.spec b/dll/win32/imm32/imm32.spec index 7ff287d3657..ba038cbcfb2 100644 --- a/dll/win32/imm32/imm32.spec +++ b/dll/win32/imm32/imm32.spec @@ -1,5 +1,9 @@ @ stdcall CtfImmIsCiceroEnabled() @ stdcall CtfImmIsTextFrameServiceDisabled() +@ stdcall -stub CtfImmTIMActivate(ptr) +@ stdcall -stub CtfImmRestoreToolbarWnd(long) +@ stdcall -stub CtfImmHideToolbarWnd() +@ stdcall -stub CtfImmDispatchDefImeMessage(ptr long ptr ptr) @ stdcall -stub ImmActivateLayout(long) @ stdcall ImmAssociateContext(ptr ptr) @ stdcall ImmAssociateContextEx(ptr ptr long) diff --git a/win32ss/user/user32/include/immtable.h b/win32ss/user/user32/include/immtable.h index ca37779bdd2..4e194a02811 100644 --- a/win32ss/user/user32/include/immtable.h +++ b/win32ss/user/user32/include/immtable.h @@ -51,3 +51,7 @@ DEFINE_IMM_ENTRY(BOOL, ImmSetCompositionStringA, (HIMC hIMC, DWORD dwIndex, LPCV DEFINE_IMM_ENTRY(BOOL, ImmSetCompositionStringW, (HIMC hIMC, DWORD dwIndex, LPCVOID lpComp, DWORD dwCompLen, LPCVOID lpRead, DWORD dwReadLen), 0, NONVOID) DEFINE_IMM_ENTRY(BOOL, ImmEnumInputContext, (DWORD dwThreadID, IMCENUMPROC lpfn, LPARAM lParam), 0, NONVOID) DEFINE_IMM_ENTRY(LRESULT, ImmSystemHandler, (HIMC hIMC, WPARAM wParam, LPARAM lParam), 0, NONVOID) +DEFINE_IMM_ENTRY(LRESULT, CtfImmTIMActivate, (HKL hKL), 0, NONVOID) +DEFINE_IMM_ENTRY(VOID, CtfImmRestoreToolbarWnd, (DWORD dwStatus), 0, VOID) +DEFINE_IMM_ENTRY(DWORD, CtfImmHideToolbarWnd, (VOID), 0, NONVOID) +DEFINE_IMM_ENTRY(LRESULT, CtfImmDispatchDefImeMessage, (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam), 0, NONVOID) diff --git a/win32ss/user/user32/include/user32.h b/win32ss/user/user32/include/user32.h index 2615fb61549..8431d54f838 100644 --- a/win32ss/user/user32/include/user32.h +++ b/win32ss/user/user32/include/user32.h @@ -72,4 +72,8 @@ typedef struct _PATRECT HBRUSH hBrush; } PATRECT, * PPATRECT; +HRESULT +GetImmFileName(_Out_ LPWSTR lpBuffer, + _In_ size_t cchBuffer); + #endif /* _USER32_PCH_ */ diff --git a/win32ss/user/user32/misc/dllmain.c b/win32ss/user/user32/misc/dllmain.c index 6f43b9eeb6b..b757ea22e9d 100644 --- a/win32ss/user/user32/misc/dllmain.c +++ b/win32ss/user/user32/misc/dllmain.c @@ -1,6 +1,6 @@ #include - #include +#include #define MAX_USER_MODE_DRV_BUFFER 526 @@ -438,6 +438,7 @@ Init(PUSERCONNECT UserCon /*PUSERSRV_API_CONNECTINFO*/) gHandleTable = SharedPtrToUser(UserCon->siClient.aheList); gHandleEntries = SharedPtrToUser(gHandleTable->handles); gSharedInfo = UserCon->siClient; + gSharedInfo.psi = gpsi; } // FIXME: Yet another hack... This call should normally not be done here, but @@ -544,18 +545,19 @@ DllMain( if (!gfServerProcess) { -#if WIN32K_ISNT_BROKEN - InitializeImmEntryTable(); -#else - /* imm32 takes a refcount and prevents us from unloading */ - LoadLibraryW(L"user32"); -#endif - // - // Wine is stub and throws an exception so save this for real Imm32.dll testing!!!! - // - //gImmApiEntries.pImmRegisterClient(&gSharedInfo, ghImm32); + HINSTANCE hImm32 = NULL; + + if (gpsi && (gpsi->dwSRVIFlags & SRVINFO_IMM32)) + { + WCHAR szImmFile[MAX_PATH]; + InitializeImmEntryTable(); + GetImmFileName(szImmFile, _countof(szImmFile)); + hImm32 = GetModuleHandleW(szImmFile); + } + + if (!IMM_FN(ImmRegisterClient)(&gSharedInfo, hImm32)) + return FALSE; } - break; } diff --git a/win32ss/user/user32/misc/imm.c b/win32ss/user/user32/misc/imm.c index ef821aea8fa..8f267df2983 100644 --- a/win32ss/user/user32/misc/imm.c +++ b/win32ss/user/user32/misc/imm.c @@ -16,7 +16,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(user32); #define IMM_INIT_MAGIC 0x19650412 +/* Is != NULL when we have loaded the IMM ourselves */ HINSTANCE ghImm32 = NULL; + BOOL bImmInitializing = FALSE; /* define stub functions */ @@ -33,43 +35,50 @@ Imm32ApiTable gImmApiEntries = { #include "immtable.h" }; -HRESULT WINAPI GetImmFileName(PWSTR lpBuffer, UINT uSize) +HRESULT +GetImmFileName(_Out_ LPWSTR lpBuffer, + _In_ size_t cchBuffer) { - UINT length; - STRSAFE_LPWSTR Safe = lpBuffer; - - length = GetSystemDirectoryW(lpBuffer, uSize); - if ( length && length < uSize ) - { - StringCchCatW(Safe, uSize, L"\\"); - return StringCchCatW(Safe, uSize, L"imm32.dll"); - } - return StringCchCopyW(Safe, uSize, L"imm32.dll"); -} + UINT length = GetSystemDirectoryW(lpBuffer, cchBuffer); + if (length && length < cchBuffer) + { + StringCchCatW(lpBuffer, cchBuffer, L"\\"); + return StringCchCatW(lpBuffer, cchBuffer, L"imm32.dll"); + } + return StringCchCopyW(lpBuffer, cchBuffer, L"imm32.dll"); +} /* * @unimplemented */ -BOOL WINAPI IntInitializeImmEntryTable(VOID) +static BOOL IntInitializeImmEntryTable(VOID) { WCHAR ImmFile[MAX_PATH]; HMODULE imm32 = ghImm32; - GetImmFileName(ImmFile, sizeof(ImmFile)); - TRACE("File %ws\n",ImmFile); + /* Check whether the IMM table has already been initialized */ + if (IMM_FN(ImmWINNLSEnableIME) != IMMSTUB_ImmWINNLSEnableIME) + return TRUE; + GetImmFileName(ImmFile, _countof(ImmFile)); + TRACE("File %S\n", ImmFile); + + /* If IMM32 is already loaded, use it without increasing reference count. */ if (imm32 == NULL) - { - imm32 = GetModuleHandleW(ImmFile); - } + imm32 = GetModuleHandleW(ImmFile); + /* + * Loading imm32.dll will call imm32!DllMain function. + * imm32!DllMain calls User32InitializeImmEntryTable. + * Thus, if imm32.dll was loaded, the table has been loaded. + */ if (imm32 == NULL) { imm32 = ghImm32 = LoadLibraryW(ImmFile); if (imm32 == NULL) { - ERR("Did not load!\n"); - return FALSE; + ERR("Did not load imm32.dll!\n"); + return FALSE; } return TRUE; } @@ -79,9 +88,11 @@ BOOL WINAPI IntInitializeImmEntryTable(VOID) #define DEFINE_IMM_ENTRY(type, name, params, retval, retkind) \ do { \ FN_##name proc = (FN_##name)GetProcAddress(imm32, #name); \ - if (proc) { \ - IMM_FN(name) = proc; \ + if (!proc) { \ + ERR("Could not load %s\n", #name); \ + return FALSE; \ } \ + IMM_FN(name) = proc; \ } while (0); #include "immtable.h" @@ -90,8 +101,8 @@ BOOL WINAPI IntInitializeImmEntryTable(VOID) BOOL WINAPI InitializeImmEntryTable(VOID) { - bImmInitializing = TRUE; - return IntInitializeImmEntryTable(); + bImmInitializing = TRUE; + return IntInitializeImmEntryTable(); } BOOL WINAPI User32InitializeImmEntryTable(DWORD magic) @@ -101,24 +112,25 @@ BOOL WINAPI User32InitializeImmEntryTable(DWORD magic) if (magic != IMM_INIT_MAGIC) return FALSE; - if (IMM_FN(ImmIsIME) != IMMSTUB_ImmIsIME) + /* Check whether the IMM table has already been initialized */ + if (IMM_FN(ImmWINNLSEnableIME) != IMMSTUB_ImmWINNLSEnableIME) return TRUE; IntInitializeImmEntryTable(); if (ghImm32 == NULL && !bImmInitializing) { - WCHAR ImmFile[MAX_PATH]; - GetImmFileName(ImmFile, sizeof(ImmFile)); - ghImm32 = LoadLibraryW(ImmFile); - if (ghImm32 == NULL) - { - ERR("Did not load! 2\n"); - return FALSE; - } + WCHAR ImmFile[MAX_PATH]; + GetImmFileName(ImmFile, _countof(ImmFile)); + ghImm32 = LoadLibraryW(ImmFile); + if (ghImm32 == NULL) + { + ERR("Did not load imm32.dll!\n"); + return FALSE; + } } - return TRUE; + return IMM_FN(ImmRegisterClient)(&gSharedInfo, ghImm32); } LRESULT WINAPI ImeWndProc_common( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, BOOL unicode ) // ReactOS