PFD/SDV Clean - SDV Roletypes in Samples and Shipping Drivers
In parallel to the Annotation effort (detailed in this post), other members on our team were focused on enabling better checking of Inbox and Sample drivers by adding role types for use with the drivers we were scanning with Static Driver Verifier (SDV). As mentioned in the previous blog post from Andrew (his entry on Role Types is here), role types “act as documentation by describing the intended role of a driver entry point routine (or callback function) and the routine’s return value and parameter types. Best of all, role types enable Static Driver Verifier which can discover complex inter-procedural bugs causing blue screens and system hangs.”
Role types and “function class” are synonymous when applied to these routines, and are also useful to PFD. When you use a function class from one of the header files in the WDK, you inherit the PFD annotations on that declaration as well, and enable the PFD (OACR) code checker to identify misuse of an API. Further, if that API for some reason changes in a subsequent release of the WDK, PFD Warning 28253 will appear alerting you that the declaration (set by the role type / function class) and definition no longer match. For example, I made a change to the annotation on the IRP (to “__in_opt”) in my DispatchPower definition in driver.c, which does not match the role type declaration for DRIVER_DISPATCH (IRP is just __in). Note that there is also a special case here: if a function is (a) declared using a function typedef, and (b) the function definition (body) has absolutely NO annotations, it inherits the annotations from the typedef “magically”. If, however, there are annotations on the function definition, then they better match exactly.
Unlike with the annotation work items, the tactic was different here: our team reviewed the drivers and added updated the appropriate header files with the role types, then submitted those changes to the developers for review. Since the role types apply to the IRP handling routines, it’s not necessary for the developer adding the role types to know exactly what those functions do. The beauty of SDV is that once this map is in place, it does the work of figuring out what a function can and can’t do.
Sample drivers (WDM and KMDF) in the Windows Driver Kit has been updated to use these role types. The “featured1” version of Toaster is an excellent example of this, found at WDKRoot\ src\general\toaster\wdm\func\featured1 (clip of func\shared\toaster.h):
…
DRIVER_INITIALIZE DriverEntry;
DRIVER_ADD_DEVICE ToasterAddDevice;
__drv_dispatchType(IRP_MJ_PNP)
DRIVER_DISPATCH ToasterDispatchPnp;
__drv_dispatchType(IRP_MJ_POWER)
DRIVER_DISPATCH ToasterDispatchPower;
__drv_dispatchType(IRP_MJ_DEVICE_CONTROL)
__drv_dispatchType(IRP_MJ_READ)
__drv_dispatchType(IRP_MJ_WRITE)
DRIVER_DISPATCH ToasterDispatchIO;
…
Including the role types as part of the Toaster sample is a significant “win” for our tools, since Toaster serves as an introduction to many new driver developers, and the template for a number of new drivers. Each will allow developers to use SDV without significant additional work, enabling them to produce high quality drivers earlier in their development cycle.