using System.IO; namespace MPF.Data { /// /// Represents information for a single drive /// public class Drive { /// /// Represents drive type /// public InternalDriveType? InternalDriveType { get; set; } /// /// Drive partition format /// public string DriveFormat => driveInfo?.DriveFormat; /// /// Windows drive letter /// public char Letter => driveInfo?.Name[0] ?? '\0'; /// /// Windows drive path /// public string Name => driveInfo?.Name; /// /// Represents if Windows has marked the drive as active /// public bool MarkedActive => driveInfo?.IsReady ?? false; /// /// Media label as read by Windows /// public string VolumeLabel { get { string volumeLabel = Template.DiscNotDetected; if (driveInfo.IsReady) { if (string.IsNullOrWhiteSpace(driveInfo.VolumeLabel)) volumeLabel = "track"; else volumeLabel = driveInfo.VolumeLabel; } foreach (char c in Path.GetInvalidFileNameChars()) volumeLabel = volumeLabel.Replace(c, '_'); return volumeLabel; } } /// /// DriveInfo object representing the drive, if possible /// private readonly DriveInfo driveInfo; public Drive(InternalDriveType? driveType, DriveInfo driveInfo) { this.InternalDriveType = driveType; this.driveInfo = driveInfo; } /// /// Read a sector with a specified size from the drive /// /// Sector number, non-negative /// Size of a sector in bytes /// Byte array representing the sector, null on error public byte[] ReadSector(long num, int size = 2048) { // Missing drive leter is not supported if (string.IsNullOrEmpty(this.driveInfo?.Name)) return null; // We don't support negative sectors if (num < 0) return null; // Wrap the following in case of device access errors Stream fs = null; try { // Open the drive as a device fs = File.OpenRead($"\\\\?\\{this.Letter}:"); // Seek to the start of the sector, if possible long start = num * size; fs.Seek(start, SeekOrigin.Begin); // Read and return the sector byte[] buffer = new byte[size]; fs.Read(buffer, 0, size); return buffer; } catch { return null; } finally { fs?.Dispose(); } } } }