Книга: Writing Windows WDM Device Drivers

Kernel Calls

Kernel Calls

Device drivers cannot access any standard C, C++, or Win32 functions. You cannot use the C++ new and delete operators. Instead, you must make use of a large number of kernel routines. The main categories of kernel routines are shown in Table 3.1.

The book describes each kernel routine when it is first used. However, I decided not to provide a full list of each function's parameters because it would take up too much room. You may find it useful to have the Driver Development Kit (DDK) documentation to hand. However, I hope that you can follow the thread of the argument without having to sit beside your computer.

If you are using one of the proprietary toolkits listed in Chapter 1, these will provide a set of classes that make drivers easier to write. This includes routines that make it easier to call the kernel. For example, drivers must use Unicode strings when talking to the rest of the kernel. The kernel routines that manipulate Unicode strings are fairly laborious to use. Most proprietary toolkits provide a class wrapper for Unicode strings that makes them easier to use.

There are various Win32 function calls that are used only in connection with device drivers. In particular, the SetupDi… routines are used to find devices that implement a specified device interface.

Table 3.1 Kernel Mode Routines available to drivers

Ex… Executive Support
Hal… Hardware Abstraction Layer (NT/W2000 only)
Io… I/O Manager (including Plug and Play routines)
Ke… Kernel
Ks… Kernel stream IRP management routines
Mm… Memory Manager
Ob… Object Manager
Po… Power Management
Ps… Process Structure
Rtl… Runtime Library
Se… Security Reference Monitor
Zw… Other Routines

Table 3.2 shows routines that are used only by specific types of driver. Most of these are provided for miniclass drivers, miniport drivers, and minidrivers. Others, such as the Hid… and Usb… functions are used by client drivers.

In addition to those routines listed, audio miniport drivers define several standard interfaces. The IEEE 1394 bus driver makes many routines available, with no common initial name.

Table 3.2 Bus driver and class specific routines

BatteryClass… Battery class routines for miniclass drivers
Hid… Human Input Device routines
Pc… Port class driver routines
ScsiPort… SCSI port driver routines for miniport drivers
StreamClass… Stream class driver functions for stream minidrivers
TapeClass… SCSI Tape class routines for miniclass drivers
Usb… Universal Serial Bus Driver Interface routines for USB client drivers

Kernel Macros

If you look in the DDK header files, you will find that a few of the kernel functions are implemented as macros. The definition of one or two of these macros is quite poor. For example, RemoveHeadList is defined as follows:

#define RemoveHeadList(ListHead) (ListHead)->Flink; {RemoveEntryList((ListHead)->Flink);}

If you call RemoveHeadList in the following way, the wrong code is compiled.

if (SomethingInList) Entry = RemoveHeadList(list);

The only way to make this safe is to use braces.

if (SomethinglnList) {
 Entry = RemoveHeadList(list);
}

Therefore, to be on the safe side, it is best to use braces in all if, for, and while statements, etc.

Kernel Objects

The DDK documentation makes much use of the word object when describing kernel structures. This does not mean object in the C++ sense of the word. However, it means the same in principle. In the purest definition, a kernel object should only be accessed using kernel function calls. In practice, each kernel structure usually has many fields that can be accessed directly. However, it is definitely true that some fields should be considered private and not touched by your driver. This book describes which fields can be used safely in each kernel object.

Driver Routine Names

There is a useful convention for naming driver routines, similar to the kernel API naming scheme. Each routine name should have a small prefix based on the driver's name (e.g. Par for a Parallel port driver). This prefix should be followed by verbs or nouns as necessary. This naming scheme makes it easier to identify a driver when looking at a debugger trace. A driver initially has just one exposed routine that must be called DriverEntry so it can found.

Many driver routines have standard names that most people use. For example, the Create IRP handler in the Wdm1 driver is called Wdm1Create; the Read IRP is handled in Wdm1Read, etc.

Оглавление книги


Генерация: 0.601. Запросов К БД/Cache: 2 / 0
поделиться
Вверх Вниз