diff --git a/DiscImageChef.Filesystems/NTFS.cs b/DiscImageChef.Filesystems/NTFS.cs
index 48ff3729c..6ad3ed3ec 100644
--- a/DiscImageChef.Filesystems/NTFS.cs
+++ b/DiscImageChef.Filesystems/NTFS.cs
@@ -34,8 +34,10 @@ using System;
using System.Text;
using DiscImageChef;
using System.Collections.Generic;
+using System.Runtime.InteropServices;
// Information from Inside Windows NT
+using DiscImageChef.Checksums;
namespace DiscImageChef.Filesystems
{
public class NTFS : Filesystem
@@ -96,41 +98,13 @@ namespace DiscImageChef.Filesystems
byte[] ntfs_bpb = imagePlugin.ReadSector(0 + partitionStart);
NTFS_BootBlock ntfs_bb = new NTFS_BootBlock();
+ IntPtr bpbPtr = Marshal.AllocHGlobal(512);
+ Marshal.Copy(ntfs_bpb, 0, bpbPtr, 512);
+ ntfs_bb = (NTFS_BootBlock)Marshal.PtrToStructure(bpbPtr, typeof(NTFS_BootBlock));
+ Marshal.FreeHGlobal(bpbPtr);
byte[] oem_name = new byte[8];
- ntfs_bb.jmp1 = ntfs_bpb[0x000];
- ntfs_bb.jmp2 = BitConverter.ToUInt16(ntfs_bpb, 0x001);
- Array.Copy(ntfs_bpb, 0x003, oem_name, 0, 8);
- ntfs_bb.OEMName = StringHandlers.CToString(oem_name);
- ntfs_bb.bps = BitConverter.ToUInt16(ntfs_bpb, 0x00B);
- ntfs_bb.spc = ntfs_bpb[0x00D];
- ntfs_bb.rsectors = BitConverter.ToUInt16(ntfs_bpb, 0x00E);
- ntfs_bb.fats_no = ntfs_bpb[0x010];
- ntfs_bb.root_ent = BitConverter.ToUInt16(ntfs_bpb, 0x011);
- ntfs_bb.sml_sectors = BitConverter.ToUInt16(ntfs_bpb, 0x013);
- ntfs_bb.media = ntfs_bpb[0x015];
- ntfs_bb.spfat = BitConverter.ToUInt16(ntfs_bpb, 0x016);
- ntfs_bb.sptrk = BitConverter.ToUInt16(ntfs_bpb, 0x018);
- ntfs_bb.heads = BitConverter.ToUInt16(ntfs_bpb, 0x01A);
- ntfs_bb.hsectors = BitConverter.ToUInt32(ntfs_bpb, 0x01C);
- ntfs_bb.big_sectors = BitConverter.ToUInt32(ntfs_bpb, 0x020);
- ntfs_bb.drive_no = ntfs_bpb[0x024];
- ntfs_bb.nt_flags = ntfs_bpb[0x025];
- ntfs_bb.signature1 = ntfs_bpb[0x026];
- ntfs_bb.dummy = ntfs_bpb[0x027];
- ntfs_bb.sectors = BitConverter.ToInt64(ntfs_bpb, 0x028);
- ntfs_bb.mft_lsn = BitConverter.ToInt64(ntfs_bpb, 0x030);
- ntfs_bb.mftmirror_lsn = BitConverter.ToInt64(ntfs_bpb, 0x038);
- ntfs_bb.mft_rc_clusters = (sbyte)ntfs_bpb[0x040];
- ntfs_bb.dummy2 = ntfs_bpb[0x041];
- ntfs_bb.dummy3 = BitConverter.ToUInt16(ntfs_bpb, 0x042);
- ntfs_bb.index_blk_cts = (sbyte)ntfs_bpb[0x044];
- ntfs_bb.dummy4 = ntfs_bpb[0x045];
- ntfs_bb.dummy5 = BitConverter.ToUInt16(ntfs_bpb, 0x046);
- ntfs_bb.serial_no = BitConverter.ToUInt64(ntfs_bpb, 0x048);
- ntfs_bb.signature2 = BitConverter.ToUInt16(ntfs_bpb, 0x1FE);
-
sb.AppendFormat("{0} bytes per sector", ntfs_bb.bps).AppendLine();
sb.AppendFormat("{0} sectors per cluster ({1} bytes)", ntfs_bb.spc, ntfs_bb.spc * ntfs_bb.bps).AppendLine();
// sb.AppendFormat("{0} reserved sectors", ntfs_bb.rsectors).AppendLine();
@@ -165,6 +139,17 @@ namespace DiscImageChef.Filesystems
// sb.AppendFormat("Signature 2: 0x{0:X4}", ntfs_bb.signature2).AppendLine();
xmlFSType = new Schemas.FileSystemType();
+
+ if(ntfs_bb.jump[0] == 0xEB && ntfs_bb.jump[1] > 0x4E && ntfs_bb.jump[1] < 0x80 && ntfs_bb.signature2 == 0xAA55)
+ {
+ xmlFSType.Bootable = true;
+ SHA1Context sha1Ctx = new SHA1Context();
+ sha1Ctx.Init();
+ string bootChk = sha1Ctx.Data(ntfs_bb.boot_code, out byte[] sha1_out);
+ sb.AppendLine("Volume is bootable");
+ sb.AppendFormat("Boot code's SHA1: {0}", bootChk).AppendLine();
+ }
+
xmlFSType.ClusterSize = ntfs_bb.spc * ntfs_bb.bps;
xmlFSType.Clusters = ntfs_bb.sectors / ntfs_bb.spc;
xmlFSType.VolumeSerial = string.Format("{0:X16}", ntfs_bb.serial_no);
@@ -176,15 +161,16 @@ namespace DiscImageChef.Filesystems
///
/// NTFS $BOOT
///
+ [StructLayout(LayoutKind.Sequential, Pack = 1)]
struct NTFS_BootBlock
{
// Start of BIOS Parameter Block
/// 0x000, Jump to boot code
- public byte jmp1;
- /// 0x001, ...;
- public ushort jmp2;
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
+ public byte[] jump;
/// 0x003, OEM Name, 8 bytes, space-padded, must be "NTFS "
- public string OEMName;
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
+ public byte[] oem_name;
/// 0x00B, Bytes per sector
public ushort bps;
/// 0x00D, Sectors per cluster
@@ -221,11 +207,11 @@ namespace DiscImageChef.Filesystems
// Start of NTFS real superblock
/// 0x028, Sectors on volume
- public Int64 sectors;
+ public long sectors;
/// 0x030, LSN of $MFT
- public Int64 mft_lsn;
+ public long mft_lsn;
/// 0x038, LSN of $MFTMirror
- public Int64 mftmirror_lsn;
+ public long mftmirror_lsn;
/// 0x040, Clusters per MFT record
public sbyte mft_rc_clusters;
/// 0x041, Alignment
@@ -240,8 +226,9 @@ namespace DiscImageChef.Filesystems
public ushort dummy5;
/// 0x048, Volume serial number
public ulong serial_no;
- // End of NTFS superblock, followed by 430 bytes of boot code
-
+ /// Boot code.
+ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 430)]
+ public byte[] boot_code;
/// 0x1FE, 0xAA55
public ushort signature2;
}