I/O 控制代码的缓冲区说明

I/O 控制代码包含在 IRP_MJ_DEVICE_CONTROLIRP_MJ_INTERNAL_DEVICE_CONTROL 请求中。 由于调用 DeviceIoControlIoBuildDeviceIoControlRequest,I/O 管理器会创建这些请求。

由于 DeviceIoControlIoBuildDeviceIoControlRequest 同时接受输入缓冲区和输出缓冲区作为参数,因此所有 IRP_MJ_DEVICE_CONTROLIRP_MJ_INTERNAL_DEVICE_CONTROL 请求同时提供输入缓冲区和输出缓冲区。 系统描述这些缓冲区的方式取决于数据传输类型。 传输类型由创建 IOCTL 代码值的CTL_CODE宏中的 TransferType 值指定。

系统按如下所示描述每个 TransferType 值的缓冲区。

缓冲方法

对于此传输类型,IRP 提供指向 Irp-AssociatedIrp.SystemBuffer> 处缓冲区的指针。 此缓冲区表示在调用 DeviceIoControlIoBuildDeviceIoControlRequest 时指定的输入缓冲区和输出缓冲区。 驱动程序将数据移出,然后传输到此缓冲区。

对于输入数据,缓冲区大小由驱动程序IO_STACK_LOCATION结构中的 Parameters.DeviceIoControl.InputBufferLength 指定。 对于输出数据,缓冲区大小由驱动程序IO_STACK_LOCATION结构中的 Parameters.DeviceIoControl.OutputBufferLength 指定。

系统为单个输入/输出缓冲区分配的空间大小是两个长度值中的较大值。

METHOD_IN_DIRECT 或 METHOD_OUT_DIRECT

对于这些传输类型,IRP 提供指向 Irp-AssociatedIrp.SystemBuffer> 处缓冲区的指针。 这表示对 DeviceIoControlIoBuildDeviceIoControlRequest 的调用中指定的第一个缓冲区。 缓冲区大小由驱动程序IO_STACK_LOCATION结构中的 Parameters.DeviceIoControl.InputBufferLength 指定。

对于这些传输类型,IRP 还提供指向 Irp-MdlAddress> 中的 MDL 的指针。 这表示在对 DeviceIoControlIoBuildDeviceIoControlRequest 的调用中指定的第二个缓冲区。 此缓冲区可用作输入缓冲区或输出缓冲区,如下所示:

  • 如果处理 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 提供为 DeviceIoControlIoBuildDeviceIoControlRequest 指定的输入和输出缓冲区的用户模式虚拟地址,而无需验证或映射它们。

输入缓冲区的地址由驱动程序IO_STACK_LOCATION结构中的 Parameters.DeviceIoControl.Type3InputBuffer 提供,输出缓冲区的地址由 Irp-UserBuffer> 指定。

缓冲区大小由驱动程序IO_STACK_LOCATION结构中的 Parameters.DeviceIoControl.InputBufferLengthParameters.DeviceIoControl.OutputBufferLength 提供。

有关 上述CTL_CODE 宏和传输类型的详细信息,请参阅 定义 I/O 控制代码