mirror of
				https://github.com/winfsp/winfsp.git
				synced 2025-10-30 19:48:38 -05:00 
			
		
		
		
	sys: ContextByName
This commit is contained in:
		
							
								
								
									
										158
									
								
								src/sys/device.c
									
									
									
									
									
								
							
							
						
						
									
										158
									
								
								src/sys/device.c
									
									
									
									
									
								
							| @@ -35,6 +35,15 @@ VOID FspFsvolDeviceDeleteContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier, | ||||
| static RTL_AVL_COMPARE_ROUTINE FspFsvolDeviceCompareContext; | ||||
| static RTL_AVL_ALLOCATE_ROUTINE FspFsvolDeviceAllocateContext; | ||||
| static RTL_AVL_FREE_ROUTINE FspFsvolDeviceFreeContext; | ||||
| PVOID FspFsvolDeviceLookupContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING FileName); | ||||
| PVOID FspFsvolDeviceLookupChildContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING FileName); | ||||
| PVOID FspFsvolDeviceInsertContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING FileName, PVOID Context, | ||||
|     FSP_DEVICE_CONTEXT_BY_NAME_TABLE_ELEMENT *ElementStorage, PBOOLEAN PInserted); | ||||
| VOID FspFsvolDeviceDeleteContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING FileName, | ||||
|     PBOOLEAN PDeleted); | ||||
| static RTL_AVL_COMPARE_ROUTINE FspFsvolDeviceCompareContextByName; | ||||
| static RTL_AVL_ALLOCATE_ROUTINE FspFsvolDeviceAllocateContextByName; | ||||
| static RTL_AVL_FREE_ROUTINE FspFsvolDeviceFreeContextByName; | ||||
| VOID FspFsvolGetVolumeInfo(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_VOLUME_INFO *VolumeInfo); | ||||
| BOOLEAN FspFsvolTryGetVolumeInfo(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_VOLUME_INFO *VolumeInfo); | ||||
| VOID FspFsvolSetVolumeInfo(PDEVICE_OBJECT DeviceObject, const FSP_FSCTL_VOLUME_INFO *VolumeInfo); | ||||
| @@ -59,6 +68,13 @@ VOID FspDeviceDeleteAll(VOID); | ||||
| #pragma alloc_text(PAGE, FspFsvolDeviceCompareContext) | ||||
| #pragma alloc_text(PAGE, FspFsvolDeviceAllocateContext) | ||||
| #pragma alloc_text(PAGE, FspFsvolDeviceFreeContext) | ||||
| #pragma alloc_text(PAGE, FspFsvolDeviceLookupContextByName) | ||||
| #pragma alloc_text(PAGE, FspFsvolDeviceLookupChildContextByName) | ||||
| #pragma alloc_text(PAGE, FspFsvolDeviceInsertContextByName) | ||||
| #pragma alloc_text(PAGE, FspFsvolDeviceDeleteContextByName) | ||||
| #pragma alloc_text(PAGE, FspFsvolDeviceCompareContextByName) | ||||
| #pragma alloc_text(PAGE, FspFsvolDeviceAllocateContextByName) | ||||
| #pragma alloc_text(PAGE, FspFsvolDeviceFreeContextByName) | ||||
| #pragma alloc_text(PAGE, FspDeviceCopyList) | ||||
| #pragma alloc_text(PAGE, FspDeviceDeleteList) | ||||
| #pragma alloc_text(PAGE, FspDeviceDeleteAll) | ||||
| @@ -293,10 +309,19 @@ static NTSTATUS FspFsvolDeviceInit(PDEVICE_OBJECT DeviceObject) | ||||
|         return Result; | ||||
|     FsvolDeviceExtension->InitDoneIoq = 1; | ||||
|  | ||||
|     /* initialize our generic table */ | ||||
|     /* initialize our context table */ | ||||
|     ExInitializeResourceLite(&FsvolDeviceExtension->FileRenameResource); | ||||
|     ExInitializeResourceLite(&FsvolDeviceExtension->ContextTableResource); | ||||
|     RtlInitializeGenericTableAvl(&FsvolDeviceExtension->ContextTable, | ||||
|         FspFsvolDeviceCompareContext, FspFsvolDeviceAllocateContext, FspFsvolDeviceFreeContext, 0); | ||||
|         FspFsvolDeviceCompareContext, | ||||
|         FspFsvolDeviceAllocateContext, | ||||
|         FspFsvolDeviceFreeContext, | ||||
|         0); | ||||
|     RtlInitializeGenericTableAvl(&FsvolDeviceExtension->ContextByNameTable, | ||||
|         FspFsvolDeviceCompareContextByName, | ||||
|         FspFsvolDeviceAllocateContextByName, | ||||
|         FspFsvolDeviceFreeContextByName, | ||||
|         0); | ||||
|     FsvolDeviceExtension->InitDoneCtxTab = 1; | ||||
|  | ||||
|     /* initialize our timer routine and start our expiration timer */ | ||||
| @@ -339,17 +364,13 @@ static VOID FspFsvolDeviceFini(PDEVICE_OBJECT DeviceObject) | ||||
|  | ||||
|     if (FsvolDeviceExtension->InitDoneCtxTab) | ||||
|     { | ||||
| #if 0 | ||||
|         /* FspDeviceFreeElement is now a no-op, so this is no longer necessary */ | ||||
|         /* | ||||
|          * Enumerate and delete all entries in the ContextTable. | ||||
|          * There is no need to protect accesses to the table as we are in the device destructor. | ||||
|          * FspDeviceFreeContext/FspDeviceFreeContextByName is a no-op, so it is not necessary | ||||
|          * to enumerate and delete all entries in the ContextTable. | ||||
|          */ | ||||
|         FSP_DEVICE_GENERIC_TABLE_ELEMENT_DATA *Element; | ||||
|         while (0 != (Element = RtlGetElementGenericTableAvl(&FsvolDeviceExtension->ContextTable, 0))) | ||||
|             RtlDeleteElementGenericTableAvl(&FsvolDeviceExtension->ContextTable, &Element->Identifier); | ||||
| #endif | ||||
|  | ||||
|         ExDeleteResourceLite(&FsvolDeviceExtension->ContextTableResource); | ||||
|         ExDeleteResourceLite(&FsvolDeviceExtension->FileRenameResource); | ||||
|     } | ||||
|  | ||||
|     /* finalize our delete lock */ | ||||
| @@ -516,6 +537,123 @@ static VOID NTAPI FspFsvolDeviceFreeContext( | ||||
|     PAGED_CODE(); | ||||
| } | ||||
|  | ||||
| PVOID FspFsvolDeviceLookupContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING FileName) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject); | ||||
|     FSP_DEVICE_CONTEXT_BY_NAME_TABLE_ELEMENT_DATA *Result; | ||||
|  | ||||
|     Result = RtlLookupElementGenericTableAvl(&FsvolDeviceExtension->ContextByNameTable, &FileName); | ||||
|  | ||||
|     return 0 != Result ? Result->Context : 0; | ||||
| } | ||||
|  | ||||
| PVOID FspFsvolDeviceLookupChildContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING FileName) | ||||
| { | ||||
|     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; | ||||
|  | ||||
|     Result = RtlLookupFirstMatchingElementGenericTableAvl(&FsvolDeviceExtension->ContextByNameTable, | ||||
|         &FileName, &RestartKey); | ||||
|     if (0 == Result) | ||||
|         return 0; | ||||
|  | ||||
|     Result = RtlEnumerateGenericTableWithoutSplayingAvl(&FsvolDeviceExtension->ContextByNameTable, | ||||
|         &RestartKey); | ||||
|     if (0 == Result) | ||||
|         return 0; | ||||
|  | ||||
|     if (RtlPrefixUnicodeString(FileName, Result->FileName, CaseInsensitive) && | ||||
|         FileName->Length < Result->FileName->Length && | ||||
|         '\\' == Result->FileName->Buffer[FileName->Length / sizeof(WCHAR)]) | ||||
|         return Result->Context; | ||||
|     else | ||||
|         return 0; | ||||
| } | ||||
|  | ||||
| PVOID FspFsvolDeviceInsertContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING FileName, PVOID Context, | ||||
|     FSP_DEVICE_CONTEXT_BY_NAME_TABLE_ELEMENT *ElementStorage, PBOOLEAN PInserted) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject); | ||||
|     FSP_DEVICE_CONTEXT_BY_NAME_TABLE_ELEMENT_DATA *Result, Element = { 0 }; | ||||
|  | ||||
|     ASSERT(0 != ElementStorage); | ||||
|     Element.FileName = FileName; | ||||
|     Element.Context = Context; | ||||
|  | ||||
|     FsvolDeviceExtension->ContextByNameTableElementStorage = ElementStorage; | ||||
|     Result = RtlInsertElementGenericTableAvl(&FsvolDeviceExtension->ContextByNameTable, | ||||
|         &Element, sizeof Element, PInserted); | ||||
|     FsvolDeviceExtension->ContextByNameTableElementStorage = 0; | ||||
|  | ||||
|     ASSERT(0 != Result); | ||||
|  | ||||
|     return Result->Context; | ||||
| } | ||||
|  | ||||
| VOID FspFsvolDeviceDeleteContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING FileName, | ||||
|     PBOOLEAN PDeleted) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject); | ||||
|     BOOLEAN Deleted; | ||||
|  | ||||
|     Deleted = RtlDeleteElementGenericTableAvl(&FsvolDeviceExtension->ContextByNameTable, &FileName); | ||||
|  | ||||
|     if (0 != PDeleted) | ||||
|         *PDeleted = Deleted; | ||||
| } | ||||
|  | ||||
| static RTL_GENERIC_COMPARE_RESULTS NTAPI FspFsvolDeviceCompareContextByName( | ||||
|     PRTL_AVL_TABLE Table, PVOID FirstElement, PVOID SecondElement) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = | ||||
|         CONTAINING_RECORD(Table, FSP_FSVOL_DEVICE_EXTENSION, ContextByNameTable); | ||||
|     BOOLEAN CaseInsensitive = 0 == FsvolDeviceExtension->VolumeParams.CaseSensitiveSearch; | ||||
|     PUNICODE_STRING FirstFileName = *(PUNICODE_STRING *)FirstElement; | ||||
|     PUNICODE_STRING SecondFileName = *(PUNICODE_STRING *)SecondElement; | ||||
|     LONG ComparisonResult; | ||||
|  | ||||
|     ComparisonResult = RtlCompareUnicodeString(FirstFileName, SecondFileName, CaseInsensitive); | ||||
|  | ||||
|     if (0 > ComparisonResult) | ||||
|         return GenericLessThan; | ||||
|     else | ||||
|     if (0 < ComparisonResult) | ||||
|         return GenericGreaterThan; | ||||
|     else | ||||
|         return GenericEqual; | ||||
| } | ||||
|  | ||||
| static PVOID NTAPI FspFsvolDeviceAllocateContextByName( | ||||
|     PRTL_AVL_TABLE Table, CLONG ByteSize) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = | ||||
|         CONTAINING_RECORD(Table, FSP_FSVOL_DEVICE_EXTENSION, ContextByNameTable); | ||||
|  | ||||
|     ASSERT(sizeof(FSP_DEVICE_CONTEXT_BY_NAME_TABLE_ELEMENT) == ByteSize); | ||||
|  | ||||
|     return FsvolDeviceExtension->ContextByNameTableElementStorage; | ||||
| } | ||||
|  | ||||
| static VOID NTAPI FspFsvolDeviceFreeContextByName( | ||||
|     PRTL_AVL_TABLE Table, PVOID Buffer) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
| } | ||||
|  | ||||
| VOID FspFsvolGetVolumeInfo(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_VOLUME_INFO *VolumeInfo) | ||||
| { | ||||
|     // !PAGED_CODE(); | ||||
|   | ||||
| @@ -449,6 +449,16 @@ typedef struct | ||||
|     RTL_BALANCED_LINKS Header; | ||||
|     FSP_DEVICE_CONTEXT_TABLE_ELEMENT_DATA Data; | ||||
| } FSP_DEVICE_CONTEXT_TABLE_ELEMENT; | ||||
| typedef struct | ||||
| { | ||||
|     PUNICODE_STRING FileName; | ||||
|     PVOID Context; | ||||
| } FSP_DEVICE_CONTEXT_BY_NAME_TABLE_ELEMENT_DATA; | ||||
| typedef struct | ||||
| { | ||||
|     RTL_BALANCED_LINKS Header; | ||||
|     FSP_DEVICE_CONTEXT_BY_NAME_TABLE_ELEMENT_DATA Data; | ||||
| } FSP_DEVICE_CONTEXT_BY_NAME_TABLE_ELEMENT; | ||||
| enum | ||||
| { | ||||
|     FspFsctlDeviceExtensionKind = '\0ltC',  /* file system control device (e.g. \Device\WinFsp.Disk) */ | ||||
| @@ -478,9 +488,12 @@ typedef struct | ||||
|     KSPIN_LOCK ExpirationLock; | ||||
|     WORK_QUEUE_ITEM ExpirationWorkItem; | ||||
|     BOOLEAN ExpirationInProgress; | ||||
|     ERESOURCE FileRenameResource; | ||||
|     ERESOURCE ContextTableResource; | ||||
|     RTL_AVL_TABLE ContextTable; | ||||
|     PVOID ContextTableElementStorage; | ||||
|     RTL_AVL_TABLE ContextByNameTable; | ||||
|     PVOID ContextByNameTableElementStorage; | ||||
|     UNICODE_STRING VolumeName; | ||||
|     WCHAR VolumeNameBuf[FSP_DEVICE_VOLUME_NAME_LENMAX / sizeof(WCHAR)]; | ||||
|     KSPIN_LOCK InfoSpinLock; | ||||
| @@ -516,6 +529,12 @@ PVOID FspFsvolDeviceInsertContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier | ||||
|     FSP_DEVICE_CONTEXT_TABLE_ELEMENT *ElementStorage, PBOOLEAN PInserted); | ||||
| VOID FspFsvolDeviceDeleteContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier, | ||||
|     PBOOLEAN PDeleted); | ||||
| PVOID FspFsvolDeviceLookupContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING FileName); | ||||
| PVOID FspFsvolDeviceLookupChildContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING FileName); | ||||
| PVOID FspFsvolDeviceInsertContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING FileName, PVOID Context, | ||||
|     FSP_DEVICE_CONTEXT_BY_NAME_TABLE_ELEMENT *ElementStorage, PBOOLEAN PInserted); | ||||
| VOID FspFsvolDeviceDeleteContextByName(PDEVICE_OBJECT DeviceObject, PUNICODE_STRING FileName, | ||||
|     PBOOLEAN PDeleted); | ||||
| VOID FspFsvolGetVolumeInfo(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_VOLUME_INFO *VolumeInfo); | ||||
| BOOLEAN FspFsvolTryGetVolumeInfo(PDEVICE_OBJECT DeviceObject, FSP_FSCTL_VOLUME_INFO *VolumeInfo); | ||||
| VOID FspFsvolSetVolumeInfo(PDEVICE_OBJECT DeviceObject, const FSP_FSCTL_VOLUME_INFO *VolumeInfo); | ||||
| @@ -570,9 +589,13 @@ typedef struct | ||||
|     /* interlocked access */ | ||||
|     LONG RefCount; | ||||
|     UINT32 DeletePending; | ||||
|     /* locked access (ContextTable lock) */ | ||||
|     /* locked under FSP_FSVOL_DEVICE_EXTENSION::ContextTableResource */ | ||||
|     LONG OpenCount; | ||||
|     SHARE_ACCESS ShareAccess; | ||||
|     FSP_DEVICE_CONTEXT_TABLE_ELEMENT ContextElementStorage; | ||||
|     FSP_DEVICE_CONTEXT_BY_NAME_TABLE_ELEMENT ContextByNameElementStorage; | ||||
|     /* locked under FSP_FSVOL_DEVICE_EXTENSION::FileRenameResource */ | ||||
|     UNICODE_STRING FileName; | ||||
|     /* locked under Header.Resource */ | ||||
|     UINT64 InfoExpirationTime; | ||||
|     UINT32 FileAttributes; | ||||
| @@ -588,8 +611,6 @@ typedef struct | ||||
|     UINT64 UserContext; | ||||
|     UINT64 IndexNumber; | ||||
|     BOOLEAN IsDirectory; | ||||
|     FSP_DEVICE_CONTEXT_TABLE_ELEMENT ElementStorage; | ||||
|     UNICODE_STRING FileName; | ||||
|     WCHAR FileNameBuf[]; | ||||
| } FSP_FILE_NODE; | ||||
| typedef struct | ||||
|   | ||||
| @@ -249,7 +249,7 @@ FSP_FILE_NODE *FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, | ||||
|     FspFsvolDeviceLockContextTable(FsvolDeviceObject); | ||||
|  | ||||
|     OpenedFileNode = FspFsvolDeviceInsertContext(FsvolDeviceObject, | ||||
|         FileNode->UserContext, FileNode, &FileNode->ElementStorage, &Inserted); | ||||
|         FileNode->UserContext, FileNode, &FileNode->ContextElementStorage, &Inserted); | ||||
|     ASSERT(0 != OpenedFileNode); | ||||
|  | ||||
|     if (Inserted) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user