I discovered this when I was PInvoking SetupDiCreateDeviceInfoList.
The C++ function signature is:
HDEVINFO SetupDiCreateDeviceInfoList(
_In_opt_ const GUID *ClassGuid,
_In_opt_ HWND hwndParent
);
In C# I have defined the GUID
structure like this:
[StructLayout(LayoutKind.Sequential)]
public struct GUID
{
public uint Data1;
public ushort Data2;
public ushort Data3;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public byte[] Data4;
}
and the function like this:
[DllImport("Setupapi.dll")]
public static extern IntPtr SetupDiCreateDeviceInfoList(GUID ClassGuid, IntPtr hwndParent);
Since in C# structures are passed by copy by default (unlike classes) this function signature should not match. And indeed when calling the function on 32-bit runtime:
GUID classGuid = new GUID();
IntPtr deviceInfoSet = SetupDiCreateDeviceInfoList(classGuid, IntPtr.Zero);
I get an error:
SetupDiCreateDeviceInfoList' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.
But on 64-bit runtime the code above works. Why ???
Of course, if I pass the structure by reference instead, the function works correctly on both 32-bit and 64-bit runtimes:
[DllImport("Setupapi.dll")]
public static extern IntPtr SetupDiCreateDeviceInfoList(ref GUID ClassGuid, IntPtr hwndParent);
GUID classGuid = new GUID();
IntPtr deviceInfoSet = SetupDiCreateDeviceInfoList(ref classGuid, IntPtr.Zero);