diff --git a/build.xml b/build.xml index 2a69e30..557de61 100644 --- a/build.xml +++ b/build.xml @@ -77,5 +77,8 @@ + + + \ No newline at end of file diff --git a/native/MsgHook.suo b/native/MsgHook.suo index ee98348..e708592 100644 Binary files a/native/MsgHook.suo and b/native/MsgHook.suo differ diff --git a/native/MsgHook/MsgHook.cpp b/native/MsgHook/MsgHook.cpp index e2a7565..5677596 100644 --- a/native/MsgHook/MsgHook.cpp +++ b/native/MsgHook/MsgHook.cpp @@ -12,7 +12,7 @@ #include "stdafx.h" -LRESULT CALLBACK HookProc(int nCode, WPARAM wParam, LPARAM lParam) +LRESULT CALLBACK CwpHookProc(int nCode, WPARAM wParam, LPARAM lParam) { COPYDATASTRUCT CDS; HEVENT Event; @@ -21,43 +21,84 @@ LRESULT CALLBACK HookProc(int nCode, WPARAM wParam, LPARAM lParam) CDS.cbData = sizeof(Event); CDS.lpData = &Event; - if (nCode == HC_ACTION) { + //if (nCode == HC_ACTION) + { //For WH_CALLWNDPROC hook a pointer to a CWPSTRUCT structure that contains details about the message. CWPSTRUCT *cwps = (CWPSTRUCT *)lParam; + Event.hWnd = cwps->hwnd; + Event.lParam = cwps->lParam; + Event.wParam = cwps->wParam; + Event.nCode = cwps->message; + Event.dwHookType = WH_CALLWNDPROC; + memset((void *)&Event.wParamStr, '\0', sizeof(TCHAR) * 25); + memset((void *)&Event.lParamStr, '\0', sizeof(TCHAR) * 25); + //if (cwps->message == WM_SETTEXT && cwps->lParam != 0) + // _tcscpy_s(Event.lParamStr, 25, (const wchar_t*)Event.lParam); - Event.lParam = cwps->lParam; - Event.wParam = cwps->wParam; - Event.nCode = cwps->message; - Event.dwHookType = WH_CALLWNDPROC; - - BOOL bRes = SendMessage(pData->g_hWnd, WM_COPYDATA, 0, (LPARAM)(VOID*)&CDS); // ask the controlling program if the hook should be passed + BOOL bRes = (BOOL)SendMessage(pData->g_hWnd, WM_COPYDATA, 0, (LPARAM)(VOID*)&CDS); // ask the controlling program if the hook should be passed } - return CallNextHookEx(pData->g_hHook, nCode, wParam, lParam); // pass hook to next handler + return CallNextHookEx(pData->g_CwpHook, nCode, wParam, lParam); // pass hook to next handler //return bRes; // Don't tell the other hooks about this message. } -extern "C" __declspec(dllexport) BOOL SetHook(HWND callerHWnd, DWORD threadId) +LRESULT CALLBACK MsgHookProc(int nCode, WPARAM wParam, LPARAM lParam) +{ + COPYDATASTRUCT CDS; + HEVENT Event; + + CDS.dwData = 0; + CDS.cbData = sizeof(Event); + CDS.lpData = &Event; + + //if (nCode == HC_ACTION) + { + //For WH_GETMESSAGE hook a pointer to a MSG structure that contains details about the message. + MSG *msg = (MSG *)lParam; + Event.hWnd = msg->hwnd; + Event.lParam = msg->lParam; + Event.wParam = msg->wParam; + Event.nCode = msg->message; + Event.dwHookType = WH_GETMESSAGE; + memset((void *)&Event.wParamStr, '\0', sizeof(TCHAR) * 25); + memset((void *)&Event.lParamStr, '\0', sizeof(TCHAR) * 25); + //if (msg->message == WM_SETTEXT && msg->lParam != 0) + // _tcscpy_s(Event.lParamStr, 25, (const wchar_t*)Event.lParam); + //if (msg->message == WM_COMMAND || msg->message == WM_MENUCOMMAND) //infinite loop? + BOOL bRes = (BOOL)SendMessage(pData->g_hWnd, WM_COPYDATA, 0, (LPARAM)(VOID*)&CDS); // ask the controlling program if the hook should be passed + } + + return CallNextHookEx(pData->g_MsgHook, nCode, wParam, lParam); // pass hook to next handler + //return bRes; // Don't tell the other hooks about this message. +} + +extern "C" __declspec(dllexport) BOOL SetMsgHook(HWND callerHWnd, DWORD threadId) { if(bStartingProcess) // if we're just starting the DLL for the first time, { pData->g_hWnd = callerHWnd; // remember the windows and hook handle for further instances - pData->g_hHook = SetWindowsHookEx(WH_CALLWNDPROC, (HOOKPROC)HookProc, (HINSTANCE)pData->g_hInstance, threadId); + pData->g_CwpHook = SetWindowsHookEx(WH_CALLWNDPROC, (HOOKPROC)CwpHookProc, (HINSTANCE)pData->g_hInstance, threadId); + //pData->g_MsgHook = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)MsgHookProc, (HINSTANCE)pData->g_hInstance, threadId); - return (pData->g_hHook != NULL); + return (pData->g_CwpHook != NULL); //pData->g_CwpHook != NULL && } - else - return false; + else + return false; } extern "C" __declspec(dllexport) BOOL RemoveHook() { if (pData == NULL) return false; - if(pData->g_hHook) // if the hook is defined + if(pData->g_MsgHook) // if the hook is defined { - bool ret = UnhookWindowsHookEx(pData->g_hHook); + UnhookWindowsHookEx(pData->g_MsgHook); + pData->g_MsgHook = NULL; + } + if(pData->g_CwpHook) // if the hook is defined + { + BOOL ret = UnhookWindowsHookEx(pData->g_CwpHook); pData->g_hWnd = NULL; // reset data - pData->g_hHook = NULL; + pData->g_CwpHook = NULL; return ret; } return false; diff --git a/native/MsgHook/MsgHook.vcxproj b/native/MsgHook/MsgHook.vcxproj index f613a06..33a1f06 100644 --- a/native/MsgHook/MsgHook.vcxproj +++ b/native/MsgHook/MsgHook.vcxproj @@ -70,9 +70,11 @@ false + $(JAVA_HOME)\include;$(JAVA_HOME)\include\win32;$(IncludePath) false + $(JAVA_HOME)\include;$(JAVA_HOME)\include\win32;$(IncludePath) @@ -142,6 +144,7 @@ copy /Y "$(TargetPath)" "$(ProjectDir)bin\MsgHook$(PlatformArchitecture)$(Target + @@ -161,6 +164,7 @@ copy /Y "$(TargetPath)" "$(ProjectDir)bin\MsgHook$(PlatformArchitecture)$(Target + Create Create diff --git a/native/MsgHook/MsgHook.vcxproj.filters b/native/MsgHook/MsgHook.vcxproj.filters index c8c6ca7..61ce41a 100644 --- a/native/MsgHook/MsgHook.vcxproj.filters +++ b/native/MsgHook/MsgHook.vcxproj.filters @@ -24,6 +24,9 @@ Header Files + + Header Files + @@ -35,5 +38,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/native/MsgHook/bin/MsgHook32.dll b/native/MsgHook/bin/MsgHook32.dll index 7aa62dd..fc01f28 100644 Binary files a/native/MsgHook/bin/MsgHook32.dll and b/native/MsgHook/bin/MsgHook32.dll differ diff --git a/native/MsgHook/bin/MsgHook64.dll b/native/MsgHook/bin/MsgHook64.dll index 845c912..a62d705 100644 Binary files a/native/MsgHook/bin/MsgHook64.dll and b/native/MsgHook/bin/MsgHook64.dll differ diff --git a/native/MsgHook/dllmain.cpp b/native/MsgHook/dllmain.cpp index d7866d3..5882787 100644 --- a/native/MsgHook/dllmain.cpp +++ b/native/MsgHook/dllmain.cpp @@ -19,9 +19,10 @@ BOOL APIENTRY DllMain( HMODULE hModule, memset((void *)&szBaseName, '\0', sizeof(TCHAR) * _MAX_FNAME); if (GetModuleBaseName(GetCurrentProcess(), (HMODULE)hModule, szTmp, sizeof(szTmp)))// compute MMF-filename from current module base name, uses Psapi - _wsplitpath(szTmp, NULL, NULL, szBaseName, NULL); + _wsplitpath_s(szTmp, NULL, NULL, szBaseName, _MAX_FNAME, NULL, NULL, NULL, NULL); + //_wsplitpath(szTmp, NULL, NULL, szBaseName, NULL); - wcscat(szBaseName, TEXT("MsgHookSharedMem")); // add specifier string + wcscat_s(szBaseName, TEXT("MsgHookSharedMem")); // add specifier string hMappedFile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(GLOBALDATA), szBaseName); pData = (GLOBALDATA*)MapViewOfFile(hMappedFile, FILE_MAP_WRITE, 0, 0, 0); @@ -29,9 +30,10 @@ BOOL APIENTRY DllMain( HMODULE hModule, if(bStartingProcess) // if the MMF doesn't exist, we have the first instance { - pData->g_hInstance = hModule; // so set the instance handle - pData->g_hWnd = NULL; // and initialize the other handles - pData->g_hHook = NULL; + pData->g_hInstance = hModule; // so set the instance handle + pData->g_hWnd = NULL; // and initialize the other handles + pData->g_CwpHook = NULL; + pData->g_MsgHook = NULL; } DisableThreadLibraryCalls((HMODULE)hModule); } diff --git a/native/MsgHook/org_synthuse_MsgHook.cpp b/native/MsgHook/org_synthuse_MsgHook.cpp new file mode 100644 index 0000000..a5665c1 --- /dev/null +++ b/native/MsgHook/org_synthuse_MsgHook.cpp @@ -0,0 +1,29 @@ +/* + * Copyright 2014, Synthuse.org + * Released under the Apache Version 2.0 License. + * + * last modified by ejakubowski7@gmail.com +*/ + +#include "stdafx.h" +#include "org_synthuse_MsgHook.h" + +/* + * Class: org_synthuse_MsgHook + * Method: setMessageHook + * Signature: (JJ)Z + */ +JNIEXPORT jboolean JNICALL Java_org_synthuse_MsgHook_setMessageHook(JNIEnv *env, jobject obj, jlong jhWnd, jlong jthreadId) +{ + return SetMsgHook((HWND)jhWnd, (DWORD)jthreadId); +} + +/* + * Class: org_synthuse_MsgHook + * Method: removeMessageHook + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_org_synthuse_MsgHook_removeMessageHook(JNIEnv *env, jobject obj) +{ + return RemoveHook(); +} \ No newline at end of file diff --git a/native/MsgHook/org_synthuse_MsgHook.h b/native/MsgHook/org_synthuse_MsgHook.h new file mode 100644 index 0000000..93144b7 --- /dev/null +++ b/native/MsgHook/org_synthuse_MsgHook.h @@ -0,0 +1,29 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_synthuse_MsgHook */ + +#ifndef _Included_org_synthuse_MsgHook +#define _Included_org_synthuse_MsgHook +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_synthuse_MsgHook + * Method: setMessageHook + * Signature: (JJ)Z + */ +JNIEXPORT jboolean JNICALL Java_org_synthuse_MsgHook_setMessageHook + (JNIEnv *, jobject, jlong, jlong); + +/* + * Class: org_synthuse_MsgHook + * Method: removeMessageHook + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_org_synthuse_MsgHook_removeMessageHook + (JNIEnv *, jobject); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/native/MsgHook/stdafx.h b/native/MsgHook/stdafx.h index bf473c9..2ee36f5 100644 --- a/native/MsgHook/stdafx.h +++ b/native/MsgHook/stdafx.h @@ -10,6 +10,7 @@ #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers // Windows Header Files: #include +#include #include #include @@ -19,15 +20,20 @@ typedef struct { + HWND hWnd; int nCode; DWORD dwHookType; WPARAM wParam; LPARAM lParam; + TCHAR wParamStr[25]; + TCHAR lParamStr[25]; }HEVENT; typedef struct { - HHOOK g_hHook; + HHOOK g_CwpHook; + HHOOK g_MsgHook; + //HHOOK g_hHook; HWND g_hWnd; HANDLE g_hInstance; }GLOBALDATA; @@ -35,6 +41,9 @@ typedef struct #ifndef GLOBAL_VARS_H // header guards #define GLOBAL_VARS_H +extern "C" __declspec(dllexport) BOOL SetMsgHook(HWND callerHWnd, DWORD threadId); +extern "C" __declspec(dllexport) BOOL RemoveHook(); + //Global variables , remember not to initialize here extern HANDLE hMappedFile; extern GLOBALDATA* pData; diff --git a/native/MsgHookTest/MsgHook.h b/native/MsgHookTest/MsgHook.h index bc22199..792d5e6 100644 --- a/native/MsgHookTest/MsgHook.h +++ b/native/MsgHookTest/MsgHook.h @@ -1,12 +1,19 @@ +/* + * Copyright 2014, Synthuse.org + * Released under the Apache Version 2.0 License. + * + * last modified by ejakubowski7@gmail.com +*/ + #include #define MSGHOOKER_FILE TEXT("MsgHook.dll") HINSTANCE msgHookDll; -//BOOL SetHook(HWND callerHWnd, DWORD threadId) -typedef BOOL (* SETHOOK)(HWND, DWORD); -SETHOOK SetHook; +//BOOL SetMsgHook(HWND callerHWnd, DWORD threadId) +typedef BOOL (* SETMSGHOOK)(HWND, DWORD); +SETMSGHOOK SetMsgHook; //BOOL RemoveHook() typedef BOOL (* REMOVEHOOK)(VOID); @@ -14,10 +21,13 @@ REMOVEHOOK RemoveHook; typedef struct { + HWND hWnd; int nCode; DWORD dwHookType; WPARAM wParam; LPARAM lParam; + TCHAR wParamStr[25]; + TCHAR lParamStr[25]; }HEVENT; /* @@ -30,16 +40,16 @@ typedef struct { } KBDLLHOOKSTRUCT, *PKBDLLHOOKSTRUCT; */ -BOOL InitHook(HWND hw, int threadId) +BOOL InitMsgHook(HWND hw, int threadId) { msgHookDll = LoadLibrary(MSGHOOKER_FILE); if (msgHookDll != NULL) { - SetHook = (SETHOOK)GetProcAddress(msgHookDll, "SetHook"); + SetMsgHook = (SETMSGHOOK)GetProcAddress(msgHookDll, "SetMsgHook"); RemoveHook = (REMOVEHOOK)GetProcAddress(msgHookDll, "RemoveHook"); - if (SetHook) + if (SetMsgHook) { - return SetHook(hw, threadId); + return SetMsgHook(hw, threadId); } } return false; @@ -195,8 +205,8 @@ void InitializeMsgLookup(int allowList[], int allowSize) case WM_CTLCOLORDLG: _tcscpy_s(MSG_LOOKUP[i], _T("WM_CTLCOLORDLG")); break; case WM_CTLCOLORSCROLLBAR: _tcscpy_s(MSG_LOOKUP[i], _T("WM_CTLCOLORSCROLLBAR")); break; case WM_CTLCOLORSTATIC: _tcscpy_s(MSG_LOOKUP[i], _T("WM_CTLCOLORSTATIC")); break; - case WM_MOUSEFIRST: _tcscpy_s(MSG_LOOKUP[i], _T("WM_MOUSEFIRST")); break; - //case WM_MOUSEMOVE: _tcscpy_s(MSG_LOOKUP[i], _T("WM_MOUSEMOVE")); break; + //case WM_MOUSEFIRST: _tcscpy_s(MSG_LOOKUP[i], _T("WM_MOUSEFIRST")); break; + case WM_MOUSEMOVE: _tcscpy_s(MSG_LOOKUP[i], _T("WM_MOUSEMOVE")); break; case WM_LBUTTONDOWN: _tcscpy_s(MSG_LOOKUP[i], _T("WM_LBUTTONDOWN")); break; case WM_LBUTTONUP: _tcscpy_s(MSG_LOOKUP[i], _T("WM_LBUTTONUP")); break; case WM_LBUTTONDBLCLK: _tcscpy_s(MSG_LOOKUP[i], _T("WM_LBUTTONDBLCLK")); break; diff --git a/native/MsgHookTest/MsgHookTest.aps b/native/MsgHookTest/MsgHookTest.aps index af32054..b48c55d 100644 Binary files a/native/MsgHookTest/MsgHookTest.aps and b/native/MsgHookTest/MsgHookTest.aps differ diff --git a/native/MsgHookTest/MsgHookTest.cpp b/native/MsgHookTest/MsgHookTest.cpp index a9c6580..2db2094 100644 --- a/native/MsgHookTest/MsgHookTest.cpp +++ b/native/MsgHookTest/MsgHookTest.cpp @@ -1,3 +1,10 @@ +/* + * Copyright 2014, Synthuse.org + * Released under the Apache Version 2.0 License. + * + * last modified by ejakubowski7@gmail.com +*/ + // MsgHookTest.cpp : Defines the entry point for the application. // @@ -21,11 +28,17 @@ bool filterWmNotify = false; bool filterAbove = false; +const int MAX_TEST_SIZE = 100; +TCHAR testWmSettextL[MAX_TEST_SIZE] = _T("This is a test"); +TCHAR testWmSettextW[MAX_TEST_SIZE] = _T("0"); +TCHAR testWmCommandL[MAX_TEST_SIZE] = _T("0"); +TCHAR testWmCommandW[MAX_TEST_SIZE] = _T("1"); + // Forward declarations of functions included in this code module: ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); -INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); +INT_PTR CALLBACK DlgProc(HWND, UINT, WPARAM, LPARAM); int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { @@ -127,7 +140,7 @@ void StartMessageHook() return; } - if (InitHook(mainHwnd, tid)) + if (InitMsgHook(mainHwnd, tid)) { AppendText(txtbox, _T("Hook successfully initialized\r\n")); } @@ -175,7 +188,7 @@ bool OnCopyData(COPYDATASTRUCT* pCopyDataStruct) // WM_COPYDATA lParam will have if (_tcscmp(msgName, _T("")) != 0) { TCHAR tmp[200]; - _stprintf_s(tmp, _T("msg: %s (%ld), wparam: %ld, lparam: %ld\r\n"), msgName, Event.nCode, Event.wParam, Event.lParam); + _stprintf_s(tmp, _T("%d hwnd: %ld, msg: %s (%ld), wparam: '%s'[%ld], lparam: '%s'{%ld}\r\n"),Event.dwHookType, Event.hWnd, msgName, Event.nCode, Event.wParamStr, Event.wParam, Event.lParamStr,Event.lParam); AppendText(txtbox, tmp); } } @@ -185,11 +198,22 @@ bool OnCopyData(COPYDATASTRUCT* pCopyDataStruct) // WM_COPYDATA lParam will have void SendWmSettext() //ID_TESTMSGS_WM { //SetWindowText(targetHwnd, _T("This is a test")); - TCHAR txt[] = _T("This is a test"); - SendMessage(targetHwnd, WM_SETTEXT, 0 , (LPARAM)txt); + //TCHAR txt[] = _T("This is a test"); + TCHAR *stopStr; + long wparam = _tcstol(testWmSettextW, &stopStr, 10); + SendMessage(targetHwnd, WM_SETTEXT, wparam, (LPARAM)testWmSettextL); //PostMessage(targetHwnd, WM_SETTEXT, 0 , (LPARAM)txt); } + +void SendWmCommand() //ID_TESTMSGS_WM +{ + TCHAR *stopStr; + long wparam = _tcstol(testWmCommandW, &stopStr, 10); + long lparam = _tcstol(testWmCommandL, &stopStr, 10); + SendMessage(targetHwnd, WM_COMMAND, wparam, lparam); +} + // // FUNCTION: MyRegisterClass() // @@ -299,11 +323,17 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) case ID_TESTMSGS_WM: SendWmSettext(); break; + case ID_TESTMSGS_WMCOM: + SendWmCommand(); + break; case ID_FILE_SETTINGS: - DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOG1), hWnd, About); + DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOG1), hWnd, DlgProc); break; case IDM_ABOUT: - DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); + DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, DlgProc); + break; + case ID_FILE_CLEAR: + SetWindowText(txtbox, _T("")); break; case IDM_EXIT: DestroyWindow(hWnd); @@ -334,7 +364,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) } // Message handler for about box. -INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) +INT_PTR CALLBACK DlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { UNREFERENCED_PARAMETER(lParam); switch (message) @@ -342,26 +372,28 @@ INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) case WM_INITDIALOG: { //IDC_EDIT1 - HWND classnameHwnd = GetDlgItem(hDlg, IDC_EDIT1); - if (classnameHwnd != NULL) - SetWindowText(classnameHwnd, targetClassname); - + SendDlgItemMessage(hDlg, IDC_EDIT1, WM_SETTEXT, 0 , (LPARAM)targetClassname); if (filterWmCommand) SendDlgItemMessage(hDlg, IDC_CHECK_CMD, BM_SETCHECK, BST_CHECKED, 0); if (filterWmNotify) SendDlgItemMessage(hDlg, IDC_CHECK_NOT, BM_SETCHECK, BST_CHECKED, 0); if (filterAbove) SendDlgItemMessage(hDlg, IDC_CHECK_ABO, BM_SETCHECK, BST_CHECKED, 0); - + SendDlgItemMessage(hDlg, IDC_WMCOMW, WM_SETTEXT, 0 , (LPARAM)testWmCommandW); + SendDlgItemMessage(hDlg, IDC_WMCOML, WM_SETTEXT, 0 , (LPARAM)testWmCommandL); + SendDlgItemMessage(hDlg, IDC_WMSETW, WM_SETTEXT, 0 , (LPARAM)testWmSettextW); + SendDlgItemMessage(hDlg, IDC_WMSETL, WM_SETTEXT, 0 , (LPARAM)testWmSettextL); } return (INT_PTR)TRUE; case WM_COMMAND: if (LOWORD(wParam) == IDOK) //only save on OK { - HWND classnameHwnd = GetDlgItem(hDlg, IDC_EDIT1); - if (classnameHwnd != NULL) - GetWindowText(classnameHwnd, targetClassname, 100); + GetDlgItemText(hDlg, IDC_EDIT1, targetClassname, 100); + GetDlgItemText(hDlg, IDC_WMCOMW, testWmCommandW, MAX_TEST_SIZE); + GetDlgItemText(hDlg, IDC_WMCOML, testWmCommandL, MAX_TEST_SIZE); + GetDlgItemText(hDlg, IDC_WMSETW, testWmSettextW, MAX_TEST_SIZE); + GetDlgItemText(hDlg, IDC_WMSETL, testWmSettextL, MAX_TEST_SIZE); // check filter options if (SendDlgItemMessage(hDlg, IDC_CHECK_CMD, BM_GETCHECK, 0, 0) == BST_CHECKED) // the hard way filterWmCommand = true; @@ -375,6 +407,7 @@ INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) filterAbove = true; else filterAbove = false; + InitMsgFiltersAndLookup(); } if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) diff --git a/native/MsgHookTest/MsgHookTest.rc b/native/MsgHookTest/MsgHookTest.rc index aa28307..9c8e9a5 100644 Binary files a/native/MsgHookTest/MsgHookTest.rc and b/native/MsgHookTest/MsgHookTest.rc differ diff --git a/native/MsgHookTest/bin/x32/MsgHook.dll b/native/MsgHookTest/bin/x32/MsgHook.dll index c618653..fc01f28 100644 Binary files a/native/MsgHookTest/bin/x32/MsgHook.dll and b/native/MsgHookTest/bin/x32/MsgHook.dll differ diff --git a/native/MsgHookTest/bin/x32/MsgHook.exp b/native/MsgHookTest/bin/x32/MsgHook.exp index 1d8c88c..a93c2a0 100644 Binary files a/native/MsgHookTest/bin/x32/MsgHook.exp and b/native/MsgHookTest/bin/x32/MsgHook.exp differ diff --git a/native/MsgHookTest/bin/x32/MsgHook.lib b/native/MsgHookTest/bin/x32/MsgHook.lib index c6192c3..80a7bde 100644 Binary files a/native/MsgHookTest/bin/x32/MsgHook.lib and b/native/MsgHookTest/bin/x32/MsgHook.lib differ diff --git a/native/MsgHookTest/bin/x32/MsgHookTest.exe b/native/MsgHookTest/bin/x32/MsgHookTest.exe index 773a387..a6aafd4 100644 Binary files a/native/MsgHookTest/bin/x32/MsgHookTest.exe and b/native/MsgHookTest/bin/x32/MsgHookTest.exe differ diff --git a/native/MsgHookTest/bin/x64/MsgHook.dll b/native/MsgHookTest/bin/x64/MsgHook.dll index b47b70c..a62d705 100644 Binary files a/native/MsgHookTest/bin/x64/MsgHook.dll and b/native/MsgHookTest/bin/x64/MsgHook.dll differ diff --git a/native/MsgHookTest/bin/x64/MsgHook.exp b/native/MsgHookTest/bin/x64/MsgHook.exp index dfc8590..02b3396 100644 Binary files a/native/MsgHookTest/bin/x64/MsgHook.exp and b/native/MsgHookTest/bin/x64/MsgHook.exp differ diff --git a/native/MsgHookTest/bin/x64/MsgHook.lib b/native/MsgHookTest/bin/x64/MsgHook.lib index f9c2879..b3e9ccc 100644 Binary files a/native/MsgHookTest/bin/x64/MsgHook.lib and b/native/MsgHookTest/bin/x64/MsgHook.lib differ diff --git a/native/MsgHookTest/bin/x64/MsgHookTest.exe b/native/MsgHookTest/bin/x64/MsgHookTest.exe index 1787834..0cad9a2 100644 Binary files a/native/MsgHookTest/bin/x64/MsgHookTest.exe and b/native/MsgHookTest/bin/x64/MsgHookTest.exe differ diff --git a/native/MsgHookTest/resource.h b/native/MsgHookTest/resource.h index 36293d5..596d9a1 100644 Binary files a/native/MsgHookTest/resource.h and b/native/MsgHookTest/resource.h differ diff --git a/src/org/synthuse/MessageHookFrame.java b/src/org/synthuse/MessageHookFrame.java index 7ce1751..887a0fb 100644 --- a/src/org/synthuse/MessageHookFrame.java +++ b/src/org/synthuse/MessageHookFrame.java @@ -26,6 +26,8 @@ public class MessageHookFrame extends JFrame { public static final int WH_GETMESSAGE = 3; public static final int WH_KEYBOARD_LL = 13; + public static final int WM_COPYDATA = 74; + private JTextArea textArea; private JButton btnSave; private JButton btnStartMsgHook; @@ -91,6 +93,8 @@ public class MessageHookFrame extends JFrame { } public void createMessageHook() { + /* + // Below set windows hook is called from inside the native DLL if (hHook != null) return; //hook already running don't add anymore System.out.println("starting global message hook"); @@ -108,13 +112,17 @@ public class MessageHookFrame extends JFrame { hHook = User32.INSTANCE.SetWindowsHookEx(WH_CALLWNDPROC, lpfn, hMod, threadId); if (hHook == null) return; + */ + MsgHook mh = new MsgHook(); + //mh.setMessageHook(hwnd, threadId); MSG msg = new MSG(); try { while (!quit) { User32.INSTANCE.PeekMessage(msg, null, 0, 0, 1); - if (msg.message == User32.WM_HOTKEY){ // && msg.wParam.intValue() == 1 + if (msg.message == WM_COPYDATA){ // && msg.wParam.intValue() == 1 + System.out.println("WM_COPYDATA"); msg = new MSG(); //must clear msg so it doesn't repeat } Thread.sleep(10); diff --git a/src/org/synthuse/MsgHook.java b/src/org/synthuse/MsgHook.java index a23b374..ed8228c 100644 --- a/src/org/synthuse/MsgHook.java +++ b/src/org/synthuse/MsgHook.java @@ -1,6 +1,84 @@ package org.synthuse; +import java.io.File; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.StringWriter; + +import javax.swing.JOptionPane; + public class MsgHook { - + + static + { + String loadFailedMsg = "Failed to load MsgHook library.\n"; + //System.out.println("SynthuseDlg.config.disableUiaBridge: " + SynthuseDlg.config.disableUiaBridge); + String archDataModel = System.getProperty("sun.arch.data.model");//32 or 64 bit + try { + loadNativeLibraryFromJar("/MsgHook" + archDataModel + ".dll"); + } catch (Exception ex) { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + ex.printStackTrace(pw); + System.out.println(sw.toString()); + JOptionPane.showMessageDialog(null, loadFailedMsg + sw.toString() , "Native Library Load Error", JOptionPane.ERROR_MESSAGE); + } + } + + public static void loadNativeLibraryFromJar(String path) { + // Obtain filename from path + String[] parts = path.split("/"); + String filename = (parts.length > 1) ? parts[parts.length - 1] : null; + // Split filename to prexif and suffix (extension) + String prefix = ""; + String suffix = null; + if (filename != null) { + parts = filename.split("\\.", 2); + prefix = parts[0]; + suffix = (parts.length > 1) ? "."+parts[parts.length - 1] : null; + } + File temp = null; + try { + // Prepare temporary file + temp = File.createTempFile(prefix, suffix); + temp.deleteOnExit(); + } catch(Exception e) { + e.printStackTrace(); + } + if (!temp.exists()) { //some reason the temp file wasn't create so abort + System.out.println("File " + temp.getAbsolutePath() + " does not exist."); + return; + } + + // Prepare buffer for data copying + byte[] buffer = new byte[1024]; + int readBytes; + // Open and check input stream + InputStream is = MsgHook.class.getResourceAsStream(path); + if (is == null) { //check if valid + System.out.println("File " + path + " was not found inside JAR."); + return; + } + // Open output stream and copy data between source file in JAR and the temporary file + OutputStream os = null; + try { + os = new FileOutputStream(temp); + while ((readBytes = is.read(buffer)) != -1) { + os.write(buffer, 0, readBytes); + } + os.close(); + is.close(); + } catch(Exception e) { + e.printStackTrace(); + } + // Finally, load the library + System.load(temp.getAbsolutePath()); + } + + public native boolean setMessageHook(long hwnd, long threadId); + public native boolean removeMessageHook(); + } diff --git a/src/org/synthuse/SynthuseDlg.java b/src/org/synthuse/SynthuseDlg.java index c673b80..94ec29a 100644 --- a/src/org/synthuse/SynthuseDlg.java +++ b/src/org/synthuse/SynthuseDlg.java @@ -215,7 +215,7 @@ public class SynthuseDlg extends JFrame { helpBtn.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { String about = ""; - about += "Synthuse Version " + VERSION_STR + " create by Edward Jakubowski ejakubowski7@gmail.com\n\n"; + about += "Synthuse Version " + VERSION_STR + " created by Edward Jakubowski ejakubowski7@gmail.com\n\n"; about += "Application information: \n"; about += " alwaysOnTop - " + config.isAlwaysOnTop() + "\n"; diff --git a/src/org/synthuse/XpathManager.java b/src/org/synthuse/XpathManager.java index d2cf170..b00ad18 100644 --- a/src/org/synthuse/XpathManager.java +++ b/src/org/synthuse/XpathManager.java @@ -235,7 +235,7 @@ public class XpathManager implements Runnable{ ++matches; } } - lblStatus.setText(results + " matches"); + lblStatus.setText(results + " match(es)"); if (cPos > 0 && matches == 0 && !alwaysFromTop) { //ask if user wants to search from top int result = JOptionPane.showConfirmDialog(target.getTopLevelAncestor(), "No more matches found. Do you want to search from the top of the document?", "Find", JOptionPane.YES_NO_OPTION); if (result == JOptionPane.YES_OPTION) {