第一部分:
; Attribute Form Codes
RESIDENT_FORM EQU 0
NONRESIDENT_FORM EQU 1
if (Attribute->FormCode == NONRESIDENT_FORM) {
ListEntry->LowestVcn = Attribute->Form.Nonresident.LowestVcn;
}
第二部分:
1: kd> dt Attribute_RECORD_HEADER -r
Ntfs!ATTRIBUTE_RECORD_HEADER
+0x000 TypeCode : Uint4B
+0x004 RecordLength : Uint4B
+0x008 FormCode : UChar
+0x009 NameLength : UChar
+0x00a NameOffset : Uint2B
+0x00c Flags : Uint2B
+0x00e Instance : Uint2B
+0x010 Form : __unnamed
+0x000 Resident : __unnamed
+0x000 ValueLength : Uint4B
+0x004 ValueOffset : Uint2B
+0x006 ResidentFlags : UChar
+0x007 Reserved : UChar
+0x000 Nonresident : __unnamed
+0x000 LowestVcn : Int8B
+0x008 HighestVcn : Int8B
+0x010 MappingPairsOffset : Uint2B
+0x012 CompressionUnit : UChar
+0x013 Reserved : [5] UChar
+0x018 AllocatedLength : Int8B
+0x020 FileSize : Int8B
+0x028 ValidDataLength : Int8B
+0x030 TotalAllocated : Int8B
第三部分:例子:
1: kd> dx -id 0,0,899a2278 -r1 ((Ntfs!_FILE_RECORD_SEGMENT_HEADER *)0xc4313400)
((Ntfs!_FILE_RECORD_SEGMENT_HEADER *)0xc4313400) : 0xc4313400 [Type: _FILE_RECORD_SEGMENT_HEADER *]
[+0x000] MultiSectorHeader [Type: _MULTI_SECTOR_HEADER]
[+0x008] Lsn : {123755220} [Type: _LARGE_INTEGER]
[+0x010] SequenceNumber : 0x1 [Type: unsigned short]
[+0x012] ReferenceCount : 0x2 [Type: unsigned short]
[+0x014] FirstAttributeOffset : 0x38 [Type: unsigned short]
[+0x016] Flags : 0x1 [Type: unsigned short]
[+0x018] FirstFreeByte : 0x1e0 [Type: unsigned long]
[+0x01c] BytesAvailable : 0x400 [Type: unsigned long]
[+0x020] BaseFileRecordSegment [Type: _MFT_SEGMENT_REFERENCE]
[+0x028] NextAttributeInstance : 0x7 [Type: unsigned short]
[+0x02a] SegmentNumberHighPart : 0x0 [Type: unsigned short]
[+0x02c] SegmentNumberLowPart : 0x274d [Type: unsigned long]
[+0x030] UpdateArrayForCreateOnly [Type: unsigned short [1]]
1: kd> dt Attribute_RECORD_HEADER 0xc4313000+0x38
Ntfs!ATTRIBUTE_RECORD_HEADER
+0x000 TypeCode : 0x10
+0x004 RecordLength : 0x60
+0x008 FormCode : 0 ''
+0x009 NameLength : 0 ''
+0x00a NameOffset : 0
+0x00c Flags : 0
+0x00e Instance : 0
+0x010 Form : __unnamed
1: kd> dt Attribute_RECORD_HEADER 0xc4313400+0x38+60
Ntfs!ATTRIBUTE_RECORD_HEADER
+0x000 TypeCode : 0x30
+0x004 RecordLength : 0x78
+0x008 FormCode : 0 ''
+0x009 NameLength : 0 ''
+0x00a NameOffset : 0
+0x00c Flags : 0
+0x00e Instance : 6
+0x010 Form : __unnamed
1: kd> dt Attribute_RECORD_HEADER 0xc4313400+0x38+60+78
Ntfs!ATTRIBUTE_RECORD_HEADER
+0x000 TypeCode : 0x30
+0x004 RecordLength : 0x80
+0x008 FormCode : 0 ''
+0x009 NameLength : 0 ''
+0x00a NameOffset : 0
+0x00c Flags : 0
+0x00e Instance : 5
+0x010 Form : __unnamed
第四部分:
1: kd> dt Attribute_RECORD_HEADER 0xc4313400+0x38+60+78+80
Ntfs!ATTRIBUTE_RECORD_HEADER
+0x000 TypeCode : 0x80
+0x004 RecordLength : 0x48
+0x008 FormCode : 0x1 '' //+0x008 FormCode : 0x1 ''
+0x009 NameLength : 0 ''
+0x00a NameOffset : 0
+0x00c Flags : 0
+0x00e Instance : 4
+0x010 Form : __unnamed
1: kd> dd 0xc4313400+0x38+60+78+80
c4313590 00000080 00000048 00000001 00040000
c43135a0 00000000 00000000 00000000 00000000
c43135b0 00000040 00000000 00001000 00000000
c43135c0 00000603 00000000 00000603 00000000
c43135d0 902d0131 00010050
+0x000 Nonresident : __unnamed
+0x000 LowestVcn : Int8B 00000000 00000000
+0x008 HighestVcn : Int8B 00000000 00000000
+0x010 MappingPairsOffset : Uint2B 0040
+0x012 CompressionUnit : UChar
+0x013 Reserved : [5] UChar
+0x018 AllocatedLength : Int8B 00001000 00000000
+0x020 FileSize : Int8B 00000603 00000000
+0x028 ValidDataLength : Int8B 00000603 00000000
+0x030 TotalAllocated : Int8B 902d0131 00010050
31 01 2d 90 50 00 01 00
VcnBytes = *ch & 0xF; 1
LcnBytes = (*ch++ >> 4) & 0xF; // avoid sign extended case 3
0x1 是VCN号
0x50902d 是LCN号
第五部分:
MappingPairs = (PCHAR)Attribute + (ULONG)Attribute->Form.Nonresident.MappingPairsOffset;
HighestVcn = NtfsGetHighestVcn( IrpContext,
Attribute->Form.Nonresident.LowestVcn,
(PCHAR)Attribute + (ULONG)Attribute->RecordLength,
MappingPairs );
第六部分:
VCN
NtfsGetHighestVcn (
IN PIRP_CONTEXT IrpContext,
IN VCN LowestVcn,
IN PCHAR EndOfMappingPairs,
IN PCHAR MappingPairs
)
{
VCN CurrentVcn, NextVcn;
ULONG VcnBytes, LcnBytes;
LONGLONG Change;
PCHAR ch = MappingPairs;
PCHAR VcnStart;
PAGED_CODE();
//
// Implement the decompression algorithm, as defined in ntfs.h.
//
NextVcn = LowestVcn;
ch = MappingPairs;
//
// Loop to process mapping pairs.
//
while ((ch < EndOfMappingPairs) && !IsCharZero(*ch)) {
//
// Set Current Vcn from initial value or last pass through loop.
//
CurrentVcn = NextVcn;
//
// Extract the counts from the two nibbles of this byte.
//
VcnBytes = *ch & 0xF;
LcnBytes = (*ch++ >> 4) & 0xF; // avoid sign extended case
VcnStart = ch;
//
// Calculate next mapping pair location first and check for buffer overrun
//
ch += VcnBytes + LcnBytes;
//
// Extract the Vcn change (use of RtlCopyMemory works for little-Endian)
// and update NextVcn.
//
Change = 0;
if ((ch > EndOfMappingPairs) ||
VcnBytes > 8 ||
LcnBytes > 8 ||
IsCharLtrZero(*(VcnStart + VcnBytes - 1))) {
NtfsRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR, NULL, NULL );
}
RtlCopyMemory( &Change, VcnStart, VcnBytes );
NextVcn = NextVcn + Change;
}
Change = NextVcn - 1;
return *(PVCN)&Change;