VxD編程
一、VxD介紹?
?
本文介紹VxD的作用。如果Windows?95提供的標準VxD對你的硬件或者?
軟件不能提供100%的兼容支持,你需要為你的硬件或者軟件(包括16位?
和32位軟件)創建VxD。如果你想讓Windows用戶使用你的硬件或者軟件?
的某些新特征,你也可以創建VxD。?
本文介紹如何寫VxD,講述了創建VxD所需的結構、過程和調用,還給出?
了創建和測試VxD的步驟。VxD可以是靜態的或者動態裝載的,下面的內?
容主要講述靜態VxD,不過關于格式和功能的內容兩者都適用。?
?
二、什么是VxD?
?
VxD是一個管理例如硬件設備或者已安裝軟件等系統資源的32位可執行程?
序,使得幾個應用程序可以同時使用這些資源。Windows通過使用VxD允?
許基于Windows的應用程序實現多任務。VxD在與Windows的連接工作中?
處理中斷,并在不影響其它應用程序的執行的情況下為特定的應用程序執?
行I/O操作。?
大多數VxD管理硬件設備,也有一些VxD管理或代替與之相關的軟件,例?
如ROM?BIOS例程。VxD可以包含必須在相應設備上執行的設備相關代碼,?
也可以依靠其它軟件去執行這些對設備的操作。任何情況下,VxD都會為?
每一個應用程序保留該設備狀態的記錄,保證無論何時一個應用程序繼續?
執行該設備均處于正確狀態。?
一些VxD僅僅管理已安裝軟件,例如MS-DOS設備驅動程序或者TSR程序,?
這樣的VxD通常包含仿真這些軟件或者保護這些軟件用于正在運行的應用?
程序的數據的代碼。VxD有時還用于提高已安裝軟件的性能,Intel兼容CPU?
執行32位的VxD比執行16位的MS-DOS設備驅動程序或者TSR程序有更?
高的效率。?
?
三、標準VxD?
?
Windows包括多種VxD,用于支持公共硬件設備和可安裝軟件。在某些情?
況下,可能需要修改VxD以提供新的特征或者支持非標準硬件。?
Windows提供許多不準備修改,但能夠輔助支持其他VxD的VxD。例如:?
許多VxD使用V86內存管理器(V86MMGR)和虛擬可編程中斷控制器設備?
(VPICD)提供的功能保存V86模式內存和允許硬件中斷請求。?
要取得開發VxD的幫助,Windows?95設備驅動程序開發工具包(DDK)包?
括了大量可用設備驅動程序的源代碼。?
?
四、創建VxD?
?
你可以通過修改VxD例子程序或者自己手工創建來創建VxD。你可以用匯?
編語言來寫VxD,也可以用高級語言(例如C語言)來寫一部分VxD。?
要創建一個VxD,需要以下步驟:?
1、閱讀硬件手冊中關于描述這種型號硬件VxD的章節。?
2、寫出所需的控制過程,VxD服務和API函數。?
3、建立為VxD標識適當模塊名的模塊定義文件,并引出需要的設備描述?
塊。?
4、匯編連接VxD。?
5、用調試版Windows?95測試VxD,要獲得更多關于調試VxD的信息,請?
參閱相關資料(可以用Soft-ICE調試——譯者注)。?
6、為VxD和相關文件建立安裝文件(INF文件),通過修改注冊信息和向?
Windows的SYSTEM目錄和相關目錄拷貝文件來安裝VxD。?
7、建立最終發行軟件包。?
?
五、你需要怎樣開始?
?
本文假定你是一位有經驗的匯編語言程序員,而且熟悉Intel兼容處理器?
的指令集和系統結構。在某些特殊情況下,你還應該懂得下列內容:?
?
保護模式和虛擬8086(即V86——譯者注)模式。?
平坦內存模式?
中斷和異常處理?
保護和特權級?
段和頁式內存管理以及錯誤處理?
輸入和輸出保護以及錯誤處理?
?
本文也假定你已經熟練了解專門硬件的特征和相應的ROM?BIOS例程以及?
其他可安裝軟件。?
?
六、寫一個VxD?
?
許多情況下,寫一個VxD用來代替一個由Windows?95提供的標準VxD。然?
而,大多數情況下,寫一個VxD是用來支持新硬件設備或者軟件的,在這?
種情況下,通常手工創建一個VxD比修改已經存在的VxD要容易,原因是?
大多數VxD都是設備相關的。然而,已存在VxD的源代碼需要盡可能地仔?
細分析,原因是它們可能包含通用的格式和結構,以及說明怎樣使用VMM?
和VxD服務去實現有用的功能。?
寫一個VxD需要下列步驟:?
1、建立包含VxD各個段,VxD聲明,設備控制過程,處理系統控制消息過?
程的基本部分和API過程的基本部分的VxD框架。?
2、加入實模式初始化過程(可選)。?
3、完成處理初始化消息的過程。這些過程應該能夠初始化控制塊,分配?
全局內存以及安裝中斷、I/O捕獲和頁錯誤回調過程。?
4、完成處理不同中斷和錯誤的回調過程。?
5、為服務加入服務表定義和聲明(可選)。?
6、完成API過程(可選)?
7、完成處理系統控制消息的過程以建立和刪除虛擬機。?
在寫一個VxD的過程中,你可以安裝該VxD并在調試器控制下運行?
Windows,在該VxD中設置斷點監視該VxD管理的中斷,這樣可以幫助你?
查明該VxD是否正確工作。?
?
1、VxD段?
?
VxD可以包含下面5個段的一些組合:?
1、VxD_CODE段:保護模式代碼段(必須)。該段包含VxD系統控制過程、?
回調過程、服務和API過程。該段用宏VxD_CODE_SEG和VxD_CODE_ENDS?
定義開始和結束,也可命名為_LTEXT。?
2、VxD_DATA段:保護模式數據段(必須)。該段包括設備描述表、服務表?
和部分VxD全局數據。該段用宏VxD_DATA_SEG和VxD_DATA_ENDS定義開?
始和結束,也可命名為_LDATA。?
3、VxD_ICODE段:保護模式初始化代碼段(可選)。該段一般包括只在VxD?
初始化過程中使用的過程和服務,VMM在Init_Complete消息發生后丟棄?
此段。該段用宏VxD_ICODE_SEG和VxD_ICODE_ENDS定義開始和結束,也?
可命名為_ITEXT。?
4、VxD_IDATA段:保護模式初始化數據段(可選)。該段一般包括初始化?
過程和服務使用的數據,VMM在Init_Complete消息發生后丟棄此段。該?
段用宏VxD_IDATA_SEG和VxD_IDATA_ENDS定義開始和結束,也可命名為?
_IDATA。?
5、VxD_REAL_INIT段:實模式初始化段(可選)。該段包含實模式初始化?
過程和數據,VMM在裝載VxD其它部分之前調用此過程,過程返回后丟棄?
此段,該段用宏VxD_REAL_INIT_SEG和VxD_REAL_INIT_ENDS定義開始和?
結束,也可命名為_RTEXT。?
除實模式初始化段以外,所有代碼和數據段均為32位平坦內存模式的保?
護模式段,這就是說定義在保護模式段中的過程和數據均為32位的偏移?
量。當VMM裝載VxD時,按照VxD在內存中的實際位置修正所有的偏移量。?
因此,在保護模式段中使用普通OFFSET命令(偽操作,下同——譯者注)?
處應該使用OFFSET32宏,OFFSET32宏定義的偏移量為連接器確定了正確?
的偏移量修正信息。?
VxD不能改變CS、DS、ES和SS段寄存器,VxD能夠使用FS和GS段寄存?
器。?
?
2、保護模式指令?
?
VxD的源程序文件必須以.386p命令開始,以通知匯編器允許保護模式指?
令。雖然VxD工作在0特權級,但也不應該用保護模式指令去修改CPU的?
運行,例如修改全局描述符(選擇子——譯者注)或中斷描述符以及修改?
任務狀態段或寄存器,這樣做可能會對Windows運行有不利影響。唯一的?
例外情況是當該VxD為虛擬數學協處理器設備驅動程序(VMCPD),允許修?
改CR0寄存器中的80387位。?
?
3、包含(Include)文件?
?
包含文件定義了VxD需要的宏、結構、符號和服務表,用于聲明段和過程?
以及使用VMM和其它VxD服務。下面是每個包含文件包含的公共服務定義、?
宏和符號定義列表:?
1、VMM.INC:包含所有的VMM服務以及所需的宏和符號,例如?
Declare_Virtual_Device和VMMCall。?
2、DEBUG.INC:包含在調試終端上輸出信息和執行各種數據檢查的宏。這?
些宏的功能由定義了調試符號的VxD在匯編時該文件生成的代碼實現。?
3、VPICD.INC:包含為虛擬可編程中斷控制器設備(VPICD)定義的所有?
服務、宏和符號。VPICD處理所有的中斷,所以許多VxD需要VPICD服務。?
4、SHELL.INC:包含虛擬外殼設備提供的公共服務的定義。虛擬外殼設備?
提供對例如MessageBox這樣的Windows函數的調用,可以讓VxD顯示對?
話框。?
?
4、VxD聲明?
?
每一個VxD都要聲明一個名稱、一個版本號、一個初始化順序和一個設備?
控制過程,許多虛擬設備驅動程序還聲明一個設備標識和一些API過程。?
VxD一般使用Declare_Virtual_Device宏來實現這些聲明,例如:?
Declare_Virtual_Device?VSAMPLED,?4,?0,?VSAMPLED_Control,?\?
?VSAMPLED_Device_ID,?VSAMPLED_Init_Order,?\?
?VSAMPLED_V86_API_Handler,?\?
?VSAMPLED_PM_API_Handler?
本例聲明了一個VxD實例——VSAMPLED?V4.0,在對應的源文件必須定義?
名字為VSAMPLED_Control的設備控制過程。符號VSAMPLED_Device_ID和?
VSAMPLED_Init_Order說明非標準VxD的標識和初始化順序,該VxD支持?
V86模式和保護模式API過程。?
VMM用宏定義的信息來初始化VxD并發送系統控制消息給VxD,并且允許?
MS-DOS應用程序、設備驅動程序和TSR調用VxD。為了使VMM存取這些信?
息,相應的宏建立一個設備描述塊(DDB)并將其保存在保護模式數據段?
中(DDB的格式與VxD_Desc_Block結構相同),宏為DDB建立了一個必須?
在VxD連接時被顯式引出的標號。在上例中,DDB的名稱是VSAMPLED_DDB。?
?
5、VxD標識(ID)?
?
一個VxD提供一個VxD標識,以區別于其它VxD。VMM動態連接例程使用VxD?
標識為合適的VxD連接服務調用,如果VxD提供服務或者提供V86模式和?
保護模式API過程以及其它需要唯一標識的情況,VxD就必須有唯一標識。?
雖然標準VxD使用預定義VxD標識(符號定義在VMM.INC文件中),支持?
新設備和新軟件接口的VxD還是必須全部有新標識。為了防止與其他新VxD?
沖突,Microsoft通過請求和注冊標識來保證沒有其它廠商使用自己的VxD?
的標識,Microsoft保留0—01FFH之間的所有VxD標識自己使用。不提供?
服務或者API過程,或者不需要唯一標識的VxD應該使用?
Undefined_Device_ID符號來定義VxD標識。?
?
6、初始化順序?
?
每一個VxD都有一個用于指定VMM應該何時初始化該VxD的初始化順序值,?
VMM按照該值從小到大的順序初始化虛擬機(VM——譯者注)。如果兩個或?
者兩個以上的VxD有相同的值,VMM會按照SYSTEM.INI文件中出現的順序?
來初始化,但指定順序是沒有保證的。?
對于需要調用其它VxD服務或者需要在其它VxD之前攔截中斷的VxD,初?
始化順序是很重要的。如果一個VxD需要在標準VxD之前或者之后初始化,?
它的初始化順序值應該通過在標準VxD預定義的初始化順序符號(在?
VMM.INC文件中定義)上加上或者減去一個小數值來創建。?
如果一個VxD不需要初始化順序值,應該使用Undefined_Init_Order符?
號代替初始化順序值。?
?
7、設備控制過程?
?
每一個VxD都有一個設備控制過程,VMM通過調用此過程給VxD發送VxD?
系統控制消息。系統控制消息指導VxD完成動作,例如自身初始化或者通?
知VxD虛擬機的變化(例如創建虛擬機)等。大多數VxD通過使用?
Begin_Control_Dispatch、Control_Dispatch和End_Control_Dispatch?
宏來定義設備控制過程,例如:?
Begin_Control_Dispatch?VSAMPLED?
?Control_Dispatch?Sys_Critical_Init,?VSAMPLED_Crit_Init?
?Control_Dispatch?Device_Init,?VSAMPLED_Device_Init?
?Control_Dispatch?Sys_Critical_Exit,?VSAMPLED_Crit_Exit?
End_Control_Dispatch?VSAMPLED?
上例中,宏創建了一個名字為VSAMPLED_Control的設備控制過程,并生?
成了檢查Sys_Critical_Init、Device_Init和Sys_Critical_Exit消息?
的指令。當這些消息發送到該過程時,該過程通過控制相應的過程(例如?
VSAMPLED_Crit_Init)來處理消息,這些消息處理過程必須在VxD中定義。?
?
七、系統控制消息?
?
VMM發送系統控制消息給VxD,以通知VxD影響系統和虛擬機的變化。大?
多數VxD需要跟蹤虛擬機的創建和狀態,所以無論何時創建、初始化或者?
終止虛擬機,VMM都會發送消息給VxD。VMM也會在執行焦點移動到一個虛?
擬機或者從一個虛擬機移走時,以及虛擬外殼設備需要給用戶顯示一個消?
息框時發送消息給VxD。?
下面是公共消息和VxD應該怎樣處理這些消息的方法列表:?
Begin_Message_Mode消息:當虛擬外殼設備需要給用戶顯示一個消息框但?
不能使用系統虛擬機和Windows函數時VxD收到此消息。虛擬鍵盤、鼠標?
和顯示設備保存當前狀態,允許任何消息模式服務并為消息模式處理初始?
化相應設備。?
Create_VM消息:這是當一個新的虛擬機被創建時VxD收到的第一條消息。?
VxD應該初始化與虛擬機有關的數據,特別是控制塊。?
Debug_Query消息:VxD從WDEB386調試器收到此消息。VxD可以顯示調試?
列表和從調試終端讀取用戶命令。?
Destroy_VM消息:這是VxD收到的第三條虛擬機終止消息。Simulate_Int?
和Exec_Int服務對獲得此消息的虛擬機不再有效。?
Device_Init消息:這是VxD收到的第二條消息。允許中斷,大多數VxD?
分配和拷貝初始狀態到系統虛擬機控制塊中的設備指定部分,安裝中斷回?
調函數和I/O保護異常以及指定實例數據。這時,Simulate_Int和Exec_Int?
服務變得有效。?
End_Message_Mode消息:當虛擬外殼設備不再需要顯示消息框時VxD收到?
此消息。虛擬鍵盤、鼠標和顯示器設備恢復獲得此消息的虛擬機以前保存?
的狀態,禁止任何消息模式服務。?
Init_Complete消息:這是VxD收到的第三條消息,也是最后一條與系統?
初始化有關的消息。雖然大多數VxD都不處理此消息,但使用V86內存的?
VxD應該在此消息返回前定位和申請內存。當VxD返回此消息時,VMM丟?
棄VxD的初始化代碼和數據段。?
Query_Destory消息:當虛擬外殼設備需要決定是否可以刪除虛擬機時VxD?
收到此消息。VxD可以通過設置進位標志(CF——譯者注)返回以阻止虛?
擬機被刪除,在這種情況下VxD應該使用SHELL_Message服務來通知用戶?
問題。?
Reboot_Processor消息:當用戶試圖重新啟動計算機時VxD收到此消息。?
可以重新啟動計算機的VxD,例如鍵盤設備應該完成該工作。?
Set_Device_Focus消息:當執行焦點從一個虛擬機移動到另一個虛擬機時?
VxD收到此消息。VxD恢復硬件設備到與虛擬機有關的狀態。如果VxD使?
用I/O捕獲管理沒有執行焦點時的虛擬機,VxD應該盡可能地移走太多的?
I/O捕獲,使虛擬機運行盡可能地快一些。?
Sys_Critical_Exit消息:這是VxD收到的最后一條消息。禁止中斷,?
Simualte_Int和Exec_Int服務不再有效。VxD應該復位與之相關的硬件?
設備,保證能夠無問題地返回到實模式。?
Sys_Critical_Init消息:這是VxD收到的第一條消息。中斷仍然不被允?
許,所以VxD應該盡可能快地完成任務。大多數VxD完成下列任務:?
安裝和初始化需要支持來自設備的硬件中斷和來自VMM或者其它VxD的軟?
件中斷的任何函數,為設備提供需要單獨使用V86模式內存頁的申請,例?
如虛擬顯示設備申請顯示內存。?
初始化VxD服務需要的任何數據,這通常包括讀取SYSTEM.INI文件中的?
設置。當處理此消息時,Simualte_Int和Exec_Int服務必須不被使用。?
Sys_VM_Init消息:在Init_Complete消息之后VxD收到此消息。VxD應?
該初始化系統虛擬機的硬件和軟件狀態。如果VxD設置進位標志返回,VMM?
終止所有進程并退出Windows。?
Sys_VM_Terminate消息:這是VxD收到的第一條系統虛擬機終止消息。VxD?
可以開始為虛擬機終止做準備。Simulate_Int和Exec_Int服務有效,系?
統虛擬機總是最后一個被終止的虛擬機。?
System_Exit消息:這是當系統終止時VxD收到的第一條消息。VMM在發?
送Sys_VM_Terminate消息之后發送此消息,允許中斷,但Simualte_Int?
和Exec_Int服務不再有效。如果此消息來自一個致命錯誤的結果,VxD可?
以通過修改系統虛擬機的內存以恢復系統狀態,使得Windows能夠終止而?
不死機。?
VM_Critical_Init消息:這是當一個新的VxD(虛擬機——譯者注)被創?
建時VxD收到的第二條消息。VxD可以通過設置進位標志返回以阻止虛擬?
機被建立。禁止中斷,Simualte_Int和Exec_Int服務不再有效。?
VM_Init消息:這是當一個新的VxD被創建時VxD收到的第三條消息。VxD?
應該初始化虛擬機的硬件和軟件狀態,例如虛擬顯示設備執行INT?10H功?
能設置初始顯示模式。?
VM_Not_Execute消息:這是VxD收到的第二條虛擬機終止消息(如果虛擬?
機已經被虛擬外殼設備刪除,這是收到的第一條消息)。VxD可以通過檢查?
EDX寄存器中的標志來查明終止原因。Simulate_Int和Exec_Int服務對?
獲得此消息的虛擬機不再有效。?
VM_Resume消息:當虛擬機的執行被恢復時VxD收到此消息,例如切換到?
前臺時。VxD應該鎖定任何資源和為虛擬機重新開始準備內部結構。如果?
VxD設置進位標志返回,VMM不恢復執行虛擬機。?
VM_Suspend消息:當虛擬機已經被掛起時VxD收到此消息,例如切換到后?
臺時。VxD應該解鎖任何與虛擬機有關的資源。?
VM_Terminate消息:這是VxD收到的第一條虛擬機終止消息。VxD可以開?
始準備虛擬機的終止。Simulate_Int和Exec_Int服務有效。?
?
八、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。?
評論
查看更多