/// <summary>
        /// Creates a new primary partition with a target size.
        /// </summary>
        /// <param name="size">The target size (in bytes).</param>
        /// <param name="type">The partition type.</param>
        /// <param name="active">Whether the partition is active (bootable).</param>
        /// <returns>The index of the new partition.</returns>
        public override int Create(long size, WellKnownPartitionType type, bool active)
        {
            if (size < _diskGeometry.BytesPerSector)
            {
                throw new ArgumentOutOfRangeException("size", size, "size must be at least one sector");
            }

            long sectorLength = size / _diskGeometry.BytesPerSector;
            long start        = FindGap(size / _diskGeometry.BytesPerSector, 1);

            return(Create(start, start + sectorLength - 1, GuidPartitionTypes.Convert(type), 0, "Data Partition"));
        }
        /// <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());

            EstablishReservedPartition(allEntries);

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

            return(Create(start, end, GuidPartitionTypes.Convert(type), 0, "Data Partition"));
        }
        /// <summary>
        /// Creates a new aligned partition with a target size.
        /// </summary>
        /// <param name="size">The target size (in bytes).</param>
        /// <param name="type">The partition type.</param>
        /// <param name="active">Whether the partition is active (bootable).</param>
        /// <param name="alignment">The alignment (in bytes).</param>
        /// <returns>The index of the new partition.</returns>
        /// <remarks>
        /// Traditionally partitions were aligned to the physical structure of the underlying disk,
        /// however with modern storage greater efficiency is achieved by aligning partitions on
        /// large values that are a power of two.
        /// </remarks>
        public override int CreateAligned(long size, WellKnownPartitionType type, bool active, int alignment)
        {
            if (size < _diskGeometry.BytesPerSector)
            {
                throw new ArgumentOutOfRangeException("size", size, "size must be at least one sector");
            }

            if (alignment % _diskGeometry.BytesPerSector != 0)
            {
                throw new ArgumentException("Alignment is not a multiple of the sector size");
            }

            if (size % alignment != 0)
            {
                throw new ArgumentException("Size is not a multiple of the alignment");
            }

            long sectorLength = size / _diskGeometry.BytesPerSector;
            long start        = FindGap(size / _diskGeometry.BytesPerSector, alignment / _diskGeometry.BytesPerSector);

            return(Create(start, start + sectorLength - 1, GuidPartitionTypes.Convert(type), 0, "Data Partition"));
        }
        /// <summary>
        /// Creates a new aligned partition that encompasses the entire disk.
        /// </summary>
        /// <param name="type">The partition type.</param>
        /// <param name="active">Whether the partition is active (bootable).</param>
        /// <param name="alignment">The alignment (in bytes).</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>
        /// <remarks>
        /// Traditionally partitions were aligned to the physical structure of the underlying disk,
        /// however with modern storage greater efficiency is acheived by aligning partitions on
        /// large values that are a power of two.
        /// </remarks>
        public override int CreateAligned(WellKnownPartitionType type, bool active, int alignment)
        {
            if (alignment % _diskGeometry.BytesPerSector != 0)
            {
                throw new ArgumentException("Alignment is not a multiple of the sector size");
            }

            List <GptEntry> allEntries = new List <GptEntry>(GetAllEntries());

            EstablishReservedPartition(allEntries);

            // Fill the rest of the disk with the requested partition
            long start = Utilities.RoundUp(FirstAvailableSector(allEntries), alignment / _diskGeometry.BytesPerSector);
            long end   = Utilities.RoundDown(FindLastFreeSector(start, allEntries) + 1, alignment / _diskGeometry.BytesPerSector);

            if (end <= start)
            {
                throw new IOException("No available space");
            }

            return(Create(start, end - 1, GuidPartitionTypes.Convert(type), 0, "Data Partition"));
        }