This sample provides a starting point for Microsoft Windows driver Windows PowerShell sacript development. This sample contains annotated code to illustrate the functionality of a bus driver; a function driver; assorted class, device, and bus filter drivers; a class installer; and a device-specific co-installer for a hypothetical Toaster bus and its devices.
Every device driver stack for a Plug and Play (PnP) device on a Microsoft Windows Server 2003, Windows XP, or Windows 2000 operating system typically consists of a bus driver, a function driver, and zero or more filter drivers. These drivers must support PnP, power management, and Windows Management Instrumentation (WMI) to provide a better user experience and greater satisfaction.
These terms make sense if you have developed a driver for Windows 98 or Windows 95. But, if you have developed only Windows NT drivers, you might wonder: What are these terms? Why do I need to worry about them? How do I implement them?
Imagine a system with a new type of PnP I/O bus called a toaster bus. A controller chip on the motherboard initializes and manages the bus. The bus has a couple of ports that you can plug your toasters into.
To provide support for this bus on Windows NT 4.0, you must modify the hardware abstraction layer (HAL) to recognize and initialize the I/O bus during system startup, and you must provide a set of HAL functions for scanning the bus and accessing the configuration space of the devices by other drivers. Next, you must write drivers for every type of toaster device that loads along with the system, and then use the exported HAL functions to scan the bus to detect the device, read the I/O resource requirements, and configure and initialize the device. These drivers are loaded regardless of whether or not a particular toaster is plugged in.
If another driver requires the I/O resources that your driver claims, there is no resource distribution mechanism on Windows NT 4.0 to instruct the driver to relinquish them and use other resources if possible. If you want to expose instrumentation data or report some exceptional events to user mode, you must provide your own interface and custom applications. That is, there is no generic interface like WMI and no power management.
To support this bus and its devices under Windows, however, you do not have to modify the HAL or export a new set of functions. Instead, you need only to write a bus driver that has knowledge of bus architecture, identifies (that is, enumerates) devices on the bus, reads their resource requirements, and configures them. This driver model also makes the operating system independent of its I/O bus, so you do not need help from Microsoft if you design a new I/O bus to modify the HAL. Then, you write function drivers to control individual devices that are connected to the bus. Later on, you can write one or more filter drivers to add or modify the features that are supported by the bus, a specific device, or class of devices. There can be any number of lower-level or upper-level filter drivers for a bus, a device, or a class of devices.
The Windows Driver Kit (WDK) documentation explains these new concepts and features by providing background information and describing how to implement them in your drivers. The Toaster sample drivers provide annotated code samples that illustrate the functionality of various drivers without getting into detailed hardware specifics. These samples will help you start coding right away.
To make the sample code closer to a real-world driver, the sample defines a new class of devices called the TOASTER class and includes a bus driver, function driver, and all possible class, device, and bus filter drivers for this hypothetical TOASTER bus and its devices. There is also a sample coinstaller DLL to show how you can parse a custom section from an INF file and perform some special operations before and after the installation of a device and how you can create FriendlyName for a device. The function and bus driver also show how you can provide power manager and WMI support.
You can learn the implementation details of these sample drivers by looking at the code and reading the WDK documentation. The rest of this topic discusses the contents of the Toaster sample package and how to install, build, and test these drivers. This topic also briefly examines the various registry entries that are created by the system to set up and load the drivers.
Bus
Contains the source code of the bus driver (Busenum.sys)
Func
Contains the source code of the function driver (Toaster.sys).
Filter
Contains the source code of a generic WDM filter driver.
Toastmon
Contains the source code of a root-enumerated function driver that demonstrates how to open a PnP device in kernel mode and communicate with it in a PnP-friendly way.
ToastPkg
Contains various sample code to illustrate how to write a driver installation package.
ClassInstaller
Contains the sample code of a class installer DLL. This code demonstrates how to add an advanced property page to the device manager.
CoInstaller
Contains the sample code of a coinstaller. This code demonstrates how to create a friendly name for a device and how to parse custom INF sections.
INF
Contains INF files for installing bus, function, and filter drivers.
DISK
The target directory for all of the binaries when the source is built in the WDK. Except for Toaster.sys, all of the binaries all placed in this folder under a platform-specific directory.
This sample driver package contains bus, func, filter, exe, inc, coinstaller, classinstaller, inf, toastmon, and toastpkg directories. The following list describes the directories and key files:
bus
Contains the source code of the toaster bus driver (Busenum.sys). This driver services the TOASTER bus controller, enumerate devices that are plugged in, and performs bus-level power management. The bus driver supports D0 and D3 power states. It also has a WMI interface.
func
Contains subdirectories that contain the source code of the function driver (Toaster.sys) for standard toaster devices. To be an illustrative and useful learning sample for beginners to driver development, the sample has been built from almost nothing (skeletal) to fully functional, adding useful features at each step. When the sample is built, all of the different versions produce Toaster.sys files in the subdirectories of func. You can use the standard Toaster.inf or Toastco.inf to install and test. You can either manually install the driver (root-enumerations) or bus enumerate the driver by using the toaster bus driver. They all share one common header file that is present in the shared directory. Assume that the function driver owns the power policy of the toaster device and supports D0, D1, and D3 power states and also that the toaster device can wake up the system from the D1 state.
The func directory contains the following subdirectories:
Incomplete1: The simplest form of a WDM driver. The Toaster.sys file in this directory shows bare minimum functionality that is required to be installed and loaded in the system. You cannot open the device or talk to it. As the name suggests, this driver is not complete and safe enough to be used as a model for a production level driver.
Incomplete2: A slightly advanced form from the Incomplete1 version. The Toaster.sys file in this directory shows how to track I/O IRPs and handle stop and remove PnP requests safely with respect to driver unload. Instead of using remlocks, this sample implements its own locking scheme to be more general purpose and compatible with Windows 98 and Windows 95 operating systems. You can open the registered interface from user mode and send read, write, and IOCTL requests. This sample is still an incomplete sample because it does not handle power IRPs and perform the necessary S-to-D power IRP conversion that the bus driver requires.
Featured1: A complete version of Toaster.sys. The Toaster.sys file in this directory contains full power management and WMI support.
Featured2: A complete version of Toaster.sys. The Toaster.sys file in this directory contains wait-wake support and Event Tracing support in addition to all of the features that the Featured1 sample supports.
inc
Contains headers files that are shared among drivers and applications.
Disk
The build target path. All of the toaster binaries are placed in the Disk directory during build under the respective build_environment\target_OS subdirectories. For example, if you build under the Windows Server 2003 x86 checked build environment, the target path will be disk\chk_wnet_x86\i386\. Because there is more than one version of Toaster.sys, it is not placed in Disk directory to avoid overwriting other versions. All of the various versions of Toaster.sys are built under their respective source directory.
exe
Contains three subdirectories, notify, enum, and toast, with files to produce Notify.exe, Enum.exe, and Toast.exe (user-mode console applications):
Enum.exe is a user-mode enumerator, a simple console application. Because the toaster bus is not real, you need to have a mechanism to tell the bus driver when you plug in, unplug, and eject devices from the system. The Enum.exe application serves that purpose. Typically, it is written as a control panel applet for non-PnP (legacy) devices (for example, Game.cpl).
Usage: Enum [-a SerialNo] - Plugs in a device. SerialNo must be greater than zero.
[-r SerialNo or 0] - Unplugs devices. Specify 0 to unplug all of the devices that are enumerated so far.
[-e SerialNo or 0] - Ejects devices. Specify 0 to eject all of the devices that are enumerated so far.
By design every toaster device will have a globally unique serial number.
Toast.exe is a user-mode console application to control the toaster.
Notify.exe is a GUI application that combines the functionality of Enum.exe and Toast.exe and shows how to handle PnP notification in user mode. You should install the coinstaller for the toaster device by using Toastco.inf to get a meaningful display of the PnP notification. In Notify.exe, you can also specify some other hardware ID (instead of the default toaster device ID) and cause other drivers to be loaded as a function driver. This functionality is useful for testing prototype drivers to check whether the PnP code works.
filter
Contains six different subdirectories that each produce one of the following drivers from a common source file (Filter.c):
Class upper filter (Clsupper.sys)
Class lower filter (Clslower.sys)
Device upper filter (Devupper.sys)
Device lower filter (Devlower.sys)
Bus FDO upper filter (Bfdoupr.sys)
Bus FDO lower filter (Bfdolwr.sys)
coinstaller
Contains source code of the device-specific coinstaller (Tostrco1.dll). The WDK documentation has a good overview of a coinstaller and its operation. The coinstaller demonstrates how to create a FriendlyName for a device based on its unique instance ID. In this sample, during enumeration, the bus driver provides the serial number in the UINumber field of the device capabilities. The FriendlyName is required to uniquely identify multiple devices of the same interface class. The coinstaller also shows how to open an INF file and parse a custom section.
classinstaller
Contains source code of the class-installer (Tostrcls.dll). The WDK documentation has a good overview of a class installer and its operation. This fake class installer is included to provide a class icon for all of the TOASTER class devices. This installer is copied to the system32 directory when the class is installed for the first time in the system.
inf
Contains three subdirectories (i386, amd64, and ia64), and each subdirectory contains the following files:
Bus.inf installs Basenum.sys and sets up the registry.
Simple.inf creates the Toaster class, installs Toaster.sys, and sets up the registry.
Toaster.inf is functionally similar to Simple.inf but also installs the class installer. The class installer provides the custom icon for the class and an advanced property page to change the FriendlyName of the device in the device manager.
Toastco.inf is functionally similar to Toaster.inf but also installs the coinstaller. The coinstaller is used to dynamically create a unique FriendlyName of the device based on the serial number.
Busf.inf and Toasterf.inf are functionally similar to the preceding INF files but also install all of the previously mentioned filter drivers.
Filter.inf installs a device upper filter for the toaster device. Please read the Filter section under Operating System Concepts to learn how to use this INF file.
Toaster.cat is a dummy catalog file.
toastmon
Contains the source code of a root-enumerated driver called Toastmon.sys. For more information about this driver, see the Toastmon section under Operating System Concepts.
toastpkg
Contains the source code for an integrated device installation solution that illustrates how to provide support for the various user approaches to adding new hardware, while providing optional value-added software, and so on. For more information, see the Toastpkg.htm file in the toastpkg directory.
To build the Toaster sample drivers, you must first set up the WDK environment on your host computer . The "Installation and Release Notes" in the WDK has a complete description on how to do this. The basic steps are as follows:
Run the build -ceZ command in the src\general\toaster directory to build Busenum.sys, Toaster.sys, Enum.exe, Toast.exe, Tostrco1.dll, Tostrcls.dll, and the six filter drivers that were mentioned previously.
Copy all of the .sys, .exe, and .dll files, a bus driver INF file (Bus.inf), Toaster.cat, and a toaster device INF file (Toastco.inf) to a floppy disk or a temporary directory on the target system.
General
First, install the bus driver. To install the bus driver on Windows 2000:
Double-click Add or Remove Hardware in Control Panel.
In the Add or Remove Hardware wizard, click Next.
Select Add/Troubleshoot a device, and then click Next.
Select Add a new device, and then click Next.
Select No, I Want to Select the Hardware from a list, and then click Next.
Select System Devices, and then click Next. Note that this operation might take a few minutes.
Click Have Disk, make sure that drive A (or your disk drive) is in the Copy manufacturer's files from box, and click OK.
Click the entry that you want, and then click Next.
On the Start Hardware Installation page, click Next.
On the Completing the Add/Remove Hardware Wizard page, click Finish.
To install the bus driver on Windows XP and Windows Server 2003:
On the Welcome to the Add Hardware Wizard page, click Next.
Select Yes, I have already connected the hardware, and then click Next.
Select Add a new hardware device near the bottom of the list, and then click Next.
Select Install the hardware that I manually select from a list (Advanced), and then click Next.
Select System devices, and then click Next.
On the The wizard is ready to install your hardware page, click Next.
To install the bus driver on Windows 7:
Click Start and enter Hdwwiz.exe.
The system copies the Busenum.sys file to the %Systemroot%\system32\drivers directory and sets up the following registry keys to represent the bus driver to the PnP manager:
The system copies the INF file as OEM.n.INF, where n is a zero-based number, to the system INF directory. It also creates the following standard Services keys to load the driver:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\busenum.
After the driver is installed, the system creates device registry keys (Hardware keys) under:
Alternate Installation
You can also quickly install the bus driver without going through so many mouse clicks by using the Installer sample application in the ntddk\src\general\devcon directory of the WDK. This sample enables you to root-enumerate a driver with one simple command. Please read the help file that is included in the sample to learn how to build and use the application to install this driver. To install the bus driver by using Devcon.exe, run devcon.exe install bus.inf "root\busenum".
After the Toaster bus driver is installed and started by the PnP manager, you can run the Enum.exe or Notify.exe application from a command prompt to simulate plug in, unplug, or ejection of toaster devices on the system. Both of these applications send an I/O control (IOCTL) to the bus driver with the user-provided globally unique serial number and hardware ID of the device and trigger the entire enumeration process. The PnP manager takes the ID information that the bus driver provides and searches the system INF directory to find a matching INF file. If the PnP manager does not find a suitable INF file (for example, when you install for the first time), it prompts the user to specify an INF file. At this point, you can pick one of the three INF files (Toaster.inf, Toastco.inf, or Toasterf.inf) to be the device INF file. If you are testing this sample for the first time, you should choose Toastco.inf.
You can remove or eject a single device by giving its serial number or remove or eject all of the devices by specifying 0 (zero) as the serial number of the device.
To plug in a device
At a command prompt, run enum -p 1.
To unplug a device
At a command prompt, run enum -u 1.
To eject a device
At a command prompt, run enum -e 1.
To test a plugged in device, you can use the Toast.exe application. This application basically enumerates all of the toaster class devices, displays its properties (such as FriendlyName and InstanceId), and opens the last enumerated device to perform a read operation and send DeviceIoControl to the device, depending on the user command-line option.
If you call Toast.exe without any option, it opens the last enumerated interface and prompts you to initiate a read operation in a loop. You press any key to continue the read loop or press Q to break out of the loop. If you use the -h option, Toast.exe opens the last enumerated interface and sends DeviceIoControl to hide the device from the Device Manager before performing the read operation.
Usage: Toast <-h> {-h option causes the device to hide from the Device Manager user interface}
Both Toast.exe and Enum.exe use the SetupDi functions to enumerate and open the device interfaces. These functions are documented in the WDK documentation.
The preceding section describes how to install the Toaster.sys driver for a toaster bus-enumerated device. You can also manually install the function driver (root-enumeration) by using the Add Hardware wizard.
Depending on which INF file you want to install, you will need a different set of files:
If you use Toaster.inf, you need any one version of Toaster.sys and Tostrcls.dll. Copy those files to a floppy disk or to a directory on the target computer and follow the install instructions that follow this list.
If you use Toastco.inf, you also need Tostrco1.dll.
If you use Toasterf.inf, you also need Devupper.sys, Devlower.sys, Clasuppr.sys, and Classlwr.sys filter drivers and Toaster.sys and Tostrcls.dll. You must make sure that the toaster class has not already been installed on that computer. Otherwise, the computer will not install the class filter drivers. For testing purposes, if the toaster class is already installed, uninstall all of the devices, and then manually delete the class registry (HKLM\System\CurrentControlSet\Control\Class\{B85B7C50-6A01-11d2-B841-00C04FAD5171}) before you install the driver with Toasterf.inf.
To install the Toaster.sys driver on Windows Server 2003 or Windows XP:
Double-click the Add Hardware wizard in Control Panel.
To install the Toaster.sys driver on Windows 7:
Maheshkumar S Tiwari edited Original. Comment: Added Tag and minor edit