译者序 1
前言 1
第1章 Windows 2000 驱动程序概述 1
1.1 总的系统体系结构 1
1.1.1 Windows 2000 的设计目标 1
1.1.2 Windows 2000中的硬件特权层 1
1.1.3 可移植性 2
1.1.4 可扩展性 3
1.1.5 性能 3
1.1.6 执行程序组件 4
1.2 内核模式I/O组件 8
1.2.1 I/O子系统的设计目标 8
1.2.2 Windows 2000 中驱动程序的种类 8
1.3 特殊的驱动程序结构 10
1.3.1 视频驱动程序 11
1.3.2 打印机驱动程序 12
1.3.3 多媒体驱动程序 13
1.3.4 网络驱动程序 14
1.4 小结 14
第2章 硬件环境 15
2.1 硬件基础 15
2.1.1 设备寄存器 15
2.1.2 访问设备寄存器 16
2.1.3 设备中断 18
2.1.4 数据传输机制 20
2.1.5 DMA机制 20
2.1.7 自动识别和自动配置 21
2.1.6 设备专用内存 21
2.2 总线和Windws 2000 22
2.2.1 ISA: 工业标准体系结构 23
2.2.2 EISA: 扩展工业标准体系结构 25
2.2.3 PCI: 外设部件互连标准 27
2.2.4 USB: 通用串行总线架构 29
2.2.5 IEEE 1394: Firewire总线 31
2.2.6 PC卡(PCMCIA)总线 32
2.3 硬件使用心得 33
2.3.1 了解硬件 33
2.3.2 使用硬件智能 34
2.3.3 测试硬件 34
2.4 小结 34
3.1.1 陷阱或者异常环境 35
第3章 内核模式I/O处理技术 35
3.1 内核模式代码如何执行 35
3.1.2 中断环境 36
3.1.3 内核模式线程环境 36
3.2 Windows 2000使用的中断优先级 36
3.2.1 CPU优先级分层 36
3.2.2 中断处理顺序 37
3.2.3 软件产生的中断 37
3.3 延迟过程调用(DPC) 38
3.3.1 DPC运行 38
3.3.2 DPC行为 39
3.4 用户缓冲区访问 39
3.5 内核模式驱动程序结构 40
3.5.2 I/O系统服务调度例程 41
3.5.1 驱动程序初始化和清除例程 41
3.5.3 数据传输例程 42
3.5.4 资源同步回调 42
3.5.5 其他驱动程序例程 43
3.6 I/O处理顺序 44
3.6.1 I/O管理程序预处理 44
3.6.2 设备驱动程序预处理 44
3.6.3 设备启动和中断服务 45
3.6.4 驱动程序后处理 45
3.6.5 I/O管理程序后处理 46
3.7 小结 47
第4章 驱动程序和内核模式对象 48
4.1 数据对象和Windows 2000 48
4.1.1 Windows 2000和OOP 48
4.2.1 IRP布局 49
4.1.2 Windows 2000对象和Win32对象 49
4.2 I/O请求包(IRP) 49
4.2.2 操纵IRP 51
4.3 驱动程序对象 52
4.4 设备对象和设备扩展 53
4.4.1 设备对象布局 53
4.4.2 操纵设备对象 54
4.4.3 设备扩展 55
4.5 控制器对象和控制器扩展 55
4.5.1 控制器对象布局 56
4.5.2 操纵控制器对象 56
4.5.3 控制器扩展 56
4.6 适配器对象 57
4.7 中断对象 58
4.6.1 适配器对象布局 58
4.6.2 操纵适配器对象 58
4.7.1 中断对象布局 59
4.7.2 操纵中断对象 59
4.8 小结 59
第5章 一般开发问题 60
5.1 驱动程序设计策略 60
5.1.1 使用形式化设计方法 60
5.1.2 使用增量开发方法 61
5.1.3 检查和使用示例驱动程序 61
5.2 编码规范和技术 61
5.2.1 一般性建议 62
5.2.2 命名规范 62
5.2.3 头文件 62
5.2.4 状态返回值 63
5.2.5 Windows 2000驱动程序支持例程 64
5.2.6 丢弃初始化例程 65
5.2.7 控制驱动程序分页 66
5.3 驱动程序存储分配 66
5.3.1 驱动程序可用的内存 66
5.3.2 使用内核堆栈 67
5.3.3 使用池区域 67
5.3.4 内存再分配的系统支持 68
5.4 Unicode字符串 70
5.4.1 Unicode字符串数据类型 70
5.4.2 使用Unicode 71
5.5 中断同步 73
5.5.1 问题 73
5.5.2 中断阻止 74
5.5.3 阻止中断的规则 75
5.5.4 使用延迟过程调用进行同步 75
5.6 多个CPU同步 75
5.6.1 自旋锁如何工作 75
5.6.2 使用自旋锁 75
5.6.3 使用自旋锁的规则 76
5.7 链表 77
5.7.1 单向链表 77
5.7.2 双向链表 78
5.7.3 删除链表中的块 78
5.8 小结 79
6.1.1 执行环境 80
6.1 编写DriverEntry例程 80
第6章 初始化和清除例程 80
6.1.2 DriverEntry例程进行的工作 81
6.1.3 声明DriverEntry入口点 81
6.1.4 建立设备对象 82
6.1.5 选择缓冲策略 83
6.1.6 设备名字 83
6.2 代码示例: 驱动程序初始化 84
6.2.1 DriverEntry 84
6.2.2 CreateDevice 85
6.3 编写Reinitialize例程 87
6.3.1 执行环境 87
6.4.2 Unload例程进行的工作 88
6.4.1 执行环境 88
6.3.2 Reinitialize例程进行的工作 88
6.4 编写Unload例程 88
6.5 代码示例: 驱动程序卸载 89
6.6 编写Shutdown例程 90
6.6.1 执行环境 90
6.6.2 Shutdown例程进行的工作 90
6.6.3 启用关闭通知 90
6.7 测试驱动程序 91
6.7.1 测试过程 91
6.7.2 Visual C+ +设备驱动程序AppWizard向导 91
6.7.3 Windows 2000 DDK 92
6.7.4 驱动程序编译结果 92
6.7.5 手动安装内核模式驱动程序 92
6.7.7 Windows 2000 计算机管理控制台 93
6.7.6 装载驱动程序 93
6.7.8 WINOBJ实用程序 95
6.8 小结 95
第7章 驱动程序Dispatch例程 97
7.1 声明驱动程序Dispatch例程 97
7.1.1 I/O请求的调度机制 97
7.1.2 启用特定的函数代码 97
7.1.3 确定支持哪些函数代码 99
7.2 编写驱动程序Dispatch例程 100
7.2.1 执行环境 100
7.2.2 Dispatch例程进行的工作 100
7.2.3 退出Dispatch例程 101
7.3 处理读写请求 103
7.4 代码示例: 回送设备 104
7.5.1 定义专用的IOCTL值 106
7.5 扩展Dispatch接口 106
7.5.2 IOCTL参数传递方法 107
7.5.3 编写IOCTL头文件 108
7.5.4 处理IOCTL请求 109
7.5.5 管理IOCTL缓冲区 110
7.6 测试驱动程序Dispatch例程 111
7.6.1 测试步骤 112
7.6.2 测试程序示例 112
7.7 小结 112
第8章 中断驱动的I/O 113
8.1 程控I/O工作原理 113
8.1.1 程控I/O期间发生的事情 113
8.1.2 同步驱动程序例程 114
8.2.2 初始化DpcForIsr 115
8.2.3 与中断源相连接 115
8.2.1 初始化Start I/O入口点 115
8.2 驱动程序初始化和清除工作 115
8.2.4 断开与中断源的连接 117
8.3 编写Start I/O例程 117
8.3.1 执行环境 117
8.3.2 Start I/O例程进行的工作 117
8.4 编写中断服务例程(ISR) 118
8.4.1 执行环境 118
8.4.2 中断服务例程进行的工作 118
8.5 编写DpcForIsr例程 119
8.5.1 执行环境 119
8.5.2 DpcForIsr例程进行的工作 119
8.5.3 优先权增加 119
8.6.1 并行端口进行的工作 120
8.6 一些硬件: 并行端口 120
8.6.2 设备寄存器 121
8.6.3 中断行为 122
8.6.4 并行端口的回送连接器 122
8.7 代码示例: 并行端口回送驱动程序 122
8.7.1 驱动程序目的 122
8.7.2 Driver.h 123
8.7.3 Driver.cpp 124
8.8 测试并行端口回送驱动程序 128
8.9 小结 129
第9章 硬件初始化 130
9.1 即插即用体系结构: 简要历史回顾 130
9.1.1 即插即用结构的目标 131
9.1.2 即插即用结构的组成部分 131
9.2 遗留驱动程序注册表的作用 132
9.3 探测即插即用设备 133
9.4 驱动程序分层在即插即用结构中的作用 133
9.5 新的WDM IRP Dispatch函数 137
9.5.1 要求的即插即用IRP 138
9.5.2 PDO即插即用IRP 139
9.5.3 传递即插即用请求 140
9.5.4 I/O完成例程 141
9.5.5 总线驱动程序即插即用请求 144
9.6 设备列举 144
9.6.1 硬件资源描述符 145
9.6.2 在驱动程序中使用硬件资源 147
9.7 设备接口 147
9.7.1 接口定义 147
9.7.3 接口引用计数 148
9.7.2 接口构造 148
9.7.4 注册和启用一个接口 149
9.8 代码示例: 简单的即插即用驱动程序 150
9.9 小结 150
第10章 电源管理 151
10.1 热插拔设备 151
10.1.1 总线考虑 151
10.1.2 设备考虑 152
10.2 OnNow规范 152
10.2.1 电源状态 152
10.2.2 电源策略 153
10.2.4 电源状态更改 154
10.2.3 电源状态矩阵 154
10.3 唤醒请求 158
10.4 电源管理问题 159
10.4.1 空闲管理 160
10.4.2 电源管理的用户接口 160
10.5 小结 161
第11章 计时器 162
11.1 处理设备超时 162
11.1.1 I/O计时器例程工作原理 162
11.1.2 如何捕获设备超时条件 163
11.2 代码示例: 捕获设备超时 164
11.2.1 设备扩展补充 164
11.2.2 AddDevice补充 164
11.2.3 更改Dispatch例程 164
11.2.5 ISR更改 165
11.2.4 StartIo更改 165
11.2.6 I/O计时器回调例程 166
11.3 管理没有中断的设备 167
11.3.1 使用轮询式设备 167
11.3.2 CustomTimerDpc例程工作原理 168
11.3.3 如何建立CustomTimerDpc例程 168
11.3.4 如何规定终止时间 170
11.3.5 CustomTimerDpc例程的其他用法 171
11.4 代码示例: 基于计时器的驱动程序 171
11.4.1 设备扩展补充 171
11.4.2 AddDevice修改 172
11.4.3 TransmitBytes更改 172
11.4.4 PollingTimerDpc例程 173
11.5 小结 173
12.1.1 用适配器对象隐藏DMA硬件变化 174
第12章 DMA驱动程序 174
12.1 Windows 2000中DMA的工作原理 174
12.1.2 分散/集中问题 175
12.1.3 内存描述符列表 176
12.1.4 维护高速缓存相关性 178
12.1.5 基于包的DMA和通用缓冲区DMA 180
12.1.6 Windows 2000 DAM结构的局限性 180
12.2 操作适配器对象 180
12.2.1 查找正确的适配器对象 180
12.2.2 获取和释放适配器对象 182
12.2.3 设置DMA硬件 184
12.2.4 刷新适配器对象高速缓存 184
12.3 编写基于包的从属DMA驱动程序 185
12.3.1 基于包的从属DMA工作原理 185
12.3.2 分割DMA传输 187
12.4 代码示例: 基于包的从属DMA驱动程序 189
12.4.1 DRIVER.H 189
12.4.2 GetDmaInfo例程 189
12.4.3 Start I/O更改 190
12.4.4 AdapterControl(适配器控制)例程 192
12.4.5 DpcForIsr例程 193
12.5 编写基于包的总线主控器DMA驱动程序 195
12.5.1 建立总线主控器硬件 195
12.5.2 支持分散/集中的硬件 197
12.5.3 用MapTransfer建立分散/集中列表 198
12.6 编写通用缓冲区从属DMA驱动程序 201
12.6.1 分配一个通用缓冲区 201
12.6.2 使用通用缓冲区从属DMA维护吞吐量 202
12.7 编写通用缓冲区总线主控器DMA驱动程序 204
12.8 小结 206
第13章 Windows管理和设备测试 207
13.1 WMI: 业界蓝图 207
13.2 WMI体系结构 208
13.2.1 在WDM驱动程序中提供WMI支持 209
13.2.2 MOF语法 210
13.2.3 MOF类定义示例 212
13.2.4 编译MOF源文件 213
13.2.5 处理WMI IRP请求 213
13.2.6 类和实例 214
13.2.7 WMILIB 215
13.3 WMI概述 220
13.4 常规驱动程序事件记录 221
13.4.1 事件记录工作原理 221
13.4.2 操作消息 222
13.4.3 编写消息定义文件 223
13.4.4 一个简单的例子 224
13.4.5 编译消息定义文件 225
13.4.6 把消息资源添加到驱动程序 225
13.4.7 把驱动程序注册为事件源 226
13.4.8 产生日志项 226
13.4.9 分配错误日志包 226
13.4.10 记录错误 227
13.5 小结 228
第14章 系统线程 229
14.1 系统线程的定义使用 229
14.1.1 使用线程的时机 229
14.1.2 建立和终止系统线程 230
14.2 线程同步 231
14.1.3 管理线程优先权 231
14.1.4 系统工作者线程 231
14.2.1 时间同步 232
14.2.2 一般同步 232
14.3 使用调度程序对象 233
14.3.1 事件对象 234
14.3.2 在驱动程序间共享事件 235
14.3.3 互斥对象 235
14.3.4 信号量对象 236
14.3.5 计时器对象 237
14.3.6 线程对象 238
14.3.7 互斥对象的变体 239
14.3.8 同步死锁 240
14.4.1 驱动程序工作原理 241
14.4 代码示例: 基于线程的驱动程序 241
14.4.2 DEVICE_EXTENSION结构 242
14.4.3 AddDevice函数 242
14.4.4 DispatchReadWrite函数 244
14.4.5 Thread.cpp 245
14.4.6 Transfer.c 247
14.5 小结 253
第15章 分层驱动程序 254
15.1 中级驱动程序综述 254
15.1.1 中级驱动程序定义 254
15.1.2 使用分层体系结构的时机 255
15.2 编写分层驱动程序 256
15.2.1 分层驱动程序工作原理 256
15.2.2 分层驱动程序中的初始化和清除工作 257
15.2.3 代码段:连接到另一个驱动程序 258
15.2.4 分层驱动程序的其他初始化问题 259
15.2.5 分层驱动程序中的I/O请求处理技术 259
15.2.6 代码段:调用一个低级驱动程序 261
15.3 编写I/O完成例程 262
15.3.1 请求I/O完成例程回调 262
15.3.2 执行环境 262
15.3.3 I/O完成例程进行的工作 263
15.3.4 代码段:I/O完成例程 264
15.4 分配新增的IRP 265
15.4.1 IRP的I/O堆栈再访问 266
15.4.2 控制IRP堆栈的大小 266
15.4.3 用IoBuildSynchronousFsdRequest建立IRP 268
15.4.4 用IoBuildAsynchronousFsdRequest建立IRP 269
15.4.5 用IoBuildDeviceIoControlRequest建立IRP 270
15.4.6 从零开始建立IRP 271
15.4.7 建立低级驱动程序的缓冲区 274
15.4.8 跟踪驱动程序分配的IRP 274
15.5 编写过滤器驱动程序 275
15.5.1 过滤器驱动程序工作原理 276
15.5.2 过滤器驱动程序中的初始化和清除工作 277
15.5.3 使连接透明 278
15.6 代码示例: 过滤器驱动程序 278
15.6.1 DEVICE_EXTENSION结构 278
15.6.2 DriverEntry函数 279
15.6.3 AddDevice函数 279
15.6.4 OverriddenDispatchWrite函数 281
15.6.6 DispatchPassThru函数 283
15.6.5 OverriddenDispatchDeviceIoControl函数 283
15.6.7 I/O完成例程 284
15.7 编写紧耦合驱动程序 286
15.7.1 紧耦合驱动程序工作原理 287
15.7.2 紧耦合驱动程序中的初始化和清除工作 287
15.8 小结 288
第16章 驱动程序安装 289
16.1 驱动程序安装概述 289
16.2 使用INF文件自动安装 289
16.2.1 INF文件结构 289
16.2.2 Version节 290
16.2.3 Manufacturers节 291
16.2.4 Models节 291
16.2.5 DDInstall节 291
16.2.6 CopyFiles节 292
16.2.7 AddReg节 293
16.2.8 SourceDisksNames节 294
16.2.9 SourceDisksFiles节 295
16.3 使用驱动程序的INF文件 299
16.3.1 手动安装 299
16.3.2 自动安装 299
16.3.3 添加/删除硬件向导 300
16.3.4 类别名字和设备ID 300
16.3.5 定制安装 302
16.4 控制驱动程序装载顺序 303
16.5 驱动程序数字签名 304
16.5.1 Microsoft验证驱动程序的原因 304
16.6 小结 305
16.5.2 数字签名 305
第17章 测试和调试驱动程序 306
17.1 驱动程序测试准则 306
17.1.1 测试驱动程序的常规方法 306
17.1.2 Microsoft硬件兼容性测试 308
17.2 驱动程序失败的原因 308
17.2.1 驱动程序错误分类 309
17.2.2 重演驱动程序错误 310
17.2.3 防错性编码策略 311
17.2.4 跟踪驱动程序错误 311
17.3 阅读故障屏幕 312
17.3.1 系统崩溃时发生什么 312
17.3.2 蓝色死机屏幕 313
17.4.1 源代码调试的关键 314
17.4.2 一些WinDbg命令 314
17.4 WinDbg综述 314
17.5 故障转储分析 316
17.5.1 分析的目标 316
17.5.2 开始分析 316
17.5.3 跟踪堆栈 317
17.5.4 间接调查方法 319
17.6 交互式调试 322
17.6.1 启动和停止一个调试对话 322
17.6.2 设置断点 323
17.6.3 设置硬断点 323
17.6.4 中间输出 324
17.7 编写WinDbg扩展 324
17.7.1 WinDbg扩展工作原理 324
17.7.2 初始化和版本检查函数 324
17.7.3 编写扩展命令 325
17.7.4 WinDbg助手函数 326
17.7.5 建立并使用扩展DLL 327
17.8 代码示例: WinDbg扩展 327
17.9 其他调试技术 332
17.9.1 把已经调试的代码留在驱动程序中 332
17.9.2 捕获不正确的假设 332
17.9.3 使用故障检验回调函数 333
17.9.4 捕获内存泄漏 333
17.9.5 使用计数器、位和缓冲区 334
17.10 小结 336
附录A 驱动程序调试环境 337
附录B 故障检验码 343
附录C 编译驱动程序 354
附录D 关于CD-ROM 360