Search code examples
winapirecordpascal

Pascal: Get field from LPSYSTEMTIME record


I'm using the Win32 api to get date and time of a file. I have a LPSYSTEMTIME structure, and I'm trying to print its wYear variable.

I've got a function (GetFileDate):

function GetFileDate : LPSYSTEMTIME
var
    CheckFile: Long;
    FileTime: LPFILETIME;
    FileTimeReturn: LPFILETIME;
    SystemTimeReturn: LPSYSTEMTIME;
begin
    CheckFile := CreateFile(PChar('main.pas'), GENERIC_READ, FILE_SHARE_READ, NIL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
    GetFileTime(CheckFile, FileTime, NIL, NIL);
    FileTimeToLocalFileTime(FileTime, FileTimeReturn);
    FileTimeToSystemTime(FileTimeReturn, SystemTimeReturn);
    GetFileDate := SystemTimeReturn;
end;

But when I do this...

begin
    Write(GetFileDate.wYear);
end.

It spits back

main.pas(22,20) Error: Illegal qualifier
main.pas(22,20) Fatal: Syntax error, ")" expected but "identifier WYEAR" found
Fatal: Compilation aborted

Any help on this?


Solution

  • LPSYSTEMTIME is a pointer to a SYSTEMTIME structure. Try using the ^ operator to dereference that pointer, eg:

    Write(GetFileDate^.wYear);
    

    Or:

    Write(GetFileDate()^.wYear);
    

    With that said, aside from the fact that you are not doing any error handling at all, your GetFileDate() implementation is passing the wrong parameter values to the various API functions. That code should not even compile, let alone run correctly.

    Try this instead:

    function GetFileDate : SYSTEMTIME;
    var 
      CheckFile: HANDLE; 
      FileTime: FILETIME; 
      FileTimeReturn: FILETIME; 
      SystemTimeReturn: SYSTEMTIME;
      GetFileDateResult: SYSTEMTIME;
    begin 
      ZeroMemory(@GetFileDateResult, SizeOf(GetFileDateResult));
      CheckFile := CreateFile('FullPathTo\main.pas', GENERIC_READ, FILE_SHARE_READ, NIL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); 
      if CheckFile <> INVALID_HANDLE_VALUE then
      begin
        if GetFileTime(CheckFile, @FileTime, nil, nil) then
        begin
          if FileTimeToLocalFileTime(@FileTime, @FileTimeReturn) then
          begin
            if FileTimeToSystemTime(@FileTimeReturn, @SystemTimeReturn) then
              GetFileDateResult := SystemTimeReturn;
          end;
        end;
        CloseHandle(CheckFile);
      end; 
      GetFileDate := GetFileDateResult;
    end; 
    
    begin   
      Write(GetFileDate.wYear);   
    end.
    

    Alternatively, I would suggest using FindFirstFile() instead of CreateFile() so you do not have to open the file just to get its date. The filesystem can supply that information, eg:

    function GetFileDate : SYSTEMTIME;
    var 
      CheckFile: HANDLE; 
      FindFileData: WIN32_FIND_DATA;
      FileTimeReturn: FILETIME; 
      SystemTimeReturn: SYSTEMTIME;
      GetFileDateResult: SYSTEMTIME;
    begin 
      ZeroMemory(@GetFileDateResult, SizeOf(GetFileDateResult));
      CheckFile := FindFirstFile('FullPathTo\main.pas', @FindFileData);
      if CheckFile <> 0 then
      begin
        if FileTimeToLocalFileTime(@FindFileData.ftCreationTime, @FileTimeReturn) then
        begin
          if FileTimeToSystemTime(@FileTimeReturn, @SystemTimeReturn) then
            GetFileDateResult := SystemTimeReturn;
        end;
        FindClose(CheckFile);
      end; 
      GetFileDate := GetFileDateResult;
    end;