Driver is a very important piece of software that provides a way for a particular hardware to interact with a particular Operating System. Another thing that you need to know about drivers is that it is particularly hard to deal with them. Driver development not always goes smoothly even for major players in the hardware industry, not to mention small startups or enthusiast developers. Sure, there are always experts out there that you can hire to do your driver development for you (companies like Apriorit). However, it is never late to start learning Linux or Windows driver development by yourself. We hope that this simple Windows device driver development tutorial will prove a great starting point for you in this endeavor.
Defining a driver
The simplest way to define a driver is to say that it is a piece of software that provides the system with the ability to work with a particular device. However, this gives us an incomplete understanding of what a driver is. There are actually different types of drivers out there, all of which can be divided into several groups by the two important criteria:
Division by tasks:
• Functional driver– a regular driver working directly with hardware. Uses standard I/O requests. Such drivers are more often than not created by vendors to ensure smooth operation of their hardware on a particular system.
• Filter driver – drivers that do not communicated with hardware directly, but rather take part in processing request to the device as a part of a driver stack that handles most requests to a hardware. They are used to modify requests, log them, or eve to restrict access to device. A good example of a filter driver is anti-virus scanner that checks files for viruses before allowing user to open them.
• Software driver. This type of drivers have nothing to do with physical devices. A good example of software driver is when you need to create an app that will detect all hidden processes. In order to do this, you need to get information from the system kernel that describes all running processes. The best way is to split your app into two chunks – one running in kernel mode and providing the necessary system information, and a simple graphical interface running in user mode.
Division by the context of execution:
• Kernel Mode drivers. Drivers of this type are executed in a system kernel itself, and have access to all closed system information.
• User Mode drivers. Not all drivers need to use system kernel. Sometimes they can be executed in user mode, which allows to avoid any major potential impact on the system stability.
Specifics of driver development
Programmers see drivers as a set of functions designed to process requests to a specific piece of hardware. Specific procedures should be implemented with regards to specific requests.
When developing a driver, it is important to remember that any mistake when dealing with kernel mode can lead to the crash of the whole system. Thus, it is very important to exercise caution.
When it comes to languages that are used for driver development, you select them based on the type of the driver you want to create. For example, only C language is supported by WDK compiler for kernel mode driver, while user mode drivers can be developed in C++ with COM interfaces used for interactions with WDK.
Tools you may need
Developing, debugging and testing your driver requires a fairly robust tool set. For Windows device driver development, tools below are very useful:
• For libraries, compilers and sample code you use Windows Development Kit (WDK)
• As a development environment you use Microsoft Visual Studio
• OSR Loader is a great tool for installing/uninstalling and running your driver
• WinDbg – a great and easy to use debugger, part of WDK
It’s also best to use virtual machines to develop and test your driver, as to not cause any trouble for your real system. The most popular ones are VMWare and VirtualBox. You can also employ VirtualKD – a great tool, allows you to setup virtual machine for debug in kernel mode in a fast and easy way.
Developing a simple driver
Next, we will cover the basics of how to create your own simple Windows device driver. The first thing you need to do is to open Visual Studio and create an Empty Driver project. Driver should define at least a single function – DriverEntry, used to load it. A basic logic can be included in the function, for example, you can make it display a sample text. When all is done, you can build your driver.
When the driver is complete, the following files will be created:
• .sys – the driver file
• .pdb – this file has the necessary data for debugging (variables and functions)
• .inf – configuration file
• .cer – certificate for the driver. Windows will refuse to load an unsigned driver
To get your driver running, you need to install it. You need to run OSLOADER.exe and set the path to the driver. Complete the installation and click “Register Service”. Now the driver will appear in the registry.
Another thing you should not forget to do is to allow the driver to be unloaded when it does not needed. Otherwise, it will be stuck in the memory until the next reboot.
To receive requests for your device, you should also register it in the system. This involves defining the data structure, device name, and finally creating an object. Application will also need a link to a device in order to be able to work with it. Request handling function should also be registered by filling out an array of pointers. In order to see the device you just registered you can use WinObj utility from Sysinternals.
Now, a thing to note about processing errors. In C language, it is considered common practice to return an error code from the function. Returned errors will be checked and processed by the calling routine. The “goto” statement is used to release resources if an error has occurred.
Microsoft provides Driver verifier as a part of Windows distributive – a great tool to test your drivers. To access it you need to type verifier in Command Prompt. You can use it to catch memory leaks, deadlocks, incorrectly processed requests, and other errors.
This short and simple Windows drivers development tutorial covered a lot of basics. However, driver development is a very complex topic, and there are still a ton of stuff to discover. Each system presents its own set of challenges, not to mention the variety of devices out there. Thus we want to encourage you to keep learning and keep experimenting with virtual systems. You can look up any information on Windows API at Microsoft Software Development Network.
Good luck with your driver development efforts!
Written by Dennis Turpitka