八、VxD初始化
VMM初始化一個VxD時做下列工作:
1、裝載實模式初始化段並調用實模式初始化過程。該過程可以完成阻止裝載VxD,阻止啟動Windows,指定設備實例數據和在內存中選擇頁面給
設備專用的工作。
2、裝載VxD其它段到32位平坦內存模式的保護模式內存,並丟棄實模式初始化段。
3、發送Sys_Critical_Init消息到設備控制過程。禁止硬件中斷,所以VxD應該盡可能地用較少的時間完成自身初始化。
4、發送Device_Init消息到設備控制過程。允許硬件中斷,所以必須准備讓VxD管理來自設備的中斷。
5、發送Init_Complete消息到設備控制過程。
6、丟棄初始化代碼和數據段,釋放其它被使用的內存。VxD不能在處理完Init_Complete消息以後試圖存取這些段中的過程和數據。
在初始化過程中的任何時刻,VxD都可以設置進位標志返回到VMM以阻止裝載VxD。部分VMM服務,例如初始化信息服務只在初始化過程中有效。
九、實模式初始化
任何靜態設備驅動程序都可以提供實模式初始化過程以在Windows切換到保護模式之前執行初始化任務。VMM裝載VxD時調用該過程,該過程檢查
有關的Windows環境,包括注冊表和初始化文件中的有關設置以判斷是否應該裝載該VxD。該過程也可以給Windows返回信息以為每個虛擬機的實
例指定物理內存頁保留給設備專用和數據項地址。要獲得關於實模式初始化的更多信息,請參閱相關資料。
十、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。
十一、VxD API過程
一個VxD提供V86模式和保護模式API過程以允許在一個虛擬機中運行的應用程序和其它軟件訪問該VxD的特征。如果要使這些可選的過程有效,
VxD必須將它們定義為Declare_Virtual_Device宏的參數,如果沒有定義,VMM認為該VxD沒有API過程。
在一個虛擬機中運行的應用程序或者其它軟件通過設置BX寄存器為VxD標識並調用獲取設備入口地址功能(INT 2FH 1684H功能)獲取特定的虛
擬機的API過程的入口地址,VMM返回該地址使得應用程序可以間接調用該API過程。
當一個應用程序調用該入口地址時,VMM保存該應用程序的寄存器並調用VxD相應的API過程,保存當前虛擬機的句柄到BX寄存器中並保存
Client_Reg_Struc結構地址到EBP寄存器中。API過程必須檢測客戶寄存器的值(使用Client_Reg_Struc結構)以判斷運行的API調用。
按照常規,大多數API過程使用AH寄存器指定主功能號,使用AL寄存器指定次功能號,其它客戶寄存器用於附加參數。API過程通過修改客戶寄
存器返回值,API過程可以修改EAX、EBX、ECX、EDX、ESI和EDI寄存器。
下面的實例給出了一個實例API過程——VSAMPLED_API_Get_Version:
BeginProc VSAMPLED_API_Get_Version
movzx eax, [ebp.Client_AX] ;取功能號
or eax, eax
jnz Undefined
Get_Version:
mov [ebp.Client_AX], 030AH ;在客戶寄存器AX中返回值
and [ebp.Client_Flags], NOT CF_Mask ;清除進位標志
ret
Undefined:
or [ebp.Client_Flags], CF_Mask ;設置進位標志
ret
EndProc VSAMPLED_API_Get_Version
十二、VxD INT 2FH功能
VxD可以通過為INT 2FH中斷安裝回調過程提供INT 2FH功能。INT 2FH功能允許在一個虛擬機中運行的應用程序和其它軟件在VxD不提供API過
程的情況下訪問VxD,例如,標准虛擬顯示設備支持與Windows顯示驅動程序通信的INT 2FH功能集合。
Windows安裝自己的INT 2FH中斷處理程序支持各種功能,以允許MS-DOS 設備驅動程序和TSR在Windows啟動或者虛擬機運行過程中執行特定動作。要獲得有關這些功能的更多信息,請參閱有關資料。
十三、建立一個VxD
應該通過進行下列步驟來建立一個VxD:
1、創建VxD源文件並用32位平坦模式匯編器MASM.EXE(MASM 6.11以上——譯者注)匯編源文件。
2、創建模塊定義文件(DEF文件)並用32位平坦模式連接器LINK.EXE連接目標文件。按照常規,結果可執行文件應該有與VxD相同的文件名,文
件擴展名為VXD。
3、用MAPSYM.EXE為可執行文件創建調試信息。
VxD並不與Windows動態鏈接庫兼容,基於Windows的應用程序並不能直接裝載和使用VxD,然而,基於Win32的應用程序可以通過使用CreateFile
和DeviceIoControl函數裝載動態裝載的VxD和與之相互作用。VxD模塊定義文件有以下格式:
LIBRARY VSAMPLED
DESCRIPTION 'VSAMPLED Device (Version 4.0)'
EXETYPE DEV386
SEGMENTS
_LTEXT PRELOAD NONDISCARDABLE
_LDATA PRELOAD NONDISCARDABLE
_ITEXT CLASS 'ICODE' DISCARDABLE
_IDATA CLASS 'ICODE' DISCARDABLE
_TEXT CLASS 'PCODE' NONDISCARDABLE
_DATA CLASS 'PCODE' NONDISCARDABLE
EXPORTS
VSAMPLED_DDB @1
LIBRARY語句必須指定一個與在已知設備描述塊(DDB)中相同的VxD名字,EXPORT語句必須指定一個DDB的名字,在任何情況下,DDB引出序號都是1。