diff --git a/dlls/imm32/imm.c b/dlls/imm32/imm.c index 1418fc8e4cc..f09b132c768 100644 --- a/dlls/imm32/imm.c +++ b/dlls/imm32/imm.c @@ -37,6 +37,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(imm); +#define IMM_INIT_MAGIC 0x19650412 +BOOL WINAPI User32InitializeImmEntryTable(DWORD); + #define MAKE_FUNCPTR(f) typeof(f) * p##f typedef struct _tagImmHkl{ struct list entry; @@ -93,15 +96,6 @@ typedef struct _tagIMMThreadData { static DWORD tlsIndex = 0; static struct list ImmHklList = LIST_INIT(ImmHklList); -/* MSIME messages */ -static UINT WM_MSIME_SERVICE; -static UINT WM_MSIME_RECONVERTOPTIONS; -static UINT WM_MSIME_MOUSE; -static UINT WM_MSIME_RECONVERTREQUEST; -static UINT WM_MSIME_RECONVERT; -static UINT WM_MSIME_QUERYPOSITION; -static UINT WM_MSIME_DOCUMENTFEED; - static const WCHAR szwWineIMCProperty[] = {'W','i','n','e','I','m','m','H','I','M','C','P','r','o','p','e','r','t','y',0}; static const WCHAR szImeFileW[] = {'I','m','e',' ','F','i','l','e',0}; @@ -110,9 +104,6 @@ static const WCHAR szImeRegFmt[] = {'S','y','s','t','e','m','\\','C','u','r','r' static const WCHAR szwIME[] = {'I','M','E',0}; -static LRESULT WINAPI DefIME_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, - LPARAM lParam); - #define is_himc_ime_unicode(p) (p->immKbd->imeInfo.fdwProperty & IME_PROP_UNICODE) #define is_kbd_ime_unicode(p) (p->imeInfo.fdwProperty & IME_PROP_UNICODE) @@ -347,6 +338,12 @@ static ImmHkl *IMM_GetImmHkl(HKL hkl) } #undef LOAD_FUNCPTR +HWND WINAPI __wine_get_ui_window(HKL hkl) +{ + ImmHkl *immHkl = IMM_GetImmHkl(hkl); + return immHkl->UIWnd; +} + static void IMM_FreeAllImmHkl(void) { ImmHkl *ptr,*cursor2; @@ -365,43 +362,20 @@ static void IMM_FreeAllImmHkl(void) } } -static void IMM_RegisterMessages(void) -{ - WM_MSIME_SERVICE = RegisterWindowMessageA("MSIMEService"); - WM_MSIME_RECONVERTOPTIONS = RegisterWindowMessageA("MSIMEReconvertOptions"); - WM_MSIME_MOUSE = RegisterWindowMessageA("MSIMEMouseOperation"); - WM_MSIME_RECONVERTREQUEST = RegisterWindowMessageA("MSIMEReconvertRequest"); - WM_MSIME_RECONVERT = RegisterWindowMessageA("MSIMEReconvert"); - WM_MSIME_QUERYPOSITION = RegisterWindowMessageA("MSIMEQueryPosition"); - WM_MSIME_DOCUMENTFEED = RegisterWindowMessageA("MSIMEDocumentFeed"); -} - -static void IMM_RegisterIMEClass(void) -{ - WNDCLASSW wndClass; - - ZeroMemory(&wndClass, sizeof(WNDCLASSW)); - - wndClass.style = CS_GLOBALCLASS; - wndClass.lpfnWndProc = (WNDPROC) DefIME_WindowProc; - wndClass.cbWndExtra = 2 * sizeof(LONG_PTR); - wndClass.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW); - wndClass.lpszClassName = szwIME; - - RegisterClassW(&wndClass); -} - BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved) { TRACE("%p, %x, %p\n",hInstDLL,fdwReason,lpReserved); switch (fdwReason) { case DLL_PROCESS_ATTACH: - IMM_RegisterMessages(); tlsIndex = TlsAlloc(); if (tlsIndex == TLS_OUT_OF_INDEXES) return FALSE; - IMM_RegisterIMEClass(); + if (!User32InitializeImmEntryTable(IMM_INIT_MAGIC)) + { + TlsFree(tlsIndex); + return FALSE; + } break; case DLL_THREAD_ATTACH: break; @@ -413,7 +387,6 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved) IMM_FreeThreadData(); IMM_FreeAllImmHkl(); TlsFree(tlsIndex); - UnregisterClassW(szwIME, NULL); break; } return TRUE; @@ -2940,53 +2913,3 @@ BOOL WINAPI ImmGetHotKey(DWORD hotkey, UINT *modifiers, UINT *key, HKL hkl) FIXME("%x, %p, %p, %p: stub\n", hotkey, modifiers, key, hkl); return FALSE; } - - -/* - * Window Proc for the Default IME window class - */ -static LRESULT WINAPI DefIME_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, - LPARAM lParam) -{ - switch (uMsg) - { - case WM_CREATE: - case WM_NCCREATE: - return TRUE; - case WM_IME_STARTCOMPOSITION: - case WM_IME_ENDCOMPOSITION: - case WM_IME_COMPOSITION: - case WM_IME_SETCONTEXT: - case WM_IME_NOTIFY: - case WM_IME_CONTROL: - case WM_IME_COMPOSITIONFULL: - case WM_IME_SELECT: - case WM_IME_CHAR: - case WM_IME_REQUEST: - case WM_IME_KEYDOWN: - case WM_IME_KEYUP: - { - ImmHkl *immHkl = IMM_GetImmHkl(GetKeyboardLayout(0)); - if (immHkl->UIWnd) - return SendMessageW(immHkl->UIWnd,uMsg,wParam,lParam); - else - return FALSE; - } - default: - if ((uMsg == WM_MSIME_RECONVERTOPTIONS) || - (uMsg == WM_MSIME_SERVICE) || - (uMsg == WM_MSIME_MOUSE) || - (uMsg == WM_MSIME_RECONVERTREQUEST) || - (uMsg == WM_MSIME_RECONVERT) || - (uMsg == WM_MSIME_QUERYPOSITION) || - (uMsg == WM_MSIME_DOCUMENTFEED)) - { - ImmHkl *immHkl = IMM_GetImmHkl(GetKeyboardLayout(0)); - if (immHkl->UIWnd) - return SendMessageW(immHkl->UIWnd,uMsg,wParam,lParam); - else - return FALSE; - } - return DefWindowProcW(hwnd, uMsg, wParam, lParam); - } -} diff --git a/dlls/imm32/imm32.spec b/dlls/imm32/imm32.spec index 37c46ab345e..0bee92a9596 100644 --- a/dlls/imm32/imm32.spec +++ b/dlls/imm32/imm32.spec @@ -110,3 +110,7 @@ @ stub ImmWINNLSEnableIME @ stub ImmWINNLSGetEnableStatus @ stub ImmWINNLSGetIMEHotkey + +################################################################ +# Wine internal extensions +@ stdcall __wine_get_ui_window(ptr) diff --git a/dlls/user32/class.c b/dlls/user32/class.c index d40d22e1cd2..531c2e394d3 100644 --- a/dlls/user32/class.c +++ b/dlls/user32/class.c @@ -447,6 +447,7 @@ static BOOL WINAPI register_builtins( INIT_ONCE *once, void *param, void **conte register_builtin( &MENU_builtin_class ); register_builtin( &SCROLL_builtin_class ); register_builtin( &STATIC_builtin_class ); + register_builtin( &IME_builtin_class ); return TRUE; } diff --git a/dlls/user32/controls.h b/dlls/user32/controls.h index 3ce804f231d..a5a6adcbaf3 100644 --- a/dlls/user32/controls.h +++ b/dlls/user32/controls.h @@ -42,6 +42,7 @@ enum builtin_winprocs WINPROC_MDICLIENT, WINPROC_SCROLLBAR, WINPROC_STATIC, + WINPROC_IME, /* unicode-only procs */ WINPROC_DESKTOP, WINPROC_ICONTITLE, @@ -78,7 +79,10 @@ extern const struct builtin_class_descr MENU_builtin_class DECLSPEC_HIDDEN; extern const struct builtin_class_descr MESSAGE_builtin_class DECLSPEC_HIDDEN; extern const struct builtin_class_descr SCROLL_builtin_class DECLSPEC_HIDDEN; extern const struct builtin_class_descr STATIC_builtin_class DECLSPEC_HIDDEN; +extern const struct builtin_class_descr IME_builtin_class DECLSPEC_HIDDEN; +extern LRESULT WINAPI ImeWndProcA(HWND,UINT,WPARAM,LPARAM); +extern LRESULT WINAPI ImeWndProcW(HWND,UINT,WPARAM,LPARAM); extern LRESULT WINAPI DesktopWndProc(HWND,UINT,WPARAM,LPARAM) DECLSPEC_HIDDEN; extern LRESULT WINAPI IconTitleWndProc(HWND,UINT,WPARAM,LPARAM) DECLSPEC_HIDDEN; extern LRESULT WINAPI PopupMenuWndProc(HWND,UINT,WPARAM,LPARAM) DECLSPEC_HIDDEN; diff --git a/dlls/user32/misc.c b/dlls/user32/misc.c index 2e6cc35ae2d..bcf62636665 100644 --- a/dlls/user32/misc.c +++ b/dlls/user32/misc.c @@ -29,6 +29,7 @@ #include "winuser.h" #include "winnls.h" #include "winternl.h" +#include "controls.h" #include "user_private.h" #include "wine/unicode.h" @@ -36,6 +37,18 @@ WINE_DEFAULT_DEBUG_CHANNEL(win); +#define IMM_INIT_MAGIC 0x19650412 +static HWND (WINAPI *imm_get_ui_window)(HKL); + +/* MSIME messages */ +static UINT WM_MSIME_SERVICE; +static UINT WM_MSIME_RECONVERTOPTIONS; +static UINT WM_MSIME_MOUSE; +static UINT WM_MSIME_RECONVERTREQUEST; +static UINT WM_MSIME_RECONVERT; +static UINT WM_MSIME_QUERYPOSITION; +static UINT WM_MSIME_DOCUMENTFEED; + /* USER signal proc flags and codes */ /* See UserSignalProc for comments */ #define USIG_FLAGS_WIN32 0x0001 @@ -597,10 +610,32 @@ VOID WINAPI LoadLocalFonts(VOID) /*********************************************************************** * User32InitializeImmEntryTable */ -BOOL WINAPI User32InitializeImmEntryTable(LPVOID ptr) +BOOL WINAPI User32InitializeImmEntryTable(DWORD magic) { - FIXME("(%p): stub\n", ptr); - return TRUE; + static const WCHAR imm32_dllW[] = {'i','m','m','3','2','.','d','l','l',0}; + HMODULE imm32 = GetModuleHandleW(imm32_dllW); + + TRACE("(%x)\n", magic); + + if (!imm32 || magic != IMM_INIT_MAGIC) + return FALSE; + + if (imm_get_ui_window) + return TRUE; + + WM_MSIME_SERVICE = RegisterWindowMessageA("MSIMEService"); + WM_MSIME_RECONVERTOPTIONS = RegisterWindowMessageA("MSIMEReconvertOptions"); + WM_MSIME_MOUSE = RegisterWindowMessageA("MSIMEMouseOperation"); + WM_MSIME_RECONVERTREQUEST = RegisterWindowMessageA("MSIMEReconvertRequest"); + WM_MSIME_RECONVERT = RegisterWindowMessageA("MSIMEReconvert"); + WM_MSIME_QUERYPOSITION = RegisterWindowMessageA("MSIMEQueryPosition"); + WM_MSIME_DOCUMENTFEED = RegisterWindowMessageA("MSIMEDocumentFeed"); + + /* this part is not compatible with native imm32.dll */ + imm_get_ui_window = (void*)GetProcAddress(imm32, "__wine_get_ui_window"); + if (!imm_get_ui_window) + FIXME("native imm32.dll not supported\n"); + return TRUE; } /********************************************************************** @@ -694,3 +729,78 @@ BOOL WINAPI SetGestureConfig( HWND hwnd, DWORD reserved, UINT id, PGESTURECONFIG SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return 0; } + +static const WCHAR imeW[] = {'I','M','E',0}; +const struct builtin_class_descr IME_builtin_class = +{ + imeW, /* name */ + 0, /* style */ + WINPROC_IME, /* proc */ + 2*sizeof(LONG_PTR), /* extra */ + IDC_ARROW, /* cursor */ + 0 /* brush */ +}; + +static BOOL is_ime_ui_msg( UINT msg ) +{ + switch(msg) { + case WM_IME_STARTCOMPOSITION: + case WM_IME_ENDCOMPOSITION: + case WM_IME_COMPOSITION: + case WM_IME_SETCONTEXT: + case WM_IME_NOTIFY: + case WM_IME_CONTROL: + case WM_IME_COMPOSITIONFULL: + case WM_IME_SELECT: + case WM_IME_CHAR: + case WM_IME_REQUEST: + case WM_IME_KEYDOWN: + case WM_IME_KEYUP: + return TRUE; + default: + if ((msg == WM_MSIME_RECONVERTOPTIONS) || + (msg == WM_MSIME_SERVICE) || + (msg == WM_MSIME_MOUSE) || + (msg == WM_MSIME_RECONVERTREQUEST) || + (msg == WM_MSIME_RECONVERT) || + (msg == WM_MSIME_QUERYPOSITION) || + (msg == WM_MSIME_DOCUMENTFEED)) + return TRUE; + + return FALSE; + } +} + +LRESULT WINAPI ImeWndProcA( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ) +{ + HWND uiwnd; + + if (msg==WM_CREATE || msg==WM_NCCREATE) + return TRUE; + + if (imm_get_ui_window && is_ime_ui_msg(msg)) + { + if ((uiwnd = imm_get_ui_window(GetKeyboardLayout(0)))) + return SendMessageA(uiwnd, msg, wParam, lParam); + return FALSE; + } + + return DefWindowProcA(hwnd, msg, wParam, lParam); +} + +LRESULT WINAPI ImeWndProcW( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ) +{ + HWND uiwnd; + + if (msg==WM_CREATE || msg==WM_NCCREATE) + return TRUE; + + if (imm_get_ui_window && is_ime_ui_msg(msg)) + { + if ((uiwnd = imm_get_ui_window(GetKeyboardLayout(0)))) + return SendMessageW(uiwnd, msg, wParam, lParam); + return FALSE; + } + + return DefWindowProcW(hwnd, msg, wParam, lParam); +} diff --git a/dlls/user32/tests/class.c b/dlls/user32/tests/class.c index 95cfc3ccff4..b5adac416bc 100644 --- a/dlls/user32/tests/class.c +++ b/dlls/user32/tests/class.c @@ -1107,7 +1107,6 @@ static void test_IME(void) char module_name[MAX_PATH], *ptr; MEMORY_BASIC_INFORMATION mbi; - HMODULE imm32 = NULL; WNDCLASSW wnd_classw; WNDCLASSA wnd_class; SIZE_T size; @@ -1119,15 +1118,13 @@ static void test_IME(void) return; } - todo_wine ok(GetModuleHandleA("imm32") != 0, "imm32.dll is not loaded\n"); - if (!GetModuleHandleA("imm32")) - imm32 = LoadLibraryA("imm32"); + ok(GetModuleHandleA("imm32") != 0, "imm32.dll is not loaded\n"); ret = GetClassInfoA(NULL, "IME", &wnd_class); ok(ret, "GetClassInfo failed: %d\n", GetLastError()); size = VirtualQuery(wnd_class.lpfnWndProc, &mbi, sizeof(mbi)); - todo_wine ok(size == sizeof(mbi), "VirtualQuery returned %ld\n", size); + ok(size == sizeof(mbi), "VirtualQuery returned %ld\n", size); if (size == sizeof(mbi)) { size = GetModuleFileNameA(mbi.AllocationBase, module_name, sizeof(module_name)); ok(size, "GetModuleFileName failed\n"); @@ -1147,9 +1144,7 @@ static void test_IME(void) for (ptr = module_name+size-1; ptr > module_name; ptr--) if (*ptr == '\\' || *ptr == '/') break; if (*ptr == '\\' || *ptr=='/') ptr++; - todo_wine ok(!lstrcmpiA(ptr, "user32.dll") || !lstrcmpiA(ptr, "ntdll.dll"), "IME window proc implemented in %s\n", ptr); - - if (imm32) FreeLibrary(imm32); + ok(!lstrcmpiA(ptr, "user32.dll") || !lstrcmpiA(ptr, "ntdll.dll"), "IME window proc implemented in %s\n", ptr); } START_TEST(class) diff --git a/dlls/user32/user_main.c b/dlls/user32/user_main.c index d08a93c2dca..12764e664c8 100644 --- a/dlls/user32/user_main.c +++ b/dlls/user32/user_main.c @@ -322,18 +322,24 @@ static void thread_detach(void) */ BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved ) { + static const WCHAR imm32_dllW[] = {'i','m','m','3','2','.','d','l','l',0}; + static HMODULE imm32_module; BOOL ret = TRUE; + switch(reason) { case DLL_PROCESS_ATTACH: user32_module = inst; ret = process_attach(); + if(ret) + imm32_module = LoadLibraryW(imm32_dllW); break; case DLL_THREAD_DETACH: thread_detach(); break; case DLL_PROCESS_DETACH: USER_unload_driver(); + FreeLibrary(imm32_module); DeleteCriticalSection(&user_section); break; } diff --git a/dlls/user32/winproc.c b/dlls/user32/winproc.c index 57adfc26521..364210984b3 100644 --- a/dlls/user32/winproc.c +++ b/dlls/user32/winproc.c @@ -75,6 +75,7 @@ static WINDOWPROC winproc_array[MAX_WINPROCS] = { MDIClientWndProcA, MDIClientWndProcW }, /* WINPROC_MDICLIENT */ { ScrollBarWndProcA, ScrollBarWndProcW }, /* WINPROC_SCROLLBAR */ { StaticWndProcA, StaticWndProcW }, /* WINPROC_STATIC */ + { ImeWndProcA, ImeWndProcW }, /* WINPROC_IME */ { NULL, DesktopWndProc }, /* WINPROC_DESKTOP */ { NULL, IconTitleWndProc }, /* WINPROC_ICONTITLE */ { NULL, PopupMenuWndProc }, /* WINPROC_MENU */