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.ByValTStr, 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();
}
}
dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uRGlhZ25vc3RpY3M7CnVzaW5nIFN5c3RlbS5SdW50aW1lLkludGVyb3BTZXJ2aWNlczsKdXNpbmcgU3lzdGVtLlRleHQ7CgpwdWJsaWMgY2xhc3MgVGVzdAp7CglbU3RydWN0TGF5b3V0KExheW91dEtpbmQuU2VxdWVudGlhbCwgQ2hhclNldCA9IENoYXJTZXQuQW5zaSwgU2l6ZSA9IDI0KV0KICAgIHN0cnVjdCBWYWxpZAogICAgewogICAgICAgIHB1YmxpYyB1aW50IExlbmd0aDsKICAgICAgICBwdWJsaWMgdWludCBWZXJzaW9uOwogICAgICAgIFtNYXJzaGFsQXMoVW5tYW5hZ2VkVHlwZS5CeVZhbEFycmF5LCBTaXplQ29uc3QgPSAxNildCiAgICAgICAgcHVibGljIGJ5dGVbXSBNYWNoaW5lSWQ7CiAgICB9CgogICAgW1N0cnVjdExheW91dChMYXlvdXRLaW5kLlNlcXVlbnRpYWwsIENoYXJTZXQgPSBDaGFyU2V0LkFuc2ksIFNpemUgPSAyNCldCiAgICBzdHJ1Y3QgSW52YWxpZAogICAgewogICAgICAgIHB1YmxpYyB1aW50IExlbmd0aDsKICAgICAgICBwdWJsaWMgdWludCBWZXJzaW9uOwogICAgICAgIFtNYXJzaGFsQXMoVW5tYW5hZ2VkVHlwZS5CeVZhbFRTdHIsIFNpemVDb25zdCA9IDE2KV0gcHVibGljIHN0cmluZyBNYWNoaW5lSWQ7CiAgICB9CgoJcHVibGljIHN0YXRpYyB2b2lkIE1haW4oKQoJewoJCXZhciBieXRlcyA9IG5ldyBieXRlW10KICAgICAgICB7CiAgICAgICAgICAgIDB4NTgsIDAsIDAsIDAsCiAgICAgICAgICAgIDAsIDAsIDAsIDAsCiAgICAgICAgICAgIDB4NDEsIDB4NDIsIDB4NDMsIDB4NDQsIDB4NDUsIDB4NDYsIDB4NDcsIDB4NDgsIDB4NDksIDB4NEEsIDB4NEIsIDB4NEMsIDB4NEQsIDB4NEUsIDB4NEYsIDAKICAgICAgICB9OwoKICAgICAgICB2YXIgcGlubmVkQnVmZmVyID0gR0NIYW5kbGUuQWxsb2MoYnl0ZXMsIEdDSGFuZGxlVHlwZS5QaW5uZWQpOwogICAgICAgIHZhciBwdHIgPSBwaW5uZWRCdWZmZXIuQWRkck9mUGlubmVkT2JqZWN0KCk7CgogICAgICAgIC8vIFdvcmtzIQogICAgICAgIERlYnVnLkFzc2VydChieXRlcy5MZW5ndGggPT0gTWFyc2hhbC5TaXplT2Y8VmFsaWQ+KCkpOwogICAgICAgIAogICAgICAgIHZhciB0cmFja2VyRGF0YTEgPSBNYXJzaGFsLlB0clRvU3RydWN0dXJlPFZhbGlkPihwdHIpOwoKICAgICAgICBDb25zb2xlLldyaXRlTGluZSgiTGVuZ3RoOiB7MH0iLCB0cmFja2VyRGF0YTEuTGVuZ3RoKTsKICAgICAgICBDb25zb2xlLldyaXRlTGluZSgiVmVyc2lvbjogezB9IiwgdHJhY2tlckRhdGExLlZlcnNpb24pOwogICAgICAgIENvbnNvbGUuV3JpdGVMaW5lKCJNYWNoaW5lSWQ6IHswfSIsIEVuY29kaW5nLkFTQ0lJLkdldFN0cmluZyh0cmFja2VyRGF0YTEuTWFjaGluZUlkKSk7CgogICAgICAgIC8vIERvZXNudCB3b3JrIQogICAgICAgIERlYnVnLkFzc2VydChieXRlcy5MZW5ndGggPT0gTWFyc2hhbC5TaXplT2Y8SW52YWxpZD4oKSk7CiAgICAgICAgCiAgICAgICAgLy8gVGhyb3dzIFN5c3RlbS5BY2Nlc3NWaW9sYXRpb25FeGNlcHRpb24KICAgICAgICB2YXIgdHJhY2tlckRhdGEyID0gTWFyc2hhbC5QdHJUb1N0cnVjdHVyZTxJbnZhbGlkPihwdHIpOwoKICAgICAgICBDb25zb2xlLldyaXRlTGluZSgiTGVuZ3RoOiB7MH0iLCB0cmFja2VyRGF0YTIuTGVuZ3RoKTsKICAgICAgICBDb25zb2xlLldyaXRlTGluZSgiVmVyc2lvbjogezB9IiwgdHJhY2tlckRhdGEyLlZlcnNpb24pOwogICAgICAgIENvbnNvbGUuV3JpdGVMaW5lKCJNYWNoaW5lSWQ6IHswfSIsIHRyYWNrZXJEYXRhMi5NYWNoaW5lSWQpOwoKICAgICAgICBwaW5uZWRCdWZmZXIuRnJlZSgpOwoKICAgICAgICBDb25zb2xlLkluLlJlYWRMaW5lKCk7Cgl9Cn0=