IoSetCompletionRoutine function (wdm.h)

The IoSetCompletionRoutine routine registers an IoCompletion routine, which will be called when the next-lower-level driver has completed the requested operation for the given IRP.


void IoSetCompletionRoutine(
  [in]           PIRP                   Irp,
  [in, optional] PIO_COMPLETION_ROUTINE CompletionRoutine,
  [in, optional] __drv_aliasesMem PVOID Context,
  [in]           BOOLEAN                InvokeOnSuccess,
  [in]           BOOLEAN                InvokeOnError,
  [in]           BOOLEAN                InvokeOnCancel


[in] Irp

Pointer to the IRP that the driver is processing.

[in, optional] CompletionRoutine

Specifies the entry point for the driver-supplied IoCompletion routine, which is called when the next-lower driver completes the packet.

[in, optional] Context

Pointer to a driver-determined context to pass to the IoCompletion routine. Context information must be stored in nonpaged memory, because the IoCompletion routine is called at IRQL <= DISPATCH_LEVEL.

[in] InvokeOnSuccess

Specifies whether the completion routine is called if the IRP is completed with a success status value in the IRP's IO_STATUS_BLOCK structure, based on results of the NT_SUCCESS macro (see Using NTSTATUS values).

[in] InvokeOnError

Specifies whether the completion routine is called if the IRP is completed with a nonsuccess status value in the IRP's IO_STATUS_BLOCK structure.

[in] InvokeOnCancel

Specifies whether the completion routine is called if a driver or the kernel has called IoCancelIrp to cancel the IRP.

Return value



Only a driver that can guarantee it will not be unloaded before its completion routine finishes can use IoSetCompletionRoutine. Otherwise, the driver must use IoSetCompletionRoutineEx, which prevents the driver from unloading until its completion routine executes.

This routine sets the transfer address of the IoCompletion routine in the given IRP. The lowest-level driver in a chain of layered drivers cannot call this routine.

IoSetCompletionRoutine registers the specified routine to be called when the next-lower-level driver has completed the requested operation in any or all of the following ways:

  • With a success status value

  • With a nonsuccess status value

  • By canceling the IRP

Usually, the I/O status block is set by the underlying device driver. It is read but not altered by any higher-level drivers' IoCompletion routines.

Higher-level drivers that allocate IRP's with IoAllocateIrp or IoBuildAsynchronousFsdRequest must call this routine with all InvokeOnXxx parameters set to TRUE before passing the driver-allocated IRP to IoCallDriver. When the IoCompletion routine is called with such an IRP, it must free the driver-allocated IRP and any other resources that the driver set up for the request, such as MDLs with IoBuildPartialMdl. Such a driver should return STATUS_MORE_PROCESSING_REQUIRED when it calls IoFreeIrp to forestall the I/O manager's completion processing for the driver-allocated IRP.

Non-PnP drivers that might be unloaded before their IoCompletion routines run should use IoSetCompletionRoutineEx instead.


Requirement Value
Target Platform Desktop
Header wdm.h (include Wdm.h, Ntddk.h, Ntifs.h)
DDI compliance rules CompleteRequest(wdm), CompleteRequestStatusCheck(wdm), CompletionRoutineRegistered(wdm), IoAllocateForward(wdm), IoAllocateIrpSignalEventInCompletion(wdm), IoAllocateIrpSignalEventInCompletion2(wdm), IoAllocateIrpSignalEventInCompletion3(wdm), IoAllocateIrpSignalEventInCompletionTimeout(wdm), IoBuildFsdForward(wdm), IoBuildFsdIrpSignalEventInCompletion(wdm), IoBuildFsdIrpSignalEventInCompletion2(wdm), IoBuildFsdIrpSignalEventInCompletion3(wdm), IoBuildFsdIrpSignalEventInCompletionTimeout(wdm), IoFreeIrp(storport), IoSetCompletionRoutineNonPnpDriver(wdm), LowerDriverReturn(wdm), MarkPower(wdm), MarkPowerDown(wdm), MarkQueryRelations(wdm), MarkStartDevice(wdm), PendedCompletedRequest(wdm), SetCompletionRoutineFromDispatch(kmdf), SignalEventInCompletion(wdm), SignalEventInCompletion2(wdm), SignalEventInCompletion3(wdm), StartDeviceWait(wdm), StartDeviceWait3(wdm)

See also