public byte[] GetBytes(int bytesPerIndexRecord, bool applyUsaProtection) { int strideCount = bytesPerIndexRecord / MultiSectorHelper.BytesPerStride; ushort updateSequenceArraySize = (ushort)(1 + strideCount); MultiSectorHeader multiSectorHeader = new MultiSectorHeader(ValidSignature, UpdateSequenceArrayOffset, updateSequenceArraySize); int updateSequenceArrayPaddedLength = (int)Math.Ceiling((double)(updateSequenceArraySize * 2) / 8) * 8; m_indexHeader.EntriesOffset = (uint)(IndexHeader.Length + updateSequenceArrayPaddedLength); m_indexHeader.TotalLength = (uint)(IndexHeader.Length + updateSequenceArrayPaddedLength + IndexEntry.GetLength(IndexEntries)); m_indexHeader.AllocatedLength = (uint)(bytesPerIndexRecord - IndexHeaderOffset); int length = applyUsaProtection ? bytesPerIndexRecord : GetNumberOfBytesInUse(bytesPerIndexRecord); byte[] buffer = new byte[length]; multiSectorHeader.WriteBytes(buffer, 0x00); LittleEndianWriter.WriteUInt64(buffer, 0x08, LogFileSequenceNumber); LittleEndianWriter.WriteUInt64(buffer, 0x10, (ulong)RecordVBN); m_indexHeader.WriteBytes(buffer, 0x18); LittleEndianWriter.WriteUInt16(buffer, UpdateSequenceArrayOffset, UpdateSequenceNumber); IndexEntry.WriteIndexEntries(buffer, UpdateSequenceArrayOffset + updateSequenceArrayPaddedLength, IndexEntries); if (applyUsaProtection) { MultiSectorHelper.ApplyUsaProtection(buffer, 0); } return(buffer); }
public byte[] GetBytes(int bytesPerIndexRecord) { int strideCount = bytesPerIndexRecord / MultiSectorHelper.BytesPerStride; ushort updateSequenceArraySize = (ushort)(1 + strideCount); MultiSectorHeader multiSectorHeader = new MultiSectorHeader(ValidSignature, UpdateSequenceArrayOffset, updateSequenceArraySize); int updateSequenceArrayPaddedLength = (int)Math.Ceiling((double)(updateSequenceArraySize * 2) / 8) * 8; m_indexHeader.EntriesOffset = (uint)(IndexHeader.Length + updateSequenceArrayPaddedLength); m_indexHeader.TotalLength = (uint)(IndexHeader.Length + updateSequenceArrayPaddedLength + IndexEntry.GetLength(IndexEntries)); m_indexHeader.AllocatedLength = (uint)(bytesPerIndexRecord - IndexHeaderOffset); byte[] buffer = new byte[bytesPerIndexRecord]; multiSectorHeader.WriteBytes(buffer, 0x00); LittleEndianWriter.WriteUInt64(buffer, 0x08, LogFileSequenceNumber); LittleEndianWriter.WriteUInt64(buffer, 0x10, (ulong)RecordVBN); m_indexHeader.WriteBytes(buffer, 0x18); IndexEntry.WriteIndexEntries(buffer, UpdateSequenceArrayOffset + updateSequenceArrayPaddedLength, IndexEntries); // Write UpdateSequenceNumber and UpdateSequenceReplacementData List <byte[]> updateSequenceReplacementData = MultiSectorHelper.EncodeSegmentBuffer(buffer, 0, bytesPerIndexRecord, UpdateSequenceNumber); MultiSectorHelper.WriteUpdateSequenceArray(buffer, UpdateSequenceArrayOffset, updateSequenceArraySize, UpdateSequenceNumber, updateSequenceReplacementData); return(buffer); }
/// <remarks> /// The USN will be written at the end of each 512-byte stride, even if the device has more (or less) than 512 bytes per sector. /// https://docs.microsoft.com/en-us/windows/desktop/DevNotes/multi-sector-header /// </remarks> public static void RevertUsaProtection(byte[] buffer, int offset) { MultiSectorHeader multiSectorHeader = new MultiSectorHeader(buffer, offset + 0x00); int position = offset + multiSectorHeader.UpdateSequenceArrayOffset; if (position > buffer.Length - 2) { throw new InvalidDataException("UpdateSequenceArrayOffset is out of range"); } uint updateSequenceNumber = LittleEndianReader.ReadUInt16(buffer, ref position); // First do validation check - make sure the USN matches on all sectors) for (int index = 0; index < multiSectorHeader.UpdateSequenceArraySize - 1; ++index) { if (updateSequenceNumber != LittleEndianConverter.ToUInt16(buffer, offset + (BytesPerStride * (index + 1)) - 2)) { throw new InvalidDataException("Corrupt multi-sector transfer, USN does not match MultiSectorHeader"); } } for (int index = 0; index < multiSectorHeader.UpdateSequenceArraySize - 1; index++) { byte[] endOfSectorBytes = ByteReader.ReadBytes(buffer, ref position, 2); ByteWriter.WriteBytes(buffer, offset + (BytesPerStride * (index + 1)) - 2, endOfSectorBytes); } }
/// <param name="segmentLength">This refers to the maximum length of FileRecord as defined in the Volume's BootRecord</param> public byte[] GetBytes(int bytesPerFileRecordSegment, ushort minorNTFSVersion) { int strideCount = bytesPerFileRecordSegment / MultiSectorHelper.BytesPerStride; ushort updateSequenceArraySize = (ushort)(1 + strideCount); ushort updateSequenceArrayOffset; if (minorNTFSVersion == 0) { updateSequenceArrayOffset = NTFS30UpdateSequenceArrayOffset; } else { updateSequenceArrayOffset = NTFS31UpdateSequenceArrayOffset; } MultiSectorHeader multiSectorHeader = new MultiSectorHeader(ValidSignature, updateSequenceArrayOffset, updateSequenceArraySize); ushort firstAttributeOffset = GetFirstAttributeOffset(bytesPerFileRecordSegment, minorNTFSVersion); byte[] buffer = new byte[bytesPerFileRecordSegment]; multiSectorHeader.WriteBytes(buffer, 0x00); LittleEndianWriter.WriteUInt64(buffer, 0x08, LogFileSequenceNumber); LittleEndianWriter.WriteUInt16(buffer, 0x10, m_sequenceNumber); LittleEndianWriter.WriteUInt16(buffer, 0x12, ReferenceCount); LittleEndianWriter.WriteUInt16(buffer, 0x14, firstAttributeOffset); LittleEndianWriter.WriteUInt16(buffer, 0x16, (ushort)m_flags); LittleEndianWriter.WriteInt32(buffer, 0x1C, bytesPerFileRecordSegment); m_baseFileRecordSegment.WriteBytes(buffer, 0x20); LittleEndianWriter.WriteUInt16(buffer, 0x28, NextAttributeInstance); if (minorNTFSVersion == 1) { LittleEndianWriter.WriteUInt32(buffer, 0x2C, (uint)m_segmentNumber); } // write attributes int position = firstAttributeOffset; foreach (AttributeRecord attribute in m_immediateAttributes) { byte[] attributeBytes = attribute.GetBytes(); ByteWriter.WriteBytes(buffer, position, attributeBytes); position += attributeBytes.Length; } byte[] marker = GetEndMarker(); ByteWriter.WriteBytes(buffer, position, marker); position += marker.Length; position += 4; // record (length) is aligned to 8-byte boundary uint segmentLength = (uint)position; LittleEndianWriter.WriteUInt32(buffer, 0x18, segmentLength); // Write UpdateSequenceNumber and UpdateSequenceReplacementData List <byte[]> updateSequenceReplacementData = MultiSectorHelper.EncodeSegmentBuffer(buffer, 0, bytesPerFileRecordSegment, UpdateSequenceNumber); MultiSectorHelper.WriteUpdateSequenceArray(buffer, updateSequenceArrayOffset, updateSequenceArraySize, UpdateSequenceNumber, updateSequenceReplacementData); return(buffer); }
public byte[] GetBytes(int bytesPerSystemPage, bool applyUsaProtection) { m_systemPageSize = (uint)bytesPerSystemPage; int strideCount = bytesPerSystemPage / MultiSectorHelper.BytesPerStride; ushort updateSequenceArraySize = (ushort)(1 + strideCount); MultiSectorHeader multiSectorHeader = new MultiSectorHeader(ValidSignature, UpdateSequenceArrayOffset, updateSequenceArraySize); int restartOffset = (int)Math.Ceiling((double)(UpdateSequenceArrayOffset + updateSequenceArraySize * 2) / 8) * 8; byte[] buffer = new byte[bytesPerSystemPage]; multiSectorHeader.WriteBytes(buffer, 0); LittleEndianWriter.WriteUInt64(buffer, 0x08, ChkDskLsn); LittleEndianWriter.WriteUInt32(buffer, 0x10, m_systemPageSize); LittleEndianWriter.WriteUInt32(buffer, 0x14, LogPageSize); LittleEndianWriter.WriteUInt16(buffer, 0x18, (ushort)restartOffset); LittleEndianWriter.WriteInt16(buffer, 0x1A, MinorVersion); LittleEndianWriter.WriteInt16(buffer, 0x1C, MajorVersion); LittleEndianWriter.WriteUInt16(buffer, UpdateSequenceArrayOffset, UpdateSequenceNumber); RestartArea.WriteBytes(buffer, restartOffset); if (applyUsaProtection) { MultiSectorHelper.ApplyUsaProtection(buffer, 0); } return(buffer); }
public static void ApplyUsaProtection(byte[] buffer, int offset) { MultiSectorHeader multiSectorHeader = new MultiSectorHeader(buffer, offset + 0x00); int position = offset + multiSectorHeader.UpdateSequenceArrayOffset; ushort updateSequenceNumber = LittleEndianReader.ReadUInt16(buffer, ref position); for (int index = 0; index < multiSectorHeader.UpdateSequenceArraySize - 1; index++) { // Read in the bytes that are replaced by the USN byte[] endOfSectorBytes = ByteReader.ReadBytes(buffer, offset + (BytesPerStride * (index + 1)) - 2, 2); // Relocate the bytes that are replaced by the USN ByteWriter.WriteBytes(buffer, ref position, endOfSectorBytes); // Write the USN LittleEndianWriter.WriteUInt16(buffer, offset + (BytesPerStride * (index + 1)) - 2, updateSequenceNumber); } }
public IndexRecord(byte[] buffer, int offset) { MultiSectorHeader multiSectorHeader = new MultiSectorHeader(buffer, offset + 0x00); if (multiSectorHeader.Signature != ValidSignature) { throw new InvalidDataException("Invalid INDX record signature"); } LogFileSequenceNumber = LittleEndianConverter.ToUInt64(buffer, offset + 0x08); RecordVBN = (long)LittleEndianConverter.ToUInt64(buffer, offset + 0x10); m_indexHeader = new IndexHeader(buffer, offset + 0x18); UpdateSequenceNumber = LittleEndianConverter.ToUInt16(buffer, offset + multiSectorHeader.UpdateSequenceArrayOffset); int entriesOffset = 0x18 + (int)m_indexHeader.EntriesOffset; IndexEntries = IndexEntry.ReadIndexEntries(buffer, entriesOffset); }
public FileRecordSegment(byte[] buffer, int offset, long segmentNumber) { MultiSectorHeader multiSectorHeader = new MultiSectorHeader(buffer, offset + 0x00); if (multiSectorHeader.Signature != ValidSignature) { throw new InvalidDataException("Invalid FILE record signature"); } LogFileSequenceNumber = LittleEndianConverter.ToUInt64(buffer, offset + 0x08); m_sequenceNumber = LittleEndianConverter.ToUInt16(buffer, offset + 0x10); ReferenceCount = LittleEndianConverter.ToUInt16(buffer, offset + 0x12); ushort firstAttributeOffset = LittleEndianConverter.ToUInt16(buffer, offset + 0x14); m_flags = (FileRecordFlags)LittleEndianConverter.ToUInt16(buffer, offset + 0x16); uint segmentLength = LittleEndianConverter.ToUInt32(buffer, offset + 0x18); uint segmentAllocatedLength = LittleEndianConverter.ToUInt32(buffer, offset + 0x1C); m_baseFileRecordSegment = new MftSegmentReference(buffer, offset + 0x20); NextAttributeInstance = LittleEndianConverter.ToUInt16(buffer, offset + 0x28); // 2 bytes padding m_segmentNumberOnDisk = LittleEndianConverter.ToUInt32(buffer, offset + 0x2C); UpdateSequenceNumber = LittleEndianConverter.ToUInt16(buffer, offset + multiSectorHeader.UpdateSequenceArrayOffset); if (firstAttributeOffset % 8 > 0) { throw new InvalidDataException("Corrupt file record segment, first attribute not aligned to 8-byte boundary"); } // Read attributes int position = offset + firstAttributeOffset; while (!IsEndMarker(buffer, position)) { AttributeRecord attribute = AttributeRecord.FromBytes(buffer, position); m_immediateAttributes.Add(attribute); position += (int)attribute.RecordLengthOnDisk; if (position > buffer.Length) { throw new InvalidDataException("Invalid attribute length"); } } m_segmentNumber = segmentNumber; }
public LfsRestartPage(byte[] buffer, int offset) { MultiSectorHeader multiSectorHeader = new MultiSectorHeader(buffer, offset + 0x00); if (multiSectorHeader.Signature != ValidSignature && multiSectorHeader.Signature != ModifiedSignature) { throw new InvalidDataException("Invalid RSTR record signature"); } ChkDskLsn = LittleEndianConverter.ToUInt64(buffer, offset + 0x08); m_systemPageSize = LittleEndianConverter.ToUInt32(buffer, offset + 0x10); LogPageSize = LittleEndianConverter.ToUInt32(buffer, offset + 0x14); ushort restartOffset = LittleEndianConverter.ToUInt16(buffer, offset + 0x18); MinorVersion = LittleEndianConverter.ToInt16(buffer, offset + 0x1A); MajorVersion = LittleEndianConverter.ToInt16(buffer, offset + 0x1C); UpdateSequenceNumber = LittleEndianConverter.ToUInt16(buffer, offset + multiSectorHeader.UpdateSequenceArrayOffset); RestartArea = new LfsRestartArea(buffer, offset + restartOffset); }
public LfsRecordPage(byte[] pageBytes, int dataOffset) { MultiSectorHeader multiSectorHeader = new MultiSectorHeader(pageBytes, 0x00); if (multiSectorHeader.Signature != ValidSignature) { throw new InvalidDataException("Invalid RCRD record signature"); } LastLsnOrFileOffset = LittleEndianConverter.ToUInt64(pageBytes, 0x08); Flags = (LfsRecordPageFlags)LittleEndianConverter.ToUInt32(pageBytes, 0x10); PageCount = LittleEndianConverter.ToUInt16(pageBytes, 0x14); PagePosition = LittleEndianConverter.ToUInt16(pageBytes, 0x16); NextRecordOffset = LittleEndianConverter.ToUInt16(pageBytes, 0x18); LastEndLsn = LittleEndianConverter.ToUInt64(pageBytes, 0x20); UpdateSequenceNumber = LittleEndianConverter.ToUInt16(pageBytes, multiSectorHeader.UpdateSequenceArrayOffset); Data = ByteReader.ReadBytes(pageBytes, dataOffset, pageBytes.Length - dataOffset); m_dataOffset = dataOffset; }
public LogRestartPage(byte[] buffer, int offset) { MultiSectorHeader multiSectorHeader = new MultiSectorHeader(buffer, offset + 0x00); if (multiSectorHeader.Signature != ValidSignature) { throw new InvalidDataException("Invalid RSTR record signature"); } ChkDskLsn = LittleEndianConverter.ToUInt64(buffer, offset + 0x08); m_systemPageSize = LittleEndianConverter.ToUInt32(buffer, offset + 0x10); LogPageSize = LittleEndianConverter.ToUInt32(buffer, offset + 0x14); ushort restartOffset = LittleEndianConverter.ToUInt16(buffer, offset + 0x18); MinorVersion = LittleEndianConverter.ToInt16(buffer, offset + 0x1A); MajorVersion = LittleEndianConverter.ToInt16(buffer, offset + 0x1C); int position = offset + multiSectorHeader.UpdateSequenceArrayOffset; List <byte[]> updateSequenceReplacementData = MultiSectorHelper.ReadUpdateSequenceArray(buffer, position, multiSectorHeader.UpdateSequenceArraySize, out UpdateSequenceNumber); MultiSectorHelper.DecodeSegmentBuffer(buffer, offset, UpdateSequenceNumber, updateSequenceReplacementData); LogRestartArea = new LogRestartArea(buffer, offset + restartOffset); }
public IndexRecord(byte[] buffer, int offset) { MultiSectorHeader multiSectorHeader = new MultiSectorHeader(buffer, offset + 0x00); if (multiSectorHeader.Signature != ValidSignature) { throw new InvalidDataException("Invalid INDX record signature"); } LogFileSequenceNumber = LittleEndianConverter.ToUInt64(buffer, offset + 0x08); RecordVBN = (long)LittleEndianConverter.ToUInt64(buffer, offset + 0x10); m_indexHeader = new IndexHeader(buffer, offset + 0x18); int position = offset + multiSectorHeader.UpdateSequenceArrayOffset; List <byte[]> updateSequenceReplacementData = MultiSectorHelper.ReadUpdateSequenceArray(buffer, position, multiSectorHeader.UpdateSequenceArraySize, out UpdateSequenceNumber); MultiSectorHelper.DecodeSegmentBuffer(buffer, offset, UpdateSequenceNumber, updateSequenceReplacementData); int entriesOffset = 0x18 + (int)m_indexHeader.EntriesOffset; IndexEntries = IndexEntry.ReadIndexEntries(buffer, entriesOffset); }
public LogRecordPage(byte[] buffer, int offset, int dataOffset) { MultiSectorHeader multiSectorHeader = new MultiSectorHeader(buffer, offset + 0x00); if (multiSectorHeader.Signature != ValidSignature) { throw new InvalidDataException("Invalid RCRD record signature"); } LastLsnOrFileOffset = LittleEndianConverter.ToUInt64(buffer, offset + 0x08); Flags = (LogRecordPageFlags)LittleEndianConverter.ToUInt32(buffer, offset + 0x10); PageCount = LittleEndianConverter.ToUInt16(buffer, offset + 0x14); PagePosition = LittleEndianConverter.ToUInt16(buffer, offset + 0x16); ushort nextRecordOffset = LittleEndianConverter.ToUInt16(buffer, offset + 0x18); LastEndLsn = LittleEndianConverter.ToUInt64(buffer, offset + 0x20); int position = offset + multiSectorHeader.UpdateSequenceArrayOffset; List <byte[]> updateSequenceReplacementData = MultiSectorHelper.ReadUpdateSequenceArray(buffer, position, multiSectorHeader.UpdateSequenceArraySize, out UpdateSequenceNumber); MultiSectorHelper.DecodeSegmentBuffer(buffer, offset, UpdateSequenceNumber, updateSequenceReplacementData); Data = ByteReader.ReadBytes(buffer, offset + dataOffset, (int)(nextRecordOffset - dataOffset)); }
public byte[] GetBytes(int bytesPerLogPage, int dataOffset) { int strideCount = bytesPerLogPage / MultiSectorHelper.BytesPerStride; ushort updateSequenceArraySize = (ushort)(1 + strideCount); MultiSectorHeader multiSectorHeader = new MultiSectorHeader(ValidSignature, UpdateSequenceArrayOffset, updateSequenceArraySize); ushort nextRecordOffset = (ushort)(dataOffset + Data.Length); byte[] buffer = new byte[bytesPerLogPage]; multiSectorHeader.WriteBytes(buffer, 0); LittleEndianWriter.WriteUInt64(buffer, 0x08, LastLsnOrFileOffset); LittleEndianWriter.WriteUInt32(buffer, 0x10, (uint)Flags); LittleEndianWriter.WriteUInt16(buffer, 0x14, PageCount); LittleEndianWriter.WriteUInt16(buffer, 0x16, PagePosition); LittleEndianWriter.WriteUInt16(buffer, 0x18, nextRecordOffset); LittleEndianWriter.WriteUInt64(buffer, 0x20, LastEndLsn); ByteWriter.WriteBytes(buffer, dataOffset, Data); // Write UpdateSequenceNumber and UpdateSequenceReplacementData List <byte[]> updateSequenceReplacementData = MultiSectorHelper.EncodeSegmentBuffer(buffer, 0, bytesPerLogPage, UpdateSequenceNumber); MultiSectorHelper.WriteUpdateSequenceArray(buffer, UpdateSequenceArrayOffset, updateSequenceArraySize, UpdateSequenceNumber, updateSequenceReplacementData); return(buffer); }
public byte[] GetBytes(int bytesPerLogPage, bool applyUsaProtection) { int strideCount = bytesPerLogPage / MultiSectorHelper.BytesPerStride; ushort updateSequenceArraySize = (ushort)(1 + strideCount); MultiSectorHeader multiSectorHeader = new MultiSectorHeader(ValidSignature, UpdateSequenceArrayOffset, updateSequenceArraySize); byte[] buffer = new byte[bytesPerLogPage]; multiSectorHeader.WriteBytes(buffer, 0); LittleEndianWriter.WriteUInt64(buffer, 0x08, LastLsnOrFileOffset); LittleEndianWriter.WriteUInt32(buffer, 0x10, (uint)Flags); LittleEndianWriter.WriteUInt16(buffer, 0x14, PageCount); LittleEndianWriter.WriteUInt16(buffer, 0x16, PagePosition); LittleEndianWriter.WriteUInt16(buffer, 0x18, NextRecordOffset); LittleEndianWriter.WriteUInt64(buffer, 0x20, LastEndLsn); LittleEndianWriter.WriteUInt16(buffer, UpdateSequenceArrayOffset, UpdateSequenceNumber); ByteWriter.WriteBytes(buffer, m_dataOffset, Data); if (applyUsaProtection) { MultiSectorHelper.ApplyUsaProtection(buffer, 0); } return(buffer); }
public byte[] GetBytes(int bytesPerSystemPage) { m_systemPageSize = (uint)bytesPerSystemPage; int strideCount = bytesPerSystemPage / MultiSectorHelper.BytesPerStride; ushort updateSequenceArraySize = (ushort)(1 + strideCount); MultiSectorHeader multiSectorHeader = new MultiSectorHeader(ValidSignature, UpdateSequenceArrayOffset, updateSequenceArraySize); int restartOffset = (int)Math.Ceiling((double)(UpdateSequenceArrayOffset + updateSequenceArraySize * 2) / 8) * 8; byte[] buffer = new byte[bytesPerSystemPage]; multiSectorHeader.WriteBytes(buffer, 0); LittleEndianWriter.WriteUInt64(buffer, 0x08, ChkDskLsn); LittleEndianWriter.WriteUInt32(buffer, 0x10, m_systemPageSize); LittleEndianWriter.WriteUInt32(buffer, 0x14, LogPageSize); LittleEndianWriter.WriteUInt16(buffer, 0x18, (ushort)restartOffset); LittleEndianWriter.WriteInt16(buffer, 0x1A, MinorVersion); LittleEndianWriter.WriteInt16(buffer, 0x1C, MajorVersion); LogRestartArea.WriteBytes(buffer, restartOffset); // Write UpdateSequenceNumber and UpdateSequenceReplacementData List <byte[]> updateSequenceReplacementData = MultiSectorHelper.EncodeSegmentBuffer(buffer, 0, bytesPerSystemPage, UpdateSequenceNumber); MultiSectorHelper.WriteUpdateSequenceArray(buffer, UpdateSequenceArrayOffset, updateSequenceArraySize, UpdateSequenceNumber, updateSequenceReplacementData); return(buffer); }
public byte[] GetBytes(int bytesPerFileRecordSegment, ushort minorNTFSVersion, bool applyUsaProtection) { int strideCount = bytesPerFileRecordSegment / MultiSectorHelper.BytesPerStride; ushort updateSequenceArraySize = (ushort)(1 + strideCount); ushort updateSequenceArrayOffset; if (minorNTFSVersion == 0) { updateSequenceArrayOffset = NTFS30UpdateSequenceArrayOffset; } else { updateSequenceArrayOffset = NTFS31UpdateSequenceArrayOffset; } MultiSectorHeader multiSectorHeader = new MultiSectorHeader(ValidSignature, updateSequenceArrayOffset, updateSequenceArraySize); ushort firstAttributeOffset = GetFirstAttributeOffset(bytesPerFileRecordSegment, minorNTFSVersion); int length = applyUsaProtection ? bytesPerFileRecordSegment : GetNumberOfBytesInUse(bytesPerFileRecordSegment, minorNTFSVersion); byte[] buffer = new byte[length]; multiSectorHeader.WriteBytes(buffer, 0x00); LittleEndianWriter.WriteUInt64(buffer, 0x08, LogFileSequenceNumber); LittleEndianWriter.WriteUInt16(buffer, 0x10, m_sequenceNumber); LittleEndianWriter.WriteUInt16(buffer, 0x12, ReferenceCount); LittleEndianWriter.WriteUInt16(buffer, 0x14, firstAttributeOffset); LittleEndianWriter.WriteUInt16(buffer, 0x16, (ushort)m_flags); LittleEndianWriter.WriteInt32(buffer, 0x1C, bytesPerFileRecordSegment); m_baseFileRecordSegment.WriteBytes(buffer, 0x20); LittleEndianWriter.WriteUInt16(buffer, 0x28, NextAttributeInstance); if (minorNTFSVersion == 1) { LittleEndianWriter.WriteUInt32(buffer, 0x2C, (uint)m_segmentNumber); } LittleEndianWriter.WriteUInt32(buffer, updateSequenceArrayOffset, UpdateSequenceNumber); // write attributes int position = firstAttributeOffset; foreach (AttributeRecord attribute in m_immediateAttributes) { byte[] attributeBytes = attribute.GetBytes(); ByteWriter.WriteBytes(buffer, position, attributeBytes); position += attributeBytes.Length; } LittleEndianWriter.WriteUInt32(buffer, position, AttributesEndMarker); position += AttributesEndMarkerLength; // End marker + alignment to 8-byte boundary uint segmentLength = (uint)position; LittleEndianWriter.WriteUInt32(buffer, 0x18, segmentLength); if (applyUsaProtection) { MultiSectorHelper.ApplyUsaProtection(buffer, 0); } return(buffer); }