共用方式為


Example 5: Inferred Purpose Based on Function Characteristics

PFD uses information about the role a callback function fulfills to refine its analysis of the function. The role of a callback function includes things such as being the start-IO function or the cancel routine. If you are familiar with Static Driver Verifier, this is described as the role type of the function.

The preferred method to inform PFD that a callback function fulfills a particular role is to use the __drv_functionClass annotation. The __drv_functionClass annotation can be used directly, but is best used as part of a function typedef statement. In the absence of a __drv_functionClass annotation, PFD attempts inferences to acquire the same information.

In the following code example, the IRQLCancel function is declared to be of type DRIVER_CANCEL.

DRIVER_CANCEL IRQLCancel;

...

void
IRQLCancel(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
{
    // Cancel a pending operation.
    IoReleaseCancelSpinLock(Irp->CancelIrql);
}

Because this declaration specifies the function role type, PFD can act on that information. The declaration also prevents PREfast for Drivers from making any inappropriate inferences about the function. For example, PREfast for Drivers would not apply rules for start-IO routines to functions of type DRIVER_CANCEL, even though the two are of the same C type (signature).

Although this syntax for declaring a function has rarely been used in the past, the DRIVER_CANCEL declaration type conforms to all C and C++ standards. In addition, if you declare the function type, the compiler requires that the parameter types in the function body be exactly the same as those that are declared in the function type declaration, instead of merely being "assignment-compatible" with the function pointer assignment and call.

PFD also confirms that all uses of functions that have explicit or implicit __drv_functionClass annotations are used consistently. Specifically, PREfast for Drivers might report Warning 28155, which warns that both functions in an assignment or implied assignment should be annotated to indicate that they are of the same function type.

In the absence of such an annotation, PFD attempts to identify certain types of functions based on the function signature (that is, the arguments and result type) of the function that is being analyzed or words in the function name, such as "Callback" or "Cancel." In these situations, PREfast for Drivers applies additional rules that are specific to that type of function. When PREfast identifies such a function, it displays an informational message, such as Warning 28101, to make its assumption explicit. For example:

The Drivers module has inferred that the current function is a Cancel function: This is informational only. No problem has been detected.problem occurs in function 'IRQLCancel'

The preferred way to avoid Warning 28101 is to declare the function role type explicitly using a function typedef.

In either case, PREfast for Drivers uses function-specific rules to analyze the function. For example, when it identifies a Cancel routine, PREfast for Drivers verifies that the routine releases the cancel spin lock and restores the previous IRQL before exiting. In the following example, PREfast for Drivers displays Warning 28144 because the driver does not release the cancel spinlock. The checks that use function typedefs are generally more thorough than the ones resulting from an inference.

PREfast analysis path begins

 1991....IRQLCancel(

abc.c(1991) : warning 28144: Within a cancel routine, at the point of exit, the IRQL found Irp->CancelIrql should be the current IRQL.: The value need not be restored by any specific function, but must be restored before exit. PREfast was unable to determine that it was restored to the required value.problem occurs in function 'IRQLCancel'

1992    IN PDEVICE_OBJECT DeviceObject,
1993    IN PIRP Irp
1994    )
1995    {
1996        //Cancel a pending operation
1997    }

If the routine is not a Cancel routine, you can ignore the warning. However, if it is a Cancel routine, the routine should include a call to IoReleaseCancelSpinLock with the Irp->CancelIrql parameter before returning from the function, as shown in the following code. Ideally, the driver should release the cancel spinlock as soon as possible after entering the function because holding the cancel spinlock hampers the performance of the entire system.

void
IRQLCancel(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
{
//Cancel a pending operation.
IoReleaseCancelSpinLock(Irp->CancelIrql);
}

When you use function type definitions to describe role types, if the function declaration or any additional function prototypes are not identical to the declaration in the header file, the Visual Studio compiler might generate one or more of the following warnings or errors.. To resolve the problem, change the function so that it conforms exactly to the declaration of the function type.

Because these compiler warnings and errors are generated by the compiler that is used to generate code, they appear when compiling code for execution, even when you are not using the PREfast command.

  • Error C2371: '<function>': redefinition; different basic types
    The data type of the return value of the specified function does not match the type of the function typedef. Typically, this error occurs when the function type declaration is the void type (returning nothing) and the definition is declared as returning an integer (int). This error often occurs in older code that assumes "default-int" result types. The C language no longer supports default-int. Using the default-int now generates compiler Warning C4331, however, that warning is often suppressed on older code.

  • Warning C4716: '<function>': must return a value
    This warning often appears with Error C2371 and might be resolved by fixing the cause of C2371.

  • Warning C4431: missing type specifier - int assumed
    Note that C no longer supports default-int. This warning often appears with Error C2371 and might be resolved by fixing the cause of C2371:

  • Warning C4142: benign redefinition of type
    The data type of the function's return value does not match the type of the function typedef. The data type is very close to a compatible type, but it is not exactly the same type (such as using long rather than NTSTATUS).

  • Warning C4028: formal parameter <n> different from declaration
    The data type of the formal parameter <n> does not match the type in the function type declaration. Typically, this error occurs when the called function uses a void pointer instead of the declared type, or when one is a CONST. Because the function prototype is in scope, use the correct type definition.

  • Warning C4029: declared formal parameter list different from definition
    The parameter list of a declared function differs from the parameter list that is specified in the function declaration. Typically, this error indicates that the parameter lists are of different lengths, but it might also indicate that the lists were so different that the compiler could not reconcile them. This error should be rare, but it might occur if the function body simply omits an unused parameter.

 

 

Send comments about this topic to Microsoft

Build date: 5/3/2011