PEファイルのMS-DOSヘッダ(IMAGE_DOS_HEADER
)とNTヘッダ(IMAGE_NT_HEADERS
)のシグネチャをメモリマップトファイルで読み込むサンプルコードです。IMAGE_DOS_HEADER
は固定長配列を含むため、マーシャリングとGCHandleを利用しています。IMAGE_NT_HEADERS
は最初のフィールドがシグネチャなので直接読み込んでいます。
using System; using System.IO; using System.IO.MemoryMappedFiles; using System.Runtime.InteropServices; using System.Text; class Program { static void Main() { var path = Path.Combine(Environment.SystemDirectory, "notepad.exe"); using var mmap = MemoryMappedFile.CreateFromFile(path, FileMode.Open, null, 0, MemoryMappedFileAccess.Read); using var accessor = mmap.CreateViewAccessor(0, 0, MemoryMappedFileAccess.Read); ReadMarshalStructure<IMAGE_DOS_HEADER>(accessor, 0, out var imgDosHdr); var mzSignature = imgDosHdr.e_magic; // 0x5a4d var peSignature = accessor.ReadUInt32(imgDosHdr.e_lfanew); // 0x00004550 var mzSignatureStr = Encoding.ASCII.GetString(BitConverter.GetBytes(mzSignature)); // "MZ" var peSignatureStr = Encoding.ASCII.GetString(BitConverter.GetBytes(peSignature)); // "PE\0\0" } private static void ReadMarshalStructure<T>(MemoryMappedViewAccessor accessor, long position, out T obj) where T : struct { var buffer = new byte[Marshal.SizeOf<T>()]; accessor.ReadArray<byte>(position, buffer, 0, buffer.Length); var handle = default(GCHandle); try { handle = GCHandle.Alloc(buffer, GCHandleType.Pinned); obj = Marshal.PtrToStructure<T>(handle.AddrOfPinnedObject()); } finally { handle.Free(); } } [StructLayout(LayoutKind.Sequential)] private struct IMAGE_DOS_HEADER { public ushort e_magic; public ushort e_cblp; public ushort e_cp; public ushort e_crlc; public ushort e_cparhdr; public ushort e_minalloc; public ushort e_maxalloc; public ushort e_ss; public ushort e_sp; public ushort e_csum; public ushort e_ip; public ushort e_cs; public ushort e_lfarlc; public ushort e_ovno; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public ushort[] e_res; public ushort e_oemid; public ushort e_oeminfo; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)] public ushort[] e_res2; public int e_lfanew; } }