IRP Completion
Overview
In the Windows kernel, an I/O Request Packet (IRP) is the primary data structure used to communicate I/O requests between drivers. Completing an IRP signals that the I/O operation is finished and returns control (and status) to the caller.
This page describes the recommended patterns for completing IRPs, the IoCompleteRequest routine, and best‑practice error handling.
Syntax
VOID IoCompleteRequest(
_In_ PIRP Irp,
_In_ CCHAR PriorityBoost
);
| Parameter | Description |
|---|---|
Irp |
Pointer to the IRP to be completed. |
PriorityBoost |
Number of priority levels to boost the thread that issued the IRP. Use IO_NO_INCREMENT when no boost is required. |
Remarks
- The driver that owns the IRP must set
Irp->IoStatus.StatusandIrp->IoStatus.Informationbefore callingIoCompleteRequest. - Only the driver that last processed the IRP should complete it. Premature completion can cause memory corruption or deadlocks.
- If the IRP has a completion routine set via
IoSetCompletionRoutine, that routine is called afterIoCompleteRequestreturns. - For IRPs that are pending, the driver should return
STATUS_PENDINGafter queuing any asynchronous work, and later callIoCompleteRequestwhen the work finishes.
Example
The following snippet shows a typical driver dispatch routine that processes a read request and completes the IRP.
#include <ntddk.h>
NTSTATUS
MyDriverRead(
_In_ PDEVICE_OBJECT DeviceObject,
_Inout_ PIRP Irp
)
{
UNREFERENCED_PARAMETER(DeviceObject);
// Validate buffer length
ULONG length = IoGetCurrentIrpStackLocation(Irp)->Parameters.Read.Length;
if (length == 0) {
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_INVALID_PARAMETER;
}
// Perform read (synchronously for demo)
// In a real driver you would copy data to the user buffer here.
RtlZeroMemory(Irp->AssociatedIrp.SystemBuffer, length);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = length; // bytes transferred
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}