mirror of
				https://github.com/winfsp/winfsp.git
				synced 2025-10-30 19:48:38 -05:00 
			
		
		
		
	Experimental fix for github issue #45
This commit is contained in:
		| @@ -80,8 +80,18 @@ static NTSTATUS FspFsvolClose( | ||||
|     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 | ||||
|      * Post as a BestEffort WORK request. This allows us to complete our own IRP | ||||
|      * and return immediately. | ||||
|      */ | ||||
|     FspIopPostWorkRequestBestEffort(FsvolDeviceObject, Request); | ||||
|   | ||||
| @@ -41,6 +41,7 @@ VOID FspFsvolDeviceFileRenameAcquireExclusive(PDEVICE_OBJECT DeviceObject); | ||||
| VOID FspFsvolDeviceFileRenameSetOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner); | ||||
| VOID FspFsvolDeviceFileRenameRelease(PDEVICE_OBJECT DeviceObject); | ||||
| VOID FspFsvolDeviceFileRenameReleaseOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner); | ||||
| BOOLEAN FspFsvolDeviceFileRenameIsAcquiredExclusive(PDEVICE_OBJECT DeviceObject); | ||||
| VOID FspFsvolDeviceLockContextTable(PDEVICE_OBJECT DeviceObject); | ||||
| VOID FspFsvolDeviceUnlockContextTable(PDEVICE_OBJECT DeviceObject); | ||||
| NTSTATUS FspFsvolDeviceCopyContextList(PDEVICE_OBJECT DeviceObject, | ||||
| @@ -80,6 +81,7 @@ VOID FspDeviceDeleteAll(VOID); | ||||
| #pragma alloc_text(PAGE, FspFsvolDeviceFileRenameSetOwner) | ||||
| #pragma alloc_text(PAGE, FspFsvolDeviceFileRenameRelease) | ||||
| #pragma alloc_text(PAGE, FspFsvolDeviceFileRenameReleaseOwner) | ||||
| #pragma alloc_text(PAGE, FspFsvolDeviceFileRenameIsAcquiredExclusive) | ||||
| #pragma alloc_text(PAGE, FspFsvolDeviceLockContextTable) | ||||
| #pragma alloc_text(PAGE, FspFsvolDeviceUnlockContextTable) | ||||
| #pragma alloc_text(PAGE, FspFsvolDeviceCopyContextList) | ||||
| @@ -574,6 +576,15 @@ VOID FspFsvolDeviceFileRenameReleaseOwner(PDEVICE_OBJECT DeviceObject, PVOID Own | ||||
|         ExReleaseResourceForThreadLite(&FsvolDeviceExtension->FileRenameResource, (ERESOURCE_THREAD)Owner); | ||||
| } | ||||
|  | ||||
| BOOLEAN FspFsvolDeviceFileRenameIsAcquiredExclusive(PDEVICE_OBJECT DeviceObject) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject); | ||||
|  | ||||
|     return ExIsResourceAcquiredExclusiveLite(&FsvolDeviceExtension->FileRenameResource); | ||||
| } | ||||
|  | ||||
| VOID FspFsvolDeviceLockContextTable(PDEVICE_OBJECT DeviceObject) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|   | ||||
| @@ -1064,6 +1064,7 @@ VOID FspFsvolDeviceFileRenameAcquireExclusive(PDEVICE_OBJECT DeviceObject); | ||||
| VOID FspFsvolDeviceFileRenameSetOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner); | ||||
| VOID FspFsvolDeviceFileRenameRelease(PDEVICE_OBJECT DeviceObject); | ||||
| VOID FspFsvolDeviceFileRenameReleaseOwner(PDEVICE_OBJECT DeviceObject, PVOID Owner); | ||||
| BOOLEAN FspFsvolDeviceFileRenameIsAcquiredExclusive(PDEVICE_OBJECT DeviceObject); | ||||
| VOID FspFsvolDeviceLockContextTable(PDEVICE_OBJECT DeviceObject); | ||||
| VOID FspFsvolDeviceUnlockContextTable(PDEVICE_OBJECT DeviceObject); | ||||
| NTSTATUS FspFsvolDeviceCopyContextList(PDEVICE_OBJECT DeviceObject, | ||||
|   | ||||
| @@ -1243,6 +1243,50 @@ NTSTATUS FspFileNodeRenameCheck(PDEVICE_OBJECT FsvolDeviceObject, PIRP OplockIrp | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* flush and purge cleaned up but still open files affected by rename (github issue #45) */ | ||||
|     { | ||||
|         PIRP TopLevelIrp; | ||||
|         IO_STATUS_BLOCK IoStatus; | ||||
|  | ||||
|         /* reset the top-level IRP to avoid deadlock on the FileNodes' resources */ | ||||
|         TopLevelIrp = IoGetTopLevelIrp(); | ||||
|         IoSetTopLevelIrp(0); | ||||
|  | ||||
|         /* enumerate in reverse order so that files are flushed before containing directories */ | ||||
|         for ( | ||||
|             DescendantFileNodeIndex = DescendantFileNodeCount - 1; | ||||
|             DescendantFileNodeCount > DescendantFileNodeIndex; | ||||
|             DescendantFileNodeIndex--) | ||||
|         { | ||||
|             DescendantFileNode = DescendantFileNodes[DescendantFileNodeIndex]; | ||||
|             HasHandles = (UINT_PTR)DescendantFileNode & 1; | ||||
|             DescendantFileNode = (PVOID)((UINT_PTR)DescendantFileNode & ~7); | ||||
|  | ||||
|             if (HasHandles) | ||||
|                 continue; | ||||
|             if (CheckingOldName && | ||||
|                 (DescendantFileNode->FileName.Length <= FileName->Length || | ||||
|                     L'\\' != DescendantFileNode->FileName.Buffer[FileName->Length / sizeof(WCHAR)])) | ||||
|                 continue; | ||||
|             if (MmDoesFileHaveUserWritableReferences(&DescendantFileNode->NonPaged->SectionObjectPointers)) | ||||
|                 continue; | ||||
|  | ||||
|             /* | ||||
|              * There are no handles and no writable user mappings. [Ideally we would want to know | ||||
|              * that there are no handles and no user mappings, period. Is there an DDI/method to | ||||
|              * do that?] There may be a read-only user mapping, but in this case CcFlushCache | ||||
|              * should be a no-op and MmForceSectionClosed will fail (which is fine). | ||||
|              */ | ||||
|  | ||||
|             ASSERT(DescendantFileNode != FileNode && DescendantFileNode->MainFileNode != FileNode); | ||||
|  | ||||
|             FspCcFlushCache(&DescendantFileNode->NonPaged->SectionObjectPointers, 0, 0, &IoStatus); | ||||
|             MmForceSectionClosed(&DescendantFileNode->NonPaged->SectionObjectPointers, FALSE); | ||||
|         } | ||||
|  | ||||
|         IoSetTopLevelIrp(TopLevelIrp); | ||||
|     } | ||||
|  | ||||
|     /* break any Batch or Handle oplocks on descendants */ | ||||
|     Result = STATUS_SUCCESS; | ||||
|     for ( | ||||
|   | ||||
		Reference in New Issue
	
	Block a user