33#define TAG_NTFS_CONTEXT 'CftN'
34#define TAG_NTFS_LIST 'LftN'
35#define TAG_NTFS_MFT 'MftN'
36#define TAG_NTFS_INDEX_REC 'IftN'
37#define TAG_NTFS_BITMAP 'BftN'
38#define TAG_NTFS_FILE 'FftN'
39#define TAG_NTFS_VOLUME 'VftN'
40#define TAG_NTFS_DATA 'DftN'
42#define NTFS_MAX_ATTRIBUTE_LIST_RECURSION 8
64 return AttrRecord->
Resident.ValueLength;
69 UCHAR DataRunOffsetSize;
70 UCHAR DataRunLengthSize;
73 DataRunOffsetSize = (*DataRun >> 4) & 0xF;
74 DataRunLengthSize = *DataRun & 0xF;
78 for (
i = 0;
i < DataRunLengthSize;
i++)
80 *DataRunLength += ((
ULONG64)*DataRun) << (
i * 8);
85 if (DataRunOffsetSize == 0)
91 for (
i = 0;
i < DataRunOffsetSize - 1;
i++)
93 *DataRunOffset += ((
ULONG64)*DataRun) << (
i * 8);
97 *DataRunOffset = ((
LONG64)(
CHAR)(*(DataRun++)) << (
i * 8)) + *DataRunOffset;
100 TRACE(
"DataRunOffsetSize: %x\n", DataRunOffsetSize);
101 TRACE(
"DataRunLengthSize: %x\n", DataRunLengthSize);
102 TRACE(
"DataRunOffset: %x\n", *DataRunOffset);
103 TRACE(
"DataRunLength: %x\n", *DataRunLength);
123 Context->CacheRunLength = DataRunLength;
124 if (DataRunOffset != -1)
128 Context->CacheRunLastLCN = DataRunOffset;
133 Context->CacheRunStartLCN = -1;
136 Context->CacheRunCurrentOffset = 0;
235 if (!
Context->Record.IsNonResident)
260 LastLCN =
Context->CacheRunLastLCN;
261 DataRunStartLCN =
Context->CacheRunStartLCN;
262 DataRunLength =
Context->CacheRunLength;
263 CurrentOffset =
Context->CacheRunCurrentOffset;
273 DataRun =
NtfsDecodeRun(DataRun, &DataRunOffset, &DataRunLength);
274 if (DataRunOffset != -1)
277 DataRunStartLCN = LastLCN + DataRunOffset;
278 LastLCN = DataRunStartLCN;
283 DataRunStartLCN = -1;
286 if (
Offset >= CurrentOffset &&
287 Offset < CurrentOffset + (DataRunLength *
Volume->ClusterSize))
297 CurrentOffset += DataRunLength *
Volume->ClusterSize;
306 if (DataRunStartLCN == -1)
316 CurrentOffset += DataRunLength *
Volume->ClusterSize;
317 DataRun =
NtfsDecodeRun(DataRun, &DataRunOffset, &DataRunLength);
320 DataRunStartLCN = LastLCN + DataRunOffset;
321 LastLCN = DataRunStartLCN;
324 DataRunStartLCN = -1;
330 if (DataRunStartLCN == -1)
349 CurrentOffset += DataRunLength *
Volume->ClusterSize;
350 DataRun =
NtfsDecodeRun(DataRun, &DataRunOffset, &DataRunLength);
351 if (DataRunOffset != -1)
354 DataRunStartLCN = LastLCN + DataRunOffset;
355 LastLCN = DataRunStartLCN;
360 DataRunStartLCN = -1;
368 Context->CacheRunStartLCN = DataRunStartLCN;
369 Context->CacheRunLength = DataRunLength;
370 Context->CacheRunLastLCN = LastLCN;
371 Context->CacheRunCurrentOffset = CurrentOffset;
384 ULONG RecursionLimit,
396 ULONG RecursionLimit)
401 if (RecursionLimit < 1)
408 while (AttrListRecord < AttrListRecordEnd)
417 TRACE(
"RecursionLimit = %u, AttrType = 0x%x, MftIndex = %I64u\n", RecursionLimit, AttrType, MftIndex);
419 if (MftIndex == ParentMftIndex)
421 TRACE(
"Skipping unnecessary recursion level!\n");
425 if (AttrType ==
Type &&
436 if (PrevMftIndex != MftIndex)
438 PrevMftIndex = MftIndex;
447 AttrRecord, AttrRecordEnd,
449 RecursionLimit - 1, AttrId);
475 ULONG RecursionLimit,
482 if (RecursionLimit < 1)
485 while (AttrRecord < AttrRecordEnd)
493 TRACE(
"RecursionLimit = %u, AttrType = 0x%x\n", RecursionLimit, AttrType);
500 ListContext = ListBuffer =
NULL;
511 if (ListSize <= 0xFFFFFFFF)
518 TRACE(
"Failed to allocate memory: %x\n", (
ULONG)ListSize);
528 ListAttrRecord, ListAttrRecordEnd,
537 if (AttrType ==
Type &&
556 if (AttrRecord->
Length == 0)
577 for (NameLength = 0;
Name[NameLength] != 0; NameLength++)
591 USANumber = *(USA++);
592 USACount =
Record->USACount - 1;
597 if (*Block != USANumber)
624 CHAR AnsiFileName[256];
645 UCHAR EntryFileNameLength;
648 EntryFileName = IndexEntry->FileName.FileName;
649 EntryFileNameLength = IndexEntry->FileName.FileNameLength;
653 NtfsPrintFile(IndexEntry);
665 for (
i = 0;
i < EntryFileNameLength;
i++)
694 ULONG IndexBlockSize;
700 if (MftRecord ==
NULL)
710 if (IndexRootCtx ==
NULL)
717 if (IndexRecord ==
NULL)
732 while (IndexEntry < IndexEntryEnd &&
748 TRACE(
"Large Index!\n");
753 if (IndexBitmapCtx ==
NULL)
755 TRACE(
"Corrupted filesystem!\n");
760 TRACE(
"BitmapDataSize: %x\n", (
ULONG)BitmapDataSize);
761 if(BitmapDataSize <= 0xFFFFFFFF)
776 if (IndexAllocationCtx ==
NULL)
778 TRACE(
"Corrupted filesystem!\n");
790 TRACE(
"RecordOffset: %x IndexAllocationSize: %x\n", RecordOffset, IndexAllocationSize);
791 for (; RecordOffset < IndexAllocationSize;)
793 UCHAR Bit = 1 << ((RecordOffset / IndexBlockSize) & 7);
794 ULONG Byte = (RecordOffset / IndexBlockSize) >> 3;
797 RecordOffset += IndexBlockSize;
800 if (RecordOffset >= IndexAllocationSize)
816 while (IndexEntry < IndexEntryEnd &&
821 TRACE(
"File found\n");
833 RecordOffset += IndexBlockSize;
844 TRACE(
"Can't read MFT record\n");
853 ULONG NumberOfPathParts;
870 for (
i = 0;
i < NumberOfPathParts;
i++)
878 TRACE(
"- Lookup: %s\n", PathPart);
884 TRACE(
"- Lookup: %x\n", CurrentMFTIndex);
889 TRACE(
"NtfsLookupFile: Can't read MFT record\n");
896 TRACE(
"NtfsLookupFile: Can't find data attribute\n");
947 TRACE(
"NtfsGetFileInformation(%lu) -> FileSize = %llu, FilePointer = 0x%llx\n",
972 TRACE(
"NtfsOpen() FileName = %s\n",
Path);
1009 if (BytesRead64 > 0)
1051 return Volume->BootSector.VolumeSectorCount *
Volume->BootSector.BytesPerSector;
1072 TRACE(
"Enter NtfsMount(%lu)\n", DeviceId);
1111 Volume->ClusterSize =
Volume->BootSector.SectorsPerCluster *
Volume->BootSector.BytesPerSector;
1112 if (
Volume->BootSector.ClustersPerMftRecord > 0)
1113 Volume->MftRecordSize =
Volume->BootSector.ClustersPerMftRecord *
Volume->ClusterSize;
1115 Volume->MftRecordSize = 1 << (-
Volume->BootSector.ClustersPerMftRecord);
1116 if (
Volume->BootSector.ClustersPerIndexRecord > 0)
1117 Volume->IndexRecordSize =
Volume->BootSector.ClustersPerIndexRecord *
Volume->ClusterSize;
1119 Volume->IndexRecordSize = 1 << (-
Volume->BootSector.ClustersPerIndexRecord);
1121 TRACE(
"ClusterSize: 0x%x\n",
Volume->ClusterSize);
1122 TRACE(
"ClustersPerMftRecord: %d\n",
Volume->BootSector.ClustersPerMftRecord);
1123 TRACE(
"ClustersPerIndexRecord: %d\n",
Volume->BootSector.ClustersPerIndexRecord);
1124 TRACE(
"MftRecordSize: 0x%x\n",
Volume->MftRecordSize);
1125 TRACE(
"IndexRecordSize: 0x%x\n",
Volume->IndexRecordSize);
1130 TRACE(
"Reading MFT index...\n");
1132 if (!
Volume->MasterFileTable)
1159 if (!
Volume->TemporarySector)
1170 Volume->DeviceId = DeviceId;
1175 TRACE(
"Searching for DATA attribute...\n");
1193 TRACE(
"NtfsMount(%lu) success\n", DeviceId);
PRTL_UNICODE_STRING_BUFFER Path
#define DBG_DEFAULT_CHANNEL(ch)
struct NTFS_ATTR_RECORD * PNTFS_ATTR_RECORD
#define NTFS_FILE_ATTR_ARCHIVE
struct NTFS_INDEX_ENTRY * PNTFS_INDEX_ENTRY
#define NTFS_ATTR_TYPE_INDEX_ROOT
#define NTFS_FILE_ATTR_SYSTEM
#define NTFS_FILE_ATTR_DIRECTORY
#define NTFS_ATTR_TYPE_BITMAP
#define NTFS_ATTR_TYPE_DATA
#define NTFS_INDEX_ENTRY_END
#define NTFS_ATTR_TYPE_ATTRIBUTE_LIST
#define NTFS_ATTR_TYPE_END
#define NTFS_ATTR_TYPE_INDEX_ALLOCATION
#define NTFS_FILE_ATTR_READONLY
struct NTFS_MFT_RECORD * PNTFS_MFT_RECORD
#define NTFS_FILE_ATTR_HIDDEN
struct NTFS_ATTR_LIST_ATTR * PNTFS_ATTR_LIST_ATTR
struct NTFS_INDEX_ROOT * PNTFS_INDEX_ROOT
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)
static BOOLEAN NtfsDiskRead(PNTFS_VOLUME_INFO Volume, ULONGLONG Offset, ULONGLONG Length, PCHAR Buffer)
ARC_STATUS NtfsSeek(ULONG FileId, LARGE_INTEGER *Position, SEEKMODE SeekMode)
static BOOLEAN NtfsFixupRecord(PNTFS_VOLUME_INFO Volume, PNTFS_RECORD Record)
ULONGLONG NtfsGetVolumeSize(_In_ ULONG DeviceId)
Returns the size of the NTFS volume laid on the storage media device opened via DeviceId.
PNTFS_VOLUME_INFO NtfsVolumes[MAX_FDS]
ARC_STATUS NtfsOpen(CHAR *Path, OPENMODE OpenMode, ULONG *FileId)
ARC_STATUS NtfsGetFileInformation(ULONG FileId, FILEINFORMATION *Information)
static BOOLEAN NtfsLookupFile(PNTFS_VOLUME_INFO Volume, PCSTR FileName, PNTFS_MFT_RECORD MftRecord, PNTFS_FILE_HANDLE FileHandle)
static VOID NtfsReleaseAttributeContext(PNTFS_ATTR_CONTEXT Context)
static ULONG NtfsReadAttribute(PNTFS_VOLUME_INFO Volume, PNTFS_ATTR_CONTEXT Context, ULONGLONG Offset, PCHAR Buffer, ULONG Length)
static PNTFS_ATTR_CONTEXT NtfsPrepareAttributeContext(PNTFS_ATTR_RECORD AttrRecord)
static PNTFS_ATTR_CONTEXT NtfsFindAttributeHelper(PNTFS_VOLUME_INFO Volume, ULONGLONG CurrentMftIndex, PNTFS_ATTR_RECORD AttrRecord, PNTFS_ATTR_RECORD AttrRecordEnd, ULONG Type, const WCHAR *Name, ULONG NameLength, ULONG RecursionLimit, ULONG Instance)
const DEVVTBL NtfsFuncTable
static BOOLEAN NtfsCompareFileName(_In_ PCCH FileName, _In_ SIZE_T FileNameLen, _In_ PNTFS_INDEX_ENTRY IndexEntry)
#define TAG_NTFS_INDEX_REC
struct _NTFS_VOLUME_INFO NTFS_VOLUME_INFO
#define NTFS_MAX_ATTRIBUTE_LIST_RECURSION
ARC_STATUS NtfsClose(ULONG FileId)
static BOOLEAN NtfsFindMftRecord(_In_ PNTFS_VOLUME_INFO Volume, _In_ ULONGLONG MFTIndex, _In_ PCSTR FileName, _Out_ PULONGLONG OutMFTIndex, _Out_ PULONG FileAttributes)
static ULONGLONG NtfsGetAttributeSize(PNTFS_ATTR_RECORD AttrRecord)
static PNTFS_ATTR_CONTEXT NtfsFindAttribute(PNTFS_VOLUME_INFO Volume, PNTFS_MFT_RECORD MftRecord, ULONGLONG MftIndex, ULONG Type, const WCHAR *Name)
static PUCHAR NtfsDecodeRun(PUCHAR DataRun, LONGLONG *DataRunOffset, ULONGLONG *DataRunLength)
static BOOLEAN NtfsReadMftRecord(PNTFS_VOLUME_INFO Volume, ULONGLONG MFTIndex, PNTFS_MFT_RECORD Buffer)
static PNTFS_ATTR_CONTEXT NtfsFindAttributeHelperList(PNTFS_VOLUME_INFO Volume, ULONGLONG ParentMftIndex, PNTFS_ATTR_LIST_ATTR AttrListRecord, PNTFS_ATTR_LIST_ATTR AttrListRecordEnd, ULONG Type, const WCHAR *Name, ULONG NameLength, ULONG RecursionLimit)
const DEVVTBL * NtfsMount(ULONG DeviceId)
ARC_STATUS NtfsRead(ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))
_ACRTIMP size_t __cdecl strlen(const char *)
struct _FileName FileName
_Must_inspect_result_ _In_opt_ PFLT_INSTANCE _Out_ PHANDLE _In_ ACCESS_MASK _In_ POBJECT_ATTRIBUTES _Out_ PIO_STATUS_BLOCK _In_opt_ PLARGE_INTEGER _In_ ULONG FileAttributes
_Must_inspect_result_ _In_opt_ PFLT_INSTANCE _Out_ PHANDLE FileHandle
_Must_inspect_result_ _In_ PFILE_OBJECT _In_opt_ HANDLE _In_ ULONG FileNameLength
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
#define RtlEqualMemory(dst, src, len)
__GNU_EXTENSION typedef unsigned __int64 * PULONGLONG
_In_ ULONG _In_ ULONG Offset
_In_ ULONG _In_ ULONG _In_ ULONG Length
struct NTFS_ATTR_RECORD::@158::@160 Resident
struct NTFS_ATTR_RECORD::@158::@161 NonResident
NTFS_FILE_NAME_ATTR FileName
struct NTFS_INDEX_ENTRY::@162::@163 Directory
union NTFS_INDEX_ENTRY::@162 Data
NTFS_INDEX_HEADER IndexHeader
NTFS_BOOTSECTOR BootSector
PNTFS_MFT_RECORD MasterFileTable
PNTFS_ATTR_CONTEXT MFTContext
#define FIELD_OFFSET(t, f)
#define RtlCopyMemory(Destination, Source, Length)
#define RtlZeroMemory(Destination, Length)
_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
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_WMI_INSTANCE_CONFIG _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_opt_ WDFWMIINSTANCE * Instance
_In_ struct _KBUGCHECK_REASON_CALLBACK_RECORD * Record