Ntfs!NtfsLookupAllocation函数分析之读取runs的一个例子
第一部分:
0: kd> g
Breakpoint 2 hit
Ntfs!NtfsLookupInFileRecord:
f7171c90 55 push ebp
0: kd> kc
#
00 Ntfs!NtfsLookupInFileRecord
01 Ntfs!NtfsLookupAllocation
02 Ntfs!NtfsPrepareBuffers
03 Ntfs!NtfsNonCachedIo
04 Ntfs!NtfsCommonRead
05 Ntfs!NtfsFsdRead
06 nt!IofCallDriver
07 nt!IopPageReadInternal
08 nt!IoPageRead
09 nt!MiDispatchFault
0a nt!MmAccessFault
0b nt!_KiTrap0E
0c nt!CcMapData
0d Ntfs!NtfsMapStream
0e Ntfs!NtfsMapAttributeValue
0f Ntfs!NtfsUpdateFcbInfoFromDisk
10 Ntfs!NtfsOpenRootDirectory
11 Ntfs!NtfsMountVolume
12 Ntfs!NtfsCommonFileSystemControl
13 Ntfs!NtfsFspDispatch
14 nt!ExpWorkerThread
15 nt!PspSystemThreadStartup
16 nt!KiThreadStartup
0: kd> dv
IrpContext = 0xf78d6590
Fcb = 0xe1366838
BaseFileReference = 0xe1366840
QueriedTypeCode = 0x50
QueriedName = 0xe1352088 ""
Vcn = 0xf78d60fc
0: kd> dt _ATTRIBUTE_RECORD_HEADER 0xc1241400+0x38+48+60+28
Ntfs!_ATTRIBUTE_RECORD_HEADER
+0x000 TypeCode : 0x50
+0x004 RecordLength : 0x48
+0x008 FormCode : 0x1 ''
+0x009 NameLength : 0 ''
+0x00a NameOffset : 0x40
+0x00c Flags : 0
+0x00e Instance : 2
+0x010 Form : __unnamed
+0x000 Nonresident : __unnamed
+0x000 LowestVcn : Int8B 00 00 00 00 00 00 00 00
+0x008 HighestVcn : Int8B 01 00 00 00 00 00 00 00
+0x010 MappingPairsOffset : Uint2B 40 00
+0x012 CompressionUnit : UChar
+0x013 Reserved : [5] UChar
+0x018 AllocatedLength : Int8B 00 20 00 00 00 00 00 00
+0x020 FileSize : Int8B 30 10 00 00 00 00 00 00
+0x028 ValidDataLength : Int8B
+0x030 TotalAllocated : Int8B
0: kd> db 0xc1241400+0x38+48+60+28
c1241508 50 00 00 00 48 00 00 00-01 00 40 00 00 00 02 00 P...H.....@.....
c1241518 00 00 00 00 00 00 00 00-01 00 00 00 00 00 00 00 ................
c1241528 40 00 00 00 00 00 00 00-00 20 00 00 00 00 00 00 @........ ......
c1241538 30 10 00 00 00 00 00 00-30 10 00 00 00 00 00 00 0.......0.......
c1241548 31 02 7d f9 4f 00 00 00-90 00 00 00 e0 00 00 00 1.}.O...........
c1241558 00 04 18 00 00 00 06 00-c0 00 00 00 20 00 00 00 ............ ...
c1241568 24 00 49 00 33 00 30 00-30 00 00 00 01 00 00 00 $.I.3.0.0.......
c1241578 00 10 00 00 01 00 00 00-10 00 00 00 b0 00 00 00 ................
31 02 7d f9 4f 00 00 00
0x4ff97d
第二部分:
//
// Store run information in the Mcb until we hit the last Vcn we are
// interested in, or until we cannot find any more attribute records.
//
while(TRUE) {
VCN CurrentVcn;
LCN CurrentLcn;
LONGLONG Change;
PCHAR ch;
ULONG VcnBytes;
ULONG LcnBytes;
0: kd> dv
IrpContext = 0xf78d6590
Fcb = 0xe1366838
BaseFileReference = 0xe1366840
QueriedTypeCode = 0x50
QueriedName = 0xe1352088 ""
0: kd> dx -r1 (*((Ntfs!_ATTRIBUTE_ENUMERATION_CONTEXT *)0xf78d6028))
(*((Ntfs!_ATTRIBUTE_ENUMERATION_CONTEXT *)0xf78d6028)) [Type: _ATTRIBUTE_ENUMERATION_CONTEXT]
[+0x000] FoundAttribute [Type: _FOUND_ATTRIBUTE]
[+0x018] AttributeList [Type: _ATTRIBUTE_LIST_CONTEXT]
0: kd> dx -r1 (*((Ntfs!_FOUND_ATTRIBUTE *)0xf78d6028))
(*((Ntfs!_FOUND_ATTRIBUTE *)0xf78d6028)) [Type: _FOUND_ATTRIBUTE]
[+0x000] MftFileOffset : 5120 [Type: __int64]
[+0x008] Attribute : 0xc1241508 [Type: _ATTRIBUTE_RECORD_HEADER *]
[+0x00c] FileRecord : 0xc1241400 [Type: _FILE_RECORD_SEGMENT_HEADER *]
[+0x010] Bcb : 0x89988001 [Type: void *]
[+0x014] AttributeDeleted : 0x0 [Type: unsigned char]
0: kd> dx -r1 ((Ntfs!_ATTRIBUTE_RECORD_HEADER *)0xc1241508)
((Ntfs!_ATTRIBUTE_RECORD_HEADER *)0xc1241508) : 0xc1241508 [Type: _ATTRIBUTE_RECORD_HEADER *]
[+0x000] TypeCode : 0x50 [Type: unsigned long]
[+0x004] RecordLength : 0x48 [Type: unsigned long]
[+0x008] FormCode : 0x1 [Type: unsigned char]
[+0x009] NameLength : 0x0 [Type: unsigned char]
[+0x00a] NameOffset : 0x40 [Type: unsigned short]
[+0x00c] Flags : 0x0 [Type: unsigned short]
[+0x00e] Instance : 0x2 [Type: unsigned short]
[+0x010] Form [Type: __unnamed]
//
// Lookup the attribute record for this Scb.
//
NtfsLookupAttributeForScb( IrpContext, Scb, &Vcn, &Context );
Attribute = NtfsFoundAttribute( &Context );
#define NtfsFoundAttribute(CTX) ( \
(CTX)->FoundAttribute.Attribute \
)
第三部分:
//
// Implement the decompression algorithm, as defined in ntfs.h.
//
HighestCandidate = Attribute->Form.Nonresident.LowestVcn;
CurrentLcn = 0;
ch = (PCHAR)Attribute + Attribute->Form.Nonresident.MappingPairsOffset; c1241548 31 02 7d f9 4f 00 00 00 重要
+0x000 Nonresident : __unnamed
+0x000 LowestVcn : Int8B
+0x008 HighestVcn : Int8B
+0x010 MappingPairsOffset : Uint2B
+0x000 Nonresident : __unnamed
+0x000 LowestVcn : Int8B 00 00 00 00 00 00 00 00
+0x008 HighestVcn : Int8B 01 00 00 00 00 00 00 00
+0x010 MappingPairsOffset : Uint2B 40 00
+0x012 CompressionUnit : UChar
+0x013 Reserved : [5] UChar
+0x018 AllocatedLength : Int8B 00 20 00 00 00 00 00 00
+0x020 FileSize : Int8B 30 10 00 00 00 00 00 00
+0x028 ValidDataLength : Int8B
+0x030 TotalAllocated : Int8B
0: kd> db 0xc1241400+0x38+48+60+28
c1241508 50 00 00 00 48 00 00 00-01 00 40 00 00 00 02 00 P...H.....@.....
c1241518 00 00 00 00 00 00 00 00-01 00 00 00 00 00 00 00 ................
c1241528 40 00 00 00 00 00 00 00-00 20 00 00 00 00 00 00 @........ ......
c1241538 30 10 00 00 00 00 00 00-30 10 00 00 00 00 00 00 0.......0.......
c1241548 31 02 7d f9 4f 00 00 00-90 00 00 00 e0 00 00 00 1.}.O...........
c1241558 00 04 18 00 00 00 06 00-c0 00 00 00 20 00 00 00 ............ ...
c1241568 24 00 49 00 33 00 30 00-30 00 00 00 01 00 00 00 $.I.3.0.0.......
c1241578 00 10 00 00 01 00 00 00-10 00 00 00 b0 00 00 00 ................
第四部分:
//
// Extract the counts from the two nibbles of this byte.
//
VcnBytes = *ch & 0xF;
LcnBytes = *ch++ >> 4;
dv
ch = 0xc1241549 "???"
VcnBytes = 1
CurrentVcn = 0n0
LcnBytes = 3
CurrentLcn = 0n0
第五部分:
CurrentLcn = CurrentLcn + Change;
CurrentLcn = 0n5241213 31 02 7d f9 4f 00 00 00
0: kd> ?0n5241213
Evaluate expression: 5241213 = 004ff97d 31 02 7d f9 4f 00 00 00
第六部分:ntfs!NtfsAddNtfsMcbEntry函数分析
if (!NtfsAddNtfsMcbEntry( &Scb->Mcb,
CurrentVcn,
CurrentLcn,
ClustersToAdd,
McbMutexAcquired )) {
0: kd> dx -r1 (*((Ntfs!_NTFS_MCB *)0xe1352098))
(*((Ntfs!_NTFS_MCB *)0xe1352098)) [Type: _NTFS_MCB]
[+0x000] FcbHeader : 0xe1352008 [Type: _NTFS_ADVANCED_FCB_HEADER *]
[+0x004] PoolType : PagedPool (1) [Type: _POOL_TYPE]
[+0x008] NtfsMcbArraySizeInUse : 0x1 [Type: unsigned long]
[+0x00c] NtfsMcbArraySize : 0x1 [Type: unsigned long]
[+0x010] NtfsMcbArray : 0xe13520b0 [Type: _NTFS_MCB_ARRAY *]
[+0x014] FastMutex : 0x89954818 [Type: _FAST_MUTEX *]
0: kd> dx -r1 ((Ntfs!_NTFS_MCB_ARRAY *)0xe13520b0)
((Ntfs!_NTFS_MCB_ARRAY *)0xe13520b0) : 0xe13520b0 [Type: _NTFS_MCB_ARRAY *]
[+0x000] StartingVcn : 0 [Type: __int64]
[+0x008] EndingVcn : 1 [Type: __int64]
[+0x010] NtfsMcbEntry : 0x0 [Type: _NTFS_MCB_ENTRY *]
[+0x014] Unused : 0x0 [Type: void *]
0: kd> t
Ntfs!NtfsAddNtfsMcbEntry:
f7146a48 6a6c push 6Ch
0: kd> dv
Mcb = 0xe1352098
Vcn = 0n0
Lcn = 0n5241213
RunCount = 0n2
AlreadySynchronized = 0x01 ''
NewEntry = 0xf78d60dc
if (!NtfsAddNtfsMcbEntry( &Scb->Mcb,
CurrentVcn,
CurrentLcn,
ClustersToAdd,
McbMutexAcquired )) {
0: kd> gu
Ntfs!NtfsLookupAllocation+0x420:
f7140066 84c0 test al,al
0: kd> dx -r1 (*((Ntfs!_NTFS_MCB *)0xe1352098))
(*((Ntfs!_NTFS_MCB *)0xe1352098)) [Type: _NTFS_MCB]
[+0x000] FcbHeader : 0xe1352008 [Type: _NTFS_ADVANCED_FCB_HEADER *]
[+0x004] PoolType : PagedPool (1) [Type: _POOL_TYPE]
[+0x008] NtfsMcbArraySizeInUse : 0x1 [Type: unsigned long]
[+0x00c] NtfsMcbArraySize : 0x1 [Type: unsigned long]
[+0x010] NtfsMcbArray : 0xe13520b0 [Type: _NTFS_MCB_ARRAY *]
[+0x014] FastMutex : 0x89954818 [Type: _FAST_MUTEX *]
0: kd> dx -r1 ((Ntfs!_NTFS_MCB_ARRAY *)0xe13520b0)
((Ntfs!_NTFS_MCB_ARRAY *)0xe13520b0) : 0xe13520b0 [Type: _NTFS_MCB_ARRAY *]
[+0x000] StartingVcn : 0 [Type: __int64]
[+0x008] EndingVcn : 1 [Type: __int64]
[+0x010] NtfsMcbEntry : 0xe13520c8 [Type: _NTFS_MCB_ENTRY *]
[+0x014] Unused : 0x0 [Type: void *]
0: kd> dx -r1 ((Ntfs!_NTFS_MCB_ENTRY *)0xe13520c8)
((Ntfs!_NTFS_MCB_ENTRY *)0xe13520c8) : 0xe13520c8 [Type: _NTFS_MCB_ENTRY *]
[+0x000] LruLinks [Type: _LIST_ENTRY]
[+0x008] NtfsMcb : 0xe1352098 [Type: _NTFS_MCB *]
[+0x00c] NtfsMcbArray : 0xe13520b0 [Type: _NTFS_MCB_ARRAY *]
[+0x010] LargeMcb [Type: _LARGE_MCB]
0: kd> dx -r1 ((Ntfs!_NTFS_MCB_ARRAY *)0xe13520b0)
((Ntfs!_NTFS_MCB_ARRAY *)0xe13520b0) : 0xe13520b0 [Type: _NTFS_MCB_ARRAY *]
[+0x000] StartingVcn : 0 [Type: __int64]
[+0x008] EndingVcn : 1 [Type: __int64]
[+0x010] NtfsMcbEntry : 0xe13520c8 [Type: _NTFS_MCB_ENTRY *] //原来是: [+0x010] NtfsMcbEntry : 0x0 [Type: _NTFS_MCB_ENTRY *]
[+0x014] Unused : 0x0 [Type: void *]
0: kd> dx -r1 (*((Ntfs!_LARGE_MCB *)0xe13520d8))
(*((Ntfs!_LARGE_MCB *)0xe13520d8)) [Type: _LARGE_MCB]
[+0x000] FastMutex : 0x899c01b8 [Type: _FAST_MUTEX *]
[+0x004] BaseMcb [Type: _BASE_MCB]
0: kd> dx -r1 (*((Ntfs!_BASE_MCB *)0xe13520dc))
(*((Ntfs!_BASE_MCB *)0xe13520dc)) [Type: _BASE_MCB]
[+0x000] MaximumPairCount : 0xf [Type: unsigned long]
[+0x004] PairCount : 0x1 [Type: unsigned long]
[+0x008] PoolType : PagedPool (1) [Type: _POOL_TYPE]
[+0x00c] Mapping : 0xe135b008 [Type: void *]
0: kd> dt _mapping 0xe135b008
nt!_MAPPING
+0x000 NextVbn : 2
+0x004 Lbn : 0x4ff97d //物理簇号
if (NtfsLookupNtfsMcbEntry( &Scb->Mcb, Vcn, Lcn, ClusterCount, NULL, NULL, RangePtr, RunIndex )) {
Found = (BOOLEAN)(*Lcn != UNUSED_LCN);
if (Found) { ASSERT_LCN_RANGE_CHECKING( Vcb, (*Lcn + *ClusterCount) ); }
Found = 0x01 ''
第七部分:最终结果:查看 IoRuns
0: kd> dv
IrpContext = 0xf78d6590
Irp = 0x89630008
Scb = 0xe1352008
StartingVbo = 0n0
ByteCount = 0x1000
StreamFlags = 0
Mdl = 0x00000000
Wait = 0x01 ''
IrpSpFlags = 0x00 ''
IoRuns = struct _IO_RUN [8]
Status = 0n0
Vcb = 0x8962e100
RemainingByteCount = 0
OriginalByteCount = 0x1000
CompressionContext = struct COMPRESSION_CONTEXT
NumberRuns = 1
TempRange = 0n0
NtfsPurgeFileRecordCache( IrpContext );
NextIsAllocated = NtfsLookupAllocation( IrpContext,
Scb,
StartingVcn,
&NextLcn,
&NextClusterCount,
NULL,
NULL );
0: kd> dx -r1 ((Ntfs!_IO_RUN *)0xf78d62ec)
((Ntfs!_IO_RUN *)0xf78d62ec) : 0xf78d62ec [Type: _IO_RUN *]
[+0x000] StartingVbo : 8589934591 [Type: __int64]
[+0x008] StartingLbo : -608716059775598592 [Type: __int64]
[+0x010] BufferOffset : 0xffffffff [Type: unsigned long]
[+0x014] ByteCount : 0x80b003ed [Type: unsigned long]
[+0x018] SavedIrp : 0xffffffff [Type: _IRP *]
[+0x01c] Unused : 0x89906b60 [Type: unsigned long]
0: kd> dx -r1 (*((Ntfs!_IO_RUN (*)[8])0xf78d62ec))
(*((Ntfs!_IO_RUN (*)[8])0xf78d62ec)) [Type: _IO_RUN [8]]
[0] [Type: _IO_RUN]
[1] [Type: _IO_RUN]
[2] [Type: _IO_RUN]
[3] [Type: _IO_RUN]
[4] [Type: _IO_RUN]
[5] [Type: _IO_RUN]
[6] [Type: _IO_RUN]
[7] [Type: _IO_RUN]
0: kd> dx -r1 (*((Ntfs!_IO_RUN *)0xf78d62ec))
(*((Ntfs!_IO_RUN *)0xf78d62ec)) [Type: _IO_RUN]
[+0x000] StartingVbo : 0 [Type: __int64]
[+0x008] StartingLbo : 21468008448 [Type: __int64]
[+0x010] BufferOffset : 0x0 [Type: unsigned long]
[+0x014] ByteCount : 0x1000 [Type: unsigned long]
[+0x018] SavedIrp : 0xffffffff [Type: _IRP *]
[+0x01c] Unused : 0x89906b60 [Type: unsigned long]
0: kd> ?0n21468008448
Evaluate expression: 21468008448 = 00000004`ff97d000
0: kd> dt _mapping 0xe135b008
nt!_MAPPING
+0x000 NextVbn : 2
+0x004 Lbn : 0x4ff97d //物理簇号
移动了12位,加了3个0。
一个簇4k,4k=0x1000
RemainingByteCount = NtfsPrepareBuffers( IrpContext,
Irp,
Scb,
&StartingVbo,
ByteCount,
StreamFlags,
&Wait,
&NumberRuns,
&CompressionContext );
NumberRuns = 1