mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
- Improved the reading and writing of fragmented files.
svn path=/trunk/; revision=9412
This commit is contained in:
parent
189436c3ef
commit
d16209b9dc
4 changed files with 306 additions and 134 deletions
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue