diff --git a/CSharp/Plugins/UniversalEditor.Plugins.FileSystem/DataFormats/FileSystem/FAT/FATDataFormat.cs b/CSharp/Plugins/UniversalEditor.Plugins.FileSystem/DataFormats/FileSystem/FAT/FATDataFormat.cs
index ceeda468..d94499b8 100644
--- a/CSharp/Plugins/UniversalEditor.Plugins.FileSystem/DataFormats/FileSystem/FAT/FATDataFormat.cs
+++ b/CSharp/Plugins/UniversalEditor.Plugins.FileSystem/DataFormats/FileSystem/FAT/FATDataFormat.cs
@@ -13,8 +13,8 @@ namespace UniversalEditor.DataFormats.FileSystem.FAT
private byte[] mvarJumpInstruction = new byte[] { 0xEB, 0x3C, 0x90 };
///
/// Jump instruction. This instruction will be executed and will skip past the rest of the
- /// (non-executable) header if the partition is booted from. See Volume Boot Record. If the jump is
- /// two-byte near jmp it is followed by a NOP instruction. Must be 3 bytes.
+ /// (non-executable) header if the partition is booted from. See Volume Boot Record. If the jump is
+ /// two-byte near jmp it is followed by a NOP instruction. Must be 3 bytes.
///
public byte[] JumpInstruction { get { return mvarJumpInstruction; } set { if (value.Length != 3) { throw new ArgumentOutOfRangeException("value", value, "Jump Instruction must be exactly 3 bytes in length"); } else { mvarJumpInstruction = value; } } }
@@ -31,73 +31,73 @@ namespace UniversalEditor.DataFormats.FileSystem.FAT
public FATExtendedBiosParameterBlock ExtendedBiosParameterBlock { get { return mvarExtendedBiosParameterBlock; } }
#endregion
- #region Overrides
- private DataFormatReference _dfr = null;
- protected override DataFormatReference MakeReferenceInternal()
- {
- if (_dfr == null)
- {
- _dfr = base.MakeReferenceInternal();
- _dfr.Capabilities.Add(typeof(FileSystemObjectModel), DataFormatCapabilities.All);
- _dfr.ExportOptions.Add(new CustomOptionText("OEMName", "OEM &name:", "MSDOS5.0", 8));
-
- #region Bios Parameter Block
- {
- CustomOptionGroup grp = new CustomOptionGroup("BiosParameterBlock", "BIOS parameter block");
- grp.Options.Add(new CustomOptionNumber("BytesPerSector", "&Bytes per sector:", 512, 0, short.MaxValue));
- grp.Options.Add(new CustomOptionNumber("SectorsPerCluster", "&Sectors per cluster:", 1, 1, 128));
- grp.Options.Add(new CustomOptionNumber("ReservedSectorCount", "&Reserved sectors:", 32, 0, short.MaxValue));
- grp.Options.Add(new CustomOptionNumber("FileAllocationTableCount", "Number of &file allocation tables:", 2, 0, byte.MaxValue));
- grp.Options.Add(new CustomOptionNumber("MaximumRootDirectoryEntryCount", "Maximum number of &root directory entries:", 0, 0, short.MaxValue));
- grp.Options.Add(new CustomOptionChoice("MediaDescriptor", "Media &descriptor:", true,
- new CustomOptionFieldChoice("Unknown", FATMediaDescriptor.Unknown),
- new CustomOptionFieldChoice("3.5\" double-sided, 80 tracks per side, 18 or 36 sectors per track (1.44MB or 2.88MB)", FATMediaDescriptor.MediaDescriptor0),
- new CustomOptionFieldChoice("5.25\" double-sided, 80 tracks per side, 15 sectors per track (1.2MB)", FATMediaDescriptor.MediaDescriptor0),
- new CustomOptionFieldChoice("Fixed disk (i.e., a hard disk)", FATMediaDescriptor.FixedDisk),
- new CustomOptionFieldChoice("3.5\" double-sided, 80 tracks per side, 9 sectors per track (720K)", FATMediaDescriptor.MediaDescriptor2),
- new CustomOptionFieldChoice("5.25\" double-sided, 80 tracks per side, 15 sectors per track (1.2MB)", FATMediaDescriptor.MediaDescriptor2),
- new CustomOptionFieldChoice("5.25\" single-sided, 80 tracks per side, 8 sectors per track (320K)", FATMediaDescriptor.MediaDescriptor3),
- new CustomOptionFieldChoice("3.5\" double-sided, 80 tracks per side, 8 sectors per track (640K)", FATMediaDescriptor.MediaDescriptor4),
- new CustomOptionFieldChoice("5.25\" single-sided, 40 tracks per side, 9 sectors per track (180K)", FATMediaDescriptor.MediaDescriptor5),
- new CustomOptionFieldChoice("5.25\" or 8\" double-sided, 40 tracks per side, 9 sectors per track (360K)", FATMediaDescriptor.MediaDescriptor6),
- new CustomOptionFieldChoice("5.25\" or 8\" single-sided, 40 tracks per side, 8 sectors per track (160K)", FATMediaDescriptor.MediaDescriptor7),
- new CustomOptionFieldChoice("5.25\" double-sided, 40 tracks per side, 8 sectors per track (320K)", FATMediaDescriptor.MediaDescriptor8)
- ));
-
- grp.Options.Add(new CustomOptionNumber("SectorsPerFAT16", "Sectors per allocation table:", 0));
- grp.Options.Add(new CustomOptionNumber("SectorsPerTrack", "Sectors per track:", 0));
- grp.Options.Add(new CustomOptionNumber("NumberOfHeads", "Number of heads:", 0));
- grp.Options.Add(new CustomOptionNumber("HiddenSectorCount", "Number of &hidden sectors:", 0));
- grp.Options.Add(new CustomOptionNumber("TotalSectors", "Number of &total sectors:", 0));
- _dfr.ExportOptions.Add(grp);
- }
- #endregion
- #region Extended BIOS parameter block
- {
- CustomOptionGroup grp = new CustomOptionGroup("ExtendedBiosParameterBlock", "Extended BIOS parameter block");
- grp.Options.Add(new CustomOptionNumber("PhysicalDriveNumber", "Physical drive &number:", 0));
- grp.Options.Add(new CustomOptionMultipleChoice("CheckDiskFlags", "CHKDSK &flags:", new CustomOptionFieldChoice("Dirty", FATCheckDiskFlags.Dirty), new CustomOptionFieldChoice("Error", FATCheckDiskFlags.Error)));
- grp.Options.Add(new CustomOptionNumber("NumberOfHeads", "Number of heads:", 0));
- grp.Options.Add(new CustomOptionNumber("HiddenSectorCount", "Number of &hidden sectors:", 0));
- grp.Options.Add(new CustomOptionNumber("TotalSectors", "Number of &total sectors:", 0));
- #region Extended Boot Signature
- {
- CustomOptionGroup grp1 = new CustomOptionGroup("ExtendedBootSignature", "Extended Boot Signature");
- grp1.Options.Add(new CustomOptionBoolean("Enabled", "Include extended boot signature", true));
- grp1.Options.Add(new CustomOptionNumber("VolumeSerialNumber", "Volume &serial number:", 0));
- grp1.Options.Add(new CustomOptionText("PartitionVolumeLabel", "Partition &volume label:", String.Empty));
- grp1.Options.Add(new CustomOptionText("FileSystemType", "File system &type:", String.Empty));
- grp.Options.Add(grp1);
- }
- #endregion
- _dfr.ExportOptions.Add(grp);
- }
- #endregion
- }
- return _dfr;
- }
+ #region Overrides
+ private DataFormatReference _dfr = null;
+ protected override DataFormatReference MakeReferenceInternal()
+ {
+ if (_dfr == null)
+ {
+ _dfr = base.MakeReferenceInternal();
+ _dfr.Capabilities.Add(typeof(FileSystemObjectModel), DataFormatCapabilities.All);
+ _dfr.ExportOptions.Add(new CustomOptionText("OEMName", "OEM &name:", "MSDOS5.0", 8));
+
+ #region Bios Parameter Block
+ {
+ CustomOptionGroup grp = new CustomOptionGroup("BiosParameterBlock", "BIOS parameter block");
+ grp.Options.Add(new CustomOptionNumber("BytesPerSector", "&Bytes per sector:", 512, 0, short.MaxValue));
+ grp.Options.Add(new CustomOptionNumber("SectorsPerCluster", "&Sectors per cluster:", 1, 1, 128));
+ grp.Options.Add(new CustomOptionNumber("ReservedSectorCount", "&Reserved sectors:", 32, 0, short.MaxValue));
+ grp.Options.Add(new CustomOptionNumber("FileAllocationTableCount", "Number of &file allocation tables:", 2, 0, byte.MaxValue));
+ grp.Options.Add(new CustomOptionNumber("MaximumRootDirectoryEntryCount", "Maximum number of &root directory entries:", 0, 0, short.MaxValue));
+ grp.Options.Add(new CustomOptionChoice("MediaDescriptor", "Media &descriptor:", true,
+ new CustomOptionFieldChoice("Unknown", FATMediaDescriptor.Unknown),
+ new CustomOptionFieldChoice("3.5\" double-sided, 80 tracks per side, 18 or 36 sectors per track (1.44MB or 2.88MB)", FATMediaDescriptor.MediaDescriptor0),
+ new CustomOptionFieldChoice("5.25\" double-sided, 80 tracks per side, 15 sectors per track (1.2MB)", FATMediaDescriptor.MediaDescriptor0),
+ new CustomOptionFieldChoice("Fixed disk (i.e., a hard disk)", FATMediaDescriptor.FixedDisk),
+ new CustomOptionFieldChoice("3.5\" double-sided, 80 tracks per side, 9 sectors per track (720K)", FATMediaDescriptor.MediaDescriptor2),
+ new CustomOptionFieldChoice("5.25\" double-sided, 80 tracks per side, 15 sectors per track (1.2MB)", FATMediaDescriptor.MediaDescriptor2),
+ new CustomOptionFieldChoice("5.25\" single-sided, 80 tracks per side, 8 sectors per track (320K)", FATMediaDescriptor.MediaDescriptor3),
+ new CustomOptionFieldChoice("3.5\" double-sided, 80 tracks per side, 8 sectors per track (640K)", FATMediaDescriptor.MediaDescriptor4),
+ new CustomOptionFieldChoice("5.25\" single-sided, 40 tracks per side, 9 sectors per track (180K)", FATMediaDescriptor.MediaDescriptor5),
+ new CustomOptionFieldChoice("5.25\" or 8\" double-sided, 40 tracks per side, 9 sectors per track (360K)", FATMediaDescriptor.MediaDescriptor6),
+ new CustomOptionFieldChoice("5.25\" or 8\" single-sided, 40 tracks per side, 8 sectors per track (160K)", FATMediaDescriptor.MediaDescriptor7),
+ new CustomOptionFieldChoice("5.25\" double-sided, 40 tracks per side, 8 sectors per track (320K)", FATMediaDescriptor.MediaDescriptor8)
+ ));
+
+ grp.Options.Add(new CustomOptionNumber("SectorsPerFAT16", "Sectors per allocation table:", 0));
+ grp.Options.Add(new CustomOptionNumber("SectorsPerTrack", "Sectors per track:", 0));
+ grp.Options.Add(new CustomOptionNumber("NumberOfHeads", "Number of heads:", 0));
+ grp.Options.Add(new CustomOptionNumber("HiddenSectorCount", "Number of &hidden sectors:", 0));
+ grp.Options.Add(new CustomOptionNumber("TotalSectors", "Number of &total sectors:", 0));
+ _dfr.ExportOptions.Add(grp);
+ }
+ #endregion
+ #region Extended BIOS parameter block
+ {
+ CustomOptionGroup grp = new CustomOptionGroup("ExtendedBiosParameterBlock", "Extended BIOS parameter block");
+ grp.Options.Add(new CustomOptionNumber("PhysicalDriveNumber", "Physical drive &number:", 0));
+ grp.Options.Add(new CustomOptionMultipleChoice("CheckDiskFlags", "CHKDSK &flags:", new CustomOptionFieldChoice("Dirty", FATCheckDiskFlags.Dirty), new CustomOptionFieldChoice("Error", FATCheckDiskFlags.Error)));
+ grp.Options.Add(new CustomOptionNumber("NumberOfHeads", "Number of heads:", 0));
+ grp.Options.Add(new CustomOptionNumber("HiddenSectorCount", "Number of &hidden sectors:", 0));
+ grp.Options.Add(new CustomOptionNumber("TotalSectors", "Number of &total sectors:", 0));
+ #region Extended Boot Signature
+ {
+ CustomOptionGroup grp1 = new CustomOptionGroup("ExtendedBootSignature", "Extended Boot Signature");
+ grp1.Options.Add(new CustomOptionBoolean("Enabled", "Include extended boot signature", true));
+ grp1.Options.Add(new CustomOptionNumber("VolumeSerialNumber", "Volume &serial number:", 0));
+ grp1.Options.Add(new CustomOptionText("PartitionVolumeLabel", "Partition &volume label:", String.Empty));
+ grp1.Options.Add(new CustomOptionText("FileSystemType", "File system &type:", String.Empty));
+ grp.Options.Add(grp1);
+ }
+ #endregion
+ _dfr.ExportOptions.Add(grp);
+ }
+ #endregion
+ }
+ return _dfr;
+ }
- protected override void LoadInternal(ref ObjectModel objectModel)
+ protected override void LoadInternal(ref ObjectModel objectModel)
{
FileSystemObjectModel fsom = (objectModel as FileSystemObjectModel);
IO.Reader br = base.Accessor.Reader;
@@ -183,12 +183,12 @@ namespace UniversalEditor.DataFormats.FileSystem.FAT
// DOS 4.0 and higher, OS/2 1.2 and higher as well as the Windows NT family recognize both
// signatures accordingly.)
byte extendedBootSignature = br.ReadByte();
- mvarExtendedBiosParameterBlock.ExtendedBootSignature.Enabled = false;
+ mvarExtendedBiosParameterBlock.ExtendedBootSignature.Enabled = false;
if (extendedBootSignature == 0x29 || extendedBootSignature == 0x28)
{
- mvarExtendedBiosParameterBlock.ExtendedBootSignature.Enabled = true;
- mvarExtendedBiosParameterBlock.ExtendedBootSignature.HasPartitonLabelAndFSType = false;
+ mvarExtendedBiosParameterBlock.ExtendedBootSignature.Enabled = true;
+ mvarExtendedBiosParameterBlock.ExtendedBootSignature.HasPartitonLabelAndFSType = false;
// Typically the serial number "xxxx-xxxx" is created by a 16-bit addition of both DX values
// returned by INT 21h/AH=2Ah (get system date) and INT 21h/AH=2Ch (get system time) for the
@@ -196,14 +196,14 @@ namespace UniversalEditor.DataFormats.FileSystem.FAT
// number. Alternatively, some DR-DOS disk utilities provide a /# option to generate a
// human-readable time stamp "mmdd-hhmm" build from BCD-encoded 8-bit values for the month, day,
// hour and minute instead of a serial number.
- mvarExtendedBiosParameterBlock.ExtendedBootSignature.VolumeSerialNumber = br.ReadInt32();
+ mvarExtendedBiosParameterBlock.ExtendedBootSignature.VolumeSerialNumber = br.ReadInt32();
}
if (extendedBootSignature == 0x29)
- {
- mvarExtendedBiosParameterBlock.ExtendedBootSignature.HasPartitonLabelAndFSType = true;
+ {
+ mvarExtendedBiosParameterBlock.ExtendedBootSignature.HasPartitonLabelAndFSType = true;
mvarExtendedBiosParameterBlock.ExtendedBootSignature.PartitionVolumeLabel = br.ReadFixedLengthString(11);
- mvarExtendedBiosParameterBlock.ExtendedBootSignature.FileSystemType = br.ReadFixedLengthString(8);
+ mvarExtendedBiosParameterBlock.ExtendedBootSignature.FileSystemType = br.ReadFixedLengthString(8);
}
}
#endregion
@@ -593,513 +593,513 @@ namespace UniversalEditor.DataFormats.FileSystem.FAT
#endregion
}
- protected override void SaveInternal(ObjectModel objectModel)
- {
- IO.Writer bw = base.Accessor.Writer;
- bw.WriteBytes(mvarJumpInstruction);
- bw.WriteFixedLengthString(mvarOEMName, 8);
+ protected override void SaveInternal(ObjectModel objectModel)
+ {
+ IO.Writer bw = base.Accessor.Writer;
+ bw.WriteBytes(mvarJumpInstruction);
+ bw.WriteFixedLengthString(mvarOEMName, 8);
- #region Bios Parameter Block
- {
- bw.WriteInt16(mvarBiosParameterBlock.BytesPerSector);
- bw.WriteByte(mvarBiosParameterBlock.SectorsPerCluster);
- bw.WriteInt16(mvarBiosParameterBlock.ReservedSectorCount);
- bw.WriteByte(mvarBiosParameterBlock.FileAllocationTableCount);
- bw.WriteInt16(mvarBiosParameterBlock.MaximumRootDirectoryEntryCount);
- if (mvarBiosParameterBlock.TotalSectors <= ushort.MaxValue)
- {
- bw.WriteUInt16((ushort)mvarBiosParameterBlock.TotalSectors);
- }
- else
- {
- bw.WriteUInt16((ushort)0);
- }
- bw.WriteByte((byte)mvarBiosParameterBlock.MediaDescriptor);
- bw.WriteInt16(mvarBiosParameterBlock.SectorsPerFAT16);
+ #region Bios Parameter Block
+ {
+ bw.WriteInt16(mvarBiosParameterBlock.BytesPerSector);
+ bw.WriteByte(mvarBiosParameterBlock.SectorsPerCluster);
+ bw.WriteInt16(mvarBiosParameterBlock.ReservedSectorCount);
+ bw.WriteByte(mvarBiosParameterBlock.FileAllocationTableCount);
+ bw.WriteInt16(mvarBiosParameterBlock.MaximumRootDirectoryEntryCount);
+ if (mvarBiosParameterBlock.TotalSectors <= ushort.MaxValue)
+ {
+ bw.WriteUInt16((ushort)mvarBiosParameterBlock.TotalSectors);
+ }
+ else
+ {
+ bw.WriteUInt16((ushort)0);
+ }
+ bw.WriteByte((byte)mvarBiosParameterBlock.MediaDescriptor);
+ bw.WriteInt16(mvarBiosParameterBlock.SectorsPerFAT16);
- // The following extensions were documented since DOS 3.0, however, they were already supported by
- // some issues of DOS 2.13. MS-DOS 3.10 still supported the DOS 2.0 format, but could use the DOS
- // 3.0 format as well.
- bw.WriteInt16(mvarBiosParameterBlock.SectorsPerTrack);
- bw.WriteInt16(mvarBiosParameterBlock.NumberOfHeads);
- bw.WriteInt32(mvarBiosParameterBlock.HiddenSectorCount);
+ // The following extensions were documented since DOS 3.0, however, they were already supported by
+ // some issues of DOS 2.13. MS-DOS 3.10 still supported the DOS 2.0 format, but could use the DOS
+ // 3.0 format as well.
+ bw.WriteInt16(mvarBiosParameterBlock.SectorsPerTrack);
+ bw.WriteInt16(mvarBiosParameterBlock.NumberOfHeads);
+ bw.WriteInt32(mvarBiosParameterBlock.HiddenSectorCount);
- // Total logical sectors including hidden sectors. This DOS 3.2 entry is
- // incompatible with a similar entry at offset 0x020 in BPBs since DOS 3.31.
- // It must not be used if the logical sectors entry at offset 0x013 is zero.
- if (mvarBiosParameterBlock.TotalSectors <= ushort.MaxValue)
- {
- bw.WriteUInt16((ushort)mvarBiosParameterBlock.TotalSectors);
- }
- else
- {
- bw.WriteUInt16((ushort)0);
- }
- if (mvarBiosParameterBlock.TotalSectors > ushort.MaxValue)
- {
- bw.WriteInt32(mvarBiosParameterBlock.TotalSectors);
- }
- else
- {
- bw.WriteInt32((int)0);
- }
- }
- #endregion
+ // Total logical sectors including hidden sectors. This DOS 3.2 entry is
+ // incompatible with a similar entry at offset 0x020 in BPBs since DOS 3.31.
+ // It must not be used if the logical sectors entry at offset 0x013 is zero.
+ if (mvarBiosParameterBlock.TotalSectors <= ushort.MaxValue)
+ {
+ bw.WriteUInt16((ushort)mvarBiosParameterBlock.TotalSectors);
+ }
+ else
+ {
+ bw.WriteUInt16((ushort)0);
+ }
+ if (mvarBiosParameterBlock.TotalSectors > ushort.MaxValue)
+ {
+ bw.WriteInt32(mvarBiosParameterBlock.TotalSectors);
+ }
+ else
+ {
+ bw.WriteInt32((int)0);
+ }
+ }
+ #endregion
- long totalFileSize = (mvarBiosParameterBlock.TotalSectors * mvarBiosParameterBlock.BytesPerSector);
+ long totalFileSize = (mvarBiosParameterBlock.TotalSectors * mvarBiosParameterBlock.BytesPerSector);
- /*
- * A simple formula translates a volume's given cluster number CN to a logical sector number LSN:
- *
- * Determine (once) SSA=RSC+FN×SF+ceil((32×RDE)/SS), where the reserved sector count RSC is stored at
- * offset 0x00E, the FAT number FN at offset 0x010, the sectors per FAT SF at offset 0x016 (FAT12/FAT16)
- * or 0x024 (FAT32), the root directory entries RDE at offset 0x011, the sector size SS at offset 0x00B,
- * and ceil(x) rounds up to a whole number.
- *
- * Determine LSN=SSA+(CN-2)×SC, where the sectors per cluster SC are stored at offset 0x00D.
- *
- * On unpartitioned media the volume's number of hidden sectors is zero and therefore LSN and LBA
- * addresses become the same for as long as a volume's logical sector size is identical to the
- * underlying medium's physical sector size. Under these conditions, it is also simple to translate
- * between CHS addresses and LSNs as well:
- *
- * LSN=SPT×(HN+(NOS×TN))+SN-1, where the sectors per track SPT are stored at offset 0x018, and the
- * number of sides NOS at offset 0x01A. Track number TN, head number HN, and sector number SN
- * correspond to Cylinder-head-sector: the formula gives the known CHS to LBA translation.
- */
+ /*
+ * A simple formula translates a volume's given cluster number CN to a logical sector number LSN:
+ *
+ * Determine (once) SSA=RSC+FN×SF+ceil((32×RDE)/SS), where the reserved sector count RSC is stored at
+ * offset 0x00E, the FAT number FN at offset 0x010, the sectors per FAT SF at offset 0x016 (FAT12/FAT16)
+ * or 0x024 (FAT32), the root directory entries RDE at offset 0x011, the sector size SS at offset 0x00B,
+ * and ceil(x) rounds up to a whole number.
+ *
+ * Determine LSN=SSA+(CN-2)×SC, where the sectors per cluster SC are stored at offset 0x00D.
+ *
+ * On unpartitioned media the volume's number of hidden sectors is zero and therefore LSN and LBA
+ * addresses become the same for as long as a volume's logical sector size is identical to the
+ * underlying medium's physical sector size. Under these conditions, it is also simple to translate
+ * between CHS addresses and LSNs as well:
+ *
+ * LSN=SPT×(HN+(NOS×TN))+SN-1, where the sectors per track SPT are stored at offset 0x018, and the
+ * number of sides NOS at offset 0x01A. Track number TN, head number HN, and sector number SN
+ * correspond to Cylinder-head-sector: the formula gives the known CHS to LBA translation.
+ */
- #region Extended BIOS Parameter Block
- {
- bw.WriteByte(mvarExtendedBiosParameterBlock.PhysicalDriveNumber);
+ #region Extended BIOS Parameter Block
+ {
+ bw.WriteByte(mvarExtendedBiosParameterBlock.PhysicalDriveNumber);
- byte reserved1 = (byte)mvarExtendedBiosParameterBlock.CheckDiskFlags;
- bw.WriteByte(reserved1);
+ byte reserved1 = (byte)mvarExtendedBiosParameterBlock.CheckDiskFlags;
+ bw.WriteByte(reserved1);
- // Extended boot signature. (Should be 0x29 to indicate that an EBPB with the following 3 entries
- // exists (since OS/2 1.2 and DOS 4.0). Can be 0x28 on some OS/2 1.0-1.1 and PC DOS 3.4 disks
- // indicating an earlier form of the EBPB format with only the serial number following. MS-DOS/PC
- // DOS 4.0 and higher, OS/2 1.2 and higher as well as the Windows NT family recognize both
- // signatures accordingly.)
- byte extendedBootSignature = 0;
- if (mvarExtendedBiosParameterBlock.ExtendedBootSignature.Enabled)
- {
- if (mvarExtendedBiosParameterBlock.ExtendedBootSignature.HasPartitonLabelAndFSType)
- {
- extendedBootSignature = 0x29;
- }
- else
- {
- extendedBootSignature = 0x28;
- }
- }
- bw.WriteByte(extendedBootSignature);
+ // Extended boot signature. (Should be 0x29 to indicate that an EBPB with the following 3 entries
+ // exists (since OS/2 1.2 and DOS 4.0). Can be 0x28 on some OS/2 1.0-1.1 and PC DOS 3.4 disks
+ // indicating an earlier form of the EBPB format with only the serial number following. MS-DOS/PC
+ // DOS 4.0 and higher, OS/2 1.2 and higher as well as the Windows NT family recognize both
+ // signatures accordingly.)
+ byte extendedBootSignature = 0;
+ if (mvarExtendedBiosParameterBlock.ExtendedBootSignature.Enabled)
+ {
+ if (mvarExtendedBiosParameterBlock.ExtendedBootSignature.HasPartitonLabelAndFSType)
+ {
+ extendedBootSignature = 0x29;
+ }
+ else
+ {
+ extendedBootSignature = 0x28;
+ }
+ }
+ bw.WriteByte(extendedBootSignature);
- if (extendedBootSignature == 0x29 || extendedBootSignature == 0x28)
- {
- // Typically the serial number "xxxx-xxxx" is created by a 16-bit addition of both DX values
- // returned by INT 21h/AH=2Ah (get system date) and INT 21h/AH=2Ch (get system time) for the
- // high word and another 16-bit addition of both CX values for the low word of the serial
- // number. Alternatively, some DR-DOS disk utilities provide a /# option to generate a
- // human-readable time stamp "mmdd-hhmm" build from BCD-encoded 8-bit values for the month, day,
- // hour and minute instead of a serial number.
- bw.WriteInt32(mvarExtendedBiosParameterBlock.ExtendedBootSignature.VolumeSerialNumber);
- }
- if (extendedBootSignature == 0x29)
- {
- bw.WriteFixedLengthString(mvarExtendedBiosParameterBlock.ExtendedBootSignature.PartitionVolumeLabel, 11);
- bw.WriteFixedLengthString(mvarExtendedBiosParameterBlock.ExtendedBootSignature.FileSystemType, 8);
- }
- }
- #endregion
+ if (extendedBootSignature == 0x29 || extendedBootSignature == 0x28)
+ {
+ // Typically the serial number "xxxx-xxxx" is created by a 16-bit addition of both DX values
+ // returned by INT 21h/AH=2Ah (get system date) and INT 21h/AH=2Ch (get system time) for the
+ // high word and another 16-bit addition of both CX values for the low word of the serial
+ // number. Alternatively, some DR-DOS disk utilities provide a /# option to generate a
+ // human-readable time stamp "mmdd-hhmm" build from BCD-encoded 8-bit values for the month, day,
+ // hour and minute instead of a serial number.
+ bw.WriteInt32(mvarExtendedBiosParameterBlock.ExtendedBootSignature.VolumeSerialNumber);
+ }
+ if (extendedBootSignature == 0x29)
+ {
+ bw.WriteFixedLengthString(mvarExtendedBiosParameterBlock.ExtendedBootSignature.PartitionVolumeLabel, 11);
+ bw.WriteFixedLengthString(mvarExtendedBiosParameterBlock.ExtendedBootSignature.FileSystemType, 8);
+ }
+ }
+ #endregion
- // no clue why this is 448 bytes, but it just is...
- byte[] bootstrapProgram = new byte[448];
- bw.WriteBytes(bootstrapProgram);
+ // no clue why this is 448 bytes, but it just is...
+ byte[] bootstrapProgram = new byte[448];
+ bw.WriteBytes(bootstrapProgram);
- // The number of blocks that appear before the root directory is given by:
- int numBlocksBeforeRootDir = (mvarBiosParameterBlock.FileAllocationTableCount * mvarBiosParameterBlock.SectorsPerFAT16) + 1;
- int numBytesBeforeRootDir = mvarBiosParameterBlock.BytesPerSector * numBlocksBeforeRootDir;
+ // The number of blocks that appear before the root directory is given by:
+ int numBlocksBeforeRootDir = (mvarBiosParameterBlock.FileAllocationTableCount * mvarBiosParameterBlock.SectorsPerFAT16) + 1;
+ int numBytesBeforeRootDir = mvarBiosParameterBlock.BytesPerSector * numBlocksBeforeRootDir;
- /*
- br.Accessor.Position = numBytesBeforeRootDir;
+ /*
+ br.Accessor.Position = numBytesBeforeRootDir;
- List fileNames = new List();
- List fileOffsets = new List();
- List fileSizes = new List();
+ List fileNames = new List();
+ List fileOffsets = new List();
+ List fileSizes = new List();
- string LFN_FileName = String.Empty;
+ string LFN_FileName = String.Empty;
- #region File name table
- {
- while (!br.EndOfStream)
- {
- byte[] fileNameBytes = br.ReadBytes(8);
- if (fileNameBytes[0] == 0x00)
- {
- // Entry is available and no subsequent entry is in use. Also serves as an
- // end marker when DOS scans a directory table. (Since MS-DOS/PC DOS 1.0,
- // but not in 86-DOS).
- }
- else if (fileNameBytes[0] == 0x05)
- {
- // Initial character is actually 0xE5. (since DOS 3.0)
- //
- // Under DR DOS 6.0 and higher, including PalmDOS, Novell DOS and OpenDOS,
- // 0x05 is also used for pending delete files under DELWATCH. Once they are
- // removed from the deletion tracking queue, the first character of an erased
- // file is replaced by 0xE5.
- }
- else if (fileNameBytes[0] == 0x2E)
- {
- // 'Dot' entry; either "." or ".." (since DOS 2.0)
- }
- else if (fileNameBytes[0] == 0xE5)
- {
- // Entry has been previously erased and is available. File undelete
- // utilities must replace this character with a regular character as part of
- // the undeletion process. See also: 0x05.
- //
- // (The reason, why 0xE5 was chosen for this purpose in 86-DOS is down to the
- // fact, that 8-inch CP/M floppies came pre-formatted with this value filled
- // and so could be used to store files out-of-the box.)
+ #region File name table
+ {
+ while (!br.EndOfStream)
+ {
+ byte[] fileNameBytes = br.ReadBytes(8);
+ if (fileNameBytes[0] == 0x00)
+ {
+ // Entry is available and no subsequent entry is in use. Also serves as an
+ // end marker when DOS scans a directory table. (Since MS-DOS/PC DOS 1.0,
+ // but not in 86-DOS).
+ }
+ else if (fileNameBytes[0] == 0x05)
+ {
+ // Initial character is actually 0xE5. (since DOS 3.0)
+ //
+ // Under DR DOS 6.0 and higher, including PalmDOS, Novell DOS and OpenDOS,
+ // 0x05 is also used for pending delete files under DELWATCH. Once they are
+ // removed from the deletion tracking queue, the first character of an erased
+ // file is replaced by 0xE5.
+ }
+ else if (fileNameBytes[0] == 0x2E)
+ {
+ // 'Dot' entry; either "." or ".." (since DOS 2.0)
+ }
+ else if (fileNameBytes[0] == 0xE5)
+ {
+ // Entry has been previously erased and is available. File undelete
+ // utilities must replace this character with a regular character as part of
+ // the undeletion process. See also: 0x05.
+ //
+ // (The reason, why 0xE5 was chosen for this purpose in 86-DOS is down to the
+ // fact, that 8-inch CP/M floppies came pre-formatted with this value filled
+ // and so could be used to store files out-of-the box.)
- }
+ }
- string fileName = System.Text.Encoding.ASCII.GetString(fileNameBytes).Trim();
- if (fileName[0] == '\0') break;
+ string fileName = System.Text.Encoding.ASCII.GetString(fileNameBytes).Trim();
+ if (fileName[0] == '\0') break;
- string fileExt = br.ReadFixedLengthString(3).Trim();
+ string fileExt = br.ReadFixedLengthString(3).Trim();
- byte implementationSpecificByte1 = br.ReadByte();
+ byte implementationSpecificByte1 = br.ReadByte();
- // CP/M-86 and DOS Plus store user attributes F1'—F4' here. (DOS Plus 1.2 with BDOS 4.1 supports
- // passwords only on CP/M media, not on FAT12 or FAT16 media. While DOS Plus 2.1 supported
- // logical sectored FATs with a partition type 0xF2, FAT16B and FAT32 volumes were not supported
- // by these operation systems. Even if a partition would have been converted to FAT16B it would
- // still not be larger than 32 MB. Therefore, this usage is not conflictive with FAT32.IFS,
- // FAT16+ or FAT32+ as they can never occur on the same type of volume.):
- FATFileAttributes fileAttributes = (FATFileAttributes)implementationSpecificByte1;
+ // CP/M-86 and DOS Plus store user attributes F1'—F4' here. (DOS Plus 1.2 with BDOS 4.1 supports
+ // passwords only on CP/M media, not on FAT12 or FAT16 media. While DOS Plus 2.1 supported
+ // logical sectored FATs with a partition type 0xF2, FAT16B and FAT32 volumes were not supported
+ // by these operation systems. Even if a partition would have been converted to FAT16B it would
+ // still not be larger than 32 MB. Therefore, this usage is not conflictive with FAT32.IFS,
+ // FAT16+ or FAT32+ as they can never occur on the same type of volume.):
+ FATFileAttributes fileAttributes = (FATFileAttributes)implementationSpecificByte1;
- if ((byte)fileAttributes == 15)
- {
- br.Accessor.Position -= 12;
+ if ((byte)fileAttributes == 15)
+ {
+ br.Accessor.Position -= 12;
- byte LFN_SequenceNumber = br.ReadByte();
- byte[] LFN_UnicodeNamePart1 = br.ReadBytes(10);
- byte LFN_Attributes = br.ReadByte();
- byte LFN_Type = br.ReadByte();
- byte LFN_Checksum = br.ReadByte();
- byte[] LFN_UnicodeNamePart2 = br.ReadBytes(12);
- short LFN_FirstCluster = br.ReadInt16();
- byte[] LFN_UnicodeNamePart3 = br.ReadBytes(4);
- byte[] LFN_UnicodeNameBytes = new byte[26];
+ byte LFN_SequenceNumber = br.ReadByte();
+ byte[] LFN_UnicodeNamePart1 = br.ReadBytes(10);
+ byte LFN_Attributes = br.ReadByte();
+ byte LFN_Type = br.ReadByte();
+ byte LFN_Checksum = br.ReadByte();
+ byte[] LFN_UnicodeNamePart2 = br.ReadBytes(12);
+ short LFN_FirstCluster = br.ReadInt16();
+ byte[] LFN_UnicodeNamePart3 = br.ReadBytes(4);
+ byte[] LFN_UnicodeNameBytes = new byte[26];
- Array.Copy(LFN_UnicodeNamePart1, 0, LFN_UnicodeNameBytes, 0, LFN_UnicodeNamePart1.Length);
- Array.Copy(LFN_UnicodeNamePart2, 0, LFN_UnicodeNameBytes, LFN_UnicodeNamePart1.Length, LFN_UnicodeNamePart2.Length);
- Array.Copy(LFN_UnicodeNamePart3, 0, LFN_UnicodeNameBytes, LFN_UnicodeNamePart1.Length + LFN_UnicodeNamePart2.Length, LFN_UnicodeNamePart3.Length);
+ Array.Copy(LFN_UnicodeNamePart1, 0, LFN_UnicodeNameBytes, 0, LFN_UnicodeNamePart1.Length);
+ Array.Copy(LFN_UnicodeNamePart2, 0, LFN_UnicodeNameBytes, LFN_UnicodeNamePart1.Length, LFN_UnicodeNamePart2.Length);
+ Array.Copy(LFN_UnicodeNamePart3, 0, LFN_UnicodeNameBytes, LFN_UnicodeNamePart1.Length + LFN_UnicodeNamePart2.Length, LFN_UnicodeNamePart3.Length);
- string LFN_UnicodeName = System.Text.Encoding.Unicode.GetString(LFN_UnicodeNameBytes);
- LFN_FileName = LFN_UnicodeName + LFN_FileName;
+ string LFN_UnicodeName = System.Text.Encoding.Unicode.GetString(LFN_UnicodeNameBytes);
+ LFN_FileName = LFN_UnicodeName + LFN_FileName;
- if ((LFN_SequenceNumber & 0x40) == 0x40)
- {
- // This is last LFN entry
- }
- else if (LFN_SequenceNumber == 1)
- {
- // This is the first LFN entry, stop reading now.
- }
- continue;
- }
- if (LFN_FileName != String.Empty)
- {
- LFN_FileName = LFN_FileName.TrimNull();
- fileNames.Add(LFN_FileName);
- LFN_FileName = String.Empty;
- }
- else
- {
- fileNames.Add(fileName + "." + fileExt);
- }
+ if ((LFN_SequenceNumber & 0x40) == 0x40)
+ {
+ // This is last LFN entry
+ }
+ else if (LFN_SequenceNumber == 1)
+ {
+ // This is the first LFN entry, stop reading now.
+ }
+ continue;
+ }
+ if (LFN_FileName != String.Empty)
+ {
+ LFN_FileName = LFN_FileName.TrimNull();
+ fileNames.Add(LFN_FileName);
+ LFN_FileName = String.Empty;
+ }
+ else
+ {
+ fileNames.Add(fileName + "." + fileExt);
+ }
- // - *
- // For a deleted file, the original first character of the filename. For the same feature in
- // various other operating systems, see offset 0x0D if enabled in MSX boot sectors at sector
- // offset 0x026. MSX-DOS supported FAT12 volumes only, but third-party extensions for FAT16
- // volumes exist. Therefore, this usage is not conflictive with FAT32.IFS and FAT32+ below. It
- // does not conflict with the usage for user attributes under CP/M-86 and DOS Plus as well,
- // since they are no longer important for deleted files.
- char deletedFileFirstCharImplementation1 = (char)implementationSpecificByte1;
+ // - *
+ // For a deleted file, the original first character of the filename. For the same feature in
+ // various other operating systems, see offset 0x0D if enabled in MSX boot sectors at sector
+ // offset 0x026. MSX-DOS supported FAT12 volumes only, but third-party extensions for FAT16
+ // volumes exist. Therefore, this usage is not conflictive with FAT32.IFS and FAT32+ below. It
+ // does not conflict with the usage for user attributes under CP/M-86 and DOS Plus as well,
+ // since they are no longer important for deleted files.
+ char deletedFileFirstCharImplementation1 = (char)implementationSpecificByte1;
- // Windows NT and later versions uses bits 3 and 4 to encode case information (see below);
- // otherwise 0.
+ // Windows NT and later versions uses bits 3 and 4 to encode case information (see below);
+ // otherwise 0.
- // DR-DOS 7.0x reserved bits other than 3 and 4 for internal purposes since 1997. The value
- // should be set to 0 by formating tools and must not be changed by disk tools.
+ // DR-DOS 7.0x reserved bits other than 3 and 4 for internal purposes since 1997. The value
+ // should be set to 0 by formating tools and must not be changed by disk tools.
- // On FAT32 volumes under OS/2 and eComStation the third-party FAT32.IFS driver utilizes this
- // entry as a mark byte to indicate the presence of extra " EA. SF" files holding extended
- // attributes with parameter /EAS. Version 0.70 to 0.96 used the magic values 0x00 (no EAs),
- // 0xEA (normal EAs) and 0xEC (critical EAs), whereas version 0.97 and higher since 2003-09 use
- // 0x00, 0x40 (normal EAs) and 0x80 (critical EAs) as bitflags for compatibility with Windows NT.
+ // On FAT32 volumes under OS/2 and eComStation the third-party FAT32.IFS driver utilizes this
+ // entry as a mark byte to indicate the presence of extra " EA. SF" files holding extended
+ // attributes with parameter /EAS. Version 0.70 to 0.96 used the magic values 0x00 (no EAs),
+ // 0xEA (normal EAs) and 0xEC (critical EAs), whereas version 0.97 and higher since 2003-09 use
+ // 0x00, 0x40 (normal EAs) and 0x80 (critical EAs) as bitflags for compatibility with Windows NT.
- // Bits other than 3 and 4 are utilized by FAT+, a proposal how to store files larger than 4 GB
- // on FAT32 (and FAT16B) volumes, currently implemented in some versions of EDR-DOS. The value
- // should be set to 0 by formating tools and must not be changed by disk tools. If some of these
- // bits are set, non-enabled implementations should refuse to open the file. To avoid problems
- // with non-aware operating systems, partitions containing files larger than 4 GB could use
- // non-standard partition IDs to hide the partition from these operating systems. Under DR-DOS,
- // partition IDs of secured partition types can be utilized for this purpose. Files larger than
- // 4 GB should have the Hidden, Read-only and System attributes set to hide them from normal
- // directory searches on non-aware operating systems, similar to password protected files under
- // DR-DOS. While FAT+ implementations do not rely on these attributes being set, for FAT+ large
- // files they may ignore these attributes in file searches and when opening large files for
- // modification and instead treat the System attribute as an alternative combined
- // Read-only+Hidden attribute in this scenario.
+ // Bits other than 3 and 4 are utilized by FAT+, a proposal how to store files larger than 4 GB
+ // on FAT32 (and FAT16B) volumes, currently implemented in some versions of EDR-DOS. The value
+ // should be set to 0 by formating tools and must not be changed by disk tools. If some of these
+ // bits are set, non-enabled implementations should refuse to open the file. To avoid problems
+ // with non-aware operating systems, partitions containing files larger than 4 GB could use
+ // non-standard partition IDs to hide the partition from these operating systems. Under DR-DOS,
+ // partition IDs of secured partition types can be utilized for this purpose. Files larger than
+ // 4 GB should have the Hidden, Read-only and System attributes set to hide them from normal
+ // directory searches on non-aware operating systems, similar to password protected files under
+ // DR-DOS. While FAT+ implementations do not rely on these attributes being set, for FAT+ large
+ // files they may ignore these attributes in file searches and when opening large files for
+ // modification and instead treat the System attribute as an alternative combined
+ // Read-only+Hidden attribute in this scenario.
- // FAT32.IFS is critically conflictive with FAT32+ revision 2.
+ // FAT32.IFS is critically conflictive with FAT32+ revision 2.
- byte implementationSpecificByte2 = br.ReadByte();
- // First character of a deleted file under Novell DOS, OpenDOS and DR-DOS 7.02 and higher. A
- // value of 0xE5 (229), as set by DELPURGE, will prohibit undeletion by UNDELETE, a value of
- // 0x00 will allow conventional undeletion asking the user for the missing first filename
- // character. S/DOS 1 and PTS-DOS 6.51 and higher also support this feature if enabled with
- // SAVENAME=ON in CONFIG.SYS. For the same feature in MSX-DOS, see offset 0x0C.
- char deletedFileFirstCharImplementation2 = (char)implementationSpecificByte2;
+ byte implementationSpecificByte2 = br.ReadByte();
+ // First character of a deleted file under Novell DOS, OpenDOS and DR-DOS 7.02 and higher. A
+ // value of 0xE5 (229), as set by DELPURGE, will prohibit undeletion by UNDELETE, a value of
+ // 0x00 will allow conventional undeletion asking the user for the missing first filename
+ // character. S/DOS 1 and PTS-DOS 6.51 and higher also support this feature if enabled with
+ // SAVENAME=ON in CONFIG.SYS. For the same feature in MSX-DOS, see offset 0x0C.
+ char deletedFileFirstCharImplementation2 = (char)implementationSpecificByte2;
- // Create time, fine resolution: 10 ms units, values from 0 to 199 (since DOS 7.0 with VFAT).
- byte createTime = implementationSpecificByte2;
+ // Create time, fine resolution: 10 ms units, values from 0 to 199 (since DOS 7.0 with VFAT).
+ byte createTime = implementationSpecificByte2;
- // Double usage for create time ms and file char is not conflictive, since the creation time is
- // no longer important for deleted files.
+ // Double usage for create time ms and file char is not conflictive, since the creation time is
+ // no longer important for deleted files.
- // Under DR DOS 3.31 and higher including PalmDOS, Novell DOS and OpenDOS as well
- // as under Concurrent DOS, Multiuser DOS, System Manager, and REAL/32 and
- // possibly also under FlexOS, 4680 OS, 4690 OS any non-zero value indicates the
- // password hash of a protected file, directory or volume label. The hash is
- // calculated from the first eight characters of a password. If the file
- // operation to be carried out requires a password as per the access rights
- // bitmap stored at offset 0x14, the system tries to match the hash against the
- // hash code of the currently set global password (by PASSWORD /G) or, if this
- // fails, tries to extract a semicolon-appended password from the filespec
- // passed to the operating system and checks it against the hash code stored
- // here. A set password will be preserved even if a file is deleted and later
- // undeleted.
- short implementationSpecific3 = br.ReadInt16();
+ // Under DR DOS 3.31 and higher including PalmDOS, Novell DOS and OpenDOS as well
+ // as under Concurrent DOS, Multiuser DOS, System Manager, and REAL/32 and
+ // possibly also under FlexOS, 4680 OS, 4690 OS any non-zero value indicates the
+ // password hash of a protected file, directory or volume label. The hash is
+ // calculated from the first eight characters of a password. If the file
+ // operation to be carried out requires a password as per the access rights
+ // bitmap stored at offset 0x14, the system tries to match the hash against the
+ // hash code of the currently set global password (by PASSWORD /G) or, if this
+ // fails, tries to extract a semicolon-appended password from the filespec
+ // passed to the operating system and checks it against the hash code stored
+ // here. A set password will be preserved even if a file is deleted and later
+ // undeleted.
+ short implementationSpecific3 = br.ReadInt16();
- // Create time (since DOS 7.0 with VFAT). The hour, minute and second are encoded
- // according to the following bitmap:
- // Bits Description
- // -------- ------------------
- // 15-11 Hours (0-23)
- // 10-5 Minutes (0-59)
- // 4-0 Seconds/2 (0-29)
- //
- // The seconds is recorded only to a 2 second resolution. Finer resolution for
- // file creation is found at offset 0x0D.
- //
- // If bits 15-11 > 23 or bits 10-5 > 59 or bits 4-0 > 29 here, or when bits 12-0
- // at offset 0x14 hold an access bitmap and this is not a FAT32 volume or a
- // volume using OS/2 Extended Attributes, then this entry actually holds a
- // password hash, otherwise it can be assumed to be a file creation time.
+ // Create time (since DOS 7.0 with VFAT). The hour, minute and second are encoded
+ // according to the following bitmap:
+ // Bits Description
+ // -------- ------------------
+ // 15-11 Hours (0-23)
+ // 10-5 Minutes (0-59)
+ // 4-0 Seconds/2 (0-29)
+ //
+ // The seconds is recorded only to a 2 second resolution. Finer resolution for
+ // file creation is found at offset 0x0D.
+ //
+ // If bits 15-11 > 23 or bits 10-5 > 59 or bits 4-0 > 29 here, or when bits 12-0
+ // at offset 0x14 hold an access bitmap and this is not a FAT32 volume or a
+ // volume using OS/2 Extended Attributes, then this entry actually holds a
+ // password hash, otherwise it can be assumed to be a file creation time.
- // FlexOS, 4680 OS and 4690 OS store a record size in the word at entry 0x10.
- // This is mainly used for their special database-like file types random file,
- // direct file, keyed file, and sequential file. If the record size is set to 0
- // (default) or 1, the operating systems assume a record granularity of 1 byte
- // for the file, for which it will not perform record boundary checks in
- // read/write operations.
- //
- // With DELWATCH 2.00 and higher under Novell DOS 7, OpenDOS 7.01 and DR-DOS
- // 7.02 and higher, this entry is used to store the last modified time stamp for
- // pending delete files and directories. Cleared when file is undeleted or
- // purged. See offset 0x0E for a format description.
- //
- // Create date (since DOS 7.0 with VFAT). The year, month and day are encoded
- // according to the following bitmap:
- // Bits Description
- // -------- ------------------
- // 15-9 Year (0 = 1980, 119 = 2099 supported under DOS/Windows, theoretical
- // up to 127 = 2107)
- // 8-5 Month (1–12)
- // 4-0 Day (1–31)
- //
- // The usage for creation date for existing files and last modified time for
- // deleted files is not conflictive because they are never used at the same time.
- // For the same reason, the usage for the record size of existing files and last
- // modified time of deleted files is not conflictive as well. Creation dates and
- // record sizes cannot be used at the same time, however, both are stored only on
- // file creation and never changed later on, thereby limiting the conflict to
- // FlexOS, 4680 OS and 4690 OS systems accessing files created under foreign
- // operating systems as well as potential display or file sorting problems on
- // systems trying to interpret a record size as creation time. To avoid the
- // conflict, the storage of creation dates should be an optional feature of
- // operating systems supporting it.
- short implementationSpecific4 = br.ReadInt16();
+ // FlexOS, 4680 OS and 4690 OS store a record size in the word at entry 0x10.
+ // This is mainly used for their special database-like file types random file,
+ // direct file, keyed file, and sequential file. If the record size is set to 0
+ // (default) or 1, the operating systems assume a record granularity of 1 byte
+ // for the file, for which it will not perform record boundary checks in
+ // read/write operations.
+ //
+ // With DELWATCH 2.00 and higher under Novell DOS 7, OpenDOS 7.01 and DR-DOS
+ // 7.02 and higher, this entry is used to store the last modified time stamp for
+ // pending delete files and directories. Cleared when file is undeleted or
+ // purged. See offset 0x0E for a format description.
+ //
+ // Create date (since DOS 7.0 with VFAT). The year, month and day are encoded
+ // according to the following bitmap:
+ // Bits Description
+ // -------- ------------------
+ // 15-9 Year (0 = 1980, 119 = 2099 supported under DOS/Windows, theoretical
+ // up to 127 = 2107)
+ // 8-5 Month (1–12)
+ // 4-0 Day (1–31)
+ //
+ // The usage for creation date for existing files and last modified time for
+ // deleted files is not conflictive because they are never used at the same time.
+ // For the same reason, the usage for the record size of existing files and last
+ // modified time of deleted files is not conflictive as well. Creation dates and
+ // record sizes cannot be used at the same time, however, both are stored only on
+ // file creation and never changed later on, thereby limiting the conflict to
+ // FlexOS, 4680 OS and 4690 OS systems accessing files created under foreign
+ // operating systems as well as potential display or file sorting problems on
+ // systems trying to interpret a record size as creation time. To avoid the
+ // conflict, the storage of creation dates should be an optional feature of
+ // operating systems supporting it.
+ short implementationSpecific4 = br.ReadInt16();
- // FlexOS, 4680 OS, 4690 OS, Multiuser DOS, System Manager, REAL/32 and DR DOS
- // 6.0 and higher with multi-user security enabled use this field to store owner
- // IDs. Offset 0x12 holds the user ID, 0x13 the group ID of a file's creator.
- //
- // In multi-user versions, system access requires a logon with account name and
- // password, and the system assigns group and user IDs to running applications
- // according to the previously set up and stored authorization info and
- // inheritance rules. For 4680 OS and 4690 OS, group ID 1 is reserved for the
- // system, group ID 2 for vendor, group ID 3 for the default user group.
- // Background applications started by users have a group ID 2 and user ID 1,
- // whereas operating system background tasks have group IDs 1 or 0 and user IDs
- // 1 or 0. IBM 4680 BASIC and applications started as primary or secondary
- // always get group ID 2 and user ID 1. When applications create files, the
- // system will store their user ID and group ID and the required permissions with
- // the file.
- //
- // With DELWATCH 2.00 and higher under Novell DOS 7, OpenDOS 7.01 and DR-DOS 7.02
- // and higher, this entry is used to store the last modified date stamp for
- // pending delete files and directories. Cleared when file is undeleted or
- // purged. See [implementationSpecific4] for a format description.
- //
- // Last access date (since DOS 7.0 if ACCDATE enabled in CONFIG.SYS for the
- // corresponding drive); see [implementationSpecific4] for a format description.
- //
- // The usage for the owner IDs of existing files and last modified date stamp for
- // deleted files is not conflictive because they are never used at the same time.
- // The usage of the last modified date stamp for deleted files and access date is
- // also not conflictive since access dates are no longer important for deleted
- // files, however, owner IDs and access dates cannot be used at the same time.
- short implementationSpecific5 = br.ReadInt16();
+ // FlexOS, 4680 OS, 4690 OS, Multiuser DOS, System Manager, REAL/32 and DR DOS
+ // 6.0 and higher with multi-user security enabled use this field to store owner
+ // IDs. Offset 0x12 holds the user ID, 0x13 the group ID of a file's creator.
+ //
+ // In multi-user versions, system access requires a logon with account name and
+ // password, and the system assigns group and user IDs to running applications
+ // according to the previously set up and stored authorization info and
+ // inheritance rules. For 4680 OS and 4690 OS, group ID 1 is reserved for the
+ // system, group ID 2 for vendor, group ID 3 for the default user group.
+ // Background applications started by users have a group ID 2 and user ID 1,
+ // whereas operating system background tasks have group IDs 1 or 0 and user IDs
+ // 1 or 0. IBM 4680 BASIC and applications started as primary or secondary
+ // always get group ID 2 and user ID 1. When applications create files, the
+ // system will store their user ID and group ID and the required permissions with
+ // the file.
+ //
+ // With DELWATCH 2.00 and higher under Novell DOS 7, OpenDOS 7.01 and DR-DOS 7.02
+ // and higher, this entry is used to store the last modified date stamp for
+ // pending delete files and directories. Cleared when file is undeleted or
+ // purged. See [implementationSpecific4] for a format description.
+ //
+ // Last access date (since DOS 7.0 if ACCDATE enabled in CONFIG.SYS for the
+ // corresponding drive); see [implementationSpecific4] for a format description.
+ //
+ // The usage for the owner IDs of existing files and last modified date stamp for
+ // deleted files is not conflictive because they are never used at the same time.
+ // The usage of the last modified date stamp for deleted files and access date is
+ // also not conflictive since access dates are no longer important for deleted
+ // files, however, owner IDs and access dates cannot be used at the same time.
+ short implementationSpecific5 = br.ReadInt16();
- // Access rights bitmap for world/group/owner read/write/execute/delete
- // protection for password protected files, directories (or volume labels) under
- // DR DOS 3.31 and higher, including PalmDOS, Novell DOS and OpenDOS, and under
- // FlexOS, 4680 OS, 4690 OS, Concurrent DOS, Multiuser DOS, System Manager, and
- // REAL/32.
- //
- // Typical values stored on a single-user system are 0x0000 (PASSWORD /N for all
- // access rights "RWED"), 0x0111 (PASSWORD /D for access rights "RW?-"), 0x0555
- // (PASSWORD /W for access rights "R-?-") and 0x0DDD (PASSWORD /R for files or
- // PASSWORD /P for directories for access rights "--?-"). Bits 1, 5, 9, 12-15
- // will be preserved when changing access rights. If execute bits are set on
- // systems other than FlexOS, 4680 OS or 4690 OS, they will be treated similar
- // to read bits. (Some versions of PASSWORD allow to set passwords on volume
- // labels (PASSWORD /V) as well.)
- //
- // Single-user systems calculate the most restrictive rights of the three sets
- // (DR DOS up to 5.0 used bits 0-3 only) and check if any of the requested file
- // access types requires a permission and if a file password is stored. If not,
- // file access is granted. Otherwise the stored password is checked against an
- // optional global password provided by the operating system and an optional file
- // password provided as part of the filename separated by a semicolon (not under
- // FlexOS, 4680 OS, 4690 OS). If neither of them is provided, the request will
- // fail. If one of them matches, the system will grant access (within the limits
- // of the normal file attributes, that is, a read-only file can still not be
- // opened for write this way), otherwise fail the request.
- //
- // Under FlexOS, 4680 OS and 4690 OS the system assigns group and user IDs to
- // applications when launched. When they request file access, their group and
- // user IDs are compared with the group and user IDs of the file to be opened.
- // If both IDs match, the application will be treated as file owner. If only the
- // group ID matches, the operating system will grant group access to the
- // application, and if the group ID does not match as well, it will grant world
- // access. If an application's group ID and user ID are both 0, the operating
- // system will bypass security checking. Once the permission class has been
- // determined, the operating system will check if any of the access types of the
- // requested file operation requires a permission according to the stored
- // bitflags of the selected class owner, group or world in the file's directory
- // entry. Owner, group and world access rights are independent and do not need to
- // have diminishing access levels. Only, if none of the requested access types
- // require a permission, the operating system will grant access, otherwise it
- // fails.
- //
- // If multiuser file / directory password security is enabled the system will not
- // fail at this stage but perform the password checking mechanism for the
- // selected permission class similar to the procedure described above. With
- // multi-user security loaded many utilities since DR DOS 6.0 will provide an
- // additional /U:name parameter.
- short implementationSpecific6 = br.ReadInt16();
- FATFileAccessRightsFlags fileAccess = (FATFileAccessRightsFlags)implementationSpecific6;
+ // Access rights bitmap for world/group/owner read/write/execute/delete
+ // protection for password protected files, directories (or volume labels) under
+ // DR DOS 3.31 and higher, including PalmDOS, Novell DOS and OpenDOS, and under
+ // FlexOS, 4680 OS, 4690 OS, Concurrent DOS, Multiuser DOS, System Manager, and
+ // REAL/32.
+ //
+ // Typical values stored on a single-user system are 0x0000 (PASSWORD /N for all
+ // access rights "RWED"), 0x0111 (PASSWORD /D for access rights "RW?-"), 0x0555
+ // (PASSWORD /W for access rights "R-?-") and 0x0DDD (PASSWORD /R for files or
+ // PASSWORD /P for directories for access rights "--?-"). Bits 1, 5, 9, 12-15
+ // will be preserved when changing access rights. If execute bits are set on
+ // systems other than FlexOS, 4680 OS or 4690 OS, they will be treated similar
+ // to read bits. (Some versions of PASSWORD allow to set passwords on volume
+ // labels (PASSWORD /V) as well.)
+ //
+ // Single-user systems calculate the most restrictive rights of the three sets
+ // (DR DOS up to 5.0 used bits 0-3 only) and check if any of the requested file
+ // access types requires a permission and if a file password is stored. If not,
+ // file access is granted. Otherwise the stored password is checked against an
+ // optional global password provided by the operating system and an optional file
+ // password provided as part of the filename separated by a semicolon (not under
+ // FlexOS, 4680 OS, 4690 OS). If neither of them is provided, the request will
+ // fail. If one of them matches, the system will grant access (within the limits
+ // of the normal file attributes, that is, a read-only file can still not be
+ // opened for write this way), otherwise fail the request.
+ //
+ // Under FlexOS, 4680 OS and 4690 OS the system assigns group and user IDs to
+ // applications when launched. When they request file access, their group and
+ // user IDs are compared with the group and user IDs of the file to be opened.
+ // If both IDs match, the application will be treated as file owner. If only the
+ // group ID matches, the operating system will grant group access to the
+ // application, and if the group ID does not match as well, it will grant world
+ // access. If an application's group ID and user ID are both 0, the operating
+ // system will bypass security checking. Once the permission class has been
+ // determined, the operating system will check if any of the access types of the
+ // requested file operation requires a permission according to the stored
+ // bitflags of the selected class owner, group or world in the file's directory
+ // entry. Owner, group and world access rights are independent and do not need to
+ // have diminishing access levels. Only, if none of the requested access types
+ // require a permission, the operating system will grant access, otherwise it
+ // fails.
+ //
+ // If multiuser file / directory password security is enabled the system will not
+ // fail at this stage but perform the password checking mechanism for the
+ // selected permission class similar to the procedure described above. With
+ // multi-user security loaded many utilities since DR DOS 6.0 will provide an
+ // additional /U:name parameter.
+ short implementationSpecific6 = br.ReadInt16();
+ FATFileAccessRightsFlags fileAccess = (FATFileAccessRightsFlags)implementationSpecific6;
- // Last modified time (since DOS 1.1); see offset 0x0E for a format description.
- //
- // Under Novell DOS, OpenDOS and DR-DOS 7.02 and higher, this entry holds the
- // deletion time of pending delete files or directories under DELWATCH 2.00 or
- // higher. The last modified time stamp is copied to 0x10 for possible later
- // restoration. See offset 0x0E for a format description.
- short implementationSpecific7 = br.ReadInt16();
+ // Last modified time (since DOS 1.1); see offset 0x0E for a format description.
+ //
+ // Under Novell DOS, OpenDOS and DR-DOS 7.02 and higher, this entry holds the
+ // deletion time of pending delete files or directories under DELWATCH 2.00 or
+ // higher. The last modified time stamp is copied to 0x10 for possible later
+ // restoration. See offset 0x0E for a format description.
+ short implementationSpecific7 = br.ReadInt16();
- // Last modified date; see offset 0x10 for a format description.
- //
- // Under Novell DOS, OpenDOS and DR-DOS 7.02 and higher, this entry holds the
- // deletion date of pending delete files or directories under DELWATCH 2.00 or
- // higher. The last modified date stamp is copied to 0x12 for possible later
- // restoration. See offset 0x10 for a format description.
- short implementationSpecific8 = br.ReadInt16();
+ // Last modified date; see offset 0x10 for a format description.
+ //
+ // Under Novell DOS, OpenDOS and DR-DOS 7.02 and higher, this entry holds the
+ // deletion date of pending delete files or directories under DELWATCH 2.00 or
+ // higher. The last modified date stamp is copied to 0x12 for possible later
+ // restoration. See offset 0x10 for a format description.
+ short implementationSpecific8 = br.ReadInt16();
- // Start of file in clusters in FAT12 and FAT16. Low two bytes of first cluster
- // in FAT32; with the high two bytes stored at offset 0x14.
- //
- // Entries with the Volume Label flag, subdirectory ".." pointing to FAT12/FAT16
- // root, and empty files with size 0 should have first cluster 0.
- //
- // VFAT LFN entries also have this entry set to 0; on FAT12 and FAT16 volumes
- // this can be used as part of a detection mechanism to distinguish between
- // pending delete files under DELWATCH and VFAT LFNs; see above.
- short implementationSpecific9 = br.ReadInt16();
+ // Start of file in clusters in FAT12 and FAT16. Low two bytes of first cluster
+ // in FAT32; with the high two bytes stored at offset 0x14.
+ //
+ // Entries with the Volume Label flag, subdirectory ".." pointing to FAT12/FAT16
+ // root, and empty files with size 0 should have first cluster 0.
+ //
+ // VFAT LFN entries also have this entry set to 0; on FAT12 and FAT16 volumes
+ // this can be used as part of a detection mechanism to distinguish between
+ // pending delete files under DELWATCH and VFAT LFNs; see above.
+ short implementationSpecific9 = br.ReadInt16();
- // File size in bytes. Entries with the Volume Label or Subdirectory flag set
- // should have a size of 0.
- //
- // VFAT LFN entries never store the value 0x00000000 here. This can be used as
- // part of a detection mechanism to distinguish between pending delete files
- // under DELWATCH and VFAT LFNs; see above.
- //
- // For files larger than 4 GB following the FAT+ proposal, this entry only holds
- // the size of the last chunk of the file (that is bits 31-0). The most
- // significant bits 37-32 are stored in the entry at offset 0x0C.
- short implementationSpecific10 = br.ReadInt16();
+ // File size in bytes. Entries with the Volume Label or Subdirectory flag set
+ // should have a size of 0.
+ //
+ // VFAT LFN entries never store the value 0x00000000 here. This can be used as
+ // part of a detection mechanism to distinguish between pending delete files
+ // under DELWATCH and VFAT LFNs; see above.
+ //
+ // For files larger than 4 GB following the FAT+ proposal, this entry only holds
+ // the size of the last chunk of the file (that is bits 31-0). The most
+ // significant bits 37-32 are stored in the entry at offset 0x0C.
+ short implementationSpecific10 = br.ReadInt16();
- byte[] others = br.ReadBytes(3);
- * - //
+ byte[] others = br.ReadBytes(3);
+ * - //
- byte[] reserved = br.ReadBytes(10);
- short timeCreatedOrLastUpdated = br.ReadInt16();
- short dateCreatedOrLastUpdated = br.ReadInt16();
- short startingClusterNumber = br.ReadInt16();
- uint fileSize = br.ReadUInt32();
+ byte[] reserved = br.ReadBytes(10);
+ short timeCreatedOrLastUpdated = br.ReadInt16();
+ short dateCreatedOrLastUpdated = br.ReadInt16();
+ short startingClusterNumber = br.ReadInt16();
+ uint fileSize = br.ReadUInt32();
- fileOffsets.Add(startingClusterNumber);
- fileSizes.Add(fileSize);
- }
- }
- #endregion
- #region File data
- {
- int bytesOccupiedByRootDirEntries = (mvarBiosParameterBlock.MaximumRootDirectoryEntryCount * 32);
+ fileOffsets.Add(startingClusterNumber);
+ fileSizes.Add(fileSize);
+ }
+ }
+ #endregion
+ #region File data
+ {
+ int bytesOccupiedByRootDirEntries = (mvarBiosParameterBlock.MaximumRootDirectoryEntryCount * 32);
- for (int i = 0; i < fileNames.Count; i++)
- {
- long fileOffset = (numBytesBeforeRootDir + bytesOccupiedByRootDirEntries + ((fileOffsets[i] - 2) * mvarBiosParameterBlock.BytesPerSector));
+ for (int i = 0; i < fileNames.Count; i++)
+ {
+ long fileOffset = (numBytesBeforeRootDir + bytesOccupiedByRootDirEntries + ((fileOffsets[i] - 2) * mvarBiosParameterBlock.BytesPerSector));
- File file = new File();
- file.Name = fileNames[i];
+ File file = new File();
+ file.Name = fileNames[i];
- long pos = br.Accessor.Position;
- br.Accessor.Position = fileOffset;
- byte[] data = br.ReadBytes(fileSizes[i]);
- br.Accessor.Position = pos;
+ long pos = br.Accessor.Position;
+ br.Accessor.Position = fileOffset;
+ byte[] data = br.ReadBytes(fileSizes[i]);
+ br.Accessor.Position = pos;
- file.SetDataAsByteArray(data);
+ file.SetDataAsByteArray(data);
- fsom.Files.Add(file);
- }
- }
- #endregion
- */
- }
- #endregion
- }
+ fsom.Files.Add(file);
+ }
+ }
+ #endregion
+ */
+ }
+ #endregion
+ }
}