From: Alf P. Steinbach on
* Jeffrey Tan[MSFT]:
> I am writting a class which acts as the code thunk to "call/jmp" to
> another function. The definition is listed below:
>
> class x86CodeThunk
> {
> private:
> const static BYTE X86_THUNK_OPRAND_LENGTH = sizeof(DWORD);

Consider reserving all uppercase for macros.

That reduces problems with name clashes.

Also, all uppercase is perceived as shouting, hard to read.


> BYTE m_Opcode;
> BYTE m_Oprand[X86_THUNK_OPRAND_LENGTH];
>
> public:
> x86CodeThunk()
> {
> memset(m_Oprand, X86_NOP_INSTRUCTION, X86_THUNK_OPRAND_LENGTH);

Here you should assert statically that X86_NOP_INSTRUCTION is exactly one byte.

If it isn't, then you're in trouble (but as I recall it is).


> }
> ....
> };
>
> However, to honor x86 /PAE DEP, I have to create this class memory on a
> heap marked with executable memory protection attribute, like this:
>
> g_hHeap = HeapCreate(HEAP_CREATE_ENABLE_EXECUTE, 0, 0);
> assert(g_hHeap!=NULL);
> if(g_hHeap==NULL)
> {
> MyPrintf(TEXT("HeapCreate fails with error %d\n"),
> GetLastError());
> return FALSE;
> }
>
> x86CodeThunk * pCodeThunk = (x86CodeThunk *)HeapAlloc(g_hHeap,
> HEAP_ZERO_MEMORY, sizeof(x86CodeThunk));
>
> However, this will not invoke the constructor of the x86CodeThunk class.
> Is there any good solution for this problem?

Others will probably mention placement new, but although it looks simple it's
darned difficult to get right.

What you do is simply to define the allocation and deallocation functions for
your class.

Unfortunately the allocation function is not named something sensible like
"alloc", but "operator new", which experience shows confuses most newbies (they
erronously think it overrides the behavior of a new expression), and ditto, the
deallocation function is named "operator delete".

class Thunk
{
public:
Thunk() { ... };

static void* operator new( size_t size )
{
return HeapCreate( ... );
}

static void operator delete( void* p )
{
...
}
};

If you need arrays of Thunk, or perhaps just on principle, also define operator
new[] and operator delete[].

Note: you need to ensure that memory is suitably aligned for Thunk instances.
It may be that HeapAlloc guarantees that. If not, you might look in TR1 (e.g.
the Boost implementation) for alignment support.

Also, by the way: thunking is not something new, and is difficult to get right,
so it would be advisable to check whether some existing solution (e.g. from
Microsoft!) can be employed instead of inventing this from scratch again.


Cheers, & hth.,

- Alf