From 3e3335d228dc74c43996ac2fab01e916d447b352 Mon Sep 17 00:00:00 2001 From: Tomohiro Kashiwada Date: Thu, 9 Jun 2011 16:50:31 +0900 Subject: [PATCH] Make the keyboard hooks global. Each keyboard hook of 32bit and 64bit works only corresponding applications and controls IME through a window message. Make the reset of 64bit hooks disabled because it doesn't work. --- xkeymacs/mainfrm.cpp | 3 +- xkeymacs/xkeymacs64.cpp | 3 +- xkeymacsdll/Commands.cpp | 22 +++++++++- xkeymacsdll/Commands.h | 1 + xkeymacsdll/Utils.cpp | 5 +++ xkeymacsdll/Utils.h | 1 + xkeymacsdll/xkeymacsdll.cpp | 105 +++++++++++++++++++++++++++++++------------- xkeymacsdll/xkeymacsdll.h | 5 ++- 8 files changed, 106 insertions(+), 39 deletions(-) diff --git a/xkeymacs/mainfrm.cpp b/xkeymacs/mainfrm.cpp index cc22cf7..57f3fa5 100644 --- a/xkeymacs/mainfrm.cpp +++ b/xkeymacs/mainfrm.cpp @@ -576,9 +576,8 @@ void CMainFrame::OnExport() void CMainFrame::OnReset() { - CXkeymacsDll::ReleaseHooks(); - CXkeymacsDll::SetHooks(); TerminatePollThread(); + CXkeymacsDll::ResetHook(); StartPollThread(); CXkeymacsApp *pApp = static_cast(AfxGetApp()); if (!pApp->SendIPCMessage(XKEYMACS_RESET)) diff --git a/xkeymacs/xkeymacs64.cpp b/xkeymacs/xkeymacs64.cpp index 7e15352..08e1bc8 100644 --- a/xkeymacs/xkeymacs64.cpp +++ b/xkeymacs/xkeymacs64.cpp @@ -64,8 +64,7 @@ UINT PollIPCMessage(LPVOID lpParam) CXkeymacsDll::EnableKeyboardHook(); break; case XKEYMACS_RESET: - CXkeymacsDll::ReleaseHooks(); - CXkeymacsDll::SetHooks(); + //CXkeymacsDll::ResetHook(); break; } } diff --git a/xkeymacsdll/Commands.cpp b/xkeymacsdll/Commands.cpp index bde626d..497ea5e 100644 --- a/xkeymacsdll/Commands.cpp +++ b/xkeymacsdll/Commands.cpp @@ -2815,7 +2815,24 @@ int CCommands::CompleteCloseInputMethod() return Reset(GOTO_HOOK); } -void CCommands::SetInputMethodOpenStatus(INPUT_METHOD_OPEN_STATUS status, BOOL isComplete) +inline HWND ObtainFocus() +{ + const HWND hWnd = GetFocus(); + if (hWnd) + return hWnd; + GUITHREADINFO gui; + gui.cbSize = sizeof(gui); + return GetGUIThreadInfo(GetWindowThreadProcessId(GetForegroundWindow(), 0), &gui) ? gui.hwndFocus : GetForegroundWindow(); +} + +void CCommands::SetInputMethodOpenStatus(INPUT_METHOD_OPEN_STATUS status, BOOL isComplete) { + extern UINT g_ImeManipulationMessage; + HWND hWnd = ObtainFocus(); + //CUtils::Log(_T(" post ime manip, %d, %d, %p"), status, isComplete, hWnd); + PostMessage(hWnd, g_ImeManipulationMessage, status, isComplete); +} + +void CCommands::DoSetInputMethodOpenStatus(INPUT_METHOD_OPEN_STATUS status, BOOL isComplete) { ClearNumericArgument(); HKL hKL = GetKeyboardLayout(0); @@ -2823,8 +2840,9 @@ void CCommands::SetInputMethodOpenStatus(INPUT_METHOD_OPEN_STATUS status, BOOL i Kdu(VK_KANJI); } else if (ImmIsIME(hKL)) { // default - HWND hWnd = GetFocus(); + HWND hWnd = ObtainFocus(); HIMC hIMC = ImmGetContext(hWnd); + //CUtils::Log(_T(" do ime manip, %d, %d, %d, %p, %p"), status, isComplete, ImmGetOpenStatus(hIMC), hWnd, hIMC); if (isComplete && ImmGetOpenStatus(hIMC)) { ImmNotifyIME(hIMC, NI_COMPOSITIONSTR, CPS_COMPLETE, 0); diff --git a/xkeymacsdll/Commands.h b/xkeymacsdll/Commands.h index 6663db7..f7b53c8 100644 --- a/xkeymacsdll/Commands.h +++ b/xkeymacsdll/Commands.h @@ -176,6 +176,7 @@ public: static int GetDefaultCommandType(int nCommandID, int nIndex); static int GetDefaultCommandKey(int nCommandID, int nIndex); static int GetDefaultControlID(int nCommandID, int nIndex); + static void DoSetInputMethodOpenStatus(INPUT_METHOD_OPEN_STATUS status, BOOL isComplete = FALSE); CCommands(); virtual ~CCommands(); diff --git a/xkeymacsdll/Utils.cpp b/xkeymacsdll/Utils.cpp index 0628dd3..a8680d2 100644 --- a/xkeymacsdll/Utils.cpp +++ b/xkeymacsdll/Utils.cpp @@ -68,6 +68,11 @@ BOOL CUtils::IsAstecX() return !_tcsicmp(m_szApplicationName, _T("astecx.exe")); } +BOOL CUtils::IsXkeymacs() +{ + return !_tcsicmp(m_szApplicationName, _T("xkeymacs.exe")) || !_tcsicmp(m_szApplicationName, _T("xkeymacs64.exe")); +} + BOOL CUtils::IsBecky() { return !_tcsicmp(m_szApplicationName, _T("b2.exe")); diff --git a/xkeymacsdll/Utils.h b/xkeymacsdll/Utils.h index 37032d8..4793c5e 100644 --- a/xkeymacsdll/Utils.h +++ b/xkeymacsdll/Utils.h @@ -116,6 +116,7 @@ public: static BOOL IsExplorer(); static BOOL IsBecky(); static BOOL IsAstecX(); + static BOOL IsXkeymacs(); static BOOL CUtils::GetFindDialogTitle(CString *szDialogTitle); CUtils(); virtual ~CUtils(); diff --git a/xkeymacsdll/xkeymacsdll.cpp b/xkeymacsdll/xkeymacsdll.cpp index b37160d..19c2b2a 100644 --- a/xkeymacsdll/xkeymacsdll.cpp +++ b/xkeymacsdll/xkeymacsdll.cpp @@ -138,8 +138,42 @@ static const KeyName ControlCharacters[] = { static AFX_EXTENSION_MODULE XkeymacsdllDLL = { NULL, NULL }; -static __declspec(thread) HINSTANCE g_hDllInst = NULL; -static __declspec(thread) HHOOK g_hHookKeyboard = NULL; +HINSTANCE g_hDllInst = NULL; +UINT g_ImeManipulationMessage = 0; +#pragma data_seg(".xkmcs") +HHOOK g_hHookKeyboard = NULL; +HHOOK g_hHookDummy = NULL; +#pragma data_seg() + +inline bool IsWow64(HANDLE mod) { + typedef BOOL (WINAPI *pfnIsWow64Process_t)(HANDLE, PBOOL); + if (const pfnIsWow64Process_t IsWow64Process = (pfnIsWow64Process_t)GetProcAddress(GetModuleHandle(_T("kernel32")), "IsWow64Process")) { + BOOL b; + return IsWow64Process(mod, &b) && b; + } + return false; +} + +inline bool Is64System() { + SYSTEM_INFO info; + GetNativeSystemInfo(&info); + return info.wProcessorArchitecture != PROCESSOR_ARCHITECTURE_INTEL; +} + +inline bool Is64Process(HANDLE mod) { + return Is64System() && !IsWow64(mod); +} + +const bool IsDll64 = sizeof(void *) == 8; + +inline bool Is64ProcessHwnd(HWND hwnd) { + DWORD pid; + GetWindowThreadProcessId(hwnd, &pid); + HANDLE hmod = OpenProcess(PROCESS_ALL_ACCESS, 0, pid); + bool b = Is64Process(hmod); + CloseHandle(hmod); + return b; +} extern "C" int APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) @@ -152,6 +186,7 @@ DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) switch (dwReason) { case DLL_PROCESS_ATTACH: TRACE0("XKEYMACSDLL.DLL Initializing!\n"); + g_ImeManipulationMessage = RegisterWindowMessage(_T("XkManipulateIME")); // Extension DLL one-time initialization if (!AfxInitExtensionModule(XkeymacsdllDLL, hInstance)) { @@ -177,15 +212,12 @@ DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) e->Delete(); // CUtils::Log("DllMain: 'new' threw an exception"); } - case DLL_THREAD_ATTACH: - CXkeymacsDll::SetKeyboardHook(); break; case DLL_PROCESS_DETACH: TRACE0("XKEYMACSDLL.DLL Terminating!\n"); // Terminate the library before destructors are called AfxTermExtensionModule(XkeymacsdllDLL); - case DLL_THREAD_DETACH: - CXkeymacsDll::ReleaseKeyboardHook(); + break; } return 1; // ok } @@ -273,12 +305,18 @@ void CXkeymacsDll::SetHookAltRelease() } // set hooks +LRESULT WINAPI DummyProc(int code, WPARAM wp, LPARAM lp) { + return CallNextHookEx(0, code, wp, lp); +} + void CXkeymacsDll::SetHooks() { m_hHookCallWnd = SetWindowsHookEx(WH_CALLWNDPROC, (HOOKPROC)CallWndProc, g_hDllInst, 0); m_hHookCallWndRet = SetWindowsHookEx(WH_CALLWNDPROCRET, (HOOKPROC)CallWndRetProc, g_hDllInst, 0); m_hHookGetMessage = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)GetMsgProc, g_hDllInst, 0); m_hHookShell = SetWindowsHookEx(WH_SHELL, (HOOKPROC)ShellProc, g_hDllInst, 0); + g_hHookDummy = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)DummyProc, g_hDllInst, 0); + g_hHookKeyboard = SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC)KeyboardProc, g_hDllInst, 0); } void CXkeymacsDll::EnableKeyboardHook() @@ -286,35 +324,36 @@ void CXkeymacsDll::EnableKeyboardHook() m_bEnableKeyboardHook = TRUE; } -void CXkeymacsDll::SetKeyboardHook() +inline void unhook(HHOOK &hh) { + if (hh) + UnhookWindowsHookEx(hh); + hh = NULL; +} + +void CXkeymacsDll::ResetHook() { - if (!g_hHookKeyboard) - SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC)KeyboardProc, g_hDllInst, GetCurrentThreadId()); + unhook(m_hHookCallWnd); + unhook(m_hHookCallWndRet); + unhook(m_hHookGetMessage); + unhook(m_hHookShell); + unhook(g_hHookKeyboard); + m_hHookCallWnd = SetWindowsHookEx(WH_CALLWNDPROC, (HOOKPROC)CallWndProc, g_hDllInst, 0); + m_hHookCallWndRet = SetWindowsHookEx(WH_CALLWNDPROCRET, (HOOKPROC)CallWndRetProc, g_hDllInst, 0); + m_hHookGetMessage = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)GetMsgProc, g_hDllInst, 0); + m_hHookShell = SetWindowsHookEx(WH_SHELL, (HOOKPROC)ShellProc, g_hDllInst, 0); + g_hHookKeyboard = SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC)KeyboardProc, g_hDllInst, 0); } // release hooks void CXkeymacsDll::ReleaseHooks() { m_bEnableKeyboardHook = FALSE; - if (m_hHookCallWnd) - UnhookWindowsHookEx(m_hHookCallWnd); - m_hHookCallWnd = NULL; - if (m_hHookCallWndRet) - UnhookWindowsHookEx(m_hHookCallWndRet); - m_hHookCallWndRet = NULL; - if (m_hHookGetMessage) - UnhookWindowsHookEx(m_hHookGetMessage); - m_hHookGetMessage = NULL; - if (m_hHookShell) - UnhookWindowsHookEx(m_hHookShell); - m_hHookShell = NULL; -} - -void CXkeymacsDll::ReleaseKeyboardHook() -{ - if (g_hHookKeyboard) - UnhookWindowsHookEx(g_hHookKeyboard); - g_hHookKeyboard = NULL; + unhook(m_hHookCallWnd); + unhook(m_hHookCallWndRet); + unhook(m_hHookGetMessage); + unhook(m_hHookShell); + unhook(g_hHookKeyboard); + unhook(g_hHookDummy); } void CXkeymacsDll::SetKeyboardHookFlag(BOOL bFlag) @@ -544,7 +583,11 @@ LRESULT CALLBACK CXkeymacsDll::CallWndRetProc(int nCode, WPARAM wParam, LPARAM l LRESULT CALLBACK CXkeymacsDll::GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam) { MSG &msg = (*(MSG *)lParam); - + if (msg.message == g_ImeManipulationMessage) { + if (wParam) + CCommands::DoSetInputMethodOpenStatus((INPUT_METHOD_OPEN_STATUS)msg.wParam, msg.lParam); + return 1; + } switch (msg.message) { case WM_IME_STARTCOMPOSITION: InitKeyboardProc(TRUE); @@ -763,9 +806,9 @@ LRESULT CALLBACK CXkeymacsDll::KeyboardProc(int nCode, WPARAM wParam, LPARAM lPa static BYTE nOneShotModifier[MAX_KEY] = {'\0'}; static BOOL bCherryOneShotModifier = FALSE; -// CUtils::Log(_T("nCode = %#x, nKey = %#x, lParam = %#x"), nCode, nKey, lParam); +// CUtils::Log(_T("nCode = %#x, nKey = %#x, lParam = %p, en = %d, %d, %d"), nCode, nKey, lParam, m_bEnableKeyboardHook, IsDll64, Is64ProcessHwnd(GetForegroundWindow())); - if (!m_bEnableKeyboardHook) + if (Is64ProcessHwnd(GetForegroundWindow()) != IsDll64 || CUtils::IsXkeymacs()) return CallNextHookEx(g_hHookKeyboard, nCode, wParam, lParam); if (nCode < 0 || nCode == HC_NOREMOVE) { diff --git a/xkeymacsdll/xkeymacsdll.h b/xkeymacsdll/xkeymacsdll.h index 8101c62..c081f67 100644 --- a/xkeymacsdll/xkeymacsdll.h +++ b/xkeymacsdll/xkeymacsdll.h @@ -72,13 +72,12 @@ public: static void SetAtIbeamCursorOnly(int nApplicationID, int nCommandType, int nKey, BOOL bAtIbeamCursorOnly); static void SetApplicationName(int nApplicationID, CString szApplicationName); static void ReleaseHooks(); - static void ReleaseKeyboardHook(); static void SetEnableCUA(int nApplicationID, BOOL bEnableCUA); static void SetIgnoreUndefinedC_x(int nApplicationID, BOOL bIgnoreUndefinedC_x); static void SetIgnoreUndefinedMetaCtrl(int nApplicationID, BOOL bIgnoreUndefinedMetaCtrl); static void SetHooks(); static void EnableKeyboardHook(); - static void SetKeyboardHook(); + static void ResetHook(); static void SetSettingStyle(int nApplicationID, int nSettingStyle); static void SetUseDialogSetting(int nApplicationID, BOOL bUseDialogSetting); static void AddKillRing(BOOL bNewData = TRUE); @@ -153,4 +152,6 @@ private: static CONFIG m_Config; }; +extern UINT g_ImeManipulationMessage; + #endif // !defined(AFX_XKEYMACS_H__88552DEC_1233_4A0A_BE62_9EF7BC618EC6__INCLUDED_) -- 2.11.0