Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Treating structs like FILETIME as UInt64/Int64

Tags:

delphi

The question arise after I read a MSDN Blog article, Why can't you treat a FILETIME as an __int64?. The article said that casting a FILETIME to an __int64 can create a misaligned pointer.

FILETIME, LUID, and LUID_AND_ATTRIBUTES structs declared in Windows header as follows:

  typedef struct FILETIME {
      DWORD dwLowDateTime;
      DWORD dwHighDateTime;
  }

  typedef struct LUID {
      ULONG LowPart;
      LONG  HighPart;
  }

  typedef struct LUID_AND_ATTRIBUTES {
      LUID  Luid;
      DWORD Attributes;
  }

Since FILETIME and LUID structs has a similar layout, therefore treating a LUID as an __int64 also can create a misaligned pointer. However, Windows.pas (Delphi XE3 here) practises this--, for example:

  {$ALIGN 4}
  LUID_AND_ATTRIBUTES = record
    Luid      : Int64;  // Here, LUID is treated as Int64
    Attributes: DWORD;
  end;
  {$ALIGN ON}

another example is

  function LookupPrivilegeValue(lpSystemName, lpName: LPCWSTR;
      var lpLuid: Int64): BOOL; stdcall; // LUID is treated as Int64

How to safely treat structs like FILETIME or LUID directly  as UInt64/Int64? What is the key?

like image 666
Astaroth Avatar asked Nov 21 '12 06:11

Astaroth


1 Answers

It's a largely non-issue on the architectures that Delphi supports. The x86 and x64 architectures forgive you if you access mis-aligned data. On the other hand, accessing mis-aligned data on Itanium will result in runtime errors. But Delphi never targeted Itanium.

The issue that is significant is record layout. An Int64 has alignment of 8. But FILETIME and LUID have alignment of 4. Which is why LUID_AND_ATTRIBUTES is marked with an explicit $ALIGN 4.

If you are going to declare FILETIME and LUID to be Int64 then you need to take special care with record layout every time you include one in a record.

like image 138
David Heffernan Avatar answered Oct 02 '22 14:10

David Heffernan