// The maximum NTFS file size is 2^64 bytes, so total number of file clusters can be represented using long
        public void AllocateAdditionalClusters(NTFSVolume volume, long clustersToAllocate)
        {
            ulong desiredStartLCN = (ulong)DataRunSequence.DataLastLCN;
            KeyValuePairList <ulong, long> freeClusterRunList = volume.AllocateClusters(desiredStartLCN, clustersToAllocate);

            for (int index = 0; index < freeClusterRunList.Count; index++)
            {
                ulong runStartLCN = freeClusterRunList[index].Key;
                long  runLength   = freeClusterRunList[index].Value;

                bool mergeWithLastRun = (index == 0 && runStartLCN == desiredStartLCN);
                if (mergeWithLastRun)
                {
                    // we append this run to the last run
                    DataRun lastRun = DataRunSequence[DataRunSequence.Count - 1];
                    lastRun.RunLength += (long)runLength;
                    HighestVCN        += (long)runLength;
                }
                else
                {
                    DataRun run         = new DataRun();
                    ulong   previousLCN = (ulong)DataRunSequence.LastDataRunStartLCN;
                    run.RunOffset = (long)(runStartLCN - previousLCN);
                    run.RunLength = (long)runLength;
                    HighestVCN   += runLength;
                    DataRunSequence.Add(run);
                }
            }
        }
        // Data run NULL terminator here
        // I've noticed that Windows Server 2003 puts 0x00 0x01 here for the $MFT FileRecord, seems to have no effect
        // (I've set it to 0 for the $MFT FileRecord in the MFT and the MFT mirror, and chkdsk did not report a problem.

        public NonResidentAttributeRecord(byte[] buffer, int offset) : base(buffer, offset)
        {
            LowestVCN  = (long)LittleEndianConverter.ToUInt64(buffer, offset + 0x10);
            HighestVCN = (long)LittleEndianConverter.ToUInt64(buffer, offset + 0x18);
            ushort mappingPairsOffset = LittleEndianConverter.ToUInt16(buffer, offset + 0x20);

            CompressionUnitSize = LittleEndianConverter.ToUInt16(buffer, offset + 0x22);
            ulong allocatedLength = LittleEndianConverter.ToUInt64(buffer, offset + 0x28);

            FileSize        = LittleEndianConverter.ToUInt64(buffer, offset + 0x30);
            ValidDataLength = LittleEndianConverter.ToUInt64(buffer, offset + 0x38);

            int position = offset + mappingPairsOffset;

            while (position < offset + this.StoredRecordLength)
            {
                DataRun run    = new DataRun();
                int     length = run.Read(buffer, position);
                position += length;

                // Length 1 means there was only a header byte (i.e. terminator)
                if (length == 1)
                {
                    break;
                }

                m_dataRunSequence.Add(run);
            }

            if ((HighestVCN - LowestVCN + 1) != m_dataRunSequence.DataClusterCount)
            {
                throw new InvalidDataException("Invalid non-resident attribute record");
            }
        }
        public DataRunSequence Clone()
        {
            DataRunSequence clone = new DataRunSequence(this.Count);

            foreach (DataRun run in this)
            {
                clone.Add(run.Clone());
            }
            return(clone);
        }