mirror of
https://github.com/xiaoyifang/goldendict-ng.git
synced 2024-11-23 20:14:05 +00:00
Win-specific: ScanPopup in 64-bit applications
This commit is contained in:
parent
fa60062fa4
commit
c9192acef4
|
@ -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 )
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
14
mouseover.cc
14
mouseover.cc
|
@ -12,6 +12,7 @@
|
|||
#include <aclapi.h>
|
||||
#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
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -7,6 +7,10 @@
|
|||
#include <oleacc.h>
|
||||
#include <servprov.h>
|
||||
|
||||
#ifdef INTERFACE
|
||||
#undef INTERFACE
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#include <tchar.h>
|
||||
#include <windowsx.h>
|
||||
#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:
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
140
mouseover_win32/x64hooks.c
Normal file
140
mouseover_win32/x64hooks.c
Normal file
|
@ -0,0 +1,140 @@
|
|||
#define UNICODE
|
||||
#define _UNICODE
|
||||
|
||||
#include <Windows.h>
|
||||
#include <Tlhelp32.h>
|
||||
#include <tchar.h>
|
||||
#include <sddl.h>
|
||||
#include <accctrl.h>
|
||||
#include <aclapi.h>
|
||||
#include <basetsd.h>
|
||||
#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;
|
||||
}
|
63
x64.cc
Normal file
63
x64.cc
Normal file
|
@ -0,0 +1,63 @@
|
|||
#include <QCoreApplication>
|
||||
#include <QDir>
|
||||
|
||||
#ifndef _UNICODE
|
||||
#define _UNICODE
|
||||
#endif
|
||||
|
||||
#include "x64.hh"
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
|
||||
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;
|
||||
}
|
Loading…
Reference in a new issue