From 2a15f045bc98059ee5e8836dc5749069219485c8 Mon Sep 17 00:00:00 2001 From: Pdawg11239 <83825746+Pdawg-bytes@users.noreply.github.com> Date: Sun, 16 Mar 2025 18:40:38 -0400 Subject: [PATCH] More work on FAT32 formatter --- .../BadBuilder.Formatter.csproj | 1 + BadBuilder.Formatter/Class1.cs | 9 - BadBuilder.Formatter/Constants.cs | 9 + BadBuilder.Formatter/DiskFormatter.cs | 114 +++++++++ BadBuilder.Formatter/FAT32BootSector.cs | 69 ++--- BadBuilder.Formatter/FAT32FsInfo.cs | 22 -- BadBuilder.Formatter/FAT32FsInfoSector.cs | 26 ++ BadBuilder.Formatter/FAT32Utilities.cs | 93 ++++++- BadBuilder.Formatter/Win32.cs | 238 ++++++++++++++++++ BadBuilder/BadBuilder.csproj | 4 + BadBuilder/Program.cs | 1 + 11 files changed, 524 insertions(+), 62 deletions(-) delete mode 100644 BadBuilder.Formatter/Class1.cs create mode 100644 BadBuilder.Formatter/Constants.cs create mode 100644 BadBuilder.Formatter/DiskFormatter.cs delete mode 100644 BadBuilder.Formatter/FAT32FsInfo.cs create mode 100644 BadBuilder.Formatter/FAT32FsInfoSector.cs create mode 100644 BadBuilder.Formatter/Win32.cs diff --git a/BadBuilder.Formatter/BadBuilder.Formatter.csproj b/BadBuilder.Formatter/BadBuilder.Formatter.csproj index fa71b7a..bd44ee5 100644 --- a/BadBuilder.Formatter/BadBuilder.Formatter.csproj +++ b/BadBuilder.Formatter/BadBuilder.Formatter.csproj @@ -4,6 +4,7 @@ net8.0 enable enable + true diff --git a/BadBuilder.Formatter/Class1.cs b/BadBuilder.Formatter/Class1.cs deleted file mode 100644 index 7ba8ce6..0000000 --- a/BadBuilder.Formatter/Class1.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Runtime.InteropServices; - -namespace BadBuilder.Formatter -{ - public class DiskFormatter - { - - } -} diff --git a/BadBuilder.Formatter/Constants.cs b/BadBuilder.Formatter/Constants.cs new file mode 100644 index 0000000..99a3530 --- /dev/null +++ b/BadBuilder.Formatter/Constants.cs @@ -0,0 +1,9 @@ +namespace BadBuilder.Formatter +{ + static class Constants + { + internal const string ORANGE = "\u001b[38;2;255;114;0m"; + + internal const string ANSI_RESET = "\u001b[0m"; + } +} \ No newline at end of file diff --git a/BadBuilder.Formatter/DiskFormatter.cs b/BadBuilder.Formatter/DiskFormatter.cs new file mode 100644 index 0000000..81b7b6a --- /dev/null +++ b/BadBuilder.Formatter/DiskFormatter.cs @@ -0,0 +1,114 @@ +using static BadBuilder.Formatter.Win32; +using static BadBuilder.Formatter.Constants; +using static BadBuilder.Formatter.FAT32Utilities; +using System.Runtime.InteropServices; + +namespace BadBuilder.Formatter +{ + public static class DiskFormatter + { + public static unsafe (int, string) FormatVolume(char driveLetter) + { + uint cbRet; + + DISK_GEOMETRY diskGeometry; + PARTITION_INFORMATION diskPartInfo; + PARTITION_INFORMATION_EX exDiskPartInfo; + bool isGPT = false; + uint bytesPerSector = 0; + uint totalSectors; + uint fatSize; + + string devicePath = $"\\\\.\\{driveLetter}:"; + uint volumeID = GetVolumeID(); + + + IntPtr driveHandle = CreateFileW( + devicePath, + GENERIC_READ | GENERIC_WRITE, + 0, + 0, + OPEN_EXISTING, + FILE_FLAG_NO_BUFFERING, + 0); + + if (driveHandle == -1) return (-1, Error("Unable to open device - close all open programs or windows that may have a handle lock on the drive.")); + + if (!DeviceIoControl( driveHandle, FSCTL_ALLOW_EXTENDED_DASD_IO, 0, 0, 0, 0, out cbRet, 0)) + return (-1, Error("Failed to enable extended DASD IO on the device.")); + + if (!DeviceIoControl(driveHandle, FSCTL_LOCK_VOLUME, 0, 0, 0, 0, out cbRet, 0)) + return (-1, Error("Failed to lock the device.")); + + + using (var pDiskGeometry = NativePointer.Allocate()) + { + if (!DeviceIoControl(driveHandle, IOCTL_DISK_GET_DRIVE_GEOMETRY, 0, 0, pDiskGeometry.Pointer, pDiskGeometry.Size, out cbRet, 0)) + return (-1, Error("Failed to get the drive geometry.")); + + diskGeometry = Marshal.PtrToStructure(pDiskGeometry.Pointer); + } + bytesPerSector = diskGeometry.BytesPerSector; + + using (var pDrivePartInfo = NativePointer.Allocate()) + { + if (!DeviceIoControl(driveHandle, IOCTL_DISK_GET_PARTITION_INFO, 0, 0, pDrivePartInfo.Pointer, pDrivePartInfo.Size, out cbRet, 0)) + return (-1, Error("Failed to get the drive partition information.")); + + diskPartInfo = Marshal.PtrToStructure(pDrivePartInfo.Pointer); + } + + using (var pDriveExPartInfo = NativePointer.Allocate()) + { + if (!DeviceIoControl(driveHandle, IOCTL_DISK_GET_PARTITION_INFO_EX, 0, 0, pDriveExPartInfo.Pointer, pDriveExPartInfo.Size, out cbRet, 0)) + return (-1, Error("Failed to get the drive extended partition information.")); + + exDiskPartInfo = Marshal.PtrToStructure(pDriveExPartInfo.Pointer); + } + isGPT = (exDiskPartInfo.PartitionStyle == PARTITION_STYLE.GPT); + + totalSectors = (uint)(diskPartInfo.PartitionLength / diskGeometry.BytesPerSector); + if (totalSectors < 65536 || totalSectors >= 0xffffffff) + return (-1, Error("Invalid drive size for FAT32 - either too small (less than 64K clusters) or too large (greater than 2TB).")); + + FAT32BootSector bootSector; + FAT32FsInfoSector fsInfo; + + bootSector.JumpCode = [0xEB, 0x58, 0x90]; + bootSector.OEMName = "MSWIN4.1".ToCharArray(); + bootSector.BytesPerSector = (ushort)bytesPerSector; + bootSector.SectorsPerCluster = CalculateSectorsPerCluster((ulong)diskPartInfo.PartitionLength, bytesPerSector); + bootSector.ReservedSectorCount = 32; + bootSector.NumberOfFATs = 2; + bootSector.MaxRootEntries = 0; + bootSector.TotalSectors16 = 0; + bootSector.MediaDescriptor = 0xF8; + bootSector.SectorsPerFAT16 = 0; + bootSector.SectorsPerTrack = (ushort)diskGeometry.SectorsPerTrack; + bootSector.NumberOfHeads = (ushort)diskGeometry.TracksPerCylinder; + bootSector.HiddenSectors = diskPartInfo.HiddenSectors; + bootSector.TotalSectors = totalSectors; + + fatSize = CalculateFATSize(bootSector.TotalSectors, bootSector.ReservedSectorCount, bootSector.SectorsPerCluster, bootSector.NumberOfFATs, bytesPerSector); + + bootSector.SectorsPerFAT = fatSize; + bootSector.FATFlags = 0; + bootSector.FileSystemVersion = 0; + bootSector.RootCluster = 2; + bootSector.FSInfoSector = 1; + bootSector.BackupBootSector = 6; + bootSector.DriveNumber = 0x80; + bootSector.Reserved1 = 0; + bootSector.BootSignature = 0x29; + bootSector.VolumeID = volumeID; + bootSector.VolumeLabel = "BADUPDATE ".ToCharArray(); + bootSector.FileSystemType = "FAT32 ".ToCharArray(); + bootSector.Signature = 0x55AA; + + if (!DeviceIoControl(driveHandle, FSCTL_UNLOCK_VOLUME, 0, 0, 0, 0, out cbRet, 0)) + return (-1, Error("Failed to unlock the device.")); + + return (0, ""); + } + } +} diff --git a/BadBuilder.Formatter/FAT32BootSector.cs b/BadBuilder.Formatter/FAT32BootSector.cs index 0634994..ea5d3c6 100644 --- a/BadBuilder.Formatter/FAT32BootSector.cs +++ b/BadBuilder.Formatter/FAT32BootSector.cs @@ -2,48 +2,61 @@ namespace BadBuilder.Formatter { - [StructLayout(LayoutKind.Sequential, Pack = 1)] + // Reference: https://cscie92.dce.harvard.edu/spring2024/K70F120M/bootSector.h + + [StructLayout(LayoutKind.Explicit, Pack = 1, Size = 512)] internal struct FAT32BootSector { + [FieldOffset(0)] [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)] - public byte[] JumpCode; + internal byte[] JumpCode; + [FieldOffset(3)] [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] - public byte[] OEMName; + internal char[] OEMName; - public ushort BytesPerSector; - public byte SectorsPerCluster; - public ushort ReservedSectorCount; - public byte NumberOfFATs; - public ushort MaxRootEntries; // Unused in FAT32 - public ushort TotalSectors16; // If 0, use TotalSectors - public byte MediaDescriptor; - public ushort SectorsPerFAT16; // Unused in FAT32 - public ushort SectorsPerTrack; - public ushort NumberOfHeads; - public uint HiddenSectors; - public uint TotalSectors; // Total sectors (if TotalSectors16 is 0) + [FieldOffset(11)] internal ushort BytesPerSector; + [FieldOffset(13)] internal byte SectorsPerCluster; + [FieldOffset(14)] internal ushort ReservedSectorCount; + [FieldOffset(16)] internal byte NumberOfFATs; + [FieldOffset(17)] internal ushort MaxRootEntries; // Unused in FAT32 + [FieldOffset(19)] internal ushort TotalSectors16; // If 0, use TotalSectors + [FieldOffset(21)] internal byte MediaDescriptor; + [FieldOffset(22)] internal ushort SectorsPerFAT16; // Unused in FAT32 + [FieldOffset(24)] internal ushort SectorsPerTrack; + [FieldOffset(26)] internal ushort NumberOfHeads; + [FieldOffset(28)] internal uint HiddenSectors; + [FieldOffset(32)] internal uint TotalSectors; // Total sectors (if TotalSectors16 is 0) // FAT32-specific fields - public uint SectorsPerFAT; - public ushort FATFlags; - public ushort FileSystemVersion; - public uint RootCluster; - public ushort FSInfoSector; - public ushort BackupBootSector; + [FieldOffset(36)] internal uint SectorsPerFAT; + [FieldOffset(40)] internal ushort FATFlags; + [FieldOffset(42)] internal ushort FileSystemVersion; + [FieldOffset(44)] internal uint RootCluster; + [FieldOffset(48)] internal ushort FSInfoSector; + [FieldOffset(50)] internal ushort BackupBootSector; + [FieldOffset(52)] [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] - public byte[] Reserved; + internal byte[] Reserved; - public byte DriveNumber; - public byte Reserved1; - public byte BootSignature; - public uint VolumeID; + [FieldOffset(64)] internal byte DriveNumber; + [FieldOffset(65)] internal byte Reserved1; + [FieldOffset(66)] internal byte BootSignature; + [FieldOffset(67)] internal uint VolumeID; + [FieldOffset(71)] [MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)] - public byte[] VolumeLabel; + internal char[] VolumeLabel; + [FieldOffset(82)] [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] - public byte[] FileSystemType; + internal char[] FileSystemType; + + [FieldOffset(90)] + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 420)] + internal byte[] Reserved2; + + [FieldOffset(510)] internal ushort Signature; } } \ No newline at end of file diff --git a/BadBuilder.Formatter/FAT32FsInfo.cs b/BadBuilder.Formatter/FAT32FsInfo.cs deleted file mode 100644 index 461fe37..0000000 --- a/BadBuilder.Formatter/FAT32FsInfo.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Runtime.InteropServices; - -namespace BadBuilder.Formatter -{ - [StructLayout(LayoutKind.Sequential, Pack = 1)] - internal struct FAT32FsInfo - { - public uint LeadSignature; // Should be 0x41615252 - - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 480)] - public byte[] Reserved1; // Zeros - - public uint StructureSignature; // Should be 0x61417272 - public uint FreeClusterCount; // Number of free clusters (or 0xFFFFFFFF if unknown) - public uint NextFreeCluster; // Next free cluster (or 0xFFFFFFFF if unknown) - - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] - public byte[] Reserved2; // Zeros - - public uint TrailSignature; // Should be 0xAA550000 - } -} \ No newline at end of file diff --git a/BadBuilder.Formatter/FAT32FsInfoSector.cs b/BadBuilder.Formatter/FAT32FsInfoSector.cs new file mode 100644 index 0000000..bfdb1ef --- /dev/null +++ b/BadBuilder.Formatter/FAT32FsInfoSector.cs @@ -0,0 +1,26 @@ +using System.Runtime.InteropServices; + +namespace BadBuilder.Formatter +{ + // Reference: https://cscie92.dce.harvard.edu/spring2024/K70F120M/fsInfo.h + + [StructLayout(LayoutKind.Explicit, Pack = 1, Size = 512)] + internal struct FAT32FsInfoSector + { + [FieldOffset(0)] public uint LeadSignature; + + [FieldOffset(4)] + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 480)] + public byte[] Reserved1; // Zeros + + [FieldOffset(484)] public uint StructureSignature; + [FieldOffset(488)] public uint FreeClusterCount; + [FieldOffset(492)] public uint NextFreeCluster; + + [FieldOffset(496)] + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] + public byte[] Reserved2; + + [FieldOffset(508)] public uint TrailSignature; + } +} \ No newline at end of file diff --git a/BadBuilder.Formatter/FAT32Utilities.cs b/BadBuilder.Formatter/FAT32Utilities.cs index af7b54b..ab1c011 100644 --- a/BadBuilder.Formatter/FAT32Utilities.cs +++ b/BadBuilder.Formatter/FAT32Utilities.cs @@ -1,7 +1,46 @@ -namespace BadBuilder.Formatter +using static BadBuilder.Formatter.Win32; +using static BadBuilder.Formatter.Constants; +using System.Runtime.InteropServices; + +namespace BadBuilder.Formatter { static class FAT32Utilities { + internal struct NativePointer : IDisposable + { + internal IntPtr Pointer; + internal uint Size; + + internal NativePointer(Type type) + { + uint size = (uint)Marshal.SizeOf(type); + Pointer = Marshal.AllocHGlobal((int)size); + Size = size; + } + + public void Dispose() + { + if (Pointer != IntPtr.Zero) + { + Marshal.FreeHGlobal(Pointer); + Pointer = IntPtr.Zero; + Size = 0; + } + } + + internal static NativePointer Allocate() where T : struct + { + return new NativePointer(typeof(T)); + } + } + + internal static string Error(string error) => $"{ORANGE}[-]{ANSI_RESET} {error}"; + internal static void ExitWithError(string error) + { + Console.WriteLine($"{ORANGE}[-]{ANSI_RESET} {error}"); + Environment.Exit(-1); + } + internal static uint GetVolumeID() { DateTime now = DateTime.Now; @@ -15,14 +54,62 @@ return (uint)(low | (hi << 16)); } - internal static uint CalculateFATSize(uint diskSize, uint reservedSectorCount, uint sectorsPerCluster, uint numberOfFATs, uint bytesPerSector) + internal static uint CalculateFATSize(uint totalSectors, uint reservedSectors, uint sectorsPerCluster, uint numberOfFATs, uint bytesPerSector) { const ulong fatElementSize = 4; - ulong numerator = fatElementSize * (diskSize - reservedSectorCount); + ulong numerator = fatElementSize * (totalSectors - reservedSectors); ulong denominator = (sectorsPerCluster * bytesPerSector) + (fatElementSize * numberOfFATs); return (uint)((numerator / denominator) + 1); } + + internal static byte CalculateSectorsPerCluster(ulong diskSizeBytes, uint bytesPerSector) => (diskSizeBytes / (1024 * 1024)) switch + { + var size when size > 512 => (byte)((4 * 1024) / bytesPerSector), + var size when size > 8192 => (byte)((8 * 1024) / bytesPerSector), + var size when size > 16384 => (byte)((16 * 1024) / bytesPerSector), + var size when size > 32768 => (byte)((32 * 1024) / bytesPerSector), + _ => 1 + }; + + + internal static void SeekTo(IntPtr hDevice, uint sector, uint bytesPerSector) + { + long offset = sector * bytesPerSector; + + int lowOffset = (int)(offset & 0xFFFFFFFF); + int highOffset = (int)(offset >> 32); + + SetFilePointer(hDevice, lowOffset, ref highOffset, FILE_BEGIN); + } + + internal static void WriteSector(IntPtr hDevice, uint sector, uint numberOfSectors, uint bytesPerSector, byte[] data) + { + uint bytesWritten; + + SeekTo(hDevice, sector, bytesPerSector); + + if (!WriteFile(hDevice, data, numberOfSectors * bytesPerSector, out bytesWritten, 0)) + ExitWithError("Unable to write to write sectors to FAT32 device, exiting."); + } + + internal static void ZeroOutSectors(IntPtr hDevice, uint sector, uint numberOfSectors, uint bytesPerSector) + { + const uint burstSize = 128; + uint writeSize; + + byte[] zeroBuffer = new byte[bytesPerSector * burstSize]; + Array.Clear(zeroBuffer); + + SeekTo(hDevice, sector, bytesPerSector); + + while (numberOfSectors > 0) + { + writeSize = (numberOfSectors > burstSize) ? burstSize : numberOfSectors; + WriteSector(hDevice, sector, numberOfSectors, bytesPerSector, zeroBuffer); + numberOfSectors -= writeSize; + } + } } } \ No newline at end of file diff --git a/BadBuilder.Formatter/Win32.cs b/BadBuilder.Formatter/Win32.cs new file mode 100644 index 0000000..91154d3 --- /dev/null +++ b/BadBuilder.Formatter/Win32.cs @@ -0,0 +1,238 @@ +using System.Runtime.InteropServices; + +namespace BadBuilder.Formatter +{ + static partial class Win32 + { + internal const uint GENERIC_READ = 0x80000000; + internal const uint GENERIC_WRITE = 0x40000000; + internal const uint OPEN_EXISTING = 3; + internal const uint FILE_SHARE_READ = 1; + internal const uint FILE_BEGIN = 0; + internal const uint FILE_FLAG_NO_BUFFERING = 0x20000000; + + internal const uint IOCTL_DISK_GET_DRIVE_GEOMETRY = 0x00070000; + internal const uint IOCTL_DISK_GET_PARTITION_INFO_EX = 0x00070048; + internal const uint IOCTL_DISK_GET_PARTITION_INFO = 0x00074004; + internal const uint FSCTL_LOCK_VOLUME = 0x00090018; + internal const uint FSCTL_UNLOCK_VOLUME = 0x0009001C; + internal const uint FSCTL_QUERY_RETRIEVAL_POINTERS = 0x0009003B; + internal const uint FSCTL_GET_COMPRESSION = 0x0009003C; + internal const uint FSCTL_SET_COMPRESSION = 0x0009C040; + internal const uint FSCTL_SET_BOOTLOADER_ACCESSED = 0x0009004F; + internal const uint FSCTL_MARK_AS_SYSTEM_HIVE = 0x0009004F; + internal const uint FSCTL_OPLOCK_BREAK_ACK_NO_2 = 0x00090050; + internal const uint FSCTL_INVALIDATE_VOLUMES = 0x00090054; + internal const uint FSCTL_QUERY_FAT_BPB = 0x00090058; + internal const uint FSCTL_REQUEST_FILTER_OPLOCK = 0x0009005C; + internal const uint FSCTL_FILESYSTEM_GET_STATISTICS = 0x00090060; + internal const uint FSCTL_GET_NTFS_VOLUME_DATA = 0x00090064; + internal const uint FSCTL_GET_NTFS_FILE_RECORD = 0x00090068; + internal const uint FSCTL_GET_VOLUME_BITMAP = 0x0009006F; + internal const uint FSCTL_GET_RETRIEVAL_POINTERS = 0x00090073; + internal const uint FSCTL_MOVE_FILE = 0x00090074; + internal const uint FSCTL_IS_VOLUME_DIRTY = 0x00090078; + internal const uint FSCTL_ALLOW_EXTENDED_DASD_IO = 0x00090083; + + + private const string Kernel32 = "kernel32.dll"; + + [LibraryImport(Kernel32, SetLastError = true)] + internal static partial IntPtr CreateFileW( + [MarshalAs(UnmanagedType.LPWStr)] string lpFileName, + uint dwDesiredAccess, + uint dwShareMode, + IntPtr lpSecurityAttributes, + uint dwCreationDisposition, + uint dwFlagsAndAttributes, + IntPtr hTemplateFile); + + + [LibraryImport(Kernel32, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static partial bool WriteFile( + IntPtr hFile, + byte[] lpBuffer, + uint nNumberOfBytesToWrite, + out uint lpNumberOfBytesWritten, + IntPtr lpOverlapped); + + [LibraryImport(Kernel32, SetLastError = true)] + internal static partial uint SetFilePointer( + IntPtr hFile, + int lDistanceToMove, + ref int lpDistanceToMoveHigh, + uint dwMoveMethod); + + [LibraryImport(Kernel32, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static partial bool DeviceIoControl( + IntPtr hDevice, + uint dwIoControlCode, + IntPtr lpInBuffer, + uint nInBufferSize, + IntPtr lpOutBuffer, + uint nOutBufferSize, + out uint lpBytesReturned, + IntPtr lpOverlapped); + + [LibraryImport(Kernel32, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static partial bool CloseHandle(IntPtr hObject); + + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + internal struct DISK_GEOMETRY + { + internal long Cylinders; + internal MediaType MediaType; + internal uint TracksPerCylinder; + internal uint SectorsPerTrack; + internal uint BytesPerSector; + } + + internal enum MediaType // from winioctl.h + { + Unknown, // Format is unknown + F5_1Pt2_512, // 5.25", 1.2MB, 512 bytes/sector + F3_1Pt44_512, // 3.5", 1.44MB, 512 bytes/sector + F3_2Pt88_512, // 3.5", 2.88MB, 512 bytes/sector + F3_20Pt8_512, // 3.5", 20.8MB, 512 bytes/sector + F3_720_512, // 3.5", 720KB, 512 bytes/sector + F5_360_512, // 5.25", 360KB, 512 bytes/sector + F5_320_512, // 5.25", 320KB, 512 bytes/sector + F5_320_1024, // 5.25", 320KB, 1024 bytes/sector + F5_180_512, // 5.25", 180KB, 512 bytes/sector + F5_160_512, // 5.25", 160KB, 512 bytes/sector + RemovableMedia, // Removable media other than floppy + FixedMedia, // Fixed hard disk media + F3_120M_512, // 3.5", 120M Floppy + F3_640_512, // 3.5" , 640KB, 512 bytes/sector + F5_640_512, // 5.25", 640KB, 512 bytes/sector + F5_720_512, // 5.25", 720KB, 512 bytes/sector + F3_1Pt2_512, // 3.5" , 1.2Mb, 512 bytes/sector + F3_1Pt23_1024, // 3.5" , 1.23Mb, 1024 bytes/sector + F5_1Pt23_1024, // 5.25", 1.23MB, 1024 bytes/sector + F3_128Mb_512, // 3.5" MO 128Mb 512 bytes/sector + F3_230Mb_512, // 3.5" MO 230Mb 512 bytes/sector + F8_256_128, // 8", 256KB, 128 bytes/sector + F3_200Mb_512, // 3.5", 200M Floppy (HiFD) + F3_240M_512, // 3.5", 240Mb Floppy (HiFD) + F3_32M_512 // 3.5", 32Mb Floppy + } + + [StructLayout(LayoutKind.Sequential, Pack = 1, Size = 16)] + internal struct GUID + { + internal uint Data1; + internal ushort Data2; + internal ushort Data3; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] + internal byte[] Data4; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1, Size = 32)] + internal struct PARTITION_INFORMATION + { + internal long StartingOffset; + internal long PartitionLength; + internal uint HiddenSectors; + internal uint PartitionNumber; + internal byte PartitionType; + internal byte BootIndicator; + internal byte RecognizedPattern; + internal byte RewritePartition; + } + + [StructLayout(LayoutKind.Explicit, Size = 144)] + internal struct PARTITION_INFORMATION_EX + { + [FieldOffset(0)] + internal PARTITION_STYLE PartitionStyle; + + [FieldOffset(8)] + internal long StartingOffset; + + [FieldOffset(16)] + internal long PartitionLength; + + [FieldOffset(24)] + internal uint PartitionNumber; + + [FieldOffset(28)] + internal byte RewritePartition; + + [FieldOffset(29)] + internal byte IsServicePartition; + + [FieldOffset(32)] + internal unsafe fixed byte Union[112]; + + public unsafe PARTITION_INFORMATION_MBR Mbr + { + get + { + fixed (byte* p = Union) + { + return *(PARTITION_INFORMATION_MBR*)p; + } + } + set + { + fixed (byte* p = Union) + { + *(PARTITION_INFORMATION_MBR*)p = value; + } + } + } + + public unsafe PARTITION_INFORMATION_GPT Gpt + { + get + { + fixed (byte* p = Union) + { + return *(PARTITION_INFORMATION_GPT*)p; + } + } + set + { + fixed (byte* p = Union) + { + *(PARTITION_INFORMATION_GPT*)p = value; + } + } + } + } + + [StructLayout(LayoutKind.Sequential, Pack = 1, Size = 24)] + internal struct PARTITION_INFORMATION_MBR + { + internal byte PartitionType; + internal byte BootIndicator; + internal byte RecognizedPartition; + private byte _padding1; + internal uint HiddenSectors; + internal GUID PartitionId; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1, Size = 112)] + internal struct PARTITION_INFORMATION_GPT + { + internal GUID PartitionType; + internal GUID PartitionId; + internal ulong Attributes; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 36)] + internal ushort[] Name; + } + + internal enum PARTITION_STYLE : uint + { + MBR = 0, + GPT = 1, + RAW = 2 + } + } +} \ No newline at end of file diff --git a/BadBuilder/BadBuilder.csproj b/BadBuilder/BadBuilder.csproj index e2620de..9032e08 100644 --- a/BadBuilder/BadBuilder.csproj +++ b/BadBuilder/BadBuilder.csproj @@ -24,4 +24,8 @@ + + + + diff --git a/BadBuilder/Program.cs b/BadBuilder/Program.cs index 3dca2ff..d0967cc 100644 --- a/BadBuilder/Program.cs +++ b/BadBuilder/Program.cs @@ -26,6 +26,7 @@ namespace BadBuilder static void Main(string[] args) { + BadBuilder.Formatter.DiskFormatter.FormatVolume('E'); ShowWelcomeMessage(); while (true)