ReactOS  0.4.14-dev-854-gb9426a3
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 (PCHAR FileName, PNTFS_INDEX_ENTRY IndexEntry)
 
static BOOLEAN NtfsFindMftRecord (PNTFS_VOLUME_INFO Volume, ULONGLONG MFTIndex, PCHAR FileName, ULONGLONG *OutMFTIndex)
 
static BOOLEAN NtfsLookupFile (PNTFS_VOLUME_INFO Volume, PCSTR FileName, PNTFS_MFT_RECORD MftRecord, PNTFS_ATTR_CONTEXT *DataContext)
 
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)
 
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 755 of file ntfs.c.

756 {
758 
761 
762  return ESUCCESS;
763 }
Definition: arc.h:32
#define TAG_NTFS_FILE
Definition: ntfs.c:38
VOID * FsGetDeviceSpecific(ULONG FileId)
Definition: fs.c:416
HANDLE FileHandle
Definition: stats.c:38
static VOID NtfsReleaseAttributeContext(PNTFS_ATTR_CONTEXT Context)
Definition: ntfs.c:140
FORCEINLINE VOID FrLdrTempFree(PVOID Allocation, ULONG Tag)
Definition: mm.h:186

Referenced by NtfsDispatch().

◆ NtfsCompareFileName()

static BOOLEAN NtfsCompareFileName ( PCHAR  FileName,
PNTFS_INDEX_ENTRY  IndexEntry 
)
static

Definition at line 512 of file ntfs.c.

513 {
514  PWCHAR EntryFileName;
515  UCHAR EntryFileNameLength;
516  UCHAR i;
517 
518  EntryFileName = IndexEntry->FileName.FileName;
519  EntryFileNameLength = IndexEntry->FileName.FileNameLength;
520 
521 #if DBG
522  NtfsPrintFile(IndexEntry);
523 #endif
524 
525  if (strlen(FileName) != EntryFileNameLength)
526  return FALSE;
527 
528  /* Do case-sensitive compares for Posix file names. */
529  if (IndexEntry->FileName.FileNameType == NTFS_FILE_NAME_POSIX)
530  {
531  for (i = 0; i < EntryFileNameLength; i++)
532  if (EntryFileName[i] != FileName[i])
533  return FALSE;
534  }
535  else
536  {
537  for (i = 0; i < EntryFileNameLength; i++)
538  if (tolower(EntryFileName[i]) != tolower(FileName[i]))
539  return FALSE;
540  }
541 
542  return TRUE;
543 }
UCHAR FileNameType
Definition: ntfs.h:187
#define TRUE
Definition: types.h:120
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
uint16_t * PWCHAR
Definition: typedefs.h:54
NTFS_FILE_NAME_ATTR FileName
Definition: ntfs.h:222
WCHAR FileName[0]
Definition: ntfs.h:188
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 NTFS_FILE_NAME_POSIX
Definition: ntfs.h:63
unsigned char UCHAR
Definition: xmlstorage.h:181
UCHAR FileNameLength
Definition: ntfs.h:186
int tolower(int c)
Definition: utclib.c:902

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 }
char CHAR
Definition: xmlstorage.h:175
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
int64_t LONG64
Definition: typedefs.h:66
#define TRACE(s)
Definition: solgame.cpp:4
unsigned __int64 ULONG64
Definition: imports.h:198
unsigned char UCHAR
Definition: xmlstorage.h:181

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;
149  ULONG ReadLength;
151 
152  TRACE("NtfsDiskRead - Offset: %I64d Length: %I64d\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  //
178  Buffer += ReadLength;
179  Length -= ReadLength;
180  Offset += ReadLength;
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  //
200  Buffer += ReadLength;
201  Length -= ReadLength;
202  Offset += ReadLength;
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 }
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
Definition: arc.h:32
static COORD Position
Definition: mouse.c:34
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1015
ULONG ARC_STATUS
Definition: arc.h:4
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
Definition: bufpool.h:45
#define TRACE(s)
Definition: solgame.cpp:4
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
ARC_STATUS ArcRead(ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
Definition: fs.c:236
ARC_STATUS ArcSeek(ULONG FileId, LARGE_INTEGER *Position, SEEKMODE SeekMode)
Definition: fs.c:243
Status
Definition: gdiplustypes.h:24
unsigned short USHORT
Definition: pedump.c:61
#define min(a, b)
Definition: monoChain.cc:55
unsigned int ULONG
Definition: retypes.h:1

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 }
signed char * PCHAR
Definition: retypes.h:7
Type
Definition: Type.h:6
struct NTFS_ATTR_RECORD * PNTFS_ATTR_RECORD
USHORT AttributesOffset
Definition: ntfs.h:112
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
unsigned int ULONG
Definition: retypes.h:1

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 }
signed char * PCHAR
Definition: retypes.h:7
#define NTFS_ATTR_TYPE_ATTRIBUTE_LIST
Definition: ntfs.h:37
Type
Definition: Type.h:6
USHORT NameOffset
Definition: ntfs.h:126
struct NTFS_ATTR_RECORD * PNTFS_ATTR_RECORD
NTFS_ATTR_RECORD Record
Definition: ntfs.h:234
ULONG Type
Definition: ntfs.h:122
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
uint16_t * PWCHAR
Definition: typedefs.h:54
ULONG Length
Definition: ntfs.h:123
FORCEINLINE PVOID FrLdrTempAlloc(_In_ SIZE_T Size, _In_ ULONG Tag)
Definition: mm.h:177
smooth NULL
Definition: ftsmooth.c:416
static PNTFS_ATTR_CONTEXT NtfsPrepareAttributeContext(PNTFS_ATTR_RECORD AttrRecord)
Definition: ntfs.c:106
#define TRACE(s)
Definition: solgame.cpp:4
#define TAG_NTFS_LIST
Definition: ntfs.c:34
NTSYSAPI ULONG NTAPI RtlEqualMemory(CONST VOID *Source1, CONST VOID *Source2, ULONG Length)
uint64_t ULONGLONG
Definition: typedefs.h:65
#define NTFS_ATTR_TYPE_END
Definition: ntfs.h:50
static VOID NtfsReleaseAttributeContext(PNTFS_ATTR_CONTEXT Context)
Definition: ntfs.c:140
static ULONGLONG NtfsGetAttributeSize(PNTFS_ATTR_RECORD AttrRecord)
Definition: ntfs.c:57
static ULONG NtfsReadAttribute(PNTFS_VOLUME_INFO Volume, PNTFS_ATTR_CONTEXT Context, ULONGLONG Offset, PCHAR Buffer, ULONG Length)
Definition: ntfs.c:222
UCHAR NameLength
Definition: ntfs.h:125
struct tagContext Context
Definition: acpixf.h:1030
unsigned int ULONG
Definition: retypes.h:1
FORCEINLINE VOID FrLdrTempFree(PVOID Allocation, ULONG Tag)
Definition: mm.h:186

Referenced by NtfsFindAttribute().

◆ NtfsFindMftRecord()

static BOOLEAN NtfsFindMftRecord ( PNTFS_VOLUME_INFO  Volume,
ULONGLONG  MFTIndex,
PCHAR  FileName,
ULONGLONG OutMFTIndex 
)
static

Definition at line 545 of file ntfs.c.

546 {
547  PNTFS_MFT_RECORD MftRecord;
548  //ULONG Magic;
549  PNTFS_ATTR_CONTEXT IndexRootCtx;
550  PNTFS_ATTR_CONTEXT IndexBitmapCtx;
551  PNTFS_ATTR_CONTEXT IndexAllocationCtx;
552  PNTFS_INDEX_ROOT IndexRoot;
553  ULONGLONG BitmapDataSize;
554  ULONGLONG IndexAllocationSize;
556  PCHAR IndexRecord;
557  PNTFS_INDEX_ENTRY IndexEntry, IndexEntryEnd;
558  ULONG RecordOffset;
559  ULONG IndexBlockSize;
560 
561  MftRecord = FrLdrTempAlloc(Volume->MftRecordSize, TAG_NTFS_MFT);
562  if (MftRecord == NULL)
563  {
564  return FALSE;
565  }
566 
567  if (NtfsReadMftRecord(Volume, MFTIndex, MftRecord))
568  {
569  //Magic = MftRecord->Magic;
570 
571  IndexRootCtx = NtfsFindAttribute(Volume, MftRecord, NTFS_ATTR_TYPE_INDEX_ROOT, L"$I30");
572  if (IndexRootCtx == NULL)
573  {
574  FrLdrTempFree(MftRecord, TAG_NTFS_MFT);
575  return FALSE;
576  }
577 
578  IndexRecord = FrLdrTempAlloc(Volume->IndexRecordSize, TAG_NTFS_INDEX_REC);
579  if (IndexRecord == NULL)
580  {
581  FrLdrTempFree(MftRecord, TAG_NTFS_MFT);
582  return FALSE;
583  }
584 
585  NtfsReadAttribute(Volume, IndexRootCtx, 0, IndexRecord, Volume->IndexRecordSize);
586  IndexRoot = (PNTFS_INDEX_ROOT)IndexRecord;
587  IndexEntry = (PNTFS_INDEX_ENTRY)((PCHAR)&IndexRoot->IndexHeader + IndexRoot->IndexHeader.EntriesOffset);
588  /* Index root is always resident. */
589  IndexEntryEnd = (PNTFS_INDEX_ENTRY)(IndexRecord + IndexRootCtx->Record.Resident.ValueLength);
590  NtfsReleaseAttributeContext(IndexRootCtx);
591 
592  TRACE("IndexRecordSize: %x IndexBlockSize: %x\n", Volume->IndexRecordSize, IndexRoot->IndexBlockSize);
593 
594  while (IndexEntry < IndexEntryEnd &&
595  !(IndexEntry->Flags & NTFS_INDEX_ENTRY_END))
596  {
597  if (NtfsCompareFileName(FileName, IndexEntry))
598  {
599  *OutMFTIndex = IndexEntry->Data.Directory.IndexedFile;
600  FrLdrTempFree(IndexRecord, TAG_NTFS_INDEX_REC);
601  FrLdrTempFree(MftRecord, TAG_NTFS_MFT);
602  return TRUE;
603  }
604  IndexEntry = (PNTFS_INDEX_ENTRY)((PCHAR)IndexEntry + IndexEntry->Length);
605  }
606 
607  if (IndexRoot->IndexHeader.Flags & NTFS_LARGE_INDEX)
608  {
609  TRACE("Large Index!\n");
610 
611  IndexBlockSize = IndexRoot->IndexBlockSize;
612 
613  IndexBitmapCtx = NtfsFindAttribute(Volume, MftRecord, NTFS_ATTR_TYPE_BITMAP, L"$I30");
614  if (IndexBitmapCtx == NULL)
615  {
616  TRACE("Corrupted filesystem!\n");
617  FrLdrTempFree(MftRecord, TAG_NTFS_MFT);
618  return FALSE;
619  }
620  BitmapDataSize = NtfsGetAttributeSize(&IndexBitmapCtx->Record);
621  TRACE("BitmapDataSize: %x\n", (ULONG)BitmapDataSize);
622  if(BitmapDataSize <= 0xFFFFFFFF)
623  BitmapData = FrLdrTempAlloc((ULONG)BitmapDataSize, TAG_NTFS_BITMAP);
624  else
625  BitmapData = NULL;
626 
627  if (BitmapData == NULL)
628  {
629  FrLdrTempFree(IndexRecord, TAG_NTFS_INDEX_REC);
630  FrLdrTempFree(MftRecord, TAG_NTFS_MFT);
631  return FALSE;
632  }
633  NtfsReadAttribute(Volume, IndexBitmapCtx, 0, BitmapData, (ULONG)BitmapDataSize);
634  NtfsReleaseAttributeContext(IndexBitmapCtx);
635 
636  IndexAllocationCtx = NtfsFindAttribute(Volume, MftRecord, NTFS_ATTR_TYPE_INDEX_ALLOCATION, L"$I30");
637  if (IndexAllocationCtx == NULL)
638  {
639  TRACE("Corrupted filesystem!\n");
641  FrLdrTempFree(IndexRecord, TAG_NTFS_INDEX_REC);
642  FrLdrTempFree(MftRecord, TAG_NTFS_MFT);
643  return FALSE;
644  }
645  IndexAllocationSize = NtfsGetAttributeSize(&IndexAllocationCtx->Record);
646 
647  RecordOffset = 0;
648 
649  for (;;)
650  {
651  TRACE("RecordOffset: %x IndexAllocationSize: %x\n", RecordOffset, IndexAllocationSize);
652  for (; RecordOffset < IndexAllocationSize;)
653  {
654  UCHAR Bit = 1 << ((RecordOffset / IndexBlockSize) & 7);
655  ULONG Byte = (RecordOffset / IndexBlockSize) >> 3;
656  if ((BitmapData[Byte] & Bit))
657  break;
658  RecordOffset += IndexBlockSize;
659  }
660 
661  if (RecordOffset >= IndexAllocationSize)
662  {
663  break;
664  }
665 
666  NtfsReadAttribute(Volume, IndexAllocationCtx, RecordOffset, IndexRecord, IndexBlockSize);
667 
668  if (!NtfsFixupRecord(Volume, (PNTFS_RECORD)IndexRecord))
669  {
670  break;
671  }
672 
673  /* FIXME */
674  IndexEntry = (PNTFS_INDEX_ENTRY)(IndexRecord + 0x18 + *(USHORT *)(IndexRecord + 0x18));
675  IndexEntryEnd = (PNTFS_INDEX_ENTRY)(IndexRecord + IndexBlockSize);
676 
677  while (IndexEntry < IndexEntryEnd &&
678  !(IndexEntry->Flags & NTFS_INDEX_ENTRY_END))
679  {
680  if (NtfsCompareFileName(FileName, IndexEntry))
681  {
682  TRACE("File found\n");
683  *OutMFTIndex = IndexEntry->Data.Directory.IndexedFile;
685  FrLdrTempFree(IndexRecord, TAG_NTFS_INDEX_REC);
686  FrLdrTempFree(MftRecord, TAG_NTFS_MFT);
687  NtfsReleaseAttributeContext(IndexAllocationCtx);
688  return TRUE;
689  }
690  IndexEntry = (PNTFS_INDEX_ENTRY)((PCHAR)IndexEntry + IndexEntry->Length);
691  }
692 
693  RecordOffset += IndexBlockSize;
694  }
695 
696  NtfsReleaseAttributeContext(IndexAllocationCtx);
698  }
699 
700  FrLdrTempFree(IndexRecord, TAG_NTFS_INDEX_REC);
701  }
702  else
703  {
704  TRACE("Can't read MFT record\n");
705  }
706  FrLdrTempFree(MftRecord, TAG_NTFS_MFT);
707 
708  return FALSE;
709 }
signed char * PCHAR
Definition: retypes.h:7
UCHAR Flags
Definition: ntfs.h:160
#define TRUE
Definition: types.h:120
#define TAG_NTFS_INDEX_REC
Definition: ntfs.c:36
unsigned char Byte
Definition: zconf.h:391
NTFS_INDEX_HEADER IndexHeader
Definition: ntfs.h:171
NTFS_ATTR_RECORD Record
Definition: ntfs.h:234
ULONG EntriesOffset
Definition: ntfs.h:157
#define NTFS_ATTR_TYPE_INDEX_ALLOCATION
Definition: ntfs.h:45
#define NTFS_INDEX_ENTRY_END
Definition: ntfs.h:61
#define TAG_NTFS_BITMAP
Definition: ntfs.c:37
FORCEINLINE PVOID FrLdrTempAlloc(_In_ SIZE_T Size, _In_ ULONG Tag)
Definition: mm.h:177
static BOOLEAN NtfsReadMftRecord(PNTFS_VOLUME_INFO Volume, ULONGLONG MFTIndex, PNTFS_MFT_RECORD Buffer)
Definition: ntfs.c:481
smooth NULL
Definition: ftsmooth.c:416
#define NTFS_ATTR_TYPE_BITMAP
Definition: ntfs.h:46
#define NTFS_LARGE_INDEX
Definition: ntfs.h:58
USHORT Flags
Definition: ntfs.h:220
#define TRACE(s)
Definition: solgame.cpp:4
struct NTFS_INDEX_ROOT * PNTFS_INDEX_ROOT
static PNTFS_ATTR_CONTEXT NtfsFindAttribute(PNTFS_VOLUME_INFO Volume, PNTFS_MFT_RECORD MftRecord, ULONG Type, const WCHAR *Name)
Definition: ntfs.c:443
uint64_t ULONGLONG
Definition: typedefs.h:65
struct BitmapData BitmapData
static BOOLEAN NtfsFixupRecord(PNTFS_VOLUME_INFO Volume, PNTFS_RECORD Record)
Definition: ntfs.c:457
unsigned char UCHAR
Definition: xmlstorage.h:181
static const WCHAR L[]
Definition: oid.c:1250
static VOID NtfsReleaseAttributeContext(PNTFS_ATTR_CONTEXT Context)
Definition: ntfs.c:140
Definition: ntfs.h:203
static ULONGLONG NtfsGetAttributeSize(PNTFS_ATTR_RECORD AttrRecord)
Definition: ntfs.c:57
struct NTFS_INDEX_ENTRY::@169::@170 Directory
#define NTFS_ATTR_TYPE_INDEX_ROOT
Definition: ntfs.h:44
static ULONG NtfsReadAttribute(PNTFS_VOLUME_INFO Volume, PNTFS_ATTR_CONTEXT Context, ULONGLONG Offset, PCHAR Buffer, ULONG Length)
Definition: ntfs.c:222
unsigned short USHORT
Definition: pedump.c:61
unsigned int ULONG
Definition: retypes.h:1
static BOOLEAN NtfsCompareFileName(PCHAR FileName, PNTFS_INDEX_ENTRY IndexEntry)
Definition: ntfs.c:512
#define TAG_NTFS_MFT
Definition: ntfs.c:35
struct NTFS_INDEX_ENTRY * PNTFS_INDEX_ENTRY
struct NTFS_ATTR_RECORD::@165::@167 Resident
USHORT Length
Definition: ntfs.h:218
ULONG IndexBlockSize
Definition: ntfs.h:168
union NTFS_INDEX_ENTRY::@169 Data
FORCEINLINE VOID FrLdrTempFree(PVOID Allocation, ULONG Tag)
Definition: mm.h:186

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 }
signed char * PCHAR
Definition: retypes.h:7
#define TRUE
Definition: types.h:120
_In_ struct _KBUGCHECK_REASON_CALLBACK_RECORD * Record
Definition: ketypes.h:256
unsigned short USHORT
Definition: pedump.c:61

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:124
struct NTFS_ATTR_RECORD::@165::@168 NonResident
struct NTFS_ATTR_RECORD::@165::@167 Resident

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

◆ NtfsGetFileInformation()

ARC_STATUS NtfsGetFileInformation ( ULONG  FileId,
FILEINFORMATION Information 
)

Definition at line 765 of file ntfs.c.

766 {
768 
770  Information->EndingAddress.QuadPart = NtfsGetAttributeSize(&FileHandle->DataContext->Record);
771  Information->CurrentAddress.QuadPart = FileHandle->Offset;
772 
773  TRACE("NtfsGetFileInformation(%lu) -> FileSize = %llu, FilePointer = 0x%llx\n",
774  FileId, Information->EndingAddress.QuadPart, Information->CurrentAddress.QuadPart);
775 
776  return ESUCCESS;
777 }
Definition: arc.h:32
VOID * FsGetDeviceSpecific(ULONG FileId)
Definition: fs.c:416
HANDLE FileHandle
Definition: stats.c:38
#define TRACE(s)
Definition: solgame.cpp:4
static ULONGLONG NtfsGetAttributeSize(PNTFS_ATTR_RECORD AttrRecord)
Definition: ntfs.c:57
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
Iosb Information
Definition: create.c:4377

◆ NtfsLookupFile()

static BOOLEAN NtfsLookupFile ( PNTFS_VOLUME_INFO  Volume,
PCSTR  FileName,
PNTFS_MFT_RECORD  MftRecord,
PNTFS_ATTR_CONTEXT DataContext 
)
static

Definition at line 711 of file ntfs.c.

712 {
713  ULONG NumberOfPathParts;
714  CHAR PathPart[261];
715  ULONGLONG CurrentMFTIndex;
716  UCHAR i;
717 
718  TRACE("NtfsLookupFile() FileName = %s\n", FileName);
719 
720  CurrentMFTIndex = NTFS_FILE_ROOT;
721  NumberOfPathParts = FsGetNumPathParts(FileName);
722  for (i = 0; i < NumberOfPathParts; i++)
723  {
724  FsGetFirstNameFromPath(PathPart, FileName);
725 
726  for (; (*FileName != '\\') && (*FileName != '/') && (*FileName != '\0'); FileName++)
727  ;
728  FileName++;
729 
730  TRACE("- Lookup: %s\n", PathPart);
731  if (!NtfsFindMftRecord(Volume, CurrentMFTIndex, PathPart, &CurrentMFTIndex))
732  {
733  TRACE("- Failed\n");
734  return FALSE;
735  }
736  TRACE("- Lookup: %x\n", CurrentMFTIndex);
737  }
738 
739  if (!NtfsReadMftRecord(Volume, CurrentMFTIndex, MftRecord))
740  {
741  TRACE("NtfsLookupFile: Can't read MFT record\n");
742  return FALSE;
743  }
744 
745  *DataContext = NtfsFindAttribute(Volume, MftRecord, NTFS_ATTR_TYPE_DATA, L"");
746  if (*DataContext == NULL)
747  {
748  TRACE("NtfsLookupFile: Can't find data attribute\n");
749  return FALSE;
750  }
751 
752  return TRUE;
753 }
#define TRUE
Definition: types.h:120
VOID FsGetFirstNameFromPath(PCHAR Buffer, PCSTR Path)
Definition: fs.c:356
char CHAR
Definition: xmlstorage.h:175
ULONG FsGetNumPathParts(PCSTR Path)
Definition: fs.c:328
#define NTFS_ATTR_TYPE_DATA
Definition: ntfs.h:43
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
static BOOLEAN NtfsReadMftRecord(PNTFS_VOLUME_INFO Volume, ULONGLONG MFTIndex, PNTFS_MFT_RECORD Buffer)
Definition: ntfs.c:481
smooth NULL
Definition: ftsmooth.c:416
#define TRACE(s)
Definition: solgame.cpp:4
static PNTFS_ATTR_CONTEXT NtfsFindAttribute(PNTFS_VOLUME_INFO Volume, PNTFS_MFT_RECORD MftRecord, ULONG Type, const WCHAR *Name)
Definition: ntfs.c:443
uint64_t ULONGLONG
Definition: typedefs.h:65
unsigned char UCHAR
Definition: xmlstorage.h:181
static const WCHAR L[]
Definition: oid.c:1250
unsigned int ULONG
Definition: retypes.h:1
static BOOLEAN NtfsFindMftRecord(PNTFS_VOLUME_INFO Volume, ULONGLONG MFTIndex, PCHAR FileName, ULONGLONG *OutMFTIndex)
Definition: ntfs.c:545
#define NTFS_FILE_ROOT
Definition: ntfs.h:28

Referenced by NtfsOpen().

◆ NtfsMount()

const DEVVTBL* NtfsMount ( ULONG  DeviceId)

Definition at line 881 of file ntfs.c.

882 {
885  ULONG Count;
887 
888  TRACE("Enter NtfsMount(%lu)\n", DeviceId);
889 
890  //
891  // Allocate data for volume information
892  //
894  if (!Volume)
895  return NULL;
897 
898  //
899  // Read the BootSector
900  //
901  Position.QuadPart = 0;
902  Status = ArcSeek(DeviceId, &Position, SeekAbsolute);
903  if (Status != ESUCCESS)
904  {
906  return NULL;
907  }
908  Status = ArcRead(DeviceId, &Volume->BootSector, sizeof(Volume->BootSector), &Count);
909  if (Status != ESUCCESS || Count != sizeof(Volume->BootSector))
910  {
912  return NULL;
913  }
914 
915  //
916  // Check if BootSector is valid. If no, return early
917  //
918  if (!RtlEqualMemory(Volume->BootSector.SystemId, "NTFS", 4))
919  {
921  return NULL;
922  }
923 
924  //
925  // Calculate cluster size and MFT record size
926  //
927  Volume->ClusterSize = Volume->BootSector.SectorsPerCluster * Volume->BootSector.BytesPerSector;
928  if (Volume->BootSector.ClustersPerMftRecord > 0)
929  Volume->MftRecordSize = Volume->BootSector.ClustersPerMftRecord * Volume->ClusterSize;
930  else
931  Volume->MftRecordSize = 1 << (-Volume->BootSector.ClustersPerMftRecord);
932  if (Volume->BootSector.ClustersPerIndexRecord > 0)
933  Volume->IndexRecordSize = Volume->BootSector.ClustersPerIndexRecord * Volume->ClusterSize;
934  else
935  Volume->IndexRecordSize = 1 << (-Volume->BootSector.ClustersPerIndexRecord);
936 
937  TRACE("ClusterSize: 0x%x\n", Volume->ClusterSize);
938  TRACE("ClustersPerMftRecord: %d\n", Volume->BootSector.ClustersPerMftRecord);
939  TRACE("ClustersPerIndexRecord: %d\n", Volume->BootSector.ClustersPerIndexRecord);
940  TRACE("MftRecordSize: 0x%x\n", Volume->MftRecordSize);
941  TRACE("IndexRecordSize: 0x%x\n", Volume->IndexRecordSize);
942 
943  //
944  // Read MFT index
945  //
946  TRACE("Reading MFT index...\n");
947  Volume->MasterFileTable = FrLdrTempAlloc(Volume->MftRecordSize, TAG_NTFS_MFT);
948  if (!Volume->MasterFileTable)
949  {
951  return NULL;
952  }
953  Position.QuadPart = Volume->BootSector.MftLocation * Volume->ClusterSize;
954  Status = ArcSeek(DeviceId, &Position, SeekAbsolute);
955  if (Status != ESUCCESS)
956  {
957  FileSystemError("Failed to seek to Master File Table record.");
958  FrLdrTempFree(Volume->MasterFileTable, TAG_NTFS_MFT);
960  return NULL;
961  }
962  Status = ArcRead(DeviceId, Volume->MasterFileTable, Volume->MftRecordSize, &Count);
963  if (Status != ESUCCESS || Count != Volume->MftRecordSize)
964  {
965  FileSystemError("Failed to read the Master File Table record.");
966  FrLdrTempFree(Volume->MasterFileTable, TAG_NTFS_MFT);
968  return NULL;
969  }
970 
971  //
972  // Keep room to read partial sectors
973  //
974  Volume->TemporarySector = FrLdrTempAlloc(Volume->BootSector.BytesPerSector, TAG_NTFS_DATA);
975  if (!Volume->TemporarySector)
976  {
977  FileSystemError("Failed to allocate memory.");
978  FrLdrTempFree(Volume->MasterFileTable, TAG_NTFS_MFT);
980  return NULL;
981  }
982 
983  //
984  // Keep device id
985  //
986  Volume->DeviceId = DeviceId;
987 
988  //
989  // Search DATA attribute
990  //
991  TRACE("Searching for DATA attribute...\n");
992  Volume->MFTContext = NtfsFindAttribute(Volume, Volume->MasterFileTable, NTFS_ATTR_TYPE_DATA, L"");
993  if (!Volume->MFTContext)
994  {
995  FileSystemError("Can't find data attribute for Master File Table.");
996  FrLdrTempFree(Volume->MasterFileTable, TAG_NTFS_MFT);
998  return NULL;
999  }
1000 
1001  //
1002  // Remember NTFS volume information
1003  //
1004  NtfsVolumes[DeviceId] = Volume;
1005 
1006  //
1007  // Return success
1008  //
1009  TRACE("NtfsMount(%lu) success\n", DeviceId);
1010  return &NtfsFuncTable;
1011 }
Definition: arc.h:32
static COORD Position
Definition: mouse.c:34
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1015
ULONG ARC_STATUS
Definition: arc.h:4
#define NTFS_ATTR_TYPE_DATA
Definition: ntfs.h:43
VOID FileSystemError(PCSTR ErrorString)
Definition: fs.c:259
FORCEINLINE PVOID FrLdrTempAlloc(_In_ SIZE_T Size, _In_ ULONG Tag)
Definition: mm.h:177
smooth NULL
Definition: ftsmooth.c:416
#define TRACE(s)
Definition: solgame.cpp:4
NTSYSAPI ULONG NTAPI RtlEqualMemory(CONST VOID *Source1, CONST VOID *Source2, ULONG Length)
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_VOLUME
Definition: ntfs.c:39
ARC_STATUS ArcRead(ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
Definition: fs.c:236
static const WCHAR L[]
Definition: oid.c:1250
PNTFS_VOLUME_INFO NtfsVolumes[MAX_FDS]
Definition: ntfs.c:55
ARC_STATUS ArcSeek(ULONG FileId, LARGE_INTEGER *Position, SEEKMODE SeekMode)
Definition: fs.c:243
Status
Definition: gdiplustypes.h:24
#define TAG_NTFS_DATA
Definition: ntfs.c:40
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define TAG_NTFS_MFT
Definition: ntfs.c:35
const DEVVTBL NtfsFuncTable
Definition: ntfs.c:871
FORCEINLINE VOID FrLdrTempFree(PVOID Allocation, ULONG Tag)
Definition: mm.h:186

Referenced by ArcOpen().

◆ NtfsOpen()

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

Definition at line 779 of file ntfs.c.

780 {
783  PNTFS_MFT_RECORD MftRecord;
784  ULONG DeviceId;
785 
786  //
787  // Check parameters
788  //
789  if (OpenMode != OpenReadOnly)
790  return EACCES;
791 
792  //
793  // Get underlying device
794  //
795  DeviceId = FsGetDeviceId(*FileId);
796  Volume = NtfsVolumes[DeviceId];
797 
798  TRACE("NtfsOpen() FileName = %s\n", Path);
799 
800  //
801  // Allocate file structure
802  //
803  FileHandle = FrLdrTempAlloc(sizeof(NTFS_FILE_HANDLE) + Volume->MftRecordSize,
804  TAG_NTFS_FILE);
805  if (!FileHandle)
806  {
807  return ENOMEM;
808  }
809  RtlZeroMemory(FileHandle, sizeof(NTFS_FILE_HANDLE) + Volume->MftRecordSize);
810  FileHandle->Volume = Volume;
811 
812  //
813  // Search file entry
814  //
815  MftRecord = (PNTFS_MFT_RECORD)(FileHandle + 1);
816  if (!NtfsLookupFile(Volume, Path, MftRecord, &FileHandle->DataContext))
817  {
819  return ENOENT;
820  }
821 
823  return ESUCCESS;
824 }
struct NTFS_MFT_RECORD * PNTFS_MFT_RECORD
Definition: arc.h:32
#define TAG_NTFS_FILE
Definition: ntfs.c:38
Definition: arc.h:48
HANDLE FileHandle
Definition: stats.c:38
FORCEINLINE PVOID FrLdrTempAlloc(_In_ SIZE_T Size, _In_ ULONG Tag)
Definition: mm.h:177
#define TRACE(s)
Definition: solgame.cpp:4
static BOOLEAN NtfsLookupFile(PNTFS_VOLUME_INFO Volume, PCSTR FileName, PNTFS_MFT_RECORD MftRecord, PNTFS_ATTR_CONTEXT *DataContext)
Definition: ntfs.c:711
VOID FsSetDeviceSpecific(ULONG FileId, VOID *Specific)
Definition: fs.c:409
Definition: arc.h:34
PNTFS_VOLUME_INFO NtfsVolumes[MAX_FDS]
Definition: ntfs.c:55
PRTL_UNICODE_STRING_BUFFER Path
Definition: arc.h:46
ULONG FsGetDeviceId(ULONG FileId)
Definition: fs.c:423
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
FORCEINLINE VOID FrLdrTempFree(PVOID Allocation, ULONG Tag)
Definition: mm.h:186

◆ 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 }
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
unsigned char * PUCHAR
Definition: retypes.h:3
_In_ struct _KBUGCHECK_REASON_CALLBACK_RECORD * Record
Definition: ketypes.h:256
ULONG Length
Definition: ntfs.h:123
FORCEINLINE PVOID FrLdrTempAlloc(_In_ SIZE_T Size, _In_ ULONG Tag)
Definition: mm.h:177
int64_t LONGLONG
Definition: typedefs.h:66
#define TAG_NTFS_CONTEXT
Definition: ntfs.c:33
uint64_t ULONGLONG
Definition: typedefs.h:65
UCHAR IsNonResident
Definition: ntfs.h:124
static PUCHAR NtfsDecodeRun(PUCHAR DataRun, LONGLONG *DataRunOffset, ULONGLONG *DataRunLength)
Definition: ntfs.c:65
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
struct tagContext Context
Definition: acpixf.h:1030

Referenced by NtfsFindAttributeHelper().

◆ NtfsRead()

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

Definition at line 826 of file ntfs.c.

827 {
829  ULONGLONG BytesRead64;
830 
831  //
832  // Read file
833  //
834  BytesRead64 = NtfsReadAttribute(FileHandle->Volume, FileHandle->DataContext, FileHandle->Offset, Buffer, N);
835  FileHandle->Offset += BytesRead64;
836  *Count = (ULONG)BytesRead64;
837 
838  //
839  // Check for success
840  //
841  if (BytesRead64 > 0)
842  return ESUCCESS;
843  else
844  return EIO;
845 }
Definition: arc.h:32
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1015
VOID * FsGetDeviceSpecific(ULONG FileId)
Definition: fs.c:416
HANDLE FileHandle
Definition: stats.c:38
Definition: bufpool.h:45
uint64_t ULONGLONG
Definition: typedefs.h:65
static ULONG NtfsReadAttribute(PNTFS_VOLUME_INFO Volume, PNTFS_ATTR_CONTEXT Context, ULONGLONG Offset, PCHAR Buffer, ULONG Length)
Definition: ntfs.c:222
Definition: arc.h:40
unsigned int ULONG
Definition: retypes.h:1

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;
230  ULONG ReadLength;
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)
305  RtlZeroMemory(Buffer, ReadLength);
306  if (DataRunStartLCN == -1 || NtfsDiskRead(Volume, DataRunStartLCN * Volume->ClusterSize + Offset - CurrentOffset, ReadLength, Buffer))
307  {
308  Length -= ReadLength;
309  Buffer += ReadLength;
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)
329  RtlZeroMemory(Buffer, ReadLength);
330  else if (!NtfsDiskRead(Volume, DataRunStartLCN * Volume->ClusterSize, ReadLength, Buffer))
331  break;
332 
333  Length -= ReadLength;
334  Buffer += ReadLength;
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 }
signed char * PCHAR
Definition: retypes.h:7
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
unsigned char * PUCHAR
Definition: retypes.h:3
while(1)
Definition: macro.lex.yy.c:740
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
Definition: bufpool.h:45
int64_t LONGLONG
Definition: typedefs.h:66
static BOOLEAN NtfsDiskRead(PNTFS_VOLUME_INFO Volume, ULONGLONG Offset, ULONGLONG Length, PCHAR Buffer)
Definition: ntfs.c:145
uint64_t ULONGLONG
Definition: typedefs.h:65
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
static PUCHAR NtfsDecodeRun(PUCHAR DataRun, LONGLONG *DataRunOffset, ULONGLONG *DataRunLength)
Definition: ntfs.c:65
#define min(a, b)
Definition: monoChain.cc:55
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261

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 }
signed char * PCHAR
Definition: retypes.h:7
Definition: bufpool.h:45
uint64_t ULONGLONG
Definition: typedefs.h:65
static BOOLEAN NtfsFixupRecord(PNTFS_VOLUME_INFO Volume, PNTFS_RECORD Record)
Definition: ntfs.c:457
static ULONG NtfsReadAttribute(PNTFS_VOLUME_INFO Volume, PNTFS_ATTR_CONTEXT Context, ULONGLONG Offset, PCHAR Buffer, ULONG Length)
Definition: ntfs.c:222
_Must_inspect_result_ _In_ PFILE_OBJECT _In_opt_ PLARGE_INTEGER _In_ ULONG _In_ FLT_IO_OPERATION_FLAGS _Out_opt_ PULONG BytesRead
Definition: fltkernel.h:1255

Referenced by NtfsFindMftRecord(), and NtfsLookupFile().

◆ NtfsReleaseAttributeContext()

static VOID NtfsReleaseAttributeContext ( PNTFS_ATTR_CONTEXT  Context)
static

Definition at line 140 of file ntfs.c.

141 {
143 }
#define TAG_NTFS_CONTEXT
Definition: ntfs.c:33
FORCEINLINE VOID FrLdrTempFree(PVOID Allocation, ULONG Tag)
Definition: mm.h:186

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

◆ NtfsSeek()

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

Definition at line 847 of file ntfs.c.

848 {
850  LARGE_INTEGER NewPosition = *Position;
851 
852  switch (SeekMode)
853  {
854  case SeekAbsolute:
855  break;
856  case SeekRelative:
857  NewPosition.QuadPart += FileHandle->Offset;
858  break;
859  default:
860  ASSERT(FALSE);
861  return EINVAL;
862  }
863 
864  if (NewPosition.QuadPart >= NtfsGetAttributeSize(&FileHandle->DataContext->Record))
865  return EINVAL;
866 
867  FileHandle->Offset = NewPosition.QuadPart;
868  return ESUCCESS;
869 }
Definition: arc.h:32
Definition: arc.h:39
static COORD Position
Definition: mouse.c:34
VOID * FsGetDeviceSpecific(ULONG FileId)
Definition: fs.c:416
HANDLE FileHandle
Definition: stats.c:38
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
static ULONGLONG NtfsGetAttributeSize(PNTFS_ATTR_RECORD AttrRecord)
Definition: ntfs.c:57
LONGLONG QuadPart
Definition: typedefs.h:112

Variable Documentation

◆ NtfsFuncTable

const DEVVTBL NtfsFuncTable
Initial value:
=
{
L"ntfs",
}
ARC_STATUS NtfsOpen(CHAR *Path, OPENMODE OpenMode, ULONG *FileId)
Definition: ntfs.c:779
ARC_STATUS NtfsGetFileInformation(ULONG FileId, FILEINFORMATION *Information)
Definition: ntfs.c:765
ARC_STATUS NtfsSeek(ULONG FileId, LARGE_INTEGER *Position, SEEKMODE SeekMode)
Definition: ntfs.c:847
ARC_STATUS NtfsRead(ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
Definition: ntfs.c:826
ARC_STATUS NtfsClose(ULONG FileId)
Definition: ntfs.c:755
static const WCHAR L[]
Definition: oid.c:1250

Definition at line 871 of file ntfs.c.

Referenced by NtfsMount().

◆ NtfsVolumes

PNTFS_VOLUME_INFO NtfsVolumes[MAX_FDS]

Definition at line 55 of file ntfs.c.

Referenced by NtfsMount(), and NtfsOpen().