home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Media Share 13
/
mediashare_13.zip
/
mediashare_13
/
ZIPPED
/
PROGRAM
/
DDJ9403A.ZIP
/
UC394.ZIP
/
CALLGATE.ASM
< prev
next >
Wrap
Assembly Source File
|
1993-12-21
|
16KB
|
465 lines
;************************************************************************
;RINGO -- Installable VxD
;CGATE.ASM -- 32-bit ring 0 code
;by Alex Shmidt, November 1993
;************************************************************************
.386p
.xlist
include vmm.inc
include ringo.inc
include 386.inc
.list
public RingoInit,SeeYouAtRing0,MakeSureOurSegIsInMemory
_GATESEG segment dword use32 public 'CODE'
assume cs:_GATESEG,gs:_DATA
RingoInit proc far
BuildGateStackFrame _DATA
cmp [ebp].GateSvc,EXITRINGOCALL
jnz short @f
call RingoExit ; deallocate everything we've got
jmp short init_ret
@@:
call RelocateRingo ; run-time relocation and fixups
jc short init_ret
call DynalinkTrick ; get the VxD chain root
call InsertRingoDDB ; welcome to the VxD club
call CreateRingoGDTGate ; GDT call gate to SeeYouAtRing0
init_ret:
mov edx, eax ; prepare return values for the ring 3
shr edx, 16
ClearGateStackFrame <size CG_Params> ; clear both ring stack frames
RingoInit endp
RingoExit proc
call RemoveRingoDDB ; see you later, gentlemen
call DestroyGDTCallGate ; free the GDT call descriptor
VMMCall _PageFree,<gs:[pghandle],0> ; free locked pages
mov ax,gs:[gdt_datasel]
movzx eax,ax
VMMCall _Free_GDT_Selector,<eax,0> ; free data alias
ret
RingoExit endp
RelocateRingo proc
VMMCall Get_Cur_VM_Handle
movzx esi,word ptr [ebp].GateDw + 2 ; source selector
VMMCall _GetDescriptor,<esi,ebx,0>
; find selector's limit
mov ecx,edx
and edx,000f0000h ; limit 16-19
and eax,0ffffh ; limit 0-15
or eax,edx
test ecx, (D_GRAN_PAGE shl 16) ; byte or page granular ?
jz @f
shl eax, 12
or eax, P_SIZE - 1
@@:
mov edi,eax ; real limit
add eax, P_SIZE - 1
shr eax, 12 ; number of pages needed
; allocate pagelocked memory above 2 Gbyte and move us there
VMMCall _PageAllocate,<eax,PG_SYS,0,0,0,0,0,PageFixed+PageZeroInit>
mov ecx,eax
or ecx,edx
jnz short @f
stc
ret
@@:
mov gs:[pghandle],eax
VMMCall _SelectorMapFlat,<ebx,esi,0>
mov esi,eax ; source
mov ecx,edi ; limit in bytes
mov eax,edi
mov edi,edx ; destination
add ecx,3 ; convert to DWords for speed
shr ecx,2
cld
rep movsd ; done
push edx
;get our data selector, mapping this code seg
VMMCall _BuildDescriptorDWords,<edx,eax,RW_Data_Type,D_GRAN_BYTE,0>
VMMCall _Allocate_GDT_Selector,<edx,eax,0>
pop edx
mov ecx,offset RUNGOGDTDATASEL
add ecx,edx ; first fixup
mov [ecx],ax
mov gs:[gdt_datasel],ax
mov gs,ax
assume gs:_GATESEG
mov gs:[ringo_flat],edx
;fixups
xor ecx,ecx
init_loop:
add gs:[Gate_Service_Table][ecx*4],edx
inc ecx
cmp ecx,LASTSVC
jbe short init_loop
add gs:[OurDynalinkHandler],edx
add gs:[Ringo_DDB].DDB_Control_Proc,edx
clc
ret
RelocateRingo endp
CreateRingoGDTGate proc
movzx edx, word ptr [ebp].GateDw ; offset16
add edx,gs:[ringo_flat] ; fixup
mov ax, cs ; VMM code selector
mov cx, [ebp].GateW ; parameter count
and cx, CALLGATE_DDCOUNT_MASK ; make sure it's a reasonable number
or cx, GATE32_RING3 ; call gate type
call BuildCallGateDWords
; the undocumented flag 20000000h lets us create system descriptors
VMMCall _Allocate_GDT_Selector,<edx,eax,20000000h>
ror eax,16
ret
CreateRingoGDTGate endp
GetRingoGdtDataSel proc ; find where our data selector is
call getdataselector
RUNGOGDTDATASEL label near
dw 0
GetRingoGdtDataSel endp
getdataselector proc ; stack games
xchg eax,[esp]
mov gs,[eax] ; here we are
xchg eax,[esp]
add esp,4
ret
getdataselector endp
SeeYouAtRing0 proc far ; The callgate service proc
BuildGateStackFrame
VMMCall Get_Cur_VM_Handle ; always helpful
; service dispatcher
movzx eax, [ebp].GateSvc
cmp eax,LASTSVC
ja return_from_ringo
call gs:Gate_Service_Table[eax*4]
return_from_ringo:
mov edx, eax
shr edx, 16
ClearGateStackFrame <size CG_Params>
SeeYouAtRing0 endp
BeginProc DestroyGDTCallGate,public
movzx eax,[ebp].GateW
VMMCall _Free_GDT_Selector,<eax,0>
ret
EndProc DestroyGDTCallGate
; on Entry: ax=Gate Selector, edx=Gate Offset, cx=gate type | Dword Count
; returns: edx = hi desc dword, eax = lo dess dword
BuildCallGateDWords proc
movzx eax, ax
shl eax, 16
mov ax, dx
mov dx, cx
ret
BuildCallGateDWords endp
;****************************************************************************
; To get the VxD Base (VMM DDB ptr) we're using undocumented fact that
; VMM's dynalink handler (considered a 'fault' 20h in DDK spec parlance)
; returns it in ecx. The idea is to hook VMM fault 20h, call any VMM service
; to get our fault handler receive control, call VMM's dynalink directly
; store ecx in a static variable, and hook fault 20h again, this time
; with fault handlers reversed.
;****************************************************************************
BeginProc DynalinkTrick
mov esi, gs:[OurDynalinkHandler]
set_dyna:
mov eax, 20h
VMMCall Hook_VMM_Fault ; install our handler
mov gs:[OLD_DYNALINK_HANDLER], esi
;need to call it once to have our dynalink hook get control
VMMCall Get_VMM_Version
cmp esi, gs:[OurDynalinkHandler]
jnz set_dyna
mov eax, gs:[VXD_FIRST]
ret
EndProc DynalinkTrick
Ringo_Dynalink_Handler proc
call gs:[OLD_DYNALINK_HANDLER]
mov gs:[VXD_FIRST], ecx
ret
Ringo_Dynalink_Handler endp
; this awfully long procedure gets everything GATEVIEW needs
Get386 proc
movzx eax,word ptr [ebp].GateDw + 2
VMMCall _SelectorMapFlat,<ebx,eax,0>
movzx esi, word ptr [ebp].GateDw
add esi,eax
; get control register and page directory linear adds
mov eax,cr0
mov cr0,eax
mov [esi].SysCr.CR0R, eax
mov eax,cr2
mov cr2,eax
mov [esi].SysCr.CR2R, eax
mov eax,cr3
mov cr3,eax
mov [esi].SysCr.CR3R, eax
mov ecx, P_SIZE
VMMCall _MapPhysToLinear,<eax,ecx,0>
mov [esi].SysCr.PDIRL,eax
; get debug registers
mov eax, dr0
mov dr0,eax
mov [esi].SysDr.DR0R, eax
mov eax, dr1
mov dr1,eax
mov [esi].SysDr.DR1R, eax
mov eax, dr2
mov dr2,eax
mov [esi].SysDr.DR2R, eax
mov eax, dr3
mov dr3,eax
mov [esi].SysDr.DR3R, eax
mov eax, dr6
mov dr6,eax
mov [esi].SysDr.DR6R, eax
mov eax, dr7
mov dr7,eax
mov [esi].SysDr.DR7R, EAX
; get GDT
sgdt fword ptr [esi].SysGdt.GDTRL
; get LDT
sldt [esi].SysLdt.LDTRS ; LDT selector
movzx eax, [esi].SysLdt.LDTRS
lar eax, eax
mov [esi].SysLdt.LDTSR, eax ; access rights
movzx eax, [esi].SysLdt.LDTRS
lsl ax, ax
mov [esi].SysLdt.LDTSL, ax ; limit
movzx eax, [esi].SysLdt.LDTRS
VMMCall _SelectorMapFlat,<ebx,eax,0>
mov [esi].SysLdt.LDTB, eax ; base
;get IDT
sidt fword ptr [esi].SysIdt.IDTRL
;get TSS
str ax
mov [esi].SysTss.TREG, ax ; Task Register
movzx eax, ax
lar eax, eax
mov [esi].SysTss.TSSR, eax ; access rights
mov ax, [esi].SysTss.TREG
lsl ax, ax
mov [esi].SysTss.TSSL, ax ; limit
movzx eax, [esi].SysTss.TREG
VMMCall _SelectorMapFlat,<ebx,eax,0>
mov [esi].SysTss.TSSB, eax ; base
; get vxd root
mov eax,gs:[VXD_FIRST]
mov [esi].VxDRoot,eax
; VMM revision
VMMCall Get_VMM_Version
mov [esi].VMMRev,ecx
mov [esi].VMMVer,ax
; get # of running VMs
xor eax,eax
getvm_loop:
cmp ax,[esi].VMCount
jae short @f
mov [esi+eax*4].VMHndl,ebx
inc eax
VMMCall Get_Next_VM_Handle
VMMCall Test_Cur_VM_Handle
jnz short getvm_loop
@@:
mov [esi].VMCount,ax
ret
Get386 endp
; find physical to linear address mapping
PhysToLin proc
movzx ecx, [ebp].GateW
VMMcall _MapPhysToLinear,<[ebp].GateDw,ecx,0>
ret
PhysToLin endp
InsertRingoDDB proc
movoffs eax,Ringo_DDB
mov esi,gs:[VXD_FIRST]
push [esi].DDB_Next
pop [eax].DDB_Next
mov [esi].DDB_Next,eax
ret
InsertRingoDDB endp
RemoveRingoDDB proc
push gs
assume gs:_DATA
mov gs,gs:[gdt_datasel]
assume gs:_GATESEG
mov esi,gs:[VXD_FIRST]
push gs:[Ringo_DDB].DDB_Next
pop [esi].DDB_Next
pop gs
ret
RemoveRingoDDB endp
; this is our Control Procedure -- every VMM message parks here
; we translate the message into the structure GATEVIEW can interpret
; then we schedule Sys VM event. In there we call PostMessage function
; in the nested execution frame and post WM_USER + WM_RINGO message
RingoControlProc proc
push gs
call GetRingoGdtDataSel
cmp gs:[HWND],0
jz short @f
pushad
; build WM_RINGO message out of System_Control message
mov ecx, gs:[msgwrite]
mov gs:[ecx][msgqueue].MSG_Msg,eax
mov gs:[ecx][msgqueue].MSG_VM,ebx
mov gs:[ecx][msgqueue].MSG_PARAM1,edx
mov gs:[ecx][msgqueue].MSG_PARAM2,edi
mov gs:[ecx][msgqueue].MSG_PARAM3,esi
mov edx,ecx
add ecx, type MSGSTRUC
cmp ecx, size msgqueue
jb short no_wrap
xor ecx,ecx
no_wrap:
mov gs:[msgwrite],ecx
VMMcall Get_Sys_VM_Handle
movoffs esi,MessageEvent
VMMcall Schedule_VM_Event ; schedule our MessageEvent callback
popad
@@:
; see if we need to refuse creating VM
cmp eax,gs:[vmstop]
pop gs
jnz short @f
stc
ret
@@:
clc
ret
RingoControlProc endp
; registers the client's window handle and builds the message queue for him
RegisterHWND proc
mov ax,[ebp].GateW
mov gs:[HWND],ax
mov eax,[ebp].GateDw ; PostMessage pointer
mov gs:[CALLBACKOFFSEG],eax
movoffs edx,msgqueue
mov eax,(type MSGSTRUC * 8)- 1
VMMCall _BuildDescriptorDWords,<edx,eax,RW_Data_Type,D_GRAN_BYTE,0>
VMMCall _Allocate_LDT_Selector,<ebx,edx,eax,1,0>
mov gs:[msgsel],ax
ret
RegisterHWND endp
UnregisterHWND proc
movzx eax,gs:[msgsel]
or eax,eax
jz short @f
VMMCall _Free_LDT_Selector,<ebx,eax,0>
@@:
xor eax,eax
mov gs:[msgsel],ax
mov gs:[HWND],ax
mov gs:[CALLBACKOFFSEG], eax
ret
UnregisterHWND endp
; call PostMessage in the nest_exec block
MessageEvent proc
Push_Client_State
VMMcall Begin_Nest_Exec ; enter PM mode
push gs
call GetRingoGdtDataSel
; simulate PostMessage (hwnd, WM_USER + WM_RINGO, System_Control, lpMsgQueue)
movzx eax,gs:[HWND]
VMMCall Simulate_Push
mov eax, WM_USER + WM_RINGO
VMMCall Simulate_Push
mov eax,gs:[edx][msgqueue].MSG_MSG
VMMCall Simulate_Push
movzx eax,gs:[msgsel]
VMMCall Simulate_Push
mov eax,edx
VMMCall Simulate_Push
mov cx,word ptr gs:[CALLBACKOFFSEG] + 2
movzx edx,word ptr gs:[CALLBACKOFFSEG]
VMMcall Simulate_Far_Call
pop gs
VMMcall Resume_Exec
VMMcall End_Nest_Exec
Pop_Client_State
ret
MessageEvent endp
StopVM proc
VMMCall Get_Next_VM_Handle
VMMCall Test_Cur_VM_Handle
jz @f
xor [ebx].CB_VM_Status, VMStat_Background
jmp StopVM
@@:
movzx eax,[ebp].GateW
mov gs:[vmstop],eax
ret
StopVM endp
; this will swap us in if needed
MakeSureOurSegIsInMemory proc far
ret
MakeSureOurSegIsInMemory endp
; by the time WEP gets called, our original _GATESEG could have moved
; this will remap the call gate descriptor for the first call gate
RemapCallGate proc
movzx eax,word ptr [ebp].GateDw + 2
VMMCall _SelectorMapFlat,<ebx,eax,0>
movzx esi,word ptr [ebp].GateDw
add esi,eax ; we are here now
movzx edi,[ebp].GateW
VMMCall _GetDescriptor,<edi,ebx,0> ; old gate descriptor
; modify the offset field in the call gate descriptor
mov ax,si ; lower 16 bits
and esi,CGATE_OFFSET_16_31_MASK
and edx,(CGATE_ACCESS_RIGHTS_MASK + CGATE_DWORD_COUNT_MASK)
or edx,esi ; upper 16 bits
VMMCall _SetDescriptor,<edi,ebx,edx,eax,20000000h>
ret
RemapCallGate endp
ringo_flat dd 0 ; run-time space base
OLD_DYNALINK_HANDLER dd 0
VXD_FIRST dd 0 ; VxD chain root
OurDynalinkHandler dd offset Ringo_Dynalink_Handler
msgqueue db (type MSGSTRUC * 8) dup (0)
msgwrite dd 0
msgsel dw 0
HWND dw 0
CALLBACKOFFSEG dd 0
vmstop dd 0
Ringo_DDB VxD_Desc_Block <,,,1,0,,'Ringo ',,offset RingoControlProc,,,,,,,>
Gate_Service_Table label dword
.erre Get386_Svc*4 eq $-Gate_Service_Table
dd offset Get386
.erre PhysToLin_Svc*4 eq $-Gate_Service_Table
dd offset PhysToLin
.erre Register_Hwnd_Svc*4 eq $-Gate_Service_Table
dd offset RegisterHWND
.erre Unregister_Hwnd_Svc*4 eq $-Gate_Service_Table
dd offset UnregisterHWND
.erre StopVM_Svc*4 eq $-Gate_Service_Table
dd offset StopVM
.erre RemapGate_Svc*4 eq $-Gate_Service_Table
dd offset RemapCallGate
_GATESEG ends
_DATA segment word use16 public 'DATA'
public pghandle
pghandle dd 0
gdt_datasel dw 0
_DATA ends
end