Chapter III Writing Kernel Mode Drivers
Translation: kendiv (fcczj@263.net)
Update:
Tuesday, February 08, 2005
Disclaimer: Please indicate the source and guarantee the integrity of the article, and all rights to the translation.
As a supplement here, DRVINFO.H is given:
// _________________________________________________
//
// drvinfo.h
// Driver Info Definitions V1.00
//
06-02-2000
Sven B. Schreiber
// sbs@orgon.com
// _________________________________________________
#ifndef _drvinfo_h_
#define _drvinfo_h_
/ / =========================================================================================================================================================================================== ==================
// disclaimer
/ / =========================================================================================================================================================================================== ==================
/ *
This Software Is Provided "As IS" and Any Express or Implied
Warranties, Including, But Not Limited to, The Implied Warranties of
Merchantability and Fitness for a particular purpose are disclaimed.
In no Event Shall The Author Sven B. Schreiber Be Liable for Any
Direct, Indirect, Incidental, Special, Exemplary, or Consequential
DAMAGES (INCLUDING, But Not Limited to, Procurement of Substute
Goods or Services; Loss of Use, Data, or Business; Or Business
Interruption) However Caused and On Any THEORY OF LIABILITY,
WHETHER IN Contract, Strict Liability, or Tort (Including NEGLigenceor Otherwise) arising in any way out of the use of this software,
Even if advised of the Possibility of Such Damage.
* /
/ / =========================================================================================================================================================================================== ==================
// Revision History
/ / =========================================================================================================================================================================================== ==================
/ *
05-26-2000
V1.00 Original Version (SBS).
* /
/ / =========================================================================================================================================================================================== ==================
// Basic Types
/ / =========================================================================================================================================================================================== ==================
Typedef uchar byte, * pbyte, ** ppbyte
Typedef ushort, * pword, ** ppword;
Typedef Ulong DWORD, * pdword, ** ppdword; typedef unsigned __int64 qword, * pqword, ** ppqword;
TypeDef int BOOL, * PBOOL, ** PPBOOL
Typedef void ** ppvoid;
/ / -------------------------------------------------------------------------------------------- -----------------
#define byte_ sizeof (Byte)
#define word_ sizeof (Word)
#define dword_ sizeof (dword)
#define qword_ sizeof (qword)
#define bool_ sizeof (bool)
#define pvoid_ sizeof (PVOID)
#define handle_ sizeof (Handle)
#define physical_address_ sizeof (Physical_Address)
/ / =========================================================================================================================================================================================== ==================
// macros
/ / =========================================================================================================================================================================================== ==================
#define _DRV_DEVICE (_Name) // device // ## _name
#define _drv_link (_name) // dosdevices // ## _name
#define _drv_path (_name) .// ## _name
/ / -------------------------------------------------------------------------------------------- -----------------
#define _cstring (_Text) #_text
#define cstring (_Text) _cstring (_Text)
#define _ustring (_Text) L ## _ text
#define ustring (_text) _USTRING (_Text)
#define preset_unicode_string (_SYMBOL, _Buffer) /
Unicode_string _symbol = / {/
SIZEOF (USTRING) - SIZEOF (WORD), /
SIZEOF (USTRING (_buffer), /
UString (_Buffer) /
}
/ / -------------------------------------------------------------------------------------------- -----------------
#if DRV_VERSION_LOW <10
#define _drv_v2 (_A, _B) _A ## .0 ## _B
#define _DRV_V2X (_A, _B) V ## _A ## .0 ## _B
#ELSE / / #IF DRV_VERSION_LOW <10
#define _DRV_V2 (_A, _B) _A ##. ## _b
#define _DRV_V2X (_A, _B) V ## _A ##. ## _b
#ENDIF / / #IF DRV_VERSION_LOW <10 #Else
#define DRV_V2 (_A, _B) _DRV_V2 (_A, _B)
#define DRV_V2X (_A, _B) _DRV_V2X (_A, _B)
/ / -------------------------------------------------------------------------------------------- -----------------
#define _drv_v4 (_A, _B, _C) _A ##. ## _b ## .0. ## _C
#define drv_v4 (_A, _B, _C) _DRV_V4 (_A, _B, _C)
/ / -------------------------------------------------------------------------------------------- -----------------
#define DRV_V DRV_V2X (DRV_VERSION_HIGH, /
DRV_VERSION_LOW)
#define DRV_VERSION DRV_V2 (DRV_VERSION_HIGH, / /
DRV_VERSION_LOW)
#define DRV_VERSION_QUAD DRV_V4 (DRV_VERSION_HIGH, /
DRV_VERSION_LOW, /
DRV_BUILD)
#DEFINE DRV_VERSION_BINARY ((DRV_VERSION_HIGH * 100) /
DRV_VERSION_LOW)
/ / =========================================================================================================================================================================================== ==================
// Driver Information
/ / =========================================================================================================================================================================================== ================= # Define DRV_ID DRV_PREFIX.DRV_MODULE
#DEFINE DRV_ID_VERSION DRV_ID.DRV_VERSION_HIGH
#define DRV_FILENAME DRV_MODULE.DRV_EXTENSION
#define DRV_CAPTION DRV_NAME DRV_V
#DEFINE DRV_COMMENT DRV_DATE DRV_AUTHOR
/ / -------------------------------------------------------------------------------------------- -----------------
#define drv_device _drv_device (drv_module)
#define DRV_LINK _DRV_LINK (DRV_MODULE)
#define drv_path _DRV_PATH (DRV_MODULE)
#define drv_extension sys
/ / -------------------------------------------------------------------------------------------- -----------------
#define DRV_CLASS DRV_MODULE.DRV_VERSION_QUAD
#define DRV_ICON DRV_MODULE.ICON
/ / -------------------------------------------------------------------------------------------- -----------------
#define DRV_COPYRIGHT COPYRIGHT / XA9 DRV_YEAR
#define DRV_COPYRIGHT_EX DRV_COPYRIGHT DRV_COMPANY
/ / -------------------------------------------------------------------------------------------- -----------------
#DEFINE DRV_DATE_US DRV_MONTH-DRV_DAY-DRV_YEAR
#DEFINE DRV_DATE_GERMAN DRV_DAY.DRV_MONTH.DRV_YAR
#define DRV_DATE DRV_DATE_US
/ / =========================================================================================================================================================================================== ================= // NT4 Compatibility
/ / =========================================================================================================================================================================================== ==================
#ifndef IRP_MJ_QUERY_POWER
#define IRP_MJ_QUERY_POWER 0x16
#ENDIF
#ifndef IRP_MJ_SET_POWER
#define IRP_MJ_SET_POWER 0x17
#ENDIF
#ifndef IRP_MJ_PNP_POWER
#define IRP_MJ_PNP_POWER 0x1B
#ENDIF
#ifdef _RC_pass_
/ / =========================================================================================================================================================================================== ==================
//Header Files
/ / =========================================================================================================================================================================================== ==================
#include
/ / =========================================================================================================================================================================================== ================== // Version INFO
/ / =========================================================================================================================================================================================== ==================
#define drv_rc_version /
VS_VERSION_INFO VERSIONINFO /
/
FileVersion DRV_VERSION_High, DRV_VERSION_LOW, 0, DRV_BUILD /
ProductVersion DRV_VERSION_HIGH, DRV_VERSION_LOW, 0, DRV_BUILD /
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK /
FILEFLAGS 0 /
Fileos vos_NT /
FILETYPE VFT_DRV /
FILESUBTYPE VFT2_UNKNOWN /
{/
Block "StringfileInfo" /
{/
Block "040904B0" /
{/
Value "OriginalFileName", CSTRING (DRV_FILENAME / 0) /
Value "InternalName", CString (DRV_MODULE / 0) /
Value "ProductName", CString (DRV_NAME / 0) /
Value "FileDescription", CSTRING (DRV_CAPTION / 0) /
Value "CompanyName", CSTRING (DRV_COMPANY / 0) /
Value "ProductVersion", CSTRING (DRV_VERSION_QUAD / 0) /
Value "Fileversion", CString (DRV_VERSION_QUAD / 0) /
Value "Legalcopyright", CString (DRV_COPYRIGHT_EX / 0) /
Value "Comments", CSTRING (DRV_COMMENT / 0) /
} /
} /
Block "varfileinfo" /
{/
Value "Translation", 0x0409, 0x04b0 /
} /
}
/ / =========================================================================================================================================================================================== ================== // Resources
/ / =========================================================================================================================================================================================== ==================
#DEFINE DRV_RC_ICON DRV_ICON ICON DRV_MODULE.ICO
#ENDIF / / #IFDEF _RC_Pass_
#ENDIF / / #1ndef _drvinfo_h_
/ / =========================================================================================================================================================================================== ==================
// end of file
/ / =========================================================================================================================================================================================== ==================
Listing 3-3 and List 3-4 The c code of the driver given in the list contains almost all Kernel-Mode Driver required for almost all kernel-mod driver. I will try to make the drive wizard better customizable. You can freely change the template files provided by the wizard. For those who want to keep the original code, the following chapters will provide you with a brief introduction to some internal details of the wizard.
The entry point of the drive module generated by the wizard is DriveREntry (). Like all Windows 2000 modules, this name is from time to time. You can use any name you like, but you must tell the link that you use, you can do this through the command line option / entry of the linker. For the TestDriver mentioned earlier, the wizard has completed this work well. In the W2K_WIZ.TP template or generated TestDRV.DSP file, you will find / entry: "DriveREntry @ 8" in the command line of the linker. @ 8 suffix indicates that DriveREntry () accepts parameters of 8 bytes (these parameters are located in the stack), the prototype of the DriveREntry () provided by the list 3-1: two pointer parameters, each occupied 32 bits, a total Use 64 binary positions, namely 8 bytes. The first thing DriveEntry () is to call DriverInitialize (), which will create a device object and a symbolic link of the object, and you may use it later in the user mode. This symbolic link is communicating with the device. To find IOCREATEDEVICE () and IOCREATESYMBOLICLINK () have some difficulties, because they are all macro definitions depending on Drvzinfo.h (located in the / src / compuDe directory of this book). If you want more to understand this tip, please refer to the Program Identification section in TestDRV.H (listed in the previous list 3-4) and track the definition of DRV_ *, which is set in a variety of ways. The appearance is in drvinfo.h. For example, a complete versionInfo resource is made of a plurality of small macros. At home, DRV_DEVICE and DRV_LINK constants are also defined, where they are equivalent to / device / testdrv and / dosdevice / testdrv. Note that many kernel API functions, such as IOCREATEDEVICE () and IOCREATESYMBOLICKLINKE () do not accept a string of zero end, only support a special structure --- unicode_string, the structure has been introduced in the second chapter, list 3- 5 The definition of this structure is given again. The macro defined in Drvinfo.h --- Preset_Unicode_string (Global Data Section Applying to TestDrv.c) Creating a static Unicode_String structure from a simple Unicode string constant. This is a convenient shorthand symbol for the Unicode_String structure.
After successful creation of the device object and its symbolic link, DriverInitialize () saves the pointer of the device object pointer and device context (Device Context) in a static global variable. Device Context is a private structure of the device that can have any size and structure. The driver skeleton provided by this book comes with a simple Device_Context structure, which is defined in TestDrv.h. This structure contains only two pointers that point to devices and device driver objects, respectively. You can extend this structure to save the data specific to the device driver. The system provides the corresponding Device Context for each I / O request package (I / O Request Packet, IRP) received by the driver.
After DriverInitialize () successfully completed and returned, DriveREntry () will establish an important array that is incorporated by the system and is part of the driver object structure ---- PDRIVEROBJECT. This array provides space for all IRPs expected by the driver, while driverentry () also is a pointer to all IRPs that you want to get control. The driver skeleton provided by this book follows this design, which saves a DRIVERDISPATCHER () pointer and provides a space for 28 IRPs, as shown in Table 3-2. Later, DriverDispatcher () will decide to pay attention to those IRPs and return Status_not_implement for all IRPs that are not interested. It should be noted that the layout of the number of IRP processing routines for Windows NT and Windows 2000 has some subtle differences. In Table 3-2, this difference is identified in a black body. Translation:
In Windows NT, most I / O requests are represented by I / O request packets (IRP). In most cases, the I / O request package can be transferred from one I / O system component to another. This design allows a single application thread to manage multiple I / O requests. IRP is a data structure that contains complete information describing an I / O request.
For details, please refer to Chapter 9 I / O System in INSIDE Windows 2000.
Typedef struct _unicate_string
{
Word Length;
Word Maximumlength;
PWORD BUFFER;
} Unicode_string, * punicode_string;
Listing 3-5. A common existed Windows 2000 structure: unicode_string
element
Windows NT 4.0
Windows 2000
0x00 IRP_MJ_CREATE IRP_MJ_CREATE 0x01 IRP_MJ_CREATE_NAMED_PIPE IRP_MJ_CREATE_NAMED_PIPE 0x02 IRP_MJ_CLOSE IRP_MJ_CLOSE 0x03 IRP_MJ_READ IRP_MJ_READ 0x04 IRP_MJ_WRITE IRP_MJ_WRITE 0x05 IRP_MJ_QUERY_INFORMATION IRP_MJ_QUERY_INFORMATION 0x06 IRP_MJ_SET_INFORMATION IRP_MJ_SET_INFORMATION 0x07 IRP_MJ_QUERY_EA IRP_MJ_QUERY_EA 0x08 IRP_MJ_SET_EA IRP_MJ_SET_EA 0x09 IRP_MJ_FLUSH_BUFFERS IRP_MJ_FLUSH_BUFFERS 0x0A IRP_MJ_QUERY_VOLUME_INFORMATION IRP_MJ_QUERY_VOLUME_INFORAMTION 0x0B IRP_MJ_SET_VOLUME_INFORMATION IRP_MJ_SET_VOLUME_INFORMATION 0x0C IRP_MJ_DIRECTORY_CONTROL IRP_MJ_DIRECTORY_CONTROL 0x0D IRP_MJ_FILE_SYSTEM_CONTROL IRP_MJ_FILE_SYSTEM_CONTROL 0x0E IRP_MJ_DEVICE_CONTROL IRP_MJ_DEVICE_CONTROL 0x0F IRP_MJ_INTERNAL_DEVICE_CONTROL IRP_MJ_INTERNAL_DEVICE_CONTROL 0x10 IRP_MJ_SHUTDOWN IRP_MJ_SHUTDOWN 0x11 IRP_MJ_LOCK_CONTROL IRP_MJ_LOCK_CONTROL 0x12 IRP_MJ_CLEANUP IRP_MJ_CLEANUP 0x13 IRP_MJ_CREATE_MAILSLOT IRP_MJ_CREATE_MAILSLOT 0x14 IRP_MJ_QUERY_SECURITY IRP_MJ_QUERY_SECURITY 0x15 IRP_MJ_SET_S ECURITY IRP_MJ_SET_SECURITY 0X16 IRP_MJ_QUERY_POWERIRP_MJ_POWER
0x17 IRP_MJ_SET_POWER
IRP_MJ_SYSTEM_CONTROL
0x18 IRP_MJ_DEVICE_CHANGE
IRP_MJ_DEVICE_CHANGE
0x19 IRP_MJ_QUERY_QUOTA IRP_MJ_QUERY_QUOTA 0X1A IRP_MJ_SET_QUOTA IRP_MJ_SET_QUOTA 0X1B IRP_MJ_PNP_POWER
IRP_MJ_PNP
Table 3-2. Comparison of each I / O request package in the array
After the IRP number is set up, DriveREntry () Write its own Callback function - Driverunload () into the driver object structure, which will allow the driver to be uninstalled at runtime. The Driverunload () function is just a simple destruction of all objects created by DRiverInitialize (ie, the device object and its symbolic link). After that, the driver can be removed from the system securely.
The DriverDispatcher () function is called whenever a module requires the driver to make a corresponding action. Because the driver can handle multiple devices, Dispatcher first checks that device should respond to request. The driver skeleton provided by this book only maintains a device, so it is only necessary to check if the device object pointer accepted from IOCREATEDEVICE () is consistent when initialization. If the same, DriverDispatcher () will pass the received IRP forward, give the previous DriverDispatcher () function, and DriverInitialize () is ready for DRIVERINIALIZE (). When you expand the drive skeleton to manage multiple devices drivers, you may need to write separate IRP Dispatcher for each device. Listing 3-3 DeviceDispatcher () function is only a schematic implementation, which can only identify three common requests: IRP_MJ_CREATE, IRP_MJ_CLANUP, and IRP_MJ_CLOSE, and is represented by returning Status_Success to process the request. This is the minimum implementation of the device to be open, close, and a status_not_implement will be returned for other requests. You may want to know the purpose of #pragma alloc_text that appears in the Discardable Functions section of the list 3-3. #pragma indicator is a strong means of sending commands to compilers and linkers. The alloc_text command represents the non-default section written to the code of the specified function to the executable. By default, all program code is located in .text section. However, the indicator #pragma alloc_text (init, driverentry) will save the DRIVERENTRY () code in a new section ---- Init. The drive loader can identify this specified section and drop the section after initialization. DriverNTry () and its help function driverinitialize () will be called once when the driver is started; therefore, when they complete their own work, they can be safely removed from memory.
Now the driver skeleton has only resource script --- TestDrv.rc, as shown in Listing 3-6. This file does not have much value because it only references the macro from drvinfo.h ---- DRV_RC_VERSION, and the number of data items provided by the wizard to create a VersionInfo resource, and another macro --- DRV_RC_ICON is equivalent to TestDRV. ICO adds to the icon declaration statement in Resource Section in TESETDRV.SYS.
// TestDrv.rc
//
08-07-2000
// Copyright? 2000
#define _RC_pass_
#define_testdrv_sys_
#include "testdrv.h"
/ / =========================================================================================================================================================================================== ==================
// Standard Resources
/ / =========================================================================================================================================================================================== ================== DRV_RC_VERSION
DRV_RC_ICON
/ / =========================================================================================================================================================================================== ==================
// end of file
/ / =========================================================================================================================================================================================== ==================
Listing 3-6. Resource script of driver skeleton
....................to be continued....................