예제 #1
0
        public LfsRestartArea(byte[] buffer, int offset)
        {
            CurrentLsn = LittleEndianConverter.ToUInt64(buffer, offset + 0x00);
            ushort logClients = LittleEndianConverter.ToUInt16(buffer, offset + 0x08);

            ClientFreeList    = LittleEndianConverter.ToUInt16(buffer, offset + 0x0A);
            ClientInUseList   = LittleEndianConverter.ToUInt16(buffer, offset + 0x0C);
            Flags             = (LfsRestartFlags)LittleEndianConverter.ToUInt16(buffer, offset + 0x0E);
            SeqNumberBits     = LittleEndianConverter.ToUInt32(buffer, offset + 0x10);
            RestartAreaLength = LittleEndianConverter.ToUInt16(buffer, offset + 0x14);
            ushort clientArrayOffset = LittleEndianConverter.ToUInt16(buffer, offset + 0x16);

            FileSize           = LittleEndianConverter.ToUInt32(buffer, offset + 0x18);
            LastLsnDataLength  = LittleEndianConverter.ToUInt32(buffer, offset + 0x20);
            RecordHeaderLength = LittleEndianConverter.ToUInt16(buffer, offset + 0x24);
            LogPageDataOffset  = LittleEndianConverter.ToUInt16(buffer, offset + 0x26);
            if (clientArrayOffset >= 0x30)
            {
                RevisionNumber = LittleEndianConverter.ToUInt32(buffer, offset + 0x28);
            }
            int position = offset + clientArrayOffset;

            for (int index = 0; index < logClients; index++)
            {
                LfsClientRecord clientRecord = new LfsClientRecord(buffer, position);
                LogClientArray.Add(clientRecord);
                position += clientRecord.Length;
            }
        }
예제 #2
0
        private LfsRecord WriteRestartRecord(ulong usnJournalUnknown1, ulong previousRestartRecordLsn, MftSegmentReference usnJournal, ulong usnJournalUnknown2, bool isClean)
        {
            NTFSRestartRecord restartRecord = new NTFSRestartRecord(m_majorVersion, m_minorVersion);

            restartRecord.StartOfCheckpointLsn     = m_lastClientLsn;
            restartRecord.UsnJournalUnknown1       = usnJournalUnknown1;
            restartRecord.PreviousRestartRecordLsn = previousRestartRecordLsn;
            restartRecord.BytesPerCluster          = (uint)Volume.BytesPerCluster;
            restartRecord.UsnJournal         = usnJournal;
            restartRecord.UsnJournalUnknown2 = usnJournalUnknown2;
            if (isClean)
            {
                if (m_transactions.Count > 0)
                {
                    throw new InvalidOperationException("All TransactionIDs must be deallocated before writing a clean restart record");
                }
            }
            else
            {
                foreach (Transaction transaction in m_transactions)
                {
                    if (transaction.OldestLsn != 0 && transaction.OldestLsn < restartRecord.StartOfCheckpointLsn)
                    {
                        restartRecord.StartOfCheckpointLsn = transaction.OldestLsn;
                    }
                }

                if (m_openAttributes.Count > 0)
                {
                    byte[] attributeNameTableBytes;
                    byte[] openAttributeTableBytes = GetOpenAttributeTableBytes(out attributeNameTableBytes);
                    m_lastClientLsn = 0;
                    uint      transactionID            = AllocateTransactionID(); // These records must have a valid transactionID
                    LfsRecord openAttributeTableRecord = WriteLogRecord(null, null, 0, 0, 0, 0, NTFSLogOperation.OpenAttributeTableDump, openAttributeTableBytes, NTFSLogOperation.Noop, new byte[0], transactionID, false);
                    restartRecord.OpenAttributeTableLsn    = openAttributeTableRecord.ThisLsn;
                    restartRecord.OpenAttributeTableLength = (uint)openAttributeTableBytes.Length;
                    if (attributeNameTableBytes != null)
                    {
                        LfsRecord attributeNameTableRecord = WriteLogRecord(null, null, 0, 0, 0, 0, NTFSLogOperation.AttributeNamesDump, attributeNameTableBytes, NTFSLogOperation.Noop, new byte[0], transactionID, false);
                        restartRecord.AttributeNamesLsn    = attributeNameTableRecord.ThisLsn;
                        restartRecord.AttributeNamesLength = (uint)attributeNameTableBytes.Length;
                    }
                    DeallocateTransactionID(transactionID);
                }
            }
            byte[]    clientData = restartRecord.GetBytes(Volume.MajorVersion);
            LfsRecord result     = m_logFile.WriteRecord(m_clientIndex, LfsRecordType.ClientRestart, 0, 0, 0, clientData, true);

            m_lastClientLsn = result.ThisLsn;
            LfsClientRecord clientRecord = m_logFile.GetClientRecord(m_clientIndex);

            clientRecord.OldestLsn        = restartRecord.StartOfCheckpointLsn;
            clientRecord.ClientRestartLsn = result.ThisLsn;
            // Note that writing a client restart record without also updating ClientRestartLsn has no effect.
            // During the analysis pass, the NTFS v5.1 driver will use ClientRestartLsn in the most recent restart page to determine
            // the StartOfCheckpointLsn that the scan should start from, any client restart record that is found during the scan will be ignored.
            m_logFile.WriteRestartPage(isClean);
            m_currentRestartRecord = restartRecord;
            return(result);
        }
예제 #3
0
        private LfsRecord WriteRestartRecord(ulong previousRestartRecordLsn, MftSegmentReference usnJournal, ushort majorNTFSVersion, bool isClean)
        {
            NTFSRestartRecord restartRecord = new NTFSRestartRecord(m_majorVersion, m_minorVersion);

            restartRecord.StartOfCheckpointLsn     = m_lastClientLsn;
            restartRecord.PreviousRestartRecordLsn = previousRestartRecordLsn;
            if (isClean)
            {
                if (m_transactions.Count > 0)
                {
                    throw new InvalidOperationException("All TransactionIDs must be deallocated before writing a clean restart record");
                }
            }
            else if (m_openAttributes.Count > 0)
            {
                byte[] attributeNameTableBytes;
                byte[] openAttributeTableBytes = GetOpenAttributeTableBytes(out attributeNameTableBytes);
                m_lastClientLsn = 0;
                uint      transactionID            = AllocateTransactionID(); // These records must have a valid transactionID
                LfsRecord openAttributeTableRecord = WriteLogRecord(null, null, 0, NTFSLogOperation.OpenAttributeTableDump, openAttributeTableBytes, NTFSLogOperation.Noop, new byte[0], transactionID);
                restartRecord.OpenAttributeTableLsn    = openAttributeTableRecord.ThisLsn;
                restartRecord.OpenAttributeTableLength = (uint)openAttributeTableBytes.Length;
                if (attributeNameTableBytes != null)
                {
                    LfsRecord attributeNameTableRecord = WriteLogRecord(null, null, 0, NTFSLogOperation.AttributeNamesDump, openAttributeTableBytes, NTFSLogOperation.Noop, new byte[0], transactionID);
                    restartRecord.AttributeNamesLsn    = attributeNameTableRecord.ThisLsn;
                    restartRecord.AttributeNamesLength = (uint)attributeNameTableBytes.Length;
                }
                DeallocateTransactionID(transactionID);
            }
            restartRecord.BytesPerCluster = (uint)Volume.BytesPerCluster;
            restartRecord.UsnJournal      = usnJournal;
            byte[]    clientData = restartRecord.GetBytes(majorNTFSVersion);
            LfsRecord result     = m_logFile.WriteRecord(m_clientIndex, LfsRecordType.ClientRestart, 0, 0, 0, clientData);

            m_lastClientLsn = result.ThisLsn;
            LfsClientRecord clientRecord = m_logFile.GetClientRecord(m_clientIndex);

            if (isClean)
            {
                clientRecord.OldestLsn = restartRecord.StartOfCheckpointLsn;
            }
            else
            {
                ulong oldestLsn = restartRecord.StartOfCheckpointLsn;
                foreach (Transaction transaction in m_transactions)
                {
                    if (transaction.OldestLsn != 0 && transaction.OldestLsn < oldestLsn)
                    {
                        oldestLsn = transaction.OldestLsn;
                    }
                }
                clientRecord.OldestLsn = oldestLsn;
            }
            clientRecord.ClientRestartLsn = result.ThisLsn;
            m_logFile.WriteRestartPage(isClean);
            return(result);
        }
예제 #4
0
        private LfsRecord WriteLogRecord(NTFSLogRecord ntfsLogRecord, uint transactionID, bool flushToDisk)
        {
            LfsClientRecord clientRecord = m_logFile.GetClientRecord(m_clientIndex);

            byte[]    clientData       = ntfsLogRecord.GetBytes();
            int       transactionIndex = IndexOfTransaction(transactionID);
            ulong     lastLsnToUndo    = m_transactions[transactionIndex].LastLsnToUndo;
            LfsRecord result           = m_logFile.WriteRecord(m_clientIndex, LfsRecordType.ClientRecord, m_lastClientLsn, lastLsnToUndo, transactionID, clientData, flushToDisk);

            m_lastClientLsn = result.ThisLsn;
            m_transactions[transactionIndex].LastLsnToUndo = result.ThisLsn;
            if (m_transactions[transactionIndex].OldestLsn == 0)
            {
                m_transactions[transactionIndex].OldestLsn = result.ThisLsn;
            }
            return(result);
        }
예제 #5
0
        private static void WriteLogFile(Volume volume, long logFileStartSector, long logFileSize, int bytesPerLogPage)
        {
            const int BytesPerSystemPage = 4096;

            LfsClientRecord ntfsClientRecord = new LfsClientRecord(NTFSLogClient.ClientName);
            LfsRestartPage  restartPage      = LfsRestartPage.Create(logFileSize, BytesPerSystemPage, bytesPerLogPage, ntfsClientRecord);

            long secondRestartPageStartSector = logFileStartSector + BytesPerSystemPage / volume.BytesPerSector;
            long firstRecordPageStartSector   = logFileStartSector + 2 * BytesPerSystemPage / volume.BytesPerSector;

            byte[] restartPageBytes = restartPage.GetBytes(BytesPerSystemPage, true);
            volume.WriteSectors(logFileStartSector, restartPageBytes);
            volume.WriteSectors(secondRestartPageStartSector, restartPageBytes);
            byte[] recordPagesBytes = new byte[logFileSize - 2 * BytesPerSystemPage];
            for (int index = 0; index < recordPagesBytes.Length; index += 4)
            {
                LittleEndianWriter.WriteUInt32(recordPagesBytes, index, LfsRecordPage.UninitializedPageSignature);
            }
            volume.WriteSectors(firstRecordPageStartSector, recordPagesBytes);
        }