mirror of
				https://github.com/winfsp/winfsp.git
				synced 2025-10-30 19:48:38 -05:00 
			
		
		
		
	sys: IRP_MJ_READ: implementation
This commit is contained in:
		| @@ -184,6 +184,10 @@ typedef struct | |||||||
|         { |         { | ||||||
|             UINT64 UserContext; |             UINT64 UserContext; | ||||||
|             UINT64 UserContext2; |             UINT64 UserContext2; | ||||||
|  |             UINT64 Address; | ||||||
|  |             UINT64 Offset; | ||||||
|  |             UINT32 Length; | ||||||
|  |             UINT32 Key; | ||||||
|         } Read; |         } Read; | ||||||
|         struct |         struct | ||||||
|         { |         { | ||||||
|   | |||||||
| @@ -70,6 +70,7 @@ NTSTATUS DriverEntry( | |||||||
|     FspIopPrepareFunction[IRP_MJ_CREATE] = FspFsvolCreatePrepare; |     FspIopPrepareFunction[IRP_MJ_CREATE] = FspFsvolCreatePrepare; | ||||||
|     FspIopCompleteFunction[IRP_MJ_CREATE] = FspFsvolCreateComplete; |     FspIopCompleteFunction[IRP_MJ_CREATE] = FspFsvolCreateComplete; | ||||||
|     FspIopCompleteFunction[IRP_MJ_CLOSE] = FspFsvolCloseComplete; |     FspIopCompleteFunction[IRP_MJ_CLOSE] = FspFsvolCloseComplete; | ||||||
|  |     FspIopPrepareFunction[IRP_MJ_READ] = FspFsvolReadPrepare; | ||||||
|     FspIopCompleteFunction[IRP_MJ_READ] = FspFsvolReadComplete; |     FspIopCompleteFunction[IRP_MJ_READ] = FspFsvolReadComplete; | ||||||
|     FspIopPrepareFunction[IRP_MJ_WRITE] = FspFsvolWritePrepare; |     FspIopPrepareFunction[IRP_MJ_WRITE] = FspFsvolWritePrepare; | ||||||
|     FspIopCompleteFunction[IRP_MJ_WRITE] = FspFsvolWriteComplete; |     FspIopCompleteFunction[IRP_MJ_WRITE] = FspFsvolWriteComplete; | ||||||
|   | |||||||
| @@ -262,6 +262,7 @@ FSP_IOCMPL_DISPATCH FspFsvolQueryEaComplete; | |||||||
| FSP_IOCMPL_DISPATCH FspFsvolQueryInformationComplete; | FSP_IOCMPL_DISPATCH FspFsvolQueryInformationComplete; | ||||||
| FSP_IOCMPL_DISPATCH FspFsvolQuerySecurityComplete; | FSP_IOCMPL_DISPATCH FspFsvolQuerySecurityComplete; | ||||||
| FSP_IOCMPL_DISPATCH FspFsvolQueryVolumeInformationComplete; | FSP_IOCMPL_DISPATCH FspFsvolQueryVolumeInformationComplete; | ||||||
|  | FSP_IOPREP_DISPATCH FspFsvolReadPrepare; | ||||||
| FSP_IOCMPL_DISPATCH FspFsvolReadComplete; | FSP_IOCMPL_DISPATCH FspFsvolReadComplete; | ||||||
| FSP_IOCMPL_DISPATCH FspFsvolSetEaComplete; | FSP_IOCMPL_DISPATCH FspFsvolSetEaComplete; | ||||||
| FSP_IOCMPL_DISPATCH FspFsvolSetInformationComplete; | FSP_IOCMPL_DISPATCH FspFsvolSetInformationComplete; | ||||||
|   | |||||||
							
								
								
									
										168
									
								
								src/sys/read.c
									
									
									
									
									
								
							
							
						
						
									
										168
									
								
								src/sys/read.c
									
									
									
									
									
								
							| @@ -13,6 +13,7 @@ static NTSTATUS FspFsvolReadCached( | |||||||
|     BOOLEAN CanWait); |     BOOLEAN CanWait); | ||||||
| static NTSTATUS FspFsvolReadNonCached( | static NTSTATUS FspFsvolReadNonCached( | ||||||
|     PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); |     PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); | ||||||
|  | FSP_IOPREP_DISPATCH FspFsvolReadPrepare; | ||||||
| FSP_IOCMPL_DISPATCH FspFsvolReadComplete; | FSP_IOCMPL_DISPATCH FspFsvolReadComplete; | ||||||
| static FSP_IOP_REQUEST_FINI FspFsvolReadNonCachedRequestFini; | static FSP_IOP_REQUEST_FINI FspFsvolReadNonCachedRequestFini; | ||||||
| FSP_DRIVER_DISPATCH FspRead; | FSP_DRIVER_DISPATCH FspRead; | ||||||
| @@ -21,11 +22,21 @@ FSP_DRIVER_DISPATCH FspRead; | |||||||
| #pragma alloc_text(PAGE, FspFsvolRead) | #pragma alloc_text(PAGE, FspFsvolRead) | ||||||
| #pragma alloc_text(PAGE, FspFsvolReadCached) | #pragma alloc_text(PAGE, FspFsvolReadCached) | ||||||
| #pragma alloc_text(PAGE, FspFsvolReadNonCached) | #pragma alloc_text(PAGE, FspFsvolReadNonCached) | ||||||
|  | #pragma alloc_text(PAGE, FspFsvolReadPrepare) | ||||||
| #pragma alloc_text(PAGE, FspFsvolReadComplete) | #pragma alloc_text(PAGE, FspFsvolReadComplete) | ||||||
| #pragma alloc_text(PAGE, FspFsvolReadNonCachedRequestFini) | #pragma alloc_text(PAGE, FspFsvolReadNonCachedRequestFini) | ||||||
| #pragma alloc_text(PAGE, FspRead) | #pragma alloc_text(PAGE, FspRead) | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | enum | ||||||
|  | { | ||||||
|  |     /* ReadNonCached */ | ||||||
|  |     RequestIrp                          = 0, | ||||||
|  |     RequestSafeMdl                      = 1, | ||||||
|  |     RequestAddress                      = 2, | ||||||
|  |     RequestProcess                      = 3, | ||||||
|  | }; | ||||||
|  |  | ||||||
| static NTSTATUS FspFsvolRead( | static NTSTATUS FspFsvolRead( | ||||||
|     PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) |     PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) | ||||||
| { | { | ||||||
| @@ -164,7 +175,101 @@ static NTSTATUS FspFsvolReadNonCached( | |||||||
| { | { | ||||||
|     PAGED_CODE(); |     PAGED_CODE(); | ||||||
|  |  | ||||||
|     return STATUS_INVALID_DEVICE_REQUEST; |     NTSTATUS Result; | ||||||
|  |     PFILE_OBJECT FileObject = IrpSp->FileObject; | ||||||
|  |     FSP_FILE_NODE *FileNode = FileObject->FsContext; | ||||||
|  |     FSP_FILE_DESC *FileDesc = FileObject->FsContext2; | ||||||
|  |     LARGE_INTEGER ReadOffset = IrpSp->Parameters.Read.ByteOffset; | ||||||
|  |     ULONG ReadLength = IrpSp->Parameters.Read.Length; | ||||||
|  |     ULONG ReadKey = IrpSp->Parameters.Read.Key; | ||||||
|  |     FSP_FSCTL_TRANSACT_REQ *Request; | ||||||
|  |  | ||||||
|  |     ASSERT(FileNode == FileDesc->FileNode); | ||||||
|  |  | ||||||
|  |     /* no MDL requests on the non-cached path */ | ||||||
|  |     if (FlagOn(IrpSp->MinorFunction, IRP_MN_MDL)) | ||||||
|  |         return STATUS_INVALID_PARAMETER; | ||||||
|  |  | ||||||
|  |     /* probe and lock the user buffer */ | ||||||
|  |     if (0 == Irp->MdlAddress) | ||||||
|  |     { | ||||||
|  |         Result = FspLockUserBuffer(Irp->UserBuffer, ReadLength, | ||||||
|  |             Irp->RequestorMode, IoReadAccess, &Irp->MdlAddress); | ||||||
|  |         if (!NT_SUCCESS(Result)) | ||||||
|  |             return Result; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /* create request */ | ||||||
|  |     Result = FspIopCreateRequestEx(Irp, 0, 0, FspFsvolReadNonCachedRequestFini, &Request); | ||||||
|  |     if (!NT_SUCCESS(Result)) | ||||||
|  |         return Result; | ||||||
|  |  | ||||||
|  |     Request->Kind = FspFsctlTransactReadKind; | ||||||
|  |     Request->Req.Read.UserContext = FileNode->UserContext; | ||||||
|  |     Request->Req.Read.UserContext2 = FileDesc->UserContext2; | ||||||
|  |     Request->Req.Read.Offset = ReadOffset.QuadPart; | ||||||
|  |     Request->Req.Read.Length = ReadLength; | ||||||
|  |     Request->Req.Read.Key = ReadKey; | ||||||
|  |  | ||||||
|  |     return FSP_STATUS_IOQ_POST; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | NTSTATUS FspFsvolReadPrepare( | ||||||
|  |     PIRP Irp, FSP_FSCTL_TRANSACT_REQ *Request) | ||||||
|  | { | ||||||
|  |     PAGED_CODE(); | ||||||
|  |  | ||||||
|  |     NTSTATUS Result; | ||||||
|  |     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); | ||||||
|  |     PFILE_OBJECT FileObject = IrpSp->FileObject; | ||||||
|  |     FSP_FILE_NODE *FileNode = FileObject->FsContext; | ||||||
|  |     FSP_SAFE_MDL *SafeMdl = 0; | ||||||
|  |     PVOID Address; | ||||||
|  |     PEPROCESS Process; | ||||||
|  |     BOOLEAN Success; | ||||||
|  |  | ||||||
|  |     Success = DEBUGTEST(90, TRUE) && FspFileNodeTryAcquireShared(FileNode, Full); | ||||||
|  |     if (!Success) | ||||||
|  |     { | ||||||
|  |         FspIopRetryPrepareIrp(Irp, &Result); | ||||||
|  |         return Result; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /* create a "safe" MDL if necessary */ | ||||||
|  |     if (!FspSafeMdlCheck(Irp->MdlAddress)) | ||||||
|  |     { | ||||||
|  |         Result = FspSafeMdlCreate(Irp->MdlAddress, IoWriteAccess, &SafeMdl); | ||||||
|  |         if (!NT_SUCCESS(Result)) | ||||||
|  |         { | ||||||
|  |             FspFileNodeRelease(FileNode, Full); | ||||||
|  |             return STATUS_INSUFFICIENT_RESOURCES; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /* map the MDL into user-mode */ | ||||||
|  |     Result = FspMapLockedPagesInUserMode(0 != SafeMdl ? SafeMdl->Mdl : Irp->MdlAddress, &Address); | ||||||
|  |     if (!NT_SUCCESS(Result)) | ||||||
|  |     { | ||||||
|  |         if (0 != SafeMdl) | ||||||
|  |             FspSafeMdlDelete(SafeMdl); | ||||||
|  |  | ||||||
|  |         FspFileNodeRelease(FileNode, Full); | ||||||
|  |         return Result; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /* get a pointer to the current process so that we can unmap the address later */ | ||||||
|  |     Process = PsGetCurrentProcess(); | ||||||
|  |     ObReferenceObject(Process); | ||||||
|  |  | ||||||
|  |     Request->Req.Read.Address = (UINT64)(UINT_PTR)Address; | ||||||
|  |  | ||||||
|  |     FspFileNodeSetOwner(FileNode, Full, Request); | ||||||
|  |     FspIopRequestContext(Request, RequestIrp) = Irp; | ||||||
|  |     FspIopRequestContext(Request, RequestSafeMdl) = SafeMdl; | ||||||
|  |     FspIopRequestContext(Request, RequestAddress) = Address; | ||||||
|  |     FspIopRequestContext(Request, RequestProcess) = Process; | ||||||
|  |  | ||||||
|  |     return STATUS_SUCCESS; | ||||||
| } | } | ||||||
|  |  | ||||||
| NTSTATUS FspFsvolReadComplete( | NTSTATUS FspFsvolReadComplete( | ||||||
| @@ -172,6 +277,29 @@ NTSTATUS FspFsvolReadComplete( | |||||||
| { | { | ||||||
|     FSP_ENTER_IOC(PAGED_CODE()); |     FSP_ENTER_IOC(PAGED_CODE()); | ||||||
|  |  | ||||||
|  |     PFILE_OBJECT FileObject = IrpSp->FileObject; | ||||||
|  |     LARGE_INTEGER ReadOffset = IrpSp->Parameters.Read.ByteOffset; | ||||||
|  |     BOOLEAN PagingIo = BooleanFlagOn(Irp->Flags, IRP_PAGING_IO); | ||||||
|  |     BOOLEAN SynchronousIo = BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO); | ||||||
|  |  | ||||||
|  |     if (!NT_SUCCESS(Response->IoStatus.Status)) | ||||||
|  |     { | ||||||
|  |         Irp->IoStatus.Information = 0; | ||||||
|  |         Result = Response->IoStatus.Status; | ||||||
|  |         FSP_RETURN(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (!PagingIo) | ||||||
|  |     { | ||||||
|  |         /* update the current file offset if synchronous I/O (and not paging I/O) */ | ||||||
|  |         if (SynchronousIo) | ||||||
|  |             FileObject->CurrentByteOffset.QuadPart = | ||||||
|  |                 ReadOffset.QuadPart + Response->IoStatus.Information; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     Irp->IoStatus.Information = Response->IoStatus.Information; | ||||||
|  |     Result = STATUS_SUCCESS; | ||||||
|  |  | ||||||
|     FSP_LEAVE_IOC( |     FSP_LEAVE_IOC( | ||||||
|         "FileObject=%p, UserBuffer=%p, MdlAddress=%p, " |         "FileObject=%p, UserBuffer=%p, MdlAddress=%p, " | ||||||
|         "Key=%#lx, ByteOffset=%#lx:%#lx, Length=%ld", |         "Key=%#lx, ByteOffset=%#lx:%#lx, Length=%ld", | ||||||
| @@ -181,6 +309,44 @@ NTSTATUS FspFsvolReadComplete( | |||||||
|         IrpSp->Parameters.Read.Length); |         IrpSp->Parameters.Read.Length); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | static VOID FspFsvolReadNonCachedRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Context[4]) | ||||||
|  | { | ||||||
|  |     PAGED_CODE(); | ||||||
|  |  | ||||||
|  |     PIRP Irp = Context[RequestIrp]; | ||||||
|  |     FSP_SAFE_MDL *SafeMdl = Context[RequestSafeMdl]; | ||||||
|  |     PVOID Address = Context[RequestAddress]; | ||||||
|  |     PEPROCESS Process = Context[RequestProcess]; | ||||||
|  |  | ||||||
|  |     if (0 != Address) | ||||||
|  |     { | ||||||
|  |         KAPC_STATE ApcState; | ||||||
|  |         BOOLEAN Attach; | ||||||
|  |  | ||||||
|  |         ASSERT(0 != Process); | ||||||
|  |         Attach = Process != PsGetCurrentProcess(); | ||||||
|  |  | ||||||
|  |         if (Attach) | ||||||
|  |             KeStackAttachProcess(Process, &ApcState); | ||||||
|  |         MmUnmapLockedPages(Address, 0 != SafeMdl ? SafeMdl->Mdl : Irp->MdlAddress); | ||||||
|  |         if (Attach) | ||||||
|  |             KeUnstackDetachProcess(&ApcState); | ||||||
|  |  | ||||||
|  |         ObDereferenceObject(Process); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (0 != SafeMdl) | ||||||
|  |         FspSafeMdlDelete(SafeMdl); | ||||||
|  |  | ||||||
|  |     if (0 != Irp) | ||||||
|  |     { | ||||||
|  |         PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); | ||||||
|  |         FSP_FILE_NODE *FileNode = IrpSp->FileObject->FsContext; | ||||||
|  |  | ||||||
|  |         FspFileNodeReleaseOwner(FileNode, Full, Request); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| NTSTATUS FspRead( | NTSTATUS FspRead( | ||||||
|     PDEVICE_OBJECT DeviceObject, PIRP Irp) |     PDEVICE_OBJECT DeviceObject, PIRP Irp) | ||||||
| { | { | ||||||
|   | |||||||
| @@ -251,38 +251,10 @@ static NTSTATUS FspFsvolWriteNonCached( | |||||||
|     if (PagingIo && WriteToEndOfFile) |     if (PagingIo && WriteToEndOfFile) | ||||||
|         return STATUS_INVALID_PARAMETER; |         return STATUS_INVALID_PARAMETER; | ||||||
|  |  | ||||||
|     /* if non-cached I/O check the offset/length alignment */ |  | ||||||
|     /* |  | ||||||
|      * We are going to avoid doing this test, because we don't really need to restrict |  | ||||||
|      * ourselves for non-cached I/O, but also because we do not always know the correct |  | ||||||
|      * file size for our alignment test. The file size is needed, because the alignment |  | ||||||
|      * test is: |  | ||||||
|      * |  | ||||||
|      *     if WriteOffset is sector aligned |  | ||||||
|      *     and (WriteLength is sector aligned or WriteOffset + WriteLength >= FileSize) |  | ||||||
|      * |  | ||||||
|      * This means that the user-mode file system must be able to deal with variable size |  | ||||||
|      * I/O, but this was the case anyway because of the following part of the test: |  | ||||||
|      * |  | ||||||
|      *     WriteOffset + WriteLength >= FileSize |  | ||||||
|      * |  | ||||||
|      * In any case the user-mode file system can enforce this rule if it wants! |  | ||||||
|      */ |  | ||||||
| #if 0 |  | ||||||
|     if (!PagingIo) |  | ||||||
|     { |  | ||||||
|         FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = |  | ||||||
|             FspFsvolDeviceExtension(FsvolDeviceObject); |  | ||||||
|         if (0 != WriteOffset.QuadPart % FsvolDeviceExtension->VolumeParams.SectorSize || |  | ||||||
|             0 != WriteLength % FsvolDeviceExtension->VolumeParams.SectorSize) |  | ||||||
|             return STATUS_NOT_IMPLEMENTED; /* FastFat does this! */ |  | ||||||
|     } |  | ||||||
| #endif |  | ||||||
|  |  | ||||||
|     /* probe and lock the user buffer */ |     /* probe and lock the user buffer */ | ||||||
|     if (0 == Irp->MdlAddress) |     if (0 == Irp->MdlAddress) | ||||||
|     { |     { | ||||||
|         Result = FspLockUserBuffer(Irp->UserBuffer, IrpSp->Parameters.Write.Length, |         Result = FspLockUserBuffer(Irp->UserBuffer, WriteLength, | ||||||
|             Irp->RequestorMode, IoReadAccess, &Irp->MdlAddress); |             Irp->RequestorMode, IoReadAccess, &Irp->MdlAddress); | ||||||
|         if (!NT_SUCCESS(Result)) |         if (!NT_SUCCESS(Result)) | ||||||
|             return Result; |             return Result; | ||||||
| @@ -382,7 +354,7 @@ NTSTATUS FspFsvolWritePrepare( | |||||||
|  |  | ||||||
|     Request->Req.Write.Address = (UINT64)(UINT_PTR)Address; |     Request->Req.Write.Address = (UINT64)(UINT_PTR)Address; | ||||||
|  |  | ||||||
|     FspFileNodeSetOwner(FileNode, Pgio, Request); |     FspFileNodeSetOwner(FileNode, Full, Request); | ||||||
|     FspIopRequestContext(Request, RequestIrp) = Irp; |     FspIopRequestContext(Request, RequestIrp) = Irp; | ||||||
|     FspIopRequestContext(Request, RequestSafeMdl) = SafeMdl; |     FspIopRequestContext(Request, RequestSafeMdl) = SafeMdl; | ||||||
|     FspIopRequestContext(Request, RequestAddress) = Address; |     FspIopRequestContext(Request, RequestAddress) = Address; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user