When a driver completes an IRP with a success or warning status, the I/O Manager:
· Copies the data from the buffer specified in the IRP back to the user’s buffer, if the IRP specified METHOD_BUFFERED I/O. The driver specifies the number of bytes to be copied in theIrp->IoStatus.Information field.
· Copies the results from the IRP’s status block (Irp->IoStatus.Status andIrp‑>IoStatus.Information) to the caller’s original request block.
· Signals the event specified by the caller that initiated the request.
Not all of these actions occur in all cases. For example, if a driver completes an IRP with an error status, the I/O Manager does not copy any data back to the user’s buffer, and it copies only the value of the Irp->IoStatus.Status field, not the value of the IoStatus.Information field. If a driver completes an IRP synchronously, the I/O Manager does not signal the event. If a driver completes an IRP asynchronously, the I/O Manager might or might not signal the event. Therefore, a driver that calls ZwReadFile,ZwDeviceIoControl, or similarZwXxx routines should wait on the event only if theZwXxx routine returns STATUS_PENDING.
The following values indicate error and warning status codes:
· NTSTATUS codes 0xC0000000 - 0xFFFFFFFF are errors.
· NTSTATUS codes 0x80000000 - 0xBFFFFFFF are warnings.
If the value of the Irp->IoStatus.Status field is an error code, the operating system does not return any data, so the contents of theIrp->IoStatus.Information field should always be zero. If the value of theIrp->IoStatus.Status field is a warning code, the operating system can return data, so the contents of theIrp‑>IoStatus.Information field can be nonzero.
A simple scenario can help explain this situation. Assume that an IRP requires a driver to return data in a buffer that is defined with the following two fields:
ULONG Length;
UCHAR Data []; // Variable length array
The Length field specifies the size required to retrieve the data. The application sends a ULONG request to get theLength, and then sends a second request with a bigger buffer to retrieve all the data. The driver, in turn, always expects the buffer to be at least the size of a ULONG data item.
If the buffer is large enough, the driver completes the IRP with STATUS_SUCCESS, andLength andIrp->IoStatus.Information receive the number of bytes transferred.
If the buffer is not large enough to hold the data, the driver completes the IRP with the warning STATUS_BUFFER_OVERFLOW. In this case, the data is too large for the buffer. The driver updates theLength with the size required and writes sizeof(ULONG) intoIrp->IoStatus.Information.
If the buffer is too small to write the required length (that is, the buffer is smaller thansizeof(ULONG)), the driver completes the IRP with the error STATUS_BUFFER_TOO_SMALL and setsIrp->IoStatus.Information to 0.