7.3  Requirements for Using Interlocked Queues or Device Queues

A lowest-level NT driver either must have a StartIo routine or must set up and manage its own internal queue(s) of IRPs. A higher-level NT driver can have its own internal queues of IRPs at the discretion of the driver designer.

Depending on the functionality required and the nature of the underlying device, an NT driver writer might implement a StartIo routine and set up one or more driver-managed supplemental queues for IRPs.

The system provides support for the following kinds of internal queues of IRPs that NT drivers can use:

·A doubly-linked interlocked queue into which the driver inserts IRPs by calling ExInterlockedInsertTailList or ExInterlockedInsertHeadList, and from which a device-dedicated thread, worker-thread callback, or another driver routine removes IRPs by calling ExInterlockedRemoveHeadList

·A device queue associated with a device object into which the driver can insert IRPs by calling KeInsertDeviceQueue or KeInsertByKeyDeviceQueue, and from which it can remove IRPs by calling KeRemoveDeviceQueue, KeRemoveByKeyDeviceQueue, or KeRemoveEntryDeviceQueue

If the driver has a StartIo routine, it can queue and dequeue IRPs from the device queue associated with its device object(s) by calling IoStartNextPacket or IoStartNextPacketByKey, as mentioned in Section 7.2.1.

An interlocked queue is simpler to manage, particularly for drivers with device-dedicated threads or worker-thread callbacks. On the other hand, supplemental device queues give an NT driver more control over whether a given IRP is placed in the queue and over the ordering of entries in the queue.

An NT driver should not use a singly-linked interlocked queue for IRPs.