Пример #1
0
        public static List <DiskExtent> GetUnallocatedExtents(Disk disk)
        {
            MasterBootRecord  mbr    = MasterBootRecord.ReadFromDisk(disk);
            List <DiskExtent> result = new List <DiskExtent>();

            if (mbr == null)
            {
                result.Add(new DiskExtent(disk, 0, disk.Size));
                return(result);
            }
            else
            {
                long dataRegionStartSector;
                long dataRegionSize;
                if (!mbr.IsGPTBasedDisk)
                {
                    dataRegionStartSector = MBRDiskFirstUsableSector;
                    dataRegionSize        = Math.Min(disk.Size, UInt32.MaxValue * disk.BytesPerSector) - dataRegionStartSector;
                }
                else
                {
                    GuidPartitionTableHeader gptHeader = GuidPartitionTableHeader.ReadFromDisk(disk);
                    dataRegionStartSector = (long)gptHeader.FirstUsableLBA;
                    dataRegionSize        = (long)(gptHeader.LastUsableLBA - gptHeader.FirstUsableLBA + 1) * disk.BytesPerSector;
                }

                List <Partition>  partitions  = GetPartitions(disk);
                List <DiskExtent> usedExtents = new List <DiskExtent>();
                foreach (Partition partition in partitions)
                {
                    usedExtents.Add(partition.Extent);
                }
                return(DiskExtentsHelper.GetUnallocatedExtents(disk, dataRegionStartSector, dataRegionSize, usedExtents));
            }
        }
Пример #2
0
 public static Guid?GetWindowsVolumeGuid(Volume volume)
 {
     if (volume is MBRPartition)
     {
         MBRPartition     partition = (MBRPartition)volume;
         MasterBootRecord mbr       = MasterBootRecord.ReadFromDisk(((MBRPartition)volume).Disk);
         return(GetWindowsVolumeGuid(mbr.DiskSignature, (ulong)(partition.FirstSector * partition.BytesPerSector)));
     }
     else if (volume is GPTPartition)
     {
         return(((GPTPartition)volume).VolumeGuid);
     }
     else if (volume is DynamicVolume)
     {
         return(((DynamicVolume)volume).VolumeGuid);
     }
     else if (volume is OperatingSystemVolume)
     {
         return(((OperatingSystemVolume)volume).VolumeGuid);
     }
     else
     {
         return(null);
     }
 }
        public static void InitializeDisk(Disk disk, long firstUsableLBA, List <GuidPartitionEntry> partitionEntries)
        {
            MasterBootRecord mbr = new MasterBootRecord();

            mbr.DiskSignature = (uint)new Random().Next(Int32.MaxValue);
            mbr.PartitionTable[0].PartitionTypeName = PartitionTypeName.EFIGPT;
            mbr.PartitionTable[0].FirstSectorLBA    = 1;
            mbr.PartitionTable[0].SectorCountLBA    = (uint)Math.Min(disk.TotalSectors - firstUsableLBA, UInt32.MaxValue);
            mbr.MBRSignature = 0xAA55;
            MasterBootRecord.WriteToDisk(disk, mbr);

            const int DefaultNumberOfEntries       = 128;
            const int DefaultSizeOfEntry           = 128;
            int       partitionEntriesLength       = DefaultNumberOfEntries * DefaultSizeOfEntry;
            long      partitionEntriesPrimaryLBA   = 2;
            long      partitionEntriesSecondaryLBA = disk.TotalSectors - 1 - partitionEntriesLength / disk.BytesPerSector;

            GuidPartitionTableHeader primaryHeader = new GuidPartitionTableHeader();

            primaryHeader.HeaderSize               = 92;
            primaryHeader.CurrentLBA               = 1;
            primaryHeader.BackupLBA                = (ulong)(disk.TotalSectors - 1);
            primaryHeader.DiskGuid                 = Guid.NewGuid();
            primaryHeader.FirstUsableLBA           = (ulong)firstUsableLBA;
            primaryHeader.LastUsableLBA            = (ulong)(partitionEntriesSecondaryLBA - 1);
            primaryHeader.PartitionEntriesLBA      = (ulong)partitionEntriesPrimaryLBA;
            primaryHeader.NumberOfPartitionEntries = DefaultNumberOfEntries;
            primaryHeader.SizeOfPartitionEntry     = DefaultSizeOfEntry;
            byte[] partitionTableEntries = new byte[partitionEntriesLength];

            for (int index = 0; index < partitionEntries.Count; index++)
            {
                partitionEntries[index].WriteBytes(partitionTableEntries, index * DefaultSizeOfEntry);
            }
            primaryHeader.PartitionArrayCRC32 = CRC32.Compute(partitionTableEntries);

            GuidPartitionTableHeader secondaryHeader = primaryHeader.Clone();

            secondaryHeader.CurrentLBA          = (ulong)(disk.TotalSectors - 1);
            secondaryHeader.BackupLBA           = 1;
            secondaryHeader.PartitionEntriesLBA = (ulong)partitionEntriesSecondaryLBA;

            GuidPartitionTableHeader.WriteToDisk(disk, primaryHeader);
            disk.WriteSectors(partitionEntriesPrimaryLBA, partitionTableEntries);
            GuidPartitionTableHeader.WriteToDisk(disk, secondaryHeader);
            disk.WriteSectors(partitionEntriesSecondaryLBA, partitionTableEntries);
        }
Пример #4
0
        public static void ExtendMBRPartition(MBRPartition partition, long numberOfAdditionalExtentSectors)
        {
            Disk             disk = partition.Disk;
            MasterBootRecord mbr  = MasterBootRecord.ReadFromDisk(disk);

            for (int index = 0; index < mbr.PartitionTable.Length; index++)
            {
                if (mbr.PartitionTable[index].FirstSectorLBA == partition.FirstSector)
                {
                    mbr.PartitionTable[index].SectorCountLBA += (uint)numberOfAdditionalExtentSectors;
                    ulong lastSectorLBA = mbr.PartitionTable[index].LastSectorLBA;
                    mbr.PartitionTable[index].LastSectorCHS = CHSAddress.FromLBA(lastSectorLBA, disk);
                    break;
                }
            }
            MasterBootRecord.WriteToDisk(disk, mbr);
        }
Пример #5
0
        /// <returns>Number of bytes</returns>
        public static long GetMaximumSizeToExtendMBRPartition(MBRPartition partition)
        {
            MasterBootRecord mbr = MasterBootRecord.ReadFromDisk(partition.Disk);
            long             partitonEndSector = partition.FirstSector + partition.Size / partition.BytesPerSector;

            long max = partition.Disk.Size - (partition.FirstSector * partition.BytesPerSector + partition.Size);

            foreach (PartitionTableEntry entry in mbr.PartitionTable)
            {
                if (entry.FirstSectorLBA > partition.FirstSector)
                {
                    long available = (entry.FirstSectorLBA - partition.FirstSector) * partition.BytesPerSector - partition.Size;
                    max = Math.Min(max, available);
                }
            }

            // MBR partition cannot be larger than 2^32 sectors
            max = Math.Min(max, UInt32.MaxValue * partition.BytesPerSector);
            return(max);
        }
Пример #6
0
 public static Guid?GetVolumeUniqueID(Volume volume)
 {
     if (volume is MBRPartition)
     {
         MBRPartition     partition        = (MBRPartition)volume;
         MasterBootRecord mbr              = MasterBootRecord.ReadFromDisk(partition.Disk);
         byte[]           firstSectorBytes = BigEndianConverter.GetBytes(partition.FirstSector);
         return(new Guid((int)mbr.DiskSignature, 0, 0, firstSectorBytes));
     }
     else if (volume is GPTPartition)
     {
         return(((GPTPartition)volume).VolumeGuid);
     }
     else if (volume is DynamicVolume)
     {
         return(((DynamicVolume)volume).VolumeGuid);
     }
     else
     {
         return(null);
     }
 }
Пример #7
0
        public static List <Partition> GetPartitions(Disk disk)
        {
            List <Partition> result = new List <Partition>();

            MasterBootRecord mbr = MasterBootRecord.ReadFromDisk(disk);

            if (mbr != null)
            {
                if (!mbr.IsGPTBasedDisk)
                {
                    for (int index = 0; index < mbr.PartitionTable.Length; index++)
                    {
                        PartitionTableEntry entry = mbr.PartitionTable[index];
                        if (entry.SectorCountLBA > 0)
                        {
                            long         size      = entry.SectorCountLBA * disk.BytesPerSector;
                            MBRPartition partition = new MBRPartition(entry.PartitionType, disk, entry.FirstSectorLBA, size);
                            result.Add(partition);
                        }
                    }
                }
                else
                {
                    List <GuidPartitionEntry> entries = GuidPartitionTable.ReadEntriesFromDisk(disk);
                    if (entries != null)
                    {
                        foreach (GuidPartitionEntry entry in entries)
                        {
                            GPTPartition partition = new GPTPartition(entry.PartitionGuid, entry.PartitionTypeGuid, entry.PartitionName, disk, (long)entry.FirstLBA, (long)(entry.SizeLBA * (uint)disk.BytesPerSector));
                            result.Add(partition);
                        }
                    }
                }
            }
            return(result);
        }
        /// <summary>
        /// Read valid GPT (header and partition table), and write it to the correct locations at the beginning and end of the disk.
        /// The protective MBR partition size will be updated as well.
        /// </summary>
        public static void RebaseDisk(Disk disk, MasterBootRecord mbr)
        {
            GuidPartitionTableHeader  primaryHeader   = GuidPartitionTableHeader.ReadPrimaryFromDisk(disk);
            GuidPartitionTableHeader  secondaryHeader = null;
            List <GuidPartitionEntry> entries         = null;

            if (primaryHeader != null)
            {
                entries = ReadEntriesFromDisk(disk, primaryHeader);
            }

            if (primaryHeader == null || entries == null)
            {
                secondaryHeader = GuidPartitionTableHeader.ReadSecondaryFromDisk(disk, primaryHeader);
                if (secondaryHeader != null)
                {
                    entries = ReadEntriesFromDisk(disk, secondaryHeader);
                }
            }

            if (entries == null)
            {
                throw new InvalidDataException("Both the primary and secondary GPT are corrupted");
            }

            if (secondaryHeader != null)
            {
                primaryHeader = secondaryHeader.Clone();
            }
            else
            {
                secondaryHeader = primaryHeader.Clone();
            }

            byte[] partitionTableEntries = GuidPartitionEntryCollection.GetBytes(primaryHeader, entries);

            int  partitionEntriesLength       = (int)(primaryHeader.NumberOfPartitionEntries * primaryHeader.SizeOfPartitionEntry);
            long partitionEntriesPrimaryLBA   = 2;
            long partitionEntriesSecondaryLBA = disk.TotalSectors - 1 - partitionEntriesLength / disk.BytesPerSector;

            // If the disk was trimmed or converted to GPT without a secondary header, we don't want to overwrite partition data
            bool writeSecondaryGPT = primaryHeader.LastUsableLBA <= (ulong)(partitionEntriesSecondaryLBA - 1);

            primaryHeader.CurrentLBA          = 1;
            primaryHeader.BackupLBA           = (ulong)(disk.TotalSectors - 1);
            primaryHeader.PartitionEntriesLBA = (ulong)partitionEntriesPrimaryLBA;
            primaryHeader.LastUsableLBA       = (ulong)(partitionEntriesSecondaryLBA - 1);

            secondaryHeader.CurrentLBA          = (ulong)(disk.TotalSectors - 1);
            secondaryHeader.BackupLBA           = 1;
            secondaryHeader.PartitionEntriesLBA = (ulong)partitionEntriesSecondaryLBA;
            secondaryHeader.LastUsableLBA       = (ulong)(partitionEntriesSecondaryLBA - 1);

            // Update protective MBR partition size
            uint firstUsableLBA = mbr.PartitionTable[0].FirstSectorLBA;

            mbr.PartitionTable[0].SectorCountLBA = (uint)Math.Min(disk.TotalSectors - firstUsableLBA, UInt32.MaxValue);
            MasterBootRecord.WriteToDisk(disk, mbr);

            // Write primary and secondary GPT
            GuidPartitionTableHeader.WriteToDisk(disk, primaryHeader);
            disk.WriteSectors(partitionEntriesPrimaryLBA, partitionTableEntries);
            if (writeSecondaryGPT)
            {
                GuidPartitionTableHeader.WriteToDisk(disk, secondaryHeader);
                disk.WriteSectors(partitionEntriesSecondaryLBA, partitionTableEntries);
            }
        }
 public static void WriteToDisk(Disk disk, MasterBootRecord mbr)
 {
     byte[] buffer = mbr.GetBytes(disk.BytesPerSector);
     disk.WriteSectors(0, buffer);
 }