0

我正在使用(WH_KEYBOARD)带有 ms word (OpusApp) 的本地挂钩。好吧,据我所知,一个 32 位应用程序32bit DLL必须只能与32bit target applications. 奇怪的是该程序仅适用于 64 位应用程序!!!就是这样,只有64bits APPS!例如,it works with IE 64 but not with IE 32! 该应用程序dll是 32bit 编译的radstudio XE2,我将版本确认为 PE 标头。在 32 位操作系统中,应用程序和 dll 不起作用。

我在网上没有找到解决方案,也没有找到解决这个奇怪问题的起点。

DLL 代码:

// Exported functions

extern "C" __declspec(dllexport)bool __stdcall InstallMouseHook(unsigned long, void *);

extern "C" __declspec(dllexport)bool __stdcall RemoveMouseHook();

// Callback Procedure Declaration

LRESULT CALLBACK HookProc(int code, WPARAM wParam, LPARAM lParam);

// Global variables

HHOOK HookHandle;
HINSTANCE DllInstance;
typedef void (__stdcall *CALLIT)(int,WPARAM,LPARAM);
CALLIT callIt = NULL;

int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*)
{
  DllInstance=hinst;
  return 1;
}

bool __stdcall InstallMouseHook(unsigned long pid, void *function)
{

     callIt = ( CALLIT ) function;

     if (function == NULL) {

        ShowMessage("function is null!");

     } else if (callIt == NULL) {

        ShowMessage("callIt is null!");

     }  

     HookHandle=SetWindowsHookEx(WH_KEYBOARD ,reinterpret_cast<HOOKPROC> (HookProc),DllInstance,pid);

    if (HookHandle==NULL)return false;

    else return true;

}

bool __stdcall  RemoveMouseHook()
{
  if(UnhookWindowsHookEx(HookHandle)==0)
  {
    return false;
  }
  else return true;
}

LRESULT CALLBACK HookProc(int code, WPARAM wParam, LPARAM lParam)
{
    if (code<0) {
        return CallNextHookEx(HookHandle,code,wParam,lParam);
    }

    if (callIt != NULL) {
        callIt(code,wParam,lParam);
    } else {
        ShowMessage("HookProc - no function to execute OR 32/64 bits problem!");
    }

  //Call the next hook in the chain
  return CallNextHookEx(HookHandle,code,wParam,lParam);
}

EXE调用代码:

void __fastcall TfrmMouseHook::btnHookAppDllClick(TObject *Sender)
{
    HWND hWindow;
    unsigned long pid;

    String s = "MouseHookDLL.dll";
    DllHandle=LoadLibrary(s.w_str());
    MOUSEHOOKFCT_2 InstHook=reinterpret_cast<MOUSEHOOKFCT_2> (GetProcAddress(DllHandle,"InstallMouseHook"));

    hWindow = FindWindow(ComboBox1->Text.w_str(),NULL);

    if (!hWindow) {
        msg("hWindow fail");
        return;
    }

    pid = GetWindowThreadProcessId(hWindow ,0);
    if (!pid) {
       msg("pid fail");
       return;
    }

    if(!InstHook(pid, (void *) callIt )) {
        msg("Unable to install  hook!");
    } else {
        msg(" #### hook INSTALLED! ####");
    }


}

CALLIT callIt(code,wParam,lParam) {
    frmMouseHook->msg("hook callit: code="+IntToStr(code) +" wparam="+IntToStr(wParam)+" lparam="+IntToStr(lParam) );
}



   Call IT is a function pointer to a hooker app function.

    Any ideas will be very wellcome!
4

2 回答 2

1

32 位应用程序在物理上不可能安装 32 位挂钩 DLL 并让它在 64 位进程中执行。32 位 DLL 根本无法注入 64 位进程。时期。MSDN 在多个地方都这样说,包括在SetWindowsHookEx() 文档中:

SetWindowsHookEx 可用于将 DLL 注入另一个进程。32位DLL不能注入64位进程,64位DLL不能注入32位进程。如果应用程序需要在其他进程中使用钩子,则需要 32 位应用程序调用 SetWindowsHookEx 将 32 位 DLL 注入 32 位进程,64 位应用程序调用 SetWindowsHookEx 将 64 位DLL 转换为 64 位进程。32 位和 64 位 DLL 必须具有不同的名称。

因为钩子在应用程序的上下文中运行,所以它们必须与应用程序的“位数”相匹配。如果 32 位应用程序在 64 位 Windows 上安装全局挂钩,则 32 位挂钩将被注入每个 32 位进程(通常的安全边界适用)。在 64 位进程中,线程仍被标记为“已挂钩”。但是,由于 32 位应用程序必须运行钩子代码,系统会在钩子应用程序的上下文中执行钩子;具体来说,在调用 SetWindowsHookEx 的线程上。这意味着挂钩应用程序必须继续发送消息,否则可能会阻止 64 位进程的正常运行。

如果 64 位应用程序在 64 位 Windows 上安装全局挂钩,则 64 位挂钩将注入到每个 64 位进程中,而所有 32 位进程都使用对挂钩应用程序的回调。

您说您的应用程序和 DLL 不能在 32 位操作系统版本上运行这一事实表明您的挂钩代码一开始就有缺陷。但是您没有显示足够的代码来以一种或另一种方式诊断。

于 2012-09-20T22:51:57.653 回答
0

发生什么了?除了MSDN或其他人说的,XE6有一些bug,在较新版本的IDE中编译DLL会使这种行为消失,实际上,新的DLL崩溃并没有钩子。

正如 Remy 所指出的,通过测试,我向 DLL 传递了一个函数指针,这是一件错误的事情,但是当添加了 Embarcadero 所做的错误事情时,它就可以正常工作了。

到现在为止,我知道人们会生气,我将这两种方法(错误和正确的钩子)都放在同一个 DLL 和我的应用程序中,然后......变得疯狂......可以只使用 32 位和 64 位应用程序一个DLL。

不相信?安装 XE6 并尝试!

并且适用于 Windows 10 以及 Windows 7。

于 2020-12-18T19:16:35.793 回答