mirror of
				https://github.com/winfsp/winfsp.git
				synced 2025-10-30 19:48:38 -05:00 
			
		
		
		
	sys: device extension reference count
This commit is contained in:
		
							
								
								
									
										315
									
								
								src/sys/device.c
									
									
									
									
									
								
							
							
						
						
									
										315
									
								
								src/sys/device.c
									
									
									
									
									
								
							| @@ -6,40 +6,249 @@ | ||||
|  | ||||
| #include <sys/driver.h> | ||||
|  | ||||
| NTSTATUS FspDeviceCreateList( | ||||
|     PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT **PDeviceObjects, PULONG PDeviceObjectCount); | ||||
| NTSTATUS FspDeviceCreateSecure(UINT32 Kind, ULONG ExtraSize, | ||||
|     PUNICODE_STRING DeviceName, DEVICE_TYPE DeviceType, | ||||
|     PUNICODE_STRING DeviceSddl, LPCGUID DeviceClassGuid, | ||||
|     PDEVICE_OBJECT *PDeviceObject); | ||||
| NTSTATUS FspDeviceCreate(UINT32 Kind, ULONG ExtraSize, | ||||
|     DEVICE_TYPE DeviceType, | ||||
|     PDEVICE_OBJECT *PDeviceObject); | ||||
| VOID FspDeviceDelete(PDEVICE_OBJECT DeviceObject); | ||||
| static NTSTATUS FspFsctlDeviceInit(PDEVICE_OBJECT DeviceObject); | ||||
| static VOID FspFsctlDeviceFini(PDEVICE_OBJECT DeviceObject); | ||||
| static NTSTATUS FspFsvrtDeviceInit(PDEVICE_OBJECT DeviceObject); | ||||
| static VOID FspFsvrtDeviceFini(PDEVICE_OBJECT DeviceObject); | ||||
| static NTSTATUS FspFsvolDeviceInit(PDEVICE_OBJECT DeviceObject); | ||||
| static VOID FspFsvolDeviceFini(PDEVICE_OBJECT DeviceObject); | ||||
| BOOLEAN FspDeviceRetain(PDEVICE_OBJECT DeviceObject); | ||||
| VOID FspDeviceRelease(PDEVICE_OBJECT DeviceObject); | ||||
| NTSTATUS FspDeviceCopyList( | ||||
|     PDEVICE_OBJECT **PDeviceObjects, PULONG PDeviceObjectCount); | ||||
| VOID FspDeviceDeleteList( | ||||
|     PDEVICE_OBJECT *DeviceObjects, ULONG DeviceObjectCount); | ||||
| NTSTATUS FspDeviceOwned( | ||||
|     PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT DeviceObject); | ||||
| VOID FspDeviceInitExtension(PDEVICE_OBJECT DeviceObject, UINT8 Kind); | ||||
| static VOID FspFsctlDeviceDeleteObject(PDEVICE_OBJECT DeviceObject); | ||||
| static VOID FspFsvrtDeviceDeleteObject(PDEVICE_OBJECT DeviceObject); | ||||
| static VOID FspFsvolDeviceDeleteObject(PDEVICE_OBJECT DeviceObject); | ||||
| VOID FspDeviceDeleteObject(PDEVICE_OBJECT DeviceObject); | ||||
| VOID FspDeviceDeleteObjects(PDRIVER_OBJECT DriverObject); | ||||
| NTSTATUS FspDeviceOwned(PDEVICE_OBJECT DeviceObject); | ||||
| VOID FspDeviceDeleteAll(VOID); | ||||
|  | ||||
| #ifdef ALLOC_PRAGMA | ||||
| #pragma alloc_text(PAGE, FspDeviceCreateList) | ||||
| #pragma alloc_text(PAGE, FspDeviceCreateSecure) | ||||
| #pragma alloc_text(PAGE, FspDeviceCreate) | ||||
| #pragma alloc_text(PAGE, FspDeviceDelete) | ||||
| #pragma alloc_text(PAGE, FspFsctlDeviceInit) | ||||
| #pragma alloc_text(PAGE, FspFsctlDeviceFini) | ||||
| #pragma alloc_text(PAGE, FspFsvrtDeviceInit) | ||||
| #pragma alloc_text(PAGE, FspFsvrtDeviceFini) | ||||
| #pragma alloc_text(PAGE, FspFsvolDeviceInit) | ||||
| #pragma alloc_text(PAGE, FspFsvolDeviceFini) | ||||
| #pragma alloc_text(PAGE, FspDeviceCopyList) | ||||
| #pragma alloc_text(PAGE, FspDeviceDeleteList) | ||||
| #pragma alloc_text(PAGE, FspDeviceOwned) | ||||
| #pragma alloc_text(PAGE, FspDeviceInitExtension) | ||||
| #pragma alloc_text(PAGE, FspFsctlDeviceDeleteObject) | ||||
| #pragma alloc_text(PAGE, FspFsvrtDeviceDeleteObject) | ||||
| #pragma alloc_text(PAGE, FspFsvolDeviceDeleteObject) | ||||
| #pragma alloc_text(PAGE, FspDeviceDeleteObject) | ||||
| #pragma alloc_text(PAGE, FspDeviceDeleteObjects) | ||||
| #pragma alloc_text(PAGE, FspDeviceDeleteAll) | ||||
| #endif | ||||
|  | ||||
| NTSTATUS FspDeviceCreateList( | ||||
|     PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT **PDeviceObjects, PULONG PDeviceObjectCount) | ||||
| NTSTATUS FspDeviceCreateSecure(UINT32 Kind, ULONG ExtraSize, | ||||
|     PUNICODE_STRING DeviceName, DEVICE_TYPE DeviceType, | ||||
|     PUNICODE_STRING DeviceSddl, LPCGUID DeviceClassGuid, | ||||
|     PDEVICE_OBJECT *PDeviceObject) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     NTSTATUS Result; | ||||
|     ULONG DeviceExtensionSize; | ||||
|     PDEVICE_OBJECT DeviceObject; | ||||
|     FSP_DEVICE_EXTENSION *DeviceExtension; | ||||
|  | ||||
|     switch (Kind) | ||||
|     { | ||||
|     case FspFsvolDeviceExtensionKind: | ||||
|         DeviceExtensionSize = sizeof(FSP_FSVOL_DEVICE_EXTENSION); | ||||
|         break; | ||||
|     case FspFsvrtDeviceExtensionKind: | ||||
|         DeviceExtensionSize = sizeof(FSP_FSVRT_DEVICE_EXTENSION); | ||||
|         break; | ||||
|     case FspFsctlDeviceExtensionKind: | ||||
|         DeviceExtensionSize = sizeof(FSP_FSCTL_DEVICE_EXTENSION); | ||||
|         break; | ||||
|     default: | ||||
|         ASSERT(0); | ||||
|         return STATUS_INVALID_PARAMETER; | ||||
|     } | ||||
|  | ||||
|     if (0 != DeviceSddl) | ||||
|         Result = IoCreateDeviceSecure(FspDriverObject, | ||||
|             DeviceExtensionSize + ExtraSize, DeviceName, DeviceType, | ||||
|             FILE_DEVICE_SECURE_OPEN, FALSE, | ||||
|             DeviceSddl, DeviceClassGuid, | ||||
|             &DeviceObject); | ||||
|     else | ||||
|         Result = IoCreateDevice(FspDriverObject, | ||||
|             DeviceExtensionSize + ExtraSize, DeviceName, DeviceType, | ||||
|             0, FALSE, | ||||
|             &DeviceObject); | ||||
|     if (!NT_SUCCESS(Result)) | ||||
|         return Result; | ||||
|  | ||||
|     DeviceExtension = FspDeviceExtension(DeviceObject); | ||||
|     KeInitializeSpinLock(&DeviceExtension->SpinLock); | ||||
|     DeviceExtension->RefCount = 1; | ||||
|     ExInitializeResourceLite(&DeviceExtension->Resource); | ||||
|     DeviceExtension->Kind = Kind; | ||||
|  | ||||
|     switch (Kind) | ||||
|     { | ||||
|     case FspFsvolDeviceExtensionKind: | ||||
|         Result = FspFsvolDeviceInit(DeviceObject); | ||||
|         break; | ||||
|     case FspFsvrtDeviceExtensionKind: | ||||
|         Result = FspFsvrtDeviceInit(DeviceObject); | ||||
|         break; | ||||
|     case FspFsctlDeviceExtensionKind: | ||||
|         Result = FspFsctlDeviceInit(DeviceObject); | ||||
|         break; | ||||
|     } | ||||
|  | ||||
|     if (!NT_SUCCESS(Result)) | ||||
|     { | ||||
|         ExDeleteResourceLite(&DeviceExtension->Resource); | ||||
|         IoDeleteDevice(DeviceObject); | ||||
|     } | ||||
|     else | ||||
|         *PDeviceObject = DeviceObject; | ||||
|  | ||||
|     return Result; | ||||
| } | ||||
|  | ||||
| NTSTATUS FspDeviceCreate(UINT32 Kind, ULONG ExtraSize, | ||||
|     DEVICE_TYPE DeviceType, | ||||
|     PDEVICE_OBJECT *PDeviceObject) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     return FspDeviceCreateSecure(Kind, ExtraSize, 0, DeviceType, 0, 0, PDeviceObject); | ||||
| } | ||||
|  | ||||
| VOID FspDeviceDelete(PDEVICE_OBJECT DeviceObject) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     FSP_DEVICE_EXTENSION *DeviceExtension = FspDeviceExtension(DeviceObject); | ||||
|  | ||||
|     switch (DeviceExtension->Kind) | ||||
|     { | ||||
|     case FspFsvolDeviceExtensionKind: | ||||
|         FspFsvolDeviceFini(DeviceObject); | ||||
|         break; | ||||
|     case FspFsvrtDeviceExtensionKind: | ||||
|         FspFsvrtDeviceFini(DeviceObject); | ||||
|         break; | ||||
|     case FspFsctlDeviceExtensionKind: | ||||
|         FspFsctlDeviceFini(DeviceObject); | ||||
|         break; | ||||
|     default: | ||||
|         ASSERT(0); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     ExDeleteResourceLite(&DeviceExtension->Resource); | ||||
|     IoDeleteDevice(DeviceObject); | ||||
| } | ||||
|  | ||||
| static NTSTATUS FspFsctlDeviceInit(PDEVICE_OBJECT DeviceObject) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     return STATUS_SUCCESS; | ||||
| } | ||||
|  | ||||
| static VOID FspFsctlDeviceFini(PDEVICE_OBJECT DeviceObject) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
| } | ||||
|  | ||||
| static NTSTATUS FspFsvrtDeviceInit(PDEVICE_OBJECT DeviceObject) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(DeviceObject); | ||||
|  | ||||
|     FspIoqInitialize(&FsvrtDeviceExtension->Ioq); | ||||
|  | ||||
|     FsvrtDeviceExtension->SwapVpb = ExAllocatePoolWithTag(NonPagedPool, | ||||
|         sizeof *FsvrtDeviceExtension->SwapVpb, FSP_TAG); | ||||
|     if (0 == FsvrtDeviceExtension->SwapVpb) | ||||
|         return STATUS_INSUFFICIENT_RESOURCES; | ||||
|     RtlZeroMemory(FsvrtDeviceExtension->SwapVpb, sizeof *FsvrtDeviceExtension->SwapVpb); | ||||
|  | ||||
|     return STATUS_SUCCESS; | ||||
| } | ||||
|  | ||||
| static VOID FspFsvrtDeviceFini(PDEVICE_OBJECT DeviceObject) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(DeviceObject); | ||||
|  | ||||
|     if (0 != FsvrtDeviceExtension->SwapVpb) | ||||
|         ExFreePoolWithTag(FsvrtDeviceExtension->SwapVpb, FSP_TAG); | ||||
| } | ||||
|  | ||||
| static NTSTATUS FspFsvolDeviceInit(PDEVICE_OBJECT DeviceObject) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     return STATUS_SUCCESS; | ||||
| } | ||||
|  | ||||
| static VOID FspFsvolDeviceFini(PDEVICE_OBJECT DeviceObject) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
| } | ||||
|  | ||||
| BOOLEAN FspDeviceRetain(PDEVICE_OBJECT DeviceObject) | ||||
| { | ||||
|     // !PAGED_CODE(); | ||||
|  | ||||
|     BOOLEAN Result; | ||||
|     FSP_DEVICE_EXTENSION *DeviceExtension; | ||||
|     KIRQL Irql; | ||||
|  | ||||
|     DeviceExtension = FspDeviceExtension(DeviceObject); | ||||
|     KeAcquireSpinLock(&DeviceExtension->SpinLock, &Irql); | ||||
|     Result = 0 != DeviceExtension->RefCount; | ||||
|     if (!Result) | ||||
|         DeviceExtension->RefCount++; | ||||
|     KeReleaseSpinLock(&DeviceExtension->SpinLock, Irql); | ||||
|  | ||||
|     return Result; | ||||
| } | ||||
|  | ||||
| VOID FspDeviceRelease(PDEVICE_OBJECT DeviceObject) | ||||
| { | ||||
|     // !PAGED_CODE(); | ||||
|  | ||||
|     BOOLEAN Result; | ||||
|     FSP_DEVICE_EXTENSION *DeviceExtension; | ||||
|     KIRQL Irql; | ||||
|  | ||||
|     DeviceExtension = FspDeviceExtension(DeviceObject); | ||||
|     KeAcquireSpinLock(&DeviceExtension->SpinLock, &Irql); | ||||
|     if (0 != DeviceExtension->RefCount) | ||||
|         DeviceExtension->RefCount--; | ||||
|     Result = 0 != DeviceExtension->RefCount; | ||||
|     KeReleaseSpinLock(&DeviceExtension->SpinLock, Irql); | ||||
|  | ||||
|     if (!Result) | ||||
|         FspDeviceDelete(DeviceObject); | ||||
| } | ||||
|  | ||||
| NTSTATUS FspDeviceCopyList( | ||||
|     PDEVICE_OBJECT **PDeviceObjects, PULONG PDeviceObjectCount) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     PDEVICE_OBJECT *DeviceObjects = 0; | ||||
|     ULONG DeviceObjectCount = 0; | ||||
|  | ||||
|     while (STATUS_BUFFER_TOO_SMALL == IoEnumerateDeviceObjectList(DriverObject, | ||||
|     while (STATUS_BUFFER_TOO_SMALL == IoEnumerateDeviceObjectList(FspDriverObject, | ||||
|         DeviceObjects, DeviceObjectCount, &DeviceObjectCount)) | ||||
|     { | ||||
|         if (0 != DeviceObjects) | ||||
| @@ -68,8 +277,7 @@ VOID FspDeviceDeleteList( | ||||
|     ExFreePoolWithTag(DeviceObjects, FSP_TAG); | ||||
| } | ||||
|  | ||||
| NTSTATUS FspDeviceOwned( | ||||
|     PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT DeviceObject) | ||||
| NTSTATUS FspDeviceOwned(PDEVICE_OBJECT DeviceObject) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
| @@ -77,7 +285,7 @@ NTSTATUS FspDeviceOwned( | ||||
|     PDEVICE_OBJECT *DeviceObjects = 0; | ||||
|     ULONG DeviceObjectCount = 0; | ||||
|  | ||||
|     Result = FspDeviceCreateList(DriverObject, &DeviceObjects, &DeviceObjectCount); | ||||
|     Result = FspDeviceCopyList(&DeviceObjects, &DeviceObjectCount); | ||||
|     if (!NT_SUCCESS(Result)) | ||||
|         return Result; | ||||
|  | ||||
| @@ -93,62 +301,7 @@ NTSTATUS FspDeviceOwned( | ||||
|     return Result; | ||||
| } | ||||
|  | ||||
| VOID FspDeviceInitExtension(PDEVICE_OBJECT DeviceObject, UINT8 Kind) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     FSP_DEVICE_EXTENSION *DeviceExtension = FspDeviceExtension(DeviceObject); | ||||
|  | ||||
|     DeviceExtension->Kind = Kind; | ||||
|     ExInitializeResourceLite(&DeviceExtension->Resource); | ||||
| } | ||||
|  | ||||
| static VOID FspFsctlDeviceDeleteObject(PDEVICE_OBJECT DeviceObject) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
| } | ||||
|  | ||||
| static VOID FspFsvrtDeviceDeleteObject(PDEVICE_OBJECT DeviceObject) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(DeviceObject); | ||||
|  | ||||
|     if (0 != FsvrtDeviceExtension->SwapVpb) | ||||
|         ExFreePoolWithTag(FsvrtDeviceExtension->SwapVpb, FSP_TAG); | ||||
| } | ||||
|  | ||||
| static VOID FspFsvolDeviceDeleteObject(PDEVICE_OBJECT DeviceObject) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
| } | ||||
|  | ||||
| VOID FspDeviceDeleteObject(PDEVICE_OBJECT DeviceObject) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
|     switch (FspDeviceExtension(DeviceObject)->Kind) | ||||
|     { | ||||
|     case FspFsvolDeviceExtensionKind: | ||||
|         FspFsvolDeviceDeleteObject(DeviceObject); | ||||
|         break; | ||||
|     case FspFsvrtDeviceExtensionKind: | ||||
|         FspFsvrtDeviceDeleteObject(DeviceObject); | ||||
|         break; | ||||
|     case FspFsctlDeviceExtensionKind: | ||||
|         FspFsctlDeviceDeleteObject(DeviceObject); | ||||
|         break; | ||||
|     default: | ||||
|         ASSERT(0); | ||||
|         break; | ||||
|     } | ||||
|  | ||||
|     ExDeleteResourceLite(&FspDeviceExtension(DeviceObject)->Resource); | ||||
|  | ||||
|     IoDeleteDevice(DeviceObject); | ||||
| } | ||||
|  | ||||
| VOID FspDeviceDeleteObjects(PDRIVER_OBJECT DriverObject) | ||||
| VOID FspDeviceDeleteAll(VOID) | ||||
| { | ||||
|     PAGED_CODE(); | ||||
|  | ||||
| @@ -156,12 +309,12 @@ VOID FspDeviceDeleteObjects(PDRIVER_OBJECT DriverObject) | ||||
|     PDEVICE_OBJECT *DeviceObjects = 0; | ||||
|     ULONG DeviceObjectCount = 0; | ||||
|  | ||||
|     Result = FspDeviceCreateList(DriverObject, &DeviceObjects, &DeviceObjectCount); | ||||
|     Result = FspDeviceCopyList(&DeviceObjects, &DeviceObjectCount); | ||||
|     if (!NT_SUCCESS(Result)) | ||||
|         return; | ||||
|  | ||||
|     for (ULONG i = 0; DeviceObjectCount > i; i++) | ||||
|         FspDeviceDeleteObject(DeviceObjects[i]); | ||||
|         FspDeviceDelete(DeviceObjects[i]); | ||||
|  | ||||
|     FspDeviceDeleteList(DeviceObjects, DeviceObjectCount); | ||||
| } | ||||
|   | ||||
| @@ -19,28 +19,26 @@ NTSTATUS DriverEntry( | ||||
| { | ||||
|     FSP_ENTER(); | ||||
|  | ||||
|     FspDriverObject = DriverObject; | ||||
|  | ||||
|     /* create the file system control device objects */ | ||||
|     UNICODE_STRING DeviceSddl; | ||||
|     UNICODE_STRING DeviceName; | ||||
|     RtlInitUnicodeString(&DeviceSddl, L"" FSP_FSCTL_DEVICE_SDDL); | ||||
|     RtlInitUnicodeString(&DeviceName, L"\\Device\\" FSP_FSCTL_DISK_DEVICE_NAME); | ||||
|     Result = IoCreateDeviceSecure(DriverObject, | ||||
|         sizeof(FSP_FSCTL_DEVICE_EXTENSION), &DeviceName, FILE_DEVICE_DISK_FILE_SYSTEM, | ||||
|         FILE_DEVICE_SECURE_OPEN, FALSE, | ||||
|     Result = FspDeviceCreateSecure(FspFsctlDeviceExtensionKind, 0, | ||||
|         &DeviceName, FILE_DEVICE_DISK_FILE_SYSTEM, | ||||
|         &DeviceSddl, &FspFsctlDeviceClassGuid, | ||||
|         &FspFsctlDiskDeviceObject); | ||||
|     if (!NT_SUCCESS(Result)) | ||||
|         FSP_RETURN(); | ||||
|     RtlInitUnicodeString(&DeviceName, L"\\Device\\" FSP_FSCTL_NET_DEVICE_NAME); | ||||
|     Result = IoCreateDeviceSecure(DriverObject, | ||||
|         sizeof(FSP_FSCTL_DEVICE_EXTENSION), &DeviceName, FILE_DEVICE_NETWORK_FILE_SYSTEM, | ||||
|         FILE_DEVICE_SECURE_OPEN, FALSE, | ||||
|     Result = FspDeviceCreateSecure(FspFsctlDeviceExtensionKind, 0, | ||||
|         &DeviceName, FILE_DEVICE_NETWORK_FILE_SYSTEM, | ||||
|         &DeviceSddl, &FspFsctlDeviceClassGuid, | ||||
|         &FspFsctlNetDeviceObject); | ||||
|     if (!NT_SUCCESS(Result)) | ||||
|         FSP_RETURN(IoDeleteDevice(FspFsctlDiskDeviceObject)); | ||||
|     FspDeviceInitExtension(FspFsctlDiskDeviceObject, FspFsctlDeviceExtensionKind); | ||||
|     FspDeviceInitExtension(FspFsctlNetDeviceObject, FspFsctlDeviceExtensionKind); | ||||
|         FSP_RETURN(FspDeviceDelete(FspFsctlDiskDeviceObject)); | ||||
|  | ||||
|     /* setup the driver object */ | ||||
|     DriverObject->DriverUnload = FspUnload; | ||||
| @@ -134,12 +132,15 @@ VOID FspUnload( | ||||
|  | ||||
|     FspFsctlDiskDeviceObject = 0; | ||||
|     FspFsctlNetDeviceObject = 0; | ||||
|     FspDeviceDeleteObjects(DriverObject); | ||||
|     FspDeviceDeleteAll(); | ||||
|  | ||||
|     FspDriverObject = 0; | ||||
|  | ||||
| #pragma prefast(suppress:28175, "We are in DriverUnload: ok to access DriverName") | ||||
|     FSP_LEAVE_VOID("DriverName=\"%wZ\"", | ||||
|         &DriverObject->DriverName); | ||||
| } | ||||
|  | ||||
| PDRIVER_OBJECT FspDriverObject; | ||||
| PDEVICE_OBJECT FspFsctlDiskDeviceObject; | ||||
| PDEVICE_OBJECT FspFsctlNetDeviceObject; | ||||
|   | ||||
| @@ -80,13 +80,21 @@ | ||||
|     FSP_LEAVE_(FSP_DEBUGLOG_(fmt, " = %s", __VA_ARGS__, NtStatusSym(Result))); return Result | ||||
| #define FSP_ENTER_MJ(...)               \ | ||||
|     NTSTATUS Result = STATUS_SUCCESS;   \ | ||||
|     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); (VOID)IrpSp;\ | ||||
|     FSP_ENTER_(__VA_ARGS__) | ||||
|     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);\ | ||||
|     FSP_ENTER_(__VA_ARGS__);            \ | ||||
|     do                                  \ | ||||
|     {                                   \ | ||||
|         if (!FspDeviceRetain(IrpSp->DeviceObject))\ | ||||
|         {                               \ | ||||
|             Result = STATUS_CANCELLED;  \ | ||||
|             goto fsp_leave_label;       \ | ||||
|         }                               \ | ||||
|     } while (0,0) | ||||
| #define FSP_LEAVE_MJ(fmt, ...)          \ | ||||
|     FSP_LEAVE_(                         \ | ||||
|         FSP_DEBUGLOG_("%p, %c%c, %s%s, " fmt, " = %s[%lld]",\ | ||||
|         FSP_DEBUGLOG_("%p, %s%c, %s%s, " fmt, " = %s[%lld]",\ | ||||
|             Irp,                        \ | ||||
|             FspDeviceExtension(IrpSp->DeviceObject)->Kind,\ | ||||
|             (const char *)&FspDeviceExtension(IrpSp->DeviceObject)->Kind,\ | ||||
|             Irp->RequestorMode == KernelMode ? 'K' : 'U',\ | ||||
|             IrpMajorFunctionSym(IrpSp->MajorFunction),\ | ||||
|             IrpMinorFunctionSym(IrpSp->MajorFunction, IrpSp->MajorFunction),\ | ||||
| @@ -121,9 +129,9 @@ | ||||
|     FSP_ENTER_NOCRIT_(__VA_ARGS__) | ||||
| #define FSP_LEAVE_IOC(fmt, ...)         \ | ||||
|     FSP_LEAVE_NOCRIT_(                  \ | ||||
|         FSP_DEBUGLOG_NOCRIT_("%p, %c%c, %s%s, " fmt, " = %s[%lld]",\ | ||||
|         FSP_DEBUGLOG_NOCRIT_("%p, %s%c, %s%s, " fmt, " = %s[%lld]",\ | ||||
|             Irp,                        \ | ||||
|             FspDeviceExtension(IrpSp->DeviceObject)->Kind,\ | ||||
|             (const char *)&FspDeviceExtension(IrpSp->DeviceObject)->Kind,\ | ||||
|             Irp->RequestorMode == KernelMode ? 'K' : 'U',\ | ||||
|             IrpMajorFunctionSym(IrpSp->MajorFunction),\ | ||||
|             IrpMinorFunctionSym(IrpSp->MajorFunction, IrpSp->MajorFunction),\ | ||||
| @@ -235,17 +243,19 @@ PIRP FspIoqNextPendingIrp(FSP_IOQ *Ioq, ULONG millis); | ||||
| BOOLEAN FspIoqStartProcessingIrp(FSP_IOQ *Ioq, PIRP Irp); | ||||
| PIRP FspIoqEndProcessingIrp(FSP_IOQ *Ioq, UINT_PTR IrpHint); | ||||
|  | ||||
| /* device extensions */ | ||||
| /* device management */ | ||||
| enum | ||||
| { | ||||
|     FspFsctlDeviceExtensionKind = 'C',  /* file system control device (e.g. \Device\WinFsp.Disk) */ | ||||
|     FspFsvrtDeviceExtensionKind = 'V',  /* virtual volume device (e.g. \Device\Volume{GUID}) */ | ||||
|     FspFsvolDeviceExtensionKind = 'F',  /* file system volume device (unnamed) */ | ||||
|     FspFsctlDeviceExtensionKind = '\0ltC',  /* file system control device (e.g. \Device\WinFsp.Disk) */ | ||||
|     FspFsvrtDeviceExtensionKind = '\0trV',  /* virtual volume device (e.g. \Device\Volume{GUID}) */ | ||||
|     FspFsvolDeviceExtensionKind = '\0loV',  /* file system volume device (unnamed) */ | ||||
| }; | ||||
| typedef struct | ||||
| { | ||||
|     UINT8 Kind; | ||||
|     KSPIN_LOCK SpinLock; | ||||
|     LONG RefCount; | ||||
|     ERESOURCE Resource; | ||||
|     UINT32 Kind; | ||||
| } FSP_DEVICE_EXTENSION; | ||||
| typedef struct | ||||
| { | ||||
| @@ -255,6 +265,7 @@ typedef struct | ||||
| { | ||||
|     FSP_DEVICE_EXTENSION Base; | ||||
|     PDEVICE_OBJECT FsctlDeviceObject; | ||||
|     PDEVICE_OBJECT FsvolDeviceObject; | ||||
|     FSP_FSCTL_VOLUME_PARAMS VolumeParams; | ||||
|     FSP_IOQ Ioq; | ||||
|     PVPB SwapVpb; | ||||
| @@ -288,15 +299,22 @@ FSP_FSVOL_DEVICE_EXTENSION *FspFsvolDeviceExtension(PDEVICE_OBJECT DeviceObject) | ||||
|     ASSERT(FspFsvolDeviceExtensionKind == ((FSP_DEVICE_EXTENSION *)DeviceObject->DeviceExtension)->Kind); | ||||
|     return DeviceObject->DeviceExtension; | ||||
| } | ||||
| NTSTATUS FspDeviceCreateList( | ||||
|     PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT **PDeviceObjects, PULONG PDeviceObjectCount); | ||||
| NTSTATUS FspDeviceCreateSecure(UINT32 Kind, ULONG ExtraSize, | ||||
|     PUNICODE_STRING DeviceName, DEVICE_TYPE DeviceType, | ||||
|     PUNICODE_STRING DeviceSddl, LPCGUID DeviceClassGuid, | ||||
|     PDEVICE_OBJECT *PDeviceObject); | ||||
| NTSTATUS FspDeviceCreate(UINT32 Kind, ULONG ExtraSize, | ||||
|     DEVICE_TYPE DeviceType, | ||||
|     PDEVICE_OBJECT *PDeviceObject); | ||||
| VOID FspDeviceDelete(PDEVICE_OBJECT DeviceObject); | ||||
| BOOLEAN FspDeviceRetain(PDEVICE_OBJECT DeviceObject); | ||||
| VOID FspDeviceRelease(PDEVICE_OBJECT DeviceObject); | ||||
| NTSTATUS FspDeviceCopyList( | ||||
|     PDEVICE_OBJECT **PDeviceObjects, PULONG PDeviceObjectCount); | ||||
| VOID FspDeviceDeleteList( | ||||
|     PDEVICE_OBJECT *DeviceObjects, ULONG DeviceObjectCount); | ||||
| NTSTATUS FspDeviceOwned( | ||||
|     PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT DeviceObject); | ||||
| VOID FspDeviceInitExtension(PDEVICE_OBJECT DeviceObject, UINT8 Kind); | ||||
| VOID FspDeviceDeleteObject(PDEVICE_OBJECT DeviceObject); | ||||
| VOID FspDeviceDeleteObjects(PDRIVER_OBJECT DriverObject); | ||||
| NTSTATUS FspDeviceOwned(PDEVICE_OBJECT DeviceObject); | ||||
| VOID FspDeviceDeleteAll(VOID); | ||||
|  | ||||
| /* I/O processing */ | ||||
| VOID FspIopCompleteRequest(PIRP Irp, NTSTATUS Result); | ||||
| @@ -317,6 +335,7 @@ const char *IoctlCodeSym(ULONG ControlCode); | ||||
| #endif | ||||
|  | ||||
| /* extern */ | ||||
| extern PDRIVER_OBJECT FspDriverObject; | ||||
| extern PDEVICE_OBJECT FspFsctlDiskDeviceObject; | ||||
| extern PDEVICE_OBJECT FspFsctlNetDeviceObject; | ||||
| extern FSP_IOCMPL_DISPATCH *FspIopCompleteFunction[]; | ||||
|   | ||||
| @@ -56,32 +56,20 @@ static NTSTATUS FspFsctlCreateVolume( | ||||
|  | ||||
|     NTSTATUS Result; | ||||
|     PVOID SecurityDescriptorBuf = 0; | ||||
|     PVPB SwapVpb = 0; | ||||
|     FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension; | ||||
|  | ||||
|     /* create volume guid */ | ||||
|     GUID Guid; | ||||
|     Result = FspCreateGuid(&Guid); | ||||
|     if (!NT_SUCCESS(Result)) | ||||
|         goto exit; | ||||
|         return Result; | ||||
|  | ||||
|     /* copy the security descriptor from the system buffer to a temporary one */ | ||||
|     SecurityDescriptorBuf = ExAllocatePoolWithTag(PagedPool, SecurityDescriptorSize, FSP_TAG); | ||||
|     if (0 == SecurityDescriptorBuf) | ||||
|     { | ||||
|         Result = STATUS_INSUFFICIENT_RESOURCES; | ||||
|         goto exit; | ||||
|     } | ||||
|         return STATUS_INSUFFICIENT_RESOURCES; | ||||
|     RtlCopyMemory(SecurityDescriptorBuf, SecurityDescriptor, SecurityDescriptorSize); | ||||
|  | ||||
|     /* preallocate swap VPB */ | ||||
|     SwapVpb = ExAllocatePoolWithTag(NonPagedPool, sizeof *SwapVpb, FSP_TAG); | ||||
|     if (0 == SwapVpb) | ||||
|     { | ||||
|         Result = STATUS_INSUFFICIENT_RESOURCES; | ||||
|         goto exit; | ||||
|     } | ||||
|     RtlZeroMemory(SwapVpb, sizeof *SwapVpb); | ||||
|  | ||||
|     /* create the virtual volume device */ | ||||
|     PDEVICE_OBJECT FsvrtDeviceObject; | ||||
|     UNICODE_STRING DeviceSddl; | ||||
| @@ -94,33 +82,24 @@ static NTSTATUS FspFsctlCreateVolume( | ||||
|         Guid.Data4[0], Guid.Data4[1], Guid.Data4[2], Guid.Data4[3], | ||||
|         Guid.Data4[4], Guid.Data4[5], Guid.Data4[6], Guid.Data4[7]); | ||||
|     ASSERT(NT_SUCCESS(Result)); | ||||
|     Result = IoCreateDeviceSecure(DeviceObject->DriverObject, | ||||
|         sizeof(FSP_FSVRT_DEVICE_EXTENSION) + SecurityDescriptorSize, &DeviceName, FILE_DEVICE_VIRTUAL_DISK, | ||||
|         FILE_DEVICE_SECURE_OPEN, FALSE, | ||||
|         &DeviceSddl, 0, | ||||
|     Result = FspDeviceCreateSecure(FspFsvrtDeviceExtensionKind, SecurityDescriptorSize, | ||||
|         &DeviceName, FILE_DEVICE_VIRTUAL_DISK, | ||||
|         &DeviceSddl, &FspFsvrtDeviceClassGuid, | ||||
|         &FsvrtDeviceObject); | ||||
|     if (NT_SUCCESS(Result)) | ||||
|     { | ||||
|         FspDeviceInitExtension(FsvrtDeviceObject, FspFsvrtDeviceExtensionKind); | ||||
|         FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(FsvrtDeviceObject); | ||||
|         FsvrtDeviceExtension = FspFsvrtDeviceExtension(FsvrtDeviceObject); | ||||
|         FsvrtDeviceExtension->FsctlDeviceObject = DeviceObject; | ||||
|         FsvrtDeviceExtension->VolumeParams = *Params; | ||||
|         FspIoqInitialize(&FsvrtDeviceExtension->Ioq); | ||||
|         FsvrtDeviceExtension->SwapVpb = SwapVpb; | ||||
|         RtlCopyMemory(FspFsvrtDeviceExtension(FsvrtDeviceObject)->SecurityDescriptorBuf, | ||||
|         RtlCopyMemory(FsvrtDeviceExtension->SecurityDescriptorBuf, | ||||
|             SecurityDescriptorBuf, SecurityDescriptorSize); | ||||
|         ClearFlag(FsvrtDeviceObject->Flags, DO_DEVICE_INITIALIZING); | ||||
|         Irp->IoStatus.Information = DeviceName.Length + 1; | ||||
|         SwapVpb = 0; | ||||
|     } | ||||
|  | ||||
| exit: | ||||
|     /* free the temporary security descriptor */ | ||||
|     if (0 != SecurityDescriptorBuf) | ||||
|         ExFreePoolWithTag(SecurityDescriptorBuf, FSP_TAG); | ||||
|     /* free swap VPB if we failed */ | ||||
|     if (0 != SwapVpb) | ||||
|         ExFreePoolWithTag(SwapVpb, FSP_TAG); | ||||
|  | ||||
|     return Result; | ||||
| } | ||||
| @@ -132,12 +111,14 @@ static NTSTATUS FspFsctlMountVolume( | ||||
|  | ||||
|     NTSTATUS Result; | ||||
|     FSP_FSCTL_DEVICE_EXTENSION *FsctlDeviceExtension = FspFsctlDeviceExtension(DeviceObject); | ||||
|     FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension; | ||||
|     FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension; | ||||
|     PVPB Vpb = IrpSp->Parameters.MountVolume.Vpb; | ||||
|     PDEVICE_OBJECT FsvrtDeviceObject = Vpb->RealDevice; | ||||
|     PDEVICE_OBJECT FsvolDeviceObject; | ||||
|  | ||||
|     /* check the passed in volume object; it must be one of our own */ | ||||
|     Result = FspDeviceOwned(DeviceObject->DriverObject, FsvrtDeviceObject); | ||||
|     Result = FspDeviceOwned(FsvrtDeviceObject); | ||||
|     if (!NT_SUCCESS(Result)) | ||||
|     { | ||||
|         if (STATUS_NO_SUCH_DEVICE == Result) | ||||
| @@ -151,18 +132,17 @@ static NTSTATUS FspFsctlMountVolume( | ||||
|     ExAcquireResourceExclusiveLite(&FsctlDeviceExtension->Base.Resource, TRUE); | ||||
|  | ||||
|     /* create the file system device object */ | ||||
|     Result = IoCreateDevice(DeviceObject->DriverObject, | ||||
|         sizeof(FSP_FSVOL_DEVICE_EXTENSION), 0, DeviceObject->DeviceType, | ||||
|         0, FALSE, | ||||
|     Result = FspDeviceCreate(FspFsvolDeviceExtensionKind, 0, | ||||
|         DeviceObject->DeviceType, | ||||
|         &FsvolDeviceObject); | ||||
|     if (NT_SUCCESS(Result)) | ||||
|     { | ||||
|         FsvrtDeviceExtension = FspFsvrtDeviceExtension(FsvrtDeviceObject); | ||||
|         FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject); | ||||
| #pragma prefast(suppress:28175, "We are a filesystem: ok to access SectorSize") | ||||
|         FsvolDeviceObject->SectorSize = | ||||
|             FspFsvrtDeviceExtension(FsvrtDeviceObject)->VolumeParams.SectorSize; | ||||
|         FspDeviceInitExtension(FsvolDeviceObject, FspFsvolDeviceExtensionKind); | ||||
|         FSP_FSVOL_DEVICE_EXTENSION *FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject); | ||||
|         FsvolDeviceObject->SectorSize = FsvrtDeviceExtension->VolumeParams.SectorSize; | ||||
|         FsvolDeviceExtension->FsvrtDeviceObject = FsvrtDeviceObject; | ||||
|         FsvrtDeviceExtension->FsvolDeviceObject = FsvolDeviceObject; | ||||
|         ClearFlag(FsvolDeviceObject->Flags, DO_DEVICE_INITIALIZING); | ||||
|         Vpb->DeviceObject = FsvolDeviceObject; | ||||
|         Irp->IoStatus.Information = 0; | ||||
| @@ -183,6 +163,8 @@ static NTSTATUS FspFsvrtDeleteVolume( | ||||
|         FspFsvrtDeviceExtension(DeviceObject); | ||||
|     FSP_FSCTL_DEVICE_EXTENSION *FsctlDeviceExtension = | ||||
|         FspFsctlDeviceExtension(FsvrtDeviceExtension->FsctlDeviceObject); | ||||
|     PVPB OldVpb; | ||||
|     KIRQL Irql; | ||||
|  | ||||
|     /* access check */ | ||||
|     Result = FspSecuritySubjectContextAccessCheck( | ||||
| @@ -196,8 +178,8 @@ static NTSTATUS FspFsvrtDeleteVolume( | ||||
|     FspIoqStop(&FsvrtDeviceExtension->Ioq); | ||||
|  | ||||
|     /* swap the preallocated VPB */ | ||||
|     PVPB OldVpb; | ||||
|     KIRQL Irql; | ||||
| #pragma prefast(push) | ||||
| #pragma prefast(disable:28175, "We are a filesystem: ok to access Vpb") | ||||
|     IoAcquireVpbSpinLock(&Irql); | ||||
|     OldVpb = DeviceObject->Vpb; | ||||
|     if (0 != OldVpb) | ||||
| @@ -211,21 +193,17 @@ static NTSTATUS FspFsvrtDeleteVolume( | ||||
|         FsvrtDeviceExtension->SwapVpb = 0; | ||||
|     } | ||||
|     IoReleaseVpbSpinLock(Irql); | ||||
| #pragma prefast(pop) | ||||
|  | ||||
|     /* delete the file system device object */ | ||||
|     if (0 != OldVpb && 0 != OldVpb->DeviceObject && | ||||
|         FspDeviceOwned(DeviceObject->DriverObject, OldVpb->DeviceObject)) | ||||
|     { | ||||
|         ASSERT(FspFsvolDeviceExtensionKind == FspDeviceExtension(OldVpb->DeviceObject)->Kind); | ||||
|         FspDeviceDeleteObject(OldVpb->DeviceObject); | ||||
|     } | ||||
|  | ||||
|     /* delete the virtual volume device */ | ||||
|     FspDeviceDeleteObject(DeviceObject); | ||||
|     /* release the file system device and virtual volume objects */ | ||||
|     PDEVICE_OBJECT FsvolDeviceObject = FsvrtDeviceExtension->FsvolDeviceObject; | ||||
|     FsvrtDeviceExtension->FsvolDeviceObject = 0; | ||||
|     FspDeviceRelease(FsvolDeviceObject); | ||||
|     FspDeviceRelease(DeviceObject); | ||||
|  | ||||
|     ExReleaseResourceLite(&FsctlDeviceExtension->Base.Resource); | ||||
|  | ||||
|     return STATUS_INVALID_DEVICE_REQUEST; | ||||
|     return STATUS_SUCCESS; | ||||
| } | ||||
|  | ||||
| static NTSTATUS FspFsvrtTransact( | ||||
|   | ||||
| @@ -24,10 +24,14 @@ VOID FspIopCompleteRequest(PIRP Irp, NTSTATUS Result) | ||||
|         Irp->Tail.Overlay.DriverContext[0] = 0; | ||||
|     } | ||||
|  | ||||
|     PDEVICE_OBJECT DeviceObject = IoGetCurrentIrpStackLocation(Irp)->DeviceObject; | ||||
|  | ||||
|     if (!NT_SUCCESS(Result)) | ||||
|         Irp->IoStatus.Information = 0; | ||||
|     Irp->IoStatus.Status = Result; | ||||
|     IoCompleteRequest(Irp, FSP_IO_INCREMENT); | ||||
|  | ||||
|     FspDeviceRelease(DeviceObject); | ||||
| } | ||||
|  | ||||
| VOID FspIopDispatchComplete(PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user