&svi, SPY_VERSION_INFO_))
{
_printf (L"rn%s V%lu.lu readyrn",
svi.awName,
svi.dVersion / 100, svi.dVersion % 100);
}
dOptions = COMMAND_OPTION_NONE;
dRequest = CommandParse (hDevice, ppwArguments, dArguments,
TRUE, &dOptions);
dOptions = COMMAND_OPTION_NONE;
dReceive = CommandParse (hDevice, ppwArguments, dArguments,
FALSE, &dOptions);
if (dRequest)
{
_printf (awSummary,
dRequest, (dRequest == 1 ? awByte : awBytes),
dReceive, (dReceive == 1 ? awByte : awBytes));
}
_printf (L"rnClosing the spy device ...rn");
CloseHandle (hDevice);
}
else
{
_printf (L"Unable to open the spy device.rn");
}
if ((hControl != NULL) && gfSpyUnload)
{
_printf (L"Unloading the spy device ...rn");
w2kServiceUnload (awSpyDevice, hControl);
}
return;
}
列表 4-29. 控制 Spy 设备
请注意 列表 4-29 顶部给出的四个全局字符串的定义 。常量 DRV_FILENAME 、 DRV_MODULE 、 DRV_NAME 和 DRV_PATH 来自 Spy 驱动的头文件 w2k_spy.h。表 4-4 列出了它们的当前值 。你不会在 w2k_mem.exe 的源代码中发现设备相关的定义,w2k_spy.h 提供了客户端程序所需的一切 。这非常重要:如果以后改变了任何设备相关的定义,就不需要更新任何程序文件了 。只需要以新的头文件编译、链接程序即可 。
列表 4-29 顶部调用的 w2kFilePath() 可以保证由全局变量 awSpyFile (见 表 4-4 )指定的 w2k_spy.sys 总是从 w2k_mem.exe 所在目录中加载 。接下来,列表 4-29 中的代码将全局字符串 awSpyDevice 和 awSpyDisplay ()传递给 w2kServiceLoad(),以加载 Spy 设备的驱动 。如果驱动没有被加载,这些字符串将被保存在驱动的属性列表中,可以由其他程序取出;否则,将保留当前的属性设置 。尽管 列表 4-29 中的 w2kServiceLoad() 调用可返回一个句柄,但这并不是一个可用于任何 IOCTL 函数的句柄 。要获取 Spy 设备的句柄,必须使用 Win32 的多用途函数 CreateFile()。该函数可打开或创建 Windows 2000 中几乎所有可被打开和创建的东西 。如果提供了内核设备的符号链接名,形如 . 给 CreateFile() 的 lpFileName 参数,那么该函数就可打开这个内核设备 。Spy 设备的符号链接名是: w2k_spy,因此,CreateFile() 的第一个参数必须是 .w2k_spy,这正是 表 4-4 中的 awSpyPath 的值 。
表 4-4. 设备相关的字符串定义
w2k_spy 常量
w2k_mem 变量
值
DRV_FILENAME
awSpyFile
w2k_spy.sys
DRV_MODULE
awSpyDevice
w2k_spy
DRV_NAME
awSpyDisplay
SBS Windows 2000 Spy Device
DRV_PATH
awSpyPath
. w2k_spy
如果 CreateFile() 成功,它将返回一个设备的句柄,该句柄可传递给 DeviceIoControl()。列表 4-29 中的 Execute() 函数使用该句柄来查询 Spy 设备的版本信息,如果 IOCTL 调用成功,该信息将会在屏幕上显示出来 。接下来,CommandParser() 函数将被调用两次,第一次调用只是简单的检查命令行中是否有无效的参数,并显示任何可能的错误 。第二次调用则执行所有的命令 。我不想讨论该函数的细节 。列表 4-29 中的剩余代码是为了进行清理工作,如关闭句柄和卸载 Spy 驱动(该功能是可选的) 。w2k_mem.exe 的源代码中还有一些有趣的代码片断,但我不在这里讨论它们了 。请参考本书光盘的 srcw2k_mem 目录下的 w2k_mem.c 和 w2k_mem.h。
现在唯一需要注意的就是 gfSpyUnload 标志,该标志决定是否卸载 Spy 驱动 。我已经将这个全局标志设为了 FALSE,因此不会自动卸载该驱动 。这提高 w2k_mem.exe 或 w2k_spy.sys 的任何客户端的性能,因为加载一个驱动需要花费一定的时间 。只有第一个客户端会产生加载开销 。这种设置还可避免多个客户端间的竞争,如,一个客户试图卸载该驱动而此时另一个还在使用这个驱动 。当然,Windows 2000 不会卸载一个驱动,除非该驱动的所有句柄都被关闭了,但系统会将驱动置于 STOP_PENDING 状态,这样新的客户端将无法访问此设备 。不过,如果你不在一个多客户端的环境下运行 w2k_spy.sys,而且你需要经常更新设备的驱动程序,你就应该将 gfSpyUnload 标志设为 TRUE。
推荐阅读
- 佐助见到秽土鼬是哪集
- Windows 2000 上配置和应用安全模板
- 如何在 Windows 2000 中启用自动登录
- 2 《Undocumented Windows 2000 Secrets》翻译 --- 第四章
- 1 《Undocumented Windows 2000 Secrets》翻译 --- 第四章
- Windows 2000下的Raw Socket编程
- Windows 2000开发过程中一些有趣的数据
- Windows2000软件冲突一例
- 大叔与少年什么时候开始播
- 盛世嫡妃好看吗