More work on FAT32 formatter
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace BadBuilder.Formatter
|
||||
{
|
||||
public class DiskFormatter
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
9
BadBuilder.Formatter/Constants.cs
Normal file
9
BadBuilder.Formatter/Constants.cs
Normal file
@@ -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";
|
||||
}
|
||||
}
|
||||
114
BadBuilder.Formatter/DiskFormatter.cs
Normal file
114
BadBuilder.Formatter/DiskFormatter.cs
Normal file
@@ -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<DISK_GEOMETRY>())
|
||||
{
|
||||
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<DISK_GEOMETRY>(pDiskGeometry.Pointer);
|
||||
}
|
||||
bytesPerSector = diskGeometry.BytesPerSector;
|
||||
|
||||
using (var pDrivePartInfo = NativePointer.Allocate<PARTITION_INFORMATION>())
|
||||
{
|
||||
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<PARTITION_INFORMATION>(pDrivePartInfo.Pointer);
|
||||
}
|
||||
|
||||
using (var pDriveExPartInfo = NativePointer.Allocate<PARTITION_INFORMATION_EX>())
|
||||
{
|
||||
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<PARTITION_INFORMATION_EX>(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, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
26
BadBuilder.Formatter/FAT32FsInfoSector.cs
Normal file
26
BadBuilder.Formatter/FAT32FsInfoSector.cs
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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<T>() 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
238
BadBuilder.Formatter/Win32.cs
Normal file
238
BadBuilder.Formatter/Win32.cs
Normal file
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user