First of all the Boolean type is said to have a default marshal type of a four-byte value. So the following code works:
struct A
{
public
The line commented with 'FAILS, WOW, WTF?' fails because of the way boolean comparison is performed. It is comparing 2 to 1:
IL_007e: ldc.i4.1
IL_007f: ldloca.s 3
IL_0081: ldflda valuetype Test/A Test/Broken::a
IL_0086: ldfld bool Test/A::bValue1
IL_008b: ceq
ceq ends up comparing 1 to the byte in bValue, which is 2.
The funny thing is that if (broken.a.bValue1) will test 'true' because it's non-zero.
As far as the other problem (broken.a.iValue2 == 4), it went away when I applied:
[MarshalAs (UnmanagedType.Bool)]
to both boolean fields in the structures. This makes sure the booleans are marshaled as an integer (4 bytes in .NET).