While using GetLastError
after calling a Windows API function wrapper like ExtractShortPathName
I noticed that GetLastError
returns a non-zero error code regardless of whether the call to ExtractShortPathName
succeeded or failed. In fact, there seems to be a "last error" before my program even executes, e.g.
program TestGetLastError;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
var
ErrorCode: Integer;
begin
try
ErrorCode := GetLastError;
if ErrorCode <> 0 then
RaiseLastOSError;
except
on E: Exception do
WriteLn(E.ClassName, ': ', E.Message);
end;
end.
results in:
EOSError: System Error. Code: 122.
The data area passed to a system call is too small
Am I misunderstanding something or doing something wrong?
If the Delphi run-time is doing something that results in GetLastError
being set, what is the correct way to clear that error before my program starts executing? Should I use SetLastError(ERROR_SUCCESS);
like this example from the Delphi API documentation:
procedure TForm2.btRaiseLastClick(Sender: TObject);
begin
{ Set the last OS error to a bogus value. }
System.SetLastError(ERROR_ACCESS_DENIED);
try
RaiseLastOSError();
except
on Ex : EOSError do
MessageDlg('Caught an OS error with code: ' + IntToStr(Ex.ErrorCode), mtError, [mbOK], 0);
end;
{ Let the Delphi Exception dialog appear. }
RaiseLastOSError(ERROR_NOT_ENOUGH_MEMORY);
{ Finally set the last error to none. }
System.SetLastError(ERROR_SUCCESS);
if GetLastError() <> ERROR_SUCCESS then
MessageDlg('Whoops, something went wrong in the mean time!', mtError, [mbOK], 0);
{ No exception should be thrown here because last OS error is "ERROR_SUCCESS". }
CheckOSError(GetLastError());
end;
http://docwiki.embarcadero.com/CodeExamples/Tokyo/en/LastOSError_(Delphi)
GetLastError's documentation indicates that is only of use if
The return value is the calling thread's last-error code.
The Return Value section of the documentation for each function that sets the last-error code notes the conditions under which the function sets the last-error code. Most functions that set the thread's last-error code set it when they fail. However, some functions also set the last-error code when they succeed. If the function is not documented to set the last-error code, the value returned by this function is simply the most recent last-error code to have been set; some functions set the last-error code to 0 on success and others do not.
This indicates that calling it without first having a failure in a function documented to set it on failure is meaningless. You can't call GetLastError unless you know an error occurred, and only if you're calling it after a specific function you called indicates it failed.