Declaring Functions Using Function Role Types for WDM Drivers

To inform SDV about the driver's entry points when you analyze a WDM driver, you must declare functions using function role type declarations. The function role types are defined in Wdm.h. Each entry point in the DriverEntry routine in your WDM driver must be declared by specifying the corresponding role type. The role types are predefined typedefs that correspond to the recognized entry points in a WDM driver.

For example, to create a function role type declaration for a driver's Unload routine called CsampUnload, use the predefined typedef DRIVER_UNLOAD role type declaration. The function role type declaration must appear before the function definition.


The definition of the CsampUnload function remains unchanged:

    IN PDRIVER_OBJECT DriverObject

SDV recognizes the types of entry points shown in the following table.

WDM function role type WDM routine









Dispatch_type( type ) DRIVER_DISPATCH

The dispatch routine(s) used by the driver. See Writing Dispatch Routines. The Dispatch_type(type) annotation must be combined with the DRIVER_DISPATCH role type declaration to specify the driver entry points.



The IoCompletion routine is set by calling IoSetCompletionRoutine or IoSetCompletionRoutineEx and passing the function pointer to the IoCompletion routine as the second parameter.



The Cancel routine is set by calling IoSetCancelRoutine and passing the function pointer to the cancellation routine for the IRP as the second parameter to the function.



The DpcForIsr routine is registered by calling IoInitializeDpcRequest and passing the function pointer to the DpcForIsr routine as the second parameter. To queue the DPC, call IoQueueDpc from the ISR routine by using the same DPC object.



The CustomDpc routine is set by calling KeInitializeDpc and passing the function pointer to the CustomDpc as the second parameter. To queue the CustomDpc for the driver, call KeInsertQueueDpc from the ISR routine by using the same DPC object.



The InterruptService routine (ISR) services a device interrupt and schedules post-interrupt processing of received data, if necessary.


The PowerCompletion callback routine completes the processing of a power IRP. If the driver needs to perform additional tasks after all other drivers have completed the IRP, the driver registers a PowerCompletion callback routine during the call to the PoRequestPowerIrp routine that allocates the IRP.



Routine is the callback routine that is specified in the second parameter to the ExInitializeWorkItem function.

The Routine should only be declared this way if the driver calls ExQueueWorkItem to add the work item to a system queue.

Declaring Driver Dispatch Routines

The function role type declarations for dispatch routines require additional information. Use the annotation _Dispatch_type_(type) in the declarations for dispatch routines that serve major IRP function codes. The type is the major I/O function code (for example, IRP_MJ_CREATE, IRP_MJ_CLOSE, IRP_MJ_SYSTEM_CONTROL).

For an example of how to declare driver dispatch routines, see the source code for the Cancel sample driver (Cancel.sys). In the header file for the driver (Cancel.h) there is a function role type declaration for CsampCleanup, a driver dispatch routine that handles the IRP_MJ_CLEANUP I/O function code. The _Dispatch_type_ (type) annotation precedes the DRIVER_DISPATCH role type declaration.

The CsampCleanup routine is declared as follows:


The Cancel sample driver also has a driver dispatch routine, CsampCreateClose, that handles both IRP_MJ_CREATE and IRP_MJ_CLOSE I/O function codes. The CsampCreateClose routine is declared in Cancel.h. Because this routine handles two I/O function codes, it requires two _Dispatch_type_ annotations in addition to the DRIVER_DISPATCH role type declaration.


Suppose that a filter driver has a driver dispatch routine called FilterDispatchIo that handles the IRP_MJ_CREATE, IRP_MJ_CLOSE, IRP_MJ_CLEANUP, and IRP_MJ_DEVICE_CONTROL I/O function codes.

The FilterDispatchIo routine is declared in Filter.h as follows.


Quick Steps: How to Annotate a WDM Driver

The procedure for declaring functions using the function role types is as follows:

  1. Locate the source code for the DriverEntry routine.

  2. Ensure that routines that are assigned to the following pointers are declared using function role types.


    For example, the following code example shows the function role type declarations for routines that correspond to these pointers (myDriverStartIO, myUnload, and myAddDevice).

    DRIVER_STARTIO myDriverStartIo;
    DRIVER_UNLOAD myUnload;
    DRIVER_ADD_DEVICE myAddDevice 
  3. Ensure that routines that are assigned to the following pointers are declared using the DRIVER_DISPATCH role type and that they have the _Dispatch_type_ annotations.


    For example:

    DRIVER_DISPATCH CsampCleanup;

Function Parameters and Function Role Types

As required in the C programming language, the parameter types that you use in the function definition must match the parameter types of the function prototype, or in this case, the function role type. SDV depends upon the function signatures for analysis and ignores functions whose signatures do not match.

For example, you should declare an IoCompletion routine using the IO_COMPLETION_ROUTINE function role type:

IO_COMPLETION_ROUTINE myCompletionRoutine;

When you implement myCompletionRoutine, the parameter types must match those used by IO_COMPLETION_ROUTINE, namely, PDEVICE_OBJECT, PIRP, and PVOID (see IoCompletion routine for syntax).

 PDEVICE_OBJECT  DeviceObject,
 PIRP  Irp,
 PVOID  Context

Running Code Analysis for Drivers to verify the function declarations

To help you determine whether the source code is prepared, run Code Analysis for Drivers. Code Analysis for Drivers checks for function role type declarations and can help identify function declarations that might have been missed or warn you when the parameters of the function definition do not match those in the function role type.