I/O control codes are contained in IRP_MJ_DEVICE_CONTROL and IRP_MJ_INTERNAL_DEVICE_CONTROL requests. The I/O manager creates these requests as a result of calls to DeviceIoControl and IoBuildDeviceIoControlRequest.
Because DeviceIoControl and IoBuildDeviceIoControlRequest accept both an input buffer and an output buffer as arguments, all IRP_MJ_DEVICE_CONTROL and IRP_MJ_INTERNAL_DEVICE_CONTROL requests supply both an input buffer and an output buffer. 系统描述这些缓冲区的方式取决于数据传输类型。 The transfer type is specified by the TransferType value in the CTL_CODE macro that creates IOCTL code values.
The system describes buffers for each TransferType value as follows.
METHOD_BUFFERED
For this transfer type, IRPs supply a pointer to a buffer at Irp->AssociatedIrp.SystemBuffer. This buffer represents both the input buffer and the output buffer that are specified in calls to DeviceIoControl and IoBuildDeviceIoControlRequest. 驱动程序将数据移出,然后传输到此缓冲区。
For input data, the buffer size is specified by Parameters.DeviceIoControl.InputBufferLength in the driver's IO_STACK_LOCATION structure. For output data, the buffer size is specified by Parameters.DeviceIoControl.OutputBufferLength in the driver's IO_STACK_LOCATION structure.
系统为单个输入/输出缓冲区分配的空间大小是两个长度值中的较大值。
METHOD_IN_DIRECT 或 METHOD_OUT_DIRECT
For these transfer types, IRPs supply a pointer to a buffer at Irp->AssociatedIrp.SystemBuffer. This represents the first buffer that is specified in calls to DeviceIoControl and IoBuildDeviceIoControlRequest. The buffer size is specified by Parameters.DeviceIoControl.InputBufferLength in the driver's IO_STACK_LOCATION structure.
For these transfer types, IRPs also supply a pointer to an MDL at Irp->MdlAddress. This represents the second buffer that is specified in calls to DeviceIoControl and IoBuildDeviceIoControlRequest. 此缓冲区可用作输入缓冲区或输出缓冲区,如下所示:
- 如果处理 IRP 的驱动程序在调用缓冲区时接收缓冲区中的数据,则指定METHOD_IN_DIRECT。 MDL 描述输入缓冲区,并指定METHOD_IN_DIRECT可确保执行线程对缓冲区具有读取访问权限。 
- 如果处理 IRP 的驱动程序在完成 IRP 之前将数据写入缓冲区,则指定METHOD_OUT_DIRECT。 MDL 描述输出缓冲区,并指定METHOD_OUT_DIRECT可确保执行线程对缓冲区具有写入访问权限。 
For both of these transfer types, Parameters.DeviceIoControl.OutputBufferLength specifies the size of the buffer that is described by the MDL.
METHOD_NEITHER
I/O 管理器不提供任何系统缓冲区或 MDL。 The IRP supplies the user-mode virtual addresses of the input and output buffers that were specified to DeviceIoControl or IoBuildDeviceIoControlRequest, without validating or mapping them.
The input buffer's address is supplied by Parameters.DeviceIoControl.Type3InputBuffer in the driver's IO_STACK_LOCATION structure, and the output buffer's address is specified by Irp->UserBuffer.
Buffer sizes are supplied by Parameters.DeviceIoControl.InputBufferLength and Parameters.DeviceIoControl.OutputBufferLength in the driver's IO_STACK_LOCATION structure.
For more information about the CTL_CODE macro and the transfer types listed above, see Defining I/O Control Codes.