该驱动程序的头文件有一部分已经由 列表 4-2 到 列表 4-5 给出 。这个文件有些像 DLL 的头文件:它包含在编译过程中,模块所需的定义,而且还为客户端程序提供了足够的接口信息 。DLL 和驱动程序以及客户端程序都包含相同的头文件,但每个模块会取出各自所需的定义以完成正确的操作 。不过,头文件的这种两面性给内核驱动程序带来的麻烦要远多于给 DLL 带来的,这都是因为微软给驱动程序提供的特殊开发环境所致 。不幸的是,DDK 中的头文件并不能和 SDK 中的 Win32 文件兼容 。至少在 C 工程,二者的头文件是不能混合使用的 。这样的结果就是陷入了僵局,此种情况下,内核驱动可以访问的常量、宏和数据类型对于客户端程序来说是却是无法使用的 。因此,w2k_spy.c 定义了一个名为 _W2K_SPY_SYS_ 的标志常量,w2k_spy.h 通过 #ifdef…..#else…..#endif 来检查该常量是否出现,以决定需要补充哪些缺少的定义 。这意味着,所有出现在 #ifdef _W2K_SPY_SYS_ 之后的定义仅可被驱动代码看到,位于 #else 之后的则专用于客户端程序 。w2k_spy.h 中条件语句之外的所有部分被这两个模块同时使用 。
在第三章中,在讨论我的驱动向导时,我给出了向导生成的驱动程序骨架,如 列表 3-3 所示 。由该驱动向导生成的新的驱动工程均开始于 DeviceDispatcher() 函数 。该函数接受一个设备上下文指针,以及一个指向 IRP ( I/O 请求包)的指针,该 IRP 随后将会被分派 。向导的样板代码已经处理了基本的 I/O 请求: IRP_MJ_CREATE 、 IRP_MJ_CLEANUP 和 IRP_MJ_CLSE,当客户要关闭一个设备时,会给该设备发送这些 I/O 请求 。DeviceDispatcher() 针对这些请求只是简单的返回 STATUS_SUCCESS,因此设备可以被正确的打开和关闭 。对于某些设备,这种动作已经足够,但有些设备还需要初始化和清理代码,这些代码多少都有些复杂 。对于其他的请求,第三章中的驱动程序骨架总是返回 STATUS_NOT_IMPLEMENTED。扩展该骨架代码的第一步是修改默认的动作,以便处理更多的 I/O 请求 。就像 w2k_spy.sys 的主要任务之一:通过 IOCTL 调用将在用户模式下无法访问的数据发送给 Win32 应用程序,因此首先需要在 DeviceDispatcher() 中添加处理 IRP_MJ_DEVICE_CONTROL 的函数 。列表 4-6 给出了更新后的代码 。
NTSTATUS DeviceDispatcher (PDEVICE_CONTEXT pDeviceContext,
PIRP pIrp)
{
PIO_STACK_LOCATION pisl;
DWord dInfo = 0;
NTSTATUS ns = STATUS_NOT_IMPLEMENTED;
pisl = IoGetCurrentIrpStackLocation (pIrp);
switch (pisl->MajorFunction)
{
case IRP_MJ_CREATE:
case IRP_MJ_CLEANUP:
case IRP_MJ_CLOSE:
{
ns = STATUS_SUCCESS;
break;
}
case IRP_MJ_DEVICE_CONTROL:
{
ns = SpyDispatcher (pDeviceContext,
pisl->Parameters.DeviceIoControl.IoControlCode,
pIrp->AssociatedIrp.SystemBuffer,
pisl->Parameters.DeviceIoControl.InputBufferLength,
pIrp->AssociatedIrp.SystemBuffer,
pisl->Parameters.DeviceIoControl.OutputBufferLength,
&dInfo);
break;
}
}
pIrp->IoStatus.Status = ns;
pIrp->IoStatus.Information = dInfo;
IoCompleteRequest (pIrp, IO_NO_INCREMENT);
return ns;
}
列表 4-6. 为 Dispatcher 增加处理的 IRP_MJ_DEVICE_CONTROL 函数
列表 4-6 中的 IOCTL 处理代码非常简单,它仅调用了 SpyDispatcher(),并将一个扩展后的 IRP 结构和当前 I/O 堆栈位置作为参数传递给 SpyDispatcher()。SpyDispatcher() 在 列表 4-7 中给出,该函数需要如下的参数:
l pDeviceContext 一个驱动程序的设备上下文指针 。驱动程序向导提供了的基本 Device_Context 结构,该结构中包含驱动程序和设备对象指针(参见 列表 3-4 ) 。不过,Spy 驱动程序在该结构中增加了一对私有成员 。
推荐阅读
- Windows 2000/2003下如何使用组策略禁止用户修改密码
- windows 2000密码破解
- Windows 2000对调试技术的支持
- 永久删除 Windows 2000 默认本地 C, D 盘共享的两个批处理文件
- Windows 2000 无法直接关机解决方案
- 2 《Undocumented Windows 2000 Secrets》翻译 --- 第二章
- 2 《Undocumented Windows 2000 Secrets》翻译 --- 2
- 使用 Windows 2000 中的 IPSec IP 筛选器列表
- 火影忍者是哪一年出的
- 体验 Windows 2000 运行如飞的感觉