- Improved the reading and writing of fragmented files.

svn path=/trunk/; revision=9412
This commit is contained in:
Hartmut Birr 2004-05-15 23:00:02 +00:00
parent 189436c3ef
commit d16209b9dc
4 changed files with 306 additions and 134 deletions

View file

@ -38,12 +38,53 @@ VfatReadWriteCompletion (IN PDEVICE_OBJECT DeviceObject,
}
*Irp->UserIosb = Irp->IoStatus;
KeSetEvent(Irp->UserEvent, IO_NO_INCREMENT, FALSE);
if (Irp->PendingReturned)
{
KeSetEvent(Irp->UserEvent, IO_NO_INCREMENT, FALSE);
}
IoFreeIrp(Irp);
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS STDCALL
VfatReadWritePartialCompletion (IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context)
{
PVFAT_IRP_CONTEXT IrpContext;
PMDL Mdl;
DPRINT("VfatReadWritePartialCompletion() called\n");
IrpContext = (PVFAT_IRP_CONTEXT)Context;
while ((Mdl = Irp->MdlAddress))
{
Irp->MdlAddress = Mdl->Next;
IoFreeMdl(Mdl);
}
if (Irp->PendingReturned)
{
IrpContext->Flags |= IRPCONTEXT_PENDINGRETURNED;
}
if (!NT_SUCCESS(Irp->IoStatus.Status))
{
IrpContext->Irp->IoStatus.Status = Irp->IoStatus.Status;
}
if (0 == InterlockedDecrement((PLONG)&IrpContext->RefCount) &&
IrpContext->Flags & IRPCONTEXT_PENDINGRETURNED)
{
KeSetEvent(&IrpContext->Event, IO_NO_INCREMENT, FALSE);
}
IoFreeIrp(Irp);
DPRINT("VfatReadWritePartialCompletion() done\n");
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS
VfatReadDisk (IN PDEVICE_OBJECT pDeviceObject,
IN PLARGE_INTEGER ReadOffset,
@ -113,29 +154,100 @@ VfatReadDisk (IN PDEVICE_OBJECT pDeviceObject,
}
NTSTATUS
VfatWriteDisk (IN PDEVICE_OBJECT pDeviceObject,
IN PLARGE_INTEGER WriteOffset,
IN ULONG WriteLength,
IN PUCHAR Buffer)
VfatReadDiskPartial (IN PVFAT_IRP_CONTEXT IrpContext,
IN PLARGE_INTEGER ReadOffset,
IN ULONG ReadLength,
ULONG BufferOffset,
IN BOOLEAN Wait)
{
PIRP Irp;
IO_STATUS_BLOCK IoStatus;
KEVENT event;
NTSTATUS Status;
PVOID Buffer;
DPRINT ("VfatWriteSectors(pDeviceObject %x, Offset %I64x, Size %d, Buffer %x)\n",
pDeviceObject, WriteOffset->QuadPart, WriteLength, Buffer);
DPRINT ("VfatReadDiskPartial(IrpContext %x, ReadOffset %I64x, ReadLength %d, BufferOffset %x, Wait %d)\n",
IrpContext, ReadOffset->QuadPart, ReadLength, BufferOffset, Wait);
KeInitializeEvent (&event, NotificationEvent, FALSE);
DPRINT ("Building synchronous FSD Request...\n");
Buffer = MmGetMdlVirtualAddress(IrpContext->Irp->MdlAddress) + BufferOffset;
Irp = IoBuildSynchronousFsdRequest (IRP_MJ_READ,
IrpContext->DeviceExt->StorageDevice,
NULL,
ReadLength,
ReadOffset,
NULL,
NULL);
if (Irp == NULL)
{
DPRINT("IoBuildSynchronousFsdRequest failed\n");
return(STATUS_UNSUCCESSFUL);
}
if (!IoAllocateMdl(Buffer, ReadLength, FALSE, FALSE, Irp))
{
DPRINT("IoAllocateMdl failed\n");
IoFreeIrp(Irp);
return STATUS_UNSUCCESSFUL;
}
IoBuildPartialMdl(IrpContext->Irp->MdlAddress, Irp->MdlAddress, Buffer, ReadLength);
IoSetCompletionRoutine(Irp,
VfatReadWritePartialCompletion,
IrpContext,
TRUE,
TRUE,
TRUE);
if (Wait)
{
KeInitializeEvent(&IrpContext->Event, NotificationEvent, FALSE);
IrpContext->RefCount = 1;
}
else
{
InterlockedIncrement((PLONG)&IrpContext->RefCount);
}
DPRINT ("Calling IO Driver... with irp %x\n", Irp);
Status = IoCallDriver (IrpContext->DeviceExt->StorageDevice, Irp);
if (Wait && Status == STATUS_PENDING)
{
KeWaitForSingleObject(&IrpContext->Event, Executive, KernelMode, FALSE, NULL);
Status = IrpContext->Irp->IoStatus.Status;
}
DPRINT("%x\n", Status);
return Status;
}
NTSTATUS
VfatWriteDiskPartial (IN PVFAT_IRP_CONTEXT IrpContext,
IN PLARGE_INTEGER WriteOffset,
IN ULONG WriteLength,
IN ULONG BufferOffset,
IN BOOLEAN Wait)
{
PIRP Irp;
NTSTATUS Status;
PVOID Buffer;
DPRINT ("VfatWriteDiskPartial(IrpContext %x, WriteOffset %I64x, WriteLength %d, BufferOffset %x, Wait %d)\n",
IrpContext, WriteOffset->QuadPart, WriteLength, BufferOffset, Wait);
Buffer = MmGetMdlVirtualAddress(IrpContext->Irp->MdlAddress) + BufferOffset;
DPRINT ("Building synchronous FSD Request...\n");
Irp = IoBuildSynchronousFsdRequest (IRP_MJ_WRITE,
pDeviceObject,
Buffer,
IrpContext->DeviceExt->StorageDevice,
NULL,
WriteLength,
WriteOffset,
&event,
&IoStatus);
NULL,
NULL);
if (!Irp)
{
@ -143,32 +255,41 @@ VfatWriteDisk (IN PDEVICE_OBJECT pDeviceObject,
return (STATUS_UNSUCCESSFUL);
}
if (!IoAllocateMdl(Buffer, WriteLength, FALSE, FALSE, Irp))
{
DPRINT("IoAllocateMdl failed\n");
IoFreeIrp(Irp);
return STATUS_UNSUCCESSFUL;
}
IoBuildPartialMdl(IrpContext->Irp->MdlAddress, Irp->MdlAddress, Buffer, WriteLength);
IoSetCompletionRoutine(Irp,
VfatReadWriteCompletion,
NULL,
VfatReadWritePartialCompletion,
IrpContext,
TRUE,
TRUE,
TRUE);
if (Wait)
{
KeInitializeEvent(&IrpContext->Event, NotificationEvent, FALSE);
IrpContext->RefCount = 1;
}
else
{
InterlockedIncrement((PLONG)&IrpContext->RefCount);
}
DPRINT ("Calling IO Driver...\n");
Status = IoCallDriver (pDeviceObject, Irp);
DPRINT ("Waiting for IO Operation...\n");
if (Status == STATUS_PENDING)
Status = IoCallDriver (IrpContext->DeviceExt->StorageDevice, Irp);
if (Wait && Status == STATUS_PENDING)
{
KeWaitForSingleObject (&event, Suspended, KernelMode, FALSE, NULL);
DPRINT ("Getting IO Status...\n");
Status = IoStatus.Status;
KeWaitForSingleObject(&IrpContext->Event, Executive, KernelMode, FALSE, NULL);
Status = IrpContext->Irp->IoStatus.Status;
}
if (!NT_SUCCESS (Status))
{
DPRINT ("IO failed!!! VfatWriteSectors : Error code: %x\n", Status);
return (Status);
}
DPRINT ("Block request succeeded\n");
return (STATUS_SUCCESS);
return Status;
}
NTSTATUS
@ -188,9 +309,9 @@ VfatBlockDeviceIoControl (IN PDEVICE_OBJECT DeviceObject,
DPRINT("VfatBlockDeviceIoControl(DeviceObject %x, CtlCode %x, "
"InputBuffer %x, InputBufferSize %x, OutputBuffer %x, "
"POutputBufferSize %x (%x)\n", DeviceObject, CtlCode,
InputBuffer, InputBufferSize, OutputBuffer, pOutputBufferSize,
pOutputBufferSize ? *pOutputBufferSize : 0);
"OutputBufferSize %x (%x)\n", DeviceObject, CtlCode,
InputBuffer, InputBufferSize, OutputBuffer, OutputBufferSize,
OutputBufferSize ? *OutputBufferSize : 0);
KeInitializeEvent (&Event, NotificationEvent, FALSE);

View file

@ -1,4 +1,4 @@
/* $Id: misc.c,v 1.12 2004/03/04 01:29:24 gdalsnes Exp $
/* $Id: misc.c,v 1.13 2004/05/15 23:00:02 hbirr Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -164,7 +164,7 @@ PVFAT_IRP_CONTEXT VfatAllocateIrpContext(PDEVICE_OBJECT DeviceObject, PIRP Irp)
IrpContext = ExAllocateFromNPagedLookasideList(&VfatGlobalData->IrpContextLookasideList);
if (IrpContext)
{
RtlZeroMemory(IrpContext, sizeof(IrpContext));
RtlZeroMemory(IrpContext, sizeof(VFAT_IRP_CONTEXT));
IrpContext->Irp = Irp;
IrpContext->DeviceObject = DeviceObject;
IrpContext->DeviceExt = DeviceObject->DeviceExtension;
@ -173,6 +173,7 @@ PVFAT_IRP_CONTEXT VfatAllocateIrpContext(PDEVICE_OBJECT DeviceObject, PIRP Irp)
MajorFunction = IrpContext->MajorFunction = IrpContext->Stack->MajorFunction;
IrpContext->MinorFunction = IrpContext->Stack->MinorFunction;
IrpContext->FileObject = IrpContext->Stack->FileObject;
IrpContext->Flags = 0;
if (MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL ||
MajorFunction == IRP_MJ_DEVICE_CONTROL ||
MajorFunction == IRP_MJ_SHUTDOWN)
@ -185,6 +186,8 @@ PVFAT_IRP_CONTEXT VfatAllocateIrpContext(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
IrpContext->Flags |= IRPCONTEXT_CANWAIT;
}
KeInitializeEvent(&IrpContext->Event, NotificationEvent, FALSE);
IrpContext->RefCount = 0;
}
return IrpContext;
}

View file

@ -1,5 +1,5 @@
/* $Id: rw.c,v 1.65 2004/03/31 03:30:36 jimtabor Exp $
/* $Id: rw.c,v 1.66 2004/05/15 23:00:02 hbirr Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -114,8 +114,10 @@ OffsetToCluster(PDEVICE_EXTENSION DeviceExt,
}
NTSTATUS
VfatReadFileData (PVFAT_IRP_CONTEXT IrpContext, PVOID Buffer,
ULONG Length, LARGE_INTEGER ReadOffset, PULONG LengthRead)
VfatReadFileData (PVFAT_IRP_CONTEXT IrpContext,
ULONG Length,
LARGE_INTEGER ReadOffset,
PULONG LengthRead)
/*
* FUNCTION: Reads data from a file
*/
@ -133,6 +135,7 @@ VfatReadFileData (PVFAT_IRP_CONTEXT IrpContext, PVOID Buffer,
ULONG BytesDone;
ULONG BytesPerSector;
ULONG BytesPerCluster;
ULONG Count;
/* PRECONDITION */
assert (IrpContext);
@ -142,9 +145,9 @@ VfatReadFileData (PVFAT_IRP_CONTEXT IrpContext, PVOID Buffer,
assert (IrpContext->FileObject);
assert (IrpContext->FileObject->FsContext2 != NULL);
DPRINT("VfatReadFileData(DeviceExt %x, FileObject %x, Buffer %x, "
DPRINT("VfatReadFileData(DeviceExt %x, FileObject %x, "
"Length %d, ReadOffset 0x%I64x)\n", DeviceExt,
IrpContext->FileObject, Buffer, Length, ReadOffset.QuadPart);
IrpContext->FileObject, Length, ReadOffset.QuadPart);
*LengthRead = 0;
@ -161,7 +164,7 @@ VfatReadFileData (PVFAT_IRP_CONTEXT IrpContext, PVOID Buffer,
if (Fcb->Flags & FCB_IS_FAT)
{
ReadOffset.QuadPart += DeviceExt->FatInfo.FATStart * BytesPerSector;
Status = VfatReadDisk(DeviceExt->StorageDevice, &ReadOffset, Length, Buffer, FALSE);
Status = VfatReadDiskPartial(IrpContext, &ReadOffset, Length, 0, TRUE);
if (NT_SUCCESS(Status))
{
@ -176,7 +179,7 @@ VfatReadFileData (PVFAT_IRP_CONTEXT IrpContext, PVOID Buffer,
/* Is this a read of the Volume ? */
if (Fcb->Flags & FCB_IS_VOLUME)
{
Status = VfatReadDisk(DeviceExt->StorageDevice, &ReadOffset, Length, Buffer, FALSE);
Status = VfatReadDiskPartial(IrpContext, &ReadOffset, Length, 0, TRUE);
if (NT_SUCCESS(Status))
{
*LengthRead = Length;
@ -206,10 +209,10 @@ VfatReadFileData (PVFAT_IRP_CONTEXT IrpContext, PVOID Buffer,
// Fire up the read command
Status = VfatReadDisk (DeviceExt->StorageDevice, &ReadOffset, Length, Buffer, FALSE);
Status = VfatReadDiskPartial (IrpContext, &ReadOffset, Length, 0, TRUE);
if (NT_SUCCESS(Status))
{
*LengthRead += Length;
*LengthRead = Length;
}
return Status;
}
@ -231,7 +234,11 @@ VfatReadFileData (PVFAT_IRP_CONTEXT IrpContext, PVOID Buffer,
Ccb->LastCluster = CurrentCluster;
Ccb->LastOffset = ROUND_DOWN (ReadOffset.u.LowPart, BytesPerCluster);
while (Length > 0 && CurrentCluster != 0xffffffff && NT_SUCCESS(Status))
KeInitializeEvent(&IrpContext->Event, NotificationEvent, FALSE);
IrpContext->RefCount = 1;
Count = 0;
while (Length > 0 && CurrentCluster != 0xffffffff)
{
StartCluster = CurrentCluster;
StartOffset.QuadPart = ClusterToSector(DeviceExt, StartCluster) * BytesPerSector;
@ -267,32 +274,40 @@ VfatReadFileData (PVFAT_IRP_CONTEXT IrpContext, PVOID Buffer,
Ccb->LastCluster = StartCluster + (ClusterCount - 1);
Ccb->LastOffset = ReadOffset.u.LowPart + (ClusterCount - 1) * BytesPerCluster;
// Fire up the read command
Status = VfatReadDisk (DeviceExt->StorageDevice, &StartOffset, BytesDone, Buffer, FALSE);
Count++;
if (NT_SUCCESS(Status))
{
*LengthRead += BytesDone;
/* GCC allows arithmetics on the void type. Conforming compilers do not. */
#ifdef __GNUC__
Buffer += BytesDone;
#else
// Fire up the read command
Status = VfatReadDiskPartial (IrpContext, &StartOffset, BytesDone, *LengthRead, FALSE);
if (!NT_SUCCESS(Status) && Status != STATUS_PENDING)
{
char* pBuf = (char*)Buffer + BytesDone;
Buffer = (PVOID)pBuf;
break;
}
#endif
Length -= BytesDone;
ReadOffset.u.LowPart += BytesDone;
}
*LengthRead += BytesDone;
Length -= BytesDone;
ReadOffset.u.LowPart += BytesDone;
}
if (0 != InterlockedDecrement((PLONG)&IrpContext->RefCount))
{
KeWaitForSingleObject(&IrpContext->Event, Executive, KernelMode, FALSE, NULL);
}
if (NT_SUCCESS(Status) || Status == STATUS_PENDING)
{
if (Length > 0)
{
Status = STATUS_UNSUCCESSFUL;
}
else
{
Status = IrpContext->Irp->IoStatus.Status;
}
}
return Status;
}
NTSTATUS VfatWriteFileData(PVFAT_IRP_CONTEXT IrpContext,
PVOID Buffer,
ULONG Length,
LARGE_INTEGER WriteOffset)
NTSTATUS
VfatWriteFileData(PVFAT_IRP_CONTEXT IrpContext,
ULONG Length,
LARGE_INTEGER WriteOffset)
{
PDEVICE_EXTENSION DeviceExt;
PVFATFCB Fcb;
@ -308,6 +323,7 @@ NTSTATUS VfatWriteFileData(PVFAT_IRP_CONTEXT IrpContext,
ULONG BytesPerSector;
ULONG BytesPerCluster;
LARGE_INTEGER StartOffset;
ULONG BufferOffset;
/* PRECONDITION */
assert (IrpContext);
@ -322,9 +338,9 @@ NTSTATUS VfatWriteFileData(PVFAT_IRP_CONTEXT IrpContext,
BytesPerCluster = DeviceExt->FatInfo.BytesPerCluster;
BytesPerSector = DeviceExt->FatInfo.BytesPerSector;
DPRINT("VfatWriteFileData(DeviceExt %x, FileObject %x, Buffer %x, "
DPRINT("VfatWriteFileData(DeviceExt %x, FileObject %x, "
"Length %d, WriteOffset 0x%I64x), '%wZ'\n", DeviceExt,
IrpContext->FileObject, Buffer, Length, WriteOffset,
IrpContext->FileObject, Length, WriteOffset,
&Fcb->PathNameU);
assert(WriteOffset.QuadPart + Length <= Fcb->RFCB.AllocationSize.QuadPart);
@ -334,7 +350,7 @@ NTSTATUS VfatWriteFileData(PVFAT_IRP_CONTEXT IrpContext,
// Is this a write of the volume ?
if (Fcb->Flags & FCB_IS_VOLUME)
{
Status = VfatWriteDisk(DeviceExt->StorageDevice, &WriteOffset, Length, Buffer);
Status = VfatWriteDiskPartial(IrpContext, &WriteOffset, Length, 0, TRUE);
if (!NT_SUCCESS(Status))
{
DPRINT1("Volume writing failed, Status %x\n", Status);
@ -346,15 +362,25 @@ NTSTATUS VfatWriteFileData(PVFAT_IRP_CONTEXT IrpContext,
if (Fcb->Flags & FCB_IS_FAT)
{
WriteOffset.u.LowPart += DeviceExt->FatInfo.FATStart * BytesPerSector;
IrpContext->RefCount = 1;
for (Count = 0; Count < DeviceExt->FatInfo.FATCount; Count++)
{
Status = VfatWriteDisk(DeviceExt->StorageDevice, &WriteOffset, Length, Buffer);
if (!NT_SUCCESS(Status))
Status = VfatWriteDiskPartial(IrpContext, &WriteOffset, Length, 0, FALSE);
if (!NT_SUCCESS(Status) && Status != STATUS_PENDING)
{
DPRINT1("FAT writing failed, Status %x\n", Status);
break;
}
WriteOffset.u.LowPart += Fcb->RFCB.FileSize.u.LowPart;
}
if (0 != InterlockedDecrement((PLONG)&IrpContext->RefCount))
{
KeWaitForSingleObject(&IrpContext->Event, Executive, KernelMode, FALSE, NULL);
}
if (NT_SUCCESS(Status) || Status == STATUS_PENDING)
{
Status = IrpContext->Irp->IoStatus.Status;
}
return Status;
}
@ -370,7 +396,7 @@ NTSTATUS VfatWriteFileData(PVFAT_IRP_CONTEXT IrpContext,
// Directory of FAT12/16 needs a special handling
WriteOffset.u.LowPart += DeviceExt->FatInfo.rootStart * BytesPerSector;
// Fire up the write command
Status = VfatWriteDisk (DeviceExt->StorageDevice, &WriteOffset, Length, Buffer);
Status = VfatWriteDiskPartial (IrpContext, &WriteOffset, Length, 0, TRUE);
return Status;
}
@ -394,7 +420,11 @@ NTSTATUS VfatWriteFileData(PVFAT_IRP_CONTEXT IrpContext,
Ccb->LastCluster = CurrentCluster;
Ccb->LastOffset = ROUND_DOWN (WriteOffset.u.LowPart, BytesPerCluster);
while (Length > 0 && CurrentCluster != 0xffffffff && NT_SUCCESS(Status))
IrpContext->RefCount = 1;
Count = 0;
BufferOffset = 0;
while (Length > 0 && CurrentCluster != 0xffffffff)
{
StartCluster = CurrentCluster;
StartOffset.QuadPart = ClusterToSector(DeviceExt, StartCluster) * BytesPerSector;
@ -431,22 +461,31 @@ NTSTATUS VfatWriteFileData(PVFAT_IRP_CONTEXT IrpContext,
Ccb->LastOffset = WriteOffset.u.LowPart + (ClusterCount - 1) * BytesPerCluster;
// Fire up the write command
Status = VfatWriteDisk (DeviceExt->StorageDevice, &StartOffset, BytesDone, Buffer);
if (NT_SUCCESS(Status))
{
/* GCC allows arithmetics on the void type. Conforming compilers do not. */
#ifdef __GNUC__
Buffer += BytesDone;
#else
{
char* pBuf = (char*)Buffer + BytesDone;
Buffer = (PVOID)pBuf;
}
#endif
Length -= BytesDone;
WriteOffset.u.LowPart += BytesDone;
}
Status = VfatWriteDiskPartial (IrpContext, &StartOffset, BytesDone, BufferOffset, FALSE);
Count++;
if (!NT_SUCCESS(Status) && Status != STATUS_PENDING)
{
break;
}
BufferOffset += BytesDone;
Length -= BytesDone;
WriteOffset.u.LowPart += BytesDone;
}
if (0 != InterlockedDecrement((PLONG)&IrpContext->RefCount))
{
KeWaitForSingleObject(&IrpContext->Event, Executive, KernelMode, FALSE, NULL);
}
if (NT_SUCCESS(Status) || Status == STATUS_PENDING)
{
if (Length > 0)
{
Status = STATUS_UNSUCCESSFUL;
}
else
{
Status = IrpContext->Irp->IoStatus.Status;
}
}
return Status;
}
@ -486,12 +525,10 @@ VfatRead(PVFAT_IRP_CONTEXT IrpContext)
if (Fcb->Flags & FCB_IS_PAGE_FILE)
{
PIO_STACK_LOCATION Stack;
PFATINFO FatInfo = &IrpContext->DeviceExt->FatInfo;
IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp);
Stack = IoGetNextIrpStackLocation(IrpContext->Irp);
Stack->Parameters.Read.ByteOffset.QuadPart += FatInfo->dataStart * FatInfo->BytesPerSector;
DPRINT("Read from page file, disk offset %I64x\n", Stack->Parameters.Read.ByteOffset.QuadPart);
IrpContext->Stack->Parameters.Read.ByteOffset.QuadPart += FatInfo->dataStart * FatInfo->BytesPerSector;
IoSkipCurrentIrpStackLocation(IrpContext->Irp);
DPRINT("Read from page file, disk offset %I64x\n", IrpContext->Stack->Parameters.Read.ByteOffset.QuadPart);
Status = IoCallDriver(IrpContext->DeviceExt->StorageDevice, IrpContext->Irp);
VfatFreeIrpContext(IrpContext);
return Status;
@ -527,7 +564,7 @@ VfatRead(PVFAT_IRP_CONTEXT IrpContext)
if (ByteOffset.u.LowPart % BytesPerSector != 0 || Length % BytesPerSector != 0)
{
DPRINT("%d %d\n", ByteOffset.u.LowPart, Length);
// non chached read must be sector aligned
// non cached read must be sector aligned
Status = STATUS_INVALID_PARAMETER;
goto ByeBye;
}
@ -569,6 +606,13 @@ VfatRead(PVFAT_IRP_CONTEXT IrpContext)
}
}
Buffer = VfatGetUserBuffer(IrpContext->Irp);
if (!Buffer)
{
Status = STATUS_INVALID_USER_BUFFER;
goto ByeBye;
}
if (!(IrpContext->Irp->Flags & (IRP_NOCACHE|IRP_PAGING_IO)) &&
!(Fcb->Flags & (FCB_IS_PAGE_FILE|FCB_IS_VOLUME)))
{
@ -581,13 +625,6 @@ VfatRead(PVFAT_IRP_CONTEXT IrpContext)
Status = /*STATUS_END_OF_FILE*/STATUS_SUCCESS;
}
Buffer = VfatGetUserBuffer(IrpContext->Irp);
if (!Buffer)
{
Status = STATUS_INVALID_USER_BUFFER;
goto ByeBye;
}
CHECKPOINT;
if (IrpContext->FileObject->PrivateCacheMap == NULL)
{
@ -621,14 +658,13 @@ VfatRead(PVFAT_IRP_CONTEXT IrpContext)
Length = (ULONG)(ROUND_UP(Fcb->RFCB.FileSize.QuadPart, BytesPerSector) - ByteOffset.QuadPart);
}
Buffer = VfatGetUserBuffer(IrpContext->Irp);
if (!Buffer)
{
Status = STATUS_INVALID_USER_BUFFER;
goto ByeBye;
}
Status = VfatLockUserBuffer(IrpContext->Irp, Length, IoWriteAccess);
if (!NT_SUCCESS(Status))
{
goto ByeBye;
}
Status = VfatReadFileData(IrpContext, Buffer, Length, ByteOffset, &ReturnedLength);
Status = VfatReadFileData(IrpContext, Length, ByteOffset, &ReturnedLength);
/**/
if (Status == STATUS_VERIFY_REQUIRED)
{
@ -639,7 +675,7 @@ VfatRead(PVFAT_IRP_CONTEXT IrpContext)
if (NT_SUCCESS(Status))
{
Status = VfatReadFileData(IrpContext, Buffer, Length,
Status = VfatReadFileData(IrpContext, Length,
ByteOffset, &ReturnedLength);
}
@ -725,12 +761,10 @@ NTSTATUS VfatWrite (PVFAT_IRP_CONTEXT IrpContext)
if (Fcb->Flags & FCB_IS_PAGE_FILE)
{
PIO_STACK_LOCATION Stack;
PFATINFO FatInfo = &IrpContext->DeviceExt->FatInfo;
IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp);
Stack = IoGetNextIrpStackLocation(IrpContext->Irp);
Stack->Parameters.Write.ByteOffset.QuadPart += FatInfo->dataStart * FatInfo->BytesPerSector;
DPRINT("Write to page file, disk offset %I64x\n", Stack->Parameters.Write.ByteOffset.QuadPart);
IrpContext->Stack->Parameters.Write.ByteOffset.QuadPart += FatInfo->dataStart * FatInfo->BytesPerSector;
IoSkipCurrentIrpStackLocation(IrpContext->Irp);
DPRINT("Write to page file, disk offset %I64x\n", IrpContext->Stack->Parameters.Write.ByteOffset.QuadPart);
Status = IoCallDriver(IrpContext->DeviceExt->StorageDevice, IrpContext->Irp);
VfatFreeIrpContext(IrpContext);
return Status;
@ -768,7 +802,7 @@ NTSTATUS VfatWrite (PVFAT_IRP_CONTEXT IrpContext)
{
if (ByteOffset.u.LowPart % BytesPerSector != 0 || Length % BytesPerSector != 0)
{
// non chached write must be sector aligned
// non cached write must be sector aligned
Status = STATUS_INVALID_PARAMETER;
goto ByeBye;
}
@ -776,6 +810,9 @@ NTSTATUS VfatWrite (PVFAT_IRP_CONTEXT IrpContext)
if (Length == 0)
{
/* FIXME:
* Update last write time
*/
IrpContext->Irp->IoStatus.Information = 0;
Status = STATUS_SUCCESS;
goto ByeBye;
@ -850,6 +887,14 @@ NTSTATUS VfatWrite (PVFAT_IRP_CONTEXT IrpContext)
OldFileSize = Fcb->RFCB.FileSize;
OldAllocationSize = Fcb->RFCB.AllocationSize.u.LowPart;
Buffer = VfatGetUserBuffer(IrpContext->Irp);
if (!Buffer)
{
Status = STATUS_INVALID_USER_BUFFER;
goto ByeBye;
}
if (!(Fcb->Flags & (FCB_IS_FAT|FCB_IS_VOLUME)) &&
!(IrpContext->Irp->Flags & IRP_PAGING_IO) &&
ByteOffset.u.LowPart + Length > Fcb->RFCB.FileSize.u.LowPart)
@ -872,13 +917,6 @@ NTSTATUS VfatWrite (PVFAT_IRP_CONTEXT IrpContext)
// cached write
CHECKPOINT;
Buffer = VfatGetUserBuffer(IrpContext->Irp);
if (!Buffer)
{
Status = STATUS_INVALID_USER_BUFFER;
goto ByeBye;
}
CHECKPOINT;
if (IrpContext->FileObject->PrivateCacheMap == NULL)
{
ULONG CacheSize;
@ -914,14 +952,14 @@ NTSTATUS VfatWrite (PVFAT_IRP_CONTEXT IrpContext)
{
CcZeroData(IrpContext->FileObject, &OldFileSize, &ByteOffset, TRUE);
}
Buffer = VfatGetUserBuffer(IrpContext->Irp);
if (!Buffer)
{
Status = STATUS_INVALID_USER_BUFFER;
goto ByeBye;
}
Status = VfatWriteFileData(IrpContext, Buffer, Length, ByteOffset);
Status = VfatLockUserBuffer(IrpContext->Irp, Length, IoReadAccess);
if (!NT_SUCCESS(Status))
{
goto ByeBye;
}
Status = VfatWriteFileData(IrpContext, Length, ByteOffset);
if (NT_SUCCESS(Status))
{
IrpContext->Irp->IoStatus.Information = Length;

View file

@ -1,4 +1,4 @@
/* $Id: vfat.h,v 1.62 2004/05/02 20:16:46 hbirr Exp $ */
/* $Id: vfat.h,v 1.63 2004/05/15 23:00:02 hbirr Exp $ */
#include <ddk/ntifs.h>
@ -288,7 +288,8 @@ typedef struct __DOSDATE
}
DOSDATE, *PDOSDATE;
#define IRPCONTEXT_CANWAIT 0x0001
#define IRPCONTEXT_CANWAIT 0x0001
#define IRPCONTEXT_PENDINGRETURNED 0x0002
typedef struct
{
@ -301,6 +302,8 @@ typedef struct
UCHAR MajorFunction;
UCHAR MinorFunction;
PFILE_OBJECT FileObject;
ULONG RefCount;
KEVENT Event;
} VFAT_IRP_CONTEXT, *PVFAT_IRP_CONTEXT;
typedef struct _VFAT_DIRENTRY_CONTEXT
@ -332,10 +335,17 @@ NTSTATUS VfatReadDisk(IN PDEVICE_OBJECT pDeviceObject,
IN PUCHAR Buffer,
IN BOOLEAN Override);
NTSTATUS VfatWriteDisk(IN PDEVICE_OBJECT pDeviceObject,
IN PLARGE_INTEGER WriteOffset,
IN ULONG WriteLength,
IN PUCHAR Buffer);
NTSTATUS VfatReadDiskPartial (IN PVFAT_IRP_CONTEXT IrpContext,
IN PLARGE_INTEGER ReadOffset,
IN ULONG ReadLength,
IN ULONG BufferOffset,
IN BOOLEAN Wait);
NTSTATUS VfatWriteDiskPartial(IN PVFAT_IRP_CONTEXT IrpContext,
IN PLARGE_INTEGER WriteOffset,
IN ULONG WriteLength,
IN ULONG BufferOffset,
IN BOOLEAN Wait);
NTSTATUS VfatBlockDeviceIoControl (IN PDEVICE_OBJECT DeviceObject,
IN ULONG CtlCode,