Driver Language and Libraries

A driver is a Dynamic Link Library (DLL) with the file extension .sys. It is usually written in C or C++ and can include resources, such as a version block, event messages, and Windows Management Instrumentation (WMI) class definitions. In Windows 98, a driver executable must have an 8.3 filename.

Although drivers were traditionally written just in C, it is quite straightforward to use C++. The main requirement is to use the extern 'C' directive in a couple of important places. However, do not use the new keyword in C++. The new keyword may be implemented using malloc, which is not available to kernel mode drivers.

In fact, most standard libraries and classes are not available to driver writers in either language, because they make inappropriate use of memory. If you are using one of the proprietary driver development kits, these provide various useful classes, including safe memory allocators.

Instead, you can use any of the routines provided by the operating system to kernel mode devices, as described in Chapter 3. While these are useful, it takes a while to get used to the different set of routines that are available.

Assembly code can be used if absolutely necessary. Obviously, this makes for more work if you port the driver to the Windows 2000 Alpha platform.

Resources

A resource .rc file should include a standard version block. Increment the version numbers as new builds are released. Make sure that you keep a full source backup of each version you release. Many version control packages can help you manage this task.

If you generate NT or Windows 2000 events, you should write these in an .mc file that is compiled using the mc utility and included in a driver's resource file. More details of this process are in Chapter 13.

Similarly, if you generate custom WMI classes, you need to write a .mof file that is compiled using the mofcomp tool and included in the driver's resource file. See Chapter 12 for more information.

A sophisticated driver might need to download microcode to its device and so would include the microcode as a binary resource in its executable.

Good Code

A driver is an integral part of the operating system, so it can easily crash Windows if it goes wrong. You do not have the protection of a Win32 address space to stop you from overwriting memory that does not belong to you.

Please be especially careful when you write your driver. Keep it as simple as possible and document it well.

Treat all compiler warnings as errors that need to be fixed. For example, whether an integer is signed or not can make all the difference.

Make sure that you check the return values of all kernel functions that you call, and act on them accordingly. For example, if you get an error after you create a device, make sure that the clean-up code deletes the device.

Make sure that you use the kernel resources carefully, particularly memory. Some resources are scarce and overuse may degrade system functioning.

build Utility

The DDK build command line utility is the primary tool for building drivers. It invokes the nmake make utility to build your driver using the correct compiler and linker settings. If necessary, build can be used to build standard user mode Win32 executables, etc.

The next section describes how to invoke build from within Visual Studio. However, you must still set up build so that it can be run at the command line. As well as your source code, you must specify a SOURCES file, a standard makefile, the directory structure, and optionally a makefile.inc file and a dirs file. All these steps are described in the following text.

build displays progress details and error results to its standard output. In addition, it lists the errors in a file called build.err, the warnings in build.wrn, and a log in build.log. In W2000 there are free and checked build versions of each of these files, i.e., buildfre.log, buildchk.log, etc.

makefiles

Younger readers may not have come across makefiles. In the days before Integrated Development Environments (IDEs) such as Visual Studio, you had to use makefiles to determine which files in a project needed recompiling. If you changed only one module in a project consisting of eight modules, you want to recompile only that one module and then link the whole lot together.

The nmake utility uses instructions in a file called makefile to determine what commands to run to update a project. The following makefile shows that if haggis.cpp has been updated, it is compiled into haggis.obj using the cl compiler. haggis.obj is linked to make haggis.exe using the link tool.

haggis.exe: haggis.obj

            link –o haggis.exe haggis.obj

haggis.obj: haggis.cpp

            cl haggis

Most makefiles are a good deal more complicated than this, which is why they were happily forgotten when IDEs came along. However, setting up the compiler and linker settings for drivers is quite a complicated task. Therefore, Microsoft has stuck with makefiles. See the Visual Studio nmake documentation for more details of makefiles.

SOURCES

build looks for an nmake macro file called SOURCES in the current directory for details of what to build.

Listing 4.1 shows the SOURCES file for the Wdm1 project. It specifies that the driver target name is Wdm1.sys, that it is a WDM driver, and that it should be built in the OBJ subdirectory. Source browser information should be generated. The DDK inc directory is added to the search list for header files. The SOURCES macro specifies a list of files to compile. NTTARGETFILES specifies some post build steps, as described in the following text.

Other less common SOURCES macro definitions can be found in the DDK documentation. Note that there must be no spaces between the SOURCES macro and its equal sign.

Listing 4.1 Wdm1 project SOURCES file

TARGETNAME=Wdm1

TARGETTYPE=DRIVER

DRIVERTYPE=WDM

TARGETPATH=OBJ

BROWSER_INFO=1

INCLUDES=$(BASEDIR)inc;

SOURCES=init.cpp

        dispatch.cpp

        pnp.cpp

        DebugPrint.c

        version.rc

NTTARGETFILES=PostBuildSteps

makefile File

You must provide a standard file called makefile as shown in Listing 4.2. This invokes the standard make file makefile.def in the DDK inc directory.

As it says, do not edit this file at all. If you want to add to the list of files to compile, add them to the SOURCES macro in the SOURCES file.

Listing 4.2 Wdm1 project makefile

#

# 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

build Directories

Windows 98 and NT

build always puts the compiled object files in the OBJi386 subdirectory (for x86 targets). The SOURCES TARGETPATH macro specifies where the final executables go. If you specify OBJ for this, then the driver executables go in the OBJi386free and OBJi386checked subdirectories. There is a long-standing bug in build that means that you have to create these last two directories by hand for build. if you were making Wdm1 from scratch, then you would have to make subdirectories OBJi386free and OBJi386checked.

Both the free and checked builds put their object files in the same directory. If you switch between these build types, make sure that you rebuild all the files in the project (by putting '-nmake /a' on the build command line).

The checked build output file OBJi386checkedWdm1.sys contains the debug symbols.

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату