public FileRecordSegment(byte[] buffer, int offset, int bytesPerSector, long segmentNumber) { Signature = ByteReader.ReadAnsiString(buffer, offset + 0x00, 4); ushort updateSequenceArrayOffset = LittleEndianConverter.ToUInt16(buffer, offset + 0x04); ushort updateSequenceArraySize = LittleEndianConverter.ToUInt16(buffer, offset + 0x06); LogFileSequenceNumber = LittleEndianConverter.ToUInt64(buffer, offset + 0x08); SequenceNumber = LittleEndianConverter.ToUInt16(buffer, offset + 0x10); HardLinkCount = LittleEndianConverter.ToUInt16(buffer, offset + 0x12); ushort firstAttributeOffset = LittleEndianConverter.ToUInt16(buffer, offset + 0x14); m_flags = (FileRecordFlags)LittleEndianConverter.ToUInt16(buffer, offset + 0x16); uint segmentRealSize = LittleEndianConverter.ToUInt32(buffer, offset + 0x18); uint segmentAllocatedSize = LittleEndianConverter.ToUInt32(buffer, offset + 0x1C); BaseFileRecordSegmentNumber = LittleEndianConverter.ToUInt64(buffer, offset + 0x20); NextAttributeId = LittleEndianConverter.ToUInt16(buffer, offset + 0x28); // 2 zeros - padding MftSegmentNumberXP = LittleEndianConverter.ToUInt32(buffer, offset + 0x2C); // There is an UpdateSequenceNumber for the FileRecordSegment, // and an entry in the UpdateSequenceArray for each sector of the record // The last two bytes of each sector contains this entry for integrity-check purposes int position = offset + updateSequenceArrayOffset; UpdateSequenceNumber = LittleEndianConverter.ToUInt16(buffer, position); position += 2; // This stores the data that was supposed to be placed at the end of each sector, and was replaced with an UpdateSequenceNumber List <byte[]> updateSequenceReplacementData = new List <byte[]>(); for (int index = 0; index < updateSequenceArraySize - 1; index++) { byte[] endOfSectorBytes = new byte[2]; endOfSectorBytes[0] = buffer[position + 0]; endOfSectorBytes[1] = buffer[position + 1]; updateSequenceReplacementData.Add(endOfSectorBytes); position += 2; } MultiSectorHelper.DecodeSegmentBuffer(buffer, offset, UpdateSequenceNumber, updateSequenceReplacementData); // read attributes position = offset + firstAttributeOffset; while (!IsEndMarker(buffer, position)) { AttributeRecord attribute = AttributeRecord.FromBytes(buffer, position); m_immediateAttributes.Add(attribute); position += (int)attribute.StoredRecordLength; if (position > buffer.Length) { throw new InvalidDataException("Improper attribute length"); } } m_mftSegmentNumber = segmentNumber; }
public IndexRecord(byte[] buffer, int offset) { Signature = ByteReader.ReadAnsiString(buffer, offset + 0x00, 4); if (Signature != ValidSignature) { throw new InvalidDataException("Invalid INDX record signature"); } ushort updateSequenceArrayOffset = LittleEndianConverter.ToUInt16(buffer, offset + 0x04); ushort updateSequenceArraySize = LittleEndianConverter.ToUInt16(buffer, offset + 0x06); LogFileSequenceNumber = LittleEndianConverter.ToUInt64(buffer, offset + 0x08); RecordVCN = LittleEndianConverter.ToUInt64(buffer, offset + 0x10); EntriesOffset = LittleEndianConverter.ToUInt32(buffer, offset + 0x18); IndexLength = LittleEndianConverter.ToUInt32(buffer, offset + 0x1C); AllocatedLength = LittleEndianConverter.ToUInt32(buffer, offset + 0x20); HasChildren = ByteReader.ReadByte(buffer, offset + 0x24) > 0; int position = offset + updateSequenceArrayOffset; UpdateSequenceNumber = LittleEndianConverter.ToUInt16(buffer, position); position += 2; List <byte[]> updateSequenceReplacementData = new List <byte[]>(); for (int index = 0; index < updateSequenceArraySize - 1; index++) { byte[] endOfSectorBytes = new byte[2]; endOfSectorBytes[0] = buffer[position + 0]; endOfSectorBytes[1] = buffer[position + 1]; updateSequenceReplacementData.Add(endOfSectorBytes); position += 2; } MultiSectorHelper.DecodeSegmentBuffer(buffer, offset, UpdateSequenceNumber, updateSequenceReplacementData); position = 0x18 + (int)EntriesOffset; if (HasChildren) { IndexNode node = new IndexNode(buffer, position); IndexEntries = node.Entries; } else { FileNameIndexLeafNode leaf = new FileNameIndexLeafNode(buffer, position); FileNameEntries = leaf.Entries; } }
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); int position = offset + multiSectorHeader.UpdateSequenceArrayOffset; List <byte[]> updateSequenceReplacementData = MultiSectorHelper.ReadUpdateSequenceArray(buffer, position, multiSectorHeader.UpdateSequenceArraySize, out UpdateSequenceNumber); MultiSectorHelper.DecodeSegmentBuffer(buffer, offset, UpdateSequenceNumber, updateSequenceReplacementData); // Read attributes 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 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 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); }