Пример #1
0
        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);
            }
        }
Пример #2
0
        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];
            }
        }
Пример #3
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));
        }
Пример #4
0
        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));
        }
Пример #5
0
 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));
 }