📄 rw.c
字号:
ASSERT(WriteOffset.QuadPart + Length <= Fcb->RFCB.AllocationSize.QuadPart);
ASSERT(WriteOffset.u.LowPart % BytesPerSector == 0);
ASSERT(Length % BytesPerSector == 0);
// Is this a write of the volume ?
if (Fcb->Flags & FCB_IS_VOLUME)
{
Status = VfatWriteDiskPartial(IrpContext, &WriteOffset, Length, 0, TRUE);
if (!NT_SUCCESS(Status))
{
DPRINT1("Volume writing failed, Status %x\n", Status);
}
return Status;
}
// Is this a write to the FAT ?
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 = 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;
}
/*
* Find the first cluster
*/
FirstCluster = CurrentCluster =
vfatDirEntryGetFirstCluster (DeviceExt, &Fcb->entry);
if (FirstCluster == 1)
{
ASSERT(WriteOffset.u.LowPart + Length <= DeviceExt->FatInfo.rootDirectorySectors * BytesPerSector);
// Directory of FAT12/16 needs a special handling
WriteOffset.u.LowPart += DeviceExt->FatInfo.rootStart * BytesPerSector;
// Fire up the write command
Status = VfatWriteDiskPartial (IrpContext, &WriteOffset, Length, 0, TRUE);
return Status;
}
ExAcquireFastMutex(&Fcb->LastMutex);
LastCluster = Fcb->LastCluster;
LastOffset = Fcb->LastOffset;
ExReleaseFastMutex(&Fcb->LastMutex);
/*
* Find the cluster to start the write from
*/
if (LastCluster > 0 && WriteOffset.u.LowPart >= LastOffset)
{
Status = OffsetToCluster(DeviceExt, LastCluster,
ROUND_DOWN(WriteOffset.u.LowPart, BytesPerCluster) -
LastOffset,
&CurrentCluster, FALSE);
#ifdef DEBUG_VERIFY_OFFSET_CACHING
/* DEBUG VERIFICATION */
{
ULONG CorrectCluster;
OffsetToCluster(DeviceExt, FirstCluster,
ROUND_DOWN(WriteOffset.u.LowPart, BytesPerCluster),
&CorrectCluster, FALSE);
if (CorrectCluster != CurrentCluster)
KEBUGCHECK(FAT_FILE_SYSTEM);
}
#endif
}
else
{
Status = OffsetToCluster(DeviceExt, FirstCluster,
ROUND_DOWN(WriteOffset.u.LowPart, BytesPerCluster),
&CurrentCluster, FALSE);
}
if (!NT_SUCCESS(Status))
{
return(Status);
}
ExAcquireFastMutex(&Fcb->LastMutex);
Fcb->LastCluster = CurrentCluster;
Fcb->LastOffset = ROUND_DOWN (WriteOffset.u.LowPart, BytesPerCluster);
ExReleaseFastMutex(&Fcb->LastMutex);
IrpContext->RefCount = 1;
BufferOffset = 0;
while (Length > 0 && CurrentCluster != 0xffffffff)
{
StartCluster = CurrentCluster;
StartOffset.QuadPart = ClusterToSector(DeviceExt, StartCluster) * BytesPerSector;
BytesDone = 0;
ClusterCount = 0;
do
{
ClusterCount++;
if (First)
{
BytesDone = min (Length, BytesPerCluster - (WriteOffset.u.LowPart % BytesPerCluster));
StartOffset.QuadPart += WriteOffset.u.LowPart % BytesPerCluster;
First = FALSE;
}
else
{
if (Length - BytesDone > BytesPerCluster)
{
BytesDone += BytesPerCluster;
}
else
{
BytesDone = Length;
}
}
Status = NextCluster(DeviceExt, FirstCluster, &CurrentCluster, FALSE);
}
while (StartCluster + ClusterCount == CurrentCluster && NT_SUCCESS(Status) && Length > BytesDone);
DPRINT("start %08x, next %08x, count %d\n",
StartCluster, CurrentCluster, ClusterCount);
ExAcquireFastMutex(&Fcb->LastMutex);
Fcb->LastCluster = StartCluster + (ClusterCount - 1);
Fcb->LastOffset = ROUND_DOWN(WriteOffset.u.LowPart, BytesPerCluster) + (ClusterCount - 1) * BytesPerCluster;
ExReleaseFastMutex(&Fcb->LastMutex);
// Fire up the write command
Status = VfatWriteDiskPartial (IrpContext, &StartOffset, BytesDone, BufferOffset, FALSE);
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;
}
NTSTATUS
VfatRead(PVFAT_IRP_CONTEXT IrpContext)
{
NTSTATUS Status;
PVFATFCB Fcb;
ULONG Length = 0;
ULONG ReturnedLength = 0;
PERESOURCE Resource = NULL;
LARGE_INTEGER ByteOffset;
PVOID Buffer;
PDEVICE_OBJECT DeviceToVerify;
ULONG BytesPerSector;
ASSERT(IrpContext);
DPRINT("VfatRead(IrpContext %x)\n", IrpContext);
ASSERT(IrpContext->DeviceObject);
// This request is not allowed on the main device object
if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject)
{
DPRINT("VfatRead is called with the main device object.\n");
Status = STATUS_INVALID_DEVICE_REQUEST;
goto ByeBye;
}
ASSERT(IrpContext->DeviceExt);
ASSERT(IrpContext->FileObject);
Fcb = IrpContext->FileObject->FsContext;
ASSERT(Fcb);
DPRINT("<%wZ>\n", &Fcb->PathNameU);
if (Fcb->Flags & FCB_IS_PAGE_FILE)
{
PFATINFO FatInfo = &IrpContext->DeviceExt->FatInfo;
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;
}
ByteOffset = IrpContext->Stack->Parameters.Read.ByteOffset;
Length = IrpContext->Stack->Parameters.Read.Length;
BytesPerSector = IrpContext->DeviceExt->FatInfo.BytesPerSector;
/* fail if file is a directory and no paged read */
if (*Fcb->Attributes & FILE_ATTRIBUTE_DIRECTORY && !(IrpContext->Irp->Flags & IRP_PAGING_IO))
{
Status = STATUS_INVALID_PARAMETER;
goto ByeBye;
}
DPRINT("'%wZ', Offset: %d, Length %d\n", &Fcb->PathNameU, ByteOffset.u.LowPart, Length);
if (ByteOffset.u.HighPart && !(Fcb->Flags & FCB_IS_VOLUME))
{
Status = STATUS_INVALID_PARAMETER;
goto ByeBye;
}
if (ByteOffset.QuadPart >= Fcb->RFCB.FileSize.QuadPart)
{
IrpContext->Irp->IoStatus.Information = 0;
Status = STATUS_END_OF_FILE;
goto ByeBye;
}
if (IrpContext->Irp->Flags & (IRP_PAGING_IO | IRP_NOCACHE) || (Fcb->Flags & FCB_IS_VOLUME))
{
if (ByteOffset.u.LowPart % BytesPerSector != 0 || Length % BytesPerSector != 0)
{
DPRINT("%d %d\n", ByteOffset.u.LowPart, Length);
// non cached read must be sector aligned
Status = STATUS_INVALID_PARAMETER;
goto ByeBye;
}
}
if (Length == 0)
{
IrpContext->Irp->IoStatus.Information = 0;
Status = STATUS_SUCCESS;
goto ByeBye;
}
if (Fcb->Flags & FCB_IS_VOLUME)
{
Resource = &IrpContext->DeviceExt->DirResource;
}
else if (IrpContext->Irp->Flags & IRP_PAGING_IO)
{
Resource = &Fcb->PagingIoResource;
}
else
{
Resource = &Fcb->MainResource;
}
if (!ExAcquireResourceSharedLite(Resource,
IrpContext->Flags & IRPCONTEXT_CANWAIT ? TRUE : FALSE))
{
Resource = NULL;
Status = STATUS_PENDING;
goto ByeBye;
}
if (!(IrpContext->Irp->Flags & IRP_PAGING_IO) &&
FsRtlAreThereCurrentFileLocks(&Fcb->FileLock))
{
if (!FsRtlCheckLockForReadAccess(&Fcb->FileLock, IrpContext->Irp))
{
Status = STATUS_FILE_LOCK_CONFLICT;
goto ByeBye;
}
}
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)))
{
// cached read
CHECKPOINT;
Status = STATUS_SUCCESS;
if (ByteOffset.u.LowPart + Length > Fcb->RFCB.FileSize.u.LowPart)
{
Length = Fcb->RFCB.FileSize.u.LowPart - ByteOffset.u.LowPart;
Status = /*STATUS_END_OF_FILE*/STATUS_SUCCESS;
}
CHECKPOINT;
if (IrpContext->FileObject->PrivateCacheMap == NULL)
{
#ifdef USE_ROS_CC_AND_FS
ULONG CacheSize;
CacheSize = max(IrpContext->DeviceExt->FatInfo.BytesPerCluster,
8 * PAGE_SIZE);
CcRosInitializeFileCache(IrpContext->FileObject, CacheSize);
#else
/* FIXME: Guard by SEH. */
CcInitializeCacheMap(IrpContext->FileObject,
(PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize),
FALSE,
&(VfatGlobalData->CacheMgrCallbacks),
Fcb);
#endif
}
if (!CcCopyRead(IrpContext->FileObject, &ByteOffset, Length,
(BOOLEAN)(IrpContext->Flags & IRPCONTEXT_CANWAIT), Buffer,
&IrpContext->Irp->IoStatus))
{
Status = IrpContext->Irp->IoStatus.Status;//STATUS_PENDING;
goto ByeBye;
}
CHECKPOINT;
if (!NT_SUCCESS(IrpContext->Irp->IoStatus.Status))
{
Status = IrpContext->Irp->IoStatus.Status;
}
}
else
{
// non cached read
CHECKPOINT;
if (ByteOffset.QuadPart + Length > ROUND_UP(Fcb->RFCB.FileSize.QuadPart, BytesPerSector))
{
Length = (ULONG)(ROUND_UP(Fcb->RFCB.FileSize.QuadPart, BytesPerSector) - ByteOffset.QuadPart);
}
Status = VfatLockUserBuffer(IrpContext->Irp, Length, IoWriteAccess);
if (!NT_SUCCESS(Status))
{
goto ByeBye;
}
Status = VfatReadFileData(IrpContext, Length, ByteOffset, &ReturnedLength);
/**/
if (Status == STATUS_VERIFY_REQUIRED)
{
DPRINT("VfatReadFile returned STATUS_VERIFY_REQUIRED\n");
DeviceToVerify = IoGetDeviceToVerify(PsGetCurrentThread());
IoSetDeviceToVerify(PsGetCurrentThread(), DeviceToVerify);
Status = IoVerifyVolume (DeviceToVerify, FALSE);
if (NT_SUCCESS(Status))
{
Status = VfatReadFileData(IrpContext, Length,
ByteOffset, &ReturnedLength);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -