Skip to content
Snippets Groups Projects
Commit 16222f2d authored by Rémi Bernon's avatar Rémi Bernon :speech_balloon: Committed by Alexandre Julliard
Browse files

imm32/tests: Redirect IME function to the main module.

For easier testing and to wokaround some Windows IME caching mechanism
that prevent the IME module from reloading.
parent d07a5e6b
Branches
Tags
No related merge requests found
......@@ -32,4 +32,25 @@
#include "imm.h"
#include "immdev.h"
struct ime_functions
{
BOOL (*WINAPI pImeConfigure)(HKL,HWND,DWORD,void *);
DWORD (*WINAPI pImeConversionList)(HIMC,const WCHAR *,CANDIDATELIST *,DWORD,UINT);
BOOL (*WINAPI pImeDestroy)(UINT);
UINT (*WINAPI pImeEnumRegisterWord)(REGISTERWORDENUMPROCW,const WCHAR *,DWORD,const WCHAR *,void *);
LRESULT (*WINAPI pImeEscape)(HIMC,UINT,void *);
DWORD (*WINAPI pImeGetImeMenuItems)(HIMC,DWORD,DWORD,IMEMENUITEMINFOW *,IMEMENUITEMINFOW *,DWORD);
UINT (*WINAPI pImeGetRegisterWordStyle)(UINT,STYLEBUFW *);
BOOL (*WINAPI pImeInquire)(IMEINFO *,WCHAR *,DWORD);
BOOL (*WINAPI pImeProcessKey)(HIMC,UINT,LPARAM,BYTE *);
BOOL (*WINAPI pImeRegisterWord)(const WCHAR *,DWORD,const WCHAR *);
BOOL (*WINAPI pImeSelect)(HIMC,BOOL);
BOOL (*WINAPI pImeSetActiveContext)(HIMC,BOOL);
BOOL (*WINAPI pImeSetCompositionString)(HIMC,DWORD,const void *,DWORD,const void *,DWORD);
UINT (*WINAPI pImeToAsciiEx)(UINT,UINT,BYTE *,TRANSMSGLIST *,UINT,HIMC);
BOOL (*WINAPI pImeUnregisterWord)(const WCHAR *,DWORD,const WCHAR *);
BOOL (*WINAPI pNotifyIME)(HIMC,DWORD,DWORD,DWORD);
BOOL (*WINAPI pDllMain)(HINSTANCE,DWORD,void *);
};
#endif /* __WINE_IME_TEST_H */
......@@ -18,90 +18,125 @@
#include "ime_test.h"
struct ime_functions ime_functions = {0};
BOOL WINAPI ImeConfigure( HKL hkl, HWND hwnd, DWORD mode, void *data )
{
return FALSE;
if (!ime_functions.pImeConfigure) return FALSE;
return ime_functions.pImeConfigure( hkl, hwnd, mode, data );
}
DWORD WINAPI ImeConversionList( HIMC himc, const WCHAR *source, CANDIDATELIST *dest, DWORD dest_len, UINT flag )
{
return 0;
if (!ime_functions.pImeConversionList) return 0;
return ime_functions.pImeConversionList( himc, source, dest, dest_len, flag );
}
BOOL WINAPI ImeDestroy( UINT force )
{
return FALSE;
if (!ime_functions.pImeDestroy) return FALSE;
return ime_functions.pImeDestroy( force );
}
UINT WINAPI ImeEnumRegisterWord( REGISTERWORDENUMPROCW proc, const WCHAR *reading, DWORD style,
const WCHAR *string, void *data )
{
return 0;
if (!ime_functions.pImeEnumRegisterWord) return 0;
return ime_functions.pImeEnumRegisterWord( proc, reading, style, string, data );
}
LRESULT WINAPI ImeEscape( HIMC himc, UINT escape, void *data )
{
return 0;
if (!ime_functions.pImeEscape) return 0;
return ime_functions.pImeEscape( himc, escape, data );
}
DWORD WINAPI ImeGetImeMenuItems( HIMC himc, DWORD flags, DWORD type, IMEMENUITEMINFOW *parent,
IMEMENUITEMINFOW *menu, DWORD size )
{
return 0;
if (!ime_functions.pImeGetImeMenuItems) return 0;
return ime_functions.pImeGetImeMenuItems( himc, flags, type, parent, menu, size );
}
UINT WINAPI ImeGetRegisterWordStyle( UINT item, STYLEBUFW *style_buf )
{
return 0;
if (!ime_functions.pImeGetRegisterWordStyle) return 0;
return ime_functions.pImeGetRegisterWordStyle( item, style_buf );
}
BOOL WINAPI ImeInquire( IMEINFO *info, WCHAR *ui_class, DWORD flags )
{
return FALSE;
if (!ime_functions.pImeInquire) return FALSE;
return ime_functions.pImeInquire( info, ui_class, flags );
}
BOOL WINAPI ImeProcessKey( HIMC himc, UINT vkey, LPARAM key_data, BYTE *key_state )
{
return FALSE;
if (!ime_functions.pImeProcessKey) return FALSE;
return ime_functions.pImeProcessKey( himc, vkey, key_data, key_state );
}
BOOL WINAPI ImeRegisterWord( const WCHAR *reading, DWORD style, const WCHAR *string )
{
return FALSE;
if (!ime_functions.pImeRegisterWord) return FALSE;
return ime_functions.pImeRegisterWord( reading, style, string );
}
BOOL WINAPI ImeSelect( HIMC himc, BOOL select )
{
return FALSE;
if (!ime_functions.pImeSelect) return FALSE;
return ime_functions.pImeSelect( himc, select );
}
BOOL WINAPI ImeSetActiveContext( HIMC himc, BOOL flag )
{
return FALSE;
if (!ime_functions.pImeSetActiveContext) return FALSE;
return ime_functions.pImeSetActiveContext( himc, flag );
}
BOOL WINAPI ImeSetCompositionString( HIMC himc, DWORD index, const void *comp, DWORD comp_len,
const void *read, DWORD read_len )
{
return FALSE;
if (!ime_functions.pImeSetCompositionString) return FALSE;
return ime_functions.pImeSetCompositionString( himc, index, comp, comp_len, read, read_len );
}
UINT WINAPI ImeToAsciiEx( UINT vkey, UINT scan_code, BYTE *key_state, TRANSMSGLIST *msgs, UINT state, HIMC himc )
{
return 0;
if (!ime_functions.pImeToAsciiEx) return 0;
return ime_functions.pImeToAsciiEx( vkey, scan_code, key_state, msgs, state, himc );
}
BOOL WINAPI ImeUnregisterWord( const WCHAR *reading, DWORD style, const WCHAR *string )
{
return FALSE;
if (!ime_functions.pImeUnregisterWord) return FALSE;
return ime_functions.pImeUnregisterWord( reading, style, string );
}
BOOL WINAPI NotifyIME( HIMC himc, DWORD action, DWORD index, DWORD value )
{
return FALSE;
if (!ime_functions.pNotifyIME) return FALSE;
return ime_functions.pNotifyIME( himc, action, index, value );
}
BOOL WINAPI DllMain( HINSTANCE instance, DWORD reason, LPVOID reserved )
{
static HMODULE module;
switch (reason)
{
case DLL_PROCESS_ATTACH:
if (!(module = GetModuleHandleW( L"winetest_ime.dll" ))) return TRUE;
ime_functions = *(struct ime_functions *)GetProcAddress( module, "ime_functions" );
if (!ime_functions.pDllMain) return TRUE;
return ime_functions.pDllMain( instance, reason, reserved );
case DLL_PROCESS_DETACH:
if (module == instance) return TRUE;
if (!ime_functions.pDllMain) return TRUE;
ime_functions.pDllMain( instance, reason, reserved );
memset( &ime_functions, 0, sizeof(ime_functions) );
}
return TRUE;
}
......@@ -14,3 +14,4 @@
@ stdcall ImeToAsciiEx(long long ptr ptr long long)
@ stdcall ImeUnregisterWord(wstr long wstr)
@ stdcall NotifyIME(long long long long)
@ extern -private ime_functions
......@@ -2483,16 +2483,219 @@ static void test_ImmDisableIME(void)
ok(!def, "ImmGetDefaultIMEWnd(hwnd) returned %p\n", def);
}
#define ime_trace( msg, ... ) if (winetest_debug > 1) trace( "%04lx:%s " msg, GetCurrentThreadId(), __func__, ## __VA_ARGS__ )
static LRESULT CALLBACK ime_ui_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
{
ime_trace( "hwnd %p, msg %#x, wparam %#Ix, lparam %#Ix\n", hwnd, msg, wparam, lparam );
ok( 0, "unexpected call\n" );
return DefWindowProcW( hwnd, msg, wparam, lparam );
}
static WNDCLASSEXW ime_ui_class =
{
.cbSize = sizeof(WNDCLASSEXW),
.style = CS_IME,
.lpfnWndProc = ime_ui_window_proc,
.cbWndExtra = 2 * sizeof(LONG_PTR),
.lpszClassName = L"WineTestIME",
};
static BOOL WINAPI ime_ImeConfigure( HKL hkl, HWND hwnd, DWORD mode, void *data )
{
ime_trace( "hkl %p, hwnd %p, mode %lu, data %p\n", hkl, hwnd, mode, data );
ok( 0, "unexpected call\n" );
return FALSE;
}
static DWORD WINAPI ime_ImeConversionList( HIMC himc, const WCHAR *source, CANDIDATELIST *dest,
DWORD dest_len, UINT flag )
{
ime_trace( "himc %p, source %s, dest %p, dest_len %lu, flag %#x\n",
himc, debugstr_w(source), dest, dest_len, flag );
ok( 0, "unexpected call\n" );
return 0;
}
static BOOL WINAPI ime_ImeDestroy( UINT force )
{
ime_trace( "force %u\n", force );
ok( 0, "unexpected call\n" );
return TRUE;
}
static UINT WINAPI ime_ImeEnumRegisterWord( REGISTERWORDENUMPROCW proc, const WCHAR *reading, DWORD style,
const WCHAR *string, void *data )
{
ime_trace( "proc %p, reading %s, style %lu, string %s, data %p\n",
proc, debugstr_w(reading), style, debugstr_w(string), data );
ok( 0, "unexpected call\n" );
return 0;
}
static LRESULT WINAPI ime_ImeEscape( HIMC himc, UINT escape, void *data )
{
ime_trace( "himc %p, escape %#x, data %p\n", himc, escape, data );
ok( 0, "unexpected call\n" );
return TRUE;
}
static DWORD WINAPI ime_ImeGetImeMenuItems( HIMC himc, DWORD flags, DWORD type, IMEMENUITEMINFOW *parent,
IMEMENUITEMINFOW *menu, DWORD size )
{
ime_trace( "himc %p, flags %#lx, type %lu, parent %p, menu %p, size %#lx\n",
himc, flags, type, parent, menu, size );
ok( 0, "unexpected call\n" );
return 0;
}
static UINT WINAPI ime_ImeGetRegisterWordStyle( UINT item, STYLEBUFW *style )
{
ime_trace( "item %u, style %p\n", item, style );
ok( 0, "unexpected call\n" );
return 0;
}
static BOOL WINAPI ime_ImeInquire( IMEINFO *info, WCHAR *ui_class, DWORD flags )
{
ime_trace( "info %p, ui_class %p, flags %#lx\n", info, ui_class, flags );
ok( 0, "unexpected call\n" );
return TRUE;
}
static BOOL WINAPI ime_ImeProcessKey( HIMC himc, UINT vkey, LPARAM key_data, BYTE *key_state )
{
ime_trace( "himc %p, vkey %u, key_data %#Ix, key_state %p\n",
himc, vkey, key_data, key_state );
ok( 0, "unexpected call\n" );
return FALSE;
}
static BOOL WINAPI ime_ImeRegisterWord( const WCHAR *reading, DWORD style, const WCHAR *string )
{
ime_trace( "reading %s, style %lu, string %s\n", debugstr_w(reading), style, debugstr_w(string) );
ok( 0, "unexpected call\n" );
return FALSE;
}
static BOOL WINAPI ime_ImeSelect( HIMC himc, BOOL select )
{
ime_trace( "himc %p, select %d\n", himc, select );
ok( 0, "unexpected call\n" );
return FALSE;
}
static BOOL WINAPI ime_ImeSetActiveContext( HIMC himc, BOOL flag )
{
ime_trace( "himc %p, flag %#x\n", himc, flag );
ok( 0, "unexpected call\n" );
return FALSE;
}
static BOOL WINAPI ime_ImeSetCompositionString( HIMC himc, DWORD index, const void *comp, DWORD comp_len,
const void *read, DWORD read_len )
{
ime_trace( "himc %p, index %lu, comp %p, comp_len %lu, read %p, read_len %lu\n",
himc, index, comp, comp_len, read, read_len );
ok( 0, "unexpected call\n" );
return FALSE;
}
static UINT WINAPI ime_ImeToAsciiEx( UINT vkey, UINT scan_code, BYTE *key_state, TRANSMSGLIST *msgs, UINT state, HIMC himc )
{
ime_trace( "vkey %u, scan_code %u, key_state %p, msgs %p, state %u, himc %p\n",
vkey, scan_code, key_state, msgs, state, himc );
ok( 0, "unexpected call\n" );
return 0;
}
static BOOL WINAPI ime_ImeUnregisterWord( const WCHAR *reading, DWORD style, const WCHAR *string )
{
ime_trace( "reading %s, style %lu, string %s\n", debugstr_w(reading), style, debugstr_w(string) );
ok( 0, "unexpected call\n" );
return FALSE;
}
static BOOL WINAPI ime_NotifyIME( HIMC himc, DWORD action, DWORD index, DWORD value )
{
ime_trace( "himc %p, action %lu, index %lu, value %lu\n", himc, action, index, value );
ok( 0, "unexpected call\n" );
return FALSE;
}
static BOOL WINAPI ime_DllMain( HINSTANCE instance, DWORD reason, LPVOID reserved )
{
ime_trace( "instance %p, reason %lu, reserved %p.\n", instance, reason, reserved );
switch (reason)
{
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls( instance );
ime_ui_class.hInstance = instance;
RegisterClassExW( &ime_ui_class );
break;
case DLL_PROCESS_DETACH:
UnregisterClassW( ime_ui_class.lpszClassName, instance );
break;
}
return TRUE;
}
static struct ime_functions ime_functions =
{
ime_ImeConfigure,
ime_ImeConversionList,
ime_ImeDestroy,
ime_ImeEnumRegisterWord,
ime_ImeEscape,
ime_ImeGetImeMenuItems,
ime_ImeGetRegisterWordStyle,
ime_ImeInquire,
ime_ImeProcessKey,
ime_ImeRegisterWord,
ime_ImeSelect,
ime_ImeSetActiveContext,
ime_ImeSetCompositionString,
ime_ImeToAsciiEx,
ime_ImeUnregisterWord,
ime_NotifyIME,
ime_DllMain,
};
static UINT ime_count;
static WCHAR ime_path[MAX_PATH];
static HKL ime_install(void)
{
WCHAR buffer[MAX_PATH];
HMODULE module;
DWORD len, ret;
HKEY hkey;
HKL hkl;
/* IME module gets cached and won't reload from disk as soon as a window has
* loaded it. To workaround the issue we load the module first as a DLL,
* set its function pointers from the test, and later when the cached IME
* gets loaded, read the function pointers from the separately loaded DLL.
*/
load_resource( L"ime_wrapper.dll", buffer );
SetLastError( 0xdeadbeef );
ret = MoveFileW( buffer, L"c:\\windows\\system32\\winetest_ime.dll" );
if (!ret)
{
ok( GetLastError() == ERROR_ACCESS_DENIED, "got error %lu\n", GetLastError() );
win_skip( "Failed to copy DLL to system directory\n" );
return 0;
}
module = LoadLibraryW( L"c:\\windows\\system32\\winetest_ime.dll" );
ok( !!module, "LoadLibraryW failed, error %lu\n", GetLastError() );
*(struct ime_functions *)GetProcAddress( module, "ime_functions" ) = ime_functions;
/* install the actual IME module, it will lookup the functions from the DLL */
load_resource( L"ime_wrapper.dll", buffer );
......@@ -2540,6 +2743,7 @@ static HKL ime_install(void)
static void ime_cleanup( HKL hkl )
{
HMODULE module = GetModuleHandleW( L"winetest_ime.dll" );
WCHAR buffer[MAX_PATH], value[MAX_PATH];
DWORD i, buffer_len, value_len, ret;
HKEY hkey;
......@@ -2573,6 +2777,12 @@ static void ime_cleanup( HKL hkl )
todo_wine_if( GetLastError() == ERROR_ACCESS_DENIED )
ok( ret || broken( !ret ) /* sometimes still in use */,
"DeleteFileW failed, error %lu\n", GetLastError() );
ret = FreeLibrary( module );
ok( ret, "FreeLibrary failed, error %lu\n", GetLastError() );
ret = DeleteFileW( L"c:\\windows\\system32\\winetest_ime.dll" );
ok( ret, "DeleteFileW failed, error %lu\n", GetLastError() );
}
static void test_ImmInstallIME(void)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment