- Move the ROUND_UP & ROUND_DOWN macro definition to header
- Make NtfsReadDisk() sector size aware so that it can properly align read on the disk (and thus prevent them from failing)
- If $ATTRIBUTE_LIST is non resident, then display a message and continue, don't assert on it. This is to be implemented later on.

This fixes directory enumeration on a Windows 7 NTFS volume.

svn path=/trunk/; revision=65240
This commit is contained in:
Pierre Schweitzer 2014-11-04 07:56:20 +00:00
parent 217a030519
commit 099910fd83
4 changed files with 67 additions and 34 deletions

View file

@ -36,6 +36,7 @@ NTSTATUS
NtfsReadDisk(IN PDEVICE_OBJECT DeviceObject,
IN LONGLONG StartingOffset,
IN ULONG Length,
IN ULONG SectorSize,
IN OUT PUCHAR Buffer,
IN BOOLEAN Override)
{
@ -45,20 +46,41 @@ NtfsReadDisk(IN PDEVICE_OBJECT DeviceObject,
KEVENT Event;
PIRP Irp;
NTSTATUS Status;
ULONGLONG RealReadOffset;
ULONG RealLength;
BOOLEAN AllocatedBuffer = FALSE;
PUCHAR ReadBuffer = Buffer;
DPRINT("NtfsReadDisk(%p, %I64x, %u, %p, %d)\n", DeviceObject, StartingOffset, Length, Buffer, Override);
DPRINT("NtfsReadDisk(%p, %I64x, %u, %u, %p, %d)\n", DeviceObject, StartingOffset, Length, SectorSize, Buffer, Override);
KeInitializeEvent(&Event,
NotificationEvent,
FALSE);
Offset.QuadPart = StartingOffset;
RealReadOffset = (ULONGLONG)StartingOffset;
RealLength = Length;
if ((RealReadOffset % SectorSize) != 0 || (RealLength % SectorSize) != 0)
{
RealReadOffset = ROUND_DOWN(StartingOffset, SectorSize);
RealLength = ROUND_UP(Length, SectorSize);
ReadBuffer = ExAllocatePoolWithTag(NonPagedPool, RealLength + SectorSize, TAG_NTFS);
if (ReadBuffer == NULL)
{
DPRINT1("Not enough memory!\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
AllocatedBuffer = TRUE;
}
Offset.QuadPart = RealReadOffset;
DPRINT("Building synchronous FSD Request...\n");
Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
DeviceObject,
Buffer,
Length,
ReadBuffer,
RealLength,
&Offset,
&Event,
&IoStatus);
@ -86,6 +108,12 @@ NtfsReadDisk(IN PDEVICE_OBJECT DeviceObject,
Status = IoStatus.Status;
}
if (NT_SUCCESS(Status) && AllocatedBuffer)
{
RtlCopyMemory(Buffer, ReadBuffer + (StartingOffset - RealReadOffset), Length);
ExFreePoolWithTag(ReadBuffer, TAG_NTFS);
}
DPRINT("NtfsReadDisk() done (Status %x)\n", Status);
return Status;
@ -105,7 +133,7 @@ NtfsReadSectors(IN PDEVICE_OBJECT DeviceObject,
Offset = (LONGLONG)DiskSector * (LONGLONG)SectorSize;
BlockSize = SectorCount * SectorSize;
return NtfsReadDisk(DeviceObject, Offset, BlockSize, Buffer, Override);
return NtfsReadDisk(DeviceObject, Offset, BlockSize, SectorSize, Buffer, Override);
}

View file

@ -106,37 +106,43 @@ FindAttributeHelper(PDEVICE_EXTENSION Vcb,
PNTFS_ATTR_RECORD ListAttrRecordEnd;
// Do not handle non-resident yet
ASSERT(!(AttrRecord->IsNonResident & 1));
ListContext = PrepareAttributeContext(AttrRecord);
ListSize = AttributeDataLength(&ListContext->Record);
if(ListSize <= 0xFFFFFFFF)
ListBuffer = ExAllocatePoolWithTag(NonPagedPool, (ULONG)ListSize, TAG_NTFS);
else
ListBuffer = NULL;
if(!ListBuffer)
if (AttrRecord->IsNonResident)
{
DPRINT("Failed to allocate memory: %x\n", (ULONG)ListSize);
UNIMPLEMENTED;
continue;
}
ListAttrRecord = (PNTFS_ATTR_RECORD)ListBuffer;
ListAttrRecordEnd = (PNTFS_ATTR_RECORD)((PCHAR)ListBuffer + ListSize);
if (ReadAttribute(Vcb, ListContext, 0, ListBuffer, (ULONG)ListSize) == ListSize)
else
{
Context = FindAttributeHelper(Vcb, ListAttrRecord, ListAttrRecordEnd,
Type, Name, NameLength);
ListContext = PrepareAttributeContext(AttrRecord);
ReleaseAttributeContext(ListContext);
ExFreePoolWithTag(ListBuffer, TAG_NTFS);
ListSize = AttributeDataLength(&ListContext->Record);
if(ListSize <= 0xFFFFFFFF)
ListBuffer = ExAllocatePoolWithTag(NonPagedPool, (ULONG)ListSize, TAG_NTFS);
else
ListBuffer = NULL;
if (Context != NULL)
if(!ListBuffer)
{
DPRINT("Found context = %p\n", Context);
return Context;
DPRINT("Failed to allocate memory: %x\n", (ULONG)ListSize);
continue;
}
ListAttrRecord = (PNTFS_ATTR_RECORD)ListBuffer;
ListAttrRecordEnd = (PNTFS_ATTR_RECORD)((PCHAR)ListBuffer + ListSize);
if (ReadAttribute(Vcb, ListContext, 0, ListBuffer, (ULONG)ListSize) == ListSize)
{
Context = FindAttributeHelper(Vcb, ListAttrRecord, ListAttrRecordEnd,
Type, Name, NameLength);
ReleaseAttributeContext(ListContext);
ExFreePoolWithTag(ListBuffer, TAG_NTFS);
if (Context != NULL)
{
DPRINT("Found context = %p\n", Context);
return Context;
}
}
}
}
@ -310,6 +316,7 @@ ReadAttribute(PDEVICE_EXTENSION Vcb,
Status = NtfsReadDisk(Vcb->StorageDevice,
DataRunStartLCN * Vcb->NtfsInfo.BytesPerCluster + Offset - CurrentOffset,
ReadLength,
Vcb->NtfsInfo.BytesPerSector,
(PVOID)Buffer,
FALSE);
if (NT_SUCCESS(Status))
@ -344,6 +351,7 @@ ReadAttribute(PDEVICE_EXTENSION Vcb,
Status = NtfsReadDisk(Vcb->StorageDevice,
DataRunStartLCN * Vcb->NtfsInfo.BytesPerCluster,
ReadLength,
Vcb->NtfsInfo.BytesPerSector,
(PVOID)Buffer,
FALSE);
if (!NT_SUCCESS(Status))

View file

@ -10,6 +10,7 @@
#define TAG_NTFS 'SFTN'
#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
#define ROUND_DOWN(N, S) ((N) - ((N) % (S)))
#define DEVICE_NAME L"\\Ntfs"
@ -456,6 +457,7 @@ NTSTATUS
NtfsReadDisk(IN PDEVICE_OBJECT DeviceObject,
IN LONGLONG StartingOffset,
IN ULONG Length,
IN ULONG SectorSize,
IN OUT PUCHAR Buffer,
IN BOOLEAN Override);

View file

@ -32,11 +32,6 @@
#define NDEBUG
#include <debug.h>
/* GLOBALS *******************************************************************/
#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
#define ROUND_DOWN(N, S) ((N) - ((N) % (S)))
/* FUNCTIONS ****************************************************************/
/*