分享
 
 
 

《Undocumented Windows 2000 Secrets》翻译 --- 第三章(2)

王朝system·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

第三章 编写内核模式驱动程序

翻译:Kendiv

更新:Tuesday, February 08, 2005

作为补充这里给出DrvInfo.h的内容:

// __________________________________________________________

//

// 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 substitute

goods or services; loss of use, data, or profits; or business

interruption) however caused and on any theory of liability,

whether in contract, strict liability, or tort (including negligence

or 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 WORD, *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 (_buffer)) - 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_YEAR

#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 <winver.h>

// =================================================================

// 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 // #ifndef _DRVINFO_H_

// =================================================================

// END OF FILE

// =================================================================

列表3-3和列表3-4给出的驱动程序的C代码中包含了几乎所有Kernel-mode Driver都需要的基本代码。我会尽量使该驱动向导有更好的可定制性。你可以自由的更改向导提供的模板文件。对于想保留原有代码的人,下面的章节会为你提供该向导的一些内部细节的简要介绍。

该向导生成的驱动模块的进入点是DriverEntry()。像所有的Windows 2000模块的进入点一样,这个名字并不时必须的。你可以使用任何你喜欢的名称,但是你必须告诉链接器你所使用的进入点名称,通过链接器的命令行选项/entry可以做到这一点。对于前面提及的TestDriver,向导已经很好的完成了这项工作。在w2k_wiz.tp模板或生成的TestDrv.dsp文件中,你会在链接器的命令行中找到/entry:”DriverEntry@8”这样的字符串。@8后缀表示DriverEntry()接受8个字节的参数(这些参数位于栈中),这和列表3-1提供的DriverEntry()的原型一致:两个指针参数,每个占据32个位,共使用64个二进制位,即8字节。

DriverEntry()做的第一件事是调用DriverInitialize(),该函数将创建一个设备对象(Device Object)和该对象的一个符号链接(Symbolic link),在稍后你可能在用户模式的程序中使用该符号链接来与设备通讯。要想找到IoCreateDevice()和IoCreateSymbolicLink()所使用的名字就有些许的困难,因为它们都是依赖DrvzInfo.h(位于本书光盘的\src\common\include目录)中的宏定义。如果你想更多的了解这个技巧,请参考TestDrv.h(前面的列表3-4已列出)中的PROGRAM IDENTIFICATION一节,并跟踪形如DRV_*的定义,它们以多种方式成组的出现在DrvInfo.h中。例如,一个完整的VERSIONINFO资源就是由多个小的宏构成的。在别处,还定义了DRV_DEVICE和DRV_LINK常量,在这里,它们分别等价于\Device\TestDrv和\DosDevice\TestDrv。注意,很多内核API函数,如IoCreateDevice()和IoCreateSymbolickLinke()不接受一个以零结尾的字符串,仅支持一个特殊的结构体---UNICODE_STRING,该结构在第二章已经介绍过,列表3-5再次给出了该结构的定义。定义于DrvInfo.h中的宏----PRESET_UNICODE_STRING(应用于TestDrv.c的GLOBAL DATA Section)从一个简单的Unicode字符串常量创建出一个静态的UNICODE_STRING结构。这是针对UNICODE_STRING结构的一个方便的速记符号。

在成功的创建完设备对象及其符号链接后,DriverInitialize()将设备对象指针和设备上下文(Device Context)的指针保存在一个静态全局变量中。Device Context是设备的一个私有结构,该结构可以有任意的大小和结构。本书提供的驱动程序骨架附带了一个简单的DEVICE_CONTEXT结构,该结构定义于TestDrv.h中。该结构仅包含分别指向设备和设备驱动程序对象的两个指针。你可以扩展该结构来保存设备驱动程序所特有的数据。系统针对驱动程序接收到的每个I/O请求包(I/O Request Packet, IRP)提供相应的Device Context。

在DriverInitialize()成功完成并返回后,DriverEntry()将建立一个重要的数组,该数组由系统传入,并做为驱动程序对象结构----pDriverObject的一部分。该数组为驱动程序期望的所有IRP提供空间,同时DriverEntry()还为所有希望得到控制的IRP写入对应的CallBack函数的指针。本书提供的驱动程序骨架遵循此种设计,它保存了一个DriverDispatcher()指针,并提供了可存放28个IRP的空间,如表3-2所示。稍后,DriverDispatcher()将决定需要注意那些类型的IRP,并针对所有不感兴趣的IRP返回STATUS_NOT_IMPLEMENTED。需要注意的是,Windows NT和Windows 2000的IRP处理例程数组的布局有一些微妙的差别。在表3-2中,这种差别以黑体标识出来。

译注:

在Windows NT中,大多数的I/O请求都是用I/O请求包(IRP)来表示的。在多数情况下,I/O请求包可以从一个I/O系统组件转移到另一组件。这种设计允许单个应用程序线程并行的管理多个I/O请求。IRP是一种数据结构,包含描述一个I/O请求的完整信息。

具体的细节,请参考《Inside Windows 2000》的第9章I/O System

typedef struct _UNICODE_STRING

{

WORD Length;

WORD MaximumLength;

PWORD Buffer;

} UNICODE_STRING, *PUNICODE_STRING;

列表3-5. 一个普遍存在的Windows 2000结构:UNICODE_STRING

元素

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_SECURITY

IRP_MJ_SET_SECURITY

0x16

IRP_MJ_QUERY_POWER

IRP_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

表3-2. 数组中的每个I/O请求包的比较

在IRP数组建立好之后,DriverEntry()将自己的CallBack函数----DriverUnload()写入驱动程序对象结构中,这将允许在运行时卸载该驱动程序。DriverUnload()函数只是简单的销毁由DriverInitialize()创建的所有对象(即设备对象和其符号链接)。在此之后,就可安全的将驱动程序从系统中移除。

每当一个模块要求驱动程序做出相应时,就会调用DriverDispatcher()函数。因为,驱动程序能够处理多个设备,Dispatcher首先检查那个设备应该响应该请求。本书提供的驱动程序骨架仅维护了一个设备,因此,仅需要在初始化时检查从IoCreateDevice()接受到的设备对象指针是否一致。如果一致,DriverDispatcher()将接收到的IRP向前传递,给之前的DriverDispatcher()函数,随之传递的还有DriverInitialize()准备好的Device Context。当你扩展该驱动骨架以管理多个设备驱动程序时,你可能需要为每个设备编写独立的IRP dispatcher。列表3-3中的DeviceDispatcher()函数只是一个示意性的实现,它仅能识别三种常见的请求:IRP_MJ_CREATE、IRP_MJ_CLEANUP和IRP_MJ_CLOSE,并通过返回STATUS_SUCCESS来表示以处理该请求。这是使设备能够正常打开、关闭的最小实现方式,对于其他的请求都将返回一个STATUS_NOT_IMPLEMENTED。

你可能想知道在列表3-3的DISCARDABLE FUNCTIONS一节中出现的#pragma alloc_text的目的。#pragma指示符是将命令送往编译器和链接器的有力手段。alloc_text命令表示将指定函数的代码写入可执行文件的非默认section中。默认情况下,所有程序代码都位于.text section。然而,指示符#pragma alloc_text(INIT,DriverEntry)将使DriverEntry()的代码保存在一个新的section----INIT中。驱动加载器可以识别这种指定的section,并在初始化之后丢掉该section。DriverEntry()和它的帮助函数DriverInitialize()仅在驱动程序启动时会被调用一次;因此,当它们完成自己的工作后,就可安全的将它们从内存中移除。

现在驱动程序骨架就只剩下了资源脚本---TestDrv.rc,如列表3-6所示。该文件没有太大价值,因为它仅引用了来自DrvInfo.h的宏----DRV_RC_VERSION以及向导提供的几个数据项来创建一个VERSIONINFO资源,另一个宏---DRV_RC_ICON则等同于将TestDrv.ico加入TesetDrv.sys的Resource Section中的ICON声明语句。

// TestDrv.rc

// 08-07-2000 <MyName>

// Copyright ?2000 <MyCompany>

#define _RC_PASS_

#define _TESTDRV_SYS_

#include "TestDrv.h"

// =================================================================

// STANDARD RESOURCES

// =================================================================

DRV_RC_VERSION

DRV_RC_ICON

// =================================================================

// END OF FILE

// =================================================================

列表3-6. 驱动程序骨架的资源脚本

....................待续....................

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有