VxD程序设计入门.doc

上传人:sk****8 文档编号:3502232 上传时间:2019-06-01 格式:DOC 页数:6 大小:41KB
下载 相关 举报
VxD程序设计入门.doc_第1页
第1页 / 共6页
VxD程序设计入门.doc_第2页
第2页 / 共6页
VxD程序设计入门.doc_第3页
第3页 / 共6页
VxD程序设计入门.doc_第4页
第4页 / 共6页
VxD程序设计入门.doc_第5页
第5页 / 共6页
点击查看更多>>
资源描述

1、VxD 程序设计入门VxD 的初始化和结束 VxD 程序分为两种:静态的和动态的。每种的加载方法都不同,接受到的初始化和结束的控制消息也不同。 静态 VxD: 下列情况下,VMM 加载一个静态 VxD: 一个实模式常驻程序通过调用中断 2FH,1605H,来调用此 VxD。 此 VxD 在注册表中的如下位置有定义: HKEY_LOCAL_MACHINESystemCurrentControlSetServicesVxDkeyStaticVxD=VxD 带路径文件名 此 VxD 在 system.ini 中的386enh行下有定义:386enh section: device=VxD 带路径文件

2、名 在开发的时候,我建议你从 system.ini 载入 VxD 程序,因为这样如果你的 VxD程序有错而导致 Windows 不能启动的话,你可以在 Dos 下修改 system.ini,而如果你使用的注册表载入的办法,就无法修改了。 当 VMM 加载你的静态 VxD 程序时,你的 VxD 程序会按以下顺序接收到三个系统控制消息: Sys_Critical_Init VMM 在转入到保护模式后,开放中断前发出这个控制消息。大多数 VxD 程序到不要用到这个消息,除非: 你的 VxD 程序要接管一些其他 VxD 程序或者保护模式程序要用到的中断。既然你处理这个消息的时候这个中断还没有打开,你就

3、可以确定在你接管这个中断的时候此中断不会被调用。 你的 VxD 程序为其他的 VxD 程序提供了一些 VxD 服务。例如,一些在你的 VxD程序后加载的 VxD 程序在处理 Device_Init 控制消息时需要调用一些你的 VxD服务,既然 Sys_Critical_Init 控制消息在 Device_Init 消息之前被发送,所以你应该在 Sys_Critical_Init 消息发送时初始化你的程序。 如果你要对这消息进行处理,你应该尽可能快的做完初始化工作,以免太长的执行时间导致的硬中断丢失。(记住:中断还没打开) Device_Init VMM 在开放中断后发送此信息。大多数 VxD

4、程序都在得到这个消息时初始化。因为中断都开放了,所以耗时的操作也可以在这里执行而不必怕会导致硬中断的丢失。你可以在这时进行初始化(如果你需要的话) 。 Init_Complete 在所有的 VxD 程序处理完 Device_Init 消息之后,VMM 释放初始化段(ICODE 和 RCODE 段类)之前,VMM 发出这个控制消息。只有少数几个 VxD要处理这个消息。 你的 VxD 程序在成功地初始化后,必须将返回标志清零,反之,必须在返回之前把返回标志设为出错信息。如果你的 VxD 不需要初始化,你就不必对这些消息进行处理。 当要结束静态 VxD 的时候,VMM 发送如下的控制消息: Syst

5、em_Exit2 当你的 VxD 程序收到这个消息,Windows95 正在关闭系统,除了系统虚拟机所有其他虚拟机都已经退出了。尽管如此,CPU 仍然处于保护模式下,在系统虚拟机上执行实模式编码也是安全的。在这时 Kernel32.dll 也已经被卸载了。 Sys_Critical_Exit2 当所有的 VxD 完成对 System_Exit2 的响应处理并且中断都被关闭后,你的 VxD 收到到这个消息。 许多 VxD 程序并不要响应这两个消息,除非你要为系统做转换到实模式的准备。要知道,当 Window95 关闭时,它进入到实模式。所以如果你的 VxD 程序对实模式影像做了一些会导致它不稳定

6、的操作,它就需要在这时进行恢复。 你也许会感到奇怪:为什么这两个消息后面都跟着个“2“ ” 。这是因为:在VMM 加载 VxD 程序的时候,它是按照初始化顺序值小的 VxD 先加载的顺序加载的,这样 VxD 程序就可以使用那些在它们之前加载的 VxD 程序提供的服务。例如,VxD2 要用到 VxD1 中的服务,它就必须把它的初始化顺序值定义的比 VxD小。加载的顺序是: . VxD1 = VxD2 = VxD3 . 那么卸载的时候,理所当然的是初始化顺序值大的 VxD 程序先被卸载,这样他们仍然可以使用比它们后加载的那些 VxD 程序提供的服务。如上面的例子,次序是: . VxD3 = VxD

7、2 = VxD1. 在上边的例子中,如果 VxD2 在初始化时调用了 VxD1 中的某些服务,那么卸载时它可能也要再次用到一些 VxD1 中的服务。System_Exit2 和Sys_Critical_Exit2 是反初始化顺序发送的。这表示,当 VxD2 接受到这些消息时,VxD1 还没有被卸载,它仍可以调用 VxD1 的服务,而 System_Exit 和Sys_Critical_Exit 消息不是按照反初始化顺序发送的。这意味着,你不能肯定你是否仍能调用在你之前加载的 VxD 提供的 VxD 服务。新一代的 VxD 程序不应该使用这些消息。 还有两种退出消息: Device_Reboot

8、_Notify2 告诉 VxD 程序 VMM 正在准备重新启动系统。这时候中断还是开放的。 Crit_Reboot_Notify2 告诉 VxD 程序 VMM 正在准备重新启动系统。这时候中断已经被关闭了。 到这里,你可以猜到还有 Device_Reboot_Notify 和 Crit_Reboot_Notify 消息,但它们并不是像“2”版本的消息一样按反初始化顺序发送的。 动态 VxD: 动态 VxD 在 Windows9x 里可以动态的被加载和卸载。这个特点在 Window3.x 下是没有的。动态 VxD 程序的主要作用是用来支持某些动态的硬件设备的重装,比如:即插即用设备。尽管如此,你

9、可以从你的 Win32 程序中加载/卸载它,也可以把它看作是你的程序的一个到 ring-0 的扩展。 上一节我们提到的例子是一个静态的 VxD,你可以把它转换成一个动态的 VxD,只要在.def 文件中 VxD 标记的后面加上关键字 DYNAMIC。 VxD FIRSTVxD DYNAMIC 这就是你把一个静态 VxD 转换成一个动态的 VxD 所要做的一切。 一个动态的 VxD 可以按以下的方法被加载: 把它放到你的 Windows 目录下的SYSTEMIOSUBSYS 目录中。在这个目录里的VxD 会被输入输出监视器(ios)加载。这些 VxD 必须支持层设备驱动。所以用这种方法加载你的动

10、态 VxD 并不是一个好办法。 用 VxD 加载服务。 VxDLDR 是一个可以加载动态 VxD 的静态 VxD。你可以在其他VxD 里面或者在 16 位代码里面调用它的服务。 用 Win32 应用程序里的 CreateFile API。你在调用 CreateFile 时,你的动态VxD 要以下面的格式填写: .VxD 完整路径名 例如,如果你要加载一个在当前目录下名为 FirstVxD 的动态 VxD,你需要做如下的工作: .data VxDName db “.FirstVxD.VxD“,0 . .data? hDevice dd ? . .code . invoke CreateFile,

11、 addr VxDName,0,0,0,0, FILE_FLAG_DELETE_ON_CLOSE,0 mov hDevice,eax . invoke CloseHandle,hDevice . FILE_FLAG_DELETE_ON_CLOSE 这个标志用来说明该 VxD 在 CreateFile 返回的句柄关闭时被卸载。 如果你用 CreateFile 来加载一个动态 VxD,那么这个动态 VxD 必须处理w32_DeviceIoControl 消息。当你的动态 VxD 第一次被 CreateFile 函数加载的时候,VWIN32 向你的 VxD 发出这个消息。你的 VxD 响应这个消息,

12、返回时 eax中的值必须为零。当应用程序调用 DeviceIoControl API 来与一个动态 VxD 通讯时,w32_DeviceIoControl 消息也被发送。我们会在下一章讲到DeviceIoControl 接口。 一个动态 VxD 在初始化时收到一个消息: Sys_Dynamic_Device_Init 在结束时也收到一个控制消息: Sys_Dynamic_Device_Exit 动态 VxD 不会收到 Sys_Critical_Init, Device_Init 和 Init_Complete 控制消息,因为这些消息是在系统虚拟机初始化时发送的。除了这三个消息,动态VxD 能收

13、到所有的控制消息,只要它还在内存里。它可以做静态 VxD 可以做的所有事情。简单的说,动态 VxD 除了加载机制和接收到的初始化/结束消息跟静态 VxD 不同以外,它能做静态 VxD 所能做的一切。 其它系统控制消息 当 VxD 在内存里的时候,除了接收和初始化及结束相关的消息外,它还要收到许多别的控制消息。有些消息是关于虚拟机管理器的,有的是关于各种事件的。例如,关于虚拟机的消息如下: Create_VM VM_Critical_Init VM_Suspend VM_Resume Close_VM_Notify Destroy_VM 选择地响应你所感兴趣的消息是你自己的责任。 在 VxD 内

14、创建函数 你要在一个段里面定义你的函数。你应该首先定义一个段,然后把你的函数放进去。例如,如果你要把你的函数放到一个可调页段中。你应该先定义一个可调页段,像这样: VxD_PAGEABLE_CODE_SEG (你的函数写在这里) VxD_PAGEABLE_CODE_ENDS 你可以在一个段里面插入多个的函数。作为一个 VxD 编写者,你必须决定每一个函数应该放到哪个段里面去。如果你的函数必须时刻存在于内存中,如某些硬件中断处理程序,就把它们放到锁定页面段里面,否则,你应该把它们放到可调页段。 你要用 BeginProc 和 EndProc 宏来定义你的函数: BeginProc 函数名 End

15、Proc 函数名 使用 BeginProc 宏还可以加上一些参数,想了解这些细节,你可以看看 Win95 DDK 的文档。大多数时候,你只用填写函数的名字就够了。 因为 BeginProc-EndProc 宏比 proc-endp 指令的功能要强,所以你应该用BeginProc-EndProc 宏来代替 proc-endp 指令 VxD 编程约定 寄存器的使用 你的 VxD 程序可以使用所有的寄存器,FS 和 GS。但是在改动段寄存器的时候一定要小心。尤其是,一定不要改动 CS 和 SS 的内容,除非你对将发生的事情有绝对的把握。你可以使用 DS 和 ES,但一定要记住在返回时恢复它们初值。有

16、两个特征位尤其重要:方向和中断特征位。不要长时间的屏蔽中断。还有如果你要改动方向特征位,不要忘了在返回之前恢复它的初值。 参数传递约定 VxD 服务函数有两种调用约定:寄存器法和堆栈法。调用寄存器法服务函数时,你通过各种寄存器来传递服务函数的参数。并且,在调用完成后检查寄存器的值来看操作是否成功。不要总是以为在调用服务函数后主要寄存器的值还和以前一样。当调用堆栈法服务函数时,你把要传递的参数压栈,在 eax 得到返回值。堆栈调用法的服务函数保存 ebx,esi,edi 和 ebp 的值。许多寄存器调用法服务函数都源于 Windows3.x 的时代。在大多数时候,你可以通过名字来区分这两种服务函

17、数,如果一个函数的名字一下划线开头,如_HeapAllocate,它就是一个堆栈法的服务函数(除了少数从 VWIN32.VxD 导出的函数) 。如果函数名不是一下划线开头,它就是一个寄存器法的服务函数。 调用 VxD 服务函数 你可以通过 VMMCall 和 VxDCall 宏来调用 VMM 和 VxD 服务。这两个宏的语法是一样的。当你要调用 VMM 导出的 VxD 服务函数时,用 VMMCall。当你要用其它VxD 程序导出的 VxD 服务函数时,用 VxDCall。 VMMCall service ; 调用寄存器法服务函数 e VMMCall _service, ; 调用堆栈法服务函数

18、正如我在前面所讲的,VMMCall 和 VxDCall 分解出一个跟着一个双字的 20h 中断,这样用起来很方便。当你调用堆栈法服务时,你必须用角括号把你的参数列括起来。 VMMCall _HeapAllocate, _HeapAllocate 是一个堆栈法服务函数。它有两个参数,我们必须用角括号把它们括起来。由于第一个参数是一个这个宏不能正确解释的表达式,所以我们又要用一个角括号把它括起来。 Flat 地址 在老的编译工具里,当你使用 offset 操作符时,编译器和联接器会生成错误地址,所以 VxD 编写者用 offset flat:来代替 offset。imm.inc 包括了一个使这更简单的宏:OFFSET32 来代替 offset flat:。所以如果你要用地址操作时,用 OFFSET32 来代替 offset 操作符。 注意: 当我写这篇教程的时候,我试了一下用 offset 操作符。它可以生成正确的地址。所以我想 MASM6.14 修正了这个 bug。但是为了安全起见,你还是应该用 OFFSET32 宏来代替 offset。

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 实用文档资料库 > 策划方案

Copyright © 2018-2021 Wenke99.com All rights reserved

工信部备案号浙ICP备20026746号-2  

公安局备案号:浙公网安备33038302330469号

本站为C2C交文档易平台,即用户上传的文档直接卖给下载用户,本站只是网络服务中间平台,所有原创文档下载所得归上传人所有,若您发现上传作品侵犯了您的权利,请立刻联系网站客服并提供证据,平台将在3个工作日内予以改正。