PIRP
KeyboardClassDequeueRead(
_In_ PCHAR DeviceExtension
)
/
*
+
+
Routine Description:
Dequeues the
next
available read irp regardless of FileObject
Assumptions:
DeviceExtension
-
>SpinLock
is
already held (so no further sync
is
required).
-
-
*
/
{
ASSERT(NULL !
=
DeviceExtension);
PIRP nextIrp
=
NULL;
LIST_ENTRY
*
ReadQueue
=
(LIST_ENTRY
*
)(DeviceExtension
+
READ_QUEUE_OFFSET_DE);
while
(!nextIrp && !IsListEmpty(ReadQueue)) {
PDRIVER_CANCEL oldCancelRoutine;
PLIST_ENTRY listEntry
=
RemoveHeadList(ReadQueue);
/
/
/
/
Get the
next
IRP off the queue
and
clear the cancel routine
/
/
nextIrp
=
CONTAINING_RECORD(listEntry, IRP, Tail.Overlay.ListEntry);
oldCancelRoutine
=
IoSetCancelRoutine(nextIrp, NULL);
/
/
/
/
IoCancelIrp() could have just been called on this IRP.
/
/
What we're interested
in
is
not
whether IoCancelIrp() was called
/
/
(ie, nextIrp
-
>Cancel
is
set
), but whether IoCancelIrp() called (
or
/
/
is
about to call) our cancel routine. To check that, check the result
/
/
of the test
-
and
-
set
macro IoSetCancelRoutine.
/
/
if
(oldCancelRoutine) {
/
/
/
/
Cancel routine
not
called
for
this IRP. Return this IRP.
/
/
/
*
ASSERT(oldCancelRoutine
=
=
KeyboardClassCancel);
*
/
}
else
{
/
/
/
/
This IRP was just cancelled
and
the cancel routine was (
or
will
/
/
be) called. The cancel routine will complete this IRP as soon as
/
/
we drop the spinlock. So don't do anything with the IRP.
/
/
/
/
Also, the cancel routine will
try
to dequeue the IRP, so make the
/
/
IRP's listEntry point to itself.
/
/
/
/
ASSERT(nextIrp
-
>Cancel);
InitializeListHead(&nextIrp
-
>Tail.Overlay.ListEntry);
nextIrp
=
NULL;
}
}
return
nextIrp;
}