ReactOS 0.4.16-dev-1946-g52006dd
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'
 

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, PNTFS_ATTR_RECORD AttrRecord, PNTFS_ATTR_RECORD AttrRecordEnd, ULONG Type, const WCHAR *Name, ULONG NameLength)
 
static PNTFS_ATTR_CONTEXT NtfsFindAttribute (PNTFS_VOLUME_INFO Volume, PNTFS_MFT_RECORD MftRecord, ULONG Type, const WCHAR *Name)
 
static BOOLEAN NtfsFixupRecord (PNTFS_VOLUME_INFO Volume, PNTFS_RECORD Record)
 
static BOOLEAN NtfsReadMftRecord (PNTFS_VOLUME_INFO Volume, ULONGLONG MFTIndex, PNTFS_MFT_RECORD Buffer)
 
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

◆ 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 794 of file ntfs.c.

795{
797
800
801 return ESUCCESS;
802}
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:140
#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 513 of file ntfs.c.

517{
518 PWCHAR EntryFileName;
519 UCHAR EntryFileNameLength;
520 UCHAR i;
521
522 EntryFileName = IndexEntry->FileName.FileName;
523 EntryFileNameLength = IndexEntry->FileName.FileNameLength;
524
525#if DBG
526 NtfsPrintFile(IndexEntry);
527#endif
528
529 if (FileNameLen != EntryFileNameLength)
530 return FALSE;
531
532 /*
533 * Always perform case-insensitive comparison for file names.
534 * This is necessary, because when modifying e.g. on Linux a Windows NTFS
535 * partition formatted with Windows itself, the NTLDR/BOOTMGR will boot
536 * normally ignoring the case of the paths.
537 */
538 for (i = 0; i < EntryFileNameLength; i++)
539 {
540 if (tolower(EntryFileName[i]) != tolower(FileName[i]))
541 return FALSE;
542 }
543
544 return TRUE;
545}
int tolower(int c)
Definition: utclib.c:902
Dirent FileNameLen
Definition: dirsup.c:506
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
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
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 65 of file ntfs.c.

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

146{
148 ULONG Count;
151
152 TRACE("NtfsDiskRead - Offset: %I64u Length: %I64u\n", Offset, Length);
153
154 //
155 // I. Read partial first sector if needed
156 //
157 if (Offset % Volume->BootSector.BytesPerSector)
158 {
159 Position.QuadPart = Offset & ~(Volume->BootSector.BytesPerSector - 1);
160 Status = ArcSeek(Volume->DeviceId, &Position, SeekAbsolute);
161 if (Status != ESUCCESS)
162 return FALSE;
163 Status = ArcRead(Volume->DeviceId, Volume->TemporarySector, Volume->BootSector.BytesPerSector, &Count);
164 if (Status != ESUCCESS || Count != Volume->BootSector.BytesPerSector)
165 return FALSE;
166 ReadLength = (USHORT)min(Length, Volume->BootSector.BytesPerSector - (Offset % Volume->BootSector.BytesPerSector));
167
168 //
169 // Copy interesting data
170 //
172 &Volume->TemporarySector[Offset % Volume->BootSector.BytesPerSector],
173 ReadLength);
174
175 //
176 // Move to unfilled buffer part
177 //
181 }
182
183 //
184 // II. Read all complete blocks
185 //
186 if (Length >= Volume->BootSector.BytesPerSector)
187 {
188 Position.QuadPart = Offset;
189 Status = ArcSeek(Volume->DeviceId, &Position, SeekAbsolute);
190 if (Status != ESUCCESS)
191 return FALSE;
192 ReadLength = Length & ~(Volume->BootSector.BytesPerSector - 1);
193 Status = ArcRead(Volume->DeviceId, Buffer, ReadLength, &Count);
194 if (Status != ESUCCESS || Count != ReadLength)
195 return FALSE;
196
197 //
198 // Move to unfilled buffer part
199 //
203 }
204
205 //
206 // III. Read the rest of data
207 //
208 if (Length)
209 {
210 Position.QuadPart = Offset;
211 Status = ArcSeek(Volume->DeviceId, &Position, SeekAbsolute);
212 if (Status != ESUCCESS)
213 return FALSE;
214 Status = ArcRead(Volume->DeviceId, Buffer, (ULONG)Length, &Count);
215 if (Status != ESUCCESS || Count != Length)
216 return FALSE;
217 }
218
219 return TRUE;
220}
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,
ULONG  Type,
const WCHAR Name 
)
static

Definition at line 443 of file ntfs.c.

444{
445 PNTFS_ATTR_RECORD AttrRecord;
446 PNTFS_ATTR_RECORD AttrRecordEnd;
447 ULONG NameLength;
448
449 AttrRecord = (PNTFS_ATTR_RECORD)((PCHAR)MftRecord + MftRecord->AttributesOffset);
450 AttrRecordEnd = (PNTFS_ATTR_RECORD)((PCHAR)MftRecord + Volume->MftRecordSize);
451 for (NameLength = 0; Name[NameLength] != 0; NameLength++)
452 ;
453
454 return NtfsFindAttributeHelper(Volume, AttrRecord, AttrRecordEnd, Type, Name, NameLength);
455}
Type
Definition: Type.h:7
struct NTFS_ATTR_RECORD * PNTFS_ATTR_RECORD
static PNTFS_ATTR_CONTEXT NtfsFindAttributeHelper(PNTFS_VOLUME_INFO Volume, PNTFS_ATTR_RECORD AttrRecord, PNTFS_ATTR_RECORD AttrRecordEnd, ULONG Type, const WCHAR *Name, ULONG NameLength)
Definition: ntfs.c:374
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,
PNTFS_ATTR_RECORD  AttrRecord,
PNTFS_ATTR_RECORD  AttrRecordEnd,
ULONG  Type,
const WCHAR Name,
ULONG  NameLength 
)
static

Definition at line 374 of file ntfs.c.

375{
376 while (AttrRecord < AttrRecordEnd)
377 {
378 if (AttrRecord->Type == NTFS_ATTR_TYPE_END)
379 break;
380
381 if (AttrRecord->Type == NTFS_ATTR_TYPE_ATTRIBUTE_LIST)
382 {
384 PNTFS_ATTR_CONTEXT ListContext;
385 PVOID ListBuffer;
386 ULONGLONG ListSize;
387 PNTFS_ATTR_RECORD ListAttrRecord;
388 PNTFS_ATTR_RECORD ListAttrRecordEnd;
389
390 ListContext = NtfsPrepareAttributeContext(AttrRecord);
391
392 ListSize = NtfsGetAttributeSize(&ListContext->Record);
393 if(ListSize <= 0xFFFFFFFF)
394 ListBuffer = FrLdrTempAlloc((ULONG)ListSize, TAG_NTFS_LIST);
395 else
396 ListBuffer = NULL;
397
398 if(!ListBuffer)
399 {
400 TRACE("Failed to allocate memory: %x\n", (ULONG)ListSize);
401 continue;
402 }
403
404 ListAttrRecord = (PNTFS_ATTR_RECORD)ListBuffer;
405 ListAttrRecordEnd = (PNTFS_ATTR_RECORD)((PCHAR)ListBuffer + ListSize);
406
407 if (NtfsReadAttribute(Volume, ListContext, 0, ListBuffer, (ULONG)ListSize) == ListSize)
408 {
409 Context = NtfsFindAttributeHelper(Volume, ListAttrRecord, ListAttrRecordEnd,
410 Type, Name, NameLength);
411
412 NtfsReleaseAttributeContext(ListContext);
413 FrLdrTempFree(ListBuffer, TAG_NTFS_LIST);
414
415 if (Context != NULL)
416 return Context;
417 }
418 }
419
420 if (AttrRecord->Type == Type)
421 {
422 if (AttrRecord->NameLength == NameLength)
423 {
424 PWCHAR AttrName;
425
426 AttrName = (PWCHAR)((PCHAR)AttrRecord + AttrRecord->NameOffset);
427 if (RtlEqualMemory(AttrName, Name, NameLength << 1))
428 {
429 /* Found it, fill up the context and return. */
430 return NtfsPrepareAttributeContext(AttrRecord);
431 }
432 }
433 }
434
435 if (AttrRecord->Length == 0)
436 return NULL;
437 AttrRecord = (PNTFS_ATTR_RECORD)((PCHAR)AttrRecord + AttrRecord->Length);
438 }
439
440 return NULL;
441}
#define NTFS_ATTR_TYPE_ATTRIBUTE_LIST
Definition: ntfs.h:37
#define NTFS_ATTR_TYPE_END
Definition: ntfs.h:50
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:222
static PNTFS_ATTR_CONTEXT NtfsPrepareAttributeContext(PNTFS_ATTR_RECORD AttrRecord)
Definition: ntfs.c:106
static ULONGLONG NtfsGetAttributeSize(PNTFS_ATTR_RECORD AttrRecord)
Definition: ntfs.c:57
#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
UCHAR NameLength
Definition: ntfs.h:137
ULONG Type
Definition: ntfs.h:134
uint64_t ULONGLONG
Definition: typedefs.h:67

Referenced by NtfsFindAttribute(), and 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 548 of file ntfs.c.

554{
555 PNTFS_MFT_RECORD MftRecord;
556 //ULONG Magic;
557 PNTFS_ATTR_CONTEXT IndexRootCtx;
558 PNTFS_ATTR_CONTEXT IndexBitmapCtx;
559 PNTFS_ATTR_CONTEXT IndexAllocationCtx;
560 PNTFS_INDEX_ROOT IndexRoot;
561 ULONGLONG BitmapDataSize;
562 ULONGLONG IndexAllocationSize;
564 PCHAR IndexRecord;
565 PNTFS_INDEX_ENTRY IndexEntry, IndexEntryEnd;
566 ULONG RecordOffset;
567 ULONG IndexBlockSize;
569
571
572 MftRecord = FrLdrTempAlloc(Volume->MftRecordSize, TAG_NTFS_MFT);
573 if (MftRecord == NULL)
574 {
575 return FALSE;
576 }
577
578 if (NtfsReadMftRecord(Volume, MFTIndex, MftRecord))
579 {
580 //Magic = MftRecord->Magic;
581
582 IndexRootCtx = NtfsFindAttribute(Volume, MftRecord, NTFS_ATTR_TYPE_INDEX_ROOT, L"$I30");
583 if (IndexRootCtx == NULL)
584 {
585 FrLdrTempFree(MftRecord, TAG_NTFS_MFT);
586 return FALSE;
587 }
588
589 IndexRecord = FrLdrTempAlloc(Volume->IndexRecordSize, TAG_NTFS_INDEX_REC);
590 if (IndexRecord == NULL)
591 {
592 FrLdrTempFree(MftRecord, TAG_NTFS_MFT);
593 return FALSE;
594 }
595
596 NtfsReadAttribute(Volume, IndexRootCtx, 0, IndexRecord, Volume->IndexRecordSize);
597 IndexRoot = (PNTFS_INDEX_ROOT)IndexRecord;
598 IndexEntry = (PNTFS_INDEX_ENTRY)((PCHAR)&IndexRoot->IndexHeader + IndexRoot->IndexHeader.EntriesOffset);
599 /* Index root is always resident. */
600 IndexEntryEnd = (PNTFS_INDEX_ENTRY)(IndexRecord + IndexRootCtx->Record.Resident.ValueLength);
601 NtfsReleaseAttributeContext(IndexRootCtx);
602
603 TRACE("IndexRecordSize: %x IndexBlockSize: %x\n", Volume->IndexRecordSize, IndexRoot->IndexBlockSize);
604
605 while (IndexEntry < IndexEntryEnd &&
606 !(IndexEntry->Flags & NTFS_INDEX_ENTRY_END))
607 {
608 if (NtfsCompareFileName(FileName, FileNameLen, IndexEntry))
609 {
610 *OutMFTIndex = (IndexEntry->Data.Directory.IndexedFile & NTFS_MFT_MASK);
612 FrLdrTempFree(IndexRecord, TAG_NTFS_INDEX_REC);
613 FrLdrTempFree(MftRecord, TAG_NTFS_MFT);
614 return TRUE;
615 }
616 IndexEntry = (PNTFS_INDEX_ENTRY)((PCHAR)IndexEntry + IndexEntry->Length);
617 }
618
619 if (IndexRoot->IndexHeader.Flags & NTFS_LARGE_INDEX)
620 {
621 TRACE("Large Index!\n");
622
623 IndexBlockSize = IndexRoot->IndexBlockSize;
624
625 IndexBitmapCtx = NtfsFindAttribute(Volume, MftRecord, NTFS_ATTR_TYPE_BITMAP, L"$I30");
626 if (IndexBitmapCtx == NULL)
627 {
628 TRACE("Corrupted filesystem!\n");
629 FrLdrTempFree(MftRecord, TAG_NTFS_MFT);
630 return FALSE;
631 }
632 BitmapDataSize = NtfsGetAttributeSize(&IndexBitmapCtx->Record);
633 TRACE("BitmapDataSize: %x\n", (ULONG)BitmapDataSize);
634 if(BitmapDataSize <= 0xFFFFFFFF)
636 else
638
639 if (BitmapData == NULL)
640 {
641 FrLdrTempFree(IndexRecord, TAG_NTFS_INDEX_REC);
642 FrLdrTempFree(MftRecord, TAG_NTFS_MFT);
643 return FALSE;
644 }
645 NtfsReadAttribute(Volume, IndexBitmapCtx, 0, BitmapData, (ULONG)BitmapDataSize);
646 NtfsReleaseAttributeContext(IndexBitmapCtx);
647
648 IndexAllocationCtx = NtfsFindAttribute(Volume, MftRecord, NTFS_ATTR_TYPE_INDEX_ALLOCATION, L"$I30");
649 if (IndexAllocationCtx == NULL)
650 {
651 TRACE("Corrupted filesystem!\n");
653 FrLdrTempFree(IndexRecord, TAG_NTFS_INDEX_REC);
654 FrLdrTempFree(MftRecord, TAG_NTFS_MFT);
655 return FALSE;
656 }
657 IndexAllocationSize = NtfsGetAttributeSize(&IndexAllocationCtx->Record);
658
659 RecordOffset = 0;
660
661 for (;;)
662 {
663 TRACE("RecordOffset: %x IndexAllocationSize: %x\n", RecordOffset, IndexAllocationSize);
664 for (; RecordOffset < IndexAllocationSize;)
665 {
666 UCHAR Bit = 1 << ((RecordOffset / IndexBlockSize) & 7);
667 ULONG Byte = (RecordOffset / IndexBlockSize) >> 3;
668 if ((BitmapData[Byte] & Bit))
669 break;
670 RecordOffset += IndexBlockSize;
671 }
672
673 if (RecordOffset >= IndexAllocationSize)
674 {
675 break;
676 }
677
678 NtfsReadAttribute(Volume, IndexAllocationCtx, RecordOffset, IndexRecord, IndexBlockSize);
679
680 if (!NtfsFixupRecord(Volume, (PNTFS_RECORD)IndexRecord))
681 {
682 break;
683 }
684
685 /* FIXME */
686 IndexEntry = (PNTFS_INDEX_ENTRY)(IndexRecord + 0x18 + *(USHORT *)(IndexRecord + 0x18));
687 IndexEntryEnd = (PNTFS_INDEX_ENTRY)(IndexRecord + IndexBlockSize);
688
689 while (IndexEntry < IndexEntryEnd &&
690 !(IndexEntry->Flags & NTFS_INDEX_ENTRY_END))
691 {
692 if (NtfsCompareFileName(FileName, FileNameLen, IndexEntry))
693 {
694 TRACE("File found\n");
695 *OutMFTIndex = (IndexEntry->Data.Directory.IndexedFile & NTFS_MFT_MASK);
697 NtfsReleaseAttributeContext(IndexAllocationCtx);
699 FrLdrTempFree(IndexRecord, TAG_NTFS_INDEX_REC);
700 FrLdrTempFree(MftRecord, TAG_NTFS_MFT);
701 return TRUE;
702 }
703 IndexEntry = (PNTFS_INDEX_ENTRY)((PCHAR)IndexEntry + IndexEntry->Length);
704 }
705
706 RecordOffset += IndexBlockSize;
707 }
708
709 NtfsReleaseAttributeContext(IndexAllocationCtx);
711 }
712
713 FrLdrTempFree(IndexRecord, TAG_NTFS_INDEX_REC);
714 }
715 else
716 {
717 TRACE("Can't read MFT record\n");
718 }
719 FrLdrTempFree(MftRecord, TAG_NTFS_MFT);
720
721 return FALSE;
722}
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
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_MFT_MASK
Definition: ntfs.h:76
#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:457
#define TAG_NTFS_MFT
Definition: ntfs.c:35
static BOOLEAN NtfsCompareFileName(_In_ PCCH FileName, _In_ SIZE_T FileNameLen, _In_ PNTFS_INDEX_ENTRY IndexEntry)
Definition: ntfs.c:513
#define TAG_NTFS_INDEX_REC
Definition: ntfs.c:36
static PNTFS_ATTR_CONTEXT NtfsFindAttribute(PNTFS_VOLUME_INFO Volume, PNTFS_MFT_RECORD MftRecord, ULONG Type, const WCHAR *Name)
Definition: ntfs.c:443
#define TAG_NTFS_BITMAP
Definition: ntfs.c:37
static BOOLEAN NtfsReadMftRecord(PNTFS_VOLUME_INFO Volume, ULONGLONG MFTIndex, PNTFS_MFT_RECORD Buffer)
Definition: ntfs.c:481
unsigned char Byte
Definition: zlib.h:37
#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::@206::@208 Resident
ULONG FileAttributes
Definition: ntfs.h:195
Definition: ntfs.h:216
struct NTFS_INDEX_ENTRY::@210::@211 Directory
union NTFS_INDEX_ENTRY::@210 Data
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 457 of file ntfs.c.

458{
459 USHORT *USA;
460 USHORT USANumber;
461 USHORT USACount;
462 USHORT *Block;
463
464 USA = (USHORT*)((PCHAR)Record + Record->USAOffset);
465 USANumber = *(USA++);
466 USACount = Record->USACount - 1; /* Exclude the USA Number. */
467 Block = (USHORT*)((PCHAR)Record + Volume->BootSector.BytesPerSector - 2);
468
469 while (USACount)
470 {
471 if (*Block != USANumber)
472 return FALSE;
473 *Block = *(USA++);
474 Block = (USHORT*)((PCHAR)Block + Volume->BootSector.BytesPerSector);
475 USACount--;
476 }
477
478 return TRUE;
479}
_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 57 of file ntfs.c.

58{
59 if (AttrRecord->IsNonResident)
60 return AttrRecord->NonResident.DataSize;
61 else
62 return AttrRecord->Resident.ValueLength;
63}
UCHAR IsNonResident
Definition: ntfs.h:136
struct NTFS_ATTR_RECORD::@206::@209 NonResident

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

◆ NtfsGetFileInformation()

ARC_STATUS NtfsGetFileInformation ( ULONG  FileId,
FILEINFORMATION Information 
)

Definition at line 804 of file ntfs.c.

805{
807
809 Information->EndingAddress.QuadPart = NtfsGetAttributeSize(&FileHandle->DataContext->Record);
810 Information->CurrentAddress.QuadPart = FileHandle->Offset;
811
812 /* Set the ARC file attributes */
813 Information->Attributes = FileHandle->Attributes;
814
815 /* Copy the file name, perhaps truncated, and NUL-terminated */
816 Information->FileNameLength = min(FileHandle->FileNameLength, sizeof(Information->FileName) - 1);
817 RtlCopyMemory(Information->FileName, FileHandle->FileName, Information->FileNameLength);
818 Information->FileName[Information->FileNameLength] = ANSI_NULL;
819
820 TRACE("NtfsGetFileInformation(%lu) -> FileSize = %llu, FilePointer = 0x%llx\n",
821 FileId, Information->EndingAddress.QuadPart, Information->CurrentAddress.QuadPart);
822
823 return ESUCCESS;
824}
#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 919 of file ntfs.c.

921{
923 ASSERT(Volume);
924 return Volume->BootSector.VolumeSectorCount * Volume->BootSector.BytesPerSector;
925}
PNTFS_VOLUME_INFO NtfsVolumes[MAX_FDS]
Definition: ntfs.c:55
#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 724 of file ntfs.c.

725{
726 ULONG NumberOfPathParts;
727 ULONG i;
728 ULONGLONG CurrentMFTIndex;
730 CHAR PathPart[261];
731
732 TRACE("NtfsLookupFile() FileName = %s\n", FileName);
733
734 CurrentMFTIndex = NTFS_FILE_ROOT;
735
736 /* Skip leading path separator, if any */
737 if (*FileName == '\\' || *FileName == '/')
738 ++FileName;
739 PathPart[0] = ANSI_NULL;
740
741 /* Figure out how many sub-directories we are nested in and loop once for each part */
742 NumberOfPathParts = FsGetNumPathParts(FileName);
743 for (i = 0; i < NumberOfPathParts; i++)
744 {
746
747 for (; (*FileName != '\\') && (*FileName != '/') && (*FileName != '\0'); FileName++)
748 ;
749 FileName++;
750
751 TRACE("- Lookup: %s\n", PathPart);
752 if (!NtfsFindMftRecord(Volume, CurrentMFTIndex, PathPart, &CurrentMFTIndex, &FileAttributes))
753 {
754 TRACE("- Failed\n");
755 return FALSE;
756 }
757 TRACE("- Lookup: %x\n", CurrentMFTIndex);
758 }
759
760 if (!NtfsReadMftRecord(Volume, CurrentMFTIndex, MftRecord))
761 {
762 TRACE("NtfsLookupFile: Can't read MFT record\n");
763 return FALSE;
764 }
765
766 FileHandle->DataContext = NtfsFindAttribute(Volume, MftRecord, NTFS_ATTR_TYPE_DATA, L"");
767 if (FileHandle->DataContext == NULL)
768 {
769 TRACE("NtfsLookupFile: Can't find data attribute\n");
770 return FALSE;
771 }
772
773 /* Map the attributes to ARC file attributes */
774 FileHandle->Attributes = 0;
776 FileHandle->Attributes |= ReadOnlyFile;
778 FileHandle->Attributes |= HiddenFile;
780 FileHandle->Attributes |= SystemFile;
782 FileHandle->Attributes |= ArchiveFile;
784 FileHandle->Attributes |= DirectoryFile;
785
786 /* Copy the file name, perhaps truncated */
787 FileHandle->FileNameLength = (ULONG)strlen(PathPart);
788 FileHandle->FileNameLength = min(FileHandle->FileNameLength, sizeof(FileHandle->FileName) - 1);
789 RtlCopyMemory(FileHandle->FileName, PathPart, FileHandle->FileNameLength);
790
791 return TRUE;
792}
#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:548
@ 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 938 of file ntfs.c.

939{
942 ULONG Count;
944
945 TRACE("Enter NtfsMount(%lu)\n", DeviceId);
946
947 //
948 // Allocate data for volume information
949 //
951 if (!Volume)
952 return NULL;
954
955 //
956 // Read the BootSector
957 //
958 Position.QuadPart = 0;
959 Status = ArcSeek(DeviceId, &Position, SeekAbsolute);
960 if (Status != ESUCCESS)
961 {
963 return NULL;
964 }
965 Status = ArcRead(DeviceId, &Volume->BootSector, sizeof(Volume->BootSector), &Count);
966 if (Status != ESUCCESS || Count != sizeof(Volume->BootSector))
967 {
969 return NULL;
970 }
971
972 //
973 // Check if BootSector is valid. If no, return early
974 //
975 if (!RtlEqualMemory(Volume->BootSector.SystemId, "NTFS", 4))
976 {
978 return NULL;
979 }
980
981 //
982 // Calculate cluster size and MFT record size
983 //
984 Volume->ClusterSize = Volume->BootSector.SectorsPerCluster * Volume->BootSector.BytesPerSector;
985 if (Volume->BootSector.ClustersPerMftRecord > 0)
986 Volume->MftRecordSize = Volume->BootSector.ClustersPerMftRecord * Volume->ClusterSize;
987 else
988 Volume->MftRecordSize = 1 << (-Volume->BootSector.ClustersPerMftRecord);
989 if (Volume->BootSector.ClustersPerIndexRecord > 0)
990 Volume->IndexRecordSize = Volume->BootSector.ClustersPerIndexRecord * Volume->ClusterSize;
991 else
992 Volume->IndexRecordSize = 1 << (-Volume->BootSector.ClustersPerIndexRecord);
993
994 TRACE("ClusterSize: 0x%x\n", Volume->ClusterSize);
995 TRACE("ClustersPerMftRecord: %d\n", Volume->BootSector.ClustersPerMftRecord);
996 TRACE("ClustersPerIndexRecord: %d\n", Volume->BootSector.ClustersPerIndexRecord);
997 TRACE("MftRecordSize: 0x%x\n", Volume->MftRecordSize);
998 TRACE("IndexRecordSize: 0x%x\n", Volume->IndexRecordSize);
999
1000 //
1001 // Read MFT index
1002 //
1003 TRACE("Reading MFT index...\n");
1004 Volume->MasterFileTable = FrLdrTempAlloc(Volume->MftRecordSize, TAG_NTFS_MFT);
1005 if (!Volume->MasterFileTable)
1006 {
1008 return NULL;
1009 }
1010 Position.QuadPart = Volume->BootSector.MftLocation * Volume->ClusterSize;
1011 Status = ArcSeek(DeviceId, &Position, SeekAbsolute);
1012 if (Status != ESUCCESS)
1013 {
1014 FileSystemError("Failed to seek to Master File Table record.");
1015 FrLdrTempFree(Volume->MasterFileTable, TAG_NTFS_MFT);
1017 return NULL;
1018 }
1019 Status = ArcRead(DeviceId, Volume->MasterFileTable, Volume->MftRecordSize, &Count);
1020 if (Status != ESUCCESS || Count != Volume->MftRecordSize)
1021 {
1022 FileSystemError("Failed to read the Master File Table record.");
1023 FrLdrTempFree(Volume->MasterFileTable, TAG_NTFS_MFT);
1025 return NULL;
1026 }
1027
1028 //
1029 // Keep room to read partial sectors
1030 //
1031 Volume->TemporarySector = FrLdrTempAlloc(Volume->BootSector.BytesPerSector, TAG_NTFS_DATA);
1032 if (!Volume->TemporarySector)
1033 {
1034 FileSystemError("Failed to allocate memory.");
1035 FrLdrTempFree(Volume->MasterFileTable, TAG_NTFS_MFT);
1037 return NULL;
1038 }
1039
1040 //
1041 // Keep device id
1042 //
1043 Volume->DeviceId = DeviceId;
1044
1045 //
1046 // Search DATA attribute
1047 //
1048 TRACE("Searching for DATA attribute...\n");
1049 Volume->MFTContext = NtfsFindAttribute(Volume, Volume->MasterFileTable, NTFS_ATTR_TYPE_DATA, L"");
1050 if (!Volume->MFTContext)
1051 {
1052 FileSystemError("Can't find data attribute for Master File Table.");
1053 FrLdrTempFree(Volume->MasterFileTable, TAG_NTFS_MFT);
1055 return NULL;
1056 }
1057
1058 //
1059 // Remember NTFS volume information
1060 //
1061 NtfsVolumes[DeviceId] = Volume;
1062
1063 //
1064 // Return success
1065 //
1066 TRACE("NtfsMount(%lu) success\n", DeviceId);
1067 return &NtfsFuncTable;
1068}
VOID FileSystemError(PCSTR ErrorString)
Definition: fs.c:471
const DEVVTBL NtfsFuncTable
Definition: ntfs.c:928
#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 826 of file ntfs.c.

827{
830 PNTFS_MFT_RECORD MftRecord;
831 ULONG DeviceId;
832
833 //
834 // Check parameters
835 //
836 if (OpenMode != OpenReadOnly)
837 return EACCES;
838
839 //
840 // Get underlying device
841 //
842 DeviceId = FsGetDeviceId(*FileId);
843 Volume = NtfsVolumes[DeviceId];
844
845 TRACE("NtfsOpen() FileName = %s\n", Path);
846
847 //
848 // Allocate file structure
849 //
850 FileHandle = FrLdrTempAlloc(sizeof(NTFS_FILE_HANDLE) + Volume->MftRecordSize,
852 if (!FileHandle)
853 {
854 return ENOMEM;
855 }
856 RtlZeroMemory(FileHandle, sizeof(NTFS_FILE_HANDLE) + Volume->MftRecordSize);
858
859 //
860 // Search file entry
861 //
862 MftRecord = (PNTFS_MFT_RECORD)(FileHandle + 1);
863 if (!NtfsLookupFile(Volume, Path, MftRecord, FileHandle))
864 {
866 return ENOENT;
867 }
868
870 return ESUCCESS;
871}
PRTL_UNICODE_STRING_BUFFER Path
#define ENOENT
Definition: acclib.h:79
#define ENOMEM
Definition: acclib.h:84
#define EACCES
Definition: acclib.h:85
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:724
@ 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 106 of file ntfs.c.

107{
109
112 RtlCopyMemory(&Context->Record, AttrRecord, AttrRecord->Length);
113 if (AttrRecord->IsNonResident)
114 {
115 LONGLONG DataRunOffset;
116 ULONGLONG DataRunLength;
117
118 Context->CacheRun = (PUCHAR)&Context->Record + Context->Record.NonResident.MappingPairsOffset;
119 Context->CacheRunOffset = 0;
120 Context->CacheRun = NtfsDecodeRun(Context->CacheRun, &DataRunOffset, &DataRunLength);
121 Context->CacheRunLength = DataRunLength;
122 if (DataRunOffset != -1)
123 {
124 /* Normal run. */
125 Context->CacheRunStartLCN =
126 Context->CacheRunLastLCN = DataRunOffset;
127 }
128 else
129 {
130 /* Sparse run. */
131 Context->CacheRunStartLCN = -1;
132 Context->CacheRunLastLCN = 0;
133 }
134 Context->CacheRunCurrentOffset = 0;
135 }
136
137 return Context;
138}
#define TAG_NTFS_CONTEXT
Definition: ntfs.c:33
static PUCHAR NtfsDecodeRun(PUCHAR DataRun, LONGLONG *DataRunOffset, ULONGLONG *DataRunLength)
Definition: ntfs.c:65
#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 873 of file ntfs.c.

874{
876 ULONGLONG BytesRead64;
877
878 /* Read data */
879 BytesRead64 = NtfsReadAttribute(FileHandle->Volume, FileHandle->DataContext, FileHandle->Offset, Buffer, N);
880 FileHandle->Offset += BytesRead64;
881 *Count = (ULONG)BytesRead64;
882 if (BytesRead64 > 0)
883 return ESUCCESS;
884 else
885 return EIO;
886}
#define N
Definition: crc32.c:57
#define EIO
Definition: acclib.h:81

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 222 of file ntfs.c.

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

482{
484
485 BytesRead = NtfsReadAttribute(Volume, Volume->MFTContext, MFTIndex * Volume->MftRecordSize, (PCHAR)Buffer, Volume->MftRecordSize);
486 if (BytesRead != Volume->MftRecordSize)
487 return FALSE;
488
489 /* Apply update sequence array fixups. */
491}
_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 NtfsFindMftRecord(), and NtfsLookupFile().

◆ NtfsReleaseAttributeContext()

static VOID NtfsReleaseAttributeContext ( PNTFS_ATTR_CONTEXT  Context)
static

Definition at line 140 of file ntfs.c.

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

◆ NtfsSeek()

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

Definition at line 888 of file ntfs.c.

889{
891 LARGE_INTEGER NewPosition = *Position;
892
893 switch (SeekMode)
894 {
895 case SeekAbsolute:
896 break;
897 case SeekRelative:
898 NewPosition.QuadPart += FileHandle->Offset;
899 break;
900 default:
901 ASSERT(FALSE);
902 return EINVAL;
903 }
904
905 if (NewPosition.QuadPart >= NtfsGetAttributeSize(&FileHandle->DataContext->Record))
906 return EINVAL;
907
908 FileHandle->Offset = NewPosition.QuadPart;
909 return ESUCCESS;
910}
#define EINVAL
Definition: acclib.h:90
@ 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:888
ARC_STATUS NtfsOpen(CHAR *Path, OPENMODE OpenMode, ULONG *FileId)
Definition: ntfs.c:826
ARC_STATUS NtfsGetFileInformation(ULONG FileId, FILEINFORMATION *Information)
Definition: ntfs.c:804
ARC_STATUS NtfsClose(ULONG FileId)
Definition: ntfs.c:794
ARC_STATUS NtfsRead(ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
Definition: ntfs.c:873

Definition at line 928 of file ntfs.c.

Referenced by NtfsMount().

◆ NtfsVolumes

PNTFS_VOLUME_INFO NtfsVolumes[MAX_FDS]

Definition at line 55 of file ntfs.c.

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