📄 rw.c
字号:
}
/**/
if (NT_SUCCESS(Status))
{
IrpContext->Irp->IoStatus.Information = ReturnedLength;
}
}
ByeBye:
if (Resource)
{
ExReleaseResourceLite(Resource);
}
if (Status == STATUS_PENDING)
{
Status = VfatLockUserBuffer(IrpContext->Irp, Length, IoWriteAccess);
if (NT_SUCCESS(Status))
{
Status = VfatQueueRequest(IrpContext);
}
else
{
IrpContext->Irp->IoStatus.Status = Status;
IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
VfatFreeIrpContext(IrpContext);
}
}
else
{
IrpContext->Irp->IoStatus.Status = Status;
if (IrpContext->FileObject->Flags & FO_SYNCHRONOUS_IO &&
!(IrpContext->Irp->Flags & IRP_PAGING_IO) &&
(NT_SUCCESS(Status) || Status==STATUS_END_OF_FILE))
{
IrpContext->FileObject->CurrentByteOffset.QuadPart =
ByteOffset.QuadPart + IrpContext->Irp->IoStatus.Information;
}
IoCompleteRequest(IrpContext->Irp,
(CCHAR)(NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT));
VfatFreeIrpContext(IrpContext);
}
DPRINT("%x\n", Status);
return Status;
}
NTSTATUS VfatWrite (PVFAT_IRP_CONTEXT IrpContext)
{
PVFATFCB Fcb;
PERESOURCE Resource = NULL;
LARGE_INTEGER ByteOffset;
LARGE_INTEGER OldFileSize;
NTSTATUS Status = STATUS_SUCCESS;
ULONG Length = 0;
ULONG OldAllocationSize;
PVOID Buffer;
ULONG BytesPerSector;
ASSERT(IrpContext);
DPRINT("VfatWrite(IrpContext %x)\n", IrpContext);
ASSERT(IrpContext->DeviceObject);
// This request is not allowed on the main device object
if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject)
{
DPRINT("VfatWrite 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.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;
}
/* 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;
}
ByteOffset = IrpContext->Stack->Parameters.Write.ByteOffset;
if (ByteOffset.u.LowPart == FILE_WRITE_TO_END_OF_FILE &&
ByteOffset.u.HighPart == -1)
{
ByteOffset.QuadPart = Fcb->RFCB.FileSize.QuadPart;
}
Length = IrpContext->Stack->Parameters.Write.Length;
BytesPerSector = IrpContext->DeviceExt->FatInfo.BytesPerSector;
if (ByteOffset.u.HighPart && !(Fcb->Flags & FCB_IS_VOLUME))
{
Status = STATUS_INVALID_PARAMETER;
goto ByeBye;
}
if (Fcb->Flags & (FCB_IS_FAT | FCB_IS_VOLUME) ||
1 == vfatDirEntryGetFirstCluster (IrpContext->DeviceExt, &Fcb->entry))
{
if (ByteOffset.QuadPart + Length > Fcb->RFCB.FileSize.QuadPart)
{
// we can't extend the FAT, the volume or the root on FAT12/FAT16
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)
{
// non cached write must be sector aligned
Status = STATUS_INVALID_PARAMETER;
goto ByeBye;
}
}
if (Length == 0)
{
/* FIXME:
* Update last write time
*/
IrpContext->Irp->IoStatus.Information = 0;
Status = STATUS_SUCCESS;
goto ByeBye;
}
if (IrpContext->Irp->Flags & IRP_PAGING_IO)
{
if (ByteOffset.u.LowPart + Length > Fcb->RFCB.AllocationSize.u.LowPart)
{
Status = STATUS_INVALID_PARAMETER;
goto ByeBye;
}
if (ByteOffset.u.LowPart + Length > ROUND_UP(Fcb->RFCB.AllocationSize.u.LowPart, BytesPerSector))
{
Length = ROUND_UP(Fcb->RFCB.FileSize.u.LowPart, BytesPerSector) - ByteOffset.u.LowPart;
}
}
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 (Fcb->Flags & FCB_IS_PAGE_FILE)
{
if (!ExAcquireResourceSharedLite(Resource,
(BOOLEAN)(IrpContext->Flags & IRPCONTEXT_CANWAIT)))
{
Resource = NULL;
Status = STATUS_PENDING;
goto ByeBye;
}
}
else
{
if (!ExAcquireResourceExclusiveLite(Resource,
(BOOLEAN)(IrpContext->Flags & IRPCONTEXT_CANWAIT)))
{
Resource = NULL;
Status = STATUS_PENDING;
goto ByeBye;
}
}
if (!(IrpContext->Irp->Flags & IRP_PAGING_IO) &&
FsRtlAreThereCurrentFileLocks(&Fcb->FileLock))
{
if (!FsRtlCheckLockForWriteAccess(&Fcb->FileLock, IrpContext->Irp))
{
Status = STATUS_FILE_LOCK_CONFLICT;
goto ByeBye;
}
}
if (!(IrpContext->Flags & IRPCONTEXT_CANWAIT) && !(Fcb->Flags & FCB_IS_VOLUME))
{
if (ByteOffset.u.LowPart + Length > Fcb->RFCB.AllocationSize.u.LowPart)
{
Status = STATUS_PENDING;
goto ByeBye;
}
}
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)
{
LARGE_INTEGER AllocationSize;
AllocationSize.QuadPart = ByteOffset.u.LowPart + Length;
Status = VfatSetAllocationSizeInformation(IrpContext->FileObject, Fcb,
IrpContext->DeviceExt, &AllocationSize);
if (!NT_SUCCESS (Status))
{
CHECKPOINT;
goto ByeBye;
}
}
if (!(IrpContext->Irp->Flags & (IRP_NOCACHE|IRP_PAGING_IO)) &&
!(Fcb->Flags & (FCB_IS_PAGE_FILE|FCB_IS_VOLUME)))
{
// cached write
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 (ByteOffset.QuadPart > OldFileSize.QuadPart)
{
CcZeroData(IrpContext->FileObject, &OldFileSize, &ByteOffset, TRUE);
}
if (CcCopyWrite(IrpContext->FileObject, &ByteOffset, Length,
1 /*IrpContext->Flags & IRPCONTEXT_CANWAIT*/, Buffer))
{
IrpContext->Irp->IoStatus.Information = Length;
Status = STATUS_SUCCESS;
}
else
{
Status = STATUS_UNSUCCESSFUL;
}
CHECKPOINT;
}
else
{
// non cached write
CHECKPOINT;
if (ByteOffset.QuadPart > OldFileSize.QuadPart)
{
CcZeroData(IrpContext->FileObject, &OldFileSize, &ByteOffset, TRUE);
}
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;
}
}
if (!(IrpContext->Irp->Flags & IRP_PAGING_IO) &&
!(Fcb->Flags & (FCB_IS_FAT|FCB_IS_VOLUME)))
{
if(!(*Fcb->Attributes & FILE_ATTRIBUTE_DIRECTORY))
{
LARGE_INTEGER SystemTime;
// set dates and times
KeQuerySystemTime (&SystemTime);
if (Fcb->Flags & FCB_IS_FATX_ENTRY)
{
FsdSystemTimeToDosDateTime (IrpContext->DeviceExt,
&SystemTime, &Fcb->entry.FatX.UpdateDate,
&Fcb->entry.FatX.UpdateTime);
Fcb->entry.FatX.AccessDate = Fcb->entry.FatX.UpdateDate;
Fcb->entry.FatX.AccessTime = Fcb->entry.FatX.UpdateTime;
}
else
{
FsdSystemTimeToDosDateTime (IrpContext->DeviceExt,
&SystemTime, &Fcb->entry.Fat.UpdateDate,
&Fcb->entry.Fat.UpdateTime);
Fcb->entry.Fat.AccessDate = Fcb->entry.Fat.UpdateDate;
}
/* set date and times to dirty */
Fcb->Flags |= FCB_IS_DIRTY;
}
}
ByeBye:
if (Resource)
{
ExReleaseResourceLite(Resource);
}
if (Status == STATUS_PENDING)
{
Status = VfatLockUserBuffer(IrpContext->Irp, Length, IoReadAccess);
if (NT_SUCCESS(Status))
{
Status = VfatQueueRequest(IrpContext);
}
else
{
IrpContext->Irp->IoStatus.Status = Status;
IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
VfatFreeIrpContext(IrpContext);
}
}
else
{
IrpContext->Irp->IoStatus.Status = Status;
if (IrpContext->FileObject->Flags & FO_SYNCHRONOUS_IO &&
!(IrpContext->Irp->Flags & IRP_PAGING_IO) && NT_SUCCESS(Status))
{
IrpContext->FileObject->CurrentByteOffset.QuadPart =
ByteOffset.QuadPart + IrpContext->Irp->IoStatus.Information;
}
IoCompleteRequest(IrpContext->Irp,
(CCHAR)(NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT));
VfatFreeIrpContext(IrpContext);
}
DPRINT("%x\n", Status);
return Status;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -