sys: device extension reference count

This commit is contained in:
Bill Zissimopoulos
2015-11-30 00:35:28 -08:00
parent 7bd979a3fd
commit 7c3d69f63b
5 changed files with 314 additions and 159 deletions

View File

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