📄 write.c
字号:
&Irp->MdlAddress,
&Irp->IoStatus );
Status = Irp->IoStatus.Status;
} else {
Buffer = RfsdGetUserBuffer(Irp);
if (Buffer == NULL) {
DbgBreak();
Status = STATUS_INVALID_USER_BUFFER;
__leave;
}
if (!CcCopyWrite( Vcb->StreamObj,
(PLARGE_INTEGER)(&ByteOffset),
Length,
TRUE,
Buffer )) {
Status = STATUS_PENDING;
__leave;
}
Status = Irp->IoStatus.Status;
RfsdAddMcbEntry(Vcb, ByteOffset.QuadPart, (LONGLONG)Length);
}
if (NT_SUCCESS(Status)) {
Irp->IoStatus.Information = Length;
}
} else {
PRFSD_BDL rfsd_bdl = NULL;
ULONG Blocks = 0;
LONGLONG DirtyStart;
LONGLONG DirtyLba;
LONGLONG DirtyLength;
LONGLONG RemainLength;
if ((ByteOffset.QuadPart + Length) >
Vcb->PartitionInformation.PartitionLength.QuadPart ) {
Length = (ULONG) (
Vcb->PartitionInformation.PartitionLength.QuadPart -
ByteOffset.QuadPart);
Length &= ~((ULONG)SECTOR_SIZE - 1);
}
Status = RfsdLockUserBuffer(
IrpContext->Irp,
Length,
IoReadAccess );
if (!NT_SUCCESS(Status)) {
__leave;
}
rfsd_bdl = ExAllocatePool( PagedPool,
(Length / Vcb->BlockSize) *
sizeof(RFSD_BDL) );
if (!rfsd_bdl) {
Status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
}
DirtyLba = ByteOffset.QuadPart;
RemainLength = (LONGLONG) Length;
while (RemainLength > 0) {
DirtyStart = DirtyLba;
if (RfsdLookupMcbEntry( Vcb,
DirtyStart,
&DirtyLba,
&DirtyLength,
(PLONGLONG)NULL,
(PLONGLONG)NULL,
(PULONG)NULL) ) {
if (DirtyLba == -1) {
DirtyLba = DirtyStart + DirtyLength;
RemainLength = ByteOffset.QuadPart +
(LONGLONG)Length -
DirtyLba;
continue;
}
rfsd_bdl[Blocks].Irp = NULL;
rfsd_bdl[Blocks].Lba = DirtyLba;
rfsd_bdl[Blocks].Offset = (ULONG)( (LONGLONG)Length +
DirtyStart -
RemainLength -
DirtyLba );
if (DirtyLba + DirtyLength > DirtyStart + RemainLength) {
rfsd_bdl[Blocks].Length = (ULONG)( DirtyStart +
RemainLength -
DirtyLba );
RemainLength = 0;
} else {
rfsd_bdl[Blocks].Length = (ULONG)DirtyLength;
RemainLength = (DirtyStart + RemainLength) -
(DirtyLba + DirtyLength);
}
DirtyLba = DirtyStart + DirtyLength;
Blocks++;
} else {
if (Blocks == 0) {
if (rfsd_bdl)
ExFreePool(rfsd_bdl);
//
// Lookup fails at the first time, ie.
// no dirty blocks in the run
//
DbgBreak();
if (RemainLength == (LONGLONG)Length)
Status = STATUS_SUCCESS;
else
Status = STATUS_UNSUCCESSFUL;
__leave;
} else {
break;
}
}
}
if (Blocks > 0) {
Status = RfsdReadWriteBlocks(IrpContext,
Vcb,
rfsd_bdl,
Length,
Blocks,
FALSE );
Irp = IrpContext->Irp;
if (NT_SUCCESS(Status)) {
ULONG i;
for (i=0; i<Blocks;i++) {
RfsdRemoveMcbEntry( Vcb,
rfsd_bdl[i].Lba,
rfsd_bdl[i].Length );
}
}
if (rfsd_bdl)
ExFreePool(rfsd_bdl);
if (!Irp)
__leave;
} else {
if (rfsd_bdl)
ExFreePool(rfsd_bdl);
Irp->IoStatus.Information = Length;
Status = STATUS_SUCCESS;
__leave;
}
}
} __finally {
if (PagingIoResourceAcquired) {
ExReleaseResourceForThreadLite(
&Vcb->PagingIoResource,
ExGetCurrentResourceThread());
}
if (MainResourceAcquired) {
ExReleaseResourceForThreadLite(
&Vcb->MainResource,
ExGetCurrentResourceThread());
}
if (!IrpContext->ExceptionInProgress) {
if (Irp) {
if (Status == STATUS_PENDING) {
if(!bDeferred) {
Status = RfsdLockUserBuffer(
IrpContext->Irp,
Length,
IoReadAccess );
if (NT_SUCCESS(Status)) {
Status = RfsdQueueRequest(IrpContext);
} else {
RfsdCompleteIrpContext(IrpContext, Status);
}
}
} else {
if (NT_SUCCESS(Status)) {
if (SynchronousIo && !PagingIo) {
FileObject->CurrentByteOffset.QuadPart =
ByteOffset.QuadPart + Irp->IoStatus.Information;
}
if (!PagingIo) {
SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
}
}
RfsdCompleteIrpContext(IrpContext, Status);
}
} else {
RfsdFreeIrpContext(IrpContext);
}
}
}
return Status;
}
NTSTATUS
RfsdWriteInode (
IN PRFSD_IRP_CONTEXT IrpContext,
IN PRFSD_VCB Vcb,
IN ULONG InodeNo,
IN PRFSD_INODE Inode,
IN ULONGLONG Offset,
IN PVOID Buffer,
IN ULONG Size,
IN BOOLEAN bWriteToDisk,
OUT PULONG dwRet
)
{
PRFSD_BDL rfsd_bdl = NULL;
ULONG blocks, i;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
ULONGLONG FileSize;
ULONGLONG AllocSize;
BOOLEAN bAlloc = FALSE;
if (dwRet) {
*dwRet = 0;
}
//
// For file/non pagingio, we support the allocation on writing.
//
if (S_ISREG(Inode->i_mode)) {
if (!(IrpContext->Irp->Flags & IRP_PAGING_IO)) {
bAlloc = TRUE;
}
}
//
// Initialize the FileSize / AllocationSize ...
//
FileSize = (ULONGLONG) Inode->i_size;
if (S_ISREG(Inode->i_mode))
FileSize |= ((ULONGLONG)(Inode->i_size_high) << 32);
AllocSize = CEILING_ALIGNED(FileSize, (ULONGLONG)Vcb->BlockSize);
//
// Check the inputed parameters ...
//
if (!bAlloc) {
if (Offset >= AllocSize) {
RfsdPrint((DBG_ERROR, "RfsdWritenode: beyond the file range.\n"));
return STATUS_SUCCESS;
}
if (Offset + Size > AllocSize) {
Size = (ULONG)(AllocSize - Offset);
}
}
Status = RfsdBuildBDL (
IrpContext,
Vcb,
InodeNo,
Inode,
Offset,
Size,
bAlloc,
&rfsd_bdl,
&blocks
);
if (blocks <= 0) {
Status = STATUS_SUCCESS;
goto errorout;
}
if (bWriteToDisk) {
//
// We assume the offset is aligned.
//
Status = RfsdReadWriteBlocks(
IrpContext,
Vcb,
rfsd_bdl,
Size,
blocks,
FALSE
);
} else {
for(i = 0; i < blocks; i++) {
if( !RfsdSaveBuffer(
IrpContext,
Vcb,
rfsd_bdl[i].Lba,
rfsd_bdl[i].Length,
(PVOID)((PUCHAR)Buffer + rfsd_bdl[i].Offset)
)) {
goto errorout;
}
}
if (IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK)) {
RfsdPrint((DBG_USER, "RfsdWriteInode is starting FlushingDpc...\n"));
RfsdStartFloppyFlushDpc(Vcb, NULL, NULL);
}
Status = STATUS_SUCCESS;
}
errorout:
if (rfsd_bdl)
ExFreePool(rfsd_bdl);
if (NT_SUCCESS(Status)) {
if (dwRet) *dwRet = Size;
}
return Status;
}
NTSTATUS
RfsdWriteFile(IN PRFSD_IRP_CONTEXT IrpContext)
{
NTSTATUS Status = STATUS_UNSUCCESSFUL;
PRFSD_VCB Vcb;
PRFSD_FCB Fcb;
PRFSD_CCB Ccb;
PFILE_OBJECT FileObject;
PFILE_OBJECT CacheObject;
PDEVICE_OBJECT DeviceObject;
PIRP Irp;
PIO_STACK_LOCATION IoStackLocation;
ULONG Length;
ULONG ReturnedLength;
LARGE_INTEGER ByteOffset;
BOOLEAN PagingIo;
BOOLEAN Nocache;
BOOLEAN SynchronousIo;
BOOLEAN MainResourceAcquired = FALSE;
BOOLEAN PagingIoResourceAcquired = FALSE;
BOOLEAN bNeedExtending = FALSE;
BOOLEAN bAppendFile = FALSE;
BOOLEAN bDeferred = FALSE;
PUCHAR Buffer;
__try {
ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == RFSDICX) &&
(IrpContext->Identifier.Size == sizeof(RFSD_IRP_CONTEXT)));
DeviceObject = IrpContext->DeviceObject;
Vcb = (PRFSD_VCB) DeviceObject->DeviceExtension;
ASSERT(Vcb != NULL);
ASSERT((Vcb->Identifier.Type == RFSDVCB) &&
(Vcb->Identifier.Size == sizeof(RFSD_VCB)));
FileObject = IrpContext->FileObject;
Fcb = (PRFSD_FCB) FileObject->FsContext;
ASSERT(Fcb);
ASSERT((Fcb->Identifier.Type == RFSDFCB) &&
(Fcb->Identifier.Size == sizeof(RFSD_FCB)));
Ccb = (PRFSD_CCB) FileObject->FsContext2;
Irp = IrpContext->Irp;
IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
Length = IoStackLocation->Parameters.Write.Length;
ByteOffset = IoStackLocation->Parameters.Write.ByteOffset;
PagingIo = (Irp->Flags & IRP_PAGING_IO ? TRUE : FALSE);
Nocache = (Irp->Flags & IRP_NOCACHE ? TRUE : FALSE);
SynchronousIo = (FileObject->Flags & FO_SYNCHRONOUS_IO ? TRUE : FALSE);
RfsdPrint((DBG_INFO, "RfsdWriteFile: Off=%I64xh Len=%xh Paging=%xh Nocache=%xh\n",
ByteOffset.QuadPart, Length, PagingIo, Nocache));
/*
if (IsFlagOn(Fcb->Flags, FCB_FILE_DELETED))
{
Status = STATUS_FILE_DELETED;
__leave;
}
if (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING))
{
Status = STATUS_DELETE_PENDING;
__leave;
}
*/
if (Length == 0) {
Irp->IoStatus.Information = 0;
Status = STATUS_SUCCESS;
__leave;
}
if (Nocache &&
(ByteOffset.LowPart & (SECTOR_SIZE - 1) ||
Length & (SECTOR_SIZE - 1))) {
Status = STATUS_INVALID_PARAMETER;
__leave;
}
if (FlagOn(IrpContext->MinorFunction, IRP_MN_DPC)) {
ClearFlag(IrpContext->MinorFunction, IRP_MN_DPC);
Status = STATUS_PENDING;
__leave;
}
#if FALSE
if (!Nocache) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -