mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-06 15:04:44 +00:00
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.
This commit is contained in:
parent
d07a5e6b91
commit
16222f2de6
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue