- 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, NtfsReadDisk(IN PDEVICE_OBJECT DeviceObject,
IN LONGLONG StartingOffset, IN LONGLONG StartingOffset,
IN ULONG Length, IN ULONG Length,
IN ULONG SectorSize,
IN OUT PUCHAR Buffer, IN OUT PUCHAR Buffer,
IN BOOLEAN Override) IN BOOLEAN Override)
{ {
@ -45,20 +46,41 @@ NtfsReadDisk(IN PDEVICE_OBJECT DeviceObject,
KEVENT Event; KEVENT Event;
PIRP Irp; PIRP Irp;
NTSTATUS Status; 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, KeInitializeEvent(&Event,
NotificationEvent, NotificationEvent,
FALSE); 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"); DPRINT("Building synchronous FSD Request...\n");
Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ, Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
DeviceObject, DeviceObject,
Buffer, ReadBuffer,
Length, RealLength,
&Offset, &Offset,
&Event, &Event,
&IoStatus); &IoStatus);
@ -86,6 +108,12 @@ NtfsReadDisk(IN PDEVICE_OBJECT DeviceObject,
Status = IoStatus.Status; 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); DPRINT("NtfsReadDisk() done (Status %x)\n", Status);
return Status; return Status;
@ -105,7 +133,7 @@ NtfsReadSectors(IN PDEVICE_OBJECT DeviceObject,
Offset = (LONGLONG)DiskSector * (LONGLONG)SectorSize; Offset = (LONGLONG)DiskSector * (LONGLONG)SectorSize;
BlockSize = SectorCount * 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; PNTFS_ATTR_RECORD ListAttrRecordEnd;
// Do not handle non-resident yet // Do not handle non-resident yet
ASSERT(!(AttrRecord->IsNonResident & 1)); if (AttrRecord->IsNonResident)
ListContext = PrepareAttributeContext(AttrRecord);
ListSize = AttributeDataLength(&ListContext->Record);
if(ListSize <= 0xFFFFFFFF)
ListBuffer = ExAllocatePoolWithTag(NonPagedPool, (ULONG)ListSize, TAG_NTFS);
else
ListBuffer = NULL;
if(!ListBuffer)
{ {
DPRINT("Failed to allocate memory: %x\n", (ULONG)ListSize); UNIMPLEMENTED;
continue; continue;
} }
else
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, ListContext = PrepareAttributeContext(AttrRecord);
Type, Name, NameLength);
ReleaseAttributeContext(ListContext); ListSize = AttributeDataLength(&ListContext->Record);
ExFreePoolWithTag(ListBuffer, TAG_NTFS); if(ListSize <= 0xFFFFFFFF)
ListBuffer = ExAllocatePoolWithTag(NonPagedPool, (ULONG)ListSize, TAG_NTFS);
else
ListBuffer = NULL;
if (Context != NULL) if(!ListBuffer)
{ {
DPRINT("Found context = %p\n", Context); DPRINT("Failed to allocate memory: %x\n", (ULONG)ListSize);
return Context; 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, Status = NtfsReadDisk(Vcb->StorageDevice,
DataRunStartLCN * Vcb->NtfsInfo.BytesPerCluster + Offset - CurrentOffset, DataRunStartLCN * Vcb->NtfsInfo.BytesPerCluster + Offset - CurrentOffset,
ReadLength, ReadLength,
Vcb->NtfsInfo.BytesPerSector,
(PVOID)Buffer, (PVOID)Buffer,
FALSE); FALSE);
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
@ -344,6 +351,7 @@ ReadAttribute(PDEVICE_EXTENSION Vcb,
Status = NtfsReadDisk(Vcb->StorageDevice, Status = NtfsReadDisk(Vcb->StorageDevice,
DataRunStartLCN * Vcb->NtfsInfo.BytesPerCluster, DataRunStartLCN * Vcb->NtfsInfo.BytesPerCluster,
ReadLength, ReadLength,
Vcb->NtfsInfo.BytesPerSector,
(PVOID)Buffer, (PVOID)Buffer,
FALSE); FALSE);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))

View file

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

View file

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