Programming 版 (精华区)

发信人: tih (我不敢说), 信区: Programming
标  题: Windows 95虚拟设备驱动程序(VxD)10
发信站: 紫 丁 香 (Thu Sep  9 08:25:18 1999), 转信

十、VxD服务

VxD可以提供服务功能(函数或过程——译者注)给VMM和其它VxD使用。这些
服务让其它VxD可以直接访问该VxD的特征,允许测试和修改该VxD的功能和能
力。
VxD不能和Windows DLL一样引出函数,代之的是VMM通过INT 20H提供到VxD服
务的动态链接,该中断处理过程使用服务编号判断支持服务的VxD,该中断处
理过程也使用服务编号查询在VxD服务表中的服务地址。
下面的内容讲述怎样在VxD中定义服务,声明VxD服务表以及从一个VxD向另一
个VxD中引入服务。

1、定义服务

VxD使用BeginProc和EndProc宏以及Service和Async_Service选项定义服务。
宏标记服务过程代码的开始和结束,选项标识该过程是一个服务。下面的实
例给出了VSAMPLED_Get_Version服务的定义:
BeginProc VSAMPLED_Get_Version, Service
 mov ax, 030Ah
 clc
 ret
EndProc VSAMPLED_Get_Version
Async_Service选项标识该服务可以被异步调用,也就是说在处理中断的过程
中调用。异步服务必须是可重入的,而且不能调用VMM和不是异步服务的VxD服
务。
VMM和标准VxD对服务使用两种调用约定:基于寄存器的调用约定和基于32位C
语言的调用约定。这两种调用约定有不同的服务名格式,参数传递和返回值方
法以及寄存器保护。
对于基于寄存器的服务,服务名不应该以下划线(_)开头,所有的参数通过
寄存器传递,结果也通过寄存器返回,服务保护所有不显式用于返回值的寄
存器。
对于基于C语言的服务,服务名必须以下划线(_)开头,所有的参数通过堆栈
中的32位值传递,结果(如果存在)通过EAX寄存器(32位值)或者EAX和EDX
寄存器(64位值)返回,服务保护EBX、ES、FS和GS寄存器以及ESI和EDI寄存
器,只有标志寄存器和EAX、EBX、EDX寄存器被修改。

2、声明服务

VxD使用Begin_Service_Table和End_Service_Table宏声明服务。宏标记包含
服务名和可选的包含服务的段名的列表的开始和结束。声明必须建立在进行
VxD定义的文件中(也就是说在包含Declare_Virtual_Device宏的文件中),
而且必须先进行设备指定符号的定义。下面的实例给出了一个实例VxD——
VSAMPLED的服务表声明:
Create_VSAMPLED_Service_Table equ 1

Begin_Service_Table VSAMPLED
 VSAMPELD_Service VSAMPLED_Get_Version, Local
 VSAMPLED_Service VSAMPLED_Service_1
 VSAMPLED_Service VSAMPLED_Service_2, VxD_ICODE
End_Service_Table VSAMPLED
上例中,Create_VSAMPLED_Service_Table符号在紧接服务表声明之前定义,指
定Begin_Service_Table宏为VSAMPLED创建服务表。声明开始以后,
VSAMPLED_Service宏定义实际服务,这个宏是Begin_Service_Table宏创建的,
只在服务表声明中有效。每个服务名必须与服务定义名,也就是BeginProc宏
给出的名字完全符合。
当声明服务时,如果一个服务定义在包含服务表声明的文件中,必须在服务名
后使用LOCAL选项,也就是说如果不使用LOCAL选项,服务表自动声明一个服务
是外部服务。上例中,VSAMPLED_Get_Version服务定义在包含服务表声明的文
件中。
与之相似,如果一个服务不是定义在VxD_CODE段中,必须在服务名后注明段
名。上例中,VSAMPLED_Service_2服务定义在VxD_ICODE段中。
服务声明的顺序是很重要的。VxD中第一个被声明的服务必须是Get_Version服
务(该服务清除进位标志并在AX寄存器中返回VxD版本号),任何加入VxD的新
服务必须定义在服务表的末尾(或者定义在服务表中显式保留的空间中)。由
于VMM依靠服务在服务表中的顺序正确链接服务,在服务表中间插入一个新服务
需要VxD使用的所有VxD服务被重建。为了方便,服务表声明应该放在一个包含
文件中,使得其它VxD可以通过包含该文件引入服务而不需要重新声明。

3、引入服务

一个VxD可以通过包含另一个VxD的服务表声明引入另一个VxD的服务,
在这种情况下,设备指定符号的定义不能先于该服务表声明(参见上
一节的讲述)。例如:VSAMPLED.INC文件包含VSAMPLED服务的服务表
声明,一个包含该文件的VxD可以调用这些服务。VxD使用VMMcall宏调
用VMM服务,使用VxDcall宏调用VxD服务。
由于计算机配置不同,一个VxD可能会在Windows启动时装载失败,这说
明使用其它VxD提供的服务的VxD必须检验其它VxD服务在调用它们之前是
否有效。为了检验服务,调用服务的VxD必须尝试调用提供服务的VxD的
Get_Version功能,如果VxD没有装载,VMM会设置进位标志并在AX寄存器
中返回0。

--

※ 来源:.紫 丁 香 bbs.hit.edu.cn.[FROM: deu.hit.edu.cn]
[百宝箱] [返回首页] [上级目录] [根目录] [返回顶部] [刷新] [返回]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:3.015毫秒