A lot of articles have been investigating in application layer issues, like skin-based dialogs, MFC, ATL, thread, process, registry etc. It won't be easy to find any driver related articles posted with full source code. The root cause is that most drivers are developed for specific hardware. Without the domain knowledge, you will never want to get in touch with it. I believe a lot of software engineers are afraid when they involve in kernel mode programming for the very first time, and there are not too much resources that can guide them through the whole process from DDK study to program stage. Hence I decided to share some of my experiences in driver programming in Windows. This demo focuses on a quick introduction to WDM Driver's architecture, and will introduce two I/O modes coming with Windows, which are Direct I/O and Buffered I/O, how to communicate with drivers residing in system kernel space, and read/write data to it.
There is no need for you to read the demo program with any hardware related background, the demo drivers are all pseudo drivers. That's drivers installed without a physical device in computer.
The member functions defined in this demo program can be used as templates for later driver development by you.
You might be a well-experienced software engineer and might want to involve in kernel programming.
Before we start, declaration for member routines and structures is required. The most important driver-required data structure is - <code>DEVICE_EXTENSION</code>!

Collapse
<a href="http://writeblog.csdn.net/#">Copy Code</a>
Code segment below demonstrates the start of creating a valid WDM Driver.
There are mandatory and optional members in a WDM Driver. A valid WDM Driver should come with the following member routines, the most important task item for <code>DriverEntry</code> is to register all member routines to kernel:

Normal operation workflow within WDM Driver
Code segment below demonstrates the workflow in <code>AddDevice</code> routine: the most important task for <code>AddDevice</code> routine is to create a Device object, and attach it to the existing device stack.

Code segment below shows how to support <code>IRP_MJ_CREATE</code>, it is send when client application tries to connect to the underlying Pseudo Driver. Before proceeding, see graph below in advance to realize the connection process.
Usually, you will use <code>CreateFile</code>/<code>fopen</code> Win32 API to connect to the underlying device. It is the right time that Win32 Subsystem submits <code>IRP_MJ_CREATE</code> and asks driver to connect to the target device!

Code segment below shows how to support <code>IRP_MJ_CLOSE</code>, the IRP is sent when client application tries to close connection to the underlying Pseudo Driver. Before proceeding, see graph below in advance to realize the closing process.
Usually, you will use <code>CloseHandle</code>/<code>fclose</code> Win32 API to close connection to the underlying device. It is the right time that Win32 Subsystem submits <code>IRP_MJ_CLOSE</code> and asks driver to close connection to target device!

There are three I/O modes in Windows kernel, they are Buffer, Direct and Neither modes. Now, we'll talk about Buffered I/O, and this article will not involve Neither mode for data transfer if processing under user-thread occupied memory space, it might be dangerous!! If client application is going to read/write data to and from driver, the memory address of data source will not be directly referenced by the underlying driver. System kernel will allocate another data buffer with equivalent size in kernel. All data transferred must be copied into this area before they are to the target place. Usually, you will call <code>ReadFile</code>/<code>WriteFile</code> or <code>fread</code>/<code>fwrite</code> to make read/write request.
Below code segment demos the workflow in I/O handle for read request. As we can see, the routine that is registered for reading is <code>PsdoDispatchRead</code> in <code>DriverEntry</code>, this member routine will read data out of Driver's internal member - <code>DataBuffer</code> to client application:

Below code segment demos the possible task items in workflow that can support the normal I/O requests to write data from application to driver.

Below graph exhibits how Direct I/O mode is supported when data is transferred between client application and driver. Under Direct I/O mode, Memory Manager will create MDL (Memory Descriptor List) to reference the physical address taken by user-provided buffer, all data can be directly referenced via MDL from kernel environment.
In DDK, some <code>MMXxx</code> routines are provided to help you to get MDL that maps to physical address of user-provided buffer.
Below code segment contains the statements that can support data reading under Direct I/O mode. It is achieved by <code>Mmxxx</code> routine, please read it carefully, and you can also find the full code in the zip file. The most important <code>MmXxx</code> you will use in this mode should be - <code>MmGetSystemAddressForMdlSafe</code>, it can obtain the MDL that references the physical address of user-buffer.

Below code segment demos the possible workflow to write data from user application to driver:

The zip file contains below subfolders:
Application: it contains the client applications to the Pseudo Driver.
bin: it contains the install/uninstall utility for Pseudo Driver.
BufferedIO_PW: it is where the Pseudo Driver that employees Buffered I/O mode for read/write resides.
DirectIO_PW: it is where the Pseudo Driver that employees Direct I/O Mode for read/write resides.
IOCTL_PW: it is where the Pseudo Driver that simply supports user-defined I/O Control Code resides.
ShareFiles: it is the common shared library for PnP, Power Management, I/O completion.
Install: it contains the source code of install/uninstall utility. (Install utility is directly referenced from DDK's sample, I won't provide redundant copy of it, only the uninstall utility source code is provided in it).
Unzip the package to some folder you'd like it to be, let's name it ROOT_OF_SOURCE.
Select Start->Programs->Development Kits->Windows DDK xxxx.xxxx->Build Environments->Free Build. (This is for free release without debug information in it.)
Enter ROOT_OF_SOURCE/SharedFiles subfolder, enter build -cefw, it all goes well, shared library will be generated.
Enter ROOT_OF_SOURCE/BufferedIO_PW subfolder, enter build -cefw, it will create Pseudo Driver - BufferDrv.sys. Copy this file into ROOT_OF_SOURCE/BufferedIO_PW/Install if you have made add-in for any new features, the copy is for later driver install.
Enter ROOT_OF_SOURCE/DirectIO_PW subfolder, enter build -cefw, it will create Pseudo Driver - DirectDrv.sys. Copy this file into ROOT_OF_SOURCE/DirectIO_PW/Install if you have made add-in for any new features, the copy is for later driver install.
Enter ROOT_OF_SOURCE/IOCTL_PW subfolder, enter build -cefw, it will create Pseudo Driver - PseudoDrv.sys. Copy this file into ROOT_OF_SOURCE/IOCTL_PW/Install if you have made add-in for any new features, the copy is for later driver install.
Unzip the source file, launch DOS prompt-console.
Enter into bin subfolder.
Execute DevInst.bat, it will automatically install the Pseudo Driver into your system.
Execute DevRemove.bat, it will automatically uninstall all-driver related resources from your system.
You can enter into ROOT_OF_SOURCE/Application subfolder, execute bufferclient.exe, directclient.exe, and clientapp.exe to verify if the three Pseudo Drivers have been installed successfully.
The install/uninstall of Pseudo Driver won't wok on Window 2000, the root cause might be that the Setup API doesn't work on Window 2000, can't allow driver installed without a physical hardware in it. Can anybody help to resolve it? Many Thanks.
If you'd like to install/uninstall the Pseudo Driver in Windows 2000, you will need to launch New Hardware Wizard from within Device Manager, and select to install new hardware->Display all hardware->Install from disk->"ROOT_OF_SOURCE/BufferedIO_PW/Install", click on OK button. New Hardware Wizard will install Buffered I/O Pseudo Driver. (This is for Buffered I/O demo driver install. As for Direct I/O, please set source directory to "ROOT_OF_SOURCE/DirectIO_PW/Install").
Reboot is required if the driver has been reinstalled after un-installation. I don't know why this happened, I hope somebody can inform me. Many Thanks.
Fix above issues.
WMI support in Pseudo Driver will be added-in.