Книга: 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.
- 5.5.1. Initialization via initcalls
- 16.3.3. Machine-Dependent Calls
- 9.2.5. Kernel Calls for Process Management
- 9.3.4. Kernel Calls for Memory Management
- 9.4.4. Kernel Calls for Communication
- 4.4.4 The Dispatcher
- Определение необходимого системного вызова
- Test Driver Code
- Creating and Deleting Device Objects
- 5.2.3. Architecture Setup
- 5.5. The init Thread
- 9.3. MEMORY MANAGEMENT IN CHORUS