Code: Select all
void DoHook()
{
InitThunk((TMFP) &CInitHook::OurInitializePrintMonitor2, this, 2);
FARPROC thunk = GetThunk();
if (thunk == NULL)
LogItem(LOG_INFO, NULL, L"Thunk Failed");
else
{
LogItem(LOG_INFO, NULL, L"Thunk Succeeded");
BOOL rc = HookAPI(dll.c_str(), "InitializePrintMonitor2", thunk, (PVOID*) &OrigInitializePrintMonitor2);
if (rc)
LogItem(LOG_INFO, NULL, L"Hook Succeeded");
else
LogItem(LOG_INFO, NULL, L"Hook Failed");
};
Same code works fine when not using the thunk, just static functions but I need my "this" pointer
Any idea why HookAPI fails? nothing in the docs.
Code for the thunk below:
Code: Select all
template <class T>
class CAuxThunk
{
// stub "code" is no longer the class itself
BYTE m_thunk[1024]; // fixed; don't know size required apriori!
// for 3 arguments the size required is under 200 bytes
public:
typedef void (T::*TMFP)();
// need an extra parameter, # of real arguments in the callback
void InitThunk(TMFP method, T* pThis, int nArgs = 3)
{
ATLASSERT(static_cast< CAuxThunk<T>* >(this) == pThis); // not really required as argument?
union { void* (*func)(); TMFP method; } addr;
addr.method = (TMFP)method;
ATLASSERT(sizeof(TMFP)==sizeof( void* (*)() )); // shouldn't be virtual
#if defined(_DEBUG) && defined(_WIN64)
// @@@ 64 bit compiler creates TMFP pointers that are 16 bytes long (!) even without virtuals
ATLASSERT(sizeof(TMFP)==sizeof(ULONGLONG)*2);
union {
struct {ULONGLONG a, b;};
TMFP method;
} ck_;
ck_.method = method;
ATLASSERT(0==ck_.b); // no useful information in high pointer?
#endif
// pass "this" as the first fixed argument
// that will put it on the stack instead of ECX, as should be in x64
void *fixed[] = { pThis };
size_t thunk_size = vbind(addr.func, nArgs+1, m_thunk, 0, fixed, 1);
ATLASSERT(thunk_size < sizeof(m_thunk));
unsigned long old;
VirtualProtect(m_thunk, thunk_size, PAGE_EXECUTE_READWRITE, &old);
FlushInstructionCache(GetCurrentProcess(), m_thunk, thunk_size);
}
FARPROC GetThunk() const { return (FARPROC)(void*)m_thunk; }
};