mirror of
				https://github.com/winfsp/winfsp.git
				synced 2025-10-30 11:38:39 -05:00 
			
		
		
		
	sys: FSP_FILE_NODE: add HandleCount field and refactor cleanup/close/rename
This commit is contained in:
		| @@ -14,7 +14,6 @@ static NTSTATUS FspFsvolCleanup( | |||||||
|     PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); |     PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp); | ||||||
| FSP_IOCMPL_DISPATCH FspFsvolCleanupComplete; | FSP_IOCMPL_DISPATCH FspFsvolCleanupComplete; | ||||||
| static FSP_IOP_REQUEST_FINI FspFsvolCleanupRequestFini; | static FSP_IOP_REQUEST_FINI FspFsvolCleanupRequestFini; | ||||||
| static VOID FspFsvolCleanupUninitialize(PVOID Context); |  | ||||||
| FSP_DRIVER_DISPATCH FspCleanup; | FSP_DRIVER_DISPATCH FspCleanup; | ||||||
|  |  | ||||||
| #ifdef ALLOC_PRAGMA | #ifdef ALLOC_PRAGMA | ||||||
| @@ -23,7 +22,6 @@ FSP_DRIVER_DISPATCH FspCleanup; | |||||||
| #pragma alloc_text(PAGE, FspFsvolCleanup) | #pragma alloc_text(PAGE, FspFsvolCleanup) | ||||||
| #pragma alloc_text(PAGE, FspFsvolCleanupComplete) | #pragma alloc_text(PAGE, FspFsvolCleanupComplete) | ||||||
| #pragma alloc_text(PAGE, FspFsvolCleanupRequestFini) | #pragma alloc_text(PAGE, FspFsvolCleanupRequestFini) | ||||||
| #pragma alloc_text(PAGE, FspFsvolCleanupUninitialize) |  | ||||||
| #pragma alloc_text(PAGE, FspCleanup) | #pragma alloc_text(PAGE, FspCleanup) | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| @@ -33,13 +31,6 @@ enum | |||||||
|     RequestIrp                          = 0, |     RequestIrp                          = 0, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| typedef struct |  | ||||||
| { |  | ||||||
|     PFILE_OBJECT FileObject; |  | ||||||
|     LARGE_INTEGER TruncateSize, *PTruncateSize; |  | ||||||
|     WORK_QUEUE_ITEM WorkQueueItem; |  | ||||||
| } FSP_FSVOL_CLEANUP_UNINITIALIZE_WORK_ITEM; |  | ||||||
|  |  | ||||||
| static NTSTATUS FspFsctlCleanup( | static NTSTATUS FspFsctlCleanup( | ||||||
|     PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) |     PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp) | ||||||
| { | { | ||||||
| @@ -78,11 +69,9 @@ static NTSTATUS FspFsvolCleanup( | |||||||
|  |  | ||||||
|     ASSERT(FileNode == FileDesc->FileNode); |     ASSERT(FileNode == FileDesc->FileNode); | ||||||
|  |  | ||||||
|  |     FspFileNodeAcquireExclusive(FileNode, Main); | ||||||
|  |  | ||||||
|     FspFileNodeCleanup(FileNode, FileObject, &DeletePending); |     FspFileNodeCleanup(FileNode, FileObject, &DeletePending); | ||||||
|     if (DeletePending) |  | ||||||
|         FspFileNodeAcquireExclusive(FileNode, Full); |  | ||||||
|     else |  | ||||||
|         FspFileNodeAcquireShared(FileNode, Full); |  | ||||||
|  |  | ||||||
|     /* create the user-mode file system request; MustSucceed because IRP_MJ_CLEANUP cannot fail */ |     /* create the user-mode file system request; MustSucceed because IRP_MJ_CLEANUP cannot fail */ | ||||||
|     FspIopCreateRequestMustSucceedEx(Irp, DeletePending ? &FileNode->FileName : 0, 0, |     FspIopCreateRequestMustSucceedEx(Irp, DeletePending ? &FileNode->FileName : 0, 0, | ||||||
| @@ -92,6 +81,8 @@ static NTSTATUS FspFsvolCleanup( | |||||||
|     Request->Req.Cleanup.UserContext2 = FileDesc->UserContext2; |     Request->Req.Cleanup.UserContext2 = FileDesc->UserContext2; | ||||||
|     Request->Req.Cleanup.Delete = DeletePending; |     Request->Req.Cleanup.Delete = DeletePending; | ||||||
|  |  | ||||||
|  |     FspFileNodeAcquireExclusive(FileNode, Pgio); | ||||||
|  |  | ||||||
|     FspFileNodeSetOwner(FileNode, Full, Request); |     FspFileNodeSetOwner(FileNode, Full, Request); | ||||||
|     FspIopRequestContext(Request, RequestIrp) = Irp; |     FspIopRequestContext(Request, RequestIrp) = Irp; | ||||||
|  |  | ||||||
| @@ -129,93 +120,14 @@ static VOID FspFsvolCleanupRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PVOID Co | |||||||
|     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); |     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); | ||||||
|     PFILE_OBJECT FileObject = IrpSp->FileObject; |     PFILE_OBJECT FileObject = IrpSp->FileObject; | ||||||
|     FSP_FILE_NODE *FileNode = FileObject->FsContext; |     FSP_FILE_NODE *FileNode = FileObject->FsContext; | ||||||
|     FSP_FSCTL_FILE_INFO FileInfo; |  | ||||||
|     LARGE_INTEGER TruncateSize = { 0 }, *PTruncateSize = 0; |  | ||||||
|     BOOLEAN DeletePending = 0 != Request->Req.Cleanup.Delete; |  | ||||||
|     BOOLEAN DeletedFromContextTable; |  | ||||||
|     BOOLEAN Success; |  | ||||||
|  |  | ||||||
|     FspFileNodeClose(FileNode, FileObject, &DeletedFromContextTable); |     FspFileNodeReleaseOwner(FileNode, Pgio, Request); | ||||||
|     if (DeletedFromContextTable) |  | ||||||
|     { |  | ||||||
|         if (DeletePending) |  | ||||||
|             PTruncateSize = &TruncateSize; |  | ||||||
|         else if (FileNode->TruncateOnClose) |  | ||||||
|         { |  | ||||||
|             /* |  | ||||||
|              * Even when FileInfoTimeout != Infinity, |  | ||||||
|              * this is the last size that the cache manager knows. |  | ||||||
|              */ |  | ||||||
|             FspFileNodeGetFileInfo(FileNode, &FileInfo); |  | ||||||
|  |  | ||||||
|             TruncateSize.QuadPart = FileInfo.FileSize; |     FspFileNodeCleanupComplete(FileNode, FileObject); | ||||||
|             PTruncateSize = &TruncateSize; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     if (DeletePending) |  | ||||||
|     { |  | ||||||
|         /* FileNode is Exclusive Full; release Pgio */ |  | ||||||
|         FspFileNodeReleaseOwner(FileNode, Pgio, Request); |  | ||||||
|  |  | ||||||
|         /* FileNode is now Exclusive Main; owner is Request */ |  | ||||||
|     } |  | ||||||
|     else |  | ||||||
|     { |  | ||||||
|         /* FileNode is Shared Full; reacquire as Exclusive Main for CcUninitializeCacheMap */ |  | ||||||
|         FspFileNodeReleaseOwner(FileNode, Full, Request); |  | ||||||
|  |  | ||||||
|         Success = DEBUGTEST(90, TRUE) && FspFileNodeTryAcquireExclusive(FileNode, Main); |  | ||||||
|         if (!Success) |  | ||||||
|         { |  | ||||||
|             /* oh, maaan! we now have to do delayed uninitialize! */ |  | ||||||
|  |  | ||||||
|             FSP_FSVOL_CLEANUP_UNINITIALIZE_WORK_ITEM *WorkItem; |  | ||||||
|  |  | ||||||
|             WorkItem = FspAllocatePoolMustSucceed( |  | ||||||
|                 NonPagedPool, sizeof *WorkItem, FSP_ALLOC_INTERNAL_TAG); |  | ||||||
|             WorkItem->FileObject = FileObject; |  | ||||||
|             WorkItem->TruncateSize = TruncateSize; |  | ||||||
|             WorkItem->PTruncateSize = 0 != PTruncateSize ? &WorkItem->TruncateSize : 0; |  | ||||||
|             ExInitializeWorkItem(&WorkItem->WorkQueueItem, FspFsvolCleanupUninitialize, WorkItem); |  | ||||||
|  |  | ||||||
|             /* make sure that the file object (and corresponding device object) stay around! */ |  | ||||||
|             ObReferenceObject(FileObject); |  | ||||||
|  |  | ||||||
|             ExQueueWorkItem(&WorkItem->WorkQueueItem, CriticalWorkQueue); |  | ||||||
|  |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         /* FileNode is now Exclusive Main; owner is current thread */ |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     CcUninitializeCacheMap(FileObject, PTruncateSize, 0); |  | ||||||
|  |  | ||||||
|     /* this works correctly even if owner is current thread */ |  | ||||||
|     FspFileNodeReleaseOwner(FileNode, Main, Request); |     FspFileNodeReleaseOwner(FileNode, Main, Request); | ||||||
| } | } | ||||||
|  |  | ||||||
| static VOID FspFsvolCleanupUninitialize(PVOID Context) |  | ||||||
| { |  | ||||||
|     PAGED_CODE(); |  | ||||||
|  |  | ||||||
|     FSP_FSVOL_CLEANUP_UNINITIALIZE_WORK_ITEM *WorkItem = Context; |  | ||||||
|     PFILE_OBJECT FileObject = WorkItem->FileObject; |  | ||||||
|     FSP_FILE_NODE *FileNode = FileObject->FsContext; |  | ||||||
|     LARGE_INTEGER *PTruncateSize = WorkItem->PTruncateSize; |  | ||||||
|  |  | ||||||
|     FspFileNodeAcquireExclusive(FileNode, Main); |  | ||||||
|  |  | ||||||
|     CcUninitializeCacheMap(FileObject, PTruncateSize, 0); |  | ||||||
|  |  | ||||||
|     FspFileNodeRelease(FileNode, Main); |  | ||||||
|  |  | ||||||
|     ObDereferenceObject(FileObject); |  | ||||||
|  |  | ||||||
|     FspFree(WorkItem); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| NTSTATUS FspCleanup( | NTSTATUS FspCleanup( | ||||||
|     PDEVICE_OBJECT DeviceObject, PIRP Irp) |     PDEVICE_OBJECT DeviceObject, PIRP Irp) | ||||||
| { | { | ||||||
|   | |||||||
| @@ -63,6 +63,7 @@ static NTSTATUS FspFsvolClose( | |||||||
|     Request->Req.Close.UserContext = FileNode->UserContext; |     Request->Req.Close.UserContext = FileNode->UserContext; | ||||||
|     Request->Req.Close.UserContext2 = FileDesc->UserContext2; |     Request->Req.Close.UserContext2 = FileDesc->UserContext2; | ||||||
|  |  | ||||||
|  |     FspFileNodeClose(FileNode, FileObject); | ||||||
|     FspFileNodeDereference(FileNode); |     FspFileNodeDereference(FileNode); | ||||||
|     FspFileDescDelete(FileDesc); |     FspFileDescDelete(FileDesc); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -742,7 +742,7 @@ static NTSTATUS FspFsvolCreateTryOpen(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Re | |||||||
|             if (0 == Request) |             if (0 == Request) | ||||||
|             { |             { | ||||||
|                 FspFsvolCreatePostClose(FileDesc); |                 FspFsvolCreatePostClose(FileDesc); | ||||||
|                 FspFileNodeClose(FileNode, FileObject, 0); |                 FspFileNodeClose(FileNode, FileObject); | ||||||
|             } |             } | ||||||
|          |          | ||||||
|             return DeleteOnClose ? STATUS_CANNOT_DELETE : STATUS_SHARING_VIOLATION; |             return DeleteOnClose ? STATUS_CANNOT_DELETE : STATUS_SHARING_VIOLATION; | ||||||
| @@ -843,7 +843,7 @@ static VOID FspFsvolCreateTryOpenRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, PV | |||||||
|         ASSERT(0 != FileObject); |         ASSERT(0 != FileObject); | ||||||
|  |  | ||||||
|         FspFsvolCreatePostClose(FileDesc); |         FspFsvolCreatePostClose(FileDesc); | ||||||
|         FspFileNodeClose(FileDesc->FileNode, FileObject, 0); |         FspFileNodeClose(FileDesc->FileNode, FileObject); | ||||||
|         FspFileNodeDereference(FileDesc->FileNode); |         FspFileNodeDereference(FileDesc->FileNode); | ||||||
|         FspFileDescDelete(FileDesc); |         FspFileDescDelete(FileDesc); | ||||||
|     } |     } | ||||||
| @@ -870,7 +870,7 @@ static VOID FspFsvolCreateOverwriteRequestFini(FSP_FSCTL_TRANSACT_REQ *Request, | |||||||
|         else if (RequestProcessing == State) |         else if (RequestProcessing == State) | ||||||
|             FspFileNodeReleaseOwner(FileDesc->FileNode, Full, Request); |             FspFileNodeReleaseOwner(FileDesc->FileNode, Full, Request); | ||||||
|  |  | ||||||
|         FspFileNodeClose(FileDesc->FileNode, FileObject, 0); |         FspFileNodeClose(FileDesc->FileNode, FileObject); | ||||||
|         FspFileNodeDereference(FileDesc->FileNode); |         FspFileNodeDereference(FileDesc->FileNode); | ||||||
|         FspFileDescDelete(FileDesc); |         FspFileDescDelete(FileDesc); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -40,9 +40,9 @@ VOID FspFsvolDeviceDeleteContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier, | |||||||
| static RTL_AVL_COMPARE_ROUTINE FspFsvolDeviceCompareContext; | static RTL_AVL_COMPARE_ROUTINE FspFsvolDeviceCompareContext; | ||||||
| static RTL_AVL_ALLOCATE_ROUTINE FspFsvolDeviceAllocateContext; | static RTL_AVL_ALLOCATE_ROUTINE FspFsvolDeviceAllocateContext; | ||||||
| static RTL_AVL_FREE_ROUTINE FspFsvolDeviceFreeContext; | static RTL_AVL_FREE_ROUTINE FspFsvolDeviceFreeContext; | ||||||
|  | PVOID FspFsvolDeviceEnumerateContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING FileName, | ||||||
|  |     BOOLEAN SubpathOnly, PVOID *PRestartKey); | ||||||
| PVOID FspFsvolDeviceLookupContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING FileName); | PVOID FspFsvolDeviceLookupContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING FileName); | ||||||
| PVOID FspFsvolDeviceLookupDescendantContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING FileName, |  | ||||||
|     BOOLEAN ChildOnly); |  | ||||||
| PVOID FspFsvolDeviceInsertContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING FileName, PVOID Context, | PVOID FspFsvolDeviceInsertContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING FileName, PVOID Context, | ||||||
|     FSP_DEVICE_CONTEXT_BY_NAME_TABLE_ELEMENT *ElementStorage, PBOOLEAN PInserted); |     FSP_DEVICE_CONTEXT_BY_NAME_TABLE_ELEMENT *ElementStorage, PBOOLEAN PInserted); | ||||||
| VOID FspFsvolDeviceDeleteContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING FileName, | VOID FspFsvolDeviceDeleteContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING FileName, | ||||||
| @@ -79,8 +79,8 @@ VOID FspDeviceDeleteAll(VOID); | |||||||
| #pragma alloc_text(PAGE, FspFsvolDeviceCompareContext) | #pragma alloc_text(PAGE, FspFsvolDeviceCompareContext) | ||||||
| #pragma alloc_text(PAGE, FspFsvolDeviceAllocateContext) | #pragma alloc_text(PAGE, FspFsvolDeviceAllocateContext) | ||||||
| #pragma alloc_text(PAGE, FspFsvolDeviceFreeContext) | #pragma alloc_text(PAGE, FspFsvolDeviceFreeContext) | ||||||
|  | #pragma alloc_text(PAGE, FspFsvolDeviceEnumerateContextByName) | ||||||
| #pragma alloc_text(PAGE, FspFsvolDeviceLookupContextByName) | #pragma alloc_text(PAGE, FspFsvolDeviceLookupContextByName) | ||||||
| #pragma alloc_text(PAGE, FspFsvolDeviceLookupDescendantContextByName) |  | ||||||
| #pragma alloc_text(PAGE, FspFsvolDeviceInsertContextByName) | #pragma alloc_text(PAGE, FspFsvolDeviceInsertContextByName) | ||||||
| #pragma alloc_text(PAGE, FspFsvolDeviceDeleteContextByName) | #pragma alloc_text(PAGE, FspFsvolDeviceDeleteContextByName) | ||||||
| #pragma alloc_text(PAGE, FspFsvolDeviceCompareContextByName) | #pragma alloc_text(PAGE, FspFsvolDeviceCompareContextByName) | ||||||
| @@ -623,6 +623,31 @@ static VOID NTAPI FspFsvolDeviceFreeContext( | |||||||
|     PAGED_CODE(); |     PAGED_CODE(); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | PVOID FspFsvolDeviceEnumerateContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING FileName, | ||||||
|  |     BOOLEAN SubpathOnly, PVOID *PRestartKey) | ||||||
|  | { | ||||||
|  |     PAGED_CODE(); | ||||||
|  |  | ||||||
|  |     FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject); | ||||||
|  |     BOOLEAN CaseInsensitive = 0 == FsvolDeviceExtension->VolumeParams.CaseSensitiveSearch; | ||||||
|  |     FSP_DEVICE_CONTEXT_BY_NAME_TABLE_ELEMENT_DATA *Result; | ||||||
|  |     ULONG DeleteCount = 0; | ||||||
|  |  | ||||||
|  |     if (0 != *PRestartKey) | ||||||
|  |         SubpathOnly = FALSE; | ||||||
|  |  | ||||||
|  |     Result = RtlEnumerateGenericTableLikeADirectory(&FsvolDeviceExtension->ContextByNameTable, | ||||||
|  |         0, 0, SubpathOnly, PRestartKey, &DeleteCount, &FileName); | ||||||
|  |      | ||||||
|  |     if (0 != Result && | ||||||
|  |         RtlPrefixUnicodeString(FileName, Result->FileName, CaseInsensitive) && | ||||||
|  |         FileName->Length < Result->FileName->Length && | ||||||
|  |         '\\' == Result->FileName->Buffer[FileName->Length / sizeof(WCHAR)]) | ||||||
|  |         return Result->Context; | ||||||
|  |     else | ||||||
|  |         return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
| PVOID FspFsvolDeviceLookupContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING FileName) | PVOID FspFsvolDeviceLookupContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING FileName) | ||||||
| { | { | ||||||
|     PAGED_CODE(); |     PAGED_CODE(); | ||||||
| @@ -635,27 +660,6 @@ PVOID FspFsvolDeviceLookupContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_ST | |||||||
|     return 0 != Result ? Result->Context : 0; |     return 0 != Result ? Result->Context : 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| PVOID FspFsvolDeviceLookupDescendantContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING FileName, |  | ||||||
|     BOOLEAN ChildOnly) |  | ||||||
| { |  | ||||||
|     PAGED_CODE(); |  | ||||||
|  |  | ||||||
|     FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject); |  | ||||||
|     BOOLEAN CaseInsensitive = 0 == FsvolDeviceExtension->VolumeParams.CaseSensitiveSearch; |  | ||||||
|     FSP_DEVICE_CONTEXT_BY_NAME_TABLE_ELEMENT_DATA *Result; |  | ||||||
|     PVOID RestartKey = 0; |  | ||||||
|     ULONG DeleteCount = 0; |  | ||||||
|  |  | ||||||
|     Result = RtlEnumerateGenericTableLikeADirectory(&FsvolDeviceExtension->ContextByNameTable, |  | ||||||
|         0, 0, ChildOnly, &RestartKey, &DeleteCount, &FileName); |  | ||||||
|     if (0 == Result || |  | ||||||
|         !RtlPrefixUnicodeString(FileName, Result->FileName, CaseInsensitive) || |  | ||||||
|         (FileName->Length < Result->FileName->Length && |  | ||||||
|             '\\' != Result->FileName->Buffer[FileName->Length / sizeof(WCHAR)])) |  | ||||||
|         return 0; |  | ||||||
|     return Result->Context; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| PVOID FspFsvolDeviceInsertContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING FileName, PVOID Context, | PVOID FspFsvolDeviceInsertContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING FileName, PVOID Context, | ||||||
|     FSP_DEVICE_CONTEXT_BY_NAME_TABLE_ELEMENT *ElementStorage, PBOOLEAN PInserted) |     FSP_DEVICE_CONTEXT_BY_NAME_TABLE_ELEMENT *ElementStorage, PBOOLEAN PInserted) | ||||||
| { | { | ||||||
|   | |||||||
| @@ -707,9 +707,9 @@ PVOID FspFsvolDeviceInsertContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier | |||||||
|     FSP_DEVICE_CONTEXT_TABLE_ELEMENT *ElementStorage, PBOOLEAN PInserted); |     FSP_DEVICE_CONTEXT_TABLE_ELEMENT *ElementStorage, PBOOLEAN PInserted); | ||||||
| VOID FspFsvolDeviceDeleteContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier, | VOID FspFsvolDeviceDeleteContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier, | ||||||
|     PBOOLEAN PDeleted); |     PBOOLEAN PDeleted); | ||||||
|  | PVOID FspFsvolDeviceEnumerateContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING FileName, | ||||||
|  |     BOOLEAN SubpathOnly, PVOID *PRestartKey); | ||||||
| PVOID FspFsvolDeviceLookupContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING FileName); | PVOID FspFsvolDeviceLookupContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING FileName); | ||||||
| PVOID FspFsvolDeviceLookupDescendantContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING FileName, |  | ||||||
|     BOOLEAN ChildOnly); |  | ||||||
| PVOID FspFsvolDeviceInsertContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING FileName, PVOID Context, | PVOID FspFsvolDeviceInsertContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING FileName, PVOID Context, | ||||||
|     FSP_DEVICE_CONTEXT_BY_NAME_TABLE_ELEMENT *ElementStorage, PBOOLEAN PInserted); |     FSP_DEVICE_CONTEXT_BY_NAME_TABLE_ELEMENT *ElementStorage, PBOOLEAN PInserted); | ||||||
| VOID FspFsvolDeviceDeleteContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING FileName, | VOID FspFsvolDeviceDeleteContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING FileName, | ||||||
| @@ -775,7 +775,8 @@ typedef struct | |||||||
|     LONG RefCount; |     LONG RefCount; | ||||||
|     UINT32 DeletePending; |     UINT32 DeletePending; | ||||||
|     /* locked under FSP_FSVOL_DEVICE_EXTENSION::ContextTableResource */ |     /* locked under FSP_FSVOL_DEVICE_EXTENSION::ContextTableResource */ | ||||||
|     LONG OpenCount; |     LONG OpenCount;                     /* ContextTable ref count */ | ||||||
|  |     LONG HandleCount;                   /* HANDLE count (CREATE/CLEANUP) */ | ||||||
|     SHARE_ACCESS ShareAccess; |     SHARE_ACCESS ShareAccess; | ||||||
|     FSP_DEVICE_CONTEXT_BY_NAME_TABLE_ELEMENT ContextByNameElementStorage; |     FSP_DEVICE_CONTEXT_BY_NAME_TABLE_ELEMENT ContextByNameElementStorage; | ||||||
|     /* locked under FSP_FSVOL_DEVICE_EXTENSION::FileRenameResource or Header.Resource */ |     /* locked under FSP_FSVOL_DEVICE_EXTENSION::FileRenameResource or Header.Resource */ | ||||||
| @@ -838,9 +839,11 @@ FSP_FILE_NODE *FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, | |||||||
|     UINT32 GrantedAccess, UINT32 ShareAccess, NTSTATUS *PResult); |     UINT32 GrantedAccess, UINT32 ShareAccess, NTSTATUS *PResult); | ||||||
| VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, | VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, | ||||||
|     PBOOLEAN PDeletePending); |     PBOOLEAN PDeletePending); | ||||||
| VOID FspFileNodeClose(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, | VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject); | ||||||
|     PBOOLEAN PDeletedFromContextTable); | VOID FspFileNodeClose(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject); | ||||||
| VOID FspFileNodeRename(FSP_FILE_NODE *FileNode, PUNICODE_STRING NewFileName); | VOID FspFileNodeRename(FSP_FILE_NODE *FileNode, PUNICODE_STRING NewFileName); | ||||||
|  | BOOLEAN FspFileNodeHasOpenHandles(PDEVICE_OBJECT FsvolDeviceObject, | ||||||
|  |     PUNICODE_STRING FileName, BOOLEAN SubpathOnly); | ||||||
| VOID FspFileNodeGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileInfo); | VOID FspFileNodeGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileInfo); | ||||||
| BOOLEAN FspFileNodeTryGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileInfo); | BOOLEAN FspFileNodeTryGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileInfo); | ||||||
| VOID FspFileNodeSetFileInfo(FSP_FILE_NODE *FileNode, PFILE_OBJECT CcFileObject, | VOID FspFileNodeSetFileInfo(FSP_FILE_NODE *FileNode, PFILE_OBJECT CcFileObject, | ||||||
|   | |||||||
							
								
								
									
										121
									
								
								src/sys/file.c
									
									
									
									
									
								
							
							
						
						
									
										121
									
								
								src/sys/file.c
									
									
									
									
									
								
							| @@ -20,9 +20,11 @@ FSP_FILE_NODE *FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, | |||||||
|     UINT32 GrantedAccess, UINT32 ShareAccess, NTSTATUS *PResult); |     UINT32 GrantedAccess, UINT32 ShareAccess, NTSTATUS *PResult); | ||||||
| VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, | VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, | ||||||
|     PBOOLEAN PDeletePending); |     PBOOLEAN PDeletePending); | ||||||
| VOID FspFileNodeClose(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, | VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject); | ||||||
|     PBOOLEAN PDeletedFromContextTable); | VOID FspFileNodeClose(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject); | ||||||
| VOID FspFileNodeRename(FSP_FILE_NODE *FileNode, PUNICODE_STRING NewFileName); | VOID FspFileNodeRename(FSP_FILE_NODE *FileNode, PUNICODE_STRING NewFileName); | ||||||
|  | BOOLEAN FspFileNodeHasOpenHandles(PDEVICE_OBJECT FsvolDeviceObject, | ||||||
|  |     PUNICODE_STRING FileName, BOOLEAN SubpathOnly); | ||||||
| VOID FspFileNodeGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileInfo); | VOID FspFileNodeGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileInfo); | ||||||
| BOOLEAN FspFileNodeTryGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileInfo); | BOOLEAN FspFileNodeTryGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileInfo); | ||||||
| VOID FspFileNodeSetFileInfo(FSP_FILE_NODE *FileNode, PFILE_OBJECT CcFileObject, | VOID FspFileNodeSetFileInfo(FSP_FILE_NODE *FileNode, PFILE_OBJECT CcFileObject, | ||||||
| @@ -48,8 +50,10 @@ VOID FspFileDescDelete(FSP_FILE_DESC *FileDesc); | |||||||
| #pragma alloc_text(PAGE, FspFileNodeReleaseOwnerF) | #pragma alloc_text(PAGE, FspFileNodeReleaseOwnerF) | ||||||
| #pragma alloc_text(PAGE, FspFileNodeOpen) | #pragma alloc_text(PAGE, FspFileNodeOpen) | ||||||
| #pragma alloc_text(PAGE, FspFileNodeCleanup) | #pragma alloc_text(PAGE, FspFileNodeCleanup) | ||||||
|  | #pragma alloc_text(PAGE, FspFileNodeCleanupComplete) | ||||||
| #pragma alloc_text(PAGE, FspFileNodeClose) | #pragma alloc_text(PAGE, FspFileNodeClose) | ||||||
| #pragma alloc_text(PAGE, FspFileNodeRename) | #pragma alloc_text(PAGE, FspFileNodeRename) | ||||||
|  | #pragma alloc_text(PAGE, FspFileNodeHasOpenHandles) | ||||||
| #pragma alloc_text(PAGE, FspFileNodeGetFileInfo) | #pragma alloc_text(PAGE, FspFileNodeGetFileInfo) | ||||||
| #pragma alloc_text(PAGE, FspFileNodeTryGetFileInfo) | #pragma alloc_text(PAGE, FspFileNodeTryGetFileInfo) | ||||||
| #pragma alloc_text(PAGE, FspFileNodeSetFileInfo) | #pragma alloc_text(PAGE, FspFileNodeSetFileInfo) | ||||||
| @@ -308,6 +312,8 @@ FSP_FILE_NODE *FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, | |||||||
|      * Attempt to insert our FileNode into the volume device's generic table. |      * Attempt to insert our FileNode into the volume device's generic table. | ||||||
|      * If an FileNode with the same UserContext already exists, then use that |      * If an FileNode with the same UserContext already exists, then use that | ||||||
|      * FileNode instead. |      * FileNode instead. | ||||||
|  |      * | ||||||
|  |      * There is no FileNode that can be acquired when calling this function. | ||||||
|      */ |      */ | ||||||
|  |  | ||||||
|     PAGED_CODE(); |     PAGED_CODE(); | ||||||
| @@ -386,6 +392,7 @@ FSP_FILE_NODE *FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, | |||||||
|     { |     { | ||||||
|         FspFileNodeReference(OpenedFileNode); |         FspFileNodeReference(OpenedFileNode); | ||||||
|         OpenedFileNode->OpenCount++; |         OpenedFileNode->OpenCount++; | ||||||
|  |         OpenedFileNode->HandleCount++; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     FspFsvolDeviceUnlockContextTable(FsvolDeviceObject); |     FspFsvolDeviceUnlockContextTable(FsvolDeviceObject); | ||||||
| @@ -397,16 +404,18 @@ VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, | |||||||
|     PBOOLEAN PDeletePending) |     PBOOLEAN PDeletePending) | ||||||
| { | { | ||||||
|     /* |     /* | ||||||
|      * Determine whether a FileNode should be deleted. Note that when |      * Determine whether a FileNode should be deleted. Note that when FileNode->DeletePending | ||||||
|      * FileNode->DeletePending is set, the OpenCount cannot be changed |      * is set, the OpenCount/HandleCount cannot be increased because FspFileNodeOpen() will | ||||||
|      * because FspFileNodeOpen() will return STATUS_DELETE_PENDING. |      * return STATUS_DELETE_PENDING. | ||||||
|  |      * | ||||||
|  |      * The FileNode must be acquired exclusive (Main) when calling this function. | ||||||
|      */ |      */ | ||||||
|  |  | ||||||
|     PAGED_CODE(); |     PAGED_CODE(); | ||||||
|  |  | ||||||
|     PDEVICE_OBJECT FsvolDeviceObject = FileNode->FsvolDeviceObject; |     PDEVICE_OBJECT FsvolDeviceObject = FileNode->FsvolDeviceObject; | ||||||
|     FSP_FILE_DESC *FileDesc = FileObject->FsContext2; |     FSP_FILE_DESC *FileDesc = FileObject->FsContext2; | ||||||
|     BOOLEAN DeletePending, SingleOpen; |     BOOLEAN DeletePending, SingleHandle; | ||||||
|  |  | ||||||
|     FspFsvolDeviceLockContextTable(FsvolDeviceObject); |     FspFsvolDeviceLockContextTable(FsvolDeviceObject); | ||||||
|  |  | ||||||
| @@ -415,40 +424,91 @@ VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, | |||||||
|     DeletePending = 0 != FileNode->DeletePending; |     DeletePending = 0 != FileNode->DeletePending; | ||||||
|     MemoryBarrier(); |     MemoryBarrier(); | ||||||
|  |  | ||||||
|     SingleOpen = 1 == FileNode->OpenCount; |     SingleHandle = 1 == FileNode->HandleCount; | ||||||
|  |  | ||||||
|     FspFsvolDeviceUnlockContextTable(FsvolDeviceObject); |     FspFsvolDeviceUnlockContextTable(FsvolDeviceObject); | ||||||
|  |  | ||||||
|     if (0 != PDeletePending) |     if (0 != PDeletePending) | ||||||
|         *PDeletePending = SingleOpen && DeletePending; |         *PDeletePending = SingleHandle && DeletePending; | ||||||
| } | } | ||||||
|  |  | ||||||
| VOID FspFileNodeClose(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, | VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject) | ||||||
|     PBOOLEAN PDeletedFromContextTable) |  | ||||||
| { | { | ||||||
|     /* |     /* | ||||||
|      * Close the FileNode. If the OpenCount becomes zero remove it |      * Complete the cleanup of a FileNode. Remove its share access and | ||||||
|      * from the Context table. |      * finalize its cache. | ||||||
|  |      * | ||||||
|  |      * NOTE: If the FileNode is not being deleted (!FileNode->DeletePending) | ||||||
|  |      * the FileNode REMAINS in the Context table until Close time! | ||||||
|  |      * This is so that if there are mapped views or write behind's pending | ||||||
|  |      * when a file gets reopened the FileNode will be correctly reused. | ||||||
|  |      * | ||||||
|  |      * The FileNode must be acquired exclusive (Main) when calling this function. | ||||||
|      */ |      */ | ||||||
|  |  | ||||||
|     PAGED_CODE(); |     PAGED_CODE(); | ||||||
|  |  | ||||||
|     PDEVICE_OBJECT FsvolDeviceObject = FileNode->FsvolDeviceObject; |     PDEVICE_OBJECT FsvolDeviceObject = FileNode->FsvolDeviceObject; | ||||||
|     BOOLEAN Deleted = FALSE; |     LARGE_INTEGER TruncateSize = { 0 }, *PTruncateSize = 0; | ||||||
|  |     BOOLEAN DeletePending; | ||||||
|  |     BOOLEAN DeletedFromContextTable = FALSE; | ||||||
|  |  | ||||||
|     FspFsvolDeviceLockContextTable(FsvolDeviceObject); |     FspFsvolDeviceLockContextTable(FsvolDeviceObject); | ||||||
|  |  | ||||||
|     IoRemoveShareAccess(FileObject, &FileNode->ShareAccess); |     IoRemoveShareAccess(FileObject, &FileNode->ShareAccess); | ||||||
|     if (0 == --FileNode->OpenCount) |  | ||||||
|         FspFsvolDeviceDeleteContextByName(FsvolDeviceObject, &FileNode->FileName, &Deleted); |     if (0 == --FileNode->HandleCount) | ||||||
|  |     { | ||||||
|  |         DeletePending = 0 != FileNode->DeletePending; | ||||||
|  |         MemoryBarrier(); | ||||||
|  |  | ||||||
|  |         if (DeletePending) | ||||||
|  |         { | ||||||
|  |             PTruncateSize = &TruncateSize; | ||||||
|  |  | ||||||
|  |             if (0 == --FileNode->OpenCount) | ||||||
|  |                 FspFsvolDeviceDeleteContextByName(FsvolDeviceObject, &FileNode->FileName, | ||||||
|  |                     &DeletedFromContextTable); | ||||||
|  |         } | ||||||
|  |         else if (FileNode->TruncateOnClose && FlagOn(FileObject->Flags, FO_CACHE_SUPPORTED)) | ||||||
|  |         { | ||||||
|  |             TruncateSize = FileNode->Header.FileSize; | ||||||
|  |             PTruncateSize = &TruncateSize; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     FspFsvolDeviceUnlockContextTable(FsvolDeviceObject); |     FspFsvolDeviceUnlockContextTable(FsvolDeviceObject); | ||||||
|  |  | ||||||
|     if (Deleted) |     CcUninitializeCacheMap(FileObject, PTruncateSize, 0); | ||||||
|         FspFileNodeDereference(FileNode); |  | ||||||
|  |  | ||||||
|     if (0 != PDeletedFromContextTable) |     if (DeletedFromContextTable) | ||||||
|         *PDeletedFromContextTable = Deleted; |         FspFileNodeDereference(FileNode); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | VOID FspFileNodeClose(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject) | ||||||
|  | { | ||||||
|  |     /* | ||||||
|  |      * Close the FileNode. If the OpenCount becomes zero remove it | ||||||
|  |      * from the Context table. | ||||||
|  |      * | ||||||
|  |      * The FileNode may or may not be acquired when calling this function. | ||||||
|  |      */ | ||||||
|  |  | ||||||
|  |     PAGED_CODE(); | ||||||
|  |  | ||||||
|  |     PDEVICE_OBJECT FsvolDeviceObject = FileNode->FsvolDeviceObject; | ||||||
|  |     BOOLEAN DeletedFromContextTable = FALSE; | ||||||
|  |  | ||||||
|  |     FspFsvolDeviceLockContextTable(FsvolDeviceObject); | ||||||
|  |  | ||||||
|  |     if (0 < FileNode->OpenCount && 0 == --FileNode->OpenCount) | ||||||
|  |         FspFsvolDeviceDeleteContextByName(FsvolDeviceObject, &FileNode->FileName, | ||||||
|  |             &DeletedFromContextTable); | ||||||
|  |  | ||||||
|  |     FspFsvolDeviceUnlockContextTable(FsvolDeviceObject); | ||||||
|  |  | ||||||
|  |     if (DeletedFromContextTable) | ||||||
|  |         FspFileNodeDereference(FileNode); | ||||||
| } | } | ||||||
|  |  | ||||||
| VOID FspFileNodeRename(FSP_FILE_NODE *FileNode, PUNICODE_STRING NewFileName) | VOID FspFileNodeRename(FSP_FILE_NODE *FileNode, PUNICODE_STRING NewFileName) | ||||||
| @@ -475,6 +535,29 @@ VOID FspFileNodeRename(FSP_FILE_NODE *FileNode, PUNICODE_STRING NewFileName) | |||||||
|     FspFsvolDeviceUnlockContextTable(FsvolDeviceObject); |     FspFsvolDeviceUnlockContextTable(FsvolDeviceObject); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | BOOLEAN FspFileNodeHasOpenHandles(PDEVICE_OBJECT FsvolDeviceObject, | ||||||
|  |     PUNICODE_STRING FileName, BOOLEAN SubpathOnly) | ||||||
|  | { | ||||||
|  |     /* | ||||||
|  |      * The ContextByNameTable must be already locked. | ||||||
|  |      */ | ||||||
|  |  | ||||||
|  |     PAGED_CODE(); | ||||||
|  |  | ||||||
|  |     FSP_FILE_NODE *FileNode; | ||||||
|  |     PVOID RestartKey = 0; | ||||||
|  |  | ||||||
|  |     for (;;) | ||||||
|  |     { | ||||||
|  |         FileNode = FspFsvolDeviceEnumerateContextByName(FsvolDeviceObject, FileName, SubpathOnly, | ||||||
|  |             &RestartKey); | ||||||
|  |         if (0 == FileNode) | ||||||
|  |             return FALSE; | ||||||
|  |         if (0 < FileNode->HandleCount) | ||||||
|  |             return TRUE; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
| VOID FspFileNodeGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileInfo) | VOID FspFileNodeGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileInfo) | ||||||
| { | { | ||||||
|     PAGED_CODE(); |     PAGED_CODE(); | ||||||
|   | |||||||
| @@ -879,10 +879,10 @@ static NTSTATUS FspFsvolSetRenameInformation( | |||||||
|  |  | ||||||
|     Result = STATUS_SUCCESS; |     Result = STATUS_SUCCESS; | ||||||
|     FspFsvolDeviceLockContextTable(FsvolDeviceObject); |     FspFsvolDeviceLockContextTable(FsvolDeviceObject); | ||||||
|     if (1 < FileNode->OpenCount || |     if (1 < FileNode->HandleCount || | ||||||
|         (FileNode->IsDirectory && |         (FileNode->IsDirectory && | ||||||
|             0 != FspFsvolDeviceLookupDescendantContextByName(FsvolDeviceObject, &FileNode->FileName, TRUE)) || |             FspFileNodeHasOpenHandles(FsvolDeviceObject, &FileNode->FileName, TRUE)) || | ||||||
|         0 != FspFsvolDeviceLookupDescendantContextByName(FsvolDeviceObject, &NewFileName, FALSE)) |         FspFileNodeHasOpenHandles(FsvolDeviceObject, &NewFileName, FALSE)) | ||||||
|         Result = STATUS_ACCESS_DENIED; |         Result = STATUS_ACCESS_DENIED; | ||||||
|     FspFsvolDeviceUnlockContextTable(FsvolDeviceObject); |     FspFsvolDeviceUnlockContextTable(FsvolDeviceObject); | ||||||
|     if (!NT_SUCCESS(Result)) |     if (!NT_SUCCESS(Result)) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user