/** * @file sys/close.c * * @copyright 2015-2019 Bill Zissimopoulos */ /* * This file is part of WinFsp. * * You can redistribute it and/or modify it under the terms of the GNU * General Public License version 3 as published by the Free Software * Foundation. * * Licensees holding a valid commercial license may use this software * in accordance with the commercial license agreement provided in * conjunction with the software. The terms and conditions of any such * commercial license agreement shall govern, supersede, and render * ineffective any application of the GPLv3 license to this software, * notwithstanding of any reference thereto in the software or * associated repository. */ #include static NTSTATUS FspFsctlClose( PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); static NTSTATUS FspFsvrtClose( PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); static NTSTATUS FspFsvolClose( PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); FSP_IOCMPL_DISPATCH FspFsvolCloseComplete; FSP_DRIVER_DISPATCH FspClose; #ifdef ALLOC_PRAGMA #pragma alloc_text(PAGE, FspFsctlClose) #pragma alloc_text(PAGE, FspFsvrtClose) #pragma alloc_text(PAGE, FspFsvolClose) #pragma alloc_text(PAGE, FspFsvolCloseComplete) #pragma alloc_text(PAGE, FspClose) #endif static NTSTATUS FspFsctlClose( PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) { PAGED_CODE(); Irp->IoStatus.Information = 0; return STATUS_SUCCESS; } static NTSTATUS FspFsvrtClose( PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) { PAGED_CODE(); Irp->IoStatus.Information = 0; return STATUS_SUCCESS; } static NTSTATUS FspFsvolClose( PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) { PAGED_CODE(); /* is this a valid FileObject? */ if (!FspFileNodeIsValid(IrpSp->FileObject->FsContext)) return STATUS_SUCCESS; PFILE_OBJECT FileObject = IrpSp->FileObject; FSP_FILE_NODE *FileNode = FileObject->FsContext; FSP_FILE_DESC *FileDesc = FileObject->FsContext2; FSP_FSCTL_TRANSACT_REQ *Request; ASSERT(FileNode == FileDesc->FileNode); /* create the user-mode file system request; MustSucceed because IRP_MJ_CLOSE cannot fail */ FspIopCreateRequestMustSucceed(0, 0, 0, &Request); Request->Kind = FspFsctlTransactCloseKind; Request->Req.Close.UserContext = FileNode->UserContext; Request->Req.Close.UserContext2 = FileDesc->UserContext2; FspFileNodeClose(FileNode, 0, FALSE); /* delete the FileDesc and deref the FileNode; order is important (FileDesc has FileNode ref) */ FspFileDescDelete(FileDesc); /* this will also close the MainFileObject if any */ FspFileNodeDereference(FileNode); /* if we are closing files in the context of a rename make it synchronous */ if (FspFsvolDeviceFileRenameIsAcquiredExclusive(FsvolDeviceObject)) { /* acquire ownership of the Request */ Request->Hint = (UINT_PTR)Irp; FspIrpSetRequest(Irp, Request); return FSP_STATUS_IOQ_POST_BEST_EFFORT; } /* * Post as a BestEffort WORK request. This allows us to complete our own IRP * and return immediately. */ FspIopPostWorkRequestBestEffort(FsvolDeviceObject, Request); /* * Note that it is still possible for this request to not be delivered, * if the volume device Ioq is stopped. But such failures are benign * from our perspective, because they mean that the file system is going * away and should correctly tear things down. */ Irp->IoStatus.Information = 0; return STATUS_SUCCESS; } NTSTATUS FspFsvolCloseComplete( PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response) { FSP_ENTER_IOC(PAGED_CODE()); FSP_LEAVE_IOC("FileObject=%p", IrpSp->FileObject); } NTSTATUS FspClose( PDEVICE_OBJECT DeviceObject, PIRP Irp) { FSP_ENTER_MJ(PAGED_CODE()); switch (FspDeviceExtension(DeviceObject)->Kind) { case FspFsvolDeviceExtensionKind: FSP_RETURN(Result = FspFsvolClose(DeviceObject, Irp, IrpSp)); case FspFsvrtDeviceExtensionKind: FSP_RETURN(Result = FspFsvrtClose(DeviceObject, Irp, IrpSp)); case FspFsctlDeviceExtensionKind: FSP_RETURN(Result = FspFsctlClose(DeviceObject, Irp, IrpSp)); default: FSP_RETURN(Result = STATUS_INVALID_DEVICE_REQUEST); } FSP_LEAVE_MJ("FileObject=%p", IrpSp->FileObject); }