using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
public class Test
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Size = 24)]
struct Valid
{
public uint Length;
public uint Version;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public byte[] MachineId;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Size = 24)]
struct Invalid
{
public uint Length;
public uint Version;
[MarshalAs(UnmanagedType.LPStr, SizeConst = 16)] public string MachineId;
}
public static void Main()
{
var bytes = new byte[]
{
0x58, 0, 0, 0,
0, 0, 0, 0,
0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0
};
var pinnedBuffer = GCHandle.Alloc(bytes, GCHandleType.Pinned);
var ptr = pinnedBuffer.AddrOfPinnedObject();
// Works!
Debug.Assert(bytes.Length == Marshal.SizeOf<Valid>());
var trackerData1 = Marshal.PtrToStructure<Valid>(ptr);
Console.WriteLine("Length: {0}", trackerData1.Length);
Console.WriteLine("Version: {0}", trackerData1.Version);
Console.WriteLine("MachineId: {0}", Encoding.ASCII.GetString(trackerData1.MachineId));
// Doesnt work!
Debug.Assert(bytes.Length == Marshal.SizeOf<Invalid>());
// Throws System.AccessViolationException
var trackerData2 = Marshal.PtrToStructure<Invalid>(ptr);
Console.WriteLine("Length: {0}", trackerData2.Length);
Console.WriteLine("Version: {0}", trackerData2.Version);
Console.WriteLine("MachineId: {0}", trackerData2.MachineId);
pinnedBuffer.Free();
Console.In.ReadLine();
}
}
dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uRGlhZ25vc3RpY3M7CnVzaW5nIFN5c3RlbS5SdW50aW1lLkludGVyb3BTZXJ2aWNlczsKdXNpbmcgU3lzdGVtLlRleHQ7CgpwdWJsaWMgY2xhc3MgVGVzdAp7CglbU3RydWN0TGF5b3V0KExheW91dEtpbmQuU2VxdWVudGlhbCwgQ2hhclNldCA9IENoYXJTZXQuQW5zaSwgU2l6ZSA9IDI0KV0KICAgIHN0cnVjdCBWYWxpZAogICAgewogICAgICAgIHB1YmxpYyB1aW50IExlbmd0aDsKICAgICAgICBwdWJsaWMgdWludCBWZXJzaW9uOwogICAgICAgIFtNYXJzaGFsQXMoVW5tYW5hZ2VkVHlwZS5CeVZhbEFycmF5LCBTaXplQ29uc3QgPSAxNildCiAgICAgICAgcHVibGljIGJ5dGVbXSBNYWNoaW5lSWQ7CiAgICB9CgogICAgW1N0cnVjdExheW91dChMYXlvdXRLaW5kLlNlcXVlbnRpYWwsIENoYXJTZXQgPSBDaGFyU2V0LkFuc2ksIFNpemUgPSAyNCldCiAgICBzdHJ1Y3QgSW52YWxpZAogICAgewogICAgICAgIHB1YmxpYyB1aW50IExlbmd0aDsKICAgICAgICBwdWJsaWMgdWludCBWZXJzaW9uOwogICAgICAgIFtNYXJzaGFsQXMoVW5tYW5hZ2VkVHlwZS5MUFN0ciwgU2l6ZUNvbnN0ID0gMTYpXSBwdWJsaWMgc3RyaW5nIE1hY2hpbmVJZDsKICAgIH0KCglwdWJsaWMgc3RhdGljIHZvaWQgTWFpbigpCgl7CgkJdmFyIGJ5dGVzID0gbmV3IGJ5dGVbXQogICAgICAgIHsKICAgICAgICAgICAgMHg1OCwgMCwgMCwgMCwKICAgICAgICAgICAgMCwgMCwgMCwgMCwKICAgICAgICAgICAgMHg0MSwgMHg0MiwgMHg0MywgMHg0NCwgMHg0NSwgMHg0NiwgMHg0NywgMHg0OCwgMHg0OSwgMHg0QSwgMHg0QiwgMHg0QywgMHg0RCwgMHg0RSwgMHg0RiwgMAogICAgICAgIH07CgogICAgICAgIHZhciBwaW5uZWRCdWZmZXIgPSBHQ0hhbmRsZS5BbGxvYyhieXRlcywgR0NIYW5kbGVUeXBlLlBpbm5lZCk7CiAgICAgICAgdmFyIHB0ciA9IHBpbm5lZEJ1ZmZlci5BZGRyT2ZQaW5uZWRPYmplY3QoKTsKCiAgICAgICAgLy8gV29ya3MhCiAgICAgICAgRGVidWcuQXNzZXJ0KGJ5dGVzLkxlbmd0aCA9PSBNYXJzaGFsLlNpemVPZjxWYWxpZD4oKSk7CiAgICAgICAgCiAgICAgICAgdmFyIHRyYWNrZXJEYXRhMSA9IE1hcnNoYWwuUHRyVG9TdHJ1Y3R1cmU8VmFsaWQ+KHB0cik7CgogICAgICAgIENvbnNvbGUuV3JpdGVMaW5lKCJMZW5ndGg6IHswfSIsIHRyYWNrZXJEYXRhMS5MZW5ndGgpOwogICAgICAgIENvbnNvbGUuV3JpdGVMaW5lKCJWZXJzaW9uOiB7MH0iLCB0cmFja2VyRGF0YTEuVmVyc2lvbik7CiAgICAgICAgQ29uc29sZS5Xcml0ZUxpbmUoIk1hY2hpbmVJZDogezB9IiwgRW5jb2RpbmcuQVNDSUkuR2V0U3RyaW5nKHRyYWNrZXJEYXRhMS5NYWNoaW5lSWQpKTsKCiAgICAgICAgLy8gRG9lc250IHdvcmshCiAgICAgICAgRGVidWcuQXNzZXJ0KGJ5dGVzLkxlbmd0aCA9PSBNYXJzaGFsLlNpemVPZjxJbnZhbGlkPigpKTsKICAgICAgICAKICAgICAgICAvLyBUaHJvd3MgU3lzdGVtLkFjY2Vzc1Zpb2xhdGlvbkV4Y2VwdGlvbgogICAgICAgIHZhciB0cmFja2VyRGF0YTIgPSBNYXJzaGFsLlB0clRvU3RydWN0dXJlPEludmFsaWQ+KHB0cik7CgogICAgICAgIENvbnNvbGUuV3JpdGVMaW5lKCJMZW5ndGg6IHswfSIsIHRyYWNrZXJEYXRhMi5MZW5ndGgpOwogICAgICAgIENvbnNvbGUuV3JpdGVMaW5lKCJWZXJzaW9uOiB7MH0iLCB0cmFja2VyRGF0YTIuVmVyc2lvbik7CiAgICAgICAgQ29uc29sZS5Xcml0ZUxpbmUoIk1hY2hpbmVJZDogezB9IiwgdHJhY2tlckRhdGEyLk1hY2hpbmVJZCk7CgogICAgICAgIHBpbm5lZEJ1ZmZlci5GcmVlKCk7CgogICAgICAgIENvbnNvbGUuSW4uUmVhZExpbmUoKTsKCX0KfQ==