home *** CD-ROM | disk | FTP | other *** search
/ Media Share 13 / mediashare_13.zip / mediashare_13 / ZIPPED / PROGRAM / DDJ9403A.ZIP / UC394.ASC < prev    next >
Text File  |  1994-01-30  |  11KB  |  312 lines

  1. _UNDOCUMENTED CORNER COLUMN_
  2. edited by Andrew Schulman 
  3. "RINGO: VXDS ON THE FLY"
  4. by Alex Shmidt
  5.  
  6.  
  7. Listing 1
  8.  
  9. /* CALLGATE.H */
  10. typedef DWORD (FAR PASCAL *GATEPROC)(WORD svc, WORD cnt, DWORD extra);
  11.  
  12. /* SeeYouAtRing0  services */
  13. #define Get386_Svc               0                       //get system info
  14. #define PhysToLin_Svc            Get386_Svc + 1          //map phys to linear
  15. #define Register_Hwnd_Svc        PhysToLin_Svc + 1       //register HWND
  16. #define Unregister_Hwnd_Svc      Register_Hwnd_Svc + 1   //unregister HWND
  17. #define StopVM_Svc               Unregister_Hwnd_Svc + 1 //toggle DOS box exec
  18. #define RemapGate_Svc            StopVM_Svc + 1          //remap call gate
  19.  
  20. typedef struct {        /* call gate procedure parameters */
  21.    DWORD G_Dword;       // Dword parameter
  22.    WORD  G_Word;        // Word parameter
  23.    WORD  G_Svc;         // service number
  24. }GPARAM;
  25.  
  26. /* RingoInit functions */
  27. #define EXITRINGO   0xFFFF
  28. #define INITRINGO   0
  29.  
  30.  
  31.  
  32. Listing 2
  33.  
  34. /* RINGO.C -- excerpts */
  35. //#define CALLGATE_386  //define CALLGATE_386 to get gates from CALLGATE.386
  36.  
  37. #include <windows.h>
  38. #include "386.h"
  39. #include "callgate.h"
  40.  
  41. #ifdef CALLGATE_386
  42. GATEPROC GetFirstCallGateVxD (FARPROC entrypoint,BYTE paramcount);
  43. void     DestroyInitGateVxD (WORD callgateselector);
  44. #endif
  45.  
  46. VOID WINAPI RingoInit(void);
  47. VOID WINAPI SeeYouAtRing0(void);
  48. VOID WINAPI MakeSureOurSegIsInMemory(void);
  49. GATEPROC GetLdtRing0CallGate (FARPROC entrypoint,
  50.         BYTE paramcount,WORD callgate);
  51. GATEPROC GDT_Gate,LDT_Gate;
  52.  
  53. int FAR PASCAL LibMain ( HANDLE hInstance, WORD wDataSeg,
  54.                          WORD cbHeapSize, LPSTR lpszCmdLine )
  55. {
  56.    FARPROC ri = (FARPROC) RingoInit;
  57.  
  58.    if (!(GetWinFlags () & WF_ENHANCED))  /*VxDs exist in enhanced mode only*/
  59.       return 0;
  60.  
  61. #ifdef CALLGATE_386             // get the GDT call gate from CALLGATE.386
  62.    if (!(LDT_Gate = GetFirstCallGateVxD (ri, sizeof(GPARAM)/4)))
  63. #else                           // get the LDT call gate with INT 2F, AX=168A
  64.    if (!(LDT_Gate = GetLdtRing0CallGate (ri, sizeof(GPARAM)/4, 0)))
  65. #endif
  66.       return 0;
  67.  
  68.    /*** get the main call gate in GDT ***/
  69.    GDT_Gate = (GATEPROC)LDT_Gate (INITRINGO, sizeof(GPARAM)/4,
  70.           (DWORD)SeeYouAtRing0);
  71.    if (cbHeapSize)
  72.       UnlockData (0);
  73.    return (1);
  74. }
  75.  
  76. char vendor[] = "MS-DOS";               // Microsoft's signature
  77.  
  78. GATEPROC GetLdtRing0CallGate (FARPROC gproc, BYTE params,WORD gatesel)
  79. {
  80. #define VENDOR_SPECIFIC_API 0x168a
  81. WORD    ldt_map;                       // LDT selector, which maps LDT itself
  82. WORD    (far * entryp)(void);          // entry point to get the above
  83. LPCALLGATEDESCRPT  CGateDescriptor;    // build call gate descriptor with this
  84. WORD    RW_ldt_map;   /* ldt map selector fixes segment read-only problem */
  85. WORD    CGateSelector;                  // to be a call gate selector
  86. DWORD   initgate_flat;                  // callgate procedure's linear address
  87.  
  88.    _asm {
  89.    mov     si, offset vendor
  90.    mov     ax, VENDOR_SPECIFIC_API
  91.    int     2fh
  92.    or      al, al
  93.    jnz     no_vendor
  94.    mov     word ptr [entryp], di        /* private entry point */
  95.    mov     word ptr [entryp+2], es
  96.    mov     ax, 100h                     /* magic number */
  97.    }
  98.  
  99.    ldt_map = entryp();                  /* returns LDT map selector */
  100.  
  101.    _asm    jnc vendor_ok
  102. no_vendor:
  103.    return  0;
  104.  
  105. vendor_ok:
  106.    // When run under SoftICE/W LDT alias returns read_only, give us a good one
  107.    if (!(RW_ldt_map = AllocSelector(SELECTOROF((void FAR *)&GDT_Gate))))
  108.       return 0;
  109.    SetSelectorBase(RW_ldt_map, GetSelectorBase(ldt_map));
  110.    SetSelectorLimit(RW_ldt_map, GetSelectorLimit(ldt_map));
  111.    if ((CGateSelector = gatesel) == 0)          // we might already have one
  112.       if (!(CGateSelector = AllocSelector(0)))  // Get a selector for the gate
  113.       {
  114.          FreeSelector (RW_ldt_map);
  115.          return 0;
  116.       }
  117.  
  118.    // create a pointer to write into the LDT
  119.    CGateDescriptor = MAKELP(RW_ldt_map,CGateSelector & SELECTOR_MASK);
  120.  
  121.    // build 32-bit ring 3-to-0 call gate
  122.    #define MK_LIN(x)  (GetSelectorBase(SELECTOROF(x)) + (DWORD)OFFSETOF(x))
  123.    initgate_flat = MK_LIN(gproc);
  124.    CGateDescriptor->Offset_O_15 =  LOWORD (initgate_flat);
  125.    CGateDescriptor->Offset_16_31 = HIWORD (initgate_flat);
  126.    CGateDescriptor->Selector = 0x28;                // ring0 flat code seg
  127.    CGateDescriptor->DWord_Count = params & CALLGATE_DDCOUNT_MASK;
  128.    CGateDescriptor->Access_Rights = GATE32_RING3;   //pres,sys,dpl3,32CallGate
  129.    FreeSelector (RW_ldt_map);                       // don't need you any more
  130.    return ((GATEPROC)MAKELP(CGateSelector,0));
  131. }
  132.  
  133. DWORD WINAPI _export MapPhysToLinear (DWORD physaddr, WORD mapsize)
  134. {
  135.    return (GDT_Gate)(PhysToLin_Svc,mapsize,physaddr); /* DPMI alternative */
  136. }
  137.  
  138.  
  139.  
  140. Listing 3
  141.  
  142. ;;; RINGO.INC -- excerpts
  143.  
  144. GPARAM          struc           ; parameters
  145.  G_Dword        dd      ?
  146.  G_Word         dw      ?
  147.  G_Svc          dw      ?
  148. GPARAM          ends
  149. CALLGATE_FRAME  struc           ; stack frame at the time of ring transition
  150.  CG_pushbp      dd      ?
  151.  CG_Old_EIP     dd      ?               ; this is where we came from
  152.  CG_Old_CS      dd      ?               ; and will get back
  153.  CG_Params      db (type GPARAM) dup (?) ; call gate parameters
  154.  CG_Old_ESP     dd      ?               ; caller's
  155.  CG_Old_SS      dd      ?               ; stack
  156. CALLGATE_FRAME  ends
  157.  
  158. BuildGateStackFrame     macro dataseg
  159.         push    ebp
  160.         mov     ebp,esp
  161.         push    gs
  162.         push    ds
  163.         push    es
  164.         push    fs
  165.         push    esi
  166.         push    edi
  167.  ifidni <dataseg>,<_DATA>
  168.         mov     ax,ds
  169.         mov     gs,ax           ; we'll access our data seg via gs
  170.  endif
  171.         mov     ax,ss
  172.         mov     ds,ax           ; ring 0 flat data delector
  173.         mov     es,ax
  174.         mov     fs,ax
  175.  ifdifi <dataseg>,<_DATA>
  176.         call    GetRingoGdtDataSel
  177.  endif
  178. endm
  179.  
  180. ClearGateStackFrame     macro cleanup
  181.         pop     edi
  182.         pop     esi
  183.         pop     fs
  184.         pop     es
  185.         pop     ds
  186.         pop     gs
  187.         pop     ebp
  188.         ret     cleanup
  189. endm
  190.  
  191. movoffs macro   reg,off32                ; run-time fixup
  192.         mov     reg, offset &off32
  193.         add     reg,gs:[ringo_flat]
  194. endm
  195.  
  196.  
  197.  
  198. Listing Four
  199.  
  200. ;;; CALLGATE.ASM -- excerpts
  201.  
  202. .386p
  203.         include vmm.inc
  204.         include ringo.inc
  205.         include 386.inc
  206. public  RingoInit,SeeYouAtRing0,MakeSureOurSegIsInMemory
  207. _GATESEG segment dword use32 public 'CODE'
  208.         assume  cs:_GATESEG,gs:_DATA
  209. RingoInit       proc    far
  210.         BuildGateStackFrame _DATA
  211.         cmp     [ebp].CG_Params.G_Svc,EXITRINGOCALL
  212.         jnz     short @f
  213.         call    RingoExit               ; deallocate everything we've got
  214.         jmp     short retini
  215. @@:     call    RelocateRingo           ; run-time relocation and fixups
  216.         jc      short init_ret
  217.         call    DynalinkTrick           ; get the VxD chain root
  218.         call    InsertRingoDDB          ; welcome to the VxD club
  219.         call    CreateRingoGDTGate      ; GDT call gate to SeeYouAtRing0
  220. retini: mov     edx, eax                ; prepare return values for the ring 3
  221.         shr     edx, 16
  222.         ClearGateStackFrame <size CG_Params>    ; clear both ring stack frames
  223. RingoInit       endp
  224.  
  225. SeeYouAtRing0   proc     far            ; The callgate service proc
  226.         BuildGateStackFrame
  227.         VMMCall Get_Cur_VM_Handle               ; always helpful
  228.         movzx   eax, [ebp].CG_Params.G_Svc      ; service dispatcher
  229.         cmp     eax,LASTSVC
  230.         ja      @f
  231.         call    gs:Gate_Service_Table[eax*4]
  232. @@:     mov     edx, eax
  233.         shr     edx, 16
  234.         ClearGateStackFrame <size CG_Params>
  235. SeeYouAtRing0   endp
  236.  
  237. CreateRingoGDTGate      proc
  238.         movzx   edx, word ptr [ebp].CG_Params.G_Dword   ; offset16
  239.         add     edx,gs:[ringo_flat]                     ; fixup
  240.         mov     ax, cs                                  ; VMM code selector
  241.         mov     cx, [ebp].CG_Params.G_Word              ; parameter count
  242.         and     cx, CALLGATE_DDCOUNT_MASK ; make sure it's a reasonable number
  243.         or      cx, GATE32_RING3                        ; call gate type
  244.         call    BuildCallGateDWords
  245.         VMMCall _Allocate_GDT_Selector,<edx,eax,20000000h> ; undocumented flag
  246.         ror     eax,16
  247.         ret
  248. CreateRingoGDTGate      endp
  249.  
  250. BeginProc       DestroyGDTCallGate,public
  251.         movzx   eax,[ebp].CG_Params.G_Word
  252.         VMMCall _Free_GDT_Selector,<eax,0>
  253.         ret
  254. EndProc         DestroyGDTCallGate
  255.  
  256. BuildCallGateDWords     proc
  257.         movzx   eax, ax
  258.         shl     eax, 16                         ; selector
  259.         mov     ax, dx                          ; offset 0-15
  260.         mov     dx, cx                          ; offset 16-31 + type + count
  261.         ret
  262. BuildCallGateDWords     endp
  263.  
  264. ;****************************************************************************
  265. ; To get the VxD Base (VMM DDB ptr) we're using the undocumented fact that
  266. ; VMM's dynalink handler (considered a 'fault' 20h in DDK spec parlance)
  267. ; returns it in ecx. The idea is to hook VMM fault 20h, call any VMM service
  268. ; to get our fault handler receive control, call VMM's dynalink directly,
  269. ; store ecx in a static variable, and hook fault 20h again, this time
  270. ; with fault handlers reversed.
  271. ;****************************************************************************
  272.  
  273. BeginProc       DynalinkTrick
  274.         mov     esi, gs:[OurDynalinkHandler]
  275. twice:  mov     eax, 20h
  276.         VMMCall Hook_VMM_Fault              ; install our handler
  277.         mov     gs:[OLD_DYNALINK_HANDLER], esi
  278.         VMMCall Get_VMM_Version             ; need one call get it executed
  279.         cmp     esi, gs:[OurDynalinkHandler]
  280.         jnz     twice
  281.         mov     eax, gs:[VXD_FIRST]
  282.         ret
  283. EndProc         DynalinkTrick
  284.  
  285. Ringo_Dynalink_Handler  proc
  286.         call    gs:[OLD_DYNALINK_HANDLER]
  287.         mov     gs:[VXD_FIRST], ecx             ; DDB pointer
  288.         ret
  289. Ringo_Dynalink_Handler  endp
  290.  
  291. PhysToLin       proc               ; physical to linear address mapping
  292.         movzx   ecx, [ebp].CG_Params.G_Word
  293.         VMMcall _MapPhysToLinear,<[ebp].CG_Params.G_Dword,ecx,0>
  294.         ret
  295. PhysToLin       endp
  296.  
  297. ringo_flat              dd      0               ; run-time space base
  298. OLD_DYNALINK_HANDLER    dd      0
  299. VXD_FIRST               dd      0               ; VxD chain root
  300. OurDynalinkHandler      dd      offset Ringo_Dynalink_Handler
  301. Ringo_DDB VxD_Desc_Block  <,,,1,0,,'Ringo   ',,offset RingoControlProc,,,,,,,>
  302. Gate_Service_Table      label   dword
  303.         dd      offset          Get386
  304.         dd      offset          PhysToLin
  305.         dd      offset          RegisterHWND
  306.         dd      offset          UnregisterHWND
  307.         dd      offset          StopVM
  308.         dd      offset          RemapCallGate
  309. _GATESEG  ends
  310. end
  311.  
  312.