分享
 
 
 

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

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

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

翻译: Kendiv

更新: Monday, February 07, 2005

在下一章中,我们会经常访问那些仅在内核模式下才有效的系统资源。大量的示例代码都被设计为内核驱动例程( Kernel-mode driver routine )。因此,需要有关开发此种软件的基本知识。因为我不能假定所有读者都有这方面的经验,我会在此简要地介绍一下内核模式驱动程序编程,不过这仅集中在如何使用驱动开发向导(在本书光盘上)。

本章还将讨论 Windows 2000 服务控制管理器( Service Control Manager , SCM )的基本知识,这包括 SCM 如何允许在运行时加载、控制和卸载驱动程序, resulting in wonderfully short change-build-test turnaround cycles 。本章的题目或许会让人有些误解,驱动一词通常与控制硬件的底层软件相关。事实上,很多内核程序员每天都在做这些事情。不过, Windows 2000 的驱动程序分层模式允许做比这更多的事情。内核驱动程序可以完成任意复杂的任务,若不考虑它们运行于更高的 CPU 特权级别上而且使用不同的开发接口,那它们很像用户模式下的 DLL 。在此,我们将使用这种强大的开发技术来侦测 Windows 2000 的内部秘密,使用内核驱动程序就像驾驶从狭小的用户模式飞往 Windows 2000 内核的太空飞船。

创建一个驱动程序的骨架

即使长时间开发 Win32 应用程序和库的开发人员,在首次编写内核驱动程序时,也会感觉像是一个绝对的初学者。这是因为,内核模式下的代码运行在一个完全不同的操作系统环境中。 Win32 开发人员的工作仅局限在属于 Windows 2000 Win32 子系统的几个系统组件上。其他开发人员可能编写 POSI 或 OS/2 应用程序, Windows 2000 的附加子系统为它们提供支持。感谢子系统这个概念, Windows 2000 就像一个变色龙 --- 它可通过这些子系统(前面提及的)导出不同的应用程序开发接口来模拟不同的操作系统。与此相反,内核模式的代码可以看到“真实”的 Windows 2000 操作系统。它们使用的接口可以称之为“最终边界”。当然,这并不是说,内核模式完全摆脱了子系统。在第二章中,我们看到 win32k.sys 就是 Win32 GUI 和窗口管理器在内核模式下的分支,将它们放在内核是出于性能考虑。然而, win32k.sys 导出的 API 函数集合中只有一小部分出现在了 gdi32.dll 和 user32.dll 中,这也意味着只有这一小部分函数可以作为 Win32 API 函数来使用,因此, Win32K 决不只是 Win32 踏入内核世界的一脚,实际上,应把它看作是一个高性能的内核模式的图形引擎。

Windows 2000 DDK ( Device Driver Kit )

由于内核模式下的编程使用了不同的系统接口,在 Win32 编程中经常使用的头文件和库都将无法在内核模式下使用。针对 Win32 开发,微软提供了 Platform Software Development Kit ( SDK )。而与内核模式的驱动开发相关的是, Windows 2000 Device Driver Kit ( DDK )。随文档一起, DDK 还提供了特殊的头文件和导入库,这些都是 Windows 2000 内核模块必须的接口。安装完 DDK 之后,接下来你应该打开 Visual C/C++ ,把 DDK 的路径加入到编译器和链接器的目录列表中。在主菜单中选择 Tools à Options ,然后单击 Directories 。在目录选择下拉列表中选择 Include files ,然后将 DDK 的适当路径加入,如 图 3-1 所示。默认情况下, DDK 将安装到 \NTDDK 目录下, included 文件位于 \NTDDK\inc 子目录中。需要注意的是,请将新添加的路径置于原有路径的上方,这样就会使用新的头文件或者库。

图 3-1 添加 DDK 头文件路径

图 3-2 添加 DDK 导入库路径

在添加完 DDK 头文件路径后,用同样的方法添加导入库的路径。 DDK 包含两组导入库,一组叫做 free ( release ) builds ,另一组叫做 checked ( debug ) builds 。其对应的目录为: \NTDDK\libfre\i386 和 \NTDDK\libchk\i386 ,参见 图 3-2 。

DDK 开发环境与 Win32 模式有所不同,下面给出二者之间的一些明显区别:

l 对于 Win32 程序员来说,主要的头文件是 windows.h ,对于内核模式代码来说,应使用 ntddk.h 替代之。

l 主进入点函数叫做 DirverEntry() ,而不再是 WinMain() 或 main() 。 列表 3-1 给出了它们的原型。

l 不能再使用一些常见的 Win32 数据类型,如 BYTE 、 WORD 和 DWORD 。 DDK 使用 UCHAR 、 USHORT 、 ULONG 等。不过,很容易就能定义你自己喜欢的类型, 列表 3-2 给出了这样的一个示例。

NTSTATUS DriverEntry ( PDRIVER_OBJECT pDriverObject,

PUNICODE_STRING pusRegistryPath);

列表 3-1 DriverEntry 函数的原型

typedef UCHAR BYTE, *PBYTE;

typedef USHORT WORD, *PWORD;

typedef ULONG DWORD, *PDWORD;

列表 3-2 定义常见的 Win32 数据类型

此外,还需要注意 Windows NT 4.0 和 Windows 2000 所使用的 DDK 之间的差别,有三点不同需要注意,如下:

l 默认情况下, Windows NT 4.0 DDK 的主目录叫做 \DDK ,而 Windows 2000 DDK 叫做 \NTDDK

l 在 Windows NT 4.0 DDK 中,主要的头文件 ntddk.h 位于主目录之下。而在 Windows 2000 DDK 中,该文件被移到了 \NTDDK\DDK 子目录下。

l 导入库的路径也发生了变化: lib\i386\free 变成了 libfre\i386 , lib\i386\checked 变成了 libchk\i386 。

我不知道微软的这种改变有什么实际意义,不过为了生活,我们还是需要了解其变化 J 。

可定制的驱动程序向导

开发内核驱动程序的主要困难在于 Visual C/C++ 没有提供此种类型的工程向导。幸运的是, MSDN 里有一系列不错的关于 Windows NT 内核驱动开发的文章,是 Ruediger R.Asche. 在 1994 至 1995 年编写的。其中的两篇文章( Asche 1995a , 1995b )详细说明了如何在 Visual C/C++ 中加入自定义的驱动程序向导,这些文章给了我很大的帮助,尽管原始向导的输出文件不能满足我的所有需求,但这是一个很好的开始。我提供的内核驱动向导将基于 Ruediger Asche 的原始向导产生的输出文件。

我提供的驱动向导的所有源代码位于本书光盘的 \src\w2k_wiz 目录。通过阅读这些代码,你会发现它实际的标题“ SBS Windows 2000 Code Wizard ”。事实上,这是一个一般性的 Windows 2000 程序骨架生成器,该生成器可以产生多种类型的程序,包括 Win32 DLL 和应用程序。不过,光盘中的配置文件针对内核驱动开发做了一定的修改。基本上来说,我提供的向导是一个文件转换器,它读取一组文件,然后按照一些简单的规则将它们进行转换,最后将结果写入另一组文件中。输入文件是模板,输出文件是 C 工程文件。通过修改模板文件,该向导可以变成一个 DLL 向导等等。必须提供 7 个模板文件(如果丢失了某一个,会产生错误):

l 扩展名为 .tw 的文件是 workspace 模板,此种文件将会被保存为 Visual Studio 的工程文件 .dsw 。

l 扩展名为 .tp 的文件是工程模板,此种文件将被保存为 .dsp 文件。工程文件由于之关联的 workspace 文件引用,工程文件还包含生成工程的所有配置选项。

l 扩展名为 .tc 、 .th 、 .tr 和 .td 的文件都是 C 代码文件,这些文件最后会变成相应的 .c 、 .h 、 .rc 和 .def 文件。

l 扩展名为 .ti 的是 icon 文件,该文件会被直接保存为 .ico 文件。

这七个文件是一个新工程所必需的。 .def 文件以一种较老风格的方法从 DLL 中导出 API 函数,不过我更喜欢 __declspec(dllexport) 方式。因为驱动程序通常不导出函数,所以我省略了 .td 模板,导致的结果是,在开始时,向导会报告一个错误。我还省略了资源脚本和 icon 文件,不过经验告诉我,最好提供它们。采用的转换规则也非常简单,仅包含一个很短的字符串替换列表。在扫描模板文件时,转换器查找以 % 号开始的转义符。当它找到后,会根据 % 后的字符来决定执行什么样的动作。 表 3-1 列出了验证过的转义符。

表 3-1 中有几处需参考配置文件 ---w2k_wiz.ini 。 示例 3-1 给出了其默认设置。在使用向导之前,你应该将光盘 \src\w2k_wiz\release 目录下的 w2k_wiz.exe 、 w2k_wiz.ini 和所有的 w2k_wiz.t* 模板文件复制到你的硬盘上,然后编辑配置文件,将对应内容改为你自己的设置。你还需要修改 Include 、 Free 和 Checked ,使其和你的 DDK 安装相匹配。如果你使用 Visual C/C++ 6.0 ,可以不改变 Root 的值。如果不,则将其设为你存放工程文件的根目录。如果以一个反斜线结尾,它将作为默认值。在 示例 3-1 中,其键值为: HKEY_CURRENT_USER\SoftWare\Microsofto\DevStudio\6.0\Directories ,而 WorkspaceDir 用来存放基本的工作目录。

键入 w2k_wiz MyDriver 来执行该向导,它会当前目录下创建名为 MyDriver 的工程目录,该目录将存放向导生成的 MyDriver.dsw 、 MyDriver.dsp 、 MyDriver.c 、 MyDriver.h 、 MyDriver.rc 和 MyDriver.ico 文件。如果你指定了具体的路径,则会在你指定的路径下创建该目录。另一个合法的命令选项是星号,如: w2k_wiz *MyDriver 。在此种情况下,向导不会在当前目录下创建工程目录,而是去查找 Visual C/C++ 维护的默认的工程根目录,即 w2k_wiz.ini 中的 Root 所指向的位置。

; w2k_wiz.ini

; 08-27-2000 Sven B. Schreiber

; sbs@orgon.com

[Settings]

Text = <SBS Windows 2000 Code Wizard Project>

Company = <MyCompany>

Author = <MyName>

Email = <my@email>

Prefix = <MyPrefix>

Include = E:\NTDDK\inc

Free = E:\NTDDK\libfre\i386

Checked = E:\NTDDK\libchk\i386

Root = HKEY_CURRENT_USER\Software\Microsoft\DevStudio\6.0\Directories\WorkspaceDir

示例 3-1. 向导支持的自定义选项

运行驱动向导

现在,来试试这个驱动向导。 示例 3-2 给出了在 Windows 2000 控制台下执行 w2k_wiz *TestDrv 后的输出。这将在 Visual C/C++ 默认的工程根目录下创建一个名为 TestDrv 的工程目录。

显然,除了将 .td 模板转换为 .def 时出了错,其余转换都成功的完成了。因为该向导生成的驱动程序骨架不需要 .def 文件,所以不需要提供 .td 模板文件。现在,用 Visual C/C++ 打开一个新的 WorkSpace ,然后你会发现一个名为 TestDrv 的新目录,该目录中包含一个名为 TestDrv.dsw 的 WorkSpace 文件。该文件可以被正确的打开。接下来,你因该为生成项目选择活动的配置信息。驱动向导生成的 .dsp 文件提供了如下两个可用配置:

1. Win2k Kernel-mode Driver(debug)

2. Win2k Kernel-mode Driver(release)

默认情况下,将使用 debug 配置来生成项目,但是你可在任何时候从 Visual C/C++ 菜单 Build/Set Active Configuration 来选择不同的项目配置。最后,你要将光盘中的 \src\common\include\DrvInfo.h 复制到你自己的头文件目录中。在打开 TestDrv.rc 时,应使用文本模式来打开(如 图 3-3 所示),这是因为该文件使用了来自 DrvInfo.h 中的复杂的宏定义,这些宏会导致资源编辑器异常退出。这个错误从 Visual C/C++ 5.0 开始,在我印象中,一直没有被改正过。和编辑器不同,资源编译器( Resource Compiler )可以正常的处理这些宏。

图 3-3. 以文本模式打开 TestDrv.c 、 TestDrv.h 和 TestDrv.rc

现在,已经为第一次编译做好了所有准备。在示例 3-3 中,我通过选择 Build/Rebuild 菜单来建立 Driver 的 Release 版,看起来一切都正常。顺便说一下,头两行末尾的省略号表示我截断了 Build 命令的输出。

链接器会在 Debug 或 Release 目录下创建了一个名为 TestDrv.sys 的可执行文件,这依赖于你的生成配置。 Test Driver 的 Release 版大小为 5.5KB ,其 Debug 版为 8KB 。你可以使用本书光盘中的 MFVDasm 或 PEView 来验证 TestDrv.sys 是否包含有效的代码和数据。

深入驱动程序的骨架

列表 3-3 展示了向导生成的 TestDrv.c 。与之相关的头文件 TestDrv.h 在 列表 3-4 中。在 列表 3-3 中,请注意标题处的 <MyName> 和 <MyCompany> 标志。如果 w2k_wiz.ini 中的作者和公司名称正确,那你自己的名字和相应的公司名称将会替代它们。

// TestDrv.c

// 08-07-2000 <MyName>

// Copyright @2005 <MyCompany>

#define _TESTDRV_SYS_

#include <ntddk.h>

#include "TestDrv.h"

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

// DISCLAIMER

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

/*

This software is provided "as is" and any express or implied

warranties, including, but not limited to, the implied warranties of

merc

[1] [2] 下一页

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
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- 王朝網路 版權所有