📄 queue.c
字号:
// CharSample_DDKQueueCancelRoutine
// Cancel routine used for queue IRPs while in the queue
//
// Arguments:
// IN DeviceObject
// Device object for our device
//
// IN Irp
// IRP to be cancelled
//
// Return Value:
// none
//
VOID CharSample_DDKQueueCancelRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
KIRQL oldIrql;
PCHARSAMPLE_DDK_QUEUE queue;
// release the system cancel spinlock
oldIrql = Irp->CancelIrql;
IoReleaseCancelSpinLock(DISPATCH_LEVEL);
// get our queue from the IRP
queue = (PCHARSAMPLE_DDK_QUEUE)Irp->Tail.Overlay.DriverContext[0];
ASSERT(queue != NULL);
// grab the queue protection
KeAcquireSpinLockAtDpcLevel(&queue->QueueLock);
// remove our IRP from the queue
RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
// drop the queue protection
KeReleaseSpinLock(&queue->QueueLock, oldIrql);
// cancel the IRP
Irp->IoStatus.Status = STATUS_CANCELLED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// Cancel Safe IRP List
///////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
// CharSample_DDKInitializeList
// Sets up a cancel safe IRP list.
//
// Arguments:
// IN List
// An instance of our list structure
//
// IN DeviceObject
// Device object for our driver
//
// Return Value:
// none
//
VOID CharSample_DDKInitializeList(
IN PCHARSAMPLE_DDK_LIST List,
IN PDEVICE_OBJECT DeviceObject
)
{
// save off the user info
List->DeviceObject = DeviceObject;
// initialize our queue lock
KeInitializeSpinLock(&List->ListLock);
// initialize our IRP list
InitializeListHead(&List->IrpList);
List->ErrorStatus = STATUS_SUCCESS;
return;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// CharSample_DDKInsertHead
// Puts Irp entry at head of list
//
// Arguments:
// IN List
// An instance of our list structure
//
// IN Irp
// IRP to be put in list
//
// Return Value:
// Status
//
NTSTATUS CharSample_DDKInsertHead(
IN PCHARSAMPLE_DDK_LIST List,
IN PIRP Irp
)
{
NTSTATUS status;
KIRQL oldIrql;
PCHARSAMPLE_DDK_DEVICE_EXTENSION deviceExtension;
deviceExtension = (PCHARSAMPLE_DDK_DEVICE_EXTENSION)List->DeviceObject->DeviceExtension;
// Grab the list protection
KeAcquireSpinLock(&List->ListLock, &oldIrql);
if (List->ErrorStatus != STATUS_SUCCESS)
{
status = List->ErrorStatus;
// drop the queue protection
KeReleaseSpinLock(&List->ListLock, oldIrql);
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
// put our list pointer into the IRP
Irp->Tail.Overlay.DriverContext[0] = List;
// put the entry at the head of the list
InsertHeadList(&List->IrpList, &Irp->Tail.Overlay.ListEntry);
// set cancel routine
IoSetCancelRoutine(Irp, CharSample_DDKListCancelRoutine);
// Make sure the IRP was not cancelled before
// we inserted our cancel routine
if (Irp->Cancel)
{
// If the IRP was cancelled after we put in our cancel routine we
// will get back NULL here and we will let the cancel routine handle
// the IRP. If NULL is not returned here then we know the IRP was
// cancelled before we inserted the cancel routine, and we
// need to cancel the IRP
if (IoSetCancelRoutine(Irp, NULL) != NULL)
{
RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
// drop the list protection
KeReleaseSpinLock(&List->ListLock, oldIrql);
// cancel the IRP
status = STATUS_CANCELLED;
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
}
// mark irp pending since STATUS_PENDING is returned
IoMarkIrpPending(Irp);
status = STATUS_PENDING;
// drop the list protection
KeReleaseSpinLock(&List->ListLock, oldIrql);
return status;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// CharSample_DDKInsertTail
// Puts Irp entry at end of list
//
// Arguments:
// IN List
// An instance of our list structure
//
// IN Irp
// IRP to be put in list
//
// Return Value:
// Status
//
NTSTATUS CharSample_DDKInsertTail(
IN PCHARSAMPLE_DDK_LIST List,
IN PIRP Irp
)
{
NTSTATUS status;
KIRQL oldIrql;
PCHARSAMPLE_DDK_DEVICE_EXTENSION deviceExtension;
deviceExtension = (PCHARSAMPLE_DDK_DEVICE_EXTENSION)List->DeviceObject->DeviceExtension;
// Grab the list protection
KeAcquireSpinLock(&List->ListLock, &oldIrql);
if (List->ErrorStatus != STATUS_SUCCESS)
{
status = List->ErrorStatus;
// drop the queue protection
KeReleaseSpinLock(&List->ListLock, oldIrql);
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
// put our list pointer into the IRP
Irp->Tail.Overlay.DriverContext[0] = (PVOID)List;
// put the entry at the head of the list
InsertHeadList(&List->IrpList, &Irp->Tail.Overlay.ListEntry);
// set cancel routine
IoSetCancelRoutine(Irp, CharSample_DDKListCancelRoutine);
// Make sure the IRP was not cancelled before
// we inserted our cancel routine
if (Irp->Cancel)
{
// If the IRP was cancelled after we put in our cancel routine we
// will get back NULL here and we will let the cancel routine handle
// the IRP. If NULL is not returned here then we know the IRP was
// cancelled before we inserted the cancel routine, and we
// need to cancel the IRP
if (IoSetCancelRoutine(Irp, NULL) != NULL)
{
RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
// drop the list protection
KeReleaseSpinLock(&List->ListLock, oldIrql);
// cancel the IRP
status = STATUS_CANCELLED;
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
}
// mark irp pending since STATUS_PENDING is returned
IoMarkIrpPending(Irp);
status = STATUS_PENDING;
// drop the list protection
KeReleaseSpinLock(&List->ListLock, oldIrql);
return status;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// CharSample_DDKRemoveHead
// Removes an Irp entry from the head of list
//
// Arguments:
// IN List
// An instance of our list structure
//
// Return Value:
// IRP removed from head of list
//
PIRP CharSample_DDKRemoveHead(
IN PCHARSAMPLE_DDK_LIST List
)
{
PLIST_ENTRY entry;
PIRP irp;
KIRQL oldIrql;
// Grab the list protection
KeAcquireSpinLock(&List->ListLock, &oldIrql);
// Make sure there are entries in the list
if (IsListEmpty(&List->IrpList))
{
// drop the list protection
KeReleaseSpinLock(&List->ListLock, oldIrql);
return NULL;
}
// get a new IRP from the queue
for (entry = List->IrpList.Flink; entry != &List->IrpList; entry = entry->Flink)
{
// get our IRP from the entry
irp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.ListEntry);
ASSERT(irp->Type == IO_TYPE_IRP);
// if we found an IRP, pull the queue cancel routine out of it
// See if the IRP is canceled
if (IoSetCancelRoutine(irp, NULL) == NULL)
{
// cancel routine already has a hold on this IRP,
// just go on to the next one
irp = NULL;
}
else
{
// Found a usable IRP, pull the entry out of the list
RemoveEntryList(entry);
break;
}
}
// drop the list protection
KeReleaseSpinLock(&List->ListLock, oldIrql);
return irp;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// CharSample_DDKRemoveTail
// Removes an Irp entry from the tail of list
//
// Arguments:
// IN List
// An instance of our list structure
//
// Return Value:
// IRP removed from end of list
//
PIRP CharSample_DDKRemoveTail(
IN PCHARSAMPLE_DDK_LIST List
)
{
PLIST_ENTRY entry;
PIRP irp;
KIRQL oldIrql;
// Grab the list protection
KeAcquireSpinLock(&List->ListLock, &oldIrql);
// Make sure there are entries in the list
if (IsListEmpty(&List->IrpList))
{
// drop the list protection
KeReleaseSpinLock(&List->ListLock, oldIrql);
return NULL;
}
// get a new IRP from the queue
for (entry = List->IrpList.Blink; entry != &List->IrpList; entry = entry->Blink)
{
// get our IRP from the entry
irp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.ListEntry);
ASSERT(irp->Type == IO_TYPE_IRP);
// if we found an IRP, pull the queue cancel routine out of it
// See if the IRP is canceled
if (IoSetCancelRoutine(irp, NULL) == NULL)
{
// cancel routine already has a hold on this IRP,
// just go on to the next one
irp = NULL;
}
else
{
// Found a usable IRP, pull the entry out of the list
RemoveEntryList(entry);
break;
}
}
// drop the list protection
KeReleaseSpinLock(&List->ListLock, oldIrql);
return irp;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// CharSample_DDKFlushList
// Cancels all IRPs in the list, or all IRPs in the list related to a
// particular open handle.
//
// Arguments:
// IN List
// An instance of our list structure
//
// IN FileObject
// If NULL all IRPs in list are cancelled, if non-NULL then all
// IRPs related to this file object are cancelled.
//
// Return Value:
// none
//
VOID CharSample_DDKFlushList(
IN PCHARSAMPLE_DDK_LIST List,
IN PFILE_OBJECT FileObject
)
{
PLIST_ENTRY entry;
PLIST_ENTRY nextEntry;
PIRP irp;
PIO_STACK_LOCATION irpStack;
KIRQL oldIrql;
LIST_ENTRY cancelList;
// initialize our cancel list
InitializeListHead(&cancelList);
// grab the list protection
KeAcquireSpinLock(&List->ListLock, &oldIrql);
// Look at the first entry in the list
entry = List->IrpList.Flink;
while (entry != &List->IrpList)
{
// get the next list entry
nextEntry = entry->Flink;
// Get the IRP from the entry
irp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.ListEntry);
ASSERT(irp->Type == IO_TYPE_IRP);
// Determine if we need to pull out of list
if (FileObject != NULL)
{
// get the current IRP stack location from the IRP
irpStack = IoGetCurrentIrpStackLocation(irp);
if (irpStack->FileObject != FileObject)
{
// go to the next entry
entry = nextEntry;
// We are not flushing this IRP
continue;
}
}
// Attempt to cancel the IRP
if (IoSetCancelRoutine(irp, NULL) == NULL)
{
// go to the next entry
entry = nextEntry;
// cancel routine already has this IRP,
// just go on
continue;
}
// pull the IRP from the list
RemoveEntryList(entry);
InsertTailList(&cancelList, entry);
// go to the next entry
entry = nextEntry;
}
// drop the list protection
KeReleaseSpinLock(&List->ListLock, oldIrql);
// Now clear out our cancel list
while (!IsListEmpty(&cancelList))
{
// Get the first entry on the list
entry = RemoveHeadList(&cancelList);
// Get the IRP for that entry
irp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.ListEntry);
// Cancel the IRP
irp->IoStatus.Status = STATUS_CANCELLED;
irp->IoStatus.Information = 0;
IoCompleteRequest(irp, IO_NO_INCREMENT);
}
return;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// CharSample_DDKInvalidateList
// Stops list from receiving anymore IRPs, all IRPs are completed upon
// receipt
//
// Arguments:
// IN List
// An instance of our list structure
//
// Return Value:
// none
//
VOID CharSample_DDKInvalidateList(
IN PCHARSAMPLE_DDK_LIST List,
IN NTSTATUS ErrorStatus
)
{
// indicate the list is shutdown
List->ErrorStatus = ErrorStatus;
// flush all requests from the list
CharSample_DDKFlushList(List, NULL);
return;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// CharSample_DDKListCancelRoutine
// Cancel routine used for our cancel safe IRP list
//
// Arguments:
// IN DeviceObject
// Device object for our device
//
// IN Irp
// IRP to be cancelled
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -