Commit 16222f2d authored by Rémi Bernon's avatar Rémi Bernon Committed by Alexandre Julliard

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
......@@ -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)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment