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 值的缓冲区。

METHOD_BUFFERED

对于此传输类型,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 控制代码