Coding Guidelines

When I get a new client, I ask for a copy of their driver coding guidelines.   Typically I get one of several responses.


·         We trust our developers to do the right thing.


·         The last time we brought this up there was almost open revolt.


·         They hand me a corporate standard for coding applications, most of which is worthless for drivers.


Whether companies recognize it or not, they need a set of coding guidelines for drivers.  There are a lot of ways of doing things in drivers that can cause problems, and a good set of guidelines can help.  Consider some of the following areas:


·         C++ – There can be an argument for this in many cases, but if C++ is used for drivers, there needs to be limits placed upon the language for it to work in the kernel.


·         Undocumented or unusual routines – What is your company’s policy on the use of undocumented kernel interfaces?  What about routines not normally used in the kernel, but documented for user space?  How about functions from the IFS kit for a regular driver?  There are a lot decisions to make here.


·         WDM, WDF or 3rd party toolkits – What is your policy on drivers:  should they be the traditional WDM model, the new WDF models or a 3rd party model? 


·         Development Environment – What do you require for a development environment?  This should be simple; namely a specific version of the DDK/WDK, but if you don’t spec it you can get anything.


·         Windows Logo – Do you want your drivers to have a Windows Logo?  This impacts the routines, models, and methodology for developing drivers.


·         Static Verification tools – What is your policy on code passing static and dynamic verification tools?  Do you require code to be PREfast clean?  Does your code need to run through Static Driver Verifier?  Do you require annotations to aid the above tools in finding bugs?  Do you use PC-Lint and do you have your own definitions file? 


·         Testing – Does the code need to pass Driver Verifier?  For Server 2003, does your code need to pass Call Usage Verifier? Is there a code coverage tool and standards to be met?  What other tests are required?


·         Diagnostics – What is your model for tracing and debug prints?  Do you require event logging?  Do you expect data to be presented to the performance monitor?  Is there information going to Windows Management Instrumentation?

·         Coding style – This is the one that causes the biggest fights.  You should probably not be dictating the location of braces or indentation, but there are things that make code easier to review or for the next person to work on it.

The above is not a complete list, but even more needs to be considered.  If you do not have the resources in-house, consider engaging a consultant to develop the guidelines based on your current practice. 


You do not want to end up like one firm I know that hired a contractor to develop a driver.  When the driver was delivered, the company discovered the contractor had used a toolkit the firm did not own and would cost over $100,000 to buy for the developers and train them on.  The choice between slipping the product schedule and buying the tool was not a pleasant one.  With some preparation up front in specifying coding guidelines, such scenarios can be prevented and time and money saved in the end.


 

Tag, you’re it

I’ve been spending the last couple of days tracking down a bug in a driver I am writing. The effort reminded me of how great tags on memory allocations and frees can be. Also, the work reminded me that there are at least a couple of features Microsoft does not promote and I rarely see.


For the uninitiated, tags are a four character value that is passed as an argument in memory allocation calls. The tag gives you a way to identify what the memory was allocated for by having a different tag for each common structure allocated. Here is a common problem: many driver developers commonly assume that they have only one tag for their whole driver because so many of the common samples do this. There is nothing stopping you from having multiple tags, and in fact there is a strong reason to have them.


Right now I am developing a file system mini-filter that has twenty-one different tags it uses for allocations. All the major buffer types and context blocks each have a unique tag for their allocations and frees.


Yes, I said frees. Part of the reason to have multiple tags is that you can also put the tag on the free of the memory by using the call ExFreePoolWithTag. Unfortunately, this call has been described as worthless in Walter Oney’s Programming the Windows Driver Model and is incorrectly documented by Microsoft.


The value of ExFreePoolWithTag is when you combine it with a tag with the PROTECTED_POOL bit set. This bit requires that you free the memory with ExFreePoolWithTag, and the OS will bug check if the memory being freed does not have the matching tag. Unfortunately, PROTECTED_POOL is not documented except in include files, and is not used by any Microsoft sample. Using ExFreePoolWithTag with PROTECTED_POOL tags gives you an automatic check that you are freeing what you intended to.


You do have to be careful on memory you allocate that the system will be freeing, since Windows will not know what tag you are using, so the system frees everything without tags. For everything except the rare instance where the system frees the memory, using multiple tags with PROTECTED_POOL is worthwhile.