mirror of
https://github.com/reactos/reactos.git
synced 2025-07-31 19:21:38 +00:00
[User32|IMM32] Fix a recursion crash in IMM. See CORE-14041.
Required a sync port from wine. This is a hack fix with Win32SS until proper IMM support is added to Win32SS.
This commit is contained in:
parent
9b349f958c
commit
c45a6e15bf
9 changed files with 469 additions and 287 deletions
|
@ -113,6 +113,10 @@ NtUserCallNoParam(DWORD Routine)
|
|||
case NOPARAM_ROUTINE_ISCONSOLEMODE:
|
||||
RETURN( ScreenDeviceContext == NULL );
|
||||
|
||||
case NOPARAM_ROUTINE_UPDATEPERUSERIMMENABLING:
|
||||
gpsi->dwSRVIFlags |= SRVINFO_IMM32; // Always set.
|
||||
RETURN(1); // Always return TRUE.
|
||||
|
||||
default:
|
||||
ERR("Calling invalid routine number 0x%x in NtUserCallNoParam\n", Routine);
|
||||
EngSetLastError(ERROR_INVALID_PARAMETER);
|
||||
|
|
|
@ -134,5 +134,6 @@ VOID DeleteFrameBrushes(VOID);
|
|||
BOOL WINAPI GdiValidateHandle(HGDIOBJ);
|
||||
HANDLE FASTCALL UserGetProp(HWND hWnd, ATOM Atom, BOOLEAN SystemProp);
|
||||
BOOL WINAPI InitializeImmEntryTable(VOID);
|
||||
BOOL WINAPI UpdatePerUserImmEnabling(VOID);
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -25,19 +25,6 @@ HINSTANCE ghImm32 = NULL;
|
|||
BOOL bImmInitializing = FALSE;
|
||||
BOOL ImmApiTableZero = TRUE;
|
||||
|
||||
HRESULT WINAPI GetImmFileName(PWSTR lpBuffer, UINT uSize)
|
||||
{
|
||||
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");
|
||||
}
|
||||
|
||||
/*
|
||||
* This function should not be implemented, it is used,
|
||||
|
@ -59,6 +46,20 @@ BOOL WINAPI IMM_ImmNotifyIME(HIMC himc, DWORD dword1, DWORD dword2, DWORD dword3
|
|||
BOOL WINAPI IMM_ImmRegisterClient(PVOID ptr, HINSTANCE hMod) { return 0; }
|
||||
UINT WINAPI IMM_ImmProcessKey(HWND hwnd, HKL hkl, UINT Vk, LPARAM lParam, DWORD HotKey) { return 0; }
|
||||
|
||||
HRESULT WINAPI GetImmFileName(PWSTR lpBuffer, UINT uSize)
|
||||
{
|
||||
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");
|
||||
}
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
|
@ -189,7 +190,7 @@ BOOL WINAPI InitializeImmEntryTable(VOID)
|
|||
|
||||
BOOL WINAPI User32InitializeImmEntryTable(DWORD magic)
|
||||
{
|
||||
TRACE("(%x)\n", magic);
|
||||
TRACE("Imm (%x)\n", magic);
|
||||
|
||||
if (magic != IMM_INIT_MAGIC)
|
||||
return FALSE;
|
||||
|
@ -205,9 +206,7 @@ BOOL WINAPI User32InitializeImmEntryTable(DWORD magic)
|
|||
if (ghImm32 == NULL && !bImmInitializing)
|
||||
{
|
||||
WCHAR ImmFile[MAX_PATH];
|
||||
ERR("IMM32 not installed!\n");
|
||||
GetImmFileName(ImmFile, sizeof(ImmFile));
|
||||
ERR("File %ws\n",ImmFile);
|
||||
ghImm32 = LoadLibraryW(ImmFile);
|
||||
if (ghImm32 == NULL)
|
||||
{
|
||||
|
@ -285,6 +284,30 @@ LRESULT WINAPI ImeWndProcW( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
|
|||
return ImeWndProc_common(hwnd, msg, wParam, lParam, TRUE);
|
||||
}
|
||||
|
||||
BOOL
|
||||
WINAPI
|
||||
UpdatePerUserImmEnabling(VOID)
|
||||
{
|
||||
BOOL Ret = NtUserCallNoParam(NOPARAM_ROUTINE_UPDATEPERUSERIMMENABLING);
|
||||
if ( Ret )
|
||||
{
|
||||
if ( gpsi->dwSRVIFlags & SRVINFO_IMM32 )
|
||||
{
|
||||
HMODULE imm32 = GetModuleHandleW(L"imm32.dll");
|
||||
if ( !imm32 )
|
||||
{
|
||||
imm32 = LoadLibraryW(L"imm32.dll");
|
||||
if (!imm32)
|
||||
{
|
||||
ERR("UPUIE: Imm32 not installed!\n");
|
||||
Ret = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Ret;
|
||||
}
|
||||
|
||||
static const WCHAR imeW[] = {'I','M','E',0};
|
||||
|
||||
BOOL
|
||||
|
@ -311,6 +334,7 @@ RegisterIMEClass(VOID)
|
|||
if (atom)
|
||||
{
|
||||
RegisterDefaultClasses |= ICLASS_TO_MASK(ICLS_IME);
|
||||
TRACE("Register IME Class!\n");
|
||||
return TRUE;
|
||||
}
|
||||
ERR("Failed to register IME Class!\n");
|
||||
|
|
|
@ -107,5 +107,8 @@ WINAPI
|
|||
UpdatePerUserSystemParameters(DWORD dwReserved,
|
||||
BOOL bEnable)
|
||||
{
|
||||
// Update Imm support and load Imm32.dll.
|
||||
UpdatePerUserImmEnabling();
|
||||
|
||||
return NtUserUpdatePerUserSystemParameters(dwReserved, bEnable);
|
||||
}
|
||||
|
|
|
@ -797,75 +797,6 @@ GoSS:
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* helpers for calling IMM32 (from Wine 10/22/2008)
|
||||
*
|
||||
* WM_IME_* messages are generated only by IMM32,
|
||||
* so I assume imm32 is already LoadLibrary-ed.
|
||||
*/
|
||||
static HWND
|
||||
DefWndImmGetDefaultIMEWnd(HWND hwnd)
|
||||
{
|
||||
HINSTANCE hInstIMM = GetModuleHandleW(L"imm32\0");
|
||||
HWND (WINAPI *pFunc)(HWND);
|
||||
HWND hwndRet = 0;
|
||||
|
||||
if (!hInstIMM)
|
||||
{
|
||||
ERR("cannot get IMM32 handle\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
pFunc = (void*) GetProcAddress(hInstIMM, "ImmGetDefaultIMEWnd");
|
||||
if (pFunc != NULL)
|
||||
hwndRet = (*pFunc)(hwnd);
|
||||
|
||||
return hwndRet;
|
||||
}
|
||||
|
||||
|
||||
static BOOL
|
||||
DefWndImmIsUIMessageA(HWND hwndIME, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
HINSTANCE hInstIMM = GetModuleHandleW(L"imm32\0");
|
||||
BOOL (WINAPI *pFunc)(HWND,UINT,WPARAM,LPARAM);
|
||||
BOOL fRet = FALSE;
|
||||
|
||||
if (!hInstIMM)
|
||||
{
|
||||
ERR("cannot get IMM32 handle\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pFunc = (void*) GetProcAddress(hInstIMM, "ImmIsUIMessageA");
|
||||
if (pFunc != NULL)
|
||||
fRet = (*pFunc)(hwndIME, msg, wParam, lParam);
|
||||
|
||||
return fRet;
|
||||
}
|
||||
|
||||
|
||||
static BOOL
|
||||
DefWndImmIsUIMessageW(HWND hwndIME, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
HINSTANCE hInstIMM = GetModuleHandleW(L"imm32\0");
|
||||
BOOL (WINAPI *pFunc)(HWND,UINT,WPARAM,LPARAM);
|
||||
BOOL fRet = FALSE;
|
||||
|
||||
if (!hInstIMM)
|
||||
{
|
||||
ERR("cannot get IMM32 handle\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pFunc = (void*) GetProcAddress(hInstIMM, "ImmIsUIMessageW");
|
||||
if (pFunc != NULL)
|
||||
fRet = (*pFunc)(hwndIME, msg, wParam, lParam);
|
||||
|
||||
return fRet;
|
||||
}
|
||||
|
||||
|
||||
LRESULT WINAPI
|
||||
RealDefWindowProcA(HWND hWnd,
|
||||
UINT Msg,
|
||||
|
@ -1003,8 +934,44 @@ RealDefWindowProcA(HWND hWnd,
|
|||
break;
|
||||
}
|
||||
|
||||
case WM_IME_STARTCOMPOSITION:
|
||||
case WM_IME_COMPOSITION:
|
||||
if (lParam & GCS_RESULTSTR)
|
||||
{
|
||||
LONG size, i;
|
||||
unsigned char lead = 0;
|
||||
char *buf = NULL;
|
||||
HIMC himc = ImmGetContext( hWnd );
|
||||
|
||||
if (himc)
|
||||
{
|
||||
if ((size = ImmGetCompositionStringA( himc, GCS_RESULTSTR, NULL, 0 )))
|
||||
{
|
||||
if (!(buf = HeapAlloc( GetProcessHeap(), 0, size ))) size = 0;
|
||||
else size = ImmGetCompositionStringA( himc, GCS_RESULTSTR, buf, size );
|
||||
}
|
||||
ImmReleaseContext( hWnd, himc );
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
unsigned char c = buf[i];
|
||||
if (!lead)
|
||||
{
|
||||
if (IsDBCSLeadByte( c ))
|
||||
lead = c;
|
||||
else
|
||||
SendMessageA( hWnd, WM_IME_CHAR, c, 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
SendMessageA( hWnd, WM_IME_CHAR, MAKEWORD(c, lead), 1 );
|
||||
lead = 0;
|
||||
}
|
||||
}
|
||||
HeapFree( GetProcessHeap(), 0, buf );
|
||||
}
|
||||
}
|
||||
/* fall through */
|
||||
case WM_IME_STARTCOMPOSITION:
|
||||
case WM_IME_ENDCOMPOSITION:
|
||||
case WM_IME_SELECT:
|
||||
case WM_IME_NOTIFY:
|
||||
|
@ -1012,7 +979,7 @@ RealDefWindowProcA(HWND hWnd,
|
|||
{
|
||||
HWND hwndIME;
|
||||
|
||||
hwndIME = DefWndImmGetDefaultIMEWnd(hWnd);
|
||||
hwndIME = ImmGetDefaultIMEWnd(hWnd);
|
||||
if (hwndIME)
|
||||
Result = SendMessageA(hwndIME, Msg, wParam, lParam);
|
||||
break;
|
||||
|
@ -1022,9 +989,9 @@ RealDefWindowProcA(HWND hWnd,
|
|||
{
|
||||
HWND hwndIME;
|
||||
|
||||
hwndIME = DefWndImmGetDefaultIMEWnd(hWnd);
|
||||
hwndIME = ImmGetDefaultIMEWnd(hWnd);
|
||||
if (hwndIME)
|
||||
Result = DefWndImmIsUIMessageA(hwndIME, Msg, wParam, lParam);
|
||||
Result = ImmIsUIMessageA(hwndIME, Msg, wParam, lParam);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1165,8 +1132,29 @@ RealDefWindowProcW(HWND hWnd,
|
|||
break;
|
||||
}
|
||||
|
||||
case WM_IME_STARTCOMPOSITION:
|
||||
case WM_IME_COMPOSITION:
|
||||
if (lParam & GCS_RESULTSTR)
|
||||
{
|
||||
LONG size, i;
|
||||
WCHAR *buf = NULL;
|
||||
HIMC himc = ImmGetContext( hWnd );
|
||||
|
||||
if (himc)
|
||||
{
|
||||
if ((size = ImmGetCompositionStringW( himc, GCS_RESULTSTR, NULL, 0 )))
|
||||
{
|
||||
if (!(buf = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) ))) size = 0;
|
||||
else size = ImmGetCompositionStringW( himc, GCS_RESULTSTR, buf, size * sizeof(WCHAR) );
|
||||
}
|
||||
ImmReleaseContext( hWnd, himc );
|
||||
|
||||
for (i = 0; i < size / sizeof(WCHAR); i++)
|
||||
SendMessageW( hWnd, WM_IME_CHAR, buf[i], 1 );
|
||||
HeapFree( GetProcessHeap(), 0, buf );
|
||||
}
|
||||
}
|
||||
/* fall through */
|
||||
case WM_IME_STARTCOMPOSITION:
|
||||
case WM_IME_ENDCOMPOSITION:
|
||||
case WM_IME_SELECT:
|
||||
case WM_IME_NOTIFY:
|
||||
|
@ -1174,7 +1162,7 @@ RealDefWindowProcW(HWND hWnd,
|
|||
{
|
||||
HWND hwndIME;
|
||||
|
||||
hwndIME = DefWndImmGetDefaultIMEWnd(hWnd);
|
||||
hwndIME = ImmGetDefaultIMEWnd(hWnd);
|
||||
if (hwndIME)
|
||||
Result = SendMessageW(hwndIME, Msg, wParam, lParam);
|
||||
break;
|
||||
|
@ -1184,9 +1172,9 @@ RealDefWindowProcW(HWND hWnd,
|
|||
{
|
||||
HWND hwndIME;
|
||||
|
||||
hwndIME = DefWndImmGetDefaultIMEWnd(hWnd);
|
||||
hwndIME = ImmGetDefaultIMEWnd(hWnd);
|
||||
if (hwndIME)
|
||||
Result = DefWndImmIsUIMessageW(hwndIME, Msg, wParam, lParam);
|
||||
Result = ImmIsUIMessageW(hwndIME, Msg, wParam, lParam);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue