[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