📄 vxd-c1.htm
字号:
size=-1>VxD程序,包括VMM,通过以下三种途径在相互之间进行通讯:</FONT></FONT>
<UL>
<LI><FONT face=Arial,Helvetica><FONT size=-1>控制消息</FONT></FONT>
<LI><FONT face=Arial,Helvetica><FONT size=-1>服务API</FONT></FONT>
<LI><FONT face=Arial,Helvetica><FONT size=-1>回调</FONT></FONT>
</LI></UL><FONT face=Arial,Helvetica><FONT size=-1><B><U><FONT
color=#ff99ff>控制消息</FONT></U></B>: 当有VMM感兴趣的事件发生时,它就向系统中<B><FONT color=#ffff99>所有</FONT></B>载入的VxD程序发送控制消息。控制消息就像是第三层级别的Windows应用程序的消息。每个VxD程序都有一个接受和处理控制消息的函数,叫做<B><FONT color=#ffff99>设备控制函数</FONT></B>。系统控制消息总共有50多个。控制消息不多的原因是系统中通常加载了很多VxD程序,而每个VxD程序在收到一个控制消息时都要进行处理。如果控制消息太多,就会导致系统停滞。所以控制消息只包括那些与虚拟机有关的重要消息,如:一个虚拟机被创建,被销毁等等。作为对系统控制消息的附加,一个VxD程序可以定义自己的控制消息,这些消息可以用来和那些能响应这些消息的VxD程序通讯。</FONT></FONT>
<P><FONT face=Arial,Helvetica><FONT size=-1><B><U><FONT color=#ff99ff>服务函数</FONT></U></B>: 一个VxD程序,包括VMM在内,通常要导出一系列的被别的VxD程序调用的公共函数,这些函数被称为VxD服务。调用这些服务的机制和在第三层级别运行的的应用程序有很大的不同:每个导出VxD服务的VxD程序<B><FONT
color=#ffff99>必须</FONT></B>有一个唯一的ID,你可以从Microsoft得到一个这样的ID。这个ID是一个包含了一个VxD唯一的身份验证的16位的数字,例如:</FONT></FONT>
<UL><B><TT><FONT size=-1>UNDEFINED_DEVICE_ID EQU
00000H</FONT></TT></B> <BR><B><TT><FONT
size=-1>VMM_DEVICE_ID
EQU 00001H</FONT></TT></B> <BR><B><TT><FONT
size=-1>DEBUG_DEVICE_ID EQU
00002H</FONT></TT></B> <BR><B><TT><FONT
size=-1>VPICD_DEVICE_ID EQU
00003H</FONT></TT></B> <BR><B><TT><FONT
size=-1>VDMAD_DEVICE_ID EQU
00004H</FONT></TT></B> <BR><B><TT><FONT
size=-1>VTD_DEVICE_ID
EQU 00005H</FONT></TT></B></UL><FONT face=Arial,Helvetica><FONT size=-1>你可以看到VMM的ID是1,VPICD的ID是3,等等。VMM用这些ID来找到导出所需VxD服务的VxD程序。当一个VxD程序导出VxD服务时,它把所有服务的地址存在一个表里面。所以,你还需要通过服务分支表里面服务的索引来找到你所要的服务。例如,如果你要调用第一个服务,GetVersion服务,你就要指定0(这个索引是从0开始的)。调用VxD服务的实机制包括中断20h,你的代码产生一个中断20h,并带有一个双字的值,这个值包含了设备ID和服务索引。例如,如果你要调用一个VxD程序导出的VxD服务,假设VxD程序设备ID是000DH,服务号码是1,那么代码应该是:</FONT></FONT>
<UL><B><FONT face=Arial,Helvetica><FONT size=-1>int
20h</FONT></FONT></B> <BR><B><FONT face=Arial,Helvetica><FONT size=-1>dd 000D0001h</font></font></b></ul>
<font face="Arial,Helvetica"><font size=-1>跟在中断20H后的双字的高字包含设备ID。低字是在服务列表中的索引。</FONT></FONT>
<BR><FONT face=Arial,Helvetica><FONT size=-1>当20H中断执行时,VMM得到了控制权,并马上检测跟着的双字。然后它提出设备ID用来找到VxD程序,用服务索引来定位在那个VxD程序中的所要求的服务的地址。</FONT></FONT> <BR><FONT face=Arial,Helvetica><FONT size=-1>你可以看到这个操作时很费时的。VMM必须浪费很多时间来定位VxD程序和所要服务的地址,所以VMM作了个小小的<I><FONT
color=#66ff99>弊</FONT></I> 。当中断20H操作成功后,VMM<B><FONT color=#ffff99>抓取链接</FONT></B>。这就是说,VMM用直接的服务调用来替代20H中断和它后面的双字。所以上面的20H中断代码片断就被改变成:</FONT></FONT>
<UL><B><FONT face=Arial,Helvetica><FONT size=-1>call dword ptr
[VxD_Service_Address]</FONT></FONT></B></UL><FONT face=Arial,Helvetica><FONT
size=-1>这个把戏是成功的,因为<B><FONT color=#ffff99>int
20h+dword</FONT></B>加一个双字用6个字节,正好和<B><FONT
color=#ffff99>call dword ptr</FONT></B>结构相等。所以接下来的服务调用是快速而有效的。这个方法具有直接性,简洁性。在好的一方面,它减轻了VMM和VxD载入器的工作量,因为它们不用定位VxD中<B><FONT color=#ffff99>所有</FONT></B>的服务,那些没有执行过的服务将会保持原样。再不那么好的一方面,一旦一个静态VxD程序导出的服务被调用,那么就不可能把这个静态的VxD程序卸载了。由于VMM把调用锁定到VxD服务的实际地址上,如果提供这个服务的VxD程序从内存中被卸载了,其他VxD程序调用这个服务时就会很快的因为调用无效的内存地址而导致系统崩溃。没有办法来<B><FONT
color=#ffff99>消除</FONT></B>抓取的链接。这个问题的结论是动态VxD不适合作为服务提供者。</FONT></FONT>
<P><FONT face=Arial,Helvetica><FONT size=-1><B><U><FONT
color=#ff99ff>回调</FONT></U></B>: 回调或者回调函数是在VxD程序中给其他的VxD程序调用的函数,不要把回调函数和VxD服务搞混淆了。回调函数不像服务那样是公共的,它们是私有函数,VxD在特定的情况下把它们的地址送给其他的VxD程序。例如,当一个VxD程序在处理一个硬件中断时,由于VMM是不可重入的,这个VxD程序不能使用VxD服务,否则会引起页面错误(重入VMM)。这个VxD程序可以把它自己的一个回调函数的地址给VMM,这样VMM就可以在能忍受页面错误时调用这个函数。回调函数的想法不是VxD独有的。许多Windows API都在用。最好的例子也许是窗口函数,你把窗口函数的地址填在WINDCLASS或WINDCLASSEX结构里并把它当作函数来调用RegisterClass或者RegisterClassEx。当有这个窗口的消息传来时,Windows就会调用你的窗口函数。另一个例子是窗口接管函数。你的程序把接管函数的地址送给Windows,这样当你感兴趣的事件发生时,Windows就会调用你的接管函数。</FONT></FONT> <BR><FONT face=Arial,Helvetica><FONT size=-1>上述三种方法是VxD之间通讯的,我们还要讲对V86,保护模式和Win32应用程序的接口。在下一章里,我们要学习VxD对Win32应用程序的接口。</FONT></FONT> <BR>
<hr size="1">
<div align="center">
<script language="JavaScript1.1" src=http://ad.t2t2.com/textclick.asp?user=bigluo&style=4&bkcolor=no></script>
<br>
</div>
<!-- 10:1 文本广告交换 -->
<div align="center">
<script language="JavaScript1.1" src=http://coolsite21.com:90/c21.dll?Type=PT&id=1047&col=6&ReferID=1047&v=0></script>
<!-- 10:1 文本广告交换 --> </div>
<hr size="1">
<br>
<div align="center"> 由 Ryo 翻译,发表于 <a href="http://asm.yeah.net">http://asm.yeah.net</a>,英文版本来自
[<A href="http://win32asm.cjb.net/">Iczelion's Win32 Assembly Homepage</A>]
</div>
</BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -