Benj
Benj

Reputation: 32398

Can I automatically build an argument list with a macro?

I've been writing a little hooking library, which uses MS Detours and can attach to any MS API in any process and log what it's doing. One of things I've tried to do in my library is to remove all the boiler plate from hooking so that each hook can be written very simply.

I've got it down to this being all that's required to hook the CreateFile function and print its first parameter to the debugger:

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);

This would mean that could almost write a printf that would allow me to log what any API was doing provided its parameters could be reasonably captured with a format string.

But is this possible as a macro? I guess some problems are:

  1. I have to expand the ... of the macro into both auto param1, auto param2 as well as param1, param2.
  2. 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...
  3. If I want to print all the parameters, I wouldn't be able to pass rest...

It's possible I've already simplified this as far as I can, I'm just curious to see if anything approaching it is possible.

Upvotes: 1

Views: 144

Answers (1)

cdhowie
cdhowie

Reputation: 169068

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.

Upvotes: 1

Related Questions