mirror of
https://github.com/winfsp/winfsp.git
synced 2025-04-23 08:53:01 -05:00
sys: implement FsvrtDeviceExpirationRoutine and supporting infra
This commit is contained in:
parent
ec0e8548b5
commit
460c4e0c55
122
src/sys/device.c
122
src/sys/device.c
@ -13,17 +13,23 @@ NTSTATUS FspDeviceCreateSecure(UINT32 Kind, ULONG ExtraSize,
|
|||||||
NTSTATUS FspDeviceCreate(UINT32 Kind, ULONG ExtraSize,
|
NTSTATUS FspDeviceCreate(UINT32 Kind, ULONG ExtraSize,
|
||||||
DEVICE_TYPE DeviceType,
|
DEVICE_TYPE DeviceType,
|
||||||
PDEVICE_OBJECT *PDeviceObject);
|
PDEVICE_OBJECT *PDeviceObject);
|
||||||
|
VOID FspDeviceInitComplete(PDEVICE_OBJECT DeviceObject);
|
||||||
VOID FspDeviceDelete(PDEVICE_OBJECT DeviceObject);
|
VOID FspDeviceDelete(PDEVICE_OBJECT DeviceObject);
|
||||||
static NTSTATUS FspFsctlDeviceInit(PDEVICE_OBJECT DeviceObject);
|
static NTSTATUS FspFsctlDeviceInit(PDEVICE_OBJECT DeviceObject);
|
||||||
|
static VOID FspFsctlDeviceInitComplete(PDEVICE_OBJECT DeviceObject);
|
||||||
static VOID FspFsctlDeviceFini(PDEVICE_OBJECT DeviceObject);
|
static VOID FspFsctlDeviceFini(PDEVICE_OBJECT DeviceObject);
|
||||||
static NTSTATUS FspFsvrtDeviceInit(PDEVICE_OBJECT DeviceObject);
|
static NTSTATUS FspFsvrtDeviceInit(PDEVICE_OBJECT DeviceObject);
|
||||||
|
static VOID FspFsvrtDeviceInitComplete(PDEVICE_OBJECT DeviceObject);
|
||||||
static VOID FspFsvrtDeviceFini(PDEVICE_OBJECT DeviceObject);
|
static VOID FspFsvrtDeviceFini(PDEVICE_OBJECT DeviceObject);
|
||||||
static NTSTATUS FspFsvolDeviceInit(PDEVICE_OBJECT DeviceObject);
|
static NTSTATUS FspFsvolDeviceInit(PDEVICE_OBJECT DeviceObject);
|
||||||
|
static VOID FspFsvolDeviceInitComplete(PDEVICE_OBJECT DeviceObject);
|
||||||
static VOID FspFsvolDeviceFini(PDEVICE_OBJECT DeviceObject);
|
static VOID FspFsvolDeviceFini(PDEVICE_OBJECT DeviceObject);
|
||||||
BOOLEAN FspDeviceRetain(PDEVICE_OBJECT DeviceObject);
|
BOOLEAN FspDeviceRetain(PDEVICE_OBJECT DeviceObject);
|
||||||
VOID FspDeviceRelease(PDEVICE_OBJECT DeviceObject);
|
VOID FspDeviceRelease(PDEVICE_OBJECT DeviceObject);
|
||||||
VOID FspFsctlDeviceVolumeCreated(PDEVICE_OBJECT DeviceObject);
|
VOID FspFsctlDeviceVolumeCreated(PDEVICE_OBJECT DeviceObject);
|
||||||
VOID FspFsctlDeviceVolumeDeleted(PDEVICE_OBJECT DeviceObject);
|
VOID FspFsctlDeviceVolumeDeleted(PDEVICE_OBJECT DeviceObject);
|
||||||
|
static IO_TIMER_ROUTINE FspFsvrtDeviceTimerRoutine;
|
||||||
|
static WORKER_THREAD_ROUTINE FspFsvrtDeviceExpirationRoutine;
|
||||||
PVOID FspFsvolDeviceLookupContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier);
|
PVOID FspFsvolDeviceLookupContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier);
|
||||||
PVOID FspFsvolDeviceInsertContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier, PVOID Context,
|
PVOID FspFsvolDeviceInsertContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier, PVOID Context,
|
||||||
FSP_DEVICE_GENERIC_TABLE_ELEMENT *ElementStorage, PBOOLEAN PInserted);
|
FSP_DEVICE_GENERIC_TABLE_ELEMENT *ElementStorage, PBOOLEAN PInserted);
|
||||||
@ -41,12 +47,16 @@ VOID FspDeviceDeleteAll(VOID);
|
|||||||
#ifdef ALLOC_PRAGMA
|
#ifdef ALLOC_PRAGMA
|
||||||
#pragma alloc_text(PAGE, FspDeviceCreateSecure)
|
#pragma alloc_text(PAGE, FspDeviceCreateSecure)
|
||||||
#pragma alloc_text(PAGE, FspDeviceCreate)
|
#pragma alloc_text(PAGE, FspDeviceCreate)
|
||||||
|
#pragma alloc_text(PAGE, FspDeviceInitComplete)
|
||||||
#pragma alloc_text(PAGE, FspDeviceDelete)
|
#pragma alloc_text(PAGE, FspDeviceDelete)
|
||||||
#pragma alloc_text(PAGE, FspFsctlDeviceInit)
|
#pragma alloc_text(PAGE, FspFsctlDeviceInit)
|
||||||
|
#pragma alloc_text(PAGE, FspFsctlDeviceInitComplete)
|
||||||
#pragma alloc_text(PAGE, FspFsctlDeviceFini)
|
#pragma alloc_text(PAGE, FspFsctlDeviceFini)
|
||||||
#pragma alloc_text(PAGE, FspFsvrtDeviceInit)
|
#pragma alloc_text(PAGE, FspFsvrtDeviceInit)
|
||||||
|
#pragma alloc_text(PAGE, FspFsvrtDeviceInitComplete)
|
||||||
#pragma alloc_text(PAGE, FspFsvrtDeviceFini)
|
#pragma alloc_text(PAGE, FspFsvrtDeviceFini)
|
||||||
#pragma alloc_text(PAGE, FspFsvolDeviceInit)
|
#pragma alloc_text(PAGE, FspFsvolDeviceInit)
|
||||||
|
#pragma alloc_text(PAGE, FspFsvolDeviceInitComplete)
|
||||||
#pragma alloc_text(PAGE, FspFsvolDeviceFini)
|
#pragma alloc_text(PAGE, FspFsvolDeviceFini)
|
||||||
#pragma alloc_text(PAGE, FspFsctlDeviceVolumeCreated)
|
#pragma alloc_text(PAGE, FspFsctlDeviceVolumeCreated)
|
||||||
#pragma alloc_text(PAGE, FspFsctlDeviceVolumeDeleted)
|
#pragma alloc_text(PAGE, FspFsctlDeviceVolumeDeleted)
|
||||||
@ -142,6 +152,31 @@ NTSTATUS FspDeviceCreate(UINT32 Kind, ULONG ExtraSize,
|
|||||||
return FspDeviceCreateSecure(Kind, ExtraSize, 0, DeviceType, 0, 0, PDeviceObject);
|
return FspDeviceCreateSecure(Kind, ExtraSize, 0, DeviceType, 0, 0, PDeviceObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID FspDeviceInitComplete(PDEVICE_OBJECT DeviceObject)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
FSP_DEVICE_EXTENSION *DeviceExtension = FspDeviceExtension(DeviceObject);
|
||||||
|
|
||||||
|
switch (DeviceExtension->Kind)
|
||||||
|
{
|
||||||
|
case FspFsvolDeviceExtensionKind:
|
||||||
|
FspFsvolDeviceInitComplete(DeviceObject);
|
||||||
|
break;
|
||||||
|
case FspFsvrtDeviceExtensionKind:
|
||||||
|
FspFsvrtDeviceInitComplete(DeviceObject);
|
||||||
|
break;
|
||||||
|
case FspFsctlDeviceExtensionKind:
|
||||||
|
FspFsctlDeviceInitComplete(DeviceObject);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ASSERT(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClearFlag(DeviceObject->Flags, DO_DEVICE_INITIALIZING);
|
||||||
|
}
|
||||||
|
|
||||||
VOID FspDeviceDelete(PDEVICE_OBJECT DeviceObject)
|
VOID FspDeviceDelete(PDEVICE_OBJECT DeviceObject)
|
||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
@ -176,6 +211,11 @@ static NTSTATUS FspFsctlDeviceInit(PDEVICE_OBJECT DeviceObject)
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VOID FspFsctlDeviceInitComplete(PDEVICE_OBJECT DeviceObject)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
}
|
||||||
|
|
||||||
static VOID FspFsctlDeviceFini(PDEVICE_OBJECT DeviceObject)
|
static VOID FspFsctlDeviceFini(PDEVICE_OBJECT DeviceObject)
|
||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
@ -185,9 +225,18 @@ static NTSTATUS FspFsvrtDeviceInit(PDEVICE_OBJECT DeviceObject)
|
|||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
|
NTSTATUS Result;
|
||||||
FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(DeviceObject);
|
FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(DeviceObject);
|
||||||
|
|
||||||
|
/* initialize our timer routine */
|
||||||
|
Result = IoInitializeTimer(DeviceObject, FspFsvrtDeviceTimerRoutine, 0);
|
||||||
|
if (!NT_SUCCESS(Result))
|
||||||
|
return Result;
|
||||||
|
|
||||||
FspIoqInitialize(&FsvrtDeviceExtension->Ioq);
|
FspIoqInitialize(&FsvrtDeviceExtension->Ioq);
|
||||||
|
KeInitializeSpinLock(&FsvrtDeviceExtension->ExpirationLock);
|
||||||
|
ExInitializeWorkItem(&FsvrtDeviceExtension->ExpirationWorkItem,
|
||||||
|
FspFsvrtDeviceExpirationRoutine, DeviceObject);
|
||||||
|
|
||||||
FsvrtDeviceExtension->SwapVpb = FspAllocNonPagedExternal(sizeof *FsvrtDeviceExtension->SwapVpb);
|
FsvrtDeviceExtension->SwapVpb = FspAllocNonPagedExternal(sizeof *FsvrtDeviceExtension->SwapVpb);
|
||||||
if (0 == FsvrtDeviceExtension->SwapVpb)
|
if (0 == FsvrtDeviceExtension->SwapVpb)
|
||||||
@ -197,12 +246,28 @@ static NTSTATUS FspFsvrtDeviceInit(PDEVICE_OBJECT DeviceObject)
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VOID FspFsvrtDeviceInitComplete(PDEVICE_OBJECT DeviceObject)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
|
||||||
|
IoStartTimer(DeviceObject);
|
||||||
|
}
|
||||||
|
|
||||||
static VOID FspFsvrtDeviceFini(PDEVICE_OBJECT DeviceObject)
|
static VOID FspFsvrtDeviceFini(PDEVICE_OBJECT DeviceObject)
|
||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(DeviceObject);
|
FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(DeviceObject);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* First things first: stop our timer.
|
||||||
|
*
|
||||||
|
* Our IoTimer routine will NOT be called again after IoStopTimer() returns.
|
||||||
|
* However a work item may be in flight. For this reason our IoTimer routine
|
||||||
|
* does an ObReferenceObject() on our DeviceObject before queueing work items.
|
||||||
|
*/
|
||||||
|
IoStopTimer(DeviceObject);
|
||||||
|
|
||||||
if (0 != FsvrtDeviceExtension->SwapVpb)
|
if (0 != FsvrtDeviceExtension->SwapVpb)
|
||||||
FspFreeExternal(FsvrtDeviceExtension->SwapVpb);
|
FspFreeExternal(FsvrtDeviceExtension->SwapVpb);
|
||||||
}
|
}
|
||||||
@ -219,6 +284,11 @@ static NTSTATUS FspFsvolDeviceInit(PDEVICE_OBJECT DeviceObject)
|
|||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VOID FspFsvolDeviceInitComplete(PDEVICE_OBJECT DeviceObject)
|
||||||
|
{
|
||||||
|
PAGED_CODE();
|
||||||
|
}
|
||||||
|
|
||||||
static VOID FspFsvolDeviceFini(PDEVICE_OBJECT DeviceObject)
|
static VOID FspFsvolDeviceFini(PDEVICE_OBJECT DeviceObject)
|
||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
@ -314,6 +384,58 @@ VOID FspFsctlDeviceVolumeDeleted(PDEVICE_OBJECT DeviceObject)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VOID FspFsvrtDeviceTimerRoutine(PDEVICE_OBJECT DeviceObject, PVOID Context)
|
||||||
|
{
|
||||||
|
// !PAGED_CODE();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This routine runs at DPC level. Reference our DeviceObject and queue a work item
|
||||||
|
* so that we can do our processing at Passive level. Only do so if the work item
|
||||||
|
* is not already in flight (otherwise we could requeue the same work item).
|
||||||
|
*/
|
||||||
|
|
||||||
|
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
|
||||||
|
|
||||||
|
FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(DeviceObject);
|
||||||
|
|
||||||
|
KeAcquireSpinLockAtDpcLevel(&FsvrtDeviceExtension->ExpirationLock);
|
||||||
|
if (!FsvrtDeviceExtension->ExpirationInProgress)
|
||||||
|
{
|
||||||
|
FsvrtDeviceExtension->ExpirationInProgress = TRUE;
|
||||||
|
ObReferenceObject(DeviceObject);
|
||||||
|
ExQueueWorkItem(&FsvrtDeviceExtension->ExpirationWorkItem, DelayedWorkQueue);
|
||||||
|
}
|
||||||
|
KeReleaseSpinLockFromDpcLevel(&FsvrtDeviceExtension->ExpirationLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID FspFsvrtDeviceExpirationRoutine(PVOID Context)
|
||||||
|
{
|
||||||
|
// !PAGED_CODE();
|
||||||
|
|
||||||
|
PDEVICE_OBJECT DeviceObject = Context;
|
||||||
|
if (FspDeviceRetain(DeviceObject))
|
||||||
|
try
|
||||||
|
{
|
||||||
|
FSP_FSVRT_DEVICE_EXTENSION *FsvrtDeviceExtension = FspFsvrtDeviceExtension(DeviceObject);
|
||||||
|
LARGE_INTEGER Timeout;
|
||||||
|
KIRQL Irql;
|
||||||
|
|
||||||
|
Timeout.QuadPart = FsvrtDeviceExtension->VolumeParams.IrpTimeout * 10000;
|
||||||
|
/* convert millis to nanos */
|
||||||
|
FspIoqRemoveExpired(&FsvrtDeviceExtension->Ioq, &Timeout);
|
||||||
|
|
||||||
|
KeAcquireSpinLock(&FsvrtDeviceExtension->ExpirationLock, &Irql);
|
||||||
|
FsvrtDeviceExtension->ExpirationInProgress = FALSE;
|
||||||
|
KeReleaseSpinLock(&FsvrtDeviceExtension->ExpirationLock, Irql);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
FspDeviceRelease(DeviceObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
ObDereferenceObject(DeviceObject);
|
||||||
|
}
|
||||||
|
|
||||||
PVOID FspFsvolDeviceLookupContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier)
|
PVOID FspFsvolDeviceLookupContext(PDEVICE_OBJECT DeviceObject, UINT64 Identifier)
|
||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
@ -39,6 +39,8 @@ NTSTATUS DriverEntry(
|
|||||||
&FspFsctlNetDeviceObject);
|
&FspFsctlNetDeviceObject);
|
||||||
if (!NT_SUCCESS(Result))
|
if (!NT_SUCCESS(Result))
|
||||||
FSP_RETURN(FspDeviceDelete(FspFsctlDiskDeviceObject));
|
FSP_RETURN(FspDeviceDelete(FspFsctlDiskDeviceObject));
|
||||||
|
FspDeviceInitComplete(FspFsctlDiskDeviceObject);
|
||||||
|
FspDeviceInitComplete(FspFsctlNetDeviceObject);
|
||||||
|
|
||||||
/* setup the driver object */
|
/* setup the driver object */
|
||||||
DriverObject->DriverUnload = FspUnload;
|
DriverObject->DriverUnload = FspUnload;
|
||||||
|
@ -318,6 +318,9 @@ typedef struct
|
|||||||
PDEVICE_OBJECT FsvolDeviceObject;
|
PDEVICE_OBJECT FsvolDeviceObject;
|
||||||
FSP_FSCTL_VOLUME_PARAMS VolumeParams;
|
FSP_FSCTL_VOLUME_PARAMS VolumeParams;
|
||||||
FSP_IOQ Ioq;
|
FSP_IOQ Ioq;
|
||||||
|
KSPIN_LOCK ExpirationLock;
|
||||||
|
WORK_QUEUE_ITEM ExpirationWorkItem;
|
||||||
|
BOOLEAN ExpirationInProgress;
|
||||||
PVPB SwapVpb;
|
PVPB SwapVpb;
|
||||||
BOOLEAN Deleted;
|
BOOLEAN Deleted;
|
||||||
FSP_FSCTL_DECLSPEC_ALIGN UINT8 SecurityDescriptorBuf[];
|
FSP_FSCTL_DECLSPEC_ALIGN UINT8 SecurityDescriptorBuf[];
|
||||||
@ -369,6 +372,7 @@ NTSTATUS FspDeviceCreateSecure(UINT32 Kind, ULONG ExtraSize,
|
|||||||
NTSTATUS FspDeviceCreate(UINT32 Kind, ULONG ExtraSize,
|
NTSTATUS FspDeviceCreate(UINT32 Kind, ULONG ExtraSize,
|
||||||
DEVICE_TYPE DeviceType,
|
DEVICE_TYPE DeviceType,
|
||||||
PDEVICE_OBJECT *PDeviceObject);
|
PDEVICE_OBJECT *PDeviceObject);
|
||||||
|
VOID FspDeviceInitComplete(PDEVICE_OBJECT DeviceObject);
|
||||||
VOID FspDeviceDelete(PDEVICE_OBJECT DeviceObject);
|
VOID FspDeviceDelete(PDEVICE_OBJECT DeviceObject);
|
||||||
BOOLEAN FspDeviceRetain(PDEVICE_OBJECT DeviceObject);
|
BOOLEAN FspDeviceRetain(PDEVICE_OBJECT DeviceObject);
|
||||||
VOID FspDeviceRelease(PDEVICE_OBJECT DeviceObject);
|
VOID FspDeviceRelease(PDEVICE_OBJECT DeviceObject);
|
||||||
|
@ -178,7 +178,7 @@ static NTSTATUS FspFsctlCreateVolume(
|
|||||||
FsvrtDeviceExtension->VolumeParams = VolumeParams;
|
FsvrtDeviceExtension->VolumeParams = VolumeParams;
|
||||||
RtlCopyMemory(FsvrtDeviceExtension->SecurityDescriptorBuf,
|
RtlCopyMemory(FsvrtDeviceExtension->SecurityDescriptorBuf,
|
||||||
SecurityDescriptorBuf, SecurityDescriptorSize);
|
SecurityDescriptorBuf, SecurityDescriptorSize);
|
||||||
ClearFlag(FsvrtDeviceObject->Flags, DO_DEVICE_INITIALIZING);
|
FspDeviceInitComplete(FsvrtDeviceObject);
|
||||||
Irp->IoStatus.Information = DeviceName.Length + sizeof(WCHAR);
|
Irp->IoStatus.Information = DeviceName.Length + sizeof(WCHAR);
|
||||||
FspFsctlDeviceVolumeCreated(DeviceObject);
|
FspFsctlDeviceVolumeCreated(DeviceObject);
|
||||||
}
|
}
|
||||||
@ -255,7 +255,7 @@ static NTSTATUS FspFsctlMountVolume(
|
|||||||
FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
FsvolDeviceExtension = FspFsvolDeviceExtension(FsvolDeviceObject);
|
||||||
FsvolDeviceExtension->FsvrtDeviceObject = FsvrtDeviceObject;
|
FsvolDeviceExtension->FsvrtDeviceObject = FsvrtDeviceObject;
|
||||||
FsvrtDeviceExtension->FsvolDeviceObject = FsvolDeviceObject;
|
FsvrtDeviceExtension->FsvolDeviceObject = FsvolDeviceObject;
|
||||||
ClearFlag(FsvolDeviceObject->Flags, DO_DEVICE_INITIALIZING);
|
FspDeviceInitComplete(FsvolDeviceObject);
|
||||||
Vpb->DeviceObject = FsvolDeviceObject;
|
Vpb->DeviceObject = FsvolDeviceObject;
|
||||||
Vpb->SerialNumber = FsvrtDeviceExtension->VolumeParams.SerialNumber;
|
Vpb->SerialNumber = FsvrtDeviceExtension->VolumeParams.SerialNumber;
|
||||||
Irp->IoStatus.Information = 0;
|
Irp->IoStatus.Information = 0;
|
||||||
|
@ -238,7 +238,11 @@ VOID FspIoqRemoveExpired(FSP_IOQ *Ioq, PLARGE_INTEGER Timeout)
|
|||||||
{
|
{
|
||||||
FSP_IOQ_PEEK_CONTEXT PeekContext;
|
FSP_IOQ_PEEK_CONTEXT PeekContext;
|
||||||
PeekContext.IrpHint = 0;
|
PeekContext.IrpHint = 0;
|
||||||
PeekContext.ExpirationTime = KeQueryInterruptTime() - Timeout->QuadPart;
|
PeekContext.ExpirationTime = KeQueryInterruptTime();
|
||||||
|
if (PeekContext.ExpirationTime >= (ULONGLONG)Timeout->QuadPart)
|
||||||
|
PeekContext.ExpirationTime -= Timeout->QuadPart;
|
||||||
|
else
|
||||||
|
PeekContext.ExpirationTime = 0;
|
||||||
PIRP Irp;
|
PIRP Irp;
|
||||||
while (0 != (Irp = IoCsqRemoveNextIrp(&Ioq->PendingIoCsq, &PeekContext)))
|
while (0 != (Irp = IoCsqRemoveNextIrp(&Ioq->PendingIoCsq, &PeekContext)))
|
||||||
FspIoqPendingCompleteCanceledIrp(&Ioq->PendingIoCsq, Irp);
|
FspIoqPendingCompleteCanceledIrp(&Ioq->PendingIoCsq, Irp);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user