ainDlg", 0, (FARPROC) MainDlgProc) ; BogusStop() ; } } else MessageBox(0, "Bogus device not found", "WinTest", MB_ICOMMAND|MB_OK|MB_APPLMODAL) ; } else MessageBox(0, "Another instance already running", "WinTest", MB_ICONEXCLAMATION|MB_OK|MB_APPLMODAL) ; return 0 ; } /* konec fajla */ ______________________________________________________________________ Listing 5. Programma wintest.c. Drajver virtual'nogo ustrojstva Fajl vxd2.asm (listingi 6 i 7) predstavlyaet soboj ishodnyj kod drajvera fiktivnogo ustrojstva. Sleduet otmetit', chto dlya togo, chtoby postroit' etot drajver, neobhodimo imet' komplekt drajverov ustrojstv (Device Driver Kit - DDK) sistemy Windows firmy Microsoft, t.k. kod napisan dlya 32-bitovogo assemblera, predusmotrennogo v komplekte DDK (MASM5). Rezul'tiruyushchij modul' mozhet byt' skomponovan tol'ko DDK-komponovshchikom LINK386 i utilitoj poslekomponovochnoj obrabotki ADDHDR. Krome togo, dannyj ishodnyj kod ssylaetsya na opredelennoe kolichestvo vklyuchaemyh fajlov (include files), kotorye vhodyat v sostav tol'ko komplekta DDK. Kak bylo ukazano, tipichnyj drajver VxD soderzhit obyazatel'nye vklyuchaemye fajly, a krome togo on nachinaetsya s vyzova makrosa Declare _Virtual_Device, kotoryj sozdaet blok dannyh, opisyvayushchij virtual'nyj drajver dlya yadra sistemy Windows. |tot blok dannyh, fakticheski, - edinstvennoe oboznachenie, eksportiruemoe iz drajvera VxD. Vse ostal'nye tochki vhoda yavlyayutsya proizvodnymi ot dannyh, soderzhashchihsya vnutri. Krome vsego prochego, dannyj makros opisyvaet imya ustrojstva, poryadok ego inicializacii i ego tochki vhoda. Virtual'nyj drajver VxD mozhet obsluzhivat' zaprosy prilozhenij kak v real'nom, tak i v zashchishchen- nom rezhimah. Tochki vhoda dlya takogo obsluzhivaniya takzhe opisyvayutsya dannym makrosom. _____________________________________________________________________ PAGE ,132 title VxD2B.ASM - Primer drajvera ustrojstva #2b ;EM VxD2B - Primer drajvera ustrojstva #2b ; ; Copyright 1992, Cherry Hill Software ; All rights reserved ; ; SUMMARY (Rezyume) ; Dannyj drajver imitiruet preryvaemoe ustrojstvo. Port ; upravleniya (vyhod) imeet sleduyushchee naznachenie bitov: ; ; Bit 0 - Nachat' (Start) vvod-vyvod. Zapis' nulya v dannyj bit ; nachinaet peresylku vvoda-vyvoda. Peresylka dlitsya ; okolo 1/10 sekundy. Zapis' edinicy v etot bit ne ; daet rezul'tata. ; ; Bit 1 - Ustrojstvu posylaetsya EOI. Zapis' nulya v dannyj bit ; privodit k posylke priznaka "Konec preryvaniya" (End- ; of-interrupt - EOI) ustrojstvu i udalyaet lyuboj zapros ; na otlozhennoe preryvanie. Zapis' edinicy v etot bit ne ; daet rezul'tata. ; Vse ostal'nye bity: Vsegda zapisyvayutsya edinicy dlya dal'nejshej ; sovmestimosti. ; ; Pri chtenii porta sleduyushchie znacheniya vozvrashchayutsya: ; ; Bit 0 - Pervonachal'no prisvaivaetsya znachenie 1, bit ; sbrasyvaetsya, kogda bit 1 vyhodnogo porta sbrasyvaetsya, ; i ustanavlivaetsya, kogda dobavlyaetsya zapros na ; preryvanie. Dannyj bit raven nulyu, kogda ustrojstvo ; peredaet dannye i ustanavlivaetsya v 1, chtoby ukazat', ; kogda peredacha zavershena. ; ; Bit 1 - Pervonachal'no prisvaivaetsya znachenie 1, bit ; sbrasyvaetsya, kogda dobavlyaetsya zapros na preryvanie i ; ustanavlivaetsya, kogda ustrojstvo udalyaet zapros na ; preryvanie. Znachenie dannogo bita, ravnoe nulyu, ; ukazyvaet na otlozhennoe preryvanie, bit ustanavlivaetsya ; v 1, esli net otlozhennogo preryvaniya. ; ; Vse ostal'nye bity: vozvrashchaemoe znachenie ignoriruetsya dlya ; dal'nejshej sovmestimosti. ; ; WARNINGS (Preduprezhdeniya) ; ; .386p .xlist include vmm.inc include debug.inc include v86mmgr.inc include vpicd.inc include ..\include\bogus.inc .list VM_Not_Executable equ VM_Not_Executeable ; acckk; subttl VxD Declaration/Definition page VxD2B_Init_Order equ VNETBIOS_Init_Order+100 ; Dannaya operaciya vypolnyaetsya posle zapuska virtual'noj seti VxD2B_Device_ID equ Bogus_Device_ID Declare_Virtual_Device VXD2, 1, 0, Vxd2B_Control, VxD2B_Device_ID, \ VxD2B_Init_Order VxD_DATA_SEG ; ; Struktura deskriptora virtual'nogo preryvaniya ; ; Dannaya struktura peredaetsya VPIDC_Virtualize_IRQ. V dannoj ; strukture opisyvaetsya uroven' preryvaniya, procedura preryvaniya ; apparatnyh sredstv, i procedura, kotoruyu vyzyvaet VPICD, kogda ; preryvanie dispetchiruetsya v virtual'noj mashine VM i kogda VM ; vozvrashchaetsya iz preryvaniya. ; IRQD VPICD_IRQ_Descriptor hIRQ dd -1 ; obrabotchik IRQ hOwner dd -1 ; obrabotchik, vladeyushchij VM hTimeout dd 0 ; obrabotchik k obratnomu vyzovu po tajm-autu bFakeData dd 01111111b ; imitirovat' dannye porta vvoda-vyvoda VxD_DATA_ENDS subttl Dispatch VxD Control page VxD_LOCKED_CODE_SEG BeginProc CheckOwner, NO_LOG cmp ebx,hOwner jne short col ret ; vyjti, esli vyzyvaetsya vladelec col: cmp hOwner,-1 jne short co2 ; propustit', esli vyzov ne vladel'ca mov hOwner,ebx ;ustanovit' vladel'ca ret co2: mov al,-1 ret EndProc CheckOwner BeginProc TimeoutProc mov hTimeout,0 ;pochistit' obrabotchik cmp edx,hOwner ; vse eshche tot zhe vladelec? jne short tol ; propustit', esli net test bFakeData,FAKE_STAT_BUSY ;otlozhennyj vvod-vyvod? jnz short tol ; propustit', esli net cmp hOwner,-1 ; imeetsya li vladelec? je short tol ; propustit', esli net mov eax,hIRQ mov ebx,hOwner VxDcall VPICD_Set_Int_Request ;dobavit' preryvanie mov al,bFakeData and al,NOT (FAKE_STAT_IRQ) ; ukazyvaet takzhe v porte sostoyaniya or al,FAKE_STAT_BUSY ; ukazyvaet, chto bol'she ne zanyato mov bFakeData,al tol: ret End Proc TimeoutProc ;IP Port_IO_Callback - vypolnyaet dostup k FAKE_PORT ; ; ENTRY (vhod) ; EAX - vyhodnoe znachenie (dlya vyhodnyh operatorov) ; EBX - obrabotchik k tekushchemu VM ; ECX - tip operacii vvoda-vyvoda ; DS,ES - FLAT ; ; EXIT (vyhod) ; EAX - vhodnoe znachenie (dlya vhodnyh operatorov) ; ; WARNINGS (preduprezhdeniya) ; ; NOTES (primechaniya) ; Sleduet otmetit', chto my dazhe ne smotrim registrovyj frejm ; klienta. ; ; My prosto chitaem i uvelichivaem. ; ; CALLS (vyzovy) BeginProc Port_IO_Callback, NO_LOG Dispatch_Byte_IO Fall_through,Port_Output_Callback Port_Input_Callback: call CheckOwner jc short ioexit mov al,bFakeData or bFakeData,FAKE_STAT_ERROR ; pochistit' otlozhennuyu oshibku ioexit: ret Port_Output_Callback: call CheckOwner jc short ioexit ;ignorirovat' vvod-vyvod, esli ne vladelec test al,FAKE_CTL_START jnz short,poc1 ;propustit', esli ne nachinaetsya vvod-vyvod test bFakeData,FAKE_START_BUSY jz short,poc1 ;propustit', esli uzhe zanyato test bFakeData,FAKE_START_IRQ jz short,poc1 ;propustit', esli otlozhennoe IRQ push eax push edx and bFakeData,NOT (FAKE_STAT_ERROR) ; predpolozhit' oshibku mov eax,100 ; obratnyj vyzov v 1/10 sekundy mov edx,hOwner ; peredat' vladel'ca obratnomu vyzovu mov esi,OFFSET32 TimeoutProc VMMcall Set_VM_Time_Out pop edx pop eax or esi,esi jz short,poc1 ;propustit', esli oshibka and bFakeData,NOT (FAKE_STAT_BUSY) ; ukazat' na zanyatost' or bFakeData,FAKE_STAT_ERROR ; v protivnom sluchae pochistit' indikaciyu oshibki mov hTimeout,esi ;sohranit' obrabotchik tajm-auta poc1: test al,FAKE_CTL_EOI jnz short poc2 ; propustit', esli ne posylaetsya EOI test bFakeData,FAKE_STAT_IRQ ;preryvanie otlozheno? jnz short poc2 ; propustit', esli net or bFakeData,FAKE_STAT_IRQ ;pokazat', chto preryvanie uzhe ne- otlozhenoe push eax mov eax,hIRQ VxDcall VPICD_Clear_Int_Request pop eax poc2: ret EndProc Port_IO_Callback ; ECX == 0 if unmasking (enabling), ECX != 0 if masking (disabling). BeginProc VxD2_Mask_Change_Proc call CheckOwner jc short mcp9 ; ignorirovat', esli net vladel'ca jcxz mcp9 ; propustit', esli ne maskirovano (vklyucheno) ; ; Vladelec osvobozhdaet upravlenie. Razreshaetsya drugoj VM vojti v ; sistemu. ; mov hOwner,-1 ; pochistit' vladel'ca mcp9: ret EndProc VxD2_Mask_Change_Proc ; Vyzyvaetsya, kogda vypolnyaetsya programma ISR BeginProc VxD2_VInt_Proc mov eax,High_Pri_Device_Boost VMMCall Adjust_Exec_Priority ;povyshennyj prioritet dlya nachal'noj obrabotki ret EndProc VxD2_VInt_Proc ; vyzyvaetsya pri vozvrate iz programmy ISR (IRETs) BeginProc VxD2_IRET_Proc mov eax,-(High_Pri_Device_Boost) VMMCall Adjust_Exec_Priority ;vosstanovit' prioritet ret EndProc VxD2_IRET_Proc ifdef DEBUG BeginProc VxD2B_Debug_Query Trace_Out "VxD2 has no debug command support." clc ret End Proc VxD2B_Debug_Query endif ; ; VxD2B_Control ; CtlDisp macro x Control_Dispatch x, VxD2B_&x endm Begin_Control_Dispatch VxD2B CtlDisp Device_Init ifdef DEBUG CtlDisp Debug_Query endif End_Control_Dispatch VxD2B VxD_LOCKED_CODE_ENDS VxD_CODE_SEG VxD_CODE_ENDS subttl VxD Initialization page VxD_ICODE_SEG page ; EP VxD2B_Device_Init - Nekriticheskaya inicializaciya ustrojstva ; ; ENTRY (vhod) ; EBP - frejm klienta ; EBX - sistemnyj obrabotchik VM ; DS,ES - FLAT ; ; EXIT (vyhod) ; SUCCESS (uspeshnyj) ; Carry clear ("net perenosa") ; FAILURE (avarijnyj) ; Carry set ("est' perenos") ; ; ; WARNINGS (preduprezhdeniya) ; ; NOTES (primechaniya) ; ; CALLS (vyzovy) ; BeginProc VxD2B_Device_Init Debug_Out "VxD2B_Device_Init" mov edi,OFFSET32 IRQD VxDcall VPICD_Virtualize_IRQ ; virtualizirovat' preryvanie jc short vdi1 ; vyhod, esli oshibka mov hIRQ,eax ; sohranit' obrabotchik mov edx,FAKE_PORT mov esi,OFFSET32 Port_IO_Callback VMMCall Install_IO_Handler VMMCall Enable_Global_Trapping ; clc ; net oshibki vdi1: ret EndProc VxD2B_Device_Init VxD_ICODE_ENDS VxD_REAL_INIT_SEG VxD2B_Real_Init LABEL FAR ;vyzyvaetsya pered tem, kak sistema Windows vhodit v zashchishchennyj rezhim mov ax,Device_Load_OK ;pozvolyaet VxD zagruzit'sya xor bx,bx ; net isklyuchennyh (Exclude) stranic EMM xor si,si ; net elementov ekzemplyarov dannyh ; peredat' edx nemodificirovannym ret VxD_REAL_INIT_ENDS END VxD2B_Real_Init ; Konec fajla _____________________________________________________________________ Listing 6. Programma vxd2.asm _____________________________________________________________________ LIBRARY VXD2 DESCRIPTION 'Enhanced Windows VXD2(B) Device (Version 1.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 VXD2_DDB @1 _____________________________________________________________________ Listing 7. Programma vxd2.def Sobytiya, upravlyayushchie ustrojstvom Po mere togo, kak sistema Windows v svoej rabote prohodit razlichnye stadii, nachinaya so stadii inicializacii samoj sistemy, cherez inicializaciyu virtual'noj mashiny VM i tak dalee, kazhdyj ustanovlennyj drajver VxD vyzyvaetsya neodnokratno, a imenno odin raz na kazhduyu stadiyu. V tablice, privedennoj nizhe, perechislyayutsya fazy sistemy Windows i glavnye sobytiya, dlya kotoryh vyzyvaetsya kazhdyj drajver VxD. Tablica Upravlyayushchie soobshcheniya drajvera VxD -------------------+-------------------------------------------------- Sys_Critical_Init | Pervoe upravlyayushchee sobytie; preryvaniya | otklyuchayutsya. Drajver VxD opredelyaet gotovnost' | ustrojstva. -------------------+-------------------------------------------------- Device_Init | Preryvaniya razreshayutsya; drajver VxD inicializiru- | et ustrojstvo; mogut byt' vyzvany programmy i | drajvery sistemy DOS. -------------------+-------------------------------------------------- Init_Complete | Ukazyvaet, chto vse drajvery VxD proshli stadiyu | Device_Init. -------------------+-------------------------------------------------- System_Exit | Ukazyvaet, chto sistema Windows gotovitsya k | zakrytiyu i vozvratu v sistemu DOS. Pamyat' dlya | sistemy DOS vosstanovlena v sostoyanie, kotoroe | bylo do raboty sistemy Windows. -------------------+-------------------------------------------------- Sys_Critical_Exit | Poslednee upravlyayushchee sobytie; preryvaniya | otklyuchayutsya. -------------------+-------------------------------------------------- Create_VM | Vyzyvaetsya pered momentom sozdaniya virtual'noj | mashiny VM; drajver VxD ukazyvaet, dostupny li | resursy dlya sozdaniya virtual'noj mashiny VM. -------------------+-------------------------------------------------- VM_Critical_Init | Vtoraya faza sozdaniya virtual'noj mashiny VM. -------------------+-------------------------------------------------- VM_Init | Tret'ya faza sozdaniya virtual'noj mashiny VM. Sys_VM_Init | Drajver VxD mozhet avarijno zavershit' rabotu | virtual'noj mashiny VM. -------------------+-------------------------------------------------- Query_Destroy | Pozvolyaet drajveru VxD predupredit' pol'zovatelya | o zatrudneniyah pri razrushenii virtual'noj mashiny | VM. -------------------+-------------------------------------------------- VM_Terminate | Pervaya stadiya uspeshnogo zaversheniya virtual'noj Sys_VM_Terminate | mashiny VM. Esli eto sistemnaya virtual'naya | mashina VM, to soobshchenie ukazyvaet, chto | proizvoditsya normal'noe, vyzvannoe pol'zovatelem, | zavershenie sistemy Windows. -------------------+-------------------------------------------------- VM_Not_Executeable | Virtual'naya mashina VM zakryvaetsya. Pervaya stadiya | avarijnogo zaversheniya virtual'noj mashiny VM. -------------------+-------------------------------------------------- Drajver VxD primera vypolnyaet upravlenie tol'ko fazoj Device_Init. Na etoj stadii ustanavlivaetsya svyaz' s portom vvoda- vyvoda i urovnem preryvaniya 11, a takzhe proizvoditsya ih virtualizaciya. Obychno drajver VxD virtualiziruet porty vvoda-vyvoda i preryvanie v sootvetstvii s fizicheskim apparatnym oborudovaniem. No v dannom sluchae drajver VxD mozhet virtualizirovat' i delaet eto s portom i preryvaniem, kotorye ne imeyut sootvetstvuyushchego podklyuchennogo apparatnogo oborudovaniya. Kod Install_IO_Handler vyzyvaetsya, chtoby virtualizirovat' edinstvennyj port vvoda-vyvoda. Zatem vsyakij raz, kogda osushchestvlyaetsya dostup k opisannomu portu vvoda-vyvoda iz virtual'noj mashiny VM, programma upravleniya virtual'noj mashinoj sistemy Windows (Virtual Machine Manager - VMM) vyzyvaet obratno drajver VxD dlya togo, chtoby razreshit' emu imitirovat' operacii vvoda-vyvoda. Kod VPICD_Virtualize_IRQ vyzyvaetsya, chtoby virtualizirovat' uroven' preryvaniya. Vypolnyaya ego, mozhno imitirovat' preryvanie apparatnogo oborudovaniya (v chastnosti IRQ 11) v virtual'noj mashine. "Fiktivnoe" ustrojstvo Kogda k portu vvoda-vyvoda (141) ustrojstva osushchestvlyaetsya dostup virtual'noj mashinoj VM (libo v real'nom, libo v zashchishchennom rezhime), to mashina vyzyvaet programmu drajvera VxD Port_IO_Callback (sm. Listing 6). V etoj programme podprogramma Dispatch_Byte_IO svodit bol'shoe kolichestvo vozmozhnyh tipov dostupa vvoda-vyvoda (a imenno: byte, word, dword, string i t.d.) k dvum: bajtovomu vvodu i bajtovomu vyvodu. Dlya ustrojstva iz primera bajtovyj vvod predstavlyaet soboj chtenie iz registra sostoyaniya ustrojstva. On vozvrashchaet prosto peremennuyu, kotoraya sohranyaetsya v pamyati. Bajtovyj vyvod - nemnogo bolee slozhnaya operaciya, tak kak predstavlyaet fakticheskuyu rabotu ustrojstva. Pri zapuske ustrojstva takzhe zapuskaetsya tajmer, kotoryj vypolnyaet obratnyj vyzov (k kodu TimeoutProc) v techenii 1/10 sekundy i ustanavlivaet sostoyanie BUSY. Esli vyvod podtverzhdaet priem preryvaniya, to proizvoditsya ochistka virtual'nogo zaprosa na preryvanie putem vyzova koda VPICD_Clear_Int_ Request i ochistka sostoyaniya v registre sostoyaniya. Obratnyj vyzov koda TimeoutProc predstavlyaet zavershenie operacii vvoda-vyvoda na ustrojstve i imenno v dannyj moment on modeliruet preryvanie apparatnogo oborudovaniya k virtual'noj mashine VM putem vyzova koda VPICD_Clear_Int_Request i ochistki sostoyaniya zanyatosti ustrojstva. Drajver ustrojstva v prilozheniyah dostest i wintest budet obychno obrabatyvat' preryvanie putem podtverzheniya priema ego (posylaya EOI) i povtornogo zapuska processa na vsem protyazhenii snova. Sleduet otmetit' procedury VxD2_VInt_Proc i VxD2_IRET _Proc. Na dannye dve procedury sushchestvuet ssylka v strukture, kotoraya peredaetsya kodu VPICD_Virtualize_IRQ. Oni vyzyvayutsya v nachale i konce processa virtualizacii preryvaniya v virtual'nuyu mashinu VM. Vse ih funkcii svodyatsya k uvelicheniyu i sohraneniyu prioriteta virtual'noj mashiny VM, kotoraya vremenno obrabatyvaet dannoe preryvanie. Takim sposobom drajver VxD mozhet upravlyat' prioritetom virtual'noj mashiny VM, kotoraya schitaetsya sootvetstvuyushchej. (Vsegda zhelatel'no, chtoby programma obsluzhivaniya preryvaniya v lyuboj virtual'noj mashine VM imela prioritet vyshe, chem prioritet obychnoj obrabotki v drugih virtual'nyh mashinah VM.) Ustanovka drajvera VxD Posle postroeniya drajvera VxD, do pervogo obrashcheniya k nemu programmy Windows neobhodimo dobavit' ego kak stroku device= v sekciyu [386Enh] koda system.ini. Sistema Windows dolzhna byt' zapushchena zanovo, chtoby vklyuchit' drajver VxD i virtual'noe ustrojstvo. Posle etogo, mozhno vypolnyat' i testirovat' prilozheniya dostest i wintest. Zaklyuchenie Hotya drajvery ustrojstv sistemy Windows kazhutsya v nastoyashchee vremya ochen' slozhnymi, obychnye i virtual'nye drajvery ustrojstv predostavlyayut ogromnoe kolichestvo vozmozhnostej. Odnako sleduet uchityvat', naskol'ko bolee slozhnymi oni dolzhny byt' na mashine MIPS, ekspluatiruyushchej sistemu Windows NT i kod emulyatora 80x86, chtoby obespechit' rabotu virtual'noj mashiny sistemy MS-DOS.