mirror of
				https://github.com/winfsp/winfsp.git
				synced 2025-10-30 19:48:38 -05:00 
			
		
		
		
	sys: FileRenameResource implementation
This commit is contained in:
		| @@ -12,6 +12,8 @@ static NTSTATUS FspFsvrtCreate( | ||||
|     PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); | ||||
| static NTSTATUS FspFsvolCreate( | ||||
|     PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); | ||||
| static NTSTATUS FspFsvolCreateNoLock( | ||||
|     PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); | ||||
| FSP_IOPREP_DISPATCH FspFsvolCreatePrepare; | ||||
| FSP_IOCMPL_DISPATCH FspFsvolCreateComplete; | ||||
| static NTSTATUS FspFsvolCreateTryOpen(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response, | ||||
| @@ -27,6 +29,7 @@ FSP_DRIVER_DISPATCH FspCreate; | ||||
| #pragma alloc_text(PAGE, FspFsctlCreate) | ||||
| #pragma alloc_text(PAGE, FspFsvrtCreate) | ||||
| #pragma alloc_text(PAGE, FspFsvolCreate) | ||||
| #pragma alloc_text(PAGE, FspFsvolCreateNoLock) | ||||
| #pragma alloc_text(PAGE, FspFsvolCreatePrepare) | ||||
| #pragma alloc_text(PAGE, FspFsvolCreateComplete) | ||||
| #pragma alloc_text(PAGE, FspFsvolCreateTryOpen) | ||||
| @@ -43,14 +46,16 @@ FSP_DRIVER_DISPATCH FspCreate; | ||||
| enum | ||||
| { | ||||
|     /* Create */ | ||||
|     RequestFileDesc                     = 0, | ||||
|     RequestAccessToken                  = 1, | ||||
|     RequestProcess                      = 2, | ||||
|     RequestDeviceObject                 = 0, | ||||
|     RequestFileDesc                     = 1, | ||||
|     RequestAccessToken                  = 2, | ||||
|     RequestProcess                      = 3, | ||||
|  | ||||
|     /* TryOpen/Overwrite */ | ||||
|     //RequestFileDesc                   = 0, | ||||
|     RequestFileObject                   = 1, | ||||
|     RequestState                        = 2, | ||||
|     //RequestDeviceObject               = 0, | ||||
|     //RequestFileDesc                   = 1, | ||||
|     RequestFileObject                   = 2, | ||||
|     RequestState                        = 3, | ||||
|  | ||||
|     /* RequestState */ | ||||
|     RequestPending                      = 0, | ||||
| @@ -92,6 +97,27 @@ static NTSTATUS FspFsvolCreate( | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     NTSTATUS Result = STATUS_SUCCESS; | ||||
|  | ||||
|     FspFsvolDeviceFileRenameAcquireShared(FsvolDeviceObject); | ||||
|     try | ||||
|     { | ||||
|         Result = FspFsvolCreateNoLock(FsvolDeviceObject, Irp, IrpSp); | ||||
|     } | ||||
|     finally | ||||
|     { | ||||
|         if (FSP_STATUS_IOQ_POST != Result) | ||||
|             FspFsvolDeviceFileRenameRelease(FsvolDeviceObject); | ||||
|     } | ||||
|  | ||||
|     return Result; | ||||
| } | ||||
|  | ||||
| static NTSTATUS FspFsvolCreateNoLock( | ||||
|     PDEVICE_OBJECT FsvolDeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     NTSTATUS Result; | ||||
|     FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject); | ||||
|     PFILE_OBJECT FileObject = IrpSp->FileObject; | ||||
| @@ -180,6 +206,11 @@ static NTSTATUS FspFsvolCreate( | ||||
|     { | ||||
|         RelatedFileNode = RelatedFileObject->FsContext; | ||||
|  | ||||
|         /* | ||||
|          * Accesses of RelatedFileNode->FileName are protected | ||||
|          * by FSP_FSVOL_DEVICE_EXTENSION::FileRenameResource. | ||||
|          */ | ||||
|  | ||||
|         /* is this a valid RelatedFileObject? */ | ||||
|         if (!FspFileNodeIsValid(RelatedFileNode)) | ||||
|             return STATUS_OBJECT_PATH_NOT_FOUND; | ||||
| @@ -202,12 +233,6 @@ static NTSTATUS FspFsvolCreate( | ||||
|             sizeof(WCHAR) == RelatedFileNode->FileName.Length && 0 == FileName.Length) | ||||
|             return STATUS_CANNOT_DELETE; | ||||
|  | ||||
|         /* | ||||
|          * There is no need to lock our accesses of RelatedFileObject->FileNode->FileName, | ||||
|          * because RelatedFileObject->FileNode->Filename is read-only (after creation) and | ||||
|          * because RelatedFileObject->FileNode is guaranteed to exist while RelatedFileObject | ||||
|          * exists. | ||||
|          */ | ||||
|         BOOLEAN AppendBackslash = | ||||
|             sizeof(WCHAR) * 2/* not empty or root */ <= RelatedFileNode->FileName.Length && | ||||
|             sizeof(WCHAR) <= FileName.Length && L':' != FileName.Buffer[0]; | ||||
| @@ -320,6 +345,8 @@ static NTSTATUS FspFsvolCreate( | ||||
|      * delete the Request and any associated resources. | ||||
|      */ | ||||
|     FileDesc->FileNode = FileNode; | ||||
|     FspFsvolDeviceFileRenameSetOwner(FsvolDeviceObject, Request); | ||||
|     FspIopRequestContext(Request, RequestDeviceObject) = FsvolDeviceObject; | ||||
|     FspIopRequestContext(Request, RequestFileDesc) = FileDesc; | ||||
|  | ||||
|     /* populate the Create request */ | ||||
| @@ -589,25 +616,20 @@ NTSTATUS FspFsvolCreateComplete( | ||||
|             if (FileNode->IsDirectory) | ||||
|                 SetFlag(FileAttributes, FILE_ATTRIBUTE_DIRECTORY); | ||||
|  | ||||
|             /* delete the old request */ | ||||
|             FspIrpRequest(Irp) = 0; | ||||
|             /* disassociate the FileDesc momentarily from the Request */ | ||||
|             FspIopRequestContext(Request, RequestDeviceObject) = 0; | ||||
|             FspIopRequestContext(Request, RequestFileDesc) = 0; | ||||
|                 /* disassociate the FileDesc from the old Request as we want to keep it around! */ | ||||
|             FspIopDeleteRequest(Request); | ||||
|  | ||||
|             /* create the Overwrite request; MustSucceed because we must either overwrite or close */ | ||||
|             FspIopCreateRequestFunnel(Irp, | ||||
|                 FsvolDeviceExtension->VolumeParams.FileNameRequired ? &FileNode->FileName : 0, 0, | ||||
|                 FspFsvolCreateOverwriteRequestFini, TRUE, | ||||
|                 &Request); | ||||
|  | ||||
|             /* associate the FileDesc and FileObject with the Overwrite request */ | ||||
|             /* reset the request */ | ||||
|             Request->Kind = FspFsctlTransactOverwriteKind; | ||||
|             RtlZeroMemory(&Request->Req.Create, sizeof Request->Req.Create); | ||||
|             FspIopResetRequest(Request, FspFsvolCreateOverwriteRequestFini); | ||||
|             FspIopRequestContext(Request, RequestDeviceObject) = FsvolDeviceObject; | ||||
|             FspIopRequestContext(Request, RequestFileDesc) = FileDesc; | ||||
|             FspIopRequestContext(Request, RequestFileObject) = FileObject; | ||||
|             FspIopRequestContext(Request, RequestState) = (PVOID)RequestPending; | ||||
|  | ||||
|             /* populate the Overwrite request */ | ||||
|             Request->Kind = FspFsctlTransactOverwriteKind; | ||||
|             Request->Req.Overwrite.UserContext = FileNode->UserContext; | ||||
|             Request->Req.Overwrite.UserContext2 = FileDesc->UserContext2; | ||||
|             Request->Req.Overwrite.FileAttributes = FileAttributes; | ||||
| @@ -681,13 +703,17 @@ static NTSTATUS FspFsvolCreateTryOpen(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Re | ||||
|  | ||||
|         if (FspFsctlTransactCreateKind == Request->Kind) | ||||
|         { | ||||
|             PDEVICE_OBJECT FsvolDeviceObject = FspIopRequestContext(Request, RequestDeviceObject); | ||||
|  | ||||
|             /* disassociate the FileDesc momentarily from the Request */ | ||||
|             Request = FspIrpRequest(Irp); | ||||
|             FspIopRequestContext(Request, RequestDeviceObject) = 0; | ||||
|             FspIopRequestContext(Request, RequestFileDesc) = 0; | ||||
|  | ||||
|             /* reset the Request and reassociate the FileDesc and FileObject with it */ | ||||
|             Request->Kind = FspFsctlTransactReservedKind; | ||||
|             FspIopResetRequest(Request, FspFsvolCreateTryOpenRequestFini); | ||||
|             FspIopRequestContext(Request, RequestDeviceObject) = FsvolDeviceObject; | ||||
|             FspIopRequestContext(Request, RequestFileDesc) = FileDesc; | ||||
|             FspIopRequestContext(Request, RequestFileObject) = FileObject; | ||||
|             FspIopRequestContext(Request, RequestState) = (PVOID)(UINT_PTR)FlushImage; | ||||
| @@ -761,10 +787,11 @@ static VOID FspFsvolCreatePostClose(FSP_FILE_DESC *FileDesc) | ||||
|      */ | ||||
| } | ||||
|  | ||||
| static VOID FspFsvolCreateRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Context[3]) | ||||
| static VOID FspFsvolCreateRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Context[4]) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     PDEVICE_OBJECT FsvolDeviceObject = Context[RequestDeviceObject]; | ||||
|     FSP_FILE_DESC *FileDesc = Context[RequestFileDesc]; | ||||
|     HANDLE AccessToken = Context[RequestAccessToken]; | ||||
|     PEPROCESS Process = Context[RequestProcess]; | ||||
| @@ -798,12 +825,16 @@ static VOID FspFsvolCreateRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Con | ||||
|  | ||||
|         ObDereferenceObject(Process); | ||||
|     } | ||||
|  | ||||
|     if (0 != FsvolDeviceObject) | ||||
|         FspFsvolDeviceFileRenameReleaseOwner(FsvolDeviceObject, Request); | ||||
| } | ||||
|  | ||||
| static VOID FspFsvolCreateTryOpenRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Context[3]) | ||||
| static VOID FspFsvolCreateTryOpenRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Context[4]) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     PDEVICE_OBJECT FsvolDeviceObject = Context[RequestDeviceObject]; | ||||
|     FSP_FILE_DESC *FileDesc = Context[RequestFileDesc]; | ||||
|     PFILE_OBJECT FileObject = Context[RequestFileObject]; | ||||
|  | ||||
| @@ -816,12 +847,16 @@ static VOID FspFsvolCreateTryOpenRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PV | ||||
|         FspFileNodeDereference(FileDesc->FileNode); | ||||
|         FspFileDescDelete(FileDesc); | ||||
|     } | ||||
|  | ||||
|     if (0 != FsvolDeviceObject) | ||||
|         FspFsvolDeviceFileRenameReleaseOwner(FsvolDeviceObject, Request); | ||||
| } | ||||
|  | ||||
| static VOID FspFsvolCreateOverwriteRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Context[3]) | ||||
| static VOID FspFsvolCreateOverwriteRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Context[4]) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     PDEVICE_OBJECT FsvolDeviceObject = Context[RequestDeviceObject]; | ||||
|     FSP_FILE_DESC *FileDesc = Context[RequestFileDesc]; | ||||
|     PFILE_OBJECT FileObject = Context[RequestFileObject]; | ||||
|     ULONG State = (ULONG)(UINT_PTR)Context[RequestState]; | ||||
| @@ -839,6 +874,9 @@ static VOID FspFsvolCreateOverwriteRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, | ||||
|         FspFileNodeDereference(FileDesc->FileNode); | ||||
|         FspFileDescDelete(FileDesc); | ||||
|     } | ||||
|  | ||||
|     if (0 != FsvolDeviceObject) | ||||
|         FspFsvolDeviceFileRenameReleaseOwner(FsvolDeviceObject, Request); | ||||
| } | ||||
|  | ||||
| NTSTATUS FspCreate( | ||||
|   | ||||
| @@ -25,6 +25,11 @@ static NTSTATUS FspFsvolDeviceInit(PDEVICE_OBJECT DeviceObject); | ||||
| static VOID FspFsvolDeviceFini(PDEVICE_OBJECT DeviceObject); | ||||
| static IO_TIMER_ROUTINE FspFsvolDeviceTimerRoutine; | ||||
| static WORKER_THREAD_ROUTINE FspFsvolDeviceExpirationRoutine; | ||||
| VOID FspFsvolDeviceFileRenameAcquireShared(PDEVICE_OBJECT DeviceObject); | ||||
| VOID FspFsvolDeviceFileRenameAcquireExclusive(PDEVICE_OBJECT DeviceObject); | ||||
| VOID FspFsvolDeviceFileRenameSetOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner); | ||||
| VOID FspFsvolDeviceFileRenameRelease(PDEVICE_OBJECT DeviceObject); | ||||
| VOID FspFsvolDeviceFileRenameReleaseOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner); | ||||
| VOID FspFsvolDeviceLockContextTable(PDEVICE_OBJECT DeviceObject); | ||||
| VOID FspFsvolDeviceUnlockContextTable(PDEVICE_OBJECT DeviceObject); | ||||
| PVOID FspFsvolDeviceLookupContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier); | ||||
| @@ -60,6 +65,11 @@ VOID FspDeviceDeleteAll(VOID); | ||||
| #pragma alloc_text(PAGE, FspDeviceDelete) | ||||
| #pragma alloc_text(PAGE, FspFsvolDeviceInit) | ||||
| #pragma alloc_text(PAGE, FspFsvolDeviceFini) | ||||
| #pragma alloc_text(PAGE, FspFsvolDeviceFileRenameAcquireShared) | ||||
| #pragma alloc_text(PAGE, FspFsvolDeviceFileRenameAcquireExclusive) | ||||
| #pragma alloc_text(PAGE, FspFsvolDeviceFileRenameSetOwner) | ||||
| #pragma alloc_text(PAGE, FspFsvolDeviceFileRenameRelease) | ||||
| #pragma alloc_text(PAGE, FspFsvolDeviceFileRenameReleaseOwner) | ||||
| #pragma alloc_text(PAGE, FspFsvolDeviceLockContextTable) | ||||
| #pragma alloc_text(PAGE, FspFsvolDeviceUnlockContextTable) | ||||
| #pragma alloc_text(PAGE, FspFsvolDeviceLookupContext) | ||||
| @@ -437,6 +447,58 @@ static VOID FspFsvolDeviceExpirationRoutine(PVOID Context) | ||||
|     FspDeviceDereference(DeviceObject); | ||||
| } | ||||
|  | ||||
| VOID FspFsvolDeviceFileRenameAcquireShared(PDEVICE_OBJECT DeviceObject) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject); | ||||
|  | ||||
|     ExAcquireResourceSharedLite(&FsvolDeviceExtension->FileRenameResource, TRUE); | ||||
| } | ||||
|  | ||||
| VOID FspFsvolDeviceFileRenameAcquireExclusive(PDEVICE_OBJECT DeviceObject) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject); | ||||
|  | ||||
|     ExAcquireResourceExclusiveLite(&FsvolDeviceExtension->FileRenameResource, TRUE); | ||||
| } | ||||
|  | ||||
| VOID FspFsvolDeviceFileRenameSetOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject); | ||||
|  | ||||
|     Owner = (PVOID)((UINT_PTR)Owner | 3); | ||||
|  | ||||
|     ExSetResourceOwnerPointer(&FsvolDeviceExtension->FileRenameResource, Owner); | ||||
| } | ||||
|  | ||||
| VOID FspFsvolDeviceFileRenameRelease(PDEVICE_OBJECT DeviceObject) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject); | ||||
|  | ||||
|     ExReleaseResourceLite(&FsvolDeviceExtension->FileRenameResource); | ||||
| } | ||||
|  | ||||
| VOID FspFsvolDeviceFileRenameReleaseOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject); | ||||
|  | ||||
|     Owner = (PVOID)((UINT_PTR)Owner | 3); | ||||
|  | ||||
|     if (ExIsResourceAcquiredLite(&FsvolDeviceExtension->FileRenameResource)) | ||||
|         ExReleaseResourceLite(&FsvolDeviceExtension->FileRenameResource); | ||||
|     else | ||||
|         ExReleaseResourceForThreadLite(&FsvolDeviceExtension->FileRenameResource, (ERESOURCE_THREAD)Owner); | ||||
| } | ||||
|  | ||||
| VOID FspFsvolDeviceLockContextTable(PDEVICE_OBJECT DeviceObject) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|   | ||||
| @@ -419,7 +419,7 @@ PIRP FspIoqNextCompleteIrp(FSP_IOQ *Ioq, PIRP BoundaryIrp); | ||||
| #define FspIopPostWorkRequestBestEffort(D, R)\ | ||||
|     FspIopPostWorkRequestFunnel(D, R, TRUE) | ||||
| #define FspIopCompleteIrp(I, R)         FspIopCompleteIrpEx(I, R, TRUE) | ||||
| typedef VOID FSP_IOP_REQUEST_FINI(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Context[3]); | ||||
| typedef VOID FSP_IOP_REQUEST_FINI(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Context[4]); | ||||
| NTSTATUS FspIopCreateRequestFunnel( | ||||
|     PIRP Irp, PUNICODE_STRING FileName, ULONG ExtraSize, FSP_IOP_REQUEST_FINI *RequestFini, | ||||
|     BOOLEAN MustSucceed, | ||||
| @@ -522,6 +522,11 @@ NTSTATUS FspDeviceInitialize(PDEVICE_OBJECT DeviceObject); | ||||
| VOID FspDeviceDelete(PDEVICE_OBJECT DeviceObject); | ||||
| BOOLEAN FspDeviceReference(PDEVICE_OBJECT DeviceObject); | ||||
| VOID FspDeviceDereference(PDEVICE_OBJECT DeviceObject); | ||||
| VOID FspFsvolDeviceFileRenameAcquireShared(PDEVICE_OBJECT DeviceObject); | ||||
| VOID FspFsvolDeviceFileRenameAcquireExclusive(PDEVICE_OBJECT DeviceObject); | ||||
| VOID FspFsvolDeviceFileRenameSetOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner); | ||||
| VOID FspFsvolDeviceFileRenameRelease(PDEVICE_OBJECT DeviceObject); | ||||
| VOID FspFsvolDeviceFileRenameReleaseOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner); | ||||
| VOID FspFsvolDeviceLockContextTable(PDEVICE_OBJECT DeviceObject); | ||||
| VOID FspFsvolDeviceUnlockContextTable(PDEVICE_OBJECT DeviceObject); | ||||
| PVOID FspFsvolDeviceLookupContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier); | ||||
|   | ||||
| @@ -851,7 +851,7 @@ NTSTATUS FspFsvolSetInformationComplete( | ||||
|         IrpSp->FileObject); | ||||
| } | ||||
|  | ||||
| static VOID FspFsvolInformationRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Context[3]) | ||||
| static VOID FspFsvolInformationRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Context[4]) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|   | ||||
| @@ -84,7 +84,7 @@ static PVOID FspAllocateIrpMustSucceed(CCHAR StackSize) | ||||
| typedef struct | ||||
| { | ||||
|     FSP_IOP_REQUEST_FINI *RequestFini; | ||||
|     PVOID Context[3]; | ||||
|     PVOID Context[4]; | ||||
|     FSP_FSCTL_TRANSACT_RSP *Response; | ||||
|     __declspec(align(MEMORY_ALLOCATION_ALIGNMENT)) UINT8 RequestBuf[]; | ||||
| } FSP_FSCTL_TRANSACT_REQ_HEADER; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user