typedef struct _FILE_OBJECTID_INFORMATION {
LONGLONG FileReference;
UCHAR ObjectId[16];
union {
struct {
UCHAR BirthVolumeId[16];
UCHAR BirthObjectId[16];
UCHAR DomainId[16];
} DUMMYSTRUCTNAME;
UCHAR ExtendedInfo[48];
} DUMMYUNIONNAME;
} FILE_OBJECTID_INFORMATION, *PFILE_OBJECTID_INFORMATION;
How to translate such a union to Delphi?
The Pascal equivalent of a C union
is known as a variant record.
A record type can have a variant part, which looks like a case statement. The variant part must follow the other fields in the record declaration.
To declare a record type with a variant part, use the following syntax:
type recordTypeName = record fieldList1: type1; ... fieldListn: typen; case tag: ordinalType of constantList1: (variant1); ... constantListn: (variantn); end;
The first part of the declaration - up to the reserved word case - is the same as that of a standard record type. The remainder of the declaration - from case to the optional final semicolon - is called the variant part. In the variant part,
- tag is optional and can be any valid identifier. If you omit tag, omit the colon (:) after it as well.
- ordinalType denotes an ordinal type.
- Each constantList is a constant denoting a value of type ordinalType, or a comma-delimited list of such constants. No value can be represented more than once in the combined constantLists.
Each variant is a semicolon-delimited list of declarations resembling the fieldList: type constructions in the main part of the record type. That is, a variant has the form:
fieldList1: type1; ... fieldListn: typen;
where each fieldList is a valid identifier or comma-delimited list of identifiers, each type denotes a type, and the final semicolon is optional. The types must not be long strings, dynamic arrays, variants (that is, Variant types), or interfaces, nor can they be structured types that contain long strings, dynamic arrays, variants, or interfaces; but they can be pointers to these types.
Records with variant parts are complicated syntactically but deceptively simple semantically. The variant part of a record contains several variants which share the same space in memory. You can read or write to any field of any variant at any time; but if you write to a field in one variant and then to a field in another variant, you may be overwriting your own data. The tag, if there is one, functions as an extra field (of type ordinalType) in the non-variant part of the record.
As for the rest, it's pretty routine: LONGLONG
is a 64 bit integer, and UCHAR
is unsigned char
, or AnsiChar
in Delphi.
type
TFileObjectIDInformation = record
FileReference: Int64;
ObjectID: array[0..15] of AnsiChar;
case Integer of
0:
(
BirthVolumeId: array[0..15] of AnsiChar;
BirthObjectId: array[0..15] of AnsiChar;
DomainId: array[0..15] of AnsiChar;
);
1:
(ExtendedInfo: array[0..47] of AnsiChar);
end;
It's possible that Byte
may be more appropriate than AnsiChar
. It's a bit hard to tell of course because C, unlike Pascal, doesn't have separate types for Byte
and AnsiChar
. But these arrays look to me as though they would be read as text so my guess is that AnsiChar
would be more appropriate.
Similar structure can be found in JEDI API Lib:
_FILE_OBJECTID_BUFFER = record
//
// This is the portion of the object id that is indexed.
//
ObjectId: array [0..15] of BYTE;
//
// This portion of the object id is not indexed, it's just
// some metadata for the user's benefit.
//
case Integer of
0: (
BirthVolumeId: array [0..15] of BYTE;
BirthObjectId: array [0..15] of BYTE;
DomainId: array [0..15] of BYTE);
1: (
ExtendedInfo: array [0..47] of BYTE);
end;
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