ReactOS 0.4.15-dev-7788-g1ad9096
attrib.c File Reference
#include "ntfs.h"
#include <ntintsafe.h>
#include <debug.h>
Include dependency graph for attrib.c:

Go to the source code of this file.

Macros

#define NDEBUG
 

Functions

AddBitmap

@implemented

Adds a $BITMAP attribute to a given FileRecord.

Parameters
VcbPointer to an NTFS_VCB for the destination volume.
FileRecordPointer to a complete file record to add the attribute to.
AttributeAddressPointer to the region of memory that will receive the $INDEX_ALLOCATION attribute. This address must reside within FileRecord. Must be aligned to an 8-byte boundary (relative to FileRecord).
NamePointer to a string of 16-bit Unicode characters naming the attribute. Most often L"$I30".
NameLengthThe number of wide-characters in the name. L"$I30" Would use 4 here.
Returns
STATUS_SUCCESS on success. STATUS_NOT_IMPLEMENTED if target address isn't at the end of the given file record, or if the file record isn't large enough for the attribute.
Remarks
Only adding the attribute to the end of the file record is supported; AttributeAddress must be of type AttributeEnd. This could be improved by adding an $ATTRIBUTE_LIST to the file record if there's not enough space.
NTSTATUS AddBitmap (PNTFS_VCB Vcb, PFILE_RECORD_HEADER FileRecord, PNTFS_ATTR_RECORD AttributeAddress, PCWSTR Name, USHORT NameLength)
 
AddData

@implemented

Adds a $DATA attribute to a given FileRecord.

Parameters
FileRecordPointer to a complete file record to add the attribute to. Caller is responsible for ensuring FileRecord is large enough to contain $DATA.
AttributeAddressPointer to the region of memory that will receive the $DATA attribute. This address must reside within FileRecord. Must be aligned to an 8-byte boundary (relative to FileRecord).
Returns
STATUS_SUCCESS on success. STATUS_NOT_IMPLEMENTED if target address isn't at the end of the given file record.
Remarks
Only adding the attribute to the end of the file record is supported; AttributeAddress must be of type AttributeEnd. As it's implemented, this function is only intended to assist in creating new file records. It could be made more general-purpose by considering file records with an $ATTRIBUTE_LIST. It's the caller's responsibility to ensure the given file record has enough memory allocated for the attribute.
NTSTATUS AddData (PFILE_RECORD_HEADER FileRecord, PNTFS_ATTR_RECORD AttributeAddress)
 
AddFileName

@implemented

Adds a $FILE_NAME attribute to a given FileRecord.

Parameters
FileRecordPointer to a complete file record to add the attribute to. Caller is responsible for ensuring FileRecord is large enough to contain $FILE_NAME.
AttributeAddressPointer to the region of memory that will receive the $FILE_NAME attribute. This address must reside within FileRecord. Must be aligned to an 8-byte boundary (relative to FileRecord).
DeviceExtPoints to the target disk's DEVICE_EXTENSION.
FileObjectPointer to the FILE_OBJECT which represents the new name. This parameter is used to determine the filename and parent directory.
CaseSensitiveBoolean indicating if the function should operate in case-sensitive mode. This will be TRUE if an application opened the file with the FILE_FLAG_POSIX_SEMANTICS flag.
ParentMftIndexPointer to a ULONGLONG which will receive the index of the parent directory.
Returns
STATUS_SUCCESS on success. STATUS_NOT_IMPLEMENTED if target address isn't at the end of the given file record.
Remarks
Only adding the attribute to the end of the file record is supported; AttributeAddress must be of type AttributeEnd. As it's implemented, this function is only intended to assist in creating new file records. It could be made more general-purpose by considering file records with an $ATTRIBUTE_LIST. It's the caller's responsibility to ensure the given file record has enough memory allocated for the attribute.
NTSTATUS AddFileName (PFILE_RECORD_HEADER FileRecord, PNTFS_ATTR_RECORD AttributeAddress, PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, BOOLEAN CaseSensitive, PULONGLONG ParentMftIndex)
 
AddIndexAllocation

@implemented

Adds an $INDEX_ALLOCATION attribute to a given FileRecord.

Parameters
VcbPointer to an NTFS_VCB for the destination volume.
FileRecordPointer to a complete file record to add the attribute to.
AttributeAddressPointer to the region of memory that will receive the $INDEX_ALLOCATION attribute. This address must reside within FileRecord. Must be aligned to an 8-byte boundary (relative to FileRecord).
NamePointer to a string of 16-bit Unicode characters naming the attribute. Most often, this will be L"$I30".
NameLengthThe number of wide-characters in the name. L"$I30" Would use 4 here.
Returns
STATUS_SUCCESS on success. STATUS_NOT_IMPLEMENTED if target address isn't at the end of the given file record, or if the file record isn't large enough for the attribute.
Remarks
Only adding the attribute to the end of the file record is supported; AttributeAddress must be of type AttributeEnd. This could be improved by adding an $ATTRIBUTE_LIST to the file record if there's not enough space.
NTSTATUS AddIndexAllocation (PNTFS_VCB Vcb, PFILE_RECORD_HEADER FileRecord, PNTFS_ATTR_RECORD AttributeAddress, PCWSTR Name, USHORT NameLength)
 
AddIndexRoot

@implemented

Adds an $INDEX_ROOT attribute to a given FileRecord.

Parameters
VcbPointer to an NTFS_VCB for the destination volume.
FileRecordPointer to a complete file record to add the attribute to. Caller is responsible for ensuring FileRecord is large enough to contain $INDEX_ROOT.
AttributeAddressPointer to the region of memory that will receive the $INDEX_ROOT attribute. This address must reside within FileRecord. Must be aligned to an 8-byte boundary (relative to FileRecord).
NewIndexRootPointer to an INDEX_ROOT_ATTRIBUTE containing the index root that will be copied to the new attribute.
RootLengthThe length of NewIndexRoot, in bytes.
NamePointer to a string of 16-bit Unicode characters naming the attribute. Most often, this will be L"$I30".
NameLengthThe number of wide-characters in the name. L"$I30" Would use 4 here.
Returns
STATUS_SUCCESS on success. STATUS_NOT_IMPLEMENTED if target address isn't at the end of the given file record.
Remarks
This function is intended to assist in creating new folders. Only adding the attribute to the end of the file record is supported; AttributeAddress must be of type AttributeEnd. It's the caller's responsibility to ensure the given file record has enough memory allocated for the attribute, and this memory must have been zeroed.
NTSTATUS AddIndexRoot (PNTFS_VCB Vcb, PFILE_RECORD_HEADER FileRecord, PNTFS_ATTR_RECORD AttributeAddress, PINDEX_ROOT_ATTRIBUTE NewIndexRoot, ULONG RootLength, PCWSTR Name, USHORT NameLength)
 
AddRun

@implemented

Adds a run of allocated clusters to a non-resident attribute.

Parameters
VcbPointer to an NTFS_VCB for the destination volume.
AttrContextPointer to an NTFS_ATTR_CONTEXT describing the destination attribute.
AttrOffsetByte offset of the destination attribute relative to its file record.
FileRecordPointer to a complete copy of the file record containing the destination attribute. Must be at least Vcb->NtfsInfo.BytesPerFileRecord bytes long.
NextAssignedClusterLogical cluster number of the start of the data run being added.
RunLengthHow many clusters are in the data run being added. Can't be 0.
Returns
STATUS_SUCCESS on success. STATUS_INVALID_PARAMETER if AttrContext describes a resident attribute. STATUS_INSUFFICIENT_RESOURCES if ConvertDataRunsToLargeMCB() fails or if we fail to allocate a buffer for the new data runs. STATUS_INSUFFICIENT_RESOURCES or STATUS_UNSUCCESSFUL if FsRtlAddLargeMcbEntry() fails. STATUS_BUFFER_TOO_SMALL if ConvertLargeMCBToDataRuns() fails. STATUS_NOT_IMPLEMENTED if we need to migrate the attribute to an attribute list (TODO).
Remarks
Clusters should have been allocated previously with NtfsAllocateClusters().
NTSTATUS AddRun (PNTFS_VCB Vcb, PNTFS_ATTR_CONTEXT AttrContext, ULONG AttrOffset, PFILE_RECORD_HEADER FileRecord, ULONGLONG NextAssignedCluster, ULONG RunLength)
 
AddStandardInformation

@implemented

Adds a $STANDARD_INFORMATION attribute to a given FileRecord.

Parameters
FileRecordPointer to a complete file record to add the attribute to. Caller is responsible for ensuring FileRecord is large enough to contain $STANDARD_INFORMATION.
AttributeAddressPointer to the region of memory that will receive the $STANDARD_INFORMATION attribute. This address must reside within FileRecord. Must be aligned to an 8-byte boundary (relative to FileRecord).
Returns
STATUS_SUCCESS on success. STATUS_NOT_IMPLEMENTED if target address isn't at the end of the given file record.
Remarks
Only adding the attribute to the end of the file record is supported; AttributeAddress must be of type AttributeEnd. As it's implemented, this function is only intended to assist in creating new file records. It could be made more general-purpose by considering file records with an $ATTRIBUTE_LIST. It's the caller's responsibility to ensure the given file record has enough memory allocated for the attribute.
NTSTATUS AddStandardInformation (PFILE_RECORD_HEADER FileRecord, PNTFS_ATTR_RECORD AttributeAddress)
 
ConvertDataRunsToLargeMCB

@implemented

Converts binary data runs to a map control block.

Parameters
DataRunPointer to the run data
DataRunsMCBPointer to an unitialized LARGE_MCB structure.
Returns
STATUS_SUCCESS on success, STATUS_INSUFFICIENT_RESOURCES or STATUS_UNSUCCESSFUL if we fail to initialize the mcb or add an entry.
Remarks
Initializes the LARGE_MCB pointed to by DataRunsMCB. If this function succeeds, you need to call FsRtlUninitializeLargeMcb() when you're done with DataRunsMCB. This function will ensure the LargeMCB has been unitialized in case of failure.
NTSTATUS ConvertDataRunsToLargeMCB (PUCHAR DataRun, PLARGE_MCB DataRunsMCB, PULONGLONG pNextVBN)
 
ConvertLargeMCBToDataRuns

@implemented

Converts a map control block to a series of encoded data runs (used by non-resident attributes).

Parameters
DataRunsMCBPointer to a LARGE_MCB structure describing the data runs.
RunBufferPointer to the buffer that will receive the encoded data runs.
MaxBufferSizeSize of RunBuffer, in bytes.
UsedBufferSizePointer to a ULONG that will receive the size of the data runs in bytes. Can't be NULL.
Returns
STATUS_SUCCESS on success, STATUS_BUFFER_TOO_SMALL if RunBuffer is too small to contain the complete output.
NTSTATUS ConvertLargeMCBToDataRuns (PLARGE_MCB DataRunsMCB, PUCHAR RunBuffer, ULONG MaxBufferSize, PULONG UsedBufferSize)
 
PUCHAR DecodeRun (PUCHAR DataRun, LONGLONG *DataRunOffset, ULONGLONG *DataRunLength)
 
BOOLEAN FindRun (PNTFS_ATTR_RECORD NresAttr, ULONGLONG vcn, PULONGLONG lcn, PULONGLONG count)
 
FreeClusters

@implemented

Shrinks the allocation size of a non-resident attribute by a given number of clusters. Frees the clusters from the volume's $BITMAP file as well as the attribute's data runs.

Parameters
VcbPointer to an NTFS_VCB for the destination volume.
AttrContextPointer to an NTFS_ATTR_CONTEXT describing the attribute from which the clusters will be freed.
AttrOffsetByte offset of the destination attribute relative to its file record.
FileRecordPointer to a complete copy of the file record containing the attribute. Must be at least Vcb->NtfsInfo.BytesPerFileRecord bytes long.
ClustersToFreeNumber of clusters that should be freed from the end of the data stream. Must be no more Than the number of clusters assigned to the attribute (HighestVCN + 1).
Returns
STATUS_SUCCESS on success. STATUS_INVALID_PARAMETER if AttrContext describes a resident attribute, or if the caller requested more clusters be freed than the attribute has been allocated. STATUS_INSUFFICIENT_RESOURCES if allocating a buffer for the data runs fails or if ConvertDataRunsToLargeMCB() fails. STATUS_BUFFER_TOO_SMALL if ConvertLargeMCBToDataRuns() fails.
NTSTATUS FreeClusters (PNTFS_VCB Vcb, PNTFS_ATTR_CONTEXT AttrContext, ULONG AttrOffset, PFILE_RECORD_HEADER FileRecord, ULONG ClustersToFree)
 
static NTSTATUS InternalReadNonResidentAttributes (PFIND_ATTR_CONTXT Context)
 
static PNTFS_ATTRIBUTE_LIST_ITEM InternalGetNextAttributeListItem (PFIND_ATTR_CONTXT Context)
 
NTSTATUS FindFirstAttributeListItem (PFIND_ATTR_CONTXT Context, PNTFS_ATTRIBUTE_LIST_ITEM *Item)
 
NTSTATUS FindNextAttributeListItem (PFIND_ATTR_CONTXT Context, PNTFS_ATTRIBUTE_LIST_ITEM *Item)
 
static PNTFS_ATTR_RECORD InternalGetNextAttribute (PFIND_ATTR_CONTXT Context)
 
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)
 
static VOID NtfsDumpFileNameAttribute (PNTFS_ATTR_RECORD Attribute)
 
static VOID NtfsDumpStandardInformationAttribute (PNTFS_ATTR_RECORD Attribute)
 
static VOID NtfsDumpVolumeNameAttribute (PNTFS_ATTR_RECORD Attribute)
 
static VOID NtfsDumpVolumeInformationAttribute (PNTFS_ATTR_RECORD Attribute)
 
static VOID NtfsDumpIndexRootAttribute (PNTFS_ATTR_RECORD Attribute)
 
static VOID NtfsDumpAttribute (PDEVICE_EXTENSION Vcb, PNTFS_ATTR_RECORD Attribute)
 
VOID NtfsDumpDataRunData (PUCHAR DataRun)
 
VOID NtfsDumpDataRuns (PVOID StartOfRun, ULONGLONG CurrentLCN)
 
VOID NtfsDumpFileAttributes (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)
 
PSTANDARD_INFORMATION GetStandardInformationFromRecord (PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER FileRecord)
 
GetFileNameAttributeLength

@implemented

Returns the size of a given FILENAME_ATTRIBUTE, in bytes.

Parameters
FileNameAttributePointer to a FILENAME_ATTRIBUTE to determine the size of.
Remarks
The length of a FILENAME_ATTRIBUTE is variable and is dependent on the length of the file name stored at the end. This function operates on the FILENAME_ATTRIBUTE proper, so don't try to pass it a PNTFS_ATTR_RECORD.
ULONG GetFileNameAttributeLength (PFILENAME_ATTRIBUTE FileNameAttribute)
 
PFILENAME_ATTRIBUTE GetBestFileNameFromRecord (PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER FileRecord)
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 34 of file attrib.c.

Function Documentation

◆ AddBitmap()

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

Definition at line 72 of file attrib.c.

77{
78 ULONG AttributeLength;
79 // Calculate the header length
80 ULONG ResidentHeaderLength = FIELD_OFFSET(NTFS_ATTR_RECORD, Resident.Reserved) + sizeof(UCHAR);
81 ULONG FileRecordEnd = AttributeAddress->Length;
82 ULONG NameOffset;
83 ULONG ValueOffset;
84 // We'll start out with 8 bytes of bitmap data
86 ULONG BytesAvailable;
87
88 if (AttributeAddress->Type != AttributeEnd)
89 {
90 DPRINT1("FIXME: Can only add $BITMAP attribute to the end of a file record.\n");
92 }
93
94 NameOffset = ResidentHeaderLength;
95
96 // Calculate ValueOffset, which will be aligned to a 4-byte boundary
97 ValueOffset = ALIGN_UP_BY(NameOffset + (sizeof(WCHAR) * NameLength), VALUE_OFFSET_ALIGNMENT);
98
99 // Calculate length of attribute
100 AttributeLength = ValueOffset + ValueLength;
101 AttributeLength = ALIGN_UP_BY(AttributeLength, ATTR_RECORD_ALIGNMENT);
102
103 // Make sure the file record is large enough for the new attribute
104 BytesAvailable = Vcb->NtfsInfo.BytesPerFileRecord - FileRecord->BytesInUse;
105 if (BytesAvailable < AttributeLength)
106 {
107 DPRINT1("FIXME: Not enough room in file record for index allocation attribute!\n");
109 }
110
111 // Set Attribute fields
112 RtlZeroMemory(AttributeAddress, AttributeLength);
113
114 AttributeAddress->Type = AttributeBitmap;
115 AttributeAddress->Length = AttributeLength;
116 AttributeAddress->NameLength = NameLength;
117 AttributeAddress->NameOffset = NameOffset;
118 AttributeAddress->Instance = FileRecord->NextAttributeNumber++;
119
120 AttributeAddress->Resident.ValueLength = ValueLength;
121 AttributeAddress->Resident.ValueOffset = ValueOffset;
122
123 // Set the name
124 RtlCopyMemory((PCHAR)((ULONG_PTR)AttributeAddress + NameOffset), Name, NameLength * sizeof(WCHAR));
125
126 // move the attribute-end and file-record-end markers to the end of the file record
127 AttributeAddress = (PNTFS_ATTR_RECORD)((ULONG_PTR)AttributeAddress + AttributeAddress->Length);
128 SetFileRecordEnd(FileRecord, AttributeAddress, FileRecordEnd);
129
130 return STATUS_SUCCESS;
131}
#define ALIGN_UP_BY(size, align)
#define DPRINT1
Definition: precomp.h:8
struct NTFS_ATTR_RECORD * PNTFS_ATTR_RECORD
#define VALUE_OFFSET_ALIGNMENT
Definition: ntfs.h:326
@ AttributeEnd
Definition: ntfs.h:177
@ AttributeBitmap
Definition: ntfs.h:171
#define ATTR_RECORD_ALIGNMENT
Definition: ntfs.h:320
VOID SetFileRecordEnd(PFILE_RECORD_HEADER FileRecord, PNTFS_ATTR_RECORD AttrEnd, ULONG EndMarker)
Definition: mft.c:706
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
#define Vcb
Definition: cdprocs.h:1415
#define STATUS_SUCCESS
Definition: shellext.h:65
UCHAR Reserved
Definition: ntfs.h:141
ULONG Length
Definition: ntfs.h:127
USHORT NameOffset
Definition: ntfs.h:130
USHORT Instance
Definition: ntfs.h:132
struct NTFS_ATTR_RECORD::@175::@177 Resident
UCHAR NameLength
Definition: ntfs.h:129
ULONG Type
Definition: ntfs.h:126
USHORT NextAttributeNumber
Definition: ntfs.h:260
ULONG BytesInUse
Definition: ntfs.h:257
#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
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180

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

◆ AddData()

NTSTATUS AddData ( PFILE_RECORD_HEADER  FileRecord,
PNTFS_ATTR_RECORD  AttributeAddress 
)

Definition at line 160 of file attrib.c.

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

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 230 of file attrib.c.

236{
237 ULONG ResidentHeaderLength = FIELD_OFFSET(NTFS_ATTR_RECORD, Resident.Reserved) + sizeof(UCHAR);
238 PFILENAME_ATTRIBUTE FileNameAttribute;
239 LARGE_INTEGER SystemTime;
240 ULONG FileRecordEnd = AttributeAddress->Length;
241 ULONGLONG CurrentMFTIndex = NTFS_FILE_ROOT;
242 UNICODE_STRING Current, Remaining, FilenameNoPath;
244 ULONG FirstEntry;
245
246 if (AttributeAddress->Type != AttributeEnd)
247 {
248 DPRINT1("FIXME: Can only add $FILE_NAME attribute to the end of a file record.\n");
250 }
251
252 AttributeAddress->Type = AttributeFileName;
253 AttributeAddress->Instance = FileRecord->NextAttributeNumber++;
254
255 FileNameAttribute = (PFILENAME_ATTRIBUTE)((LONG_PTR)AttributeAddress + ResidentHeaderLength);
256
257 // set timestamps
258 KeQuerySystemTime(&SystemTime);
259 FileNameAttribute->CreationTime = SystemTime.QuadPart;
260 FileNameAttribute->ChangeTime = SystemTime.QuadPart;
261 FileNameAttribute->LastWriteTime = SystemTime.QuadPart;
262 FileNameAttribute->LastAccessTime = SystemTime.QuadPart;
263
264 // Is this a directory?
265 if(FileRecord->Flags & FRH_DIRECTORY)
266 FileNameAttribute->FileAttributes = NTFS_FILE_TYPE_DIRECTORY;
267 else
268 FileNameAttribute->FileAttributes = NTFS_FILE_TYPE_ARCHIVE;
269
270 // we need to extract the filename from the path
271 DPRINT1("Pathname: %wZ\n", &FileObject->FileName);
272
273 FsRtlDissectName(FileObject->FileName, &Current, &Remaining);
274
275 FilenameNoPath.Buffer = Current.Buffer;
276 FilenameNoPath.MaximumLength = FilenameNoPath.Length = Current.Length;
277
278 while (Current.Length != 0)
279 {
280 DPRINT1("Current: %wZ\n", &Current);
281
282 if (Remaining.Length != 0)
283 {
284 FilenameNoPath.Buffer = Remaining.Buffer;
285 FilenameNoPath.Length = FilenameNoPath.MaximumLength = Remaining.Length;
286 }
287
288 FirstEntry = 0;
289 Status = NtfsFindMftRecord(DeviceExt,
290 CurrentMFTIndex,
291 &Current,
292 &FirstEntry,
293 FALSE,
294 CaseSensitive,
295 &CurrentMFTIndex);
296 if (!NT_SUCCESS(Status))
297 break;
298
299 if (Remaining.Length == 0 )
300 {
301 if (Current.Length != 0)
302 {
303 FilenameNoPath.Buffer = Current.Buffer;
304 FilenameNoPath.Length = FilenameNoPath.MaximumLength = Current.Length;
305 }
306 break;
307 }
308
309 FsRtlDissectName(Remaining, &Current, &Remaining);
310 }
311
312 DPRINT1("MFT Index of parent: %I64u\n", CurrentMFTIndex);
313
314 // set reference to parent directory
315 FileNameAttribute->DirectoryFileReferenceNumber = CurrentMFTIndex;
316 *ParentMftIndex = CurrentMFTIndex;
317
318 DPRINT1("SequenceNumber: 0x%02x\n", FileRecord->SequenceNumber);
319
320 // The highest 2 bytes should be the sequence number, unless the parent happens to be root
321 if (CurrentMFTIndex == NTFS_FILE_ROOT)
322 FileNameAttribute->DirectoryFileReferenceNumber |= (ULONGLONG)NTFS_FILE_ROOT << 48;
323 else
324 FileNameAttribute->DirectoryFileReferenceNumber |= (ULONGLONG)FileRecord->SequenceNumber << 48;
325
326 DPRINT1("FileNameAttribute->DirectoryFileReferenceNumber: 0x%016I64x\n", FileNameAttribute->DirectoryFileReferenceNumber);
327
328 FileNameAttribute->NameLength = FilenameNoPath.Length / sizeof(WCHAR);
329 RtlCopyMemory(FileNameAttribute->Name, FilenameNoPath.Buffer, FilenameNoPath.Length);
330
331 // For now, we're emulating the way Windows behaves when 8.3 name generation is disabled
332 // TODO: add DOS Filename as needed
333 if (!CaseSensitive && RtlIsNameLegalDOS8Dot3(&FilenameNoPath, NULL, NULL))
334 FileNameAttribute->NameType = NTFS_FILE_NAME_WIN32_AND_DOS;
335 else
336 FileNameAttribute->NameType = NTFS_FILE_NAME_POSIX;
337
338 FileRecord->LinkCount++;
339
340 AttributeAddress->Length = ResidentHeaderLength +
341 FIELD_OFFSET(FILENAME_ATTRIBUTE, Name) + FilenameNoPath.Length;
342 AttributeAddress->Length = ALIGN_UP_BY(AttributeAddress->Length, ATTR_RECORD_ALIGNMENT);
343
344 AttributeAddress->Resident.ValueLength = FIELD_OFFSET(FILENAME_ATTRIBUTE, Name) + FilenameNoPath.Length;
345 AttributeAddress->Resident.ValueOffset = ResidentHeaderLength;
346 AttributeAddress->Resident.Flags = RA_INDEXED;
347
348 // move the attribute-end and file-record-end markers to the end of the file record
349 AttributeAddress = (PNTFS_ATTR_RECORD)((ULONG_PTR)AttributeAddress + AttributeAddress->Length);
350 SetFileRecordEnd(FileRecord, AttributeAddress, FileRecordEnd);
351
352 return Status;
353}
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(PNTFS_VOLUME_INFO Volume, ULONGLONG MFTIndex, PCHAR FileName, ULONGLONG *OutMFTIndex)
Definition: ntfs.c:545
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
struct FILENAME_ATTRIBUTE * PFILENAME_ATTRIBUTE
#define FRH_DIRECTORY
Definition: ntfs.h:268
#define NTFS_FILE_TYPE_DIRECTORY
Definition: ntfs.h:232
@ AttributeFileName
Definition: ntfs.h:163
#define NTFS_FILE_TYPE_ARCHIVE
Definition: ntfs.h:225
#define RA_INDEXED
Definition: ntfs.h:235
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
Status
Definition: gdiplustypes.h:25
BOOLEAN NTAPI RtlIsNameLegalDOS8Dot3(_In_ PUNICODE_STRING Name, _Inout_opt_ POEM_STRING OemName, _Inout_opt_ PBOOLEAN NameContainsSpaces)
__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:398
ULONGLONG LastWriteTime
Definition: ntfs.h:363
UCHAR NameLength
Definition: ntfs.h:377
ULONGLONG DirectoryFileReferenceNumber
Definition: ntfs.h:360
UCHAR NameType
Definition: ntfs.h:378
ULONG FileAttributes
Definition: ntfs.h:367
ULONGLONG LastAccessTime
Definition: ntfs.h:364
ULONGLONG CreationTime
Definition: ntfs.h:361
WCHAR Name[1]
Definition: ntfs.h:379
ULONGLONG ChangeTime
Definition: ntfs.h:362
USHORT SequenceNumber
Definition: ntfs.h:253
USHORT Flags
Definition: ntfs.h:256
USHORT LinkCount
Definition: ntfs.h:254
USHORT MaximumLength
Definition: env_spec_w32.h:370
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().

◆ AddIndexAllocation()

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

Definition at line 388 of file attrib.c.

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

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

Referenced by NtfsCreateDirectory().

◆ AddRun()

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

Definition at line 599 of file attrib.c.

605{
607 int DataRunMaxLength;
608 PNTFS_ATTR_RECORD DestinationAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + AttrOffset);
609 ULONG NextAttributeOffset = AttrOffset + AttrContext->pRecord->Length;
610 ULONGLONG NextVBN = 0;
611
612 PUCHAR RunBuffer;
613 ULONG RunBufferSize;
614
615 if (!AttrContext->pRecord->IsNonResident)
617
618 if (AttrContext->pRecord->NonResident.AllocatedSize != 0)
619 NextVBN = AttrContext->pRecord->NonResident.HighestVCN + 1;
620
621 // Add newly-assigned clusters to mcb
623 {
624 if (!FsRtlAddLargeMcbEntry(&AttrContext->DataRunsMCB,
625 NextVBN,
626 NextAssignedCluster,
627 RunLength))
628 {
630 }
631 }
633 {
634 DPRINT1("Failed to add LargeMcb Entry!\n");
636 }
637 _SEH2_END;
638
639 RunBuffer = ExAllocatePoolWithTag(NonPagedPool, Vcb->NtfsInfo.BytesPerFileRecord, TAG_NTFS);
640 if (!RunBuffer)
641 {
642 DPRINT1("ERROR: Couldn't allocate memory for data runs!\n");
644 }
645
646 // Convert the map control block back to encoded data runs
647 ConvertLargeMCBToDataRuns(&AttrContext->DataRunsMCB, RunBuffer, Vcb->NtfsInfo.BytesPerCluster, &RunBufferSize);
648
649 // Get the amount of free space between the start of the of the first data run and the attribute end
650 DataRunMaxLength = AttrContext->pRecord->Length - AttrContext->pRecord->NonResident.MappingPairsOffset;
651
652 // Do we need to extend the attribute (or convert to attribute list)?
653 if (DataRunMaxLength < RunBufferSize)
654 {
655 PNTFS_ATTR_RECORD NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + NextAttributeOffset);
656 PNTFS_ATTR_RECORD NewRecord;
657
658 // Add free space at the end of the file record to DataRunMaxLength
659 DataRunMaxLength += Vcb->NtfsInfo.BytesPerFileRecord - FileRecord->BytesInUse;
660
661 // Can we resize the attribute?
662 if (DataRunMaxLength < RunBufferSize)
663 {
664 DPRINT1("FIXME: Need to create attribute list! Max Data Run Length available: %d, RunBufferSize: %d\n", DataRunMaxLength, RunBufferSize);
665 ExFreePoolWithTag(RunBuffer, TAG_NTFS);
667 }
668
669 // Are there more attributes after the one we're resizing?
670 if (NextAttribute->Type != AttributeEnd)
671 {
672 PNTFS_ATTR_RECORD FinalAttribute;
673
674 // Calculate where to move the trailing attributes
675 ULONG_PTR MoveTo = (ULONG_PTR)DestinationAttribute + AttrContext->pRecord->NonResident.MappingPairsOffset + RunBufferSize;
676 MoveTo = ALIGN_UP_BY(MoveTo, ATTR_RECORD_ALIGNMENT);
677
678 DPRINT1("Moving attribute(s) after this one starting with type 0x%lx\n", NextAttribute->Type);
679
680 // Move the trailing attributes; FinalAttribute will point to the end marker
681 FinalAttribute = MoveAttributes(Vcb, NextAttribute, NextAttributeOffset, MoveTo);
682
683 // set the file record end
684 SetFileRecordEnd(FileRecord, FinalAttribute, FILE_RECORD_END);
685 }
686
687 // calculate position of end markers
688 NextAttributeOffset = AttrOffset + AttrContext->pRecord->NonResident.MappingPairsOffset + RunBufferSize;
689 NextAttributeOffset = ALIGN_UP_BY(NextAttributeOffset, ATTR_RECORD_ALIGNMENT);
690
691 // Update the length of the destination attribute
692 DestinationAttribute->Length = NextAttributeOffset - AttrOffset;
693
694 // Create a new copy of the attribute record
695 NewRecord = ExAllocatePoolWithTag(NonPagedPool, DestinationAttribute->Length, TAG_NTFS);
696 RtlCopyMemory(NewRecord, AttrContext->pRecord, AttrContext->pRecord->Length);
697 NewRecord->Length = DestinationAttribute->Length;
698
699 // Free the old copy of the attribute record, which won't be large enough
700 ExFreePoolWithTag(AttrContext->pRecord, TAG_NTFS);
701
702 // Set the attribute context's record to the new copy
703 AttrContext->pRecord = NewRecord;
704
705 // if NextAttribute is the AttributeEnd marker
706 if (NextAttribute->Type == AttributeEnd)
707 {
708 // End the file record
709 NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + NextAttributeOffset);
710 SetFileRecordEnd(FileRecord, NextAttribute, FILE_RECORD_END);
711 }
712 }
713
714 // Update HighestVCN
715 DestinationAttribute->NonResident.HighestVCN =
716 AttrContext->pRecord->NonResident.HighestVCN = max(NextVBN - 1 + RunLength,
717 AttrContext->pRecord->NonResident.HighestVCN);
718
719 // Write data runs to destination attribute
720 RtlCopyMemory((PVOID)((ULONG_PTR)DestinationAttribute + DestinationAttribute->NonResident.MappingPairsOffset),
721 RunBuffer,
722 RunBufferSize);
723
724 // Update the attribute record in the attribute context
725 RtlCopyMemory((PVOID)((ULONG_PTR)AttrContext->pRecord + AttrContext->pRecord->NonResident.MappingPairsOffset),
726 RunBuffer,
727 RunBufferSize);
728
729 // Update the file record
730 Status = UpdateFileRecord(Vcb, AttrContext->FileMFTIndex, FileRecord);
731
732 ExFreePoolWithTag(RunBuffer, TAG_NTFS);
733
734 NtfsDumpDataRuns((PUCHAR)((ULONG_PTR)DestinationAttribute + DestinationAttribute->NonResident.MappingPairsOffset), 0);
735
736 return Status;
737}
VOID NtfsDumpDataRuns(PVOID StartOfRun, ULONGLONG CurrentLCN)
Definition: attrib.c:1755
NTSTATUS ConvertLargeMCBToDataRuns(PLARGE_MCB DataRunsMCB, PUCHAR RunBuffer, ULONG MaxBufferSize, PULONG UsedBufferSize)
Definition: attrib.c:896
#define FILE_RECORD_END
Definition: ntfs.h:182
#define TAG_NTFS
Definition: ntfs.h:12
#define ULONG_PTR
Definition: config.h:101
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define NonPagedPool
Definition: env_spec_w32.h:307
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
BOOLEAN NTAPI FsRtlAddLargeMcbEntry(IN PLARGE_MCB Mcb, IN LONGLONG Vbn, IN LONGLONG Lbn, IN LONGLONG SectorCount)
Definition: largemcb.c:288
NTSTATUS UpdateFileRecord(PDEVICE_EXTENSION Vcb, ULONGLONG MftIndex, PFILE_RECORD_HEADER FileRecord)
Definition: mft.c:1931
PNTFS_ATTR_RECORD MoveAttributes(PDEVICE_EXTENSION DeviceExt, PNTFS_ATTR_RECORD FirstAttributeToMove, ULONG FirstAttributeOffset, ULONG_PTR MoveTo)
Definition: mft.c:512
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
#define ExRaiseStatus
Definition: ntoskrnl.h:114
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:159
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:162
#define max(a, b)
Definition: svc.c:63
unsigned char * PUCHAR
Definition: typedefs.h:53
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158

Referenced by SetNonResidentAttributeDataLength().

◆ AddStandardInformation()

NTSTATUS AddStandardInformation ( PFILE_RECORD_HEADER  FileRecord,
PNTFS_ATTR_RECORD  AttributeAddress 
)

Definition at line 766 of file attrib.c.

768{
769 ULONG ResidentHeaderLength = FIELD_OFFSET(NTFS_ATTR_RECORD, Resident.Reserved) + sizeof(UCHAR);
770 PSTANDARD_INFORMATION StandardInfo = (PSTANDARD_INFORMATION)((LONG_PTR)AttributeAddress + ResidentHeaderLength);
771 LARGE_INTEGER SystemTime;
772 ULONG FileRecordEnd = AttributeAddress->Length;
773
774 if (AttributeAddress->Type != AttributeEnd)
775 {
776 DPRINT1("FIXME: Can only add $STANDARD_INFORMATION attribute to the end of a file record.\n");
778 }
779
780 AttributeAddress->Type = AttributeStandardInformation;
781 AttributeAddress->Length = sizeof(STANDARD_INFORMATION) + ResidentHeaderLength;
782 AttributeAddress->Length = ALIGN_UP_BY(AttributeAddress->Length, ATTR_RECORD_ALIGNMENT);
783 AttributeAddress->Resident.ValueLength = sizeof(STANDARD_INFORMATION);
784 AttributeAddress->Resident.ValueOffset = ResidentHeaderLength;
785 AttributeAddress->Instance = FileRecord->NextAttributeNumber++;
786
787 // set dates and times
788 KeQuerySystemTime(&SystemTime);
789 StandardInfo->CreationTime = SystemTime.QuadPart;
790 StandardInfo->ChangeTime = SystemTime.QuadPart;
791 StandardInfo->LastWriteTime = SystemTime.QuadPart;
792 StandardInfo->LastAccessTime = SystemTime.QuadPart;
794
795 // move the attribute-end and file-record-end markers to the end of the file record
796 AttributeAddress = (PNTFS_ATTR_RECORD)((ULONG_PTR)AttributeAddress + AttributeAddress->Length);
797 SetFileRecordEnd(FileRecord, AttributeAddress, FileRecordEnd);
798
799 return STATUS_SUCCESS;
800}
struct STANDARD_INFORMATION * PSTANDARD_INFORMATION
@ AttributeStandardInformation
Definition: ntfs.h:161
ULONGLONG LastAccessTime
Definition: ntfs.h:333
ULONGLONG ChangeTime
Definition: ntfs.h:331
ULONGLONG LastWriteTime
Definition: ntfs.h:332
ULONG FileAttribute
Definition: ntfs.h:334
ULONGLONG CreationTime
Definition: ntfs.h:330

Referenced by NtfsCreateDirectory(), and NtfsCreateFileRecord().

◆ ConvertDataRunsToLargeMCB()

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

Definition at line 825 of file attrib.c.

828{
829 LONGLONG DataRunOffset;
830 ULONGLONG DataRunLength;
831 LONGLONG DataRunStartLCN;
832 ULONGLONG LastLCN = 0;
833
834 // Initialize the MCB, potentially catch an exception
835 _SEH2_TRY{
839 } _SEH2_END;
840
841 while (*DataRun != 0)
842 {
843 DataRun = DecodeRun(DataRun, &DataRunOffset, &DataRunLength);
844
845 if (DataRunOffset != -1)
846 {
847 // Normal data run.
848 DataRunStartLCN = LastLCN + DataRunOffset;
849 LastLCN = DataRunStartLCN;
850
851 _SEH2_TRY{
852 if (!FsRtlAddLargeMcbEntry(DataRunsMCB,
853 *pNextVBN,
854 DataRunStartLCN,
855 DataRunLength))
856 {
858 }
860 FsRtlUninitializeLargeMcb(DataRunsMCB);
862 } _SEH2_END;
863
864 }
865
866 *pNextVBN += DataRunLength;
867 }
868
869 return STATUS_SUCCESS;
870}
PUCHAR DecodeRun(PUCHAR DataRun, LONGLONG *DataRunOffset, ULONGLONG *DataRunLength)
Definition: attrib.c:966
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,
PUCHAR  RunBuffer,
ULONG  MaxBufferSize,
PULONG  UsedBufferSize 
)

Definition at line 896 of file attrib.c.

900{
902 ULONG RunBufferOffset = 0;
903 LONGLONG DataRunOffset;
904 ULONGLONG LastLCN = 0;
906 ULONG i;
907
908
909 DPRINT("\t[Vbn, Lbn, Count]\n");
910
911 // convert each mcb entry to a data run
912 for (i = 0; FsRtlGetNextLargeMcbEntry(DataRunsMCB, i, &Vbn, &Lbn, &Count); i++)
913 {
914 UCHAR DataRunOffsetSize = 0;
915 UCHAR DataRunLengthSize = 0;
916 UCHAR ControlByte = 0;
917
918 // [vbn, lbn, count]
919 DPRINT("\t[%I64d, %I64d,%I64d]\n", Vbn, Lbn, Count);
920
921 // TODO: check for holes and convert to sparse runs
922 DataRunOffset = Lbn - LastLCN;
923 LastLCN = Lbn;
924
925 // now we need to determine how to represent DataRunOffset with the minimum number of bytes
926 DPRINT("Determining how many bytes needed to represent %I64x\n", DataRunOffset);
927 DataRunOffsetSize = GetPackedByteCount(DataRunOffset, TRUE);
928 DPRINT("%d bytes needed.\n", DataRunOffsetSize);
929
930 // determine how to represent DataRunLengthSize with the minimum number of bytes
931 DPRINT("Determining how many bytes needed to represent %I64x\n", Count);
932 DataRunLengthSize = GetPackedByteCount(Count, TRUE);
933 DPRINT("%d bytes needed.\n", DataRunLengthSize);
934
935 // ensure the next data run + end marker would be <= Max buffer size
936 if (RunBufferOffset + 2 + DataRunLengthSize + DataRunOffsetSize > MaxBufferSize)
937 {
939 DPRINT1("FIXME: Ran out of room in buffer for data runs!\n");
940 break;
941 }
942
943 // pack and copy the control byte
944 ControlByte = (DataRunOffsetSize << 4) + DataRunLengthSize;
945 RunBuffer[RunBufferOffset++] = ControlByte;
946
947 // copy DataRunLength
948 RtlCopyMemory(RunBuffer + RunBufferOffset, &Count, DataRunLengthSize);
949 RunBufferOffset += DataRunLengthSize;
950
951 // copy DataRunOffset
952 RtlCopyMemory(RunBuffer + RunBufferOffset, &DataRunOffset, DataRunOffsetSize);
953 RunBufferOffset += DataRunOffsetSize;
954 }
955
956 // End of data runs
957 RunBuffer[RunBufferOffset++] = 0;
958
959 *UsedBufferSize = RunBufferOffset;
960 DPRINT("New Size of DataRuns: %ld\n", *UsedBufferSize);
961
962 return Status;
963}
UCHAR GetPackedByteCount(LONGLONG NumberToPack, BOOLEAN IsSigned)
Definition: attrib.c:1846
_In_ LONGLONG Vbn
Definition: fsrtlfuncs.h:470
_Must_inspect_result_ _In_ LONGLONG _In_ LONGLONG Lbn
Definition: fsrtlfuncs.h:480
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
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
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define DPRINT
Definition: sndvol32.h:71

Referenced by AddRun(), FreeClusters(), ReadAttribute(), and WriteAttribute().

◆ DecodeRun()

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

Definition at line 966 of file attrib.c.

969{
970 UCHAR DataRunOffsetSize;
971 UCHAR DataRunLengthSize;
972 CHAR i;
973
974 DataRunOffsetSize = (*DataRun >> 4) & 0xF;
975 DataRunLengthSize = *DataRun & 0xF;
976 *DataRunOffset = 0;
977 *DataRunLength = 0;
978 DataRun++;
979 for (i = 0; i < DataRunLengthSize; i++)
980 {
981 *DataRunLength += ((ULONG64)*DataRun) << (i * 8);
982 DataRun++;
983 }
984
985 /* NTFS 3+ sparse files */
986 if (DataRunOffsetSize == 0)
987 {
988 *DataRunOffset = -1;
989 }
990 else
991 {
992 for (i = 0; i < DataRunOffsetSize - 1; i++)
993 {
994 *DataRunOffset += ((ULONG64)*DataRun) << (i * 8);
995 DataRun++;
996 }
997 /* The last byte contains sign so we must process it different way. */
998 *DataRunOffset = ((LONG64)(CHAR)(*(DataRun++)) << (i * 8)) + *DataRunOffset;
999 }
1000
1001 DPRINT("DataRunOffsetSize: %x\n", DataRunOffsetSize);
1002 DPRINT("DataRunLengthSize: %x\n", DataRunLengthSize);
1003 DPRINT("DataRunOffset: %x\n", *DataRunOffset);
1004 DPRINT("DataRunLength: %x\n", *DataRunLength);
1005
1006 return DataRun;
1007}
unsigned __int64 ULONG64
Definition: imports.h:198
int64_t LONG64
Definition: typedefs.h:68
char CHAR
Definition: xmlstorage.h:175

Referenced by ConvertDataRunsToLargeMCB(), FindRun(), GetLastClusterInDataRun(), NtfsDumpDataRuns(), PrepareAttributeContext(), ReadAttribute(), and WriteAttribute().

◆ FindCloseAttribute()

VOID FindCloseAttribute ( PFIND_ATTR_CONTXT  Context)

Definition at line 1465 of file attrib.c.

1466{
1467 if (Context->NonResidentStart != NULL)
1468 {
1469 ExFreePoolWithTag(Context->NonResidentStart, TAG_NTFS);
1470 Context->NonResidentStart = NULL;
1471 }
1472}

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 1383 of file attrib.c.

1388{
1390
1391 DPRINT("FindFistAttribute(%p, %p, %p, %p, %u, %p)\n", Context, Vcb, FileRecord, OnlyResident, Attribute);
1392
1393 Context->Vcb = Vcb;
1394 Context->OnlyResident = OnlyResident;
1395 Context->FirstAttr = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + FileRecord->AttributeOffset);
1396 Context->CurrAttr = Context->FirstAttr;
1397 Context->LastAttr = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + FileRecord->BytesInUse);
1398 Context->NonResidentStart = NULL;
1399 Context->NonResidentEnd = NULL;
1400 Context->Offset = FileRecord->AttributeOffset;
1401
1402 if (Context->FirstAttr->Type == AttributeEnd)
1403 {
1404 Context->CurrAttr = (PVOID)-1;
1405 return STATUS_END_OF_FILE;
1406 }
1407 else if (Context->FirstAttr->Type == AttributeAttributeList)
1408 {
1410 if (!NT_SUCCESS(Status))
1411 {
1412 return Status;
1413 }
1414
1415 *Attribute = InternalGetNextAttribute(Context);
1416 if (*Attribute == NULL)
1417 {
1418 return STATUS_END_OF_FILE;
1419 }
1420 }
1421 else
1422 {
1423 *Attribute = Context->CurrAttr;
1424 Context->Offset = (UCHAR*)Context->CurrAttr - (UCHAR*)FileRecord;
1425 }
1426
1427 return STATUS_SUCCESS;
1428}
static NTSTATUS InternalReadNonResidentAttributes(PFIND_ATTR_CONTXT Context)
Definition: attrib.c:1214
static PNTFS_ATTR_RECORD InternalGetNextAttribute(PFIND_ATTR_CONTXT Context)
Definition: attrib.c:1334
@ AttributeAttributeList
Definition: ntfs.h:162
#define STATUS_END_OF_FILE
Definition: shellext.h:67
USHORT AttributeOffset
Definition: ntfs.h:255
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 1307 of file attrib.c.

1309{
1310 if (Context->NonResidentStart == NULL || Context->NonResidentStart->Type == AttributeEnd)
1311 {
1312 return STATUS_UNSUCCESSFUL;
1313 }
1314
1315 Context->NonResidentCur = Context->NonResidentStart;
1316 *Item = Context->NonResidentCur;
1317 return STATUS_SUCCESS;
1318}
_In_ WDFCOLLECTION _In_ WDFOBJECT Item

Referenced by FindAttribute().

◆ FindNextAttribute()

NTSTATUS FindNextAttribute ( PFIND_ATTR_CONTXT  Context,
PNTFS_ATTR_RECORD Attribute 
)

Definition at line 1431 of file attrib.c.

1433{
1435
1436 DPRINT("FindNextAttribute(%p, %p)\n", Context, Attribute);
1437
1438 *Attribute = InternalGetNextAttribute(Context);
1439 if (*Attribute == NULL)
1440 {
1441 return STATUS_END_OF_FILE;
1442 }
1443
1444 if (Context->CurrAttr->Type != AttributeAttributeList)
1445 {
1446 return STATUS_SUCCESS;
1447 }
1448
1450 if (!NT_SUCCESS(Status))
1451 {
1452 return Status;
1453 }
1454
1455 *Attribute = InternalGetNextAttribute(Context);
1456 if (*Attribute == NULL)
1457 {
1458 return STATUS_END_OF_FILE;
1459 }
1460
1461 return STATUS_SUCCESS;
1462}

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 1321 of file attrib.c.

1323{
1325 if (*Item == NULL)
1326 {
1327 return STATUS_UNSUCCESSFUL;
1328 }
1329 return STATUS_SUCCESS;
1330}
static PNTFS_ATTRIBUTE_LIST_ITEM InternalGetNextAttributeListItem(PFIND_ATTR_CONTXT Context)
Definition: attrib.c:1267

Referenced by FindAttribute().

◆ FindRun()

BOOLEAN FindRun ( PNTFS_ATTR_RECORD  NresAttr,
ULONGLONG  vcn,
PULONGLONG  lcn,
PULONGLONG  count 
)

Definition at line 1010 of file attrib.c.

1014{
1015 if (vcn < NresAttr->NonResident.LowestVCN || vcn > NresAttr->NonResident.HighestVCN)
1016 return FALSE;
1017
1018 DecodeRun((PUCHAR)((ULONG_PTR)NresAttr + NresAttr->NonResident.MappingPairsOffset), (PLONGLONG)lcn, count);
1019
1020 return TRUE;
1021}
GLuint GLuint GLsizei count
Definition: gl.h:1545
__GNU_EXTENSION typedef __int64 * PLONGLONG
Definition: ntbasedef.h:382

Referenced by NtfsDumpAttribute().

◆ FreeClusters()

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

Definition at line 1057 of file attrib.c.

1062{
1064 ULONG ClustersLeftToFree = ClustersToFree;
1065
1066 PNTFS_ATTR_RECORD DestinationAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + AttrOffset);
1067 ULONG NextAttributeOffset = AttrOffset + AttrContext->pRecord->Length;
1068 PNTFS_ATTR_RECORD NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + NextAttributeOffset);
1069
1070 PUCHAR RunBuffer;
1071 ULONG RunBufferSize = 0;
1072
1073 PFILE_RECORD_HEADER BitmapRecord;
1074 PNTFS_ATTR_CONTEXT DataContext;
1075 ULONGLONG BitmapDataSize;
1078 ULONG LengthWritten;
1079
1080 if (!AttrContext->pRecord->IsNonResident)
1081 {
1083 }
1084
1085 // Read the $Bitmap file
1086 BitmapRecord = ExAllocateFromNPagedLookasideList(&Vcb->FileRecLookasideList);
1087 if (BitmapRecord == NULL)
1088 {
1089 DPRINT1("Error: Unable to allocate memory for bitmap file record!\n");
1090 return STATUS_NO_MEMORY;
1091 }
1092
1093 Status = ReadFileRecord(Vcb, NTFS_FILE_BITMAP, BitmapRecord);
1094 if (!NT_SUCCESS(Status))
1095 {
1096 DPRINT1("Error: Unable to read file record for bitmap!\n");
1097 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, BitmapRecord);
1098 return 0;
1099 }
1100
1101 Status = FindAttribute(Vcb, BitmapRecord, AttributeData, L"", 0, &DataContext, NULL);
1102 if (!NT_SUCCESS(Status))
1103 {
1104 DPRINT1("Error: Unable to find data attribute for bitmap file!\n");
1105 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, BitmapRecord);
1106 return 0;
1107 }
1108
1109 BitmapDataSize = AttributeDataLength(DataContext->pRecord);
1110 BitmapDataSize = min(BitmapDataSize, ULONG_MAX);
1111 ASSERT((BitmapDataSize * 8) >= Vcb->NtfsInfo.ClusterCount);
1112 BitmapData = ExAllocatePoolWithTag(NonPagedPool, ROUND_UP(BitmapDataSize, Vcb->NtfsInfo.BytesPerSector), TAG_NTFS);
1113 if (BitmapData == NULL)
1114 {
1115 DPRINT1("Error: Unable to allocate memory for bitmap file data!\n");
1116 ReleaseAttributeContext(DataContext);
1117 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, BitmapRecord);
1118 return 0;
1119 }
1120
1121 ReadAttribute(Vcb, DataContext, 0, (PCHAR)BitmapData, (ULONG)BitmapDataSize);
1122
1123 RtlInitializeBitMap(&Bitmap, (PULONG)BitmapData, Vcb->NtfsInfo.ClusterCount);
1124
1125 // free clusters in $BITMAP file
1126 while (ClustersLeftToFree > 0)
1127 {
1129
1130 if (!FsRtlLookupLastLargeMcbEntry(&AttrContext->DataRunsMCB, &LargeVbn, &LargeLbn))
1131 {
1133 DPRINT1("DRIVER ERROR: FreeClusters called to free %lu clusters, which is %lu more clusters than are assigned to attribute!",
1134 ClustersToFree,
1135 ClustersLeftToFree);
1136 break;
1137 }
1138
1139 if (LargeLbn != -1)
1140 {
1141 // deallocate this cluster
1143 }
1144 FsRtlTruncateLargeMcb(&AttrContext->DataRunsMCB, AttrContext->pRecord->NonResident.HighestVCN);
1145
1146 // decrement HighestVCN, but don't let it go below 0
1147 AttrContext->pRecord->NonResident.HighestVCN = min(AttrContext->pRecord->NonResident.HighestVCN, AttrContext->pRecord->NonResident.HighestVCN - 1);
1148 ClustersLeftToFree--;
1149 }
1150
1151 // update $BITMAP file on disk
1152 Status = WriteAttribute(Vcb, DataContext, 0, BitmapData, (ULONG)BitmapDataSize, &LengthWritten, FileRecord);
1153 if (!NT_SUCCESS(Status))
1154 {
1155 ReleaseAttributeContext(DataContext);
1157 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, BitmapRecord);
1158 return Status;
1159 }
1160
1161 ReleaseAttributeContext(DataContext);
1163 ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, BitmapRecord);
1164
1165 // Save updated data runs to file record
1166
1167 // Allocate some memory for a new RunBuffer
1168 RunBuffer = ExAllocatePoolWithTag(NonPagedPool, Vcb->NtfsInfo.BytesPerFileRecord, TAG_NTFS);
1169 if (!RunBuffer)
1170 {
1171 DPRINT1("ERROR: Couldn't allocate memory for data runs!\n");
1173 }
1174
1175 // Convert the map control block back to encoded data runs
1176 ConvertLargeMCBToDataRuns(&AttrContext->DataRunsMCB, RunBuffer, Vcb->NtfsInfo.BytesPerCluster, &RunBufferSize);
1177
1178 // Update HighestVCN
1179 DestinationAttribute->NonResident.HighestVCN = AttrContext->pRecord->NonResident.HighestVCN;
1180
1181 // Write data runs to destination attribute
1182 RtlCopyMemory((PVOID)((ULONG_PTR)DestinationAttribute + DestinationAttribute->NonResident.MappingPairsOffset),
1183 RunBuffer,
1184 RunBufferSize);
1185
1186 // Is DestinationAttribute the last attribute in the file record?
1187 if (NextAttribute->Type == AttributeEnd)
1188 {
1189 // update attribute length
1190 DestinationAttribute->Length = ALIGN_UP_BY(AttrContext->pRecord->NonResident.MappingPairsOffset + RunBufferSize,
1192
1193 ASSERT(DestinationAttribute->Length <= AttrContext->pRecord->Length);
1194
1195 AttrContext->pRecord->Length = DestinationAttribute->Length;
1196
1197 // write end markers
1198 NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)DestinationAttribute + DestinationAttribute->Length);
1199 SetFileRecordEnd(FileRecord, NextAttribute, FILE_RECORD_END);
1200 }
1201
1202 // Update the file record
1203 Status = UpdateFileRecord(Vcb, AttrContext->FileMFTIndex, FileRecord);
1204
1205 ExFreePoolWithTag(RunBuffer, TAG_NTFS);
1206
1207 NtfsDumpDataRuns((PUCHAR)((ULONG_PTR)DestinationAttribute + DestinationAttribute->NonResident.MappingPairsOffset), 0);
1208
1209 return Status;
1210}
#define NTFS_FILE_BITMAP
Definition: ntfs.h:29
#define ROUND_UP(n, align)
Definition: eventvwr.h:34
_Out_ PLONGLONG LargeVbn
Definition: fsrtlfuncs.h:520
_Out_ PLONGLONG _Out_ PLONGLONG LargeLbn
Definition: fsrtlfuncs.h:521
#define ULONG_MAX
Definition: limits.h:44
NTSYSAPI void WINAPI RtlInitializeBitMap(PRTL_BITMAP, PULONG, ULONG)
NTSYSAPI void WINAPI RtlClearBits(PRTL_BITMAP, ULONG, ULONG)
VOID NTAPI FsRtlTruncateLargeMcb(IN PLARGE_MCB Mcb, IN LONGLONG Vbn)
Definition: largemcb.c:1059
BOOLEAN NTAPI FsRtlLookupLastLargeMcbEntry(IN PLARGE_MCB Mcb, OUT PLONGLONG Vbn, OUT PLONGLONG Lbn)
Definition: largemcb.c:718
NTSTATUS ReadFileRecord(PDEVICE_EXTENSION Vcb, ULONGLONG index, PFILE_RECORD_HEADER file)
Definition: mft.c:1631
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:1065
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:1315
#define ASSERT(a)
Definition: mode.c:44
#define min(a, b)
Definition: monoChain.cc:55
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
#define L(x)
Definition: ntvdm.h:50
uint32_t * PULONG
Definition: typedefs.h:59

Referenced by FatExamineFatEntries(), GetDiskFreeSpaceW(), HandleNotify(), NtfsAllocateClusters(), NtfsGetFreeClusters(), and SetNonResidentAttributeDataLength().

◆ GetBestFileNameFromRecord()

PFILENAME_ATTRIBUTE GetBestFileNameFromRecord ( PDEVICE_EXTENSION  Vcb,
PFILE_RECORD_HEADER  FileRecord 
)

Definition at line 1985 of file attrib.c.

1987{
1989
1991 if (FileName == NULL)
1992 {
1994 if (FileName == NULL)
1995 {
1997 }
1998 }
1999
2000 return FileName;
2001}
#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:1809
struct _FileName FileName
Definition: fatprocs.h:896

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

◆ GetFileNameAttributeLength()

ULONG GetFileNameAttributeLength ( PFILENAME_ATTRIBUTE  FileNameAttribute)

Definition at line 1978 of file attrib.c.

1979{
1980 ULONG Length = FIELD_OFFSET(FILENAME_ATTRIBUTE, Name) + (FileNameAttribute->NameLength * sizeof(WCHAR));
1981 return Length;
1982}
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102

Referenced by CreateBTreeKeyFromFilename().

◆ GetFileNameFromRecord()

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

Definition at line 1809 of file attrib.c.

1812{
1814 PNTFS_ATTR_RECORD Attribute;
1817
1818 Status = FindFirstAttribute(&Context, Vcb, FileRecord, FALSE, &Attribute);
1819 while (NT_SUCCESS(Status))
1820 {
1821 if (Attribute->Type == AttributeFileName)
1822 {
1823 Name = (PFILENAME_ATTRIBUTE)((ULONG_PTR)Attribute + Attribute->Resident.ValueOffset);
1824 if (Name->NameType == NameType ||
1827 {
1829 return Name;
1830 }
1831 }
1832
1833 Status = FindNextAttribute(&Context, &Attribute);
1834 }
1835
1837 return NULL;
1838}
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
struct NameRec_ * Name
Definition: cdprocs.h:460
NTSTATUS FindFirstAttribute(PFIND_ATTR_CONTXT Context, PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER FileRecord, BOOLEAN OnlyResident, PNTFS_ATTR_RECORD *Attribute)
Definition: attrib.c:1383
VOID FindCloseAttribute(PFIND_ATTR_CONTXT Context)
Definition: attrib.c:1465
NTSTATUS FindNextAttribute(PFIND_ATTR_CONTXT Context, PNTFS_ATTR_RECORD *Attribute)
Definition: attrib.c:1431

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

◆ GetLastClusterInDataRun()

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

Definition at line 1908 of file attrib.c.

1909{
1910 LONGLONG DataRunOffset;
1911 ULONGLONG DataRunLength;
1912 LONGLONG DataRunStartLCN;
1913
1914 ULONGLONG LastLCN = 0;
1915 PUCHAR DataRun = (PUCHAR)Attribute + Attribute->NonResident.MappingPairsOffset;
1916
1917 if (!Attribute->IsNonResident)
1919
1920 while (1)
1921 {
1922 DataRun = DecodeRun(DataRun, &DataRunOffset, &DataRunLength);
1923
1924 if (DataRunOffset != -1)
1925 {
1926 // Normal data run.
1927 DataRunStartLCN = LastLCN + DataRunOffset;
1928 LastLCN = DataRunStartLCN;
1929 *LastCluster = LastLCN + DataRunLength - 1;
1930 }
1931
1932 if (*DataRun == 0)
1933 break;
1934 }
1935
1936 return STATUS_SUCCESS;
1937}
if(dx< 0)
Definition: linetemp.h:194

◆ 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 1846 of file attrib.c.

1848{
1849 if (!IsSigned)
1850 {
1851 if (NumberToPack >= 0x0100000000000000)
1852 return 8;
1853 if (NumberToPack >= 0x0001000000000000)
1854 return 7;
1855 if (NumberToPack >= 0x0000010000000000)
1856 return 6;
1857 if (NumberToPack >= 0x0000000100000000)
1858 return 5;
1859 if (NumberToPack >= 0x0000000001000000)
1860 return 4;
1861 if (NumberToPack >= 0x0000000000010000)
1862 return 3;
1863 if (NumberToPack >= 0x0000000000000100)
1864 return 2;
1865 return 1;
1866 }
1867
1868 if (NumberToPack > 0)
1869 {
1870 // we have to make sure the number that gets encoded won't be interpreted as negative
1871 if (NumberToPack >= 0x0080000000000000)
1872 return 8;
1873 if (NumberToPack >= 0x0000800000000000)
1874 return 7;
1875 if (NumberToPack >= 0x0000008000000000)
1876 return 6;
1877 if (NumberToPack >= 0x0000000080000000)
1878 return 5;
1879 if (NumberToPack >= 0x0000000000800000)
1880 return 4;
1881 if (NumberToPack >= 0x0000000000008000)
1882 return 3;
1883 if (NumberToPack >= 0x0000000000000080)
1884 return 2;
1885 }
1886 else
1887 {
1888 // negative number
1889 if (NumberToPack <= 0xff80000000000000)
1890 return 8;
1891 if (NumberToPack <= 0xffff800000000000)
1892 return 7;
1893 if (NumberToPack <= 0xffffff8000000000)
1894 return 6;
1895 if (NumberToPack <= 0xffffffff80000000)
1896 return 5;
1897 if (NumberToPack <= 0xffffffffff800000)
1898 return 4;
1899 if (NumberToPack <= 0xffffffffffff8000)
1900 return 3;
1901 if (NumberToPack <= 0xffffffffffffff80)
1902 return 2;
1903 }
1904 return 1;
1905}

Referenced by ConvertLargeMCBToDataRuns().

◆ GetStandardInformationFromRecord()

PSTANDARD_INFORMATION GetStandardInformationFromRecord ( PDEVICE_EXTENSION  Vcb,
PFILE_RECORD_HEADER  FileRecord 
)

Definition at line 1940 of file attrib.c.

1942{
1945 PNTFS_ATTR_RECORD Attribute;
1946 PSTANDARD_INFORMATION StdInfo;
1947
1948 Status = FindFirstAttribute(&Context, Vcb, FileRecord, FALSE, &Attribute);
1949 while (NT_SUCCESS(Status))
1950 {
1951 if (Attribute->Type == AttributeStandardInformation)
1952 {
1953 StdInfo = (PSTANDARD_INFORMATION)((ULONG_PTR)Attribute + Attribute->Resident.ValueOffset);
1955 return StdInfo;
1956 }
1957
1958 Status = FindNextAttribute(&Context, &Attribute);
1959 }
1960
1962 return NULL;
1963}

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

◆ InternalGetNextAttribute()

static PNTFS_ATTR_RECORD InternalGetNextAttribute ( PFIND_ATTR_CONTXT  Context)
static

Definition at line 1334 of file attrib.c.

1335{
1336 PNTFS_ATTR_RECORD NextAttribute;
1337
1338 if (Context->CurrAttr == (PVOID)-1)
1339 {
1340 return NULL;
1341 }
1342
1343 if (Context->CurrAttr >= Context->FirstAttr &&
1344 Context->CurrAttr < Context->LastAttr)
1345 {
1346 if (Context->CurrAttr->Length == 0)
1347 {
1348 DPRINT1("Broken length!\n");
1349 Context->CurrAttr = (PVOID)-1;
1350 return NULL;
1351 }
1352
1353 NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)Context->CurrAttr + Context->CurrAttr->Length);
1354
1355 if (NextAttribute > Context->LastAttr || NextAttribute < Context->FirstAttr)
1356 {
1357 DPRINT1("Broken length: 0x%lx!\n", Context->CurrAttr->Length);
1358 Context->CurrAttr = (PVOID)-1;
1359 return NULL;
1360 }
1361
1362 Context->Offset += ((ULONG_PTR)NextAttribute - (ULONG_PTR)Context->CurrAttr);
1363 Context->CurrAttr = NextAttribute;
1364
1365 if (Context->CurrAttr < Context->LastAttr &&
1366 Context->CurrAttr->Type != AttributeEnd)
1367 {
1368 return Context->CurrAttr;
1369 }
1370 }
1371
1372 if (Context->NonResidentStart == NULL)
1373 {
1374 Context->CurrAttr = (PVOID)-1;
1375 return NULL;
1376 }
1377
1378 Context->CurrAttr = (PVOID)-1;
1379 return NULL;
1380}

Referenced by FindFirstAttribute(), and FindNextAttribute().

◆ InternalGetNextAttributeListItem()

static PNTFS_ATTRIBUTE_LIST_ITEM InternalGetNextAttributeListItem ( PFIND_ATTR_CONTXT  Context)
static

Definition at line 1267 of file attrib.c.

1268{
1270
1271 if (Context->NonResidentCur == (PVOID)-1)
1272 {
1273 return NULL;
1274 }
1275
1276 if (Context->NonResidentCur == NULL || Context->NonResidentCur->Type == AttributeEnd)
1277 {
1278 Context->NonResidentCur = (PVOID)-1;
1279 return NULL;
1280 }
1281
1282 if (Context->NonResidentCur->Length == 0)
1283 {
1284 DPRINT1("Broken length list entry length !");
1285 Context->NonResidentCur = (PVOID)-1;
1286 return NULL;
1287 }
1288
1289 NextItem = (PNTFS_ATTRIBUTE_LIST_ITEM)((PCHAR)Context->NonResidentCur + Context->NonResidentCur->Length);
1290 if (NextItem->Length == 0 || NextItem->Type == AttributeEnd)
1291 {
1292 Context->NonResidentCur = (PVOID)-1;
1293 return NULL;
1294 }
1295
1296 if (NextItem < Context->NonResidentStart || NextItem > Context->NonResidentEnd)
1297 {
1298 Context->NonResidentCur = (PVOID)-1;
1299 return NULL;
1300 }
1301
1302 Context->NonResidentCur = NextItem;
1303 return NextItem;
1304}
static LPDATABLOCK_HEADER NextItem(LPDBLIST lpList)
Definition: clist.c:42
struct NTFS_ATTRIBUTE_LIST_ITEM * PNTFS_ATTRIBUTE_LIST_ITEM

Referenced by FindNextAttributeListItem().

◆ InternalReadNonResidentAttributes()

static NTSTATUS InternalReadNonResidentAttributes ( PFIND_ATTR_CONTXT  Context)
static

Definition at line 1214 of file attrib.c.

1215{
1216 ULONGLONG ListSize;
1217 PNTFS_ATTR_RECORD Attribute;
1218 PNTFS_ATTR_CONTEXT ListContext;
1219
1220 DPRINT("InternalReadNonResidentAttributes(%p)\n", Context);
1221
1222 Attribute = Context->CurrAttr;
1223 ASSERT(Attribute->Type == AttributeAttributeList);
1224
1225 if (Context->OnlyResident)
1226 {
1227 Context->NonResidentStart = NULL;
1228 Context->NonResidentEnd = NULL;
1229 return STATUS_SUCCESS;
1230 }
1231
1232 if (Context->NonResidentStart != NULL)
1233 {
1235 }
1236
1237 ListContext = PrepareAttributeContext(Attribute);
1238 ListSize = AttributeDataLength(ListContext->pRecord);
1239 if (ListSize > 0xFFFFFFFF)
1240 {
1241 ReleaseAttributeContext(ListContext);
1243 }
1244
1245 Context->NonResidentStart = ExAllocatePoolWithTag(NonPagedPool, (ULONG)ListSize, TAG_NTFS);
1246 if (Context->NonResidentStart == NULL)
1247 {
1248 ReleaseAttributeContext(ListContext);
1250 }
1251
1252 if (ReadAttribute(Context->Vcb, ListContext, 0, (PCHAR)Context->NonResidentStart, (ULONG)ListSize) != ListSize)
1253 {
1254 ExFreePoolWithTag(Context->NonResidentStart, TAG_NTFS);
1255 Context->NonResidentStart = NULL;
1256 ReleaseAttributeContext(ListContext);
1258 }
1259
1260 ReleaseAttributeContext(ListContext);
1261 Context->NonResidentEnd = (PNTFS_ATTRIBUTE_LIST_ITEM)((PCHAR)Context->NonResidentStart + ListSize);
1262 return STATUS_SUCCESS;
1263}
PNTFS_ATTR_CONTEXT PrepareAttributeContext(PNTFS_ATTR_RECORD AttrRecord)
Definition: mft.c:41
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
#define STATUS_FILE_CORRUPT_ERROR
Definition: udferr_usr.h:168

Referenced by FindFirstAttribute(), and FindNextAttribute().

◆ NtfsDumpAttribute()

static VOID NtfsDumpAttribute ( PDEVICE_EXTENSION  Vcb,
PNTFS_ATTR_RECORD  Attribute 
)
static

Definition at line 1617 of file attrib.c.

1619{
1621
1622 ULONGLONG lcn = 0;
1623 ULONGLONG runcount = 0;
1624
1625 switch (Attribute->Type)
1626 {
1627 case AttributeFileName:
1628 NtfsDumpFileNameAttribute(Attribute);
1629 break;
1630
1633 break;
1634
1635 case AttributeObjectId:
1636 DbgPrint(" $OBJECT_ID ");
1637 break;
1638
1640 DbgPrint(" $SECURITY_DESCRIPTOR ");
1641 break;
1642
1644 NtfsDumpVolumeNameAttribute(Attribute);
1645 break;
1646
1649 break;
1650
1651 case AttributeData:
1652 DbgPrint(" $DATA ");
1653 //DataBuf = ExAllocatePool(NonPagedPool,AttributeLengthAllocated(Attribute));
1654 break;
1655
1656 case AttributeIndexRoot:
1657 NtfsDumpIndexRootAttribute(Attribute);
1658 break;
1659
1661 DbgPrint(" $INDEX_ALLOCATION ");
1662 break;
1663
1664 case AttributeBitmap:
1665 DbgPrint(" $BITMAP ");
1666 break;
1667
1669 DbgPrint(" $REPARSE_POINT ");
1670 break;
1671
1673 DbgPrint(" $EA_INFORMATION ");
1674 break;
1675
1676 case AttributeEA:
1677 DbgPrint(" $EA ");
1678 break;
1679
1681 DbgPrint(" $PROPERTY_SET ");
1682 break;
1683
1685 DbgPrint(" $LOGGED_UTILITY_STREAM ");
1686 break;
1687
1688 default:
1689 DbgPrint(" Attribute %lx ",
1690 Attribute->Type);
1691 break;
1692 }
1693
1694 if (Attribute->Type != AttributeAttributeList)
1695 {
1696 if (Attribute->NameLength != 0)
1697 {
1698 Name.Length = Attribute->NameLength * sizeof(WCHAR);
1699 Name.MaximumLength = Name.Length;
1700 Name.Buffer = (PWCHAR)((ULONG_PTR)Attribute + Attribute->NameOffset);
1701
1702 DbgPrint("'%wZ' ", &Name);
1703 }
1704
1705 DbgPrint("(%s)\n",
1706 Attribute->IsNonResident ? "non-resident" : "resident");
1707
1708 if (Attribute->IsNonResident)
1709 {
1710 FindRun(Attribute,0,&lcn, &runcount);
1711
1712 DbgPrint(" AllocatedSize %I64u DataSize %I64u InitilizedSize %I64u\n",
1713 Attribute->NonResident.AllocatedSize, Attribute->NonResident.DataSize, Attribute->NonResident.InitializedSize);
1714 DbgPrint(" logical clusters: %I64u - %I64u\n",
1715 lcn, lcn + runcount - 1);
1716 }
1717 else
1718 DbgPrint(" %u bytes of data\n", Attribute->Resident.ValueLength);
1719 }
1720}
static VOID NtfsDumpVolumeInformationAttribute(PNTFS_ATTR_RECORD Attribute)
Definition: attrib.c:1524
static VOID NtfsDumpFileNameAttribute(PNTFS_ATTR_RECORD Attribute)
Definition: attrib.c:1476
static VOID NtfsDumpStandardInformationAttribute(PNTFS_ATTR_RECORD Attribute)
Definition: attrib.c:1494
BOOLEAN FindRun(PNTFS_ATTR_RECORD NresAttr, ULONGLONG vcn, PULONGLONG lcn, PULONGLONG count)
Definition: attrib.c:1010
static VOID NtfsDumpVolumeNameAttribute(PNTFS_ATTR_RECORD Attribute)
Definition: attrib.c:1509
static VOID NtfsDumpIndexRootAttribute(PNTFS_ATTR_RECORD Attribute)
Definition: attrib.c:1542
@ AttributeVolumeName
Definition: ntfs.h:166
@ AttributePropertySet
Definition: ntfs.h:175
@ AttributeReparsePoint
Definition: ntfs.h:172
@ AttributeEAInformation
Definition: ntfs.h:173
@ AttributeEA
Definition: ntfs.h:174
@ AttributeVolumeInformation
Definition: ntfs.h:167
@ AttributeSecurityDescriptor
Definition: ntfs.h:165
@ AttributeObjectId
Definition: ntfs.h:164
@ AttributeLoggedUtilityStream
Definition: ntfs.h:176
#define DbgPrint
Definition: hal.h:12
uint16_t * PWCHAR
Definition: typedefs.h:56

Referenced by NtfsDumpFileAttributes().

◆ NtfsDumpDataRunData()

VOID NtfsDumpDataRunData ( PUCHAR  DataRun)

Definition at line 1723 of file attrib.c.

1724{
1725 UCHAR DataRunOffsetSize;
1726 UCHAR DataRunLengthSize;
1727 CHAR i;
1728
1729 DbgPrint("%02x ", *DataRun);
1730
1731 if (*DataRun == 0)
1732 return;
1733
1734 DataRunOffsetSize = (*DataRun >> 4) & 0xF;
1735 DataRunLengthSize = *DataRun & 0xF;
1736
1737 DataRun++;
1738 for (i = 0; i < DataRunLengthSize; i++)
1739 {
1740 DbgPrint("%02x ", *DataRun);
1741 DataRun++;
1742 }
1743
1744 for (i = 0; i < DataRunOffsetSize; i++)
1745 {
1746 DbgPrint("%02x ", *DataRun);
1747 DataRun++;
1748 }
1749
1750 NtfsDumpDataRunData(DataRun);
1751}
VOID NtfsDumpDataRunData(PUCHAR DataRun)
Definition: attrib.c:1723

Referenced by NtfsDumpDataRunData(), and NtfsDumpDataRuns().

◆ NtfsDumpDataRuns()

VOID NtfsDumpDataRuns ( PVOID  StartOfRun,
ULONGLONG  CurrentLCN 
)

Definition at line 1755 of file attrib.c.

1757{
1758 PUCHAR DataRun = StartOfRun;
1759 LONGLONG DataRunOffset;
1760 ULONGLONG DataRunLength;
1761
1762 if (CurrentLCN == 0)
1763 {
1764 DPRINT1("Dumping data runs.\n\tData:\n\t\t");
1765 NtfsDumpDataRunData(StartOfRun);
1766 DbgPrint("\n\tRuns:\n\t\tOff\t\tLCN\t\tLength\n");
1767 }
1768
1769 DataRun = DecodeRun(DataRun, &DataRunOffset, &DataRunLength);
1770
1771 if (DataRunOffset != -1)
1772 CurrentLCN += DataRunOffset;
1773
1774 DbgPrint("\t\t%I64d\t", DataRunOffset);
1775 if (DataRunOffset < 99999)
1776 DbgPrint("\t");
1777 DbgPrint("%I64u\t", CurrentLCN);
1778 if (CurrentLCN < 99999)
1779 DbgPrint("\t");
1780 DbgPrint("%I64u\n", DataRunLength);
1781
1782 if (*DataRun == 0)
1783 DbgPrint("\t\t00\n");
1784 else
1785 NtfsDumpDataRuns(DataRun, CurrentLCN);
1786}

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

◆ NtfsDumpFileAttributes()

VOID NtfsDumpFileAttributes ( PDEVICE_EXTENSION  Vcb,
PFILE_RECORD_HEADER  FileRecord 
)

Definition at line 1790 of file attrib.c.

1792{
1795 PNTFS_ATTR_RECORD Attribute;
1796
1797 Status = FindFirstAttribute(&Context, Vcb, FileRecord, FALSE, &Attribute);
1798 while (NT_SUCCESS(Status))
1799 {
1800 NtfsDumpAttribute(Vcb, Attribute);
1801
1802 Status = FindNextAttribute(&Context, &Attribute);
1803 }
1804
1806}
static VOID NtfsDumpAttribute(PDEVICE_EXTENSION Vcb, PNTFS_ATTR_RECORD Attribute)
Definition: attrib.c:1617

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

◆ NtfsDumpFileNameAttribute()

static VOID NtfsDumpFileNameAttribute ( PNTFS_ATTR_RECORD  Attribute)
static

Definition at line 1476 of file attrib.c.

1477{
1478 PFILENAME_ATTRIBUTE FileNameAttr;
1479
1480 DbgPrint(" $FILE_NAME ");
1481
1482// DbgPrint(" Length %lu Offset %hu ", Attribute->Resident.ValueLength, Attribute->Resident.ValueOffset);
1483
1484 FileNameAttr = (PFILENAME_ATTRIBUTE)((ULONG_PTR)Attribute + Attribute->Resident.ValueOffset);
1485 DbgPrint(" (%x) '%.*S' ", FileNameAttr->NameType, FileNameAttr->NameLength, FileNameAttr->Name);
1486 DbgPrint(" '%x' \n", FileNameAttr->FileAttributes);
1487 DbgPrint(" AllocatedSize: %I64u\nDataSize: %I64u\n", FileNameAttr->AllocatedSize, FileNameAttr->DataSize);
1488 DbgPrint(" File reference: 0x%016I64x\n", FileNameAttr->DirectoryFileReferenceNumber);
1489}
ULONGLONG DataSize
Definition: ntfs.h:366
ULONGLONG AllocatedSize
Definition: ntfs.h:365

Referenced by NtfsDumpAttribute().

◆ NtfsDumpIndexRootAttribute()

static VOID NtfsDumpIndexRootAttribute ( PNTFS_ATTR_RECORD  Attribute)
static

Definition at line 1542 of file attrib.c.

1543{
1544 PINDEX_ROOT_ATTRIBUTE IndexRootAttr;
1545 ULONG CurrentOffset;
1546 ULONG CurrentNode;
1547
1548 IndexRootAttr = (PINDEX_ROOT_ATTRIBUTE)((ULONG_PTR)Attribute + Attribute->Resident.ValueOffset);
1549
1550 if (IndexRootAttr->AttributeType == AttributeFileName)
1551 ASSERT(IndexRootAttr->CollationRule == COLLATION_FILE_NAME);
1552
1553 DbgPrint(" $INDEX_ROOT (%u bytes per index record, %u clusters) ", IndexRootAttr->SizeOfEntry, IndexRootAttr->ClustersPerIndexRecord);
1554
1555 if (IndexRootAttr->Header.Flags == INDEX_ROOT_SMALL)
1556 {
1557 DbgPrint(" (small)\n");
1558 }
1559 else
1560 {
1561 ASSERT(IndexRootAttr->Header.Flags == INDEX_ROOT_LARGE);
1562 DbgPrint(" (large)\n");
1563 }
1564
1565 DbgPrint(" Offset to first index: 0x%lx\n Total size of index entries: 0x%lx\n Allocated size of node: 0x%lx\n",
1566 IndexRootAttr->Header.FirstEntryOffset,
1567 IndexRootAttr->Header.TotalSizeOfEntries,
1568 IndexRootAttr->Header.AllocatedSize);
1569 CurrentOffset = IndexRootAttr->Header.FirstEntryOffset;
1570 CurrentNode = 0;
1571 // print details of every node in the index
1572 while (CurrentOffset < IndexRootAttr->Header.TotalSizeOfEntries)
1573 {
1574 PINDEX_ENTRY_ATTRIBUTE currentIndexExtry = (PINDEX_ENTRY_ATTRIBUTE)((ULONG_PTR)IndexRootAttr + 0x10 + CurrentOffset);
1575 DbgPrint(" Index Node Entry %lu", CurrentNode++);
1576 if (BooleanFlagOn(currentIndexExtry->Flags, NTFS_INDEX_ENTRY_NODE))
1577 DbgPrint(" (Branch)");
1578 else
1579 DbgPrint(" (Leaf)");
1580 if (BooleanFlagOn(currentIndexExtry->Flags, NTFS_INDEX_ENTRY_END))
1581 {
1582 DbgPrint(" (Dummy Key)");
1583 }
1584 DbgPrint("\n File Reference: 0x%016I64x\n", currentIndexExtry->Data.Directory.IndexedFile);
1585 DbgPrint(" Index Entry Length: 0x%x\n", currentIndexExtry->Length);
1586 DbgPrint(" Index Key Length: 0x%x\n", currentIndexExtry->KeyLength);
1587
1588 // if this isn't the final (dummy) node, print info about the key (Filename attribute)
1589 if (!(currentIndexExtry->Flags & NTFS_INDEX_ENTRY_END))
1590 {
1592 DbgPrint(" Parent File Reference: 0x%016I64x\n", currentIndexExtry->FileName.DirectoryFileReferenceNumber);
1593 DbgPrint(" $FILENAME indexed: ");
1594 Name.Length = currentIndexExtry->FileName.NameLength * sizeof(WCHAR);
1595 Name.MaximumLength = Name.Length;
1596 Name.Buffer = currentIndexExtry->FileName.Name;
1597 DbgPrint("'%wZ'\n", &Name);
1598 }
1599
1600 // if this node has a sub-node beneath it
1601 if (currentIndexExtry->Flags & NTFS_INDEX_ENTRY_NODE)
1602 {
1603 // Print the VCN of the sub-node
1604 PULONGLONG SubNodeVCN = (PULONGLONG)((ULONG_PTR)currentIndexExtry + currentIndexExtry->Length - sizeof(ULONGLONG));
1605 DbgPrint(" VCN of sub-node: 0x%llx\n", *SubNodeVCN);
1606 }
1607
1608 CurrentOffset += currentIndexExtry->Length;
1609 ASSERT(currentIndexExtry->Length);
1610 }
1611
1612}
#define NTFS_INDEX_ENTRY_NODE
Definition: ntfs.h:60
#define NTFS_INDEX_ENTRY_END
Definition: ntfs.h:61
Definition: Header.h:9
#define INDEX_ROOT_SMALL
Definition: ntfs.h:208
struct INDEX_ENTRY_ATTRIBUTE * PINDEX_ENTRY_ATTRIBUTE
#define COLLATION_FILE_NAME
Definition: ntfs.h:201
#define INDEX_ROOT_LARGE
Definition: ntfs.h:209
struct INDEX_ROOT_ATTRIBUTE * PINDEX_ROOT_ATTRIBUTE
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
__GNU_EXTENSION typedef unsigned __int64 * PULONGLONG
Definition: ntbasedef.h:383
Definition: ntfs.h:409
union INDEX_ENTRY_ATTRIBUTE::@762 Data
FILENAME_ATTRIBUTE FileName
Definition: ntfs.h:427
USHORT Length
Definition: ntfs.h:423
USHORT KeyLength
Definition: ntfs.h:424
struct INDEX_ENTRY_ATTRIBUTE::@762::@763 Directory
USHORT Flags
Definition: ntfs.h:425
ULONG FirstEntryOffset
Definition: ntfs.h:384
ULONG TotalSizeOfEntries
Definition: ntfs.h:385
ULONG AttributeType
Definition: ntfs.h:393
ULONG CollationRule
Definition: ntfs.h:394
INDEX_HEADER_ATTRIBUTE Header
Definition: ntfs.h:398
UCHAR ClustersPerIndexRecord
Definition: ntfs.h:396
ULONG SizeOfEntry
Definition: ntfs.h:395

Referenced by NtfsDumpAttribute().

◆ NtfsDumpStandardInformationAttribute()

static VOID NtfsDumpStandardInformationAttribute ( PNTFS_ATTR_RECORD  Attribute)
static

Definition at line 1494 of file attrib.c.

1495{
1496 PSTANDARD_INFORMATION StandardInfoAttr;
1497
1498 DbgPrint(" $STANDARD_INFORMATION ");
1499
1500// DbgPrint(" Length %lu Offset %hu ", Attribute->Resident.ValueLength, Attribute->Resident.ValueOffset);
1501
1502 StandardInfoAttr = (PSTANDARD_INFORMATION)((ULONG_PTR)Attribute + Attribute->Resident.ValueOffset);
1503 DbgPrint(" '%x' ", StandardInfoAttr->FileAttribute);
1504}

Referenced by NtfsDumpAttribute().

◆ NtfsDumpVolumeInformationAttribute()

static VOID NtfsDumpVolumeInformationAttribute ( PNTFS_ATTR_RECORD  Attribute)
static

Definition at line 1524 of file attrib.c.

1525{
1526 PVOLINFO_ATTRIBUTE VolInfoAttr;
1527
1528 DbgPrint(" $VOLUME_INFORMATION ");
1529
1530// DbgPrint(" Length %lu Offset %hu ", Attribute->Resident.ValueLength, Attribute->Resident.ValueOffset);
1531
1532 VolInfoAttr = (PVOLINFO_ATTRIBUTE)((ULONG_PTR)Attribute + Attribute->Resident.ValueOffset);
1533 DbgPrint(" NTFS Version %u.%u Flags 0x%04hx ",
1534 VolInfoAttr->MajorVersion,
1535 VolInfoAttr->MinorVersion,
1536 VolInfoAttr->Flags);
1537}
struct VOLINFO_ATTRIBUTE * PVOLINFO_ATTRIBUTE
UCHAR MinorVersion
Definition: ntfs.h:462
UCHAR MajorVersion
Definition: ntfs.h:461
USHORT Flags
Definition: ntfs.h:463

Referenced by NtfsDumpAttribute().

◆ NtfsDumpVolumeNameAttribute()

static VOID NtfsDumpVolumeNameAttribute ( PNTFS_ATTR_RECORD  Attribute)
static

Definition at line 1509 of file attrib.c.

1510{
1512
1513 DbgPrint(" $VOLUME_NAME ");
1514
1515// DbgPrint(" Length %lu Offset %hu ", Attribute->Resident.ValueLength, Attribute->Resident.ValueOffset);
1516
1517 VolumeName = (PWCHAR)((ULONG_PTR)Attribute + Attribute->Resident.ValueOffset);
1518 DbgPrint(" '%.*S' ", Attribute->Resident.ValueLength / sizeof(WCHAR), VolumeName);
1519}
_Must_inspect_result_ _Inout_opt_ PUNICODE_STRING VolumeName
Definition: fltkernel.h:1117

Referenced by NtfsDumpAttribute().