mirror of
				https://github.com/winfsp/winfsp.git
				synced 2025-10-30 19:48:38 -05:00 
			
		
		
		
	sys: FspFileNodeCleanup:
- Handle the scenario where there are cleaned up, but unclosed streams in the context table.
This commit is contained in:
		
							
								
								
									
										156
									
								
								src/sys/file.c
									
									
									
									
									
								
							
							
						
						
									
										156
									
								
								src/sys/file.c
									
									
									
									
									
								
							| @@ -166,6 +166,65 @@ VOID FspFileNodeOplockComplete(PVOID Context, PIRP Irp); | |||||||
|     if (IrpValid)                       \ |     if (IrpValid)                       \ | ||||||
|         FspIrpSetFlags(Irp, FspIrpFlags(Irp) & (~Flags & 3)) |         FspIrpSetFlags(Irp, FspIrpFlags(Irp) & (~Flags & 3)) | ||||||
|  |  | ||||||
|  | #define GATHER_DESCENDANTS(FILENAME, REFERENCE, ...)\ | ||||||
|  |     FSP_FILE_NODE *DescendantFileNode;\ | ||||||
|  |     FSP_FILE_NODE *DescendantFileNodeArray[16], **DescendantFileNodes;\ | ||||||
|  |     ULONG DescendantFileNodeCount, DescendantFileNodeIndex;\ | ||||||
|  |     FSP_DEVICE_CONTEXT_BY_NAME_TABLE_RESTART_KEY RestartKey;\ | ||||||
|  |     DescendantFileNodes = DescendantFileNodeArray;\ | ||||||
|  |     DescendantFileNodeCount = 0;\ | ||||||
|  |     memset(&RestartKey, 0, sizeof RestartKey);\ | ||||||
|  |     for (;;)                            \ | ||||||
|  |     {                                   \ | ||||||
|  |         DescendantFileNode = FspFsvolDeviceEnumerateContextByName(FsvolDeviceObject,\ | ||||||
|  |             FILENAME, FALSE, &RestartKey);\ | ||||||
|  |         if (0 == DescendantFileNode)    \ | ||||||
|  |             break;                      \ | ||||||
|  |         ASSERT(0 == ((UINT_PTR)DescendantFileNode & 7));\ | ||||||
|  |         __VA_ARGS__;                    \ | ||||||
|  |         if (REFERENCE)                  \ | ||||||
|  |             FspFileNodeReference((PVOID)((UINT_PTR)DescendantFileNode & ~7));\ | ||||||
|  |         if (ARRAYSIZE(DescendantFileNodeArray) > DescendantFileNodeCount)\ | ||||||
|  |             DescendantFileNodes[DescendantFileNodeCount] = DescendantFileNode;\ | ||||||
|  |         DescendantFileNodeCount++;      \ | ||||||
|  |     }                                   \ | ||||||
|  |     if (ARRAYSIZE(DescendantFileNodeArray) < DescendantFileNodeCount ||\ | ||||||
|  |         DEBUGTEST_EX(0 != DescendantFileNodeCount, 10, FALSE))  \ | ||||||
|  |     {                                   \ | ||||||
|  |         DescendantFileNodes = FspAllocMustSucceed(DescendantFileNodeCount * sizeof(FSP_FILE_NODE *));\ | ||||||
|  |         DescendantFileNodeIndex = 0;    \ | ||||||
|  |         memset(&RestartKey, 0, sizeof RestartKey);\ | ||||||
|  |         for (;;)                        \ | ||||||
|  |         {                               \ | ||||||
|  |             DescendantFileNode = FspFsvolDeviceEnumerateContextByName(FsvolDeviceObject,\ | ||||||
|  |                 FILENAME, FALSE, &RestartKey);\ | ||||||
|  |             if (0 == DescendantFileNode)\ | ||||||
|  |                 break;                  \ | ||||||
|  |             ASSERT(0 == ((UINT_PTR)DescendantFileNode & 7));\ | ||||||
|  |             __VA_ARGS__;                \ | ||||||
|  |             DescendantFileNodes[DescendantFileNodeIndex] = DescendantFileNode;\ | ||||||
|  |             DescendantFileNodeIndex++;  \ | ||||||
|  |             ASSERT(DescendantFileNodeCount >= DescendantFileNodeIndex);\ | ||||||
|  |         }                               \ | ||||||
|  |         ASSERT(DescendantFileNodeCount == DescendantFileNodeIndex);\ | ||||||
|  |     }                                   \ | ||||||
|  |     ((VOID)0) | ||||||
|  | #define SCATTER_DESCENDANTS(REFERENCE)  \ | ||||||
|  |     if (REFERENCE)                      \ | ||||||
|  |     {                                   \ | ||||||
|  |         for (                           \ | ||||||
|  |             DescendantFileNodeIndex = 0;\ | ||||||
|  |             DescendantFileNodeCount > DescendantFileNodeIndex;\ | ||||||
|  |             DescendantFileNodeIndex++)  \ | ||||||
|  |         {                               \ | ||||||
|  |             DescendantFileNode = DescendantFileNodes[DescendantFileNodeIndex];\ | ||||||
|  |             FspFileNodeDereference((PVOID)((UINT_PTR)DescendantFileNode & ~7));\ | ||||||
|  |         }                               \ | ||||||
|  |     }                                   \ | ||||||
|  |     if (DescendantFileNodeArray != DescendantFileNodes)\ | ||||||
|  |         FspFree(DescendantFileNodes);   \ | ||||||
|  |     ((VOID)0) | ||||||
|  |  | ||||||
| NTSTATUS FspFileNodeCopyList(PDEVICE_OBJECT DeviceObject, | NTSTATUS FspFileNodeCopyList(PDEVICE_OBJECT DeviceObject, | ||||||
|     FSP_FILE_NODE ***PFileNodes, PULONG PFileNodeCount) |     FSP_FILE_NODE ***PFileNodes, PULONG PFileNodeCount) | ||||||
| { | { | ||||||
| @@ -728,6 +787,44 @@ VOID FspFileNodeCleanupComplete(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject | |||||||
|  |  | ||||||
|             FileNode->OpenCount = 0; |             FileNode->OpenCount = 0; | ||||||
|             FileNode->Header.FileSize.QuadPart = 0; |             FileNode->Header.FileSize.QuadPart = 0; | ||||||
|  |  | ||||||
|  |             /* | ||||||
|  |              * We now have to deal with the scenario where there are cleaned up, | ||||||
|  |              * but unclosed streams for this file still in the context table. | ||||||
|  |              */ | ||||||
|  |             if (FspFsvolDeviceExtension(FsvolDeviceObject)->VolumeParams.NamedStreams && | ||||||
|  |                 0 == FileNode->MainFileNode) | ||||||
|  |             { | ||||||
|  |                 BOOLEAN StreamDeletedFromContextTable; | ||||||
|  |                 USHORT FileNameLength = FileNode->FileName.Length; | ||||||
|  |  | ||||||
|  |                 GATHER_DESCENDANTS(&FileNode->FileName, FALSE, | ||||||
|  |                     if (DescendantFileNode->FileName.Length > FileNameLength && | ||||||
|  |                         L'\\' == DescendantFileNode->FileName.Buffer[FileNameLength / sizeof(WCHAR)]) | ||||||
|  |                         break; | ||||||
|  |                     ASSERT(FileNode != DescendantFileNode); | ||||||
|  |                     ASSERT(0 != DescendantFileNode->OpenCount); | ||||||
|  |                     ASSERT(0 == DescendantFileNode->HandleCount); | ||||||
|  |                     ); | ||||||
|  |  | ||||||
|  |                 for ( | ||||||
|  |                     DescendantFileNodeIndex = 0; | ||||||
|  |                     DescendantFileNodeCount > DescendantFileNodeIndex; | ||||||
|  |                     DescendantFileNodeIndex++) | ||||||
|  |                 { | ||||||
|  |                     DescendantFileNode = DescendantFileNodes[DescendantFileNodeIndex]; | ||||||
|  |  | ||||||
|  |                     FspFsvolDeviceDeleteContextByName(FsvolDeviceObject, &DescendantFileNode->FileName, | ||||||
|  |                         &StreamDeletedFromContextTable); | ||||||
|  |                     if (StreamDeletedFromContextTable) | ||||||
|  |                     { | ||||||
|  |                         DescendantFileNode->OpenCount = 0; | ||||||
|  |                         FspFileNodeDereference(DescendantFileNode); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 SCATTER_DESCENDANTS(FALSE); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if (DeletePending || FileNode->TruncateOnClose) |         if (DeletePending || FileNode->TruncateOnClose) | ||||||
| @@ -872,65 +969,6 @@ NTSTATUS FspFileNodeFlushAndPurgeCache(FSP_FILE_NODE *FileNode, | |||||||
|     return IoStatus.Status; |     return IoStatus.Status; | ||||||
| } | } | ||||||
|  |  | ||||||
| #define GATHER_DESCENDANTS(FILENAME, REFERENCE, ...)\ |  | ||||||
|     FSP_FILE_NODE *DescendantFileNode;\ |  | ||||||
|     FSP_FILE_NODE *DescendantFileNodeArray[16], **DescendantFileNodes;\ |  | ||||||
|     ULONG DescendantFileNodeCount, DescendantFileNodeIndex;\ |  | ||||||
|     FSP_DEVICE_CONTEXT_BY_NAME_TABLE_RESTART_KEY RestartKey;\ |  | ||||||
|     DescendantFileNodes = DescendantFileNodeArray;\ |  | ||||||
|     DescendantFileNodeCount = 0;\ |  | ||||||
|     memset(&RestartKey, 0, sizeof RestartKey);\ |  | ||||||
|     for (;;)                            \ |  | ||||||
|     {                                   \ |  | ||||||
|         DescendantFileNode = FspFsvolDeviceEnumerateContextByName(FsvolDeviceObject,\ |  | ||||||
|             FILENAME, FALSE, &RestartKey);\ |  | ||||||
|         if (0 == DescendantFileNode)    \ |  | ||||||
|             break;                      \ |  | ||||||
|         ASSERT(0 == ((UINT_PTR)DescendantFileNode & 7));\ |  | ||||||
|         __VA_ARGS__;                    \ |  | ||||||
|         if (REFERENCE)                  \ |  | ||||||
|             FspFileNodeReference((PVOID)((UINT_PTR)DescendantFileNode & ~7));\ |  | ||||||
|         if (ARRAYSIZE(DescendantFileNodeArray) > DescendantFileNodeCount)\ |  | ||||||
|             DescendantFileNodes[DescendantFileNodeCount] = DescendantFileNode;\ |  | ||||||
|         DescendantFileNodeCount++;      \ |  | ||||||
|     }                                   \ |  | ||||||
|     if (ARRAYSIZE(DescendantFileNodeArray) < DescendantFileNodeCount ||\ |  | ||||||
|         DEBUGTEST_EX(0 != DescendantFileNodeCount, 10, FALSE))  \ |  | ||||||
|     {                                   \ |  | ||||||
|         DescendantFileNodes = FspAllocMustSucceed(DescendantFileNodeCount * sizeof(FSP_FILE_NODE *));\ |  | ||||||
|         DescendantFileNodeIndex = 0;    \ |  | ||||||
|         memset(&RestartKey, 0, sizeof RestartKey);\ |  | ||||||
|         for (;;)                        \ |  | ||||||
|         {                               \ |  | ||||||
|             DescendantFileNode = FspFsvolDeviceEnumerateContextByName(FsvolDeviceObject,\ |  | ||||||
|                 FILENAME, FALSE, &RestartKey);\ |  | ||||||
|             if (0 == DescendantFileNode)\ |  | ||||||
|                 break;                  \ |  | ||||||
|             ASSERT(0 == ((UINT_PTR)DescendantFileNode & 7));\ |  | ||||||
|             __VA_ARGS__;                \ |  | ||||||
|             DescendantFileNodes[DescendantFileNodeIndex] = DescendantFileNode;\ |  | ||||||
|             DescendantFileNodeIndex++;  \ |  | ||||||
|             ASSERT(DescendantFileNodeCount >= DescendantFileNodeIndex);\ |  | ||||||
|         }                               \ |  | ||||||
|         ASSERT(DescendantFileNodeCount == DescendantFileNodeIndex);\ |  | ||||||
|     }                                   \ |  | ||||||
|     ((VOID)0) |  | ||||||
| #define SCATTER_DESCENDANTS(REFERENCE)  \ |  | ||||||
|     if (REFERENCE)                      \ |  | ||||||
|     {                                   \ |  | ||||||
|         for (                           \ |  | ||||||
|             DescendantFileNodeIndex = 0;\ |  | ||||||
|             DescendantFileNodeCount > DescendantFileNodeIndex;\ |  | ||||||
|             DescendantFileNodeIndex++)  \ |  | ||||||
|         {                               \ |  | ||||||
|             DescendantFileNode = DescendantFileNodes[DescendantFileNodeIndex];\ |  | ||||||
|             FspFileNodeDereference((PVOID)((UINT_PTR)DescendantFileNode & ~7));\ |  | ||||||
|         }                               \ |  | ||||||
|     }                                   \ |  | ||||||
|     if (DescendantFileNodeArray != DescendantFileNodes)\ |  | ||||||
|         FspFree(DescendantFileNodes);   \ |  | ||||||
|     ((VOID)0) |  | ||||||
|  |  | ||||||
| VOID FspFileNodeOverwriteStreams(FSP_FILE_NODE *FileNode) | VOID FspFileNodeOverwriteStreams(FSP_FILE_NODE *FileNode) | ||||||
| { | { | ||||||
|     /* |     /* | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user