DllMain DLL_PROCESS_DETACH和GetMessage函数重入

时间:2013-11-28 16:42:01

标签: winapi setwindowshookex reentrancy getmessage dllmain

我编写了一个全局钩子,它使用 SetWindowsHookEx 挂钩WH_GETMESSAGE,WH_CALLWNDPROC和WH_CALLWNDPROCRET。
hook dll在hooked进程中创建一个新线程,除其他外,它检查进程的音频状态并调用 IAudioSessionManager2 :: GetSessionEnumerator()

现在有趣的部分,我在钩子主机上调用 UnhookWindowsHookEx()并且在我的dll工作线程运行 IAudioSessionManager2 :: GetSessionEnumerator()。该调用位于同一线程的调用堆栈中,其中调用了 DllMain与DLL_PROCESS_DETACH 。 我假设原因是, GetSessionEnumerator()在某处调用 GetMessage()函数,后者是可重入的。不幸的是我不记得了,但我想我在调用堆栈中看到了它。

但是我想知道有多个重要的事情以及尚不清楚的事情。所以这里是我的相关问题:

  1. DllMain可以随时调用DLL_PROCESS_DETACH,即使是在一个运行当前正在卸载的dll函数的线程中吗?
  2. 当DllMain DLL_PROCESS_DETACH退出时,堆栈中的函数会发生什么?调用堆栈函数中的代码最终会执行吗?
  3. 如果这些功能没有退出怎么办?什么时候卸载dll?
  4. 在WH_GETMESSAGE,WH_CALLWNDPROC和WH_CALLWNDPROCRET挂钩的回调期间,是否可以类似地调用DllMain DLL_PROCESS_DETACH?我知道并且已经通过实验证实,有时虽然不常见,但这些函数是可重入的,因此在前一次调用仍在同一堆栈中运行时可以注入对这些函数的调用,但我不知道是否也调用DllMain可以以类似的方式注入。
  5. 当精确地在一个线程中调用DllMain时 - 是否需要调用某些特定的Windows API函数,这些函数又可能导致DllMain DLL_PROCESS_DETACH调用,还是可能在任何指令处发生?
  6. 如果DllMain DLL_PROCESS_DETACH调用可以随时“注入”并且函数向上调用堆栈不再执行,那么我怎么知道调用堆栈中的函数到底被中断了?所以我可以在DllMain里面释放一些由函数分配的句柄或资源。
  7. 有没有办法暂时阻止/推迟对DllMain DLL_PROCESS_DETACH的调用?如果在同一堆栈中发生呼叫/中断,则锁显然无效。
  8. 不幸的是,我可能无法通过实验解决这些问题,因为我已经在多台计算机上运行了几个月的挂钩(也是取消挂钩)代码,之后在脱钩期间发生了DllMain。虽然由于某种原因,它同时出现了四个不同的程序......


    也请,有足够声誉的人喜欢合并标签“reentrant”和“reentrancy”吗?

1 个答案:

答案 0 :(得分:0)

感谢 Hans 我现在知道点(4)DllMain DLL_PROCESS_DETACH不会与钩子程序重入。

关于钩子创建的线程,我的日志文件当前指示如果将DllMain DLL_PROCESS_DETACH注入到该线程的堆栈中,那么该线程确实将在DllMain退出后终止并且不会运行完成。这应该回答第(2)和(3)点。问题本身隐含地回答了要点(1)。

但是为了解决钩子创建的那个线程的问题,我假设可以通过调用来阻止DllMain DLL_PROCESS_DETACH

GetModuleHandleEx
(
    GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
    (LPCTSTR)DllMain,
    &hModule_thread
)

并在线程终止调用之前

FreeLibraryAndExitThread(hModule_thread, 0)

因此,使用 GetModuleHandleEx 应该回答点(7),这反过来使所有其他点无关紧要。当然,我必须使用一些 IPC 来触发挂钩进程中的线程终止。

剩下的有趣问题是第(5)点,但这只是出于好奇:
“当精确地在一个线程中调用DllMain DLL_PROCESS_DETACH时 - 是否需要调用某些特定的Windows API函数,这些函数又可能导致DllMain DLL_PROCESS_DETACH调用,还是可能在任何指令处发生?”< / p>