ReactOS 0.4.16-dev-2279-gc890759
ntfs.c File Reference
#include <freeldr.h>
#include <debug.h>
Include dependency graph for ntfs.c:

Go to the source code of this file.

Classes

struct  _NTFS_VOLUME_INFO
 

Macros

#define TAG_NTFS_CONTEXT   'CftN'
 
#define TAG_NTFS_LIST   'LftN'
 
#define TAG_NTFS_MFT   'MftN'
 
#define TAG_NTFS_INDEX_REC   'IftN'
 
#define TAG_NTFS_BITMAP   'BftN'
 
#define TAG_NTFS_FILE   'FftN'
 
#define TAG_NTFS_VOLUME   'VftN'
 
#define TAG_NTFS_DATA   'DftN'
 
#define NTFS_MAX_ATTRIBUTE_LIST_RECURSION   8
 

Typedefs

typedef struct _NTFS_VOLUME_INFO NTFS_VOLUME_INFO
 

Functions

 DBG_DEFAULT_CHANNEL (FILESYSTEM)
 
static ULONGLONG NtfsGetAttributeSize (PNTFS_ATTR_RECORD AttrRecord)
 
static PUCHAR NtfsDecodeRun (PUCHAR DataRun, LONGLONG *DataRunOffset, ULONGLONG *DataRunLength)
 
static PNTFS_ATTR_CONTEXT NtfsPrepareAttributeContext (PNTFS_ATTR_RECORD AttrRecord)
 
static VOID NtfsReleaseAttributeContext (PNTFS_ATTR_CONTEXT Context)
 
static BOOLEAN NtfsDiskRead (PNTFS_VOLUME_INFO Volume, ULONGLONG Offset, ULONGLONG Length, PCHAR Buffer)
 
static ULONG NtfsReadAttribute (PNTFS_VOLUME_INFO Volume, PNTFS_ATTR_CONTEXT Context, ULONGLONG Offset, PCHAR Buffer, ULONG Length)
 
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)
 
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)
 
static PNTFS_ATTR_CONTEXT NtfsFindAttribute (PNTFS_VOLUME_INFO Volume, PNTFS_MFT_RECORD MftRecord, ULONGLONG MftIndex, ULONG Type, const WCHAR *Name)
 
static BOOLEAN NtfsFixupRecord (PNTFS_VOLUME_INFO Volume, PNTFS_RECORD Record)
 
static BOOLEAN NtfsCompareFileName (_In_ PCCH FileName, _In_ SIZE_T FileNameLen, _In_ PNTFS_INDEX_ENTRY IndexEntry)
 
static BOOLEAN NtfsFindMftRecord (_In_ PNTFS_VOLUME_INFO Volume, _In_ ULONGLONG MFTIndex, _In_ PCSTR FileName, _Out_ PULONGLONG OutMFTIndex, _Out_ PULONG FileAttributes)
 
static BOOLEAN NtfsLookupFile (PNTFS_VOLUME_INFO Volume, PCSTR FileName, PNTFS_MFT_RECORD MftRecord, PNTFS_FILE_HANDLE FileHandle)
 
ARC_STATUS NtfsClose (ULONG FileId)
 
ARC_STATUS NtfsGetFileInformation (ULONG FileId, FILEINFORMATION *Information)
 
ARC_STATUS NtfsOpen (CHAR *Path, OPENMODE OpenMode, ULONG *FileId)
 
ARC_STATUS NtfsRead (ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
 
ARC_STATUS NtfsSeek (ULONG FileId, LARGE_INTEGER *Position, SEEKMODE SeekMode)
 
ULONGLONG NtfsGetVolumeSize (_In_ ULONG DeviceId)
 Returns the size of the NTFS volume laid on the storage media device opened via DeviceId.
 
const DEVVTBLNtfsMount (ULONG DeviceId)
 

Variables

PNTFS_VOLUME_INFO NtfsVolumes [MAX_FDS]
 
const DEVVTBL NtfsFuncTable
 

Macro Definition Documentation

◆ NTFS_MAX_ATTRIBUTE_LIST_RECURSION

#define NTFS_MAX_ATTRIBUTE_LIST_RECURSION   8

Definition at line 42 of file ntfs.c.

◆ TAG_NTFS_BITMAP

#define TAG_NTFS_BITMAP   'BftN'

Definition at line 37 of file ntfs.c.

◆ TAG_NTFS_CONTEXT

#define TAG_NTFS_CONTEXT   'CftN'

Definition at line 33 of file ntfs.c.

◆ TAG_NTFS_DATA

#define TAG_NTFS_DATA   'DftN'

Definition at line 40 of file ntfs.c.

◆ TAG_NTFS_FILE

#define TAG_NTFS_FILE   'FftN'

Definition at line 38 of file ntfs.c.

◆ TAG_NTFS_INDEX_REC

#define TAG_NTFS_INDEX_REC   'IftN'

Definition at line 36 of file ntfs.c.

◆ TAG_NTFS_LIST

#define TAG_NTFS_LIST   'LftN'

Definition at line 34 of file ntfs.c.

◆ TAG_NTFS_MFT

#define TAG_NTFS_MFT   'MftN'

Definition at line 35 of file ntfs.c.

◆ TAG_NTFS_VOLUME

#define TAG_NTFS_VOLUME   'VftN'

Definition at line 39 of file ntfs.c.

Typedef Documentation

◆ NTFS_VOLUME_INFO

Function Documentation

◆ DBG_DEFAULT_CHANNEL()

DBG_DEFAULT_CHANNEL ( FILESYSTEM  )

◆ NtfsClose()

ARC_STATUS NtfsClose ( ULONG  FileId)

Definition at line 921 of file ntfs.c.

922{
924
927
928 return ESUCCESS;
929}
PVOID FsGetDeviceSpecific(ULONG FileId)
Definition: fs.c:709
VOID FrLdrTempFree(PVOID Allocation, ULONG Tag)
Definition: heap.c:553
static VOID NtfsReleaseAttributeContext(PNTFS_ATTR_CONTEXT Context)
Definition: ntfs.c:142
#define TAG_NTFS_FILE
Definition: ntfs.c:38
_Must_inspect_result_ _In_opt_ PFLT_INSTANCE _Out_ PHANDLE FileHandle
Definition: fltkernel.h:1231
@ ESUCCESS
Definition: arc.h:32

Referenced by NtfsDispatch().

◆ NtfsCompareFileName()

static BOOLEAN NtfsCompareFileName ( _In_ PCCH  FileName,
_In_ SIZE_T  FileNameLen,
_In_ PNTFS_INDEX_ENTRY  IndexEntry 
)
static

Definition at line 639 of file ntfs.c.

643{
644 PWCHAR EntryFileName;
645 UCHAR EntryFileNameLength;
646 UCHAR i;
647
648 EntryFileName = IndexEntry->FileName.FileName;
649 EntryFileNameLength = IndexEntry->FileName.FileNameLength;
650
651#if DBG
652 TRACE("%s ", FileName);
653 NtfsPrintFile(IndexEntry);
654#endif
655
656 if (FileNameLen != EntryFileNameLength)
657 return FALSE;
658
659 /*
660 * Always perform case-insensitive comparison for file names.
661 * This is necessary, because when modifying e.g. on Linux a Windows NTFS
662 * partition formatted with Windows itself, the NTLDR/BOOTMGR will boot
663 * normally ignoring the case of the paths.
664 */
665 for (i = 0; i < EntryFileNameLength; i++)
666 {
667 if (tolower(EntryFileName[i]) != tolower(FileName[i]))
668 return FALSE;
669 }
670
671 return TRUE;
672}
Dirent FileNameLen
Definition: dirsup.c:506
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
int CDECL tolower(int c)
Definition: ctype.c:572
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
Definition: glfuncs.h:248
#define TRACE(s)
Definition: solgame.cpp:4
uint16_t * PWCHAR
Definition: typedefs.h:56
unsigned char UCHAR
Definition: xmlstorage.h:181

Referenced by NtfsFindMftRecord().

◆ NtfsDecodeRun()

static PUCHAR NtfsDecodeRun ( PUCHAR  DataRun,
LONGLONG DataRunOffset,
ULONGLONG DataRunLength 
)
static

Definition at line 67 of file ntfs.c.

68{
69 UCHAR DataRunOffsetSize;
70 UCHAR DataRunLengthSize;
71 CHAR i;
72
73 DataRunOffsetSize = (*DataRun >> 4) & 0xF;
74 DataRunLengthSize = *DataRun & 0xF;
75 *DataRunOffset = 0;
76 *DataRunLength = 0;
77 DataRun++;
78 for (i = 0; i < DataRunLengthSize; i++)
79 {
80 *DataRunLength += ((ULONG64)*DataRun) << (i * 8);
81 DataRun++;
82 }
83
84 /* NTFS 3+ sparse files */
85 if (DataRunOffsetSize == 0)
86 {
87 *DataRunOffset = -1;
88 }
89 else
90 {
91 for (i = 0; i < DataRunOffsetSize - 1; i++)
92 {
93 *DataRunOffset += ((ULONG64)*DataRun) << (i * 8);
94 DataRun++;
95 }
96 /* The last byte contains sign so we must process it different way. */
97 *DataRunOffset = ((LONG64)(CHAR)(*(DataRun++)) << (i * 8)) + *DataRunOffset;
98 }
99
100 TRACE("DataRunOffsetSize: %x\n", DataRunOffsetSize);
101 TRACE("DataRunLengthSize: %x\n", DataRunLengthSize);
102 TRACE("DataRunOffset: %x\n", *DataRunOffset);
103 TRACE("DataRunLength: %x\n", *DataRunLength);
104
105 return DataRun;
106}
unsigned __int64 ULONG64
Definition: imports.h:198
int64_t LONG64
Definition: typedefs.h:68
char CHAR
Definition: xmlstorage.h:175

Referenced by NtfsPrepareAttributeContext(), and NtfsReadAttribute().

◆ NtfsDiskRead()

static BOOLEAN NtfsDiskRead ( PNTFS_VOLUME_INFO  Volume,
ULONGLONG  Offset,
ULONGLONG  Length,
PCHAR  Buffer 
)
static

Definition at line 147 of file ntfs.c.

148{
150 ULONG Count;
153
154 TRACE("NtfsDiskRead - Offset: %I64u Length: %I64u\n", Offset, Length);
155
156 //
157 // I. Read partial first sector if needed
158 //
159 if (Offset % Volume->BootSector.BytesPerSector)
160 {
161 Position.QuadPart = Offset & ~(Volume->BootSector.BytesPerSector - 1);
162 Status = ArcSeek(Volume->DeviceId, &Position, SeekAbsolute);
163 if (Status != ESUCCESS)
164 return FALSE;
165 Status = ArcRead(Volume->DeviceId, Volume->TemporarySector, Volume->BootSector.BytesPerSector, &Count);
166 if (Status != ESUCCESS || Count != Volume->BootSector.BytesPerSector)
167 return FALSE;
168 ReadLength = (USHORT)min(Length, Volume->BootSector.BytesPerSector - (Offset % Volume->BootSector.BytesPerSector));
169
170 //
171 // Copy interesting data
172 //
174 &Volume->TemporarySector[Offset % Volume->BootSector.BytesPerSector],
175 ReadLength);
176
177 //
178 // Move to unfilled buffer part
179 //
183 }
184
185 //
186 // II. Read all complete blocks
187 //
188 if (Length >= Volume->BootSector.BytesPerSector)
189 {
190 Position.QuadPart = Offset;
191 Status = ArcSeek(Volume->DeviceId, &Position, SeekAbsolute);
192 if (Status != ESUCCESS)
193 return FALSE;
194 ReadLength = Length & ~(Volume->BootSector.BytesPerSector - 1);
195 Status = ArcRead(Volume->DeviceId, Buffer, ReadLength, &Count);
196 if (Status != ESUCCESS || Count != ReadLength)
197 return FALSE;
198
199 //
200 // Move to unfilled buffer part
201 //
205 }
206
207 //
208 // III. Read the rest of data
209 //
210 if (Length)
211 {
212 Position.QuadPart = Offset;
213 Status = ArcSeek(Volume->DeviceId, &Position, SeekAbsolute);
214 if (Status != ESUCCESS)
215 return FALSE;
216 Status = ArcRead(Volume->DeviceId, Buffer, (ULONG)Length, &Count);
217 if (Status != ESUCCESS || Count != Length)
218 return FALSE;
219 }
220
221 return TRUE;
222}
ULONG ReadLength
ARC_STATUS ArcSeek(ULONG FileId, LARGE_INTEGER *Position, SEEKMODE SeekMode)
Definition: fs.c:455
ARC_STATUS ArcRead(ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
Definition: fs.c:448
Definition: bufpool.h:45
Status
Definition: gdiplustypes.h:25
UNICODE_STRING Volume
Definition: fltkernel.h:1172
#define min(a, b)
Definition: monoChain.cc:55
int Count
Definition: noreturn.cpp:7
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
unsigned short USHORT
Definition: pedump.c:61
ULONG ARC_STATUS
Definition: arc.h:4
@ SeekAbsolute
Definition: arc.h:59
static COORD Position
Definition: mouse.c:34
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint32_t ULONG
Definition: typedefs.h:59

Referenced by NtfsReadAttribute().

◆ NtfsFindAttribute()

static PNTFS_ATTR_CONTEXT NtfsFindAttribute ( PNTFS_VOLUME_INFO  Volume,
PNTFS_MFT_RECORD  MftRecord,
ULONGLONG  MftIndex,
ULONG  Type,
const WCHAR Name 
)
static

Definition at line 569 of file ntfs.c.

570{
571 PNTFS_ATTR_RECORD AttrRecord;
572 PNTFS_ATTR_RECORD AttrRecordEnd;
573 ULONG NameLength;
574
575 AttrRecord = (PNTFS_ATTR_RECORD)((PCHAR)MftRecord + MftRecord->AttributesOffset);
576 AttrRecordEnd = (PNTFS_ATTR_RECORD)((PCHAR)MftRecord + Volume->MftRecordSize);
577 for (NameLength = 0; Name[NameLength] != 0; NameLength++)
578 ;
579
580 return NtfsFindAttributeHelper(Volume, MftIndex, AttrRecord, AttrRecordEnd, Type, Name, NameLength, NTFS_MAX_ATTRIBUTE_LIST_RECURSION, -1);
581}
Type
Definition: Type.h:7
struct NTFS_ATTR_RECORD * PNTFS_ATTR_RECORD
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)
Definition: ntfs.c:467
#define NTFS_MAX_ATTRIBUTE_LIST_RECURSION
Definition: ntfs.c:42
LPWSTR Name
Definition: desk.c:124
USHORT AttributesOffset
Definition: ntfs.h:122
char * PCHAR
Definition: typedefs.h:51

Referenced by NtfsFindMftRecord(), NtfsLookupFile(), and NtfsMount().

◆ NtfsFindAttributeHelper()

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 
)
static

Definition at line 467 of file ntfs.c.

477{
479 PNTFS_ATTR_CONTEXT ListContext = NULL;
480 PVOID ListBuffer = NULL;
481 ULONGLONG ListSize = 0;
482 if (RecursionLimit < 1)
483 return NULL;
484
485 while (AttrRecord < AttrRecordEnd)
486 {
487 ULONG AttrType = AttrRecord->Type;
488 ULONG AttrInstance = AttrRecord->Instance;
489
490 if (AttrType == NTFS_ATTR_TYPE_END)
491 break;
492
493 TRACE("RecursionLimit = %u, AttrType = 0x%x\n", RecursionLimit, AttrType);
494
495 if (ListContext)
496 NtfsReleaseAttributeContext(ListContext);
497 if (ListBuffer)
498 FrLdrTempFree(ListBuffer, TAG_NTFS_LIST);
499
500 ListContext = ListBuffer = NULL;
501
502 /* Limit the $ATTRIBUTE_LIST recursion or else infinity loop */
503 if (AttrType != Type && AttrType == NTFS_ATTR_TYPE_ATTRIBUTE_LIST && RecursionLimit >= 2)
504 {
505 PNTFS_ATTR_LIST_ATTR ListAttrRecord;
506 PNTFS_ATTR_LIST_ATTR ListAttrRecordEnd;
507
508 ListContext = NtfsPrepareAttributeContext(AttrRecord);
509
510 ListSize = NtfsGetAttributeSize(&ListContext->Record);
511 if (ListSize <= 0xFFFFFFFF)
512 ListBuffer = FrLdrTempAlloc((ULONG)ListSize, TAG_NTFS_LIST);
513 else
514 ListBuffer = NULL;
515
516 if (!ListBuffer)
517 {
518 TRACE("Failed to allocate memory: %x\n", (ULONG)ListSize);
519 goto skip;
520 }
521
522 ListAttrRecord = (PNTFS_ATTR_LIST_ATTR)ListBuffer;
523 ListAttrRecordEnd = (PNTFS_ATTR_LIST_ATTR)((PCHAR)ListBuffer + ListSize);
524
525 if (NtfsReadAttribute(Volume, ListContext, 0, ListBuffer, (ULONG)ListSize) == ListSize)
526 {
527 Context = NtfsFindAttributeHelperList(Volume, CurrentMftIndex,
528 ListAttrRecord, ListAttrRecordEnd,
529 Type, Name, NameLength,
530 RecursionLimit - 1);
531
532 if (Context != NULL)
533 break;
534 }
535 }
536
537 if (AttrType == Type &&
538 AttrRecord->NameLength == NameLength &&
539 /* HACK for ntfs3 driver on linux! Because the ntfs3 likes to generate invalid
540 * attribute size when mft record increases and I don't know how I will handle this */
541 NtfsGetAttributeSize(AttrRecord) != 0 &&
542 (Instance == (ULONG)-1 || AttrInstance == Instance))
543 {
544 PWCHAR AttrName;
545
546 AttrName = (PWCHAR)((PCHAR)AttrRecord + AttrRecord->NameOffset);
547 if (RtlEqualMemory(AttrName, Name, NameLength * sizeof(WCHAR)))
548 {
549 /* Found it, fill up the context and return */
551 break;
552 }
553 }
554
555skip:
556 if (AttrRecord->Length == 0)
557 break;
558 AttrRecord = (PNTFS_ATTR_RECORD)((PCHAR)AttrRecord + AttrRecord->Length);
559 }
560
561 if (ListContext)
562 NtfsReleaseAttributeContext(ListContext);
563 if (ListBuffer)
564 FrLdrTempFree(ListBuffer, TAG_NTFS_LIST);
565
566 return Context;
567}
#define skip(...)
Definition: atltest.h:64
#define NTFS_ATTR_TYPE_ATTRIBUTE_LIST
Definition: ntfs.h:37
#define NTFS_ATTR_TYPE_END
Definition: ntfs.h:50
struct NTFS_ATTR_LIST_ATTR * PNTFS_ATTR_LIST_ATTR
PVOID FrLdrTempAlloc(_In_ SIZE_T Size, _In_ ULONG Tag)
Definition: heap.c:545
#define TAG_NTFS_LIST
Definition: ntfs.c:34
static ULONG NtfsReadAttribute(PNTFS_VOLUME_INFO Volume, PNTFS_ATTR_CONTEXT Context, ULONGLONG Offset, PCHAR Buffer, ULONG Length)
Definition: ntfs.c:224
static PNTFS_ATTR_CONTEXT NtfsPrepareAttributeContext(PNTFS_ATTR_RECORD AttrRecord)
Definition: ntfs.c:108
static ULONGLONG NtfsGetAttributeSize(PNTFS_ATTR_RECORD AttrRecord)
Definition: ntfs.c:59
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)
Definition: ntfs.c:388
#define NULL
Definition: types.h:112
#define RtlEqualMemory(dst, src, len)
Definition: kdvm.h:18
NTFS_ATTR_RECORD Record
Definition: ntfs.h:246
ULONG Length
Definition: ntfs.h:135
USHORT NameOffset
Definition: ntfs.h:138
USHORT Instance
Definition: ntfs.h:140
UCHAR NameLength
Definition: ntfs.h:137
ULONG Type
Definition: ntfs.h:134
uint64_t ULONGLONG
Definition: typedefs.h:67
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_WMI_INSTANCE_CONFIG _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_opt_ WDFWMIINSTANCE * Instance
Definition: wdfwmi.h:481
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by NtfsFindAttribute(), and NtfsFindAttributeHelperList().

◆ NtfsFindAttributeHelperList()

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 
)
static

Definition at line 388 of file ntfs.c.

397{
398 ULONGLONG PrevMftIndex = -1;
400 PNTFS_MFT_RECORD MftRecord;
401 if (RecursionLimit < 1)
402 return NULL;
403
404 MftRecord = FrLdrTempAlloc(Volume->MftRecordSize, TAG_NTFS_MFT);
405 if (!MftRecord)
406 return NULL;
407
408 while (AttrListRecord < AttrListRecordEnd)
409 {
410 ULONGLONG MftIndex = AttrListRecord->BaseFileRef & NTFS_MFT_MASK;
411 ULONG AttrType = AttrListRecord->Type;
412 ULONG AttrId = AttrListRecord->AttrId;
413
414 if (AttrType == NTFS_ATTR_TYPE_END)
415 break;
416
417 TRACE("RecursionLimit = %u, AttrType = 0x%x, MftIndex = %I64u\n", RecursionLimit, AttrType, MftIndex);
418
419 if (MftIndex == ParentMftIndex)
420 {
421 TRACE("Skipping unnecessary recursion level!\n");
422 goto skip;
423 }
424
425 if (AttrType == Type &&
426 AttrListRecord->NameLength == NameLength)
427 {
428 PWCHAR AttrListName;
429
430 AttrListName = (PWCHAR)((PCHAR)AttrListRecord + AttrListRecord->NameOffset);
431 if (RtlEqualMemory(AttrListName, Name, NameLength * sizeof(WCHAR)))
432 {
433 PNTFS_ATTR_RECORD AttrRecord;
434 PNTFS_ATTR_RECORD AttrRecordEnd;
435
436 if (PrevMftIndex != MftIndex)
437 {
438 PrevMftIndex = MftIndex;
439 if (!NtfsReadMftRecord(Volume, MftIndex, MftRecord))
440 goto skip;
441 }
442
443 AttrRecord = (PNTFS_ATTR_RECORD)((PCHAR)MftRecord + MftRecord->AttributesOffset);
444 AttrRecordEnd = (PNTFS_ATTR_RECORD)((PCHAR)MftRecord + Volume->MftRecordSize);
445
447 AttrRecord, AttrRecordEnd,
448 Type, Name, NameLength,
449 RecursionLimit - 1, AttrId);
450 if (Context)
451 break;
452 }
453 }
454
455skip:
456 if (AttrListRecord->RecLength == 0)
457 break;
458 AttrListRecord = (PNTFS_ATTR_LIST_ATTR)((PCHAR)AttrListRecord + AttrListRecord->RecLength);
459 }
460
461 if (MftRecord)
462 FrLdrTempFree(MftRecord, TAG_NTFS_MFT);
463
464 return Context;
465}
#define NTFS_MFT_MASK
Definition: ntfs.h:76
#define TAG_NTFS_MFT
Definition: ntfs.c:35
static BOOLEAN NtfsReadMftRecord(PNTFS_VOLUME_INFO Volume, ULONGLONG MFTIndex, PNTFS_MFT_RECORD Buffer)
Definition: ntfs.c:607
UCHAR NameOffset
Definition: ntfs.h:208
ULONGLONG BaseFileRef
Definition: ntfs.h:210
USHORT AttrId
Definition: ntfs.h:211
USHORT RecLength
Definition: ntfs.h:206
UCHAR NameLength
Definition: ntfs.h:207

Referenced by NtfsFindAttributeHelper().

◆ NtfsFindMftRecord()

static BOOLEAN NtfsFindMftRecord ( _In_ PNTFS_VOLUME_INFO  Volume,
_In_ ULONGLONG  MFTIndex,
_In_ PCSTR  FileName,
_Out_ PULONGLONG  OutMFTIndex,
_Out_ PULONG  FileAttributes 
)
static

Definition at line 675 of file ntfs.c.

681{
682 PNTFS_MFT_RECORD MftRecord;
683 //ULONG Magic;
684 PNTFS_ATTR_CONTEXT IndexRootCtx;
685 PNTFS_ATTR_CONTEXT IndexBitmapCtx;
686 PNTFS_ATTR_CONTEXT IndexAllocationCtx;
687 PNTFS_INDEX_ROOT IndexRoot;
688 ULONGLONG BitmapDataSize;
689 ULONGLONG IndexAllocationSize;
691 PCHAR IndexRecord;
692 PNTFS_INDEX_ENTRY IndexEntry, IndexEntryEnd;
693 ULONG RecordOffset;
694 ULONG IndexBlockSize;
696
698
699 MftRecord = FrLdrTempAlloc(Volume->MftRecordSize, TAG_NTFS_MFT);
700 if (MftRecord == NULL)
701 {
702 return FALSE;
703 }
704
705 if (NtfsReadMftRecord(Volume, MFTIndex, MftRecord))
706 {
707 //Magic = MftRecord->Magic;
708
709 IndexRootCtx = NtfsFindAttribute(Volume, MftRecord, MFTIndex, NTFS_ATTR_TYPE_INDEX_ROOT, L"$I30");
710 if (IndexRootCtx == NULL)
711 {
712 FrLdrTempFree(MftRecord, TAG_NTFS_MFT);
713 return FALSE;
714 }
715
716 IndexRecord = FrLdrTempAlloc(Volume->IndexRecordSize, TAG_NTFS_INDEX_REC);
717 if (IndexRecord == NULL)
718 {
719 FrLdrTempFree(MftRecord, TAG_NTFS_MFT);
720 return FALSE;
721 }
722
723 NtfsReadAttribute(Volume, IndexRootCtx, 0, IndexRecord, Volume->IndexRecordSize);
724 IndexRoot = (PNTFS_INDEX_ROOT)IndexRecord;
725 IndexEntry = (PNTFS_INDEX_ENTRY)((PCHAR)&IndexRoot->IndexHeader + IndexRoot->IndexHeader.EntriesOffset);
726 /* Index root is always resident. */
727 IndexEntryEnd = (PNTFS_INDEX_ENTRY)(IndexRecord + IndexRootCtx->Record.Resident.ValueLength);
728 NtfsReleaseAttributeContext(IndexRootCtx);
729
730 TRACE("IndexRecordSize: %x IndexBlockSize: %x\n", Volume->IndexRecordSize, IndexRoot->IndexBlockSize);
731
732 while (IndexEntry < IndexEntryEnd &&
733 !(IndexEntry->Flags & NTFS_INDEX_ENTRY_END))
734 {
735 if (NtfsCompareFileName(FileName, FileNameLen, IndexEntry))
736 {
737 *OutMFTIndex = (IndexEntry->Data.Directory.IndexedFile & NTFS_MFT_MASK);
739 FrLdrTempFree(IndexRecord, TAG_NTFS_INDEX_REC);
740 FrLdrTempFree(MftRecord, TAG_NTFS_MFT);
741 return TRUE;
742 }
743 IndexEntry = (PNTFS_INDEX_ENTRY)((PCHAR)IndexEntry + IndexEntry->Length);
744 }
745
746 if (IndexRoot->IndexHeader.Flags & NTFS_LARGE_INDEX)
747 {
748 TRACE("Large Index!\n");
749
750 IndexBlockSize = IndexRoot->IndexBlockSize;
751
752 IndexBitmapCtx = NtfsFindAttribute(Volume, MftRecord, MFTIndex, NTFS_ATTR_TYPE_BITMAP, L"$I30");
753 if (IndexBitmapCtx == NULL)
754 {
755 TRACE("Corrupted filesystem!\n");
756 FrLdrTempFree(MftRecord, TAG_NTFS_MFT);
757 return FALSE;
758 }
759 BitmapDataSize = NtfsGetAttributeSize(&IndexBitmapCtx->Record);
760 TRACE("BitmapDataSize: %x\n", (ULONG)BitmapDataSize);
761 if(BitmapDataSize <= 0xFFFFFFFF)
763 else
765
766 if (BitmapData == NULL)
767 {
768 FrLdrTempFree(IndexRecord, TAG_NTFS_INDEX_REC);
769 FrLdrTempFree(MftRecord, TAG_NTFS_MFT);
770 return FALSE;
771 }
772 NtfsReadAttribute(Volume, IndexBitmapCtx, 0, BitmapData, (ULONG)BitmapDataSize);
773 NtfsReleaseAttributeContext(IndexBitmapCtx);
774
775 IndexAllocationCtx = NtfsFindAttribute(Volume, MftRecord, MFTIndex, NTFS_ATTR_TYPE_INDEX_ALLOCATION, L"$I30");
776 if (IndexAllocationCtx == NULL)
777 {
778 TRACE("Corrupted filesystem!\n");
780 FrLdrTempFree(IndexRecord, TAG_NTFS_INDEX_REC);
781 FrLdrTempFree(MftRecord, TAG_NTFS_MFT);
782 return FALSE;
783 }
784 IndexAllocationSize = NtfsGetAttributeSize(&IndexAllocationCtx->Record);
785
786 RecordOffset = 0;
787
788 for (;;)
789 {
790 TRACE("RecordOffset: %x IndexAllocationSize: %x\n", RecordOffset, IndexAllocationSize);
791 for (; RecordOffset < IndexAllocationSize;)
792 {
793 UCHAR Bit = 1 << ((RecordOffset / IndexBlockSize) & 7);
794 ULONG Byte = (RecordOffset / IndexBlockSize) >> 3;
795 if ((BitmapData[Byte] & Bit))
796 break;
797 RecordOffset += IndexBlockSize;
798 }
799
800 if (RecordOffset >= IndexAllocationSize)
801 {
802 break;
803 }
804
805 NtfsReadAttribute(Volume, IndexAllocationCtx, RecordOffset, IndexRecord, IndexBlockSize);
806
807 if (!NtfsFixupRecord(Volume, (PNTFS_RECORD)IndexRecord))
808 {
809 break;
810 }
811
812 /* FIXME */
813 IndexEntry = (PNTFS_INDEX_ENTRY)(IndexRecord + 0x18 + *(USHORT *)(IndexRecord + 0x18));
814 IndexEntryEnd = (PNTFS_INDEX_ENTRY)(IndexRecord + IndexBlockSize);
815
816 while (IndexEntry < IndexEntryEnd &&
817 !(IndexEntry->Flags & NTFS_INDEX_ENTRY_END))
818 {
819 if (NtfsCompareFileName(FileName, FileNameLen, IndexEntry))
820 {
821 TRACE("File found\n");
822 *OutMFTIndex = (IndexEntry->Data.Directory.IndexedFile & NTFS_MFT_MASK);
824 NtfsReleaseAttributeContext(IndexAllocationCtx);
826 FrLdrTempFree(IndexRecord, TAG_NTFS_INDEX_REC);
827 FrLdrTempFree(MftRecord, TAG_NTFS_MFT);
828 return TRUE;
829 }
830 IndexEntry = (PNTFS_INDEX_ENTRY)((PCHAR)IndexEntry + IndexEntry->Length);
831 }
832
833 RecordOffset += IndexBlockSize;
834 }
835
836 NtfsReleaseAttributeContext(IndexAllocationCtx);
838 }
839
840 FrLdrTempFree(IndexRecord, TAG_NTFS_INDEX_REC);
841 }
842 else
843 {
844 TRACE("Can't read MFT record\n");
845 }
846 FrLdrTempFree(MftRecord, TAG_NTFS_MFT);
847
848 return FALSE;
849}
struct NTFS_INDEX_ENTRY * PNTFS_INDEX_ENTRY
#define NTFS_ATTR_TYPE_INDEX_ROOT
Definition: ntfs.h:44
#define NTFS_ATTR_TYPE_BITMAP
Definition: ntfs.h:46
#define NTFS_INDEX_ENTRY_END
Definition: ntfs.h:61
#define NTFS_ATTR_TYPE_INDEX_ALLOCATION
Definition: ntfs.h:45
#define NTFS_LARGE_INDEX
Definition: ntfs.h:58
struct NTFS_INDEX_ROOT * PNTFS_INDEX_ROOT
static BOOLEAN NtfsFixupRecord(PNTFS_VOLUME_INFO Volume, PNTFS_RECORD Record)
Definition: ntfs.c:583
static BOOLEAN NtfsCompareFileName(_In_ PCCH FileName, _In_ SIZE_T FileNameLen, _In_ PNTFS_INDEX_ENTRY IndexEntry)
Definition: ntfs.c:639
#define TAG_NTFS_INDEX_REC
Definition: ntfs.c:36
static PNTFS_ATTR_CONTEXT NtfsFindAttribute(PNTFS_VOLUME_INFO Volume, PNTFS_MFT_RECORD MftRecord, ULONGLONG MftIndex, ULONG Type, const WCHAR *Name)
Definition: ntfs.c:569
#define TAG_NTFS_BITMAP
Definition: ntfs.c:37
unsigned char Byte
Definition: zlib.h:37
_ACRTIMP size_t __cdecl strlen(const char *)
Definition: string.c:1592
#define L(x)
Definition: resources.c:13
_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
Definition: fltkernel.h:1236
struct NTFS_ATTR_RECORD::@157::@159 Resident
ULONG FileAttributes
Definition: ntfs.h:195
Definition: ntfs.h:216
union NTFS_INDEX_ENTRY::@161 Data
struct NTFS_INDEX_ENTRY::@161::@162 Directory
NTFS_FILE_NAME_ATTR FileName
Definition: ntfs.h:234
USHORT Flags
Definition: ntfs.h:232
USHORT Length
Definition: ntfs.h:230
UCHAR Flags
Definition: ntfs.h:172
ULONG EntriesOffset
Definition: ntfs.h:169
NTFS_INDEX_HEADER IndexHeader
Definition: ntfs.h:183
ULONG IndexBlockSize
Definition: ntfs.h:180
ULONG_PTR SIZE_T
Definition: typedefs.h:80

Referenced by AddFileName(), and NtfsLookupFile().

◆ NtfsFixupRecord()

static BOOLEAN NtfsFixupRecord ( PNTFS_VOLUME_INFO  Volume,
PNTFS_RECORD  Record 
)
static

Definition at line 583 of file ntfs.c.

584{
585 USHORT *USA;
586 USHORT USANumber;
587 USHORT USACount;
588 USHORT *Block;
589
590 USA = (USHORT*)((PCHAR)Record + Record->USAOffset);
591 USANumber = *(USA++);
592 USACount = Record->USACount - 1; /* Exclude the USA Number. */
593 Block = (USHORT*)((PCHAR)Record + Volume->BootSector.BytesPerSector - 2);
594
595 while (USACount)
596 {
597 if (*Block != USANumber)
598 return FALSE;
599 *Block = *(USA++);
600 Block = (USHORT*)((PCHAR)Block + Volume->BootSector.BytesPerSector);
601 USACount--;
602 }
603
604 return TRUE;
605}
_In_ struct _KBUGCHECK_REASON_CALLBACK_RECORD * Record
Definition: ketypes.h:320

Referenced by NtfsFindMftRecord(), and NtfsReadMftRecord().

◆ NtfsGetAttributeSize()

static ULONGLONG NtfsGetAttributeSize ( PNTFS_ATTR_RECORD  AttrRecord)
static

Definition at line 59 of file ntfs.c.

60{
61 if (AttrRecord->IsNonResident)
62 return AttrRecord->NonResident.DataSize;
63 else
64 return AttrRecord->Resident.ValueLength;
65}
struct NTFS_ATTR_RECORD::@157::@160 NonResident
UCHAR IsNonResident
Definition: ntfs.h:136

Referenced by NtfsFindAttributeHelper(), NtfsFindMftRecord(), NtfsGetFileInformation(), and NtfsSeek().

◆ NtfsGetFileInformation()

ARC_STATUS NtfsGetFileInformation ( ULONG  FileId,
FILEINFORMATION Information 
)

Definition at line 931 of file ntfs.c.

932{
934
936 Information->EndingAddress.QuadPart = NtfsGetAttributeSize(&FileHandle->DataContext->Record);
937 Information->CurrentAddress.QuadPart = FileHandle->Offset;
938
939 /* Set the ARC file attributes */
940 Information->Attributes = FileHandle->Attributes;
941
942 /* Copy the file name, perhaps truncated, and NUL-terminated */
943 Information->FileNameLength = min(FileHandle->FileNameLength, sizeof(Information->FileName) - 1);
944 RtlCopyMemory(Information->FileName, FileHandle->FileName, Information->FileNameLength);
945 Information->FileName[Information->FileNameLength] = ANSI_NULL;
946
947 TRACE("NtfsGetFileInformation(%lu) -> FileSize = %llu, FilePointer = 0x%llx\n",
948 FileId, Information->EndingAddress.QuadPart, Information->CurrentAddress.QuadPart);
949
950 return ESUCCESS;
951}
#define ANSI_NULL
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
_In_ WDFREQUEST _In_ NTSTATUS _In_ ULONG_PTR Information
Definition: wdfrequest.h:1049

◆ NtfsGetVolumeSize()

ULONGLONG NtfsGetVolumeSize ( _In_ ULONG  DeviceId)

Returns the size of the NTFS volume laid on the storage media device opened via DeviceId.

Definition at line 1046 of file ntfs.c.

1048{
1050 ASSERT(Volume);
1051 return Volume->BootSector.VolumeSectorCount * Volume->BootSector.BytesPerSector;
1052}
PNTFS_VOLUME_INFO NtfsVolumes[MAX_FDS]
Definition: ntfs.c:57
#define ASSERT(a)
Definition: mode.c:44

Referenced by FsGetVolumeSize().

◆ NtfsLookupFile()

static BOOLEAN NtfsLookupFile ( PNTFS_VOLUME_INFO  Volume,
PCSTR  FileName,
PNTFS_MFT_RECORD  MftRecord,
PNTFS_FILE_HANDLE  FileHandle 
)
static

Definition at line 851 of file ntfs.c.

852{
853 ULONG NumberOfPathParts;
854 ULONG i;
855 ULONGLONG CurrentMFTIndex;
857 CHAR PathPart[261];
858
859 TRACE("NtfsLookupFile() FileName = %s\n", FileName);
860
861 CurrentMFTIndex = NTFS_FILE_ROOT;
862
863 /* Skip leading path separator, if any */
864 if (*FileName == '\\' || *FileName == '/')
865 ++FileName;
866 PathPart[0] = ANSI_NULL;
867
868 /* Figure out how many sub-directories we are nested in and loop once for each part */
869 NumberOfPathParts = FsGetNumPathParts(FileName);
870 for (i = 0; i < NumberOfPathParts; i++)
871 {
873
874 for (; (*FileName != '\\') && (*FileName != '/') && (*FileName != '\0'); FileName++)
875 ;
876 FileName++;
877
878 TRACE("- Lookup: %s\n", PathPart);
879 if (!NtfsFindMftRecord(Volume, CurrentMFTIndex, PathPart, &CurrentMFTIndex, &FileAttributes))
880 {
881 TRACE("- Failed\n");
882 return FALSE;
883 }
884 TRACE("- Lookup: %x\n", CurrentMFTIndex);
885 }
886
887 if (!NtfsReadMftRecord(Volume, CurrentMFTIndex, MftRecord))
888 {
889 TRACE("NtfsLookupFile: Can't read MFT record\n");
890 return FALSE;
891 }
892
893 FileHandle->DataContext = NtfsFindAttribute(Volume, MftRecord, CurrentMFTIndex, NTFS_ATTR_TYPE_DATA, L"");
894 if (FileHandle->DataContext == NULL)
895 {
896 TRACE("NtfsLookupFile: Can't find data attribute\n");
897 return FALSE;
898 }
899
900 /* Map the attributes to ARC file attributes */
901 FileHandle->Attributes = 0;
903 FileHandle->Attributes |= ReadOnlyFile;
905 FileHandle->Attributes |= HiddenFile;
907 FileHandle->Attributes |= SystemFile;
909 FileHandle->Attributes |= ArchiveFile;
911 FileHandle->Attributes |= DirectoryFile;
912
913 /* Copy the file name, perhaps truncated */
914 FileHandle->FileNameLength = (ULONG)strlen(PathPart);
915 FileHandle->FileNameLength = min(FileHandle->FileNameLength, sizeof(FileHandle->FileName) - 1);
916 RtlCopyMemory(FileHandle->FileName, PathPart, FileHandle->FileNameLength);
917
918 return TRUE;
919}
#define NTFS_FILE_ATTR_ARCHIVE
Definition: ntfs.h:73
#define NTFS_FILE_ATTR_SYSTEM
Definition: ntfs.h:71
#define NTFS_FILE_ATTR_DIRECTORY
Definition: ntfs.h:74
#define NTFS_ATTR_TYPE_DATA
Definition: ntfs.h:43
#define NTFS_FILE_ROOT
Definition: ntfs.h:28
#define NTFS_FILE_ATTR_READONLY
Definition: ntfs.h:69
#define NTFS_FILE_ATTR_HIDDEN
Definition: ntfs.h:70
ULONG FsGetNumPathParts(PCSTR Path)
Definition: fs.c:617
VOID FsGetFirstNameFromPath(PCHAR Buffer, PCSTR Path)
Definition: fs.c:645
static BOOLEAN NtfsFindMftRecord(_In_ PNTFS_VOLUME_INFO Volume, _In_ ULONGLONG MFTIndex, _In_ PCSTR FileName, _Out_ PULONGLONG OutMFTIndex, _Out_ PULONG FileAttributes)
Definition: ntfs.c:675
@ DirectoryFile
Definition: fatprocs.h:1047
struct _FileName FileName
Definition: fatprocs.h:897
@ ReadOnlyFile
Definition: arc.h:78
@ ArchiveFile
Definition: arc.h:81
@ SystemFile
Definition: arc.h:80
@ HiddenFile
Definition: arc.h:79

Referenced by NtfsOpen().

◆ NtfsMount()

const DEVVTBL * NtfsMount ( ULONG  DeviceId)

Definition at line 1065 of file ntfs.c.

1066{
1069 ULONG Count;
1071
1072 TRACE("Enter NtfsMount(%lu)\n", DeviceId);
1073
1074 //
1075 // Allocate data for volume information
1076 //
1078 if (!Volume)
1079 return NULL;
1081
1082 //
1083 // Read the BootSector
1084 //
1085 Position.QuadPart = 0;
1086 Status = ArcSeek(DeviceId, &Position, SeekAbsolute);
1087 if (Status != ESUCCESS)
1088 {
1090 return NULL;
1091 }
1092 Status = ArcRead(DeviceId, &Volume->BootSector, sizeof(Volume->BootSector), &Count);
1093 if (Status != ESUCCESS || Count != sizeof(Volume->BootSector))
1094 {
1096 return NULL;
1097 }
1098
1099 //
1100 // Check if BootSector is valid. If no, return early
1101 //
1102 if (!RtlEqualMemory(Volume->BootSector.SystemId, "NTFS", 4))
1103 {
1105 return NULL;
1106 }
1107
1108 //
1109 // Calculate cluster size and MFT record size
1110 //
1111 Volume->ClusterSize = Volume->BootSector.SectorsPerCluster * Volume->BootSector.BytesPerSector;
1112 if (Volume->BootSector.ClustersPerMftRecord > 0)
1113 Volume->MftRecordSize = Volume->BootSector.ClustersPerMftRecord * Volume->ClusterSize;
1114 else
1115 Volume->MftRecordSize = 1 << (-Volume->BootSector.ClustersPerMftRecord);
1116 if (Volume->BootSector.ClustersPerIndexRecord > 0)
1117 Volume->IndexRecordSize = Volume->BootSector.ClustersPerIndexRecord * Volume->ClusterSize;
1118 else
1119 Volume->IndexRecordSize = 1 << (-Volume->BootSector.ClustersPerIndexRecord);
1120
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);
1126
1127 //
1128 // Read MFT index
1129 //
1130 TRACE("Reading MFT index...\n");
1131 Volume->MasterFileTable = FrLdrTempAlloc(Volume->MftRecordSize, TAG_NTFS_MFT);
1132 if (!Volume->MasterFileTable)
1133 {
1135 return NULL;
1136 }
1137 Position.QuadPart = Volume->BootSector.MftLocation * Volume->ClusterSize;
1138 Status = ArcSeek(DeviceId, &Position, SeekAbsolute);
1139 if (Status != ESUCCESS)
1140 {
1141 FileSystemError("Failed to seek to Master File Table record.");
1142 FrLdrTempFree(Volume->MasterFileTable, TAG_NTFS_MFT);
1144 return NULL;
1145 }
1146 Status = ArcRead(DeviceId, Volume->MasterFileTable, Volume->MftRecordSize, &Count);
1147 if (Status != ESUCCESS || Count != Volume->MftRecordSize)
1148 {
1149 FileSystemError("Failed to read the Master File Table record.");
1150 FrLdrTempFree(Volume->MasterFileTable, TAG_NTFS_MFT);
1152 return NULL;
1153 }
1154
1155 //
1156 // Keep room to read partial sectors
1157 //
1158 Volume->TemporarySector = FrLdrTempAlloc(Volume->BootSector.BytesPerSector, TAG_NTFS_DATA);
1159 if (!Volume->TemporarySector)
1160 {
1161 FileSystemError("Failed to allocate memory.");
1162 FrLdrTempFree(Volume->MasterFileTable, TAG_NTFS_MFT);
1164 return NULL;
1165 }
1166
1167 //
1168 // Keep device id
1169 //
1170 Volume->DeviceId = DeviceId;
1171
1172 //
1173 // Search DATA attribute
1174 //
1175 TRACE("Searching for DATA attribute...\n");
1176 Volume->MFTContext = NtfsFindAttribute(Volume, Volume->MasterFileTable, 0, NTFS_ATTR_TYPE_DATA, L"");
1177 if (!Volume->MFTContext)
1178 {
1179 FileSystemError("Can't find data attribute for Master File Table.");
1180 FrLdrTempFree(Volume->MasterFileTable, TAG_NTFS_MFT);
1182 return NULL;
1183 }
1184
1185 //
1186 // Remember NTFS volume information
1187 //
1188 NtfsVolumes[DeviceId] = Volume;
1189
1190 //
1191 // Return success
1192 //
1193 TRACE("NtfsMount(%lu) success\n", DeviceId);
1194 return &NtfsFuncTable;
1195}
VOID FileSystemError(PCSTR ErrorString)
Definition: fs.c:471
const DEVVTBL NtfsFuncTable
Definition: ntfs.c:1055
#define TAG_NTFS_DATA
Definition: ntfs.c:40
#define TAG_NTFS_VOLUME
Definition: ntfs.c:39

◆ NtfsOpen()

ARC_STATUS NtfsOpen ( CHAR Path,
OPENMODE  OpenMode,
ULONG FileId 
)

Definition at line 953 of file ntfs.c.

954{
957 PNTFS_MFT_RECORD MftRecord;
958 ULONG DeviceId;
959
960 //
961 // Check parameters
962 //
963 if (OpenMode != OpenReadOnly)
964 return EACCES;
965
966 //
967 // Get underlying device
968 //
969 DeviceId = FsGetDeviceId(*FileId);
970 Volume = NtfsVolumes[DeviceId];
971
972 TRACE("NtfsOpen() FileName = %s\n", Path);
973
974 //
975 // Allocate file structure
976 //
977 FileHandle = FrLdrTempAlloc(sizeof(NTFS_FILE_HANDLE) + Volume->MftRecordSize,
979 if (!FileHandle)
980 {
981 return ENOMEM;
982 }
983 RtlZeroMemory(FileHandle, sizeof(NTFS_FILE_HANDLE) + Volume->MftRecordSize);
985
986 //
987 // Search file entry
988 //
989 MftRecord = (PNTFS_MFT_RECORD)(FileHandle + 1);
990 if (!NtfsLookupFile(Volume, Path, MftRecord, FileHandle))
991 {
993 return ENOENT;
994 }
995
997 return ESUCCESS;
998}
PRTL_UNICODE_STRING_BUFFER Path
struct NTFS_MFT_RECORD * PNTFS_MFT_RECORD
VOID FsSetDeviceSpecific(ULONG FileId, PVOID Specific)
Definition: fs.c:702
ULONG FsGetDeviceId(ULONG FileId)
Definition: fs.c:716
static BOOLEAN NtfsLookupFile(PNTFS_VOLUME_INFO Volume, PCSTR FileName, PNTFS_MFT_RECORD MftRecord, PNTFS_FILE_HANDLE FileHandle)
Definition: ntfs.c:851
#define ENOENT
Definition: errno.h:25
#define ENOMEM
Definition: errno.h:35
#define EACCES
Definition: errno.h:36
@ OpenReadOnly
Definition: arc.h:65
PVOID Volume
Definition: fltmgrint.h:141

◆ NtfsPrepareAttributeContext()

static PNTFS_ATTR_CONTEXT NtfsPrepareAttributeContext ( PNTFS_ATTR_RECORD  AttrRecord)
static

Definition at line 108 of file ntfs.c.

109{
111
114 RtlCopyMemory(&Context->Record, AttrRecord, AttrRecord->Length);
115 if (AttrRecord->IsNonResident)
116 {
117 LONGLONG DataRunOffset;
118 ULONGLONG DataRunLength;
119
120 Context->CacheRun = (PUCHAR)&Context->Record + Context->Record.NonResident.MappingPairsOffset;
121 Context->CacheRunOffset = 0;
122 Context->CacheRun = NtfsDecodeRun(Context->CacheRun, &DataRunOffset, &DataRunLength);
123 Context->CacheRunLength = DataRunLength;
124 if (DataRunOffset != -1)
125 {
126 /* Normal run. */
127 Context->CacheRunStartLCN =
128 Context->CacheRunLastLCN = DataRunOffset;
129 }
130 else
131 {
132 /* Sparse run. */
133 Context->CacheRunStartLCN = -1;
134 Context->CacheRunLastLCN = 0;
135 }
136 Context->CacheRunCurrentOffset = 0;
137 }
138
139 return Context;
140}
#define TAG_NTFS_CONTEXT
Definition: ntfs.c:33
static PUCHAR NtfsDecodeRun(PUCHAR DataRun, LONGLONG *DataRunOffset, ULONGLONG *DataRunLength)
Definition: ntfs.c:67
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
int64_t LONGLONG
Definition: typedefs.h:68
unsigned char * PUCHAR
Definition: typedefs.h:53

Referenced by NtfsFindAttributeHelper().

◆ NtfsRead()

ARC_STATUS NtfsRead ( ULONG  FileId,
VOID Buffer,
ULONG  N,
ULONG Count 
)

Definition at line 1000 of file ntfs.c.

1001{
1003 ULONGLONG BytesRead64;
1004
1005 /* Read data */
1006 BytesRead64 = NtfsReadAttribute(FileHandle->Volume, FileHandle->DataContext, FileHandle->Offset, Buffer, N);
1007 FileHandle->Offset += BytesRead64;
1008 *Count = (ULONG)BytesRead64;
1009 if (BytesRead64 > 0)
1010 return ESUCCESS;
1011 else
1012 return EIO;
1013}
#define N
Definition: crc32.c:57
#define EIO
Definition: errno.h:28

Referenced by NtfsDispatch().

◆ NtfsReadAttribute()

static ULONG NtfsReadAttribute ( PNTFS_VOLUME_INFO  Volume,
PNTFS_ATTR_CONTEXT  Context,
ULONGLONG  Offset,
PCHAR  Buffer,
ULONG  Length 
)
static

Definition at line 224 of file ntfs.c.

225{
226 ULONGLONG LastLCN;
227 PUCHAR DataRun;
228 LONGLONG DataRunOffset;
229 ULONGLONG DataRunLength;
230 LONGLONG DataRunStartLCN;
231 ULONGLONG CurrentOffset;
233 ULONG AlreadyRead;
234
235 if (!Context->Record.IsNonResident)
236 {
237 if (Offset > Context->Record.Resident.ValueLength)
238 return 0;
239 if (Offset + Length > Context->Record.Resident.ValueLength)
240 Length = (ULONG)(Context->Record.Resident.ValueLength - Offset);
241 RtlCopyMemory(Buffer, (PCHAR)&Context->Record + Context->Record.Resident.ValueOffset + Offset, Length);
242 return Length;
243 }
244
245 /*
246 * Non-resident attribute
247 */
248
249 /*
250 * I. Find the corresponding start data run.
251 */
252
253 AlreadyRead = 0;
254
255 // FIXME: Cache seems to be non-working. Disable it for now
256 //if(Context->CacheRunOffset <= Offset && Offset < Context->CacheRunOffset + Context->CacheRunLength * Volume->ClusterSize)
257 if (0)
258 {
259 DataRun = Context->CacheRun;
260 LastLCN = Context->CacheRunLastLCN;
261 DataRunStartLCN = Context->CacheRunStartLCN;
262 DataRunLength = Context->CacheRunLength;
263 CurrentOffset = Context->CacheRunCurrentOffset;
264 }
265 else
266 {
267 LastLCN = 0;
268 DataRun = (PUCHAR)&Context->Record + Context->Record.NonResident.MappingPairsOffset;
269 CurrentOffset = 0;
270
271 while (1)
272 {
273 DataRun = NtfsDecodeRun(DataRun, &DataRunOffset, &DataRunLength);
274 if (DataRunOffset != -1)
275 {
276 /* Normal data run. */
277 DataRunStartLCN = LastLCN + DataRunOffset;
278 LastLCN = DataRunStartLCN;
279 }
280 else
281 {
282 /* Sparse data run. */
283 DataRunStartLCN = -1;
284 }
285
286 if (Offset >= CurrentOffset &&
287 Offset < CurrentOffset + (DataRunLength * Volume->ClusterSize))
288 {
289 break;
290 }
291
292 if (*DataRun == 0)
293 {
294 return AlreadyRead;
295 }
296
297 CurrentOffset += DataRunLength * Volume->ClusterSize;
298 }
299 }
300
301 /*
302 * II. Go through the run list and read the data
303 */
304
305 ReadLength = (ULONG)min(DataRunLength * Volume->ClusterSize - (Offset - CurrentOffset), Length);
306 if (DataRunStartLCN == -1)
308 if (DataRunStartLCN == -1 || NtfsDiskRead(Volume, DataRunStartLCN * Volume->ClusterSize + Offset - CurrentOffset, ReadLength, Buffer))
309 {
312 AlreadyRead += ReadLength;
313
314 if (ReadLength == DataRunLength * Volume->ClusterSize - (Offset - CurrentOffset))
315 {
316 CurrentOffset += DataRunLength * Volume->ClusterSize;
317 DataRun = NtfsDecodeRun(DataRun, &DataRunOffset, &DataRunLength);
318 if (DataRunOffset != (ULONGLONG)-1)
319 {
320 DataRunStartLCN = LastLCN + DataRunOffset;
321 LastLCN = DataRunStartLCN;
322 }
323 else
324 DataRunStartLCN = -1;
325 }
326
327 while (Length > 0)
328 {
329 ReadLength = (ULONG)min(DataRunLength * Volume->ClusterSize, Length);
330 if (DataRunStartLCN == -1)
332 else if (!NtfsDiskRead(Volume, DataRunStartLCN * Volume->ClusterSize, ReadLength, Buffer))
333 break;
334
337 AlreadyRead += ReadLength;
338
339 /* We finished this request, but there still data in this data run. */
340 if (Length == 0 && ReadLength != DataRunLength * Volume->ClusterSize)
341 break;
342
343 /*
344 * Go to next run in the list.
345 */
346
347 if (*DataRun == 0)
348 break;
349 CurrentOffset += DataRunLength * Volume->ClusterSize;
350 DataRun = NtfsDecodeRun(DataRun, &DataRunOffset, &DataRunLength);
351 if (DataRunOffset != -1)
352 {
353 /* Normal data run. */
354 DataRunStartLCN = LastLCN + DataRunOffset;
355 LastLCN = DataRunStartLCN;
356 }
357 else
358 {
359 /* Sparse data run. */
360 DataRunStartLCN = -1;
361 }
362 } /* while */
363
364 } /* if Disk */
365
366 Context->CacheRun = DataRun;
367 Context->CacheRunOffset = Offset + AlreadyRead;
368 Context->CacheRunStartLCN = DataRunStartLCN;
369 Context->CacheRunLength = DataRunLength;
370 Context->CacheRunLastLCN = LastLCN;
371 Context->CacheRunCurrentOffset = CurrentOffset;
372
373 return AlreadyRead;
374}
static BOOLEAN NtfsDiskRead(PNTFS_VOLUME_INFO Volume, ULONGLONG Offset, ULONGLONG Length, PCHAR Buffer)
Definition: ntfs.c:147
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))

Referenced by NtfsFindAttributeHelper(), NtfsFindMftRecord(), NtfsRead(), and NtfsReadMftRecord().

◆ NtfsReadMftRecord()

static BOOLEAN NtfsReadMftRecord ( PNTFS_VOLUME_INFO  Volume,
ULONGLONG  MFTIndex,
PNTFS_MFT_RECORD  Buffer 
)
static

Definition at line 607 of file ntfs.c.

608{
610
611 BytesRead = NtfsReadAttribute(Volume, Volume->MFTContext, MFTIndex * Volume->MftRecordSize, (PCHAR)Buffer, Volume->MftRecordSize);
612 if (BytesRead != Volume->MftRecordSize)
613 return FALSE;
614
615 /* Apply update sequence array fixups. */
617}
_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
Definition: wdfiotarget.h:870

Referenced by NtfsFindAttributeHelperList(), NtfsFindMftRecord(), and NtfsLookupFile().

◆ NtfsReleaseAttributeContext()

static VOID NtfsReleaseAttributeContext ( PNTFS_ATTR_CONTEXT  Context)
static

Definition at line 142 of file ntfs.c.

Referenced by NtfsClose(), NtfsFindAttributeHelper(), and NtfsFindMftRecord().

◆ NtfsSeek()

ARC_STATUS NtfsSeek ( ULONG  FileId,
LARGE_INTEGER Position,
SEEKMODE  SeekMode 
)

Definition at line 1015 of file ntfs.c.

1016{
1018 LARGE_INTEGER NewPosition = *Position;
1019
1020 switch (SeekMode)
1021 {
1022 case SeekAbsolute:
1023 break;
1024 case SeekRelative:
1025 NewPosition.QuadPart += FileHandle->Offset;
1026 break;
1027 default:
1028 ASSERT(FALSE);
1029 return EINVAL;
1030 }
1031
1032 if (NewPosition.QuadPart >= NtfsGetAttributeSize(&FileHandle->DataContext->Record))
1033 return EINVAL;
1034
1035 FileHandle->Offset = NewPosition.QuadPart;
1036 return ESUCCESS;
1037}
#define EINVAL
Definition: errno.h:44
@ SeekRelative
Definition: arc.h:60
LONGLONG QuadPart
Definition: typedefs.h:114

Variable Documentation

◆ NtfsFuncTable

const DEVVTBL NtfsFuncTable
Initial value:
=
{
L"ntfs",
}
ARC_STATUS NtfsSeek(ULONG FileId, LARGE_INTEGER *Position, SEEKMODE SeekMode)
Definition: ntfs.c:1015
ARC_STATUS NtfsOpen(CHAR *Path, OPENMODE OpenMode, ULONG *FileId)
Definition: ntfs.c:953
ARC_STATUS NtfsGetFileInformation(ULONG FileId, FILEINFORMATION *Information)
Definition: ntfs.c:931
ARC_STATUS NtfsClose(ULONG FileId)
Definition: ntfs.c:921
ARC_STATUS NtfsRead(ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
Definition: ntfs.c:1000

Definition at line 1055 of file ntfs.c.

Referenced by NtfsMount().

◆ NtfsVolumes

PNTFS_VOLUME_INFO NtfsVolumes[MAX_FDS]

Definition at line 57 of file ntfs.c.

Referenced by NtfsGetVolumeSize(), NtfsMount(), and NtfsOpen().