Windows API函数可以覆盖并在之后调用吗?

时间:2011-10-14 16:17:01

标签: c++ winapi

我想修改Windows API中可用的本机函数,例如CreateWindowExShowWindow,以便在使用包含的函数编译应用程序时,它将调用我的函数,执行那里的任务,然后调用原始的本机函数。

换句话说,我想以某种方式代理函数,同时仍使用相同的名称(因此,如果编写的程序是使用本机API编译的,只需添加这些函数就可以修改这些本机函数的方式处理)

HWND WINAPI CreateWindowEx(
  __in      DWORD dwExStyle,
  __in_opt  LPCTSTR lpClassName,
  __in_opt  LPCTSTR lpWindowName,
  __in      DWORD dwStyle,
  __in      int x,
  __in      int y,
  __in      int nWidth,
  __in      int nHeight,
  __in_opt  HWND hWndParent,
  __in_opt  HMENU hMenu,
  __in_opt  HINSTANCE hInstance,
  __in_opt  LPVOID lpParam
) {

    //my custom code here....

    // done with my custom code... so now I want to run the native function
    return CreateWindowEx(dwExStyle, lpClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
}

这(由于显而易见的原因)给出了堆栈溢出,因为它一直在反复调用自身。我想要它做的是,当它被调用时,它运行我创建的自定义函数,然后运行Windows API中可用的本机函数。

我对c ++很新,但是在很多其他语言中,我可以用另一个名称存储对本机函数的引用,然后我可以在我的自定义函数中调用它。 c ++中有没有类似的东西?

3 个答案:

答案 0 :(得分:3)

正如我在评论中所写,许多挂钩库的父级可能是微软Detours

现在它不再是免费的,有各种各样的选择。这里有一些比较(链接删除。我不确定它是安全的。尝试谷歌搜索“微软Detours是一个在特定拦截中使用的库”并选择一个源或更简单的Detours Alternatives。

嗯,目前唯一的免费替代方案是http://easyhook.codeplex.com/http://www.codeproject.com/KB/system/mini_hook_engine.aspx

如果您有兴趣,可以提出一个问题:Detours alternative for Registry interception

答案 1 :(得分:1)

您的问题的一个解释是您有一个项目,包含源代码,并且您想要更改该项目,以便它使用您自己的某些winapi函数版本。

这是一个可以为每个导入的API函数实现的解决方案。此处的示例适用于ShowWindow

#define ShowWindow Deleted_Winapi_ShowWindow // prevent windows.h from defining ShowWindow
#include <windows.h>
#undef ShowWindow

namespace HiddenWinapi
{
    extern "C"
    {
        // Do what windows.h does, but hide it inside a namespace.
        WINUSERAPI BOOL WINAPI ShowWindow( __in HWND hWnd, __in int nCmdShow);
    }
}

// make your own function to be called instead of the API, and delegate to the actual API in the namespace.
BOOL WINAPI ShowWindow(HWND hwnd, int nCmdShow)
{
    // ... do stuff ...
    // call the original API
    return HiddenWinapi::ShowWindow(hwnd, nCmdShow);
}

要将此解决方案用于CreateWindowEx,您需要存根实际导入的函数名称(例如CreateWindowExW),因为CreateWindowEx只是一个扩展为CreateWindowExW的宏或CreateWindowExA

这是一个用您自己的宏取代宏的解决方案,但我认为在所有情况下最好使用上述解决方案。

#include <windows.h>

#undef CreateWindowEx

// Note that this is a unicode-only version. If your app mixes A and W versions, see 
// the solution below for non-macro APIs.
HWND WINAPI CreateWindowEx(DWORD dwExStyle, LPCWSTR lpClassName, LPCWSTR lpWindowName, DWORD dwStyle, int X, int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam)
{
    // ... do stuff ...
    // call the REAL function.
    return CreateWindowExW(dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
}

答案 2 :(得分:0)

如果您想自己这样做,最简单的方法是修改PE(可移植可执行文件)标头中的导入地址表。不过,这不是微不足道的。

但是,我相信有一个标准库可以满足你想要的Detours。我自己从来没有使用过那个,因为当我开始这样做的时候它并不存在,所以我有一个 - 不用于公共消费 - 库在我需要的时候通过导入表来实现它。