- 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; *Irp->UserIosb = Irp->IoStatus;
KeSetEvent(Irp->UserEvent, IO_NO_INCREMENT, FALSE); if (Irp->PendingReturned)
{
KeSetEvent(Irp->UserEvent, IO_NO_INCREMENT, FALSE);
}
IoFreeIrp(Irp); IoFreeIrp(Irp);
return STATUS_MORE_PROCESSING_REQUIRED; 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 NTSTATUS
VfatReadDisk (IN PDEVICE_OBJECT pDeviceObject, VfatReadDisk (IN PDEVICE_OBJECT pDeviceObject,
IN PLARGE_INTEGER ReadOffset, IN PLARGE_INTEGER ReadOffset,
@ -113,29 +154,100 @@ VfatReadDisk (IN PDEVICE_OBJECT pDeviceObject,
} }
NTSTATUS NTSTATUS
VfatWriteDisk (IN PDEVICE_OBJECT pDeviceObject, VfatReadDiskPartial (IN PVFAT_IRP_CONTEXT IrpContext,
IN PLARGE_INTEGER WriteOffset, IN PLARGE_INTEGER ReadOffset,
IN ULONG WriteLength, IN ULONG ReadLength,
IN PUCHAR Buffer) ULONG BufferOffset,
IN BOOLEAN Wait)
{ {
PIRP Irp; PIRP Irp;
IO_STATUS_BLOCK IoStatus;
KEVENT event;
NTSTATUS Status; NTSTATUS Status;
PVOID Buffer;
DPRINT ("VfatWriteSectors(pDeviceObject %x, Offset %I64x, Size %d, Buffer %x)\n", DPRINT ("VfatReadDiskPartial(IrpContext %x, ReadOffset %I64x, ReadLength %d, BufferOffset %x, Wait %d)\n",
pDeviceObject, WriteOffset->QuadPart, WriteLength, Buffer); 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"); DPRINT ("Building synchronous FSD Request...\n");
Irp = IoBuildSynchronousFsdRequest (IRP_MJ_WRITE, Irp = IoBuildSynchronousFsdRequest (IRP_MJ_WRITE,
pDeviceObject, IrpContext->DeviceExt->StorageDevice,
Buffer, NULL,
WriteLength, WriteLength,
WriteOffset, WriteOffset,
&event, NULL,
&IoStatus); NULL);
if (!Irp) if (!Irp)
{ {
@ -143,32 +255,41 @@ VfatWriteDisk (IN PDEVICE_OBJECT pDeviceObject,
return (STATUS_UNSUCCESSFUL); 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, IoSetCompletionRoutine(Irp,
VfatReadWriteCompletion, VfatReadWritePartialCompletion,
NULL, IrpContext,
TRUE, TRUE,
TRUE, TRUE,
TRUE); TRUE);
if (Wait)
{
KeInitializeEvent(&IrpContext->Event, NotificationEvent, FALSE);
IrpContext->RefCount = 1;
}
else
{
InterlockedIncrement((PLONG)&IrpContext->RefCount);
}
DPRINT ("Calling IO Driver...\n"); DPRINT ("Calling IO Driver...\n");
Status = IoCallDriver (pDeviceObject, Irp); Status = IoCallDriver (IrpContext->DeviceExt->StorageDevice, Irp);
if (Wait && Status == STATUS_PENDING)
DPRINT ("Waiting for IO Operation...\n");
if (Status == STATUS_PENDING)
{ {
KeWaitForSingleObject (&event, Suspended, KernelMode, FALSE, NULL); KeWaitForSingleObject(&IrpContext->Event, Executive, KernelMode, FALSE, NULL);
DPRINT ("Getting IO Status...\n"); Status = IrpContext->Irp->IoStatus.Status;
Status = IoStatus.Status;
} }
if (!NT_SUCCESS (Status)) return Status;
{
DPRINT ("IO failed!!! VfatWriteSectors : Error code: %x\n", Status);
return (Status);
}
DPRINT ("Block request succeeded\n");
return (STATUS_SUCCESS);
} }
NTSTATUS NTSTATUS
@ -188,9 +309,9 @@ VfatBlockDeviceIoControl (IN PDEVICE_OBJECT DeviceObject,
DPRINT("VfatBlockDeviceIoControl(DeviceObject %x, CtlCode %x, " DPRINT("VfatBlockDeviceIoControl(DeviceObject %x, CtlCode %x, "
"InputBuffer %x, InputBufferSize %x, OutputBuffer %x, " "InputBuffer %x, InputBufferSize %x, OutputBuffer %x, "
"POutputBufferSize %x (%x)\n", DeviceObject, CtlCode, "OutputBufferSize %x (%x)\n", DeviceObject, CtlCode,
InputBuffer, InputBufferSize, OutputBuffer, pOutputBufferSize, InputBuffer, InputBufferSize, OutputBuffer, OutputBufferSize,
pOutputBufferSize ? *pOutputBufferSize : 0); OutputBufferSize ? *OutputBufferSize : 0);
KeInitializeEvent (&Event, NotificationEvent, FALSE); 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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -164,7 +164,7 @@ PVFAT_IRP_CONTEXT VfatAllocateIrpContext(PDEVICE_OBJECT DeviceObject, PIRP Irp)
IrpContext = ExAllocateFromNPagedLookasideList(&VfatGlobalData->IrpContextLookasideList); IrpContext = ExAllocateFromNPagedLookasideList(&VfatGlobalData->IrpContextLookasideList);
if (IrpContext) if (IrpContext)
{ {
RtlZeroMemory(IrpContext, sizeof(IrpContext)); RtlZeroMemory(IrpContext, sizeof(VFAT_IRP_CONTEXT));
IrpContext->Irp = Irp; IrpContext->Irp = Irp;
IrpContext->DeviceObject = DeviceObject; IrpContext->DeviceObject = DeviceObject;
IrpContext->DeviceExt = DeviceObject->DeviceExtension; IrpContext->DeviceExt = DeviceObject->DeviceExtension;
@ -173,6 +173,7 @@ PVFAT_IRP_CONTEXT VfatAllocateIrpContext(PDEVICE_OBJECT DeviceObject, PIRP Irp)
MajorFunction = IrpContext->MajorFunction = IrpContext->Stack->MajorFunction; MajorFunction = IrpContext->MajorFunction = IrpContext->Stack->MajorFunction;
IrpContext->MinorFunction = IrpContext->Stack->MinorFunction; IrpContext->MinorFunction = IrpContext->Stack->MinorFunction;
IrpContext->FileObject = IrpContext->Stack->FileObject; IrpContext->FileObject = IrpContext->Stack->FileObject;
IrpContext->Flags = 0;
if (MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL || if (MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL ||
MajorFunction == IRP_MJ_DEVICE_CONTROL || MajorFunction == IRP_MJ_DEVICE_CONTROL ||
MajorFunction == IRP_MJ_SHUTDOWN) MajorFunction == IRP_MJ_SHUTDOWN)
@ -185,6 +186,8 @@ PVFAT_IRP_CONTEXT VfatAllocateIrpContext(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{ {
IrpContext->Flags |= IRPCONTEXT_CANWAIT; IrpContext->Flags |= IRPCONTEXT_CANWAIT;
} }
KeInitializeEvent(&IrpContext->Event, NotificationEvent, FALSE);
IrpContext->RefCount = 0;
} }
return IrpContext; 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 * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -114,8 +114,10 @@ OffsetToCluster(PDEVICE_EXTENSION DeviceExt,
} }
NTSTATUS NTSTATUS
VfatReadFileData (PVFAT_IRP_CONTEXT IrpContext, PVOID Buffer, VfatReadFileData (PVFAT_IRP_CONTEXT IrpContext,
ULONG Length, LARGE_INTEGER ReadOffset, PULONG LengthRead) ULONG Length,
LARGE_INTEGER ReadOffset,
PULONG LengthRead)
/* /*
* FUNCTION: Reads data from a file * FUNCTION: Reads data from a file
*/ */
@ -133,6 +135,7 @@ VfatReadFileData (PVFAT_IRP_CONTEXT IrpContext, PVOID Buffer,
ULONG BytesDone; ULONG BytesDone;
ULONG BytesPerSector; ULONG BytesPerSector;
ULONG BytesPerCluster; ULONG BytesPerCluster;
ULONG Count;
/* PRECONDITION */ /* PRECONDITION */
assert (IrpContext); assert (IrpContext);
@ -142,9 +145,9 @@ VfatReadFileData (PVFAT_IRP_CONTEXT IrpContext, PVOID Buffer,
assert (IrpContext->FileObject); assert (IrpContext->FileObject);
assert (IrpContext->FileObject->FsContext2 != NULL); 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, "Length %d, ReadOffset 0x%I64x)\n", DeviceExt,
IrpContext->FileObject, Buffer, Length, ReadOffset.QuadPart); IrpContext->FileObject, Length, ReadOffset.QuadPart);
*LengthRead = 0; *LengthRead = 0;
@ -161,7 +164,7 @@ VfatReadFileData (PVFAT_IRP_CONTEXT IrpContext, PVOID Buffer,
if (Fcb->Flags & FCB_IS_FAT) if (Fcb->Flags & FCB_IS_FAT)
{ {
ReadOffset.QuadPart += DeviceExt->FatInfo.FATStart * BytesPerSector; 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)) if (NT_SUCCESS(Status))
{ {
@ -176,7 +179,7 @@ VfatReadFileData (PVFAT_IRP_CONTEXT IrpContext, PVOID Buffer,
/* Is this a read of the Volume ? */ /* Is this a read of the Volume ? */
if (Fcb->Flags & FCB_IS_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)) if (NT_SUCCESS(Status))
{ {
*LengthRead = Length; *LengthRead = Length;
@ -206,10 +209,10 @@ VfatReadFileData (PVFAT_IRP_CONTEXT IrpContext, PVOID Buffer,
// Fire up the read command // Fire up the read command
Status = VfatReadDisk (DeviceExt->StorageDevice, &ReadOffset, Length, Buffer, FALSE); Status = VfatReadDiskPartial (IrpContext, &ReadOffset, Length, 0, TRUE);
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
{ {
*LengthRead += Length; *LengthRead = Length;
} }
return Status; return Status;
} }
@ -231,7 +234,11 @@ VfatReadFileData (PVFAT_IRP_CONTEXT IrpContext, PVOID Buffer,
Ccb->LastCluster = CurrentCluster; Ccb->LastCluster = CurrentCluster;
Ccb->LastOffset = ROUND_DOWN (ReadOffset.u.LowPart, BytesPerCluster); 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; StartCluster = CurrentCluster;
StartOffset.QuadPart = ClusterToSector(DeviceExt, StartCluster) * BytesPerSector; StartOffset.QuadPart = ClusterToSector(DeviceExt, StartCluster) * BytesPerSector;
@ -267,32 +274,40 @@ VfatReadFileData (PVFAT_IRP_CONTEXT IrpContext, PVOID Buffer,
Ccb->LastCluster = StartCluster + (ClusterCount - 1); Ccb->LastCluster = StartCluster + (ClusterCount - 1);
Ccb->LastOffset = ReadOffset.u.LowPart + (ClusterCount - 1) * BytesPerCluster; Ccb->LastOffset = ReadOffset.u.LowPart + (ClusterCount - 1) * BytesPerCluster;
// Fire up the read command Count++;
Status = VfatReadDisk (DeviceExt->StorageDevice, &StartOffset, BytesDone, Buffer, FALSE);
if (NT_SUCCESS(Status)) // Fire up the read command
{ Status = VfatReadDiskPartial (IrpContext, &StartOffset, BytesDone, *LengthRead, FALSE);
*LengthRead += BytesDone; if (!NT_SUCCESS(Status) && Status != STATUS_PENDING)
/* GCC allows arithmetics on the void type. Conforming compilers do not. */
#ifdef __GNUC__
Buffer += BytesDone;
#else
{ {
char* pBuf = (char*)Buffer + BytesDone; break;
Buffer = (PVOID)pBuf;
} }
#endif *LengthRead += BytesDone;
Length -= BytesDone; Length -= BytesDone;
ReadOffset.u.LowPart += 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; return Status;
} }
NTSTATUS VfatWriteFileData(PVFAT_IRP_CONTEXT IrpContext, NTSTATUS
PVOID Buffer, VfatWriteFileData(PVFAT_IRP_CONTEXT IrpContext,
ULONG Length, ULONG Length,
LARGE_INTEGER WriteOffset) LARGE_INTEGER WriteOffset)
{ {
PDEVICE_EXTENSION DeviceExt; PDEVICE_EXTENSION DeviceExt;
PVFATFCB Fcb; PVFATFCB Fcb;
@ -308,6 +323,7 @@ NTSTATUS VfatWriteFileData(PVFAT_IRP_CONTEXT IrpContext,
ULONG BytesPerSector; ULONG BytesPerSector;
ULONG BytesPerCluster; ULONG BytesPerCluster;
LARGE_INTEGER StartOffset; LARGE_INTEGER StartOffset;
ULONG BufferOffset;
/* PRECONDITION */ /* PRECONDITION */
assert (IrpContext); assert (IrpContext);
@ -322,9 +338,9 @@ NTSTATUS VfatWriteFileData(PVFAT_IRP_CONTEXT IrpContext,
BytesPerCluster = DeviceExt->FatInfo.BytesPerCluster; BytesPerCluster = DeviceExt->FatInfo.BytesPerCluster;
BytesPerSector = DeviceExt->FatInfo.BytesPerSector; 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, "Length %d, WriteOffset 0x%I64x), '%wZ'\n", DeviceExt,
IrpContext->FileObject, Buffer, Length, WriteOffset, IrpContext->FileObject, Length, WriteOffset,
&Fcb->PathNameU); &Fcb->PathNameU);
assert(WriteOffset.QuadPart + Length <= Fcb->RFCB.AllocationSize.QuadPart); 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 ? // Is this a write of the volume ?
if (Fcb->Flags & FCB_IS_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)) if (!NT_SUCCESS(Status))
{ {
DPRINT1("Volume writing failed, Status %x\n", 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) if (Fcb->Flags & FCB_IS_FAT)
{ {
WriteOffset.u.LowPart += DeviceExt->FatInfo.FATStart * BytesPerSector; WriteOffset.u.LowPart += DeviceExt->FatInfo.FATStart * BytesPerSector;
IrpContext->RefCount = 1;
for (Count = 0; Count < DeviceExt->FatInfo.FATCount; Count++) for (Count = 0; Count < DeviceExt->FatInfo.FATCount; Count++)
{ {
Status = VfatWriteDisk(DeviceExt->StorageDevice, &WriteOffset, Length, Buffer); Status = VfatWriteDiskPartial(IrpContext, &WriteOffset, Length, 0, FALSE);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status) && Status != STATUS_PENDING)
{ {
DPRINT1("FAT writing failed, Status %x\n", Status); DPRINT1("FAT writing failed, Status %x\n", Status);
break;
} }
WriteOffset.u.LowPart += Fcb->RFCB.FileSize.u.LowPart; 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; return Status;
} }
@ -370,7 +396,7 @@ NTSTATUS VfatWriteFileData(PVFAT_IRP_CONTEXT IrpContext,
// Directory of FAT12/16 needs a special handling // Directory of FAT12/16 needs a special handling
WriteOffset.u.LowPart += DeviceExt->FatInfo.rootStart * BytesPerSector; WriteOffset.u.LowPart += DeviceExt->FatInfo.rootStart * BytesPerSector;
// Fire up the write command // Fire up the write command
Status = VfatWriteDisk (DeviceExt->StorageDevice, &WriteOffset, Length, Buffer); Status = VfatWriteDiskPartial (IrpContext, &WriteOffset, Length, 0, TRUE);
return Status; return Status;
} }
@ -394,7 +420,11 @@ NTSTATUS VfatWriteFileData(PVFAT_IRP_CONTEXT IrpContext,
Ccb->LastCluster = CurrentCluster; Ccb->LastCluster = CurrentCluster;
Ccb->LastOffset = ROUND_DOWN (WriteOffset.u.LowPart, BytesPerCluster); 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; StartCluster = CurrentCluster;
StartOffset.QuadPart = ClusterToSector(DeviceExt, StartCluster) * BytesPerSector; StartOffset.QuadPart = ClusterToSector(DeviceExt, StartCluster) * BytesPerSector;
@ -431,22 +461,31 @@ NTSTATUS VfatWriteFileData(PVFAT_IRP_CONTEXT IrpContext,
Ccb->LastOffset = WriteOffset.u.LowPart + (ClusterCount - 1) * BytesPerCluster; Ccb->LastOffset = WriteOffset.u.LowPart + (ClusterCount - 1) * BytesPerCluster;
// Fire up the write command // Fire up the write command
Status = VfatWriteDisk (DeviceExt->StorageDevice, &StartOffset, BytesDone, Buffer); Status = VfatWriteDiskPartial (IrpContext, &StartOffset, BytesDone, BufferOffset, FALSE);
if (NT_SUCCESS(Status)) Count++;
{ if (!NT_SUCCESS(Status) && Status != STATUS_PENDING)
/* GCC allows arithmetics on the void type. Conforming compilers do not. */ {
#ifdef __GNUC__ break;
Buffer += BytesDone; }
#else BufferOffset += BytesDone;
{ Length -= BytesDone;
char* pBuf = (char*)Buffer + BytesDone; WriteOffset.u.LowPart += BytesDone;
Buffer = (PVOID)pBuf;
}
#endif
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; return Status;
} }
@ -486,12 +525,10 @@ VfatRead(PVFAT_IRP_CONTEXT IrpContext)
if (Fcb->Flags & FCB_IS_PAGE_FILE) if (Fcb->Flags & FCB_IS_PAGE_FILE)
{ {
PIO_STACK_LOCATION Stack;
PFATINFO FatInfo = &IrpContext->DeviceExt->FatInfo; PFATINFO FatInfo = &IrpContext->DeviceExt->FatInfo;
IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp); IrpContext->Stack->Parameters.Read.ByteOffset.QuadPart += FatInfo->dataStart * FatInfo->BytesPerSector;
Stack = IoGetNextIrpStackLocation(IrpContext->Irp); IoSkipCurrentIrpStackLocation(IrpContext->Irp);
Stack->Parameters.Read.ByteOffset.QuadPart += FatInfo->dataStart * FatInfo->BytesPerSector; DPRINT("Read from page file, disk offset %I64x\n", IrpContext->Stack->Parameters.Read.ByteOffset.QuadPart);
DPRINT("Read from page file, disk offset %I64x\n", Stack->Parameters.Read.ByteOffset.QuadPart);
Status = IoCallDriver(IrpContext->DeviceExt->StorageDevice, IrpContext->Irp); Status = IoCallDriver(IrpContext->DeviceExt->StorageDevice, IrpContext->Irp);
VfatFreeIrpContext(IrpContext); VfatFreeIrpContext(IrpContext);
return Status; return Status;
@ -527,7 +564,7 @@ VfatRead(PVFAT_IRP_CONTEXT IrpContext)
if (ByteOffset.u.LowPart % BytesPerSector != 0 || Length % BytesPerSector != 0) if (ByteOffset.u.LowPart % BytesPerSector != 0 || Length % BytesPerSector != 0)
{ {
DPRINT("%d %d\n", ByteOffset.u.LowPart, Length); 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; Status = STATUS_INVALID_PARAMETER;
goto ByeBye; 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)) && if (!(IrpContext->Irp->Flags & (IRP_NOCACHE|IRP_PAGING_IO)) &&
!(Fcb->Flags & (FCB_IS_PAGE_FILE|FCB_IS_VOLUME))) !(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; Status = /*STATUS_END_OF_FILE*/STATUS_SUCCESS;
} }
Buffer = VfatGetUserBuffer(IrpContext->Irp);
if (!Buffer)
{
Status = STATUS_INVALID_USER_BUFFER;
goto ByeBye;
}
CHECKPOINT; CHECKPOINT;
if (IrpContext->FileObject->PrivateCacheMap == NULL) 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); Length = (ULONG)(ROUND_UP(Fcb->RFCB.FileSize.QuadPart, BytesPerSector) - ByteOffset.QuadPart);
} }
Buffer = VfatGetUserBuffer(IrpContext->Irp); Status = VfatLockUserBuffer(IrpContext->Irp, Length, IoWriteAccess);
if (!Buffer) if (!NT_SUCCESS(Status))
{ {
Status = STATUS_INVALID_USER_BUFFER; goto ByeBye;
goto ByeBye; }
}
Status = VfatReadFileData(IrpContext, Buffer, Length, ByteOffset, &ReturnedLength); Status = VfatReadFileData(IrpContext, Length, ByteOffset, &ReturnedLength);
/**/ /**/
if (Status == STATUS_VERIFY_REQUIRED) if (Status == STATUS_VERIFY_REQUIRED)
{ {
@ -639,7 +675,7 @@ VfatRead(PVFAT_IRP_CONTEXT IrpContext)
if (NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
{ {
Status = VfatReadFileData(IrpContext, Buffer, Length, Status = VfatReadFileData(IrpContext, Length,
ByteOffset, &ReturnedLength); ByteOffset, &ReturnedLength);
} }
@ -725,12 +761,10 @@ NTSTATUS VfatWrite (PVFAT_IRP_CONTEXT IrpContext)
if (Fcb->Flags & FCB_IS_PAGE_FILE) if (Fcb->Flags & FCB_IS_PAGE_FILE)
{ {
PIO_STACK_LOCATION Stack;
PFATINFO FatInfo = &IrpContext->DeviceExt->FatInfo; PFATINFO FatInfo = &IrpContext->DeviceExt->FatInfo;
IoCopyCurrentIrpStackLocationToNext(IrpContext->Irp); IrpContext->Stack->Parameters.Write.ByteOffset.QuadPart += FatInfo->dataStart * FatInfo->BytesPerSector;
Stack = IoGetNextIrpStackLocation(IrpContext->Irp); IoSkipCurrentIrpStackLocation(IrpContext->Irp);
Stack->Parameters.Write.ByteOffset.QuadPart += FatInfo->dataStart * FatInfo->BytesPerSector; DPRINT("Write to page file, disk offset %I64x\n", IrpContext->Stack->Parameters.Write.ByteOffset.QuadPart);
DPRINT("Write to page file, disk offset %I64x\n", Stack->Parameters.Write.ByteOffset.QuadPart);
Status = IoCallDriver(IrpContext->DeviceExt->StorageDevice, IrpContext->Irp); Status = IoCallDriver(IrpContext->DeviceExt->StorageDevice, IrpContext->Irp);
VfatFreeIrpContext(IrpContext); VfatFreeIrpContext(IrpContext);
return Status; return Status;
@ -768,7 +802,7 @@ NTSTATUS VfatWrite (PVFAT_IRP_CONTEXT IrpContext)
{ {
if (ByteOffset.u.LowPart % BytesPerSector != 0 || Length % BytesPerSector != 0) 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; Status = STATUS_INVALID_PARAMETER;
goto ByeBye; goto ByeBye;
} }
@ -776,6 +810,9 @@ NTSTATUS VfatWrite (PVFAT_IRP_CONTEXT IrpContext)
if (Length == 0) if (Length == 0)
{ {
/* FIXME:
* Update last write time
*/
IrpContext->Irp->IoStatus.Information = 0; IrpContext->Irp->IoStatus.Information = 0;
Status = STATUS_SUCCESS; Status = STATUS_SUCCESS;
goto ByeBye; goto ByeBye;
@ -850,6 +887,14 @@ NTSTATUS VfatWrite (PVFAT_IRP_CONTEXT IrpContext)
OldFileSize = Fcb->RFCB.FileSize; OldFileSize = Fcb->RFCB.FileSize;
OldAllocationSize = Fcb->RFCB.AllocationSize.u.LowPart; 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)) && if (!(Fcb->Flags & (FCB_IS_FAT|FCB_IS_VOLUME)) &&
!(IrpContext->Irp->Flags & IRP_PAGING_IO) && !(IrpContext->Irp->Flags & IRP_PAGING_IO) &&
ByteOffset.u.LowPart + Length > Fcb->RFCB.FileSize.u.LowPart) ByteOffset.u.LowPart + Length > Fcb->RFCB.FileSize.u.LowPart)
@ -872,13 +917,6 @@ NTSTATUS VfatWrite (PVFAT_IRP_CONTEXT IrpContext)
// cached write // cached write
CHECKPOINT; CHECKPOINT;
Buffer = VfatGetUserBuffer(IrpContext->Irp);
if (!Buffer)
{
Status = STATUS_INVALID_USER_BUFFER;
goto ByeBye;
}
CHECKPOINT;
if (IrpContext->FileObject->PrivateCacheMap == NULL) if (IrpContext->FileObject->PrivateCacheMap == NULL)
{ {
ULONG CacheSize; ULONG CacheSize;
@ -914,14 +952,14 @@ NTSTATUS VfatWrite (PVFAT_IRP_CONTEXT IrpContext)
{ {
CcZeroData(IrpContext->FileObject, &OldFileSize, &ByteOffset, TRUE); 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)) if (NT_SUCCESS(Status))
{ {
IrpContext->Irp->IoStatus.Information = Length; 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> #include <ddk/ntifs.h>
@ -288,7 +288,8 @@ typedef struct __DOSDATE
} }
DOSDATE, *PDOSDATE; DOSDATE, *PDOSDATE;
#define IRPCONTEXT_CANWAIT 0x0001 #define IRPCONTEXT_CANWAIT 0x0001
#define IRPCONTEXT_PENDINGRETURNED 0x0002
typedef struct typedef struct
{ {
@ -301,6 +302,8 @@ typedef struct
UCHAR MajorFunction; UCHAR MajorFunction;
UCHAR MinorFunction; UCHAR MinorFunction;
PFILE_OBJECT FileObject; PFILE_OBJECT FileObject;
ULONG RefCount;
KEVENT Event;
} VFAT_IRP_CONTEXT, *PVFAT_IRP_CONTEXT; } VFAT_IRP_CONTEXT, *PVFAT_IRP_CONTEXT;
typedef struct _VFAT_DIRENTRY_CONTEXT typedef struct _VFAT_DIRENTRY_CONTEXT
@ -332,10 +335,17 @@ NTSTATUS VfatReadDisk(IN PDEVICE_OBJECT pDeviceObject,
IN PUCHAR Buffer, IN PUCHAR Buffer,
IN BOOLEAN Override); IN BOOLEAN Override);
NTSTATUS VfatWriteDisk(IN PDEVICE_OBJECT pDeviceObject, NTSTATUS VfatReadDiskPartial (IN PVFAT_IRP_CONTEXT IrpContext,
IN PLARGE_INTEGER WriteOffset, IN PLARGE_INTEGER ReadOffset,
IN ULONG WriteLength, IN ULONG ReadLength,
IN PUCHAR Buffer); 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, NTSTATUS VfatBlockDeviceIoControl (IN PDEVICE_OBJECT DeviceObject,
IN ULONG CtlCode, IN ULONG CtlCode,