ReactOS 0.4.17-dev-1190-g4c812f4
ntfs.h File Reference
#include <ntifs.h>
#include <pseh/pseh2.h>
#include <section_attribs.h>
#include <pshpack1.h>
#include <poppack.h>
Include dependency graph for ntfs.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  _BIOS_PARAMETERS_BLOCK
 
struct  _EXTENDED_BIOS_PARAMETERS_BLOCK
 
struct  _BOOT_SECTOR
 
struct  _NTFS_INFO
 
struct  NTFSIDENTIFIER
 
struct  DEVICE_EXTENSION
 
struct  NTFS_CCB
 
struct  NTFS_GLOBAL_DATA
 
struct  NTFS_RECORD_HEADER
 
struct  _FILE_RECORD_HEADER
 
struct  NTFS_ATTR_RECORD
 
struct  NTFS_ATTRIBUTE_LIST_ITEM
 
struct  STANDARD_INFORMATION
 
struct  ATTRIBUTE_LIST
 
struct  FILENAME_ATTRIBUTE
 
struct  INDEX_HEADER_ATTRIBUTE
 
struct  INDEX_ROOT_ATTRIBUTE
 
struct  INDEX_BUFFER
 
struct  INDEX_ENTRY_ATTRIBUTE
 
struct  _B_TREE_KEY
 
struct  _B_TREE_FILENAME_NODE
 
struct  B_TREE
 
struct  VOLINFO_ATTRIBUTE
 
struct  REPARSE_POINT_ATTRIBUTE
 
struct  _NTFS_IO_RUN
 
struct  _NTFS_IO_RUN_LIST
 
struct  _NTFS_IO_CONTEXT
 
struct  NTFS_IRP_CONTEXT
 
struct  _NTFS_ATTR_CONTEXT
 
struct  _FCB
 
struct  _FIND_ATTR_CONTXT
 
struct  FIXUP_ARRAY
 
struct  _NTFS_FILENAME_UPDATE
 

Macros

#define CACHEPAGESIZE(pDeviceExt)
 
#define TAG_NTFS   '0ftN'
 
#define TAG_CCB   'CftN'
 
#define TAG_FCB   'FftN'
 
#define TAG_IRP_CTXT   'iftN'
 
#define TAG_ATT_CTXT   'aftN'
 
#define TAG_FILE_REC   'rftN'
 
#define TAG_IO_RUNS   'RftN'
 
#define ROUND_UP(N, S)   ((((N) + (S) - 1) / (S)) * (S))
 
#define ROUND_DOWN(N, S)   ((N) - ((N) % (S)))
 
#define DEVICE_NAME   L"\\Ntfs"
 
#define NTFS_TYPE_CCB   '20SF'
 
#define NTFS_TYPE_FCB   '30SF'
 
#define NTFS_TYPE_VCB   '50SF'
 
#define NTFS_TYPE_IRP_CONTEXT   '60SF'
 
#define NTFS_TYPE_GLOBAL_DATA   '70SF'
 
#define VCB_VOLUME_LOCKED   0x0001
 
#define VCB_VOLUME_DISMOUNTED   0x0002
 
#define CCB_RETURNED_DOT   0x0001
 
#define CCB_RETURNED_DOTDOT   0x0002
 
#define FILE_RECORD_END   0x11477982
 
#define NTFS_FILE_MFT   0
 
#define NTFS_FILE_MFTMIRR   1
 
#define NTFS_FILE_LOGFILE   2
 
#define NTFS_FILE_VOLUME   3
 
#define NTFS_FILE_ATTRDEF   4
 
#define NTFS_FILE_ROOT   5
 
#define NTFS_FILE_BITMAP   6
 
#define NTFS_FILE_BOOT   7
 
#define NTFS_FILE_BADCLUS   8
 
#define NTFS_FILE_QUOTA   9
 
#define NTFS_FILE_UPCASE   10
 
#define NTFS_FILE_EXTEND   11
 
#define NTFS_FILE_FIRST_USER_FILE   16
 
#define NTFS_MFT_MASK   0x0000FFFFFFFFFFFFULL
 
#define COLLATION_BINARY   0x00
 
#define COLLATION_FILE_NAME   0x01
 
#define COLLATION_UNICODE_STRING   0x02
 
#define COLLATION_NTOFS_ULONG   0x10
 
#define COLLATION_NTOFS_SID   0x11
 
#define COLLATION_NTOFS_SECURITY_HASH   0x12
 
#define COLLATION_NTOFS_ULONGS   0x13
 
#define INDEX_ROOT_SMALL   0x0
 
#define INDEX_ROOT_LARGE   0x1
 
#define INDEX_NODE_SMALL   0x0
 
#define INDEX_NODE_LARGE   0x1
 
#define NTFS_INDEX_ENTRY_NODE   1
 
#define NTFS_INDEX_ENTRY_END   2
 
#define NTFS_FILE_NAME_POSIX   0
 
#define NTFS_FILE_NAME_WIN32   1
 
#define NTFS_FILE_NAME_DOS   2
 
#define NTFS_FILE_NAME_WIN32_AND_DOS   3
 
#define NTFS_FILE_TYPE_READ_ONLY   0x1
 
#define NTFS_FILE_TYPE_HIDDEN   0x2
 
#define NTFS_FILE_TYPE_SYSTEM   0x4
 
#define NTFS_FILE_TYPE_ARCHIVE   0x20
 
#define NTFS_FILE_TYPE_TEMPORARY   0x100
 
#define NTFS_FILE_TYPE_SPARSE   0x200
 
#define NTFS_FILE_TYPE_REPARSE   0x400
 
#define NTFS_FILE_TYPE_COMPRESSED   0x800
 
#define NTFS_FILE_TYPE_OFFLINE   0x1000
 
#define NTFS_FILE_TYPE_ENCRYPTED   0x4000
 
#define NTFS_FILE_TYPE_DIRECTORY   0x10000000
 
#define NTFS_ATTR_COMPRESSION_MASK   0x00FF
 
#define NTFS_ATTR_SPARSE   0x8000
 
#define RA_INDEXED   0x01
 
#define NRH_FILE_TYPE   0x454C4946 /* 'FILE' */
 
#define NRH_INDX_TYPE   0x58444E49 /* 'INDX' */
 
#define FRH_IN_USE   0x0001 /* Record is in use */
 
#define FRH_DIRECTORY   0x0002 /* Record is a directory */
 
#define FRH_UNKNOWN1   0x0004 /* Don't know */
 
#define FRH_UNKNOWN2   0x0008 /* Don't know */
 
#define ATTR_RECORD_ALIGNMENT   8
 
#define DATA_RUN_ALIGNMENT   4
 
#define VALUE_OFFSET_ALIGNMENT   4
 
#define IRPCONTEXT_CANWAIT   0x1
 
#define IRPCONTEXT_COMPLETE   0x2
 
#define IRPCONTEXT_QUEUE   0x4
 
#define NTFS_SPARSE_LBO   ((LONGLONG)-1)
 
#define NTFS_MAX_IO_RUNS_ON_STACK   8
 
#define FCB_CACHE_INITIALIZED   0x0001
 
#define FCB_IS_VOLUME_STREAM   0x0002
 
#define FCB_IS_VOLUME   0x0004
 
#define FCB_DELETE_PENDING   0x0008
 
#define FCB_DELETED   0x0010
 
#define MAX_PATH   260
 
#define NTFS_FILENAME_UPDATE_SIZES   0x1
 
#define NTFS_FILENAME_UPDATE_TIMES   0x2
 
#define NTFS_FILENAME_UPDATE_ATTRS   0x4
 

Typedefs

typedef struct _BIOS_PARAMETERS_BLOCK BIOS_PARAMETERS_BLOCK
 
typedef struct _BIOS_PARAMETERS_BLOCK * PBIOS_PARAMETERS_BLOCK
 
typedef struct _EXTENDED_BIOS_PARAMETERS_BLOCK EXTENDED_BIOS_PARAMETERS_BLOCK
 
typedef struct _EXTENDED_BIOS_PARAMETERS_BLOCK * PEXTENDED_BIOS_PARAMETERS_BLOCK
 
typedef struct _BOOT_SECTOR BOOT_SECTOR
 
typedef struct _BOOT_SECTOR * PBOOT_SECTOR
 
typedef struct _NTFS_INFO NTFS_INFO
 
typedef struct _NTFS_INFO * PNTFS_INFO
 
typedef struct NTFSIDENTIFIER * PNTFSIDENTIFIER
 
typedef struct DEVICE_EXTENSION * PDEVICE_EXTENSION
 
typedef struct DEVICE_EXTENSION NTFS_VCB
 
typedef struct DEVICE_EXTENSION * PNTFS_VCB
 
typedef struct NTFS_CCB * PNTFS_CCB
 
typedef struct NTFS_GLOBAL_DATA * PNTFS_GLOBAL_DATA
 
typedef enum ATTRIBUTE_TYPE * PATTRIBUTE_TYPE
 
typedef struct NTFS_RECORD_HEADER * PNTFS_RECORD_HEADER
 
typedef struct _FILE_RECORD_HEADER FILE_RECORD_HEADER
 
typedef struct _FILE_RECORD_HEADER * PFILE_RECORD_HEADER
 
typedef struct NTFS_ATTR_RECORD * PNTFS_ATTR_RECORD
 
typedef struct NTFS_ATTRIBUTE_LIST_ITEM * PNTFS_ATTRIBUTE_LIST_ITEM
 
typedef struct STANDARD_INFORMATION * PSTANDARD_INFORMATION
 
typedef struct ATTRIBUTE_LIST * PATTRIBUTE_LIST
 
typedef struct FILENAME_ATTRIBUTE * PFILENAME_ATTRIBUTE
 
typedef struct INDEX_HEADER_ATTRIBUTE * PINDEX_HEADER_ATTRIBUTE
 
typedef struct INDEX_ROOT_ATTRIBUTE * PINDEX_ROOT_ATTRIBUTE
 
typedef struct INDEX_BUFFER * PINDEX_BUFFER
 
typedef struct INDEX_ENTRY_ATTRIBUTE * PINDEX_ENTRY_ATTRIBUTE
 
typedef struct _B_TREE_FILENAME_NODE B_TREE_FILENAME_NODE
 
typedef struct _B_TREE_KEY B_TREE_KEY
 
typedef struct _B_TREE_KEY * PB_TREE_KEY
 
typedef struct _B_TREE_FILENAME_NODE * PB_TREE_FILENAME_NODE
 
typedef struct B_TREE * PB_TREE
 
typedef struct VOLINFO_ATTRIBUTE * PVOLINFO_ATTRIBUTE
 
typedef struct REPARSE_POINT_ATTRIBUTE * PREPARSE_POINT_ATTRIBUTE
 
typedef struct _NTFS_IO_RUN NTFS_IO_RUN
 
typedef struct _NTFS_IO_RUN * PNTFS_IO_RUN
 
typedef struct _NTFS_IO_RUN_LIST NTFS_IO_RUN_LIST
 
typedef struct _NTFS_IO_RUN_LIST * PNTFS_IO_RUN_LIST
 
typedef struct _NTFS_IO_CONTEXT NTFS_IO_CONTEXT
 
typedef struct _NTFS_IO_CONTEXT * PNTFS_IO_CONTEXT
 
typedef struct NTFS_IRP_CONTEXT * PNTFS_IRP_CONTEXT
 
typedef struct _NTFS_ATTR_CONTEXT NTFS_ATTR_CONTEXT
 
typedef struct _NTFS_ATTR_CONTEXT * PNTFS_ATTR_CONTEXT
 
typedef struct _FCB NTFS_FCB
 
typedef struct _FCB * PNTFS_FCB
 
typedef struct _FIND_ATTR_CONTXT FIND_ATTR_CONTXT
 
typedef struct _FIND_ATTR_CONTXT * PFIND_ATTR_CONTXT
 
typedef struct FIXUP_ARRAY * PFIXUP_ARRAY
 
typedef struct _NTFS_FILENAME_UPDATE NTFS_FILENAME_UPDATE
 
typedef struct _NTFS_FILENAME_UPDATE * PNTFS_FILENAME_UPDATE
 

Enumerations

enum  ATTRIBUTE_TYPE {
  AttributeStandardInformation = 0x10 , AttributeAttributeList = 0x20 , AttributeFileName = 0x30 , AttributeObjectId = 0x40 ,
  AttributeSecurityDescriptor = 0x50 , AttributeVolumeName = 0x60 , AttributeVolumeInformation = 0x70 , AttributeData = 0x80 ,
  AttributeIndexRoot = 0x90 , AttributeIndexAllocation = 0xA0 , AttributeBitmap = 0xB0 , AttributeReparsePoint = 0xC0 ,
  AttributeEAInformation = 0xD0 , AttributeEA = 0xE0 , AttributePropertySet = 0xF0 , AttributeLoggedUtilityStream = 0x100 ,
  AttributeEnd = 0xFFFFFFFF , AttributeStandardInformation = 0x10 , AttributeAttributeList = 0x20 , AttributeFileName = 0x30 ,
  AttributeObjectId = 0x40 , AttributeSecurityDescriptor = 0x50 , AttributeVolumeName = 0x60 , AttributeVolumeInformation = 0x70 ,
  AttributeData = 0x80 , AttributeIndexRoot = 0x90 , AttributeIndexAllocation = 0xA0 , AttributeBitmap = 0xB0 ,
  AttributeReparsePoint = 0xC0 , AttributeEAInformation = 0xD0 , AttributeEA = 0xE0 , AttributePropertySet = 0xF0 ,
  AttributeLoggedUtilityStream = 0x100 , AttributeEnd = 0xFFFFFFFF
}
 

Functions

FORCEINLINE NTSTATUS NtfsMarkIrpContextForQueue (PNTFS_IRP_CONTEXT IrpContext)
 
NTSTATUS AddBitmap (PNTFS_VCB Vcb, PFILE_RECORD_HEADER FileRecord, PNTFS_ATTR_RECORD AttributeAddress, PCWSTR Name, USHORT NameLength)
 
NTSTATUS AddData (PFILE_RECORD_HEADER FileRecord, PNTFS_ATTR_RECORD AttributeAddress)
 
NTSTATUS AddRun (PNTFS_VCB Vcb, PNTFS_ATTR_CONTEXT AttrContext, ULONG AttrOffset, PFILE_RECORD_HEADER FileRecord, ULONGLONG NextAssignedCluster, ULONG RunLength)
 
NTSTATUS AddIndexAllocation (PNTFS_VCB Vcb, PFILE_RECORD_HEADER FileRecord, PNTFS_ATTR_RECORD AttributeAddress, PCWSTR Name, USHORT NameLength)
 
NTSTATUS AddIndexRoot (PNTFS_VCB Vcb, PFILE_RECORD_HEADER FileRecord, PNTFS_ATTR_RECORD AttributeAddress, PINDEX_ROOT_ATTRIBUTE NewIndexRoot, ULONG RootLength, PCWSTR Name, USHORT NameLength)
 
NTSTATUS AddFileName (PFILE_RECORD_HEADER FileRecord, PNTFS_ATTR_RECORD AttributeAddress, PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, BOOLEAN CaseSensitive, PULONGLONG ParentMftIndex)
 
NTSTATUS AddStandardInformation (PFILE_RECORD_HEADER FileRecord, PNTFS_ATTR_RECORD AttributeAddress)
 
NTSTATUS ConvertDataRunsToLargeMCB (PUCHAR DataRun, PLARGE_MCB DataRunsMCB, PULONGLONG pNextVBN)
 
NTSTATUS ConvertLargeMCBToDataRuns (PLARGE_MCB DataRunsMCB, ULONGLONG VcnCount, PUCHAR RunBuffer, ULONG MaxBufferSize, PULONG UsedBufferSize)
 
PUCHAR DecodeRun (PUCHAR DataRun, LONGLONG *DataRunOffset, ULONGLONG *DataRunLength)
 
ULONG GetFileNameAttributeLength (PFILENAME_ATTRIBUTE FileNameAttribute)
 
VOID NtfsDumpDataRuns (PVOID StartOfRun, ULONGLONG CurrentLCN)
 
VOID NtfsDumpFileAttributes (PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER FileRecord)
 
PSTANDARD_INFORMATION GetStandardInformationFromRecord (PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER FileRecord)
 
PFILENAME_ATTRIBUTE GetFileNameFromRecord (PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER FileRecord, UCHAR NameType)
 
UCHAR GetPackedByteCount (LONGLONG NumberToPack, BOOLEAN IsSigned)
 
NTSTATUS GetLastClusterInDataRun (PDEVICE_EXTENSION Vcb, PNTFS_ATTR_RECORD Attribute, PULONGLONG LastCluster)
 
PFILENAME_ATTRIBUTE GetBestFileNameFromRecord (PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER FileRecord)
 
NTSTATUS FindFirstAttributeListItem (PFIND_ATTR_CONTXT Context, PNTFS_ATTRIBUTE_LIST_ITEM *Item)
 
NTSTATUS FindNextAttributeListItem (PFIND_ATTR_CONTXT Context, PNTFS_ATTRIBUTE_LIST_ITEM *Item)
 
NTSTATUS FindFirstAttribute (PFIND_ATTR_CONTXT Context, PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER FileRecord, BOOLEAN OnlyResident, PNTFS_ATTR_RECORD *Attribute)
 
NTSTATUS FindNextAttribute (PFIND_ATTR_CONTXT Context, PNTFS_ATTR_RECORD *Attribute)
 
VOID FindCloseAttribute (PFIND_ATTR_CONTXT Context)
 
NTSTATUS FreeClusters (PNTFS_VCB Vcb, PNTFS_ATTR_CONTEXT AttrContext, ULONG AttrOffset, PFILE_RECORD_HEADER FileRecord, ULONG ClustersToFree)
 
VOID NtfsInitIoRunList (OUT PNTFS_IO_RUN_LIST RunList)
 
NTSTATUS NtfsAddIoRun (IN OUT PNTFS_IO_RUN_LIST RunList, IN LONGLONG Lbo, IN ULONG ByteCount)
 
VOID NtfsFreeIoRunList (IN OUT PNTFS_IO_RUN_LIST RunList)
 
NTSTATUS NtfsPerformIoRuns (IN PDEVICE_OBJECT DeviceObject, IN UCHAR MajorFunction, IN ULONG SectorSize, IN OUT PUCHAR Buffer, IN PNTFS_IO_RUN_LIST RunList, IN BOOLEAN Override, OUT PULONG BytesTransferred OPTIONAL)
 
NTSTATUS NtfsPerformIrpIoRuns (IN PDEVICE_OBJECT DeviceObject, IN UCHAR MajorFunction, IN ULONG SectorSize, IN PIRP Irp, IN OUT PUCHAR Buffer, IN PNTFS_IO_RUN_LIST RunList, IN BOOLEAN Override, OUT PULONG BytesTransferred)
 
NTSTATUS NtfsReadDisk (IN PDEVICE_OBJECT DeviceObject, IN LONGLONG StartingOffset, IN ULONG Length, IN ULONG SectorSize, IN OUT PUCHAR Buffer, IN BOOLEAN Override)
 
NTSTATUS NtfsWriteDisk (IN PDEVICE_OBJECT DeviceObject, IN LONGLONG StartingOffset, IN ULONG Length, IN ULONG SectorSize, IN const PUCHAR Buffer)
 
NTSTATUS NtfsFlushDevice (IN PDEVICE_OBJECT DeviceObject)
 
NTSTATUS NtfsReadSectors (IN PDEVICE_OBJECT DeviceObject, IN ULONG DiskSector, IN ULONG SectorCount, IN ULONG SectorSize, IN OUT PUCHAR Buffer, IN BOOLEAN Override)
 
NTSTATUS NtfsDeviceIoControl (IN PDEVICE_OBJECT DeviceObject, IN ULONG ControlCode, IN PVOID InputBuffer, IN ULONG InputBufferSize, IN OUT PVOID OutputBuffer, IN OUT PULONG OutputBufferSize, IN BOOLEAN Override)
 
LONG CompareTreeKeys (PB_TREE_KEY Key1, PB_TREE_KEY Key2, BOOLEAN CaseSensitive)
 
NTSTATUS CreateBTreeFromIndex (PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER FileRecordWithIndex, PNTFS_ATTR_CONTEXT IndexRootContext, PINDEX_ROOT_ATTRIBUTE IndexRoot, PB_TREE *NewTree)
 
NTSTATUS CreateIndexRootFromBTree (PDEVICE_EXTENSION DeviceExt, PB_TREE Tree, ULONG MaxIndexSize, PINDEX_ROOT_ATTRIBUTE *IndexRoot, ULONG *Length)
 
NTSTATUS DemoteBTreeRoot (PB_TREE Tree)
 
PB_TREE_KEY CreateBTreeKeyFromFilename (ULONGLONG FileReference, PFILENAME_ATTRIBUTE FileNameAttribute)
 
VOID DestroyBTree (PB_TREE Tree)
 
VOID DestroyBTreeKey (PB_TREE_KEY Key)
 
VOID DestroyBTreeNode (PB_TREE_FILENAME_NODE Node)
 
VOID DumpBTree (PB_TREE Tree)
 
VOID DumpBTreeKey (PB_TREE Tree, PB_TREE_KEY Key, ULONG Number, ULONG Depth)
 
VOID DumpBTreeNode (PB_TREE Tree, PB_TREE_FILENAME_NODE Node, ULONG Number, ULONG Depth)
 
NTSTATUS CreateEmptyBTree (PB_TREE *NewTree)
 
ULONGLONG GetAllocationOffsetFromVCN (PDEVICE_EXTENSION DeviceExt, ULONG IndexBufferSize, ULONGLONG Vcn)
 
ULONGLONG GetIndexEntryVCN (PINDEX_ENTRY_ATTRIBUTE IndexEntry)
 
ULONG GetSizeOfIndexEntries (PB_TREE_FILENAME_NODE Node)
 
NTSTATUS NtfsInsertKey (PB_TREE Tree, ULONGLONG FileReference, PFILENAME_ATTRIBUTE FileNameAttribute, PB_TREE_FILENAME_NODE Node, BOOLEAN CaseSensitive, ULONG MaxIndexRootSize, ULONG IndexRecordSize, PB_TREE_KEY *MedianKey, PB_TREE_FILENAME_NODE *NewRightHandSibling)
 
NTSTATUS NtfsRemoveKey (PB_TREE_FILENAME_NODE Node, PB_TREE_KEY SearchKey, BOOLEAN CaseSensitive)
 
NTSTATUS SplitBTreeNode (PB_TREE Tree, PB_TREE_FILENAME_NODE Node, PB_TREE_KEY *MedianKey, PB_TREE_FILENAME_NODE *NewRightHandSibling, BOOLEAN CaseSensitive)
 
NTSTATUS UpdateIndexAllocation (PDEVICE_EXTENSION DeviceExt, PB_TREE Tree, ULONG IndexBufferSize, PFILE_RECORD_HEADER FileRecord)
 
NTSTATUS UpdateIndexNode (PDEVICE_EXTENSION DeviceExt, PFILE_RECORD_HEADER FileRecord, PB_TREE_FILENAME_NODE Node, ULONG IndexBufferSize, PNTFS_ATTR_CONTEXT IndexAllocationContext, ULONG IndexAllocationOffset)
 
NTSTATUS NtfsCleanup (PNTFS_IRP_CONTEXT IrpContext)
 
NTSTATUS NtfsCloseFile (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject)
 
NTSTATUS NtfsClose (PNTFS_IRP_CONTEXT IrpContext)
 
NTSTATUS NtfsCreate (PNTFS_IRP_CONTEXT IrpContext)
 
NTSTATUS NtfsCreateDirectory (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, BOOLEAN CaseSensitive, BOOLEAN CanWait)
 
PFILE_RECORD_HEADER NtfsCreateEmptyFileRecord (PDEVICE_EXTENSION DeviceExt)
 
NTSTATUS NtfsCreateFileRecord (PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, BOOLEAN CaseSensitive, BOOLEAN CanWait)
 
NTSTATUS NtfsDeviceControl (PNTFS_IRP_CONTEXT IrpContext)
 
ULONGLONG NtfsGetFileSize (PDEVICE_EXTENSION DeviceExt, PFILE_RECORD_HEADER FileRecord, PCWSTR Stream, ULONG StreamLength, PULONGLONG AllocatedSize)
 
NTSTATUS NtfsDirectoryControl (PNTFS_IRP_CONTEXT IrpContext)
 
NTSTATUS NTAPI NtfsFsdDispatch (PDEVICE_OBJECT DeviceObject, PIRP Irp)
 
BOOLEAN NTAPI NtfsAcqLazyWrite (PVOID Context, BOOLEAN Wait)
 
VOID NTAPI NtfsRelLazyWrite (PVOID Context)
 
BOOLEAN NTAPI NtfsAcqReadAhead (PVOID Context, BOOLEAN Wait)
 
VOID NTAPI NtfsRelReadAhead (PVOID Context)
 
PNTFS_FCB NtfsCreateFCB (PCWSTR FileName, PCWSTR Stream, PNTFS_VCB Vcb)
 
VOID NtfsDestroyFCB (PNTFS_FCB Fcb)
 
BOOLEAN NtfsFCBIsDirectory (PNTFS_FCB Fcb)
 
BOOLEAN NTAPI NtfsIsRegularFileObject (_In_ PFILE_OBJECT FileObject)
 
BOOLEAN NtfsFCBIsReparsePoint (PNTFS_FCB Fcb)
 
BOOLEAN NtfsFCBIsCompressed (PNTFS_FCB Fcb)
 
BOOLEAN NtfsFCBIsEncrypted (PNTFS_FCB Fcb)
 
BOOLEAN NtfsFCBIsRoot (PNTFS_FCB Fcb)
 
VOID NtfsGrabFCB (PNTFS_VCB Vcb, PNTFS_FCB Fcb)
 
VOID NtfsReleaseFCB (PNTFS_VCB Vcb, PNTFS_FCB Fcb)
 
VOID NtfsAddFCBToTable (PNTFS_VCB Vcb, PNTFS_FCB Fcb)
 
VOID NtfsRemoveFCBFromTable (_In_ PNTFS_VCB Vcb, _In_ PNTFS_FCB Fcb)
 
PNTFS_FCB NtfsGrabFCBFromTable (PNTFS_VCB Vcb, PCWSTR FileName)
 
NTSTATUS NtfsFCBInitializeCache (PNTFS_VCB Vcb, PNTFS_FCB Fcb)
 
PNTFS_FCB NtfsMakeRootFCB (PNTFS_VCB Vcb)
 
PNTFS_FCB NtfsOpenRootFCB (PNTFS_VCB Vcb)
 
NTSTATUS NtfsAttachFCBToFileObject (PNTFS_VCB Vcb, PNTFS_FCB Fcb, PFILE_OBJECT FileObject)
 
NTSTATUS NtfsGetFCBForFile (PNTFS_VCB Vcb, PNTFS_FCB *pParentFCB, PNTFS_FCB *pFCB, PCWSTR pFileName, BOOLEAN CaseSensitive)
 
NTSTATUS NtfsReadFCBAttribute (PNTFS_VCB Vcb, PNTFS_FCB pFCB, ULONG Type, PCWSTR Name, ULONG NameLength, PVOID *Data)
 
NTSTATUS NtfsMakeFCBFromDirEntry (PNTFS_VCB Vcb, PNTFS_FCB DirectoryFCB, PUNICODE_STRING Name, PCWSTR Stream, PFILE_RECORD_HEADER Record, ULONGLONG MFTIndex, PNTFS_FCB *fileFCB)
 
NTSTATUS NtfsQueryInformation (PNTFS_IRP_CONTEXT IrpContext)
 
NTSTATUS NtfsSetEndOfFile (PNTFS_FCB Fcb, PFILE_OBJECT FileObject, PDEVICE_EXTENSION DeviceExt, ULONG IrpFlags, BOOLEAN CaseSensitive, PLARGE_INTEGER NewFileSize)
 
NTSTATUS NtfsSetInformation (PNTFS_IRP_CONTEXT IrpContext)
 
NTSTATUS NtfsFileSystemControl (PNTFS_IRP_CONTEXT IrpContext)
 
NTSTATUS NtfsFlushBuffers (PNTFS_IRP_CONTEXT IrpContext)
 
NTSTATUS NTAPI NtfsLockControl (_In_ PNTFS_IRP_CONTEXT IrpContext)
 
NTSTATUS NtfsAddFilenameToDirectory (PDEVICE_EXTENSION DeviceExt, ULONGLONG DirectoryMftIndex, ULONGLONG FileReferenceNumber, PFILENAME_ATTRIBUTE FilenameAttribute, BOOLEAN CaseSensitive)
 
NTSTATUS NtfsRemoveFilenameFromDirectory (PDEVICE_EXTENSION DeviceExt, ULONGLONG DirectoryMftIndex, PFILENAME_ATTRIBUTE FilenameAttribute, BOOLEAN CaseSensitive)
 
NTSTATUS FreeMftEntry (PDEVICE_EXTENSION DeviceExt, ULONGLONG MftIndex)
 
NTSTATUS NtfsDeleteFileRecord (PDEVICE_EXTENSION DeviceExt, ULONGLONG MftIndex, BOOLEAN CaseSensitive)
 
NTSTATUS AddNewMftEntry (PFILE_RECORD_HEADER FileRecord, PDEVICE_EXTENSION DeviceExt, PULONGLONG DestinationIndex, BOOLEAN CanWait)
 
VOID NtfsDumpData (ULONG_PTR Buffer, ULONG Length)
 
PNTFS_ATTR_CONTEXT PrepareAttributeContext (PNTFS_ATTR_RECORD AttrRecord)
 
VOID ReleaseAttributeContext (PNTFS_ATTR_CONTEXT Context)
 
ULONG ReadAttribute (PDEVICE_EXTENSION Vcb, PNTFS_ATTR_CONTEXT Context, ULONGLONG Offset, PCHAR Buffer, ULONG Length)
 
ULONG ReadAttributeToIrp (PDEVICE_EXTENSION Vcb, PNTFS_ATTR_CONTEXT Context, ULONGLONG Offset, PCHAR Buffer, ULONG Length, PIRP Irp)
 
NTSTATUS WriteAttribute (PDEVICE_EXTENSION Vcb, PNTFS_ATTR_CONTEXT Context, ULONGLONG Offset, const PUCHAR Buffer, ULONG Length, PULONG LengthWritten, PFILE_RECORD_HEADER FileRecord)
 
NTSTATUS WriteAttributeFromIrp (PDEVICE_EXTENSION Vcb, PNTFS_ATTR_CONTEXT Context, ULONGLONG Offset, const PUCHAR Buffer, ULONG Length, PULONG LengthWritten, PFILE_RECORD_HEADER FileRecord, PIRP Irp)
 
ULONGLONG AttributeDataLength (PNTFS_ATTR_RECORD AttrRecord)
 
NTSTATUS InternalSetResidentAttributeLength (PDEVICE_EXTENSION DeviceExt, PNTFS_ATTR_CONTEXT AttrContext, PFILE_RECORD_HEADER FileRecord, ULONG AttrOffset, ULONG DataSize)
 
PNTFS_ATTR_RECORD MoveAttributes (PDEVICE_EXTENSION DeviceExt, PNTFS_ATTR_RECORD FirstAttributeToMove, ULONG FirstAttributeOffset, ULONG_PTR MoveTo)
 
NTSTATUS SetAttributeDataLength (PFILE_OBJECT FileObject, PNTFS_FCB Fcb, PNTFS_ATTR_CONTEXT AttrContext, ULONG AttrOffset, PFILE_RECORD_HEADER FileRecord, PLARGE_INTEGER DataSize)
 
VOID SetFileRecordEnd (PFILE_RECORD_HEADER FileRecord, PNTFS_ATTR_RECORD AttrEnd, ULONG EndMarker)
 
NTSTATUS SetNonResidentAttributeDataLength (PDEVICE_EXTENSION Vcb, PNTFS_ATTR_CONTEXT AttrContext, ULONG AttrOffset, PFILE_RECORD_HEADER FileRecord, PLARGE_INTEGER DataSize)
 
NTSTATUS NtfsExtendAllocation (_In_ PDEVICE_EXTENSION Vcb, _In_ PNTFS_ATTR_CONTEXT AttrContext, _In_ ULONG AttrOffset, _In_ PFILE_RECORD_HEADER FileRecord, _In_ ULONGLONG AllocationSize)
 
NTSTATUS NtfsTrimAllocation (_In_ PNTFS_FCB Fcb)
 
NTSTATUS NtfsResizeAllocation (_In_ PNTFS_FCB Fcb, _In_ PFILE_OBJECT FileObject, _In_ BOOLEAN CaseSensitive, _In_ ULONGLONG AllocationSize)
 
NTSTATUS SetResidentAttributeDataLength (PDEVICE_EXTENSION Vcb, PNTFS_ATTR_CONTEXT AttrContext, ULONG AttrOffset, PFILE_RECORD_HEADER FileRecord, PLARGE_INTEGER DataSize)
 
ULONGLONG AttributeAllocatedLength (PNTFS_ATTR_RECORD AttrRecord)
 
BOOLEAN CompareFileName (PDEVICE_EXTENSION Vcb, PUNICODE_STRING FileName, PINDEX_ENTRY_ATTRIBUTE IndexEntry, BOOLEAN DirSearch, BOOLEAN CaseSensitive)
 
NTSTATUS UpdateMftMirror (PNTFS_VCB Vcb)
 
NTSTATUS NtfsLoadUpCaseTable (PDEVICE_EXTENSION Vcb)
 
NTSTATUS ReadFileRecord (PDEVICE_EXTENSION Vcb, ULONGLONG index, PFILE_RECORD_HEADER file)
 
NTSTATUS UpdateIndexEntryFileName (PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER MftRecord, PCHAR IndexRecord, ULONG IndexBlockSize, PINDEX_ENTRY_ATTRIBUTE FirstEntry, PINDEX_ENTRY_ATTRIBUTE LastEntry, PUNICODE_STRING FileName, PULONG StartEntry, PULONG CurrentEntry, BOOLEAN DirSearch, PNTFS_FILENAME_UPDATE Update, BOOLEAN CaseSensitive)
 
NTSTATUS NtfsUpdateDuplicatedInformation (PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER FileRecord, ULONGLONG MFTIndex, ULONG Flags, BOOLEAN CaseSensitive)
 
NTSTATUS UpdateFileNameRecord (PDEVICE_EXTENSION Vcb, ULONGLONG ParentMFTIndex, PUNICODE_STRING FileName, BOOLEAN DirSearch, PNTFS_FILENAME_UPDATE Update, BOOLEAN CaseSensitive)
 
NTSTATUS UpdateFileRecord (PDEVICE_EXTENSION Vcb, ULONGLONG MftIndex, PFILE_RECORD_HEADER FileRecord)
 
NTSTATUS FindAttribute (PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER MftRecord, ULONG Type, PCWSTR Name, ULONG NameLength, PNTFS_ATTR_CONTEXT *AttrCtx, PULONG Offset)
 
VOID ReadVCN (PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER file, ATTRIBUTE_TYPE type, ULONGLONG vcn, ULONG count, PVOID buffer)
 
NTSTATUS FixupUpdateSequenceArray (PDEVICE_EXTENSION Vcb, PNTFS_RECORD_HEADER Record)
 
NTSTATUS AddFixupArray (PDEVICE_EXTENSION Vcb, PNTFS_RECORD_HEADER Record)
 
NTSTATUS ReadLCN (PDEVICE_EXTENSION Vcb, ULONGLONG lcn, ULONG count, PVOID buffer)
 
VOID EnumerAttribute (PFILE_RECORD_HEADER file, PDEVICE_EXTENSION Vcb, PDEVICE_OBJECT DeviceObject)
 
NTSTATUS NtfsLookupFile (PDEVICE_EXTENSION Vcb, PUNICODE_STRING PathName, BOOLEAN CaseSensitive, PFILE_RECORD_HEADER *FileRecord, PULONGLONG MFTIndex)
 
NTSTATUS NtfsLookupFileAt (PDEVICE_EXTENSION Vcb, PUNICODE_STRING PathName, BOOLEAN CaseSensitive, PFILE_RECORD_HEADER *FileRecord, PULONGLONG MFTIndex, ULONGLONG CurrentMFTIndex)
 
VOID NtfsDumpFileRecord (PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER FileRecord)
 
NTSTATUS NtfsFindFileAt (PDEVICE_EXTENSION Vcb, PUNICODE_STRING SearchPattern, PULONG FirstEntry, PFILE_RECORD_HEADER *FileRecord, PULONGLONG MFTIndex, ULONGLONG CurrentMFTIndex, BOOLEAN CaseSensitive)
 
NTSTATUS NtfsIsDirectoryEmpty (_In_ PDEVICE_EXTENSION Vcb, _In_ ULONGLONG MftIndex, _Out_ PBOOLEAN Empty)
 
NTSTATUS NtfsFindMftRecord (PDEVICE_EXTENSION Vcb, ULONGLONG MFTIndex, PUNICODE_STRING FileName, PULONG FirstEntry, BOOLEAN DirSearch, BOOLEAN CaseSensitive, ULONGLONG *OutMFTIndex)
 
BOOLEAN NtfsIsIrpTopLevel (PIRP Irp)
 
PNTFS_IRP_CONTEXT NtfsAllocateIrpContext (PDEVICE_OBJECT DeviceObject, PIRP Irp)
 
PVOID NtfsGetUserBuffer (PIRP Irp, BOOLEAN Paging)
 
NTSTATUS NtfsLockUserBuffer (IN PIRP Irp, IN ULONG Length, IN LOCK_OPERATION Operation)
 
VOID NtfsFileFlagsToAttributes (ULONG NtfsAttributes, PULONG FileAttributes)
 
NTSTATUS NtfsRead (PNTFS_IRP_CONTEXT IrpContext)
 
NTSTATUS NtfsWrite (PNTFS_IRP_CONTEXT IrpContext)
 
NTSTATUS NtfsAllocateClusters (PDEVICE_EXTENSION DeviceExt, ULONG FirstDesiredCluster, ULONG DesiredClusters, PULONG FirstAssignedCluster, PULONG AssignedClusters)
 
ULONGLONG NtfsGetFreeClusters (PDEVICE_EXTENSION DeviceExt)
 
NTSTATUS NtfsLoadVolumeBitmap (_In_ PDEVICE_EXTENSION DeviceExt)
 
VOID NtfsFreeVolumeBitmap (_In_ PDEVICE_EXTENSION DeviceExt)
 
NTSTATUS NtfsWriteVolumeBitmap (_In_ PDEVICE_EXTENSION DeviceExt, _In_ ULONG FirstCluster, _In_ ULONG ClusterCount)
 
NTSTATUS NtfsQueryVolumeInformation (PNTFS_IRP_CONTEXT IrpContext)
 
NTSTATUS NtfsSetVolumeInformation (PNTFS_IRP_CONTEXT IrpContext)
 
VOID NTAPI NtfsInitializeFunctionPointers (PDRIVER_OBJECT DriverObject)
 

Variables

PNTFS_GLOBAL_DATA NtfsGlobalData
 
DRIVER_DISPATCH NtfsFsdDispatch
 
FAST_IO_CHECK_IF_POSSIBLE NtfsFastIoCheckIfPossible
 
FAST_IO_READ NtfsFastIoRead
 
FAST_IO_WRITE NtfsFastIoWrite
 
DRIVER_INITIALIZE DriverEntry
 

Macro Definition Documentation

◆ ATTR_RECORD_ALIGNMENT

#define ATTR_RECORD_ALIGNMENT   8

Definition at line 351 of file ntfs.h.

◆ CACHEPAGESIZE

#define CACHEPAGESIZE (   pDeviceExt)
Value:
((pDeviceExt)->NtfsInfo.UCHARsPerCluster > PAGE_SIZE ? \
(pDeviceExt)->NtfsInfo.UCHARsPerCluster : PAGE_SIZE)
#define PAGE_SIZE
Definition: env_spec_w32.h:49

Definition at line 8 of file ntfs.h.

◆ CCB_RETURNED_DOT

#define CCB_RETURNED_DOT   0x0001

Definition at line 167 of file ntfs.h.

◆ CCB_RETURNED_DOTDOT

#define CCB_RETURNED_DOTDOT   0x0002

Definition at line 168 of file ntfs.h.

◆ COLLATION_BINARY

#define COLLATION_BINARY   0x00

Definition at line 227 of file ntfs.h.

◆ COLLATION_FILE_NAME

#define COLLATION_FILE_NAME   0x01

Definition at line 228 of file ntfs.h.

◆ COLLATION_NTOFS_SECURITY_HASH

#define COLLATION_NTOFS_SECURITY_HASH   0x12

Definition at line 232 of file ntfs.h.

◆ COLLATION_NTOFS_SID

#define COLLATION_NTOFS_SID   0x11

Definition at line 231 of file ntfs.h.

◆ COLLATION_NTOFS_ULONG

#define COLLATION_NTOFS_ULONG   0x10

Definition at line 230 of file ntfs.h.

◆ COLLATION_NTOFS_ULONGS

#define COLLATION_NTOFS_ULONGS   0x13

Definition at line 233 of file ntfs.h.

◆ COLLATION_UNICODE_STRING

#define COLLATION_UNICODE_STRING   0x02

Definition at line 229 of file ntfs.h.

◆ DATA_RUN_ALIGNMENT

#define DATA_RUN_ALIGNMENT   4

Definition at line 354 of file ntfs.h.

◆ DEVICE_NAME

#define DEVICE_NAME   L"\\Ntfs"

Definition at line 23 of file ntfs.h.

◆ FCB_CACHE_INITIALIZED

#define FCB_CACHE_INITIALIZED   0x0001

Definition at line 583 of file ntfs.h.

◆ FCB_DELETE_PENDING

#define FCB_DELETE_PENDING   0x0008

Definition at line 586 of file ntfs.h.

◆ FCB_DELETED

#define FCB_DELETED   0x0010

Definition at line 587 of file ntfs.h.

◆ FCB_IS_VOLUME

#define FCB_IS_VOLUME   0x0004

Definition at line 585 of file ntfs.h.

◆ FCB_IS_VOLUME_STREAM

#define FCB_IS_VOLUME_STREAM   0x0002

Definition at line 584 of file ntfs.h.

◆ FILE_RECORD_END

#define FILE_RECORD_END   0x11477982

Definition at line 209 of file ntfs.h.

◆ FRH_DIRECTORY

#define FRH_DIRECTORY   0x0002 /* Record is a directory */

Definition at line 299 of file ntfs.h.

◆ FRH_IN_USE

#define FRH_IN_USE   0x0001 /* Record is in use */

Definition at line 298 of file ntfs.h.

◆ FRH_UNKNOWN1

#define FRH_UNKNOWN1   0x0004 /* Don't know */

Definition at line 300 of file ntfs.h.

◆ FRH_UNKNOWN2

#define FRH_UNKNOWN2   0x0008 /* Don't know */

Definition at line 301 of file ntfs.h.

◆ INDEX_NODE_LARGE

#define INDEX_NODE_LARGE   0x1

Definition at line 239 of file ntfs.h.

◆ INDEX_NODE_SMALL

#define INDEX_NODE_SMALL   0x0

Definition at line 238 of file ntfs.h.

◆ INDEX_ROOT_LARGE

#define INDEX_ROOT_LARGE   0x1

Definition at line 236 of file ntfs.h.

◆ INDEX_ROOT_SMALL

#define INDEX_ROOT_SMALL   0x0

Definition at line 235 of file ntfs.h.

◆ IRPCONTEXT_CANWAIT

#define IRPCONTEXT_CANWAIT   0x1

Definition at line 505 of file ntfs.h.

◆ IRPCONTEXT_COMPLETE

#define IRPCONTEXT_COMPLETE   0x2

Definition at line 506 of file ntfs.h.

◆ IRPCONTEXT_QUEUE

#define IRPCONTEXT_QUEUE   0x4

Definition at line 507 of file ntfs.h.

◆ MAX_PATH

#define MAX_PATH   260

Definition at line 588 of file ntfs.h.

◆ NRH_FILE_TYPE

#define NRH_FILE_TYPE   0x454C4946 /* 'FILE' */

Definition at line 277 of file ntfs.h.

◆ NRH_INDX_TYPE

#define NRH_INDX_TYPE   0x58444E49 /* 'INDX' */

Definition at line 278 of file ntfs.h.

◆ NTFS_ATTR_COMPRESSION_MASK

#define NTFS_ATTR_COMPRESSION_MASK   0x00FF

Definition at line 262 of file ntfs.h.

◆ NTFS_ATTR_SPARSE

#define NTFS_ATTR_SPARSE   0x8000

Definition at line 263 of file ntfs.h.

◆ NTFS_FILE_ATTRDEF

#define NTFS_FILE_ATTRDEF   4

Definition at line 215 of file ntfs.h.

◆ NTFS_FILE_BADCLUS

#define NTFS_FILE_BADCLUS   8

Definition at line 219 of file ntfs.h.

◆ NTFS_FILE_BITMAP

#define NTFS_FILE_BITMAP   6

Definition at line 217 of file ntfs.h.

◆ NTFS_FILE_BOOT

#define NTFS_FILE_BOOT   7

Definition at line 218 of file ntfs.h.

◆ NTFS_FILE_EXTEND

#define NTFS_FILE_EXTEND   11

Definition at line 222 of file ntfs.h.

◆ NTFS_FILE_FIRST_USER_FILE

#define NTFS_FILE_FIRST_USER_FILE   16

Definition at line 223 of file ntfs.h.

◆ NTFS_FILE_LOGFILE

#define NTFS_FILE_LOGFILE   2

Definition at line 213 of file ntfs.h.

◆ NTFS_FILE_MFT

#define NTFS_FILE_MFT   0

Definition at line 211 of file ntfs.h.

◆ NTFS_FILE_MFTMIRR

#define NTFS_FILE_MFTMIRR   1

Definition at line 212 of file ntfs.h.

◆ NTFS_FILE_NAME_DOS

#define NTFS_FILE_NAME_DOS   2

Definition at line 246 of file ntfs.h.

◆ NTFS_FILE_NAME_POSIX

#define NTFS_FILE_NAME_POSIX   0

Definition at line 244 of file ntfs.h.

◆ NTFS_FILE_NAME_WIN32

#define NTFS_FILE_NAME_WIN32   1

Definition at line 245 of file ntfs.h.

◆ NTFS_FILE_NAME_WIN32_AND_DOS

#define NTFS_FILE_NAME_WIN32_AND_DOS   3

Definition at line 247 of file ntfs.h.

◆ NTFS_FILE_QUOTA

#define NTFS_FILE_QUOTA   9

Definition at line 220 of file ntfs.h.

◆ NTFS_FILE_ROOT

#define NTFS_FILE_ROOT   5

Definition at line 216 of file ntfs.h.

◆ NTFS_FILE_TYPE_ARCHIVE

#define NTFS_FILE_TYPE_ARCHIVE   0x20

Definition at line 252 of file ntfs.h.

◆ NTFS_FILE_TYPE_COMPRESSED

#define NTFS_FILE_TYPE_COMPRESSED   0x800

Definition at line 256 of file ntfs.h.

◆ NTFS_FILE_TYPE_DIRECTORY

#define NTFS_FILE_TYPE_DIRECTORY   0x10000000

Definition at line 259 of file ntfs.h.

◆ NTFS_FILE_TYPE_ENCRYPTED

#define NTFS_FILE_TYPE_ENCRYPTED   0x4000

Definition at line 258 of file ntfs.h.

◆ NTFS_FILE_TYPE_HIDDEN

#define NTFS_FILE_TYPE_HIDDEN   0x2

Definition at line 250 of file ntfs.h.

◆ NTFS_FILE_TYPE_OFFLINE

#define NTFS_FILE_TYPE_OFFLINE   0x1000

Definition at line 257 of file ntfs.h.

◆ NTFS_FILE_TYPE_READ_ONLY

#define NTFS_FILE_TYPE_READ_ONLY   0x1

Definition at line 249 of file ntfs.h.

◆ NTFS_FILE_TYPE_REPARSE

#define NTFS_FILE_TYPE_REPARSE   0x400

Definition at line 255 of file ntfs.h.

◆ NTFS_FILE_TYPE_SPARSE

#define NTFS_FILE_TYPE_SPARSE   0x200

Definition at line 254 of file ntfs.h.

◆ NTFS_FILE_TYPE_SYSTEM

#define NTFS_FILE_TYPE_SYSTEM   0x4

Definition at line 251 of file ntfs.h.

◆ NTFS_FILE_TYPE_TEMPORARY

#define NTFS_FILE_TYPE_TEMPORARY   0x100

Definition at line 253 of file ntfs.h.

◆ NTFS_FILE_UPCASE

#define NTFS_FILE_UPCASE   10

Definition at line 221 of file ntfs.h.

◆ NTFS_FILE_VOLUME

#define NTFS_FILE_VOLUME   3

Definition at line 214 of file ntfs.h.

◆ NTFS_FILENAME_UPDATE_ATTRS

#define NTFS_FILENAME_UPDATE_ATTRS   0x4

Definition at line 1334 of file ntfs.h.

◆ NTFS_FILENAME_UPDATE_SIZES

#define NTFS_FILENAME_UPDATE_SIZES   0x1

Definition at line 1332 of file ntfs.h.

◆ NTFS_FILENAME_UPDATE_TIMES

#define NTFS_FILENAME_UPDATE_TIMES   0x2

Definition at line 1333 of file ntfs.h.

◆ NTFS_INDEX_ENTRY_END

#define NTFS_INDEX_ENTRY_END   2

Definition at line 242 of file ntfs.h.

◆ NTFS_INDEX_ENTRY_NODE

#define NTFS_INDEX_ENTRY_NODE   1

Definition at line 241 of file ntfs.h.

◆ NTFS_MAX_IO_RUNS_ON_STACK

#define NTFS_MAX_IO_RUNS_ON_STACK   8

Definition at line 513 of file ntfs.h.

◆ NTFS_MFT_MASK

#define NTFS_MFT_MASK   0x0000FFFFFFFFFFFFULL

Definition at line 225 of file ntfs.h.

◆ NTFS_SPARSE_LBO

#define NTFS_SPARSE_LBO   ((LONGLONG)-1)

Definition at line 510 of file ntfs.h.

◆ NTFS_TYPE_CCB

#define NTFS_TYPE_CCB   '20SF'

Definition at line 88 of file ntfs.h.

◆ NTFS_TYPE_FCB

#define NTFS_TYPE_FCB   '30SF'

Definition at line 89 of file ntfs.h.

◆ NTFS_TYPE_GLOBAL_DATA

#define NTFS_TYPE_GLOBAL_DATA   '70SF'

Definition at line 92 of file ntfs.h.

◆ NTFS_TYPE_IRP_CONTEXT

#define NTFS_TYPE_IRP_CONTEXT   '60SF'

Definition at line 91 of file ntfs.h.

◆ NTFS_TYPE_VCB

#define NTFS_TYPE_VCB   '50SF'

Definition at line 90 of file ntfs.h.

◆ RA_INDEXED

#define RA_INDEXED   0x01

Definition at line 266 of file ntfs.h.

◆ ROUND_DOWN

#define ROUND_DOWN (   N,
  S 
)    ((N) - ((N) % (S)))

Definition at line 21 of file ntfs.h.

◆ ROUND_UP

#define ROUND_UP (   N,
  S 
)    ((((N) + (S) - 1) / (S)) * (S))

Definition at line 20 of file ntfs.h.

◆ TAG_ATT_CTXT

#define TAG_ATT_CTXT   'aftN'

Definition at line 16 of file ntfs.h.

◆ TAG_CCB

#define TAG_CCB   'CftN'

Definition at line 13 of file ntfs.h.

◆ TAG_FCB

#define TAG_FCB   'FftN'

Definition at line 14 of file ntfs.h.

◆ TAG_FILE_REC

#define TAG_FILE_REC   'rftN'

Definition at line 17 of file ntfs.h.

◆ TAG_IO_RUNS

#define TAG_IO_RUNS   'RftN'

Definition at line 18 of file ntfs.h.

◆ TAG_IRP_CTXT

#define TAG_IRP_CTXT   'iftN'

Definition at line 15 of file ntfs.h.

◆ TAG_NTFS

#define TAG_NTFS   '0ftN'

Definition at line 12 of file ntfs.h.

◆ VALUE_OFFSET_ALIGNMENT

#define VALUE_OFFSET_ALIGNMENT   4

Definition at line 357 of file ntfs.h.

◆ VCB_VOLUME_DISMOUNTED

#define VCB_VOLUME_DISMOUNTED   0x0002

Definition at line 148 of file ntfs.h.

◆ VCB_VOLUME_LOCKED

#define VCB_VOLUME_LOCKED   0x0001

Definition at line 146 of file ntfs.h.

Typedef Documentation

◆ B_TREE_FILENAME_NODE

Definition at line 462 of file ntfs.h.

◆ B_TREE_KEY

◆ BIOS_PARAMETERS_BLOCK

◆ BOOT_SECTOR

◆ EXTENDED_BIOS_PARAMETERS_BLOCK

◆ FILE_RECORD_HEADER

◆ FIND_ATTR_CONTXT

◆ NTFS_ATTR_CONTEXT

◆ NTFS_FCB

typedef struct _FCB NTFS_FCB

◆ NTFS_FILENAME_UPDATE

◆ NTFS_INFO

◆ NTFS_IO_CONTEXT

◆ NTFS_IO_RUN

◆ NTFS_IO_RUN_LIST

◆ NTFS_VCB

◆ PATTRIBUTE_LIST

◆ PATTRIBUTE_TYPE

◆ PB_TREE

typedef struct B_TREE * PB_TREE

◆ PB_TREE_FILENAME_NODE

◆ PB_TREE_KEY

◆ PBIOS_PARAMETERS_BLOCK

◆ PBOOT_SECTOR

◆ PDEVICE_EXTENSION

◆ PEXTENDED_BIOS_PARAMETERS_BLOCK

◆ PFILE_RECORD_HEADER

◆ PFILENAME_ATTRIBUTE

◆ PFIND_ATTR_CONTXT

◆ PFIXUP_ARRAY

◆ PINDEX_BUFFER

◆ PINDEX_ENTRY_ATTRIBUTE

◆ PINDEX_HEADER_ATTRIBUTE

◆ PINDEX_ROOT_ATTRIBUTE

◆ PNTFS_ATTR_CONTEXT

◆ PNTFS_ATTR_RECORD

◆ PNTFS_ATTRIBUTE_LIST_ITEM

◆ PNTFS_CCB

◆ PNTFS_FCB

typedef struct _FCB * PNTFS_FCB

◆ PNTFS_FILENAME_UPDATE

◆ PNTFS_GLOBAL_DATA

◆ PNTFS_INFO

◆ PNTFS_IO_CONTEXT

◆ PNTFS_IO_RUN

◆ PNTFS_IO_RUN_LIST

◆ PNTFS_IRP_CONTEXT

◆ PNTFS_RECORD_HEADER

◆ PNTFS_VCB

◆ PNTFSIDENTIFIER

◆ PREPARSE_POINT_ATTRIBUTE

◆ PSTANDARD_INFORMATION

◆ PVOLINFO_ATTRIBUTE

Enumeration Type Documentation

◆ ATTRIBUTE_TYPE

Enumerator
AttributeStandardInformation 
AttributeAttributeList 
AttributeFileName 
AttributeObjectId 
AttributeSecurityDescriptor 
AttributeVolumeName 
AttributeVolumeInformation 
AttributeData 
AttributeIndexRoot 
AttributeIndexAllocation 
AttributeBitmap 
AttributeReparsePoint 
AttributeEAInformation 
AttributeEA 
AttributePropertySet 
AttributeLoggedUtilityStream 
AttributeEnd 
AttributeStandardInformation 
AttributeAttributeList 
AttributeFileName 
AttributeObjectId 
AttributeSecurityDescriptor 
AttributeVolumeName 
AttributeVolumeInformation 
AttributeData 
AttributeIndexRoot 
AttributeIndexAllocation 
AttributeBitmap 
AttributeReparsePoint 
AttributeEAInformation 
AttributeEA 
AttributePropertySet 
AttributeLoggedUtilityStream 
AttributeEnd 

Definition at line 186 of file ntfs.h.

187{
190 AttributeFileName = 0x30,
191 AttributeObjectId = 0x40,
193 AttributeVolumeName = 0x60,
195 AttributeData = 0x80,
196 AttributeIndexRoot = 0x90,
198 AttributeBitmap = 0xB0,
201 AttributeEA = 0xE0,
204 AttributeEnd = 0xFFFFFFFF
enum ATTRIBUTE_TYPE * PATTRIBUTE_TYPE
ATTRIBUTE_TYPE
Definition: ntfs.h:187
@ AttributeVolumeName
Definition: ntfs.h:193
@ AttributeEnd
Definition: ntfs.h:204
@ AttributeIndexRoot
Definition: ntfs.h:196
@ AttributePropertySet
Definition: ntfs.h:202
@ AttributeReparsePoint
Definition: ntfs.h:199
@ AttributeFileName
Definition: ntfs.h:190
@ AttributeEAInformation
Definition: ntfs.h:200
@ AttributeStandardInformation
Definition: ntfs.h:188
@ AttributeEA
Definition: ntfs.h:201
@ AttributeAttributeList
Definition: ntfs.h:189
@ AttributeVolumeInformation
Definition: ntfs.h:194
@ AttributeSecurityDescriptor
Definition: ntfs.h:192
@ AttributeIndexAllocation
Definition: ntfs.h:197
@ AttributeObjectId
Definition: ntfs.h:191
@ AttributeLoggedUtilityStream
Definition: ntfs.h:203
@ AttributeData
Definition: ntfs.h:195
@ AttributeBitmap
Definition: ntfs.h:198

Function Documentation

◆ AddBitmap()

NTSTATUS AddBitmap ( PNTFS_VCB  Vcb,
PFILE_RECORD_HEADER  FileRecord,
PNTFS_ATTR_RECORD  AttributeAddress,
PCWSTR  Name,
USHORT  NameLength 
)

Definition at line 76 of file attrib.c.

81{
82 ULONG AttributeLength;
83 // Calculate the header length
84 ULONG ResidentHeaderLength = FIELD_OFFSET(NTFS_ATTR_RECORD, Resident.Reserved) + sizeof(UCHAR);
85 ULONG FileRecordEnd = AttributeAddress->Length;
86 ULONG NameOffset;
87 ULONG ValueOffset;
88 // We'll start out with 8 bytes of bitmap data
90 ULONG BytesAvailable;
91
92 if (AttributeAddress->Type != AttributeEnd)
93 {
94 DPRINT1("FIXME: Can only add $BITMAP attribute to the end of a file record.\n");
96 }
97
98 NameOffset = ResidentHeaderLength;
99
100 // Calculate ValueOffset, which will be aligned to a 4-byte boundary
101 ValueOffset = ALIGN_UP_BY(NameOffset + (sizeof(WCHAR) * NameLength), VALUE_OFFSET_ALIGNMENT);
102
103 // Calculate length of attribute
104 AttributeLength = ValueOffset + ValueLength;
105 AttributeLength = ALIGN_UP_BY(AttributeLength, ATTR_RECORD_ALIGNMENT);
106
107 // Make sure the file record is large enough for the new attribute
108 BytesAvailable = Vcb->NtfsInfo.BytesPerFileRecord - FileRecord->BytesInUse;
109 if (BytesAvailable < AttributeLength)
110 {
111 DPRINT1("FIXME: Not enough room in file record for index allocation attribute!\n");
113 }
114
115 // Set Attribute fields
116 RtlZeroMemory(AttributeAddress, AttributeLength);
117
118 AttributeAddress->Type = AttributeBitmap;
119 AttributeAddress->Length = AttributeLength;
120 AttributeAddress->NameLength = NameLength;
121 AttributeAddress->NameOffset = NameOffset;
122 AttributeAddress->Instance = FileRecord->NextAttributeNumber++;
123
124 AttributeAddress->Resident.ValueLength = ValueLength;
125 AttributeAddress->Resident.ValueOffset = ValueOffset;
126
127 // Set the name
128 RtlCopyMemory((PCHAR)((ULONG_PTR)AttributeAddress + NameOffset), Name, NameLength * sizeof(WCHAR));
129
130 // move the attribute-end and file-record-end markers to the end of the file record
131 AttributeAddress = (PNTFS_ATTR_RECORD)((ULONG_PTR)AttributeAddress + AttributeAddress->Length);
132 SetFileRecordEnd(FileRecord, AttributeAddress, FileRecordEnd);
133
134 return STATUS_SUCCESS;
135}
#define ALIGN_UP_BY(size, align)
#define DPRINT1
Definition: precomp.h:8
struct NTFS_ATTR_RECORD * PNTFS_ATTR_RECORD
#define STATUS_NOT_IMPLEMENTED
Definition: d3dkmdt.h:42
@ Resident
Definition: data.h:23
LPWSTR Name
Definition: desk.c:124
#define VALUE_OFFSET_ALIGNMENT
Definition: ntfs.h:357
#define ATTR_RECORD_ALIGNMENT
Definition: ntfs.h:351
VOID SetFileRecordEnd(PFILE_RECORD_HEADER FileRecord, PNTFS_ATTR_RECORD AttrEnd, ULONG EndMarker)
Definition: mft.c:706
short WCHAR
Definition: pedump.c:58
#define Vcb
Definition: cdprocs.h:1415
#define STATUS_SUCCESS
Definition: shellext.h:65
struct NTFS_ATTR_RECORD::@170::@172 Resident
ULONG Length
Definition: ntfs.h:135
USHORT NameOffset
Definition: ntfs.h:138
USHORT Instance
Definition: ntfs.h:140
UCHAR NameLength
Definition: ntfs.h:137
ULONG Type
Definition: ntfs.h:134
USHORT NextAttributeNumber
Definition: ntfs.h:291
ULONG BytesInUse
Definition: ntfs.h:288
unsigned char UCHAR
Definition: typedefs.h:53
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint32_t ULONG
Definition: typedefs.h:59
char * PCHAR
Definition: typedefs.h:51
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _In_ ULONG ValueLength
Definition: wdfregistry.h:275

Referenced by DECLARE_INTERFACE_(), CFontsDialog::InitToolbar(), and UpdateIndexAllocation().

◆ AddData()

NTSTATUS AddData ( PFILE_RECORD_HEADER  FileRecord,
PNTFS_ATTR_RECORD  AttributeAddress 
)

Definition at line 164 of file attrib.c.

166{
167 ULONG ResidentHeaderLength = FIELD_OFFSET(NTFS_ATTR_RECORD, Resident.Reserved) + sizeof(UCHAR);
168 ULONG FileRecordEnd = AttributeAddress->Length;
169
170 if (AttributeAddress->Type != AttributeEnd)
171 {
172 DPRINT1("FIXME: Can only add $DATA attribute to the end of a file record.\n");
174 }
175
176 AttributeAddress->Type = AttributeData;
177 AttributeAddress->Length = ResidentHeaderLength;
178 AttributeAddress->Length = ALIGN_UP_BY(AttributeAddress->Length, ATTR_RECORD_ALIGNMENT);
179 AttributeAddress->Resident.ValueLength = 0;
180 AttributeAddress->Resident.ValueOffset = ResidentHeaderLength;
181
182 // for unnamed $DATA attributes, NameOffset equals header length
183 AttributeAddress->NameOffset = ResidentHeaderLength;
184 AttributeAddress->Instance = FileRecord->NextAttributeNumber++;
185
186 // move the attribute-end and file-record-end markers to the end of the file record
187 AttributeAddress = (PNTFS_ATTR_RECORD)((ULONG_PTR)AttributeAddress + AttributeAddress->Length);
188 SetFileRecordEnd(FileRecord, AttributeAddress, FileRecordEnd);
189
190 return STATUS_SUCCESS;
191}

Referenced by DECLARE_INTERFACE_(), and NtfsCreateFileRecord().

◆ AddFileName()

NTSTATUS AddFileName ( PFILE_RECORD_HEADER  FileRecord,
PNTFS_ATTR_RECORD  AttributeAddress,
PDEVICE_EXTENSION  DeviceExt,
PFILE_OBJECT  FileObject,
BOOLEAN  CaseSensitive,
PULONGLONG  ParentMftIndex 
)

Definition at line 234 of file attrib.c.

240{
241 ULONG ResidentHeaderLength = FIELD_OFFSET(NTFS_ATTR_RECORD, Resident.Reserved) + sizeof(UCHAR);
242 PFILENAME_ATTRIBUTE FileNameAttribute;
243 LARGE_INTEGER SystemTime;
244 ULONG FileRecordEnd = AttributeAddress->Length;
245 ULONGLONG CurrentMFTIndex = NTFS_FILE_ROOT;
246 UNICODE_STRING Current, Remaining, FilenameNoPath;
248 ULONG FirstEntry;
249
250 if (AttributeAddress->Type != AttributeEnd)
251 {
252 DPRINT1("FIXME: Can only add $FILE_NAME attribute to the end of a file record.\n");
254 }
255
256 AttributeAddress->Type = AttributeFileName;
257 AttributeAddress->Instance = FileRecord->NextAttributeNumber++;
258
259 FileNameAttribute = (PFILENAME_ATTRIBUTE)((LONG_PTR)AttributeAddress + ResidentHeaderLength);
260
261 // set timestamps
262 KeQuerySystemTime(&SystemTime);
263 FileNameAttribute->CreationTime = SystemTime.QuadPart;
264 FileNameAttribute->ChangeTime = SystemTime.QuadPart;
265 FileNameAttribute->LastWriteTime = SystemTime.QuadPart;
266 FileNameAttribute->LastAccessTime = SystemTime.QuadPart;
267
268 // Is this a directory?
269 if(FileRecord->Flags & FRH_DIRECTORY)
270 FileNameAttribute->FileAttributes = NTFS_FILE_TYPE_DIRECTORY;
271 else
272 FileNameAttribute->FileAttributes = NTFS_FILE_TYPE_ARCHIVE;
273
274 // we need to extract the filename from the path
275 DPRINT("Pathname: %wZ\n", &FileObject->FileName);
276
277 FsRtlDissectName(FileObject->FileName, &Current, &Remaining);
278
279 while (Remaining.Length != 0)
280 {
281 DPRINT("Current: %wZ\n", &Current);
282
283 FirstEntry = 0;
284 Status = NtfsFindMftRecord(DeviceExt,
285 CurrentMFTIndex,
286 &Current,
287 &FirstEntry,
288 FALSE,
289 CaseSensitive,
290 &CurrentMFTIndex);
291 if (!NT_SUCCESS(Status))
292 {
293 DPRINT1("Path component '%wZ' of '%wZ' not found (Status %lx)\n",
294 &Current, &FileObject->FileName, Status);
295 return Status;
296 }
297
298 FsRtlDissectName(Remaining, &Current, &Remaining);
299 }
300
301 /* Whatever is left over is the file's own name */
302 FilenameNoPath = Current;
303
304 DPRINT("MFT Index of parent: %I64u\n", CurrentMFTIndex);
305
306 // set reference to parent directory
307 FileNameAttribute->DirectoryFileReferenceNumber = CurrentMFTIndex;
308 *ParentMftIndex = CurrentMFTIndex;
309
310 DPRINT("SequenceNumber: 0x%02x\n", FileRecord->SequenceNumber);
311
312 // The highest 2 bytes should be the sequence number, unless the parent happens to be root
313 if (CurrentMFTIndex == NTFS_FILE_ROOT)
314 FileNameAttribute->DirectoryFileReferenceNumber |= (ULONGLONG)NTFS_FILE_ROOT << 48;
315 else
316 FileNameAttribute->DirectoryFileReferenceNumber |= (ULONGLONG)FileRecord->SequenceNumber << 48;
317
318 DPRINT("FileNameAttribute->DirectoryFileReferenceNumber: 0x%016I64x\n", FileNameAttribute->DirectoryFileReferenceNumber);
319
320 FileNameAttribute->NameLength = FilenameNoPath.Length / sizeof(WCHAR);
321 RtlCopyMemory(FileNameAttribute->Name, FilenameNoPath.Buffer, FilenameNoPath.Length);
322
323 // For now, we're emulating the way Windows behaves when 8.3 name generation is disabled
324 // TODO: add DOS Filename as needed
325 if (!CaseSensitive && RtlIsNameLegalDOS8Dot3(&FilenameNoPath, NULL, NULL))
326 FileNameAttribute->NameType = NTFS_FILE_NAME_WIN32_AND_DOS;
327 else
328 FileNameAttribute->NameType = NTFS_FILE_NAME_POSIX;
329
330 FileRecord->LinkCount++;
331
332 AttributeAddress->Length = ResidentHeaderLength +
333 FIELD_OFFSET(FILENAME_ATTRIBUTE, Name) + FilenameNoPath.Length;
334 AttributeAddress->Length = ALIGN_UP_BY(AttributeAddress->Length, ATTR_RECORD_ALIGNMENT);
335
336 AttributeAddress->Resident.ValueLength = FIELD_OFFSET(FILENAME_ATTRIBUTE, Name) + FilenameNoPath.Length;
337 AttributeAddress->Resident.ValueOffset = ResidentHeaderLength;
338 AttributeAddress->Resident.Flags = RA_INDEXED;
339
340 // move the attribute-end and file-record-end markers to the end of the file record
341 AttributeAddress = (PNTFS_ATTR_RECORD)((ULONG_PTR)AttributeAddress + AttributeAddress->Length);
342 SetFileRecordEnd(FileRecord, AttributeAddress, FileRecordEnd);
343
344 return Status;
345}
LONG NTSTATUS
Definition: precomp.h:26
#define NTFS_FILE_ROOT
Definition: ntfs.h:28
#define NTFS_FILE_NAME_POSIX
Definition: ntfs.h:63
#define NTFS_FILE_NAME_WIN32_AND_DOS
Definition: ntfs.h:66
static BOOLEAN NtfsFindMftRecord(_In_ PNTFS_VOLUME_INFO Volume, _In_ ULONGLONG MFTIndex, _In_ PCSTR FileName, _Out_ PULONGLONG OutMFTIndex, _Out_ PULONG FileAttributes)
Definition: ntfs.c:675
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
struct FILENAME_ATTRIBUTE * PFILENAME_ATTRIBUTE
#define FRH_DIRECTORY
Definition: ntfs.h:299
#define NTFS_FILE_TYPE_DIRECTORY
Definition: ntfs.h:259
#define NTFS_FILE_TYPE_ARCHIVE
Definition: ntfs.h:252
#define RA_INDEXED
Definition: ntfs.h:266
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
Status
Definition: gdiplustypes.h:24
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
VOID NTAPI FsRtlDissectName(IN UNICODE_STRING Name, OUT PUNICODE_STRING FirstPart, OUT PUNICODE_STRING RemainingPart)
Definition: name.c:147
BOOLEAN NTAPI RtlIsNameLegalDOS8Dot3(_In_ PUNICODE_STRING Name, _Inout_opt_ POEM_STRING OemName, _Inout_opt_ PBOOLEAN NameContainsSpaces)
#define DPRINT
Definition: sndvol32.h:73
ULONGLONG LastWriteTime
Definition: ntfs.h:393
UCHAR NameLength
Definition: ntfs.h:408
ULONGLONG DirectoryFileReferenceNumber
Definition: ntfs.h:391
UCHAR NameType
Definition: ntfs.h:409
ULONG FileAttributes
Definition: ntfs.h:398
ULONGLONG LastAccessTime
Definition: ntfs.h:395
ULONGLONG CreationTime
Definition: ntfs.h:392
WCHAR Name[1]
Definition: ntfs.h:410
ULONGLONG ChangeTime
Definition: ntfs.h:394
USHORT SequenceNumber
Definition: ntfs.h:284
USHORT Flags
Definition: ntfs.h:287
USHORT LinkCount
Definition: ntfs.h:285
uint64_t ULONGLONG
Definition: typedefs.h:67
LONGLONG QuadPart
Definition: typedefs.h:114
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550

Referenced by NtfsCreateDirectory(), and NtfsCreateFileRecord().

◆ AddFixupArray()

NTSTATUS AddFixupArray ( PDEVICE_EXTENSION  Vcb,
PNTFS_RECORD_HEADER  Record 
)

Definition at line 3575 of file mft.c.

3577{
3578 USHORT *pShortToFixUp;
3579 ULONG ArrayEntryCount = Record->UsaCount - 1;
3580 ULONG Offset = Vcb->NtfsInfo.BytesPerSector - 2;
3581 ULONG i;
3582
3583 PFIXUP_ARRAY fixupArray = (PFIXUP_ARRAY)((UCHAR*)Record + Record->UsaOffset);
3584
3585 DPRINT("AddFixupArray(%p, %p)\n fixupArray->USN: %u, ArrayEntryCount: %u\n", Vcb, Record, fixupArray->USN, ArrayEntryCount);
3586
3587 fixupArray->USN++;
3588
3589 for (i = 0; i < ArrayEntryCount; i++)
3590 {
3591 DPRINT("USN: %u\tOffset: %u\n", fixupArray->USN, Offset);
3592
3593 pShortToFixUp = (USHORT*)((PCHAR)Record + Offset);
3594 fixupArray->Array[i] = *pShortToFixUp;
3595 *pShortToFixUp = fixupArray->USN;
3596 Offset += Vcb->NtfsInfo.BytesPerSector;
3597 }
3598
3599 return STATUS_SUCCESS;
3600}
struct FIXUP_ARRAY * PFIXUP_ARRAY
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
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
unsigned short USHORT
Definition: pedump.c:61
USHORT Array[]
Definition: ntfs.h:645
USHORT USN
Definition: ntfs.h:644
_In_ struct _KBUGCHECK_REASON_CALLBACK_RECORD * Record
Definition: ketypes.h:320

Referenced by CreateIndexBufferFromBTreeNode(), UpdateFileRecord(), and UpdateIndexEntryFileName().

◆ AddIndexAllocation()

NTSTATUS AddIndexAllocation ( PNTFS_VCB  Vcb,
PFILE_RECORD_HEADER  FileRecord,
PNTFS_ATTR_RECORD  AttributeAddress,
PCWSTR  Name,
USHORT  NameLength 
)

Definition at line 380 of file attrib.c.

385{
386 ULONG RecordLength;
387 ULONG FileRecordEnd;
388 ULONG NameOffset;
389 ULONG DataRunOffset;
390 ULONG BytesAvailable;
391
392 if (AttributeAddress->Type != AttributeEnd)
393 {
394 DPRINT1("FIXME: Can only add $INDEX_ALLOCATION attribute to the end of a file record.\n");
396 }
397
398 // Calculate the name offset
399 NameOffset = FIELD_OFFSET(NTFS_ATTR_RECORD, NonResident.CompressedSize);
400
401 // Calculate the offset to the first data run
402 DataRunOffset = (sizeof(WCHAR) * NameLength) + NameOffset;
403 // The data run offset must be aligned to a 4-byte boundary
404 DataRunOffset = ALIGN_UP_BY(DataRunOffset, DATA_RUN_ALIGNMENT);
405
406 // Calculate the length of the new attribute; the empty data run will consist of a single byte
407 RecordLength = DataRunOffset + 1;
408
409 // The size of the attribute itself must be aligned to an 8 - byte boundary
410 RecordLength = ALIGN_UP_BY(RecordLength, ATTR_RECORD_ALIGNMENT);
411
412 // Back up the last 4-bytes of the file record (even though this value doesn't matter)
413 FileRecordEnd = AttributeAddress->Length;
414
415 // Make sure the file record can contain the new attribute
416 BytesAvailable = Vcb->NtfsInfo.BytesPerFileRecord - FileRecord->BytesInUse;
417 if (BytesAvailable < RecordLength)
418 {
419 DPRINT1("FIXME: Not enough room in file record for index allocation attribute!\n");
421 }
422
423 // Set fields of attribute header
424 RtlZeroMemory(AttributeAddress, RecordLength);
425
426 AttributeAddress->Type = AttributeIndexAllocation;
427 AttributeAddress->Length = RecordLength;
428 AttributeAddress->IsNonResident = TRUE;
429 AttributeAddress->NameLength = NameLength;
430 AttributeAddress->NameOffset = NameOffset;
431 AttributeAddress->Instance = FileRecord->NextAttributeNumber++;
432
433 AttributeAddress->NonResident.MappingPairsOffset = DataRunOffset;
434 AttributeAddress->NonResident.HighestVCN = (LONGLONG)-1;
435
436 // Set the name
437 RtlCopyMemory((PCHAR)((ULONG_PTR)AttributeAddress + NameOffset), Name, NameLength * sizeof(WCHAR));
438
439 // move the attribute-end and file-record-end markers to the end of the file record
440 AttributeAddress = (PNTFS_ATTR_RECORD)((ULONG_PTR)AttributeAddress + AttributeAddress->Length);
441 SetFileRecordEnd(FileRecord, AttributeAddress, FileRecordEnd);
442
443 return STATUS_SUCCESS;
444}
@ NonResident
Definition: data.h:24
#define TRUE
Definition: types.h:120
#define DATA_RUN_ALIGNMENT
Definition: ntfs.h:354
struct NTFS_ATTR_RECORD::@170::@173 NonResident
UCHAR IsNonResident
Definition: ntfs.h:136
int64_t LONGLONG
Definition: typedefs.h:68

Referenced by UpdateIndexAllocation().

◆ AddIndexRoot()

NTSTATUS AddIndexRoot ( PNTFS_VCB  Vcb,
PFILE_RECORD_HEADER  FileRecord,
PNTFS_ATTR_RECORD  AttributeAddress,
PINDEX_ROOT_ATTRIBUTE  NewIndexRoot,
ULONG  RootLength,
PCWSTR  Name,
USHORT  NameLength 
)

Definition at line 487 of file attrib.c.

494{
495 ULONG AttributeLength;
496 // Calculate the header length
497 ULONG ResidentHeaderLength = FIELD_OFFSET(NTFS_ATTR_RECORD, Resident.Reserved) + sizeof(UCHAR);
498 // Back up the file record's final ULONG (even though it doesn't matter)
499 ULONG FileRecordEnd = AttributeAddress->Length;
500 ULONG NameOffset;
501 ULONG ValueOffset;
502 ULONG BytesAvailable;
503
504 if (AttributeAddress->Type != AttributeEnd)
505 {
506 DPRINT1("FIXME: Can only add $DATA attribute to the end of a file record.\n");
508 }
509
510 NameOffset = ResidentHeaderLength;
511
512 // Calculate ValueOffset, which will be aligned to a 4-byte boundary
513 ValueOffset = ALIGN_UP_BY(NameOffset + (sizeof(WCHAR) * NameLength), VALUE_OFFSET_ALIGNMENT);
514
515 // Calculate length of attribute
516 AttributeLength = ValueOffset + RootLength;
517 AttributeLength = ALIGN_UP_BY(AttributeLength, ATTR_RECORD_ALIGNMENT);
518
519 // Make sure the file record is large enough for the new attribute
520 BytesAvailable = Vcb->NtfsInfo.BytesPerFileRecord - FileRecord->BytesInUse;
521 if (BytesAvailable < AttributeLength)
522 {
523 DPRINT1("FIXME: Not enough room in file record for index allocation attribute!\n");
525 }
526
527 // Set Attribute fields
528 RtlZeroMemory(AttributeAddress, AttributeLength);
529
530 AttributeAddress->Type = AttributeIndexRoot;
531 AttributeAddress->Length = AttributeLength;
532 AttributeAddress->NameLength = NameLength;
533 AttributeAddress->NameOffset = NameOffset;
534 AttributeAddress->Instance = FileRecord->NextAttributeNumber++;
535
536 AttributeAddress->Resident.ValueLength = RootLength;
537 AttributeAddress->Resident.ValueOffset = ValueOffset;
538
539 // Set the name
540 RtlCopyMemory((PCHAR)((ULONG_PTR)AttributeAddress + NameOffset), Name, NameLength * sizeof(WCHAR));
541
542 // Copy the index root attribute
543 RtlCopyMemory((PCHAR)((ULONG_PTR)AttributeAddress + ValueOffset), NewIndexRoot, RootLength);
544
545 // move the attribute-end and file-record-end markers to the end of the file record
546 AttributeAddress = (PNTFS_ATTR_RECORD)((ULONG_PTR)AttributeAddress + AttributeAddress->Length);
547 SetFileRecordEnd(FileRecord, AttributeAddress, FileRecordEnd);
548
549 return STATUS_SUCCESS;
550}

Referenced by NtfsCreateDirectory().

◆ AddNewMftEntry()

NTSTATUS AddNewMftEntry ( PFILE_RECORD_HEADER  FileRecord,
PDEVICE_EXTENSION  DeviceExt,
PULONGLONG  DestinationIndex,
BOOLEAN  CanWait 
)

Definition at line 2482 of file mft.c.

2486{
2488 ULONGLONG MftIndex;
2490 ULONGLONG BitmapDataSize;
2491 ULONGLONG AttrBytesRead;
2494 ULONG LengthWritten;
2495 PNTFS_ATTR_CONTEXT BitmapContext;
2496 LARGE_INTEGER BitmapBits;
2497 UCHAR SystemReservedBits;
2498
2499 DPRINT("AddNewMftEntry(%p, %p, %p, %s)\n", FileRecord, DeviceExt, DestinationIndex, CanWait ? "TRUE" : "FALSE");
2500
2501 // First, we have to read the mft's $Bitmap attribute
2502
2503 // Find the attribute
2504 Status = FindAttribute(DeviceExt, DeviceExt->MasterFileTable, AttributeBitmap, L"", 0, &BitmapContext, NULL);
2505 if (!NT_SUCCESS(Status))
2506 {
2507 DPRINT1("ERROR: Couldn't find $Bitmap attribute of master file table!\n");
2508 return Status;
2509 }
2510
2511 // Get size of bitmap
2512 BitmapDataSize = AttributeDataLength(BitmapContext->pRecord);
2513
2514 // RtlInitializeBitmap wants a ULONG-aligned pointer, and wants the memory passed to it to be a ULONG-multiple
2515 // Allocate a buffer for the $Bitmap attribute plus enough to ensure we can get a ULONG-aligned pointer
2516 BitmapBuffer = ExAllocatePoolWithTag(NonPagedPool, BitmapDataSize + sizeof(ULONG), TAG_NTFS);
2517 if (!BitmapBuffer)
2518 {
2519 ReleaseAttributeContext(BitmapContext);
2521 }
2522 RtlZeroMemory(BitmapBuffer, BitmapDataSize + sizeof(ULONG));
2523
2524 // Get a ULONG-aligned pointer for the bitmap itself
2526
2527 // read $Bitmap attribute
2528 AttrBytesRead = ReadAttribute(DeviceExt, BitmapContext, 0, (PCHAR)BitmapData, BitmapDataSize);
2529
2530 if (AttrBytesRead != BitmapDataSize)
2531 {
2532 DPRINT1("ERROR: Unable to read $Bitmap attribute of master file table!\n");
2534 ReleaseAttributeContext(BitmapContext);
2536 }
2537
2538 // We need to backup the bits for records 0x10 - 0x17 (3rd byte of bitmap) and mark these records
2539 // as in-use so we don't assign files to those indices. They're reserved for the system (e.g. ChkDsk).
2540 SystemReservedBits = BitmapData[2];
2541 BitmapData[2] = 0xff;
2542
2543 // Calculate bit count
2544 BitmapBits.QuadPart = AttributeDataLength(DeviceExt->MFTContext->pRecord) /
2545 DeviceExt->NtfsInfo.BytesPerFileRecord;
2546 if (BitmapBits.HighPart != 0)
2547 {
2548 DPRINT1("\tFIXME: bitmap sizes beyond 32bits are not yet supported! (Your NTFS volume is too large)\n");
2551 ReleaseAttributeContext(BitmapContext);
2553 }
2554
2555 // convert buffer into bitmap
2557
2558 // set next available bit, preferrably after 23rd bit
2559 MftIndex = RtlFindClearBitsAndSet(&Bitmap, 1, 24);
2560 if ((LONG)MftIndex == -1)
2561 {
2562 DPRINT1("Couldn't find free space in MFT for file record, increasing MFT size.\n");
2563
2565 ReleaseAttributeContext(BitmapContext);
2566
2567 // Couldn't find a free record in the MFT, add some blank records and try again
2568 Status = IncreaseMftSize(DeviceExt, CanWait);
2569 if (!NT_SUCCESS(Status))
2570 {
2571 DPRINT1("ERROR: Couldn't find space in MFT for file or increase MFT size!\n");
2572 return Status;
2573 }
2574
2575 return AddNewMftEntry(FileRecord, DeviceExt, DestinationIndex, CanWait);
2576 }
2577
2578 DPRINT("Creating file record at MFT index: %I64u\n", MftIndex);
2579
2580 // update file record with index
2581 FileRecord->MFTRecordNumber = MftIndex;
2582
2583 // [BitmapData should have been updated via RtlFindClearBitsAndSet()]
2584
2585 // Restore the system reserved bits
2586 BitmapData[2] = SystemReservedBits;
2587
2588 // write the bitmap back to the MFT's $Bitmap attribute
2589 Status = WriteAttribute(DeviceExt, BitmapContext, 0, BitmapData, BitmapDataSize, &LengthWritten, FileRecord);
2590 if (!NT_SUCCESS(Status))
2591 {
2592 DPRINT1("ERROR encountered when writing $Bitmap attribute!\n");
2594 ReleaseAttributeContext(BitmapContext);
2595 return Status;
2596 }
2597
2598 // update the file record (write it to disk)
2599 Status = UpdateFileRecord(DeviceExt, MftIndex, FileRecord);
2600
2601 if (!NT_SUCCESS(Status))
2602 {
2603 DPRINT1("ERROR: Unable to write file record!\n");
2605 ReleaseAttributeContext(BitmapContext);
2606 return Status;
2607 }
2608
2609 *DestinationIndex = MftIndex;
2610
2612 ReleaseAttributeContext(BitmapContext);
2613
2614 return Status;
2615}
#define RtlInitializeBitMap
Definition: dbgbitmap.h:326
#define RtlFindClearBitsAndSet
Definition: dbgbitmap.h:333
#define L(x)
Definition: resources.c:13
PNTFS_GLOBAL_DATA NtfsGlobalData
Definition: ntfs.c:36
#define TAG_NTFS
Definition: ntfs.h:12
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define NonPagedPool
Definition: env_spec_w32.h:307
static ULONG BitmapBuffer[(XMS_BLOCKS+31)/32]
Definition: himem.c:86
NTSTATUS UpdateFileRecord(PDEVICE_EXTENSION Vcb, ULONGLONG MftIndex, PFILE_RECORD_HEADER FileRecord)
Definition: mft.c:2391
VOID ReleaseAttributeContext(PNTFS_ATTR_CONTEXT Context)
Definition: mft.c:104
ULONGLONG AttributeDataLength(PNTFS_ATTR_RECORD AttrRecord)
Definition: mft.c:259
NTSTATUS FindAttribute(PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER MftRecord, ULONG Type, PCWSTR Name, ULONG NameLength, PNTFS_ATTR_CONTEXT *AttrCtx, PULONG Offset)
Definition: mft.c:131
ULONG ReadAttribute(PDEVICE_EXTENSION Vcb, PNTFS_ATTR_CONTEXT Context, ULONGLONG Offset, PCHAR Buffer, ULONG Length)
Definition: mft.c:1625
NTSTATUS WriteAttribute(PDEVICE_EXTENSION Vcb, PNTFS_ATTR_CONTEXT Context, ULONGLONG Offset, const PUCHAR Buffer, ULONG Length, PULONG RealLengthWritten, PFILE_RECORD_HEADER FileRecord)
Definition: mft.c:1829
NTSTATUS IncreaseMftSize(PDEVICE_EXTENSION Vcb, BOOLEAN CanWait)
Definition: mft.c:293
NTSTATUS AddNewMftEntry(PFILE_RECORD_HEADER FileRecord, PDEVICE_EXTENSION DeviceExt, PULONGLONG DestinationIndex, BOOLEAN CanWait)
Definition: mft.c:2482
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
long LONG
Definition: pedump.c:60
BOOLEAN EnableWriteSupport
Definition: ntfs.h:182
ULONG MFTRecordNumber
Definition: ntfs.h:293
uint32_t * PULONG
Definition: typedefs.h:59
unsigned char * PUCHAR
Definition: typedefs.h:53
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
ULONG LowPart
Definition: typedefs.h:106

Referenced by AddNewMftEntry(), NtfsCreateDirectory(), and NtfsCreateFileRecord().

◆ AddRun()

NTSTATUS AddRun ( PNTFS_VCB  Vcb,
PNTFS_ATTR_CONTEXT  AttrContext,
ULONG  AttrOffset,
PFILE_RECORD_HEADER  FileRecord,
ULONGLONG  NextAssignedCluster,
ULONG  RunLength 
)

Definition at line 591 of file attrib.c.

597{
599 int DataRunMaxLength;
600 PNTFS_ATTR_RECORD DestinationAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + AttrOffset);
601 ULONG NextAttributeOffset = AttrOffset + AttrContext->pRecord->Length;
602 ULONGLONG NextVBN = 0;
603 ULONGLONG HighestVcn;
604
605 PUCHAR RunBuffer;
606 ULONG RunBufferSize;
607
608 if (!AttrContext->pRecord->IsNonResident)
610
611 if (AttrContext->pRecord->NonResident.AllocatedSize != 0)
612 NextVBN = AttrContext->pRecord->NonResident.HighestVCN + 1;
613
614 /* The run goes on the end, so it holds the new last VCN */
615 HighestVcn = NextVBN + RunLength - 1;
616
617 // Add newly-assigned clusters to mcb
619 {
620 if (!FsRtlAddLargeMcbEntry(&AttrContext->DataRunsMCB,
621 NextVBN,
622 NextAssignedCluster,
623 RunLength))
624 {
626 }
627 }
629 {
630 DPRINT1("Failed to add LargeMcb Entry!\n");
632 }
633 _SEH2_END;
634
635 RunBuffer = ExAllocatePoolWithTag(NonPagedPool, Vcb->NtfsInfo.BytesPerFileRecord, TAG_NTFS);
636 if (!RunBuffer)
637 {
638 DPRINT1("ERROR: Couldn't allocate memory for data runs!\n");
640 }
641
642 // Convert the map control block back to encoded data runs.
643 Status = ConvertLargeMCBToDataRuns(&AttrContext->DataRunsMCB, HighestVcn + 1, RunBuffer, Vcb->NtfsInfo.BytesPerFileRecord, &RunBufferSize);
645 {
646 // Runs won't fit in a single record; migrating to an $ATTRIBUTE_LIST isn't supported yet.
647 DPRINT1("Data runs too large for one file record - $ATTRIBUTE_LIST needed (not implemented)\n");
648 ExFreePoolWithTag(RunBuffer, TAG_NTFS);
650 }
651 else if (!NT_SUCCESS(Status))
652 {
653 DPRINT1("ERROR: Failed to convert data runs! (Status %lx)\n", Status);
654 ExFreePoolWithTag(RunBuffer, TAG_NTFS);
655 return Status;
656 }
657
658 // Get the amount of free space between the start of the of the first data run and the attribute end
659 DataRunMaxLength = AttrContext->pRecord->Length - AttrContext->pRecord->NonResident.MappingPairsOffset;
660
661 // Do we need to extend the attribute (or convert to attribute list)?
662 if (DataRunMaxLength < RunBufferSize)
663 {
664 PNTFS_ATTR_RECORD NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + NextAttributeOffset);
665 PNTFS_ATTR_RECORD NewRecord;
666
667 // Add free space at the end of the file record to DataRunMaxLength
668 DataRunMaxLength += Vcb->NtfsInfo.BytesPerFileRecord - FileRecord->BytesInUse;
669
670 // Can we resize the attribute?
671 if (DataRunMaxLength < RunBufferSize)
672 {
673 DPRINT1("FIXME: Need to create attribute list! Max Data Run Length available: %d, RunBufferSize: %d\n", DataRunMaxLength, RunBufferSize);
674 ExFreePoolWithTag(RunBuffer, TAG_NTFS);
676 }
677
678 // Are there more attributes after the one we're resizing?
679 if (NextAttribute->Type != AttributeEnd)
680 {
681 PNTFS_ATTR_RECORD FinalAttribute;
682
683 // Calculate where to move the trailing attributes
684 ULONG_PTR MoveTo = (ULONG_PTR)DestinationAttribute + AttrContext->pRecord->NonResident.MappingPairsOffset + RunBufferSize;
685 MoveTo = ALIGN_UP_BY(MoveTo, ATTR_RECORD_ALIGNMENT);
686
687 DPRINT("Moving attribute(s) after this one starting with type 0x%lx\n", NextAttribute->Type);
688
689 // Move the trailing attributes; FinalAttribute will point to the end marker
690 FinalAttribute = MoveAttributes(Vcb, NextAttribute, NextAttributeOffset, MoveTo);
691
692 // set the file record end
693 SetFileRecordEnd(FileRecord, FinalAttribute, FILE_RECORD_END);
694 }
695
696 // calculate position of end markers
697 NextAttributeOffset = AttrOffset + AttrContext->pRecord->NonResident.MappingPairsOffset + RunBufferSize;
698 NextAttributeOffset = ALIGN_UP_BY(NextAttributeOffset, ATTR_RECORD_ALIGNMENT);
699
700 // Update the length of the destination attribute
701 DestinationAttribute->Length = NextAttributeOffset - AttrOffset;
702
703 // Create a new copy of the attribute record
704 NewRecord = ExAllocatePoolWithTag(NonPagedPool, DestinationAttribute->Length, TAG_NTFS);
705 RtlCopyMemory(NewRecord, AttrContext->pRecord, AttrContext->pRecord->Length);
706 NewRecord->Length = DestinationAttribute->Length;
707
708 // Free the old copy of the attribute record, which won't be large enough
709 ExFreePoolWithTag(AttrContext->pRecord, TAG_NTFS);
710
711 // Set the attribute context's record to the new copy
712 AttrContext->pRecord = NewRecord;
713
714 // if NextAttribute is the AttributeEnd marker
715 if (NextAttribute->Type == AttributeEnd)
716 {
717 // End the file record
718 NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + NextAttributeOffset);
719 SetFileRecordEnd(FileRecord, NextAttribute, FILE_RECORD_END);
720 }
721 }
722
723 // Update HighestVCN
724 DestinationAttribute->NonResident.HighestVCN =
725 AttrContext->pRecord->NonResident.HighestVCN = HighestVcn;
726
727 /* Sparse and compressed streams also count the clusters they really own */
728 if (AttrContext->pRecord->Flags & (NTFS_ATTR_COMPRESSION_MASK | NTFS_ATTR_SPARSE))
729 {
730 AttrContext->pRecord->NonResident.CompressedSize += (ULONGLONG)RunLength * Vcb->NtfsInfo.BytesPerCluster;
731 DestinationAttribute->NonResident.CompressedSize = AttrContext->pRecord->NonResident.CompressedSize;
732 }
733
734 // Write data runs to destination attribute
735 RtlCopyMemory((PVOID)((ULONG_PTR)DestinationAttribute + DestinationAttribute->NonResident.MappingPairsOffset),
736 RunBuffer,
737 RunBufferSize);
738
739 // Update the attribute record in the attribute context
740 RtlCopyMemory((PVOID)((ULONG_PTR)AttrContext->pRecord + AttrContext->pRecord->NonResident.MappingPairsOffset),
741 RunBuffer,
742 RunBufferSize);
743
744 // Update the file record
745 Status = UpdateFileRecord(Vcb, AttrContext->FileMFTIndex, FileRecord);
746
747 ExFreePoolWithTag(RunBuffer, TAG_NTFS);
748
749#if NTFS_DUMP_DATA_RUNS
750 NtfsDumpDataRuns((PUCHAR)((ULONG_PTR)DestinationAttribute + DestinationAttribute->NonResident.MappingPairsOffset), 0);
751#endif
752
753 return Status;
754}
NTSTATUS ConvertLargeMCBToDataRuns(PLARGE_MCB DataRunsMCB, ULONGLONG VcnCount, PUCHAR RunBuffer, ULONG MaxBufferSize, PULONG UsedBufferSize)
Definition: attrib.c:917
VOID NtfsDumpDataRuns(PVOID StartOfRun, ULONGLONG CurrentLCN)
Definition: attrib.c:1785
#define FILE_RECORD_END
Definition: ntfs.h:209
#define NTFS_ATTR_SPARSE
Definition: ntfs.h:263
#define NTFS_ATTR_COMPRESSION_MASK
Definition: ntfs.h:262
#define ULONG_PTR
Definition: config.h:101
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
BOOLEAN NTAPI FsRtlAddLargeMcbEntry(IN PLARGE_MCB Mcb, IN LONGLONG Vbn, IN LONGLONG Lbn, IN LONGLONG SectorCount)
Definition: largemcb.c:288
PNTFS_ATTR_RECORD MoveAttributes(PDEVICE_EXTENSION DeviceExt, PNTFS_ATTR_RECORD FirstAttributeToMove, ULONG FirstAttributeOffset, ULONG_PTR MoveTo)
Definition: mft.c:512
#define ExRaiseStatus
Definition: ntoskrnl.h:114
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:204
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:104
#define _SEH2_END
Definition: pseh2_64.h:194
#define _SEH2_TRY
Definition: pseh2_64.h:93
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:207
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132

Referenced by NtfsExtendAllocation().

◆ AddStandardInformation()

NTSTATUS AddStandardInformation ( PFILE_RECORD_HEADER  FileRecord,
PNTFS_ATTR_RECORD  AttributeAddress 
)

Definition at line 783 of file attrib.c.

785{
786 ULONG ResidentHeaderLength = FIELD_OFFSET(NTFS_ATTR_RECORD, Resident.Reserved) + sizeof(UCHAR);
787 PSTANDARD_INFORMATION StandardInfo = (PSTANDARD_INFORMATION)((LONG_PTR)AttributeAddress + ResidentHeaderLength);
788 LARGE_INTEGER SystemTime;
789 ULONG FileRecordEnd = AttributeAddress->Length;
790
791 if (AttributeAddress->Type != AttributeEnd)
792 {
793 DPRINT1("FIXME: Can only add $STANDARD_INFORMATION attribute to the end of a file record.\n");
795 }
796
797 AttributeAddress->Type = AttributeStandardInformation;
798 AttributeAddress->Length = sizeof(STANDARD_INFORMATION) + ResidentHeaderLength;
799 AttributeAddress->Length = ALIGN_UP_BY(AttributeAddress->Length, ATTR_RECORD_ALIGNMENT);
800 AttributeAddress->Resident.ValueLength = sizeof(STANDARD_INFORMATION);
801 AttributeAddress->Resident.ValueOffset = ResidentHeaderLength;
802 AttributeAddress->Instance = FileRecord->NextAttributeNumber++;
803
804 // set dates and times
805 KeQuerySystemTime(&SystemTime);
806 StandardInfo->CreationTime = SystemTime.QuadPart;
807 StandardInfo->ChangeTime = SystemTime.QuadPart;
808 StandardInfo->LastWriteTime = SystemTime.QuadPart;
809 StandardInfo->LastAccessTime = SystemTime.QuadPart;
811
812 // move the attribute-end and file-record-end markers to the end of the file record
813 AttributeAddress = (PNTFS_ATTR_RECORD)((ULONG_PTR)AttributeAddress + AttributeAddress->Length);
814 SetFileRecordEnd(FileRecord, AttributeAddress, FileRecordEnd);
815
816 return STATUS_SUCCESS;
817}
struct STANDARD_INFORMATION * PSTANDARD_INFORMATION
ULONGLONG LastAccessTime
Definition: ntfs.h:364
ULONGLONG ChangeTime
Definition: ntfs.h:363
ULONGLONG LastWriteTime
Definition: ntfs.h:362
ULONG FileAttribute
Definition: ntfs.h:365
ULONGLONG CreationTime
Definition: ntfs.h:361

Referenced by NtfsCreateDirectory(), and NtfsCreateFileRecord().

◆ AttributeAllocatedLength()

ULONGLONG AttributeAllocatedLength ( PNTFS_ATTR_RECORD  AttrRecord)

Definition at line 249 of file mft.c.

250{
251 if (AttrRecord->IsNonResident)
252 return AttrRecord->NonResident.AllocatedSize;
253 else
254 return ALIGN_UP_BY(AttrRecord->Resident.ValueLength, ATTR_RECORD_ALIGNMENT);
255}

Referenced by NtfsGetFileSize(), NtfsGetStreamInformation(), and NtfsReadFile().

◆ AttributeDataLength()

◆ CompareFileName()

BOOLEAN CompareFileName ( PDEVICE_EXTENSION  Vcb,
PUNICODE_STRING  FileName,
PINDEX_ENTRY_ATTRIBUTE  IndexEntry,
BOOLEAN  DirSearch,
BOOLEAN  CaseSensitive 
)

Definition at line 3622 of file mft.c.

3627{
3628 BOOLEAN Ret, Alloc = FALSE;
3629 UNICODE_STRING EntryName;
3630
3631 EntryName.Buffer = IndexEntry->FileName.Name;
3632 EntryName.Length =
3633 EntryName.MaximumLength = IndexEntry->FileName.NameLength * sizeof(WCHAR);
3634
3635 if (DirSearch)
3636 {
3637 UNICODE_STRING IntFileName;
3638 if (!CaseSensitive)
3639 {
3641 Alloc = TRUE;
3642 }
3643 else
3644 {
3645 IntFileName = *FileName;
3646 }
3647
3648 /* With a real upcase table the matcher folds both sides through it,
3649 * which is what NTFS means by case-insensitive. */
3650 Ret = FsRtlIsNameInExpression(&IntFileName, &EntryName, !CaseSensitive,
3651 Vcb ? Vcb->UpCaseTable : NULL);
3652
3653 if (Alloc)
3654 {
3655 RtlFreeUnicodeString(&IntFileName);
3656 }
3657
3658 return Ret;
3659 }
3660 else
3661 {
3662 return (RtlCompareUnicodeString(FileName, &EntryName, !CaseSensitive) == 0);
3663 }
3664}
unsigned char BOOLEAN
Definition: actypes.h:127
PVOID Alloc(IN DWORD dwFlags, IN SIZE_T dwBytes)
Definition: main.c:63
ULONG RtlCompareUnicodeString(PUNICODE_STRING s1, PUNICODE_STRING s2, BOOLEAN UpCase)
Definition: string_lib.cpp:31
NTSTATUS RtlUpcaseUnicodeString(PUNICODE_STRING dst, PUNICODE_STRING src, BOOLEAN Alloc)
Definition: string_lib.cpp:46
struct _FileName FileName
Definition: fatprocs.h:897
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
FILENAME_ATTRIBUTE FileName
Definition: ntfs.h:458
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define NT_VERIFY(exp)
Definition: rtlfuncs.h:3311

Referenced by BrowseIndexEntries(), BrowseSubNodeIndexEntries(), and UpdateIndexEntryFileName().

◆ CompareTreeKeys()

LONG CompareTreeKeys ( PB_TREE_KEY  Key1,
PB_TREE_KEY  Key2,
BOOLEAN  CaseSensitive 
)

Definition at line 422 of file btree.c.

423{
424 UNICODE_STRING Key1Name, Key2Name;
425 LONG Comparison;
426
427 // Key1 must not be the final key (AKA the dummy key)
429
430 // If Key2 is the "dummy key", key 1 will always come first
431 if (Key2->NextKey == NULL)
432 return -1;
433
434 Key1Name.Buffer = Key1->IndexEntry->FileName.Name;
435 Key1Name.Length = Key1Name.MaximumLength
436 = Key1->IndexEntry->FileName.NameLength * sizeof(WCHAR);
437
438 Key2Name.Buffer = Key2->IndexEntry->FileName.Name;
439 Key2Name.Length = Key2Name.MaximumLength
440 = Key2->IndexEntry->FileName.NameLength * sizeof(WCHAR);
441
442 // Are the two keys the same length?
443 if (Key1Name.Length == Key2Name.Length)
444 return RtlCompareUnicodeString(&Key1Name, &Key2Name, !CaseSensitive);
445
446 // Is Key1 shorter?
447 if (Key1Name.Length < Key2Name.Length)
448 {
449 // Truncate KeyName2 to be the same length as KeyName1
450 Key2Name.Length = Key1Name.Length;
451
452 // Compare the names of the same length
453 Comparison = RtlCompareUnicodeString(&Key1Name, &Key2Name, !CaseSensitive);
454
455 // If the truncated names are the same length, the shorter one comes first
456 if (Comparison == 0)
457 return -1;
458 }
459 else
460 {
461 // Key2 is shorter
462 // Truncate KeyName1 to be the same length as KeyName2
463 Key1Name.Length = Key2Name.Length;
464
465 // Compare the names of the same length
466 Comparison = RtlCompareUnicodeString(&Key1Name, &Key2Name, !CaseSensitive);
467
468 // If the truncated names are the same length, the shorter one comes first
469 if (Comparison == 0)
470 return 1;
471 }
472
473 return Comparison;
474}
#define NTFS_INDEX_ENTRY_END
Definition: ntfs.h:61
#define ASSERT(a)
Definition: mode.c:44
USHORT Flags
Definition: ntfs.h:456
struct _B_TREE_KEY * NextKey
Definition: ntfs.h:467
PINDEX_ENTRY_ATTRIBUTE IndexEntry
Definition: ntfs.h:469

Referenced by NtfsInsertKey(), and NtfsRemoveKey().

◆ ConvertDataRunsToLargeMCB()

NTSTATUS ConvertDataRunsToLargeMCB ( PUCHAR  DataRun,
PLARGE_MCB  DataRunsMCB,
PULONGLONG  pNextVBN 
)

Definition at line 842 of file attrib.c.

845{
846 LONGLONG DataRunOffset;
847 ULONGLONG DataRunLength;
848 LONGLONG DataRunStartLCN;
849 ULONGLONG LastLCN = 0;
850
851 // Initialize the MCB, potentially catch an exception
852 _SEH2_TRY{
856 } _SEH2_END;
857
858 while (*DataRun != 0)
859 {
860 DataRun = DecodeRun(DataRun, &DataRunOffset, &DataRunLength);
861
862 if (DataRunOffset != -1)
863 {
864 // Normal data run.
865 DataRunStartLCN = LastLCN + DataRunOffset;
866 LastLCN = DataRunStartLCN;
867
868 _SEH2_TRY{
869 if (!FsRtlAddLargeMcbEntry(DataRunsMCB,
870 *pNextVBN,
871 DataRunStartLCN,
872 DataRunLength))
873 {
875 }
877 FsRtlUninitializeLargeMcb(DataRunsMCB);
879 } _SEH2_END;
880
881 }
882
883 *pNextVBN += DataRunLength;
884 }
885
886 return STATUS_SUCCESS;
887}
PUCHAR DecodeRun(PUCHAR DataRun, LONGLONG *DataRunOffset, ULONGLONG *DataRunLength)
Definition: attrib.c:1010
VOID NTAPI FsRtlUninitializeLargeMcb(IN PLARGE_MCB Mcb)
Definition: largemcb.c:1096
VOID NTAPI FsRtlInitializeLargeMcb(IN PLARGE_MCB Mcb, IN POOL_TYPE PoolType)
Definition: largemcb.c:451

Referenced by PrepareAttributeContext().

◆ ConvertLargeMCBToDataRuns()

NTSTATUS ConvertLargeMCBToDataRuns ( PLARGE_MCB  DataRunsMCB,
ULONGLONG  VcnCount,
PUCHAR  RunBuffer,
ULONG  MaxBufferSize,
PULONG  UsedBufferSize 
)

Definition at line 917 of file attrib.c.

922{
924 ULONG RunBufferOffset = 0;
925 LONGLONG DataRunOffset = 0;
926 ULONGLONG LastLCN = 0;
927 ULONGLONG NextVcn = 0;
929 ULONG i;
930 BOOLEAN Tail = FALSE;
931
932
933 DPRINT("\t[Vbn, Lbn, Count]\n");
934
935 // convert each mcb entry to a data run, then the trailing hole if there is one
936 for (i = 0; ; i++)
937 {
938 UCHAR DataRunOffsetSize = 0;
939 UCHAR DataRunLengthSize = 0;
940 UCHAR ControlByte = 0;
941
942 if (!FsRtlGetNextLargeMcbEntry(DataRunsMCB, i, &Vbn, &Lbn, &Count))
943 {
944 if (NextVcn >= VcnCount)
945 break;
946
947 /* The MCB only knows mapped clusters, so a hole at the end isn't in it */
948 Vbn = NextVcn;
949 Lbn = -1;
950 Count = VcnCount - NextVcn;
951 Tail = TRUE;
952 }
953
954 // [vbn, lbn, count]
955 DPRINT("\t[%I64d, %I64d,%I64d]\n", Vbn, Lbn, Count);
956
957 // determine how to represent DataRunLengthSize with the minimum number of bytes
958 DPRINT("Determining how many bytes needed to represent %I64x\n", Count);
959 DataRunLengthSize = GetPackedByteCount(Count, TRUE);
960 DPRINT("%d bytes needed.\n", DataRunLengthSize);
961
962 /* A sparse run has no offset, and the next real run is relative to the last real one */
963 if (Lbn != -1)
964 {
965 DataRunOffset = Lbn - LastLCN;
966 LastLCN = Lbn;
967
968 // now we need to determine how to represent DataRunOffset with the minimum number of bytes
969 DPRINT("Determining how many bytes needed to represent %I64x\n", DataRunOffset);
970 DataRunOffsetSize = GetPackedByteCount(DataRunOffset, TRUE);
971 DPRINT("%d bytes needed.\n", DataRunOffsetSize);
972 }
973
974 // ensure the next data run + end marker would be <= Max buffer size
975 if (RunBufferOffset + 2 + DataRunLengthSize + DataRunOffsetSize > MaxBufferSize)
976 {
978 DPRINT1("FIXME: Ran out of room in buffer for data runs!\n");
979 break;
980 }
981
982 // pack and copy the control byte
983 ControlByte = (DataRunOffsetSize << 4) + DataRunLengthSize;
984 RunBuffer[RunBufferOffset++] = ControlByte;
985
986 // copy DataRunLength
987 RtlCopyMemory(RunBuffer + RunBufferOffset, &Count, DataRunLengthSize);
988 RunBufferOffset += DataRunLengthSize;
989
990 // copy DataRunOffset
991 RtlCopyMemory(RunBuffer + RunBufferOffset, &DataRunOffset, DataRunOffsetSize);
992 RunBufferOffset += DataRunOffsetSize;
993
994 NextVcn = Vbn + Count;
995
996 if (Tail)
997 break;
998 }
999
1000 // End of data runs
1001 RunBuffer[RunBufferOffset++] = 0;
1002
1003 *UsedBufferSize = RunBufferOffset;
1004 DPRINT("New Size of DataRuns: %ld\n", *UsedBufferSize);
1005
1006 return Status;
1007}
UCHAR GetPackedByteCount(LONGLONG NumberToPack, BOOLEAN IsSigned)
Definition: attrib.c:1876
_In_ LONGLONG Vbn
Definition: fsrtlfuncs.h:470
_Must_inspect_result_ _In_ LONGLONG _In_ LONGLONG Lbn
Definition: fsrtlfuncs.h:480
BOOLEAN NTAPI FsRtlGetNextLargeMcbEntry(IN PLARGE_MCB Mcb, IN ULONG RunIndex, OUT PLONGLONG Vbn, OUT PLONGLONG Lbn, OUT PLONGLONG SectorCount)
Definition: largemcb.c:392
int Count
Definition: noreturn.cpp:7

Referenced by AddRun(), FreeClusters(), and NtfsMapAttributeRuns().

◆ CreateBTreeFromIndex()

NTSTATUS CreateBTreeFromIndex ( PDEVICE_EXTENSION  Vcb,
PFILE_RECORD_HEADER  FileRecordWithIndex,
PNTFS_ATTR_CONTEXT  IndexRootContext,
PINDEX_ROOT_ATTRIBUTE  IndexRoot,
PB_TREE *  NewTree 
)

Definition at line 687 of file btree.c.

693{
694 PINDEX_ENTRY_ATTRIBUTE CurrentNodeEntry;
698 ULONG CurrentOffset = IndexRoot->Header.FirstEntryOffset;
699 PNTFS_ATTR_CONTEXT IndexAllocationContext = NULL;
701
702 DPRINT("CreateBTreeFromIndex(%p, %p)\n", IndexRoot, NewTree);
703
704 if (!Tree || !RootNode || !CurrentKey)
705 {
706 DPRINT1("Couldn't allocate enough memory for B-Tree!\n");
707 if (Tree)
709 if (CurrentKey)
710 ExFreePoolWithTag(CurrentKey, TAG_NTFS);
711 if (RootNode)
714 }
715
716 RtlZeroMemory(Tree, sizeof(B_TREE));
718 RtlZeroMemory(CurrentKey, sizeof(B_TREE_KEY));
719
720 // See if the file record has an attribute allocation
722 FileRecordWithIndex,
724 L"$I30",
725 4,
726 &IndexAllocationContext,
727 NULL);
728 if (!NT_SUCCESS(Status))
729 IndexAllocationContext = NULL;
730
731 // Setup the Tree
732 RootNode->FirstKey = CurrentKey;
733 Tree->RootNode = RootNode;
734
735 // Make sure we won't try reading past the attribute-end
736 if (FIELD_OFFSET(INDEX_ROOT_ATTRIBUTE, Header) + IndexRoot->Header.TotalSizeOfEntries > IndexRootContext->pRecord->Resident.ValueLength)
737 {
738 DPRINT1("Filesystem corruption detected!\n");
741 goto Cleanup;
742 }
743
744 // Start at the first node entry
745 CurrentNodeEntry = (PINDEX_ENTRY_ATTRIBUTE)((ULONG_PTR)IndexRoot
747 + IndexRoot->Header.FirstEntryOffset);
748
749 // Create a key for each entry in the node
750 while (CurrentOffset < IndexRoot->Header.TotalSizeOfEntries)
751 {
752 // Allocate memory for the current entry
753 CurrentKey->IndexEntry = ExAllocatePoolWithTag(NonPagedPool, CurrentNodeEntry->Length, TAG_NTFS);
754 if (!CurrentKey->IndexEntry)
755 {
756 DPRINT1("ERROR: Couldn't allocate memory for next key!\n");
759 goto Cleanup;
760 }
761
762 RootNode->KeyCount++;
763
764 // If this isn't the last entry
765 if (!(CurrentNodeEntry->Flags & NTFS_INDEX_ENTRY_END))
766 {
767 // Create the next key
769 if (!NextKey)
770 {
771 DPRINT1("ERROR: Couldn't allocate memory for next key!\n");
774 goto Cleanup;
775 }
776
777 RtlZeroMemory(NextKey, sizeof(B_TREE_KEY));
778
779 // Add NextKey to the end of the list
780 CurrentKey->NextKey = NextKey;
781
782 // Copy the current entry to its key
783 RtlCopyMemory(CurrentKey->IndexEntry, CurrentNodeEntry, CurrentNodeEntry->Length);
784
785 // Does this key have a sub-node?
786 if (CurrentKey->IndexEntry->Flags & NTFS_INDEX_ENTRY_NODE)
787 {
788 // Create the child node
790 IndexRoot,
791 IndexAllocationContext,
792 CurrentKey->IndexEntry);
793 if (!CurrentKey->LesserChild)
794 {
795 DPRINT1("ERROR: Couldn't create child node!\n");
798 goto Cleanup;
799 }
800 }
801
802 // Advance to the next entry
803 CurrentOffset += CurrentNodeEntry->Length;
804 CurrentNodeEntry = (PINDEX_ENTRY_ATTRIBUTE)((ULONG_PTR)CurrentNodeEntry + CurrentNodeEntry->Length);
805 CurrentKey = NextKey;
806 }
807 else
808 {
809 // Copy the final entry to its key
810 RtlCopyMemory(CurrentKey->IndexEntry, CurrentNodeEntry, CurrentNodeEntry->Length);
811 CurrentKey->NextKey = NULL;
812
813 // Does this key have a sub-node?
814 if (CurrentKey->IndexEntry->Flags & NTFS_INDEX_ENTRY_NODE)
815 {
816 // Create the child node
818 IndexRoot,
819 IndexAllocationContext,
820 CurrentKey->IndexEntry);
821 if (!CurrentKey->LesserChild)
822 {
823 DPRINT1("ERROR: Couldn't create child node!\n");
826 goto Cleanup;
827 }
828 }
829
830 break;
831 }
832 }
833
834 *NewTree = Tree;
836
837Cleanup:
838 if (IndexAllocationContext)
839 ReleaseAttributeContext(IndexAllocationContext);
840
841 return Status;
842}
CRegistryTree Tree
#define NTFS_INDEX_ENTRY_NODE
Definition: ntfs.h:60
PB_TREE_FILENAME_NODE CreateBTreeNodeFromIndexNode(PDEVICE_EXTENSION Vcb, PINDEX_ROOT_ATTRIBUTE IndexRoot, PNTFS_ATTR_CONTEXT IndexAllocationAttributeCtx, PINDEX_ENTRY_ATTRIBUTE NodeEntry)
Definition: btree.c:504
VOID DestroyBTree(PB_TREE Tree)
Definition: btree.c:1549
Definition: Header.h:9
static const WCHAR Cleanup[]
Definition: register.c:80
struct INDEX_ENTRY_ATTRIBUTE * PINDEX_ENTRY_ATTRIBUTE
PCONFIGURATION_COMPONENT_DATA RootNode
Definition: macharm.c:19
Definition: ntfs.h:485
Definition: ntfs.h:440
USHORT Length
Definition: ntfs.h:454
ULONG FirstEntryOffset
Definition: ntfs.h:415
ULONG TotalSizeOfEntries
Definition: ntfs.h:416
INDEX_HEADER_ATTRIBUTE Header
Definition: ntfs.h:429
B_TREE_FILENAME_NODE * LesserChild
Definition: ntfs.h:468
#define STATUS_FILE_CORRUPT_ERROR
Definition: udferr_usr.h:168

Referenced by AddFilenameToDirectoryWorker(), and RemoveFilenameFromDirectoryWorker().

◆ CreateBTreeKeyFromFilename()

PB_TREE_KEY CreateBTreeKeyFromFilename ( ULONGLONG  FileReference,
PFILENAME_ATTRIBUTE  FileNameAttribute 
)

Definition at line 1466 of file btree.c.

1467{
1468 PB_TREE_KEY NewKey;
1469 ULONG AttributeSize = GetFileNameAttributeLength(FileNameAttribute);
1471
1472 // Create a new Index Entry for the file
1474 if (!NewEntry)
1475 {
1476 DPRINT1("ERROR: Failed to allocate memory for Index Entry!\n");
1477 return NULL;
1478 }
1479
1480 // Setup the Index Entry
1481 RtlZeroMemory(NewEntry, EntrySize);
1482 NewEntry->Data.Directory.IndexedFile = FileReference;
1483 NewEntry->Length = EntrySize;
1484 NewEntry->KeyLength = AttributeSize;
1485
1486 // Copy the FileNameAttribute
1487 RtlCopyMemory(&NewEntry->FileName, FileNameAttribute, AttributeSize);
1488
1489 // Setup the New Key
1491 if (!NewKey)
1492 {
1493 DPRINT1("ERROR: Failed to allocate memory for new key!\n");
1494 ExFreePoolWithTag(NewEntry, TAG_NTFS);
1495 return NULL;
1496 }
1497
1498 /* DestroyBTreeKey() follows LesserChild, it can't be left to pool garbage */
1499 RtlZeroMemory(NewKey, sizeof(*NewKey));
1500 NewKey->IndexEntry = NewEntry;
1501
1502 return NewKey;
1503}
ULONG GetFileNameAttributeLength(PFILENAME_ATTRIBUTE FileNameAttribute)
Definition: attrib.c:2008
union INDEX_ENTRY_ATTRIBUTE::@970 Data
struct INDEX_ENTRY_ATTRIBUTE::@970::@971 Directory
USHORT KeyLength
Definition: ntfs.h:455
_In_ UCHAR EntrySize
Definition: iofuncs.h:642

Referenced by NtfsInsertKey(), and RemoveFilenameFromDirectoryWorker().

◆ CreateEmptyBTree()

NTSTATUS CreateEmptyBTree ( PB_TREE *  NewTree)

Definition at line 353 of file btree.c.

354{
357 PB_TREE_KEY DummyKey;
358
359 DPRINT("CreateEmptyBTree(%p) called\n", NewTree);
360
361 if (!Tree || !RootNode)
362 {
363 DPRINT1("Couldn't allocate enough memory for B-Tree!\n");
364 if (Tree)
366 if (RootNode)
369 }
370
371 // Create the dummy key
372 DummyKey = CreateDummyKey(FALSE);
373 if (!DummyKey)
374 {
375 DPRINT1("ERROR: Failed to create dummy key!\n");
379 }
380
381 RtlZeroMemory(Tree, sizeof(B_TREE));
383
384 // Setup the Tree
385 RootNode->FirstKey = DummyKey;
386 RootNode->KeyCount = 1;
387 RootNode->DiskNeedsUpdating = TRUE;
388 Tree->RootNode = RootNode;
389
390 *NewTree = Tree;
391
392 // Memory will be freed when DestroyBTree() is called
393
394 return STATUS_SUCCESS;
395}
PB_TREE_KEY CreateDummyKey(BOOLEAN HasChildNode)
Definition: btree.c:294

Referenced by NtfsCreateDirectory().

◆ CreateIndexRootFromBTree()

NTSTATUS CreateIndexRootFromBTree ( PDEVICE_EXTENSION  DeviceExt,
PB_TREE  Tree,
ULONG  MaxIndexSize,
PINDEX_ROOT_ATTRIBUTE *  IndexRoot,
ULONG *  Length 
)

Definition at line 915 of file btree.c.

920{
921 ULONG i;
922 PB_TREE_KEY CurrentKey;
923 PINDEX_ENTRY_ATTRIBUTE CurrentNodeEntry;
925 DeviceExt->NtfsInfo.BytesPerFileRecord,
926 TAG_NTFS);
927
928 DPRINT("CreateIndexRootFromBTree(%p, %p, 0x%lx, %p, %p)\n", DeviceExt, Tree, MaxIndexSize, IndexRoot, Length);
929
930#ifndef NDEBUG
932#endif
933
934 if (!NewIndexRoot)
935 {
936 DPRINT1("Failed to allocate memory for Index Root!\n");
938 }
939
940 // Setup the new index root
941 RtlZeroMemory(NewIndexRoot, DeviceExt->NtfsInfo.BytesPerFileRecord);
942
943 NewIndexRoot->AttributeType = AttributeFileName;
944 NewIndexRoot->CollationRule = COLLATION_FILE_NAME;
945 NewIndexRoot->SizeOfEntry = DeviceExt->NtfsInfo.BytesPerIndexRecord;
946 // If Bytes per index record is less than cluster size, clusters per index record becomes sectors per index
947 if (NewIndexRoot->SizeOfEntry < DeviceExt->NtfsInfo.BytesPerCluster)
948 NewIndexRoot->ClustersPerIndexRecord = NewIndexRoot->SizeOfEntry / DeviceExt->NtfsInfo.BytesPerSector;
949 else
950 NewIndexRoot->ClustersPerIndexRecord = NewIndexRoot->SizeOfEntry / DeviceExt->NtfsInfo.BytesPerCluster;
951
952 // Setup the Index node header
953 NewIndexRoot->Header.FirstEntryOffset = sizeof(INDEX_HEADER_ATTRIBUTE);
954 NewIndexRoot->Header.Flags = INDEX_ROOT_SMALL;
955
956 // Start summing the total size of this node's entries
957 NewIndexRoot->Header.TotalSizeOfEntries = NewIndexRoot->Header.FirstEntryOffset;
958
959 // Setup each Node Entry
960 CurrentKey = Tree->RootNode->FirstKey;
961 CurrentNodeEntry = (PINDEX_ENTRY_ATTRIBUTE)((ULONG_PTR)NewIndexRoot
963 + NewIndexRoot->Header.FirstEntryOffset);
964 for (i = 0; i < Tree->RootNode->KeyCount; i++)
965 {
966 // Would adding the current entry to the index increase the index size beyond the limit we've set?
967 ULONG IndexSize = NewIndexRoot->Header.TotalSizeOfEntries - NewIndexRoot->Header.FirstEntryOffset + CurrentKey->IndexEntry->Length;
968 if (IndexSize > MaxIndexSize)
969 {
970 DPRINT1("TODO: Adding file would require creating an attribute list!\n");
971 ExFreePoolWithTag(NewIndexRoot, TAG_NTFS);
973 }
974
975 ASSERT(CurrentKey->IndexEntry->Length != 0);
976
977 // Copy the index entry
978 RtlCopyMemory(CurrentNodeEntry, CurrentKey->IndexEntry, CurrentKey->IndexEntry->Length);
979
980 DPRINT("Index Node Entry Stream Length: %u\nIndex Node Entry Length: %u\n",
981 CurrentNodeEntry->KeyLength,
982 CurrentNodeEntry->Length);
983
984 // Does the current key have any sub-nodes?
985 if (CurrentKey->LesserChild)
986 NewIndexRoot->Header.Flags = INDEX_ROOT_LARGE;
987
988 // Add Length of Current Entry to Total Size of Entries
989 NewIndexRoot->Header.TotalSizeOfEntries += CurrentKey->IndexEntry->Length;
990
991 // Go to the next node entry
992 CurrentNodeEntry = (PINDEX_ENTRY_ATTRIBUTE)((ULONG_PTR)CurrentNodeEntry + CurrentNodeEntry->Length);
993
994 CurrentKey = CurrentKey->NextKey;
995 }
996
997 NewIndexRoot->Header.AllocatedSize = NewIndexRoot->Header.TotalSizeOfEntries;
998
999 *IndexRoot = NewIndexRoot;
1001
1002 return STATUS_SUCCESS;
1003}
VOID DumpBTree(PB_TREE Tree)
Definition: btree.c:1629
#define INDEX_ROOT_SMALL
Definition: ntfs.h:235
#define COLLATION_FILE_NAME
Definition: ntfs.h:228
#define INDEX_ROOT_LARGE
Definition: ntfs.h:236
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
ULONG AttributeType
Definition: ntfs.h:424
ULONG CollationRule
Definition: ntfs.h:425
UCHAR ClustersPerIndexRecord
Definition: ntfs.h:427
ULONG SizeOfEntry
Definition: ntfs.h:426

Referenced by AddFilenameToDirectoryWorker(), NtfsCreateDirectory(), and RemoveFilenameFromDirectoryWorker().

◆ DecodeRun()

PUCHAR DecodeRun ( PUCHAR  DataRun,
LONGLONG *  DataRunOffset,
ULONGLONG *  DataRunLength 
)

Definition at line 1010 of file attrib.c.

1013{
1014 UCHAR DataRunOffsetSize;
1015 UCHAR DataRunLengthSize;
1016 CHAR i;
1017
1018 DataRunOffsetSize = (*DataRun >> 4) & 0xF;
1019 DataRunLengthSize = *DataRun & 0xF;
1020 *DataRunOffset = 0;
1021 *DataRunLength = 0;
1022 DataRun++;
1023 for (i = 0; i < DataRunLengthSize; i++)
1024 {
1025 *DataRunLength += ((ULONG64)*DataRun) << (i * 8);
1026 DataRun++;
1027 }
1028
1029 /* NTFS 3+ sparse files */
1030 if (DataRunOffsetSize == 0)
1031 {
1032 *DataRunOffset = -1;
1033 }
1034 else
1035 {
1036 for (i = 0; i < DataRunOffsetSize - 1; i++)
1037 {
1038 *DataRunOffset += ((ULONG64)*DataRun) << (i * 8);
1039 DataRun++;
1040 }
1041 /* The last byte contains sign so we must process it different way. */
1042 *DataRunOffset = ((LONG64)(CHAR)(*(DataRun++)) << (i * 8)) + *DataRunOffset;
1043 }
1044
1045 DPRINT("DataRunOffsetSize: %x\n", DataRunOffsetSize);
1046 DPRINT("DataRunLengthSize: %x\n", DataRunLengthSize);
1047 DPRINT("DataRunOffset: %x\n", *DataRunOffset);
1048 DPRINT("DataRunLength: %x\n", *DataRunLength);
1049
1050 return DataRun;
1051}
unsigned __int64 ULONG64
Definition: imports.h:198
char CHAR
Definition: pedump.c:57
int64_t LONG64
Definition: typedefs.h:68

Referenced by ConvertDataRunsToLargeMCB(), FindRun(), GetLastClusterInDataRun(), NtfsDumpDataRuns(), NtfsMapAttributeRuns(), PrepareAttributeContext(), and PrintAttributeInfo().

◆ DemoteBTreeRoot()

NTSTATUS DemoteBTreeRoot ( PB_TREE  Tree)

Definition at line 1094 of file btree.c.

1095{
1096 PB_TREE_FILENAME_NODE NewSubNode, NewIndexRoot;
1097 PB_TREE_KEY DummyKey;
1098
1099 DPRINT("Collapsing Index Root into sub-node.\n");
1100
1101#ifndef NDEBUG
1102 DumpBTree(Tree);
1103#endif
1104
1105 // Create a new node that will hold the keys currently in index root
1107 if (!NewSubNode)
1108 {
1109 DPRINT1("ERROR: Couldn't allocate memory for new sub-node.\n");
1111 }
1112 RtlZeroMemory(NewSubNode, sizeof(B_TREE_FILENAME_NODE));
1113
1114 // Copy the applicable data from the old index root node
1115 NewSubNode->KeyCount = Tree->RootNode->KeyCount;
1116 NewSubNode->FirstKey = Tree->RootNode->FirstKey;
1117 NewSubNode->DiskNeedsUpdating = TRUE;
1118
1119 // Create a new dummy key, and make the new node it's child
1120 DummyKey = CreateDummyKey(TRUE);
1121 if (!DummyKey)
1122 {
1123 DPRINT1("ERROR: Couldn't allocate memory for new root node.\n");
1124 ExFreePoolWithTag(NewSubNode, TAG_NTFS);
1126 }
1127
1128 // Make the new node a child of the dummy key
1129 DummyKey->LesserChild = NewSubNode;
1130
1131 // Create a new index root node
1133 if (!NewIndexRoot)
1134 {
1135 DPRINT1("ERROR: Couldn't allocate memory for new index root.\n");
1136 ExFreePoolWithTag(NewSubNode, TAG_NTFS);
1137 ExFreePoolWithTag(DummyKey, TAG_NTFS);
1139 }
1140 RtlZeroMemory(NewIndexRoot, sizeof(B_TREE_FILENAME_NODE));
1141
1142 NewIndexRoot->DiskNeedsUpdating = TRUE;
1143
1144 // Insert the dummy key into the new node
1145 NewIndexRoot->FirstKey = DummyKey;
1146 NewIndexRoot->KeyCount = 1;
1147 NewIndexRoot->DiskNeedsUpdating = TRUE;
1148
1149 // Make the new node the Tree's root node
1150 Tree->RootNode = NewIndexRoot;
1151
1152#ifndef NDEBUG
1153 DumpBTree(Tree);
1154#endif
1155
1156 return STATUS_SUCCESS;
1157}
BOOLEAN DiskNeedsUpdating
Definition: ntfs.h:479
PB_TREE_KEY FirstKey
Definition: ntfs.h:481

Referenced by AddFilenameToDirectoryWorker().

◆ DestroyBTree()

VOID DestroyBTree ( PB_TREE  Tree)

Definition at line 1549 of file btree.c.

1550{
1551 DestroyBTreeNode(Tree->RootNode);
1553}
VOID DestroyBTreeNode(PB_TREE_FILENAME_NODE Node)
Definition: btree.c:1518

Referenced by AddFilenameToDirectoryWorker(), CreateBTreeFromIndex(), NtfsCreateDirectory(), and RemoveFilenameFromDirectoryWorker().

◆ DestroyBTreeKey()

VOID DestroyBTreeKey ( PB_TREE_KEY  Key)

Definition at line 1506 of file btree.c.

1507{
1508 if (Key->IndexEntry)
1509 ExFreePoolWithTag(Key->IndexEntry, TAG_NTFS);
1510
1511 if (Key->LesserChild)
1512 DestroyBTreeNode(Key->LesserChild);
1513
1515}

Referenced by DestroyBTreeNode(), NtfsInsertKey(), RemoveFilenameFromDirectoryWorker(), and RemoveKeyFromNode().

◆ DestroyBTreeNode()

VOID DestroyBTreeNode ( PB_TREE_FILENAME_NODE  Node)

Definition at line 1518 of file btree.c.

1519{
1520 PB_TREE_KEY NextKey;
1521 PB_TREE_KEY CurrentKey = Node->FirstKey;
1522 ULONG i;
1523 for (i = 0; i < Node->KeyCount; i++)
1524 {
1525 NT_ASSERT(CurrentKey);
1526 NextKey = CurrentKey->NextKey;
1527 DestroyBTreeKey(CurrentKey);
1528 CurrentKey = NextKey;
1529 }
1530
1531 NT_ASSERT(NextKey == NULL);
1532
1534}
VOID DestroyBTreeKey(PB_TREE_KEY Key)
Definition: btree.c:1506
Definition: dlist.c:348
#define NT_ASSERT
Definition: rtlfuncs.h:3334

Referenced by CreateBTreeNodeFromIndexNode(), DestroyBTree(), and DestroyBTreeKey().

◆ DumpBTree()

VOID DumpBTree ( PB_TREE  Tree)

Definition at line 1629 of file btree.c.

1630{
1631 DbgPrint("B_TREE @ %p\n", Tree);
1632 DumpBTreeNode(Tree, Tree->RootNode, 0, 0);
1633}
VOID DumpBTreeNode(PB_TREE Tree, PB_TREE_FILENAME_NODE Node, ULONG Number, ULONG Depth)
Definition: btree.c:1590
#define DbgPrint
Definition: hal.h:12

Referenced by AddFilenameToDirectoryWorker(), CreateIndexRootFromBTree(), DemoteBTreeRoot(), NtfsInsertKey(), and UpdateIndexAllocation().

◆ DumpBTreeKey()

VOID DumpBTreeKey ( PB_TREE  Tree,
PB_TREE_KEY  Key,
ULONG  Number,
ULONG  Depth 
)

Definition at line 1556 of file btree.c.

1557{
1558 ULONG i;
1559 for (i = 0; i < Depth; i++)
1560 DbgPrint(" ");
1561 DbgPrint(" Key #%d", Number);
1562
1563 if (!(Key->IndexEntry->Flags & NTFS_INDEX_ENTRY_END))
1564 {
1566 FileName.Length = Key->IndexEntry->FileName.NameLength * sizeof(WCHAR);
1567 FileName.MaximumLength = FileName.Length;
1568 FileName.Buffer = Key->IndexEntry->FileName.Name;
1569 DbgPrint(" '%wZ'\n", &FileName);
1570 }
1571 else
1572 {
1573 DbgPrint(" (Dummy Key)\n");
1574 }
1575
1576 // Is there a child node?
1577 if (Key->IndexEntry->Flags & NTFS_INDEX_ENTRY_NODE)
1578 {
1579 if (Key->LesserChild)
1580 DumpBTreeNode(Tree, Key->LesserChild, Number, Depth + 1);
1581 else
1582 {
1583 // This will be an assert once nodes with arbitrary depth are debugged
1584 DPRINT1("DRIVER ERROR: No Key->LesserChild despite Key->IndexEntry->Flags indicating this is a node!\n");
1585 }
1586 }
1587}
UINT Depth
Definition: d3d12.idl:4644
_In_ ULONG Number
Definition: haltypes.h:1940

Referenced by DumpBTreeNode().

◆ DumpBTreeNode()

VOID DumpBTreeNode ( PB_TREE  Tree,
PB_TREE_FILENAME_NODE  Node,
ULONG  Number,
ULONG  Depth 
)

Definition at line 1590 of file btree.c.

1594{
1595 PB_TREE_KEY CurrentKey;
1596 ULONG i;
1597 for (i = 0; i < Depth; i++)
1598 DbgPrint(" ");
1599 DbgPrint("Node #%d, Depth %d, has %d key%s", Number, Depth, Node->KeyCount, Node->KeyCount == 1 ? "" : "s");
1600
1601 if (Node->HasValidVCN)
1602 DbgPrint(" VCN: %I64u\n", Node->VCN);
1603 else if (Tree->RootNode == Node)
1604 DbgPrint(" Index Root");
1605 else
1606 DbgPrint(" NOT ASSIGNED VCN YET\n");
1607
1608 CurrentKey = Node->FirstKey;
1609 for (i = 0; i < Node->KeyCount; i++)
1610 {
1611 DumpBTreeKey(Tree, CurrentKey, i, Depth);
1612 CurrentKey = CurrentKey->NextKey;
1613 }
1614}
VOID DumpBTreeKey(PB_TREE Tree, PB_TREE_KEY Key, ULONG Number, ULONG Depth)
Definition: btree.c:1556

Referenced by DumpBTree(), DumpBTreeKey(), and SplitBTreeNode().

◆ EnumerAttribute()

VOID EnumerAttribute ( PFILE_RECORD_HEADER  file,
PDEVICE_EXTENSION  Vcb,
PDEVICE_OBJECT  DeviceObject 
)

◆ FindAttribute()

NTSTATUS FindAttribute ( PDEVICE_EXTENSION  Vcb,
PFILE_RECORD_HEADER  MftRecord,
ULONG  Type,
PCWSTR  Name,
ULONG  NameLength,
PNTFS_ATTR_CONTEXT *  AttrCtx,
PULONG  Offset 
)

Definition at line 131 of file mft.c.

138{
142 PNTFS_ATTR_RECORD Attribute;
143 PNTFS_ATTRIBUTE_LIST_ITEM AttrListItem;
144
145 DPRINT("FindAttribute(%p, %p, 0x%x, %S, %lu, %p, %p)\n", Vcb, MftRecord, Type, Name, NameLength, AttrCtx, Offset);
146
147 Found = FALSE;
148 Status = FindFirstAttribute(&Context, Vcb, MftRecord, FALSE, &Attribute);
149 while (NT_SUCCESS(Status))
150 {
151 if (Attribute->Type == Type && Attribute->NameLength == NameLength)
152 {
153 if (NameLength != 0)
154 {
155 PWCHAR AttrName;
156
157 AttrName = (PWCHAR)((PCHAR)Attribute + Attribute->NameOffset);
158 DPRINT("%.*S, %.*S\n", Attribute->NameLength, AttrName, NameLength, Name);
159 if (RtlCompareMemory(AttrName, Name, NameLength * sizeof(WCHAR)) == (NameLength * sizeof(WCHAR)))
160 {
161 Found = TRUE;
162 }
163 }
164 else
165 {
166 Found = TRUE;
167 }
168
169 if (Found)
170 {
171 /* Found it, fill up the context and return. */
172 DPRINT("Found context\n");
173 *AttrCtx = PrepareAttributeContext(Attribute);
174
175 (*AttrCtx)->FileMFTIndex = MftRecord->MFTRecordNumber;
176
177 if (Offset != NULL)
178 *Offset = Context.Offset;
179
181 return STATUS_SUCCESS;
182 }
183 }
184
185 Status = FindNextAttribute(&Context, &Attribute);
186 }
187
188 /* No attribute found, check if it is referenced in another file record */
189 Status = FindFirstAttributeListItem(&Context, &AttrListItem);
190 while (NT_SUCCESS(Status))
191 {
192 if (AttrListItem->Type == Type && AttrListItem->NameLength == NameLength)
193 {
194 if (NameLength != 0)
195 {
196 PWCHAR AttrName;
197
198 AttrName = (PWCHAR)((PCHAR)AttrListItem + AttrListItem->NameOffset);
199 DPRINT("%.*S, %.*S\n", AttrListItem->NameLength, AttrName, NameLength, Name);
200 if (RtlCompareMemory(AttrName, Name, NameLength * sizeof(WCHAR)) == (NameLength * sizeof(WCHAR)))
201 {
202 Found = TRUE;
203 }
204 }
205 else
206 {
207 Found = TRUE;
208 }
209
210 if (Found == TRUE)
211 {
212 /* Get the MFT Index of attribute */
213 ULONGLONG MftIndex;
214 PFILE_RECORD_HEADER RemoteHdr;
215
216 MftIndex = AttrListItem->MFTIndex & NTFS_MFT_MASK;
217 RemoteHdr = ExAllocateFromNPagedLookasideList(&Vcb->FileRecLookasideList);
218
219 if (RemoteHdr == NULL)
220 {
223 }
224
225 /* Check we are not reading ourselves */
226 if (MftRecord->MFTRecordNumber == MftIndex)
227 {
228 DPRINT1("Attribute list references missing attribute to this file entry !");
229 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, RemoteHdr);
232 }
233 /* Read the new file record */
234 ReadFileRecord(Vcb, MftIndex, RemoteHdr);
235 Status = FindAttribute(Vcb, RemoteHdr, Type, Name, NameLength, AttrCtx, Offset);
236 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, RemoteHdr);
238 return Status;
239 }
240 }
241 Status = FindNextAttributeListItem(&Context, &AttrListItem);
242 }
245}
Type
Definition: Type.h:7
#define NTFS_MFT_MASK
Definition: ntfs.h:76
return Found
Definition: dirsup.c:1270
NTSTATUS FindFirstAttribute(PFIND_ATTR_CONTXT Context, PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER FileRecord, BOOLEAN OnlyResident, PNTFS_ATTR_RECORD *Attribute)
Definition: attrib.c:1413
NTSTATUS FindFirstAttributeListItem(PFIND_ATTR_CONTXT Context, PNTFS_ATTRIBUTE_LIST_ITEM *Item)
Definition: attrib.c:1337
VOID FindCloseAttribute(PFIND_ATTR_CONTXT Context)
Definition: attrib.c:1495
NTSTATUS FindNextAttribute(PFIND_ATTR_CONTXT Context, PNTFS_ATTR_RECORD *Attribute)
Definition: attrib.c:1461
NTSTATUS FindNextAttributeListItem(PFIND_ATTR_CONTXT Context, PNTFS_ATTRIBUTE_LIST_ITEM *Item)
Definition: attrib.c:1351
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
_In_ PIRP _In_ PIO_COMPLETION_ROUTINE _In_ PVOID Context
Definition: kse.h:81
NTSTATUS ReadFileRecord(PDEVICE_EXTENSION Vcb, ULONGLONG index, PFILE_RECORD_HEADER file)
Definition: mft.c:1936
PNTFS_ATTR_CONTEXT PrepareAttributeContext(PNTFS_ATTR_RECORD AttrRecord)
Definition: mft.c:41
ULONGLONG MFTIndex
Definition: ntfs.h:345
uint16_t * PWCHAR
Definition: typedefs.h:56

Referenced by AddFilenameToDirectoryWorker(), AddNewMftEntry(), AllocateIndexNode(), BrowseIndexEntries(), CreateBTreeFromIndex(), tinyxml2::XMLElement::FindAttribute(), FindAttribute(), FreeMftEntry(), IncreaseMftSize(), NtfsCreateFile(), NtfsDeleteFileRecord(), NtfsDirFindFile(), NtfsFindMftRecord(), NtfsGetFileSize(), NtfsGetVolumeData(), NtfsGrowFileForWrite(), NtfsIsDirectoryEmpty(), NtfsLoadVolumeBitmap(), NtfsReadFCBAttribute(), NtfsReadFile(), NtfsReadUpCaseTable(), NtfsResizeAllocation(), NtfsSetEndOfFile(), NtfsTrimAllocation(), NtfsWriteFile(), tinyxml2::XMLElement::QueryBoolAttribute(), tinyxml2::XMLElement::QueryDoubleAttribute(), tinyxml2::XMLElement::QueryFloatAttribute(), tinyxml2::XMLElement::QueryIntAttribute(), tinyxml2::XMLElement::QueryUnsignedAttribute(), RemoveFilenameFromDirectoryWorker(), UpdateFileNameRecordWorker(), UpdateIndexAllocation(), UpdateIndexEntryFileName(), UpdateMftMirror(), and WriteAttributeFromIrp().

◆ FindCloseAttribute()

VOID FindCloseAttribute ( PFIND_ATTR_CONTXT  Context)

Definition at line 1495 of file attrib.c.

1496{
1497 if (Context->NonResidentStart != NULL)
1498 {
1499 ExFreePoolWithTag(Context->NonResidentStart, TAG_NTFS);
1500 Context->NonResidentStart = NULL;
1501 }
1502}

Referenced by FindAttribute(), GetFileNameFromRecord(), GetNfsVolumeData(), GetStandardInformationFromRecord(), NtfsDumpFileAttributes(), NtfsGetStreamInformation(), NtfsReadFile(), and NtfsWriteFile().

◆ FindFirstAttribute()

NTSTATUS FindFirstAttribute ( PFIND_ATTR_CONTXT  Context,
PDEVICE_EXTENSION  Vcb,
PFILE_RECORD_HEADER  FileRecord,
BOOLEAN  OnlyResident,
PNTFS_ATTR_RECORD *  Attribute 
)

Definition at line 1413 of file attrib.c.

1418{
1420
1421 DPRINT("FindFistAttribute(%p, %p, %p, %p, %u, %p)\n", Context, Vcb, FileRecord, OnlyResident, Attribute);
1422
1423 Context->Vcb = Vcb;
1424 Context->OnlyResident = OnlyResident;
1425 Context->FirstAttr = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + FileRecord->AttributeOffset);
1426 Context->CurrAttr = Context->FirstAttr;
1427 Context->LastAttr = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + FileRecord->BytesInUse);
1428 Context->NonResidentStart = NULL;
1429 Context->NonResidentEnd = NULL;
1430 Context->Offset = FileRecord->AttributeOffset;
1431
1432 if (Context->FirstAttr->Type == AttributeEnd)
1433 {
1434 Context->CurrAttr = (PVOID)-1;
1435 return STATUS_END_OF_FILE;
1436 }
1437 else if (Context->FirstAttr->Type == AttributeAttributeList)
1438 {
1440 if (!NT_SUCCESS(Status))
1441 {
1442 return Status;
1443 }
1444
1445 *Attribute = InternalGetNextAttribute(Context);
1446 if (*Attribute == NULL)
1447 {
1448 return STATUS_END_OF_FILE;
1449 }
1450 }
1451 else
1452 {
1453 *Attribute = Context->CurrAttr;
1454 Context->Offset = (UCHAR*)Context->CurrAttr - (UCHAR*)FileRecord;
1455 }
1456
1457 return STATUS_SUCCESS;
1458}
static NTSTATUS InternalReadNonResidentAttributes(PFIND_ATTR_CONTXT Context)
Definition: attrib.c:1244
static PNTFS_ATTR_RECORD InternalGetNextAttribute(PFIND_ATTR_CONTXT Context)
Definition: attrib.c:1364
#define STATUS_END_OF_FILE
Definition: shellext.h:67
USHORT AttributeOffset
Definition: ntfs.h:286
void * PVOID
Definition: typedefs.h:50

Referenced by FindAttribute(), GetFileNameFromRecord(), GetNfsVolumeData(), GetStandardInformationFromRecord(), NtfsDumpFileAttributes(), NtfsGetStreamInformation(), NtfsReadFile(), and NtfsWriteFile().

◆ FindFirstAttributeListItem()

NTSTATUS FindFirstAttributeListItem ( PFIND_ATTR_CONTXT  Context,
PNTFS_ATTRIBUTE_LIST_ITEM *  Item 
)

Definition at line 1337 of file attrib.c.

1339{
1340 if (Context->NonResidentStart == NULL || Context->NonResidentStart->Type == AttributeEnd)
1341 {
1342 return STATUS_UNSUCCESSFUL;
1343 }
1344
1345 Context->NonResidentCur = Context->NonResidentStart;
1346 *Item = Context->NonResidentCur;
1347 return STATUS_SUCCESS;
1348}
_In_ WDFCOLLECTION _In_ WDFOBJECT Item

Referenced by FindAttribute().

◆ FindNextAttribute()

NTSTATUS FindNextAttribute ( PFIND_ATTR_CONTXT  Context,
PNTFS_ATTR_RECORD *  Attribute 
)

Definition at line 1461 of file attrib.c.

1463{
1465
1466 DPRINT("FindNextAttribute(%p, %p)\n", Context, Attribute);
1467
1468 *Attribute = InternalGetNextAttribute(Context);
1469 if (*Attribute == NULL)
1470 {
1471 return STATUS_END_OF_FILE;
1472 }
1473
1474 if (Context->CurrAttr->Type != AttributeAttributeList)
1475 {
1476 return STATUS_SUCCESS;
1477 }
1478
1480 if (!NT_SUCCESS(Status))
1481 {
1482 return Status;
1483 }
1484
1485 *Attribute = InternalGetNextAttribute(Context);
1486 if (*Attribute == NULL)
1487 {
1488 return STATUS_END_OF_FILE;
1489 }
1490
1491 return STATUS_SUCCESS;
1492}

Referenced by FindAttribute(), GetFileNameFromRecord(), GetNfsVolumeData(), GetStandardInformationFromRecord(), NtfsDumpFileAttributes(), NtfsGetStreamInformation(), NtfsReadFile(), and NtfsWriteFile().

◆ FindNextAttributeListItem()

NTSTATUS FindNextAttributeListItem ( PFIND_ATTR_CONTXT  Context,
PNTFS_ATTRIBUTE_LIST_ITEM *  Item 
)

Definition at line 1351 of file attrib.c.

1353{
1355 if (*Item == NULL)
1356 {
1357 return STATUS_UNSUCCESSFUL;
1358 }
1359 return STATUS_SUCCESS;
1360}
static PNTFS_ATTRIBUTE_LIST_ITEM InternalGetNextAttributeListItem(PFIND_ATTR_CONTXT Context)
Definition: attrib.c:1297

Referenced by FindAttribute().

◆ FixupUpdateSequenceArray()

NTSTATUS FixupUpdateSequenceArray ( PDEVICE_EXTENSION  Vcb,
PNTFS_RECORD_HEADER  Record 
)

Definition at line 2425 of file mft.c.

2427{
2428 USHORT *USA;
2429 USHORT USANumber;
2430 USHORT USACount;
2431 USHORT *Block;
2432
2433 USA = (USHORT*)((PCHAR)Record + Record->UsaOffset);
2434 USANumber = *(USA++);
2435 USACount = Record->UsaCount - 1; /* Exclude the USA Number. */
2436 Block = (USHORT*)((PCHAR)Record + Vcb->NtfsInfo.BytesPerSector - 2);
2437
2438 DPRINT("FixupUpdateSequenceArray(%p, %p)\nUSANumber: %u\tUSACount: %u\n", Vcb, Record, USANumber, USACount);
2439
2440 while (USACount)
2441 {
2442 if (*Block != USANumber)
2443 {
2444 DPRINT1("Mismatch with USA: %u read, %u expected\n" , *Block, USANumber);
2445 return STATUS_UNSUCCESSFUL;
2446 }
2447 *Block = *(USA++);
2448 Block = (USHORT*)((PCHAR)Block + Vcb->NtfsInfo.BytesPerSector);
2449 USACount--;
2450 }
2451
2452 return STATUS_SUCCESS;
2453}

Referenced by BrowseSubNodeIndexEntries(), CreateBTreeNodeFromIndexNode(), NtfsIndexNodeIsEmpty(), PrintAllVCNs(), ReadFileRecord(), UpdateFileRecord(), and UpdateIndexEntryFileName().

◆ FreeClusters()

NTSTATUS FreeClusters ( PNTFS_VCB  Vcb,
PNTFS_ATTR_CONTEXT  AttrContext,
ULONG  AttrOffset,
PFILE_RECORD_HEADER  FileRecord,
ULONG  ClustersToFree 
)

Definition at line 1101 of file attrib.c.

1106{
1108 ULONG ClustersLeftToFree = ClustersToFree;
1109
1110 PNTFS_ATTR_RECORD DestinationAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + AttrOffset);
1111 ULONG NextAttributeOffset = AttrOffset + AttrContext->pRecord->Length;
1112 PNTFS_ATTR_RECORD NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + NextAttributeOffset);
1113
1114 PUCHAR RunBuffer;
1115 ULONG RunBufferSize = 0;
1116
1117 ULONG LowestFreed = MAXULONG;
1118 ULONG HighestFreed = 0;
1119 ULONG Freed = 0;
1120
1121 if (!AttrContext->pRecord->IsNonResident)
1122 {
1124 }
1125
1126 /* Same lock NtfsAllocateClusters() holds over the bitmap copy */
1128 ExAcquireResourceExclusiveLite(&Vcb->BitmapResource, TRUE);
1129
1130 // free clusters in $BITMAP file
1131 while (ClustersLeftToFree > 0)
1132 {
1133 ULONGLONG LastVcn = AttrContext->pRecord->NonResident.HighestVCN;
1135
1136 /* An empty stream has HighestVCN -1 */
1137 if (LastVcn == (ULONGLONG)-1)
1138 {
1140 DPRINT1("DRIVER ERROR: FreeClusters called to free %lu clusters, which is %lu more clusters than are assigned to attribute!",
1141 ClustersToFree,
1142 ClustersLeftToFree);
1143 break;
1144 }
1145
1146 /* The last VCN of a sparse stream can sit in a hole, which owns no cluster */
1147 if (FsRtlLookupLargeMcbEntry(&AttrContext->DataRunsMCB, LastVcn, &LargeLbn, NULL, NULL, NULL, NULL) &&
1148 LargeLbn != -1)
1149 {
1150 // deallocate this cluster
1151 RtlClearBits(&Vcb->ClusterBitmap, (ULONG)LargeLbn, 1);
1152 LowestFreed = min(LowestFreed, (ULONG)LargeLbn);
1153 HighestFreed = max(HighestFreed, (ULONG)LargeLbn);
1154 Freed++;
1155 }
1156 FsRtlTruncateLargeMcb(&AttrContext->DataRunsMCB, LastVcn);
1157
1158 /* Freeing the last cluster leaves the -1 of an empty stream */
1159 AttrContext->pRecord->NonResident.HighestVCN = LastVcn - 1;
1160 ClustersLeftToFree--;
1161 }
1162
1163 if (AttrContext->pRecord->Flags & (NTFS_ATTR_COMPRESSION_MASK | NTFS_ATTR_SPARSE))
1164 AttrContext->pRecord->NonResident.CompressedSize -= (ULONGLONG)Freed * Vcb->NtfsInfo.BytesPerCluster;
1165
1166 if (Freed != 0)
1167 {
1168 NTSTATUS WriteStatus;
1169
1170 Vcb->FreeClusterCount += Freed;
1171
1172 // update $BITMAP file on disk
1173 WriteStatus = NtfsWriteVolumeBitmap(Vcb, LowestFreed, HighestFreed - LowestFreed + 1);
1174 if (NT_SUCCESS(Status))
1175 Status = WriteStatus;
1176 }
1177
1178 ExReleaseResourceLite(&Vcb->BitmapResource);
1180
1181 if (!NT_SUCCESS(Status))
1182 return Status;
1183
1184 // Save updated data runs to file record
1185
1186 // Allocate some memory for a new RunBuffer
1187 RunBuffer = ExAllocatePoolWithTag(NonPagedPool, Vcb->NtfsInfo.BytesPerFileRecord, TAG_NTFS);
1188 if (!RunBuffer)
1189 {
1190 DPRINT1("ERROR: Couldn't allocate memory for data runs!\n");
1192 }
1193
1194 // Convert the map control block back to encoded data runs.
1195 // RunBuffer is one file record long (not one cluster) - see AddRun().
1196 ConvertLargeMCBToDataRuns(&AttrContext->DataRunsMCB,
1197 AttrContext->pRecord->NonResident.HighestVCN + 1,
1198 RunBuffer,
1199 Vcb->NtfsInfo.BytesPerFileRecord,
1200 &RunBufferSize);
1201
1202 // Update HighestVCN
1203 DestinationAttribute->NonResident.HighestVCN = AttrContext->pRecord->NonResident.HighestVCN;
1204
1205 /* Only these headers have the field; in others its offset is the name or the runs */
1206 if (AttrContext->pRecord->Flags & (NTFS_ATTR_COMPRESSION_MASK | NTFS_ATTR_SPARSE))
1207 DestinationAttribute->NonResident.CompressedSize = AttrContext->pRecord->NonResident.CompressedSize;
1208
1209 // Write data runs to destination attribute
1210 RtlCopyMemory((PVOID)((ULONG_PTR)DestinationAttribute + DestinationAttribute->NonResident.MappingPairsOffset),
1211 RunBuffer,
1212 RunBufferSize);
1213
1214 // Is DestinationAttribute the last attribute in the file record?
1215 if (NextAttribute->Type == AttributeEnd)
1216 {
1217 // update attribute length
1218 DestinationAttribute->Length = ALIGN_UP_BY(AttrContext->pRecord->NonResident.MappingPairsOffset + RunBufferSize,
1220
1221 ASSERT(DestinationAttribute->Length <= AttrContext->pRecord->Length);
1222
1223 AttrContext->pRecord->Length = DestinationAttribute->Length;
1224
1225 // write end markers
1226 NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)DestinationAttribute + DestinationAttribute->Length);
1227 SetFileRecordEnd(FileRecord, NextAttribute, FILE_RECORD_END);
1228 }
1229
1230 // Update the file record
1231 Status = UpdateFileRecord(Vcb, AttrContext->FileMFTIndex, FileRecord);
1232
1233 ExFreePoolWithTag(RunBuffer, TAG_NTFS);
1234
1235#if NTFS_DUMP_DATA_RUNS
1236 NtfsDumpDataRuns((PUCHAR)((ULONG_PTR)DestinationAttribute + DestinationAttribute->NonResident.MappingPairsOffset), 0);
1237#endif
1238
1239 return Status;
1240}
#define RtlClearBits
Definition: dbgbitmap.h:331
NTSTATUS NtfsWriteVolumeBitmap(_In_ PDEVICE_EXTENSION DeviceExt, _In_ ULONG FirstCluster, _In_ ULONG ClusterCount)
Definition: volinfo.c:167
#define ExAcquireResourceExclusiveLite(res, wait)
Definition: env_spec_w32.h:615
_Out_ PLONGLONG _Out_ PLONGLONG LargeLbn
Definition: fsrtlfuncs.h:521
#define KeLeaveCriticalRegion()
Definition: ke_x.h:119
#define KeEnterCriticalRegion()
Definition: ke_x.h:88
VOID NTAPI FsRtlTruncateLargeMcb(IN PLARGE_MCB Mcb, IN LONGLONG Vbn)
Definition: largemcb.c:1059
BOOLEAN NTAPI FsRtlLookupLargeMcbEntry(IN PLARGE_MCB Mcb, IN LONGLONG Vbn, OUT PLONGLONG Lbn OPTIONAL, OUT PLONGLONG SectorCountFromLbn OPTIONAL, OUT PLONGLONG StartingLbn OPTIONAL, OUT PLONGLONG SectorCountFromStartingLbn OPTIONAL, OUT PULONG Index OPTIONAL)
Definition: largemcb.c:560
if(dx< 0)
Definition: linetemp.h:194
#define min(a, b)
Definition: monoChain.cc:55
VOID FASTCALL ExReleaseResourceLite(IN PERESOURCE Resource)
Definition: resource.c:1822
#define max(a, b)
Definition: svc.c:63
#define MAXULONG
Definition: typedefs.h:251

Referenced by FatExamineFatEntries(), GetDiskFreeSpaceW(), HandleNotify(), NtfsDeleteFileRecord(), NtfsGetFreeClusters(), NtfsResizeAllocation(), NtfsTrimAllocation(), and SetNonResidentAttributeDataLength().

◆ FreeMftEntry()

NTSTATUS FreeMftEntry ( PDEVICE_EXTENSION  DeviceExt,
ULONGLONG  MftIndex 
)

Definition at line 3336 of file mft.c.

3338{
3341 ULONGLONG BitmapDataSize;
3342 ULONGLONG AttrBytesRead;
3345 ULONG LengthWritten;
3346 PNTFS_ATTR_CONTEXT BitmapContext;
3347 LARGE_INTEGER BitmapBits;
3348 PFILE_RECORD_HEADER FileRecord;
3349
3350 DPRINT("FreeMftEntry(%p, %I64u)\n", DeviceExt, MftIndex);
3351
3352 // Mark the record itself as free first, so a bitmap bit is never handed out for a record
3353 // that still looks in use.
3354 FileRecord = ExAllocateFromNPagedLookasideList(&DeviceExt->FileRecLookasideList);
3355 if (!FileRecord)
3357
3358 Status = ReadFileRecord(DeviceExt, MftIndex, FileRecord);
3359 if (!NT_SUCCESS(Status))
3360 {
3361 DPRINT1("ERROR: Couldn't read file record %I64u to free it!\n", MftIndex);
3362 ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, FileRecord);
3363 return Status;
3364 }
3365
3366 FileRecord->Flags &= ~FRH_IN_USE;
3367 FileRecord->SequenceNumber++;
3368
3369 // Sequence number zero is reserved to mean "no reference"
3370 if (FileRecord->SequenceNumber == 0)
3371 FileRecord->SequenceNumber = 1;
3372
3373 Status = UpdateFileRecord(DeviceExt, MftIndex, FileRecord);
3374 ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, FileRecord);
3375
3376 if (!NT_SUCCESS(Status))
3377 {
3378 DPRINT1("ERROR: Couldn't write file record %I64u while freeing it!\n", MftIndex);
3379 return Status;
3380 }
3381
3382 Status = FindAttribute(DeviceExt, DeviceExt->MasterFileTable, AttributeBitmap, L"", 0, &BitmapContext, NULL);
3383 if (!NT_SUCCESS(Status))
3384 {
3385 DPRINT1("ERROR: Couldn't find $Bitmap attribute of master file table!\n");
3386 return Status;
3387 }
3388
3389 BitmapDataSize = AttributeDataLength(BitmapContext->pRecord);
3390
3391 // RtlInitializeBitmap wants a ULONG-aligned pointer and a ULONG-multiple of memory
3392 BitmapBuffer = ExAllocatePoolWithTag(NonPagedPool, BitmapDataSize + sizeof(ULONG), TAG_NTFS);
3393 if (!BitmapBuffer)
3394 {
3395 ReleaseAttributeContext(BitmapContext);
3397 }
3398 RtlZeroMemory(BitmapBuffer, BitmapDataSize + sizeof(ULONG));
3399
3401
3402 AttrBytesRead = ReadAttribute(DeviceExt, BitmapContext, 0, (PCHAR)BitmapData, BitmapDataSize);
3403 if (AttrBytesRead != BitmapDataSize)
3404 {
3405 DPRINT1("ERROR: Unable to read $Bitmap attribute of master file table!\n");
3407 ReleaseAttributeContext(BitmapContext);
3409 }
3410
3411 BitmapBits.QuadPart = AttributeDataLength(DeviceExt->MFTContext->pRecord) /
3412 DeviceExt->NtfsInfo.BytesPerFileRecord;
3413 if (BitmapBits.HighPart != 0)
3414 {
3415 DPRINT1("\tFIXME: bitmap sizes beyond 32bits are not yet supported! (Your NTFS volume is too large)\n");
3417 ReleaseAttributeContext(BitmapContext);
3419 }
3420
3421 if (MftIndex >= BitmapBits.QuadPart)
3422 {
3423 DPRINT1("ERROR: Mft index %I64u is beyond the end of the master file table!\n", MftIndex);
3425 ReleaseAttributeContext(BitmapContext);
3427 }
3428
3430 RtlClearBits(&Bitmap, (ULONG)MftIndex, 1);
3431
3432 Status = WriteAttribute(DeviceExt, BitmapContext, 0, BitmapData, BitmapDataSize, &LengthWritten, NULL);
3433 if (!NT_SUCCESS(Status))
3434 {
3435 DPRINT1("ERROR encountered when writing $Bitmap attribute!\n");
3436 }
3437
3439 ReleaseAttributeContext(BitmapContext);
3440
3441 return Status;
3442}

Referenced by NtfsDeleteFileRecord().

◆ GetAllocationOffsetFromVCN()

ULONGLONG GetAllocationOffsetFromVCN ( PDEVICE_EXTENSION  DeviceExt,
ULONG  IndexBufferSize,
ULONGLONG  Vcn 
)

Definition at line 1637 of file btree.c.

1640{
1641 if (IndexBufferSize < DeviceExt->NtfsInfo.BytesPerCluster)
1642 return Vcn * DeviceExt->NtfsInfo.BytesPerSector;
1643
1644 return Vcn * DeviceExt->NtfsInfo.BytesPerCluster;
1645}

Referenced by BrowseSubNodeIndexEntries(), CreateBTreeNodeFromIndexNode(), NtfsIndexNodeIsEmpty(), and UpdateIndexNode().

◆ GetBestFileNameFromRecord()

PFILENAME_ATTRIBUTE GetBestFileNameFromRecord ( PDEVICE_EXTENSION  Vcb,
PFILE_RECORD_HEADER  FileRecord 
)

Definition at line 2015 of file attrib.c.

2017{
2019
2021 if (FileName == NULL)
2022 {
2024 if (FileName == NULL)
2025 {
2027 }
2028 }
2029
2030 return FileName;
2031}
#define NTFS_FILE_NAME_DOS
Definition: ntfs.h:65
#define NTFS_FILE_NAME_WIN32
Definition: ntfs.h:64
PFILENAME_ATTRIBUTE GetFileNameFromRecord(PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER FileRecord, UCHAR NameType)
Definition: attrib.c:1839

Referenced by NtfsGetBothDirectoryInformation(), NtfsGetDirectoryInformation(), NtfsGetFullDirectoryInformation(), NtfsGetNamesInformation(), NtfsGetParentMftIndex(), NtfsMakeFCBFromDirEntry(), NtfsMoonWalkID(), NtfsSetEndOfFile(), and NtfsUpdateDuplicatedInformation().

◆ GetFileNameAttributeLength()

ULONG GetFileNameAttributeLength ( PFILENAME_ATTRIBUTE  FileNameAttribute)

Definition at line 2008 of file attrib.c.

2009{
2010 ULONG Length = FIELD_OFFSET(FILENAME_ATTRIBUTE, Name) + (FileNameAttribute->NameLength * sizeof(WCHAR));
2011 return Length;
2012}

Referenced by CreateBTreeKeyFromFilename(), and ReplaceKeyIndexEntry().

◆ GetFileNameFromRecord()

PFILENAME_ATTRIBUTE GetFileNameFromRecord ( PDEVICE_EXTENSION  Vcb,
PFILE_RECORD_HEADER  FileRecord,
UCHAR  NameType 
)

Definition at line 1839 of file attrib.c.

1842{
1844 PNTFS_ATTR_RECORD Attribute;
1847
1848 Status = FindFirstAttribute(&Context, Vcb, FileRecord, FALSE, &Attribute);
1849 while (NT_SUCCESS(Status))
1850 {
1851 if (Attribute->Type == AttributeFileName)
1852 {
1853 Name = (PFILENAME_ATTRIBUTE)((ULONG_PTR)Attribute + Attribute->Resident.ValueOffset);
1854 if (Name->NameType == NameType ||
1857 {
1859 return Name;
1860 }
1861 }
1862
1863 Status = FindNextAttribute(&Context, &Attribute);
1864 }
1865
1867 return NULL;
1868}
ACPI_PHYSICAL_ADDRESS ACPI_SIZE BOOLEAN Warn UINT32 *TableIdx UINT32 ACPI_TABLE_HEADER *OutTableHeader ACPI_TABLE_HEADER **OutTable ACPI_HANDLE UINT32 ACPI_WALK_CALLBACK ACPI_WALK_CALLBACK void void **ReturnValue UINT32 NameType
Definition: acpixf.h:658

Referenced by GetBestFileNameFromRecord(), NtfsGetBothDirectoryInformation(), and NtfsMakeRootFCB().

◆ GetIndexEntryVCN()

ULONGLONG GetIndexEntryVCN ( PINDEX_ENTRY_ATTRIBUTE  IndexEntry)

Definition at line 1648 of file btree.c.

1649{
1650 PULONGLONG Destination = (PULONGLONG)((ULONG_PTR)IndexEntry + IndexEntry->Length - sizeof(ULONGLONG));
1651
1652 ASSERT(IndexEntry->Flags & NTFS_INDEX_ENTRY_NODE);
1653
1654 return *Destination;
1655}
_In_ PUNICODE_STRING _Inout_ PUNICODE_STRING Destination
Definition: rtlfuncs.h:3051
__GNU_EXTENSION typedef unsigned __int64 * PULONGLONG
Definition: ntbasedef.h:395

Referenced by BrowseIndexEntries(), BrowseSubNodeIndexEntries(), NtfsIndexEntriesAreEmpty(), and SplitBTreeNode().

◆ GetLastClusterInDataRun()

NTSTATUS GetLastClusterInDataRun ( PDEVICE_EXTENSION  Vcb,
PNTFS_ATTR_RECORD  Attribute,
PULONGLONG  LastCluster 
)

Definition at line 1938 of file attrib.c.

1939{
1940 LONGLONG DataRunOffset;
1941 ULONGLONG DataRunLength;
1942 LONGLONG DataRunStartLCN;
1943
1944 ULONGLONG LastLCN = 0;
1945 PUCHAR DataRun = (PUCHAR)Attribute + Attribute->NonResident.MappingPairsOffset;
1946
1947 if (!Attribute->IsNonResident)
1949
1950 while (1)
1951 {
1952 DataRun = DecodeRun(DataRun, &DataRunOffset, &DataRunLength);
1953
1954 if (DataRunOffset != -1)
1955 {
1956 // Normal data run.
1957 DataRunStartLCN = LastLCN + DataRunOffset;
1958 LastLCN = DataRunStartLCN;
1959 *LastCluster = LastLCN + DataRunLength - 1;
1960 }
1961
1962 if (*DataRun == 0)
1963 break;
1964 }
1965
1966 return STATUS_SUCCESS;
1967}

◆ GetPackedByteCount()

UCHAR GetPackedByteCount ( LONGLONG  NumberToPack,
BOOLEAN  IsSigned 
)

GetPackedByteCount Returns the minimum number of bytes needed to represent the value of a 64-bit number. Used to encode data runs.

Definition at line 1876 of file attrib.c.

1878{
1879 if (!IsSigned)
1880 {
1881 if (NumberToPack >= 0x0100000000000000)
1882 return 8;
1883 if (NumberToPack >= 0x0001000000000000)
1884 return 7;
1885 if (NumberToPack >= 0x0000010000000000)
1886 return 6;
1887 if (NumberToPack >= 0x0000000100000000)
1888 return 5;
1889 if (NumberToPack >= 0x0000000001000000)
1890 return 4;
1891 if (NumberToPack >= 0x0000000000010000)
1892 return 3;
1893 if (NumberToPack >= 0x0000000000000100)
1894 return 2;
1895 return 1;
1896 }
1897
1898 if (NumberToPack > 0)
1899 {
1900 // we have to make sure the number that gets encoded won't be interpreted as negative
1901 if (NumberToPack >= 0x0080000000000000)
1902 return 8;
1903 if (NumberToPack >= 0x0000800000000000)
1904 return 7;
1905 if (NumberToPack >= 0x0000008000000000)
1906 return 6;
1907 if (NumberToPack >= 0x0000000080000000)
1908 return 5;
1909 if (NumberToPack >= 0x0000000000800000)
1910 return 4;
1911 if (NumberToPack >= 0x0000000000008000)
1912 return 3;
1913 if (NumberToPack >= 0x0000000000000080)
1914 return 2;
1915 }
1916 else
1917 {
1918 // negative number
1919 if (NumberToPack <= 0xff80000000000000)
1920 return 8;
1921 if (NumberToPack <= 0xffff800000000000)
1922 return 7;
1923 if (NumberToPack <= 0xffffff8000000000)
1924 return 6;
1925 if (NumberToPack <= 0xffffffff80000000)
1926 return 5;
1927 if (NumberToPack <= 0xffffffffff800000)
1928 return 4;
1929 if (NumberToPack <= 0xffffffffffff8000)
1930 return 3;
1931 if (NumberToPack <= 0xffffffffffffff80)
1932 return 2;
1933 }
1934 return 1;
1935}

Referenced by ConvertLargeMCBToDataRuns().

◆ GetSizeOfIndexEntries()

ULONG GetSizeOfIndexEntries ( PB_TREE_FILENAME_NODE  Node)

Definition at line 860 of file btree.c.

861{
862 // Start summing the total size of this node's entries
863 ULONG NodeSize = 0;
864
865 // Walk through the list of Node Entries
866 PB_TREE_KEY CurrentKey = Node->FirstKey;
867 ULONG i;
868 for (i = 0; i < Node->KeyCount; i++)
869 {
870 ASSERT(CurrentKey->IndexEntry->Length != 0);
871
872 // Add the length of the current node
873 NodeSize += CurrentKey->IndexEntry->Length;
874 CurrentKey = CurrentKey->NextKey;
875 }
876
877 return NodeSize;
878}

Referenced by AddFilenameToDirectoryWorker(), and NtfsInsertKey().

◆ GetStandardInformationFromRecord()

PSTANDARD_INFORMATION GetStandardInformationFromRecord ( PDEVICE_EXTENSION  Vcb,
PFILE_RECORD_HEADER  FileRecord 
)

Definition at line 1970 of file attrib.c.

1972{
1975 PNTFS_ATTR_RECORD Attribute;
1976 PSTANDARD_INFORMATION StdInfo;
1977
1978 Status = FindFirstAttribute(&Context, Vcb, FileRecord, FALSE, &Attribute);
1979 while (NT_SUCCESS(Status))
1980 {
1981 if (Attribute->Type == AttributeStandardInformation)
1982 {
1983 StdInfo = (PSTANDARD_INFORMATION)((ULONG_PTR)Attribute + Attribute->Resident.ValueOffset);
1985 return StdInfo;
1986 }
1987
1988 Status = FindNextAttribute(&Context, &Attribute);
1989 }
1990
1992 return NULL;
1993}

Referenced by NtfsGetBothDirectoryInformation(), NtfsGetDirectoryInformation(), NtfsGetFullDirectoryInformation(), NtfsMakeFCBFromDirEntry(), NtfsSetBasicInformation(), and NtfsUpdateDuplicatedInformation().

◆ InternalSetResidentAttributeLength()

NTSTATUS InternalSetResidentAttributeLength ( PDEVICE_EXTENSION  DeviceExt,
PNTFS_ATTR_CONTEXT  AttrContext,
PFILE_RECORD_HEADER  FileRecord,
ULONG  AttrOffset,
ULONG  DataSize 
)

Definition at line 542 of file mft.c.

547{
548 PNTFS_ATTR_RECORD Destination = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + AttrOffset);
550 PNTFS_ATTR_RECORD FinalAttribute;
551 ULONG OldAttributeLength = Destination->Length;
552 ULONG NextAttributeOffset;
553
554 DPRINT("InternalSetResidentAttributeLength( %p, %p, %p, %lu, %lu )\n", DeviceExt, AttrContext, FileRecord, AttrOffset, DataSize);
555
556 ASSERT(!AttrContext->pRecord->IsNonResident);
557
558 // Update ValueLength Field
559 Destination->Resident.ValueLength = DataSize;
560
561 // Calculate the record length and end marker offset
562 Destination->Length = ALIGN_UP_BY(DataSize + AttrContext->pRecord->Resident.ValueOffset, ATTR_RECORD_ALIGNMENT);
563 NextAttributeOffset = AttrOffset + Destination->Length;
564
565 // Ensure NextAttributeOffset is aligned to an 8-byte boundary
566 ASSERT(NextAttributeOffset % ATTR_RECORD_ALIGNMENT == 0);
567
568 // Will the new attribute be larger than the old one?
569 if (Destination->Length > OldAttributeLength)
570 {
571 // Free the old copy of the attribute in the context, as it will be the wrong length
572 ExFreePoolWithTag(AttrContext->pRecord, TAG_NTFS);
573
574 // Create a new copy of the attribute record for the context
576 if (!AttrContext->pRecord)
577 {
578 DPRINT1("Unable to allocate memory for attribute!\n");
580 }
581 RtlZeroMemory((PVOID)((ULONG_PTR)AttrContext->pRecord + OldAttributeLength), Destination->Length - OldAttributeLength);
582 RtlCopyMemory(AttrContext->pRecord, Destination, OldAttributeLength);
583 }
584
585 // Are there attributes after this one that need to be moved?
586 if (NextAttribute->Type != AttributeEnd)
587 {
588 // Move the attributes after this one
589 FinalAttribute = MoveAttributes(DeviceExt, NextAttribute, NextAttributeOffset, (ULONG_PTR)Destination + Destination->Length);
590 }
591 else
592 {
593 // advance to the final "attribute," adjust for the changed length of the attribute we're resizing
594 FinalAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)NextAttribute - OldAttributeLength + Destination->Length);
595 }
596
597 // Update pRecord's length
598 AttrContext->pRecord->Length = Destination->Length;
599 AttrContext->pRecord->Resident.ValueLength = DataSize;
600
601 // set the file record end
602 SetFileRecordEnd(FileRecord, FinalAttribute, FILE_RECORD_END);
603
604 //NtfsDumpFileRecord(DeviceExt, FileRecord);
605
606 return STATUS_SUCCESS;
607}
_In_ NDIS_STATUS _In_ ULONG _In_ USHORT _In_opt_ PVOID _In_ ULONG DataSize
Definition: ndis.h:4755

Referenced by AddFilenameToDirectoryWorker(), RemoveFilenameFromDirectoryWorker(), and SetResidentAttributeDataLength().

◆ MoveAttributes()

PNTFS_ATTR_RECORD MoveAttributes ( PDEVICE_EXTENSION  DeviceExt,
PNTFS_ATTR_RECORD  FirstAttributeToMove,
ULONG  FirstAttributeOffset,
ULONG_PTR  MoveTo 
)

Definition at line 512 of file mft.c.

516{
517 // Get the size of all attributes after this one
518 ULONG MemBlockSize = 0;
519 PNTFS_ATTR_RECORD CurrentAttribute = FirstAttributeToMove;
520 ULONG CurrentOffset = FirstAttributeOffset;
521 PNTFS_ATTR_RECORD FinalAttribute;
522
523 while (CurrentAttribute->Type != AttributeEnd && CurrentOffset < DeviceExt->NtfsInfo.BytesPerFileRecord)
524 {
525 CurrentOffset += CurrentAttribute->Length;
526 MemBlockSize += CurrentAttribute->Length;
527 CurrentAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)CurrentAttribute + CurrentAttribute->Length);
528 }
529
530 FinalAttribute = (PNTFS_ATTR_RECORD)(MoveTo + MemBlockSize);
531 MemBlockSize += sizeof(ULONG) * 2; // Add the AttributeEnd and file record end
532
533 ASSERT(MemBlockSize % ATTR_RECORD_ALIGNMENT == 0);
534
535 // Move the attributes after this one
536 RtlMoveMemory((PCHAR)MoveTo, FirstAttributeToMove, MemBlockSize);
537
538 return FinalAttribute;
539}
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264

Referenced by AddRun(), and InternalSetResidentAttributeLength().

◆ NtfsAcqLazyWrite()

BOOLEAN NTAPI NtfsAcqLazyWrite ( PVOID  Context,
BOOLEAN  Wait 
)

◆ NtfsAcqReadAhead()

BOOLEAN NTAPI NtfsAcqReadAhead ( PVOID  Context,
BOOLEAN  Wait 
)

◆ NtfsAddFCBToTable()

VOID NtfsAddFCBToTable ( PNTFS_VCB  Vcb,
PNTFS_FCB  Fcb 
)

Definition at line 250 of file fcb.c.

252{
253 KIRQL oldIrql;
254
255 KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql);
256 Fcb->Vcb = Vcb;
257 InsertTailList(&Vcb->FcbListHead, &Fcb->FcbListEntry);
258 KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
259}
_In_ PFCB Fcb
Definition: cdprocs.h:159
#define InsertTailList(ListHead, Entry)
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
PVCB Vcb
Definition: cdstruc.h:933
LIST_ENTRY FcbListEntry
Definition: ntfs.h:612

Referenced by NtfsMakeFCBFromDirEntry(), and NtfsMakeRootFCB().

◆ NtfsAddFilenameToDirectory()

NTSTATUS NtfsAddFilenameToDirectory ( PDEVICE_EXTENSION  DeviceExt,
ULONGLONG  DirectoryMftIndex,
ULONGLONG  FileReferenceNumber,
PFILENAME_ATTRIBUTE  FilenameAttribute,
BOOLEAN  CaseSensitive 
)

Definition at line 3049 of file mft.c.

3054{
3056
3058 ExAcquireResourceExclusiveLite(&DeviceExt->IndexResource, TRUE);
3059 Status = AddFilenameToDirectoryWorker(DeviceExt, DirectoryMftIndex, FileReferenceNumber, FilenameAttribute, CaseSensitive);
3060 ExReleaseResourceLite(&DeviceExt->IndexResource);
3062
3063 return Status;
3064}
static NTSTATUS AddFilenameToDirectoryWorker(PDEVICE_EXTENSION DeviceExt, ULONGLONG DirectoryMftIndex, ULONGLONG FileReferenceNumber, PFILENAME_ATTRIBUTE FilenameAttribute, BOOLEAN CaseSensitive)
Definition: mft.c:2704

Referenced by NtfsCommitRename(), NtfsCreateDirectory(), NtfsCreateFileRecord(), and NtfsRelinkFileNames().

◆ NtfsAddIoRun()

NTSTATUS NtfsAddIoRun ( IN OUT PNTFS_IO_RUN_LIST  RunList,
IN LONGLONG  Lbo,
IN ULONG  ByteCount 
)

Definition at line 74 of file blockdev.c.

77{
78 PNTFS_IO_RUN LastRun;
79 PNTFS_IO_RUN NewRuns;
80 ULONG NewCapacity;
81
82 if (ByteCount == 0)
83 return STATUS_SUCCESS;
84
85 /* Does this piece simply continue the previous one? */
86 if (RunList->Count != 0)
87 {
88 LastRun = &RunList->Runs[RunList->Count - 1];
89
90 if (LastRun->ByteCount <= MAXULONG - ByteCount &&
91 ((Lbo == NTFS_SPARSE_LBO && LastRun->Lbo == NTFS_SPARSE_LBO) ||
92 (Lbo != NTFS_SPARSE_LBO && LastRun->Lbo != NTFS_SPARSE_LBO &&
93 LastRun->Lbo + LastRun->ByteCount == Lbo)))
94 {
95 LastRun->ByteCount += ByteCount;
96 RunList->TotalLength += ByteCount;
97 return STATUS_SUCCESS;
98 }
99 }
100
101 if (RunList->Count == RunList->Capacity)
102 {
103 NewCapacity = RunList->Capacity * 2;
104
105 /* Non-paged: a run list stays live across the transfer, and a request
106 * on the paging path must not fault while walking it. */
108 NewCapacity * sizeof(NTFS_IO_RUN),
110 if (NewRuns == NULL)
111 {
112 DPRINT1("Not enough memory to grow the I/O run list!\n");
114 }
115
116 RtlCopyMemory(NewRuns, RunList->Runs, RunList->Count * sizeof(NTFS_IO_RUN));
117
118 if (RunList->Runs != RunList->StackRuns)
119 {
120 ExFreePoolWithTag(RunList->Runs, TAG_IO_RUNS);
121 }
122
123 RunList->Runs = NewRuns;
124 RunList->Capacity = NewCapacity;
125 }
126
127 LastRun = &RunList->Runs[RunList->Count];
128 LastRun->Lbo = Lbo;
129 LastRun->BufferOffset = RunList->TotalLength;
130 LastRun->ByteCount = ByteCount;
131 LastRun->SavedIrp = NULL;
132
133 RunList->Count++;
134 RunList->TotalLength += ByteCount;
135
136 return STATUS_SUCCESS;
137}
#define TAG_IO_RUNS
Definition: nodetype.h:168
#define NTFS_SPARSE_LBO
Definition: ntfs.h:510
IN PFCB IN VBO OUT PLBO Lbo
Definition: fatprocs.h:309
PIRP SavedIrp
Definition: ntfs.h:522
LONGLONG Lbo
Definition: ntfs.h:519
ULONG BufferOffset
Definition: ntfs.h:520
ULONG ByteCount
Definition: ntfs.h:521
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS _In_ LARGE_INTEGER ByteCount
Definition: iotypes.h:1099

Referenced by NtfsMapAttributeRuns(), NtfsReadDisk(), NtfsReadWriteVolume(), and NtfsWriteDisk().

◆ NtfsAllocateClusters()

NTSTATUS NtfsAllocateClusters ( PDEVICE_EXTENSION  DeviceExt,
ULONG  FirstDesiredCluster,
ULONG  DesiredClusters,
PULONG  FirstAssignedCluster,
PULONG  AssignedClusters 
)

NtfsAllocateClusters Allocates a run of clusters. The run allocated might be smaller than DesiredClusters.

Definition at line 213 of file volinfo.c.

218{
220 PRTL_BITMAP Bitmap = &DeviceExt->ClusterBitmap;
221 ULONG AssignedRun;
222
223 DPRINT("NtfsAllocateClusters(%p, %lu, %lu, %p, %p)\n", DeviceExt, FirstDesiredCluster, DesiredClusters, FirstAssignedCluster, AssignedClusters);
224
225 *AssignedClusters = 0;
226
227 /* Files growing in parallel must not both claim the same free run */
229 ExAcquireResourceExclusiveLite(&DeviceExt->BitmapResource, TRUE);
230
231 if (DeviceExt->FreeClusterCount < DesiredClusters)
232 {
234 goto Quit;
235 }
236
237 /* The hint is just past the file's last cluster, which can be past the volume end */
238 if (FirstDesiredCluster >= Bitmap->SizeOfBitMap)
239 FirstDesiredCluster = 0;
240
241 // TODO: Observe MFT reservation zone
242
243 // Can we get one contiguous run?
244 AssignedRun = RtlFindClearBitsAndSet(Bitmap, DesiredClusters, FirstDesiredCluster);
245
246 if (AssignedRun != 0xFFFFFFFF)
247 {
248 *FirstAssignedCluster = AssignedRun;
249 *AssignedClusters = DesiredClusters;
250 }
251 else
252 {
253 // we can't get one contiguous run
254 *AssignedClusters = RtlFindNextForwardRunClear(Bitmap, FirstDesiredCluster, FirstAssignedCluster);
255
256 if (*AssignedClusters == 0)
257 {
258 // we couldn't find any runs starting at DesiredFirstCluster
259 *AssignedClusters = RtlFindLongestRunClear(Bitmap, FirstAssignedCluster);
260 }
261
262 if (*AssignedClusters == 0)
263 {
265 goto Quit;
266 }
267
268 /* Hand out no more than was asked for, and mark it in use */
269 *AssignedClusters = min(*AssignedClusters, DesiredClusters);
270 RtlSetBits(Bitmap, *FirstAssignedCluster, *AssignedClusters);
271 }
272
273 Status = NtfsWriteVolumeBitmap(DeviceExt, *FirstAssignedCluster, *AssignedClusters);
274 if (NT_SUCCESS(Status))
275 {
276 DeviceExt->FreeClusterCount -= *AssignedClusters;
277 }
278 else
279 {
280 /* Keep the copy in step with what the disk says */
281 RtlClearBits(Bitmap, *FirstAssignedCluster, *AssignedClusters);
282 *AssignedClusters = 0;
283 }
284
285Quit:
286 ExReleaseResourceLite(&DeviceExt->BitmapResource);
288
289 return Status;
290}
#define RtlFindNextForwardRunClear
Definition: dbgbitmap.h:338
#define RtlFindLongestRunClear
Definition: dbgbitmap.h:337
#define RtlSetBits
Definition: dbgbitmap.h:345
NTSTATUS NtfsWriteVolumeBitmap(_In_ PDEVICE_EXTENSION DeviceExt, _In_ ULONG FirstCluster, _In_ ULONG ClusterCount)
Definition: volinfo.c:167
#define STATUS_DISK_FULL
Definition: udferr_usr.h:155

Referenced by NtfsExtendAllocation().

◆ NtfsAllocateIrpContext()

PNTFS_IRP_CONTEXT NtfsAllocateIrpContext ( PDEVICE_OBJECT  DeviceObject,
PIRP  Irp 
)

Definition at line 66 of file misc.c.

68{
69 PNTFS_IRP_CONTEXT IrpContext;
70
71 TRACE_(NTFS, "NtfsAllocateIrpContext()\n");
72
73 IrpContext = (PNTFS_IRP_CONTEXT)ExAllocateFromNPagedLookasideList(&NtfsGlobalData->IrpContextLookasideList);
74 if (IrpContext == NULL)
75 return NULL;
76
77 RtlZeroMemory(IrpContext, sizeof(NTFS_IRP_CONTEXT));
78
80 IrpContext->Identifier.Size = sizeof(NTFS_IRP_CONTEXT);
81 IrpContext->Irp = Irp;
82 IrpContext->DeviceObject = DeviceObject;
84 IrpContext->MajorFunction = IrpContext->Stack->MajorFunction;
85 IrpContext->MinorFunction = IrpContext->Stack->MinorFunction;
86 IrpContext->FileObject = IrpContext->Stack->FileObject;
87 IrpContext->IsTopLevel = (IoGetTopLevelIrp() == Irp);
88 IrpContext->PriorityBoost = IO_NO_INCREMENT;
89 IrpContext->Flags = IRPCONTEXT_COMPLETE;
90
91 if (IrpContext->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL ||
92 IrpContext->MajorFunction == IRP_MJ_DEVICE_CONTROL ||
93 IrpContext->MajorFunction == IRP_MJ_SHUTDOWN ||
94 (IrpContext->MajorFunction != IRP_MJ_CLEANUP &&
95 IrpContext->MajorFunction != IRP_MJ_CLOSE &&
97 {
98 IrpContext->Flags |= IRPCONTEXT_CANWAIT;
99 }
100
101 return IrpContext;
102}
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
@ NTFS
Definition: IoFilesystem.c:12
#define TRACE_(x)
Definition: compat.h:76
#define IRPCONTEXT_COMPLETE
Definition: ntfs.h:506
struct NTFS_IRP_CONTEXT * PNTFS_IRP_CONTEXT
#define IRPCONTEXT_CANWAIT
Definition: ntfs.h:505
#define NTFS_TYPE_IRP_CONTEXT
Definition: ntfs.h:91
_In_ PIRP Irp
Definition: kse.h:79
BOOLEAN NTAPI IoIsOperationSynchronous(IN PIRP Irp)
Definition: irp.c:1914
PIRP NTAPI IoGetTopLevelIrp(VOID)
Definition: irp.c:1875
#define IRP_MJ_CLOSE
Definition: rdpdr.c:45
#define IRP_MJ_DEVICE_CONTROL
Definition: rdpdr.c:52
ULONG Type
Definition: ntfs.h:96
ULONG Size
Definition: ntfs.h:97
NPAGED_LOOKASIDE_LIST IrpContextLookasideList
Definition: ntfs.h:179
NTFSIDENTIFIER Identifier
Definition: ntfs.h:555
PFILE_OBJECT FileObject
Definition: ntfs.h:564
UCHAR MajorFunction
Definition: ntfs.h:558
ULONG Flags
Definition: ntfs.h:556
PIO_STACK_LOCATION Stack
Definition: ntfs.h:557
UCHAR MinorFunction
Definition: ntfs.h:559
CCHAR PriorityBoost
Definition: ntfs.h:566
BOOLEAN IsTopLevel
Definition: ntfs.h:562
PDEVICE_OBJECT DeviceObject
Definition: ntfs.h:563
PFILE_OBJECT FileObject
Definition: iotypes.h:3184
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2061
#define IO_NO_INCREMENT
Definition: iotypes.h:598
#define IRP_MJ_FILE_SYSTEM_CONTROL
#define IRP_MJ_SHUTDOWN
#define IRP_MJ_CLEANUP

Referenced by NtfsFsdDispatch().

◆ NtfsAttachFCBToFileObject()

NTSTATUS NtfsAttachFCBToFileObject ( PNTFS_VCB  Vcb,
PNTFS_FCB  Fcb,
PFILE_OBJECT  FileObject 
)

Definition at line 533 of file fcb.c.

536{
537 PNTFS_CCB newCCB;
538
540 if (newCCB == NULL)
541 {
543 }
544
545 RtlZeroMemory(newCCB, sizeof(NTFS_CCB));
546
547 newCCB->Identifier.Type = NTFS_TYPE_CCB;
548 newCCB->Identifier.Size = sizeof(NTFS_TYPE_CCB);
549
550 FileObject->SectionObjectPointer = &Fcb->SectionObjectPointers;
551 FileObject->FsContext = Fcb;
552 FileObject->FsContext2 = newCCB;
553 newCCB->PtrFileObject = FileObject;
554 Fcb->Vcb = Vcb;
555
556 /* Directories are excluded: they have no $DATA to map, and a data section on one gives Mm
557 * pages to fault in that we can never satisfy. */
559 {
561 {
564 FALSE,
566 Fcb);
567 }
569 {
570 FileObject->FsContext2 = NULL;
571 ExFreePoolWithTag(newCCB, TAG_CCB);
572 return _SEH2_GetExceptionCode();
573 }
574 _SEH2_END;
575
577 }
578
579 //DPRINT("file open: fcb:%x file size: %d\n", Fcb, Fcb->Entry.DataLengthL);
580
581 return STATUS_SUCCESS;
582}
#define TAG_CCB
Definition: cdprocs.h:85
#define FCB_CACHE_INITIALIZED
Definition: ntfs.h:583
#define NTFS_TYPE_CCB
Definition: ntfs.h:88
VOID NTAPI CcInitializeCacheMap(IN PFILE_OBJECT FileObject, IN PCC_FILE_SIZES FileSizes, IN BOOLEAN PinAccess, IN PCACHE_MANAGER_CALLBACKS Callbacks, IN PVOID LazyWriteContext)
Definition: fssup.c:195
BOOLEAN NtfsFCBIsDirectory(PNTFS_FCB Fcb)
Definition: fcb.c:144
Definition: ntfs.h:151
PFILE_OBJECT PtrFileObject
Definition: ntfs.h:154
NTFSIDENTIFIER Identifier
Definition: ntfs.h:152
CACHE_MANAGER_CALLBACKS CacheMgrCallbacks
Definition: ntfs.h:176
ULONG Flags
Definition: ntfs.h:618
FSRTL_COMMON_FCB_HEADER RFCB
Definition: ntfs.h:593
SECTION_OBJECT_POINTERS SectionObjectPointers
Definition: ntfs.h:597
LARGE_INTEGER AllocationSize
Definition: env_spec_w32.h:755

Referenced by NtfsCreateFile(), NtfsOpenFile(), NtfsOpenFileById(), and NtfsOpenTargetDirectory().

◆ NtfsCleanup()

NTSTATUS NtfsCleanup ( PNTFS_IRP_CONTEXT  IrpContext)

Definition at line 171 of file cleanup.c.

172{
173 PDEVICE_EXTENSION DeviceExtension;
177
178 DPRINT("NtfsCleanup() called\n");
179
180 DeviceObject = IrpContext->DeviceObject;
182 {
183 DPRINT("Cleaning up file system\n");
184 IrpContext->Irp->IoStatus.Information = 0;
185 return STATUS_SUCCESS;
186 }
187
188 FileObject = IrpContext->FileObject;
189 DeviceExtension = DeviceObject->DeviceExtension;
190
191 if (!ExAcquireResourceExclusiveLite(&DeviceExtension->DirResource,
193 {
194 return NtfsMarkIrpContextForQueue(IrpContext);
195 }
196
197 /* The handle is going away, and so are the locks it took */
199 {
200 FsRtlFastUnlockAll(&((PNTFS_FCB)FileObject->FsContext)->FileLock,
202 IoGetRequestorProcess(IrpContext->Irp),
203 NULL);
204 }
205
206 Status = NtfsCleanupFile(DeviceExtension, FileObject, BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT));
207
208 ExReleaseResourceLite(&DeviceExtension->DirResource);
209
210 if (Status == STATUS_PENDING)
211 {
212 return NtfsMarkIrpContextForQueue(IrpContext);
213 }
214
215 IrpContext->Irp->IoStatus.Information = 0;
216 return Status;
217}
NTSTATUS NtfsCleanupFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, BOOLEAN CanWait)
Definition: cleanup.c:40
FORCEINLINE NTSTATUS NtfsMarkIrpContextForQueue(PNTFS_IRP_CONTEXT IrpContext)
Definition: ntfs.h:652
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
NTSTATUS NTAPI FsRtlFastUnlockAll(IN PFILE_LOCK FileLock, IN PFILE_OBJECT FileObject, IN PEPROCESS Process, IN PVOID Context OPTIONAL)
Definition: filelock.c:1027
BOOLEAN NTAPI NtfsIsRegularFileObject(_In_ PFILE_OBJECT FileObject)
Definition: fcb.c:153
PEPROCESS NTAPI IoGetRequestorProcess(IN PIRP Irp)
Definition: irp.c:1814
PDEVICE_OBJECT DeviceObject
Definition: ntfs.h:175
Definition: cdstruc.h:902
IO_STATUS_BLOCK IoStatus
#define STATUS_PENDING
Definition: telnetd.h:14
* PFILE_OBJECT
Definition: iotypes.h:1998

Referenced by NtfsDispatch().

◆ NtfsClose()

NTSTATUS NtfsClose ( PNTFS_IRP_CONTEXT  IrpContext)

Definition at line 87 of file close.c.

88{
89 PDEVICE_EXTENSION DeviceExtension;
93
94 DPRINT("NtfsClose() called\n");
95
96 DeviceObject = IrpContext->DeviceObject;
98 {
99 DPRINT("Closing file system\n");
100 IrpContext->Irp->IoStatus.Information = 0;
101 return STATUS_SUCCESS;
102 }
103
104 FileObject = IrpContext->FileObject;
105 DeviceExtension = DeviceObject->DeviceExtension;
106
107 if (!ExAcquireResourceExclusiveLite(&DeviceExtension->DirResource,
109 {
110 return NtfsMarkIrpContextForQueue(IrpContext);
111 }
112
113 Status = NtfsCloseFile(DeviceExtension, FileObject);
114
115 ExReleaseResourceLite(&DeviceExtension->DirResource);
116
117 if (Status == STATUS_PENDING)
118 {
119 return NtfsMarkIrpContextForQueue(IrpContext);
120 }
121
122 IrpContext->Irp->IoStatus.Information = 0;
123 return Status;
124}
NTSTATUS NtfsCloseFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject)
Definition: close.c:40

◆ NtfsCloseFile()

NTSTATUS NtfsCloseFile ( PDEVICE_EXTENSION  DeviceExt,
PFILE_OBJECT  FileObject 
)

Definition at line 40 of file close.c.

42{
45
46 DPRINT("NtfsCloseFile(DeviceExt %p, FileObject %p)\n",
47 DeviceExt,
49
50 Ccb = (PNTFS_CCB)(FileObject->FsContext2);
51 Fcb = (PNTFS_FCB)(FileObject->FsContext);
52
53 DPRINT("Ccb %p\n", Ccb);
54 if (Ccb == NULL)
55 {
56 return STATUS_SUCCESS;
57 }
58
59 FileObject->FsContext2 = NULL;
60 FileObject->FsContext = NULL;
61
62 /* SectionObjectPointer is deliberately left alone. Mm reaches the file's section object
63 * pointers through it for as long as a section exists, which outlasts the handle. */
64
65 DeviceExt->OpenHandleCount--;
66
67 if (FileObject->FileName.Buffer)
68 {
69 // This a FO, that was created outside from FSD.
70 // Some FO's are created with IoCreateStreamFileObject() insid from FSD.
71 // This FO's don't have a FileName.
72 NtfsReleaseFCB(DeviceExt, Fcb);
73 }
74
75 if (Ccb->DirectorySearchPattern)
76 {
77 ExFreePool(Ccb->DirectorySearchPattern);
78 }
79
81
82 return STATUS_SUCCESS;
83}
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN PFCB _In_opt_ PCCB Ccb
Definition: cdprocs.h:592
struct NTFS_CCB * PNTFS_CCB
struct _FCB * PNTFS_FCB
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
VOID NtfsReleaseFCB(PNTFS_VCB Vcb, PNTFS_FCB Fcb)
Definition: fcb.c:209

Referenced by NtfsClose(), and NtfsCreateFile().

◆ NtfsCreate()

NTSTATUS NtfsCreate ( PNTFS_IRP_CONTEXT  IrpContext)

Definition at line 824 of file create.c.

825{
826 PDEVICE_EXTENSION DeviceExt;
829
830 DeviceObject = IrpContext->DeviceObject;
832 {
833 /* DeviceObject represents FileSystem instead of logical volume */
834 DPRINT("Opening file system\n");
835 IrpContext->Irp->IoStatus.Information = FILE_OPENED;
836 return STATUS_SUCCESS;
837 }
838
839 DeviceExt = DeviceObject->DeviceExtension;
840
841 if (!(IrpContext->Flags & IRPCONTEXT_CANWAIT))
842 {
843 return NtfsMarkIrpContextForQueue(IrpContext);
844 }
845
846 ExAcquireResourceExclusiveLite(&DeviceExt->DirResource,
847 TRUE);
849 IrpContext);
850 ExReleaseResourceLite(&DeviceExt->DirResource);
851
852 return Status;
853}
static NTSTATUS NtfsCreateFile(PDEVICE_OBJECT DeviceObject, PNTFS_IRP_CONTEXT IrpContext)
Definition: create.c:497
#define FILE_OPENED
Definition: nt_native.h:769

Referenced by NtfsDispatch().

◆ NtfsCreateDirectory()

NTSTATUS NtfsCreateDirectory ( PDEVICE_EXTENSION  DeviceExt,
PFILE_OBJECT  FileObject,
BOOLEAN  CaseSensitive,
BOOLEAN  CanWait 
)

Definition at line 883 of file create.c.

887{
888
890 PFILE_RECORD_HEADER FileRecord;
891 PNTFS_ATTR_RECORD NextAttribute;
892 PFILENAME_ATTRIBUTE FilenameAttribute;
893 ULONGLONG ParentMftIndex;
894 ULONGLONG FileMftIndex;
896 PINDEX_ROOT_ATTRIBUTE NewIndexRoot;
897 ULONG MaxIndexRootSize;
898 ULONG RootLength;
899
900 DPRINT("NtfsCreateFileRecord(%p, %p, %s, %s)\n",
901 DeviceExt,
903 CaseSensitive ? "TRUE" : "FALSE",
904 CanWait ? "TRUE" : "FALSE");
905
906 // Start with an empty file record
907 FileRecord = NtfsCreateEmptyFileRecord(DeviceExt);
908 if (!FileRecord)
909 {
910 DPRINT1("ERROR: Unable to allocate memory for file record!\n");
912 }
913
914 // Set the directory flag
915 FileRecord->Flags |= FRH_DIRECTORY;
916
917 // find where the first attribute will be added
918 NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + FileRecord->AttributeOffset);
919
920 // add first attribute, $STANDARD_INFORMATION
921 AddStandardInformation(FileRecord, NextAttribute);
922
923 // advance NextAttribute pointer to the next attribute
924 NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)NextAttribute + (ULONG_PTR)NextAttribute->Length);
925
926 // Add the $FILE_NAME attribute
927 Status = AddFileName(FileRecord, NextAttribute, DeviceExt, FileObject, CaseSensitive, &ParentMftIndex);
928 if (!NT_SUCCESS(Status))
929 {
930 DPRINT1("ERROR: Failed to add the $FILE_NAME attribute for '%wZ'!\n", &FileObject->FileName);
931 ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, FileRecord);
932 return Status;
933 }
934
935 // save a pointer to the filename attribute
936 FilenameAttribute = (PFILENAME_ATTRIBUTE)((ULONG_PTR)NextAttribute + NextAttribute->Resident.ValueOffset);
937
938 // advance NextAttribute pointer to the next attribute
939 NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)NextAttribute + (ULONG_PTR)NextAttribute->Length);
940
941 // Create an empty b-tree to represent our new index
943 if (!NT_SUCCESS(Status))
944 {
945 DPRINT1("ERROR: Failed to create empty B-Tree!\n");
946 ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, FileRecord);
947 return Status;
948 }
949
950 // Calculate maximum size of index root
951 MaxIndexRootSize = DeviceExt->NtfsInfo.BytesPerFileRecord
952 - ((ULONG_PTR)NextAttribute - (ULONG_PTR)FileRecord)
953 - sizeof(ULONG) * 2;
954
955 // Create a new index record from the tree
957 Tree,
958 MaxIndexRootSize,
959 &NewIndexRoot,
960 &RootLength);
961 if (!NT_SUCCESS(Status))
962 {
963 DPRINT1("ERROR: Unable to create empty index root!\n");
965 ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, FileRecord);
966 return Status;
967 }
968
969 // We're done with the B-Tree
971
972 // add the $INDEX_ROOT attribute
973 Status = AddIndexRoot(DeviceExt, FileRecord, NextAttribute, NewIndexRoot, RootLength, L"$I30", 4);
974 if (!NT_SUCCESS(Status))
975 {
976 DPRINT1("ERROR: Failed to add index root to new file record!\n");
977 ExFreePoolWithTag(NewIndexRoot, TAG_NTFS);
978 ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, FileRecord);
979 return Status;
980 }
981
982
983#ifndef NDEBUG
984 NtfsDumpFileRecord(DeviceExt, FileRecord);
985#endif
986
987 // Now that we've built the file record in memory, we need to store it in the MFT.
988 Status = AddNewMftEntry(FileRecord, DeviceExt, &FileMftIndex, CanWait);
989 if (NT_SUCCESS(Status))
990 {
991 // The highest 2 bytes should be the sequence number, unless the parent happens to be root
992 if (FileMftIndex == NTFS_FILE_ROOT)
993 FileMftIndex = FileMftIndex + ((ULONGLONG)NTFS_FILE_ROOT << 48);
994 else
995 FileMftIndex = FileMftIndex + ((ULONGLONG)FileRecord->SequenceNumber << 48);
996
997 DPRINT("New File Reference: 0x%016I64x\n", FileMftIndex);
998
999 // Add the filename attribute to the filename-index of the parent directory
1001 ParentMftIndex,
1002 FileMftIndex,
1003 FilenameAttribute,
1004 CaseSensitive);
1005 }
1006
1007 ExFreePoolWithTag(NewIndexRoot, TAG_NTFS);
1008 ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, FileRecord);
1009
1010 return Status;
1011}
NTSTATUS CreateEmptyBTree(PB_TREE *NewTree)
Definition: btree.c:353
NTSTATUS CreateIndexRootFromBTree(PDEVICE_EXTENSION DeviceExt, PB_TREE Tree, ULONG MaxIndexSize, PINDEX_ROOT_ATTRIBUTE *IndexRoot, ULONG *Length)
Definition: btree.c:915
NTSTATUS AddIndexRoot(PNTFS_VCB Vcb, PFILE_RECORD_HEADER FileRecord, PNTFS_ATTR_RECORD AttributeAddress, PINDEX_ROOT_ATTRIBUTE NewIndexRoot, ULONG RootLength, PCWSTR Name, USHORT NameLength)
Definition: attrib.c:487
NTSTATUS AddFileName(PFILE_RECORD_HEADER FileRecord, PNTFS_ATTR_RECORD AttributeAddress, PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, BOOLEAN CaseSensitive, PULONGLONG ParentMftIndex)
Definition: attrib.c:234
NTSTATUS AddStandardInformation(PFILE_RECORD_HEADER FileRecord, PNTFS_ATTR_RECORD AttributeAddress)
Definition: attrib.c:783
PFILE_RECORD_HEADER NtfsCreateEmptyFileRecord(PDEVICE_EXTENSION DeviceExt)
Definition: create.c:1026
NTSTATUS NtfsAddFilenameToDirectory(PDEVICE_EXTENSION DeviceExt, ULONGLONG DirectoryMftIndex, ULONGLONG FileReferenceNumber, PFILENAME_ATTRIBUTE FilenameAttribute, BOOLEAN CaseSensitive)
Definition: mft.c:3049
VOID NtfsDumpFileRecord(PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER FileRecord)
Definition: mft.c:4342

Referenced by NtfsCreateFile().

◆ NtfsCreateEmptyFileRecord()

PFILE_RECORD_HEADER NtfsCreateEmptyFileRecord ( PDEVICE_EXTENSION  DeviceExt)

Definition at line 1026 of file create.c.

1027{
1028 PFILE_RECORD_HEADER FileRecord;
1029 PNTFS_ATTR_RECORD NextAttribute;
1030
1031 DPRINT("NtfsCreateEmptyFileRecord(%p)\n", DeviceExt);
1032
1033 // allocate memory for file record
1034 FileRecord = ExAllocateFromNPagedLookasideList(&DeviceExt->FileRecLookasideList);
1035 if (!FileRecord)
1036 {
1037 DPRINT1("ERROR: Unable to allocate memory for file record!\n");
1038 return NULL;
1039 }
1040
1041 RtlZeroMemory(FileRecord, DeviceExt->NtfsInfo.BytesPerFileRecord);
1042
1043 FileRecord->Ntfs.Type = NRH_FILE_TYPE;
1044
1045 // calculate USA offset and count
1046 FileRecord->Ntfs.UsaOffset = FIELD_OFFSET(FILE_RECORD_HEADER, MFTRecordNumber) + sizeof(ULONG);
1047
1048 // size of USA (in ULONG's) will be 1 (for USA number) + 1 for every sector the file record uses
1049 FileRecord->BytesAllocated = DeviceExt->NtfsInfo.BytesPerFileRecord;
1050 FileRecord->Ntfs.UsaCount = (FileRecord->BytesAllocated / DeviceExt->NtfsInfo.BytesPerSector) + 1;
1051
1052 // setup other file record fields
1053 FileRecord->SequenceNumber = 1;
1054 FileRecord->AttributeOffset = FileRecord->Ntfs.UsaOffset + (2 * FileRecord->Ntfs.UsaCount);
1056 FileRecord->Flags = FRH_IN_USE;
1057 FileRecord->BytesInUse = FileRecord->AttributeOffset + sizeof(ULONG) * 2;
1058
1059 // find where the first attribute will be added
1060 NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + FileRecord->AttributeOffset);
1061
1062 // mark the (temporary) end of the file-record
1063 NextAttribute->Type = AttributeEnd;
1064 NextAttribute->Length = FILE_RECORD_END;
1065
1066 return FileRecord;
1067}
#define NRH_FILE_TYPE
Definition: ntfs.h:277
#define FRH_IN_USE
Definition: ntfs.h:298
USHORT UsaCount
Definition: ntfs.h:272
USHORT UsaOffset
Definition: ntfs.h:271
NTFS_RECORD_HEADER Ntfs
Definition: ntfs.h:283
ULONG BytesAllocated
Definition: ntfs.h:289

Referenced by IncreaseMftSize(), NtfsCreateDirectory(), and NtfsCreateFileRecord().

◆ NtfsCreateFCB()

PNTFS_FCB NtfsCreateFCB ( PCWSTR  FileName,
PCWSTR  Stream,
PNTFS_VCB  Vcb 
)

Definition at line 67 of file fcb.c.

70{
72
73 ASSERT(Vcb);
74 ASSERT(Vcb->Identifier.Type == NTFS_TYPE_VCB);
75
76 Fcb = ExAllocateFromNPagedLookasideList(&NtfsGlobalData->FcbLookasideList);
77 if (Fcb == NULL)
78 {
79 return NULL;
80 }
81
82 RtlZeroMemory(Fcb, sizeof(NTFS_FCB));
83
86
87 Fcb->Vcb = Vcb;
88
89 if (FileName)
90 {
92 if (wcsrchr(Fcb->PathName, '\\') != 0)
93 {
95 }
96 else
97 {
99 }
100 }
101
102 if (Stream)
103 {
105 }
106 else
107 {
108 Fcb->Stream[0] = UNICODE_NULL;
109 }
110
114
117
118 /* NtfsFastIoCheckIfPossible decides per request */
120
121 return Fcb;
122}
#define wcsrchr
Definition: compat.h:16
#define NTFS_TYPE_VCB
Definition: ntfs.h:90
#define NTFS_TYPE_FCB
Definition: ntfs.h:89
NTSTATUS ExInitializeResourceLite(PULONG res)
Definition: env_spec_w32.h:641
VOID NTAPI FsRtlInitializeFileLock(IN PFILE_LOCK FileLock, IN PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine OPTIONAL, IN PUNLOCK_ROUTINE UnlockRoutine OPTIONAL)
Definition: filelock.c:1266
@ FastIoIsQuestionable
Definition: fsrtltypes.h:242
static IStream Stream
Definition: htmldoc.c:1115
#define UNICODE_NULL
wcscpy
NPAGED_LOOKASIDE_LIST FcbLookasideList
Definition: ntfs.h:180
WCHAR Stream[MAX_PATH]
Definition: ntfs.h:602
ERESOURCE PagingIoResource
Definition: ntfs.h:606
NTFSIDENTIFIER Identifier
Definition: ntfs.h:595
WCHAR * ObjectName
Definition: ntfs.h:603
FILE_LOCK FileLock
Definition: fatstruc.h:1071
WCHAR PathName[MAX_PATH]
Definition: ntfs.h:604
ERESOURCE MainResource
Definition: ntfs.h:607

Referenced by NtfsGetVolumeData(), NtfsMakeFCBFromDirEntry(), NtfsMakeRootFCB(), and NtfsMountVolume().

◆ NtfsCreateFileRecord()

NTSTATUS NtfsCreateFileRecord ( PDEVICE_EXTENSION  DeviceExt,
PFILE_OBJECT  FileObject,
BOOLEAN  CaseSensitive,
BOOLEAN  CanWait 
)

Definition at line 1094 of file create.c.

1098{
1100 PFILE_RECORD_HEADER FileRecord;
1101 PNTFS_ATTR_RECORD NextAttribute;
1102 PFILENAME_ATTRIBUTE FilenameAttribute;
1103 ULONGLONG ParentMftIndex;
1104 ULONGLONG FileMftIndex;
1105
1106 DPRINT("NtfsCreateFileRecord(%p, %p, %s, %s)\n",
1107 DeviceExt,
1108 FileObject,
1109 CaseSensitive ? "TRUE" : "FALSE",
1110 CanWait ? "TRUE" : "FALSE");
1111
1112 // allocate memory for file record
1113 FileRecord = NtfsCreateEmptyFileRecord(DeviceExt);
1114 if (!FileRecord)
1115 {
1116 DPRINT1("ERROR: Unable to allocate memory for file record!\n");
1118 }
1119
1120 // find where the first attribute will be added
1121 NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + FileRecord->AttributeOffset);
1122
1123 // add first attribute, $STANDARD_INFORMATION
1124 AddStandardInformation(FileRecord, NextAttribute);
1125
1126 // advance NextAttribute pointer to the next attribute
1127 NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)NextAttribute + (ULONG_PTR)NextAttribute->Length);
1128
1129 // Add the $FILE_NAME attribute
1130 Status = AddFileName(FileRecord, NextAttribute, DeviceExt, FileObject, CaseSensitive, &ParentMftIndex);
1131 if (!NT_SUCCESS(Status))
1132 {
1133 DPRINT1("ERROR: Failed to add the $FILE_NAME attribute for '%wZ'!\n", &FileObject->FileName);
1134 ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, FileRecord);
1135 return Status;
1136 }
1137
1138 // save a pointer to the filename attribute
1139 FilenameAttribute = (PFILENAME_ATTRIBUTE)((ULONG_PTR)NextAttribute + NextAttribute->Resident.ValueOffset);
1140
1141 // advance NextAttribute pointer to the next attribute
1142 NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)NextAttribute + (ULONG_PTR)NextAttribute->Length);
1143
1144 // add the $DATA attribute
1145 AddData(FileRecord, NextAttribute);
1146
1147#ifndef NDEBUG
1148 // dump file record in memory (for debugging)
1149 NtfsDumpFileRecord(DeviceExt, FileRecord);
1150#endif
1151
1152 // Now that we've built the file record in memory, we need to store it in the MFT.
1153 Status = AddNewMftEntry(FileRecord, DeviceExt, &FileMftIndex, CanWait);
1154 if (NT_SUCCESS(Status))
1155 {
1156 // The highest 2 bytes should be the sequence number, unless the parent happens to be root
1157 if (FileMftIndex == NTFS_FILE_ROOT)
1158 FileMftIndex = FileMftIndex + ((ULONGLONG)NTFS_FILE_ROOT << 48);
1159 else
1160 FileMftIndex = FileMftIndex + ((ULONGLONG)FileRecord->SequenceNumber << 48);
1161
1162 DPRINT("New File Reference: 0x%016I64x\n", FileMftIndex);
1163
1164 // Add the filename attribute to the filename-index of the parent directory
1166 ParentMftIndex,
1167 FileMftIndex,
1168 FilenameAttribute,
1169 CaseSensitive);
1170 }
1171
1172 ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, FileRecord);
1173
1174 return Status;
1175}
NTSTATUS AddData(PFILE_RECORD_HEADER FileRecord, PNTFS_ATTR_RECORD AttributeAddress)
Definition: attrib.c:164

Referenced by NtfsCreateFile().

◆ NtfsDeleteFileRecord()

NTSTATUS NtfsDeleteFileRecord ( PDEVICE_EXTENSION  DeviceExt,
ULONGLONG  MftIndex,
BOOLEAN  CaseSensitive 
)

Definition at line 3470 of file mft.c.

3473{
3475 PFILE_RECORD_HEADER FileRecord;
3476 PNTFS_ATTR_RECORD Attribute;
3477 PNTFS_ATTR_CONTEXT AttributeContext;
3478 ULONG AttributeOffset;
3479
3480 DPRINT("NtfsDeleteFileRecord(%p, %I64u, %s)\n", DeviceExt, MftIndex, CaseSensitive ? "TRUE" : "FALSE");
3481
3482 FileRecord = ExAllocateFromNPagedLookasideList(&DeviceExt->FileRecLookasideList);
3483 if (!FileRecord)
3485
3486 Status = ReadFileRecord(DeviceExt, MftIndex, FileRecord);
3487 if (!NT_SUCCESS(Status))
3488 {
3489 DPRINT1("ERROR: Couldn't read file record %I64u to delete it!\n", MftIndex);
3490 ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, FileRecord);
3491 return Status;
3492 }
3493
3494 // Remove every name this file has from its parent's index before anything is freed, so a
3495 // failure leaves the file whole instead of an entry pointing at a released record. A file
3496 // with both a long name and an 8.3 name is indexed twice, and both parents are named by
3497 // the attributes themselves.
3498 Attribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + FileRecord->AttributeOffset);
3499 AttributeOffset = FileRecord->AttributeOffset;
3500
3501 while (AttributeOffset < DeviceExt->NtfsInfo.BytesPerFileRecord &&
3502 Attribute->Type != AttributeEnd)
3503 {
3504 if (Attribute->Type == AttributeFileName && !Attribute->IsNonResident)
3505 {
3507 (PFILENAME_ATTRIBUTE)((ULONG_PTR)Attribute + Attribute->Resident.ValueOffset);
3508
3510 FileName->DirectoryFileReferenceNumber & NTFS_MFT_MASK,
3511 FileName,
3512 CaseSensitive);
3513 if (!NT_SUCCESS(Status))
3514 {
3515 DPRINT1("ERROR: Failed to remove '%.*S' from directory %I64u!\n",
3516 FileName->NameLength,
3517 FileName->Name,
3518 FileName->DirectoryFileReferenceNumber & NTFS_MFT_MASK);
3519 ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, FileRecord);
3520 return Status;
3521 }
3522 }
3523
3524 if (Attribute->Length == 0)
3525 break;
3526
3527 AttributeOffset += Attribute->Length;
3528 Attribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + AttributeOffset);
3529 }
3530
3531 // Release the clusters held by every non-resident attribute
3532 Attribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + FileRecord->AttributeOffset);
3533 AttributeOffset = FileRecord->AttributeOffset;
3534
3535 while (AttributeOffset < DeviceExt->NtfsInfo.BytesPerFileRecord &&
3536 Attribute->Type != AttributeEnd)
3537 {
3538 if (Attribute->IsNonResident)
3539 {
3540 Status = FindAttribute(DeviceExt,
3541 FileRecord,
3542 Attribute->Type,
3543 (PCWSTR)((ULONG_PTR)Attribute + Attribute->NameOffset),
3544 Attribute->NameLength,
3545 &AttributeContext,
3546 NULL);
3547 if (NT_SUCCESS(Status))
3548 {
3549 ULONGLONG ClusterCount = Attribute->NonResident.HighestVCN - Attribute->NonResident.LowestVCN + 1;
3550
3551 Status = FreeClusters(DeviceExt, AttributeContext, AttributeOffset, FileRecord, (ULONG)ClusterCount);
3552 if (!NT_SUCCESS(Status))
3553 {
3554 DPRINT1("ERROR: Failed to free clusters of attribute 0x%lx of file %I64u!\n",
3555 Attribute->Type, MftIndex);
3556 }
3557
3558 ReleaseAttributeContext(AttributeContext);
3559 }
3560 }
3561
3562 if (Attribute->Length == 0)
3563 break;
3564
3565 AttributeOffset += Attribute->Length;
3566 Attribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + AttributeOffset);
3567 }
3568
3569 ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, FileRecord);
3570
3571 return FreeMftEntry(DeviceExt, MftIndex);
3572}
NTSTATUS FreeClusters(PNTFS_VCB Vcb, PNTFS_ATTR_CONTEXT AttrContext, ULONG AttrOffset, PFILE_RECORD_HEADER FileRecord, ULONG ClustersToFree)
Definition: attrib.c:1101
NTSTATUS NtfsRemoveFilenameFromDirectory(PDEVICE_EXTENSION DeviceExt, ULONGLONG DirectoryMftIndex, PFILENAME_ATTRIBUTE FilenameAttribute, BOOLEAN CaseSensitive)
Definition: mft.c:3297
NTSTATUS FreeMftEntry(PDEVICE_EXTENSION DeviceExt, ULONGLONG MftIndex)
Definition: mft.c:3336
TCHAR Name[MAX_PATH]
Definition: filecomp.c:349
const uint16_t * PCWSTR
Definition: typedefs.h:57

Referenced by NtfsCleanupFile(), and NtfsClearRenameTarget().

◆ NtfsDestroyFCB()

VOID NtfsDestroyFCB ( PNTFS_FCB  Fcb)

Definition at line 126 of file fcb.c.

127{
128 ASSERT(Fcb);
130
131 /* The volume stream belongs to the VCB */
134
138
139 ExFreeToNPagedLookasideList(&NtfsGlobalData->FcbLookasideList, Fcb);
140}
#define FCB_IS_VOLUME_STREAM
Definition: ntfs.h:584
#define ExDeleteResourceLite(res)
Definition: env_spec_w32.h:647
VOID NTAPI FsRtlUninitializeFileLock(IN PFILE_LOCK FileLock)
Definition: filelock.c:1283
PFILE_OBJECT FileObject
Definition: ntfs.h:599
#define ObDereferenceObject
Definition: obfuncs.h:203

Referenced by NtfsReleaseFCB().

◆ NtfsDeviceControl()

NTSTATUS NtfsDeviceControl ( PNTFS_IRP_CONTEXT  IrpContext)

Definition at line 36 of file devctl.c.

37{
38 PDEVICE_EXTENSION DeviceExt;
39 PIRP Irp = IrpContext->Irp;
40
41 DeviceExt = IrpContext->DeviceObject->DeviceExtension;
43
44 /* Lower driver will complete - we don't have to */
45 IrpContext->Flags &= ~IRPCONTEXT_COMPLETE;
46
47 return IoCallDriver(DeviceExt->StorageDevice, Irp);
48}
#define IoSkipCurrentIrpStackLocation(Irp)
Definition: ntifs_ex.h:421
#define IoCallDriver
Definition: irp.c:1257
PVOID DeviceExtension
Definition: env_spec_w32.h:418

Referenced by NtfsDispatch().

◆ NtfsDeviceIoControl()

NTSTATUS NtfsDeviceIoControl ( IN PDEVICE_OBJECT  DeviceObject,
IN ULONG  ControlCode,
IN PVOID  InputBuffer,
IN ULONG  InputBufferSize,
IN OUT PVOID  OutputBuffer,
IN OUT PULONG  OutputBufferSize,
IN BOOLEAN  Override 
)

Definition at line 1029 of file blockdev.c.

1036{
1039 KEVENT Event;
1040 PIRP Irp;
1042
1044
1045 IoStatus.Status = STATUS_SUCCESS;
1046 IoStatus.Information = 0;
1047
1048 DPRINT("Building device I/O control request ...\n");
1055 FALSE,
1056 &Event,
1057 &IoStatus);
1058 if (Irp == NULL)
1059 {
1060 DPRINT("IoBuildDeviceIoControlRequest() failed\n");
1062 }
1063
1064 if (Override)
1065 {
1068 }
1069
1070 DPRINT("Calling IO Driver... with irp %p\n", Irp);
1072 if (Status == STATUS_PENDING)
1073 {
1075 Status = IoStatus.Status;
1076 }
1077
1078 if (OutputBufferSize)
1079 {
1080 *OutputBufferSize = IoStatus.Information;
1081 }
1082
1083 return Status;
1084}
_In_ ULONG InputBufferSize
Definition: dispmprt.h:616
_Check_return_ _In_ DXGK_EVENT_TYPE _In_ ULONG Event
Definition: dispmprt.h:1287
_In_ ULONG _In_ ULONG OutputBufferSize
Definition: dispmprt.h:618
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
__in UCHAR __in POWER_STATE __in_opt PVOID __in PIO_STATUS_BLOCK IoStatus
Definition: mxum.h:159
#define KernelMode
Definition: asm.h:38
@ NotificationEvent
PIRP NTAPI IoBuildDeviceIoControlRequest(IN ULONG IoControlCode, IN PDEVICE_OBJECT DeviceObject, IN PVOID InputBuffer, IN ULONG InputBufferLength, IN PVOID OutputBuffer, IN ULONG OutputBufferLength, IN BOOLEAN InternalDeviceIoControl, IN PKEVENT Event, IN PIO_STATUS_BLOCK IoStatusBlock)
Definition: irp.c:913
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR OutputBuffer
Definition: wdfiotarget.h:863
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR InputBuffer
Definition: wdfiotarget.h:953
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:639
_IRQL_requires_same_ typedef _In_ ULONG ControlCode
Definition: wmitypes.h:55
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2702
#define SL_OVERRIDE_VERIFY_VOLUME
Definition: iotypes.h:1823
@ Executive
Definition: ketypes.h:467

Referenced by NtfsGetVolumeData(), and NtfsHasFileSystem().

◆ NtfsDirectoryControl()

NTSTATUS NtfsDirectoryControl ( PNTFS_IRP_CONTEXT  IrpContext)

Definition at line 793 of file dirctl.c.

794{
796
797 DPRINT("NtfsDirectoryControl() called\n");
798
799 /* Handlers that fill the caller's buffer overwrite this with the byte count */
800 IrpContext->Irp->IoStatus.Information = 0;
801
802 switch (IrpContext->MinorFunction)
803 {
805 Status = NtfsQueryDirectory(IrpContext);
806 break;
807
809 DPRINT1("IRP_MN_NOTIFY_CHANGE_DIRECTORY\n");
811 break;
812
813 default:
815 break;
816 }
817
818 if (Status == STATUS_PENDING && IrpContext->Flags & IRPCONTEXT_COMPLETE)
819 {
820 return NtfsMarkIrpContextForQueue(IrpContext);
821 }
822
823 return Status;
824}
NTSTATUS NtfsQueryDirectory(PNTFS_IRP_CONTEXT IrpContext)
Definition: dirctl.c:544
#define IRP_MN_QUERY_DIRECTORY
Definition: rdpdr.c:55
#define IRP_MN_NOTIFY_CHANGE_DIRECTORY
Definition: rdpdr.c:56
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138

Referenced by NtfsDispatch().

◆ NtfsDumpData()

VOID NtfsDumpData ( ULONG_PTR  Buffer,
ULONG  Length 
)

Definition at line 4305 of file mft.c.

4306{
4307 ULONG i, j;
4308
4309 // dump binary data, 8 bytes at a time
4310 for (i = 0; i < Length; i += 8)
4311 {
4312 // display current offset, in hex
4313 DbgPrint("\t%03x\t", i);
4314
4315 // display hex value of each of the next 8 bytes
4316 for (j = 0; j < 8; j++)
4317 DbgPrint("%02x ", *(PUCHAR)(Buffer + i + j));
4318 DbgPrint("\n");
4319 }
4320}
Definition: bufpool.h:45
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 GLint GLint j
Definition: glfuncs.h:250

◆ NtfsDumpDataRuns()

VOID NtfsDumpDataRuns ( PVOID  StartOfRun,
ULONGLONG  CurrentLCN 
)

Definition at line 1785 of file attrib.c.

1787{
1788 PUCHAR DataRun = StartOfRun;
1789 LONGLONG DataRunOffset;
1790 ULONGLONG DataRunLength;
1791
1792 if (CurrentLCN == 0)
1793 {
1794 DPRINT("Dumping data runs.\n\tData:\n\t\t");
1795 NtfsDumpDataRunData(StartOfRun);
1796 DbgPrint("\n\tRuns:\n\t\tOff\t\tLCN\t\tLength\n");
1797 }
1798
1799 DataRun = DecodeRun(DataRun, &DataRunOffset, &DataRunLength);
1800
1801 if (DataRunOffset != -1)
1802 CurrentLCN += DataRunOffset;
1803
1804 DbgPrint("\t\t%I64d\t", DataRunOffset);
1805 if (DataRunOffset < 99999)
1806 DbgPrint("\t");
1807 DbgPrint("%I64u\t", CurrentLCN);
1808 if (CurrentLCN < 99999)
1809 DbgPrint("\t");
1810 DbgPrint("%I64u\n", DataRunLength);
1811
1812 if (*DataRun == 0)
1813 DbgPrint("\t\t00\n");
1814 else
1815 NtfsDumpDataRuns(DataRun, CurrentLCN);
1816}
VOID NtfsDumpDataRunData(PUCHAR DataRun)
Definition: attrib.c:1753

Referenced by AddRun(), FreeClusters(), and NtfsDumpDataRuns().

◆ NtfsDumpFileAttributes()

VOID NtfsDumpFileAttributes ( PDEVICE_EXTENSION  Vcb,
PFILE_RECORD_HEADER  FileRecord 
)

Definition at line 1820 of file attrib.c.

1822{
1825 PNTFS_ATTR_RECORD Attribute;
1826
1827 Status = FindFirstAttribute(&Context, Vcb, FileRecord, FALSE, &Attribute);
1828 while (NT_SUCCESS(Status))
1829 {
1830 NtfsDumpAttribute(Vcb, Attribute);
1831
1832 Status = FindNextAttribute(&Context, &Attribute);
1833 }
1834
1836}
static VOID NtfsDumpAttribute(PDEVICE_EXTENSION Vcb, PNTFS_ATTR_RECORD Attribute)
Definition: attrib.c:1647

Referenced by IncreaseMftSize(), NtfsDumpFileRecord(), NtfsGetBothDirectoryInformation(), NtfsGetDirectoryInformation(), NtfsGetFullDirectoryInformation(), NtfsGetNamesInformation(), and NtfsGetVolumeData().

◆ NtfsDumpFileRecord()

VOID NtfsDumpFileRecord ( PDEVICE_EXTENSION  Vcb,
PFILE_RECORD_HEADER  FileRecord 
)

Definition at line 4342 of file mft.c.

4344{
4345 ULONG i, j;
4346
4347 // dump binary data, 8 bytes at a time
4348 for (i = 0; i < FileRecord->BytesInUse; i += 8)
4349 {
4350 // display current offset, in hex
4351 DbgPrint("\t%03x\t", i);
4352
4353 // display hex value of each of the next 8 bytes
4354 for (j = 0; j < 8; j++)
4355 DbgPrint("%02x ", *(PUCHAR)((ULONG_PTR)FileRecord + i + j));
4356 DbgPrint("\n");
4357 }
4358
4359 NtfsDumpFileAttributes(Vcb, FileRecord);
4360}
VOID NtfsDumpFileAttributes(PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER FileRecord)
Definition: attrib.c:1820

Referenced by AddFilenameToDirectoryWorker(), NtfsCreateDirectory(), and NtfsCreateFileRecord().

◆ NtfsExtendAllocation()

NTSTATUS NtfsExtendAllocation ( _In_ PDEVICE_EXTENSION  Vcb,
_In_ PNTFS_ATTR_CONTEXT  AttrContext,
_In_ ULONG  AttrOffset,
_In_ PFILE_RECORD_HEADER  FileRecord,
_In_ ULONGLONG  AllocationSize 
)

Definition at line 753 of file mft.c.

759{
761 ULONG BytesPerCluster = Vcb->NtfsInfo.BytesPerCluster;
762 PNTFS_ATTR_RECORD DestinationAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + AttrOffset);
763 ULONGLONG ExistingClusters = AttrContext->pRecord->NonResident.AllocatedSize / BytesPerCluster;
764 ULONG ClustersNeeded;
765 ULONG DesiredCluster = 0;
766 LONGLONG LastVbn;
767 LONGLONG LastLbn;
768 ULONG NextAssignedCluster;
769 ULONG AssignedClusters;
770
771 ASSERT(AttrContext->pRecord->IsNonResident);
772 ASSERT(AllocationSize % BytesPerCluster == 0);
773
774 if (AttrContext->pRecord->NonResident.AllocatedSize >= AllocationSize)
775 return STATUS_SUCCESS;
776
777 ClustersNeeded = (ULONG)(AllocationSize / BytesPerCluster - ExistingClusters);
778
779 /* Ask for the clusters right after the last one the stream owns. The
780 * tail of a sparse stream is a hole, so look at the last mapping, not
781 * at HighestVCN. */
782 if (ExistingClusters != 0 &&
783 FsRtlLookupLastLargeMcbEntry(&AttrContext->DataRunsMCB, &LastVbn, &LastLbn) &&
784 LastLbn != -1)
785 {
786 DesiredCluster = (ULONG)LastLbn + 1;
787 }
788
789 DPRINT("DesiredCluster: %lu\n", DesiredCluster);
790 DPRINT("Highest VCN of record: %I64u\n", AttrContext->pRecord->NonResident.HighestVCN);
791
792 while (ClustersNeeded > 0)
793 {
795 DesiredCluster,
796 ClustersNeeded,
797 &NextAssignedCluster,
798 &AssignedClusters);
799
800 if (!NT_SUCCESS(Status))
801 {
802 DPRINT1("Error: Unable to allocate requested clusters!\n");
803 return Status;
804 }
805
806 // now we need to add the clusters we allocated to the data run
807 Status = AddRun(Vcb, AttrContext, AttrOffset, FileRecord, NextAssignedCluster, AssignedClusters);
808 if (!NT_SUCCESS(Status))
809 {
810 DPRINT1("Error: Unable to add data run!\n");
811 return Status;
812 }
813
814 /* AddRun() places the next run after HighestVCN only once the
815 * attribute owns clusters, so count these before looping */
816 AttrContext->pRecord->NonResident.AllocatedSize += (ULONGLONG)AssignedClusters * BytesPerCluster;
817
818 ClustersNeeded -= AssignedClusters;
819 DesiredCluster = NextAssignedCluster + AssignedClusters;
820 }
821
822 DestinationAttribute->NonResident.AllocatedSize = AttrContext->pRecord->NonResident.AllocatedSize;
823 DestinationAttribute->NonResident.HighestVCN = AttrContext->pRecord->NonResident.HighestVCN;
824
825 return STATUS_SUCCESS;
826}
_In_ ULONG AllocationSize
Definition: dispmprt.h:712
NTSTATUS AddRun(PNTFS_VCB Vcb, PNTFS_ATTR_CONTEXT AttrContext, ULONG AttrOffset, PFILE_RECORD_HEADER FileRecord, ULONGLONG NextAssignedCluster, ULONG RunLength)
Definition: attrib.c:591
NTSTATUS NtfsAllocateClusters(PDEVICE_EXTENSION DeviceExt, ULONG FirstDesiredCluster, ULONG DesiredClusters, PULONG FirstAssignedCluster, PULONG AssignedClusters)
Definition: volinfo.c:213
BOOLEAN NTAPI FsRtlLookupLastLargeMcbEntry(IN PLARGE_MCB Mcb, OUT PLONGLONG Vbn, OUT PLONGLONG Lbn)
Definition: largemcb.c:718

Referenced by NtfsGrowStream(), NtfsResizeAllocation(), and SetNonResidentAttributeDataLength().

◆ NtfsFCBInitializeCache()

NTSTATUS NtfsFCBInitializeCache ( PNTFS_VCB  Vcb,
PNTFS_FCB  Fcb 
)

Definition at line 334 of file fcb.c.

336{
339 PNTFS_CCB newCCB;
340
341 FileObject = IoCreateStreamFileObject(NULL, Vcb->StorageDevice);
342
344 if (newCCB == NULL)
345 {
347 }
348
349 RtlZeroMemory(newCCB, sizeof(NTFS_CCB));
350
351 newCCB->Identifier.Type = NTFS_TYPE_CCB;
352 newCCB->Identifier.Size = sizeof(NTFS_TYPE_CCB);
353
354 FileObject->SectionObjectPointer = &Fcb->SectionObjectPointers;
355 FileObject->FsContext = Fcb;
356 FileObject->FsContext2 = newCCB;
357 newCCB->PtrFileObject = FileObject;
359 Fcb->Vcb = Vcb;
360
363 {
366 FALSE,
368 Fcb);
369 }
371 {
372 FileObject->FsContext2 = NULL;
373 ExFreePoolWithTag(newCCB, TAG_CCB);
376 return _SEH2_GetExceptionCode();
377 }
378 _SEH2_END;
379
380 /* The FCB keeps its reference, tearing down the cache map would otherwise free the stream */
382
383 return Status;
384}
PFILE_OBJECT NTAPI IoCreateStreamFileObject(IN PFILE_OBJECT FileObject, IN PDEVICE_OBJECT DeviceObject)
Definition: file.c:3186

Referenced by NtfsMakeFCBFromDirEntry(), and NtfsMakeRootFCB().

◆ NtfsFCBIsCompressed()

BOOLEAN NtfsFCBIsCompressed ( PNTFS_FCB  Fcb)

Definition at line 173 of file fcb.c.

174{
176}
#define NTFS_FILE_TYPE_COMPRESSED
Definition: ntfs.h:256
FILENAME_ATTRIBUTE Entry
Definition: ntfs.h:625

Referenced by NtfsCachedRead(), NtfsCachedWrite(), NtfsFastIoCheckIfPossible(), NtfsQueryDirectory(), NtfsReadFile(), and NtfsWriteFile().

◆ NtfsFCBIsDirectory()

◆ NtfsFCBIsEncrypted()

BOOLEAN NtfsFCBIsEncrypted ( PNTFS_FCB  Fcb)

Definition at line 179 of file fcb.c.

180{
182}
#define NTFS_FILE_TYPE_ENCRYPTED
Definition: ntfs.h:258

Referenced by NtfsCachedRead(), NtfsFastIoCheckIfPossible(), and NtfsReadFile().

◆ NtfsFCBIsReparsePoint()

BOOLEAN NtfsFCBIsReparsePoint ( PNTFS_FCB  Fcb)

Definition at line 166 of file fcb.c.

167{
169}
#define NTFS_FILE_TYPE_REPARSE
Definition: ntfs.h:255

Referenced by NtfsCreateFile().

◆ NtfsFCBIsRoot()

BOOLEAN NtfsFCBIsRoot ( PNTFS_FCB  Fcb)

Definition at line 185 of file fcb.c.

186{
187 return (wcscmp(Fcb->PathName, L"\\") == 0);
188}
_ACRTIMP int __cdecl wcscmp(const wchar_t *, const wchar_t *)
Definition: wcs.c:1977

Referenced by NtfsBuildRenamePath(), NtfsMakeAbsoluteFilename(), NtfsMakeFCBFromDirEntry(), NtfsSetDispositionInformation(), and NtfsSetRenameInformation().

◆ NtfsFileFlagsToAttributes()

VOID NtfsFileFlagsToAttributes ( ULONG  NtfsAttributes,
PULONG  FileAttributes 
)

Definition at line 105 of file misc.c.

107{
108 *FileAttributes = NtfsAttributes;
109 if ((NtfsAttributes & NTFS_FILE_TYPE_DIRECTORY) == NTFS_FILE_TYPE_DIRECTORY)
110 {
111 *FileAttributes = NtfsAttributes & ~NTFS_FILE_TYPE_DIRECTORY;
113 }
114
115 if (NtfsAttributes == 0)
117}
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
_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
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705

Referenced by NtfsGetAttributeTagInformation(), NtfsGetBasicInformation(), NtfsGetBothDirectoryInformation(), NtfsGetDirectoryInformation(), NtfsGetFullDirectoryInformation(), and NtfsGetNetworkOpenInformation().

◆ NtfsFileSystemControl()

NTSTATUS NtfsFileSystemControl ( PNTFS_IRP_CONTEXT  IrpContext)

Definition at line 1045 of file fsctl.c.

1046{
1048 PIRP Irp;
1050
1051 DPRINT("NtfsFileSystemControl() called\n");
1052
1053 DeviceObject = IrpContext->DeviceObject;
1054 Irp = IrpContext->Irp;
1056
1057 switch (IrpContext->MinorFunction)
1058 {
1059 case IRP_MN_KERNEL_CALL:
1060 DPRINT1("NTFS: IRP_MN_USER_FS_REQUEST\n");
1062 break;
1063
1066 break;
1067
1069 DPRINT("NTFS: IRP_MN_MOUNT_VOLUME\n");
1071 break;
1072
1074 DPRINT1("NTFS: IRP_MN_VERIFY_VOLUME\n");
1076 break;
1077
1078 default:
1079 DPRINT1("NTFS FSC: MinorFunction %d\n", IrpContext->MinorFunction);
1081 break;
1082 }
1083
1084 return Status;
1085}
static NTSTATUS NtfsVerifyVolume(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: fsctl.c:608
static NTSTATUS NtfsMountVolume(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: fsctl.c:427
static NTSTATUS NtfsUserFsRequest(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: fsctl.c:978
#define IRP_MN_VERIFY_VOLUME
Definition: iotypes.h:4421
#define IRP_MN_USER_FS_REQUEST
Definition: iotypes.h:4419
#define IRP_MN_KERNEL_CALL
Definition: iotypes.h:4424
#define IRP_MN_MOUNT_VOLUME
Definition: iotypes.h:4420

Referenced by NtfsDispatch().

◆ NtfsFindFileAt()

NTSTATUS NtfsFindFileAt ( PDEVICE_EXTENSION  Vcb,
PUNICODE_STRING  SearchPattern,
PULONG  FirstEntry,
PFILE_RECORD_HEADER *  FileRecord,
PULONGLONG  MFTIndex,
ULONGLONG  CurrentMFTIndex,
BOOLEAN  CaseSensitive 
)

Definition at line 4363 of file mft.c.

4370{
4372
4373 DPRINT("NtfsFindFileAt(%p, %wZ, %lu, %p, %p, %I64x, %s)\n",
4374 Vcb,
4375 SearchPattern,
4376 *FirstEntry,
4377 FileRecord,
4378 MFTIndex,
4379 CurrentMFTIndex,
4380 (CaseSensitive ? "TRUE" : "FALSE"));
4381
4382 Status = NtfsFindMftRecord(Vcb, CurrentMFTIndex, SearchPattern, FirstEntry, TRUE, CaseSensitive, &CurrentMFTIndex);
4383 if (!NT_SUCCESS(Status))
4384 {
4385 DPRINT("NtfsFindFileAt: NtfsFindMftRecord() failed with status 0x%08lx\n", Status);
4386 return Status;
4387 }
4388
4389 *FileRecord = ExAllocateFromNPagedLookasideList(&Vcb->FileRecLookasideList);
4390 if (*FileRecord == NULL)
4391 {
4392 DPRINT("NtfsFindFileAt: Can't allocate MFT record\n");
4394 }
4395
4396 Status = ReadFileRecord(Vcb, CurrentMFTIndex, *FileRecord);
4397 if (!NT_SUCCESS(Status))
4398 {
4399 DPRINT("NtfsFindFileAt: Can't read MFT record\n");
4400 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, *FileRecord);
4401 return Status;
4402 }
4403
4404 *MFTIndex = CurrentMFTIndex;
4405
4406 return STATUS_SUCCESS;
4407}
NTSTATUS NtfsFindMftRecord(PDEVICE_EXTENSION Vcb, ULONGLONG MFTIndex, PUNICODE_STRING FileName, PULONG FirstEntry, BOOLEAN DirSearch, BOOLEAN CaseSensitive, ULONGLONG *OutMFTIndex)
Definition: mft.c:4151

Referenced by NtfsQueryDirectory().

◆ NtfsFindMftRecord()

NTSTATUS NtfsFindMftRecord ( PDEVICE_EXTENSION  Vcb,
ULONGLONG  MFTIndex,
PUNICODE_STRING  FileName,
PULONG  FirstEntry,
BOOLEAN  DirSearch,
BOOLEAN  CaseSensitive,
ULONGLONG *  OutMFTIndex 
)

Definition at line 4151 of file mft.c.

4158{
4159 PFILE_RECORD_HEADER MftRecord;
4160 PNTFS_ATTR_CONTEXT IndexRootCtx;
4161 PINDEX_ROOT_ATTRIBUTE IndexRoot;
4162 PCHAR IndexRecord;
4163 PINDEX_ENTRY_ATTRIBUTE IndexEntry, IndexEntryEnd;
4165 ULONG CurrentEntry = 0;
4166
4167 DPRINT("NtfsFindMftRecord(%p, %I64d, %wZ, %lu, %s, %s, %p)\n",
4168 Vcb,
4169 MFTIndex,
4170 FileName,
4171 *FirstEntry,
4172 DirSearch ? "TRUE" : "FALSE",
4173 CaseSensitive ? "TRUE" : "FALSE",
4174 OutMFTIndex);
4175
4176 MftRecord = ExAllocateFromNPagedLookasideList(&Vcb->FileRecLookasideList);
4177 if (MftRecord == NULL)
4178 {
4180 }
4181
4182 Status = ReadFileRecord(Vcb, MFTIndex, MftRecord);
4183 if (!NT_SUCCESS(Status))
4184 {
4185 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, MftRecord);
4186 return Status;
4187 }
4188
4189 ASSERT(MftRecord->Ntfs.Type == NRH_FILE_TYPE);
4190 Status = FindAttribute(Vcb, MftRecord, AttributeIndexRoot, L"$I30", 4, &IndexRootCtx, NULL);
4191 if (!NT_SUCCESS(Status))
4192 {
4193 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, MftRecord);
4194 return Status;
4195 }
4196
4197 IndexRecord = ExAllocatePoolWithTag(NonPagedPool, Vcb->NtfsInfo.BytesPerIndexRecord, TAG_NTFS);
4198 if (IndexRecord == NULL)
4199 {
4200 ReleaseAttributeContext(IndexRootCtx);
4201 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, MftRecord);
4203 }
4204
4205 ReadAttribute(Vcb, IndexRootCtx, 0, IndexRecord, Vcb->NtfsInfo.BytesPerIndexRecord);
4206 IndexRoot = (PINDEX_ROOT_ATTRIBUTE)IndexRecord;
4207 IndexEntry = (PINDEX_ENTRY_ATTRIBUTE)((PCHAR)&IndexRoot->Header + IndexRoot->Header.FirstEntryOffset);
4208 /* Index root is always resident. */
4209 /* TotalSizeOfEntries is measured from the index header, not from the
4210 * start of the attribute, and FirstEntryOffset above already is. */
4211 IndexEntryEnd = (PINDEX_ENTRY_ATTRIBUTE)((ULONG_PTR)&IndexRoot->Header + IndexRoot->Header.TotalSizeOfEntries);
4212 ReleaseAttributeContext(IndexRootCtx);
4213
4214 DPRINT("IndexRecordSize: %x IndexBlockSize: %x\n", Vcb->NtfsInfo.BytesPerIndexRecord, IndexRoot->SizeOfEntry);
4215
4217 MftRecord,
4218 (PINDEX_ROOT_ATTRIBUTE)IndexRecord,
4219 IndexRoot->SizeOfEntry,
4220 IndexEntry,
4221 IndexEntryEnd,
4222 FileName,
4223 FirstEntry,
4224 &CurrentEntry,
4225 DirSearch,
4226 CaseSensitive,
4227 OutMFTIndex);
4228
4229 ExFreePoolWithTag(IndexRecord, TAG_NTFS);
4230 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, MftRecord);
4231
4232 return Status;
4233}
struct INDEX_ROOT_ATTRIBUTE * PINDEX_ROOT_ATTRIBUTE
NTSTATUS BrowseIndexEntries(PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER MftRecord, PINDEX_ROOT_ATTRIBUTE IndexRecord, ULONG IndexBlockSize, PINDEX_ENTRY_ATTRIBUTE FirstEntry, PINDEX_ENTRY_ATTRIBUTE LastEntry, PUNICODE_STRING FileName, PULONG StartEntry, PULONG CurrentEntry, BOOLEAN DirSearch, BOOLEAN CaseSensitive, ULONGLONG *OutMFTIndex)
Definition: mft.c:3976

Referenced by NtfsFindFileAt(), and NtfsLookupFileAt().

◆ NtfsFlushBuffers()

NTSTATUS NtfsFlushBuffers ( PNTFS_IRP_CONTEXT  IrpContext)

Definition at line 107 of file flush.c.

108{
109 PDEVICE_EXTENSION DeviceExt;
112 NTSTATUS DeviceStatus;
113
114 DPRINT("NtfsFlushBuffers(%p)\n", IrpContext);
115
116 IrpContext->Irp->IoStatus.Information = 0;
117
118 /* Nothing is mounted on the main device object */
119 if (IrpContext->DeviceObject == NtfsGlobalData->DeviceObject)
120 {
121 return STATUS_SUCCESS;
122 }
123
124 DeviceExt = IrpContext->DeviceObject->DeviceExtension;
125
126 if (DeviceExt->Flags & VCB_VOLUME_DISMOUNTED)
127 {
129 }
130
131 /* Flushing waits on the disk */
132 if (!(IrpContext->Flags & IRPCONTEXT_CANWAIT))
133 return NtfsMarkIrpContextForQueue(IrpContext);
134
135 /* Cached writes only reach the disk once the cache lets them go */
136 Fcb = (PNTFS_FCB)IrpContext->FileObject->FsContext;
139 else if (Fcb != NULL && Fcb->Identifier.Type == NTFS_TYPE_FCB && (Fcb->Flags & FCB_IS_VOLUME))
140 Status = NtfsFlushVolumeFiles(DeviceExt);
141 else
143
144 DeviceStatus = NtfsFlushDevice(DeviceExt->StorageDevice);
145
146 return NT_SUCCESS(Status) ? DeviceStatus : Status;
147}
#define VCB_VOLUME_DISMOUNTED
Definition: ntfs.h:148
#define FCB_IS_VOLUME
Definition: ntfs.h:585
NTSTATUS NtfsFlushDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: blockdev.c:964
static NTSTATUS NTAPI NtfsFlushVolumeFiles(_In_ PDEVICE_EXTENSION DeviceExt)
Definition: flush.c:36
static NTSTATUS NTAPI NtfsFlushFileCache(_In_ PNTFS_FCB Fcb)
Definition: flush.c:16
#define STATUS_VOLUME_DISMOUNTED
Definition: ntstatus.h:869

Referenced by NtfsDispatch().

◆ NtfsFlushDevice()

NTSTATUS NtfsFlushDevice ( IN PDEVICE_OBJECT  DeviceObject)

Definition at line 964 of file blockdev.c.

965{
966 NTFS_IO_CONTEXT IoContext;
969 PIRP Irp;
970
971 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
972 if (Irp == NULL)
973 {
974 DPRINT1("IoAllocateIrp failed!\n");
976 }
977
978 RtlZeroMemory(&IoContext, sizeof(IoContext));
980 IoContext.Status = STATUS_SUCCESS;
981 IoContext.IrpCount = 1;
982
984 Stack->MajorFunction = IRP_MJ_FLUSH_BUFFERS;
985
988 &IoContext,
989 TRUE,
990 TRUE,
991 TRUE);
992
994
996
997 Status = (NTSTATUS)IoContext.Status;
998
1001 {
1003 }
1004
1005 DPRINT("NtfsFlushDevice() done (Status %lx)\n", Status);
1006
1007 return Status;
1008}
#define VOID
Definition: acefi.h:82
#define STATUS_NOT_SUPPORTED
Definition: d3dkmdt.h:48
#define NTSTATUS
Definition: precomp.h:19
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:490
static NTSTATUS NTAPI NtfsIoRunCompletionRoutine(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
Definition: blockdev.c:162
PIRP NTAPI IoAllocateIrp(IN CCHAR StackSize, IN BOOLEAN ChargeQuota)
Definition: irp.c:647
volatile LONG IrpCount
Definition: ntfs.h:539
volatile LONG Status
Definition: ntfs.h:540
KEVENT SyncEvent
Definition: ntfs.h:550
#define IRP_MJ_FLUSH_BUFFERS

Referenced by NtfsFlushBuffers().

◆ NtfsFreeIoRunList()

VOID NtfsFreeIoRunList ( IN OUT PNTFS_IO_RUN_LIST  RunList)

Definition at line 140 of file blockdev.c.

141{
142 if (RunList->Runs != RunList->StackRuns && RunList->Runs != NULL)
143 {
144 ExFreePoolWithTag(RunList->Runs, TAG_IO_RUNS);
145 }
146
147 RunList->Runs = NULL;
148 RunList->Count = 0;
149 RunList->Capacity = 0;
150 RunList->TotalLength = 0;
151}

Referenced by NtfsReadDisk(), NtfsReadWriteVolume(), NtfsWriteDisk(), ReadAttributeToIrp(), and WriteAttributeFromIrp().

◆ NtfsFreeVolumeBitmap()

VOID NtfsFreeVolumeBitmap ( _In_ PDEVICE_EXTENSION  DeviceExt)

Definition at line 132 of file volinfo.c.

134{
135 if (DeviceExt->BitmapBuffer != NULL)
136 {
137 ExFreePoolWithTag(DeviceExt->BitmapBuffer, TAG_NTFS);
138 DeviceExt->BitmapBuffer = NULL;
139 }
140
141 if (DeviceExt->BitmapContext != NULL)
142 {
143 ReleaseAttributeContext(DeviceExt->BitmapContext);
144 DeviceExt->BitmapContext = NULL;
145 }
146}

Referenced by NtfsLoadVolumeBitmap().

◆ NtfsFsdDispatch()

NTSTATUS NTAPI NtfsFsdDispatch ( PDEVICE_OBJECT  DeviceObject,
PIRP  Irp 
)

Definition at line 197 of file dispatch.c.

199{
200 PNTFS_IRP_CONTEXT IrpContext = NULL;
202
203 TRACE_(NTFS, "NtfsFsdDispatch()\n");
204
206 if (IrpContext == NULL)
207 {
209 Irp->IoStatus.Status = Status;
211 }
212 else
213 {
214 Status = NtfsDispatch(IrpContext);
215 }
216
217 return Status;
218}
static NTSTATUS NtfsDispatch(PNTFS_IRP_CONTEXT IrpContext)
Definition: dispatch.c:59
PNTFS_IRP_CONTEXT NtfsAllocateIrpContext(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: misc.c:66
#define IoCompleteRequest
Definition: irp.c:1272

◆ NtfsGetFCBForFile()

NTSTATUS NtfsGetFCBForFile ( PNTFS_VCB  Vcb,
PNTFS_FCB *  pParentFCB,
PNTFS_FCB *  pFCB,
PCWSTR  pFileName,
BOOLEAN  CaseSensitive 
)

Definition at line 674 of file fcb.c.

679{
681 WCHAR pathName [MAX_PATH];
682 WCHAR elementName [MAX_PATH];
683 PCWSTR currentElement;
685 PNTFS_FCB parentFCB;
686
687 DPRINT("NtfsGetFCBForFile(%p, %p, %p, '%S', %s)\n",
688 Vcb,
689 pParentFCB,
690 pFCB,
691 pFileName,
692 CaseSensitive ? "TRUE" : "FALSE");
693
694 /* Dummy code */
695// FCB = NtfsOpenRootFCB(Vcb);
696// *pFCB = FCB;
697// *pParentFCB = NULL;
698
699#if 1
700 /* Trivial case, open of the root directory on volume */
701 if (pFileName[0] == L'\0' || wcscmp(pFileName, L"\\") == 0)
702 {
703 DPRINT("returning root FCB\n");
704
706 *pFCB = FCB;
707 *pParentFCB = NULL;
708
710 }
711 else
712 {
713 currentElement = pFileName + 1;
714 wcscpy (pathName, L"\\");
716 }
717
718 parentFCB = NULL;
719
720 /* Parse filename and check each path element for existence and access */
721 while (NtfsGetNextPathElement(currentElement) != 0)
722 {
723 /* Skip blank directory levels */
724 if ((NtfsGetNextPathElement(currentElement) - currentElement) == 0)
725 {
726 currentElement++;
727 continue;
728 }
729
730 DPRINT("Parsing, currentElement:%S\n", currentElement);
731 DPRINT(" parentFCB:%p FCB:%p\n", parentFCB, FCB);
732
733 /* Descend to next directory level */
734 if (parentFCB)
735 {
736 NtfsReleaseFCB(Vcb, parentFCB);
737 parentFCB = NULL;
738 }
739
740 /* fail if element in FCB is not a directory */
742 {
743 DPRINT("Element in requested path is not a directory\n");
744
746 FCB = 0;
747 *pParentFCB = NULL;
748 *pFCB = NULL;
749
751 }
752
753 parentFCB = FCB;
754
755 /* Extract next directory level into dirName */
756 NtfsWSubString(pathName,
757 pFileName,
758 NtfsGetNextPathElement(currentElement) - pFileName);
759 DPRINT(" pathName:%S\n", pathName);
760
761 FCB = NtfsGrabFCBFromTable(Vcb, pathName);
762 if (FCB == NULL)
763 {
764 NtfsWSubString(elementName,
765 currentElement,
766 NtfsGetNextPathElement(currentElement) - currentElement);
767 DPRINT(" elementName:%S\n", elementName);
768
769 Status = NtfsDirFindFile(Vcb, parentFCB, elementName, CaseSensitive, &FCB);
771 {
772 *pParentFCB = parentFCB;
773 *pFCB = NULL;
774 currentElement = NtfsGetNextPathElement(currentElement);
775 if (*currentElement == L'\0' || NtfsGetNextPathElement(currentElement + 1) == 0)
776 {
778 }
779 else
780 {
782 }
783 }
784 else if (!NT_SUCCESS(Status))
785 {
786 NtfsReleaseFCB(Vcb, parentFCB);
787 *pParentFCB = NULL;
788 *pFCB = NULL;
789
790 return Status;
791 }
792 }
793
794 currentElement = NtfsGetNextPathElement(currentElement);
795 }
796
797 *pParentFCB = parentFCB;
798 *pFCB = FCB;
799#endif
800
801 return STATUS_SUCCESS;
802}
struct _FCB FCB
#define MAX_PATH
Definition: compat.h:34
static VOID NtfsWSubString(PWCHAR pTarget, PCWSTR pSource, size_t pLength)
Definition: fcb.c:57
PNTFS_FCB NtfsGrabFCBFromTable(PNTFS_VCB Vcb, PCWSTR FileName)
Definition: fcb.c:291
static NTSTATUS NtfsDirFindFile(PNTFS_VCB Vcb, PNTFS_FCB DirectoryFcb, PWSTR FileToFind, BOOLEAN CaseSensitive, PNTFS_FCB *FoundFCB)
Definition: fcb.c:586
PNTFS_FCB NtfsOpenRootFCB(PNTFS_VCB Vcb)
Definition: fcb.c:443
static PCWSTR NtfsGetNextPathElement(PCWSTR FileName)
Definition: fcb.c:39
#define STATUS_OBJECT_PATH_NOT_FOUND
Definition: udferr_usr.h:151

Referenced by NtfsOpenFile(), and NtfsOpenTargetDirectory().

◆ NtfsGetFileSize()

ULONGLONG NtfsGetFileSize ( PDEVICE_EXTENSION  DeviceExt,
PFILE_RECORD_HEADER  FileRecord,
PCWSTR  Stream,
ULONG  StreamLength,
PULONGLONG  AllocatedSize 
)

Definition at line 38 of file dirctl.c.

43{
47 PNTFS_ATTR_CONTEXT DataContext;
48
49 Status = FindAttribute(DeviceExt, FileRecord, AttributeData, Stream, StreamLength, &DataContext, NULL);
50 if (NT_SUCCESS(Status))
51 {
52 Size = AttributeDataLength(DataContext->pRecord);
53 Allocated = AttributeAllocatedLength(DataContext->pRecord);
54 ReleaseAttributeContext(DataContext);
55 }
56
57 if (AllocatedSize != NULL) *AllocatedSize = Allocated;
58
59 return Size;
60}
IN PFCB IN VBO OUT PLBO OUT PULONG OUT PBOOLEAN Allocated
Definition: fatprocs.h:311
ULONGLONG AttributeAllocatedLength(PNTFS_ATTR_RECORD AttrRecord)
Definition: mft.c:249
#define ULL(a, b)
Definition: format_msg.c:27
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4539

Referenced by NtfsGetBothDirectoryInformation(), NtfsGetDirectoryInformation(), NtfsGetFullDirectoryInformation(), NtfsMakeFCBFromDirEntry(), NtfsSetEndOfFile(), and NtfsUpdateDuplicatedInformation().

◆ NtfsGetFreeClusters()

ULONGLONG NtfsGetFreeClusters ( PDEVICE_EXTENSION  DeviceExt)

Definition at line 193 of file volinfo.c.

194{
196
197 DPRINT("NtfsGetFreeClusters(%p)\n", DeviceExt);
198
200 ExAcquireResourceSharedLite(&DeviceExt->BitmapResource, TRUE);
201 FreeClusters = DeviceExt->FreeClusterCount;
202 ExReleaseResourceLite(&DeviceExt->BitmapResource);
204
205 return FreeClusters;
206}
#define ExAcquireResourceSharedLite(res, wait)
Definition: env_spec_w32.h:621

Referenced by GetNfsVolumeData(), and NtfsGetFsSizeInformation().

◆ NtfsGetUserBuffer()

PVOID NtfsGetUserBuffer ( PIRP  Irp,
BOOLEAN  Paging 
)

Definition at line 120 of file misc.c.

122{
123 if (Irp->MdlAddress != NULL)
124 {
126 }
127 else
128 {
129 return Irp->UserBuffer;
130 }
131}
@ NormalPagePriority
Definition: imports.h:54
@ HighPagePriority
Definition: imports.h:55
#define MmGetSystemAddressForMdlSafe(_Mdl, _Priority)

Referenced by GetVolumeBitmap(), NtfsQueryDirectory(), NtfsRead(), and NtfsWrite().

◆ NtfsGrabFCB()

VOID NtfsGrabFCB ( PNTFS_VCB  Vcb,
PNTFS_FCB  Fcb 
)

Definition at line 192 of file fcb.c.

194{
195 KIRQL oldIrql;
196
197 DPRINT("grabbing FCB at %p: %S, refCount:%d\n",
198 Fcb,
199 Fcb->PathName,
200 Fcb->RefCount);
201
202 KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql);
203 Fcb->RefCount++;
204 KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
205}
LONG RefCount
Definition: ntfs.h:617

Referenced by NtfsMakeRootFCB().

◆ NtfsGrabFCBFromTable()

PNTFS_FCB NtfsGrabFCBFromTable ( PNTFS_VCB  Vcb,
PCWSTR  FileName 
)

Definition at line 291 of file fcb.c.

293{
294 KIRQL oldIrql;
296 PLIST_ENTRY current_entry;
297
298 KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql);
299
300 if (FileName == NULL || *FileName == 0)
301 {
302 DPRINT("Return FCB for stream file object\n");
303 Fcb = Vcb->StreamFileObject->FsContext;
304 Fcb->RefCount++;
305 KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
306 return Fcb;
307 }
308
309 current_entry = Vcb->FcbListHead.Flink;
310 while (current_entry != &Vcb->FcbListHead)
311 {
312 Fcb = CONTAINING_RECORD(current_entry, NTFS_FCB, FcbListEntry);
313
314 DPRINT("Comparing '%S' and '%S'\n", FileName, Fcb->PathName);
315 if (_wcsicmp(FileName, Fcb->PathName) == 0)
316 {
317 Fcb->RefCount++;
318 KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
319 return Fcb;
320 }
321
322 //FIXME: need to compare against short name in FCB here
323
324 current_entry = current_entry->Flink;
325 }
326
327 KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
328
329 return NULL;
330}
_ACRTIMP int __cdecl _wcsicmp(const wchar_t *, const wchar_t *)
Definition: wcs.c:164
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260

Referenced by NtfsClearRenameTarget(), NtfsGetFCBForFile(), NtfsOpenFile(), NtfsOpenFileById(), NtfsOpenRootFCB(), and NtfsOpenTargetDirectory().

◆ NtfsInitializeFunctionPointers()

VOID NTAPI NtfsInitializeFunctionPointers ( PDRIVER_OBJECT  DriverObject)

Definition at line 170 of file ntfs.c.

171{
173 DriverObject->MajorFunction[IRP_MJ_CLOSE] = NtfsFsdDispatch;
175 DriverObject->MajorFunction[IRP_MJ_READ] = NtfsFsdDispatch;
176 DriverObject->MajorFunction[IRP_MJ_WRITE] = NtfsFsdDispatch;
186
187 return;
188}
DRIVER_DISPATCH NtfsFsdDispatch
Definition: ntfs.h:1021
#define IRP_MJ_DIRECTORY_CONTROL
Definition: rdpdr.c:51
#define IRP_MJ_READ
Definition: rdpdr.c:46
#define IRP_MJ_QUERY_VOLUME_INFORMATION
Definition: rdpdr.c:50
#define IRP_MJ_LOCK_CONTROL
Definition: rdpdr.c:53
#define IRP_MJ_WRITE
Definition: rdpdr.c:47
#define IRP_MJ_SET_INFORMATION
Definition: rdpdr.c:49
#define IRP_MJ_CREATE
Definition: rdpdr.c:44
#define IRP_MJ_QUERY_INFORMATION
Definition: rdpdr.c:48
_Must_inspect_result_ _In_ PDRIVER_OBJECT DriverObject
Definition: wdfdriver.h:213
#define IRP_MJ_SET_VOLUME_INFORMATION

Referenced by DriverEntry().

◆ NtfsInitIoRunList()

VOID NtfsInitIoRunList ( OUT PNTFS_IO_RUN_LIST  RunList)

Definition at line 40 of file blockdev.c.

41{
42 RunList->Runs = RunList->StackRuns;
43 RunList->Capacity = NTFS_MAX_IO_RUNS_ON_STACK;
44 RunList->Count = 0;
45 RunList->TotalLength = 0;
46}
#define NTFS_MAX_IO_RUNS_ON_STACK
Definition: ntfs.h:513

Referenced by NtfsReadDisk(), NtfsReadWriteVolume(), NtfsWriteDisk(), ReadAttributeToIrp(), and WriteAttributeFromIrp().

◆ NtfsInsertKey()

NTSTATUS NtfsInsertKey ( PB_TREE  Tree,
ULONGLONG  FileReference,
PFILENAME_ATTRIBUTE  FileNameAttribute,
PB_TREE_FILENAME_NODE  Node,
BOOLEAN  CaseSensitive,
ULONG  MaxIndexRootSize,
ULONG  IndexRecordSize,
PB_TREE_KEY *  MedianKey,
PB_TREE_FILENAME_NODE *  NewRightHandSibling 
)

Definition at line 1698 of file btree.c.

1707{
1708 PB_TREE_KEY NewKey, CurrentKey, PreviousKey;
1710 ULONG NodeSize;
1711 ULONG AllocatedNodeSize;
1712 ULONG MaxNodeSizeWithoutHeader;
1713 ULONG i;
1714
1715 *MedianKey = NULL;
1716 *NewRightHandSibling = NULL;
1717
1718 DPRINT("NtfsInsertKey(%p, 0x%I64x, %p, %p, %s, %lu, %lu, %p, %p)\n",
1719 Tree,
1720 FileReference,
1721 FileNameAttribute,
1722 Node,
1723 CaseSensitive ? "TRUE" : "FALSE",
1724 MaxIndexRootSize,
1725 IndexRecordSize,
1726 MedianKey,
1727 NewRightHandSibling);
1728
1729 // Create the key for the filename attribute
1730 NewKey = CreateBTreeKeyFromFilename(FileReference, FileNameAttribute);
1731 if (!NewKey)
1733
1734 // Find where to insert the key
1735 CurrentKey = Node->FirstKey;
1736 PreviousKey = NULL;
1737 for (i = 0; i < Node->KeyCount; i++)
1738 {
1739 // Should the New Key go before the current key?
1740 LONG Comparison = CompareTreeKeys(NewKey, CurrentKey, CaseSensitive);
1741
1742 /* The name is already in this index. Inserting it again would leave
1743 * two entries the lookup code can never tell apart, so refuse. */
1744 if (Comparison == 0)
1745 {
1746 DPRINT1("Refusing duplicate index entry '%.*S' (existing file reference 0x%I64x)\n",
1748 NewKey->IndexEntry->FileName.Name,
1749 CurrentKey->IndexEntry->Data.Directory.IndexedFile);
1750
1751 DestroyBTreeKey(NewKey);
1752
1754 }
1755
1756 // Is NewKey < CurrentKey?
1757 if (Comparison < 0)
1758 {
1759 // Does CurrentKey have a sub-node?
1760 if (CurrentKey->LesserChild)
1761 {
1762 PB_TREE_KEY NewLeftKey;
1763 PB_TREE_FILENAME_NODE NewChild;
1764
1765 // Insert the key into the child node
1767 FileReference,
1768 FileNameAttribute,
1769 CurrentKey->LesserChild,
1770 CaseSensitive,
1771 MaxIndexRootSize,
1772 IndexRecordSize,
1773 &NewLeftKey,
1774 &NewChild);
1775 if (!NT_SUCCESS(Status))
1776 {
1777 DPRINT1("ERROR: Failed to insert key.\n");
1778 ExFreePoolWithTag(NewKey, TAG_NTFS);
1779 return Status;
1780 }
1781
1782 // Did the child node get split?
1783 if (NewLeftKey)
1784 {
1785 ASSERT(NewChild != NULL);
1786
1787 // Insert the new left key to the left of the current key
1788 NewLeftKey->NextKey = CurrentKey;
1789
1790 // Is CurrentKey the first key?
1791 if (!PreviousKey)
1792 Node->FirstKey = NewLeftKey;
1793 else
1794 PreviousKey->NextKey = NewLeftKey;
1795
1796 // CurrentKey->LesserChild will be the right-hand sibling
1797 CurrentKey->LesserChild = NewChild;
1798
1799 Node->KeyCount++;
1800 Node->DiskNeedsUpdating = TRUE;
1801
1802#ifndef NDEBUG
1803 DumpBTree(Tree);
1804#endif
1805 }
1806 }
1807 else
1808 {
1809 // Insert New Key before Current Key
1810 NewKey->NextKey = CurrentKey;
1811
1812 // Increase KeyCount and mark node as dirty
1813 Node->KeyCount++;
1814 Node->DiskNeedsUpdating = TRUE;
1815
1816 // was CurrentKey the first key?
1817 if (CurrentKey == Node->FirstKey)
1818 Node->FirstKey = NewKey;
1819 else
1820 PreviousKey->NextKey = NewKey;
1821 }
1822 break;
1823 }
1824
1825 PreviousKey = CurrentKey;
1826 CurrentKey = CurrentKey->NextKey;
1827 }
1828
1829 // Determine how much space the index entries will need
1830 NodeSize = GetSizeOfIndexEntries(Node);
1831
1832 // Is Node not the root node?
1833 if (Node != Tree->RootNode)
1834 {
1835 // Calculate maximum size of index entries without any headers
1836 AllocatedNodeSize = IndexRecordSize - FIELD_OFFSET(INDEX_BUFFER, Header);
1837
1838 // TODO: Replace magic with math
1839 MaxNodeSizeWithoutHeader = AllocatedNodeSize - 0x28;
1840
1841 // Has the node grown larger than its allocated size?
1842 if (NodeSize > MaxNodeSizeWithoutHeader)
1843 {
1845
1846 Status = SplitBTreeNode(Tree, Node, MedianKey, NewRightHandSibling, CaseSensitive);
1847 if (!NT_SUCCESS(Status))
1848 {
1849 DPRINT1("ERROR: Failed to split B-Tree node!\n");
1850 return Status;
1851 }
1852
1853 return Status;
1854 }
1855 }
1856
1857 // NewEntry and NewKey will be destroyed later by DestroyBTree()
1858
1859 return Status;
1860}
LONG CompareTreeKeys(PB_TREE_KEY Key1, PB_TREE_KEY Key2, BOOLEAN CaseSensitive)
Definition: btree.c:422
NTSTATUS SplitBTreeNode(PB_TREE Tree, PB_TREE_FILENAME_NODE Node, PB_TREE_KEY *MedianKey, PB_TREE_FILENAME_NODE *NewRightHandSibling, BOOLEAN CaseSensitive)
Definition: btree.c:2138
NTSTATUS NtfsInsertKey(PB_TREE Tree, ULONGLONG FileReference, PFILENAME_ATTRIBUTE FileNameAttribute, PB_TREE_FILENAME_NODE Node, BOOLEAN CaseSensitive, ULONG MaxIndexRootSize, ULONG IndexRecordSize, PB_TREE_KEY *MedianKey, PB_TREE_FILENAME_NODE *NewRightHandSibling)
Definition: btree.c:1698
ULONG GetSizeOfIndexEntries(PB_TREE_FILENAME_NODE Node)
Definition: btree.c:860
PB_TREE_KEY CreateBTreeKeyFromFilename(ULONGLONG FileReference, PFILENAME_ATTRIBUTE FileNameAttribute)
Definition: btree.c:1466
#define STATUS_OBJECT_NAME_COLLISION
Definition: udferr_usr.h:150

Referenced by AddFilenameToDirectoryWorker(), and NtfsInsertKey().

◆ NtfsIsDirectoryEmpty()

NTSTATUS NtfsIsDirectoryEmpty ( _In_ PDEVICE_EXTENSION  Vcb,
_In_ ULONGLONG  MftIndex,
_Out_ PBOOLEAN  Empty 
)

Definition at line 4554 of file mft.c.

4558{
4559 PFILE_RECORD_HEADER FileRecord;
4560 PNTFS_ATTR_CONTEXT IndexRootContext = NULL;
4561 PNTFS_ATTR_CONTEXT IndexAllocationContext = NULL;
4562 PINDEX_ROOT_ATTRIBUTE IndexRoot = NULL;
4563 ULONG IndexRootLength;
4565
4566 *Empty = FALSE;
4567
4568 FileRecord = ExAllocateFromNPagedLookasideList(&Vcb->FileRecLookasideList);
4569 if (FileRecord == NULL)
4571
4572 Status = ReadFileRecord(Vcb, MftIndex, FileRecord);
4573 if (!NT_SUCCESS(Status))
4574 goto Quit;
4575
4576 Status = FindAttribute(Vcb, FileRecord, AttributeIndexRoot, L"$I30", 4, &IndexRootContext, NULL);
4577 if (!NT_SUCCESS(Status))
4578 goto Quit;
4579
4580 IndexRootLength = (ULONG)AttributeDataLength(IndexRootContext->pRecord);
4581 if (IndexRootLength < sizeof(*IndexRoot))
4582 {
4584 goto Quit;
4585 }
4586
4587 IndexRoot = ExAllocatePoolWithTag(NonPagedPool, IndexRootLength, TAG_NTFS);
4588 if (IndexRoot == NULL)
4589 {
4591 goto Quit;
4592 }
4593
4594 if (ReadAttribute(Vcb, IndexRootContext, 0, (PCHAR)IndexRoot, IndexRootLength) != IndexRootLength)
4595 {
4597 goto Quit;
4598 }
4599
4600 if (FIELD_OFFSET(INDEX_ROOT_ATTRIBUTE, Header) + IndexRoot->Header.TotalSizeOfEntries > IndexRootLength)
4601 {
4603 goto Quit;
4604 }
4605
4606 /* Only a root that points down needs the allocation */
4607 if (IndexRoot->Header.Flags & INDEX_ROOT_LARGE)
4608 {
4609 Status = FindAttribute(Vcb, FileRecord, AttributeIndexAllocation, L"$I30", 4, &IndexAllocationContext, NULL);
4610 if (!NT_SUCCESS(Status))
4611 {
4613 goto Quit;
4614 }
4615 }
4616
4618 IndexAllocationContext,
4619 IndexRoot->SizeOfEntry,
4620 &IndexRoot->Header,
4621 0,
4622 Empty);
4623
4624Quit:
4625 if (IndexRoot != NULL)
4626 ExFreePoolWithTag(IndexRoot, TAG_NTFS);
4627 if (IndexAllocationContext != NULL)
4628 ReleaseAttributeContext(IndexAllocationContext);
4629 if (IndexRootContext != NULL)
4630 ReleaseAttributeContext(IndexRootContext);
4631 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, FileRecord);
4632
4633 return Status;
4634}
@ Empty
Definition: npfs.h:126
static NTSTATUS NtfsIndexEntriesAreEmpty(_In_ PDEVICE_EXTENSION Vcb, _In_ PNTFS_ATTR_CONTEXT IndexAllocationContext, _In_ ULONG IndexBlockSize, _In_ PINDEX_HEADER_ATTRIBUTE Header, _In_ ULONG Depth, _Out_ PBOOLEAN Empty)
Definition: mft.c:4491

Referenced by NtfsCleanupFile(), and NtfsSetDispositionInformation().

◆ NtfsIsIrpTopLevel()

BOOLEAN NtfsIsIrpTopLevel ( PIRP  Irp)

Definition at line 43 of file misc.c.

44{
45 BOOLEAN ReturnCode = FALSE;
46
47 TRACE_(NTFS, "NtfsIsIrpTopLevel()\n");
48
49 if (IoGetTopLevelIrp() == NULL)
50 {
52 ReturnCode = TRUE;
53 }
54
55 return ReturnCode;
56}
VOID NTAPI IoSetTopLevelIrp(IN PIRP Irp)
Definition: irp.c:2032

Referenced by NtfsDispatch().

◆ NtfsIsRegularFileObject()

BOOLEAN NTAPI NtfsIsRegularFileObject ( _In_ PFILE_OBJECT  FileObject)

Definition at line 153 of file fcb.c.

155{
156 PNTFS_FCB Fcb = (PNTFS_FCB)FileObject->FsContext;
157
159 return FALSE;
160
161 return !(Fcb->Flags & FCB_IS_VOLUME) && !NtfsFCBIsDirectory(Fcb);
162}

Referenced by NtfsCleanup(), NtfsFastIoCheckIfPossible(), NtfsFastIoRead(), NtfsFastIoWrite(), NtfsFlushBuffers(), NtfsLockControl(), NtfsRead(), and NtfsWrite().

◆ NtfsLoadUpCaseTable()

NTSTATUS NtfsLoadUpCaseTable ( PDEVICE_EXTENSION  Vcb)

Definition at line 1930 of file mft.c.

1931{
1932 return NtfsReadUpCaseTable(Vcb);
1933}
static NTSTATUS NtfsReadUpCaseTable(PDEVICE_EXTENSION Vcb)
Definition: mft.c:1866

Referenced by NtfsGetVolumeData().

◆ NtfsLoadVolumeBitmap()

NTSTATUS NtfsLoadVolumeBitmap ( _In_ PDEVICE_EXTENSION  DeviceExt)

Definition at line 49 of file volinfo.c.

51{
52 PFILE_RECORD_HEADER BitmapRecord;
53 ULONGLONG BitmapSize;
56
57 BitmapRecord = ExAllocateFromNPagedLookasideList(&DeviceExt->FileRecLookasideList);
58 if (BitmapRecord == NULL)
60
61 Status = ReadFileRecord(DeviceExt, NTFS_FILE_BITMAP, BitmapRecord);
62 if (NT_SUCCESS(Status))
63 {
64 /* The context keeps its own copy of the attribute record */
65 Status = FindAttribute(DeviceExt, BitmapRecord, AttributeData, L"", 0, &DeviceExt->BitmapContext, NULL);
66 }
67
68 ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, BitmapRecord);
69
70 if (!NT_SUCCESS(Status))
71 {
72 DPRINT1("Unable to find $Bitmap (Status %lx)\n", Status);
73 DeviceExt->BitmapContext = NULL;
74 return Status;
75 }
76
77 BitmapSize = AttributeDataLength(DeviceExt->BitmapContext->pRecord);
78 if (BitmapSize > MAXULONG ||
79 BitmapSize * 8 < DeviceExt->NtfsInfo.ClusterCount ||
80 DeviceExt->NtfsInfo.ClusterCount > MAXULONG)
81 {
82 DPRINT1("$Bitmap size %I64u does not cover %I64u clusters\n",
83 BitmapSize, DeviceExt->NtfsInfo.ClusterCount);
85 goto Fail;
86 }
87
88 /* Whole sectors, so write back never reads first */
89 BufferSize = ROUND_UP((ULONG)BitmapSize, DeviceExt->NtfsInfo.BytesPerSector);
90 DeviceExt->BitmapBuffer = ExAllocatePoolWithTag(PagedPool, BufferSize, TAG_NTFS);
91 if (DeviceExt->BitmapBuffer == NULL)
92 {
94 goto Fail;
95 }
96 RtlZeroMemory(DeviceExt->BitmapBuffer, BufferSize);
97
98 if (ReadAttribute(DeviceExt, DeviceExt->BitmapContext, 0, (PCHAR)DeviceExt->BitmapBuffer, (ULONG)BitmapSize) != (ULONG)BitmapSize)
99 {
100 DPRINT1("Unable to read $Bitmap\n");
102 goto Fail;
103 }
104
105 DeviceExt->BitmapSize = (ULONG)BitmapSize;
106
107 /* $Bitmap is rounded up to a cluster and covers a few clusters more than
108 * the volume has. Bounding by ClusterCount ignores the surplus bits, but
109 * write back still preserves them on disk. */
110 RtlInitializeBitMap(&DeviceExt->ClusterBitmap, DeviceExt->BitmapBuffer, (ULONG)DeviceExt->NtfsInfo.ClusterCount);
111 DeviceExt->FreeClusterCount = RtlNumberOfClearBits(&DeviceExt->ClusterBitmap);
112
113 DPRINT("Volume bitmap loaded: %I64u of %I64u clusters free\n",
114 DeviceExt->FreeClusterCount, DeviceExt->NtfsInfo.ClusterCount);
115
116 return STATUS_SUCCESS;
117
118Fail:
119 NtfsFreeVolumeBitmap(DeviceExt);
120 return Status;
121}
#define NTFS_FILE_BITMAP
Definition: ntfs.h:29
#define RtlNumberOfClearBits
Definition: dbgbitmap.h:342
#define BufferSize
Definition: mmc.h:75
_In_ ULONG BufferSize
Definition: dispmprt.h:490
int Fail
Definition: ehthrow.cxx:24
#define PagedPool
Definition: env_spec_w32.h:308
#define ROUND_UP(n, align)
Definition: eventvwr.h:34
VOID NtfsFreeVolumeBitmap(_In_ PDEVICE_EXTENSION DeviceExt)
Definition: volinfo.c:132

◆ NtfsLockControl()

NTSTATUS NTAPI NtfsLockControl ( _In_ PNTFS_IRP_CONTEXT  IrpContext)

Definition at line 19 of file lockctrl.c.

21{
23
24 DPRINT("NtfsLockControl(%p)\n", IrpContext);
25
26 if (IrpContext->DeviceObject == NtfsGlobalData->DeviceObject)
28
29 /* Only the data of regular files can be locked */
30 if (!NtfsIsRegularFileObject(IrpContext->FileObject))
32
33 Fcb = (PNTFS_FCB)IrpContext->FileObject->FsContext;
34
35 /* FsRtl completes the IRP, or keeps it until a conflicting lock goes away */
36 IrpContext->Flags &= ~IRPCONTEXT_COMPLETE;
37
38 return FsRtlProcessFileLock(&Fcb->FileLock, IrpContext->Irp, NULL);
39}
NTSTATUS NTAPI FsRtlProcessFileLock(IN PFILE_LOCK FileLock, IN PIRP Irp, IN PVOID Context OPTIONAL)
Definition: filelock.c:1156

Referenced by NtfsDispatch().

◆ NtfsLockUserBuffer()

NTSTATUS NtfsLockUserBuffer ( IN PIRP  Irp,
IN ULONG  Length,
IN LOCK_OPERATION  Operation 
)

Definition at line 158 of file misc.c.

161{
162 ASSERT(Irp);
163
164 if (Irp->MdlAddress)
165 {
166 return STATUS_SUCCESS;
167 }
168
169 IoAllocateMdl(Irp->UserBuffer, Length, FALSE, FALSE, Irp);
170
171 if (!Irp->MdlAddress)
172 {
174 }
175
177 {
178 MmProbeAndLockPages(Irp->MdlAddress, Irp->RequestorMode, Operation);
179 }
181 {
182 IoFreeMdl(Irp->MdlAddress);
183 Irp->MdlAddress = NULL;
185 }
186 _SEH2_END;
187
188 return STATUS_SUCCESS;
189}
FP_OP Operation
Definition: fpcontrol.c:150
#define IoFreeMdl
Definition: fxmdl.h:89
#define IoAllocateMdl
Definition: fxmdl.h:88
VOID NTAPI MmProbeAndLockPages(IN PMDL Mdl, IN KPROCESSOR_MODE AccessMode, IN LOCK_OPERATION Operation)
Definition: mdlsup.c:928

Referenced by NtfsCachedRead(), and NtfsWrite().

◆ NtfsLookupFile()

NTSTATUS NtfsLookupFile ( PDEVICE_EXTENSION  Vcb,
PUNICODE_STRING  PathName,
BOOLEAN  CaseSensitive,
PFILE_RECORD_HEADER *  FileRecord,
PULONGLONG  MFTIndex 
)

Definition at line 4295 of file mft.c.

4300{
4301 return NtfsLookupFileAt(Vcb, PathName, CaseSensitive, FileRecord, MFTIndex, NTFS_FILE_ROOT);
4302}
NTSTATUS NtfsLookupFileAt(PDEVICE_EXTENSION Vcb, PUNICODE_STRING PathName, BOOLEAN CaseSensitive, PFILE_RECORD_HEADER *FileRecord, PULONGLONG MFTIndex, ULONGLONG CurrentMFTIndex)
Definition: mft.c:4236

◆ NtfsLookupFileAt()

NTSTATUS NtfsLookupFileAt ( PDEVICE_EXTENSION  Vcb,
PUNICODE_STRING  PathName,
BOOLEAN  CaseSensitive,
PFILE_RECORD_HEADER *  FileRecord,
PULONGLONG  MFTIndex,
ULONGLONG  CurrentMFTIndex 
)

Definition at line 4236 of file mft.c.

4242{
4243 UNICODE_STRING Current, Remaining;
4245 ULONG FirstEntry = 0;
4246
4247 DPRINT("NtfsLookupFileAt(%p, %wZ, %s, %p, %p, %I64x)\n",
4248 Vcb,
4249 PathName,
4250 CaseSensitive ? "TRUE" : "FALSE",
4251 FileRecord,
4252 MFTIndex,
4253 CurrentMFTIndex);
4254
4255 FsRtlDissectName(*PathName, &Current, &Remaining);
4256
4257 while (Current.Length != 0)
4258 {
4259 DPRINT("Current: %wZ\n", &Current);
4260
4261 Status = NtfsFindMftRecord(Vcb, CurrentMFTIndex, &Current, &FirstEntry, FALSE, CaseSensitive, &CurrentMFTIndex);
4262 if (!NT_SUCCESS(Status))
4263 {
4264 return Status;
4265 }
4266
4267 if (Remaining.Length == 0)
4268 break;
4269
4270 /* Split what is left of the path, not the component we just resolved */
4271 FsRtlDissectName(Remaining, &Current, &Remaining);
4272 }
4273
4274 *FileRecord = ExAllocateFromNPagedLookasideList(&Vcb->FileRecLookasideList);
4275 if (*FileRecord == NULL)
4276 {
4277 DPRINT("NtfsLookupFileAt: Can't allocate MFT record\n");
4279 }
4280
4281 Status = ReadFileRecord(Vcb, CurrentMFTIndex, *FileRecord);
4282 if (!NT_SUCCESS(Status))
4283 {
4284 DPRINT("NtfsLookupFileAt: Can't read MFT record\n");
4285 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, *FileRecord);
4286 return Status;
4287 }
4288
4289 *MFTIndex = CurrentMFTIndex;
4290
4291 return STATUS_SUCCESS;
4292}

Referenced by NtfsDirFindFile(), and NtfsLookupFile().

◆ NtfsMakeFCBFromDirEntry()

NTSTATUS NtfsMakeFCBFromDirEntry ( PNTFS_VCB  Vcb,
PNTFS_FCB  DirectoryFCB,
PUNICODE_STRING  Name,
PCWSTR  Stream,
PFILE_RECORD_HEADER  Record,
ULONGLONG  MFTIndex,
PNTFS_FCB *  fileFCB 
)

Definition at line 458 of file fcb.c.

465{
466 WCHAR pathName[MAX_PATH];
468 PSTANDARD_INFORMATION StdInfo;
469 PNTFS_FCB rcFCB;
470 ULONGLONG Size, AllocatedSize;
471
472 DPRINT("NtfsMakeFCBFromDirEntry(%p, %p, %wZ, %p, %p, %p)\n", Vcb, DirectoryFCB, Name, Stream, Record, fileFCB);
473
475 if (!FileName)
476 {
477 return STATUS_OBJECT_NAME_NOT_FOUND; // Not sure that's the best here
478 }
479
480 if (DirectoryFCB && Name)
481 {
482 if (Name->Buffer[0] != 0 && wcslen(DirectoryFCB->PathName) +
483 sizeof(WCHAR) + Name->Length / sizeof(WCHAR) > MAX_PATH)
484 {
486 }
487
488 wcscpy(pathName, DirectoryFCB->PathName);
489 if (!NtfsFCBIsRoot(DirectoryFCB))
490 {
491 wcscat(pathName, L"\\");
492 }
493 wcscat(pathName, Name->Buffer);
494 }
495 else
496 {
497 RtlCopyMemory(pathName, FileName->Name, FileName->NameLength * sizeof (WCHAR));
498 pathName[FileName->NameLength] = UNICODE_NULL;
499 }
500
501 Size = NtfsGetFileSize(Vcb, Record, (Stream ? Stream : L""), (Stream ? wcslen(Stream) : 0), &AllocatedSize);
502
503 rcFCB = NtfsCreateFCB(pathName, Stream, Vcb);
504 if (!rcFCB)
505 {
507 }
508
509 memcpy(&rcFCB->Entry, FileName, FIELD_OFFSET(FILENAME_ATTRIBUTE, NameLength));
510 rcFCB->Entry.NameType = FileName->NameType;
511 rcFCB->RFCB.FileSize.QuadPart = Size;
513 rcFCB->RFCB.AllocationSize.QuadPart = AllocatedSize;
514
516 if (StdInfo != NULL)
517 {
518 rcFCB->Entry.FileAttributes |= StdInfo->FileAttribute;
519 }
520
522 rcFCB->RefCount = 1;
523 rcFCB->MFTIndex = MFTIndex;
524 rcFCB->LinkCount = Record->LinkCount;
525 NtfsAddFCBToTable(Vcb, rcFCB);
526 *fileFCB = rcFCB;
527
528 return STATUS_SUCCESS;
529}
_ACRTIMP size_t __cdecl wcslen(const wchar_t *)
Definition: wcs.c:2988
PSTANDARD_INFORMATION GetStandardInformationFromRecord(PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER FileRecord)
Definition: attrib.c:1970
PFILENAME_ATTRIBUTE GetBestFileNameFromRecord(PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER FileRecord)
Definition: attrib.c:2015
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
ULONGLONG NtfsGetFileSize(PDEVICE_EXTENSION DeviceExt, PFILE_RECORD_HEADER FileRecord, PCWSTR Stream, ULONG StreamLength, PULONGLONG AllocatedSize)
Definition: dirctl.c:38
BOOLEAN NtfsFCBIsRoot(PNTFS_FCB Fcb)
Definition: fcb.c:185
NTSTATUS NtfsFCBInitializeCache(PNTFS_VCB Vcb, PNTFS_FCB Fcb)
Definition: fcb.c:334
PNTFS_FCB NtfsCreateFCB(PCWSTR FileName, PCWSTR Stream, PNTFS_VCB Vcb)
Definition: fcb.c:67
VOID NtfsAddFCBToTable(PNTFS_VCB Vcb, PNTFS_FCB Fcb)
Definition: fcb.c:250
wcscat
ULONGLONG MFTIndex
Definition: ntfs.h:622
USHORT LinkCount
Definition: ntfs.h:623
LARGE_INTEGER ValidDataLength
Definition: env_spec_w32.h:757
#define STATUS_OBJECT_NAME_INVALID
Definition: udferr_usr.h:148
ActualNumberDriverObjects * sizeof(PDRIVER_OBJECT)) PDRIVER_OBJECT *DriverObjectList

Referenced by NtfsDirFindFile(), and NtfsOpenFileById().

◆ NtfsMakeRootFCB()

PNTFS_FCB NtfsMakeRootFCB ( PNTFS_VCB  Vcb)

Definition at line 388 of file fcb.c.

389{
391 PFILE_RECORD_HEADER MftRecord;
393
394 MftRecord = ExAllocateFromNPagedLookasideList(&Vcb->FileRecLookasideList);
395 if (MftRecord == NULL)
396 {
397 return NULL;
398 }
399
400 if (!NT_SUCCESS(ReadFileRecord(Vcb, NTFS_FILE_ROOT, MftRecord)))
401 {
402 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, MftRecord);
403 return NULL;
404 }
405
407 if (!FileName)
408 {
409 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, MftRecord);
410 return NULL;
411 }
412
413 Fcb = NtfsCreateFCB(L"\\", NULL, Vcb);
414 if (!Fcb)
415 {
416 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, MftRecord);
417 return NULL;
418 }
419
421 Fcb->Entry.NameType = FileName->NameType;
422 Fcb->Entry.NameLength = 0;
424 Fcb->RefCount = 1;
425 Fcb->DirIndex = 0;
426 Fcb->RFCB.FileSize.QuadPart = FileName->DataSize;
428 Fcb->RFCB.AllocationSize.QuadPart = FileName->AllocatedSize;
430 Fcb->LinkCount = MftRecord->LinkCount;
431
435
436 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, MftRecord);
437
438 return Fcb;
439}
VOID NtfsGrabFCB(PNTFS_VCB Vcb, PNTFS_FCB Fcb)
Definition: fcb.c:192
ULONG DirIndex
Definition: ntfs.h:615

Referenced by NtfsOpenRootFCB().

◆ NtfsMarkIrpContextForQueue()

FORCEINLINE NTSTATUS NtfsMarkIrpContextForQueue ( PNTFS_IRP_CONTEXT  IrpContext)

Definition at line 652 of file ntfs.h.

653{
654 PULONG Flags = &IrpContext->Flags;
655
656 *Flags &= ~IRPCONTEXT_COMPLETE;
658
659 return STATUS_PENDING;
660}
_In_ D3DDDI_VIDEO_PRESENT_TARGET_ID _In_ ULONG _In_ ULONG Flags
Definition: dispmprt.h:245
#define IRPCONTEXT_QUEUE
Definition: ntfs.h:507

Referenced by NtfsCachedRead(), NtfsCleanup(), NtfsClose(), NtfsCreate(), NtfsDirectoryControl(), NtfsFlushBuffers(), NtfsQueryInformation(), NtfsQueryVolumeInformation(), NtfsSetInformation(), and NtfsWrite().

◆ NtfsOpenRootFCB()

PNTFS_FCB NtfsOpenRootFCB ( PNTFS_VCB  Vcb)

Definition at line 443 of file fcb.c.

444{
446
448 if (Fcb == NULL)
449 {
451 }
452
453 return Fcb;
454}
PNTFS_FCB NtfsMakeRootFCB(PNTFS_VCB Vcb)
Definition: fcb.c:388

Referenced by NtfsGetFCBForFile().

◆ NtfsPerformIoRuns()

NTSTATUS NtfsPerformIoRuns ( IN PDEVICE_OBJECT  DeviceObject,
IN UCHAR  MajorFunction,
IN ULONG  SectorSize,
IN OUT PUCHAR  Buffer,
IN PNTFS_IO_RUN_LIST  RunList,
IN BOOLEAN  Override,
OUT PULONG BytesTransferred  OPTIONAL 
)

Definition at line 788 of file blockdev.c.

795{
799 Buffer,
800 NULL,
801 RunList,
802 Override,
804}
static NTSTATUS NtfsPerformIoRunsInternal(IN PDEVICE_OBJECT DeviceObject, IN UCHAR MajorFunction, IN ULONG SectorSize, IN OUT PUCHAR Buffer, IN PMDL BorrowedMdl OPTIONAL, IN PNTFS_IO_RUN_LIST RunList, IN BOOLEAN Override, OUT PULONG BytesTransferred OPTIONAL)
Definition: blockdev.c:483
_In_ UCHAR MajorFunction
Definition: wdfdevice.h:1703
_Must_inspect_result_ _In_ WDFUSBDEVICE _In_opt_ WDFREQUEST _In_opt_ PWDF_REQUEST_SEND_OPTIONS _In_ PWDF_USB_CONTROL_SETUP_PACKET _In_opt_ PWDF_MEMORY_DESCRIPTOR _Out_opt_ PULONG BytesTransferred
Definition: wdfusb.h:1342
_In_ ULONG SectorSize
Definition: halfuncs.h:291

Referenced by NtfsReadDisk(), and NtfsWriteDisk().

◆ NtfsPerformIrpIoRuns()

NTSTATUS NtfsPerformIrpIoRuns ( IN PDEVICE_OBJECT  DeviceObject,
IN UCHAR  MajorFunction,
IN ULONG  SectorSize,
IN PIRP  Irp,
IN OUT PUCHAR  Buffer,
IN PNTFS_IO_RUN_LIST  RunList,
IN BOOLEAN  Override,
OUT PULONG  BytesTransferred 
)

Definition at line 743 of file blockdev.c.

751{
752 PMDL BorrowedMdl = NULL;
753
754 if (Irp != NULL &&
755 Irp->MdlAddress != NULL &&
756 RunList->TotalLength <= MmGetMdlByteCount(Irp->MdlAddress))
757 {
758 /* Buffer maps exactly the pages this MDL describes, so it can stand
759 * in for one of our own, and on the paging path it must */
760 BorrowedMdl = Irp->MdlAddress;
761
762 /* One aligned run covering the lot goes straight down to the disk */
763 if (RunList->Count == 1 &&
764 RunList->Runs[0].Lbo != NTFS_SPARSE_LBO &&
765 (RunList->Runs[0].Lbo % SectorSize) == 0 &&
766 (RunList->Runs[0].ByteCount % SectorSize) == 0)
767 {
770 Irp,
771 &RunList->Runs[0],
772 Override,
774 }
775 }
776
780 Buffer,
781 BorrowedMdl,
782 RunList,
783 Override,
785}
static NTSTATUS NtfsForwardIrpToRun(IN PDEVICE_OBJECT DeviceObject, IN UCHAR MajorFunction, IN PIRP Irp, IN PNTFS_IO_RUN Run, IN BOOLEAN Override, OUT PULONG BytesTransferred)
Definition: blockdev.c:663
#define MmGetMdlByteCount(_Mdl)

Referenced by NtfsReadWriteVolume(), ReadAttributeToIrp(), and WriteAttributeFromIrp().

◆ NtfsQueryInformation()

NTSTATUS NtfsQueryInformation ( PNTFS_IRP_CONTEXT  IrpContext)

Definition at line 470 of file finfo.c.

471{
476 PVOID SystemBuffer;
478 PIRP Irp;
481
482 DPRINT("NtfsQueryInformation(%p)\n", IrpContext);
483
484 Irp = IrpContext->Irp;
485 Stack = IrpContext->Stack;
486 DeviceObject = IrpContext->DeviceObject;
487 FileInformationClass = Stack->Parameters.QueryFile.FileInformationClass;
488 FileObject = IrpContext->FileObject;
489 Fcb = FileObject->FsContext;
490
491 SystemBuffer = Irp->AssociatedIrp.SystemBuffer;
492 BufferLength = Stack->Parameters.QueryFile.Length;
493
496 {
497 return NtfsMarkIrpContextForQueue(IrpContext);
498 }
499
500 switch (FileInformationClass)
501 {
505 SystemBuffer,
506 &BufferLength);
507 break;
508
511 SystemBuffer,
512 &BufferLength);
513 break;
514
517 SystemBuffer,
518 &BufferLength);
519 break;
520
523 Fcb,
525 SystemBuffer,
526 &BufferLength);
527 break;
528
531 Fcb,
533 SystemBuffer,
534 &BufferLength);
535 break;
536
539 SystemBuffer,
540 &BufferLength);
541 break;
542
545 DeviceObject->DeviceExtension,
546 SystemBuffer,
547 &BufferLength);
548 break;
549
552 DeviceObject->DeviceExtension,
553 SystemBuffer,
554 &BufferLength);
555 break;
556
559 SystemBuffer,
560 &BufferLength);
561 break;
562
565 DPRINT1("Unimplemented information class: %s\n", GetInfoClassName(FileInformationClass));
567 break;
568
569 default:
570 DPRINT1("Unimplemented information class: %s\n", GetInfoClassName(FileInformationClass));
572 }
573
575
576 if (NT_SUCCESS(Status))
577 Irp->IoStatus.Information =
578 Stack->Parameters.QueryFile.Length - BufferLength;
579 else
580 Irp->IoStatus.Information = 0;
581
582 return Status;
583}
@ FilePositionInformation
Definition: from_kernel.h:75
@ FileAllInformation
Definition: from_kernel.h:79
@ FileInternalInformation
Definition: from_kernel.h:67
@ FileAttributeTagInformation
Definition: from_kernel.h:96
@ FileEaInformation
Definition: from_kernel.h:68
@ FileAlternateNameInformation
Definition: from_kernel.h:82
@ FileNameInformation
Definition: from_kernel.h:70
@ FileNetworkOpenInformation
Definition: from_kernel.h:95
@ FileStreamInformation
Definition: from_kernel.h:83
@ FileBasicInformation
Definition: from_kernel.h:65
enum _FILE_INFORMATION_CLASS FILE_INFORMATION_CLASS
Definition: directory.c:44
static OUT PIO_STATUS_BLOCK OUT PVOID IN ULONG IN FILE_INFORMATION_CLASS FileInformationClass
Definition: pipe.c:100
static NTSTATUS NtfsGetAttributeTagInformation(PNTFS_FCB Fcb, PFILE_ATTRIBUTE_TAG_INFORMATION AttributeTagInfo, PULONG BufferLength)
Definition: finfo.c:129
static NTSTATUS NtfsGetNameInformation(PFILE_OBJECT FileObject, PNTFS_FCB Fcb, PDEVICE_OBJECT DeviceObject, PFILE_NAME_INFORMATION NameInfo, PULONG BufferLength)
Definition: finfo.c:180
static NTSTATUS NtfsGetStreamInformation(PNTFS_FCB Fcb, PDEVICE_EXTENSION DeviceExt, PFILE_STREAM_INFORMATION StreamInfo, PULONG BufferLength)
Definition: finfo.c:276
static NTSTATUS NtfsGetPositionInformation(PFILE_OBJECT FileObject, PFILE_POSITION_INFORMATION PositionInfo, PULONG BufferLength)
Definition: finfo.c:78
const PCSTR GetInfoClassName(FILE_INFORMATION_CLASS infoClass)
Definition: finfo.c:346
static NTSTATUS NtfsGetStandardInformation(PNTFS_FCB Fcb, PDEVICE_OBJECT DeviceObject, PFILE_STANDARD_INFORMATION StandardInfo, PULONG BufferLength)
Definition: finfo.c:45
static NTSTATUS NtfsGetNetworkOpenInformation(PNTFS_FCB Fcb, PDEVICE_EXTENSION DeviceExt, PFILE_NETWORK_OPEN_INFORMATION NetworkInfo, PULONG BufferLength)
Definition: finfo.c:248
static NTSTATUS NtfsGetInternalInformation(PNTFS_FCB Fcb, PFILE_INTERNAL_INFORMATION InternalInfo, PULONG BufferLength)
Definition: finfo.c:227
static NTSTATUS NtfsGetBasicInformation(PFILE_OBJECT FileObject, PNTFS_FCB Fcb, PDEVICE_OBJECT DeviceObject, PFILE_BASIC_INFORMATION BasicInfo, PULONG BufferLength)
Definition: finfo.c:100
static NTSTATUS NtfsGetEaInformation(PNTFS_FCB Fcb, PFILE_EA_INFORMATION EaInfo, PULONG BufferLength)
Definition: finfo.c:155
#define FileStandardInformation
Definition: propsheet.cpp:61
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG BufferLength
Definition: wdfdevice.h:3777

Referenced by NtfsDispatch().

◆ NtfsQueryVolumeInformation()

NTSTATUS NtfsQueryVolumeInformation ( PNTFS_IRP_CONTEXT  IrpContext)

Definition at line 430 of file volinfo.c.

431{
432 PIRP Irp;
437 PVOID SystemBuffer;
439 PDEVICE_EXTENSION DeviceExt;
440
441 DPRINT("NtfsQueryVolumeInformation() called\n");
442
443 ASSERT(IrpContext);
444
445 Irp = IrpContext->Irp;
446 DeviceObject = IrpContext->DeviceObject;
447 DeviceExt = DeviceObject->DeviceExtension;
448 Stack = IrpContext->Stack;
449
450 if (!ExAcquireResourceSharedLite(&DeviceExt->DirResource,
452 {
453 return NtfsMarkIrpContextForQueue(IrpContext);
454 }
455
456 FsInformationClass = Stack->Parameters.QueryVolume.FsInformationClass;
457 BufferLength = Stack->Parameters.QueryVolume.Length;
458 SystemBuffer = Irp->AssociatedIrp.SystemBuffer;
459 RtlZeroMemory(SystemBuffer, BufferLength);
460
461 DPRINT("FsInformationClass %d\n", FsInformationClass);
462 DPRINT("SystemBuffer %p\n", SystemBuffer);
463
464 switch (FsInformationClass)
465 {
468 SystemBuffer,
469 &BufferLength);
470 break;
471
474 SystemBuffer,
475 &BufferLength);
476 break;
477
480 SystemBuffer,
481 &BufferLength);
482 break;
483
486 SystemBuffer,
487 &BufferLength);
488 break;
489
490 default:
492 }
493
494 ExReleaseResourceLite(&DeviceExt->DirResource);
495
496 if (NT_SUCCESS(Status))
497 Irp->IoStatus.Information =
498 Stack->Parameters.QueryVolume.Length - BufferLength;
499 else
500 Irp->IoStatus.Information = 0;
501
502 return Status;
503}
_Must_inspect_result_ _In_ PFILE_OBJECT _In_ ULONG _In_ FS_INFORMATION_CLASS FsInformationClass
Definition: fltkernel.h:1330
@ FileFsDeviceInformation
Definition: from_kernel.h:222
@ FileFsAttributeInformation
Definition: from_kernel.h:223
@ FileFsVolumeInformation
Definition: from_kernel.h:219
@ FileFsSizeInformation
Definition: from_kernel.h:221
enum _FSINFOCLASS FS_INFORMATION_CLASS
static NTSTATUS NtfsGetFsDeviceInformation(PDEVICE_OBJECT DeviceObject, PFILE_FS_DEVICE_INFORMATION FsDeviceInfo, PULONG BufferLength)
Definition: volinfo.c:405
static NTSTATUS NtfsGetFsVolumeInformation(PDEVICE_OBJECT DeviceObject, PFILE_FS_VOLUME_INFORMATION FsVolumeInfo, PULONG BufferLength)
Definition: volinfo.c:294
static NTSTATUS NtfsGetFsAttributeInformation(PDEVICE_EXTENSION DeviceExt, PFILE_FS_ATTRIBUTE_INFORMATION FsAttributeInfo, PULONG BufferLength)
Definition: volinfo.c:340
static NTSTATUS NtfsGetFsSizeInformation(PDEVICE_OBJECT DeviceObject, PFILE_FS_SIZE_INFORMATION FsSizeInfo, PULONG BufferLength)
Definition: volinfo.c:375

Referenced by NtfsDispatch().

◆ NtfsRead()

NTSTATUS NtfsRead ( PNTFS_IRP_CONTEXT  IrpContext)

Definition at line 396 of file rw.c.

397{
398 PDEVICE_EXTENSION DeviceExt;
404 ULONG ReturnedReadLength = 0;
406 PIRP Irp;
408
409 DPRINT("NtfsRead(IrpContext %p)\n", IrpContext);
410
411 DeviceObject = IrpContext->DeviceObject;
412 Irp = IrpContext->Irp;
413 Stack = IrpContext->Stack;
414 FileObject = IrpContext->FileObject;
415
416 DeviceExt = DeviceObject->DeviceExtension;
417 ReadLength = Stack->Parameters.Read.Length;
418 ReadOffset = Stack->Parameters.Read.ByteOffset;
420
421 /* Once dismounted the metadata can't be trusted; only raw volume access
422 * is still served */
423 if ((DeviceExt->Flags & VCB_VOLUME_DISMOUNTED) &&
424 !(((PNTFS_FCB)FileObject->FsContext)->Flags & FCB_IS_VOLUME))
425 {
426 Irp->IoStatus.Information = 0;
428 }
429
430 /* A handle on the volume itself is raw access to the partition. */
431 if (((PNTFS_FCB)FileObject->FsContext)->Flags & FCB_IS_VOLUME)
432 {
433 Status = NtfsReadWriteVolume(DeviceExt,
435 Buffer,
437 ReadOffset.QuadPart,
438 Irp,
439 &ReturnedReadLength);
440 }
441 else if (NtfsFCBIsDirectory((PNTFS_FCB)FileObject->FsContext))
442 {
443 /* A directory has no data stream to read */
444 Irp->IoStatus.Information = 0;
446 }
447 else if (!(Irp->Flags & IRP_PAGING_IO) && NtfsIsRegularFileObject(FileObject) &&
448 !FsRtlCheckLockForReadAccess(&((PNTFS_FCB)FileObject->FsContext)->FileLock, Irp))
449 {
450 Irp->IoStatus.Information = 0;
452 }
454 {
455 Status = NtfsCachedRead(IrpContext,
456 (PNTFS_FCB)FileObject->FsContext,
457 Buffer,
459 &ReadOffset,
460 &ReturnedReadLength);
461 if (Status == STATUS_PENDING)
462 return Status;
463 }
464 else
465 {
466 PNTFS_FCB Fcb = (PNTFS_FCB)FileObject->FsContext;
467
468 /* A non cached read must not miss what is still dirty in the cache */
471 {
473
475 }
476
477 Status = NtfsReadFile(DeviceExt,
479 Buffer,
481 ReadOffset.QuadPart,
482 Irp->Flags,
483 Irp,
484 &ReturnedReadLength);
485 }
486 if (NT_SUCCESS(Status))
487 {
488 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
489 {
490 FileObject->CurrentByteOffset.QuadPart =
491 ReadOffset.QuadPart + ReturnedReadLength;
492 }
493
494 Irp->IoStatus.Information = ReturnedReadLength;
495 }
496 else
497 {
498 Irp->IoStatus.Information = 0;
499 }
500
501 return Status;
502}
ULONG ReadLength
VOID NTAPI CcFlushCache(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, OUT OPTIONAL PIO_STATUS_BLOCK IoStatus)
Definition: cachesub.c:222
PVOID NtfsGetUserBuffer(PIRP Irp, BOOLEAN Paging)
Definition: misc.c:120
static NTSTATUS NtfsReadFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, PUCHAR Buffer, ULONG Length, ULONGLONG ReadOffset, ULONG IrpFlags, PIRP Irp, PULONG LengthRead)
Definition: rw.c:124
static NTSTATUS NtfsReadWriteVolume(PDEVICE_EXTENSION DeviceExt, UCHAR MajorFunction, PUCHAR Buffer, ULONG Length, LONGLONG Offset, PIRP Irp, PULONG LengthTransferred)
Definition: rw.c:80
static NTSTATUS NTAPI NtfsCachedRead(_In_ PNTFS_IRP_CONTEXT IrpContext, _In_ PNTFS_FCB Fcb, _Out_writes_bytes_(Length) PVOID Buffer, _In_ ULONG Length, _In_ PLARGE_INTEGER ReadOffset, _Out_ PULONG LengthRead)
Definition: rw.c:327
BOOLEAN NTAPI FsRtlCheckLockForReadAccess(IN PFILE_LOCK FileLock, IN PIRP Irp)
Definition: filelock.c:672
#define STATUS_FILE_LOCK_CONFLICT
Definition: ntstatus.h:414
_Must_inspect_result_ _In_ WDFUSBPIPE _In_ WDFREQUEST _In_opt_ WDFMEMORY _In_opt_ PWDFMEMORY_OFFSET ReadOffset
Definition: wdfusb.h:2003
#define IRP_PAGING_IO
#define FO_SYNCHRONOUS_IO
Definition: iotypes.h:1776
#define IRP_NOCACHE

◆ NtfsReadDisk()

NTSTATUS NtfsReadDisk ( IN PDEVICE_OBJECT  DeviceObject,
IN LONGLONG  StartingOffset,
IN ULONG  Length,
IN ULONG  SectorSize,
IN OUT PUCHAR  Buffer,
IN BOOLEAN  Override 
)

Definition at line 836 of file blockdev.c.

842{
843 NTFS_IO_RUN_LIST RunList;
845 ULONG Transferred;
846
847 DPRINT("NtfsReadDisk(%p, %I64x, %lu, %lu, %p, %d)\n",
849
850 if (Length == 0)
851 return STATUS_SUCCESS;
852
853 NtfsInitIoRunList(&RunList);
854
856 if (!NT_SUCCESS(Status))
857 return Status;
858
862 Buffer,
863 &RunList,
864 Override,
865 &Transferred);
866
867 NtfsFreeIoRunList(&RunList);
868
869 if (NT_SUCCESS(Status) && Transferred != Length)
870 {
871 DPRINT1("Short read: asked for %lu bytes, got %lu\n", Length, Transferred);
873 }
874
875 DPRINT("NtfsReadDisk() done (Status %x)\n", Status);
876
877 return Status;
878}
_In_ PFCB _In_ LONGLONG StartingOffset
Definition: cdprocs.h:291
NTSTATUS NtfsPerformIoRuns(IN PDEVICE_OBJECT DeviceObject, IN UCHAR MajorFunction, IN ULONG SectorSize, IN OUT PUCHAR Buffer, IN PNTFS_IO_RUN_LIST RunList, IN BOOLEAN Override, OUT PULONG BytesTransferred OPTIONAL)
Definition: blockdev.c:788
VOID NtfsFreeIoRunList(IN OUT PNTFS_IO_RUN_LIST RunList)
Definition: blockdev.c:140
NTSTATUS NtfsAddIoRun(IN OUT PNTFS_IO_RUN_LIST RunList, IN LONGLONG Lbo, IN ULONG ByteCount)
Definition: blockdev.c:74
VOID NtfsInitIoRunList(OUT PNTFS_IO_RUN_LIST RunList)
Definition: blockdev.c:40
#define STATUS_UNEXPECTED_IO_ERROR
Definition: ntstatus.h:563

Referenced by NtfsPerformIoRunsInternal(), and NtfsReadSectors().

◆ NtfsReadFCBAttribute()

NTSTATUS NtfsReadFCBAttribute ( PNTFS_VCB  Vcb,
PNTFS_FCB  pFCB,
ULONG  Type,
PCWSTR  Name,
ULONG  NameLength,
PVOID *  Data 
)

Definition at line 806 of file fcb.c.

812{
814 PFILE_RECORD_HEADER FileRecord;
815 PNTFS_ATTR_CONTEXT AttrCtxt;
816 ULONGLONG AttrLength;
817
818 FileRecord = ExAllocateFromNPagedLookasideList(&Vcb->FileRecLookasideList);
819 if (FileRecord == NULL)
820 {
822 }
823
824 Status = ReadFileRecord(Vcb, pFCB->MFTIndex, FileRecord);
825 if (!NT_SUCCESS(Status))
826 {
827 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, FileRecord);
828 return Status;
829 }
830
831 Status = FindAttribute(Vcb, FileRecord, Type, Name, NameLength, &AttrCtxt, NULL);
832 if (!NT_SUCCESS(Status))
833 {
834 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, FileRecord);
835 return Status;
836 }
837
838 AttrLength = AttributeDataLength(AttrCtxt->pRecord);
840 if (*Data == NULL)
841 {
842 ReleaseAttributeContext(AttrCtxt);
843 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, FileRecord);
845 }
846
847 ReadAttribute(Vcb, AttrCtxt, 0, *Data, AttrLength);
848
849 ReleaseAttributeContext(AttrCtxt);
850 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, FileRecord);
851
852 return STATUS_SUCCESS;
853}

Referenced by NtfsCreateFile().

◆ NtfsReadSectors()

NTSTATUS NtfsReadSectors ( IN PDEVICE_OBJECT  DeviceObject,
IN ULONG  DiskSector,
IN ULONG  SectorCount,
IN ULONG  SectorSize,
IN OUT PUCHAR  Buffer,
IN BOOLEAN  Override 
)

Definition at line 1011 of file blockdev.c.

1017{
1020
1021 Offset = (LONGLONG)DiskSector * (LONGLONG)SectorSize;
1023
1025}
D3D12_VIDEO_MOTION_ESTIMATOR_SEARCH_BLOCK_SIZE BlockSize
Definition: d3d12video.idl:529
NTSTATUS NtfsReadDisk(IN PDEVICE_OBJECT DeviceObject, IN LONGLONG StartingOffset, IN ULONG Length, IN ULONG SectorSize, IN OUT PUCHAR Buffer, IN BOOLEAN Override)
Definition: blockdev.c:836
ULONG SectorCount
Definition: part_brfr.c:22

Referenced by NtfsGetVolumeData(), NtfsHasFileSystem(), and ReadLCN().

◆ NtfsReleaseFCB()

VOID NtfsReleaseFCB ( PNTFS_VCB  Vcb,
PNTFS_FCB  Fcb 
)

Definition at line 209 of file fcb.c.

211{
212 KIRQL oldIrql;
213
214 DPRINT("releasing FCB at %p: %S, refCount:%d\n",
215 Fcb,
216 Fcb->PathName,
217 Fcb->RefCount);
218
219 KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql);
220 Fcb->RefCount--;
221 if (Fcb->RefCount <= 0 && (!NtfsFCBIsDirectory(Fcb) || (Fcb->Flags & FCB_DELETED)))
222 {
223 KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
224
226
229 {
230 DPRINT("Keeping FCB %p (%S): still mapped\n", Fcb, Fcb->PathName);
231 return;
232 }
233
234 /* A deleted FCB already left the table */
235 KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql);
236 if (!(Fcb->Flags & FCB_DELETED))
238 KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
239
241 }
242 else
243 {
244 KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
245 }
246}
#define FCB_DELETED
Definition: ntfs.h:587
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
BOOLEAN NTAPI CcUninitializeCacheMap(IN PFILE_OBJECT FileObject, IN OPTIONAL PLARGE_INTEGER TruncateSize, IN OPTIONAL PCACHE_UNINITIALIZE_EVENT UninitializeEvent)
Definition: fssup.c:286
VOID NtfsDestroyFCB(PNTFS_FCB Fcb)
Definition: fcb.c:126

Referenced by NtfsClearRenameTarget(), NtfsCloseFile(), NtfsFlushVolumeFiles(), NtfsGetFCBForFile(), NtfsOpenFile(), and NtfsOpenTargetDirectory().

◆ NtfsRelLazyWrite()

VOID NTAPI NtfsRelLazyWrite ( PVOID  Context)

◆ NtfsRelReadAhead()

VOID NTAPI NtfsRelReadAhead ( PVOID  Context)

◆ NtfsRemoveFCBFromTable()

VOID NtfsRemoveFCBFromTable ( _In_ PNTFS_VCB  Vcb,
_In_ PNTFS_FCB  Fcb 
)

Definition at line 270 of file fcb.c.

273{
275
276 KeAcquireSpinLock(&Vcb->FcbListLock, &OldIrql);
277
278 /* FCB_DELETED tells NtfsReleaseFCB() the entry is already unlinked */
279 if (!(Fcb->Flags & FCB_DELETED))
280 {
284 }
285
286 KeReleaseSpinLock(&Vcb->FcbListLock, OldIrql);
287}
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778

Referenced by NtfsCleanupFile().

◆ NtfsRemoveFilenameFromDirectory()

NTSTATUS NtfsRemoveFilenameFromDirectory ( PDEVICE_EXTENSION  DeviceExt,
ULONGLONG  DirectoryMftIndex,
PFILENAME_ATTRIBUTE  FilenameAttribute,
BOOLEAN  CaseSensitive 
)

Definition at line 3297 of file mft.c.

3301{
3303
3305 ExAcquireResourceExclusiveLite(&DeviceExt->IndexResource, TRUE);
3306 Status = RemoveFilenameFromDirectoryWorker(DeviceExt, DirectoryMftIndex, FilenameAttribute, CaseSensitive);
3307 ExReleaseResourceLite(&DeviceExt->IndexResource);
3309
3310 return Status;
3311}
static NTSTATUS RemoveFilenameFromDirectoryWorker(PDEVICE_EXTENSION DeviceExt, ULONGLONG DirectoryMftIndex, PFILENAME_ATTRIBUTE FilenameAttribute, BOOLEAN CaseSensitive)
Definition: mft.c:3096

Referenced by NtfsDeleteFileRecord(), and NtfsUnlinkFileNames().

◆ NtfsRemoveKey()

NTSTATUS NtfsRemoveKey ( PB_TREE_FILENAME_NODE  Node,
PB_TREE_KEY  SearchKey,
BOOLEAN  CaseSensitive 
)

Definition at line 2067 of file btree.c.

2070{
2071 PB_TREE_KEY PreviousKey = NULL;
2072 PB_TREE_KEY CurrentKey = Node->FirstKey;
2073 ULONG i;
2074
2075 for (i = 0; i < Node->KeyCount; i++)
2076 {
2077 LONG Comparison;
2078
2079 if (CurrentKey == NULL)
2080 break;
2081
2083 break;
2084
2085 Comparison = CompareTreeKeys(SearchKey, CurrentKey, CaseSensitive);
2086
2087 if (Comparison == 0)
2088 return RemoveKeyFromNode(Node, PreviousKey, CurrentKey);
2089
2090 // Everything that sorts before CurrentKey is beneath it
2091 if (Comparison < 0)
2092 break;
2093
2094 PreviousKey = CurrentKey;
2095 CurrentKey = CurrentKey->NextKey;
2096 }
2097
2098 if (CurrentKey != NULL && CurrentKey->LesserChild != NULL)
2099 return NtfsRemoveKey(CurrentKey->LesserChild, SearchKey, CaseSensitive);
2100
2102}
NTSTATUS NtfsRemoveKey(PB_TREE_FILENAME_NODE Node, PB_TREE_KEY SearchKey, BOOLEAN CaseSensitive)
Definition: btree.c:2067
static NTSTATUS RemoveKeyFromNode(PB_TREE_FILENAME_NODE Node, PB_TREE_KEY PreviousKey, PB_TREE_KEY Key)
Definition: btree.c:1995

Referenced by NtfsRemoveKey(), and RemoveFilenameFromDirectoryWorker().

◆ NtfsResizeAllocation()

NTSTATUS NtfsResizeAllocation ( _In_ PNTFS_FCB  Fcb,
_In_ PFILE_OBJECT  FileObject,
_In_ BOOLEAN  CaseSensitive,
_In_ ULONGLONG  AllocationSize 
)

Definition at line 924 of file mft.c.

929{
931 ULONG BytesPerCluster = Vcb->NtfsInfo.BytesPerCluster;
932 PFILE_RECORD_HEADER FileRecord;
933 PNTFS_ATTR_CONTEXT DataContext;
934 PNTFS_ATTR_RECORD DestinationAttribute;
935 ULONG AttributeOffset;
936 ULONGLONG CurrentSize;
937 BOOLEAN Changed = FALSE;
939
940 ASSERT(AllocationSize % BytesPerCluster == 0);
941
942 FileRecord = ExAllocateFromNPagedLookasideList(&Vcb->FileRecLookasideList);
943 if (FileRecord == NULL)
945
946 Status = ReadFileRecord(Vcb, Fcb->MFTIndex, FileRecord);
947 if (!NT_SUCCESS(Status))
948 goto Quit;
949
950 Status = FindAttribute(Vcb, FileRecord, AttributeData, Fcb->Stream, wcslen(Fcb->Stream), &DataContext, &AttributeOffset);
951 if (!NT_SUCCESS(Status))
952 goto Quit;
953
954 /* Resident data lives in the record, and compressed or sparse streams
955 * round their allocation differently; there is nothing to do for those */
956 if (!DataContext->pRecord->IsNonResident ||
957 (DataContext->pRecord->Flags & (NTFS_ATTR_COMPRESSION_MASK | NTFS_ATTR_SPARSE)))
958 {
959 ReleaseAttributeContext(DataContext);
960 goto Quit;
961 }
962
963 AllocationSize = max(AllocationSize, ROUND_UP(DataContext->pRecord->NonResident.DataSize, BytesPerCluster));
964 CurrentSize = DataContext->pRecord->NonResident.AllocatedSize;
965
966 if (AllocationSize < CurrentSize)
967 {
969
970 NewSize.QuadPart = AllocationSize;
971 if (!MmCanFileBeTruncated(FileObject->SectionObjectPointer, &NewSize))
972 {
973 ReleaseAttributeContext(DataContext);
975 goto Quit;
976 }
977 }
978
979 /* Paging writes look the runs up again, keep them out while those change */
981
982 if (AllocationSize > CurrentSize)
983 {
984 Status = NtfsExtendAllocation(Vcb, DataContext, AttributeOffset, FileRecord, AllocationSize);
985 Changed = NT_SUCCESS(Status);
986 }
987 else if (AllocationSize < CurrentSize)
988 {
990 DataContext,
991 AttributeOffset,
992 FileRecord,
993 (ULONG)((CurrentSize - AllocationSize) / BytesPerCluster));
994 if (NT_SUCCESS(Status))
995 {
996 DestinationAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + AttributeOffset);
997 DestinationAttribute->NonResident.AllocatedSize = AllocationSize;
998 Changed = TRUE;
999 }
1000 }
1001
1002 if (Changed)
1003 {
1004 Status = UpdateFileRecord(Vcb, Fcb->MFTIndex, FileRecord);
1005 if (NT_SUCCESS(Status))
1007 }
1008
1010 ReleaseAttributeContext(DataContext);
1011
1012 if (Changed && NT_SUCCESS(Status))
1013 {
1015
1016 /* The directory entries carry the allocation too */
1018 FileRecord,
1019 Fcb->MFTIndex,
1021 CaseSensitive);
1022 }
1023
1024Quit:
1025 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, FileRecord);
1026
1027 return Status;
1028}
#define NTFS_FILENAME_UPDATE_SIZES
Definition: ntfs.h:1332
_Must_inspect_result_ _In_ USHORT NewSize
Definition: fltkernel.h:975
VOID NTAPI CcSetFileSizes(IN PFILE_OBJECT FileObject, IN PCC_FILE_SIZES FileSizes)
Definition: fssup.c:356
NTSTATUS NtfsUpdateDuplicatedInformation(PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER FileRecord, ULONGLONG MFTIndex, ULONG Flags, BOOLEAN CaseSensitive)
Definition: mft.c:1995
NTSTATUS NtfsExtendAllocation(_In_ PDEVICE_EXTENSION Vcb, _In_ PNTFS_ATTR_CONTEXT AttrContext, _In_ ULONG AttrOffset, _In_ PFILE_RECORD_HEADER FileRecord, _In_ ULONGLONG AllocationSize)
Definition: mft.c:753
#define STATUS_USER_MAPPED_FILE
Definition: ntstatus.h:833
BOOLEAN NTAPI MmCanFileBeTruncated(_In_ PSECTION_OBJECT_POINTERS SectionObjectPointer, _In_opt_ PLARGE_INTEGER NewFileSize)
Definition: section.c:4312

Referenced by NtfsSetAllocationInformation().

◆ NtfsSetEndOfFile()

NTSTATUS NtfsSetEndOfFile ( PNTFS_FCB  Fcb,
PFILE_OBJECT  FileObject,
PDEVICE_EXTENSION  DeviceExt,
ULONG  IrpFlags,
BOOLEAN  CaseSensitive,
PLARGE_INTEGER  NewFileSize 
)

Definition at line 625 of file finfo.c.

631{
632 LARGE_INTEGER CurrentFileSize;
633 PFILE_RECORD_HEADER FileRecord;
634 PNTFS_ATTR_CONTEXT DataContext;
635 ULONG AttributeOffset;
637 PFILENAME_ATTRIBUTE FileNameAttribute;
638
639
640 // Allocate non-paged memory for the file record
641 FileRecord = ExAllocateFromNPagedLookasideList(&DeviceExt->FileRecLookasideList);
642 if (FileRecord == NULL)
643 {
644 DPRINT1("Couldn't allocate memory for file record!");
646 }
647
648 // read the file record
649 DPRINT("Reading file record...\n");
650 Status = ReadFileRecord(DeviceExt, Fcb->MFTIndex, FileRecord);
651 if (!NT_SUCCESS(Status))
652 {
653 // We couldn't get the file's record. Free the memory and return the error
654 DPRINT1("Can't find record for %wS!\n", Fcb->ObjectName);
655 ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, FileRecord);
656 return Status;
657 }
658
659 DPRINT("Found record for %wS\n", Fcb->ObjectName);
660
661 CurrentFileSize.QuadPart = NtfsGetFileSize(DeviceExt, FileRecord, L"", 0, NULL);
662
663 // Are we trying to decrease the file size?
664 if (NewFileSize->QuadPart < CurrentFileSize.QuadPart)
665 {
666 // Is the file mapped?
667 if (!MmCanFileBeTruncated(FileObject->SectionObjectPointer,
669 {
670 DPRINT1("Couldn't decrease file size!\n");
671 ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, FileRecord);
673 }
674 }
675
676 // Find the attribute with the data stream for our file
677 DPRINT("Finding Data Attribute...\n");
678 Status = FindAttribute(DeviceExt,
679 FileRecord,
681 Fcb->Stream,
682 wcslen(Fcb->Stream),
683 &DataContext,
684 &AttributeOffset);
685
686 // Did we fail to find the attribute?
687 if (!NT_SUCCESS(Status))
688 {
689 DPRINT1("No '%S' data stream associated with file!\n", Fcb->Stream);
690 ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, FileRecord);
691 return Status;
692 }
693
694 // Get the size of the data attribute
695 CurrentFileSize.QuadPart = AttributeDataLength(DataContext->pRecord);
696
697 // Are we enlarging the attribute?
698 if (NewFileSize->QuadPart > CurrentFileSize.QuadPart)
699 {
700 // is increasing the stream size not allowed?
701 if ((Fcb->Flags & FCB_IS_VOLUME) ||
702 (IrpFlags & IRP_PAGING_IO))
703 {
704 // TODO - just fail for now
705 ReleaseAttributeContext(DataContext);
706 ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, FileRecord);
708 }
709 }
710
711 // set the attribute data length
712 Status = SetAttributeDataLength(FileObject, Fcb, DataContext, AttributeOffset, FileRecord, NewFileSize);
713 if (!NT_SUCCESS(Status))
714 {
715 ReleaseAttributeContext(DataContext);
716 ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, FileRecord);
717 return Status;
718 }
719
720 // now we need to update this file's size in every directory index entry that references it
721 // TODO: expand to work with every filename / hardlink stored in the file record.
722 FileNameAttribute = GetBestFileNameFromRecord(Fcb->Vcb, FileRecord);
723 if (FileNameAttribute == NULL)
724 {
725 DPRINT1("Unable to find FileName attribute associated with file!\n");
726 ReleaseAttributeContext(DataContext);
727 ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, FileRecord);
729 }
730
732 FileRecord,
733 Fcb->MFTIndex,
735 CaseSensitive);
736
737 ReleaseAttributeContext(DataContext);
738 ExFreeToNPagedLookasideList(&DeviceExt->FileRecLookasideList, FileRecord);
739
740 return Status;
741}
NTSTATUS SetAttributeDataLength(PFILE_OBJECT FileObject, PNTFS_FCB Fcb, PNTFS_ATTR_CONTEXT AttrContext, ULONG AttrOffset, PFILE_RECORD_HEADER FileRecord, PLARGE_INTEGER DataSize)
Definition: mft.c:615
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
_In_opt_ PLARGE_INTEGER NewFileSize
Definition: mmfuncs.h:608

Referenced by NtfsSetAllocationInformation(), and NtfsSetInformation().

◆ NtfsSetInformation()

NTSTATUS NtfsSetInformation ( PNTFS_IRP_CONTEXT  IrpContext)

Definition at line 1748 of file finfo.c.

1749{
1752 PDEVICE_EXTENSION DeviceExt;
1754 PNTFS_FCB Fcb;
1755 PVOID SystemBuffer;
1757 PIRP Irp;
1760
1761 DPRINT("NtfsSetInformation(%p)\n", IrpContext);
1762
1763 Irp = IrpContext->Irp;
1764 Stack = IrpContext->Stack;
1765 DeviceObject = IrpContext->DeviceObject;
1766 DeviceExt = DeviceObject->DeviceExtension;
1767 FileInformationClass = Stack->Parameters.QueryFile.FileInformationClass;
1768 FileObject = IrpContext->FileObject;
1769 Fcb = FileObject->FsContext;
1770
1771 SystemBuffer = Irp->AssociatedIrp.SystemBuffer;
1772 BufferLength = Stack->Parameters.QueryFile.Length;
1773
1774 /* A rename changes two directories and the FCB table, which creates rely
1775 * on under DirResource. Take it first, the same order create does. */
1777 !ExAcquireResourceExclusiveLite(&DeviceExt->DirResource,
1778 BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT)))
1779 {
1780 return NtfsMarkIrpContextForQueue(IrpContext);
1781 }
1782
1783 /* Every class below rewrites the file record from a copy it reads, so
1784 * two of them at once on the same file would lose one update */
1786 BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT)))
1787 {
1789 ExReleaseResourceLite(&DeviceExt->DirResource);
1790
1791 return NtfsMarkIrpContextForQueue(IrpContext);
1792 }
1793
1794 switch (FileInformationClass)
1795 {
1796 PFILE_END_OF_FILE_INFORMATION EndOfFileInfo;
1797
1800 {
1802 break;
1803 }
1804
1805 /* A directory's record carries its index, which a create in it
1806 * could be changing; IndexResource keeps the two apart */
1808 ExAcquireResourceExclusiveLite(&DeviceExt->IndexResource, TRUE);
1809 Status = NtfsSetBasicInformation(DeviceExt,
1810 Fcb,
1812 (PFILE_BASIC_INFORMATION)SystemBuffer);
1813 ExReleaseResourceLite(&DeviceExt->IndexResource);
1815 break;
1816
1819 {
1821 break;
1822 }
1823
1825 FileObject,
1826 DeviceExt,
1827 Irp->Flags,
1829 &((PFILE_ALLOCATION_INFORMATION)SystemBuffer)->AllocationSize);
1830 break;
1831
1833 EndOfFileInfo = (PFILE_END_OF_FILE_INFORMATION)SystemBuffer;
1835 FileObject,
1836 DeviceExt,
1837 Irp->Flags,
1839 &EndOfFileInfo->EndOfFile);
1840 break;
1841
1844 {
1846 break;
1847 }
1848
1850 Fcb,
1851 FileObject,
1853 (PFILE_DISPOSITION_INFORMATION)SystemBuffer);
1854 break;
1855
1858 {
1860 break;
1861 }
1862
1863 Status = NtfsSetRenameInformation(DeviceExt,
1864 Fcb,
1865 Stack->Parameters.SetFile.FileObject,
1866 Stack->Parameters.SetFile.ReplaceIfExists,
1868 (PFILE_RENAME_INFORMATION)SystemBuffer,
1869 BufferLength);
1870 break;
1871
1872 // TODO: all other information classes
1873
1874 default:
1875 DPRINT1("FIXME: Unimplemented information class: %s\n", GetInfoClassName(FileInformationClass));
1877 }
1878
1880
1882 ExReleaseResourceLite(&DeviceExt->DirResource);
1883
1884 if (NT_SUCCESS(Status))
1885 Irp->IoStatus.Information =
1886 Stack->Parameters.QueryFile.Length - BufferLength;
1887 else
1888 Irp->IoStatus.Information = 0;
1889
1890 return Status;
1891}
@ FileEndOfFileInformation
Definition: from_kernel.h:81
@ FileRenameInformation
Definition: from_kernel.h:71
@ FileAllocationInformation
Definition: from_kernel.h:80
@ FileDispositionInformation
Definition: from_kernel.h:74
struct _FILE_END_OF_FILE_INFORMATION * PFILE_END_OF_FILE_INFORMATION
static NTSTATUS NtfsSetBasicInformation(PDEVICE_EXTENSION DeviceExt, PNTFS_FCB Fcb, BOOLEAN CaseSensitive, PFILE_BASIC_INFORMATION BasicInfo)
Definition: finfo.c:830
NTSTATUS NtfsSetEndOfFile(PNTFS_FCB Fcb, PFILE_OBJECT FileObject, PDEVICE_EXTENSION DeviceExt, ULONG IrpFlags, BOOLEAN CaseSensitive, PLARGE_INTEGER NewFileSize)
Definition: finfo.c:625
static NTSTATUS NTAPI NtfsSetAllocationInformation(_In_ PNTFS_FCB Fcb, _In_ PFILE_OBJECT FileObject, _In_ PDEVICE_EXTENSION DeviceExt, _In_ ULONG IrpFlags, _In_ BOOLEAN CaseSensitive, _In_ PLARGE_INTEGER AllocationSize)
Definition: finfo.c:747
static NTSTATUS NtfsSetRenameInformation(_In_ PDEVICE_EXTENSION DeviceExt, _In_ PNTFS_FCB Fcb, _In_opt_ PFILE_OBJECT TargetFileObject, _In_ BOOLEAN ReplaceIfExists, _In_ BOOLEAN CaseSensitive, _In_ PFILE_RENAME_INFORMATION RenameInfo, _In_ ULONG BufferLength)
Definition: finfo.c:1651
static NTSTATUS NtfsSetDispositionInformation(PDEVICE_EXTENSION DeviceExt, PNTFS_FCB Fcb, PFILE_OBJECT FileObject, BOOLEAN CaseSensitive, PFILE_DISPOSITION_INFORMATION DispositionInfo)
Definition: finfo.c:941
#define STATUS_INFO_LENGTH_MISMATCH
Definition: udferr_usr.h:133
#define SL_CASE_SENSITIVE
Definition: iotypes.h:1820

Referenced by NtfsDispatch().

◆ NtfsSetVolumeInformation()

NTSTATUS NtfsSetVolumeInformation ( PNTFS_IRP_CONTEXT  IrpContext)

Definition at line 507 of file volinfo.c.

508{
509 PIRP Irp;
510
511 DPRINT("NtfsSetVolumeInformation() called\n");
512
513 ASSERT(IrpContext);
514
515 Irp = IrpContext->Irp;
517 Irp->IoStatus.Information = 0;
518
520}

Referenced by NtfsDispatch().

◆ NtfsTrimAllocation()

NTSTATUS NtfsTrimAllocation ( _In_ PNTFS_FCB  Fcb)

Definition at line 842 of file mft.c.

844{
846 ULONG BytesPerCluster = Vcb->NtfsInfo.BytesPerCluster;
847 PFILE_RECORD_HEADER FileRecord;
848 PNTFS_ATTR_CONTEXT DataContext;
849 PNTFS_ATTR_RECORD DestinationAttribute;
850 ULONG AttributeOffset;
851 ULONGLONG NeededSize = 0;
853
854 FileRecord = ExAllocateFromNPagedLookasideList(&Vcb->FileRecLookasideList);
855 if (FileRecord == NULL)
857
858 /* Paging writes look the runs up again; keep them out while the tail goes */
860
861 Status = ReadFileRecord(Vcb, Fcb->MFTIndex, FileRecord);
862 if (!NT_SUCCESS(Status))
863 goto Quit;
864
865 Status = FindAttribute(Vcb, FileRecord, AttributeData, Fcb->Stream, wcslen(Fcb->Stream), &DataContext, &AttributeOffset);
866 if (!NT_SUCCESS(Status))
867 goto Quit;
868
869 if (DataContext->pRecord->IsNonResident)
870 NeededSize = ROUND_UP(DataContext->pRecord->NonResident.DataSize, BytesPerCluster);
871
872 /* Compressed and sparse streams round their allocation differently; leave them be */
873 if (DataContext->pRecord->IsNonResident &&
874 !(DataContext->pRecord->Flags & (NTFS_ATTR_COMPRESSION_MASK | NTFS_ATTR_SPARSE)) &&
875 DataContext->pRecord->NonResident.AllocatedSize > NeededSize)
876 {
878 DataContext,
879 AttributeOffset,
880 FileRecord,
881 (ULONG)((DataContext->pRecord->NonResident.AllocatedSize - NeededSize) / BytesPerCluster));
882 if (NT_SUCCESS(Status))
883 {
884 DestinationAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + AttributeOffset);
885 DestinationAttribute->NonResident.AllocatedSize = NeededSize;
886
887 Status = UpdateFileRecord(Vcb, Fcb->MFTIndex, FileRecord);
888 if (NT_SUCCESS(Status))
889 Fcb->RFCB.AllocationSize.QuadPart = NeededSize;
890 }
891 }
892
893 ReleaseAttributeContext(DataContext);
894
895Quit:
897 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, FileRecord);
898
899 return Status;
900}

Referenced by NtfsCleanupFile().

◆ NtfsUpdateDuplicatedInformation()

NTSTATUS NtfsUpdateDuplicatedInformation ( PDEVICE_EXTENSION  Vcb,
PFILE_RECORD_HEADER  FileRecord,
ULONGLONG  MFTIndex,
ULONG  Flags,
BOOLEAN  CaseSensitive 
)

Definition at line 1995 of file mft.c.

2000{
2002 PSTANDARD_INFORMATION StdInfo;
2005 ULONGLONG ParentMFTIndex;
2006 ULONG DirFlag;
2008
2009 if (Flags == 0)
2010 return STATUS_SUCCESS;
2011
2012 StdInfo = GetStandardInformationFromRecord(Vcb, FileRecord);
2013 FileName = GetBestFileNameFromRecord(Vcb, FileRecord);
2014 if (StdInfo == NULL || FileName == NULL)
2015 {
2016 DPRINT1("Record %I64u is missing $STANDARD_INFORMATION or $FILE_NAME\n", MFTIndex);
2018 }
2019
2020 DirFlag = (FileRecord->Flags & FRH_DIRECTORY) ? NTFS_FILE_TYPE_DIRECTORY : 0;
2021
2022 RtlZeroMemory(&Update, sizeof(Update));
2023 Update.Flags = Flags;
2024
2026 {
2027 Update.CreationTime = StdInfo->CreationTime;
2028 Update.LastWriteTime = StdInfo->LastWriteTime;
2029 Update.ChangeTime = StdInfo->ChangeTime;
2030 Update.LastAccessTime = StdInfo->LastAccessTime;
2031
2032 FileName->CreationTime = StdInfo->CreationTime;
2033 FileName->LastWriteTime = StdInfo->LastWriteTime;
2034 FileName->ChangeTime = StdInfo->ChangeTime;
2035 FileName->LastAccessTime = StdInfo->LastAccessTime;
2036 }
2037
2039 {
2040 Update.FileAttributes = StdInfo->FileAttribute | DirFlag;
2041 FileName->FileAttributes = Update.FileAttributes;
2042 }
2043
2045 {
2046 /* Sizes come from the unnamed $DATA attribute, the same way the times
2047 * come from $STANDARD_INFORMATION: one source of truth per field. */
2048 Update.DataSize = NtfsGetFileSize(Vcb, FileRecord, L"", 0, &Update.AllocatedSize);
2049
2050 FileName->DataSize = Update.DataSize;
2051 FileName->AllocatedSize = Update.AllocatedSize;
2052 }
2053
2054 /* Persist the $FILE_NAME just modified. Callers have no reason to write the record again,
2055 * and leaving it unwritten would let the copy in the parent index disagree with it. */
2056 Status = UpdateFileRecord(Vcb, MFTIndex, FileRecord);
2057 if (!NT_SUCCESS(Status))
2058 {
2059 DPRINT1("Failed to write file record %I64u (Status %lx)\n", MFTIndex, Status);
2060 return Status;
2061 }
2062
2063 /* Now the parent's index entry, which carries the same values */
2064 ParentMFTIndex = FileName->DirectoryFileReferenceNumber & NTFS_MFT_MASK;
2065
2066 Name.Buffer = FileName->Name;
2067 Name.Length = FileName->NameLength * sizeof(WCHAR);
2068 Name.MaximumLength = Name.Length;
2069
2070 return UpdateFileNameRecord(Vcb, ParentMFTIndex, &Name, FALSE, &Update, CaseSensitive);
2071}
@ Update
Definition: registry.c:565
#define NTFS_FILENAME_UPDATE_ATTRS
Definition: ntfs.h:1334
#define NTFS_FILENAME_UPDATE_TIMES
Definition: ntfs.h:1333
NTSTATUS UpdateFileNameRecord(PDEVICE_EXTENSION Vcb, ULONGLONG ParentMFTIndex, PUNICODE_STRING FileName, BOOLEAN DirSearch, PNTFS_FILENAME_UPDATE Update, BOOLEAN CaseSensitive)
Definition: mft.c:2191

Referenced by NtfsGrowStream(), NtfsResizeAllocation(), NtfsSetBasicInformation(), and NtfsSetEndOfFile().

◆ NtfsWrite()

NTSTATUS NtfsWrite ( PNTFS_IRP_CONTEXT  IrpContext)

Definition at line 965 of file rw.c.

966{
972 ULONG Length = 0;
973 ULONG ReturnedWriteLength = 0;
975 PDEVICE_EXTENSION DeviceExt = NULL;
977 PIRP Irp = NULL;
978 ULONG BytesPerSector;
979
980 DPRINT("NtfsWrite(IrpContext %p)\n", IrpContext);
981 ASSERT(IrpContext);
982
983 // get the I/O request packet
984 Irp = IrpContext->Irp;
985
986 // This request is not allowed on the main device object
987 if (IrpContext->DeviceObject == NtfsGlobalData->DeviceObject)
988 {
989 DPRINT1("\t\t\t\tNtfsWrite is called with the main device object.\n");
990
991 Irp->IoStatus.Information = 0;
993 }
994
995 // get the File control block
996 Fcb = (PNTFS_FCB)IrpContext->FileObject->FsContext;
997 ASSERT(Fcb);
998
999 DPRINT("About to write %wS\n", Fcb->ObjectName);
1000 DPRINT("NTFS Version: %d.%d\n", Fcb->Vcb->NtfsInfo.MajorVersion, Fcb->Vcb->NtfsInfo.MinorVersion);
1001
1002 // setup some more locals
1003 FileObject = IrpContext->FileObject;
1004 DeviceObject = IrpContext->DeviceObject;
1005 DeviceExt = DeviceObject->DeviceExtension;
1006 BytesPerSector = DeviceExt->StorageDevice->SectorSize;
1007 Length = IrpContext->Stack->Parameters.Write.Length;
1008
1009 // get the file offset we'll be writing to
1010 ByteOffset = IrpContext->Stack->Parameters.Write.ByteOffset;
1011 if (ByteOffset.u.LowPart == FILE_WRITE_TO_END_OF_FILE &&
1012 ByteOffset.u.HighPart == -1)
1013 {
1014 ByteOffset.QuadPart = Fcb->RFCB.FileSize.QuadPart;
1015 }
1016
1017 DPRINT("ByteOffset: %I64u\tLength: %lu\tBytes per sector: %lu\n", ByteOffset.QuadPart,
1018 Length, BytesPerSector);
1019
1020 /* Offsets are 64 bits all the way down, only reject what can't be a file position */
1021 if (ByteOffset.QuadPart < 0 || ByteOffset.QuadPart + Length < ByteOffset.QuadPart)
1022 {
1023 DPRINT1("Invalid write offset %I64d, length %lu\n", ByteOffset.QuadPart, Length);
1025 }
1026
1027 // Is this a non-cached write? A non-buffered write?
1028 if (IrpContext->Irp->Flags & (IRP_PAGING_IO | IRP_NOCACHE) || (Fcb->Flags & FCB_IS_VOLUME) ||
1029 IrpContext->FileObject->Flags & FILE_NO_INTERMEDIATE_BUFFERING)
1030 {
1031 // non-cached and non-buffered writes must be sector aligned
1032 if (ByteOffset.u.LowPart % BytesPerSector != 0 || Length % BytesPerSector != 0)
1033 {
1034 DPRINT1("Non-cached writes and non-buffered writes must be sector aligned!\n");
1036 }
1037 }
1038
1039 /* A zero length write is a valid no-op */
1040 if (Length == 0)
1041 {
1042 // FIXME: Update last write time
1043 IrpContext->Irp->IoStatus.Information = 0;
1044 return STATUS_SUCCESS;
1045 }
1046
1047 /* Is this an async request to a file? Serving a write means reading the
1048 * file record, walking its attributes and possibly growing the allocation,
1049 * all of it blocking metadata I/O, so post it to a worker thread which
1050 * runs the same path with IRPCONTEXT_CANWAIT set. Lock the user buffer
1051 * here, while we're still in the requesting thread's address space. */
1052 if (!(IrpContext->Flags & IRPCONTEXT_CANWAIT) && !(Fcb->Flags & FCB_IS_VOLUME))
1053 {
1055 if (!NT_SUCCESS(Status))
1056 {
1057 DPRINT1("Unable to lock user buffer!\n");
1058 return Status;
1059 }
1060
1061 return NtfsMarkIrpContextForQueue(IrpContext);
1062 }
1063
1064 /* Byte range locks only stop other handles, never Mm or Cc */
1067 {
1068 Irp->IoStatus.Information = 0;
1070 }
1071
1072 /* Regular writes go through the cache, the lazy writer brings them to disk */
1073 if (!(Irp->Flags & (IRP_PAGING_IO | IRP_NOCACHE)) &&
1076 {
1077 if (DeviceExt->Flags & VCB_VOLUME_DISMOUNTED)
1078 {
1079 Irp->IoStatus.Information = 0;
1081 }
1082
1083 Status = NtfsCachedWrite(IrpContext,
1084 Fcb,
1086 Length,
1087 &ByteOffset,
1089 &ReturnedWriteLength);
1090 if (NT_SUCCESS(Status))
1091 {
1092 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
1093 FileObject->CurrentByteOffset.QuadPart = ByteOffset.QuadPart + ReturnedWriteLength;
1094
1095 IrpContext->PriorityBoost = IO_DISK_INCREMENT;
1096 }
1097
1098 Irp->IoStatus.Information = NT_SUCCESS(Status) ? ReturnedWriteLength : 0;
1099 return Status;
1100 }
1101
1102 // get the Resource
1103 if (Fcb->Flags & FCB_IS_VOLUME)
1104 {
1105 Resource = &DeviceExt->DirResource;
1106 }
1107 else if (IrpContext->Irp->Flags & IRP_PAGING_IO)
1108 {
1110 }
1111 else
1112 {
1114 }
1115
1116 /* Paging writes never change the sizes, and Cc or Mm may already hold the
1117 * paging resource shared for us. Size changes take it exclusive. */
1118 if (Resource == &Fcb->PagingIoResource)
1119 {
1121 return STATUS_CANT_WAIT;
1122 }
1124 {
1125 return STATUS_CANT_WAIT;
1126 }
1127
1128 // get the buffer of data the user is trying to write
1130 ASSERT(Buffer);
1131
1132 // lock the buffer
1134
1135 // were we unable to lock the buffer?
1136 if (!NT_SUCCESS(Status))
1137 {
1138 DPRINT1("Unable to lock user buffer!\n");
1139
1141 return Status;
1142 }
1143
1144 DPRINT("Existing File Size(Fcb->RFCB.FileSize.QuadPart): %I64u\n", Fcb->RFCB.FileSize.QuadPart);
1145 DPRINT("About to write the data. Length: %lu\n", Length);
1146
1147
1148 /* See NtfsRead() */
1149 if ((DeviceExt->Flags & VCB_VOLUME_DISMOUNTED) &&
1150 !(Fcb->Flags & FCB_IS_VOLUME))
1151 {
1153 Irp->IoStatus.Information = 0;
1155 }
1156
1157 // write the file
1158 if (Fcb->Flags & FCB_IS_VOLUME)
1159 {
1160 /* Raw access to the partition, including after a dismount. */
1161 Status = NtfsReadWriteVolume(DeviceExt,
1163 Buffer,
1164 Length,
1165 ByteOffset.QuadPart,
1166 Irp,
1167 &ReturnedWriteLength);
1168 }
1169 else if (NtfsFCBIsDirectory(Fcb))
1170 {
1171 /* A directory has no data stream to write */
1173 Irp->IoStatus.Information = 0;
1175 }
1176 else
1177 {
1178 /* What goes straight to disk must not be overwritten by stale cached data later */
1181 {
1183
1186 }
1187
1188 Status = NtfsWriteFile(DeviceExt,
1189 FileObject,
1190 Buffer,
1191 Length,
1192 ByteOffset.QuadPart,
1193 Irp->Flags,
1195 Irp,
1196 &ReturnedWriteLength);
1197 }
1198
1199 IrpContext->Irp->IoStatus.Status = Status;
1200
1201 // was the write successful?
1202 if (NT_SUCCESS(Status))
1203 {
1204 // TODO: Update timestamps
1205
1206 if (FileObject->Flags & FO_SYNCHRONOUS_IO)
1207 {
1208 // advance the file pointer
1209 FileObject->CurrentByteOffset.QuadPart = ByteOffset.QuadPart + ReturnedWriteLength;
1210 }
1211
1212 IrpContext->PriorityBoost = IO_DISK_INCREMENT;
1213 }
1214 else
1215 {
1216 DPRINT1("Write not Succesful!\tReturned length: %lu\n", ReturnedWriteLength);
1217 }
1218
1219 Irp->IoStatus.Information = ReturnedWriteLength;
1220
1221 // Note: We leave the user buffer that we locked alone, it's up to the I/O manager to unlock and free it
1222
1224
1225 return Status;
1226}
_Acquires_exclusive_lock_ Resource _Acquires_shared_lock_ Resource _Inout_ PERESOURCE Resource
Definition: cdprocs.h:843
NTSTATUS NtfsLockUserBuffer(IN PIRP Irp, IN ULONG Length, IN LOCK_OPERATION Operation)
Definition: misc.c:158
NTSTATUS NtfsWriteFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, const PUCHAR Buffer, ULONG Length, ULONGLONG WriteOffset, ULONG IrpFlags, BOOLEAN CaseSensitive, PIRP Irp, PULONG LengthWritten)
Definition: rw.c:611
static NTSTATUS NTAPI NtfsCachedWrite(_In_ PNTFS_IRP_CONTEXT IrpContext, _In_ PNTFS_FCB Fcb, _In_reads_bytes_(Length) PVOID Buffer, _In_ ULONG Length, _In_ PLARGE_INTEGER WriteOffset, _In_ BOOLEAN CaseSensitive, _Out_ PULONG LengthWritten)
Definition: rw.c:862
ERESOURCE * PERESOURCE
Definition: env_spec_w32.h:595
#define FILE_WRITE_TO_END_OF_FILE
Definition: ext2fs.h:278
IN PDCB IN PCCB IN VBO IN OUT PULONG OUT PDIRENT OUT PBCB OUT PVBO ByteOffset
Definition: fatprocs.h:732
BOOLEAN NTAPI FsRtlCheckLockForWriteAccess(IN PFILE_LOCK FileLock, IN PIRP Irp)
Definition: filelock.c:712
#define FILE_NO_INTERMEDIATE_BUFFERING
Definition: from_kernel.h:28
BOOLEAN NTAPI CcPurgeCacheSection(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN UninitializeCacheMaps)
Definition: fssup.c:386
#define STATUS_CANT_WAIT
Definition: ntstatus.h:546
struct _IO_STACK_LOCATION::@5020::@5025 Write
union _IO_STACK_LOCATION::@1814 Parameters
#define IO_DISK_INCREMENT
Definition: iotypes.h:600
#define FO_NO_INTERMEDIATE_BUFFERING
Definition: iotypes.h:1778
@ IoReadAccess
Definition: ketypes.h:931

Referenced by NtfsDispatch().

◆ NtfsWriteDisk()

NTSTATUS NtfsWriteDisk ( IN PDEVICE_OBJECT  DeviceObject,
IN LONGLONG  StartingOffset,
IN ULONG  Length,
IN ULONG  SectorSize,
IN const PUCHAR  Buffer 
)

Definition at line 907 of file blockdev.c.

912{
913 NTFS_IO_RUN_LIST RunList;
915 ULONG Transferred;
916
917 DPRINT("NtfsWriteDisk(%p, %I64x, %lu, %lu, %p)\n",
919
920 if (Length == 0)
921 return STATUS_SUCCESS;
922
923 NtfsInitIoRunList(&RunList);
924
926 if (!NT_SUCCESS(Status))
927 return Status;
928
932 Buffer,
933 &RunList,
934 FALSE,
935 &Transferred);
936
937 NtfsFreeIoRunList(&RunList);
938
939 if (NT_SUCCESS(Status) && Transferred != Length)
940 {
941 DPRINT1("Short write: asked for %lu bytes, wrote %lu\n", Length, Transferred);
943 }
944
945 DPRINT("NtfsWriteDisk() done (Status %x)\n", Status);
946
947 return Status;
948}

◆ NtfsWriteVolumeBitmap()

NTSTATUS NtfsWriteVolumeBitmap ( _In_ PDEVICE_EXTENSION  DeviceExt,
_In_ ULONG  FirstCluster,
_In_ ULONG  ClusterCount 
)

Definition at line 167 of file volinfo.c.

171{
172 ULONG SectorSize = DeviceExt->NtfsInfo.BytesPerSector;
173 ULONG Start;
174 ULONG End;
175 ULONG LengthWritten;
176
177 ASSERT(ClusterCount != 0);
178
179 Start = ROUND_DOWN(FirstCluster / 8, SectorSize);
180 End = ROUND_UP((FirstCluster + ClusterCount - 1) / 8 + 1, SectorSize);
181 End = min(End, ROUND_UP(DeviceExt->BitmapSize, SectorSize));
182
183 return WriteAttribute(DeviceExt,
184 DeviceExt->BitmapContext,
185 Start,
186 (PUCHAR)DeviceExt->BitmapBuffer + Start,
187 End - Start,
188 &LengthWritten,
189 NULL);
190}
static _Out_opt_ PULONGLONG Start
#define ROUND_DOWN(n, align)
Definition: eventvwr.h:33

Referenced by FreeClusters(), and NtfsAllocateClusters().

◆ PrepareAttributeContext()

PNTFS_ATTR_CONTEXT PrepareAttributeContext ( PNTFS_ATTR_RECORD  AttrRecord)

Definition at line 41 of file mft.c.

42{
44
45 Context = ExAllocateFromNPagedLookasideList(&NtfsGlobalData->AttrCtxtLookasideList);
46 if(!Context)
47 {
48 DPRINT1("Error: Unable to allocate memory for context!\n");
49 return NULL;
50 }
51
52 // Allocate memory for a copy of the attribute
54 if(!Context->pRecord)
55 {
56 DPRINT1("Error: Unable to allocate memory for attribute record!\n");
57 ExFreeToNPagedLookasideList(&NtfsGlobalData->AttrCtxtLookasideList, Context);
58 return NULL;
59 }
60
61 // Copy the attribute
62 RtlCopyMemory(Context->pRecord, AttrRecord, AttrRecord->Length);
63
64 if (AttrRecord->IsNonResident)
65 {
66 LONGLONG DataRunOffset;
67 ULONGLONG DataRunLength;
68 ULONGLONG NextVBN = 0;
69 PUCHAR DataRun = (PUCHAR)((ULONG_PTR)Context->pRecord + Context->pRecord->NonResident.MappingPairsOffset);
70
71 Context->CacheRun = DataRun;
72 Context->CacheRunOffset = 0;
73 Context->CacheRun = DecodeRun(Context->CacheRun, &DataRunOffset, &DataRunLength);
74 Context->CacheRunLength = DataRunLength;
75 if (DataRunOffset != -1)
76 {
77 /* Normal run. */
78 Context->CacheRunStartLCN =
79 Context->CacheRunLastLCN = DataRunOffset;
80 }
81 else
82 {
83 /* Sparse run. */
84 Context->CacheRunStartLCN = -1;
85 Context->CacheRunLastLCN = 0;
86 }
87 Context->CacheRunCurrentOffset = 0;
88
89 // Convert the data runs to a map control block
90 if (!NT_SUCCESS(ConvertDataRunsToLargeMCB(DataRun, &Context->DataRunsMCB, &NextVBN)))
91 {
92 DPRINT1("Unable to convert data runs to MCB!\n");
94 ExFreeToNPagedLookasideList(&NtfsGlobalData->AttrCtxtLookasideList, Context);
95 return NULL;
96 }
97 }
98
99 return Context;
100}
NTSTATUS ConvertDataRunsToLargeMCB(PUCHAR DataRun, PLARGE_MCB DataRunsMCB, PULONGLONG pNextVBN)
Definition: attrib.c:842
NPAGED_LOOKASIDE_LIST AttrCtxtLookasideList
Definition: ntfs.h:181

Referenced by FindAttribute(), and InternalReadNonResidentAttributes().

◆ ReadAttribute()

◆ ReadAttributeToIrp()

ULONG ReadAttributeToIrp ( PDEVICE_EXTENSION  Vcb,
PNTFS_ATTR_CONTEXT  Context,
ULONGLONG  Offset,
PCHAR  Buffer,
ULONG  Length,
PIRP  Irp 
)

Definition at line 1556 of file mft.c.

1562{
1563 ULONG AlreadyRead = 0;
1564 ULONG Transferred = 0;
1566 NTFS_IO_RUN_LIST RunList;
1567
1568 if (!Context->pRecord->IsNonResident)
1569 {
1570 // We need to truncate Offset to a ULONG for pointer arithmetic
1571 // The check below should ensure that Offset is well within the range of 32 bits
1572 ULONG LittleOffset = (ULONG)Offset;
1573
1574 // Ensure that offset isn't beyond the end of the attribute
1575 if (Offset > Context->pRecord->Resident.ValueLength)
1576 return 0;
1577 if (Offset + Length > Context->pRecord->Resident.ValueLength)
1578 Length = (ULONG)(Context->pRecord->Resident.ValueLength - Offset);
1579
1580 RtlCopyMemory(Buffer, (PVOID)((ULONG_PTR)Context->pRecord + Context->pRecord->Resident.ValueOffset + LittleOffset), Length);
1581 return Length;
1582 }
1583
1584 /*
1585 * Non-resident attribute: map the requested range onto the volume, then
1586 * issue every run it spans in a single parallel batch.
1587 */
1588
1589 NtfsInitIoRunList(&RunList);
1590
1591 Status = NtfsMapAttributeRuns(Vcb, Context, Offset, Length, &RunList, &AlreadyRead);
1592
1593 if (NT_SUCCESS(Status) && AlreadyRead != 0)
1594 {
1595 Status = NtfsPerformIrpIoRuns(Vcb->StorageDevice,
1597 Vcb->NtfsInfo.BytesPerSector,
1598 Irp,
1599 (PUCHAR)Buffer,
1600 &RunList,
1601 FALSE,
1602 &Transferred);
1603 }
1604
1605 NtfsFreeIoRunList(&RunList);
1606
1607 if (!NT_SUCCESS(Status))
1608 {
1609 /* Our callers read the return value as a byte count and treat zero as
1610 * failure, so we cannot report a partial transfer here. */
1611 DPRINT1("Read failure (Status %lx)\n", Status);
1612 return 0;
1613 }
1614
1615 if (Transferred < AlreadyRead)
1616 {
1617 DPRINT1("Short read: expected %lu bytes, got %lu\n", AlreadyRead, Transferred);
1618 AlreadyRead = Transferred;
1619 }
1620
1621 return AlreadyRead;
1622}
static NTSTATUS NtfsMapAttributeRuns(PDEVICE_EXTENSION Vcb, PNTFS_ATTR_CONTEXT Context, ULONGLONG Offset, ULONG Length, PNTFS_IO_RUN_LIST RunList, PULONG MappedLength)
Definition: mft.c:1362
NTSTATUS NtfsPerformIrpIoRuns(IN PDEVICE_OBJECT DeviceObject, IN UCHAR MajorFunction, IN ULONG SectorSize, IN PIRP Irp, IN OUT PUCHAR Buffer, IN PNTFS_IO_RUN_LIST RunList, IN BOOLEAN Override, OUT PULONG BytesTransferred)
Definition: blockdev.c:743

Referenced by NtfsReadFile(), and ReadAttribute().

◆ ReadFileRecord()

NTSTATUS ReadFileRecord ( PDEVICE_EXTENSION  Vcb,
ULONGLONG  index,
PFILE_RECORD_HEADER  file 
)

Definition at line 1936 of file mft.c.

1939{
1941
1942 DPRINT("ReadFileRecord(%p, %I64x, %p)\n", Vcb, index, file);
1943
1944 BytesRead = ReadAttribute(Vcb, Vcb->MFTContext, index * Vcb->NtfsInfo.BytesPerFileRecord, (PCHAR)file, Vcb->NtfsInfo.BytesPerFileRecord);
1945 if (BytesRead != Vcb->NtfsInfo.BytesPerFileRecord)
1946 {
1947 DPRINT1("ReadFileRecord failed: %I64u read, %lu expected\n", BytesRead, Vcb->NtfsInfo.BytesPerFileRecord);
1948 return STATUS_PARTIAL_COPY;
1949 }
1950
1951 /* Apply update sequence array fixups. */
1952 DPRINT("Sequence number: %u\n", file->SequenceNumber);
1953 return FixupUpdateSequenceArray(Vcb, &file->Ntfs);
1954}
GLuint index
Definition: glext.h:6031
NTSTATUS FixupUpdateSequenceArray(PDEVICE_EXTENSION Vcb, PNTFS_RECORD_HEADER Record)
Definition: mft.c:2425
#define STATUS_PARTIAL_COPY
Definition: ntstatus.h:273
Definition: fci.c:123
_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 AddFilenameToDirectoryWorker(), FindAttribute(), FreeMftEntry(), GetNtfsFileRecord(), NtfsBuildRenamedFileName(), NtfsClearRenameTarget(), NtfsCreateFile(), NtfsDeleteFileRecord(), NtfsFindFileAt(), NtfsFindMftRecord(), NtfsGetDotEntry(), NtfsGetParentMftIndex(), NtfsGetStreamInformation(), NtfsGetVolumeData(), NtfsGrowFileForWrite(), NtfsIsDirectoryEmpty(), NtfsLoadVolumeBitmap(), NtfsLookupFileAt(), NtfsMakeRootFCB(), NtfsMoonWalkID(), NtfsOpenFileById(), NtfsReadFCBAttribute(), NtfsReadFile(), NtfsReadUpCaseTable(), NtfsResizeAllocation(), NtfsSetBasicInformation(), NtfsSetEndOfFile(), NtfsSetRenameInformation(), NtfsTrimAllocation(), NtfsWriteFile(), RemoveFilenameFromDirectoryWorker(), UpdateFileNameRecordWorker(), UpdateMftMirror(), and WriteAttributeFromIrp().

◆ ReadLCN()

NTSTATUS ReadLCN ( PDEVICE_EXTENSION  Vcb,
ULONGLONG  lcn,
ULONG  count,
PVOID  buffer 
)

Definition at line 3603 of file mft.c.

3607{
3608 LARGE_INTEGER DiskSector;
3609
3610 DiskSector.QuadPart = lcn;
3611
3612 return NtfsReadSectors(Vcb->StorageDevice,
3613 DiskSector.u.LowPart * Vcb->NtfsInfo.SectorsPerCluster,
3614 count * Vcb->NtfsInfo.SectorsPerCluster,
3615 Vcb->NtfsInfo.BytesPerSector,
3616 buffer,
3617 FALSE);
3618}
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLuint buffer
Definition: glext.h:5915
NTSTATUS NtfsReadSectors(IN PDEVICE_OBJECT DeviceObject, IN ULONG DiskSector, IN ULONG SectorCount, IN ULONG SectorSize, IN OUT PUCHAR Buffer, IN BOOLEAN Override)
Definition: blockdev.c:1011
struct _LARGE_INTEGER::@2753 u

◆ ReadVCN()

VOID ReadVCN ( PDEVICE_EXTENSION  Vcb,
PFILE_RECORD_HEADER  file,
ATTRIBUTE_TYPE  type,
ULONGLONG  vcn,
ULONG  count,
PVOID  buffer 
)

◆ ReleaseAttributeContext()

◆ SetAttributeDataLength()

NTSTATUS SetAttributeDataLength ( PFILE_OBJECT  FileObject,
PNTFS_FCB  Fcb,
PNTFS_ATTR_CONTEXT  AttrContext,
ULONG  AttrOffset,
PFILE_RECORD_HEADER  FileRecord,
PLARGE_INTEGER  DataSize 
)

@parameter FileRecord Pointer to a file record. Must be a full record at least Fcb->Vcb->NtfsInfo.BytesPerFileRecord bytes large, not just the header.

Definition at line 615 of file mft.c.

621{
623
624 DPRINT("SetAttributeDataLength(%p, %p, %p, %lu, %p, %I64u)\n",
626 Fcb,
627 AttrContext,
628 AttrOffset,
629 FileRecord,
630 DataSize->QuadPart);
631
632 // are we truncating the file?
633 if (DataSize->QuadPart < AttributeDataLength(AttrContext->pRecord))
634 {
635 if (!MmCanFileBeTruncated(FileObject->SectionObjectPointer, DataSize))
636 {
637 DPRINT1("Can't truncate a memory-mapped file!\n");
639 }
640 }
641
642 if (AttrContext->pRecord->IsNonResident)
643 {
645 AttrContext,
646 AttrOffset,
647 FileRecord,
648 DataSize);
649 }
650 else
651 {
652 // resident attribute
654 AttrContext,
655 AttrOffset,
656 FileRecord,
657 DataSize);
658 }
659
660 if (!NT_SUCCESS(Status))
661 {
662 DPRINT1("ERROR: Failed to set size of attribute!\n");
663 return Status;
664 }
665
666 //NtfsDumpFileAttributes(Fcb->Vcb, FileRecord);
667
668 // write the updated file record back to disk
669 Status = UpdateFileRecord(Fcb->Vcb, Fcb->MFTIndex, FileRecord);
670
671 if (NT_SUCCESS(Status))
672 {
673 if (AttrContext->pRecord->IsNonResident)
674 Fcb->RFCB.AllocationSize.QuadPart = AttrContext->pRecord->NonResident.AllocatedSize;
675 else
680 }
681
682 return STATUS_SUCCESS;
683}
NTSTATUS SetNonResidentAttributeDataLength(PDEVICE_EXTENSION Vcb, PNTFS_ATTR_CONTEXT AttrContext, ULONG AttrOffset, PFILE_RECORD_HEADER FileRecord, PLARGE_INTEGER DataSize)
Definition: mft.c:1065
NTSTATUS SetResidentAttributeDataLength(PDEVICE_EXTENSION Vcb, PNTFS_ATTR_CONTEXT AttrContext, ULONG AttrOffset, PFILE_RECORD_HEADER FileRecord, PLARGE_INTEGER DataSize)
Definition: mft.c:1148

Referenced by NtfsCreateFile(), NtfsGrowStream(), and NtfsSetEndOfFile().

◆ SetFileRecordEnd()

VOID SetFileRecordEnd ( PFILE_RECORD_HEADER  FileRecord,
PNTFS_ATTR_RECORD  AttrEnd,
ULONG  EndMarker 
)

Definition at line 706 of file mft.c.

709{
710 // Ensure AttrEnd is aligned on an 8-byte boundary, relative to FileRecord
711 ASSERT(((ULONG_PTR)AttrEnd - (ULONG_PTR)FileRecord) % ATTR_RECORD_ALIGNMENT == 0);
712
713 // mark the end of attributes
714 AttrEnd->Type = AttributeEnd;
715
716 // Restore the "file-record-end marker." The value is never checked but this behavior is consistent with Win2k3.
717 AttrEnd->Length = EndMarker;
718
719 // recalculate bytes in use
720 FileRecord->BytesInUse = (ULONG_PTR)AttrEnd - (ULONG_PTR)FileRecord + sizeof(ULONG) * 2;
721}

Referenced by AddBitmap(), AddData(), AddFileName(), AddIndexAllocation(), AddIndexRoot(), AddRun(), AddStandardInformation(), FreeClusters(), InternalSetResidentAttributeLength(), NtfsSetFileNameAttribute(), and SetResidentAttributeDataLength().

◆ SetNonResidentAttributeDataLength()

NTSTATUS SetNonResidentAttributeDataLength ( PDEVICE_EXTENSION  Vcb,
PNTFS_ATTR_CONTEXT  AttrContext,
ULONG  AttrOffset,
PFILE_RECORD_HEADER  FileRecord,
PLARGE_INTEGER  DataSize 
)

Definition at line 1065 of file mft.c.

1070{
1072 ULONG BytesPerCluster = Vcb->NtfsInfo.BytesPerCluster;
1073 ULONGLONG AllocationSize = ROUND_UP(DataSize->QuadPart, BytesPerCluster);
1074 PNTFS_ATTR_RECORD DestinationAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + AttrOffset);
1075 ULONG ExistingClusters = AttrContext->pRecord->NonResident.AllocatedSize / BytesPerCluster;
1076
1077 ASSERT(AttrContext->pRecord->IsNonResident);
1078
1079 // do we need to increase the allocation size?
1080 if (AttrContext->pRecord->NonResident.AllocatedSize < AllocationSize)
1081 {
1082 Status = NtfsExtendAllocation(Vcb, AttrContext, AttrOffset, FileRecord, AllocationSize);
1083 if (!NT_SUCCESS(Status))
1084 return Status;
1085 }
1086 else if (AttrContext->pRecord->NonResident.AllocatedSize > AllocationSize &&
1087 (ULONGLONG)DataSize->QuadPart < AttrContext->pRecord->NonResident.DataSize)
1088 {
1089 // shrink allocation size
1090 ULONG ClustersToFree = ExistingClusters - (AllocationSize / BytesPerCluster);
1091 Status = FreeClusters(Vcb, AttrContext, AttrOffset, FileRecord, ClustersToFree);
1092 AttrContext->pRecord->NonResident.AllocatedSize = AllocationSize;
1093 }
1094
1095 // TODO: is the file compressed, encrypted, or sparse?
1096
1097 AttrContext->pRecord->NonResident.DataSize = DataSize->QuadPart;
1098 AttrContext->pRecord->NonResident.InitializedSize = DataSize->QuadPart;
1099
1100 DestinationAttribute->NonResident.AllocatedSize = AttrContext->pRecord->NonResident.AllocatedSize;
1101 DestinationAttribute->NonResident.DataSize = DataSize->QuadPart;
1102 DestinationAttribute->NonResident.InitializedSize = DataSize->QuadPart;
1103
1104 /* AddRun() and FreeClusters() keep HighestVCN on the last VCN the runs
1105 * describe, holes included, so it's carried over rather than recomputed */
1106 DestinationAttribute->NonResident.HighestVCN = AttrContext->pRecord->NonResident.HighestVCN;
1107
1108 DPRINT("Allocated Size: %I64u\n", DestinationAttribute->NonResident.AllocatedSize);
1109
1110 return Status;
1111}

Referenced by AllocateIndexNode(), IncreaseMftSize(), SetAttributeDataLength(), and SetResidentAttributeDataLength().

◆ SetResidentAttributeDataLength()

NTSTATUS SetResidentAttributeDataLength ( PDEVICE_EXTENSION  Vcb,
PNTFS_ATTR_CONTEXT  AttrContext,
ULONG  AttrOffset,
PFILE_RECORD_HEADER  FileRecord,
PLARGE_INTEGER  DataSize 
)

Definition at line 1148 of file mft.c.

1153{
1155
1156 // find the next attribute
1157 ULONG NextAttributeOffset = AttrOffset + AttrContext->pRecord->Length;
1158 PNTFS_ATTR_RECORD NextAttribute = (PNTFS_ATTR_RECORD)((PCHAR)FileRecord + NextAttributeOffset);
1159
1160 ASSERT(!AttrContext->pRecord->IsNonResident);
1161
1162 //NtfsDumpFileAttributes(Vcb, FileRecord);
1163
1164 // Do we need to increase the data length?
1165 if (DataSize->QuadPart > AttrContext->pRecord->Resident.ValueLength)
1166 {
1167 // There's usually padding at the end of a record. Do we need to extend past it?
1168 ULONG MaxValueLength = AttrContext->pRecord->Length - AttrContext->pRecord->Resident.ValueOffset;
1169 if (MaxValueLength < (ULONGLONG)DataSize->QuadPart)
1170 {
1171 // If this is the last attribute, we could move the end marker to the very end of the file record
1172 MaxValueLength += Vcb->NtfsInfo.BytesPerFileRecord - NextAttributeOffset - (sizeof(ULONG) * 2);
1173
1174 if (MaxValueLength < (ULONGLONG)DataSize->QuadPart || NextAttribute->Type != AttributeEnd)
1175 {
1176 // convert attribute to non-resident
1177 PNTFS_ATTR_RECORD Destination = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + AttrOffset);
1178 PNTFS_ATTR_RECORD NewRecord;
1179 LARGE_INTEGER AttribDataSize;
1180 PVOID AttribData;
1181 ULONG NewRecordLength;
1182 ULONG EndAttributeOffset;
1183 ULONG LengthWritten;
1184
1185 DPRINT("Converting attribute to non-resident.\n");
1186
1187 AttribDataSize.QuadPart = AttrContext->pRecord->Resident.ValueLength;
1188
1189 // Is there existing data we need to back-up?
1190 if (AttribDataSize.QuadPart > 0)
1191 {
1192 AttribData = ExAllocatePoolWithTag(NonPagedPool, AttribDataSize.QuadPart, TAG_NTFS);
1193 if (AttribData == NULL)
1194 {
1195 DPRINT1("ERROR: Couldn't allocate memory for attribute data. Can't migrate to non-resident!\n");
1197 }
1198
1199 // read data to temp buffer
1200 Status = ReadAttribute(Vcb, AttrContext, 0, AttribData, AttribDataSize.QuadPart);
1201 if (!NT_SUCCESS(Status))
1202 {
1203 DPRINT1("ERROR: Unable to read attribute before migrating!\n");
1204 ExFreePoolWithTag(AttribData, TAG_NTFS);
1205 return Status;
1206 }
1207 }
1208
1209 // Start by turning this attribute into a 0-length, non-resident attribute, then enlarge it.
1210
1211 // The size of a 0-length, non-resident attribute will be 0x41 + the size of the attribute name, aligned to an 8-byte boundary
1212 NewRecordLength = ALIGN_UP_BY(0x41 + (AttrContext->pRecord->NameLength * sizeof(WCHAR)), ATTR_RECORD_ALIGNMENT);
1213
1214 // Create a new attribute record that will store the 0-length, non-resident attribute
1215 NewRecord = ExAllocatePoolWithTag(NonPagedPool, NewRecordLength, TAG_NTFS);
1216
1217 // Zero out the NonResident structure
1218 RtlZeroMemory(NewRecord, NewRecordLength);
1219
1220 // Copy the data that's common to both non-resident and resident attributes
1221 RtlCopyMemory(NewRecord, AttrContext->pRecord, FIELD_OFFSET(NTFS_ATTR_RECORD, Resident.ValueLength));
1222
1223 // The name follows the non-resident header, not the resident one
1224 NewRecord->NameOffset = FIELD_OFFSET(NTFS_ATTR_RECORD, NonResident.CompressedSize);
1225
1226 // if there's a name
1227 if (AttrContext->pRecord->NameLength != 0)
1228 {
1229 // copy the name
1230 // An attribute name will be located at offset 0x18 for a resident attribute, 0x40 for non-resident
1231 RtlCopyMemory((PCHAR)((ULONG_PTR)NewRecord + 0x40),
1232 (PCHAR)((ULONG_PTR)AttrContext->pRecord + 0x18),
1233 AttrContext->pRecord->NameLength * sizeof(WCHAR));
1234 }
1235
1236 // update the mapping pairs offset, which will be 0x40 (size of a non-resident header) + length in bytes of the name
1237 NewRecord->NonResident.MappingPairsOffset = 0x40 + (AttrContext->pRecord->NameLength * sizeof(WCHAR));
1238
1239 // update the end of the file record
1240 // calculate position of end markers (1 byte for empty data run)
1241 EndAttributeOffset = AttrOffset + NewRecord->NonResident.MappingPairsOffset + 1;
1242 EndAttributeOffset = ALIGN_UP_BY(EndAttributeOffset, ATTR_RECORD_ALIGNMENT);
1243
1244 // Update the length
1245 NewRecord->Length = EndAttributeOffset - AttrOffset;
1246
1247 ASSERT(NewRecord->Length == NewRecordLength);
1248
1249 // Copy the new attribute record into the file record
1250 RtlCopyMemory(Destination, NewRecord, NewRecord->Length);
1251
1252 // Update the file record end
1253 SetFileRecordEnd(FileRecord,
1254 (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + EndAttributeOffset),
1256
1257 // Initialize the MCB, potentially catch an exception
1258 _SEH2_TRY
1259 {
1260 FsRtlInitializeLargeMcb(&AttrContext->DataRunsMCB, NonPagedPool);
1261 }
1263 {
1264 DPRINT1("Unable to create LargeMcb!\n");
1265 if (AttribDataSize.QuadPart > 0)
1266 ExFreePoolWithTag(AttribData, TAG_NTFS);
1267 ExFreePoolWithTag(NewRecord, TAG_NTFS);
1269 } _SEH2_END;
1270
1271 // Mark the attribute as non-resident (we wait until after we know the LargeMcb was initialized)
1272 NewRecord->IsNonResident = Destination->IsNonResident = 1;
1273
1274 // Update file record on disk
1275 Status = UpdateFileRecord(Vcb, AttrContext->FileMFTIndex, FileRecord);
1276 if (!NT_SUCCESS(Status))
1277 {
1278 DPRINT1("ERROR: Couldn't update file record to continue migration!\n");
1279 if (AttribDataSize.QuadPart > 0)
1280 ExFreePoolWithTag(AttribData, TAG_NTFS);
1281 ExFreePoolWithTag(NewRecord, TAG_NTFS);
1282 return Status;
1283 }
1284
1285 // Now we need to free the old copy of the attribute record in the context and replace it with the new one
1286 ExFreePoolWithTag(AttrContext->pRecord, TAG_NTFS);
1287 AttrContext->pRecord = NewRecord;
1288
1289 // Now we can treat the attribute as non-resident and enlarge it normally
1290 Status = SetNonResidentAttributeDataLength(Vcb, AttrContext, AttrOffset, FileRecord, DataSize);
1291 if (!NT_SUCCESS(Status))
1292 {
1293 DPRINT1("ERROR: Unable to migrate resident attribute!\n");
1294 if (AttribDataSize.QuadPart > 0)
1295 ExFreePoolWithTag(AttribData, TAG_NTFS);
1296 return Status;
1297 }
1298
1299 // restore the back-up attribute, if we made one
1300 if (AttribDataSize.QuadPart > 0)
1301 {
1302 Status = WriteAttribute(Vcb, AttrContext, 0, AttribData, AttribDataSize.QuadPart, &LengthWritten, FileRecord);
1303 if (!NT_SUCCESS(Status))
1304 {
1305 DPRINT1("ERROR: Unable to write attribute data to non-resident clusters during migration!\n");
1306 // TODO: Reverse migration so no data is lost
1307 ExFreePoolWithTag(AttribData, TAG_NTFS);
1308 return Status;
1309 }
1310
1311 ExFreePoolWithTag(AttribData, TAG_NTFS);
1312 }
1313 }
1314 }
1315 }
1316
1317 // set the new length of the resident attribute (if we didn't migrate it)
1318 if (!AttrContext->pRecord->IsNonResident)
1319 return InternalSetResidentAttributeLength(Vcb, AttrContext, FileRecord, AttrOffset, DataSize->LowPart);
1320
1321 return STATUS_SUCCESS;
1322}
NTSTATUS InternalSetResidentAttributeLength(PDEVICE_EXTENSION DeviceExt, PNTFS_ATTR_CONTEXT AttrContext, PFILE_RECORD_HEADER FileRecord, ULONG AttrOffset, ULONG DataSize)
Definition: mft.c:542

Referenced by AllocateIndexNode(), IncreaseMftSize(), and SetAttributeDataLength().

◆ SplitBTreeNode()

NTSTATUS SplitBTreeNode ( PB_TREE  Tree,
PB_TREE_FILENAME_NODE  Node,
PB_TREE_KEY *  MedianKey,
PB_TREE_FILENAME_NODE *  NewRightHandSibling,
BOOLEAN  CaseSensitive 
)

Definition at line 2138 of file btree.c.

2143{
2144 ULONG MedianKeyIndex;
2145 PB_TREE_KEY LastKeyBeforeMedian, FirstKeyAfterMedian;
2146 ULONG KeyCount;
2147 ULONG HalfSize;
2148 ULONG SizeSum;
2149 ULONG i;
2150
2151 DPRINT("SplitBTreeNode(%p, %p, %p, %p, %s) called\n",
2152 Tree,
2153 Node,
2154 MedianKey,
2155 NewRightHandSibling,
2156 CaseSensitive ? "TRUE" : "FALSE");
2157
2158#ifndef NDEBUG
2159 DumpBTreeNode(Tree, Node, 0, 0);
2160#endif
2161
2162 // Create the right hand sibling
2163 *NewRightHandSibling = ExAllocatePoolWithTag(NonPagedPool, sizeof(B_TREE_FILENAME_NODE), TAG_NTFS);
2164 if (*NewRightHandSibling == NULL)
2165 {
2166 DPRINT1("Error: Failed to allocate memory for right hand sibling!\n");
2168 }
2169 RtlZeroMemory(*NewRightHandSibling, sizeof(B_TREE_FILENAME_NODE));
2170 (*NewRightHandSibling)->DiskNeedsUpdating = TRUE;
2171
2172
2173 // Find the last key before the median
2174
2175 // This is roughly how NTFS-3G calculates median, and it's not congruent with what Windows does:
2176 /*
2177 // find the median key index
2178 MedianKeyIndex = (Node->KeyCount + 1) / 2;
2179 MedianKeyIndex--;
2180
2181 LastKeyBeforeMedian = Node->FirstKey;
2182 for (i = 0; i < MedianKeyIndex - 1; i++)
2183 LastKeyBeforeMedian = LastKeyBeforeMedian->NextKey;*/
2184
2185 // The method we'll use is a little bit closer to how Windows determines the median but it's not identical.
2186 // What Windows does is actually more complicated than this, I think because Windows allocates more slack space to Odd-numbered
2187 // Index Records, leaving less room for index entries in these records (I haven't discovered why this is done).
2188 // (Neither Windows nor chkdsk complain if we choose a different median than Windows would have chosen, as our median will be in the ballpark)
2189
2190 // Use size to locate the median key / index
2191 LastKeyBeforeMedian = Node->FirstKey;
2192 MedianKeyIndex = 0;
2193 HalfSize = 2016; // half the allocated size after subtracting the first index entry offset (TODO: MATH)
2194 SizeSum = 0;
2195 for (i = 0; i < Node->KeyCount; i++)
2196 {
2197 SizeSum += LastKeyBeforeMedian->IndexEntry->Length;
2198
2199 if (SizeSum > HalfSize)
2200 break;
2201
2202 MedianKeyIndex++;
2203 LastKeyBeforeMedian = LastKeyBeforeMedian->NextKey;
2204 }
2205
2206 // Now we can get the median key and the key that follows it
2207 *MedianKey = LastKeyBeforeMedian->NextKey;
2208 FirstKeyAfterMedian = (*MedianKey)->NextKey;
2209
2210 DPRINT("%lu keys, %lu median\n", Node->KeyCount, MedianKeyIndex);
2211 DPRINT("\t\tMedian: %.*S\n", (*MedianKey)->IndexEntry->FileName.NameLength, (*MedianKey)->IndexEntry->FileName.Name);
2212
2213 // "Node" will be the left hand sibling after the split, containing all keys prior to the median key
2214
2215 // We need to create a dummy pointer at the end of the LHS. The dummy's child will be the median's child.
2216 LastKeyBeforeMedian->NextKey = CreateDummyKey(BooleanFlagOn((*MedianKey)->IndexEntry->Flags, NTFS_INDEX_ENTRY_NODE));
2217 if (LastKeyBeforeMedian->NextKey == NULL)
2218 {
2219 DPRINT1("Error: Couldn't allocate dummy key!\n");
2220 LastKeyBeforeMedian->NextKey = *MedianKey;
2221 ExFreePoolWithTag(*NewRightHandSibling, TAG_NTFS);
2223 }
2224
2225 // Did the median key have a child node?
2226 if ((*MedianKey)->IndexEntry->Flags & NTFS_INDEX_ENTRY_NODE)
2227 {
2228 // Set the child of the new dummy key
2229 LastKeyBeforeMedian->NextKey->LesserChild = (*MedianKey)->LesserChild;
2230
2231 // Give the dummy key's index entry the same sub-node VCN the median
2232 SetIndexEntryVCN(LastKeyBeforeMedian->NextKey->IndexEntry, GetIndexEntryVCN((*MedianKey)->IndexEntry));
2233 }
2234 else
2235 {
2236 // Median key didn't have a child node, but it will. Create a new index entry large enough to store a VCN.
2238 (*MedianKey)->IndexEntry->Length + sizeof(ULONGLONG),
2239 TAG_NTFS);
2240 if (!NewIndexEntry)
2241 {
2242 DPRINT1("Unable to allocate memory for new index entry!\n");
2243 LastKeyBeforeMedian->NextKey = *MedianKey;
2244 ExFreePoolWithTag(*NewRightHandSibling, TAG_NTFS);
2246 }
2247
2248 // Copy the old index entry to the new one
2249 RtlCopyMemory(NewIndexEntry, (*MedianKey)->IndexEntry, (*MedianKey)->IndexEntry->Length);
2250
2251 // Use the new index entry after freeing the old one
2252 ExFreePoolWithTag((*MedianKey)->IndexEntry, TAG_NTFS);
2253 (*MedianKey)->IndexEntry = NewIndexEntry;
2254
2255 // Update the length for the VCN
2256 (*MedianKey)->IndexEntry->Length += sizeof(ULONGLONG);
2257
2258 // Set the node flag
2259 (*MedianKey)->IndexEntry->Flags |= NTFS_INDEX_ENTRY_NODE;
2260 }
2261
2262 // "Node" will become the child of the median key
2263 (*MedianKey)->LesserChild = Node;
2264 SetIndexEntryVCN((*MedianKey)->IndexEntry, Node->VCN);
2265
2266 // Update Node's KeyCount (remember to add 1 for the new dummy key)
2267 Node->KeyCount = MedianKeyIndex + 2;
2268
2269 KeyCount = CountBTreeKeys(Node->FirstKey);
2270 ASSERT(Node->KeyCount == KeyCount);
2271
2272 // everything to the right of MedianKey becomes the right hand sibling of Node
2273 (*NewRightHandSibling)->FirstKey = FirstKeyAfterMedian;
2274 (*NewRightHandSibling)->KeyCount = CountBTreeKeys(FirstKeyAfterMedian);
2275
2276#ifndef NDEBUG
2277 DPRINT1("Left-hand node after split:\n");
2278 DumpBTreeNode(Tree, Node, 0, 0);
2279
2280 DPRINT1("Right-hand sibling node after split:\n");
2281 DumpBTreeNode(Tree, *NewRightHandSibling, 0, 0);
2282#endif
2283
2284 return STATUS_SUCCESS;
2285}
ULONG CountBTreeKeys(PB_TREE_KEY FirstKey)
Definition: btree.c:489
ULONGLONG GetIndexEntryVCN(PINDEX_ENTRY_ATTRIBUTE IndexEntry)
Definition: btree.c:1648
VOID SetIndexEntryVCN(PINDEX_ENTRY_ATTRIBUTE IndexEntry, ULONGLONG VCN)
Definition: btree.c:1177
union node Node
Definition: types.h:1255

Referenced by NtfsInsertKey().

◆ UpdateFileNameRecord()

NTSTATUS UpdateFileNameRecord ( PDEVICE_EXTENSION  Vcb,
ULONGLONG  ParentMFTIndex,
PUNICODE_STRING  FileName,
BOOLEAN  DirSearch,
PNTFS_FILENAME_UPDATE  Update,
BOOLEAN  CaseSensitive 
)

Definition at line 2191 of file mft.c.

2197{
2199
2201 ExAcquireResourceExclusiveLite(&Vcb->IndexResource, TRUE);
2202 Status = UpdateFileNameRecordWorker(Vcb, ParentMFTIndex, FileName, DirSearch, Update, CaseSensitive);
2203 ExReleaseResourceLite(&Vcb->IndexResource);
2205
2206 return Status;
2207}
static NTSTATUS UpdateFileNameRecordWorker(PDEVICE_EXTENSION Vcb, ULONGLONG ParentMFTIndex, PUNICODE_STRING FileName, BOOLEAN DirSearch, PNTFS_FILENAME_UPDATE Update, BOOLEAN CaseSensitive)
Definition: mft.c:2082

Referenced by NtfsUpdateDuplicatedInformation().

◆ UpdateFileRecord()

NTSTATUS UpdateFileRecord ( PDEVICE_EXTENSION  Vcb,
ULONGLONG  MftIndex,
PFILE_RECORD_HEADER  FileRecord 
)

Definition at line 2391 of file mft.c.

2394{
2397
2398 DPRINT("UpdateFileRecord(%p, 0x%I64x, %p)\n", Vcb, MftIndex, FileRecord);
2399
2400 // Add the fixup array to prepare the data for writing to disk
2401 AddFixupArray(Vcb, &FileRecord->Ntfs);
2402
2403 // write the file record to the master file table
2405 Vcb->MFTContext,
2406 MftIndex * Vcb->NtfsInfo.BytesPerFileRecord,
2407 (const PUCHAR)FileRecord,
2408 Vcb->NtfsInfo.BytesPerFileRecord,
2409 &BytesWritten,
2410 FileRecord);
2411
2412 if (!NT_SUCCESS(Status))
2413 {
2414 DPRINT1("UpdateFileRecord failed: %lu written, %lu expected\n", BytesWritten, Vcb->NtfsInfo.BytesPerFileRecord);
2415 }
2416
2417 // remove the fixup array (so the file record pointer can still be used)
2418 FixupUpdateSequenceArray(Vcb, &FileRecord->Ntfs);
2419
2420 return Status;
2421}
NTSTATUS AddFixupArray(PDEVICE_EXTENSION Vcb, PNTFS_RECORD_HEADER Record)
Definition: mft.c:3575
_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 BytesWritten
Definition: wdfiotarget.h:960

Referenced by AddFilenameToDirectoryWorker(), AddNewMftEntry(), AddRun(), AllocateIndexNode(), FreeClusters(), FreeMftEntry(), IncreaseMftSize(), NtfsCommitRename(), NtfsResizeAllocation(), NtfsTrimAllocation(), NtfsUpdateDuplicatedInformation(), RemoveFilenameFromDirectoryWorker(), SetAttributeDataLength(), SetResidentAttributeDataLength(), and WriteAttributeFromIrp().

◆ UpdateIndexAllocation()

NTSTATUS UpdateIndexAllocation ( PDEVICE_EXTENSION  DeviceExt,
PB_TREE  Tree,
ULONG  IndexBufferSize,
PFILE_RECORD_HEADER  FileRecord 
)

Definition at line 1187 of file btree.c.

1191{
1192 // Find the index allocation and bitmap
1193 PNTFS_ATTR_CONTEXT IndexAllocationContext;
1194 PB_TREE_KEY CurrentKey;
1196 BOOLEAN HasIndexAllocation = FALSE;
1197 ULONG i;
1198 ULONG IndexAllocationOffset;
1199
1200 DPRINT("UpdateIndexAllocation() called.\n");
1201
1202 Status = FindAttribute(DeviceExt, FileRecord, AttributeIndexAllocation, L"$I30", 4, &IndexAllocationContext, &IndexAllocationOffset);
1203 if (NT_SUCCESS(Status))
1204 {
1205 HasIndexAllocation = TRUE;
1206
1207#ifndef NDEBUG
1208 PrintAllVCNs(DeviceExt,
1209 IndexAllocationContext,
1210 IndexBufferSize);
1211#endif
1212 }
1213 // Walk through the root node and update all the sub-nodes
1214 CurrentKey = Tree->RootNode->FirstKey;
1215 for (i = 0; i < Tree->RootNode->KeyCount; i++)
1216 {
1217 if (CurrentKey->LesserChild)
1218 {
1219 if (!HasIndexAllocation)
1220 {
1221 // We need to add an index allocation to the file record
1222 PNTFS_ATTR_RECORD EndMarker = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + FileRecord->BytesInUse - (sizeof(ULONG) * 2));
1223 DPRINT("Adding index allocation...\n");
1224
1225 // Add index allocation to the very end of the file record
1226 Status = AddIndexAllocation(DeviceExt,
1227 FileRecord,
1228 EndMarker,
1229 L"$I30",
1230 4);
1231 if (!NT_SUCCESS(Status))
1232 {
1233 DPRINT1("ERROR: Failed to add index allocation!\n");
1234 return Status;
1235 }
1236
1237 // Find the new attribute
1238 Status = FindAttribute(DeviceExt, FileRecord, AttributeIndexAllocation, L"$I30", 4, &IndexAllocationContext, &IndexAllocationOffset);
1239 if (!NT_SUCCESS(Status))
1240 {
1241 DPRINT1("ERROR: Couldn't find newly-created index allocation!\n");
1242 return Status;
1243 }
1244
1245 // Advance end marker
1246 EndMarker = (PNTFS_ATTR_RECORD)((ULONG_PTR)EndMarker + EndMarker->Length);
1247
1248 // Add index bitmap to the very end of the file record
1249 Status = AddBitmap(DeviceExt,
1250 FileRecord,
1251 EndMarker,
1252 L"$I30",
1253 4);
1254 if (!NT_SUCCESS(Status))
1255 {
1256 DPRINT1("ERROR: Failed to add index bitmap!\n");
1257 ReleaseAttributeContext(IndexAllocationContext);
1258 return Status;
1259 }
1260
1261 HasIndexAllocation = TRUE;
1262 }
1263
1264 // Is the Index Entry large enough to store the VCN?
1266 {
1267 // Allocate memory for the larger index entry
1269 CurrentKey->IndexEntry->Length + sizeof(ULONGLONG),
1270 TAG_NTFS);
1271 if (!NewEntry)
1272 {
1273 DPRINT1("ERROR: Unable to allocate memory for new index entry!\n");
1274 if (HasIndexAllocation)
1275 ReleaseAttributeContext(IndexAllocationContext);
1277 }
1278
1279 // Copy the old entry to the new one
1280 RtlCopyMemory(NewEntry, CurrentKey->IndexEntry, CurrentKey->IndexEntry->Length);
1281
1282 NewEntry->Length += sizeof(ULONGLONG);
1283
1284 // Free the old memory
1286
1287 CurrentKey->IndexEntry = NewEntry;
1288 CurrentKey->IndexEntry->Flags |= NTFS_INDEX_ENTRY_NODE;
1289 }
1290
1291 // Update the sub-node
1292 Status = UpdateIndexNode(DeviceExt, FileRecord, CurrentKey->LesserChild, IndexBufferSize, IndexAllocationContext, IndexAllocationOffset);
1293 if (!NT_SUCCESS(Status))
1294 {
1295 DPRINT1("ERROR: Failed to update index node!\n");
1296 ReleaseAttributeContext(IndexAllocationContext);
1297 return Status;
1298 }
1299
1300 // Update the VCN stored in the index entry of CurrentKey
1301 SetIndexEntryVCN(CurrentKey->IndexEntry, CurrentKey->LesserChild->VCN);
1302 }
1303 CurrentKey = CurrentKey->NextKey;
1304 }
1305
1306#ifndef NDEBUG
1307 DumpBTree(Tree);
1308#endif
1309
1310 if (HasIndexAllocation)
1311 {
1312#ifndef NDEBUG
1313 PrintAllVCNs(DeviceExt,
1314 IndexAllocationContext,
1315 IndexBufferSize);
1316#endif
1317 ReleaseAttributeContext(IndexAllocationContext);
1318 }
1319
1320 return STATUS_SUCCESS;
1321}
VOID PrintAllVCNs(PDEVICE_EXTENSION Vcb, PNTFS_ATTR_CONTEXT IndexAllocationContext, ULONG NodeSize)
Definition: btree.c:38
NTSTATUS UpdateIndexNode(PDEVICE_EXTENSION DeviceExt, PFILE_RECORD_HEADER FileRecord, PB_TREE_FILENAME_NODE Node, ULONG IndexBufferSize, PNTFS_ATTR_CONTEXT IndexAllocationContext, ULONG IndexAllocationOffset)
Definition: btree.c:1324
NTSTATUS AddBitmap(PNTFS_VCB Vcb, PFILE_RECORD_HEADER FileRecord, PNTFS_ATTR_RECORD AttributeAddress, PCWSTR Name, USHORT NameLength)
Definition: attrib.c:76
NTSTATUS AddIndexAllocation(PNTFS_VCB Vcb, PFILE_RECORD_HEADER FileRecord, PNTFS_ATTR_RECORD AttributeAddress, PCWSTR Name, USHORT NameLength)
Definition: attrib.c:380
ULONGLONG VCN
Definition: ntfs.h:480

Referenced by AddFilenameToDirectoryWorker(), and RemoveFilenameFromDirectoryWorker().

◆ UpdateIndexEntryFileName()

NTSTATUS UpdateIndexEntryFileName ( PDEVICE_EXTENSION  Vcb,
PFILE_RECORD_HEADER  MftRecord,
PCHAR  IndexRecord,
ULONG  IndexBlockSize,
PINDEX_ENTRY_ATTRIBUTE  FirstEntry,
PINDEX_ENTRY_ATTRIBUTE  LastEntry,
PUNICODE_STRING  FileName,
PULONG  StartEntry,
PULONG  CurrentEntry,
BOOLEAN  DirSearch,
PNTFS_FILENAME_UPDATE  Update,
BOOLEAN  CaseSensitive 
)

Recursively searches a directory index and applies the requested update to the $FILE_NAME attribute of the proper index entry. (Heavily based on BrowseIndexEntries)

Definition at line 2215 of file mft.c.

2227{
2229 ULONG RecordOffset;
2230 PINDEX_ENTRY_ATTRIBUTE IndexEntry;
2231 PNTFS_ATTR_CONTEXT IndexAllocationCtx;
2232 ULONGLONG IndexAllocationSize;
2233 PINDEX_BUFFER IndexBuffer;
2234
2235 DPRINT("UpdateIndexEntryFileName(%p, %p, %p, %lu, %p, %p, %wZ, %lu, %lu, %s, %lx, %s)\n",
2236 Vcb,
2237 MftRecord,
2238 IndexRecord,
2239 IndexBlockSize,
2240 FirstEntry,
2241 LastEntry,
2242 FileName,
2243 *StartEntry,
2244 *CurrentEntry,
2245 DirSearch ? "TRUE" : "FALSE",
2246 Update->Flags,
2247 CaseSensitive ? "TRUE" : "FALSE");
2248
2249 // find the index entry responsible for the file we're trying to update
2250 IndexEntry = FirstEntry;
2251 while (IndexEntry < LastEntry &&
2252 !(IndexEntry->Flags & NTFS_INDEX_ENTRY_END))
2253 {
2254 if ((IndexEntry->Data.Directory.IndexedFile & NTFS_MFT_MASK) > NTFS_FILE_FIRST_USER_FILE &&
2255 *CurrentEntry >= *StartEntry &&
2256 IndexEntry->FileName.NameType != NTFS_FILE_NAME_DOS &&
2257 CompareFileName(Vcb, FileName, IndexEntry, DirSearch, CaseSensitive))
2258 {
2259 *StartEntry = *CurrentEntry;
2260
2262 {
2263 IndexEntry->FileName.DataSize = Update->DataSize;
2264 IndexEntry->FileName.AllocatedSize = Update->AllocatedSize;
2265 }
2266
2268 {
2269 IndexEntry->FileName.CreationTime = Update->CreationTime;
2270 IndexEntry->FileName.ChangeTime = Update->ChangeTime;
2271 IndexEntry->FileName.LastWriteTime = Update->LastWriteTime;
2272 IndexEntry->FileName.LastAccessTime = Update->LastAccessTime;
2273 }
2274
2276 {
2277 IndexEntry->FileName.FileAttributes = Update->FileAttributes;
2278 }
2279
2280 // indicate that the caller will still need to write the structure to the disk
2281 return STATUS_PENDING;
2282 }
2283
2284 (*CurrentEntry) += 1;
2285 ASSERT(IndexEntry->Length >= sizeof(INDEX_ENTRY_ATTRIBUTE));
2286 IndexEntry = (PINDEX_ENTRY_ATTRIBUTE)((PCHAR)IndexEntry + IndexEntry->Length);
2287 }
2288
2289 /* If we're already browsing a subnode */
2290 if (IndexRecord == NULL)
2291 {
2293 }
2294
2295 /* If there's no subnode */
2296 if (!(IndexEntry->Flags & NTFS_INDEX_ENTRY_NODE))
2297 {
2299 }
2300
2301 Status = FindAttribute(Vcb, MftRecord, AttributeIndexAllocation, L"$I30", 4, &IndexAllocationCtx, NULL);
2302 if (!NT_SUCCESS(Status))
2303 {
2304 DPRINT("Corrupted filesystem!\n");
2305 return Status;
2306 }
2307
2308 IndexAllocationSize = AttributeDataLength(IndexAllocationCtx->pRecord);
2310 for (RecordOffset = 0; RecordOffset < IndexAllocationSize; RecordOffset += IndexBlockSize)
2311 {
2312 ReadAttribute(Vcb, IndexAllocationCtx, RecordOffset, IndexRecord, IndexBlockSize);
2313 Status = FixupUpdateSequenceArray(Vcb, &((PFILE_RECORD_HEADER)IndexRecord)->Ntfs);
2314 if (!NT_SUCCESS(Status))
2315 {
2316 break;
2317 }
2318
2319 IndexBuffer = (PINDEX_BUFFER)IndexRecord;
2320 ASSERT(IndexBuffer->Ntfs.Type == NRH_INDX_TYPE);
2321 ASSERT(IndexBuffer->Header.AllocatedSize + FIELD_OFFSET(INDEX_BUFFER, Header) == IndexBlockSize);
2322 FirstEntry = (PINDEX_ENTRY_ATTRIBUTE)((ULONG_PTR)&IndexBuffer->Header + IndexBuffer->Header.FirstEntryOffset);
2323 LastEntry = (PINDEX_ENTRY_ATTRIBUTE)((ULONG_PTR)&IndexBuffer->Header + IndexBuffer->Header.TotalSizeOfEntries);
2324 ASSERT(LastEntry <= (PINDEX_ENTRY_ATTRIBUTE)((ULONG_PTR)IndexBuffer + IndexBlockSize));
2325
2327 NULL,
2328 NULL,
2329 0,
2330 FirstEntry,
2331 LastEntry,
2332 FileName,
2333 StartEntry,
2334 CurrentEntry,
2335 DirSearch,
2336 Update,
2337 CaseSensitive);
2338 if (Status == STATUS_PENDING)
2339 {
2340 // write the index record back to disk
2341 ULONG Written;
2342
2343 // first we need to update the fixup values for the index block
2344 Status = AddFixupArray(Vcb, &((PFILE_RECORD_HEADER)IndexRecord)->Ntfs);
2345 if (!NT_SUCCESS(Status))
2346 {
2347 DPRINT1("Error: Failed to update fixup sequence array!\n");
2348 break;
2349 }
2350
2351 Status = WriteAttribute(Vcb, IndexAllocationCtx, RecordOffset, (const PUCHAR)IndexRecord, IndexBlockSize, &Written, MftRecord);
2352 if (!NT_SUCCESS(Status))
2353 {
2354 DPRINT1("ERROR Performing write!\n");
2355 break;
2356 }
2357
2359 break;
2360 }
2361 if (NT_SUCCESS(Status))
2362 {
2363 break;
2364 }
2365 }
2366
2367 ReleaseAttributeContext(IndexAllocationCtx);
2368 return Status;
2369}
struct INDEX_BUFFER * PINDEX_BUFFER
#define NTFS_FILE_FIRST_USER_FILE
Definition: ntfs.h:223
#define NRH_INDX_TYPE
Definition: ntfs.h:278
NTSTATUS UpdateIndexEntryFileName(PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER MftRecord, PCHAR IndexRecord, ULONG IndexBlockSize, PINDEX_ENTRY_ATTRIBUTE FirstEntry, PINDEX_ENTRY_ATTRIBUTE LastEntry, PUNICODE_STRING FileName, PULONG StartEntry, PULONG CurrentEntry, BOOLEAN DirSearch, PNTFS_FILENAME_UPDATE Update, BOOLEAN CaseSensitive)
Definition: mft.c:2215
BOOLEAN CompareFileName(PDEVICE_EXTENSION Vcb, PUNICODE_STRING FileName, PINDEX_ENTRY_ATTRIBUTE IndexEntry, BOOLEAN DirSearch, BOOLEAN CaseSensitive)
Definition: mft.c:3622
ULONGLONG DataSize
Definition: ntfs.h:397
ULONGLONG AllocatedSize
Definition: ntfs.h:396
INDEX_HEADER_ATTRIBUTE Header
Definition: ntfs.h:436
NTFS_RECORD_HEADER Ntfs
Definition: ntfs.h:434

Referenced by UpdateFileNameRecordWorker(), and UpdateIndexEntryFileName().

◆ UpdateIndexNode()

NTSTATUS UpdateIndexNode ( PDEVICE_EXTENSION  DeviceExt,
PFILE_RECORD_HEADER  FileRecord,
PB_TREE_FILENAME_NODE  Node,
ULONG  IndexBufferSize,
PNTFS_ATTR_CONTEXT  IndexAllocationContext,
ULONG  IndexAllocationOffset 
)

Definition at line 1324 of file btree.c.

1330{
1331 ULONG i;
1332 PB_TREE_KEY CurrentKey = Node->FirstKey;
1333 BOOLEAN HasChildren = FALSE;
1335
1336
1337 DPRINT("UpdateIndexNode(%p, %p, %p, %lu, %p, %lu) called for index node with VCN %I64u\n",
1338 DeviceExt,
1339 FileRecord,
1340 Node,
1341 IndexBufferSize,
1342 IndexAllocationContext,
1343 IndexAllocationOffset,
1344 Node->VCN);
1345
1346 // Walk through the node and look for children to update
1347 for (i = 0; i < Node->KeyCount; i++)
1348 {
1349 ASSERT(CurrentKey);
1350
1351 // If there's a child node
1352 if (CurrentKey->LesserChild)
1353 {
1354 HasChildren = TRUE;
1355
1356 // Update the child node on disk
1357 Status = UpdateIndexNode(DeviceExt, FileRecord, CurrentKey->LesserChild, IndexBufferSize, IndexAllocationContext, IndexAllocationOffset);
1358 if (!NT_SUCCESS(Status))
1359 {
1360 DPRINT1("ERROR: Failed to update child node!\n");
1361 return Status;
1362 }
1363
1364 // Is the Index Entry large enough to store the VCN?
1366 {
1367 // Allocate memory for the larger index entry
1369 CurrentKey->IndexEntry->Length + sizeof(ULONGLONG),
1370 TAG_NTFS);
1371 if (!NewEntry)
1372 {
1373 DPRINT1("ERROR: Unable to allocate memory for new index entry!\n");
1375 }
1376
1377 // Copy the old entry to the new one
1378 RtlCopyMemory(NewEntry, CurrentKey->IndexEntry, CurrentKey->IndexEntry->Length);
1379
1380 NewEntry->Length += sizeof(ULONGLONG);
1381
1382 // Free the old memory
1384
1385 CurrentKey->IndexEntry = NewEntry;
1386 }
1387
1388 // Update the VCN stored in the index entry of CurrentKey
1389 SetIndexEntryVCN(CurrentKey->IndexEntry, CurrentKey->LesserChild->VCN);
1390
1391 CurrentKey->IndexEntry->Flags |= NTFS_INDEX_ENTRY_NODE;
1392 }
1393
1394 CurrentKey = CurrentKey->NextKey;
1395 }
1396
1397
1398 // Do we need to write this node to disk?
1399 if (Node->DiskNeedsUpdating)
1400 {
1401 ULONGLONG NodeOffset;
1402 ULONG LengthWritten;
1403 PINDEX_BUFFER IndexBuffer;
1404
1405 // Does the node need to be assigned a VCN?
1406 if (!Node->HasValidVCN)
1407 {
1408 // Allocate the node
1409 Status = AllocateIndexNode(DeviceExt,
1410 FileRecord,
1411 IndexBufferSize,
1412 IndexAllocationContext,
1413 IndexAllocationOffset,
1414 &Node->VCN);
1415 if (!NT_SUCCESS(Status))
1416 {
1417 DPRINT1("ERROR: Failed to allocate index record in index allocation!\n");
1418 return Status;
1419 }
1420
1421 Node->HasValidVCN = TRUE;
1422 }
1423
1424 // Allocate memory for an index buffer
1425 IndexBuffer = ExAllocatePoolWithTag(NonPagedPool, IndexBufferSize, TAG_NTFS);
1426 if (!IndexBuffer)
1427 {
1428 DPRINT1("ERROR: Failed to allocate %lu bytes for index buffer!\n", IndexBufferSize);
1430 }
1431
1432 // Create the index buffer we'll be writing to disk to represent this node
1433 Status = CreateIndexBufferFromBTreeNode(DeviceExt, Node, IndexBufferSize, HasChildren, IndexBuffer);
1434 if (!NT_SUCCESS(Status))
1435 {
1436 DPRINT1("ERROR: Failed to create index buffer from node!\n");
1437 ExFreePoolWithTag(IndexBuffer, TAG_NTFS);
1438 return Status;
1439 }
1440
1441 // Get Offset of index buffer in index allocation
1442 NodeOffset = GetAllocationOffsetFromVCN(DeviceExt, IndexBufferSize, Node->VCN);
1443
1444 // Write the buffer to the index allocation
1445 Status = WriteAttribute(DeviceExt, IndexAllocationContext, NodeOffset, (const PUCHAR)IndexBuffer, IndexBufferSize, &LengthWritten, FileRecord);
1446 if (!NT_SUCCESS(Status) || LengthWritten != IndexBufferSize)
1447 {
1448 DPRINT1("ERROR: Failed to update index allocation!\n");
1449 ExFreePoolWithTag(IndexBuffer, TAG_NTFS);
1450 if (!NT_SUCCESS(Status))
1451 return Status;
1452 else
1453 return STATUS_END_OF_FILE;
1454 }
1455
1456 Node->DiskNeedsUpdating = FALSE;
1457
1458 // Free the index buffer
1459 ExFreePoolWithTag(IndexBuffer, TAG_NTFS);
1460 }
1461
1462 return STATUS_SUCCESS;
1463}
NTSTATUS AllocateIndexNode(PDEVICE_EXTENSION DeviceExt, PFILE_RECORD_HEADER FileRecord, ULONG IndexBufferSize, PNTFS_ATTR_CONTEXT IndexAllocationCtx, ULONG IndexAllocationOffset, PULONGLONG NewVCN)
Definition: btree.c:117
ULONGLONG GetAllocationOffsetFromVCN(PDEVICE_EXTENSION DeviceExt, ULONG IndexBufferSize, ULONGLONG Vcn)
Definition: btree.c:1637
NTSTATUS CreateIndexBufferFromBTreeNode(PDEVICE_EXTENSION DeviceExt, PB_TREE_FILENAME_NODE Node, ULONG BufferSize, BOOLEAN HasChildren, PINDEX_BUFFER IndexBuffer)
Definition: btree.c:1006

Referenced by UpdateIndexAllocation(), and UpdateIndexNode().

◆ UpdateMftMirror()

NTSTATUS UpdateMftMirror ( PNTFS_VCB  Vcb)

Definition at line 3690 of file mft.c.

3691{
3692 PFILE_RECORD_HEADER MirrorFileRecord;
3693 PNTFS_ATTR_CONTEXT MirrDataContext;
3694 PNTFS_ATTR_CONTEXT MftDataContext;
3695 PCHAR DataBuffer;
3699 ULONG LengthWritten;
3700
3701 // Allocate memory for the Mft mirror file record
3702 MirrorFileRecord = ExAllocateFromNPagedLookasideList(&Vcb->FileRecLookasideList);
3703 if (!MirrorFileRecord)
3704 {
3705 DPRINT1("Error: Failed to allocate memory for $MFTMirr!\n");
3707 }
3708
3709 // Read the Mft Mirror file record
3710 Status = ReadFileRecord(Vcb, NTFS_FILE_MFTMIRR, MirrorFileRecord);
3711 if (!NT_SUCCESS(Status))
3712 {
3713 DPRINT1("ERROR: Failed to read $MFTMirr!\n");
3714 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, MirrorFileRecord);
3715 return Status;
3716 }
3717
3718 // Find the $DATA attribute of $MFTMirr
3719 Status = FindAttribute(Vcb, MirrorFileRecord, AttributeData, L"", 0, &MirrDataContext, NULL);
3720 if (!NT_SUCCESS(Status))
3721 {
3722 DPRINT1("ERROR: Couldn't find $DATA attribute!\n");
3723 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, MirrorFileRecord);
3724 return Status;
3725 }
3726
3727 // Find the $DATA attribute of $MFT
3728 Status = FindAttribute(Vcb, Vcb->MasterFileTable, AttributeData, L"", 0, &MftDataContext, NULL);
3729 if (!NT_SUCCESS(Status))
3730 {
3731 DPRINT1("ERROR: Couldn't find $DATA attribute!\n");
3732 ReleaseAttributeContext(MirrDataContext);
3733 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, MirrorFileRecord);
3734 return Status;
3735 }
3736
3737 // Get the size of the mirror's $DATA attribute
3738 DataLength = AttributeDataLength(MirrDataContext->pRecord);
3739
3740 ASSERT(DataLength % Vcb->NtfsInfo.BytesPerFileRecord == 0);
3741
3742 // Create buffer for the mirror's $DATA attribute
3744 if (!DataBuffer)
3745 {
3746 DPRINT1("Error: Couldn't allocate memory for $DATA buffer!\n");
3747 ReleaseAttributeContext(MftDataContext);
3748 ReleaseAttributeContext(MirrDataContext);
3749 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, MirrorFileRecord);
3751 }
3752
3754
3755 // Back up the first several entries of the Mft's $DATA Attribute
3756 BytesRead = ReadAttribute(Vcb, MftDataContext, 0, DataBuffer, (ULONG)DataLength);
3757 if (BytesRead != (ULONG)DataLength)
3758 {
3759 DPRINT1("Error: Failed to read $DATA for $MFTMirr!\n");
3760 ReleaseAttributeContext(MftDataContext);
3761 ReleaseAttributeContext(MirrDataContext);
3762 ExFreePoolWithTag(DataBuffer, TAG_NTFS);
3763 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, MirrorFileRecord);
3764 return STATUS_UNSUCCESSFUL;
3765 }
3766
3767 // Write the mirror's $DATA attribute
3769 MirrDataContext,
3770 0,
3771 (PUCHAR)DataBuffer,
3772 DataLength,
3773 &LengthWritten,
3774 MirrorFileRecord);
3775 if (!NT_SUCCESS(Status))
3776 {
3777 DPRINT1("ERROR: Failed to write $DATA attribute of $MFTMirr!\n");
3778 }
3779
3780 // Cleanup
3781 ReleaseAttributeContext(MftDataContext);
3782 ReleaseAttributeContext(MirrDataContext);
3783 ExFreePoolWithTag(DataBuffer, TAG_NTFS);
3784 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, MirrorFileRecord);
3785
3786 return Status;
3787}
#define NTFS_FILE_MFTMIRR
Definition: ntfs.h:24
_In_ D3DDDI_VIDEO_PRESENT_TARGET_ID _In_ ULONG _In_ ULONG DataLength
Definition: dispmprt.h:233
#define ULONG_MAX
Definition: limits.h:31

Referenced by IncreaseMftSize().

◆ WriteAttribute()

NTSTATUS WriteAttribute ( PDEVICE_EXTENSION  Vcb,
PNTFS_ATTR_CONTEXT  Context,
ULONGLONG  Offset,
const PUCHAR  Buffer,
ULONG  Length,
PULONG  LengthWritten,
PFILE_RECORD_HEADER  FileRecord 
)

Definition at line 1829 of file mft.c.

1836{
1838 Context,
1839 Offset,
1840 Buffer,
1841 Length,
1842 RealLengthWritten,
1843 FileRecord,
1844 NULL);
1845}
NTSTATUS WriteAttributeFromIrp(PDEVICE_EXTENSION Vcb, PNTFS_ATTR_CONTEXT Context, ULONGLONG Offset, const PUCHAR Buffer, ULONG Length, PULONG RealLengthWritten, PFILE_RECORD_HEADER FileRecord, PIRP Irp)
Definition: mft.c:1677

Referenced by AddFilenameToDirectoryWorker(), AddNewMftEntry(), AllocateIndexNode(), FreeMftEntry(), IncreaseMftSize(), NtfsWriteVolumeBitmap(), RemoveFilenameFromDirectoryWorker(), SetResidentAttributeDataLength(), UpdateFileNameRecordWorker(), UpdateFileRecord(), UpdateIndexEntryFileName(), UpdateIndexNode(), and UpdateMftMirror().

◆ WriteAttributeFromIrp()

NTSTATUS WriteAttributeFromIrp ( PDEVICE_EXTENSION  Vcb,
PNTFS_ATTR_CONTEXT  Context,
ULONGLONG  Offset,
const PUCHAR  Buffer,
ULONG  Length,
PULONG  LengthWritten,
PFILE_RECORD_HEADER  FileRecord,
PIRP  Irp 
)

Definition at line 1677 of file mft.c.

1685{
1686 ULONG MappedLength = 0;
1687 ULONG Transferred = 0;
1689 BOOLEAN FileRecordAllocated = FALSE;
1690 NTFS_IO_RUN_LIST RunList;
1691
1692
1693 DPRINT("WriteAttribute(%p, %p, %I64u, %p, %lu, %p, %p)\n", Vcb, Context, Offset, Buffer, Length, RealLengthWritten, FileRecord);
1694
1695 *RealLengthWritten = 0;
1696 NtfsInitIoRunList(&RunList);
1697
1698 // is this a resident attribute?
1699 if (!Context->pRecord->IsNonResident)
1700 {
1701 ULONG AttributeOffset;
1702 PNTFS_ATTR_CONTEXT FoundContext;
1704
1705 // Ensure requested data is within the bounds of the attribute
1706 ASSERT(Offset + Length <= Context->pRecord->Resident.ValueLength);
1707
1708 if (Offset + Length > Context->pRecord->Resident.ValueLength)
1709 {
1710 DPRINT1("DRIVER ERROR: Attribute is too small!\n");
1712 }
1713
1714 // Do we need to read the file record?
1715 if (FileRecord == NULL)
1716 {
1717 FileRecord = ExAllocateFromNPagedLookasideList(&Vcb->FileRecLookasideList);
1718 if (!FileRecord)
1719 {
1720 DPRINT1("Error: Couldn't allocate file record!\n");
1721 return STATUS_NO_MEMORY;
1722 }
1723
1724 FileRecordAllocated = TRUE;
1725
1726 // read the file record
1727 ReadFileRecord(Vcb, Context->FileMFTIndex, FileRecord);
1728 }
1729
1730 // find where to write the attribute data to
1731 Status = FindAttribute(Vcb, FileRecord,
1732 Context->pRecord->Type,
1733 (PCWSTR)((ULONG_PTR)Context->pRecord + Context->pRecord->NameOffset),
1734 Context->pRecord->NameLength,
1735 &FoundContext,
1736 &AttributeOffset);
1737
1738 if (!NT_SUCCESS(Status))
1739 {
1740 DPRINT1("ERROR: Couldn't find matching attribute!\n");
1741 if(FileRecordAllocated)
1742 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, FileRecord);
1743 return Status;
1744 }
1745
1746 Destination = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + AttributeOffset);
1747
1748 DPRINT("Offset: %I64u, AttributeOffset: %u, ValueOffset: %u\n", Offset, AttributeOffset, Context->pRecord->Resident.ValueLength);
1749
1750 // Will we be writing past the end of the allocated file record?
1751 if (Offset + Length + AttributeOffset + Context->pRecord->Resident.ValueOffset > Vcb->NtfsInfo.BytesPerFileRecord)
1752 {
1753 DPRINT1("DRIVER ERROR: Data being written extends past end of file record!\n");
1754 ReleaseAttributeContext(FoundContext);
1755 if (FileRecordAllocated)
1756 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, FileRecord);
1758 }
1759
1760 // copy the data being written into the file record. We cast Offset to ULONG, which is safe because it's range has been verified.
1761 RtlCopyMemory((PCHAR)((ULONG_PTR)Destination + Context->pRecord->Resident.ValueOffset + (ULONG)Offset), Buffer, Length);
1762
1763 Status = UpdateFileRecord(Vcb, Context->FileMFTIndex, FileRecord);
1764
1765 // Update the context's copy of the resident attribute
1766 ASSERT(Context->pRecord->Length == Destination->Length);
1767 RtlCopyMemory((PVOID)Context->pRecord, Destination, Context->pRecord->Length);
1768
1769 ReleaseAttributeContext(FoundContext);
1770 if (FileRecordAllocated)
1771 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, FileRecord);
1772
1773 if (NT_SUCCESS(Status))
1774 *RealLengthWritten = Length;
1775
1776 return Status;
1777 }
1778
1779 // This is a non-resident attribute: map the requested range onto the
1780 // volume, then issue every run it spans in a single parallel batch.
1781
1782 Status = NtfsMapAttributeRuns(Vcb, Context, Offset, Length, &RunList, &MappedLength);
1783
1784 if (NT_SUCCESS(Status) && MappedLength < Length)
1785 {
1786 // The attribute's allocation ends before the request does.
1787 // TODO: assign new clusters to the end of the file.
1788 // [We can reach here by creating a new file record when the MFT isn't large enough]
1789 DPRINT1("FIXME: Attribute needs to be enlarged (mapped %lu of %lu bytes).\n",
1790 MappedLength, Length);
1792 }
1793
1794 if (NT_SUCCESS(Status))
1795 {
1796 // Writing into a hole would mean allocating clusters, which we cannot
1797 // do here; NtfsPerformIrpIoRuns() rejects sparse runs on IRP_MJ_WRITE.
1798 Status = NtfsPerformIrpIoRuns(Vcb->StorageDevice,
1800 Vcb->NtfsInfo.BytesPerSector,
1801 Irp,
1802 Buffer,
1803 &RunList,
1804 FALSE,
1805 &Transferred);
1806 }
1807
1808 NtfsFreeIoRunList(&RunList);
1809
1810 if (!NT_SUCCESS(Status))
1811 {
1812 DPRINT1("Write failure (Status %lx)\n", Status);
1813 *RealLengthWritten = 0;
1814 return Status;
1815 }
1816
1817 *RealLengthWritten = Transferred;
1818
1819 if (Transferred < Length)
1820 {
1821 DPRINT1("Short write: expected %lu bytes, wrote %lu\n", Length, Transferred);
1823 }
1824
1825 return Status;
1826}
#define STATUS_NO_MEMORY
Definition: d3dkmdt.h:51

Referenced by NtfsWriteFile(), and WriteAttribute().

Variable Documentation

◆ DriverEntry

DRIVER_INITIALIZE DriverEntry

Definition at line 1545 of file ntfs.h.

◆ NtfsFastIoCheckIfPossible

FAST_IO_CHECK_IF_POSSIBLE NtfsFastIoCheckIfPossible

Definition at line 1043 of file ntfs.h.

Referenced by DriverEntry().

◆ NtfsFastIoRead

FAST_IO_READ NtfsFastIoRead

Definition at line 1044 of file ntfs.h.

Referenced by DriverEntry().

◆ NtfsFastIoWrite

FAST_IO_WRITE NtfsFastIoWrite

Definition at line 1045 of file ntfs.h.

Referenced by DriverEntry().

◆ NtfsFsdDispatch

DRIVER_DISPATCH NtfsFsdDispatch

Definition at line 1021 of file ntfs.h.

Referenced by NtfsInitializeFunctionPointers().

◆ NtfsGlobalData