ReactOS 0.4.17-dev-1190-g4c812f4
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
 
#define NTFS_DUMP_DATA_RUNS   0
 

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_NOT_IMPLEMENTED if we need to migrate the attribute to an attribute list (TODO). Any other failure from ConvertLargeMCBToDataRuns() is returned as-is.
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.
VcnCountNumber of VCNs the runs must describe, HighestVCN + 1. A hole the MCB doesn't reach, at the end of a sparse stream, is encoded up to this point.
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, ULONGLONG VcnCount, 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.

◆ NTFS_DUMP_DATA_RUNS

#define NTFS_DUMP_DATA_RUNS   0

Definition at line 39 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 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
@ AttributeEnd
Definition: ntfs.h:204
@ AttributeBitmap
Definition: ntfs.h:198
#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}
@ AttributeData
Definition: ntfs.h:195

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
@ AttributeFileName
Definition: ntfs.h:190
#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().

◆ 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
@ AttributeIndexAllocation
Definition: ntfs.h:197
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}
@ AttributeIndexRoot
Definition: ntfs.h:196

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 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 TAG_NTFS
Definition: ntfs.h:12
#define NTFS_ATTR_COMPRESSION_MASK
Definition: ntfs.h:262
#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 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
NTSTATUS UpdateFileRecord(PDEVICE_EXTENSION Vcb, ULONGLONG MftIndex, PFILE_RECORD_HEADER FileRecord)
Definition: mft.c:2391
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: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
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 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
@ AttributeStandardInformation
Definition: ntfs.h:188
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().

◆ 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}
unsigned char BOOLEAN
Definition: actypes.h:127
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
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

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

◆ 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(), and PrepareAttributeContext().

◆ 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}
_In_ PIRP _In_ PIO_COMPLETION_ROUTINE _In_ PVOID Context
Definition: kse.h:81

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
@ AttributeAttributeList
Definition: ntfs.h:189
#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().

◆ FindRun()

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

Definition at line 1054 of file attrib.c.

1058{
1059 if (vcn < NresAttr->NonResident.LowestVCN || vcn > NresAttr->NonResident.HighestVCN)
1060 return FALSE;
1061
1062 DecodeRun((PUCHAR)((ULONG_PTR)NresAttr + NresAttr->NonResident.MappingPairsOffset), (PLONGLONG)lcn, count);
1063
1064 return TRUE;
1065}
GLuint GLuint GLsizei count
Definition: gl.h:1545
__GNU_EXTENSION typedef __int64 * PLONGLONG
Definition: ntbasedef.h:394

Referenced by NtfsDumpAttribute().

◆ 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 ASSERT(a)
Definition: mode.c:44
#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().

◆ 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
struct _FileName FileName
Definition: fatprocs.h:897

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}
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102

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
NTSTATUS FindFirstAttribute(PFIND_ATTR_CONTXT Context, PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER FileRecord, BOOLEAN OnlyResident, PNTFS_ATTR_RECORD *Attribute)
Definition: attrib.c:1413
VOID FindCloseAttribute(PFIND_ATTR_CONTXT Context)
Definition: attrib.c:1495
NTSTATUS FindNextAttribute(PFIND_ATTR_CONTXT Context, PNTFS_ATTR_RECORD *Attribute)
Definition: attrib.c:1461

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

◆ 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().

◆ 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().

◆ InternalGetNextAttribute()

static PNTFS_ATTR_RECORD InternalGetNextAttribute ( PFIND_ATTR_CONTXT  Context)
static

Definition at line 1364 of file attrib.c.

1365{
1366 PNTFS_ATTR_RECORD NextAttribute;
1367
1368 if (Context->CurrAttr == (PVOID)-1)
1369 {
1370 return NULL;
1371 }
1372
1373 if (Context->CurrAttr >= Context->FirstAttr &&
1374 Context->CurrAttr < Context->LastAttr)
1375 {
1376 if (Context->CurrAttr->Length == 0)
1377 {
1378 DPRINT1("Broken length!\n");
1379 Context->CurrAttr = (PVOID)-1;
1380 return NULL;
1381 }
1382
1383 NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)Context->CurrAttr + Context->CurrAttr->Length);
1384
1385 if (NextAttribute > Context->LastAttr || NextAttribute < Context->FirstAttr)
1386 {
1387 DPRINT1("Broken length: 0x%lx!\n", Context->CurrAttr->Length);
1388 Context->CurrAttr = (PVOID)-1;
1389 return NULL;
1390 }
1391
1392 Context->Offset += ((ULONG_PTR)NextAttribute - (ULONG_PTR)Context->CurrAttr);
1393 Context->CurrAttr = NextAttribute;
1394
1395 if (Context->CurrAttr < Context->LastAttr &&
1396 Context->CurrAttr->Type != AttributeEnd)
1397 {
1398 return Context->CurrAttr;
1399 }
1400 }
1401
1402 if (Context->NonResidentStart == NULL)
1403 {
1404 Context->CurrAttr = (PVOID)-1;
1405 return NULL;
1406 }
1407
1408 Context->CurrAttr = (PVOID)-1;
1409 return NULL;
1410}

Referenced by FindFirstAttribute(), and FindNextAttribute().

◆ InternalGetNextAttributeListItem()

static PNTFS_ATTRIBUTE_LIST_ITEM InternalGetNextAttributeListItem ( PFIND_ATTR_CONTXT  Context)
static

Definition at line 1297 of file attrib.c.

1298{
1300
1301 if (Context->NonResidentCur == (PVOID)-1)
1302 {
1303 return NULL;
1304 }
1305
1306 if (Context->NonResidentCur == NULL || Context->NonResidentCur->Type == AttributeEnd)
1307 {
1308 Context->NonResidentCur = (PVOID)-1;
1309 return NULL;
1310 }
1311
1312 if (Context->NonResidentCur->Length == 0)
1313 {
1314 DPRINT1("Broken length list entry length !");
1315 Context->NonResidentCur = (PVOID)-1;
1316 return NULL;
1317 }
1318
1319 NextItem = (PNTFS_ATTRIBUTE_LIST_ITEM)((PCHAR)Context->NonResidentCur + Context->NonResidentCur->Length);
1320 if (NextItem->Length == 0 || NextItem->Type == AttributeEnd)
1321 {
1322 Context->NonResidentCur = (PVOID)-1;
1323 return NULL;
1324 }
1325
1326 if (NextItem < Context->NonResidentStart || NextItem > Context->NonResidentEnd)
1327 {
1328 Context->NonResidentCur = (PVOID)-1;
1329 return NULL;
1330 }
1331
1332 Context->NonResidentCur = NextItem;
1333 return NextItem;
1334}
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 1244 of file attrib.c.

1245{
1246 ULONGLONG ListSize;
1247 PNTFS_ATTR_RECORD Attribute;
1248 PNTFS_ATTR_CONTEXT ListContext;
1249
1250 DPRINT("InternalReadNonResidentAttributes(%p)\n", Context);
1251
1252 Attribute = Context->CurrAttr;
1253 ASSERT(Attribute->Type == AttributeAttributeList);
1254
1255 if (Context->OnlyResident)
1256 {
1257 Context->NonResidentStart = NULL;
1258 Context->NonResidentEnd = NULL;
1259 return STATUS_SUCCESS;
1260 }
1261
1262 if (Context->NonResidentStart != NULL)
1263 {
1265 }
1266
1267 ListContext = PrepareAttributeContext(Attribute);
1268 ListSize = AttributeDataLength(ListContext->pRecord);
1269 if (ListSize > 0xFFFFFFFF)
1270 {
1271 ReleaseAttributeContext(ListContext);
1273 }
1274
1275 Context->NonResidentStart = ExAllocatePoolWithTag(NonPagedPool, (ULONG)ListSize, TAG_NTFS);
1276 if (Context->NonResidentStart == NULL)
1277 {
1278 ReleaseAttributeContext(ListContext);
1280 }
1281
1282 if (ReadAttribute(Context->Vcb, ListContext, 0, (PCHAR)Context->NonResidentStart, (ULONG)ListSize) != ListSize)
1283 {
1284 ExFreePoolWithTag(Context->NonResidentStart, TAG_NTFS);
1285 Context->NonResidentStart = NULL;
1286 ReleaseAttributeContext(ListContext);
1288 }
1289
1290 ReleaseAttributeContext(ListContext);
1291 Context->NonResidentEnd = (PNTFS_ATTRIBUTE_LIST_ITEM)((PCHAR)Context->NonResidentStart + ListSize);
1292 return STATUS_SUCCESS;
1293}
VOID ReleaseAttributeContext(PNTFS_ATTR_CONTEXT Context)
Definition: mft.c:104
PNTFS_ATTR_CONTEXT PrepareAttributeContext(PNTFS_ATTR_RECORD AttrRecord)
Definition: mft.c:41
ULONGLONG AttributeDataLength(PNTFS_ATTR_RECORD AttrRecord)
Definition: mft.c:259
ULONG ReadAttribute(PDEVICE_EXTENSION Vcb, PNTFS_ATTR_CONTEXT Context, ULONGLONG Offset, PCHAR Buffer, ULONG Length)
Definition: mft.c:1625
#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 1647 of file attrib.c.

1649{
1651
1652 ULONGLONG lcn = 0;
1653 ULONGLONG runcount = 0;
1654
1655 switch (Attribute->Type)
1656 {
1657 case AttributeFileName:
1658 NtfsDumpFileNameAttribute(Attribute);
1659 break;
1660
1663 break;
1664
1665 case AttributeObjectId:
1666 DbgPrint(" $OBJECT_ID ");
1667 break;
1668
1670 DbgPrint(" $SECURITY_DESCRIPTOR ");
1671 break;
1672
1674 NtfsDumpVolumeNameAttribute(Attribute);
1675 break;
1676
1679 break;
1680
1681 case AttributeData:
1682 DbgPrint(" $DATA ");
1683 //DataBuf = ExAllocatePool(NonPagedPool,AttributeLengthAllocated(Attribute));
1684 break;
1685
1686 case AttributeIndexRoot:
1687 NtfsDumpIndexRootAttribute(Attribute);
1688 break;
1689
1691 DbgPrint(" $INDEX_ALLOCATION ");
1692 break;
1693
1694 case AttributeBitmap:
1695 DbgPrint(" $BITMAP ");
1696 break;
1697
1699 DbgPrint(" $REPARSE_POINT ");
1700 break;
1701
1703 DbgPrint(" $EA_INFORMATION ");
1704 break;
1705
1706 case AttributeEA:
1707 DbgPrint(" $EA ");
1708 break;
1709
1711 DbgPrint(" $PROPERTY_SET ");
1712 break;
1713
1715 DbgPrint(" $LOGGED_UTILITY_STREAM ");
1716 break;
1717
1718 default:
1719 DbgPrint(" Attribute %lx ",
1720 Attribute->Type);
1721 break;
1722 }
1723
1724 if (Attribute->Type != AttributeAttributeList)
1725 {
1726 if (Attribute->NameLength != 0)
1727 {
1728 Name.Length = Attribute->NameLength * sizeof(WCHAR);
1729 Name.MaximumLength = Name.Length;
1730 Name.Buffer = (PWCHAR)((ULONG_PTR)Attribute + Attribute->NameOffset);
1731
1732 DbgPrint("'%wZ' ", &Name);
1733 }
1734
1735 DbgPrint("(%s)\n",
1736 Attribute->IsNonResident ? "non-resident" : "resident");
1737
1738 if (Attribute->IsNonResident)
1739 {
1740 FindRun(Attribute,0,&lcn, &runcount);
1741
1742 DbgPrint(" AllocatedSize %I64u DataSize %I64u InitilizedSize %I64u\n",
1743 Attribute->NonResident.AllocatedSize, Attribute->NonResident.DataSize, Attribute->NonResident.InitializedSize);
1744 DbgPrint(" logical clusters: %I64u - %I64u\n",
1745 lcn, lcn + runcount - 1);
1746 }
1747 else
1748 DbgPrint(" %u bytes of data\n", Attribute->Resident.ValueLength);
1749 }
1750}
static VOID NtfsDumpVolumeInformationAttribute(PNTFS_ATTR_RECORD Attribute)
Definition: attrib.c:1554
static VOID NtfsDumpFileNameAttribute(PNTFS_ATTR_RECORD Attribute)
Definition: attrib.c:1506
static VOID NtfsDumpStandardInformationAttribute(PNTFS_ATTR_RECORD Attribute)
Definition: attrib.c:1524
BOOLEAN FindRun(PNTFS_ATTR_RECORD NresAttr, ULONGLONG vcn, PULONGLONG lcn, PULONGLONG count)
Definition: attrib.c:1054
static VOID NtfsDumpVolumeNameAttribute(PNTFS_ATTR_RECORD Attribute)
Definition: attrib.c:1539
static VOID NtfsDumpIndexRootAttribute(PNTFS_ATTR_RECORD Attribute)
Definition: attrib.c:1572
@ AttributeVolumeName
Definition: ntfs.h:193
@ AttributePropertySet
Definition: ntfs.h:202
@ AttributeReparsePoint
Definition: ntfs.h:199
@ AttributeEAInformation
Definition: ntfs.h:200
@ AttributeEA
Definition: ntfs.h:201
@ AttributeVolumeInformation
Definition: ntfs.h:194
@ AttributeSecurityDescriptor
Definition: ntfs.h:192
@ AttributeObjectId
Definition: ntfs.h:191
@ AttributeLoggedUtilityStream
Definition: ntfs.h:203
#define DbgPrint
Definition: hal.h:12
uint16_t * PWCHAR
Definition: typedefs.h:56

Referenced by NtfsDumpFileAttributes().

◆ NtfsDumpDataRunData()

VOID NtfsDumpDataRunData ( PUCHAR  DataRun)

Definition at line 1753 of file attrib.c.

1754{
1755 UCHAR DataRunOffsetSize;
1756 UCHAR DataRunLengthSize;
1757 CHAR i;
1758
1759 DbgPrint("%02x ", *DataRun);
1760
1761 if (*DataRun == 0)
1762 return;
1763
1764 DataRunOffsetSize = (*DataRun >> 4) & 0xF;
1765 DataRunLengthSize = *DataRun & 0xF;
1766
1767 DataRun++;
1768 for (i = 0; i < DataRunLengthSize; i++)
1769 {
1770 DbgPrint("%02x ", *DataRun);
1771 DataRun++;
1772 }
1773
1774 for (i = 0; i < DataRunOffsetSize; i++)
1775 {
1776 DbgPrint("%02x ", *DataRun);
1777 DataRun++;
1778 }
1779
1780 NtfsDumpDataRunData(DataRun);
1781}
VOID NtfsDumpDataRunData(PUCHAR DataRun)
Definition: attrib.c:1753

Referenced by NtfsDumpDataRunData(), and NtfsDumpDataRuns().

◆ 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}

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().

◆ NtfsDumpFileNameAttribute()

static VOID NtfsDumpFileNameAttribute ( PNTFS_ATTR_RECORD  Attribute)
static

Definition at line 1506 of file attrib.c.

1507{
1508 PFILENAME_ATTRIBUTE FileNameAttr;
1509
1510 DbgPrint(" $FILE_NAME ");
1511
1512// DbgPrint(" Length %lu Offset %hu ", Attribute->Resident.ValueLength, Attribute->Resident.ValueOffset);
1513
1514 FileNameAttr = (PFILENAME_ATTRIBUTE)((ULONG_PTR)Attribute + Attribute->Resident.ValueOffset);
1515 DbgPrint(" (%x) '%.*S' ", FileNameAttr->NameType, FileNameAttr->NameLength, FileNameAttr->Name);
1516 DbgPrint(" '%x' \n", FileNameAttr->FileAttributes);
1517 DbgPrint(" AllocatedSize: %I64u\nDataSize: %I64u\n", FileNameAttr->AllocatedSize, FileNameAttr->DataSize);
1518 DbgPrint(" File reference: 0x%016I64x\n", FileNameAttr->DirectoryFileReferenceNumber);
1519}
ULONGLONG DataSize
Definition: ntfs.h:397
ULONGLONG AllocatedSize
Definition: ntfs.h:396

Referenced by NtfsDumpAttribute().

◆ NtfsDumpIndexRootAttribute()

static VOID NtfsDumpIndexRootAttribute ( PNTFS_ATTR_RECORD  Attribute)
static

Definition at line 1572 of file attrib.c.

1573{
1574 PINDEX_ROOT_ATTRIBUTE IndexRootAttr;
1575 ULONG CurrentOffset;
1576 ULONG CurrentNode;
1577
1578 IndexRootAttr = (PINDEX_ROOT_ATTRIBUTE)((ULONG_PTR)Attribute + Attribute->Resident.ValueOffset);
1579
1580 if (IndexRootAttr->AttributeType == AttributeFileName)
1581 ASSERT(IndexRootAttr->CollationRule == COLLATION_FILE_NAME);
1582
1583 DbgPrint(" $INDEX_ROOT (%u bytes per index record, %u clusters) ", IndexRootAttr->SizeOfEntry, IndexRootAttr->ClustersPerIndexRecord);
1584
1585 if (IndexRootAttr->Header.Flags == INDEX_ROOT_SMALL)
1586 {
1587 DbgPrint(" (small)\n");
1588 }
1589 else
1590 {
1591 ASSERT(IndexRootAttr->Header.Flags == INDEX_ROOT_LARGE);
1592 DbgPrint(" (large)\n");
1593 }
1594
1595 DbgPrint(" Offset to first index: 0x%lx\n Total size of index entries: 0x%lx\n Allocated size of node: 0x%lx\n",
1596 IndexRootAttr->Header.FirstEntryOffset,
1597 IndexRootAttr->Header.TotalSizeOfEntries,
1598 IndexRootAttr->Header.AllocatedSize);
1599 CurrentOffset = IndexRootAttr->Header.FirstEntryOffset;
1600 CurrentNode = 0;
1601 // print details of every node in the index
1602 while (CurrentOffset < IndexRootAttr->Header.TotalSizeOfEntries)
1603 {
1604 PINDEX_ENTRY_ATTRIBUTE currentIndexExtry = (PINDEX_ENTRY_ATTRIBUTE)((ULONG_PTR)IndexRootAttr + 0x10 + CurrentOffset);
1605 DbgPrint(" Index Node Entry %lu", CurrentNode++);
1606 if (BooleanFlagOn(currentIndexExtry->Flags, NTFS_INDEX_ENTRY_NODE))
1607 DbgPrint(" (Branch)");
1608 else
1609 DbgPrint(" (Leaf)");
1610 if (BooleanFlagOn(currentIndexExtry->Flags, NTFS_INDEX_ENTRY_END))
1611 {
1612 DbgPrint(" (Dummy Key)");
1613 }
1614 DbgPrint("\n File Reference: 0x%016I64x\n", currentIndexExtry->Data.Directory.IndexedFile);
1615 DbgPrint(" Index Entry Length: 0x%x\n", currentIndexExtry->Length);
1616 DbgPrint(" Index Key Length: 0x%x\n", currentIndexExtry->KeyLength);
1617
1618 // if this isn't the final (dummy) node, print info about the key (Filename attribute)
1619 if (!(currentIndexExtry->Flags & NTFS_INDEX_ENTRY_END))
1620 {
1622 DbgPrint(" Parent File Reference: 0x%016I64x\n", currentIndexExtry->FileName.DirectoryFileReferenceNumber);
1623 DbgPrint(" $FILENAME indexed: ");
1624 Name.Length = currentIndexExtry->FileName.NameLength * sizeof(WCHAR);
1625 Name.MaximumLength = Name.Length;
1626 Name.Buffer = currentIndexExtry->FileName.Name;
1627 DbgPrint("'%wZ'\n", &Name);
1628 }
1629
1630 // if this node has a sub-node beneath it
1631 if (currentIndexExtry->Flags & NTFS_INDEX_ENTRY_NODE)
1632 {
1633 // Print the VCN of the sub-node
1634 PULONGLONG SubNodeVCN = (PULONGLONG)((ULONG_PTR)currentIndexExtry + currentIndexExtry->Length - sizeof(ULONGLONG));
1635 DbgPrint(" VCN of sub-node: 0x%llx\n", *SubNodeVCN);
1636 }
1637
1638 CurrentOffset += currentIndexExtry->Length;
1639 ASSERT(currentIndexExtry->Length);
1640 }
1641
1642}
#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:235
struct INDEX_ENTRY_ATTRIBUTE * PINDEX_ENTRY_ATTRIBUTE
#define COLLATION_FILE_NAME
Definition: ntfs.h:228
#define INDEX_ROOT_LARGE
Definition: ntfs.h:236
struct INDEX_ROOT_ATTRIBUTE * PINDEX_ROOT_ATTRIBUTE
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
__GNU_EXTENSION typedef unsigned __int64 * PULONGLONG
Definition: ntbasedef.h:395
Definition: ntfs.h:440
union INDEX_ENTRY_ATTRIBUTE::@970 Data
struct INDEX_ENTRY_ATTRIBUTE::@970::@971 Directory
FILENAME_ATTRIBUTE FileName
Definition: ntfs.h:458
USHORT Length
Definition: ntfs.h:454
USHORT KeyLength
Definition: ntfs.h:455
USHORT Flags
Definition: ntfs.h:456
ULONG FirstEntryOffset
Definition: ntfs.h:415
ULONG TotalSizeOfEntries
Definition: ntfs.h:416
ULONG AttributeType
Definition: ntfs.h:424
ULONG CollationRule
Definition: ntfs.h:425
INDEX_HEADER_ATTRIBUTE Header
Definition: ntfs.h:429
UCHAR ClustersPerIndexRecord
Definition: ntfs.h:427
ULONG SizeOfEntry
Definition: ntfs.h:426

Referenced by NtfsDumpAttribute().

◆ NtfsDumpStandardInformationAttribute()

static VOID NtfsDumpStandardInformationAttribute ( PNTFS_ATTR_RECORD  Attribute)
static

Definition at line 1524 of file attrib.c.

1525{
1526 PSTANDARD_INFORMATION StandardInfoAttr;
1527
1528 DbgPrint(" $STANDARD_INFORMATION ");
1529
1530// DbgPrint(" Length %lu Offset %hu ", Attribute->Resident.ValueLength, Attribute->Resident.ValueOffset);
1531
1532 StandardInfoAttr = (PSTANDARD_INFORMATION)((ULONG_PTR)Attribute + Attribute->Resident.ValueOffset);
1533 DbgPrint(" '%x' ", StandardInfoAttr->FileAttribute);
1534}

Referenced by NtfsDumpAttribute().

◆ NtfsDumpVolumeInformationAttribute()

static VOID NtfsDumpVolumeInformationAttribute ( PNTFS_ATTR_RECORD  Attribute)
static

Definition at line 1554 of file attrib.c.

1555{
1556 PVOLINFO_ATTRIBUTE VolInfoAttr;
1557
1558 DbgPrint(" $VOLUME_INFORMATION ");
1559
1560// DbgPrint(" Length %lu Offset %hu ", Attribute->Resident.ValueLength, Attribute->Resident.ValueOffset);
1561
1562 VolInfoAttr = (PVOLINFO_ATTRIBUTE)((ULONG_PTR)Attribute + Attribute->Resident.ValueOffset);
1563 DbgPrint(" NTFS Version %u.%u Flags 0x%04hx ",
1564 VolInfoAttr->MajorVersion,
1565 VolInfoAttr->MinorVersion,
1566 VolInfoAttr->Flags);
1567}
struct VOLINFO_ATTRIBUTE * PVOLINFO_ATTRIBUTE
UCHAR MinorVersion
Definition: ntfs.h:493
UCHAR MajorVersion
Definition: ntfs.h:492
USHORT Flags
Definition: ntfs.h:494

Referenced by NtfsDumpAttribute().

◆ NtfsDumpVolumeNameAttribute()

static VOID NtfsDumpVolumeNameAttribute ( PNTFS_ATTR_RECORD  Attribute)
static

Definition at line 1539 of file attrib.c.

1540{
1542
1543 DbgPrint(" $VOLUME_NAME ");
1544
1545// DbgPrint(" Length %lu Offset %hu ", Attribute->Resident.ValueLength, Attribute->Resident.ValueOffset);
1546
1547 VolumeName = (PWCHAR)((ULONG_PTR)Attribute + Attribute->Resident.ValueOffset);
1548 DbgPrint(" '%.*S' ", Attribute->Resident.ValueLength / sizeof(WCHAR), VolumeName);
1549}
_Must_inspect_result_ _Inout_opt_ PUNICODE_STRING VolumeName
Definition: fltkernel.h:1117

Referenced by NtfsDumpAttribute().