I have been using Visual Studio to build Windows kernel mode drivers since Visual Studio 5. People who insist on using the WDK (nee DDK) command line build environment are masochists. Don't listen to them.
This document describes how to configure a VM-to-VM kernel debugging environment. Using this method, I can put my complete driver development environment on a portable USB drive and be up and running on any host PC in ten minutes.
The key to making Visual Studio work is to make all the configurations as closely identical as possible. Whenever changing the project properties, unless there is a strong and compelling reason not to, always select "All platforms" and "All configurations".
Note that all the output directories are under a single "Out" directory.
The include path:
$(ProjectDir);
$(SolutionDir)Include;
"$(WDKPATH)Includekm";
"$(WDKPATH)Includeshared";
"$(VS12PATH)VCinclude"
Global environment variables:
WDKPATH=C:Program Files (x86)Windows Kits8.1
VS12PATH={VisualStudio installation directory}
All modules are optimized, even in debug builds. I disable optimization on
individual files I am actively debugging by adding these lines to the top
of the source code, just after the #includes:
Note the very short list of defines! All the common defines have
been moved out of the project configuration to NtBuild.h. Only symbols
that are specific to this configuration should be included here.
NtBuild.h:
Basic Runtime Checks are incompatible with full optimization. Between
the two, I believe keeping the optimizer is the smarter choice.
I never saw much advantage to using precompiled headers.
The Program Database file name must exactly match the entry in the Linker section.
It is a good practice to generate the assembly output and at least occasionally
read through it. This helps when I find myself trying to step through assembly
in the field, where source code may not be available.
Some warnings need to be disabled to let the driver build. No harm done.
$(IntDir)VerID.obj;ndis.lib;Fwpkclnt.lib;FltMgr.lib;uuid.lib;ntoskrnl.lib;NtDll.lib;hal.lib;BufferOverflow.lib
VerID.obj needs to be linked in explicitly since it is built during the pre-link step.
Even if the app needs Admin rights, it is better to not require it. This way
the app can at least run enough to print an informative message to the user.
The PDB file name must match the C Output file entry.
Always generate a map file, especially for release builds, and archive it
with the binaries. It will be a lifesaver for problems in the field.
This is where I update the version information.
Doing this during the prelink step means the version info won't be updated
unless at least one other object file has been generated first. This
eliminates pointless updates if nothing has changed.
VerID.c should be included in the project, but excluded from the build.
BldVerID.bat:
This is where I sign the driver.
$(SolutionDir)BinBldSign.bat "$(TargetDir)$(TargetFileName)" "$(IntDir)SignTool.log"
BldSign.bat:
signtool sign /v /ac "MSCV_VSClass3.cer" /s MY /n "nlited systems inc." /t http://timestamp.VeriSign.com/scripts/timstamp.dll %1 > %2
Version Information
See: Version Information