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 >
Assembly Source File  |  1993-12-21  |  16KB  |  465 lines

  1. ;************************************************************************
  2. ;RINGO -- Installable VxD
  3. ;CGATE.ASM -- 32-bit ring 0 code
  4. ;by Alex Shmidt, November 1993
  5. ;************************************************************************
  6. .386p
  7. .xlist
  8.         include vmm.inc
  9.         include ringo.inc
  10.         include 386.inc
  11. .list
  12. public  RingoInit,SeeYouAtRing0,MakeSureOurSegIsInMemory
  13. _GATESEG segment dword use32 public 'CODE'
  14.         assume  cs:_GATESEG,gs:_DATA
  15. RingoInit       proc    far
  16.         BuildGateStackFrame _DATA
  17.         cmp     [ebp].GateSvc,EXITRINGOCALL
  18.         jnz     short @f
  19.         call    RingoExit               ; deallocate everything we've got
  20.         jmp     short init_ret
  21. @@:
  22.         call    RelocateRingo           ; run-time relocation and fixups
  23.         jc      short init_ret
  24.         call    DynalinkTrick           ; get the VxD chain root
  25.         call    InsertRingoDDB          ; welcome to the VxD club
  26.         call    CreateRingoGDTGate      ; GDT call gate to SeeYouAtRing0
  27. init_ret:
  28.         mov     edx, eax                ; prepare return values for the ring 3
  29.         shr     edx, 16
  30.         ClearGateStackFrame <size CG_Params>    ; clear both ring stack frames
  31. RingoInit       endp
  32.  
  33. RingoExit       proc
  34.         call    RemoveRingoDDB          ; see you later, gentlemen
  35.         call    DestroyGDTCallGate      ; free the GDT call descriptor
  36.         VMMCall _PageFree,<gs:[pghandle],0>     ; free locked pages
  37.         mov     ax,gs:[gdt_datasel]
  38.         movzx   eax,ax
  39.         VMMCall _Free_GDT_Selector,<eax,0>      ; free data alias
  40.         ret
  41. RingoExit       endp
  42.  
  43. RelocateRingo   proc
  44.         VMMCall Get_Cur_VM_Handle
  45.         movzx   esi,word ptr [ebp].GateDw + 2         ; source selector
  46.         VMMCall _GetDescriptor,<esi,ebx,0>
  47. ; find selector's limit
  48.         mov     ecx,edx
  49.         and     edx,000f0000h                   ; limit 16-19
  50.         and     eax,0ffffh                      ; limit 0-15
  51.         or      eax,edx
  52.         test    ecx, (D_GRAN_PAGE shl 16)       ; byte or page granular ?
  53.         jz      @f
  54.         shl     eax, 12
  55.         or      eax, P_SIZE - 1
  56. @@:
  57.         mov     edi,eax                         ; real limit
  58.         add     eax, P_SIZE - 1
  59.         shr     eax, 12                         ; number of pages needed
  60. ; allocate pagelocked memory above 2 Gbyte and move us there
  61.         VMMCall _PageAllocate,<eax,PG_SYS,0,0,0,0,0,PageFixed+PageZeroInit>
  62.         mov     ecx,eax
  63.         or      ecx,edx
  64.         jnz     short @f
  65.         stc
  66.         ret
  67. @@:
  68.         mov     gs:[pghandle],eax
  69.         VMMCall _SelectorMapFlat,<ebx,esi,0>
  70.         mov     esi,eax                         ; source
  71.         mov     ecx,edi                         ; limit in bytes
  72.         mov     eax,edi
  73.         mov     edi,edx                         ; destination
  74.         add     ecx,3                           ; convert to DWords for speed
  75.         shr     ecx,2
  76.         cld
  77.         rep     movsd                           ; done
  78.         push    edx
  79. ;get our data selector, mapping this code seg
  80.         VMMCall _BuildDescriptorDWords,<edx,eax,RW_Data_Type,D_GRAN_BYTE,0>
  81.         VMMCall _Allocate_GDT_Selector,<edx,eax,0>
  82.         pop     edx
  83.         mov     ecx,offset RUNGOGDTDATASEL
  84.         add     ecx,edx                         ; first fixup
  85.         mov     [ecx],ax
  86.         mov     gs:[gdt_datasel],ax
  87.         mov     gs,ax
  88.         assume  gs:_GATESEG
  89.         mov     gs:[ringo_flat],edx
  90. ;fixups
  91.         xor     ecx,ecx
  92. init_loop:
  93.         add     gs:[Gate_Service_Table][ecx*4],edx
  94.         inc     ecx
  95.         cmp     ecx,LASTSVC
  96.         jbe     short init_loop
  97.         add     gs:[OurDynalinkHandler],edx
  98.         add     gs:[Ringo_DDB].DDB_Control_Proc,edx
  99.         clc
  100.         ret
  101. RelocateRingo   endp
  102.  
  103. CreateRingoGDTGate      proc
  104.         movzx   edx, word ptr [ebp].GateDw              ; offset16
  105.         add     edx,gs:[ringo_flat]                     ; fixup
  106.         mov     ax, cs                                  ; VMM code selector
  107.         mov     cx, [ebp].GateW                         ; parameter count
  108.         and     cx, CALLGATE_DDCOUNT_MASK ; make sure it's a reasonable number
  109.         or      cx, GATE32_RING3                        ; call gate type
  110.         call    BuildCallGateDWords
  111. ; the undocumented flag 20000000h lets us create system descriptors
  112.         VMMCall _Allocate_GDT_Selector,<edx,eax,20000000h>
  113.         ror     eax,16
  114.         ret
  115. CreateRingoGDTGate      endp
  116.  
  117. GetRingoGdtDataSel      proc            ; find where our data selector is
  118.         call    getdataselector
  119. RUNGOGDTDATASEL label   near
  120.         dw      0
  121. GetRingoGdtDataSel      endp
  122. getdataselector proc                    ; stack games
  123.         xchg    eax,[esp]
  124.         mov     gs,[eax]                ; here we are
  125.         xchg    eax,[esp]
  126.         add     esp,4
  127.         ret
  128. getdataselector endp
  129.  
  130. SeeYouAtRing0   proc     far            ; The callgate service proc
  131.         BuildGateStackFrame
  132.         VMMCall Get_Cur_VM_Handle       ; always helpful
  133. ; service dispatcher
  134.         movzx   eax, [ebp].GateSvc
  135.         cmp     eax,LASTSVC
  136.         ja      return_from_ringo
  137.         call    gs:Gate_Service_Table[eax*4]
  138. return_from_ringo:
  139.         mov     edx, eax
  140.         shr     edx, 16
  141.         ClearGateStackFrame <size CG_Params>
  142. SeeYouAtRing0   endp
  143.  
  144. BeginProc       DestroyGDTCallGate,public
  145.         movzx   eax,[ebp].GateW
  146.         VMMCall _Free_GDT_Selector,<eax,0>
  147.         ret
  148. EndProc         DestroyGDTCallGate
  149.  
  150. ; on Entry: ax=Gate Selector, edx=Gate Offset, cx=gate type | Dword Count
  151. ; returns:  edx = hi desc dword, eax = lo dess dword
  152. BuildCallGateDWords     proc
  153.         movzx   eax, ax
  154.         shl     eax, 16
  155.         mov     ax, dx
  156.         mov     dx, cx
  157.         ret
  158. BuildCallGateDWords     endp
  159.  
  160. ;****************************************************************************
  161. ; To get the VxD Base (VMM DDB ptr) we're using undocumented fact that
  162. ; VMM's dynalink handler (considered a 'fault' 20h in DDK spec parlance)
  163. ; returns it in ecx. The idea is to hook VMM fault 20h, call any VMM service
  164. ; to get our fault handler receive control, call VMM's dynalink directly
  165. ; store ecx in a static variable, and hook fault 20h again, this time
  166. ; with fault handlers reversed.
  167. ;****************************************************************************
  168. BeginProc       DynalinkTrick
  169.         mov     esi, gs:[OurDynalinkHandler]
  170. set_dyna:
  171.         mov     eax, 20h
  172.         VMMCall Hook_VMM_Fault                  ; install our handler
  173.         mov     gs:[OLD_DYNALINK_HANDLER], esi
  174. ;need to call it once to have our dynalink hook get control
  175.         VMMCall Get_VMM_Version
  176.         cmp     esi, gs:[OurDynalinkHandler]
  177.         jnz     set_dyna
  178.         mov     eax, gs:[VXD_FIRST]
  179.         ret
  180. EndProc         DynalinkTrick
  181.  
  182. Ringo_Dynalink_Handler  proc
  183.         call    gs:[OLD_DYNALINK_HANDLER]
  184.         mov     gs:[VXD_FIRST], ecx
  185.         ret
  186. Ringo_Dynalink_Handler  endp
  187.  
  188. ; this awfully long procedure gets everything GATEVIEW needs
  189. Get386  proc
  190.         movzx   eax,word ptr [ebp].GateDw + 2
  191.         VMMCall _SelectorMapFlat,<ebx,eax,0>
  192.         movzx   esi, word ptr [ebp].GateDw
  193.         add     esi,eax
  194. ; get control register and page directory linear adds
  195.         mov     eax,cr0
  196.         mov     cr0,eax
  197.         mov     [esi].SysCr.CR0R, eax
  198.         mov     eax,cr2
  199.         mov     cr2,eax
  200.         mov     [esi].SysCr.CR2R, eax
  201.         mov     eax,cr3
  202.         mov     cr3,eax
  203.         mov     [esi].SysCr.CR3R, eax
  204.         mov     ecx, P_SIZE
  205.         VMMCall _MapPhysToLinear,<eax,ecx,0>
  206.         mov     [esi].SysCr.PDIRL,eax
  207. ; get debug registers
  208.         mov     eax, dr0
  209.         mov     dr0,eax
  210.         mov     [esi].SysDr.DR0R, eax
  211.         mov     eax, dr1
  212.         mov     dr1,eax
  213.         mov     [esi].SysDr.DR1R, eax
  214.         mov     eax, dr2
  215.         mov     dr2,eax
  216.         mov     [esi].SysDr.DR2R, eax
  217.         mov     eax, dr3
  218.         mov     dr3,eax
  219.         mov     [esi].SysDr.DR3R, eax
  220.         mov     eax, dr6
  221.         mov     dr6,eax
  222.         mov     [esi].SysDr.DR6R, eax
  223.         mov     eax, dr7
  224.         mov     dr7,eax
  225.         mov     [esi].SysDr.DR7R, EAX
  226. ; get GDT
  227.         sgdt    fword ptr [esi].SysGdt.GDTRL
  228. ; get LDT
  229.         sldt    [esi].SysLdt.LDTRS             ; LDT selector
  230.         movzx   eax, [esi].SysLdt.LDTRS
  231.         lar     eax, eax
  232.         mov     [esi].SysLdt.LDTSR, eax        ; access rights
  233.         movzx   eax, [esi].SysLdt.LDTRS
  234.         lsl     ax, ax
  235.         mov     [esi].SysLdt.LDTSL, ax         ; limit
  236.         movzx   eax, [esi].SysLdt.LDTRS
  237.         VMMCall _SelectorMapFlat,<ebx,eax,0>
  238.         mov     [esi].SysLdt.LDTB, eax         ; base
  239. ;get IDT
  240.         sidt    fword ptr [esi].SysIdt.IDTRL
  241. ;get TSS
  242.         str     ax
  243.         mov     [esi].SysTss.TREG, ax          ; Task Register
  244.         movzx   eax, ax
  245.         lar     eax, eax
  246.         mov     [esi].SysTss.TSSR, eax         ; access rights
  247.         mov     ax, [esi].SysTss.TREG
  248.         lsl     ax, ax
  249.         mov     [esi].SysTss.TSSL, ax          ; limit
  250.         movzx   eax, [esi].SysTss.TREG
  251.         VMMCall _SelectorMapFlat,<ebx,eax,0>
  252.         mov     [esi].SysTss.TSSB, eax         ; base
  253. ; get vxd root
  254.         mov     eax,gs:[VXD_FIRST]
  255.         mov     [esi].VxDRoot,eax
  256. ; VMM revision
  257.         VMMCall Get_VMM_Version
  258.         mov     [esi].VMMRev,ecx
  259.         mov     [esi].VMMVer,ax
  260. ; get # of running VMs
  261.         xor     eax,eax
  262. getvm_loop:
  263.         cmp     ax,[esi].VMCount
  264.         jae     short @f
  265.         mov     [esi+eax*4].VMHndl,ebx
  266.         inc     eax
  267.         VMMCall Get_Next_VM_Handle
  268.         VMMCall Test_Cur_VM_Handle
  269.         jnz     short getvm_loop
  270. @@:
  271.         mov     [esi].VMCount,ax
  272.         ret
  273. Get386  endp
  274.  
  275. ; find physical to linear address mapping
  276. PhysToLin       proc
  277.         movzx   ecx, [ebp].GateW
  278.         VMMcall _MapPhysToLinear,<[ebp].GateDw,ecx,0>
  279.         ret
  280. PhysToLin       endp
  281.  
  282. InsertRingoDDB   proc
  283.         movoffs eax,Ringo_DDB
  284.         mov     esi,gs:[VXD_FIRST]
  285.         push    [esi].DDB_Next
  286.         pop     [eax].DDB_Next
  287.         mov     [esi].DDB_Next,eax
  288.         ret
  289. InsertRingoDDB   endp
  290.  
  291. RemoveRingoDDB  proc
  292.         push    gs
  293.         assume  gs:_DATA
  294.         mov     gs,gs:[gdt_datasel]
  295.         assume  gs:_GATESEG
  296.         mov     esi,gs:[VXD_FIRST]
  297.         push    gs:[Ringo_DDB].DDB_Next
  298.         pop     [esi].DDB_Next
  299.         pop     gs
  300.         ret
  301. RemoveRingoDDB  endp
  302.  
  303. ; this is our Control Procedure -- every VMM message parks here
  304. ; we translate the message into the structure GATEVIEW can interpret
  305. ; then we schedule Sys VM event. In there we call PostMessage function
  306. ; in the nested execution frame and post WM_USER + WM_RINGO message
  307. RingoControlProc        proc
  308.         push    gs
  309.         call    GetRingoGdtDataSel
  310.         cmp     gs:[HWND],0
  311.         jz      short @f
  312.         pushad
  313. ; build WM_RINGO message out of System_Control message
  314.         mov     ecx, gs:[msgwrite]
  315.         mov     gs:[ecx][msgqueue].MSG_Msg,eax
  316.         mov     gs:[ecx][msgqueue].MSG_VM,ebx
  317.         mov     gs:[ecx][msgqueue].MSG_PARAM1,edx
  318.         mov     gs:[ecx][msgqueue].MSG_PARAM2,edi
  319.         mov     gs:[ecx][msgqueue].MSG_PARAM3,esi
  320.         mov     edx,ecx
  321.         add     ecx, type MSGSTRUC
  322.         cmp     ecx, size msgqueue
  323.         jb      short no_wrap
  324.         xor     ecx,ecx
  325. no_wrap:
  326.         mov     gs:[msgwrite],ecx
  327.         VMMcall Get_Sys_VM_Handle
  328.         movoffs esi,MessageEvent
  329.         VMMcall Schedule_VM_Event       ; schedule our MessageEvent callback
  330.         popad
  331. @@:
  332. ; see if we need to refuse creating VM
  333.         cmp     eax,gs:[vmstop]
  334.         pop     gs
  335.         jnz     short @f
  336.         stc
  337.         ret
  338. @@:
  339.         clc
  340.         ret
  341. RingoControlProc        endp
  342.  
  343. ; registers the client's window handle and builds the message queue for him
  344. RegisterHWND    proc
  345.         mov     ax,[ebp].GateW
  346.         mov     gs:[HWND],ax
  347.         mov     eax,[ebp].GateDw                ; PostMessage pointer
  348.         mov     gs:[CALLBACKOFFSEG],eax
  349.         movoffs edx,msgqueue
  350.         mov     eax,(type MSGSTRUC * 8)- 1
  351.         VMMCall _BuildDescriptorDWords,<edx,eax,RW_Data_Type,D_GRAN_BYTE,0>
  352.         VMMCall _Allocate_LDT_Selector,<ebx,edx,eax,1,0>
  353.         mov     gs:[msgsel],ax
  354.         ret
  355. RegisterHWND    endp
  356.  
  357. UnregisterHWND  proc
  358.         movzx   eax,gs:[msgsel]
  359.         or      eax,eax
  360.         jz      short @f
  361.         VMMCall _Free_LDT_Selector,<ebx,eax,0>
  362. @@:
  363.         xor     eax,eax
  364.         mov     gs:[msgsel],ax
  365.         mov     gs:[HWND],ax
  366.         mov     gs:[CALLBACKOFFSEG], eax
  367.         ret
  368. UnregisterHWND  endp
  369.  
  370. ; call PostMessage in the nest_exec block
  371. MessageEvent    proc
  372.         Push_Client_State
  373.         VMMcall Begin_Nest_Exec                 ; enter PM mode
  374.         push    gs
  375.         call    GetRingoGdtDataSel
  376. ; simulate PostMessage (hwnd, WM_USER + WM_RINGO, System_Control, lpMsgQueue)
  377.         movzx   eax,gs:[HWND]
  378.         VMMCall Simulate_Push
  379.         mov     eax, WM_USER + WM_RINGO
  380.         VMMCall Simulate_Push
  381.         mov     eax,gs:[edx][msgqueue].MSG_MSG
  382.         VMMCall Simulate_Push
  383.         movzx   eax,gs:[msgsel]
  384.         VMMCall Simulate_Push
  385.         mov     eax,edx
  386.         VMMCall Simulate_Push
  387.         mov     cx,word ptr gs:[CALLBACKOFFSEG] + 2
  388.         movzx   edx,word ptr gs:[CALLBACKOFFSEG]
  389.         VMMcall Simulate_Far_Call
  390.         pop     gs
  391.         VMMcall Resume_Exec
  392.         VMMcall End_Nest_Exec
  393.         Pop_Client_State
  394.         ret
  395. MessageEvent    endp
  396.  
  397. StopVM          proc
  398.         VMMCall Get_Next_VM_Handle
  399.         VMMCall Test_Cur_VM_Handle
  400.         jz      @f
  401.         xor     [ebx].CB_VM_Status, VMStat_Background
  402.         jmp     StopVM
  403. @@:
  404.         movzx   eax,[ebp].GateW
  405.         mov     gs:[vmstop],eax
  406.         ret
  407. StopVM          endp
  408.  
  409. ; this will swap us in if needed
  410. MakeSureOurSegIsInMemory proc    far
  411.         ret
  412. MakeSureOurSegIsInMemory endp
  413.  
  414. ; by the time WEP gets called, our original _GATESEG could have moved
  415. ; this will remap the call gate descriptor for the first call gate
  416. RemapCallGate   proc
  417.         movzx   eax,word ptr [ebp].GateDw + 2
  418.         VMMCall _SelectorMapFlat,<ebx,eax,0>
  419.         movzx   esi,word ptr [ebp].GateDw
  420.         add     esi,eax                         ; we are here now
  421.         movzx   edi,[ebp].GateW
  422.         VMMCall _GetDescriptor,<edi,ebx,0>      ; old gate descriptor
  423. ; modify the offset field in the call gate descriptor
  424.         mov     ax,si                           ; lower 16 bits
  425.         and     esi,CGATE_OFFSET_16_31_MASK
  426.         and     edx,(CGATE_ACCESS_RIGHTS_MASK + CGATE_DWORD_COUNT_MASK)
  427.         or      edx,esi                         ; upper 16 bits
  428.         VMMCall _SetDescriptor,<edi,ebx,edx,eax,20000000h>
  429.         ret
  430. RemapCallGate   endp
  431.  
  432. ringo_flat              dd      0               ; run-time space base
  433. OLD_DYNALINK_HANDLER    dd      0
  434. VXD_FIRST               dd      0               ; VxD chain root
  435. OurDynalinkHandler      dd      offset Ringo_Dynalink_Handler
  436. msgqueue                db (type MSGSTRUC * 8) dup (0)
  437. msgwrite                dd      0
  438. msgsel                  dw      0
  439. HWND                    dw      0
  440. CALLBACKOFFSEG          dd      0
  441. vmstop                  dd      0
  442. Ringo_DDB VxD_Desc_Block  <,,,1,0,,'Ringo   ',,offset RingoControlProc,,,,,,,>
  443.  
  444. Gate_Service_Table      label   dword
  445. .erre           Get386_Svc*4 eq $-Gate_Service_Table
  446.         dd      offset        Get386
  447. .erre           PhysToLin_Svc*4 eq $-Gate_Service_Table
  448.         dd      offset        PhysToLin
  449. .erre           Register_Hwnd_Svc*4 eq $-Gate_Service_Table
  450.         dd      offset        RegisterHWND
  451. .erre           Unregister_Hwnd_Svc*4 eq $-Gate_Service_Table
  452.         dd      offset        UnregisterHWND
  453. .erre           StopVM_Svc*4 eq $-Gate_Service_Table
  454.         dd      offset        StopVM
  455. .erre           RemapGate_Svc*4 eq $-Gate_Service_Table
  456.         dd      offset        RemapCallGate
  457. _GATESEG  ends
  458.  
  459. _DATA   segment  word use16 public 'DATA'
  460.         public  pghandle
  461. pghandle                dd      0
  462. gdt_datasel             dw      0
  463. _DATA   ends
  464. end
  465.