A project I was working on a while back required me to hook several functions in an application written in Delphi. I was writing my code in C, so I needed to figure out some way to inter-operate with the main application's code. I ended up deciding to write a normal __cdecl function that translated its parameters to Borland Register (aka Delphi "fastcall", different from Microsoft's fastcall, read more
here).
This is what I came up with. The helper function takes a pointer to a delphi function, the number of arguments, and then the arguments you want to pass to the delphi function. The result of the invoked function is returned as a void *, but can be easily cast to whatever the return type actually is.
Code:
void *Delphi_InvokeMethod(void *pfn, size_t param_count, ...)
{
va_list ap;
void *tmp;
void *registers[3];
void *result;
va_start(ap, param_count);
for ( size_t i = 0; i < param_count; i++ ) {
tmp = va_arg(ap, void *);
if ( i < _countof(registers) )
registers[i] = tmp;
else
__asm push tmp
}
va_end(ap);
__asm {
mov eax, registers[0]
mov edx, registers[type registers * 1]
mov ecx, registers[type registers * 2]
call pfn
mov result, eax
}
return result;
}
Keep in mind this is only for x86. As far as I know x64 delphi applications use the universal Microsoft x64 calling convention (someone feel free to correct me here, I haven't had the opportunity to reverse a x64 delphi application yet, so I could be wrong).
It might not be perfect, but it worked for what I needed it for. Feel free to suggest ways to improve it or any other kinds of criticism.
I hope somebody finds this useful, cheers!