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


// 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 (位于本书光盘的 srccommoninclude 目录)中的宏定义 。如果你想更多的了解这个技巧,请参考 TestDrv.h (前面的 列表 3-4 已列出)中的 PROGRAM IDENTIFICATION 一节,并跟踪形如 DRV_* 的定义,它们以多种方式成组的出现在 DrvInfo.h 中 。例如,一个完整的 VERSIONINFO 资源就是由多个小的宏构成的 。在别处,还定义了 DRV_DEVICE 和 DRV_LINK 常量,在这里,它们分别等价于 DeviceTestDrv 和 DosDeviceTestDrv。注意,很多内核 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 中,这种差别以黑体标识出来 。

推荐阅读