Author: tthompson
Date: Sun Aug 6 02:54:15 2017
New Revision: 75493
URL:
http://svn.reactos.org/svn/reactos?rev=75493&view=rev
Log:
[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.
Modified:
branches/GSoC_2016/NTFS/drivers/filesystems/ntfs/attrib.c
branches/GSoC_2016/NTFS/drivers/filesystems/ntfs/btree.c
branches/GSoC_2016/NTFS/drivers/filesystems/ntfs/dirctl.c
branches/GSoC_2016/NTFS/drivers/filesystems/ntfs/fcb.c
branches/GSoC_2016/NTFS/drivers/filesystems/ntfs/finfo.c
branches/GSoC_2016/NTFS/drivers/filesystems/ntfs/fsctl.c
branches/GSoC_2016/NTFS/drivers/filesystems/ntfs/mft.c
branches/GSoC_2016/NTFS/drivers/filesystems/ntfs/ntfs.h
branches/GSoC_2016/NTFS/drivers/filesystems/ntfs/rw.c
branches/GSoC_2016/NTFS/drivers/filesystems/ntfs/volinfo.c
Modified: branches/GSoC_2016/NTFS/drivers/filesystems/ntfs/attrib.c
URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2016/NTFS/drivers/filesyst…
==============================================================================
--- branches/GSoC_2016/NTFS/drivers/filesystems/ntfs/attrib.c [iso-8859-1] (original)
+++ branches/GSoC_2016/NTFS/drivers/filesystems/ntfs/attrib.c [iso-8859-1] Sun Aug 6
02:54:15 2017
@@ -303,17 +303,17 @@
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 @@
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 @@
}
// 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,12 +389,17 @@
// 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
@@ -723,7 +740,7 @@
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 @@
RTL_BITMAP Bitmap;
ULONG LengthWritten;
- if (!AttrContext->Record.IsNonResident)
+ if (!AttrContext->pRecord->IsNonResident)
{
return STATUS_INVALID_PARAMETER;
}
@@ -767,7 +784,7 @@
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 @@
// 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 @@
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 @@
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 @@
}
ListContext = PrepareAttributeContext(Attribute);
- ListSize = AttributeDataLength(&ListContext->Record);
+ ListSize = AttributeDataLength(ListContext->pRecord);
if (ListSize > 0xFFFFFFFF)
{
ReleaseAttributeContext(ListContext);
Modified: branches/GSoC_2016/NTFS/drivers/filesystems/ntfs/btree.c
URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2016/NTFS/drivers/filesyst…
==============================================================================
--- branches/GSoC_2016/NTFS/drivers/filesystems/ntfs/btree.c [iso-8859-1] (original)
+++ branches/GSoC_2016/NTFS/drivers/filesystems/ntfs/btree.c [iso-8859-1] Sun Aug 6
02:54:15 2017
@@ -41,7 +41,7 @@
{
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 @@
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);
Modified: branches/GSoC_2016/NTFS/drivers/filesystems/ntfs/dirctl.c
URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2016/NTFS/drivers/filesyst…
==============================================================================
--- branches/GSoC_2016/NTFS/drivers/filesystems/ntfs/dirctl.c [iso-8859-1] (original)
+++ branches/GSoC_2016/NTFS/drivers/filesystems/ntfs/dirctl.c [iso-8859-1] Sun Aug 6
02:54:15 2017
@@ -49,8 +49,8 @@
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);
}
Modified: branches/GSoC_2016/NTFS/drivers/filesystems/ntfs/fcb.c
URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2016/NTFS/drivers/filesyst…
==============================================================================
--- branches/GSoC_2016/NTFS/drivers/filesystems/ntfs/fcb.c [iso-8859-1] (original)
+++ branches/GSoC_2016/NTFS/drivers/filesystems/ntfs/fcb.c [iso-8859-1] Sun Aug 6
02:54:15 2017
@@ -756,7 +756,7 @@
return Status;
}
- AttrLength = AttributeDataLength(&AttrCtxt->Record);
+ AttrLength = AttributeDataLength(AttrCtxt->pRecord);
*Data = ExAllocatePoolWithTag(NonPagedPool, AttrLength, TAG_NTFS);
if (*Data == NULL)
{
Modified: branches/GSoC_2016/NTFS/drivers/filesystems/ntfs/finfo.c
URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2016/NTFS/drivers/filesyst…
==============================================================================
--- branches/GSoC_2016/NTFS/drivers/filesystems/ntfs/finfo.c [iso-8859-1] (original)
+++ branches/GSoC_2016/NTFS/drivers/filesystems/ntfs/finfo.c [iso-8859-1] Sun Aug 6
02:54:15 2017
@@ -631,7 +631,7 @@
}
// 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 @@
FileName.Length = FileNameAttribute->NameLength * sizeof(WCHAR);
FileName.MaximumLength = FileName.Length;
- AllocationSize = AttributeAllocatedLength(&DataContext->Record);
+ AllocationSize = AttributeAllocatedLength(DataContext->pRecord);
Status = UpdateFileNameRecord(Fcb->Vcb,
ParentMFTId,
Modified: branches/GSoC_2016/NTFS/drivers/filesystems/ntfs/fsctl.c
URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2016/NTFS/drivers/filesyst…
==============================================================================
--- branches/GSoC_2016/NTFS/drivers/filesystems/ntfs/fsctl.c [iso-8859-1] (original)
+++ branches/GSoC_2016/NTFS/drivers/filesystems/ntfs/fsctl.c [iso-8859-1] Sun Aug 6
02:54:15 2017
@@ -341,9 +341,9 @@
/* Get volume name */
Status = FindAttribute(DeviceExt, VolumeRecord, AttributeVolumeName, L"",
0, &AttrCtxt, NULL);
- if (NT_SUCCESS(Status) && AttrCtxt->Record.Resident.ValueLength != 0)
- {
- Attribute = &AttrCtxt->Record;
+ if (NT_SUCCESS(Status) && AttrCtxt->pRecord->Resident.ValueLength !=
0)
+ {
+ Attribute = AttrCtxt->pRecord;
DPRINT("Data length %lu\n", AttributeDataLength(Attribute));
NtfsInfo->VolumeLabelLength =
min (Attribute->Resident.ValueLength, MAXIMUM_VOLUME_LABEL_LENGTH);
@@ -382,9 +382,9 @@
/* Get volume information */
Status = FindAttribute(DeviceExt, VolumeRecord, AttributeVolumeInformation,
L"", 0, &AttrCtxt, NULL);
- if (NT_SUCCESS(Status) && AttrCtxt->Record.Resident.ValueLength != 0)
- {
- Attribute = &AttrCtxt->Record;
+ if (NT_SUCCESS(Status) && AttrCtxt->pRecord->Resident.ValueLength !=
0)
+ {
+ Attribute = AttrCtxt->pRecord;
DPRINT("Data length %lu\n", AttributeDataLength (Attribute));
VolumeInfo = (PVOID)((ULONG_PTR)Attribute + Attribute->Resident.ValueOffset);
Modified: branches/GSoC_2016/NTFS/drivers/filesystems/ntfs/mft.c
URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2016/NTFS/drivers/filesyst…
==============================================================================
--- branches/GSoC_2016/NTFS/drivers/filesystems/ntfs/mft.c [iso-8859-1] (original)
+++ branches/GSoC_2016/NTFS/drivers/filesystems/ntfs/mft.c [iso-8859-1] Sun Aug 6
02:54:15 2017
@@ -42,15 +42,32 @@
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 @@
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,10 +104,13 @@
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 @@
}
// 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 @@
{
// 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 @@
return STATUS_SUCCESS;
}
-VOID
+NTSTATUS
InternalSetResidentAttributeLength(PNTFS_ATTR_CONTEXT AttrContext,
PFILE_RECORD_HEADER FileRecord,
ULONG AttrOffset,
@@ -356,32 +377,45 @@
{
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);
-
- // update ValueLength Field
- AttrContext->Record.Resident.ValueLength =
+ ASSERT(!AttrContext->pRecord->IsNonResident);
+
+ // 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 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)
+ {
+ 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
- if (NextAttributeOffset % 8 != 0)
- {
- USHORT Padding = ATTR_RECORD_ALIGNMENT - (NextAttributeOffset %
ATTR_RECORD_ALIGNMENT);
- NextAttributeOffset += Padding;
- AttrContext->Record.Length += Padding;
- Destination->Length += Padding;
- }
+ 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 @@
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 @@
}
}
- if (AttrContext->Record.IsNonResident)
+ if (AttrContext->pRecord->IsNonResident)
{
Status = SetNonResidentAttributeDataLength(Fcb->Vcb,
AttrContext,
@@ -448,8 +482,8 @@
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 @@
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;
-
- ASSERT(AttrContext->Record.IsNonResident);
+ ULONG ExistingClusters = AttrContext->pRecord->NonResident.AllocatedSize /
BytesPerCluster;
+
+ 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 @@
else
{
if (!FsRtlLookupLargeMcbEntry(&AttrContext->DataRunsMCB,
-
(LONGLONG)AttrContext->Record.NonResident.HighestVCN,
+
(LONGLONG)AttrContext->pRecord->NonResident.HighestVCN,
(PLONGLONG)&LastClusterInDataRun.QuadPart,
NULL,
NULL,
@@ -567,13 +601,13 @@
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 @@
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 @@
// 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 @@
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 @@
{
// 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 @@
// 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));
-
- // 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);
+ 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 (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 @@
} _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);
@@ -767,6 +823,10 @@
ExFreePoolWithTag(AttribData, TAG_NTFS);
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);
@@ -795,7 +855,7 @@
}
}
}
- 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 @@
}
// 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 @@
//TEMPTEMP
PUCHAR TempBuffer;
- if (!Context->Record.IsNonResident)
- {
- if (Offset > Context->Record.Resident.ValueLength)
+ if (!Context->pRecord->IsNonResident)
+ {
+ // 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 @@
} /* if Disk */
// TEMPTEMP
- if (Context->Record.IsNonResident)
+ if (Context->pRecord->IsNonResident)
ExFreePoolWithTag(TempBuffer, TAG_NTFS);
Context->CacheRun = DataRun;
@@ -1073,13 +1139,13 @@
*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 @@
// 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 @@
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 @@
} // 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 @@
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 @@
{
// 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 @@
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 @@
}
// 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 @@
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 @@
// 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 @@
// $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 @@
}
// 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 @@
return Status;
}
- IndexAllocationSize = AttributeDataLength(&IndexAllocationCtx->Record);
+ IndexAllocationSize = AttributeDataLength(IndexAllocationCtx->pRecord);
Status = STATUS_OBJECT_PATH_NOT_FOUND;
for (RecordOffset = 0; RecordOffset < IndexAllocationSize; RecordOffset +=
IndexBlockSize)
{
Modified: branches/GSoC_2016/NTFS/drivers/filesystems/ntfs/ntfs.h
URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2016/NTFS/drivers/filesyst…
==============================================================================
--- branches/GSoC_2016/NTFS/drivers/filesystems/ntfs/ntfs.h [iso-8859-1] (original)
+++ branches/GSoC_2016/NTFS/drivers/filesystems/ntfs/ntfs.h [iso-8859-1] Sun Aug 6
02:54:15 2017
@@ -480,7 +480,7 @@
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 @@
ULONGLONG
AttributeDataLength(PNTFS_ATTR_RECORD AttrRecord);
-VOID
+NTSTATUS
InternalSetResidentAttributeLength(PNTFS_ATTR_CONTEXT AttrContext,
PFILE_RECORD_HEADER FileRecord,
ULONG AttrOffset,
Modified: branches/GSoC_2016/NTFS/drivers/filesystems/ntfs/rw.c
URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2016/NTFS/drivers/filesyst…
==============================================================================
--- branches/GSoC_2016/NTFS/drivers/filesystems/ntfs/rw.c [iso-8859-1] (original)
+++ branches/GSoC_2016/NTFS/drivers/filesystems/ntfs/rw.c [iso-8859-1] Sun Aug 6 02:54:15
2017
@@ -126,7 +126,7 @@
return Status;
}
- StreamSize = AttributeDataLength(&DataContext->Record);
+ StreamSize = AttributeDataLength(DataContext->pRecord);
if (ReadOffset >= StreamSize)
{
DPRINT1("Reading beyond stream end!\n");
@@ -149,7 +149,7 @@
/* 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 @@
}
// 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 @@
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
Modified: branches/GSoC_2016/NTFS/drivers/filesystems/ntfs/volinfo.c
URL:
http://svn.reactos.org/svn/reactos/branches/GSoC_2016/NTFS/drivers/filesyst…
==============================================================================
--- branches/GSoC_2016/NTFS/drivers/filesystems/ntfs/volinfo.c [iso-8859-1] (original)
+++ branches/GSoC_2016/NTFS/drivers/filesystems/ntfs/volinfo.c [iso-8859-1] Sun Aug 6
02:54:15 2017
@@ -69,7 +69,7 @@
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 @@
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);