https://git.reactos.org/?p=reactos.git;a=commitdiff;h=4dfcd1d58295e72486625a...
commit 4dfcd1d58295e72486625ab6063a3d5bf3e59a2c Author: Trevor Thompson tmt256@email.vccs.edu AuthorDate: Sun Aug 6 02:54:15 2017 +0000
[NTFS] - Refactor to allow the copy of the attribute stored in NTFS_ATTR_CONTEXT to have a dynamic length; change Record member from an NTFS_ATTR_RECORD to a PNTFS_ATTR_RECORD. Rename it pRecord to reinforce the change. Fix some bugs related to the record size changing. -PrepareAttributeContext() - update to allocate memory for pRecord. Don't assume allocations are succeeding. -ReleaseAttributeContext() - update to free memory for pRecord. -InternalSetResidentAttributeLength() - Increase size of AttrContext->pRecord as needed. Update to return an NTSTATUS. -SetResidentAttributeDataLength() - Fix bug that could occur when migrating resident attributes to non-resident if AttrContext->pRecord is too small for the new attribute. -AddRun() - Fix a bug by reallocating AttrContext->pRecord if the record needs to be enlarged.
svn path=/branches/GSoC_2016/NTFS/; revision=75493 --- drivers/filesystems/ntfs/attrib.c | 58 ++++++--- drivers/filesystems/ntfs/btree.c | 4 +- drivers/filesystems/ntfs/dirctl.c | 4 +- drivers/filesystems/ntfs/fcb.c | 2 +- drivers/filesystems/ntfs/finfo.c | 4 +- drivers/filesystems/ntfs/fsctl.c | 8 +- drivers/filesystems/ntfs/mft.c | 236 ++++++++++++++++++++++++------------- drivers/filesystems/ntfs/ntfs.h | 4 +- drivers/filesystems/ntfs/rw.c | 8 +- drivers/filesystems/ntfs/volinfo.c | 4 +- 10 files changed, 214 insertions(+), 118 deletions(-)
diff --git a/drivers/filesystems/ntfs/attrib.c b/drivers/filesystems/ntfs/attrib.c index a6bc9a8aca..8618862344 100644 --- a/drivers/filesystems/ntfs/attrib.c +++ b/drivers/filesystems/ntfs/attrib.c @@ -303,17 +303,17 @@ AddRun(PNTFS_VCB Vcb, NTSTATUS Status; int DataRunMaxLength; PNTFS_ATTR_RECORD DestinationAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + AttrOffset); - ULONG NextAttributeOffset = AttrOffset + AttrContext->Record.Length; + ULONG NextAttributeOffset = AttrOffset + AttrContext->pRecord->Length; ULONGLONG NextVBN = 0;
PUCHAR RunBuffer; ULONG RunBufferSize;
- if (!AttrContext->Record.IsNonResident) + if (!AttrContext->pRecord->IsNonResident) return STATUS_INVALID_PARAMETER;
- if (AttrContext->Record.NonResident.AllocatedSize != 0) - NextVBN = AttrContext->Record.NonResident.HighestVCN + 1; + if (AttrContext->pRecord->NonResident.AllocatedSize != 0) + NextVBN = AttrContext->pRecord->NonResident.HighestVCN + 1;
// Add newly-assigned clusters to mcb _SEH2_TRY @@ -344,12 +344,14 @@ AddRun(PNTFS_VCB Vcb, ConvertLargeMCBToDataRuns(&AttrContext->DataRunsMCB, RunBuffer, Vcb->NtfsInfo.BytesPerCluster, &RunBufferSize);
// Get the amount of free space between the start of the of the first data run and the attribute end - DataRunMaxLength = AttrContext->Record.Length - AttrContext->Record.NonResident.MappingPairsOffset; + DataRunMaxLength = AttrContext->pRecord->Length - AttrContext->pRecord->NonResident.MappingPairsOffset;
// Do we need to extend the attribute (or convert to attribute list)? if (DataRunMaxLength < RunBufferSize) { PNTFS_ATTR_RECORD NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + NextAttributeOffset); + PNTFS_ATTR_RECORD NewRecord; + DataRunMaxLength += Vcb->NtfsInfo.BytesPerFileRecord - NextAttributeOffset - (sizeof(ULONG) * 2);
// Can we move the end of the attribute? @@ -363,12 +365,22 @@ AddRun(PNTFS_VCB Vcb, }
// calculate position of end markers - NextAttributeOffset = AttrOffset + AttrContext->Record.NonResident.MappingPairsOffset + RunBufferSize; + NextAttributeOffset = AttrOffset + AttrContext->pRecord->NonResident.MappingPairsOffset + RunBufferSize; NextAttributeOffset = ALIGN_UP_BY(NextAttributeOffset, ATTR_RECORD_ALIGNMENT);
- // Update the length + // Update the length of the destination attribute DestinationAttribute->Length = NextAttributeOffset - AttrOffset; - AttrContext->Record.Length = DestinationAttribute->Length; + + // Create a new copy of the attribute + NewRecord = ExAllocatePoolWithTag(NonPagedPool, DestinationAttribute->Length, TAG_NTFS); + RtlCopyMemory(NewRecord, AttrContext->pRecord, AttrContext->pRecord->Length); + NewRecord->Length = DestinationAttribute->Length; + + // Free the old copy of the attribute, which won't be large enough + ExFreePoolWithTag(AttrContext->pRecord, TAG_NTFS); + + // Set the attribute context's record to the new copy + AttrContext->pRecord = NewRecord;
// End the file record NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + NextAttributeOffset); @@ -377,14 +389,19 @@ AddRun(PNTFS_VCB Vcb,
// Update HighestVCN DestinationAttribute->NonResident.HighestVCN = - AttrContext->Record.NonResident.HighestVCN = max(NextVBN - 1 + RunLength, - AttrContext->Record.NonResident.HighestVCN); + AttrContext->pRecord->NonResident.HighestVCN = max(NextVBN - 1 + RunLength, + AttrContext->pRecord->NonResident.HighestVCN);
// Write data runs to destination attribute RtlCopyMemory((PVOID)((ULONG_PTR)DestinationAttribute + DestinationAttribute->NonResident.MappingPairsOffset), RunBuffer, RunBufferSize);
+ // Update the attribute copy in the attribute context + RtlCopyMemory((PVOID)((ULONG_PTR)AttrContext->pRecord + AttrContext->pRecord->NonResident.MappingPairsOffset), + RunBuffer, + RunBufferSize); + // Update the file record Status = UpdateFileRecord(Vcb, AttrContext->FileMFTIndex, FileRecord);
@@ -723,7 +740,7 @@ FreeClusters(PNTFS_VCB Vcb, ULONG ClustersLeftToFree = ClustersToFree;
PNTFS_ATTR_RECORD DestinationAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + AttrOffset); - ULONG NextAttributeOffset = AttrOffset + AttrContext->Record.Length; + ULONG NextAttributeOffset = AttrOffset + AttrContext->pRecord->Length; PNTFS_ATTR_RECORD NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + NextAttributeOffset);
PUCHAR RunBuffer; @@ -736,7 +753,7 @@ FreeClusters(PNTFS_VCB Vcb, RTL_BITMAP Bitmap; ULONG LengthWritten;
- if (!AttrContext->Record.IsNonResident) + if (!AttrContext->pRecord->IsNonResident) { return STATUS_INVALID_PARAMETER; } @@ -767,7 +784,7 @@ FreeClusters(PNTFS_VCB Vcb, return 0; }
- BitmapDataSize = AttributeDataLength(&DataContext->Record); + BitmapDataSize = AttributeDataLength(DataContext->pRecord); BitmapDataSize = min(BitmapDataSize, ULONG_MAX); ASSERT((BitmapDataSize * 8) >= Vcb->NtfsInfo.ClusterCount); BitmapData = ExAllocatePoolWithTag(NonPagedPool, ROUND_UP(BitmapDataSize, Vcb->NtfsInfo.BytesPerSector), TAG_NTFS); @@ -802,10 +819,10 @@ FreeClusters(PNTFS_VCB Vcb, // deallocate this cluster RtlClearBits(&Bitmap, LargeLbn, 1); } - FsRtlTruncateLargeMcb(&AttrContext->DataRunsMCB, AttrContext->Record.NonResident.HighestVCN); + FsRtlTruncateLargeMcb(&AttrContext->DataRunsMCB, AttrContext->pRecord->NonResident.HighestVCN);
// decrement HighestVCN, but don't let it go below 0 - AttrContext->Record.NonResident.HighestVCN = min(AttrContext->Record.NonResident.HighestVCN, AttrContext->Record.NonResident.HighestVCN - 1); + AttrContext->pRecord->NonResident.HighestVCN = min(AttrContext->pRecord->NonResident.HighestVCN, AttrContext->pRecord->NonResident.HighestVCN - 1); ClustersLeftToFree--; }
@@ -837,7 +854,7 @@ FreeClusters(PNTFS_VCB Vcb, ConvertLargeMCBToDataRuns(&AttrContext->DataRunsMCB, RunBuffer, Vcb->NtfsInfo.BytesPerCluster, &RunBufferSize);
// Update HighestVCN - DestinationAttribute->NonResident.HighestVCN = AttrContext->Record.NonResident.HighestVCN; + DestinationAttribute->NonResident.HighestVCN = AttrContext->pRecord->NonResident.HighestVCN;
// Write data runs to destination attribute RtlCopyMemory((PVOID)((ULONG_PTR)DestinationAttribute + DestinationAttribute->NonResident.MappingPairsOffset), @@ -848,9 +865,12 @@ FreeClusters(PNTFS_VCB Vcb, if (NextAttribute->Type == AttributeEnd) { // update attribute length - AttrContext->Record.Length = ALIGN_UP_BY(AttrContext->Record.NonResident.MappingPairsOffset + RunBufferSize, + DestinationAttribute->Length = ALIGN_UP_BY(AttrContext->pRecord->NonResident.MappingPairsOffset + RunBufferSize, ATTR_RECORD_ALIGNMENT); - DestinationAttribute->Length = AttrContext->Record.Length; + + ASSERT(DestinationAttribute->Length <= AttrContext->pRecord->Length); + + AttrContext->pRecord->Length = DestinationAttribute->Length;
// write end markers NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)DestinationAttribute + DestinationAttribute->Length); @@ -893,7 +913,7 @@ InternalReadNonResidentAttributes(PFIND_ATTR_CONTXT Context) }
ListContext = PrepareAttributeContext(Attribute); - ListSize = AttributeDataLength(&ListContext->Record); + ListSize = AttributeDataLength(ListContext->pRecord); if (ListSize > 0xFFFFFFFF) { ReleaseAttributeContext(ListContext); diff --git a/drivers/filesystems/ntfs/btree.c b/drivers/filesystems/ntfs/btree.c index c1a907e8fe..dbbf3f9f87 100644 --- a/drivers/filesystems/ntfs/btree.c +++ b/drivers/filesystems/ntfs/btree.c @@ -41,7 +41,7 @@ PrintAllVCNs(PDEVICE_EXTENSION Vcb, { ULONGLONG CurrentOffset = 0; PINDEX_BUFFER CurrentNode, Buffer; - ULONGLONG BufferSize = AttributeDataLength(&IndexAllocationContext->Record); + ULONGLONG BufferSize = AttributeDataLength(IndexAllocationContext->pRecord); ULONG BytesRead; ULONGLONG i; int Count = 0; @@ -393,7 +393,7 @@ CreateBTreeFromIndex(PDEVICE_EXTENSION Vcb, Tree->RootNode = RootNode;
// Make sure we won't try reading past the attribute-end - if (FIELD_OFFSET(INDEX_ROOT_ATTRIBUTE, Header) + IndexRoot->Header.TotalSizeOfEntries > IndexRootContext->Record.Resident.ValueLength) + if (FIELD_OFFSET(INDEX_ROOT_ATTRIBUTE, Header) + IndexRoot->Header.TotalSizeOfEntries > IndexRootContext->pRecord->Resident.ValueLength) { DPRINT1("Filesystem corruption detected!\n"); DestroyBTree(Tree); diff --git a/drivers/filesystems/ntfs/dirctl.c b/drivers/filesystems/ntfs/dirctl.c index 98294b4791..61316cb77d 100644 --- a/drivers/filesystems/ntfs/dirctl.c +++ b/drivers/filesystems/ntfs/dirctl.c @@ -49,8 +49,8 @@ NtfsGetFileSize(PDEVICE_EXTENSION DeviceExt, Status = FindAttribute(DeviceExt, FileRecord, AttributeData, Stream, StreamLength, &DataContext, NULL); if (NT_SUCCESS(Status)) { - Size = AttributeDataLength(&DataContext->Record); - Allocated = AttributeAllocatedLength(&DataContext->Record); + Size = AttributeDataLength(DataContext->pRecord); + Allocated = AttributeAllocatedLength(DataContext->pRecord); ReleaseAttributeContext(DataContext); }
diff --git a/drivers/filesystems/ntfs/fcb.c b/drivers/filesystems/ntfs/fcb.c index fe79511bb3..f8057ee2ff 100644 --- a/drivers/filesystems/ntfs/fcb.c +++ b/drivers/filesystems/ntfs/fcb.c @@ -756,7 +756,7 @@ NtfsReadFCBAttribute(PNTFS_VCB Vcb, return Status; }
- AttrLength = AttributeDataLength(&AttrCtxt->Record); + AttrLength = AttributeDataLength(AttrCtxt->pRecord); *Data = ExAllocatePoolWithTag(NonPagedPool, AttrLength, TAG_NTFS); if (*Data == NULL) { diff --git a/drivers/filesystems/ntfs/finfo.c b/drivers/filesystems/ntfs/finfo.c index 37debba2ca..fb7df5f4d4 100644 --- a/drivers/filesystems/ntfs/finfo.c +++ b/drivers/filesystems/ntfs/finfo.c @@ -631,7 +631,7 @@ NtfsSetEndOfFile(PNTFS_FCB Fcb, }
// Get the size of the data attribute - CurrentFileSize.QuadPart = AttributeDataLength(&DataContext->Record); + CurrentFileSize.QuadPart = AttributeDataLength(DataContext->pRecord);
// Are we enlarging the attribute? if (NewFileSize->QuadPart > CurrentFileSize.QuadPart) @@ -673,7 +673,7 @@ NtfsSetEndOfFile(PNTFS_FCB Fcb, FileName.Length = FileNameAttribute->NameLength * sizeof(WCHAR); FileName.MaximumLength = FileName.Length;
- AllocationSize = AttributeAllocatedLength(&DataContext->Record); + AllocationSize = AttributeAllocatedLength(DataContext->pRecord);
Status = UpdateFileNameRecord(Fcb->Vcb, ParentMFTId, diff --git a/drivers/filesystems/ntfs/fsctl.c b/drivers/filesystems/ntfs/fsctl.c index 8acdd64e16..76337ec448 100644 --- a/drivers/filesystems/ntfs/fsctl.c +++ b/drivers/filesystems/ntfs/fsctl.c @@ -341,9 +341,9 @@ NtfsGetVolumeData(PDEVICE_OBJECT DeviceObject, /* Get volume name */ Status = FindAttribute(DeviceExt, VolumeRecord, AttributeVolumeName, L"", 0, &AttrCtxt, NULL);
- if (NT_SUCCESS(Status) && AttrCtxt->Record.Resident.ValueLength != 0) + if (NT_SUCCESS(Status) && AttrCtxt->pRecord->Resident.ValueLength != 0) { - Attribute = &AttrCtxt->Record; + Attribute = AttrCtxt->pRecord; DPRINT("Data length %lu\n", AttributeDataLength(Attribute)); NtfsInfo->VolumeLabelLength = min (Attribute->Resident.ValueLength, MAXIMUM_VOLUME_LABEL_LENGTH); @@ -382,9 +382,9 @@ NtfsGetVolumeData(PDEVICE_OBJECT DeviceObject, /* Get volume information */ Status = FindAttribute(DeviceExt, VolumeRecord, AttributeVolumeInformation, L"", 0, &AttrCtxt, NULL);
- if (NT_SUCCESS(Status) && AttrCtxt->Record.Resident.ValueLength != 0) + if (NT_SUCCESS(Status) && AttrCtxt->pRecord->Resident.ValueLength != 0) { - Attribute = &AttrCtxt->Record; + Attribute = AttrCtxt->pRecord; DPRINT("Data length %lu\n", AttributeDataLength (Attribute)); VolumeInfo = (PVOID)((ULONG_PTR)Attribute + Attribute->Resident.ValueOffset);
diff --git a/drivers/filesystems/ntfs/mft.c b/drivers/filesystems/ntfs/mft.c index 83c966972a..23f802dfca 100644 --- a/drivers/filesystems/ntfs/mft.c +++ b/drivers/filesystems/ntfs/mft.c @@ -42,15 +42,32 @@ PrepareAttributeContext(PNTFS_ATTR_RECORD AttrRecord) PNTFS_ATTR_CONTEXT Context;
Context = ExAllocatePoolWithTag(NonPagedPool, - FIELD_OFFSET(NTFS_ATTR_CONTEXT, Record) + AttrRecord->Length, + sizeof(NTFS_ATTR_CONTEXT), TAG_NTFS); - RtlCopyMemory(&Context->Record, AttrRecord, AttrRecord->Length); + if(!Context) + { + DPRINT1("Error: Unable to allocate memory for context!\n"); + return NULL; + } + + // Allocate memory for a copy of the attribute + Context->pRecord = ExAllocatePoolWithTag(NonPagedPool, AttrRecord->Length, TAG_NTFS); + if(!Context->pRecord) + { + DPRINT1("Error: Unable to allocate memory for attribute record!\n"); + ExFreePoolWithTag(Context, TAG_NTFS); + return NULL; + } + + // Copy the attribute + RtlCopyMemory(Context->pRecord, AttrRecord, AttrRecord->Length); + if (AttrRecord->IsNonResident) { LONGLONG DataRunOffset; ULONGLONG DataRunLength; ULONGLONG NextVBN = 0; - PUCHAR DataRun = (PUCHAR)&Context->Record + Context->Record.NonResident.MappingPairsOffset; + PUCHAR DataRun = (PUCHAR)((ULONG_PTR)Context->pRecord + Context->pRecord->NonResident.MappingPairsOffset);
Context->CacheRun = DataRun; Context->CacheRunOffset = 0; @@ -74,6 +91,7 @@ PrepareAttributeContext(PNTFS_ATTR_RECORD AttrRecord) if (!NT_SUCCESS(ConvertDataRunsToLargeMCB(DataRun, &Context->DataRunsMCB, &NextVBN))) { DPRINT1("Unable to convert data runs to MCB!\n"); + ExFreePoolWithTag(Context->pRecord, TAG_NTFS); ExFreePoolWithTag(Context, TAG_NTFS); return NULL; } @@ -86,11 +104,14 @@ PrepareAttributeContext(PNTFS_ATTR_RECORD AttrRecord) VOID ReleaseAttributeContext(PNTFS_ATTR_CONTEXT Context) { - if (Context->Record.IsNonResident) + if (Context->pRecord->IsNonResident) { FsRtlUninitializeLargeMcb(&Context->DataRunsMCB); }
+ if(Context->pRecord) + ExFreePoolWithTag(Context->pRecord, TAG_NTFS); + ExFreePoolWithTag(Context, TAG_NTFS); }
@@ -245,10 +266,10 @@ IncreaseMftSize(PDEVICE_EXTENSION Vcb, BOOLEAN CanWait) }
// Get size of Bitmap Attribute - BitmapSize.QuadPart = AttributeDataLength(&BitmapContext->Record); + BitmapSize.QuadPart = AttributeDataLength(BitmapContext->pRecord);
// Calculate the new mft size - DataSize.QuadPart = AttributeDataLength(&(Vcb->MFTContext->Record)) + DataSizeDifference; + DataSize.QuadPart = AttributeDataLength(Vcb->MFTContext->pRecord) + DataSizeDifference;
// Determine how many bytes will make up the bitmap BitmapBytes = DataSize.QuadPart / Vcb->NtfsInfo.BytesPerFileRecord / 8; @@ -301,7 +322,7 @@ IncreaseMftSize(PDEVICE_EXTENSION Vcb, BOOLEAN CanWait) { // Set the new bitmap size BitmapSize.QuadPart += BitmapSizeDifference; - if (BitmapContext->Record.IsNonResident) + if (BitmapContext->pRecord->IsNonResident) Status = SetNonResidentAttributeDataLength(Vcb, BitmapContext, BitmapOffset, Vcb->MasterFileTable, &BitmapSize); else Status = SetResidentAttributeDataLength(Vcb, BitmapContext, BitmapOffset, Vcb->MasterFileTable, &BitmapSize); @@ -348,7 +369,7 @@ IncreaseMftSize(PDEVICE_EXTENSION Vcb, BOOLEAN CanWait) return STATUS_SUCCESS; }
-VOID +NTSTATUS InternalSetResidentAttributeLength(PNTFS_ATTR_CONTEXT AttrContext, PFILE_RECORD_HEADER FileRecord, ULONG AttrOffset, @@ -356,32 +377,45 @@ InternalSetResidentAttributeLength(PNTFS_ATTR_CONTEXT AttrContext, { PNTFS_ATTR_RECORD Destination = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + AttrOffset); ULONG NextAttributeOffset; + USHORT ValueOffset;
DPRINT("InternalSetResidentAttributeLength( %p, %p, %lu, %lu )\n", AttrContext, FileRecord, AttrOffset, DataSize);
- ASSERT(!AttrContext->Record.IsNonResident); + ASSERT(!AttrContext->pRecord->IsNonResident);
- // update ValueLength Field - AttrContext->Record.Resident.ValueLength = + // Update ValueLength Field Destination->Resident.ValueLength = DataSize;
- // calculate the record length and end marker offset - AttrContext->Record.Length = - Destination->Length = DataSize + AttrContext->Record.Resident.ValueOffset; - NextAttributeOffset = AttrOffset + AttrContext->Record.Length; + // Calculate the record length and end marker offset + Destination->Length = ALIGN_UP_BY(DataSize + AttrContext->pRecord->Resident.ValueOffset, ATTR_RECORD_ALIGNMENT); + NextAttributeOffset = AttrOffset + Destination->Length;
- // Ensure NextAttributeOffset is aligned to an 8-byte boundary - if (NextAttributeOffset % 8 != 0) + // Ensure FileRecord has an up-to-date copy of the attribute + ValueOffset = AttrContext->pRecord->Resident.ValueOffset; + RtlCopyMemory((PCHAR)((ULONG_PTR)FileRecord + AttrOffset + ValueOffset), + (PCHAR)((ULONG_PTR)AttrContext->pRecord + ValueOffset), + min(DataSize, AttrContext->pRecord->Resident.ValueLength)); + + // Free the old copy of the attribute in the context, as it will be the wrong length + ExFreePoolWithTag(AttrContext->pRecord, TAG_NTFS); + + // Create a new copy of the attribute for the context + AttrContext->pRecord = ExAllocatePoolWithTag(NonPagedPool, Destination->Length, TAG_NTFS); + if (!AttrContext->pRecord) { - USHORT Padding = ATTR_RECORD_ALIGNMENT - (NextAttributeOffset % ATTR_RECORD_ALIGNMENT); - NextAttributeOffset += Padding; - AttrContext->Record.Length += Padding; - Destination->Length += Padding; + DPRINT1("Unable to allocate memory for attribute!\n"); + return STATUS_INSUFFICIENT_RESOURCES; } + RtlCopyMemory(AttrContext->pRecord, Destination, Destination->Length); + + // Ensure NextAttributeOffset is aligned to an 8-byte boundary + ASSERT(NextAttributeOffset % ATTR_RECORD_ALIGNMENT == 0);
// advance Destination to the final "attribute" and set the file record end Destination = (PNTFS_ATTR_RECORD)((ULONG_PTR)Destination + Destination->Length); SetFileRecordEnd(FileRecord, Destination, FILE_RECORD_END); + + return STATUS_SUCCESS; }
/** @@ -408,7 +442,7 @@ SetAttributeDataLength(PFILE_OBJECT FileObject, DataSize->QuadPart);
// are we truncating the file? - if (DataSize->QuadPart < AttributeDataLength(&AttrContext->Record)) + if (DataSize->QuadPart < AttributeDataLength(AttrContext->pRecord)) { if (!MmCanFileBeTruncated(FileObject->SectionObjectPointer, DataSize)) { @@ -417,7 +451,7 @@ SetAttributeDataLength(PFILE_OBJECT FileObject, } }
- if (AttrContext->Record.IsNonResident) + if (AttrContext->pRecord->IsNonResident) { Status = SetNonResidentAttributeDataLength(Fcb->Vcb, AttrContext, @@ -448,8 +482,8 @@ SetAttributeDataLength(PFILE_OBJECT FileObject,
if (NT_SUCCESS(Status)) { - if (AttrContext->Record.IsNonResident) - Fcb->RFCB.AllocationSize.QuadPart = AttrContext->Record.NonResident.AllocatedSize; + if (AttrContext->pRecord->IsNonResident) + Fcb->RFCB.AllocationSize.QuadPart = AttrContext->pRecord->NonResident.AllocatedSize; else Fcb->RFCB.AllocationSize = *DataSize; Fcb->RFCB.FileSize = *DataSize; @@ -538,12 +572,12 @@ SetNonResidentAttributeDataLength(PDEVICE_EXTENSION Vcb, ULONG BytesPerCluster = Vcb->NtfsInfo.BytesPerCluster; ULONGLONG AllocationSize = ROUND_UP(DataSize->QuadPart, BytesPerCluster); PNTFS_ATTR_RECORD DestinationAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + AttrOffset); - ULONG ExistingClusters = AttrContext->Record.NonResident.AllocatedSize / BytesPerCluster; + ULONG ExistingClusters = AttrContext->pRecord->NonResident.AllocatedSize / BytesPerCluster;
- ASSERT(AttrContext->Record.IsNonResident); + ASSERT(AttrContext->pRecord->IsNonResident);
// do we need to increase the allocation size? - if (AttrContext->Record.NonResident.AllocatedSize < AllocationSize) + if (AttrContext->pRecord->NonResident.AllocatedSize < AllocationSize) { ULONG ClustersNeeded = (AllocationSize / BytesPerCluster) - ExistingClusters; LARGE_INTEGER LastClusterInDataRun; @@ -557,7 +591,7 @@ SetNonResidentAttributeDataLength(PDEVICE_EXTENSION Vcb, else { if (!FsRtlLookupLargeMcbEntry(&AttrContext->DataRunsMCB, - (LONGLONG)AttrContext->Record.NonResident.HighestVCN, + (LONGLONG)AttrContext->pRecord->NonResident.HighestVCN, (PLONGLONG)&LastClusterInDataRun.QuadPart, NULL, NULL, @@ -567,13 +601,13 @@ SetNonResidentAttributeDataLength(PDEVICE_EXTENSION Vcb, DPRINT1("Error looking up final large MCB entry!\n");
// Most likely, HighestVCN went above the largest mapping - DPRINT1("Highest VCN of record: %I64u\n", AttrContext->Record.NonResident.HighestVCN); + DPRINT1("Highest VCN of record: %I64u\n", AttrContext->pRecord->NonResident.HighestVCN); return STATUS_INVALID_PARAMETER; } }
DPRINT("LastClusterInDataRun: %I64u\n", LastClusterInDataRun.QuadPart); - DPRINT("Highest VCN of record: %I64u\n", AttrContext->Record.NonResident.HighestVCN); + DPRINT("Highest VCN of record: %I64u\n", AttrContext->pRecord->NonResident.HighestVCN);
while (ClustersNeeded > 0) { @@ -601,7 +635,7 @@ SetNonResidentAttributeDataLength(PDEVICE_EXTENSION Vcb, LastClusterInDataRun.LowPart = NextAssignedCluster + AssignedClusters - 1; } } - else if (AttrContext->Record.NonResident.AllocatedSize > AllocationSize) + else if (AttrContext->pRecord->NonResident.AllocatedSize > AllocationSize) { // shrink allocation size ULONG ClustersToFree = ExistingClusters - (AllocationSize / BytesPerCluster); @@ -610,9 +644,9 @@ SetNonResidentAttributeDataLength(PDEVICE_EXTENSION Vcb,
// TODO: is the file compressed, encrypted, or sparse?
- AttrContext->Record.NonResident.AllocatedSize = AllocationSize; - AttrContext->Record.NonResident.DataSize = DataSize->QuadPart; - AttrContext->Record.NonResident.InitializedSize = DataSize->QuadPart; + AttrContext->pRecord->NonResident.AllocatedSize = AllocationSize; + AttrContext->pRecord->NonResident.DataSize = DataSize->QuadPart; + AttrContext->pRecord->NonResident.InitializedSize = DataSize->QuadPart;
DestinationAttribute->NonResident.AllocatedSize = AllocationSize; DestinationAttribute->NonResident.DataSize = DataSize->QuadPart; @@ -667,18 +701,18 @@ SetResidentAttributeDataLength(PDEVICE_EXTENSION Vcb, NTSTATUS Status;
// find the next attribute - ULONG NextAttributeOffset = AttrOffset + AttrContext->Record.Length; + ULONG NextAttributeOffset = AttrOffset + AttrContext->pRecord->Length; PNTFS_ATTR_RECORD NextAttribute = (PNTFS_ATTR_RECORD)((PCHAR)FileRecord + NextAttributeOffset);
- ASSERT(!AttrContext->Record.IsNonResident); + ASSERT(!AttrContext->pRecord->IsNonResident);
//NtfsDumpFileAttributes(Vcb, FileRecord);
// Do we need to increase the data length? - if (DataSize->QuadPart > AttrContext->Record.Resident.ValueLength) + if (DataSize->QuadPart > AttrContext->pRecord->Resident.ValueLength) { // There's usually padding at the end of a record. Do we need to extend past it? - ULONG MaxValueLength = AttrContext->Record.Length - AttrContext->Record.Resident.ValueOffset; + ULONG MaxValueLength = AttrContext->pRecord->Length - AttrContext->pRecord->Resident.ValueOffset; if (MaxValueLength < DataSize->LowPart) { // If this is the last attribute, we could move the end marker to the very end of the file record @@ -688,14 +722,16 @@ SetResidentAttributeDataLength(PDEVICE_EXTENSION Vcb, { // convert attribute to non-resident PNTFS_ATTR_RECORD Destination = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + AttrOffset); + PNTFS_ATTR_RECORD NewRecord; LARGE_INTEGER AttribDataSize; PVOID AttribData; + ULONG NewRecordLength; ULONG EndAttributeOffset; ULONG LengthWritten;
DPRINT1("Converting attribute to non-resident.\n");
- AttribDataSize.QuadPart = AttrContext->Record.Resident.ValueLength; + AttribDataSize.QuadPart = AttrContext->pRecord->Resident.ValueLength;
// Is there existing data we need to back-up? if (AttribDataSize.QuadPart > 0) @@ -719,23 +755,43 @@ SetResidentAttributeDataLength(PDEVICE_EXTENSION Vcb,
// Start by turning this attribute into a 0-length, non-resident attribute, then enlarge it.
+ // The size of a 0-length, non-resident attribute will be 0x41 + the size of the attribute name, aligned to an 8-byte boundary + NewRecordLength = ALIGN_UP_BY(0x41 + (AttrContext->pRecord->NameLength * sizeof(WCHAR)), ATTR_RECORD_ALIGNMENT); + + // Create a new attribute record that will store the 0-length, non-resident attribute + NewRecord = ExAllocatePoolWithTag(NonPagedPool, NewRecordLength, TAG_NTFS); + // Zero out the NonResident structure - RtlZeroMemory(&AttrContext->Record.NonResident.LowestVCN, - FIELD_OFFSET(NTFS_ATTR_RECORD, NonResident.CompressedSize) - FIELD_OFFSET(NTFS_ATTR_RECORD, NonResident.LowestVCN)); - RtlZeroMemory(&Destination->NonResident.LowestVCN, - FIELD_OFFSET(NTFS_ATTR_RECORD, NonResident.CompressedSize) - FIELD_OFFSET(NTFS_ATTR_RECORD, NonResident.LowestVCN)); + RtlZeroMemory(NewRecord, NewRecordLength); + + // Copy the data that's common to both non-resident and resident attributes + RtlCopyMemory(NewRecord, AttrContext->pRecord, FIELD_OFFSET(NTFS_ATTR_RECORD, Resident.ValueLength)); + + // if there's a name + if (AttrContext->pRecord->NameLength != 0) + { + // copy the name + // An attribute name will be located at offset 0x18 for a resident attribute, 0x40 for non-resident + RtlCopyMemory((PCHAR)((ULONG_PTR)NewRecord + 0x40), + (PCHAR)((ULONG_PTR)AttrContext->pRecord + 0x18), + AttrContext->pRecord->NameLength * sizeof(WCHAR)); + }
- // update the mapping pairs offset, which will be 0x40 + length in bytes of the name - AttrContext->Record.NonResident.MappingPairsOffset = Destination->NonResident.MappingPairsOffset = 0x40 + (Destination->NameLength * 2); + // update the mapping pairs offset, which will be 0x40 (size of a non-resident header) + length in bytes of the name + NewRecord->NonResident.MappingPairsOffset = 0x40 + (AttrContext->pRecord->NameLength * sizeof(WCHAR));
// update the end of the file record // calculate position of end markers (1 byte for empty data run) - EndAttributeOffset = AttrOffset + AttrContext->Record.NonResident.MappingPairsOffset + 1; + EndAttributeOffset = AttrOffset + NewRecord->NonResident.MappingPairsOffset + 1; EndAttributeOffset = ALIGN_UP_BY(EndAttributeOffset, ATTR_RECORD_ALIGNMENT);
// Update the length - Destination->Length = EndAttributeOffset - AttrOffset; - AttrContext->Record.Length = Destination->Length; + NewRecord->Length = EndAttributeOffset - AttrOffset; + + ASSERT(NewRecord->Length == NewRecordLength); + + // Copy the new attribute record into the file record + RtlCopyMemory(Destination, NewRecord, NewRecord->Length);
// Update the file record end SetFileRecordEnd(FileRecord, @@ -756,7 +812,7 @@ SetResidentAttributeDataLength(PDEVICE_EXTENSION Vcb, } _SEH2_END;
// Mark the attribute as non-resident (we wait until after we know the LargeMcb was initialized) - AttrContext->Record.IsNonResident = Destination->IsNonResident = 1; + NewRecord->IsNonResident = Destination->IsNonResident = 1;
// Update file record on disk Status = UpdateFileRecord(Vcb, AttrContext->FileMFTIndex, FileRecord); @@ -768,6 +824,10 @@ SetResidentAttributeDataLength(PDEVICE_EXTENSION Vcb, return Status; }
+ // Now we need to free the old copy of the attribute record in the context and replace it with the new one + ExFreePoolWithTag(AttrContext->pRecord, TAG_NTFS); + AttrContext->pRecord = NewRecord; + // Now we can treat the attribute as non-resident and enlarge it normally Status = SetNonResidentAttributeDataLength(Vcb, AttrContext, AttrOffset, FileRecord, DataSize); if (!NT_SUCCESS(Status)) @@ -795,7 +855,7 @@ SetResidentAttributeDataLength(PDEVICE_EXTENSION Vcb, } } } - else if (DataSize->LowPart < AttrContext->Record.Resident.ValueLength) + else if (DataSize->LowPart < AttrContext->pRecord->Resident.ValueLength) { // we need to decrease the length if (NextAttribute->Type != AttributeEnd) @@ -806,8 +866,8 @@ SetResidentAttributeDataLength(PDEVICE_EXTENSION Vcb, }
// set the new length of the resident attribute (if we didn't migrate it) - if (!AttrContext->Record.IsNonResident) - InternalSetResidentAttributeLength(AttrContext, FileRecord, AttrOffset, DataSize->LowPart); + if (!AttrContext->pRecord->IsNonResident) + return InternalSetResidentAttributeLength(AttrContext, FileRecord, AttrOffset, DataSize->LowPart);
return STATUS_SUCCESS; } @@ -832,13 +892,19 @@ ReadAttribute(PDEVICE_EXTENSION Vcb, //TEMPTEMP PUCHAR TempBuffer;
- if (!Context->Record.IsNonResident) + if (!Context->pRecord->IsNonResident) { - if (Offset > Context->Record.Resident.ValueLength) + // We need to truncate Offset to a ULONG for pointer arithmetic + // The check below should ensure that Offset is well within the range of 32 bits + ULONG LittleOffset = (ULONG)Offset; + + // Ensure that offset isn't beyond the end of the attribute + if (Offset > Context->pRecord->Resident.ValueLength) return 0; - if (Offset + Length > Context->Record.Resident.ValueLength) - Length = (ULONG)(Context->Record.Resident.ValueLength - Offset); - RtlCopyMemory(Buffer, (PCHAR)&Context->Record + Context->Record.Resident.ValueOffset + Offset, Length); + if (Offset + Length > Context->pRecord->Resident.ValueLength) + Length = (ULONG)(Context->pRecord->Resident.ValueLength - Offset); + + RtlCopyMemory(Buffer, (PVOID)((ULONG_PTR)Context->pRecord + Context->pRecord->Resident.ValueOffset + LittleOffset), Length); return Length; }
@@ -996,7 +1062,7 @@ ReadAttribute(PDEVICE_EXTENSION Vcb, } /* if Disk */
// TEMPTEMP - if (Context->Record.IsNonResident) + if (Context->pRecord->IsNonResident) ExFreePoolWithTag(TempBuffer, TAG_NTFS);
Context->CacheRun = DataRun; @@ -1073,13 +1139,13 @@ WriteAttribute(PDEVICE_EXTENSION Vcb, *RealLengthWritten = 0;
// is this a resident attribute? - if (!Context->Record.IsNonResident) + if (!Context->pRecord->IsNonResident) { ULONG AttributeOffset; PNTFS_ATTR_CONTEXT FoundContext; PFILE_RECORD_HEADER FileRecord;
- if (Offset + Length > Context->Record.Resident.ValueLength) + if (Offset + Length > Context->pRecord->Resident.ValueLength) { DPRINT1("DRIVER ERROR: Attribute is too small!\n"); return STATUS_INVALID_PARAMETER; @@ -1098,9 +1164,9 @@ WriteAttribute(PDEVICE_EXTENSION Vcb,
// find where to write the attribute data to Status = FindAttribute(Vcb, FileRecord, - Context->Record.Type, - (PCWSTR)((PCHAR)&Context->Record + Context->Record.NameOffset), - Context->Record.NameLength, + Context->pRecord->Type, + (PCWSTR)((ULONG_PTR)Context->pRecord + Context->pRecord->NameOffset), + Context->pRecord->NameLength, &FoundContext, &AttributeOffset);
@@ -1111,8 +1177,8 @@ WriteAttribute(PDEVICE_EXTENSION Vcb, return Status; }
- DPRINT("Offset: %I64u, AttributeOffset: %u, ValueOffset: %u\n", Offset, AttributeOffset, Context->Record.Resident.ValueLength); - Offset += AttributeOffset + Context->Record.Resident.ValueOffset; + DPRINT("Offset: %I64u, AttributeOffset: %u, ValueOffset: %u\n", Offset, AttributeOffset, Context->pRecord->Resident.ValueLength); + Offset += AttributeOffset + Context->pRecord->Resident.ValueOffset;
if (Offset + Length > Vcb->NtfsInfo.BytesPerFileRecord) { @@ -1320,7 +1386,7 @@ WriteAttribute(PDEVICE_EXTENSION Vcb, } // end while (Length > 0) [more data to write]
// TEMPTEMP - if (Context->Record.IsNonResident) + if (Context->pRecord->IsNonResident) ExFreePoolWithTag(TempBuffer, TAG_NTFS);
Context->CacheRun = DataRun; @@ -1419,7 +1485,7 @@ UpdateFileNameRecord(PDEVICE_EXTENSION Vcb, return STATUS_INSUFFICIENT_RESOURCES; }
- Status = ReadAttribute(Vcb, IndexRootCtx, 0, IndexRecord, AttributeDataLength(&IndexRootCtx->Record)); + Status = ReadAttribute(Vcb, IndexRootCtx, 0, IndexRecord, AttributeDataLength(IndexRootCtx->pRecord)); if (!NT_SUCCESS(Status)) { DPRINT1("ERROR: Failed to read Index Root!\n"); @@ -1453,7 +1519,7 @@ UpdateFileNameRecord(PDEVICE_EXTENSION Vcb, { // we need to write the index root attribute back to disk ULONG LengthWritten; - Status = WriteAttribute(Vcb, IndexRootCtx, 0, (PUCHAR)IndexRecord, AttributeDataLength(&IndexRootCtx->Record), &LengthWritten); + Status = WriteAttribute(Vcb, IndexRootCtx, 0, (PUCHAR)IndexRecord, AttributeDataLength(IndexRootCtx->pRecord), &LengthWritten); if (!NT_SUCCESS(Status)) { DPRINT1("ERROR: Couldn't update Index Root!\n"); @@ -1551,7 +1617,7 @@ UpdateIndexEntryFileNameSize(PDEVICE_EXTENSION Vcb, return Status; }
- IndexAllocationSize = AttributeDataLength(&IndexAllocationCtx->Record); + IndexAllocationSize = AttributeDataLength(IndexAllocationCtx->pRecord); Status = STATUS_OBJECT_PATH_NOT_FOUND; for (RecordOffset = 0; RecordOffset < IndexAllocationSize; RecordOffset += IndexBlockSize) { @@ -1747,7 +1813,7 @@ AddNewMftEntry(PFILE_RECORD_HEADER FileRecord, }
// allocate a buffer for the $Bitmap attribute - BitmapDataSize = AttributeDataLength(&BitmapContext->Record); + BitmapDataSize = AttributeDataLength(BitmapContext->pRecord); BitmapData = ExAllocatePoolWithTag(NonPagedPool, BitmapDataSize, TAG_NTFS); if (!BitmapData) { @@ -1772,7 +1838,7 @@ AddNewMftEntry(PFILE_RECORD_HEADER FileRecord, BitmapData[2] = 0xff;
// Calculate bit count - BitmapBits.QuadPart = AttributeDataLength(&(DeviceExt->MFTContext->Record)) / + BitmapBits.QuadPart = AttributeDataLength(DeviceExt->MFTContext->pRecord) / DeviceExt->NtfsInfo.BytesPerFileRecord; if (BitmapBits.HighPart != 0) { @@ -1942,12 +2008,12 @@ NtfsAddFilenameToDirectory(PDEVICE_EXTENSION DeviceExt, // Find the maximum index size given what the file record can hold MaxIndexSize = DeviceExt->NtfsInfo.BytesPerFileRecord - IndexRootOffset - - IndexRootContext->Record.Resident.ValueOffset + - IndexRootContext->pRecord->Resident.ValueOffset - FIELD_OFFSET(INDEX_ROOT_ATTRIBUTE, Header) - (sizeof(ULONG) * 2);
// Allocate memory for the index root data - I30IndexRootLength = AttributeDataLength(&IndexRootContext->Record); + I30IndexRootLength = AttributeDataLength(IndexRootContext->pRecord); I30IndexRoot = ExAllocatePoolWithTag(NonPagedPool, I30IndexRootLength, TAG_NTFS); if (!I30IndexRoot) { @@ -2035,7 +2101,7 @@ NtfsAddFilenameToDirectory(PDEVICE_EXTENSION DeviceExt, // $ATTRIBUTE_LIST's. AttributeLength = NewIndexRoot->Header.AllocatedSize + FIELD_OFFSET(INDEX_ROOT_ATTRIBUTE, Header);
- if (AttributeLength != IndexRootContext->Record.Resident.ValueLength) + if (AttributeLength != IndexRootContext->pRecord->Resident.ValueLength) { DestinationAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)ParentFileRecord + IndexRootOffset);
@@ -2052,10 +2118,20 @@ NtfsAddFilenameToDirectory(PDEVICE_EXTENSION DeviceExt, }
// Update the length of the attribute in the file record of the parent directory - InternalSetResidentAttributeLength(IndexRootContext, - ParentFileRecord, - IndexRootOffset, - AttributeLength); + Status = InternalSetResidentAttributeLength(IndexRootContext, + ParentFileRecord, + IndexRootOffset, + AttributeLength); + if (!NT_SUCCESS(Status)) + { + ExFreePoolWithTag(NewIndexRoot, TAG_NTFS); + ReleaseAttributeContext(IndexRootContext); + ExFreePoolWithTag(I30IndexRoot, TAG_NTFS); + ExFreePoolWithTag(ParentFileRecord, TAG_NTFS); + DPRINT1("ERROR: Unable to set resident attribute length!\n"); + return Status; + } + }
NT_ASSERT(ParentFileRecord->BytesInUse <= DeviceExt->NtfsInfo.BytesPerFileRecord); @@ -2295,7 +2371,7 @@ BrowseIndexEntries(PDEVICE_EXTENSION Vcb, return Status; }
- IndexAllocationSize = AttributeDataLength(&IndexAllocationCtx->Record); + IndexAllocationSize = AttributeDataLength(IndexAllocationCtx->pRecord); Status = STATUS_OBJECT_PATH_NOT_FOUND; for (RecordOffset = 0; RecordOffset < IndexAllocationSize; RecordOffset += IndexBlockSize) { diff --git a/drivers/filesystems/ntfs/ntfs.h b/drivers/filesystems/ntfs/ntfs.h index 42168be1ab..668815ddd5 100644 --- a/drivers/filesystems/ntfs/ntfs.h +++ b/drivers/filesystems/ntfs/ntfs.h @@ -480,7 +480,7 @@ typedef struct _NTFS_ATTR_CONTEXT ULONGLONG CacheRunCurrentOffset; LARGE_MCB DataRunsMCB; ULONGLONG FileMFTIndex; - NTFS_ATTR_RECORD Record; + PNTFS_ATTR_RECORD pRecord; } NTFS_ATTR_CONTEXT, *PNTFS_ATTR_CONTEXT;
#define FCB_CACHE_INITIALIZED 0x0001 @@ -959,7 +959,7 @@ WriteAttribute(PDEVICE_EXTENSION Vcb, ULONGLONG AttributeDataLength(PNTFS_ATTR_RECORD AttrRecord);
-VOID +NTSTATUS InternalSetResidentAttributeLength(PNTFS_ATTR_CONTEXT AttrContext, PFILE_RECORD_HEADER FileRecord, ULONG AttrOffset, diff --git a/drivers/filesystems/ntfs/rw.c b/drivers/filesystems/ntfs/rw.c index cb4646495f..2c21f3a449 100644 --- a/drivers/filesystems/ntfs/rw.c +++ b/drivers/filesystems/ntfs/rw.c @@ -126,7 +126,7 @@ NtfsReadFile(PDEVICE_EXTENSION DeviceExt, return Status; }
- StreamSize = AttributeDataLength(&DataContext->Record); + StreamSize = AttributeDataLength(DataContext->pRecord); if (ReadOffset >= StreamSize) { DPRINT1("Reading beyond stream end!\n"); @@ -149,7 +149,7 @@ NtfsReadFile(PDEVICE_EXTENSION DeviceExt, /* do we need to extend RealLength by one sector? */ if (RealLength + RealReadOffset < ReadOffset + Length) { - if (RealReadOffset + RealLength + DeviceExt->NtfsInfo.BytesPerSector <= AttributeAllocatedLength(&DataContext->Record)) + if (RealReadOffset + RealLength + DeviceExt->NtfsInfo.BytesPerSector <= AttributeAllocatedLength(DataContext->pRecord)) RealLength += DeviceExt->NtfsInfo.BytesPerSector; }
@@ -413,7 +413,7 @@ NTSTATUS NtfsWriteFile(PDEVICE_EXTENSION DeviceExt, }
// Get the size of the stream on disk - StreamSize = AttributeDataLength(&DataContext->Record); + StreamSize = AttributeDataLength(DataContext->pRecord);
DPRINT("WriteOffset: %lu\tStreamSize: %I64u\n", WriteOffset, StreamSize);
@@ -442,7 +442,7 @@ NTSTATUS NtfsWriteFile(PDEVICE_EXTENSION DeviceExt, return Status; }
- AllocationSize = AttributeAllocatedLength(&DataContext->Record); + AllocationSize = AttributeAllocatedLength(DataContext->pRecord);
// now we need to update this file's size in every directory index entry that references it // TODO: put this code in its own function and adapt it to work with every filename / hardlink diff --git a/drivers/filesystems/ntfs/volinfo.c b/drivers/filesystems/ntfs/volinfo.c index 1a577d45e2..d1efa4c269 100644 --- a/drivers/filesystems/ntfs/volinfo.c +++ b/drivers/filesystems/ntfs/volinfo.c @@ -69,7 +69,7 @@ NtfsGetFreeClusters(PDEVICE_EXTENSION DeviceExt) return 0; }
- BitmapDataSize = AttributeDataLength(&DataContext->Record); + BitmapDataSize = AttributeDataLength(DataContext->pRecord); ASSERT((BitmapDataSize * 8) >= DeviceExt->NtfsInfo.ClusterCount); BitmapData = ExAllocatePoolWithTag(NonPagedPool, ROUND_UP(BitmapDataSize, DeviceExt->NtfsInfo.BytesPerSector), TAG_NTFS); if (BitmapData == NULL) @@ -144,7 +144,7 @@ NtfsAllocateClusters(PDEVICE_EXTENSION DeviceExt, return Status; }
- BitmapDataSize = AttributeDataLength(&DataContext->Record); + BitmapDataSize = AttributeDataLength(DataContext->pRecord); BitmapDataSize = min(BitmapDataSize, 0xffffffff); ASSERT((BitmapDataSize * 8) >= DeviceExt->NtfsInfo.ClusterCount); BitmapData = ExAllocatePoolWithTag(NonPagedPool, ROUND_UP(BitmapDataSize, DeviceExt->NtfsInfo.BytesPerSector), TAG_NTFS);