共用方式為


Function Class Annotations and Role Types

Drivers commonly define functions that the system calls by using a function pointer that the driver passes to the system. The AddDevice, StartIo, and Cancel functions are examples of this kind of callback function. Making sure that callback functions are annotated properly significantly improves PREfast for Driver's (PFD) ability to check for proper usage. You can achieve better results by declaring functions to be members of a function class. For more information, see the Checking Function Types section later in this topic.

Because these callback functions act in a particular role in the implementation of the driver, the types of these functions are also referred to as their role types.

Most common callback function types have a function class. This function class annotation is most useful when applied to both the function and the function pointer type. It can be most easily applied by using function type declarations (using typedef).

Function typedefs

In C and C++, you can use a typedef to declare a function type. This is distinct from a function pointer type and has not been used very much in most C code. However, with the addition of annotations and function classes, function types (or role types) become very useful. For example, rather than declaring a full function prototype for a StartIo function, the header can include the following function type declaration:

DRIVER_STARTIO MyStartIo;

This function type declaration declares MyStartIo as a function of the type DRIVER_STARTIO. In addition, the declaration applies all of the system-supplied annotations on the DRIVER_STARTIO type to MyStartIo. After you declare the function type, you can also declare a full function prototype, but it is not necessary.

This function type declaration is useful in another way: It tells developers reading the code that the function is intended to be an actual StartIo function, rather than just looking like one. For example, Cancel functions are assignment-compatible with StartIo functions (that is, a pointer to one can be assigned to a pointer to the other), so a poorly chosen function name can lead to ambiguities in the source code.

When you add a function type declaration, there is no need to change the function body (that is, the function definition). If there is no separate function prototype because the function definition appears before the first use, a function declaration that uses the type declaration (typedef) should be placed just before the function definition. When a function is declared by using a type declaration, the function type declaration should have the required annotations. The function definition does not have to be annotated because annotations that are applied to function type declarations are implicitly applied to functions and parameters of that type, the same as for any typedef. System-provided function type declarations already have the required annotations.

typedef
VOID
DRIVER_STARTIO (
    __in struct _DEVICE_OBJECT *DeviceObject,
    __in struct _IRP *Irp
    );

Checking Function Types

Use the __drv_functionClass annotation to inform PFD to check function types. This annotation has the following syntax:

__drv_functionClass(name)

This annotation indicates that the function is a member of the named class of functions that is represented by the class name name. This annotation also propagates to the corresponding function pointer typedef and causes PFD to confirm that function assignments to and from function pointers are done by using the same function class. Function class names are the device routine types that are defined in Wdm.h, Ntddk.h, or Wdf.h.

If a function does not have a function class, or a function of the wrong function class is assigned to a function pointer that does have a function pointer class, PFD issues a warning. The correct way to suppress this warning is to use the appropriate function type definition, which generally appears in the PFD error message text.

For example, the following __drv_functionClass annotation indicates that this is the function type definition for the DRIVER_INITIALIZE function class. (The typedef name and the class name are in different namespaces.) The pointer PDRIVER_INITIALIZE is of the class DRIVER_INITIALIZE because it is derived from the DRIVER_INITIALIZE type definition.

typedef
__drv_functionClass(DRIVER_INITIALIZE)

NTSTATUS
DRIVER_INITIALIZE (
    __in struct _DRIVER_OBJECT *DriverObject,
    __in PUNICODE_STRING RegistryPath
    );

typedef DRIVER_INITIALIZE *PDRIVER_INITIALIZE;

Function Types in Conditional Expressions

A few functions have annotations that apply only when the function is (or is not) called from a particular class of function that is specified by a __drv_functionClass annotation. In this case, you can add an annotation to specify the function class. Add a call to isFunctionClass$("name") as part of a conditional expression in a __drv_when annotation.

The isFunctionClass$("name") annotation determines if the function belongs to the class that is identified by name. If the function does not belong to the class, the isFunctionClass$ returns 0; if the function does belong to the class, isFunctionClass$ returns 1. For example, isFunctionClass$("DRIVER_INITIALIZE") determines if the function is a driver initialization function type. For information about other functions that can be used in conditions, see Annotation Expressions.

For example, consider a special case of IoCreateDevice that applies only to legacy drivers that allows IoCreateDevice to be called from within the DRIVER_INITIALIZE function and does not require it to explicitly keep track of the resulting device object. The system puts the device object in a location that the driver's unload function can find, but PFD cannot detect this and issues a warning.

The following annotation prevents noise that is related to this special case when running PFD on legacy drivers:

__drv_when(!isFunctionClass$("DRIVER_INITIALIZE") && return == 0,   __deref(__drv_allocatesMem(DeviceObject)) 

The return==0 clause is an example of a check for successful execution.

Dispatch Function Role Types

The DRIVER_DISPATCH function typedef is a special case of role types. There are a number of functions, performing different actions, that should all be declared by using the DRIVER_DISPATCH type. Each of these should be assigned into the appropriate dispatch table entry. By declaring the roles correctly, Static Driver Verifier is far more effective in what it does. PFD provides checking that the specific role types are properly defined.

The specific role types are implemented by the __drv_dispatchType, __drv_dispatchType_other, __drv_completionType and __drv_callbackType annotations that are described in Declaring Functions Using Function Role Types for WDM Drivers. When PFD checks on these role types, it can only confirm that the function is annotated with the appropriate __drv_dispatchType annotation, based upon the dispatch table assignments.

 

 

Send comments about this topic to Microsoft

Build date: 5/3/2011