@@ -40,6 +40,7 @@ BOOLEAN ExtReadInode(PEXT_VOLUME_INFO Volume, ULONG Inode, PEXT_INODE InodeBu
4040BOOLEAN ExtReadGroupDescriptor (PEXT_VOLUME_INFO Volume , ULONG Group , PEXT_GROUP_DESC GroupBuffer );
4141ULONG * ExtReadBlockPointerList (PEXT_VOLUME_INFO Volume , PEXT_INODE Inode );
4242ULONGLONG ExtGetInodeFileSize (PEXT_INODE Inode );
43+ BOOLEAN ExtCopyBlockPointersByExtents (PEXT_VOLUME_INFO Volume , ULONG * BlockList , ULONG * CurrentBlockInList , ULONG BlockCount , PEXT4_EXTENT_HEADER ExtentHeader );
4344BOOLEAN ExtCopyIndirectBlockPointers (PEXT_VOLUME_INFO Volume , ULONG * BlockList , ULONG * CurrentBlockInList , ULONG BlockCount , ULONG IndirectBlock );
4445BOOLEAN ExtCopyDoubleIndirectBlockPointers (PEXT_VOLUME_INFO Volume , ULONG * BlockList , ULONG * CurrentBlockInList , ULONG BlockCount , ULONG DoubleIndirectBlock );
4546BOOLEAN ExtCopyTripleIndirectBlockPointers (PEXT_VOLUME_INFO Volume , ULONG * BlockList , ULONG * CurrentBlockInList , ULONG BlockCount , ULONG TripleIndirectBlock );
@@ -1037,6 +1038,21 @@ ULONG* ExtReadBlockPointerList(PEXT_VOLUME_INFO Volume, PEXT_INODE Inode)
10371038
10381039 RtlZeroMemory (BlockList , BlockCount * sizeof (ULONG ));
10391040
1041+ // If the file is stored in extents, copy the block pointers by reading the
1042+ // extent entries.
1043+ if (Inode -> Flags & EXT4_INODE_FLAG_EXTENTS )
1044+ {
1045+ CurrentBlockInList = 0 ;
1046+
1047+ if (!ExtCopyBlockPointersByExtents (Volume , BlockList , & CurrentBlockInList , BlockCount , & Inode -> ExtentHeader ))
1048+ {
1049+ FrLdrTempFree (BlockList , TAG_EXT_BLOCK_LIST );
1050+ return NULL ;
1051+ }
1052+
1053+ return BlockList ;
1054+ }
1055+
10401056 // Copy the direct block pointers
10411057 for (CurrentBlockInList = CurrentBlock = 0 ;
10421058 CurrentBlockInList < BlockCount && CurrentBlock < sizeof (Inode -> Blocks .DirectBlocks ) / sizeof (* Inode -> Blocks .DirectBlocks );
@@ -1090,6 +1106,72 @@ ULONGLONG ExtGetInodeFileSize(PEXT_INODE Inode)
10901106 }
10911107}
10921108
1109+ BOOLEAN ExtCopyBlockPointersByExtents (PEXT_VOLUME_INFO Volume , ULONG * BlockList , ULONG * CurrentBlockInList , ULONG BlockCount , PEXT4_EXTENT_HEADER ExtentHeader )
1110+ {
1111+ TRACE ("ExtCopyBlockPointersByExtents() BlockCount = 0x%p\n" , BlockCount );
1112+
1113+ if (ExtentHeader -> Magic != EXT4_EXTENT_HEADER_MAGIC ||
1114+ ExtentHeader -> Depth > EXT4_EXTENT_MAX_LEVEL )
1115+ return FALSE;
1116+
1117+ ULONG Level = ExtentHeader -> Depth ;
1118+ ULONG Entries = ExtentHeader -> Entries ;
1119+
1120+ TRACE ("Level: %d\n" , Level );
1121+ TRACE ("Entries: %d\n" , Entries );
1122+
1123+ // If the level is 0, we have a direct extent block mapping
1124+ if (!Level )
1125+ {
1126+ PEXT4_EXTENT Extent = (PVOID )& ExtentHeader [1 ];
1127+
1128+ while ((* CurrentBlockInList ) < BlockCount && Entries -- )
1129+ {
1130+ BOOLEAN SparseExtent = (Extent -> Length > EXT4_EXTENT_MAX_LENGTH );
1131+ ULONG Length = SparseExtent ? (Extent -> Length - EXT4_EXTENT_MAX_LENGTH ) : Extent -> Length ;
1132+ ULONG CurrentBlock = SparseExtent ? 0 : Extent -> Start ;
1133+
1134+ // Copy the pointers to the block list
1135+ while ((* CurrentBlockInList ) < BlockCount && Length -- )
1136+ {
1137+ BlockList [(* CurrentBlockInList )++ ] = CurrentBlock ;
1138+
1139+ if (!SparseExtent )
1140+ CurrentBlock ++ ;
1141+ }
1142+
1143+ Extent ++ ;
1144+ }
1145+ }
1146+ else
1147+ {
1148+ PEXT4_EXTENT_IDX Extent = (PVOID )& ExtentHeader [1 ];
1149+
1150+ PEXT4_EXTENT_HEADER BlockBuffer = FrLdrTempAlloc (Volume -> BlockSizeInBytes , TAG_EXT_BUFFER );
1151+ if (!BlockBuffer )
1152+ {
1153+ return FALSE;
1154+ }
1155+
1156+ // Recursively copy the pointers to the block list
1157+ while ((* CurrentBlockInList ) < BlockCount && Entries -- )
1158+ {
1159+ if (!(ExtReadBlock (Volume , Extent -> Leaf , BlockBuffer ) &&
1160+ ExtCopyBlockPointersByExtents (Volume , BlockList , CurrentBlockInList , BlockCount , BlockBuffer )))
1161+ {
1162+ FrLdrTempFree (BlockBuffer , TAG_EXT_BUFFER );
1163+ return FALSE;
1164+ }
1165+
1166+ Extent ++ ;
1167+ }
1168+
1169+ FrLdrTempFree (BlockBuffer , TAG_EXT_BUFFER );
1170+ }
1171+
1172+ return TRUE;
1173+ }
1174+
10931175BOOLEAN ExtCopyIndirectBlockPointers (PEXT_VOLUME_INFO Volume , ULONG * BlockList , ULONG * CurrentBlockInList , ULONG BlockCount , ULONG IndirectBlock )
10941176{
10951177 ULONG * BlockBuffer ;
0 commit comments