Redirecting its calls to the test executable for easier testing and to wokaround some Windows IME caching mechanism that prevent the IME module from reloading.
-- v3: imm32/tests: Test ImmGetIMEFileName with the installed IME. imm32/tests: Test ImmGetDescription with the installed IME. imm32/tests: Test ImmInstallIMEW with an actual IME. imm32/tests: Add broken test results for w10v22H2. include: Allow overriding LANGID in module VERSIONINFO. makedep: Support resource files for embedded TESTDLL.
From: Rémi Bernon rbernon@codeweavers.com
--- tools/makedep.c | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-)
diff --git a/tools/makedep.c b/tools/makedep.c index 532145de292..3e25d83bc01 100644 --- a/tools/makedep.c +++ b/tools/makedep.c @@ -97,9 +97,10 @@ struct incl_file #define FLAG_IDL_HEADER 0x008000 /* generates a header (.h) file */ #define FLAG_RC_PO 0x010000 /* rc file contains translations */ #define FLAG_RC_HEADER 0x020000 /* rc file is a header */ -#define FLAG_C_IMPLIB 0x040000 /* file is part of an import library */ -#define FLAG_C_UNIX 0x080000 /* file is part of a Unix library */ -#define FLAG_SFD_FONTS 0x100000 /* sfd file generated bitmap fonts */ +#define FLAG_RC_TESTDLL 0x040000 /* rc file is for a test dll */ +#define FLAG_C_IMPLIB 0x080000 /* file is part of an import library */ +#define FLAG_C_UNIX 0x100000 /* file is part of a Unix library */ +#define FLAG_SFD_FONTS 0x200000 /* sfd file generated bitmap fonts */
static const struct { @@ -939,6 +940,7 @@ static void parse_pragma_directive( struct file *source, char *str ) { if (!strcmp( flag, "header" )) source->flags |= FLAG_RC_HEADER; else if (!strcmp( flag, "po" )) source->flags |= FLAG_RC_PO; + else if (!strcmp( flag, "testdll" )) source->flags |= FLAG_RC_TESTDLL; } else if (strendswith( source->name, ".sfd" )) { @@ -2744,8 +2746,14 @@ static void output_source_rc( struct makefile *make, struct incl_file *source, c if (source->file->flags & FLAG_RC_HEADER) return; if (source->file->flags & FLAG_GENERATED) strarray_add( &make->clean_files, source->name ); if (linguas.count && (source->file->flags & FLAG_RC_PO)) po_dir = "po"; - for (arch = 0; arch < archs.count; arch++) - if (!make->disabled[arch]) strarray_add( &make->res_files[arch], res_file ); + if (!(source->file->flags & FLAG_RC_TESTDLL)) + { + for (arch = 0; arch < archs.count; arch++) + { + if (make->disabled[arch]) continue; + strarray_add( &make->res_files[arch], res_file ); + } + } if (source->file->flags & FLAG_RC_PO) { strarray_add( &make->pot_files, strmake( "%s.pot", obj )); @@ -3070,11 +3078,11 @@ static void output_source_in( struct makefile *make, struct incl_file *source, c */ static void output_source_spec( struct makefile *make, struct incl_file *source, const char *obj ) { + const char *dll_name, *obj_name, *res_name, *output_file, *debug_file, *output_rsrc; struct strarray imports = get_expanded_file_local_var( make, obj, "IMPORTS" ); struct strarray dll_flags = empty_strarray; struct strarray default_imports = empty_strarray; struct strarray all_libs, dep_libs; - const char *dll_name, *obj_name, *res_name, *output_file, *debug_file; unsigned int arch;
if (!imports.count) imports = make->imports; @@ -3091,12 +3099,15 @@ static void output_source_spec( struct makefile *make, struct incl_file *source, if (!arch) strarray_addall( &all_libs, libs ); dll_name = arch_module_name( strmake( "%s.dll", obj ), arch ); obj_name = obj_dir_path( make, strmake( "%s%s.o", arch_dirs[arch], obj )); - res_name = strmake( "%s%s.res", arch_dirs[arch], obj ); output_file = obj_dir_path( make, dll_name ); + output_rsrc = strmake( "%s.res", dll_name ); + + if (!find_src_file( make, strmake( "%s.rc", obj ))) res_name = NULL; + else res_name = obj_dir_path( make, strmake( "%s.res", obj ));
strarray_add( &make->clean_files, dll_name ); - strarray_add( &make->res_files[arch], res_name ); - output( "%s:", obj_dir_path( make, res_name )); + strarray_add( &make->res_files[arch], output_rsrc ); + output( "%s:", obj_dir_path( make, output_rsrc )); output_filename( output_file ); output_filename( tools_path( make, "wrc" )); output( "\n" ); @@ -3106,6 +3117,7 @@ static void output_source_spec( struct makefile *make, struct incl_file *source, output( "%s:", output_file ); output_filename( source->filename ); output_filename( obj_name ); + if (res_name) output_filename( res_name ); output_filenames( dep_libs ); output_filename( tools_path( make, "winebuild" )); output_filename( tools_path( make, "winegcc" )); @@ -3117,6 +3129,7 @@ static void output_source_spec( struct makefile *make, struct incl_file *source, output_filename( "-shared" ); output_filename( source->filename ); output_filename( obj_name ); + if (res_name) output_filename( res_name ); if ((debug_file = get_debug_file( make, dll_name, arch ))) output_filename( strmake( "-Wl,--debug-file,%s", obj_dir_path( make, debug_file ))); output_filenames( all_libs );
From: Rémi Bernon rbernon@codeweavers.com
--- include/wine/wine_common_ver.rc | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/include/wine/wine_common_ver.rc b/include/wine/wine_common_ver.rc index 95ab04666e8..d79062416ed 100644 --- a/include/wine/wine_common_ver.rc +++ b/include/wine/wine_common_ver.rc @@ -115,6 +115,12 @@ never complain. #define WINE_CODEPAGE_HEX WINE_VER_HEXPREFIX(WINE_CODEPAGE) #endif
+#ifndef WINE_LANGID +#define WINE_LANGID 0409 /* LANG_ENGLISH/SUBLANG_DEFAULT */ +#endif +#define WINE_LANGID_STR WINE_VER_STRINGIZE(WINE_LANGID) +#define WINE_LANGID_HEX WINE_VER_HEXPREFIX(WINE_LANGID) + VS_VERSION_INFO VERSIONINFO FILEVERSION WINE_FILEVERSION PRODUCTVERSION WINE_PRODUCTVERSION @@ -126,8 +132,7 @@ FILESUBTYPE WINE_FILESUBTYPE { BLOCK "StringFileInfo" { - /* LANG_ENGLISH/SUBLANG_DEFAULT, WINE_CODEPAGE */ - BLOCK "0409" WINE_CODEPAGE_STR + BLOCK WINE_LANGID_STR WINE_CODEPAGE_STR { VALUE "CompanyName", "Microsoft Corporation" /* GameGuard depends on this */ VALUE "FileDescription", WINE_FILEDESCRIPTION_STR @@ -142,7 +147,6 @@ FILESUBTYPE WINE_FILESUBTYPE } BLOCK "VarFileInfo" { - /* LANG_ENGLISH/SUBLANG_DEFAULT, WINE_CODEPAGE */ - VALUE "Translation", 0x0409, WINE_CODEPAGE_HEX + VALUE "Translation", WINE_LANGID_HEX, WINE_CODEPAGE_HEX } }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/imm32/tests/imm32.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/dlls/imm32/tests/imm32.c b/dlls/imm32/tests/imm32.c index a97457320ce..00e192cb180 100644 --- a/dlls/imm32/tests/imm32.c +++ b/dlls/imm32/tests/imm32.c @@ -2285,7 +2285,9 @@ static DWORD WINAPI com_initialization_thread(void *arg)
static void test_com_initialization(void) { + APTTYPEQUALIFIER qualifier; HANDLE thread; + APTTYPE type; HRESULT hr; HWND wnd; BOOL r; @@ -2340,13 +2342,17 @@ static void test_com_initialization(void) ok(hr == S_OK, "CoInitialize returned %lx\n", hr); test_apttype(APTTYPE_MTA); DestroyWindow(wnd); - test_apttype(-1); + + hr = CoGetApartmentType(&type, &qualifier); + ok(hr == CO_E_NOTINITIALIZED || broken(hr == S_OK) /* w10v22H2 */, + "CoGetApartmentType returned %#lx\n", hr); + test_apttype(hr == S_OK ? APTTYPE_MTA : -1);
wnd = CreateWindowA("static", "static", WS_POPUP, 0, 0, 100, 100, 0, 0, 0, 0); ok(wnd != NULL, "CreateWindow failed\n"); - test_apttype(-1); + test_apttype(hr == S_OK ? APTTYPE_MTA : -1); ShowWindow(wnd, SW_SHOW); - test_apttype(APTTYPE_MAINSTA); + test_apttype(hr == S_OK ? APTTYPE_MTA : APTTYPE_MAINSTA); DestroyWindow(wnd); test_apttype(-1); }
From: Rémi Bernon rbernon@codeweavers.com
Redirecting its calls to the test executable for easier testing and to wokaround some Windows IME caching mechanism that prevent the IME module from reloading. --- dlls/imm32/tests/Makefile.in | 9 +- dlls/imm32/tests/ime_test.h | 56 +++++ dlls/imm32/tests/ime_wrapper.c | 142 +++++++++++ dlls/imm32/tests/ime_wrapper.rc | 28 +++ dlls/imm32/tests/ime_wrapper.spec | 17 ++ dlls/imm32/tests/imm32.c | 395 +++++++++++++++++++++++++++++- 6 files changed, 642 insertions(+), 5 deletions(-) create mode 100644 dlls/imm32/tests/ime_test.h create mode 100644 dlls/imm32/tests/ime_wrapper.c create mode 100644 dlls/imm32/tests/ime_wrapper.rc create mode 100644 dlls/imm32/tests/ime_wrapper.spec
diff --git a/dlls/imm32/tests/Makefile.in b/dlls/imm32/tests/Makefile.in index d0881429e34..141b1fd8a97 100644 --- a/dlls/imm32/tests/Makefile.in +++ b/dlls/imm32/tests/Makefile.in @@ -1,5 +1,8 @@ TESTDLL = imm32.dll -IMPORTS = imm32 ole32 user32 +IMPORTS = imm32 ole32 user32 advapi32
-C_SRCS = \ - imm32.c +SOURCES = \ + imm32.c \ + ime_wrapper.c \ + ime_wrapper.rc \ + ime_wrapper.spec diff --git a/dlls/imm32/tests/ime_test.h b/dlls/imm32/tests/ime_test.h new file mode 100644 index 00000000000..fda8065276d --- /dev/null +++ b/dlls/imm32/tests/ime_test.h @@ -0,0 +1,56 @@ +/* + * Copyright 2023 Rémi Bernon for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __WINE_IME_TEST_H +#define __WINE_IME_TEST_H + +#include <stdarg.h> +#include <stddef.h> + +#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "wingdi.h" + +#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 */ diff --git a/dlls/imm32/tests/ime_wrapper.c b/dlls/imm32/tests/ime_wrapper.c new file mode 100644 index 00000000000..d8a03499549 --- /dev/null +++ b/dlls/imm32/tests/ime_wrapper.c @@ -0,0 +1,142 @@ +/* + * Copyright 2023 Rémi Bernon for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "ime_test.h" + +struct ime_functions ime_functions = {0}; + +BOOL WINAPI ImeConfigure( HKL hkl, HWND hwnd, DWORD mode, void *data ) +{ + 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 ) +{ + if (!ime_functions.pImeConversionList) return 0; + return ime_functions.pImeConversionList( himc, source, dest, dest_len, flag ); +} + +BOOL WINAPI ImeDestroy( UINT force ) +{ + 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 ) +{ + if (!ime_functions.pImeEnumRegisterWord) return 0; + return ime_functions.pImeEnumRegisterWord( proc, reading, style, string, data ); +} + +LRESULT WINAPI ImeEscape( HIMC himc, UINT escape, void *data ) +{ + 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 ) +{ + if (!ime_functions.pImeGetImeMenuItems) return 0; + return ime_functions.pImeGetImeMenuItems( himc, flags, type, parent, menu, size ); +} + +UINT WINAPI ImeGetRegisterWordStyle( UINT item, STYLEBUFW *style_buf ) +{ + if (!ime_functions.pImeGetRegisterWordStyle) return 0; + return ime_functions.pImeGetRegisterWordStyle( item, style_buf ); +} + +BOOL WINAPI ImeInquire( IMEINFO *info, WCHAR *ui_class, DWORD flags ) +{ + 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 ) +{ + 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 ) +{ + if (!ime_functions.pImeRegisterWord) return FALSE; + return ime_functions.pImeRegisterWord( reading, style, string ); +} + +BOOL WINAPI ImeSelect( HIMC himc, BOOL select ) +{ + if (!ime_functions.pImeSelect) return FALSE; + return ime_functions.pImeSelect( himc, select ); +} + +BOOL WINAPI ImeSetActiveContext( HIMC himc, BOOL flag ) +{ + 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 ) +{ + 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 ) +{ + 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 ) +{ + if (!ime_functions.pImeUnregisterWord) return FALSE; + return ime_functions.pImeUnregisterWord( reading, style, string ); +} + +BOOL WINAPI NotifyIME( HIMC himc, DWORD action, DWORD index, DWORD value ) +{ + 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; +} diff --git a/dlls/imm32/tests/ime_wrapper.rc b/dlls/imm32/tests/ime_wrapper.rc new file mode 100644 index 00000000000..6844b62195b --- /dev/null +++ b/dlls/imm32/tests/ime_wrapper.rc @@ -0,0 +1,28 @@ +/* + * Copyright 2023 Rémi Bernon for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#pragma makedep testdll + +#define WINE_LANGID 0400 +#define WINE_FILETYPE VFT_DRV +#define WINE_FILESUBTYPE VFT2_DRV_INPUTMETHOD +#define WINE_FILENAME "ime_wrapper" +#define WINE_FILENAME_STR "ime_wrapper.dll" +#define WINE_FILEDESCRIPTION_STR "WineTest IME" + +#include "wine/wine_common_ver.rc" diff --git a/dlls/imm32/tests/ime_wrapper.spec b/dlls/imm32/tests/ime_wrapper.spec new file mode 100644 index 00000000000..05a60e84a5d --- /dev/null +++ b/dlls/imm32/tests/ime_wrapper.spec @@ -0,0 +1,17 @@ +@ stdcall ImeConfigure(long long long ptr) +@ stdcall ImeConversionList(long wstr ptr long long) +@ stdcall ImeDestroy(long) +@ stdcall ImeEnumRegisterWord(ptr wstr long wstr ptr) +@ stdcall ImeEscape(long long ptr) +@ stdcall ImeGetImeMenuItems(long long long ptr ptr long) +@ stdcall ImeGetRegisterWordStyle(long ptr) +@ stdcall ImeInquire(ptr wstr wstr) +@ stdcall ImeProcessKey(long long long ptr) +@ stdcall ImeRegisterWord(wstr long wstr) +@ stdcall ImeSelect(long long) +@ stdcall ImeSetActiveContext(long long) +@ stdcall ImeSetCompositionString(long long ptr long ptr long) +@ stdcall ImeToAsciiEx(long long ptr ptr long long) +@ stdcall ImeUnregisterWord(wstr long wstr) +@ stdcall NotifyIME(long long long long) +@ extern -private ime_functions diff --git a/dlls/imm32/tests/imm32.c b/dlls/imm32/tests/imm32.c index 00e192cb180..fadf06cce7c 100644 --- a/dlls/imm32/tests/imm32.c +++ b/dlls/imm32/tests/imm32.c @@ -18,7 +18,13 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
-#include <stdio.h> +#include <stdarg.h> +#include <stddef.h> + +#include "ntstatus.h" +#define WIN32_NO_STATUS +#include "windef.h" +#include "winbase.h"
#include "wine/test.h" #include "objbase.h" @@ -27,6 +33,8 @@ #include "imm.h" #include "immdev.h"
+#include "ime_test.h" + BOOL WINAPI ImmSetActiveContext(HWND, HIMC, BOOL);
static BOOL (WINAPI *pImmAssociateContextEx)(HWND,HIMC,DWORD); @@ -206,6 +214,28 @@ static HWND hwnd, child;
static HWND get_ime_window(void);
+static void load_resource( const WCHAR *name, WCHAR *filename ) +{ + static WCHAR path[MAX_PATH]; + DWORD written; + HANDLE file; + HRSRC res; + void *ptr; + + GetTempPathW( ARRAY_SIZE(path), path ); + GetTempFileNameW( path, name, 0, filename ); + + file = CreateFileW( filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 ); + ok( file != INVALID_HANDLE_VALUE, "failed to create %s, error %lu\n", debugstr_w(filename), GetLastError() ); + + res = FindResourceW( NULL, name, L"TESTDLL" ); + ok( res != 0, "couldn't find resource\n" ); + ptr = LockResource( LoadResource( GetModuleHandleW( NULL ), res ) ); + WriteFile( file, ptr, SizeofResource( GetModuleHandleW( NULL ), res ), &written, NULL ); + ok( written == SizeofResource( GetModuleHandleW( NULL ), res ), "couldn't write resource\n" ); + CloseHandle( file ); +} + static LRESULT WINAPI wndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { HWND default_ime_wnd; @@ -2453,7 +2483,365 @@ static void test_ImmDisableIME(void) ok(!def, "ImmGetDefaultIMEWnd(hwnd) returned %p\n", def); }
-START_TEST(imm32) { +#define ime_trace( msg, ... ) if (winetest_debug > 1) trace( "%04lx:%s " msg, GetCurrentThreadId(), __func__, ## __VA_ARGS__ ) + +DEFINE_EXPECT( ImeInquire ); +DEFINE_EXPECT( ImeDestroy ); +DEFINE_EXPECT( ImeEscape ); +DEFINE_EXPECT( IME_DLL_PROCESS_ATTACH ); +DEFINE_EXPECT( IME_DLL_PROCESS_DETACH ); + +static IMEINFO ime_info; + +static LRESULT CALLBACK ime_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_class = +{ + .cbSize = sizeof(WNDCLASSEXW), + .style = CS_IME, + .lpfnWndProc = ime_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 ); + + CHECK_EXPECT( ImeDestroy ); + + ok( !force, "got force %u\n", force ); + + 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 ); + + CHECK_EXPECT( ImeEscape ); + + ok( escape == 0xdeadbeef, "got escape %#x\n", escape ); + ok( !data, "got data %p\n", data ); + + 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 ); + + CHECK_EXPECT( ImeInquire ); + + ok( !!info, "got info %p\n", info ); + ok( !!ui_class, "got ui_class %p\n", ui_class ); + ok( !flags, "got flags %#lx\n", flags ); + + *info = ime_info; + + if (ime_info.fdwProperty & IME_PROP_UNICODE) + wcscpy( ui_class, ime_class.lpszClassName ); + else + WideCharToMultiByte( CP_ACP, 0, ime_class.lpszClassName, -1, + (char *)ui_class, 17, NULL, NULL ); + + 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_class.hInstance = instance; + RegisterClassExW( &ime_class ); + CHECK_EXPECT( IME_DLL_PROCESS_ATTACH ); + break; + + case DLL_PROCESS_DETACH: + UnregisterClassW( ime_class.lpszClassName, instance ); + todo_wine CHECK_EXPECT( IME_DLL_PROCESS_DETACH ); + 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[100], filename[MAX_PATH]; + HMODULE module = 0; + BOOL ret; + 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", filename ); + + SetLastError( 0xdeadbeef ); + ret = MoveFileW( filename, 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", filename ); + + SetLastError( 0xdeadbeef ); + swprintf( ime_path, ARRAY_SIZE(ime_path), L"c:\windows\system32\wine%04x.ime", ime_count++ ); + ret = MoveFileW( filename, ime_path ); + todo_wine_if( GetLastError() == ERROR_ALREADY_EXISTS ) + ok( ret || broken( !ret ) /* sometimes still in use */, + "MoveFileW failed, error %lu\n", GetLastError() ); + + hkl = ImmInstallIMEW( ime_path, L"WineTest IME" ); + todo_wine + ok( hkl == (HKL)( int)0xe0200400, "ImmInstallIMEW returned %p, error %lu\n", hkl, GetLastError() ); + + ret = ImmGetDescriptionW( hkl, buffer, ARRAY_SIZE(buffer) ); + ok( ret, "ImmGetDescriptionW failed, error %lu\n", GetLastError() ); + todo_wine + ok( !wcscmp( buffer, L"WineTest IME" ), "ImmGetDescriptionW returned %s\n", debugstr_w(buffer) ); + + return hkl; +} + +static void ime_cleanup( HKL hkl ) +{ + HMODULE module = GetModuleHandleW( L"winetest_ime.dll" ); + WCHAR buffer[MAX_PATH]; + DWORD ret; + + UnloadKeyboardLayout( hkl ); + + swprintf( buffer, ARRAY_SIZE(buffer), L"System\CurrentControlSet\Control\Keyboard Layouts\%08x", hkl ); + ret = RegDeleteKeyW( HKEY_LOCAL_MACHINE, buffer ); + ok( !ret, "RegDeleteKeyW returned %#lx, error %lu\n", ret, GetLastError() ); + + ret = DeleteFileW( ime_path ); + 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( BOOL unicode ) +{ + HKL hkl; + + winetest_push_context( unicode ? "unicode" : "ansi" ); + + SET_ENABLE( IME_DLL_PROCESS_ATTACH, TRUE ); + SET_ENABLE( ImeInquire, TRUE ); + SET_ENABLE( ImeEscape, TRUE ); + SET_ENABLE( ImeDestroy, TRUE ); + SET_ENABLE( IME_DLL_PROCESS_DETACH, TRUE ); + + /* IME_PROP_END_UNLOAD for the IME to unload / reload. */ + ime_info.fdwProperty = IME_PROP_END_UNLOAD; + if (unicode) ime_info.fdwProperty |= IME_PROP_UNICODE; + + if (!(hkl = ime_install())) goto cleanup; + + SET_EXPECT( IME_DLL_PROCESS_ATTACH ); + SET_EXPECT( ImeInquire ); + SET_EXPECT( ImeEscape ); + SET_EXPECT( ImeDestroy ); + SET_EXPECT( IME_DLL_PROCESS_DETACH ); + + ImmEscapeA( hkl, 0, 0xdeadbeef, NULL ); + + todo_wine_if( unicode ) + CHECK_CALLED( IME_DLL_PROCESS_ATTACH ); + todo_wine_if( unicode ) + CHECK_CALLED( ImeInquire ); + CHECK_CALLED( ImeEscape ); + todo_wine + CHECK_CALLED( ImeDestroy ); + todo_wine + CHECK_CALLED( IME_DLL_PROCESS_DETACH ); + + SET_EXPECT( IME_DLL_PROCESS_ATTACH ); + SET_EXPECT( ImeInquire ); + SET_EXPECT( ImeEscape ); + SET_EXPECT( ImeDestroy ); + SET_EXPECT( IME_DLL_PROCESS_DETACH ); + + ImmEscapeW( hkl, 0, 0xdeadbeef, NULL ); + + todo_wine + CHECK_CALLED( IME_DLL_PROCESS_ATTACH ); + todo_wine + CHECK_CALLED( ImeInquire ); + CHECK_CALLED( ImeEscape ); + todo_wine + CHECK_CALLED( ImeDestroy ); + todo_wine + CHECK_CALLED( IME_DLL_PROCESS_DETACH ); + + ime_cleanup( hkl ); + +cleanup: + SET_ENABLE( IME_DLL_PROCESS_ATTACH, FALSE ); + SET_ENABLE( ImeInquire, FALSE ); + SET_ENABLE( ImeEscape, FALSE ); + SET_ENABLE( ImeDestroy, FALSE ); + SET_ENABLE( IME_DLL_PROCESS_DETACH, FALSE ); + + winetest_pop_context(); +} + +START_TEST(imm32) +{ if (!is_ime_enabled()) { win_skip("IME support not implemented\n"); @@ -2462,6 +2850,9 @@ START_TEST(imm32) {
test_com_initialization();
+ test_ImmInstallIME( FALSE ); + test_ImmInstallIME( TRUE ); + if (init()) { test_ImmNotifyIME();
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/imm32/tests/imm32.c | 165 ++++++++++++++++++++++++--------------- 1 file changed, 102 insertions(+), 63 deletions(-)
diff --git a/dlls/imm32/tests/imm32.c b/dlls/imm32/tests/imm32.c index fadf06cce7c..252bab7d6d1 100644 --- a/dlls/imm32/tests/imm32.c +++ b/dlls/imm32/tests/imm32.c @@ -1194,61 +1194,6 @@ static void test_ImmGetContext(void) ok(ImmReleaseContext(hwnd, himc), "ImmReleaseContext failed\n"); }
-static void test_ImmGetDescription(void) -{ - HKL hkl; - WCHAR descW[100]; - CHAR descA[100]; - UINT ret, lret; - - /* FIXME: invalid keyboard layouts should not pass */ - ret = ImmGetDescriptionW(NULL, NULL, 0); - ok(!ret, "ImmGetDescriptionW failed, expected 0 received %d.\n", ret); - ret = ImmGetDescriptionA(NULL, NULL, 0); - ok(!ret, "ImmGetDescriptionA failed, expected 0 received %d.\n", ret); - - /* load a language with valid IMM descriptions */ - hkl = GetKeyboardLayout(0); - ok(hkl != 0, "GetKeyboardLayout failed, expected != 0.\n"); - - ret = ImmGetDescriptionW(hkl, NULL, 0); - if(!ret) - { - win_skip("ImmGetDescriptionW is not working for current loaded keyboard.\n"); - return; - } - - SetLastError(0xdeadcafe); - ret = ImmGetDescriptionW(0, NULL, 100); - ok (ret == 0, "ImmGetDescriptionW with 0 hkl should return 0\n"); - ret = GetLastError(); - ok (ret == 0xdeadcafe, "Last Error should remain unchanged\n"); - - ret = ImmGetDescriptionW(hkl, descW, 0); - ok(ret, "ImmGetDescriptionW failed, expected != 0 received 0.\n"); - - lret = ImmGetDescriptionW(hkl, descW, ret + 1); - ok(lret, "ImmGetDescriptionW failed, expected != 0 received 0.\n"); - ok(lret == ret, "ImmGetDescriptionW failed to return the correct amount of data. Expected %d, got %d.\n", ret, lret); - - lret = ImmGetDescriptionA(hkl, descA, ret + 1); - ok(lret, "ImmGetDescriptionA failed, expected != 0 received 0.\n"); - ok(lret == ret, "ImmGetDescriptionA failed to return the correct amount of data. Expected %d, got %d.\n", ret, lret); - - ret /= 2; /* try to copy partially */ - lret = ImmGetDescriptionW(hkl, descW, ret + 1); - ok(lret, "ImmGetDescriptionW failed, expected != 0 received 0.\n"); - ok(lret == ret, "ImmGetDescriptionW failed to return the correct amount of data. Expected %d, got %d.\n", ret, lret); - - lret = ImmGetDescriptionA(hkl, descA, ret + 1); - ok(!lret, "ImmGetDescriptionA should fail\n"); - - ret = ImmGetDescriptionW(hkl, descW, 1); - ok(!ret, "ImmGetDescriptionW failed, expected 0 received %d.\n", ret); - - UnloadKeyboardLayout(hkl); -} - static LRESULT (WINAPI *old_imm_wnd_proc)(HWND, UINT, WPARAM, LPARAM); static LRESULT WINAPI imm_wnd_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { @@ -2702,9 +2647,9 @@ static WCHAR ime_path[MAX_PATH];
static HKL ime_install(void) { - WCHAR buffer[100], filename[MAX_PATH]; + WCHAR filename[MAX_PATH]; HMODULE module = 0; - BOOL ret; + DWORD ret; HKL hkl;
/* IME module gets cached and won't reload from disk as soon as a window has @@ -2742,11 +2687,6 @@ static HKL ime_install(void) todo_wine ok( hkl == (HKL)( int)0xe0200400, "ImmInstallIMEW returned %p, error %lu\n", hkl, GetLastError() );
- ret = ImmGetDescriptionW( hkl, buffer, ARRAY_SIZE(buffer) ); - ok( ret, "ImmGetDescriptionW failed, error %lu\n", GetLastError() ); - todo_wine - ok( !wcscmp( buffer, L"WineTest IME" ), "ImmGetDescriptionW returned %s\n", debugstr_w(buffer) ); - return hkl; }
@@ -2840,6 +2780,104 @@ cleanup: winetest_pop_context(); }
+static void test_ImmGetDescription( BOOL unicode ) +{ + HKL hkl = GetKeyboardLayout( 0 ); + WCHAR bufferW[MAX_PATH]; + char bufferA[MAX_PATH]; + DWORD ret; + + SET_ENABLE( IME_DLL_PROCESS_ATTACH, TRUE ); + SET_ENABLE( ImeInquire, TRUE ); + SET_ENABLE( ImeDestroy, TRUE ); + SET_ENABLE( IME_DLL_PROCESS_DETACH, TRUE ); + + winetest_push_context( unicode ? "unicode" : "ansi" ); + + SetLastError( 0xdeadbeef ); + ret = ImmGetDescriptionW( NULL, NULL, 0 ); + ok( !ret, "ImmGetDescriptionW returned %lu\n", ret ); + ret = ImmGetDescriptionA( NULL, NULL, 0 ); + ok( !ret, "ImmGetDescriptionA returned %lu\n", ret ); + ret = ImmGetDescriptionW( NULL, NULL, 100 ); + ok( !ret, "ImmGetDescriptionW returned %lu\n", ret ); + ret = ImmGetDescriptionA( NULL, NULL, 100 ); + ok( !ret, "ImmGetDescriptionA returned %lu\n", ret ); + ret = ImmGetDescriptionW( hkl, bufferW, 100 ); + todo_wine + ok( !ret, "ImmGetDescriptionW returned %lu\n", ret ); + ret = ImmGetDescriptionA( hkl, bufferA, 100 ); + todo_wine + ok( !ret, "ImmGetDescriptionA returned %lu\n", ret ); + ret = GetLastError(); + ok( ret == 0xdeadbeef, "got error %lu\n", ret ); + + /* IME_PROP_END_UNLOAD for the IME to unload / reload. */ + ime_info.fdwProperty = IME_PROP_END_UNLOAD; + if (unicode) ime_info.fdwProperty |= IME_PROP_UNICODE; + + if (!(hkl = ime_install())) goto cleanup; + + memset( bufferW, 0xcd, sizeof(bufferW) ); + ret = ImmGetDescriptionW( hkl, bufferW, 2 ); + ok( ret == 1, "ImmGetDescriptionW returned %lu\n", ret ); + ok( !wcscmp( bufferW, L"W" ), "got bufferW %s\n", debugstr_w(bufferW) ); + memset( bufferA, 0xcd, sizeof(bufferA) ); + ret = ImmGetDescriptionA( hkl, bufferA, 2 ); + ok( ret == 0, "ImmGetDescriptionA returned %lu\n", ret ); + todo_wine + ok( !strcmp( bufferA, "" ), "got bufferA %s\n", debugstr_a(bufferA) ); + + memset( bufferW, 0xcd, sizeof(bufferW) ); + ret = ImmGetDescriptionW( hkl, bufferW, 11 ); + todo_wine + ok( ret == 10, "ImmGetDescriptionW returned %lu\n", ret ); + todo_wine + ok( !wcscmp( bufferW, L"WineTest I" ), "got bufferW %s\n", debugstr_w(bufferW) ); + memset( bufferA, 0xcd, sizeof(bufferA) ); + ret = ImmGetDescriptionA( hkl, bufferA, 11 ); + todo_wine + ok( ret == 0, "ImmGetDescriptionA returned %lu\n", ret ); + todo_wine + ok( !strcmp( bufferA, "" ), "got bufferA %s\n", debugstr_a(bufferA) ); + + memset( bufferW, 0xcd, sizeof(bufferW) ); + ret = ImmGetDescriptionW( hkl, bufferW, 12 ); + todo_wine + ok( ret == 11, "ImmGetDescriptionW returned %lu\n", ret ); + todo_wine + ok( !wcscmp( bufferW, L"WineTest IM" ), "got bufferW %s\n", debugstr_w(bufferW) ); + memset( bufferA, 0xcd, sizeof(bufferA) ); + ret = ImmGetDescriptionA( hkl, bufferA, 12 ); + todo_wine + ok( ret == 12, "ImmGetDescriptionA returned %lu\n", ret ); + todo_wine + ok( !strcmp( bufferA, "WineTest IME" ), "got bufferA %s\n", debugstr_a(bufferA) ); + + memset( bufferW, 0xcd, sizeof(bufferW) ); + ret = ImmGetDescriptionW( hkl, bufferW, 13 ); + todo_wine + ok( ret == 12, "ImmGetDescriptionW returned %lu\n", ret ); + todo_wine + ok( !wcscmp( bufferW, L"WineTest IME" ), "got bufferW %s\n", debugstr_w(bufferW) ); + memset( bufferA, 0xcd, sizeof(bufferA) ); + ret = ImmGetDescriptionA( hkl, bufferA, 13 ); + todo_wine + ok( ret == 12, "ImmGetDescriptionA returned %lu\n", ret ); + todo_wine + ok( !strcmp( bufferA, "WineTest IME" ), "got bufferA %s\n", debugstr_a(bufferA) ); + + ime_cleanup( hkl ); + +cleanup: + SET_ENABLE( IME_DLL_PROCESS_ATTACH, FALSE ); + SET_ENABLE( ImeInquire, FALSE ); + SET_ENABLE( ImeDestroy, FALSE ); + SET_ENABLE( IME_DLL_PROCESS_DETACH, FALSE ); + + winetest_pop_context(); +} + START_TEST(imm32) { if (!is_ime_enabled()) @@ -2852,6 +2890,8 @@ START_TEST(imm32)
test_ImmInstallIME( FALSE ); test_ImmInstallIME( TRUE ); + test_ImmGetDescription( FALSE ); + test_ImmGetDescription( TRUE );
if (init()) { @@ -2864,7 +2904,6 @@ START_TEST(imm32) test_ImmThreads(); test_ImmIsUIMessage(); test_ImmGetContext(); - test_ImmGetDescription(); test_ImmDefaultHwnd(); test_default_ime_window_creation(); test_ImmGetIMCLockCount();
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/imm32/tests/imm32.c | 104 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+)
diff --git a/dlls/imm32/tests/imm32.c b/dlls/imm32/tests/imm32.c index 252bab7d6d1..4d33afd3f08 100644 --- a/dlls/imm32/tests/imm32.c +++ b/dlls/imm32/tests/imm32.c @@ -2878,6 +2878,108 @@ cleanup: winetest_pop_context(); }
+static void test_ImmGetIMEFileName( BOOL unicode ) +{ + HKL hkl = GetKeyboardLayout( 0 ); + WCHAR bufferW[MAX_PATH], expectW[16]; + char bufferA[MAX_PATH], expectA[16]; + DWORD ret; + + SET_ENABLE( IME_DLL_PROCESS_ATTACH, TRUE ); + SET_ENABLE( ImeInquire, TRUE ); + SET_ENABLE( ImeDestroy, TRUE ); + SET_ENABLE( IME_DLL_PROCESS_DETACH, TRUE ); + + winetest_push_context( unicode ? "unicode" : "ansi" ); + + SetLastError( 0xdeadbeef ); + ret = ImmGetIMEFileNameW( NULL, NULL, 0 ); + ok( !ret, "ImmGetIMEFileNameW returned %lu\n", ret ); + ret = ImmGetIMEFileNameA( NULL, NULL, 0 ); + ok( !ret, "ImmGetIMEFileNameA returned %lu\n", ret ); + ret = ImmGetIMEFileNameW( NULL, NULL, 100 ); + ok( !ret, "ImmGetIMEFileNameW returned %lu\n", ret ); + ret = ImmGetIMEFileNameA( NULL, NULL, 100 ); + ok( !ret, "ImmGetIMEFileNameA returned %lu\n", ret ); + ret = ImmGetIMEFileNameW( hkl, bufferW, 100 ); + ok( !ret, "ImmGetIMEFileNameW returned %lu\n", ret ); + ret = ImmGetIMEFileNameA( hkl, bufferA, 100 ); + ok( !ret, "ImmGetIMEFileNameA returned %lu\n", ret ); + ret = GetLastError(); + todo_wine + ok( ret == 0xdeadbeef, "got error %lu\n", ret ); + + /* IME_PROP_END_UNLOAD for the IME to unload / reload. */ + ime_info.fdwProperty = IME_PROP_END_UNLOAD; + if (unicode) ime_info.fdwProperty |= IME_PROP_UNICODE; + + if (!(hkl = ime_install())) goto cleanup; + + memset( bufferW, 0xcd, sizeof(bufferW) ); + ret = ImmGetIMEFileNameW( hkl, bufferW, 2 ); + todo_wine + ok( ret == 1, "ImmGetIMEFileNameW returned %lu\n", ret ); + todo_wine + ok( !wcscmp( bufferW, L"W" ), "got bufferW %s\n", debugstr_w(bufferW) ); + memset( bufferA, 0xcd, sizeof(bufferA) ); + ret = ImmGetIMEFileNameA( hkl, bufferA, 2 ); + ok( ret == 0, "ImmGetIMEFileNameA returned %lu\n", ret ); + todo_wine + ok( !strcmp( bufferA, "" ), "got bufferA %s\n", debugstr_a(bufferA) ); + + swprintf( expectW, ARRAY_SIZE(expectW), L"WINE%04X.I", ime_count - 1 ); + memset( bufferW, 0xcd, sizeof(bufferW) ); + ret = ImmGetIMEFileNameW( hkl, bufferW, 11 ); + todo_wine + ok( ret == 10, "ImmGetIMEFileNameW returned %lu\n", ret ); + todo_wine + ok( !wcscmp( bufferW, expectW ), "got bufferW %s\n", debugstr_w(bufferW) ); + memset( bufferA, 0xcd, sizeof(bufferA) ); + ret = ImmGetIMEFileNameA( hkl, bufferA, 11 ); + ok( ret == 0, "ImmGetIMEFileNameA returned %lu\n", ret ); + todo_wine + ok( !strcmp( bufferA, "" ), "got bufferA %s\n", debugstr_a(bufferA) ); + + swprintf( expectW, ARRAY_SIZE(expectW), L"WINE%04X.IM", ime_count - 1 ); + memset( bufferW, 0xcd, sizeof(bufferW) ); + ret = ImmGetIMEFileNameW( hkl, bufferW, 12 ); + todo_wine + ok( ret == 11, "ImmGetIMEFileNameW returned %lu\n", ret ); + todo_wine + ok( !wcscmp( bufferW, expectW ), "got bufferW %s\n", debugstr_w(bufferW) ); + snprintf( expectA, ARRAY_SIZE(expectA), "WINE%04X.IME", ime_count - 1 ); + memset( bufferA, 0xcd, sizeof(bufferA) ); + ret = ImmGetIMEFileNameA( hkl, bufferA, 12 ); + todo_wine + ok( ret == 12, "ImmGetIMEFileNameA returned %lu\n", ret ); + todo_wine + ok( !strcmp( bufferA, expectA ), "got bufferA %s\n", debugstr_a(bufferA) ); + + swprintf( expectW, ARRAY_SIZE(expectW), L"WINE%04X.IME", ime_count - 1 ); + memset( bufferW, 0xcd, sizeof(bufferW) ); + ret = ImmGetIMEFileNameW( hkl, bufferW, 13 ); + todo_wine + ok( ret == 12, "ImmGetIMEFileNameW returned %lu\n", ret ); + todo_wine + ok( !wcscmp( bufferW, expectW ), "got bufferW %s\n", debugstr_w(bufferW) ); + memset( bufferA, 0xcd, sizeof(bufferA) ); + ret = ImmGetIMEFileNameA( hkl, bufferA, 13 ); + todo_wine + ok( ret == 12, "ImmGetIMEFileNameA returned %lu\n", ret ); + todo_wine + ok( !strcmp( bufferA, expectA ), "got bufferA %s\n", debugstr_a(bufferA) ); + + ime_cleanup( hkl ); + +cleanup: + SET_ENABLE( IME_DLL_PROCESS_ATTACH, FALSE ); + SET_ENABLE( ImeInquire, FALSE ); + SET_ENABLE( ImeDestroy, FALSE ); + SET_ENABLE( IME_DLL_PROCESS_DETACH, FALSE ); + + winetest_pop_context(); +} + START_TEST(imm32) { if (!is_ime_enabled()) @@ -2892,6 +2994,8 @@ START_TEST(imm32) test_ImmInstallIME( TRUE ); test_ImmGetDescription( FALSE ); test_ImmGetDescription( TRUE ); + test_ImmGetIMEFileName( FALSE ); + test_ImmGetIMEFileName( TRUE );
if (init()) {
v3: Use user default locale for the IME locale to fix failures on localized Windows instances.