VxD編程
一、VxD介紹?
?
本文介紹VxD的作用。如果Windows?95提供的標(biāo)準(zhǔn)VxD對(duì)你的硬件或者?
軟件不能提供100%的兼容支持,你需要為你的硬件或者軟件(包括16位?
和32位軟件)創(chuàng)建VxD。如果你想讓W(xué)indows用戶使用你的硬件或者軟件?
的某些新特征,你也可以創(chuàng)建VxD。?
本文介紹如何寫(xiě)VxD,講述了創(chuàng)建VxD所需的結(jié)構(gòu)、過(guò)程和調(diào)用,還給出?
了創(chuàng)建和測(cè)試VxD的步驟。VxD可以是靜態(tài)的或者動(dòng)態(tài)裝載的,下面的內(nèi)?
容主要講述靜態(tài)VxD,不過(guò)關(guān)于格式和功能的內(nèi)容兩者都適用。?
?
二、什么是VxD?
?
VxD是一個(gè)管理例如硬件設(shè)備或者已安裝軟件等系統(tǒng)資源的32位可執(zhí)行程?
序,使得幾個(gè)應(yīng)用程序可以同時(shí)使用這些資源。Windows通過(guò)使用VxD允?
許基于Windows的應(yīng)用程序?qū)崿F(xiàn)多任務(wù)。VxD在與Windows的連接工作中?
處理中斷,并在不影響其它應(yīng)用程序的執(zhí)行的情況下為特定的應(yīng)用程序執(zhí)?
行I/O操作。?
大多數(shù)VxD管理硬件設(shè)備,也有一些VxD管理或代替與之相關(guān)的軟件,例?
如ROM?BIOS例程。VxD可以包含必須在相應(yīng)設(shè)備上執(zhí)行的設(shè)備相關(guān)代碼,?
也可以依靠其它軟件去執(zhí)行這些對(duì)設(shè)備的操作。任何情況下,VxD都會(huì)為?
每一個(gè)應(yīng)用程序保留該設(shè)備狀態(tài)的記錄,保證無(wú)論何時(shí)一個(gè)應(yīng)用程序繼續(xù)?
執(zhí)行該設(shè)備均處于正確狀態(tài)。?
一些VxD僅僅管理已安裝軟件,例如MS-DOS設(shè)備驅(qū)動(dòng)程序或者TSR程序,?
這樣的VxD通常包含仿真這些軟件或者保護(hù)這些軟件用于正在運(yùn)行的應(yīng)用?
程序的數(shù)據(jù)的代碼。VxD有時(shí)還用于提高已安裝軟件的性能,Intel兼容CPU?
執(zhí)行32位的VxD比執(zhí)行16位的MS-DOS設(shè)備驅(qū)動(dòng)程序或者TSR程序有更?
高的效率。?
?
三、標(biāo)準(zhǔn)VxD?
?
Windows包括多種VxD,用于支持公共硬件設(shè)備和可安裝軟件。在某些情?
況下,可能需要修改VxD以提供新的特征或者支持非標(biāo)準(zhǔn)硬件。?
Windows提供許多不準(zhǔn)備修改,但能夠輔助支持其他VxD的VxD。例如:?
許多VxD使用V86內(nèi)存管理器(V86MMGR)和虛擬可編程中斷控制器設(shè)備?
(VPICD)提供的功能保存V86模式內(nèi)存和允許硬件中斷請(qǐng)求。?
要取得開(kāi)發(fā)VxD的幫助,Windows?95設(shè)備驅(qū)動(dòng)程序開(kāi)發(fā)工具包(DDK)包?
括了大量可用設(shè)備驅(qū)動(dòng)程序的源代碼。?
?
四、創(chuàng)建VxD?
?
你可以通過(guò)修改VxD例子程序或者自己手工創(chuàng)建來(lái)創(chuàng)建VxD。你可以用匯?
編語(yǔ)言來(lái)寫(xiě)VxD,也可以用高級(jí)語(yǔ)言(例如C語(yǔ)言)來(lái)寫(xiě)一部分VxD。?
要?jiǎng)?chuàng)建一個(gè)VxD,需要以下步驟:?
1、閱讀硬件手冊(cè)中關(guān)于描述這種型號(hào)硬件VxD的章節(jié)。?
2、寫(xiě)出所需的控制過(guò)程,VxD服務(wù)和API函數(shù)。?
3、建立為VxD標(biāo)識(shí)適當(dāng)模塊名的模塊定義文件,并引出需要的設(shè)備描述?
塊。?
4、匯編連接VxD。?
5、用調(diào)試版Windows?95測(cè)試VxD,要獲得更多關(guān)于調(diào)試VxD的信息,請(qǐng)?
參閱相關(guān)資料(可以用Soft-ICE調(diào)試——譯者注)。?
6、為VxD和相關(guān)文件建立安裝文件(INF文件),通過(guò)修改注冊(cè)信息和向?
Windows的SYSTEM目錄和相關(guān)目錄拷貝文件來(lái)安裝VxD。?
7、建立最終發(fā)行軟件包。?
?
五、你需要怎樣開(kāi)始?
?
本文假定你是一位有經(jīng)驗(yàn)的匯編語(yǔ)言程序員,而且熟悉Intel兼容處理器?
的指令集和系統(tǒng)結(jié)構(gòu)。在某些特殊情況下,你還應(yīng)該懂得下列內(nèi)容:?
?
保護(hù)模式和虛擬8086(即V86——譯者注)模式。?
平坦內(nèi)存模式?
中斷和異常處理?
保護(hù)和特權(quán)級(jí)?
段和頁(yè)式內(nèi)存管理以及錯(cuò)誤處理?
輸入和輸出保護(hù)以及錯(cuò)誤處理?
?
本文也假定你已經(jīng)熟練了解專(zhuān)門(mén)硬件的特征和相應(yīng)的ROM?BIOS例程以及?
其他可安裝軟件。?
?
六、寫(xiě)一個(gè)VxD?
?
許多情況下,寫(xiě)一個(gè)VxD用來(lái)代替一個(gè)由Windows?95提供的標(biāo)準(zhǔn)VxD。然?
而,大多數(shù)情況下,寫(xiě)一個(gè)VxD是用來(lái)支持新硬件設(shè)備或者軟件的,在這?
種情況下,通常手工創(chuàng)建一個(gè)VxD比修改已經(jīng)存在的VxD要容易,原因是?
大多數(shù)VxD都是設(shè)備相關(guān)的。然而,已存在VxD的源代碼需要盡可能地仔?
細(xì)分析,原因是它們可能包含通用的格式和結(jié)構(gòu),以及說(shuō)明怎樣使用VMM?
和VxD服務(wù)去實(shí)現(xiàn)有用的功能。?
寫(xiě)一個(gè)VxD需要下列步驟:?
1、建立包含VxD各個(gè)段,VxD聲明,設(shè)備控制過(guò)程,處理系統(tǒng)控制消息過(guò)?
程的基本部分和API過(guò)程的基本部分的VxD框架。?
2、加入實(shí)模式初始化過(guò)程(可選)。?
3、完成處理初始化消息的過(guò)程。這些過(guò)程應(yīng)該能夠初始化控制塊,分配?
全局內(nèi)存以及安裝中斷、I/O捕獲和頁(yè)錯(cuò)誤回調(diào)過(guò)程。?
4、完成處理不同中斷和錯(cuò)誤的回調(diào)過(guò)程。?
5、為服務(wù)加入服務(wù)表定義和聲明(可選)。?
6、完成API過(guò)程(可選)?
7、完成處理系統(tǒng)控制消息的過(guò)程以建立和刪除虛擬機(jī)。?
在寫(xiě)一個(gè)VxD的過(guò)程中,你可以安裝該VxD并在調(diào)試器控制下運(yùn)行?
Windows,在該VxD中設(shè)置斷點(diǎn)監(jiān)視該VxD管理的中斷,這樣可以幫助你?
查明該VxD是否正確工作。?
?
1、VxD段?
?
VxD可以包含下面5個(gè)段的一些組合:?
1、VxD_CODE段:保護(hù)模式代碼段(必須)。該段包含VxD系統(tǒng)控制過(guò)程、?
回調(diào)過(guò)程、服務(wù)和API過(guò)程。該段用宏VxD_CODE_SEG和VxD_CODE_ENDS?
定義開(kāi)始和結(jié)束,也可命名為_(kāi)LTEXT。?
2、VxD_DATA段:保護(hù)模式數(shù)據(jù)段(必須)。該段包括設(shè)備描述表、服務(wù)表?
和部分VxD全局?jǐn)?shù)據(jù)。該段用宏VxD_DATA_SEG和VxD_DATA_ENDS定義開(kāi)?
始和結(jié)束,也可命名為_(kāi)LDATA。?
3、VxD_ICODE段:保護(hù)模式初始化代碼段(可選)。該段一般包括只在VxD?
初始化過(guò)程中使用的過(guò)程和服務(wù),VMM在Init_Complete消息發(fā)生后丟棄?
此段。該段用宏VxD_ICODE_SEG和VxD_ICODE_ENDS定義開(kāi)始和結(jié)束,也?
可命名為_(kāi)ITEXT。?
4、VxD_IDATA段:保護(hù)模式初始化數(shù)據(jù)段(可選)。該段一般包括初始化?
過(guò)程和服務(wù)使用的數(shù)據(jù),VMM在Init_Complete消息發(fā)生后丟棄此段。該?
段用宏VxD_IDATA_SEG和VxD_IDATA_ENDS定義開(kāi)始和結(jié)束,也可命名為?
_IDATA。?
5、VxD_REAL_INIT段:實(shí)模式初始化段(可選)。該段包含實(shí)模式初始化?
過(guò)程和數(shù)據(jù),VMM在裝載VxD其它部分之前調(diào)用此過(guò)程,過(guò)程返回后丟棄?
此段,該段用宏VxD_REAL_INIT_SEG和VxD_REAL_INIT_ENDS定義開(kāi)始和?
結(jié)束,也可命名為_(kāi)RTEXT。?
除實(shí)模式初始化段以外,所有代碼和數(shù)據(jù)段均為32位平坦內(nèi)存模式的保?
護(hù)模式段,這就是說(shuō)定義在保護(hù)模式段中的過(guò)程和數(shù)據(jù)均為32位的偏移?
量。當(dāng)VMM裝載VxD時(shí),按照VxD在內(nèi)存中的實(shí)際位置修正所有的偏移量。?
因此,在保護(hù)模式段中使用普通OFFSET命令(偽操作,下同——譯者注)?
處應(yīng)該使用OFFSET32宏,OFFSET32宏定義的偏移量為連接器確定了正確?
的偏移量修正信息。?
VxD不能改變CS、DS、ES和SS段寄存器,VxD能夠使用FS和GS段寄存?
器。?
?
2、保護(hù)模式指令?
?
VxD的源程序文件必須以.386p命令開(kāi)始,以通知匯編器允許保護(hù)模式指?
令。雖然VxD工作在0特權(quán)級(jí),但也不應(yīng)該用保護(hù)模式指令去修改CPU的?
運(yùn)行,例如修改全局描述符(選擇子——譯者注)或中斷描述符以及修改?
任務(wù)狀態(tài)段或寄存器,這樣做可能會(huì)對(duì)Windows運(yùn)行有不利影響。唯一的?
例外情況是當(dāng)該VxD為虛擬數(shù)學(xué)協(xié)處理器設(shè)備驅(qū)動(dòng)程序(VMCPD),允許修?
改CR0寄存器中的80387位。?
?
3、包含(Include)文件?
?
包含文件定義了VxD需要的宏、結(jié)構(gòu)、符號(hào)和服務(wù)表,用于聲明段和過(guò)程?
以及使用VMM和其它VxD服務(wù)。下面是每個(gè)包含文件包含的公共服務(wù)定義、?
宏和符號(hào)定義列表:?
1、VMM.INC:包含所有的VMM服務(wù)以及所需的宏和符號(hào),例如?
Declare_Virtual_Device和VMMCall。?
2、DEBUG.INC:包含在調(diào)試終端上輸出信息和執(zhí)行各種數(shù)據(jù)檢查的宏。這?
些宏的功能由定義了調(diào)試符號(hào)的VxD在匯編時(shí)該文件生成的代碼實(shí)現(xiàn)。?
3、VPICD.INC:包含為虛擬可編程中斷控制器設(shè)備(VPICD)定義的所有?
服務(wù)、宏和符號(hào)。VPICD處理所有的中斷,所以許多VxD需要VPICD服務(wù)。?
4、SHELL.INC:包含虛擬外殼設(shè)備提供的公共服務(wù)的定義。虛擬外殼設(shè)備?
提供對(duì)例如MessageBox這樣的Windows函數(shù)的調(diào)用,可以讓VxD顯示對(duì)?
話框。?
?
4、VxD聲明?
?
每一個(gè)VxD都要聲明一個(gè)名稱(chēng)、一個(gè)版本號(hào)、一個(gè)初始化順序和一個(gè)設(shè)備?
控制過(guò)程,許多虛擬設(shè)備驅(qū)動(dòng)程序還聲明一個(gè)設(shè)備標(biāo)識(shí)和一些API過(guò)程。?
VxD一般使用Declare_Virtual_Device宏來(lái)實(shí)現(xiàn)這些聲明,例如:?
Declare_Virtual_Device?VSAMPLED,?4,?0,?VSAMPLED_Control,?\?
?VSAMPLED_Device_ID,?VSAMPLED_Init_Order,?\?
?VSAMPLED_V86_API_Handler,?\?
?VSAMPLED_PM_API_Handler?
本例聲明了一個(gè)VxD實(shí)例——VSAMPLED?V4.0,在對(duì)應(yīng)的源文件必須定義?
名字為VSAMPLED_Control的設(shè)備控制過(guò)程。符號(hào)VSAMPLED_Device_ID和?
VSAMPLED_Init_Order說(shuō)明非標(biāo)準(zhǔn)VxD的標(biāo)識(shí)和初始化順序,該VxD支持?
V86模式和保護(hù)模式API過(guò)程。?
VMM用宏定義的信息來(lái)初始化VxD并發(fā)送系統(tǒng)控制消息給VxD,并且允許?
MS-DOS應(yīng)用程序、設(shè)備驅(qū)動(dòng)程序和TSR調(diào)用VxD。為了使VMM存取這些信?
息,相應(yīng)的宏建立一個(gè)設(shè)備描述塊(DDB)并將其保存在保護(hù)模式數(shù)據(jù)段?
中(DDB的格式與VxD_Desc_Block結(jié)構(gòu)相同),宏為DDB建立了一個(gè)必須?
在VxD連接時(shí)被顯式引出的標(biāo)號(hào)。在上例中,DDB的名稱(chēng)是VSAMPLED_DDB。?
?
5、VxD標(biāo)識(shí)(ID)?
?
一個(gè)VxD提供一個(gè)VxD標(biāo)識(shí),以區(qū)別于其它VxD。VMM動(dòng)態(tài)連接例程使用VxD?
標(biāo)識(shí)為合適的VxD連接服務(wù)調(diào)用,如果VxD提供服務(wù)或者提供V86模式和?
保護(hù)模式API過(guò)程以及其它需要唯一標(biāo)識(shí)的情況,VxD就必須有唯一標(biāo)識(shí)。?
雖然標(biāo)準(zhǔn)VxD使用預(yù)定義VxD標(biāo)識(shí)(符號(hào)定義在VMM.INC文件中),支持?
新設(shè)備和新軟件接口的VxD還是必須全部有新標(biāo)識(shí)。為了防止與其他新VxD?
沖突,Microsoft通過(guò)請(qǐng)求和注冊(cè)標(biāo)識(shí)來(lái)保證沒(méi)有其它廠商使用自己的VxD?
的標(biāo)識(shí),Microsoft保留0—01FFH之間的所有VxD標(biāo)識(shí)自己使用。不提供?
服務(wù)或者API過(guò)程,或者不需要唯一標(biāo)識(shí)的VxD應(yīng)該使用?
Undefined_Device_ID符號(hào)來(lái)定義VxD標(biāo)識(shí)。?
?
6、初始化順序?
?
每一個(gè)VxD都有一個(gè)用于指定VMM應(yīng)該何時(shí)初始化該VxD的初始化順序值,?
VMM按照該值從小到大的順序初始化虛擬機(jī)(VM——譯者注)。如果兩個(gè)或?
者兩個(gè)以上的VxD有相同的值,VMM會(huì)按照SYSTEM.INI文件中出現(xiàn)的順序?
來(lái)初始化,但指定順序是沒(méi)有保證的。?
對(duì)于需要調(diào)用其它VxD服務(wù)或者需要在其它VxD之前攔截中斷的VxD,初?
始化順序是很重要的。如果一個(gè)VxD需要在標(biāo)準(zhǔn)VxD之前或者之后初始化,?
它的初始化順序值應(yīng)該通過(guò)在標(biāo)準(zhǔn)VxD預(yù)定義的初始化順序符號(hào)(在?
VMM.INC文件中定義)上加上或者減去一個(gè)小數(shù)值來(lái)創(chuàng)建。?
如果一個(gè)VxD不需要初始化順序值,應(yīng)該使用Undefined_Init_Order符?
號(hào)代替初始化順序值。?
?
7、設(shè)備控制過(guò)程?
?
每一個(gè)VxD都有一個(gè)設(shè)備控制過(guò)程,VMM通過(guò)調(diào)用此過(guò)程給VxD發(fā)送VxD?
系統(tǒng)控制消息。系統(tǒng)控制消息指導(dǎo)VxD完成動(dòng)作,例如自身初始化或者通?
知VxD虛擬機(jī)的變化(例如創(chuàng)建虛擬機(jī))等。大多數(shù)VxD通過(guò)使用?
Begin_Control_Dispatch、Control_Dispatch和End_Control_Dispatch?
宏來(lái)定義設(shè)備控制過(guò)程,例如:?
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?
上例中,宏創(chuàng)建了一個(gè)名字為VSAMPLED_Control的設(shè)備控制過(guò)程,并生?
成了檢查Sys_Critical_Init、Device_Init和Sys_Critical_Exit消息?
的指令。當(dāng)這些消息發(fā)送到該過(guò)程時(shí),該過(guò)程通過(guò)控制相應(yīng)的過(guò)程(例如?
VSAMPLED_Crit_Init)來(lái)處理消息,這些消息處理過(guò)程必須在VxD中定義。?
?
七、系統(tǒng)控制消息?
?
VMM發(fā)送系統(tǒng)控制消息給VxD,以通知VxD影響系統(tǒng)和虛擬機(jī)的變化。大?
多數(shù)VxD需要跟蹤虛擬機(jī)的創(chuàng)建和狀態(tài),所以無(wú)論何時(shí)創(chuàng)建、初始化或者?
終止虛擬機(jī),VMM都會(huì)發(fā)送消息給VxD。VMM也會(huì)在執(zhí)行焦點(diǎn)移動(dòng)到一個(gè)虛?
擬機(jī)或者從一個(gè)虛擬機(jī)移走時(shí),以及虛擬外殼設(shè)備需要給用戶顯示一個(gè)消?
息框時(shí)發(fā)送消息給VxD。?
下面是公共消息和VxD應(yīng)該怎樣處理這些消息的方法列表:?
Begin_Message_Mode消息:當(dāng)虛擬外殼設(shè)備需要給用戶顯示一個(gè)消息框但?
不能使用系統(tǒng)虛擬機(jī)和Windows函數(shù)時(shí)VxD收到此消息。虛擬鍵盤(pán)、鼠標(biāo)?
和顯示設(shè)備保存當(dāng)前狀態(tài),允許任何消息模式服務(wù)并為消息模式處理初始?
化相應(yīng)設(shè)備。?
Create_VM消息:這是當(dāng)一個(gè)新的虛擬機(jī)被創(chuàng)建時(shí)VxD收到的第一條消息。?
VxD應(yīng)該初始化與虛擬機(jī)有關(guān)的數(shù)據(jù),特別是控制塊。?
Debug_Query消息:VxD從WDEB386調(diào)試器收到此消息。VxD可以顯示調(diào)試?
列表和從調(diào)試終端讀取用戶命令。?
Destroy_VM消息:這是VxD收到的第三條虛擬機(jī)終止消息。Simulate_Int?
和Exec_Int服務(wù)對(duì)獲得此消息的虛擬機(jī)不再有效。?
Device_Init消息:這是VxD收到的第二條消息。允許中斷,大多數(shù)VxD?
分配和拷貝初始狀態(tài)到系統(tǒng)虛擬機(jī)控制塊中的設(shè)備指定部分,安裝中斷回?
調(diào)函數(shù)和I/O保護(hù)異常以及指定實(shí)例數(shù)據(jù)。這時(shí),Simulate_Int和Exec_Int?
服務(wù)變得有效。?
End_Message_Mode消息:當(dāng)虛擬外殼設(shè)備不再需要顯示消息框時(shí)VxD收到?
此消息。虛擬鍵盤(pán)、鼠標(biāo)和顯示器設(shè)備恢復(fù)獲得此消息的虛擬機(jī)以前保存?
的狀態(tài),禁止任何消息模式服務(wù)。?
Init_Complete消息:這是VxD收到的第三條消息,也是最后一條與系統(tǒng)?
初始化有關(guān)的消息。雖然大多數(shù)VxD都不處理此消息,但使用V86內(nèi)存的?
VxD應(yīng)該在此消息返回前定位和申請(qǐng)內(nèi)存。當(dāng)VxD返回此消息時(shí),VMM丟?
棄VxD的初始化代碼和數(shù)據(jù)段。?
Query_Destory消息:當(dāng)虛擬外殼設(shè)備需要決定是否可以刪除虛擬機(jī)時(shí)VxD?
收到此消息。VxD可以通過(guò)設(shè)置進(jìn)位標(biāo)志(CF——譯者注)返回以阻止虛?
擬機(jī)被刪除,在這種情況下VxD應(yīng)該使用SHELL_Message服務(wù)來(lái)通知用戶?
問(wèn)題。?
Reboot_Processor消息:當(dāng)用戶試圖重新啟動(dòng)計(jì)算機(jī)時(shí)VxD收到此消息。?
可以重新啟動(dòng)計(jì)算機(jī)的VxD,例如鍵盤(pán)設(shè)備應(yīng)該完成該工作。?
Set_Device_Focus消息:當(dāng)執(zhí)行焦點(diǎn)從一個(gè)虛擬機(jī)移動(dòng)到另一個(gè)虛擬機(jī)時(shí)?
VxD收到此消息。VxD恢復(fù)硬件設(shè)備到與虛擬機(jī)有關(guān)的狀態(tài)。如果VxD使?
用I/O捕獲管理沒(méi)有執(zhí)行焦點(diǎn)時(shí)的虛擬機(jī),VxD應(yīng)該盡可能地移走太多的?
I/O捕獲,使虛擬機(jī)運(yùn)行盡可能地快一些。?
Sys_Critical_Exit消息:這是VxD收到的最后一條消息。禁止中斷,?
Simualte_Int和Exec_Int服務(wù)不再有效。VxD應(yīng)該復(fù)位與之相關(guān)的硬件?
設(shè)備,保證能夠無(wú)問(wèn)題地返回到實(shí)模式。?
Sys_Critical_Init消息:這是VxD收到的第一條消息。中斷仍然不被允?
許,所以VxD應(yīng)該盡可能快地完成任務(wù)。大多數(shù)VxD完成下列任務(wù):?
安裝和初始化需要支持來(lái)自設(shè)備的硬件中斷和來(lái)自VMM或者其它VxD的軟?
件中斷的任何函數(shù),為設(shè)備提供需要單獨(dú)使用V86模式內(nèi)存頁(yè)的申請(qǐng),例?
如虛擬顯示設(shè)備申請(qǐng)顯示內(nèi)存。?
初始化VxD服務(wù)需要的任何數(shù)據(jù),這通常包括讀取SYSTEM.INI文件中的?
設(shè)置。當(dāng)處理此消息時(shí),Simualte_Int和Exec_Int服務(wù)必須不被使用。?
Sys_VM_Init消息:在Init_Complete消息之后VxD收到此消息。VxD應(yīng)?
該初始化系統(tǒng)虛擬機(jī)的硬件和軟件狀態(tài)。如果VxD設(shè)置進(jìn)位標(biāo)志返回,VMM?
終止所有進(jìn)程并退出Windows。?
Sys_VM_Terminate消息:這是VxD收到的第一條系統(tǒng)虛擬機(jī)終止消息。VxD?
可以開(kāi)始為虛擬機(jī)終止做準(zhǔn)備。Simulate_Int和Exec_Int服務(wù)有效,系?
統(tǒng)虛擬機(jī)總是最后一個(gè)被終止的虛擬機(jī)。?
System_Exit消息:這是當(dāng)系統(tǒng)終止時(shí)VxD收到的第一條消息。VMM在發(fā)?
送Sys_VM_Terminate消息之后發(fā)送此消息,允許中斷,但Simualte_Int?
和Exec_Int服務(wù)不再有效。如果此消息來(lái)自一個(gè)致命錯(cuò)誤的結(jié)果,VxD可?
以通過(guò)修改系統(tǒng)虛擬機(jī)的內(nèi)存以恢復(fù)系統(tǒng)狀態(tài),使得Windows能夠終止而?
不死機(jī)。?
VM_Critical_Init消息:這是當(dāng)一個(gè)新的VxD(虛擬機(jī)——譯者注)被創(chuàng)?
建時(shí)VxD收到的第二條消息。VxD可以通過(guò)設(shè)置進(jìn)位標(biāo)志返回以阻止虛擬?
機(jī)被建立。禁止中斷,Simualte_Int和Exec_Int服務(wù)不再有效。?
VM_Init消息:這是當(dāng)一個(gè)新的VxD被創(chuàng)建時(shí)VxD收到的第三條消息。VxD?
應(yīng)該初始化虛擬機(jī)的硬件和軟件狀態(tài),例如虛擬顯示設(shè)備執(zhí)行INT?10H功?
能設(shè)置初始顯示模式。?
VM_Not_Execute消息:這是VxD收到的第二條虛擬機(jī)終止消息(如果虛擬?
機(jī)已經(jīng)被虛擬外殼設(shè)備刪除,這是收到的第一條消息)。VxD可以通過(guò)檢查?
EDX寄存器中的標(biāo)志來(lái)查明終止原因。Simulate_Int和Exec_Int服務(wù)對(duì)?
獲得此消息的虛擬機(jī)不再有效。?
VM_Resume消息:當(dāng)虛擬機(jī)的執(zhí)行被恢復(fù)時(shí)VxD收到此消息,例如切換到?
前臺(tái)時(shí)。VxD應(yīng)該鎖定任何資源和為虛擬機(jī)重新開(kāi)始準(zhǔn)備內(nèi)部結(jié)構(gòu)。如果?
VxD設(shè)置進(jìn)位標(biāo)志返回,VMM不恢復(fù)執(zhí)行虛擬機(jī)。?
VM_Suspend消息:當(dāng)虛擬機(jī)已經(jīng)被掛起時(shí)VxD收到此消息,例如切換到后?
臺(tái)時(shí)。VxD應(yīng)該解鎖任何與虛擬機(jī)有關(guān)的資源。?
VM_Terminate消息:這是VxD收到的第一條虛擬機(jī)終止消息。VxD可以開(kāi)?
始準(zhǔn)備虛擬機(jī)的終止。Simulate_Int和Exec_Int服務(wù)有效。?
?
八、VxD初始化?
?
VMM初始化一個(gè)VxD時(shí)做下列工作:?
1、裝載實(shí)模式初始化段并調(diào)用實(shí)模式初始化過(guò)程。該過(guò)程可以完成阻止?
裝載VxD,阻止啟動(dòng)Windows,指定設(shè)備實(shí)例數(shù)據(jù)和在內(nèi)存中選擇頁(yè)面給?
設(shè)備專(zhuān)用的工作。?
2、裝載VxD其它段到32位平坦內(nèi)存模式的保護(hù)模式內(nèi)存,并丟棄實(shí)模式?
初始化段。?
3、發(fā)送Sys_Critical_Init消息到設(shè)備控制過(guò)程。禁止硬件中斷,所以VxD?
應(yīng)該盡可能地用較少的時(shí)間完成自身初始化。?
4、發(fā)送Device_Init消息到設(shè)備控制過(guò)程。允許硬件中斷,所以必須準(zhǔn)?
備讓VxD管理來(lái)自設(shè)備的中斷。?
5、發(fā)送Init_Complete消息到設(shè)備控制過(guò)程。?
6、丟棄初始化代碼和數(shù)據(jù)段,釋放其它被使用的內(nèi)存。VxD不能在處理完?
Init_Complete消息以后試圖存取這些段中的過(guò)程和數(shù)據(jù)。?
在初始化過(guò)程中的任何時(shí)刻,VxD都可以設(shè)置進(jìn)位標(biāo)志返回到VMM以阻止?
裝載VxD。部分VMM服務(wù),例如初始化信息服務(wù)只在初始化過(guò)程中有效。?
?
九、實(shí)模式初始化?
?
任何靜態(tài)設(shè)備驅(qū)動(dòng)程序都可以提供實(shí)模式初始化過(guò)程以在Windows切換到?
保護(hù)模式之前執(zhí)行初始化任務(wù)。VMM裝載VxD時(shí)調(diào)用該過(guò)程,該過(guò)程檢查?
有關(guān)的Windows環(huán)境,包括注冊(cè)表和初始化文件中的有關(guān)設(shè)置以判斷是否?
應(yīng)該裝載該VxD。該過(guò)程也可以給Windows返回信息以為每個(gè)虛擬機(jī)的實(shí)?
例指定物理內(nèi)存頁(yè)保留給設(shè)備專(zhuān)用和數(shù)據(jù)項(xiàng)地址。要獲得關(guān)于實(shí)模式初始?
化的更多信息,請(qǐng)參閱相關(guān)資料。?
?
十、VxD服務(wù)?
?
VxD可以提供服務(wù)功能(函數(shù)或過(guò)程——譯者注)給VMM和其它VxD使用。?
這些服務(wù)讓其它VxD可以直接訪問(wèn)該VxD的特征,允許測(cè)試和修改該VxD?
的功能和能力。?
VxD不能和Windows?DLL一樣引出函數(shù),代之的是VMM通過(guò)INT?20H提供?
到VxD服務(wù)的動(dòng)態(tài)鏈接,該中斷處理過(guò)程使用服務(wù)編號(hào)判斷支持服務(wù)的?
VxD,該中斷處理過(guò)程也使用服務(wù)編號(hào)查詢(xún)?cè)赩xD服務(wù)表中的服務(wù)地址。?
下面的內(nèi)容講述怎樣在VxD中定義服務(wù),聲明VxD服務(wù)表以及從一個(gè)VxD?
向另一個(gè)VxD中引入服務(wù)。?
?
1、定義服務(wù)?
?
VxD使用BeginProc和EndProc宏以及Service和Async_Service選項(xiàng)定?
義服務(wù)。宏標(biāo)記服務(wù)過(guò)程代碼的開(kāi)始和結(jié)束,選項(xiàng)標(biāo)識(shí)該過(guò)程是一個(gè)服務(wù)。?
下面的實(shí)例給出了VSAMPLED_Get_Version服務(wù)的定義:?
BeginProc?VSAMPLED_Get_Version,?Service?
?mov?ax,?030Ah?
?clc?
?ret?
EndProc?VSAMPLED_Get_Version?
Async_Service選項(xiàng)標(biāo)識(shí)該服務(wù)可以被異步調(diào)用,也就是說(shuō)在處理中斷的?
過(guò)程中調(diào)用。異步服務(wù)必須是可重入的,而且不能調(diào)用VMM和不是異步服?
務(wù)的VxD服務(wù)。?
VMM和標(biāo)準(zhǔn)VxD對(duì)服務(wù)使用兩種調(diào)用約定:基于寄存器的調(diào)用約定和基于?
32位C語(yǔ)言的調(diào)用約定。這兩種調(diào)用約定有不同的服務(wù)名格式,參數(shù)傳遞?
和返回值方法以及寄存器保護(hù)。?
對(duì)于基于寄存器的服務(wù),服務(wù)名不應(yīng)該以下劃線(_)開(kāi)頭,所有的參數(shù)?
通過(guò)寄存器傳遞,結(jié)果也通過(guò)寄存器返回,服務(wù)保護(hù)所有不顯式用于返回?
值的寄存器。?
對(duì)于基于C語(yǔ)言的服務(wù),服務(wù)名必須以下劃線(_)開(kāi)頭,所有的參數(shù)通?
過(guò)堆棧中的32位值傳遞,結(jié)果(如果存在)通過(guò)EAX寄存器(32位值)?
或者EAX和EDX寄存器(64位值)返回,服務(wù)保護(hù)EBX、ES、FS和GS寄?
存器以及ESI和EDI寄存器,只有標(biāo)志寄存器和EAX、EBX、EDX寄存器被?
修改。?
?
2、聲明服務(wù)?
?
VxD使用Begin_Service_Table和End_Service_Table宏聲明服務(wù)。宏標(biāo)?
記包含服務(wù)名和可選的包含服務(wù)的段名的列表的開(kāi)始和結(jié)束。聲明必須建?
立在進(jìn)行VxD定義的文件中(也就是說(shuō)在包含Declare_Virtual_Device?
宏的文件中),而且必須先進(jìn)行設(shè)備指定符號(hào)的定義。下面的實(shí)例給出了?
一個(gè)實(shí)例VxD——VSAMPLED的服務(wù)表聲明:?
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符號(hào)在緊接服務(wù)表聲明之前定?
義,指定Begin_Service_Table宏為VSAMPLED創(chuàng)建服務(wù)表。聲明開(kāi)始以?
后,VSAMPLED_Service宏定義實(shí)際服務(wù),這個(gè)宏是Begin_Service_Table?
宏創(chuàng)建的,只在服務(wù)表聲明中有效。每個(gè)服務(wù)名必須與服務(wù)定義名,也就?
是BeginProc宏給出的名字完全符合。?
當(dāng)聲明服務(wù)時(shí),如果一個(gè)服務(wù)定義在包含服務(wù)表聲明的文件中,必須在服?
務(wù)名后使用LOCAL選項(xiàng),也就是說(shuō)如果不使用LOCAL選項(xiàng),服務(wù)表自動(dòng)聲?
明一個(gè)服務(wù)是外部服務(wù)。上例中,VSAMPLED_Get_Version服務(wù)定義在包含?
服務(wù)表聲明的文件中。?
與之相似,如果一個(gè)服務(wù)不是定義在VxD_CODE段中,必須在服務(wù)名后注?
明段名。上例中,VSAMPLED_Service_2服務(wù)定義在VxD_ICODE段中。?
服務(wù)聲明的順序是很重要的。VxD中第一個(gè)被聲明的服務(wù)必須是?
Get_Version服務(wù)(該服務(wù)清除進(jìn)位標(biāo)志并在AX寄存器中返回VxD版本?
號(hào)),任何加入VxD的新服務(wù)必須定義在服務(wù)表的末尾(或者定義在服務(wù)?
表中顯式保留的空間中)。由于VMM依靠服務(wù)在服務(wù)表中的順序正確鏈接?
服務(wù),在服務(wù)表中間插入一個(gè)新服務(wù)需要VxD使用的所有VxD服務(wù)被重建。?
為了方便,服務(wù)表聲明應(yīng)該放在一個(gè)包含文件中,使得其它VxD可以通過(guò)?
包含該文件引入服務(wù)而不需要重新聲明。?
?
3、引入服務(wù)?
?
一個(gè)VxD可以通過(guò)包含另一個(gè)VxD的服務(wù)表聲明引入另一個(gè)VxD的服務(wù),?
在這種情況下,設(shè)備指定符號(hào)的定義不能先于該服務(wù)表聲明(參見(jiàn)上一節(jié)?
的講述)。例如:VSAMPLED.INC文件包含VSAMPLED服務(wù)的服務(wù)表聲明,一?
個(gè)包含該文件的VxD可以調(diào)用這些服務(wù)。VxD使用VMMcall宏調(diào)用VMM服?
務(wù),使用VxDcall宏調(diào)用VxD服務(wù)。?
由于計(jì)算機(jī)配置不同,一個(gè)VxD可能會(huì)在Windows啟動(dòng)時(shí)裝載失敗,這說(shuō)?
明使用其它VxD提供的服務(wù)的VxD必須檢驗(yàn)其它VxD服務(wù)在調(diào)用它們之前?
是否有效。為了檢驗(yàn)服務(wù),調(diào)用服務(wù)的VxD必須嘗試調(diào)用提供服務(wù)的VxD?
的Get_Version功能,如果VxD沒(méi)有裝載,VMM會(huì)設(shè)置進(jìn)位標(biāo)志并在AX寄?
存器中返回0。?
?
十一、VxD?API過(guò)程?
?
一個(gè)VxD提供V86模式和保護(hù)模式API過(guò)程以允許在一個(gè)虛擬機(jī)中運(yùn)行的?
應(yīng)用程序和其它軟件訪問(wèn)該VxD的特征。如果要使這些可選的過(guò)程有效,?
VxD必須將它們定義為Declare_Virtual_Device宏的參數(shù),如果沒(méi)有定義,?
VMM認(rèn)為該VxD沒(méi)有API過(guò)程。?
在一個(gè)虛擬機(jī)中運(yùn)行的應(yīng)用程序或者其它軟件通過(guò)設(shè)置BX寄存器為VxD?
標(biāo)識(shí)并調(diào)用獲取設(shè)備入口地址功能(INT?2FH?1684H功能)獲取特定的虛?
擬機(jī)的API過(guò)程的入口地址,VMM返回該地址使得應(yīng)用程序可以間接調(diào)用?
該API過(guò)程。?
當(dāng)一個(gè)應(yīng)用程序調(diào)用該入口地址時(shí),VMM保存該應(yīng)用程序的寄存器并調(diào)用?
VxD相應(yīng)的API過(guò)程,保存當(dāng)前虛擬機(jī)的句柄到BX寄存器中并保存?
Client_Reg_Struc結(jié)構(gòu)地址到EBP寄存器中。API過(guò)程必須檢測(cè)客戶寄存?
器的值(使用Client_Reg_Struc結(jié)構(gòu))以判斷運(yùn)行的API調(diào)用。?
按照常規(guī),大多數(shù)API過(guò)程使用AH寄存器指定主功能號(hào),使用AL寄存器?
指定次功能號(hào),其它客戶寄存器用于附加參數(shù)。API過(guò)程通過(guò)修改客戶寄?
存器返回值,API過(guò)程可以修改EAX、EBX、ECX、EDX、ESI和EDI寄存器。?
下面的實(shí)例給出了一個(gè)實(shí)例API過(guò)程——VSAMPLED_API_Get_Version:?
BeginProc?VSAMPLED_API_Get_Version?
?movzx?eax,?[ebp.Client_AX]?;取功能號(hào)?
?or?eax,?eax?
?jnz?Undefined?
?
Get_Version:?
?mov?[ebp.Client_AX],?030AH?;在客戶寄存器AX中返回值?
?and?[ebp.Client_Flags],?NOT?CF_Mask?;清除進(jìn)位標(biāo)志?
?ret?
?
Undefined:?
?or?[ebp.Client_Flags],?CF_Mask?;設(shè)置進(jìn)位標(biāo)志?
?ret?
EndProc?VSAMPLED_API_Get_Version?
?
十二、VxD?INT?2FH功能?
?
VxD可以通過(guò)為INT?2FH中斷安裝回調(diào)過(guò)程提供INT?2FH功能。INT?2FH?
功能允許在一個(gè)虛擬機(jī)中運(yùn)行的應(yīng)用程序和其它軟件在VxD不提供API過(guò)?
程的情況下訪問(wèn)VxD,例如,標(biāo)準(zhǔn)虛擬顯示設(shè)備支持與Windows顯示驅(qū)動(dòng)?
程序通信的INT?2FH功能集合。?
Windows安裝自己的INT?2FH中斷處理程序支持各種功能,以允許MS-DOS?
設(shè)備驅(qū)動(dòng)程序和TSR在Windows啟動(dòng)或者虛擬機(jī)運(yùn)行過(guò)程中執(zhí)行特定動(dòng)?
作。要獲得有關(guān)這些功能的更多信息,請(qǐng)參閱有關(guān)資料。?
?
十三、建立一個(gè)VxD?
?
應(yīng)該通過(guò)進(jìn)行下列步驟來(lái)建立一個(gè)VxD:?
1、創(chuàng)建VxD源文件并用32位平坦模式匯編器MASM.EXE(MASM?6.11以上?
——譯者注)匯編源文件。?
2、創(chuàng)建模塊定義文件(DEF文件)并用32位平坦模式連接器LINK.EXE連?
接目標(biāo)文件。按照常規(guī),結(jié)果可執(zhí)行文件應(yīng)該有與VxD相同的文件名,文?
件擴(kuò)展名為VXD。?
3、用MAPSYM.EXE為可執(zhí)行文件創(chuàng)建調(diào)試信息。?
VxD并不與Windows動(dòng)態(tài)鏈接庫(kù)兼容,基于Windows的應(yīng)用程序并不能直?
接裝載和使用VxD,然而,基于Win32的應(yīng)用程序可以通過(guò)使用CreateFile?
和DeviceIoControl函數(shù)裝載動(dòng)態(tài)裝載的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語(yǔ)句必須指定一個(gè)與在已知設(shè)備描述塊(DDB)中相同的VxD名字,?
EXPORT語(yǔ)句必須指定一個(gè)DDB的名字,在任何情況下,DDB引出序號(hào)都是1。?
評(píng)論
查看更多