mirror of
				https://github.com/winfsp/winfsp.git
				synced 2025-10-30 19:48:38 -05:00 
			
		
		
		
	sys: IRP_MJ_SET_INFORMATION: FileDispositionInformation
This commit is contained in:
		| @@ -37,17 +37,18 @@ static NTSTATUS FspFsvolSetAllocationInformation(PFILE_OBJECT FileObject, | ||||
| static NTSTATUS FspFsvolSetBasicInformation(PFILE_OBJECT FileObject, | ||||
|     PVOID Buffer, ULONG Length, | ||||
|     FSP_FSCTL_TRANSACT_REQ *Request, const FSP_FSCTL_TRANSACT_RSP *Response); | ||||
| static NTSTATUS FspFsvolSetDispositionInformation(PFILE_OBJECT FileObject, | ||||
|     PVOID Buffer, ULONG Length, | ||||
|     FSP_FSCTL_TRANSACT_REQ *Request, const FSP_FSCTL_TRANSACT_RSP *Response); | ||||
| static NTSTATUS FspFsvolSetEndOfFileInformation(PFILE_OBJECT FileObject, | ||||
|     PVOID Buffer, ULONG Length, BOOLEAN AdvanceOnly, | ||||
|     FSP_FSCTL_TRANSACT_REQ *Request, const FSP_FSCTL_TRANSACT_RSP *Response); | ||||
| static NTSTATUS FspFsvolSetPositionInformation(PFILE_OBJECT FileObject, | ||||
|     PVOID Buffer, ULONG Length); | ||||
| static NTSTATUS FspFsvolSetDispositionInformation( | ||||
|     PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); | ||||
| static NTSTATUS FspFsvolSetDispositionInformationSuccess( | ||||
|     PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response); | ||||
| static NTSTATUS FspFsvolSetRenameInformation( | ||||
|     PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); | ||||
| NTSTATUS FspFsvolSetRenameInformationSuccess( | ||||
| static NTSTATUS FspFsvolSetRenameInformationSuccess( | ||||
|     PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response); | ||||
| static NTSTATUS FspFsvolSetInformation( | ||||
|     PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); | ||||
| @@ -70,9 +71,10 @@ FSP_DRIVER_DISPATCH FspSetInformation; | ||||
| #pragma alloc_text(PAGE, FspFsvolQueryInformationRequestFini) | ||||
| #pragma alloc_text(PAGE, FspFsvolSetAllocationInformation) | ||||
| #pragma alloc_text(PAGE, FspFsvolSetBasicInformation) | ||||
| #pragma alloc_text(PAGE, FspFsvolSetDispositionInformation) | ||||
| #pragma alloc_text(PAGE, FspFsvolSetEndOfFileInformation) | ||||
| #pragma alloc_text(PAGE, FspFsvolSetPositionInformation) | ||||
| #pragma alloc_text(PAGE, FspFsvolSetDispositionInformation) | ||||
| #pragma alloc_text(PAGE, FspFsvolSetDispositionInformationSuccess) | ||||
| #pragma alloc_text(PAGE, FspFsvolSetRenameInformation) | ||||
| #pragma alloc_text(PAGE, FspFsvolSetRenameInformationSuccess) | ||||
| #pragma alloc_text(PAGE, FspFsvolSetInformation) | ||||
| @@ -640,51 +642,6 @@ static NTSTATUS FspFsvolSetBasicInformation(PFILE_OBJECT FileObject, | ||||
|     return STATUS_SUCCESS; | ||||
| } | ||||
|  | ||||
| static NTSTATUS FspFsvolSetDispositionInformation(PFILE_OBJECT FileObject, | ||||
|     PVOID Buffer, ULONG Length, | ||||
|     FSP_FSCTL_TRANSACT_REQ *Request, const FSP_FSCTL_TRANSACT_RSP *Response) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     if (0 == Request) | ||||
|     { | ||||
|         if (sizeof(FILE_DISPOSITION_INFORMATION) > Length) | ||||
|             return STATUS_INVALID_PARAMETER; | ||||
|  | ||||
|         FSP_FILE_NODE *FileNode = FileObject->FsContext; | ||||
|  | ||||
|         if (FileNode->IsRootDirectory) | ||||
|             /* cannot delete root directory */ | ||||
|             return STATUS_CANNOT_DELETE; | ||||
|     } | ||||
|     else if (0 == Response) | ||||
|     { | ||||
|         PFILE_DISPOSITION_INFORMATION Info = (PFILE_DISPOSITION_INFORMATION)Buffer; | ||||
|         BOOLEAN Success; | ||||
|  | ||||
|         if (Info->DeleteFile) | ||||
|         { | ||||
|             /* make sure no process is mapping the file as an image */ | ||||
|             Success = MmFlushImageSection(FileObject->SectionObjectPointer, | ||||
|                 MmFlushForDelete); | ||||
|             if (!Success) | ||||
|                 return STATUS_CANNOT_DELETE; | ||||
|         } | ||||
|  | ||||
|         Request->Req.SetInformation.Info.Disposition.Delete = Info->DeleteFile; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         PFILE_DISPOSITION_INFORMATION Info = (PFILE_DISPOSITION_INFORMATION)Buffer; | ||||
|         FSP_FILE_NODE *FileNode = FileObject->FsContext; | ||||
|  | ||||
|         FileNode->DeletePending = Info->DeleteFile; | ||||
|         FileObject->DeletePending = Info->DeleteFile; | ||||
|     } | ||||
|  | ||||
|     return STATUS_SUCCESS; | ||||
| } | ||||
|  | ||||
| static NTSTATUS FspFsvolSetEndOfFileInformation(PFILE_OBJECT FileObject, | ||||
|     PVOID Buffer, ULONG Length, BOOLEAN AdvanceOnly, | ||||
|     FSP_FSCTL_TRANSACT_REQ *Request, const FSP_FSCTL_TRANSACT_RSP *Response) | ||||
| @@ -739,6 +696,92 @@ static NTSTATUS FspFsvolSetPositionInformation(PFILE_OBJECT FileObject, | ||||
|     return STATUS_SUCCESS; | ||||
| } | ||||
|  | ||||
| static NTSTATUS FspFsvolSetDispositionInformation( | ||||
|     PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     NTSTATUS Result; | ||||
|     PFILE_OBJECT FileObject = IrpSp->FileObject; | ||||
|     PFILE_DISPOSITION_INFORMATION Info = (PFILE_DISPOSITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer; | ||||
|     ULONG Length = IrpSp->Parameters.SetFile.Length; | ||||
|     FSP_FILE_NODE *FileNode = FileObject->FsContext; | ||||
|     FSP_FILE_DESC *FileDesc = FileObject->FsContext2; | ||||
|     FSP_FSCTL_TRANSACT_REQ *Request; | ||||
|     BOOLEAN Success; | ||||
|  | ||||
|     ASSERT(FileNode == FileDesc->FileNode); | ||||
|  | ||||
|     if (sizeof(FILE_DISPOSITION_INFORMATION) > Length) | ||||
|         return STATUS_INVALID_PARAMETER; | ||||
|     if (FileNode->IsRootDirectory) | ||||
|         /* cannot delete root directory */ | ||||
|         return STATUS_CANNOT_DELETE; | ||||
|  | ||||
|     FspFsvolDeviceFileRenameAcquireShared(FsvolDeviceObject); | ||||
|     FspFileNodeAcquireExclusive(FileNode, Full); | ||||
|  | ||||
|     if (Info->DeleteFile) | ||||
|     { | ||||
|         /* make sure no process is mapping the file as an image */ | ||||
|         Success = MmFlushImageSection(FileObject->SectionObjectPointer, MmFlushForDelete); | ||||
|         if (!Success) | ||||
|         { | ||||
|             Result = STATUS_CANNOT_DELETE; | ||||
|             goto unlock_exit; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     Result = FspIopCreateRequestEx(Irp, &FileNode->FileName, 0, | ||||
|         FspFsvolSetInformationRequestFini, &Request); | ||||
|     if (!NT_SUCCESS(Result)) | ||||
|         goto unlock_exit; | ||||
|  | ||||
|     Request->Kind = FspFsctlTransactSetInformationKind; | ||||
|     Request->Req.SetInformation.UserContext = FileNode->UserContext; | ||||
|     Request->Req.SetInformation.UserContext2 = FileDesc->UserContext2; | ||||
|     Request->Req.SetInformation.FileInformationClass = FileDispositionInformation; | ||||
|     Request->Req.SetInformation.Info.Disposition.Delete = Info->DeleteFile; | ||||
|  | ||||
|     FspFsvolDeviceFileRenameSetOwner(FsvolDeviceObject, Request); | ||||
|     FspFileNodeSetOwner(FileNode, Full, Request); | ||||
|     FspIopRequestContext(Request, RequestFileNode) = FileNode; | ||||
|     FspIopRequestContext(Request, RequestDeviceObject) = FsvolDeviceObject; | ||||
|  | ||||
|     return FSP_STATUS_IOQ_POST; | ||||
|  | ||||
| unlock_exit: | ||||
|     FspFileNodeRelease(FileNode, Full); | ||||
|     FspFsvolDeviceFileRenameRelease(FsvolDeviceObject); | ||||
|  | ||||
|     return Result; | ||||
| } | ||||
|  | ||||
| static NTSTATUS FspFsvolSetDispositionInformationSuccess( | ||||
|     PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); | ||||
|     PDEVICE_OBJECT FsvolDeviceObject = IrpSp->DeviceObject; | ||||
|     PFILE_OBJECT FileObject = IrpSp->FileObject; | ||||
|     PFILE_DISPOSITION_INFORMATION Info = (PFILE_DISPOSITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer; | ||||
|     FSP_FILE_NODE *FileNode = FileObject->FsContext; | ||||
|     FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp); | ||||
|  | ||||
|     FileNode->DeletePending = Info->DeleteFile; | ||||
|     FileObject->DeletePending = Info->DeleteFile; | ||||
|  | ||||
|     FspIopRequestContext(Request, RequestFileNode) = 0; | ||||
|     FspIopRequestContext(Request, RequestDeviceObject) = 0; | ||||
|     FspFileNodeReleaseOwner(FileNode, Full, Request); | ||||
|     FspFsvolDeviceFileRenameRelease(FsvolDeviceObject); | ||||
|  | ||||
|     Irp->IoStatus.Information = 0; | ||||
|  | ||||
|     return STATUS_SUCCESS; | ||||
| } | ||||
|  | ||||
| static NTSTATUS FspFsvolSetRenameInformation( | ||||
|     PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) | ||||
| { | ||||
| @@ -829,14 +872,14 @@ static NTSTATUS FspFsvolSetRenameInformation( | ||||
|     FspIopRequestContext(Request, RequestDeviceObject) = FsvolDeviceObject; | ||||
|  | ||||
|     /* | ||||
|      * Special rules for renaming open files: | ||||
|      * -   A file cannot be renamed if it has any open handles, | ||||
|      *     unless it is only open because of a batch opportunistic lock (oplock) | ||||
|      *     and the batch oplock can be broken immediately. | ||||
|      * -   A file cannot be renamed if a file with the same name exists | ||||
|      *     and has open handles (except in the batch-oplock case described earlier). | ||||
|      * -   A directory cannot be renamed if it or any of its subdirectories contains a file | ||||
|      *     that has open handles (except in the batch-oplock case described earlier). | ||||
|      * Special rules for renaming open files: | ||||
|      * -   A file cannot be renamed if it has any open handles, | ||||
|      *     unless it is only open because of a batch opportunistic lock (oplock) | ||||
|      *     and the batch oplock can be broken immediately. | ||||
|      * -   A file cannot be renamed if a file with the same name exists | ||||
|      *     and has open handles (except in the batch-oplock case described earlier). | ||||
|      * -   A directory cannot be renamed if it or any of its subdirectories contains a file | ||||
|      *     that has open handles (except in the batch-oplock case described earlier). | ||||
|      */ | ||||
|  | ||||
|     NewFileName.Length = NewFileName.MaximumLength = | ||||
| @@ -873,7 +916,7 @@ unlock_exit: | ||||
|     return Result; | ||||
| } | ||||
|  | ||||
| NTSTATUS FspFsvolSetRenameInformationSuccess( | ||||
| static NTSTATUS FspFsvolSetRenameInformationSuccess( | ||||
|     PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
| @@ -913,7 +956,9 @@ static NTSTATUS FspFsvolSetInformation( | ||||
|  | ||||
|     FILE_INFORMATION_CLASS FileInformationClass = IrpSp->Parameters.SetFile.FileInformationClass; | ||||
|  | ||||
|     /* special case FileRenameInformation */ | ||||
|     /* special case FileDispositionInformation/FileRenameInformation */ | ||||
|     if (FileDispositionInformation == FileInformationClass) | ||||
|         return FspFsvolSetDispositionInformation(FsvolDeviceObject, Irp, IrpSp); | ||||
|     if (FileRenameInformation == FileInformationClass) | ||||
|         return FspFsvolSetRenameInformation(FsvolDeviceObject, Irp, IrpSp); | ||||
|  | ||||
| @@ -930,9 +975,6 @@ static NTSTATUS FspFsvolSetInformation( | ||||
|     case FileBasicInformation: | ||||
|         Result = FspFsvolSetBasicInformation(FileObject, Buffer, Length, 0, 0); | ||||
|         break; | ||||
|     case FileDispositionInformation: | ||||
|         Result = FspFsvolSetDispositionInformation(FileObject, Buffer, Length, 0, 0); | ||||
|         break; | ||||
|     case FileEndOfFileInformation: | ||||
|         Result = FspFsvolSetEndOfFileInformation(FileObject, Buffer, Length, | ||||
|             IrpSp->Parameters.SetFile.AdvanceOnly, 0, 0); | ||||
| @@ -984,9 +1026,6 @@ static NTSTATUS FspFsvolSetInformation( | ||||
|     case FileBasicInformation: | ||||
|         Result = FspFsvolSetBasicInformation(FileObject, Buffer, Length, Request, 0); | ||||
|         break; | ||||
|     case FileDispositionInformation: | ||||
|         Result = FspFsvolSetDispositionInformation(FileObject, Buffer, Length, Request, 0); | ||||
|         break; | ||||
|     case FileEndOfFileInformation: | ||||
|         Result = FspFsvolSetEndOfFileInformation(FileObject, Buffer, Length, | ||||
|             IrpSp->Parameters.SetFile.AdvanceOnly, Request, 0); | ||||
| @@ -1017,12 +1056,11 @@ NTSTATUS FspFsvolSetInformationComplete( | ||||
|  | ||||
|     FILE_INFORMATION_CLASS FileInformationClass = IrpSp->Parameters.SetFile.FileInformationClass; | ||||
|  | ||||
|     /* special case FileRenameInformation */ | ||||
|     /* special case FileDispositionInformation/FileRenameInformation */ | ||||
|     if (FileDispositionInformation == FileInformationClass) | ||||
|         FSP_RETURN(Result = FspFsvolSetDispositionInformationSuccess(Irp, Response)); | ||||
|     if (FileRenameInformation == FileInformationClass) | ||||
|     { | ||||
|         Result = FspFsvolSetRenameInformationSuccess(Irp, Response); | ||||
|         FSP_RETURN(); | ||||
|     } | ||||
|         FSP_RETURN(Result = FspFsvolSetRenameInformationSuccess(Irp, Response)); | ||||
|  | ||||
|     PFILE_OBJECT FileObject = IrpSp->FileObject; | ||||
|     FSP_FILE_NODE *FileNode = FileObject->FsContext; | ||||
| @@ -1038,9 +1076,6 @@ NTSTATUS FspFsvolSetInformationComplete( | ||||
|     case FileBasicInformation: | ||||
|         Result = FspFsvolSetBasicInformation(FileObject, Buffer, Length, Request, Response); | ||||
|         break; | ||||
|     case FileDispositionInformation: | ||||
|         Result = FspFsvolSetDispositionInformation(FileObject, Buffer, Length, Request, Response); | ||||
|         break; | ||||
|     case FileEndOfFileInformation: | ||||
|         Result = FspFsvolSetEndOfFileInformation(FileObject, Buffer, Length, | ||||
|             IrpSp->Parameters.SetFile.AdvanceOnly, Request, Response); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user