public static bool IsTargetAttributeRequired(NTFSLogOperation operation) { switch (operation) { case NTFSLogOperation.Noop: case NTFSLogOperation.CompensationLogRecord: case NTFSLogOperation.DeleteDirtyClusters: case NTFSLogOperation.EndTopLevelAction: case NTFSLogOperation.PrepareTransaction: case NTFSLogOperation.CommitTransaction: case NTFSLogOperation.ForgetTransaction: case NTFSLogOperation.OpenAttributeTableDump: case NTFSLogOperation.AttributeNamesDump: case NTFSLogOperation.DirtyPageTableDump: case NTFSLogOperation.TransactionTableDump: return(false); default: return(true); } }
public NTFSLogRecord(byte[] recordBytes) { RedoOperation = (NTFSLogOperation)LittleEndianConverter.ToUInt16(recordBytes, 0x00); UndoOperation = (NTFSLogOperation)LittleEndianConverter.ToUInt16(recordBytes, 0x02); ushort redoOffset = LittleEndianConverter.ToUInt16(recordBytes, 0x04); ushort redoLength = LittleEndianConverter.ToUInt16(recordBytes, 0x06); ushort undoOffset = LittleEndianConverter.ToUInt16(recordBytes, 0x08); ushort undoLength = LittleEndianConverter.ToUInt16(recordBytes, 0x0A); TargetAttributeIndex = LittleEndianConverter.ToUInt16(recordBytes, 0x0C); ushort lcnsToFollow = LittleEndianConverter.ToUInt16(recordBytes, 0x0E); RecordOffset = LittleEndianConverter.ToUInt16(recordBytes, 0x10); AttributeOffset = LittleEndianConverter.ToUInt16(recordBytes, 0x12); ClusterBlockOffset = LittleEndianConverter.ToUInt16(recordBytes, 0x14); Reserved = LittleEndianConverter.ToUInt16(recordBytes, 0x16); TargetVCN = (long)LittleEndianConverter.ToUInt64(recordBytes, 0x18); for (int index = 0; index < lcnsToFollow; index++) { long lcn = (long)LittleEndianConverter.ToUInt64(recordBytes, 0x20 + index * 8); LCNsForPage.Add(lcn); } /*int dataOffset = 0x20 + lcnsToFollow * 8; * int dataLength = recordBytes.Length - dataOffset;*/ RedoData = ByteReader.ReadBytes(recordBytes, redoOffset, redoLength); if (undoOffset == redoOffset && undoLength == redoLength) { UndoData = RedoData; } else if (UndoOperation != NTFSLogOperation.CompensationLogRecord) { UndoData = ByteReader.ReadBytes(recordBytes, undoOffset, undoLength); } else { // This record is logging the undo of a previous operation (e.g. when aborting a transaction) UndoData = new byte[0]; } }
private LfsRecord WriteLogRecord(int openAttributeOffset, ulong streamOffset, int recordOffset, int attributeOffset, List <long> lcnList, NTFSLogOperation redoOperation, byte[] redoData, NTFSLogOperation undoOperation, byte[] undoData, uint transactionID, bool flushToDisk) { NTFSLogRecord ntfsLogRecord = new NTFSLogRecord(); ntfsLogRecord.TargetAttributeOffset = (ushort)openAttributeOffset; ntfsLogRecord.RedoOperation = redoOperation; ntfsLogRecord.RedoData = redoData; ntfsLogRecord.UndoOperation = undoOperation; ntfsLogRecord.UndoData = undoData; ntfsLogRecord.TargetVCN = (long)(streamOffset / (uint)Volume.BytesPerCluster); ntfsLogRecord.LCNsForPage.AddRange(lcnList); int offsetInCluster = (int)(streamOffset % (uint)Volume.BytesPerCluster); ntfsLogRecord.RecordOffset = (ushort)recordOffset; ntfsLogRecord.AttributeOffset = (ushort)attributeOffset; ntfsLogRecord.ClusterBlockOffset = (ushort)(offsetInCluster / NTFSLogRecord.BytesPerLogBlock); return(WriteLogRecord(ntfsLogRecord, transactionID, flushToDisk)); }
public LfsRecord WriteLogRecord(MftSegmentReference fileReference, AttributeRecord attributeRecord, ulong streamOffset, int structureLength, int recordOffset, int attributeOffset, NTFSLogOperation redoOperation, byte[] redoData, NTFSLogOperation undoOperation, byte[] undoData, uint transactionID, bool flushToDisk) { int openAttributeOffset = 0; if (fileReference != null) { int openAttributeIndex = IndexOfOpenAttribute(fileReference, attributeRecord.AttributeType, attributeRecord.Name); if (openAttributeIndex == -1) { openAttributeIndex = AddToOpenAttributeTable(fileReference, attributeRecord.AttributeType, attributeRecord.Name, m_lastClientLsn); m_openAttributes[openAttributeIndex].AssociatedTransactions.Add(transactionID); openAttributeOffset = OpenAttributeIndexToOffset(openAttributeIndex); OpenAttributeEntry entry = new OpenAttributeEntry(m_majorVersion); entry.AllocatedOrNextFree = RestartTableEntry.RestartEntryAllocated; // Note: NTFS v5.1 driver calulates AttributeOffset using entry length of 0x28, the reason is unclear but we're immitating this. entry.AttributeOffset = (uint)(RestartTableHeader.Length + openAttributeIndex * OpenAttributeEntry.LengthV1); entry.FileReference = fileReference; entry.LsnOfOpenRecord = m_lastClientLsn; entry.AttributeTypeCode = attributeRecord.AttributeType; if (attributeRecord.AttributeType == AttributeType.IndexAllocation) { entry.BytesPerIndexBuffer = (uint)Volume.BytesPerIndexRecord; } byte[] openAttributeBytes = entry.GetBytes(); byte[] attributeNameBytes = System.Text.Encoding.Unicode.GetBytes(attributeRecord.Name); LfsRecord openAttributeRecord = WriteLogRecord(openAttributeOffset, 0, 0, 0, new List <long>(), NTFSLogOperation.OpenNonResidentAttribute, openAttributeBytes, NTFSLogOperation.Noop, attributeNameBytes, transactionID, false); } else { openAttributeOffset = OpenAttributeIndexToOffset(openAttributeIndex); if (!m_openAttributes[openAttributeIndex].AssociatedTransactions.Contains(transactionID)) { m_openAttributes[openAttributeIndex].AssociatedTransactions.Add(transactionID); } } } List <long> lcnList = new List <long>(); if (attributeRecord is NonResidentAttributeRecord) { long startVCN = (long)(streamOffset / (uint)Volume.BytesPerCluster); int clusterCount = (int)Math.Ceiling((double)structureLength / Volume.BytesPerCluster); for (long vcn = startVCN; vcn < startVCN + clusterCount; vcn++) { long lcn = ((NonResidentAttributeRecord)attributeRecord).DataRunSequence.GetDataClusterLCN(vcn); lcnList.Add(lcn); } } return(WriteLogRecord(openAttributeOffset, streamOffset, recordOffset, attributeOffset, lcnList, redoOperation, redoData, undoOperation, undoData, transactionID, flushToDisk)); }
public LfsRecord WriteLogRecord(MftSegmentReference fileReference, AttributeRecord attributeRecord, ulong streamOffset, int structureLength, NTFSLogOperation redoOperation, byte[] redoData, NTFSLogOperation undoOperation, byte[] undoData, uint transactionID) { return(WriteLogRecord(fileReference, attributeRecord, streamOffset, structureLength, 0, 0, redoOperation, redoData, undoOperation, undoData, transactionID, true)); }