TD x64 versions (64Bit)
External functions: structmember alignment on x64 (64 bit)
You might encounter issues when using TD x64 versions and using external function structures.
You have to be aware that a structure has specific requirements concerning the position of members within the structure.
The CPU in modern computer hardware performs reads and writes to memory most efficiently when the data is naturally aligned, which generally means that the data address is a multiple of the data size.
Data alignment refers to aligning elements according to their natural alignment.
To ensure natural alignment, it may be necessary to insert some padding between structure elements or after the last element of a structure.
WinAPI x64 structures require that pointers and handles need to be aligned at 8 byte boundaries.
This means that within a structure, a pointer/handle member must be at offsets 0, 8, 16, 24...
Looking at the beginning of OPENFILENAME structure
DWORD lStructSize; HWND hwndOwner; HINSTANCE hInstance; LPCTSTR lpstrFilter; etc etc
A DWORD is indeed 32 bits wide (4 bytes).
This makes this list of sizes and offsets:
TYPE NAME BYTES OFFSET DWORD lStructSize; 4 0 HWND hwndOwner; 8 4 HINSTANCE hInstance; 8 12 LPCTSTR lpstrFilter; 8 20
The second member, hwndOwner, is a handle. This means it must be on a 8 byte boundary.
But in this case, the offset will be at position 4, which is not a 8 byte boundary.
In such situations you need to have a FILLER value (internal padding). Between the first and second member to force the second member to be at offset 8.
In TD, when defining structures in external functions, the members are sequentially aligned, from top to bottom.
So, to force a FILLER, you have to define an extra member at the correct location having the correct filler size.
In this particular case, we need to add a 4 byte member between the first and second member, like this:
TYPE NAME BYTES OFFSET DWORD lStructSize; 4 0 DWORD FILLER 4 4 HWND hwndOwner; 8 8 HINSTANCE hInstance; 8 16 LPCTSTR lpstrFilter; 8 24
When calling the external function, you need to pass in the extra parameter. Value is not important, but it is best to use zero's (0).
The OPENFILENAME structure has other members which need to be aligned to 8 byte boundaries.
The complete structure having all the needed FILLERS is displayed below:
The needed implementation for the structure above is shown in the sample which can be downloaded here:
For more detailed info on data structure padding see: