我们可以从SthVxD.c中看到CVxD_Dynamic_Init和CVxD_Dynamic_Exit这两个函数的定义。
ifdef _VxD_SERVICES
extrn _CVxD_Get_Version:near
endif
extrn _CVxD_V86API@12:near
extrn _CVxD_PMAPI@12:near
extrn C EnableHlt: dword
BeginProc CVxD_Control
Control_Dispatch SYS_DYNAMIC_DEVICE_INIT,
CVxD_Dynamic_Init, sCall
Control_Dispatch SYS_DYNAMIC_DEVICE_EXIT,
CVxD_Dynamic_Exit, sCall
Control_Dispatch W32_DEVICEIOCONTROL,
CVxD_W32_DeviceIOControl,
sCall, <ebp, ecx, ebx, edx, esi>
clc
ret
EndProc CVxD_Contro
这是一段消息处理函数。
当VxD初始化时,发生SYS_DYNAMIC_DEVICE_INIT的消息而转入CVxD_Dynamic_Init函数中进行处理。
W32_DEVICEIOCONTROL是宏来定义的,设备控制程序CVxD_W32_DeviceIOControl,<ebp, ecx, ebx, edx, esi>是调用函数时用来传递参数的寄存器的名字。CVxD_W32_DeviceIOControl是留给应用程序的接口函数。当VxD的应用运行后,它和VxD进行数据交换就通过此函数来实现。因为它是用汇编编写的,所以,所有的参数都使用寄存器来传递。
接下来可以看见三个函数
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; 内核空闲(IDLE)时调用此函数
;;
;; 使用HLT指令可以降低CPU的温度
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
BeginProc _IDLEHandleProc
mov eax,[EnableHlt]
test eax,eax
jnz NEXT ;查看EnableHlt是否为真,当EnableHlt为真时
;(即允许用降温功能)转入NEXT
;当EnableHlt为假时,清去零标志位,返回系统中。
stc
ret
NEXT:
sti ;必须打开中断, 如果没有打开中断,CPU就不能响应中断,
;就会死机。当中断打开时,当运行HLT指令后,
;机器一直停止直到外部有一个中断。
;例如敲键或移动鼠标时,当中断处理写成后,
;会从下一条指令开始执行,就不会死在HLT指令处。
hlt ;CPU停机,停机就是使得CPU不工作,
;当CPU不工作时,CPU的功耗就很小,所以能降低温度
stc ;当有事件产生时,清去零标志位,
;返回系统中去处理其程序;
ret
EndProc _IDLEHandleProc
内核空闲(IDLE)时,调用_IDLEHandleProc函数,通过HLT指令达到降温
的目的。
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; 安装内核空闲(IDLE)时调用的函数
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
BeginProc _InstallIDLEProc
push esi
lea esi,[_IDLEHandleProc]
VMMCall Call_When_Idle
pop esi
mov eax,0
setnc al
ret
EndProc _InstallIDLEProc
_InstallIDLEProc函数是在SthVxD.c的CVxD_Dynamic_Init(void)的函数中
被调用的,当它被装入后,VMM空闲时,就自动地调用函数
_IDLEHandleProc。
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; 取消安装内核空闲(IDLE)时调用的函数
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
BeginProc _UnInstallIDLEProc
push esi
lea esi,[_IDLEHandleProc]
VMMCall Cancel_Call_When_Idle
pop esi
mov eax,0
setnc al
ret
EndProc _UnInstallIDLEProc
_UnInstallIDLEProc函数和_InstallIDLEProc函数一样,也是在SthVxD.c中被CVxD_Dynamic_Exit(void)函数调用的。它的作用是去掉VMM注册的空闲函数。
;**************************************************
; V86模式调用的入口
;
; 把调用转变成对C函数的调用, 以便于开发功能强大的处理能力
;
;**************************************************
BeginProc CVxD_V86
scall CVxD_V86API,
<[ebp].Client_EAX, [ebp].Client_EBX, [ebp].Client_ECX>
mov [ebp].Client_EAX,eax ; put return code
ret
EndProc CVxD_V86
;**************************************************
; 保护模式调用的入口
;
; 把调用转变成对C函数的调用, 以便于开发功能强大的处理能力
;**************************************************
BeginProc CVxD_PM
scall CVxD_PMAPI,
<[ebp].Client_EAX, [ebp].Client_EBX, [ebp].Client_ECX>
mov [ebp].Client_EAX,eax
ret
EndProc CVxD_PM
VxD_LOCKED_CODE_ENDS
以上CVxD_V86和CVxD_PM两个函数都在SthVxD.c中定义。它们是V86模式和保护模式调用的入口,其实,它们的代码分别为CVxD_V86API和CVxD_PMAPI。此处只有函数定义,没有具体的实现功能。
VxD不光可以给WIN32位程序调用,WIN16和DOS程序都可以调用VxD提供的功能,它们都通过中断2FH来调用,并设置相应的参数。保护模式与此也是一样的,不过要用到VxD的号码。
;*************************************************;
; 不是动态的VxD时,在Window启动时会被实模式调用
;
;**************************************************
VxD_REAL_INIT_SEG
BeginProc CVxD_Real_Init
xor bx, bx
xor si, si
xor edx, edx
mov ax, Device_Load_Ok
ret
EndProc CVxD_Real_Init
VxD_REAL_INIT_ENDS
END CVxD_Real_Init
以上是一段实模式的初始化调用的函数,主要是用在Windows 9x启动时。当Windows 9x启动时,就会调用到这个函数。这是一个实模式代码,可以看到代码段和寄存器是不同的。这不过是一个框架程序,它会将对汇编的调用全部转变成对C的调用。这样就很方便开发程序。