private void EstablishReservedPartition(List <GptEntry> allEntries)
        {
            // If no MicrosoftReserved partition, and no Microsoft Data partitions, and the disk
            // has a 'reasonable' size free, create a Microsoft Reserved partition.
            if (CountEntries(allEntries, e => e.PartitionType == GuidPartitionTypes.MicrosoftReserved) == 0 &&
                CountEntries(allEntries, e => e.PartitionType == GuidPartitionTypes.WindowsBasicData) == 0 &&
                _diskGeometry.Capacity > 512 * 1024 * 1024)
            {
                long reservedStart = FirstAvailableSector(allEntries);
                long reservedEnd   = FindLastFreeSector(reservedStart, allEntries);

                if ((reservedEnd - reservedStart + 1) * _diskGeometry.BytesPerSector > 512 * 1024 * 1024)
                {
                    long size = (_diskGeometry.Capacity < 16 * 1024L * 1024 * 1024 ? 32 : 128) * 1024 * 1024;
                    reservedEnd = reservedStart + size / _diskGeometry.BytesPerSector - 1;

                    int      reservedOffset   = GetFreeEntryOffset();
                    GptEntry newReservedEntry = new GptEntry();
                    newReservedEntry.PartitionType         = GuidPartitionTypes.MicrosoftReserved;
                    newReservedEntry.Identity              = Guid.NewGuid();
                    newReservedEntry.FirstUsedLogicalBlock = reservedStart;
                    newReservedEntry.LastUsedLogicalBlock  = reservedEnd;
                    newReservedEntry.Attributes            = 0;
                    newReservedEntry.Name = "Microsoft reserved partition";
                    newReservedEntry.WriteTo(_entryBuffer, reservedOffset);
                    allEntries.Add(newReservedEntry);
                }
            }
        }
        /// <summary>
        /// Creates a new partition that encompasses the entire disk.
        /// </summary>
        /// <param name="type">The partition type</param>
        /// <param name="active">Whether the partition is active (bootable)</param>
        /// <returns>The index of the partition</returns>
        /// <remarks>The partition table must be empty before this method is called,
        /// otherwise IOException is thrown.</remarks>
        public override int Create(WellKnownPartitionType type, bool active)
        {
            List <GptEntry> allEntries = new List <GptEntry>(GetAllEntries());

            // If no MicrosoftReserved partition, and no Microsoft Data partitions, and the disk
            // has a 'reasonable' size free, create a Microsoft Reserved partition.
            if (CountEntries(allEntries, e => e.PartitionType == GuidPartitionTypes.MicrosoftReserved) == 0 &&
                CountEntries(allEntries, e => e.PartitionType == GuidPartitionTypes.WindowsBasicData) == 0 &&
                _diskGeometry.Capacity > 512 * 1024 * 1024)
            {
                long reservedStart = FirstAvailableSector(allEntries);
                long reservedEnd   = FindLastFreeSector(reservedStart, allEntries);

                if ((reservedEnd - reservedStart + 1) * _diskGeometry.BytesPerSector > 512 * 1024 * 1024)
                {
                    long size = ((_diskGeometry.Capacity < (16 * 1024L * 1024 * 1024)) ? 32 : 128) * 1024 * 1024;
                    reservedEnd = reservedStart + (size / _diskGeometry.BytesPerSector) - 1;

                    int      reservedOffset   = GetFreeEntryOffset();
                    GptEntry newReservedEntry = new GptEntry();
                    newReservedEntry.PartitionType         = GuidPartitionTypes.MicrosoftReserved;
                    newReservedEntry.Identity              = Guid.NewGuid();
                    newReservedEntry.FirstUsedLogicalBlock = reservedStart;
                    newReservedEntry.LastUsedLogicalBlock  = reservedEnd;
                    newReservedEntry.Attributes            = 0;
                    newReservedEntry.Name = "Microsoft reserved partition";
                    newReservedEntry.WriteTo(_entryBuffer, reservedOffset);
                    allEntries.Add(newReservedEntry);
                }
            }

            // Fill the rest of the disk with the requested partition
            long start = FirstAvailableSector(allEntries);
            long end   = FindLastFreeSector(start, allEntries);

            int      offset   = GetFreeEntryOffset();
            GptEntry newEntry = new GptEntry();

            newEntry.PartitionType         = GuidPartitionTypes.Convert(type);
            newEntry.Identity              = Guid.NewGuid();
            newEntry.FirstUsedLogicalBlock = start;
            newEntry.LastUsedLogicalBlock  = end;
            newEntry.Attributes            = 0;
            newEntry.Name = "Data Partition";
            newEntry.WriteTo(_entryBuffer, offset);

            // Commit changes to disk
            Write();

            return(GetEntryIndex(newEntry.Identity));
        }
        private GptEntry CreateEntry(long startSector, long endSector, Guid type, long attributes, string name)
        {
            if (endSector < startSector)
            {
                throw new ArgumentException("The end sector is before the start sector");
            }

            int      offset   = GetFreeEntryOffset();
            GptEntry newEntry = new GptEntry();

            newEntry.PartitionType         = type;
            newEntry.Identity              = Guid.NewGuid();
            newEntry.FirstUsedLogicalBlock = startSector;
            newEntry.LastUsedLogicalBlock  = endSector;
            newEntry.Attributes            = (ulong)attributes;
            newEntry.Name = name;
            newEntry.WriteTo(_entryBuffer, offset);

            // Commit changes to disk
            Write();

            return(newEntry);
        }