sys: ContextByName

This commit is contained in:
Bill Zissimopoulos 2016-02-06 11:14:27 -08:00
parent 650d4c4d18
commit 3ef9042071
3 changed files with 173 additions and 14 deletions

View File

@ -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();

View File

@ -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

View File

@ -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)