/// <summary>
        /// Creates a new partition table on a disk.
        /// </summary>
        /// <param name="disk">The stream containing the disk data</param>
        /// <param name="diskGeometry">The geometry of the disk</param>
        /// <returns>An object to access the newly created partition table</returns>
        public static GuidPartitionTable Initialize(Stream disk, Geometry diskGeometry)
        {
            // Create the protective MBR partition record.
            BiosPartitionTable pt = BiosPartitionTable.Initialize(disk, diskGeometry);

            pt.CreatePrimaryByCylinder(0, diskGeometry.Cylinders - 1, BiosPartitionTypes.GptProtective, false);

            // Create the GPT headers, and blank-out the entry areas
            const int EntryCount = 128;
            const int EntrySize  = 128;

            int entrySectors = ((EntryCount * EntrySize) + diskGeometry.BytesPerSector - 1) / diskGeometry.BytesPerSector;

            byte[] entriesBuffer = new byte[EntryCount * EntrySize];

            // Prepare primary header
            GptHeader header = new GptHeader(diskGeometry.BytesPerSector);

            header.HeaderLba           = 1;
            header.AlternateHeaderLba  = (disk.Length / diskGeometry.BytesPerSector) - 1;
            header.FirstUsable         = header.HeaderLba + entrySectors + 1;
            header.LastUsable          = header.AlternateHeaderLba - entrySectors - 1;
            header.DiskGuid            = Guid.NewGuid();
            header.PartitionEntriesLba = 2;
            header.PartitionEntryCount = EntryCount;
            header.PartitionEntrySize  = EntrySize;
            header.EntriesCrc          = CalcEntriesCrc(entriesBuffer);

            // Write the primary header
            byte[] headerBuffer = new byte[diskGeometry.BytesPerSector];
            header.WriteTo(headerBuffer, 0);
            disk.Position = header.HeaderLba * diskGeometry.BytesPerSector;
            disk.Write(headerBuffer, 0, headerBuffer.Length);

            // Calc alternate header
            header.HeaderLba           = header.AlternateHeaderLba;
            header.AlternateHeaderLba  = 1;
            header.PartitionEntriesLba = header.HeaderLba - entrySectors;

            // Write the alternate header
            header.WriteTo(headerBuffer, 0);
            disk.Position = header.HeaderLba * diskGeometry.BytesPerSector;
            disk.Write(headerBuffer, 0, headerBuffer.Length);

            return(new GuidPartitionTable(disk, diskGeometry));
        }
        private void WriteSecondaryHeader()
        {
            byte[] buffer = new byte[_diskGeometry.BytesPerSector];
            _secondaryHeader.EntriesCrc = CalcEntriesCrc();
            _secondaryHeader.WriteTo(buffer, 0);
            _diskData.Position = _diskData.Length - _diskGeometry.BytesPerSector;
            _diskData.Write(buffer, 0, buffer.Length);

            _diskData.Position = _secondaryHeader.PartitionEntriesLba * _diskGeometry.BytesPerSector;
            _diskData.Write(_entryBuffer, 0, _entryBuffer.Length);
        }
        private void WritePrimaryHeader()
        {
            byte[] buffer = new byte[_diskGeometry.BytesPerSector];
            _primaryHeader.EntriesCrc = CalcEntriesCrc();
            _primaryHeader.WriteTo(buffer, 0);
            _diskData.Position = _diskGeometry.BytesPerSector;
            _diskData.Write(buffer, 0, buffer.Length);

            _diskData.Position = 2 * _diskGeometry.BytesPerSector;
            _diskData.Write(_entryBuffer, 0, _entryBuffer.Length);
        }