				Jak uruchomic,zamknac VxDka ?
				     Writeln by [CoxoC]


Oto przykladowy kod programu ,ktory uruchamia VxDka :

;====================================================================
; VxDloader
;====================================================================

      .386p
      locals
      jumps
      .model flat,STDCALL

      extrn MessageBoxA        :Proc
      extrn ExitProcess        :Proc
      extrn CloseHandle        :Proc
      extrn CreateFileA        :Proc

      .data   

      VXDHandle       dd     0
      FileHandle      dd     0
      TitleMsg        db     'VxDLoadeR',0
      Ready           db     'Wszystko OK - VxD jest uruchomiony',13,10
                      db     'Aby zamknac VxDka wystarczy wcisnac OK.',0
      VXD             db     '\\.\PIERWSZY.VXD',0
      ProblemLoad     db     'Blad : nie moge wgrac PIERWSZY.VXD !',0

      .code
      
Start:
      push    0
      push    4000000h
      push    3
      push    0
      push    3
      push    0C0000000h
      push    offset VXD
      call    CreateFileA
      cmp     eax, -1
      jz      ProblemLoading
      mov     VXDHandle ,eax
      push    0
      push    offset TitleMsg
      push    offset Ready
      push    0
      call    MessageBoxA   
      push    [VXDHandle]
      call    CloseHandle
      jmp      Exit

ProblemLoading:
      push    0
      push    offset TitleMsg
      push    offset ProblemLoad
      push    0
      call    MessageBoxA   
Exit:
      push    0h
      call    ExitProcess
      End     Start

;====================================================================

Caly sekret tkwi w funkcji CreateFileA , ktora to wgrywa VxDka no i oczywiscie 
w funkcji CloseHandle.

Piszac mojego pierwszego VxDka zatknalem sie na problem jak z poziomu Virtual Device zamknac 
siebie samego lub innego VxDka ? Po paru godzinnym poszukiwaniu znalazlem serwis 
VXDLDR_UnloadDevice ,ktory wlasnie ten problem rozwiazuje , oto przykladowa procedurka 
wykorzystujaca ta funkcje :

nazwa	db 'PIERWSZY',0

		push	ebx
		push	esi
		push	edi
		mov	ebx,UNDEFINED_DEVICE_ID
		mov	edx,offset32 nazwa
		VxDcall	VXDLDR_UnloadDevice
		pop	edi
		pop	esi
		pop	ebx
	
A oto jej opis :

DWORD VXDLDR_UnloadDevice(WORD deviceID, PCHAR szDevname);

usuwa VxDka z pamieci

Parametr	Opis

deviceID	Identyfikator urzadzenia ,ktore ma zostac zdeaktywowane.
szDevname	Jezeli deviceID jest -1, wtedy szDevname zawiera lancuch 
		zakonczony 0 z nazwa VxDka ktory ma zostac zamkniety 

Zwraca 0 jezeli wszystko OK, w innym przypadku zwraca kod Bledu . A oto lista Bledow :

VXDLDR_ERR_BAD_DEVICE_FILE	Specified VxD file is not usable.
VXDLDR_ERR_DEVICE_REFUSED	Specified device operation not allowed.
VXDLDR_ERR_DUPLICATE_DEVICE	Specified operation has already occurred for the given device.
VXDLDR_ERR_FILE_OPEN_ERROR	Unable to open specified file.
VXDLDR_ERR_FILE_READ		Unable to read specified file.
VXDLDR_ERR_IN_DOS		System error.
VXDLDR_ERR_NO_SUCH_DEVICE	Specified device not found.
VXDLDR_ERR_OUT_OF_MEMORY	Out of memory.


OK...ale jak z VxDka uruchomic innego VxDka ?

Moje poszukiwania rozpoczalem od disassembleracji wszystkich VxDkow z windowsa.I szukajac
wywolania VXDLDR_LoadDevice natknalem sie na taka oto procedure (z WSOCK.VXD) oto ona :

sub_C0003259	proc near

arg_0		= dword	ptr  8

		push	ebp
		mov	ebp, esp
		push	esi
		push	edi
		push	ebx
		mov	edx, [ebp+arg_0]
		mov	eax, 1
		VxDcall	VXDLDR_LoadDevice
		sbb	eax, eax
		pop	ebx
		pop	edi
		pop	esi
		pop	ebp
		retn	
sub_C0003259	endp

a oto opis serwisu VXDLDR_LoadDevice :

DWORD VXDLDR_LoadDevice(PCHAR szDeviceName, DWORD dwFlags, PDEVICEINFO * pHandle, PDDB * ppDDB);

Wgrywa VxDka do pamieci

szDeviceName : wskazuje adres stringu zakonczonego zerem z nazwa VxDka 

dwFlags      : jezeli parametrem tym jest wartosc VXDLDR_INIT_DEVICE wtedy VxDek jest inicjowany
               przez system.Jesli nie tak jest to wartosc ta powinna byc zerem i VxDek z ktorego
               chcemy uruchomic innego VxDka powinien sam zainicjowac urzadzenie i wyslac do niego
               komunikat SYS_DYNAMIC_DEVICE_INIT

pHandle      : wskazuje adres w pamieci => uchwyt urzadzenia dla DDB

ppDDB        : wskazuje adres w pamieci => Device Descriptor Block

Zwraca 0 jezeli wszystko OK, w innym przypadku zwraca kod Bledu (lista bledow patrz wyzej)


..... wiec juz wiemy prawie wszystko ... dwFlags podajemy w EAX i VXDLDR_INIT_DEVICE=1 ...
... EDX to wskaznik do stringu z nazwa ... ok ale co to sa pHandle i ppDDB ? ... hmm wlaczylem
SoftICE i znow prawie wszystko sie wyjasnilo ... po powrocie z call VXDLDR_LoadDevice
zmieniaja sie dwa rejestry EAX i EDX.Juz wiemy ze gdy Carry Flag jest ustawiony (patrz 
instrukcja SBB ) wtedy w EAX znajduje sie kod bledu ale jesli Carry Flag=0 wtedy w EAX i w EDX
znajduja sie pHandle i ppDDB .Jeszcze nie wiemy ktory w ktorym :PP .... aby sie dowiedziec 
siegnalem do "SoftICE Command Reference.pdf" odszukalem komende VXD i zauwazylem ze w jedna 
z informacji zwracanych przez SICE jest address of the VxD Descriptor Block. wiec bpxior i mamy
odpowiedz :) .... EAX=ppDDB wiec EDX=pHandle.

Z przytoczonej wyzej procedurki wynika,ze tak naprawde to informacje pHandle i ppDDB nie sa 
dla nas az takie istotne (...narazie) i mozna je zaniedbac .
Reasumujac :

nazwavxd	db 'PIERWSZY.VXD',0

		push	ebx
		push	esi
		push	edi
		mov	eax,VXDLDR_INIT_DEVICE
		mov	edx,offset32 nazwavxd
		VxDcall	VXDLDR_LoadDevice
		sbb	eax, eax
		pop	edi
		pop	esi
		pop	ebx

jezeli eax=0 to wszystko OK
jezeli eax=-1 to blad .Jesli chce sie znac kod bledu to mozna przed instrukcja
		sbb	eax, eax
                ... wpisac
            mov   edx,eax 
            wtedy w edx bedzie kod bledu .... ale nie wiem po co wam to tlumacze
                                              skoro to wynika samo z siebie :PP


        