我一直在写一个小挂钩库,该库使用MS Detours,可以在任何进程中连接到任何MS API并记录其运行情况。我在库中尝试做的一件事是从挂钩中删除所有样板,以便可以非常简单地编写每个挂钩。
我将其归结为挂钩CreateFile函数并将其第一个参数打印到调试器所需的全部操作:
Hooker hooker;
Hook(hooker, dllnames::Kernel32, apis::T_CreateFileW, CreateFileW, [](auto lpFilename, auto ...rest) -> auto
{
APILOG(L"%s", lpFilename);
return TruePtr(lpFilename, rest...);
});
The only boiler plate required for this, is the function pointer definition apis::T_CreateFileW
. However, it strikes me for many cases, I could go further even than this. I'm wondering if I could us a macro to write the above as:
APILOG(hooker, dllnames::Kernel32, CreateFileW, L"%s", lpFilename);
这意味着几乎可以编写一个printf,只要我可以使用格式字符串合理地捕获其参数,就可以记录任何API的操作。
但这有可能作为宏吗?我猜有些问题是:
- I have to expand the ... of the macro into both
auto param1, auto param2
as well asparam1, param2
. - I'd have to specify and print at least the first N parameters of the real API in my format string whether I want them or not, since only at that point can I pass
rest...
- If I want to print all the parameters, I wouldn't be able to pass
rest...
我可能已经尽可能简化了这一点,我只是想知道是否有任何办法可以实现。
I don't think this is possible without using multiple macros and duplicating the parameter names at least one time; you can pass a multiple-args "bundle" using parens, but you can't do something with each argument like adding the
auto
prefix.I'd instead consider more advanced code generation techniques using something other than the preprocessor. m4 comes to mind. Even a simple shell script could be used.