IRP 结构体部分不透明,它代表了一个IO请求包。驱动程序可以使用结构的以下成员:
typedef struct _IRP {
.
.
PMDL MdlAddress;
ULONG Flags;
union {
struct _IRP *MasterIrp;
.
.
PVOID SystemBuffer;
} AssociatedIrp;
.
.
IO_STATUS_BLOCK IoStatus;
KPROCESSOR_MODE RequestorMode;
BOOLEAN PendingReturned;
.
.
BOOLEAN Cancel;
KIRQL CancelIrql;
.
.
PDRIVER_CANCEL CancelRoutine;
PVOID UserBuffer;
union {
struct {
.
.
union {
KDEVICE_QUEUE_ENTRY DeviceQueueEntry;
struct {
PVOID DriverContext[4];
};
};
.
.
PETHREAD Thread;
.
.
LIST_ENTRY ListEntry;
.
.
} Overlay;
.
.
} Tail;
} IRP, *PIRP;
MdlAddress
指向描述用户缓冲区的MDL指针,如果驱动程序使用直接IO,并且IRP 主功能号是以下之一:
IRP_MJ_READ
MDL 描述了一个供设备或者驱动填入的缓冲区。
IRP_MJ_WRITE
MDL 描述了要写入到设备或者驱动程序中的缓冲区。
IRP_MJ_DEVICE_CONTROL or IRP_MJ_INTERNAL_DEVICE_CONTROL
如果IOCTL code 指定了METHOD_IN_DIRECT 传输类型, MDL 描述了一个为设备和驱动提供的包含数据的缓冲区。
如果IOCTL code 指定了METHOD_OUT_DIRECT 传输类型,MDL描述了一个供设备或者驱动程序填入的空的缓冲区。
有关METHOD_IN_DIRECT 和METHOD_OUT_DIRECT传输类型关联的缓冲区信息,见Buffer Descriptions for I/O Control Codes.
如果驱动程序不使用直接IO,那么这个指针为NULL。
Flags
文件系统使用这一块,对所有的驱动程序而言都是只读的。网络和可能的高层设备驱动也可能读取这一块的数据。这块数据可能设置为0或者是按位与的以下系统定义的符号位:
IRP_NOCACHE
IRP_PAGING_IO
IRP_MOUNT_COMPLETION
IRP_SYNCHRONOUS_API
IRP_ASSOCIATED_IRP
IRP_BUFFERED_IO
IRP_DEALLOCATE_BUFFER
IRP_INPUT_OPERATION
IRP_SYNCHRONOUS_PAGING_IO
IRP_CREATE_OPERATION
IRP_READ_OPERATION
IRP_WRITE_OPERATION
IRP_CLOSE_OPERATION
IRP_DEFER_IO_COMPLETION
IRP_OB_QUERY_NAME
IRP_HOLD_DEVICE_QUEUE
IRP_UM_DRIVER_INITIATED_IO
AssociatedIrp.MasterIrp
指向高层驱动程序调用 IoMakeAssociatedIrp创建的IRP中的主IRP。
AssociatedIrp.SystemBuffer
指向系统空间的缓冲区。如果驱动程序使用了缓冲I/O,此缓冲区的目的屈居于IRP主功能号,如下所示:
IRP_MJ_READ
缓冲区从设备和驱动程序获取数据。长度由驱动程序结构中的IO_STACK_LOCATION的 Parameters.Read.Length 成员指定。
IRP_MJ_WRITE
此缓冲区用于为设备或驱动程序提供数据。驱动程序的IO_STACK_LOCATION 的 Parameters.Write.Length 成员指定了缓冲区的长度。
IRP_MJ_DEVICE_CONTROL or IRP_MJ_INTERNAL_DEVICE_CONTROL
此参数代表提供给 DeviceIoControl 和IoBuildDeviceIoControlRequest.函数的输入和输出缓冲区,输出数据覆盖输入数据。作为输入参数它的长度由驱动程序的IO_STACK_LOCATION 的成员 Parameters.DeviceIoControl.InputBufferLength 指定。作为输出参数,缓冲区的长度由驱动程序的IO_STACK_LOCATION 的成员Parameters.DeviceIoControl.OutputBufferLength指定。更多相关信息见 Buffer Descriptions for I/O Control Codes.
如果驱动程序使用的是直接 I/O, 该缓冲区的使用目的由IRP的主功能号决定。如下所示:
IRP_MJ_READ
NULL.
IRP_MJ_WRITE
NULL.
IRP_MJ_DEVICE_CONTROL or IRP_MJ_INTERNAL_DEVICE_CONTROL
缓冲区代表了供DeviceIoControl and IoBuildDeviceIoControlRequest使用的输入参数,缓冲区的长度由驱动程序的IO_STACK_LOCATION成员 Parameters.DeviceIoControl.InputBufferLength 指定。
更多信息见 Buffer Descriptions for I/O Control Codes.
IoStatus
包含了在调用IoCompleteRequest之前驱动用于储存状态和信息的 IO_STATUS_BLOCK 结构 .
RequestorMode
此操作的最初请求者的执行模式, UserMode 与 KernelMode之一。
PendingReturned
如设置为TRUE, 一个驱动程序已经设置这个IRP为阻塞状态。任何一个 IoCompletion 例程应当检查这个标志的值。如果这个标志位是TRUE,而且如果 IoCompletion 例程不会返回STATUS_MORE_PROCESSING_REQUIRED, 那么例程应当调用IoMarkIrpPending 以将这个阻塞状态扩散到在这个设备栈之上的驱动程序中。
Cancel
如设置为TRUE, IRP已经被取消或者应当被取消。
CancelIrql
IoAcquireCancelSpinLock调用时驱动程序运行的IRQL级别。
CancelRoutine
包含了如果IRP被取消时,驱动程序提供的Cancel 例程入口点。 NULL 标识IRP当前不可取消。
UserBuffer
当以下条件满足时,包含了输出缓冲区的地址:
l I/O栈位置上的主功能号是IRP_MJ_DEVICE_CONTROL 或者是IRP_MJ_INTERNAL_DEVICE_CONTROL.
l I/O 控制码定义时使用METHOD_NEITHER或METHOD_BUFFERED
对METHOD_BUFFERED而言,驱动程序应使用 Irp->AssociatedIrp.SystemBuffer 作为输出缓冲区。当驱动程序完成了请求,I/O 管理器拷贝这个缓冲区的内容到Irp->UserBuffer指向的缓冲区中。 驱动程序不应直接写入数据到Irp->UserBuffer指向的缓冲区。更多信息,见Buffer Descriptions for I/O Control Codes.
Tail.Overlay.DeviceQueueEntry
如果IRPs 在驱动程序关联的设备队列中被排队,这个域链接设备队列中的IRP。这些链接仅能在驱动处理IRP时使用。
Tail.Overlay.DriverContext
如果IRPs 没有在驱动程序关联的设备对象中被排队,驱动程序可以使用这个域储存最多4个指针,这个域仅能在驱动程序拥有IRP时使用。
Tail.Overlay.Thread
指向调用者线程的TCB(线程控制块thread control block). 对于最初在用户模式下产生的请求,I/O 管理器总是设置这个域为指向发布这个请求的线程的TCB。
Tail.Overlay.ListEntry
如果一个驱动管理它自己的内部IRP队列。它使用这个域去链接一个IRP到下一个IRP,这些链接仅能用于当驱动在它的队列中正在掌握(?)这些IRP(while the driver is holding the IRP in its queue)或者是正在处理IRP时。
未文档化的成员被保留,仅能被I/O manager使用或是某些情况下被FSDs使用。
IRP 是基本的 I/O 管理结构,用于与驱动程序通信,或是驱动程序之间相互通信。一个IRP由以下两个不同的部分组成:
·
头,或者是包的固定部分— 这用于让I/O 管理器储存关于初始请求的信息。例如调用者设备无关的参数,文件在设备对象上打开时的地址, 等等.。同样它也被驱动程序用于储存一些信息,如请求的最终状态。
·
I/O 栈位置— 在头之后是一系列的 I/O 栈位置 (I/O stack locations), 每一个对应了IRP请求所绑定的在驱动层链中的一个驱动程序。(one per driver in the chain of layered drivers for which the request is bound)。 每一个stack location 包含参数,功能号还有上下文,用于让对应的驱动程序决定它该去做什么。更多信息见IO_STACK_LOCATION 结构.
·
高层的驱动程序可能会检查IRP中 Cancel 的值,驱动程序不能假设IRP被低层的驱动程序完成时将返回STATUS_CANCELLED ,即使这个值是TRUE.
Header |
Wdm.h (include Wdm.h, Ntddk.h, or Ntifs.h) |
IoCreateDevice
IoGetCurrentIrpStackLocation
IoGetNextIrpStackLocation
IoSetCancelRoutine
IoSetNextIrpStackLocation
IO_STACK_LOCATION
IO_STATUS_BLOCK