diff --git a/src/sys/device.c b/src/sys/device.c index 7f332c8a..dfcc5161 100644 --- a/src/sys/device.c +++ b/src/sys/device.c @@ -24,6 +24,13 @@ BOOLEAN FspDeviceRetain(PDEVICE_OBJECT DeviceObject); VOID FspDeviceRelease(PDEVICE_OBJECT DeviceObject); VOID FspFsctlDeviceVolumeCreated(PDEVICE_OBJECT DeviceObject); VOID FspFsctlDeviceVolumeDeleted(PDEVICE_OBJECT DeviceObject); +NTSTATUS FspFsvolDeviceInsertContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier, PVOID Context, + PBOOLEAN PInserted); +VOID FspFsvolDeviceDeleteContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier, + PBOOLEAN PDeleted); +static RTL_AVL_COMPARE_ROUTINE FspFsvolDeviceCompareElement; +static RTL_AVL_ALLOCATE_ROUTINE FspFsvolDeviceAllocateElement; +static RTL_AVL_FREE_ROUTINE FspFsvolDeviceFreeElement; NTSTATUS FspDeviceCopyList( PDEVICE_OBJECT **PDeviceObjects, PULONG PDeviceObjectCount); VOID FspDeviceDeleteList( @@ -39,7 +46,7 @@ VOID FspDeviceDeleteAll(VOID); #pragma alloc_text(PAGE, FspFsvrtDeviceInit) #pragma alloc_text(PAGE, FspFsvrtDeviceFini) #pragma alloc_text(PAGE, FspFsvolDeviceInit) -#pragma alloc_text(PAGE, FspFsvolDeviceFini) +//! #pragma alloc_text(PAGE, FspFsvolDeviceFini) #pragma alloc_text(PAGE, FspFsctlDeviceVolumeCreated) #pragma alloc_text(PAGE, FspFsctlDeviceVolumeDeleted) #pragma alloc_text(PAGE, FspDeviceCopyList) @@ -47,6 +54,12 @@ VOID FspDeviceDeleteAll(VOID); #pragma alloc_text(PAGE, FspDeviceDeleteAll) #endif +typedef struct +{ + UINT64 Identifier; + PVOID Context; +} FSP_DEVICE_GENERIC_TABLE_ELEMENT; + NTSTATUS FspDeviceCreateSecure(UINT32 Kind, ULONG ExtraSize, PUNICODE_STRING DeviceName, DEVICE_TYPE DeviceType, PUNICODE_STRING DeviceSddl, LPCGUID DeviceClassGuid, @@ -198,15 +211,29 @@ static NTSTATUS FspFsvolDeviceInit(PDEVICE_OBJECT DeviceObject) { PAGED_CODE(); + FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject); + + ExInitializeFastMutex(&FsvolDeviceExtension->GenericTableFastMutex); + RtlInitializeGenericTableAvl(&FsvolDeviceExtension->GenericTable, 0, 0, 0, 0); + return STATUS_SUCCESS; } static VOID FspFsvolDeviceFini(PDEVICE_OBJECT DeviceObject) { - PAGED_CODE(); + // !PAGED_CODE(); /* because of fast mutex use in GenericTable */ FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject); + /* + * Enumerate and delete all entries in the GenericTable. + */ + ExAcquireFastMutex(&FsvolDeviceExtension->GenericTableFastMutex); + FSP_DEVICE_GENERIC_TABLE_ELEMENT *Element; + while (0 != (Element = RtlGetElementGenericTableAvl(&FsvolDeviceExtension->GenericTable, 0))) + RtlDeleteElementGenericTableAvl(&FsvolDeviceExtension->GenericTable, &Element->Identifier); + ExReleaseFastMutex(&FsvolDeviceExtension->GenericTableFastMutex); + /* * Dereference the virtual volume device so that it can now go away. */ @@ -277,6 +304,75 @@ VOID FspFsctlDeviceVolumeDeleted(PDEVICE_OBJECT DeviceObject) IoUnregisterFileSystem(DeviceObject); } +NTSTATUS FspFsvolDeviceInsertContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier, PVOID Context, + PBOOLEAN PInserted) +{ + // !PAGED_CODE(); + + FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject); + ASSERT(FspFsvolDeviceExtensionKind == FsvolDeviceExtension->Base.Kind); + + NTSTATUS Result; + FSP_DEVICE_GENERIC_TABLE_ELEMENT Element = { 0 }; + Element.Identifier = Identifier; + Element.Context = Context; + + ExAcquireFastMutex(&FsvolDeviceExtension->GenericTableFastMutex); + Result = 0 != RtlInsertElementGenericTableAvl(&FsvolDeviceExtension->GenericTable, + &Element, sizeof Element, PInserted) ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES; + ExReleaseFastMutex(&FsvolDeviceExtension->GenericTableFastMutex); + + return Result; +} + +VOID FspFsvolDeviceDeleteContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier, + PBOOLEAN PDeleted) +{ + // !PAGED_CODE(); + + FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(DeviceObject); + ASSERT(FspFsvolDeviceExtensionKind == FsvolDeviceExtension->Base.Kind); + + ExAcquireFastMutex(&FsvolDeviceExtension->GenericTableFastMutex); + BOOLEAN Deleted = RtlDeleteElementGenericTableAvl(&FsvolDeviceExtension->GenericTable, + &Identifier); + ExReleaseFastMutex(&FsvolDeviceExtension->GenericTableFastMutex); + + if (0 != PDeleted) + *PDeleted = Deleted; +} + +static RTL_GENERIC_COMPARE_RESULTS NTAPI FspFsvolDeviceCompareElement( + PRTL_AVL_TABLE Table, PVOID FirstElement, PVOID SecondElement) +{ + // !PAGED_CODE(); + + if (FirstElement < SecondElement) + return GenericLessThan; + else + if (SecondElement < FirstElement) + return GenericGreaterThan; + else + return GenericEqual; +} + +static PVOID NTAPI FspFsvolDeviceAllocateElement( + PRTL_AVL_TABLE Table, CLONG ByteSize) +{ + // !PAGED_CODE(); + + /* allocate from non-paged pool because of fast mutex use in GenericTable */ + return ExAllocatePoolWithTag(NonPagedPool, ByteSize, FSP_TAG); +} + +static VOID NTAPI FspFsvolDeviceFreeElement( + PRTL_AVL_TABLE Table, PVOID Buffer) +{ + // !PAGED_CODE(); + + ExFreePoolWithTag(Buffer, FSP_TAG); +} + NTSTATUS FspDeviceCopyList( PDEVICE_OBJECT **PDeviceObjects, PULONG PDeviceObjectCount) { diff --git a/src/sys/driver.h b/src/sys/driver.h index 77f38dfa..bff4a3d2 100644 --- a/src/sys/driver.h +++ b/src/sys/driver.h @@ -303,6 +303,8 @@ typedef struct { FSP_DEVICE_EXTENSION Base; PDEVICE_OBJECT FsvrtDeviceObject; + FAST_MUTEX GenericTableFastMutex; + RTL_AVL_TABLE GenericTable; } FSP_FSVOL_DEVICE_EXTENSION; static inline FSP_DEVICE_EXTENSION *FspDeviceExtension(PDEVICE_OBJECT DeviceObject) @@ -339,6 +341,10 @@ BOOLEAN FspDeviceRetain(PDEVICE_OBJECT DeviceObject); VOID FspDeviceRelease(PDEVICE_OBJECT DeviceObject); VOID FspFsctlDeviceVolumeCreated(PDEVICE_OBJECT DeviceObject); VOID FspFsctlDeviceVolumeDeleted(PDEVICE_OBJECT DeviceObject); +NTSTATUS FspFsvolDeviceInsertContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier, PVOID Context, + PBOOLEAN PInserted); +VOID FspFsvolDeviceDeleteContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier, + PBOOLEAN PDeleted); NTSTATUS FspDeviceCopyList( PDEVICE_OBJECT **PDeviceObjects, PULONG PDeviceObjectCount); VOID FspDeviceDeleteList(