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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With