Ejemplo n.º 1
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);
        }
Ejemplo n.º 2
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);
        }