From c9192acef486ef6015a0946a9480e36d9cb63e9f Mon Sep 17 00:00:00 2001 From: Abs62 Date: Tue, 24 Jan 2012 16:39:23 +0400 Subject: [PATCH] Win-specific: ScanPopup in 64-bit applications --- goldendict.pro | 8 +- mouseover.cc | 14 +- mouseover_win32/GetWord.c | 12 +- mouseover_win32/GetWord.h | 2 +- mouseover_win32/HookImportFunction.c | 4 +- mouseover_win32/IAccExInt.h | 4 + mouseover_win32/Makefile | 61 ++++++-- mouseover_win32/TextOutHook.c | 17 ++- mouseover_win32/TextOutHook.h | 2 +- mouseover_win32/TextOutSpy.c | 204 ++++++++++++++++++--------- mouseover_win32/ThTypes.c | 35 ++++- mouseover_win32/ThTypes.h | 41 +++++- mouseover_win32/x64hooks.c | 140 ++++++++++++++++++ x64.cc | 63 +++++++++ x64.hh | 8 ++ 15 files changed, 509 insertions(+), 106 deletions(-) create mode 100644 mouseover_win32/x64hooks.c create mode 100644 x64.cc create mode 100644 x64.hh diff --git a/goldendict.pro b/goldendict.pro index 5bc2b413..54b470c2 100644 --- a/goldendict.pro +++ b/goldendict.pro @@ -281,10 +281,12 @@ SOURCES += folding.cc \ win32 { SOURCES += mouseover_win32/ThTypes.c \ wordbyauto.cc \ - guids.c + guids.c \ + x64.cc HEADERS += mouseover_win32/ThTypes.h \ wordbyauto.hh \ - uiauto.hh + uiauto.hh \ + x64.hh } RESOURCES += resources.qrc \ flags.qrc @@ -338,3 +340,5 @@ include( qtsingleapplication/src/qtsingleapplication.pri ) + + diff --git a/mouseover.cc b/mouseover.cc index e0a9caad..cf2362ab 100644 --- a/mouseover.cc +++ b/mouseover.cc @@ -12,6 +12,7 @@ #include #include "mouseover_win32/ThTypes.h" #include "wordbyauto.hh" +#include "x64.hh" #endif MouseOver & MouseOver::instance() @@ -58,7 +59,6 @@ static void SetLowLabelToGDSynchroObjects() BOOL fSaclDefaulted = FALSE; LPCWSTR pwszMapFileName = L"GoldenDictTextOutHookSharedMem"; LPCWSTR pwszSpyMutexName = L"GoldenDictTextOutSpyMutex"; - LPCWSTR pwszHookMutexName = L"GoldenDictTextOutHookMutex"; if( ConvertStringSecurityDescriptorToSecurityDescriptorW( LOW_INTEGRITY_SDDL_SACL_W, 1 /* SDDL_REVISION_1 */, &pSD, NULL ) ) { @@ -73,9 +73,6 @@ static void SetLowLabelToGDSynchroObjects() dwErr = SetNamedSecurityInfoW( (LPWSTR)pwszSpyMutexName, SE_KERNEL_OBJECT, LABEL_SECURITY_INFORMATION, NULL, NULL, NULL, pSacl); - dwErr = SetNamedSecurityInfoW( (LPWSTR)pwszHookMutexName, - SE_KERNEL_OBJECT, LABEL_SECURITY_INFORMATION, NULL, NULL, NULL, pSacl); - } LocalFree(pSD); } @@ -94,8 +91,9 @@ ChangeWindowMessageFilterExFunc changeWindowMessageFilterExFunc = NULL; ThTypes_Init(); memset( GlobalData, 0, sizeof( TGlobalDLLData ) ); - strcpy( GlobalData->LibName, - QDir::toNativeSeparators( QDir( QCoreApplication::applicationDirPath() ).filePath( "GdTextOutHook.dll" ) ).toLocal8Bit().data() ); +// strcpy( GlobalData->LibName, +// QDir::toNativeSeparators( QDir( QCoreApplication::applicationDirPath() ).filePath( "GdTextOutHook.dll" ) ).toLocal8Bit().data() ); + QDir::toNativeSeparators( QDir( QCoreApplication::applicationDirPath() ).filePath( "GdTextOutHook.dll" ) ).toWCharArray( GlobalData->LibName ); // Create the window to recive spying results to @@ -150,6 +148,7 @@ void MouseOver::enableMouseOver() if ( !mouseOverEnabled && activateSpyFn ) { activateSpyFn( true ); + installx64Hooks(); mouseOverEnabled = true; } #endif @@ -161,6 +160,7 @@ void MouseOver::disableMouseOver() if ( mouseOverEnabled && activateSpyFn ) { activateSpyFn( false ); + removex64Hooks(); mouseOverEnabled = false; } #endif @@ -338,7 +338,7 @@ MouseOver::~MouseOver() UnregisterClass( className, GetModuleHandle( 0 ) ); - Thtypes_End(); + ThTypes_End(); #endif } diff --git a/mouseover_win32/GetWord.c b/mouseover_win32/GetWord.c index 3a4646ba..9b569ad3 100644 --- a/mouseover_win32/GetWord.c +++ b/mouseover_win32/GetWord.c @@ -50,17 +50,17 @@ static BOOL Is_XP_And_Later() return (VER_PLATFORM_WIN32_NT == stOSVI.dwPlatformId && (5 < stOSVI.dwMajorVersion || (5 == stOSVI.dwMajorVersion && 1 <= stOSVI.dwMinorVersion))); } -static char* ExtractWordFromRichEditPos(HWND WND, POINT Pt, int *BeginPos) +static char* ExtractWordFromRichEditPos(HWND WND, POINT Pt, DWORD *BeginPos) { return ExtractFromEverything(WND, Pt, BeginPos); } -static char* ExtractWordFromEditPos(HWND hEdit, POINT Pt, int *BeginPos) +static char* ExtractWordFromEditPos(HWND hEdit, POINT Pt, DWORD *BeginPos) { return ExtractFromEverything(hEdit, Pt, BeginPos); } -static char* ExtractWordFromIE(HWND WND, POINT Pt, int *BeginPos) +static char* ExtractWordFromIE(HWND WND, POINT Pt, DWORD *BeginPos) { return ExtractFromEverything(WND, Pt, BeginPos); } @@ -116,7 +116,7 @@ static int GetWordFromConsolePack(TConsoleParams *params) return WordLen; } -static char* GetWordFromConsole(HWND WND, POINT Pt, int *BeginPos) +static char* GetWordFromConsole(HWND WND, POINT Pt, DWORD *BeginPos) { TConsoleParams *TP; DWORD pid; @@ -169,9 +169,9 @@ static char* GetWordFromConsole(HWND WND, POINT Pt, int *BeginPos) return Result; } -char* TryGetWordFromAnyWindow(TKnownWndClass WndType, HWND WND, POINT Pt, int *BeginPos) +char* TryGetWordFromAnyWindow(TKnownWndClass WndType, HWND WND, POINT Pt, DWORD *BeginPos) { - typedef char* (*GetWordFunction_t)(HWND, POINT, int*); + typedef char* (*GetWordFunction_t)(HWND, POINT, DWORD*); const GetWordFunction_t GetWordFunction[]= { ExtractFromEverything, ExtractWordFromRichEditPos, diff --git a/mouseover_win32/GetWord.h b/mouseover_win32/GetWord.h index d25103ca..fb4abe29 100644 --- a/mouseover_win32/GetWord.h +++ b/mouseover_win32/GetWord.h @@ -13,6 +13,6 @@ typedef enum TKnownWndClass { } TKnownWndClass; TKnownWndClass GetWindowType(HWND WND, const char* WNDClass); -char* TryGetWordFromAnyWindow(TKnownWndClass WndType, HWND WND, POINT Pt, int *BeginPos); +char* TryGetWordFromAnyWindow(TKnownWndClass WndType, HWND WND, POINT Pt, DWORD *BeginPos); #endif diff --git a/mouseover_win32/HookImportFunction.c b/mouseover_win32/HookImportFunction.c index ea65e383..3324e419 100644 --- a/mouseover_win32/HookImportFunction.c +++ b/mouseover_win32/HookImportFunction.c @@ -91,9 +91,9 @@ static BOOL HookImportFunction(HMODULE hModule, LPCSTR szImportModule, LPCSTR sz if( !VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize, PAGE_READWRITE, &mbi_thunk.Protect) ) return FALSE; if (paOrigFuncs) - *paOrigFuncs = (PROC)InterlockedExchangePointer(&(pRealThunk->u1.Function), paHookFuncs); + *paOrigFuncs = (PROC)InterlockedExchangePointer((PVOID)&(pRealThunk->u1.Function), paHookFuncs); else - InterlockedExchangePointer(&(pRealThunk->u1.Function), paHookFuncs); + InterlockedExchangePointer((PVOID)&(pRealThunk->u1.Function), paHookFuncs); VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize, mbi_thunk.Protect, &dwOldProtect); return TRUE; diff --git a/mouseover_win32/IAccExInt.h b/mouseover_win32/IAccExInt.h index f391da1a..0831c301 100644 --- a/mouseover_win32/IAccExInt.h +++ b/mouseover_win32/IAccExInt.h @@ -7,6 +7,10 @@ #include #include +#ifdef INTERFACE +#undef INTERFACE +#endif + #ifdef __cplusplus extern "C" { #endif diff --git a/mouseover_win32/Makefile b/mouseover_win32/Makefile index 308506d9..241ba306 100644 --- a/mouseover_win32/Makefile +++ b/mouseover_win32/Makefile @@ -1,11 +1,14 @@ GCC:=gcc.exe -W -Wall -s -O2 +GCC64:=x86_64-w64-mingw32-gcc.exe -W -Wall -s -O2 -.PHONY: all clean +.PHONY: all x64 clean all: GdTextOutHook.dll libGdTextOutHook.a GdTextOutSpy.dll libGdTextOutSpy.a +x64: x64helper.exe GdTextOutHook64.dll libGdTextOutHook64.a GdTextOutSpy64.dll libGdTextOutSpy64.a + clean: - rm -f *.o *.a *.dll + rm -f *.o *.a *.dll *.exe TextOutHook.o: TextOutHook.c $(GCC) -DBUILDING_DLL -c $< @@ -16,15 +19,6 @@ HookImportFunction.o: HookImportFunction.c GetWord.o: GetWord.c $(GCC) -c $< -IAccEx.o: IAccEx.c - $(GCC) -c $< - -GetWordByIAccEx.o: GetWordByIAccEx.c - $(GCC) -c $< - -guids.o: guids.c - $(GCC) -c $< - GdTextOutHook.dll libGdTextOutHook.a: TextOutHook.o HookImportFunction.o GetWord.o $(GCC) -shared -o GdTextOutHook.dll $^ -lgdi32 -Wl,--out-implib,libGdTextOutHook.a @@ -34,5 +28,50 @@ TextOutSpy.o: TextOutSpy.c ThTypes.o: ThTypes.c $(GCC) -c $< +IAccEx.o: IAccEx.c + $(GCC) -c $< + +GetWordByIAccEx.o: GetWordByIAccEx.c + $(GCC) -c $< + +guids.o: guids.c + $(GCC) -c $< + GdTextOutSpy.dll libGdTextOutSpy.a: TextOutSpy.o ThTypes.o IAccEx.o guids.o GetWordByIAccEx.o $(GCC) -shared -o GdTextOutSpy.dll $^ -lgdi32 -luuid -loleacc -loleaut32 -Wl,--out-implib,libGdTextOutSpy.a + +x64helper.exe: x64hooks64.o ThTypes64.o + $(GCC64) -Wl,--subsystem,windows -mwindows -o $@ $^ + +x64hooks64.o: x64hooks.c + $(GCC64) -o $@ -c $< + +TextOutHook64.o: TextOutHook.c + $(GCC64) -o $@ -DBUILDING_DLL -c $< + +HookImportFunction64.o: HookImportFunction.c + $(GCC64) -o $@ -c $< + +GetWord64.o: GetWord.c + $(GCC64) -o $@ -c $< + +GdTextOutHook64.dll libGdTextOutHook64.a: TextOutHook64.o HookImportFunction64.o GetWord64.o + $(GCC64) -shared -o GdTextOutHook64.dll $^ -lgdi32 -Wl,--out-implib,libGdTextOutHook64.a + +TextOutSpy64.o: TextOutSpy.c + $(GCC64) -o $@ -DBUILDING_DLL -c $< + +ThTypes64.o: ThTypes.c + $(GCC64) -o $@ -c $< + +IAccEx64.o: IAccEx.c + $(GCC64) -o $@ -c $< + +GetWordByIAccEx64.o: GetWordByIAccEx.c + $(GCC64) -o $@ -c $< + +guids64.o: guids.c + $(GCC64) -o $@ -c $< + +GdTextOutSpy64.dll libGdTextOutSpy64.a: TextOutSpy64.o ThTypes64.o IAccEx64.o guids64.o GetWordByIAccEx64.o + $(GCC64) -shared -o GdTextOutSpy64.dll $^ -lgdi32 -luuid -loleacc -loleaut32 -Wl,--out-implib,libGdTextOutSpy64.a diff --git a/mouseover_win32/TextOutHook.c b/mouseover_win32/TextOutHook.c index b0d64588..88570c0e 100644 --- a/mouseover_win32/TextOutHook.c +++ b/mouseover_win32/TextOutHook.c @@ -11,13 +11,20 @@ #include "HookImportFunction.h" typedef BOOL (WINAPI *TextOutANextHook_t)(HDC hdc, int nXStart, int nYStart, LPCSTR lpszString,int cbString); -TextOutANextHook_t TextOutANextHook __attribute__ ((aligned (4))) = NULL; typedef BOOL (WINAPI *TextOutWNextHook_t)(HDC hdc, int nXStart, int nYStart, LPCWSTR lpszString,int cbString); -TextOutWNextHook_t TextOutWNextHook __attribute__ ((aligned (4))) = NULL; typedef BOOL (WINAPI *ExtTextOutANextHook_t)(HDC hdc, int nXStart, int nYStart, UINT fuOptions, CONST RECT *lprc, LPCSTR lpszString, UINT cbString, CONST INT *lpDx); -ExtTextOutANextHook_t ExtTextOutANextHook __attribute__ ((aligned (4))) = NULL; typedef BOOL (WINAPI *ExtTextOutWNextHook_t)(HDC hdc, int nXStart, int nYStart, UINT fuOptions, CONST RECT *lprc, LPCWSTR lpszString, UINT cbString, CONST INT *lpDx); +#ifdef __WIN64 +TextOutANextHook_t TextOutANextHook __attribute__ ((aligned (8))) = NULL; +TextOutWNextHook_t TextOutWNextHook __attribute__ ((aligned (8))) = NULL; +ExtTextOutANextHook_t ExtTextOutANextHook __attribute__ ((aligned (8))) = NULL; +ExtTextOutWNextHook_t ExtTextOutWNextHook __attribute__ ((aligned (8))) = NULL; +#else +TextOutANextHook_t TextOutANextHook __attribute__ ((aligned (4))) = NULL; +TextOutWNextHook_t TextOutWNextHook __attribute__ ((aligned (4))) = NULL; +ExtTextOutANextHook_t ExtTextOutANextHook __attribute__ ((aligned (4))) = NULL; ExtTextOutWNextHook_t ExtTextOutWNextHook __attribute__ ((aligned (4))) = NULL; +#endif #define HOOKS_NUM 4 @@ -192,7 +199,7 @@ static void GetWordTextOutHook (TEverythingParams *TP) LeaveCriticalSection(&hookCS); } -char* ExtractFromEverything(HWND WND, POINT Pt, int *BeginPos) +char* ExtractFromEverything(HWND WND, POINT Pt, DWORD *BeginPos) { TEverythingParams CParams; @@ -588,6 +595,8 @@ BOOL APIENTRY DllMain (HINSTANCE hInst /* Library instance handle. */ , DWORD reason /* Reason this function is being called. */ , LPVOID reserved /* Not used. */ ) { +(void) hInst; +(void) reserved; switch (reason) { case DLL_PROCESS_ATTACH: diff --git a/mouseover_win32/TextOutHook.h b/mouseover_win32/TextOutHook.h index 1b4b6e75..de5256bd 100644 --- a/mouseover_win32/TextOutHook.h +++ b/mouseover_win32/TextOutHook.h @@ -20,7 +20,7 @@ typedef struct TEverythingParams { wchar_t MatchedWordW[256]; } TEverythingParams; -char* ExtractFromEverything(HWND WND, POINT Pt, int *BeginPos); +char* ExtractFromEverything(HWND WND, POINT Pt, DWORD *BeginPos); DLLIMPORT void GetWord (TCurrentMode *P); diff --git a/mouseover_win32/TextOutSpy.c b/mouseover_win32/TextOutSpy.c index 22f6d551..f7f196ae 100644 --- a/mouseover_win32/TextOutSpy.c +++ b/mouseover_win32/TextOutSpy.c @@ -1,3 +1,5 @@ +#include +#include #include "TextOutSpy.h" #include "ThTypes.h" #include "GDDataTranfer.h" @@ -31,17 +33,9 @@ HWND WndParent,WndChild; static void SendWordToServer() { -DWORD SendMsgAnswer, flags; +DWORD_PTR SendMsgAnswer; +DWORD flags; LRESULT lr; - if (hGetWordLib == 0) { - hGetWordLib = LoadLibrary(GlobalData->LibName); - if (hGetWordLib) { - GetWordProc = (GetWordProc_t)GetProcAddress(hGetWordLib, "__gdGetWord"); - } - else { - hGetWordLib = (HINSTANCE)-1; - } - } if( !IsWindow( GlobalData->ServerWND ) ) return; @@ -51,10 +45,21 @@ LRESULT lr; if( lr == 0 || SendMsgAnswer == 0) //No answer or no needing return; + flags = SendMsgAnswer; + + if (hGetWordLib == 0 && ( flags & GD_FLAG_METHOD_STANDARD ) ) { + hGetWordLib = LoadLibraryW(GlobalData->LibName); + if (hGetWordLib) { + GetWordProc = (GetWordProc_t)GetProcAddress(hGetWordLib, "__gdGetWord"); + } + else { + hGetWordLib = INVALID_HANDLE_VALUE; + } + } + GlobalData->CurMod.MatchedWord[0] = 0; GlobalData->CurMod.WordLen = 0; GlobalData->CurMod.BeginPos = 0; - flags = SendMsgAnswer; if( ( flags & GD_FLAG_METHOD_GD_MESSAGE ) != 0 && uGdAskMessage != 0 ) { int n; @@ -71,8 +76,14 @@ LRESULT lr; GlobalData->CurMod.WordLen = n; GlobalData->CurMod.BeginPos = 0; if(n > 0) { - if( IsWindow( GlobalData->ServerWND ) ) + if( IsWindow( GlobalData->ServerWND ) ) { +#ifdef __WIN64 + GlobalData32->CurMod.WordLen = n; + GlobalData32->CurMod.BeginPos = 0; + lstrcpyn( GlobalData32->CurMod.MatchedWord, GlobalData->CurMod.MatchedWord, sizeof( GlobalData32->CurMod.MatchedWord ) ); +#endif SendMessageTimeout(GlobalData->ServerWND, WM_MY_SHOW_TRANSLATION, 0, 0, SMTO_ABORTIFHUNG, MOUSEOVER_INTERVAL, &SendMsgAnswer); + } } return; } @@ -81,10 +92,18 @@ LRESULT lr; if( ( flags & GD_FLAG_METHOD_STANDARD ) != 0 && GetWordProc != 0 ) { GlobalData->CurMod.WND = GlobalData->LastWND; GlobalData->CurMod.Pt = GlobalData->LastPt; + GetWordProc(&(GlobalData->CurMod)); + if (GlobalData->CurMod.WordLen > 0) { - if( IsWindow( GlobalData->ServerWND ) ) + if( IsWindow( GlobalData->ServerWND ) ) { +#ifdef __WIN64 + GlobalData32->CurMod.WordLen = GlobalData->CurMod.WordLen; + GlobalData32->CurMod.BeginPos = GlobalData->CurMod.BeginPos; + lstrcpyn( GlobalData32->CurMod.MatchedWord, GlobalData->CurMod.MatchedWord, sizeof( GlobalData32->CurMod.MatchedWord ) ); +#endif SendMessageTimeout(GlobalData->ServerWND, WM_MY_SHOW_TRANSLATION, 0, 0, SMTO_ABORTIFHUNG, MOUSEOVER_INTERVAL, &SendMsgAnswer); + } return; } } @@ -92,8 +111,14 @@ LRESULT lr; if( ( flags & GD_FLAG_METHOD_IACCESSIBLEEX ) != 0 ) { getWordByAccEx( GlobalData->LastPt ); if (GlobalData->CurMod.WordLen > 0 ) { - if( IsWindow( GlobalData->ServerWND ) ) + if( IsWindow( GlobalData->ServerWND ) ) { +#ifdef __WIN64 + GlobalData32->CurMod.WordLen = GlobalData->CurMod.WordLen; + GlobalData32->CurMod.BeginPos = GlobalData->CurMod.BeginPos; + lstrcpyn( GlobalData32->CurMod.MatchedWord, GlobalData->CurMod.MatchedWord, sizeof( GlobalData32->CurMod.MatchedWord ) ); +#endif SendMessageTimeout(GlobalData->ServerWND, WM_MY_SHOW_TRANSLATION, 0, 0, SMTO_ABORTIFHUNG, MOUSEOVER_INTERVAL, &SendMsgAnswer); + } return; } } @@ -103,8 +128,11 @@ LRESULT lr; } } -void CALLBACK TimerFunc(HWND hWnd,UINT nMsg,UINT nTimerid,DWORD dwTime) +void CALLBACK TimerFunc(HWND hWnd,UINT nMsg,UINT_PTR nTimerid,DWORD dwTime) { +(void) hWnd; +(void) nMsg; +(void) dwTime; DWORD wso; wso = WaitForSingleObject(hSynhroMutex, 0); if (wso == WAIT_OBJECT_0 || wso == WAIT_ABANDONED) { @@ -144,56 +172,93 @@ DWORD wso; } } +void HookProc( POINT *ppt ) +{ +HWND WND; +TCHAR wClassName[64]; +DWORD winProcessID; + WND = GetWindowFromPoint( *ppt ); + if(WND == NULL) return; + + if ( !GetClassName(WND, wClassName, sizeof(wClassName) / sizeof(TCHAR)) ) + return; + + GetWindowThreadProcessId( WND, &winProcessID ); + + if( winProcessID != ourProcessID && lstrcmpi( wClassName, _T("ConsoleWindowClass") ) != 0 ) + return; + + if(TimerID && ( GlobalData->LastPt.x != ppt->x || GlobalData->LastPt.y != ppt->y ) ) + { + KillTimer(0, TimerID); + TimerID = 0; + } + + const char* DisableClasses[] = { + "gdkWindowChild", + "gdkWindowTemp", + "Progman", + "WorkerW", + }; + int i; + for (i=0; i<4; i++) { + if (lstrcmp(wClassName, DisableClasses[i])==0) + break; + } + if (i<4) return; + + if(GlobalData->LastPt.x != ppt->x || GlobalData->LastPt.y != ppt->y || GlobalData->LastWND != WND ) + { + GlobalData->LastWND = WND; + GlobalData->LastPt = *ppt; + TimerID = SetTimer(0, TimerID, MOUSEOVER_INTERVAL, TimerFunc); + } +} + +#ifdef __WIN64 + +LRESULT CALLBACK GetMessageHookProc(int nCode, WPARAM wParam, LPARAM lParam) +{ +PMSG pMsg; +DWORD wso; + if( nCode == HC_ACTION && wParam == PM_REMOVE ) + { + pMsg = (PMSG)lParam; + if( pMsg && ( pMsg->message == WM_MOUSEMOVE || pMsg->message == WM_NCMOUSEMOVE ) ) + { + wso = WaitForSingleObject(hSynhroMutex, 0); + if (wso == WAIT_OBJECT_0 || wso == WAIT_ABANDONED) + { + POINT pt; + pt.x = GET_X_LPARAM( pMsg->lParam ); + pt.y = GET_Y_LPARAM( pMsg->lParam ); + if( pMsg->message == WM_MOUSEMOVE && pMsg->hwnd != NULL ) + ClientToScreen( pMsg->hwnd, &pt ); + HookProc( &pt ); + ReleaseMutex(hSynhroMutex); + } + } + } + return CallNextHookEx(GlobalData->g_hHook, nCode, wParam, lParam); +} + +#else + LRESULT CALLBACK MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam) { DWORD wso; - if ((nCode == HC_ACTION) && ((wParam == WM_MOUSEMOVE) || (wParam == WM_NCMOUSEMOVE)) && (GlobalData != NULL)) { + if ( (nCode == HC_ACTION) && ((wParam == WM_MOUSEMOVE) || (wParam == WM_NCMOUSEMOVE)) ) { wso = WaitForSingleObject(hSynhroMutex, 0); if (wso == WAIT_OBJECT_0 || wso == WAIT_ABANDONED) { - HWND WND; - TCHAR wClassName[64]; - - if(TimerID && ( GlobalData->LastPt.x!=((PMOUSEHOOKSTRUCT)lParam)->pt.x || GlobalData->LastPt.y!=((PMOUSEHOOKSTRUCT)lParam)->pt.y ) ) { - KillTimer(0, TimerID); - TimerID = 0; - } - - WND = GetWindowFromPoint(((PMOUSEHOOKSTRUCT)lParam)->pt); - - if(WND == NULL) { - ReleaseMutex(hSynhroMutex); - return CallNextHookEx(GlobalData->g_hHookMouse, nCode, wParam, lParam); - } - - if (GetClassName(WND, wClassName, sizeof(wClassName) / sizeof(TCHAR))) { - const char* DisableClasses[] = { - "gdkWindowChild", - "gdkWindowTemp", - "Progman", - "WorkerW", - }; - int i; - for (i=0; i<4; i++) { - if (lstrcmp(wClassName, DisableClasses[i])==0) - break; - } - if (i<4) { - ReleaseMutex(hSynhroMutex); - return CallNextHookEx(GlobalData->g_hHookMouse, nCode, wParam, lParam); - } - } - - if(GlobalData->LastPt.x!=((PMOUSEHOOKSTRUCT)lParam)->pt.x || GlobalData->LastPt.y!=((PMOUSEHOOKSTRUCT)lParam)->pt.y || GlobalData->LastWND != WND) { - GlobalData->LastWND = WND; - GlobalData->LastPt = ((PMOUSEHOOKSTRUCT)lParam)->pt; - TimerID = SetTimer(0, TimerID, MOUSEOVER_INTERVAL, TimerFunc); - } + HookProc( &(((PMOUSEHOOKSTRUCT)lParam)->pt) ); ReleaseMutex(hSynhroMutex); } } - return CallNextHookEx(GlobalData->g_hHookMouse, nCode, wParam, lParam); + return CallNextHookEx(GlobalData->g_hHook, nCode, wParam, lParam); } +#endif + DLLIMPORT void ActivateTextOutSpying (int Activate) { // After call SetWindowsHookEx(), when you move mouse to a application's window, @@ -201,19 +266,23 @@ DLLIMPORT void ActivateTextOutSpying (int Activate) // after call UnhookWindowsHookEx(). if(GlobalData == NULL) return; if (Activate) { - if (GlobalData->g_hHookMouse != NULL) return; - GlobalData->g_hHookMouse = SetWindowsHookEx(WH_MOUSE, MouseHookProc, g_hInstance, 0); + if (GlobalData->g_hHook != NULL) return; +#ifdef __WIN64 + GlobalData->g_hHook = SetWindowsHookEx(WH_GETMESSAGE, GetMessageHookProc, g_hInstance, 0); +#else + GlobalData->g_hHook = SetWindowsHookEx(WH_MOUSE, MouseHookProc, g_hInstance, 0); +#endif } else { - if (GlobalData->g_hHookMouse == NULL) return; + if (GlobalData->g_hHook == NULL) return; WaitForSingleObject(hSynhroMutex, 2000); - UnhookWindowsHookEx(GlobalData->g_hHookMouse); + UnhookWindowsHookEx(GlobalData->g_hHook); if (TimerID) { KillTimer(0, TimerID); TimerID=0; } ReleaseMutex(hSynhroMutex); - GlobalData->g_hHookMouse = NULL; + GlobalData->g_hHook = NULL; } } @@ -222,10 +291,20 @@ BOOL APIENTRY DllMain (HINSTANCE hInst /* Library instance handle. */ , DWORD reason /* Reason this function is being called. */ , LPVOID reserved /* Not used. */ ) { +(void) reserved; switch (reason) { case DLL_PROCESS_ATTACH: g_hInstance = hInst; + ThTypes_Init(); +#ifdef __WIN64 + if( GlobalData == NULL || GlobalData32 == NULL ) { +#else + if( GlobalData == NULL ) { +#endif + ThTypes_End(); + return FALSE; + } ourProcessID = GetCurrentProcessId(); if(hSynhroMutex==0) { hSynhroMutex = CreateMutex(NULL, FALSE, "GoldenDictTextOutSpyMutex"); @@ -233,7 +312,6 @@ BOOL APIENTRY DllMain (HINSTANCE hInst /* Library instance handle. */ , return(FALSE); } } - ThTypes_Init(); uGdAskMessage = RegisterWindowMessage(GD_MESSAGE_NAME); FindGetPhysicalCursorPos(); break; @@ -254,10 +332,10 @@ BOOL APIENTRY DllMain (HINSTANCE hInst /* Library instance handle. */ , MSG msg ; while (PeekMessage (&msg, 0, WM_TIMER, WM_TIMER, PM_REMOVE)); } - if ((hGetWordLib != 0)&&(hGetWordLib != (HINSTANCE)(-1))) { + if ( (hGetWordLib != 0) && (hGetWordLib != INVALID_HANDLE_VALUE) ) { FreeLibrary(hGetWordLib); } - Thtypes_End(); + ThTypes_End(); break; case DLL_THREAD_ATTACH: diff --git a/mouseover_win32/ThTypes.c b/mouseover_win32/ThTypes.c index 9ba40230..a8d8b8b3 100644 --- a/mouseover_win32/ThTypes.c +++ b/mouseover_win32/ThTypes.c @@ -3,19 +3,38 @@ HANDLE MMFHandle = 0; TGlobalDLLData *GlobalData = NULL; +#ifdef __WIN64 +HANDLE MMFHandle32 = 0; +TGlobalDLLData32 *GlobalData32 = NULL; +LPCSTR SHARE_NAME32 = "GoldenDictTextOutHookSharedMem"; +LPCSTR SHARE_NAME = "GoldenDictTextOutHookSharedMem64"; +#else +LPCSTR SHARE_NAME = "GoldenDictTextOutHookSharedMem"; +#endif + void ThTypes_Init() { if (!MMFHandle) { - MMFHandle = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(TGlobalDLLData), "GoldenDictTextOutHookSharedMem"); + MMFHandle = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(TGlobalDLLData), SHARE_NAME); } if (!MMFHandle) { - MMFHandle = OpenFileMappingA(FILE_MAP_READ | FILE_MAP_WRITE, 0, "GoldenDictTextOutHookSharedMem"); + MMFHandle = OpenFileMappingA(FILE_MAP_READ | FILE_MAP_WRITE, 0, SHARE_NAME); } if (!GlobalData && MMFHandle != NULL) GlobalData = MapViewOfFile(MMFHandle, FILE_MAP_ALL_ACCESS, 0, 0, 0); +#ifdef __WIN64 + if (!MMFHandle32) { + MMFHandle32 = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(TGlobalDLLData32), SHARE_NAME32); + } + if (!MMFHandle32) { + MMFHandle32 = OpenFileMappingA(FILE_MAP_READ | FILE_MAP_WRITE, 0, SHARE_NAME32); + } + if (!GlobalData32 && MMFHandle32 != NULL) + GlobalData32 = MapViewOfFile(MMFHandle32, FILE_MAP_ALL_ACCESS, 0, 0, 0); +#endif } -void Thtypes_End() +void ThTypes_End() { if (GlobalData) { UnmapViewOfFile(GlobalData); @@ -25,4 +44,14 @@ void Thtypes_End() CloseHandle(MMFHandle); MMFHandle = 0; } +#ifdef __WIN64 + if (GlobalData32) { + UnmapViewOfFile(GlobalData32); + GlobalData32 = NULL; + } + if (MMFHandle32) { + CloseHandle(MMFHandle32); + MMFHandle32 = 0; + } +#endif } diff --git a/mouseover_win32/ThTypes.h b/mouseover_win32/ThTypes.h index efdaa57f..7ecb89c4 100644 --- a/mouseover_win32/ThTypes.h +++ b/mouseover_win32/ThTypes.h @@ -13,29 +13,58 @@ extern "C" { #endif /* __cplusplus */ +#pragma pack(push,4) + typedef struct TCurrentMode { HWND WND; POINT Pt; - size_t WordLen; + DWORD WordLen; char MatchedWord[256]; - int BeginPos; + DWORD BeginPos; } TCurrentMode; typedef struct TGlobalDLLData { HWND ServerWND; - HHOOK g_hHookMouse; - UINT_PTR TimerID; + HHOOK g_hHook; HWND LastWND; POINT LastPt; TCurrentMode CurMod; - char LibName[256]; + WCHAR LibName[256]; } TGlobalDLLData; +#pragma pack(pop) + extern TGlobalDLLData *GlobalData; +#ifdef __WIN64 + +#pragma pack(push,4) + +typedef struct TCurrentMode32 { + DWORD WND; + POINT Pt; + DWORD WordLen; + char MatchedWord[256]; + DWORD BeginPos; +} TCurrentMode32; + +typedef struct TGlobalDLLData32 { + DWORD ServerWND; + DWORD g_hHook; + DWORD LastWND; + POINT LastPt; + TCurrentMode32 CurMod; + WCHAR LibName[256]; +} TGlobalDLLData32; + +#pragma pack(pop) + +extern TGlobalDLLData32 *GlobalData32; + +#endif void ThTypes_Init(); -void Thtypes_End(); +void ThTypes_End(); #ifdef __cplusplus } diff --git a/mouseover_win32/x64hooks.c b/mouseover_win32/x64hooks.c new file mode 100644 index 00000000..8493ebf3 --- /dev/null +++ b/mouseover_win32/x64hooks.c @@ -0,0 +1,140 @@ +#define UNICODE +#define _UNICODE + +#include +#include +#include +#include +#include +#include +#include +#include "thtypes.h" + +typedef void ( *ActivateSpyFn )( BOOL ); + +BOOL parentIsGD() +{ +HANDLE hSnapshot, hModuleSnapshot; +PROCESSENTRY32 pe; +MODULEENTRY32 me; +DWORD procID; +BOOL b; + procID = GetCurrentProcessId(); + hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 ); + if( hSnapshot == INVALID_HANDLE_VALUE ) + return FALSE; + ZeroMemory( &pe, sizeof(pe) ); + pe.dwSize = sizeof(pe); + b = Process32First( hSnapshot, &pe ); + while(b) { + if( pe.th32ProcessID == procID ) { + hModuleSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, pe.th32ParentProcessID ); + if( hModuleSnapshot == INVALID_HANDLE_VALUE ) { + b = FALSE; + break; + } + ZeroMemory( &me, sizeof(me) ); + me.dwSize = sizeof(me); + b = Module32First( hModuleSnapshot, &me ); + if( b ) { + int n = lstrlen( me.szExePath ); + b = n >= 14 && lstrcmpi( me.szExePath + n - 14, _T("GoldenDict.exe") ) == 0; + } + CloseHandle( hModuleSnapshot ); + break; + } + b = Process32Next( hSnapshot, &pe ); + } + CloseHandle( hSnapshot ); + return b; +} + +void SetLowLabelToGDSynchroObjects() +{ +// The LABEL_SECURITY_INFORMATION SDDL SACL to be set for low integrity +#define LOW_INTEGRITY_SDDL_SACL_W L"S:(ML;;NW;;;LW)" + PSECURITY_DESCRIPTOR pSD = NULL; + + PACL pSacl = NULL; // not allocated + BOOL fSaclPresent = FALSE; + BOOL fSaclDefaulted = FALSE; + LPCWSTR pwszMapFileName = L"GoldenDictTextOutHookSharedMem64"; + + if( ConvertStringSecurityDescriptorToSecurityDescriptorW( LOW_INTEGRITY_SDDL_SACL_W, 1 /* SDDL_REVISION_1 */, &pSD, NULL ) ) + { + if( GetSecurityDescriptorSacl(pSD, &fSaclPresent, &pSacl, &fSaclDefaulted)) + { +// Note that psidOwner, psidGroup, and pDacl are +// all NULL and set the new LABEL_SECURITY_INFORMATION + + SetNamedSecurityInfoW( (LPWSTR)pwszMapFileName, SE_KERNEL_OBJECT, LABEL_SECURITY_INFORMATION, NULL, NULL, NULL, pSacl); + + } + LocalFree(pSD); + } +} + +int APIENTRY WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow) +{ +(void) hInstance; +(void) hPrevInstance; +(void) lpCmdLine; +(void) nCmdShow; + +TCHAR dir[MAX_PATH], libName[MAX_PATH], *pch; +HWND hServerWnd; +ActivateSpyFn activateSpyFn = NULL; +HINSTANCE spyDll = NULL; +int ret = -1; +MSG msg; + + if( !parentIsGD() ) + return -1; + + while( 1 ) { + ThTypes_Init(); + if( GlobalData == NULL || GlobalData32 == NULL) + break; + hServerWnd = LongToHandle( GlobalData32->ServerWND ); + + GetModuleFileName( NULL, dir, MAX_PATH ); + pch = dir + lstrlen( dir ); + while( pch != dir && *pch != '\\' ) pch--; + *(pch + 1) = 0; + lstrcpy( libName, dir ); + lstrcat( libName, _T("GdTextOutSpy64.dll") ); + + SetLowLabelToGDSynchroObjects(); + + memset( GlobalData, 0, sizeof( TGlobalDLLData ) ); + lstrcpy( GlobalData->LibName, dir ); + lstrcat( GlobalData->LibName, _T("GdTextOutHook64.dll") ); + GlobalData->ServerWND = hServerWnd; + + spyDll = LoadLibrary( libName ); + if ( spyDll ) + activateSpyFn = ( ActivateSpyFn ) GetProcAddress( spyDll, "ActivateTextOutSpying" ); + if( !activateSpyFn ) { + ret = -2; + break; + } + + activateSpyFn( TRUE ); + + while( GetMessage( &msg, 0, 0, 0 ) ) + DispatchMessage( &msg ); + + activateSpyFn( FALSE ); + + ret = 0; + break; + } + + if( spyDll ) + FreeLibrary( spyDll ); + ThTypes_End(); + return ret; +} diff --git a/x64.cc b/x64.cc new file mode 100644 index 00000000..806740ea --- /dev/null +++ b/x64.cc @@ -0,0 +1,63 @@ +#include +#include + +#ifndef _UNICODE +#define _UNICODE +#endif + +#include "x64.hh" +#include +#include + +typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL); +PROCESS_INFORMATION pInfo; + +bool isWow64() +{ + static LPFN_ISWOW64PROCESS fnIsWow64Process; + BOOL bIsWow64 = FALSE; + + if( NULL == fnIsWow64Process ) + fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress( GetModuleHandle( _T("kernel32") ), "IsWow64Process" ); + if( NULL != fnIsWow64Process ) + { + if ( !fnIsWow64Process( GetCurrentProcess(), &bIsWow64 ) ) + return false; + } + return bIsWow64; +} + +bool installx64Hooks() +{ +STARTUPINFO startup; + if( !isWow64() ) + return false; + if( pInfo.hProcess != NULL ) + removex64Hooks(); + QDir dir = QCoreApplication::applicationDirPath(); + if( !dir.cd("x64") ) + return false; + QString starterProc = QDir::toNativeSeparators( dir.filePath( "x64helper.exe" ) ); + + memset( &startup, 0, sizeof(startup) ); + startup.cb = sizeof(startup); + + BOOL b = CreateProcess( starterProc.toStdWString().c_str(), NULL, NULL, NULL, FALSE, CREATE_NO_WINDOW | DETACHED_PROCESS, NULL, NULL, &startup, &pInfo ); + if( !b ) + pInfo.hProcess = NULL; + + return b; +} + +void removex64Hooks() +{ + if( pInfo.hProcess == NULL ) + return; + PostThreadMessage( pInfo.dwThreadId, WM_QUIT, 0, 0 ); + DWORD res = WaitForSingleObject( pInfo.hProcess, 3000 ); + if( res == WAIT_TIMEOUT ) + TerminateProcess( pInfo.hProcess, 1 ); + CloseHandle( pInfo.hProcess ); + CloseHandle( pInfo.hThread ); + pInfo.hProcess = NULL; +} diff --git a/x64.hh b/x64.hh new file mode 100644 index 00000000..f8c223aa --- /dev/null +++ b/x64.hh @@ -0,0 +1,8 @@ +#ifndef __X64_HH_INCLUDED__ +#define __X64_HH_INCLUDED__ + +bool isWow64(); +bool installx64Hooks(); +void removex64Hooks(); + +#endif // __X64_HH_INCLUDED__