It is important to understand that Windows couldn't care less what your assembler or C++ compiler decides.
The structures that you are passing to a Windows function are being used in a DLL, and in front of that DLL is a sign saying "compilers, stay outta here!".
So if you pass a structure with your favourite alignment, and Windows expects another one, you are doomed.
Unfortunately, the MSDN documentation is either old and false (
VS 6.0: the default for Win32 is 8 bytes,
VS2003: "The default for this switch is /Zp8"), or new and misleading (
VS 2015: "Visual C++ generally aligns data on natural boundaries based on the target processor and the size of the data, up to
4-byte boundaries on 32-bit processors, and 8-byte boundaries on 64-bit
processors.")
More recently, Under "Using the Windows Headers", MSDN states:
The header files for the Windows API enable you to create 32- and 64-bit applications.
...
Controlling Structure Packing
Projects should be compiled to use the default structure packing, which is currently 8 bytes
OKAY.... that was 8 bytes in 2003, 4 bytes "on 32-bit processors" in VS2015, and 8 bytes again for
Win 8.1 ::)
So if you are a little bit uncertain, go the empirical route! Here is a test (32-bit and 64-bit executables attached) with a nasty structure:
SHQUERYRBINFO STRUCT
cbSize dd ?
i64Size qword ?
i64NumItems qword ?
SHQUERYRBINFO ENDS
include \Masm32\MasmBasic\Res\JBasic.inc ; ## OPT_64 0 ; put 0 for 32 bit, 1 for 64 bit assembly ##
.data
qrb SHQUERYRBINFO <SHQUERYRBINFO, 0, 0>
Init
PrintLine Chr$("This code was assembled with ", @AsmUsed$(1), " in ", jbit$, "-bit format")
lea rax, qrb.i64Size
lea rdx, qrb.cbSize
sub rax, rdx
deb 4, "offset i64Size - cbSize", rax
.if rv(SHQueryRecycleBin, Chr$("C:"), addr qrb)
Inkey Err$()
.else
Print Str$(" \nThere are %i elements in the recycle", dword ptr qrb.i64NumItems)
Inkey Str$(" bin, and their total size is %i bytes\n\n", dword ptr qrb.i64Size)
.endif
EndOfCodeOutput:This code was assembled with HJWasm32 in 64-bit format
offset i64Size - cbSize rax 8
There are 2 elements in the recycle bin, and their total size is 4640 bytes
This code was assembled with HJWasm32 in 32-bit format
offset i64Size - cbSize rax 4
There are 2 elements in the recycle bin, and their total size is 4640 bytes
So it turns out that the correct alignment for 32-bit code on my 64-bit
processor is
4 bytes, not 8. You can test it with -Zp8 for 32-bit code: SHQueryRecycleBin does
not report an error, but you'll get 0 elements with 0 bytes.
Now the good news: By sheer coincidence, all other 17 or so structures in Windows.inc+WinExtra.inc that contain QWORDs have an even number of DWORDs before the QWORDs, so it doesn't matter whether you use -Zp4 or Zp8. Isn't that cute?
P.S.: One more good advice from Redmond, in
/Zp (Struct Member Alignment), Visual Studio 2015: "You should not use this option"
