+-------------+-------+------------------+------------------+------------------+------------------+---+
| | | | | | | |
| RCRD Header | USA | Operation Record | Operation Record | Operation Record | Operation record |...|
| | | | | | | |
+-------------+-------+------------------+------------------+------------------+------------------+---+
0x00 0x28 0x40 0x1000
Operation Record
+----------------------+------------------------------------------------------------------------------+
| | |
| LFS Record Header | Client data |
| | |
+----------------------+------------------------------------------------------------------------------+
0x30
+------------------------------------------------------------------------------>
clientDataLength
Update Sequence Array
+----+----+----+----+----+
| | | | | |
|abcd|0123|4567|89ab|cdef|
| | | | | |
+----+--+-+-+--+-+--+-+--+
| | | |
| | | +-----------------------------------+
+----------------------------+ | | |
| | | |
| +----+ +---------------+ |
| | | |
| | | |
v v v v
0x00 0x1e 0x3fe 0x5fe 0x7fe
+-----------------+----+----------------------+----+--------------------+----+-------------------+----+
| | | | | | | | |
| BEFORE FIXUP |abcd| |abcd| |abcd| |abcd|
| | | | | | | | |
+-----------------+----+----------------------+----+--------------------+----+-------------------+----+
+-----------------+----+----------------------+----+--------------------+----+-------------------+----+
| | | | | | | | |
| AFTER FIXUP |0123| |4567| |89ab| |cdef|
| | | | | | | | |
+-----------------+----+----------------------+----+--------------------+----+-------------------+----+
XXX: From cntfs/ntfslog.h
typedef struct _MULTI_SECTOR_HEADER {
//
// Space for a four-character signature
//
UCHAR Signature[4];
//
// Offset to Update Sequence Array, from start of structure. The Update
// Sequence Array must end before the last USHORT in the first "sector"
// of size SEQUENCE_NUMBER_STRIDE. (I.e., with the current constants,
// the sum of the next two fields must be <= 510.)
//
USHORT UpdateSequenceArrayOffset;
//
// Size of Update Sequence Array (from above formula)
//
USHORT UpdateSequenceArraySize;
} MULTI_SECTOR_HEADER, *PMULTI_SECTOR_HEADER;
typedef struct _LFS_RECORD_PAGE_HEADER {
//
// Cache multisector protection header.
//
MULTI_SECTOR_HEADER MultiSectorHeader;
union {
//
// Highest Lsn in this log file page. This field is only for
// regular log pages.
//
LSN LastLsn;
//
// Log file offset. This is for the tail copies and indicates the
// location in the file where the original lays. In this case the
// LastLsn field above can be obtained from the last ending Lsn
// field in the PACKED_RECORD_PAGE structure.
//
LONGLONG FileOffset;
} Copy;
//
// Page Header Flags. These are the same flags that are stored in the
// Lbcb->Flags field.
//
// LOG_PAGE_LOG_RECORD_END - Page contains the end of a log record
//
ULONG Flags;
//
// I/O Page Position. The following fields are used to determine
// where this log page resides within a Lfs I/O transfer.
//
USHORT PageCount;
USHORT PagePosition;
//
// The following is the difference between version 1.1 and earlier.
//
union {
LFS_UNPACKED_RECORD_PAGE Unpacked;
LFS_PACKED_RECORD_PAGE Packed;
} Header;
} LFS_RECORD_PAGE_HEADER, *PLFS_RECORD_PAGE_HEADER;
#define LOG_PAGE_LOG_RECORD_END (0x00000001)
#define LFS_UNPACKED_RECORD_PAGE_HEADER_SIZE ( \
FIELD_OFFSET( LFS_RECORD_PAGE_HEADER, Header.Unpacked.UpdateSequenceArray ) \
)
#define LFS_PACKED_RECORD_PAGE_HEADER_SIZE ( \
FIELD_OFFSET( LFS_RECORD_PAGE_HEADER, Header.Packed.UpdateSequenceArray ) \
)
//
// Log Record Header. This is the header that begins every Log Record in
// the log file.
//
typedef struct _LFS_RECORD_HEADER {
//
// Log File Sequence Number of this log record.
//
LSN ThisLsn;
//
// The following fields are used to back link Lsn's. The ClientPrevious
// and ClientUndoNextLsn fields are used by a client to link his log
// records.
//
LSN ClientPreviousLsn;
LSN ClientUndoNextLsn;
//
// The following field is the size of data area for this record. The
// log record header will be padded if necessary to fill to a 64-bit
// boundary, so the client data will begin on a 64-bit boundary to
// insure that all of his data is 64-bit aligned. The below value
// has not been padded to 64 bits however.
//
ULONG ClientDataLength;
//
// Client ID. This identifies the owner of this log record. The owner
// is uniquely identified by his offset in the client array and the
// sequence number associated with that client record.
//
LFS_CLIENT_ID ClientId;
//
// This the Log Record type. This could be a commit protocol record,
// a client restart area or a client update record.
//
LFS_RECORD_TYPE RecordType;
//
// Transaction ID. This is used externally by a client (Transaction
// Manager) to group log file entries.
//
TRANSACTION_ID TransactionId;
//
// Log record flags.
//
USHORT Flags;
//
// Alignment field.
//
USHORT AlignWord;
} LFS_RECORD_HEADER, *PLFS_RECORD_HEADER;
typedef enum _NTFS_LOG_OPERATION {
Noop = 0x00, //
CompensationLogRecord = 0x01, //
InitializeFileRecordSegment = 0x02, // FILE_RECORD_SEGMENT_HEADER
DeallocateFileRecordSegment = 0x03, //
WriteEndOfFileRecordSegment = 0x04, // ATTRIBUTE_RECORD_HEADER
CreateAttribute = 0x05, // ATTRIBUTE_RECORD_HEADER
DeleteAttribute = 0x06, //
UpdateResidentValue = 0x07, // (value)
UpdateNonresidentValue = 0x08, // (value)
UpdateMappingPairs = 0x09, // (value = mapping pairs bytes)
DeleteDirtyClusters = 0x0A, // array of LCN_RANGE
SetNewAttributeSizes = 0x0B, // NEW_ATTRIBUTE_SIZES
AddIndexEntryRoot = 0x0C, // INDEX_ENTRY
DeleteIndexEntryRoot = 0x0D, // INDEX_ENTRY
AddIndexEntryAllocation = 0x0E, // INDEX_ENTRY
DeleteIndexEntryAllocation = 0x0F, // INDEX_ENTRY
WriteEndOfIndexBuffer = 0x10, // INDEX_ENTRY
SetIndexEntryVcnRoot = 0x11, // VCN
SetIndexEntryVcnAllocation = 0x12, // VCN
UpdateFileNameRoot = 0x13, // DUPLICATED_INFORMATION
UpdateFileNameAllocation = 0x14, // DUPLICATED_INFORMATION
SetBitsInNonresidentBitMap = 0x15, // BITMAP_RANGE
ClearBitsInNonresidentBitMap = 0x16, // BITMAP_RANGE
HotFix = 0x17, //
EndTopLevelAction = 0x18, //
PrepareTransaction = 0x19, //
CommitTransaction = 0x1A, //
ForgetTransaction = 0x1B, //
OpenNonresidentAttribute = 0x1C, // OPEN_ATTRIBUTE_ENTRY+ATTRIBUTE_NAME_ENTRY
OpenAttributeTableDump = 0x1D, // OPEN_ATTRIBUTE_ENTRY array
AttributeNamesDump = 0x1E, // (all attribute names)
DirtyPageTableDump = 0x1F, // DIRTY_PAGE_ENTRY array
TransactionTableDump = 0x20, // TRANSACTION_ENTRY array
UpdateRecordDataRoot = 0x21, // (value)
UpdateRecordDataAllocation = 0x22 // (value)
} NTFS_LOG_OPERATION, *PNTFS_LOG_OPERATION;