共用方式為


Using Function typedefs or Function Role Types in C++ Driver Code to Improve PREfast Results

When you declare your driver's callback functions using the function role type declarations, the static tools such as PREfast for Drivers (PFD) and Static Driver Verifier (SDV) can produce better results. For drivers written in C, this is simple to do. For drivers written in C++, however, there are several variations that are best clarified through examples.

This topic shows several examples of how to declare your driver-supplied functions in C++ driver code. These examples use DriverEntry, which is declared with the DRIVER_INITIALIZE function role type, but the same usage patterns also apply to other system-defined callbacks that have function typedef declarations. Note that the first few examples illustrate specific points but do not include everything that would be needed in a working driver. The last example is more complete.

DriverEntry Declared without DRIVER_INITIALIZE

The first example resembles a DriverEntry function, but it is not declared by using the DRIVER_INITIALIZE function role type (or function typedef)

NTSTATUS
DriverEntry(
   __in PDRIVER_OBJECT DriverObject,
   __in PUNICODE_STRING RegistryPath
   )
{   //... }

When analyzing this function, PFD reports warning 28101, "The Drivers module has inferred that the current function is a DriverEntry function." Note that DriverEntry is a special case: PFD recognizes it by inference from its name and signature because there is no other way for PFD to recognize it. PFD can identify other callback function types from context, so DriverEntry is the only function for which PFD makes this kind of inference.

DriverEntry Declared with DRIVER_INITIALIZE

A static member function can be used to implement DriverEntry, but not directly. C++ qualifies the linker name of the function with the class name, so the function would not be linked correctly. (Linker magic could be used to work around this problem, but it isn't recommended.)

The simplest solution is to use a wrapper function that indirectly calls the class member function. The following example declares the static member function sf_driverEntry as a DRIVER_INITIALIZE function type. The wrapper uses extern C linkage to convert the C entry point into a call to the static member function. If the static member function is not declared by using DRIVER_INITIALIZE, PFD issues warning 28101.

class MyDriverClass
{
public:
    static DRIVER_INITIALIZE sf_DriverEntry;

};

NTSTATUS
MyDriverClass::sf_DriverEntry(
   __in PDRIVER_OBJECT DriverObject,
   __in PUNICODE_STRING RegistryPath
   )
{ //... }

// The C linkage wrapper function
extern "C"
DRIVER_INITIALIZE DriverEntry;
extern "C"
NTSTATUS DriverEntry (
   PDRIVER_OBJECT DriverObject,
   PUNICODE_STRING RegistryPath
   )
{ 
    // convert the C entry point into a call to the static member function.
    return MyDriverClass::sf_DriverEntry(DriverObject, RegistryPath);
}

DriverEntry Implemented as a Regular Member Function

PFD does not recognize a member function that appears similar to a DriverEntry function as actually being a DriverEntry function. The reason for this is that the language does not allow it and the operating system does not provide a valid this pointer at the point of call.

For example, the mf_DriverEntry member function in the following class declaration is not recognized as a DriverEntry function because it is an ordinary member function:

class MyDriverClass
{
public:
NTSTATUS
mf_DriverEntry
   __in PDRIVER_OBJECT DriverObject,
   __in PUNICODE_STRING RegistryPath);

};

NTSTATUS
MyDriverClass::mf_DriverEntry(
   __in PDRIVER_OBJECT DriverObject,
   __in PUNICODE_STRING RegistryPath
   )
{  //... }

However, when the member function is declared with an explicit function role type declaration, PFD does recognize the function as being a DriverEntry function because the typedef makes it clear that the developer intends the function to meet the contractual requirements of a DriverEntry function. The function could be used to actually implement the required DriverEntry functionality if called from an extern "C" wrapper function that had access to an appropriate member pointer. The following example shows a class declaration that declares a DriverEntry member function using the DRIVER_INITIALIZE function role type:

class DriverObject
{
public:
    DRIVER_INITIALIZE DriverEntry;
};

NTSTATUS
DriverObject::DriverEntry(
   __in PDRIVER_OBJECT DriverObject,
   __in PUNICODE_STRING RegistryPath
   )
{ //... }

A More Complete Example

The following example shows all of the relevant pieces for one possible solution that uses function typedef declarations in C++ driver code. In this case, DriverEntry does the little bit of work needed to create or initialize the C++ MyDriverClass class and then calls mf_DriverEntry as a C++ member function to finish the work. Note that this example omits error handling and code for the actual work that a DriverEntry routine is expected to perform. For more information, see Writing a DriverEntry Routine.

class MyDriverClass
{
    PDRIVER_OBJECT m_DriverObject;
public:

    DRIVER_INITIALIZE mf_DriverEntry;
    MyDriverClass();
};

MyDriverClass *g_DriverObject;

// The C linkage wrapper function
extern "C"
DRIVER_INITIALIZE DriverEntry;

extern "C"
NTSTATUS
DriverEntry(
   __in PDRIVER_OBJECT DriverObject,
   __in PUNICODE_STRING RegistryPath
   )
{
   // Create/Initialize class MyDriverClass with a pointer
   // to it in g_DriverObject.
   g_DriverObject = new MyDriverClass();
   if (g_DriverObject == NULL)
   {
       //...
   }

   NTSTATUS st = g_DriverObject
        ->mf_DriverEntry(DriverObject,RegistryPath);

   //...
}

// Implement the DriverEntry member function
NTSTATUS
MyDriverClass::mf_DriverEntry(
   __in PDRIVER_OBJECT DriverObject,
   __in PUNICODE_STRING RegistryPath
   )
{
   m_DriverObject = DriverObject;
   //...
}

 

 

Send comments about this topic to Microsoft

Build date: 5/3/2011