There are some (rare) functions in the Windows API that return structures, one such function is (note: 32bit only):
function RtlConvertLongToLargeInteger
(
{ _in_ } In32bitSigned : longint
)
: TLARGE_INTEGER; stdcall; external ntdll;
In C, when this function is called, the 64 bit TLARGE_INTEGER (LARGE_INTEGER in C) is returned in the register pair eax:edx.
The problem is, FPC expects the function result to be returned on the stack instead of that register pair.
My question is: is there a way to tell FPC that the return value is in that register pair instead of on the stack ?
In this particular case, a solution is to declare the function's result as "int64" instead of TLARGE_INTEGER but, that's not accurate (it takes typecasting the int64 to TLARGE_INTEGER to access the low and high parts, which shouldn't be necessary.)
Thank you for your help.
For anyone interested, here is a little piece of code to "play with":
{$APPTYPE CONSOLE}
{$TYPEDADDRESS ON}
{$LONGSTRINGS OFF}
{$ifdef WIN64}
{$FATAL This function is not available in 32 bit. Forced compilation termination.}
{$endif}
{ --------------------------------------------------------------------------- }
program _AccessViolation;
{ NOTE: can cause an access violation due to stack corruption }
uses
Windows
;
type
TLARGE_INTEGER = LARGE_INTEGER;
const
ntdll = 'ntdll';
{$ifdef WIN32}
{ as defined in C }
function RtlConvertLongToLargeInteger
(
{ _in_ } In32bitSigned : longint
)
: TLARGE_INTEGER; stdcall; external ntdll;
{ as CAN BE defined }
function RtlConvertLongToLargeIntegerB
(
{ _in_ } In32bitSigned : longint
)
: int64; stdcall; external ntdll name 'RtlConvertLongToLargeInteger';
{$endif}
const
LONG_VALUE = high(longint);
var
LargeInteger : TLARGE_INTEGER;
begin
if IsDebuggerPresent() then asm int3 end;
writeln;
writeln;
writeln(' Long to convert : ', LONG_VALUE);
writeln;
writeln(' converted with RtlConvertLongToLargeIntegerB: ',
RtlConvertLongToLargeIntegerB(LONG_VALUE));
writeln;
writeln(' converted with RtlConvertLongToLargeInteger : ');
LargeInteger := RtlConvertLongToLargeInteger(LONG_VALUE);
with LargeInteger do
begin
writeln(' Low part: ', LowPart);
writeln(' High part: ', HighPart);
end;
writeln;
writeln;
writeln('press ENTER/RETURN to end this program');
readln;
end.