# Programming the Microsoft Windows Driver Model, Second Edition
by Walter Oney
Copyright (©) 1995 - 2003 by Microsoft Corporation
Portions Copyright (©) 2003 by Walter Oney
General Information

The companion content for Programming the Microsoft Windows Driver Model, Second Edition contains more than 40 sample drivers and test programs to illustrate the topics covered by the book. The file you're viewing contains general information about the disc, as follows:

Directory Structure
Directory of Sample Programs
Using the FastInst Utility
General Instructions for Building WDM Samples
General Instructions for Building User-Mode Samples
General Instructions for USB Samples
Using WDMWIZ.AWX
WMI Functionality in Windows 98
Definitions of EULA Terms
How to Report Errors

# Directory Structure

The SAMPLES directory on the companion disc contains the setup program for the sample programs as well as some common tools used by all the samples. If you elect to install the book samples onto your hard disk, the setup program will copy those common tools too. If you elect not to install the samples onto your hard disk, the setup program will nonetheless install some of the common tools because you won’t otherwise be able to run the samples.

For those book chapters that have sample programs, the companion disc contains a directory for that chapter. The chapter contains subdirectories for each sample program. In many cases, there’s a further subdivision into a SYS directory (containing the WDM driver) and a TEST subdirectory (containing a simple test program for exercising the driver). For example, Chapter 3 has three samples: FILEIO, FPUTEST and SEHTEST. The disc therefore has the following directory structure:

Chap3
FileIo
Sys
objchk
i386
Test
Debug
fputest
Sys
objchk
i386
test
Debug
SehTest
objchk
i386

Each sample also has an HTML file that describes the overall purpose of the sample and contains brief instructions about how to build and test the sample. Once you’ve installed a particular sample driver, you can easily read this HTML file by clicking on the "More Info" button in the "Sample Information" page of the Device Manager’s property page for the sample device.

I recommend that you read the information file before attempting to build, install, or test any sample. There are nuances for some of the samples that will drive you crazy unless you know about them ahead of time.

In addition, each information file contains a section entitled “What to look for” that explains where in the source code to find the stuff that the sample attempts to illustrate.

# Directory of Sample Programs

Chapter | Sample Name | Brief Description
Chap2 | STUPID | The most basic possible WDM driver
| INTERFACEENUM | How to enumerate registered device interfaces
Chap3 | FILEIO | File I/O operations (including Win98 workarounds)
| SEHTEST | Illustrates use of structured exception handler
| FPUTEST | Illustrates floating point operations in a WDM driver
| RESOURCE | Illustrates resource access in kernel mode
| BUGCHECK | How to generate a bug check (use this to practice reading crash dumps)
| MEMTEST | Determine how much memory can be allocated in one call.
Chap4 | SPINLOCK | How to use in-stack queued spin locks when they’re available and regular spin locks otherwise.
Chap6 | PNPEVENT | User-mode PnP events
| PNPMON | Kernel-mode PnP events
Chap7 | PCI42 | Simple PIO device using AMCC S5933 chip. Also includes a driver for the ISA card that accompanies the AMCC development kit
| PKTDMA | Simple DMA device using AMCC S5933 chip
| SCATGATH | (Untested) driver using new DMA calls for scatter/gather
Chap8 | WAKEUP | Wakeup and USB selective suspend
Chap9 | EVWAIT | How to share an event between user mode and kernel mode
| IOCTL | How to handle simple DeviceIoControl operations
| NOTIFY | How to use an asynchronous I/O control operation to notify an application when something interesting happens
Chap10 | WMI42 | How to implement a simple WMI class
| WMIEXTRA | Advanced WMI functionality
Chap11 | MULFUNC | Nonstandard multifunction device
Chap12 | FEATURE | Setting and clearing a feature
| LOOPBACK | Handling bulk transfer endpoints
| USB42 | Simple input-only bulk endpoint
| USBINT | Interrupt endpoint management
| USBISO | Isochronous endpoint management
Chap13 | HIDFAKE | Non-standard HID minidriver
Chap14 | PIOFAKE | How to setup a watchdog timer
| POLLING | How to use a system thread to poll a device
| WORKITEM | How to create an executive work item
| EVENTLOG | How to log an event
Chap15 | DEVPROP | Determining device properties in kernel and user modes
| AUTOLAUNCH | How to launch an application automatically when the PnP Manager starts your device
| SAMCLASS | Device Manager property page provider DLLs for Windows Xp and Windows 98
| FASTINST | Install single device in Windows Xp
| MAKENAME | How to generate a unique friendly name during device setup
| COINSTALLER | A sample co-installer DLL using MFC
Chap16 | FILTER | Simple filter driver that just logs IRPs that pass through
| POWTRACE | Lower filter for logging power requests
AppendixA | WDMSTUB | Stubs for selectected functions missing from Windows 98 (newer lower filter version)
| HARDERR | How to call IoRaiseInformationalHardError.
| WDMCHECK | Source for import-checking utility program
| WHICHOS | How to determine the operating system version
| GENERIC | Generic PnP and Power support for most of my samples

# Using the FastInst Utility

The Hardware Wizards in Windows Xp and Windows 98 are slow enough that you’ll quickly want to find a faster way to install new drivers. I wrote FastInst to speed up this process.

Suppose you want to install the WDMIDLE sample from Chapter 8. You can issue these commands at a command prompt (this example is for Windows 2000 or XP):

C:>cd %wdmbook%
C:\Wdmbook>fastinst chap8\wdmidle\sys\device.inf

Alternatively, select the INF file of interest in Windows Explorer with the right mouse, and select the “Install using FASTINST” choice from the context menu. For this to work, you must have checked the related option when you installed the samples. If you forgot to do that, use the Tools/Folder Options/File Types page to define an INF-file association with any desired wording. The command you want depends on the OS:

· In Windows 2000 or XP, you want to execute %wdmbook%\fastinst.exe.

· In Windows 98 or ME, you want to execute %wdmbook%\chap15\fastinst\win98\fastinst.exe

FastInst will install the driver files for the first device mentioned in the model section for the first manufacturer named in the [manufacturer] section. If you want to override this selection for an INF file that describes multiple devices, specify the device identifier for the device you want:

C:\Wdmbook>fastinst path device-id

FastInst presents a progress dialog to reassure you that something is happening. The bar is driven simply off a timer and doesn't reflect the actual progress of the install. You may see the progress bar fill and start over again a number of times the first you run FastInst in a session. Be patient—the installation process can be slow even with FastInst in the picture!

# General Instructions for Building WDM Samples

Each of the sample drivers includes a project file (with a file extension of DSP) for use with Microsoft Visual Studio 6.0 and the DDK compiler. Most of the driver samples also include a SOURCES file for use with the standard DDK BUILD utility. You will need the following software installed on your computer:

- The Windows XP Device Driver Kit, build 2600 (the Released To Manufacturing version from around September 7, 2001) or later. All the driver projects in these samples use the compiler that ships with the DDK. Alternatively, use any version of the .NET DDK.
- For some of the samples only, the Windows 98 Device Driver Kit. You need the VxD-related headers and libraries from this kit—none of the WDM functionality of any of my samples relies on this kit. The Windows Millennium files that accompany the XP DDK will not suffice because they lack the wdmvxd.clb library.

To build a driver project, follow this procedure:

1. If you haven’t already done so, use the Advanced tab of My Computer properties to set several environment variables (note that the setup program will have done this if you let it):

· WDMBOOK points to the directory where you installed these samples.

· DDKPATH points to the base directory of the DDK you’re using. E.g., “C:\winddk\3615”, or whatever.

· SIWPATH points to the directory, if any, where you installed the Soft-Ice debugger from Numega. If you haven’t installed Soft-Ice, set this the same as WDMBOOK, which causes the build scripts to use a dummy NMSYM.BAT file.

· 98DDK points to the directory, if any, where you installed the Windows 98 DDK. Note that you need this DDK for just a few of the samples, as noted in the respective sample .HTM file.

2. Open a command prompt.

3. Set the following environment variables:
C:>set path=%ddkpath%\bin\x86;%path%
C:>set include=%ddkpath%\inc\wxp;%ddkpath%\inc\crt;%include%
C:>set lib=%ddkpath%\lib\wxp\i386;%lib%
The file netddk.bat in the WDMBOOK directory contains these commands, by the way.

4. Issue the command msdev /useenv. This invokes Visual Studio in such a way that the environment variables you just set are used to locate executable files, include files, and libraries. Note that the Visual Studio setup program should have modified your PATH environment to include the directories needed by MSDEV. If that didn’t occur, look for and execute a file named VCVARS32.BAT. If that doesn’t work, figure out by trial and error which directories you need in your path and try again.

5. Use the File/Open Workspace command to open the .DSP file for the project you want to build.

6. Use the Build menu to build the project. You will be using the compiler that ships with the DDK, which is required for Xp drivers.

Project changes: I recommend that you change the project settings to request the generation of a browsing database (from the Project Settings dialog, select the Browse Info tab and check the "Build browse info file" check box). I couldn't do this for you because this option isn't controlled by the project file I put on the disc.

DDK changes: From time to time, Microsoft changes the directory organization for the DDK and/or the options needed for compiling and linking drivers. The FIXPROJ utility in the WDMBOOK directory will help you modify your driver projects to cope with these changes.

Where files end up: The drivers built by the sample projects end up in the OBJCHK_WXP_I386\I386 or OBJFRE_WXP_I386\I386 subdirectories. This is the same place that BUILD would put them.

To build a driver using BUILD, open either the checked or free build environment using the shortcut created when you installed the DDK. Change to the project directory and issue the command "build -cewz". If a directory doesn't contain a SOURCES file, it means that you can't build the corresponding project using BUILD. For example, BUILD can't cope with a few of my samples that require different compile options for different files or that generate a VxD. Additionally, we didn't attempt to make BUILD work for the user-mode test programs because we figured that even die-hard BUILD users were prepared to use the Visual C++ integrated development environment for them.

The build scripts for these samples will copy the finished driver to the Drivers directory and create a symbol file (with an extension of .NMS) for use by the Numega Soft-Ice/W debugger. The next time you reboot the computer, you will be running the newly built driver. None of my samples has a name that duplicates that of a standard driver file, but you should check for conflicts with other drivers you may have installed.

In Windows XP, use the FastInst utility to install a sample driver for the first time. The fastest way to install a newer version of a driver is to Disable and re-Enable the device in the Device Manager. The Disable step unloads the current version. The Enable step loads the driver present in the Drivers directory, which by now will the one you’ve just rebuilt.

In Windows 98, you can also use FastInst. The fastest way to replace a driver is to remove it in Device Manager and then reinstall it using FastInst.

If you use two computers, be sure that you replicate enough of the WDMBOOK tree that the installation of the SAMPLE class will go smoothly the first time you try it. The easiest way to be sure of this, of course, is install the samples on both computers.

# General Instructions for Building User-Mode Samples

Many of the sample drivers include one or more user-mode components, such as test programs. Each such component has a project file (with a file extension of DSP) for use with Microsoft Visual C++ 6.0. If you want to build one of these components, open the project and use the Build menu command.

To build most of the user-mode samples, you will need a current copy of the Microsoft Platform SDK. Be sure that the Visual C++ directory settings include the SDK directories.

Note that you should use Visual C++ 6.0 rather than the DDK compiler for all user-mode samples. You won’t be able to debug them in Visual Studio if you use the DDK compiler.

# General Instructions for USB Samples

You can test the USB sample drivers (Chap12 directory) if you have a Cypress Semiconductors EZUSB development board (see http://www.cypress.com). Each of these samples has an EZUSB subdirectory containing the firmware for the "device" that the driver works with. A pre-built firmware image with a file extension of .HEX is there.

To install and test a USB sample driver, start with the EZ-USB development board in its default state. If you’re not sure of the state, press the Reset button, or unplug and replug the USB connector. Start the EzMr.EXE utility that comes with the development kit. Use the Download button to download the .HEX firmware file to the device. This step will change the personality of the board to match the device that the sample driver expects. The PnP Manager will then detect the new device and ask you to point to the INF file for the driver. The INF file for a USB sample is always named DEVICE.INF and is in the SYS subdirectory for the sample.

# Using WDMWIZ.AWX

Appendix B contains detailed instructions about how to use WDMWIZ.AWX, which is the same custom application wizard I used with Microsoft Visual C++ 6.0 to build the code samples. I deliberately left out the following additional instructions so it would be easy to change them up until the very last minute.

The Setup program attempts to copy WDMWIZ to the template directory for Visual Studio. You may need to copy this file by hand, however. The name of that directory on my computers is c:\Program Files\Microsoft Visual Studio\Common\MSDev98\Template. It might be different on your computer, depending on how you installed Visual C++. After you copy the file, the Projects tab on the New dialog in Visual Studio will include a choice labeled WDM Driver Wizard.

WDMWIZ is able to set up most of the project options you need for building a driver. The custom wizard support in Visual Studio is still missing a couple of features, though, and you need to modify the project in these minor respects.

1. Close the workspace if it's open. From Explorer, right-click on the .DSP file that WDMWIZ created for you and select the Fix WDM Driver Project command from the resulting context menu. This will run the FixProj utility that Setup installed on your computer in order to change the names of the project configurations and the output directory structure to better match the DDK.
2. Open the Project/Settings property page. Select the choice "All Configurations" from the "Settings For" list.
3. Tab to the "Browse Info" page and check "Build Browse Info File". I recommend doing this so you can easily locate the declarations of the kernel-mode support functions and structures your driver uses.

# WMI Functionality in Windows 98

You basically can't test Windows Management Instrumentation (WMI) functionality in the original release of Windows 98, but you can do so in Windows 98, Second Edition. My samples depend on WMILIB.LIB, which wasn't shipped with the originally released version of Windows 98. In addition, there is a bug in the user-mode provider module that makes it impossible to perform WMI queries to WDM drivers.

The setup program for Windows 98, Second Edition doesn't install the WBEM core by default. You must install it by hand at some point. To do so:

- Open Add/Remove Programs in the Control Panel, and select the Windows Setup tab.
- Within the Internet Tools category, indicate that you want to install Web-Based Enterprise Mgmt.
- You may need to reboot your computer before WMI will work. The setup program doesn't indicate that you should, but some testers have reported this as a problem.

# Definition of EULA Terms

The End User License Agreement (EULA) to which you agreed when you installed the sample programs uses two terms for which this document provides the definition:

The term SAMPLE CODE includes all of the sample programs referred to in the Directory of Sample Programs earlier in this document. The following modules, present on the companion disc, are not SAMPLE CODE and therefore may not be redistributed in any form:

- WDMWIZ.AWX (But any driver you generate by using WDMWIZ shall be considered SAMPLE CODE for purposes of the EULA.)
- FIXPROJ.EXE
- FASTINST.EXE
- DEVTEST.EXE and DEVSIM.VXD
- SAMCLASS.DLL and SAMCLS16.DLL (But any similar DLL that you generate based on my source code for your own devices or classes of devices shall be considered SAMPLE CODE for purposes of the EULA.)
- WDMCHECK.EXE (but any similar program and VxD that you generate based on my source code and distribute free of charge to anyone shall be considered SAMPLE CODE for purposes of the EULA.)

The following items of SAMPLE CODE, and any modules having the same names built, in whole or in part, from SAMPLE CODE, are designated as Non-Redistributable:

- GENERIC.SYS
- POWCPL.DLL
- WDMSTUB.VXD
- AUTOLAUNCH.EXE
- ALNCH98.EXE
- STARTSERVICE.DLL

You may request a separate, royalty-free license to redistribute these modules by writing directly to the author at waltoney@oneysoft.com. Please don't install a file with one of these names on an end-user system except in accordance with such a license, because you'll probably end up breaking drivers from other vendors and diminishing the end user experience of the operating system.

# How to Report Errors

There are errors in the book and in the code samples. If I knew what they were, they wouldn't be there. But I know there's a bunch of them lurking about. I maintain an errata page at my own Web site, which you can reach http://www.oneysoft.com. If you discover a mistake, please send me e-mail at waltoney@oneysoft.com. Many readers reported mistakes in the first edition, and their diligence enabled me to make the second edition a better book.