I/O 控制代码的缓冲区说明
I/O 控制代码包含在 IRP_MJ_DEVICE_CONTROL 和 IRP_MJ_INTERNAL_DEVICE_CONTROL 请求中。 由于调用 DeviceIoControl 和 IoBuildDeviceIoControlRequest,I/O 管理器会创建这些请求。
由于 DeviceIoControl 和 IoBuildDeviceIoControlRequest 接受输入缓冲区和输出缓冲区作为参数,因此所有 IRP_MJ_DEVICE_CONTROL 和 IRP_MJ_INTERNAL_DEVICE_CONTROL 请求都提供输入缓冲区和输出缓冲区。 系统描述这些缓冲区的方式取决于数据传输类型。 传输类型由创建 IOCTL 代码值的 CTL_CODE 宏中的 TransferType 值指定。
系统按如下所示描述每个 TransferType 值的缓冲区。
METHOD_BUFFERED
对于此传输类型,IRP 提供指向 Irp-AssociatedIrp.SystemBuffer> 处缓冲区的指针。 此缓冲区表示在调用 DeviceIoControl 和 IoBuildDeviceIoControlRequest 时指定的输入缓冲区和输出缓冲区。 驱动程序将数据从此缓冲区中传输出去,然后传入此缓冲区。
对于输入数据,缓冲区大小由驱动程序IO_STACK_LOCATION结构中的 Parameters.DeviceIoControl.InputBufferLength 指定。 对于输出数据,缓冲区大小由驱动程序IO_STACK_LOCATION结构中的 Parameters.DeviceIoControl.OutputBufferLength 指定。
系统为单个输入/输出缓冲区分配的空间大小是两个长度值中的较大值。
METHOD_IN_DIRECT或METHOD_OUT_DIRECT
对于这些传输类型,IRP 提供指向 Irp-AssociatedIrp.SystemBuffer> 处缓冲区的指针。 这表示在调用 DeviceIoControl 和 IoBuildDeviceIoControlRequest 时指定的第一个缓冲区。 缓冲区大小由驱动程序IO_STACK_LOCATION结构中的 Parameters.DeviceIoControl.InputBufferLength 指定。
对于这些传输类型,IRP 还提供指向 Irp-MdlAddress> 处的 MDL 的指针。 这表示在调用 DeviceIoControl 和 IoBuildDeviceIoControlRequest 时指定的第二个缓冲区。 此缓冲区可用作输入缓冲区或输出缓冲区,如下所示:
如果处理 IRP 的驱动程序在调用缓冲区时在缓冲区中接收数据,则指定METHOD_IN_DIRECT。 MDL 描述输入缓冲区,并指定METHOD_IN_DIRECT可确保执行线程具有对缓冲区的读取访问权限。
如果处理 IRP 的驱动程序将在完成 IRP 之前将数据写入缓冲区,则指定METHOD_OUT_DIRECT。 MDL 描述输出缓冲区,并指定METHOD_OUT_DIRECT可确保执行线程对缓冲区具有写入访问权限。
对于这两种传输类型, Parameters.DeviceIoControl.OutputBufferLength 指定 MDL 描述的缓冲区的大小。
METHOD_NEITHER
I/O 管理器不提供任何系统缓冲区或 MDL。 IRP 提供指定给 DeviceIoControl 或 IoBuildDeviceIoControlRequest 的输入和输出缓冲区的用户模式虚拟地址,而无需验证或映射它们。
输入缓冲区的地址由驱动程序的 IO_STACK_LOCATION 结构中的 Parameters.DeviceIoControl.Type3InputBuffer 提供,输出缓冲区的地址由 Irp-UserBuffer> 指定。
缓冲区大小由驱动程序IO_STACK_LOCATION结构中的Parameters.DeviceIoControl.InputBufferLength 和 Parameters.DeviceIoControl.OutputBufferLength 提供。
有关 CTL_CODE 宏和上面列出的传输类型的详细信息,请参阅 定义 I/O 控制代码。