// Basically reworking what this guy already did:
// http://www.codeproject.com/KB/cpp/thunk32.aspx

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <cstdio>

using std::printf;

struct I {
    virtual void print() = 0;
};

struct C : I {
    C(int x)
        : x(x)
    { }
    
    void print() {
        printf("My x is %i\n", x);
    }
    
    int x;
};

typedef void (__stdcall *Function0)();

void nothing() {
    __asm {
        mov ecx, 0x11223344     // B9 44 33 22 11
        mov eax, 0x44332211     // B8 11 22 33 44
        jmp eax                 // FF E0
    }
}

template <typename D, typename S>
D really_reinterpret_cast(S s) {
    char __static_assert_that_types_have_same_size[sizeof(S) == sizeof(D)];

    union {
        S s;
        D d;
    } u;
    
    u.s = s;
    return u.d;
}

void main() {
    I* instance = new C(994);

    char code[] = {
        0xB9, 0, 0, 0, 0,   // mov ecx, 0
        0xB8, 0, 0, 0, 0,   // mov eax, 0
        0xFF, 0xE0          // jmp eax
    };

    // YEEHAW
    *((I**)(code + 1)) = instance;
    *((void**)(code + 6)) = really_reinterpret_cast<void*>(&I::print);

    void* buffer = VirtualAlloc(0, sizeof(code), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    memcpy(buffer, &code, sizeof(code));
    FlushInstructionCache(GetCurrentProcess(), buffer, sizeof(code));

    Function0 f0 = reinterpret_cast<Function0>(buffer);

    for (int q = 0; q < 10; q++) {
        f0();
    }

    VirtualFree(buffer, 0, MEM_RELEASE);
}