This section includes general concepts to help you understand kernel-mode programming and describes specific techniques of kernel programming. For a general overview of Windows Drivers, see Getting Started with Windows Drivers, which provides a general overview of Windows components, lists the types of device drivers used in Windows, discusses the goals of Windows device drivers, and discusses generic sample device drivers included in the kit.
Memory Management for Windows Drivers illustrates how kernel-mode drivers allocate memory for purposes such as storing internal data, buffering data during I/O operations, and sharing memory with other kernel-mode and user-mode components.
Windows Management Instrumentation (WMI) are extensions to your kernel-mode driver, which enable your driver to become a WMI provider. A WMI provider makes measurement and instrumentation data available to WMI consumers, such as user-mode applications.
A processor in a computer running Windows operates in two different modes: user mode and kernel mode. The processor switches between these modes depending on the type of code it's executing. Applications operate in user mode, while core operating system components function in kernel mode. Although many drivers operate in kernel mode, some can function in user mode.
When you launch an application in user mode, Windows creates a process for it. This process provides the application with a private virtual address space and a private handle table. Since each application's virtual address space is private, one application can't modify another application's data. Each application runs in isolation, ensuring that if one crashes, it doesn't affect other applications or the operating system.
The virtual address space of a user-mode application is also limited. A process running in user mode can't access virtual addresses that are reserved for the operating system. Limiting the virtual address space of a user-mode application prevents the application from modifying or damaging critical operating system data.
All code running in kernel mode shares a single virtual address space. As a result, a kernel-mode driver isn't isolated from other drivers or the operating system. If a kernel-mode driver mistakenly writes to the wrong virtual address, it could compromise data belonging to the operating system or another driver. If a kernel-mode driver crashes, it causes the entire operating system to crash.
Visual Studio creates one project and a solution. You can see them in the Solution Explorer window. (If the Solution Explorer window isn't visible, choose Solution Explorer from the View menu.) The solution has a driver project named KmdfHelloWorld.
Now that you've created your empty Hello World project and added the Driver.c source file, you'll write the most basic code necessary for the driver to run by implementing two basic event callback functions.
DriverEntry is the entry point for all drivers, like Main() is for many user mode applications. The job of DriverEntry is to initialize driver-wide structures and resources. In this example, you printed "Hello World" for DriverEntry, configured the driver object to register your EvtDeviceAdd callback's entry point, then created the driver object and returned.
The driver object acts as the parent object for all other framework objects you might create in your driver, which include device objects, I/O queues, timers, spinlocks, and more. For more information about framework objects, see Introduction to Framework Objects.
EvtDeviceAdd is invoked by the system when it detects that your device has arrived. Its job is to initialize structures and resources for that device. In this example, you simply printed out a "Hello World" message for EvtDeviceAdd, created the device object, and returned. In other drivers you write, you might create I/O queues for your hardware, set up a device context storage space for device-specific information, or perform other tasks needed to prepare your device.
For the device add callback, notice how you named it with your driver's name as a prefix (KmdfHelloWorldEvtDeviceAdd). Generally, we recommend naming your driver's functions in this way to differentiate them from other drivers' functions. DriverEntry is the only one you should name exactly that.
This example illustrates a fundamental concept of drivers: they're a "collection of callbacks" that, once initialized, sit and wait for the system to call them when it needs something. A system call could be a new device arrival event, an I/O request from a user mode application, a system power shutdown event, a request from another driver, or a surprise removal event when a user unplugs the device unexpectedly. Fortunately, to say "Hello World," you only needed to worry about driver and device creation.
If you see DriverVer set to a date in the future when building your driver, change your driver project settings so that Inf2Cat sets /uselocaltime. To do so, use Configuration Properties->Inf2Cat->General->Use Local Time. Now both Stampinf and Inf2Cat use local time.
Typically when you test and debug a driver, the debugger and the driver run on separate computers. The computer that runs the debugger is called the host computer, and the computer that runs the driver is called the target computer. The target computer is also called the test computer.
When you follow the steps to provision the target computer automatically using a network cable, take note of the port and key. You'll use them later in the debugging step. In this example, we'll use 50000 as the port and 1.2.3.4 as the key.
In real driver debugging scenarios, we recommend using a KDNET-generated key. For more information about how to use KDNET to generate a random key, see the Debug Drivers - Step by Step Lab (Sysvad Kernel Mode) topic.
In this exercise, the hardware ID does not identify a real piece of hardware. It identifies an imaginary device that will be given a place in the device tree as a child of the root node. For real hardware, do not select Hardware ID Driver Update; instead, select Install and Verify. You'll see the hardware ID in your driver's information (INF) file. In the Solution Explorer window, go to KmdfHelloWorld > Driver Files, and double-click KmdfHelloWorld.inf. The hardware ID is located under [Standard.NT$ARCH$].
On the Build menu, choose Deploy Solution. Visual Studio automatically copies the files required to install and run the driver to the target computer. Deployment may take a minute or two.
When you deploy a driver, the driver files are copied to the %Systemdrive%\drivertest\drivers folder on the test computer. If something goes wrong during deployment, you can check to see if the files are copied to the test computer. Verify that the .inf, .cat, test cert, and .sys files, and any other necessary files, are present in the %systemdrive%\drivertest\drivers folder.
With your Hello World driver deployed to the target computer, now you'll install the driver. When you previously provisioned the target computer with Visual Studio using the automatic option, Visual Studio set up the target computer to run test signed drivers as part of the provisioning process. Now you just need to install the driver using the DevCon tool.
The INF file required for installing this driver is KmdfHelloWorld.inf. The INF file contains the hardware ID for installing the driver binary, KmdfHelloWorld.sys. Recall that the hardware ID, located in the INF file, is Root\KmdfHelloWorld.
If you get an error message about devcon not being recognized, try adding the path to the devcon tool. For example, if you copied it to a folder on the target computer called C:\Tools, then try using the following command:
On the host computer, open a Command Prompt window as Administrator. Change to the WinDbg.exe directory. We'll use the x64version of WinDbg.exe from the Windows Driver Kit (WDK) that was installed as part of the Windows kit installation. Here's the default path to WinDbg.exe:
Launch WinDbg to connect to a kernel debug session on the target computer by using the following command. The value for the port and key should be the same as what you used to provision the target computer. We'll use 50000 for the port and 1.2.3.4 for the key, the values we used during the deploy step. The k flag indicates that this is a kernel debug session.
Make sure you use the "go" command to let the target computer run again before exiting the debugger, or the target computer will remain unresponsive to your mouse and keyboard input because it is still talking to the debugger.
The Kernel-Mode Driver Framework (KMDF) is a driver framework developed by Microsoft as a tool to aid driver developers create and maintain kernel mode device drivers for Windows 2000[a] and later releases. It is one of the frameworks included in the Windows Driver Frameworks.[1] The current version is 1.27.
In general, KMDF supports drivers that were written for the Windows Driver Model, and it runs on WDM. WDM is the driver model used since the advent of Windows 98, whereas KMDF is the driver framework Microsoft advocates and uses for Windows 2000 and beyond.
KMDF is object-based and built on top of WDM. It provides an object-based perspective to WDM, following the architectural mandate of its superset, WDF. The functionality is contained in different types of objects. KMDF implementation consists of:
Kernel drivers are programs written against Windows NT's native API (rather than the Win32 Subsystem's API) and which execute in kernel mode on the underlying hardware. This means that a driver needs to be able to deal with switching virtual memory contexts between processes, and needs to be written to be incredibly stable -- because kernel drivers run in kernel mode, if one crashes, it brings down the entire system. Kernel drivers are unsuitable for anything but hardware devices because they require administrative access to install or start, and because they remove the security the kernel normally provides to programs that crash -- namely, that they crash themselves and not the entire system.
64591212e2