Вы передаете 0 (иначе NULL) в GetModuleHandle()
, поэтому вы извлекаете HMODULE
файла EXE, в процесс которого ваша DLL загружена:
Параметры
lpModuleName
Имя загруженного модуля (файл .dll или .exe) ...
Если этот параметр имеет значение NULL, GetModuleHandle возвращает дескриптор для файл, используемый для создания вызывающего процесса (файл .exe).
Этот HMODULE
нельзя использовать для установки обратного обратного вызова SetWindowsHookEx()
, который находится в DLL. Вам нужно использовать собственную DLL HMODULE
, ie ту, которая предоставляется в качестве входного параметра для DllMain()
, например:
HHOOK _hook = NULL;
LRESULT __stdcall HookCallback(int code,
WPARAM wParam,
LPARAM lParam)
{
...
return CallNextHookEx(_hook, code, wParam, lParam);
}
void SetHook(HMODULE hModule) // <-- ADD THIS PARAM
{
if (!_hook)
{
_hook = SetWindowsHookEx(WH_CALLWNDPROCRET, HookCallback, hModule, 0); // <-- USE IT HERE
if (!_hook)
{
OutputDebugString(TEXT("Failed to Install hook"));
}
}
OutputDebugString(TEXT("Exiting SETHOOK METHOD"));
}
void ReleaseHook()
{
if (_hook)
{
UnhookWindowsHookEx(_hook);
_hook = NULL;
}
}
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
OutputDebugString(TEXT("Entered DLL"));
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hModule);
SetHook(hModule); // <-- PASS IT HERE
break;
case DLL_PROCESS_DETACH:
ReleaseHook();
break;
}
return TRUE;
}
При этом вы пытаетесь установить глобально (hMod != NULL
и dwThreadId == 0
), так что вам нужно только один вызов SetWindowsHookEx()
, не имеет смысла вызывать его в каждый процесс, в который загружена ваша DLL. Вы должны создать свой собственный EXE-файл, который загружает вашу DLL в память и вызывает для нее SetWindowsHookEx()
1 раз, например:
HMODULE _hmod = NULL;
HHOOK _hook = NULL;
// be sure to export your hook functions from the DLL..
LRESULT __stdcall HookCallback(int code,
WPARAM wParam,
LPARAM lParam)
{
...
return CallNextHookEx(_hook, code, wParam, lParam);
}
void SetHook()
{
if (!_hook)
{
_hook = SetWindowsHookEx(WH_CALLWNDPROCRET, HookCallback, _hmod, 0);
if (!_hook)
{
OutputDebugString(TEXT("Failed to Install hook"));
}
}
OutputDebugString(TEXT("Exiting SETHOOK METHOD"));
}
void ReleaseHook()
{
if (_hook)
{
UnhookWindowsHookEx(_hook);
_hook = NULL;
}
}
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
_hmod = hModule;
OutputDebugString(TEXT("Entered DLL"));
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hModule);
break;
}
return TRUE;
}
typedef void (*LPFN_SH)();
typedef void (*LPFN_RH)();
HMODULE hMod = LoadLibrary("my.dll");
LPFN_SH SetHook = (LPFN_SH) GetProcAddress(hMod, "SetHook");
LPFN_RH ReleaseHook = (LPFN_RH) GetProcAddress(hMod, "ReleaseHook");
...
SetHook();
...
ReleaseHook();
FreeLibrary(hMod);
Ваша DLL будет автоматически внедрена в каждый запущенный процесс, соответствующий вашему Побитность DLL (это означает, что вам нужны отдельные библиотеки DLL для перехвата 32-битных и 64-битных процессов) на время существования вашего EXE-процесса. Нет необходимости использовать ключ реестра AppInit_DLLS
.
В противном случае, если вы действительно хотите использовать AppInit_DLLS
для внедрения вашей DLL в каждый процесс сопоставления битов, то было бы лучше иметь вызов DLL SetWindowsHookEx()
для каждого потока (hMod == NULL
и dwThreadId != 0
) вместо глобального, например:
__declspec(thread) HHOOK _hook = NULL;
LRESULT __stdcall HookCallback(int code,
WPARAM wParam,
LPARAM lParam)
{
...
return CallNextHookEx(_hook, code, wParam, lParam);
}
void SetHook()
{
if (!_hook)
{
DWORD dwThreadId = GetCurrentThreadId();
_hook = SetWindowsHookEx(WH_CALLWNDPROCRET, HookCallback, NULL, dwThreadId);
if (!_hook)
{
OutputDebugString(TEXT("Failed to Install hook"));
}
}
OutputDebugString(TEXT("Exiting SETHOOK METHOD"));
}
void ReleaseHook()
{
if (_hook)
{
UnhookWindowsHookEx(_hook);
_hook = NULL;
}
}
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
OutputDebugString(TEXT("Entered DLL"));
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
SetHook();
break;
case DLL_PROCESS_DETACH:
case DLL_THREAD_DETACH:
ReleaseHook();
break;
}
return TRUE;
}
Тогда не будет необходимости использовать отдельный загрузчик EXE.