From 3ef90420714255173d3becdc3cdc4fe1d70c3e27 Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Sat, 6 Feb 2016 11:14:27 -0800 Subject: [PATCH] sys: ContextByName --- src/sys/device.c | 158 ++++++++++++++++++++++++++++++++++++++++++++--- src/sys/driver.h | 27 +++++++- src/sys/file.c | 2 +- 3 files changed, 173 insertions(+), 14 deletions(-) diff --git a/src/sys/device.c b/src/sys/device.c index 211bb43e..9cda6a30 100644 --- a/src/sys/device.c +++ b/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(); diff --git a/src/sys/driver.h b/src/sys/driver.h index f2a3076a..02b7504a 100644 --- a/src/sys/driver.h +++ b/src/sys/driver.h @@ -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 diff --git a/src/sys/file.c b/src/sys/file.c index 9c75e7e6..f7a61a50 100644 --- a/src/sys/file.c +++ b/src/sys/file.c @@ -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)