**************************************** ***********************/
// The required header file declares the function modules and variables:
# Include "hellowdm. H"
/*************************************** ************************
Function Name: DriverEntry ()
Function Description: WDM program entry
**************************************** ***********************/
// Extern "C" is required, indicating "using C link ". This statement can be omitted if your file name is hellowdm. C.
Extern "C"
Ntstatus DriverEntry (in pdriver_object driverobject,
In punicode_string registrypath)
{
// Specify the "add device" message to be processed by the "hellowdmadddevice ()" function:
Driverobject-> driverextension-> adddevice = hellowdmadddevice;
// Specify the "plug-and-play" message to be processed by the "hellowdmpnp ()" function:
Driverobject-> majorfunction [irp_mj_pnp] = hellowdmpnp;
// Return an ntstatus value STATUS_SUCCESS. Almost all driver routines must return an ntstatus value, which is defined in detail in the ntstatus. h DDK header file.
Return STATUS_SUCCESS;
}
/*************************************** ************************
Function Name: hellowdmadddevice ()
Function Description: processes "add device" messages.
**************************************** ***********************/
Ntstatus hellowdmadddevice (in pdriver_object driverobject,
In pdevice_object physicaldeviceobject)
{
// Define the returned value of the ntstatus type:
Ntstatus status;
// Define a function device object ):
Pdevice_object fdo;
// Create a feature device object and store it in fdo:
Status = iocreatedevice (
Driverobject, // driver object
Sizeof (device_extension), // the size of the required device extension
Null, // device name, null
File_device_unknown, // The type of the device. One of the file_device_xxx values listed in the standard header file WDM. h or ntddk. h.
0, // constants are combined with or to indicate that the media can be deleted and read-only.
False, // if only one thread can access the device at a time, the value is true; otherwise, the value is false.
& Fdo); // The returned device object.
// Nt_success macro is used to test whether the iocreatedevice kernel is successfully completed. Do not forget to check whether all calls to the kernel are successful. Nt_error macro is not the same! Nt_success, preferably! Nt_success, because in addition to errors, it also intercepts warning information.
If (! Nt_success (Status ))
Return status;
// Create a device extension object dx to store the pointer to fdo:
Pdevice_extension dx = (pdevice_extension) fdo-> deviceextension;
DX-> fdo = fdo;
// Use the ioattachdevicetodevicestack function to connect the hellowdm device to the device Stack:
DX-> nextstackdevice = ioattachdevicetodevicestack (fdo, physicaldeviceobject );
// Set flags of fdo. There are two "bits" that must be changed. One is that the do_device_initializing flag must be cleared. If iocreatedevice () is called in the DriverEntry routine, this flag does not need to be cleared. Also, the do_buffer_io flag must be set:
Fdo-> flags | = do_buffered_io | do_power_pagable;
Fdo-> flags & = ~ Do_device_initializing;
// Return value:
Return STATUS_SUCCESS;
}
/*************************************** ************************
Function Name: hellowdmpnp ()
Function Description: process the "out-of-the-box" message.
**************************************** ***********************/
Ntstatus hellowdmpnp (in pdevice_object fdo,
In pirp)
{
// Create a device extension object dx to store the pointer to fdo:
Pdevice_extension dx = (pdevice_extension) fdo-> deviceextension;
// Obtain the current IRP through iogetcurrentirpstacklocation () and obtain the minor function:
Pio_stack_location irpstack = iogetcurrentirpstacklocation (IRP );
Ulong minorfunction = irpstack-> minorfunction;
// Then pass the minor function to the next device Stack:
Ioskipcurrentirpstacklocation (IRP );
Ntstatus status = iocalldriver (DX-> nextstackdevice, IRP );
// Process the "plug-and-play" function code:
// When minor function is equal to irp_mn_remove_device, it indicates that a device has been removed or removed. In this case, cancel resource allocation and delete the device:
If (minorfunction = irp_mn_remove_device)
{
// Cancel the device interface:
Iosetdeviceinterfacestate (& DX-> ifsymlinkname, false );
Rtlfreeunicodestring (& DX-> ifsymlinkname );
// Call iodetachdevice () to remove fdo from the device Stack:
If (DX-> nextstackdevice)
Iodetachdevice (DX-> nextstackdevice );
// Delete fdo:
Iodeletedevice (fdo );
}
// Return value:
Return status;
}
/*************************************** ************************
Program name: Hello world for WDM
File Name: hellowdm. h
Author: Luo Cong
Date: 2002-8-16
**************************************** ***********************/
// Header file, which only declares some functions and variables. This is simple and not to mention. Please study it yourself:
# Ifdef _ cplusplus
Extern "C"
{
# Endif
# Include "ntddk. H"
# Ifdef _ cplusplus
}
# Endif
Typedef struct _ device_extension
{
Pdevice_object fdo;
Pdevice_object nextstackdevice;
Unicode_string ifsymlinkname;
} Device_extension, * pdevice_extension;
Ntstatus hellowdmadddevice (in pdriver_object driverobject,
In pdevice_object physicaldeviceobject );
Ntstatus hellowdmpnp (in pdevice_object fdo,
In pirp );
Well, the first WDM "Hello world" is introduced here. Although it does not actually do anything, it contains a complete framework, therefore, it is of great reference value for beginners. For how to compile and install it, please stay tuned for the next lecture. (I don't want to sell it out. These steps are really troublesome. I have to write another article to make it clear !)
Getting started with WDM drivers (2)-the secrets of drivers
Okay, I 've finally finished writing the program. Let's compile and run it! Press Ctrl + F5 (hey, let's assume you are used to using VC to write programs). I will wait ...... Suspect? Why is there no movement? Let's look at the output window. Wow! Hundreds of errors !! Can't help but get bigger -- what's going on?
Originally, the wdmprogram compiled is not our own. EXE file, but the. SYS file. It cannot be compiled directly using VC before the compiling environment is set (that is why there are hundreds of errors ). You can find many files of this type in winnt/system32/drivers. In fact, the driver is also a PE file. It also starts with the dos mz header, and has the complete Dos Stub and PE Header, as well as the import table and export table -- Hoho ...... What is the difference with a normal PE file? The great leader Chairman Mao taught us that practice is the only criterion for testing truth. Let's make a small analysis to deepen our understanding of the. SYS file! (If you are not interested in the internal details of. sys, you can skip it. ^_^)
The tdump.exe program included in delphiis first served (don't ask me why I use this, this is just a pure habit ). Let's enter:
C:/winnt/system32/drivers> tdump ccport. sys-em-ee
The-em parameter lists the import table, and the-ee parameter lists the export table. After you press enter, a lot of things are listed on the screen:
C:/winnt/system32/drivers> tdump ccport. sys-em-ee
Turbo dump version 5.0.16.12 copyright? 1988,200 0 Inprise Corporation
Display of file ccport. sys
Import: ntoskrnl. EXE = {hint: 011fh}. 'memcpy'
Import: ntoskrnl. EXE = {hint: 003dh}. 'iodeletedevic'
Import: ntoskrnl. EXE = {hint: 0030 h}. 'ioattachdevicetodevicestack'
Import: ntoskrnl. EXE = {hint: 008eh}. 'kesetevent'
Import: ntoskrnl. EXE = {hint: 0068 h}. 'iofcalldriver'
Import: ntoskrnl. EXE = {hint: 0095 h}. 'kewaitforsingleobject'
Import: ntoskrnl. EXE = {hint: 0074 h}. 'keinitializeevent'
Import: ntoskrnl. EXE = {hint: 003fh}. 'iodetachdevice'
Import: ntoskrnl. EXE = {hint: 00d3h}. 'rtlfreeunicodestring'
Import: ntoskrnl. EXE = {hint: 0077 h}. 'keinitializespinlock'
Import: ntoskrnl. EXE = {hint: 0129 h}. 'strcpy'
Import: ntoskrnl. EXE = {hint: 0121 h}. 'memset'
Import: ntoskrnl. EXE = {hint: 003ch}. 'iocreateunprotectedsymboliclink'
Import: ntoskrnl. EXE = {hint: 0038 h}. 'iocreatedevic'
Import: ntoskrnl. EXE = {hint: 00c2h}. 'rtlansistringtounicodestring'
Import: ntoskrnl. EXE = {hint: 0069 h}. 'iofcompleterequest'
Import: ntoskrnl. EXE = {hint: 0124 h}. 'sprintf'
Import: ntoskrnl. EXE = {hint: 003eh}. 'iodeletesymboliclink'
Import: ntoskrnl. EXE = {hint: 0042 h}. 'iofreeir'
Import: ntoskrnl. EXE = {hint: 004dh}. 'ioinitializeir'
Import: ntoskrnl. EXE = {hint: 002dh}. 'ioallocateir'
Import: ntoskrnl. EXE = {hint: 0027 h}. 'interlockedexchang'
Import: ntoskrnl. EXE = {hint: 0025 h}. 'interlockedcompareexchange'
Import: ntoskrnl. EXE = {hint: 0035 h}. 'iocelir'
Import: ntoskrnl. EXE = {hint: 012ah}. 'strlen'
Import: ntoskrnl. EXE = {hint: 0126 h}. 'strcat'
Import: ntoskrnl. EXE = {hint: 0114 h}. 'atoi'
Import: ntoskrnl. EXE = {hint: 0128 h}. 'strcmp'
Import: ntoskrnl. EXE = {hint: 0034 h}. 'iobuildsynchronousfsdrequest'
Import: ntoskrnl. EXE = {hint: 00d5h}. 'rtlinitansistring'
Import: Hal. dll = {hint: 0006 h}. 'kfacquirespinlock'
Import: Hal. dll = {hint: 0009 h}. 'kfreleasespinlock'
Export ord: 0001 = 'vcomm _ drivercontrol'
We can clearly see that it mainly calls ntoskrnl. EXE and Hal. DLL file (in fact, you will find that almost all WDM Drivers call ntoskrnl. EXE file, you can see from its name why ?), And a function "vcomm_drivercontrol" is output ". In this example, the. sysfile is a PE file. Similarly, the. sysfile importis usually ntoskrnl.exe, and the. exe file import is usually kernel32.dll and user32.dll.
What's the purpose of this? In fact. sys usually does not call kernel32.dll and user32.dll, so you cannot call any C, C ++, or Win32 functions in the device driver, in addition, a large number of kernel functions must be used instead of the C ++ keywords such as new and delete (which can be replaced by malloc and free. For your convenience, I will list some common kernel functions available for drivers:
Ex... Execution Support
Hal... Hardware Abstraction Layer (NT/Windows 2000 only)
Io... I/O manager (including Plug and Play functions)
Ke... Kernel
KS... Kernel stream IRP management functions
Mm... Memory Manager
Ob... Object Manager
Po... Power Management
PS... Process Structure
RTL... Runtime Library
Se... Security Reference monitoring
ZW... Other functions
Finally, let's take a look at some issues that must be paid attention to when writing device drivers:
1. kernel macro
If you view the DDK header file, several kernel functions are implemented in macro mode. The definition of several Macros in such macros is rather bad. For example, the removeheadlist is defined as follows:
# Define removeheadlist (listhead)
(Listhead)-> flink;
{Removeentrylist (listhead)-> flink )}
If removeheadlist is called in the following way, the wrong code will be compiled:
If (somethinginlist)
Entry = removeheadlist (list );
The only way to secure this call is to use curly brackets:
If (somethinginlist)
{
Entry = removeheadlist (list );
}
Therefore, we should not use non-standard writing for temporary convenience. It is best to use curly brackets in all if, for, and while statements.
2. Driver function name
Like the main () function of C/C ++, a device driver must also have an entry function named DriverEntry. However, in addition, we can use any name to name other functions-as long as you remember, of course, it is best to comply with certain rules, such as the Hungarian naming method ......
3. Problems During Installation
· In Windows 98, the executable file of the driver must be the 8.3 file name. (Don't ask me why, I don't know. I only recommend you ask Bill)
· If the INF file contains detailed information about invalid sections, Windows will not use this INF file.
Call ~~ After talking so much about it, let's have a drink first. As a matter of fact, Luo luochao has talked a lot in this section, but it has little to do with the actual programming. But in order to develop good programming habits in the future, we should follow it, right? Now, I will explain in detail how to compile and install the driver in the next section.
Getting started with WDM drivers (3) -- Installation Steps
8 DDK and 2000 DDK, which work similarly, but some drivers can only be used in 2000 DDK. Since Win98 is destined to be an operating system to be phased out, I am not going to introduce how to compile it in 98 DDK. All of the following content is for 2000 DDK.
· Preparations
1. Make sure that you have installed visual c ++
2. Install DDK 2000
3. After the 2000 DDK is successfully installed, there should be a "Development Kits"-> "Windows 2000 DDK" project in "start"> "program.
(Be sure to install the VC before installing the DDK. This order must not be reversed !!)
4. Make sure that the ddkroot environment variable is set to the base Directory of Windows 2000 DDK. If not, set this environment variable in the "advanced" tab environment variable editor of the "System" attribute of the control panel.
· Compile necessary files
When compiling a WDM program, two files are required:
1. makefile
(What is this? You may ask .) For younger programmers, you may not have seen this file. In fact, before the emergence of the vc ide, we must use makefile to determine which files in the project need to be re-compiled. The current ide has done this job automatically. (Well ...... In fact, this is good .)
The job we need to do is to provide such a file with the following content:
# Do not edit this file !!! Edit. /sources. if you want to add a new source # file to this component. this file merely indirects to the real make file # that is shared by all the driver components of the Windows nt ddk #! Include $ (ntmakeenv)/makefile. Def
As it said, Do not edit this file. In fact, the makefile content required by each WDM program is the same, that is, we only need to simply copy a makefile to a new project. (Isn't it convenient ?)
2. Sources
Targetname = hellowdmtargettype = driverdrivertype = wdmtargetpath = objreceivdes = $ (basedir)/INC;/$ (basedir)/INC/DDK;/targetlibs = $ (basedir) /lib/*/free/usbd. LIB/sources = hellowdm. CPP/
This file specifies that the target name of the driver is hellowdm. SYS. It is a WDM driver and the generated file is stored in the OBJ directory. It is worth noting that there cannot be spaces before and after "=", otherwise there will be errors during compilation.
· Start Compilation
Wahaha, Luo luochao mentioned a lot before, and now the focus is finally reached. The compilation process of WDM programs is special. It is not compiled by F7 in VC (although you can achieve this through settings ), instead, build a DDK utility. The following describes the specific steps:
1. Generation of "debug"
First, assume that your source code is stored in D:/hellowdm. Follow these steps:
Start> program> Development Kits> Windows 2000 DDK> checked Build Environment"
The screen will show: (the line with "enter" needs to be input by the reader)
New or updated msvc detected. Updating DDK environment .... Setting environment for using Microsoft Visual C ++ tools. Starting dirs creation... Completed. D:/ntddk> Cd/hellowdm (Press ENTER) D:/hellowdm> build (Press ENTER)
If the source code is correct, the generated hellowdm. sys will be stored in the objchk/i386 directory.
2. Generate "release"
Follow these steps:
Start> program> Development Kits> Windows 2000 DDK> Free Build Environment"
The subsequent steps are the same as those of the debug version. The difference is that the generated hellowdm. sys will be stored in the objfre/i386 directory.
· Installation
If there is no error in the previous compilation process, we should have now obtained a hellowdm. SYS file, assuming it is placed in D:/hellowdm/objfre/i386.
What are we going to do ?............ Yes, just install it! Otherwise, what is the purpose of hard compilation?
You can use either the registry or the INF file to install the WDM driver. We generally use the INF file (recommended by Microsoft ). The inf file can be found in the WINNT/INF directory. For smooth installation, I will first provide the hellowdm. inf file required by hellowdm:
; The Win2k DDK documentation contains an excellent INF reference .; --------- version section detail [version] Signature = "$ Chicago $" provider = lc_devicedriverver = 8/21/2002, 3.0.0.3; If device fits one of the standard classes, use the name and guid here ,; otherwise create your own device class and guid as this example shows. class = unknownclassguid = {ff646f80-8de F-11d2-9449-00105a075f6b}; --------- sourcedisknames and sourcediskfiles section ---------------------; these sections identify source disks and files for installation. they are; shown here as an example, but commented out. [sourcedisksnames] 1 = "hellowdm", disk1, [sourcedisksfiles] hellowdm. sys = 1, objfre/i386,; --------- classinstall/classinstall32 section ---------------------------------; not neces Sary if using a standard class; 9x style [classinstall] addreg = class_addreg; nt style [classinstall32] addreg = class_addreg [class_addreg] hkr, % deviceclassname % hkr ,, icon, "-5"; --------- destinationdirs section failed [destinationdirs] youmark_files_driver = 10, system32/drivers; --------- manufacturer and models sections ---------------------------------- [manufacturer] % Mfgname % = mfg0 [mfg0]; PCI hardware IDs use the form; PCI/ven_aaaa & dev_bbbb & subsys_cccccccc & rev_dd; change to your own ID % devicedesc % = youmark_ddi, PCI/ven_9999 & dev_9999; ---------- ddinstall seinstall ;--------- Windows 9x versions; experimentation has shown that ddinstall root names greater than 19 characters; cause problems in Windows 98 [youmark_ddi] copyfi Les = youmark_files_driveraddreg = youmark_9x_addreg [youmark_9x_addreg] hkr, devloader, * ntkernhkr, ntmpdriver, and hellowdm. syshkr, "Parameters", "breakonentry", 0x00010001, 0; ----------- Windows NT --------------- [Program] copyfiles = program = youmark_nt_addreg [Program] addservice = hellowdm, 0x00000002, youmark_addservice [youmark_addservice] displayname = % svcdesc % se Rvicetype = 1; service_kernel_driverstarttype = 3; service_demand_starterrorcontrol = 1; service_error_normalservicebinary = % 10%/system32/Drivers/hellowdm. sys [youmark_nt_addreg] HKLM, "system/CurrentControlSet/services/hellowdm/parameters",/"breakonentry", 0x00010001, 0; --------- files (common) ----------- [youmark_files_driver] hellowdm. sys; --------- strings section -------------------------- ------------------------- [Strings] providername = "Flying l co., Ltd." mfgname = "LC soft" devicedesc = "Hello World WDM! "Deviceclassname =" lc_device "svcdesc = "???"
Note that it can be used in both WIN98 and win2000 (the system automatically selects the appropriate installation method for the current system through the field name in the INF file ). The meaning of each field in the INF file is complex and limited by space. I will not explain it in detail here. Please read the relevant articles or books on your own.
Prepare hellowdm. after the INF file, open the control panel, double-click "Add/delete Hardware", and select "Add/Remove device fault"-> "Add new device"-> "no, select hardware> other devices from the list and select hellowdm. the path where INF is located, and then install.
After the installation is complete, the system will add the driver you have written. (You can view it in "Device Manager ). Then restart the computer and the driver will be ready for use.