72#define TAG_EXT_BLOCK_LIST 'LtxE'
73#define TAG_EXT_FILE 'FtxE'
74#define TAG_EXT_BUFFER 'BtxE'
75#define TAG_EXT_SUPER_BLOCK 'StxE'
76#define TAG_EXT_GROUP_DESC 'GtxE'
77#define TAG_EXT_VOLUME 'VtxE'
81 TRACE(
"ExtOpenVolume() DeviceId = %d\n",
Volume->DeviceId);
130 TRACE(
"File is a symbolic link\n");
143 TRACE(
"Symbolic link path = \"%s\"\n", SymLinkPath);
146 if (SymLinkPath[0] ==
'/' || SymLinkPath[0] ==
'\\')
151 strcpy(FullPath, &SymLinkPath[1]);
163 if (FullPath[
Index] ==
'/' || FullPath[
Index] ==
'\\')
168 FullPath[
Index] =
'\0';
172 strcat(FullPath, SymLinkPath);
175 TRACE(
"Full file path = \"%s\"\n", FullPath);
212 ULONG NumberOfPathParts;
215 PVOID DirectoryBuffer;
235 for (
i=0;
i<NumberOfPathParts;
i++)
269 DirectoryInode = DirectoryEntry.
Inode;
315 if ((DirectoryEntry.
NameLen >= 2 && DirectoryEntry.
Name[0] ==
'.') &&
316 ((DirectoryEntry.
NameLen == 2 && DirectoryEntry.
Name[1] !=
'.') ||
333 ULONG CurrentOffset = 0;
336 TRACE(
"ExtSearchDirectoryBufferForFile() DirectoryBuffer = 0x%x DirectorySize = %d FileName = \"%s\"\n", DirectoryBuffer, DirectorySize,
FileName);
340 while (CurrentOffset < DirectorySize)
344 if (!CurrentDirectoryEntry->
EntryLen)
347 if ((CurrentDirectoryEntry->
EntryLen + CurrentOffset) > DirectorySize)
349 FileSystemError(
"Directory entry extends past end of directory file.");
353 if (!CurrentDirectoryEntry->
Inode)
354 goto NextDirectoryEntry;
356 TRACE(
"EXT Directory Entry:\n");
357 TRACE(
"Inode = %d\n", CurrentDirectoryEntry->
Inode);
359 TRACE(
"NameLen = %d\n", CurrentDirectoryEntry->
NameLen);
362 for (
ULONG NameOffset = 0; NameOffset < CurrentDirectoryEntry->
NameLen; NameOffset++)
364 TRACE(
"%c", CurrentDirectoryEntry->
Name[NameOffset]);
376 CurrentOffset += CurrentDirectoryEntry->
EntryLen;
391 ULONG BlockNumberIndex;
394 ULONG NumberOfBlocks;
396 TRACE(
"ExtReadFileBig() BytesToRead = %d Buffer = 0x%x\n", (
ULONG)BytesToRead,
Buffer);
411 FileSystemError(
"Block pointer list is NULL and file is not a fast symbolic link.");
439 TRACE(
"Reading fast symbolic link data\n");
493 LengthInBlock = (
ULONG)((BytesToRead > (
Volume->BlockSizeInBytes - OffsetInBlock)) ? (
Volume->BlockSizeInBytes - OffsetInBlock) : BytesToRead);
506 BytesToRead -= LengthInBlock;
519 NumberOfBlocks = (
ULONG)(BytesToRead /
Volume->BlockSizeInBytes);
521 while (NumberOfBlocks > 0)
537 BytesToRead -=
Volume->BlockSizeInBytes;
584 TRACE(
"ExtReadVolumeSectors() Failed to seek\n");
592 TRACE(
"ExtReadVolumeSectors() Failed to read\n");
607 TRACE(
"ExtReadSuperBlock()\n");
611 if (SuperBlock !=
NULL)
619 if (SuperBlock ==
NULL)
622 if (SuperBlock ==
NULL)
628 Volume->SuperBlock = SuperBlock;
642 TRACE(
"Dumping super block:\n");
678 if (
i <
sizeof(SuperBlock->
UUID) - 1)
688 TRACE(
"JournalUUID: { ");
699 TRACE(
"HashSeed: { 0x%02x, 0x%02x, 0x%02x, 0x%02x }\n",
729 TRACE(
"ExtBlockSizeInBytes: %d\n",
Volume->BlockSizeInBytes);
730 TRACE(
"ExtBlockSizeInSectors: %d\n",
Volume->BlockSizeInSectors);
742 TRACE(
"ExtFragmentSizeInBytes: %d\n",
Volume->FragmentSizeInBytes);
743 TRACE(
"ExtFragmentSizeInSectors: %d\n",
Volume->FragmentSizeInSectors);
746 if (
Volume->BlockSizeInBytes !=
Volume->FragmentSizeInBytes)
754 TRACE(
"InodeSizeInBytes: %d\n",
Volume->InodeSizeInBytes);
758 TRACE(
"GroupDescSizeInBytes: %d\n",
Volume->GroupDescSizeInBytes);
762 TRACE(
"ExtInodesPerBlock: %d\n",
Volume->InodesPerBlock);
766 TRACE(
"ExtGroupDescPerBlock: %d\n",
Volume->GroupDescPerBlock);
773 ULONG GroupDescBlockCount;
775 PUCHAR CurrentGroupDescBlock;
777 TRACE(
"ExtReadGroupDescriptors()\n");
796 CurrentGroupDescBlock = (
PUCHAR)
Volume->GroupDescriptors;
797 BlockNumber =
Volume->SuperBlock->FirstDataBlock + 1;
799 while (GroupDescBlockCount--)
807 CurrentGroupDescBlock +=
Volume->BlockSizeInBytes;
817 TRACE(
"ExtReadDirectory() Inode = %d\n", Inode);
853 if (*DirectoryBuffer ==
NULL)
864 *DirectoryBuffer =
NULL;
875 CHAR ErrorString[80];
877 TRACE(
"ExtReadBlock() BlockNumber = %d Buffer = 0x%x\n", BlockNumber,
Buffer);
880 if (BlockNumber >
Volume->SuperBlock->BlocksCountLo)
882 sprintf(ErrorString,
"Error reading block %d - block out of range.", (
int) BlockNumber);
888 if (BlockNumber == 0)
890 TRACE(
"Block is part of a sparse file. Zeroing input buffer.\n");
927 return ((Inode - 1) /
Volume->SuperBlock->InodesPerGroup);
932 return (((Inode - 1) %
Volume->SuperBlock->InodesPerGroup) /
Volume->InodesPerBlock);
937 return (((Inode - 1) %
Volume->SuperBlock->InodesPerGroup) %
Volume->InodesPerBlock);
942 ULONG InodeGroupNumber;
943 ULONG InodeBlockNumber;
944 ULONG InodeOffsetInBlock;
945 CHAR ErrorString[80];
948 TRACE(
"ExtReadInode() Inode = %d\n", Inode);
951 if ((Inode < 1) || (Inode >
Volume->SuperBlock->InodesCount))
953 sprintf(ErrorString,
"Error reading inode %ld - inode out of range.", Inode);
962 TRACE(
"InodeGroupNumber = %d\n", InodeGroupNumber);
963 TRACE(
"InodeBlockNumber = %d\n", InodeBlockNumber);
964 TRACE(
"InodeOffsetInBlock = %d\n", InodeOffsetInBlock);
973 InodeBlockNumber += GroupDescriptor.
InodeTable;
974 TRACE(
"InodeBlockNumber (after group desc correction) = %d\n", InodeBlockNumber);
979 (InodeOffsetInBlock *
Volume->InodeSizeInBytes),
986 TRACE(
"Dumping inode information:\n");
987 TRACE(
"Mode = 0x%x\n", InodeBuffer->
Mode);
988 TRACE(
"UID = %d\n", InodeBuffer->
UID);
994 TRACE(
"GID = %d\n", InodeBuffer->
GID);
998 TRACE(
"OSD1 = 0x%x\n", InodeBuffer->
OSD1);
999 TRACE(
"DirectBlocks = { %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u, %u }\n",
1000 InodeBuffer->
Blocks.DirectBlocks[0], InodeBuffer->
Blocks.DirectBlocks[1], InodeBuffer->
Blocks.DirectBlocks[2], InodeBuffer->
Blocks.DirectBlocks[3],
1001 InodeBuffer->
Blocks.DirectBlocks[4], InodeBuffer->
Blocks.DirectBlocks[5], InodeBuffer->
Blocks.DirectBlocks[6], InodeBuffer->
Blocks.DirectBlocks[7],
1002 InodeBuffer->
Blocks.DirectBlocks[8], InodeBuffer->
Blocks.DirectBlocks[9], InodeBuffer->
Blocks.DirectBlocks[10], InodeBuffer->
Blocks.DirectBlocks[11]);
1003 TRACE(
"IndirectBlock = %u\n", InodeBuffer->
Blocks.IndirectBlock);
1004 TRACE(
"DoubleIndirectBlock = %u\n", InodeBuffer->
Blocks.DoubleIndirectBlock);
1005 TRACE(
"TripleIndirectBlock = %u\n", InodeBuffer->
Blocks.TripleIndirectBlock);
1010 TRACE(
"OSD2 = { %d, %d, %d }\n",
1011 InodeBuffer->
OSD2[0], InodeBuffer->
OSD2[1], InodeBuffer->
OSD2[2]);
1018 TRACE(
"ExtReadGroupDescriptor()\n");
1030 TRACE(
"Dumping group descriptor:\n");
1046 ULONG CurrentBlockInList;
1049 TRACE(
"ExtReadBlockPointerList()\n");
1063 if (BlockList ==
NULL)
1074 CurrentBlockInList = 0;
1086 for (CurrentBlockInList = CurrentBlock = 0;
1087 CurrentBlockInList < BlockCount && CurrentBlock <
sizeof(Inode->
Blocks.DirectBlocks) /
sizeof(*Inode->
Blocks.DirectBlocks);
1088 CurrentBlock++, CurrentBlockInList++)
1090 BlockList[CurrentBlockInList] = Inode->
Blocks.DirectBlocks[CurrentBlock];
1094 if (CurrentBlockInList < BlockCount)
1104 if (CurrentBlockInList < BlockCount)
1114 if (CurrentBlockInList < BlockCount)
1136 TRACE(
"ExtCopyBlockPointersByExtents() BlockCount = 0x%p\n", BlockCount);
1153 while ((*CurrentBlockInList) < BlockCount &&
Entries--)
1157 ULONG CurrentBlock = SparseExtent ? 0 :
Extent->Start;
1160 while ((*CurrentBlockInList) < BlockCount &&
Length--)
1162 BlockList[(*CurrentBlockInList)++] = CurrentBlock;
1182 while ((*CurrentBlockInList) < BlockCount &&
Entries--)
1204 ULONG BlockPointersPerBlock;
1206 TRACE(
"ExtCopyIndirectBlockPointers() BlockCount = %d\n", BlockCount);
1208 BlockPointersPerBlock =
Volume->BlockSizeInBytes /
sizeof(
ULONG);
1221 for (CurrentBlock=0; (*CurrentBlockInList)<BlockCount && CurrentBlock<BlockPointersPerBlock; CurrentBlock++)
1223 BlockList[(*CurrentBlockInList)] = BlockBuffer[CurrentBlock];
1224 (*CurrentBlockInList)++;
1236 ULONG BlockPointersPerBlock;
1238 TRACE(
"ExtCopyDoubleIndirectBlockPointers() BlockCount = %d\n", BlockCount);
1240 BlockPointersPerBlock =
Volume->BlockSizeInBytes /
sizeof(
ULONG);
1243 if (BlockBuffer ==
NULL)
1254 for (CurrentBlock=0; (*CurrentBlockInList)<BlockCount && CurrentBlock<BlockPointersPerBlock; CurrentBlock++)
1271 ULONG BlockPointersPerBlock;
1273 TRACE(
"ExtCopyTripleIndirectBlockPointers() BlockCount = %d\n", BlockCount);
1275 BlockPointersPerBlock =
Volume->BlockSizeInBytes /
sizeof(
ULONG);
1278 if (BlockBuffer ==
NULL)
1289 for (CurrentBlock=0; (*CurrentBlockInList)<BlockCount && CurrentBlock<BlockPointersPerBlock; CurrentBlock++)
1325 TRACE(
"ExtGetFileInformation(%lu) -> FileSize = %llu, FilePointer = 0x%llx\n",
1345 TRACE(
"ExtOpen() FileName = \"%s\"\n",
Path);
1439 TRACE(
"Enter ExtMount(%lu)\n", DeviceId);
1469 Volume->DeviceId = DeviceId;
1482 TRACE(
"ExtMount(%lu) success\n", DeviceId);
PRTL_UNICODE_STRING_BUFFER Path
ACPI_SIZE strlen(const char *String)
BOOLEAN CacheReadDiskSectors(UCHAR DiskNumber, ULONGLONG StartSector, ULONG SectorCount, PVOID Buffer)
BOOLEAN CacheInitializeDrive(UCHAR DriveNumber)
#define DBG_DEFAULT_CHANNEL(ch)
#define FAST_SYMLINK_MAX_NAME_SIZE
#define EXT4_EXTENT_MAX_LEVEL
#define EXT_GROUP_DESC_SIZE(sb)
struct _ExtSuperBlock * PEXT_SUPER_BLOCK
#define EXT4_EXTENT_HEADER_MAGIC
struct _ExtDirEntry * PEXT_DIR_ENTRY
#define EXT_DIR_ENTRY_MAX_NAME_LENGTH
#define EXT_INODE_SIZE(sb)
#define EXT_SUPERBLOCK_MAGIC
struct _ExtGroupDescriptor * PEXT_GROUP_DESC
#define EXT4_EXTENT_MAX_LENGTH
#define EXT4_INODE_FLAG_EXTENTS
ARC_STATUS ArcSeek(ULONG FileId, LARGE_INTEGER *Position, SEEKMODE SeekMode)
PVOID FsGetDeviceSpecific(ULONG FileId)
ULONG FsGetNumPathParts(PCSTR Path)
VOID FsSetDeviceSpecific(ULONG FileId, PVOID Specific)
VOID FileSystemError(PCSTR ErrorString)
ULONG FsGetDeviceId(ULONG FileId)
ARC_STATUS ArcRead(ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
VOID FsGetFirstNameFromPath(PCHAR Buffer, PCSTR Path)
VOID FrLdrTempFree(PVOID Allocation, ULONG Tag)
PVOID FrLdrTempAlloc(_In_ SIZE_T Size, _In_ ULONG Tag)
BOOLEAN ExtCopyTripleIndirectBlockPointers(PEXT_VOLUME_INFO Volume, ULONG *BlockList, ULONG *CurrentBlockInList, ULONG BlockCount, ULONG TripleIndirectBlock)
PEXT_FILE_INFO ExtOpenFile(PEXT_VOLUME_INFO Volume, PCSTR FileName)
ULONG ExtGetInodeGroupNumber(PEXT_VOLUME_INFO Volume, ULONG Inode)
ARC_STATUS ExtGetFileInformation(ULONG FileId, FILEINFORMATION *Information)
#define TAG_EXT_BLOCK_LIST
BOOLEAN ExtCopyBlockPointersByExtents(PEXT_VOLUME_INFO Volume, ULONG *BlockList, ULONG *CurrentBlockInList, ULONG BlockCount, PEXT4_EXTENT_HEADER ExtentHeader)
ULONGLONG ExtGetVolumeSize(_In_ ULONG DeviceId)
Returns the size of the EXT2/3/4 volume laid on the storage media device opened via DeviceId.
BOOLEAN ExtReadGroupDescriptor(PEXT_VOLUME_INFO Volume, ULONG Group, PEXT_GROUP_DESC GroupBuffer)
BOOLEAN ExtCopyIndirectBlockPointers(PEXT_VOLUME_INFO Volume, ULONG *BlockList, ULONG *CurrentBlockInList, ULONG BlockCount, ULONG IndirectBlock)
BOOLEAN ExtReadFileBig(PEXT_FILE_INFO ExtFileInfo, ULONGLONG BytesToRead, ULONGLONG *BytesRead, PVOID Buffer)
const DEVVTBL ExtFuncTable
ULONGLONG ExtGetInodeFileSize(PEXT_INODE Inode)
BOOLEAN ExtReadVolumeSectors(PEXT_VOLUME_INFO Volume, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer)
ULONG ExtGetInodeBlockNumber(PEXT_VOLUME_INFO Volume, ULONG Inode)
BOOLEAN ExtReadDirectory(PEXT_VOLUME_INFO Volume, ULONG Inode, PVOID *DirectoryBuffer, PEXT_INODE InodePointer)
BOOLEAN ExtLookupFile(PEXT_VOLUME_INFO Volume, PCSTR FileName, PEXT_FILE_INFO ExtFileInfo)
BOOLEAN ExtReadBlock(PEXT_VOLUME_INFO Volume, ULONG BlockNumber, PVOID Buffer)
BOOLEAN ExtCopyDoubleIndirectBlockPointers(PEXT_VOLUME_INFO Volume, ULONG *BlockList, ULONG *CurrentBlockInList, ULONG BlockCount, ULONG DoubleIndirectBlock)
BOOLEAN ExtOpenVolume(PEXT_VOLUME_INFO Volume)
ARC_STATUS ExtSeek(ULONG FileId, LARGE_INTEGER *Position, SEEKMODE SeekMode)
PEXT_VOLUME_INFO ExtVolumes[MAX_FDS]
ULONG ExtGetInodeOffsetInBlock(PEXT_VOLUME_INFO Volume, ULONG Inode)
BOOLEAN ExtSearchDirectoryBufferForFile(PVOID DirectoryBuffer, ULONG DirectorySize, PCHAR FileName, PEXT_DIR_ENTRY DirectoryEntry)
BOOLEAN ExtReadInode(PEXT_VOLUME_INFO Volume, ULONG Inode, PEXT_INODE InodeBuffer)
BOOLEAN ExtReadPartialBlock(PEXT_VOLUME_INFO Volume, ULONG BlockNumber, ULONG StartingOffset, ULONG Length, PVOID Buffer)
const DEVVTBL * ExtMount(ULONG DeviceId)
ARC_STATUS ExtRead(ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
ARC_STATUS ExtClose(ULONG FileId)
ARC_STATUS ExtOpen(CHAR *Path, OPENMODE OpenMode, ULONG *FileId)
BOOLEAN ExtReadSuperBlock(PEXT_VOLUME_INFO Volume)
#define TAG_EXT_GROUP_DESC
ULONG * ExtReadBlockPointerList(PEXT_VOLUME_INFO Volume, PEXT_INODE Inode)
struct _EXT_VOLUME_INFO EXT_VOLUME_INFO
BOOLEAN ExtReadGroupDescriptors(PEXT_VOLUME_INFO Volume)
#define TAG_EXT_SUPER_BLOCK
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))
_In_ PFCB _In_ LONGLONG StartingOffset
#define _strnicmp(_String1, _String2, _MaxCount)
#define ROUND_UP(n, align)
struct _FileName FileName
_Must_inspect_result_ _In_opt_ PFLT_INSTANCE _Out_ PHANDLE FileHandle
_Must_inspect_result_ _Out_ PLARGE_INTEGER FileSize
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
static const ENTRY Entries[]
_In_ ULONG _In_ ULONG _In_ ULONG Length
CHAR FileName[RTL_FIELD_SIZE(FILEINFORMATION, FileName)]
ULONG FragmentSizeInSectors
ULONG GroupDescSizeInBytes
ULONG FragmentSizeInBytes
PEXT_GROUP_DESC GroupDescriptors
PEXT_SUPER_BLOCK SuperBlock
CHAR Name[EXT_DIR_ENTRY_MAX_NAME_LENGTH]
struct _ExtInode::@203::@205 Blocks
EXT4_EXTENT_HEADER ExtentHeader
ULONG AlgorithmUsageBitmap
USHORT MinorRevisionLevel
#define RtlCopyMemory(Destination, Source, Length)
#define RtlZeroMemory(Destination, Length)
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR _In_opt_ PLONGLONG _In_opt_ PWDF_REQUEST_SEND_OPTIONS _Out_opt_ PULONG_PTR BytesRead
_In_ WDFREQUEST _In_ NTSTATUS _In_ ULONG_PTR Information
_IRQL_requires_same_ typedef _In_ ULONG _In_ UCHAR Level