[fpc-pascal] Syserrormessage, parameter data type
Jürgen Hestermann
juergen.hestermann at gmx.de
Mon Oct 6 17:54:46 CEST 2014
Am 2014-10-06 um 07:55 schrieb Sven Barth:
> On 06.10.2014 07:20, Jürgen Hestermann wrote:
>>
>> Am 2014-10-05 um 20:21 schrieb Sven Barth:
>>> Please note that GetLastError is Windows-specific. The cross platform
>>> function in SysUtils is called GetLastOSError which does return Integer.
>> And why does a function SysErrorMessage exist that expects an INTEGER
>> and handes this over to FormatMessage which expects a DWORD?
>
> SysErrorMessage is the cross platform function while FormatMessage
> is the Windows specific implementation so the types returned/used
> by these two functions are already compatible.
This is incorrect.
SysErrorMessage expects an INTEGER while FORMATMESSAGEA is
declared to use a DWORD parameter (see code snippets at the bottom).
> GetLastOSError merely uses GetLastError on Windows (on Linux it
> is errno for example) and casts its DWORD result to Integer.
Again incorrect. GetLastOSError gives back an Integer and
the DWORD coming from GetLastError it directly assigned to
this integer-type Result. There is no type casting (see below).
> SysErrorMessage gets that Integer passed in and converts it to
> DWORD again for FormatMessage on Windows (on Linux it uses a
> resourcestring table indexed by the error number for example).
Again incorrect.
"Conversion" yes, but no type casting.
Therefore, if the DWORD is above 2^31 you will
get a range check error (if range check is enabled).
And in the other direction (INTEGER assigned to a DWORD)
you will get a range check error when the valus is <0.
When I use Alt+Up and Ctrl+Shift+Down to let me point
to the defintion and declaration of each function I find:
In SYSUTILSH.INC
------------------------------------
function SysErrorMessage(ErrorCode: Integer): String;
const MaxMsgSize = Format_Message_Max_Width_Mask;
var MsgBuffer: pChar;
begin
GetMem(MsgBuffer, MaxMsgSize);
FillChar(MsgBuffer^, MaxMsgSize, #0);
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM,
nil,
ErrorCode,
MakeLangId(LANG_NEUTRAL, SUBLANG_DEFAULT),
MsgBuffer, { This function allocs the memory }
MaxMsgSize, { Maximum message size }
nil);
SysErrorMessage := StrPas(MsgBuffer);
FreeMem(MsgBuffer, MaxMsgSize);
end;
------------------------------------
In SYSUTILS:
------------------------------------
Function GetLastOSError : Integer;
begin
Result:=GetLastError;
end;
------------------------------------
(Used when coding "SysErrorMessage(GetLastOSError)")
In FUNC.INC:
------------------------------------
function GetLastError:DWORD; external 'kernel32' name 'GetLastError';
------------------------------------
All these functions are used in this way under Windows.
I don't know whether some of these functions change their
parameter types under other OS's. But under Windows it
does definitely not work correctly.
More information about the fpc-pascal
mailing list