Я прочитал несколько топиков (в том числе тот, что есть на rsdn) на тему, но не смог найти решения своей проблемы.
Собранная мной dll в MS VS2005 не грузится в исполняемое приложение (обращение по нулевому адресу).
Если кто-нибудь сталкивался с написанием подобных хуков, подскажите, пожалуйста, что я делаю не так.
Здравствуйте, Аноним, Вы писали:
А>Добрейшего времени суток, друзья!
А>Я прочитал несколько топиков (в том числе тот, что есть на rsdn) на тему, но не смог найти решения своей проблемы. А>Собранная мной dll в MS VS2005 не грузится в исполняемое приложение (обращение по нулевому адресу). А>Если кто-нибудь сталкивался с написанием подобных хуков, подскажите, пожалуйста, что я делаю не так.
1. ЕМНИП, Си оставляет имя таким, какое оно есть, без подчёркиваний.
2. При проверке, вы сразу вызываете функцию. Надо просто
if( ! InstHook )
Аналогично для второй функции.
Из-за (1) у вас возвращается нуль, а из-за (2) — обращение по этому нулю.
Re[2]: Global Mouse Hook
От:
Аноним
Дата:
18.06.08 18:52
Оценка:
Здравствуйте, VoidEx, Вы писали: VE>Из-за (1) у вас возвращается нуль, а из-за (2) — обращение по этому нулю.
Большое спасибо за помощь! Dll загружается, но хук все же не работает ...
Может быть у кого-нибудь есть что подсказать.
Вот мой конечный вариант кода:
--- код dll [сборка в MS VS2005] ---
// mousehook.cpp : Defines the entry point for the DLL application.#include"stdafx.h"#pragma data_seg(".hdata") // секция в памяти общая для всех процессов
HWND hWndServer = NULL; // эта переменная может изменяться любым процессом, поэтому здесь не д.б. ничего лишнего#pragma data_seg() // конец секции#pragma comment(linker, "/section:.hdata,rws") // даем права этой секции#ifdef __cplusplus
#define EXPORT extern"C"__declspec(dllexport)
#else
#define EXPORT __declspec(dllexport)
#endif// объявление функции обратного вызова
LRESULT CALLBACK MouseProc(int code, WPARAM wParam, LPARAM lParam);
// глобальные переменные
HHOOK HookHandle;
HINSTANCE DllInstance;
#ifdef _MANAGED
#pragma managed(push, off)
#endif//----------------------------------------------------------------------
EXPORT BOOL InstallMouseHook(HWND AWnd) {
if(hWndServer != NULL)
return false;
HookHandle = SetWindowsHookEx(WH_GETMESSAGE,
reinterpret_cast<HOOKPROC>(MouseProc), DllInstance, NULL);
HookHandle = SetWindowsHookEx(WH_MOUSE,
reinterpret_cast<HOOKPROC>(MouseProc), DllInstance, NULL);
if(HookHandle == NULL)
return false;
return true;
}
//----------------------------------------------------------------------
EXPORT BOOL RemoveMouseHook(HWND AWnd //окно, чей хук должен быть снят
)
{
if(AWnd != hWndServer)
return false;
BOOL unhooked = UnhookWindowsHookEx(HookHandle);
if(unhooked)
hWndServer = NULL;
return unhooked;
}
//----------------------------------------------------------------------
LRESULT CALLBACK MouseProc(int code, WPARAM wParam, LPARAM lParam) {
if(code < 0) {
CallNextHookEx(HookHandle, code, wParam, lParam);
return 0;
}
LPMSG msg = (LPMSG)lParam;
if( (hWndServer = FindWindow(L"TForm1", L"Form1")) == NULL )
return 0;
else {
if(msg->message == WM_LBUTTONDOWN || msg->message == WM_LBUTTONUP ||
msg->message == WM_RBUTTONDOWN || msg->message == WM_RBUTTONUP )
PostMessage(hWndServer, msg->message, 0, 0);
}
// вызываем следующий хук в цепи return CallNextHookEx(HookHandle, code, wParam, lParam);
}
//----------------------------------------------------------------------
BOOL APIENTRY DllMain( HMODULE hModule, // дескриптор экземпляра DLL
DWORD reason, // причина вызова
LPVOID lpReserved // зарезервировано
)
{
// вызывается каждый раз когда новый процесс грузит DLL в свою памятьif( reason == DLL_PROCESS_ATTACH ) {
if( ! hWndServer ) {
// cохраняем дескриптор экземпляра, он понадобится позднее для установки хука
DllInstance = hModule;
return true;
}
} else if( reason == DLL_PROCESS_DETACH ) {
if( hWndServer != NULL )
RemoveMouseHook(hWndServer);// ЕСЛИ сервер не снял хук, снимем егоreturn true;
}
return TRUE;
}
//----------------------------------------------------------------------#ifdef _MANAGED
#pragma managed(pop)
#endif
--- исполняемое приложение — сервер [сборка в C++Builder 6.0] ---
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, VoidEx, Вы писали: VE>>Из-за (1) у вас возвращается нуль, а из-за (2) — обращение по этому нулю. А>Большое спасибо за помощь! Dll загружается, но хук все же не работает ... А>Может быть у кого-нибудь есть что подсказать.
А>Вот мой конечный вариант кода:
А>--- код dll [сборка в MS VS2005] ---
А>
А>// mousehook.cpp : Defines the entry point for the DLL application.
А>#include"stdafx.h"
А>#pragma data_seg(".hdata") // секция в памяти общая для всех процессов
А>HWND hWndServer = NULL; // эта переменная может изменяться любым процессом, поэтому здесь не д.б. ничего лишнего
А>#pragma data_seg() // конец секции
А>#pragma comment(linker, "/section:.hdata,rws") // даем права этой секции
А>#ifdef __cplusplus
А>#define EXPORT extern"C"__declspec(dllexport)
А>#else
А>#define EXPORT __declspec(dllexport)
А>#endif
А>// объявление функции обратного вызова
А>LRESULT CALLBACK MouseProc(int code, WPARAM wParam, LPARAM lParam);
А>// глобальные переменные
А>HHOOK HookHandle;
А>HINSTANCE DllInstance;
А>#ifdef _MANAGED
А>#pragma managed(push, off)
А>#endif
А>//----------------------------------------------------------------------
А>EXPORT BOOL InstallMouseHook(HWND AWnd) {
А> if(hWndServer != NULL)
А> return false;
А> HookHandle = SetWindowsHookEx(WH_GETMESSAGE,
А> reinterpret_cast<HOOKPROC>(MouseProc), DllInstance, NULL);
А> HookHandle = SetWindowsHookEx(WH_MOUSE,
А> reinterpret_cast<HOOKPROC>(MouseProc), DllInstance, NULL);
А> if(HookHandle == NULL)
А> return false;
А> return true;
А> }
А>//----------------------------------------------------------------------
А>EXPORT BOOL RemoveMouseHook(HWND AWnd //окно, чей хук должен быть снят
А> )
А>{
А> if(AWnd != hWndServer)
А> return false;
А> BOOL unhooked = UnhookWindowsHookEx(HookHandle);
А> if(unhooked)
А> hWndServer = NULL;
А> return unhooked;
А> }
А>//----------------------------------------------------------------------
А>LRESULT CALLBACK MouseProc(int code, WPARAM wParam, LPARAM lParam) {
А> if(code < 0) {
А> CallNextHookEx(HookHandle, code, wParam, lParam);
А> return 0;
А> }
А> LPMSG msg = (LPMSG)lParam;
А> if( (hWndServer = FindWindow(L"TForm1", L"Form1")) == NULL )
А> return 0;
А> else {
А> if(msg->message == WM_LBUTTONDOWN || msg->message == WM_LBUTTONUP ||
msg->>message == WM_RBUTTONDOWN || msg->message == WM_RBUTTONUP )
А> PostMessage(hWndServer, msg->message, 0, 0);
А> }
А> // вызываем следующий хук в цепи
А> return CallNextHookEx(HookHandle, code, wParam, lParam);
А> }
А>//----------------------------------------------------------------------
А>BOOL APIENTRY DllMain( HMODULE hModule, // дескриптор экземпляра DLL
А> DWORD reason, // причина вызова
А> LPVOID lpReserved // зарезервировано
А> )
А>{
А> // вызывается каждый раз когда новый процесс грузит DLL в свою память
А> if( reason == DLL_PROCESS_ATTACH ) {
А> if( ! hWndServer ) {
А> // cохраняем дескриптор экземпляра, он понадобится позднее для установки хука
А> DllInstance = hModule;
А> return true;
А> }
А> } else if( reason == DLL_PROCESS_DETACH ) {
А> if( hWndServer != NULL )
А> RemoveMouseHook(hWndServer);// ЕСЛИ сервер не снял хук, снимем его
А> return true;
А> }
А> return TRUE;
А>}
А>//----------------------------------------------------------------------
А>#ifdef _MANAGED
А>#pragma managed(pop)
А>#endif
А>
1) 2 хука — 2 HookHandle.
2) HookHandle — в секцию для расшаренных данных. Не забудьте, что расшаренные данные должны быть проинициализированы в обязательном порядке.
3) Защитите доступ к расшаренным переменным
4) Этот код убьет ваш хук когда закроется первое захученое приложение.
if( reason == DLL_PROCESS_DETACH ) {
if( hWndServer != NULL )
RemoveMouseHook(hWndServer);// ЕСЛИ сервер не снял хук, снимем его
return true;
Перевожу программу с ассемблера (masm 6.14) на c++ (gcc-3.4.5 — Code::Blocks + MinGW).
Возникла проблема: hook, установленный в dll по WH_MOUSE, в варианте c++ работает только когда указатель мыши находится в пределах окна программы, устанавливающей его. Если ассемблерную dll подсунуть в основную c++-программу, то всё в порядке. Если c++-dll подсунуть в основную asm-программу — проблема.
Т.е., насколько я понимаю, проблема связана с тем как компилируется dll в gcc.
1. Чтобы dll нормально работала, приходится в с++-версии экспортировать функцию DllMain, чего в ассемблерном варианте нет (там вообще функция DllEntry).
2. Если сравнить информацию о dll, то, в частности, отличаются точки входа и Subsystem для ассемблерной — 0002h (Win32 GUI), а для сишной — 0003h (Win32 console)
Если использовать WH_MOUSE_LL, то работает как надо, но с задержками.
Т.е. вопрос, как я понимаю, сводится к тому — как правильно скомпилировать dll с ловушкой в gcc? Подскажите, пожалуйста, как это сделать.
Здравствуйте, Jarz, Вы писали:
J>Возникла проблема: hook, установленный в dll по WH_MOUSE, в варианте c++ работает только когда указатель мыши находится в пределах окна программы, устанавливающей его.
Как передается информация из хуковой процедуры в приложение?
--
С уважением, LVT
Re[6]: Global Mouse Hook
От:
Аноним
Дата:
22.12.08 09:13
Оценка:
Здравствуйте, Leonid Troyanovsky, Вы писали:
LT>Здравствуйте, Jarz, Вы писали:
J>>Возникла проблема: hook, установленный в dll по WH_MOUSE, в варианте c++ работает только когда указатель мыши находится в пределах окна программы, устанавливающей его.
LT>Как передается информация из хуковой процедуры в приложение?
PostMessage(hWnd, WM_MOUSEHOOK, somevalue, 0);
hWnd задаётся при установке хука. WM_MOUSEHOOK я сам определил.
Поставил вывод значения hWnd. Оказалось, что оно равно 0 в с++ варианте. В asm-варианте оно равно значению хэндла окна основной программы. Насколько я понял, дело в общей памяти DLL, точнее — в её отсутствии в данном случае
Компилирую я со стандартными парметрами, установленными средой Code::Blocks. Был бы признателен за подсказку — куда, как и что прописать, чтобы получилось как задумано.
Здравствуйте, Аноним, Вы писали:
А>Компилирую я со стандартными парметрами, установленными средой Code::Blocks. Был бы признателен за подсказку -куда, как и что прописать, чтобы получилось как задумано.
Ищи define для объявления shared section.
Помочь не смогу, бо не силен в C.
Или, CreateFileMapping & etc. для передачи нужного.
Ну, или FindWindow (одноразово) из хуковой процедуры.
А>Поставил вывод значения hWnd. Оказалось, что оно равно 0 в с++ варианте. В asm-варианте оно равно значению хэндла окна основной программы. Насколько я понял, дело в общей памяти DLL, точнее — в её отсутствии в данном случае
Собрал проект в VC++ 2008 Express. Опять лажа. Если ранее дело было в неверном дескрипторе окна, то теперь сама функция MouseProc вызывается только когда указатель мыши находится в пределах родительского окна. Т.е. получается локальная ловушка. Фигня какая-то.
Здравствуйте, Jarz, Вы писали:
J>Собрал проект в VC++ 2008 Express. Опять лажа. Если ранее дело было в неверном дескрипторе окна, то теперь сама функция MouseProc вызывается только когда указатель мыши находится в пределах родительского окна. Т.е. получается локальная ловушка. Фигня какая-то.
Что реально передается в 3 параметре SetWindowsHookEx?
А в 4?
LT>Что реально передается в 3 параметре SetWindowsHookEx?
LT>А в 4?
в 3-м параметре — hInst (из DllMain)
в 4-м — 0
Если подсунуть приложению, собранному в Code::Blocks (MinGW) библиотеку, полученную в VC, то всё работает нормально. При этом hInst = 0x1140000.
Если же запускать приложение, собранное в VC, то hInst всегда получается равным 0x10000000.
Попробовал разные способы. Если запускать VC-приложение, то в DLL hInst всегда == 0x10000000, а GetModuleHandle() == 0x400000
Если же запускать MinGW-приложение, то hInst != 0x10000000, а GetModuleHandle() == 0x1000000
Здравствуйте, Jarz, Вы писали:
J>Попробовал разные способы. Если запускать VC-приложение, то в DLL hInst всегда == 0x10000000, а GetModuleHandle() == 0x400000 J>Если же запускать MinGW-приложение, то hInst != 0x10000000, а GetModuleHandle() == 0x1000000
Из этого следует, что либо hInst неверен, либо GetModuleHandle применен не к тому модулю.
Кста, а есть уверенность, что обои компилируют и собирают именно PE, dll & win32?
И загружает ли целевое приложение user32.dll?
Здравствуйте, Аноним и MaksimSL. В коде обнаружены следующие ошибки.
* В MouseProc идентификатор сообщения передаётся не через через lParam, а через wParam. Т. е. в следующем куске кода
if(msg->message == WM_LBUTTONDOWN || msg->message == WM_LBUTTONUP || msg->>message == WM_RBUTTONDOWN || msg->message == WM_RBUTTONUP )
PostMessage(hWndServer, msg->message, 0, 0);
следует заменить msg->message
на
wParam.
* В исполняемом приложении функции InstHook() и RemHook() загружаются, но не вызываются.