;       SCCSID = @(#)smgvdmsv.asm       6.1 92/02/14
PAGE 60,132    ;
; ****************************************************************************
; *                                                                          *
; *                       IBM/Microsoft Confidential                         *
; *                                                                          *
; *                 Copyright (c) IBM Corporation  1987, 1990                *
; *                 Copyright (c) Microsoft Corp.  1987, 1990                *
; *                           All Rights Reserved                            *
; *                                                                          *
; ****************************************************************************

;************************************************************************
;
; Source File Name:     SMGVDMSV.ASM
;
; Subroutine Name:      VDMSTARTSESSION
;
; Descriptive Name:     Do a DosStartSession for a VDM when signalled by Dos
;                       Kernel.
;
; Function:     Start a new session for a VDM when signalled.
;               This allows VDMs to start other sessions.
;
; Notes:
;       Dependencies:   This procedure is called through DOSCREATETHREAD
;                       during the creation of the 1st VDM session.
;
; Change History:
;   Created  08/21/92  Feature 26159
;   56655    11/21/92  CJJ Need to know session id who started the new session.
;   61998    02/11/93  VLR Clear out AX register once tid is saved.
;   58348    02/22/93  CJJ Pass current directory to a VDM started VDM session.
;   72098    08/13/93  GLFulk Failure in SysServWaitQ will now return an error
;                      code indiciating DosStartSession should not be called.
;   MDLL     01/10/94  BJN Page Tune segments for Merged DLL.
;
; Entry Point:
;       Linkage:  EXTRN VDMSTARTSESSION : FAR
;          Note:  Getting an address from DOSSYSTEMSERVICE
;                 containing the parameters used in DOSSTARTSESSION
;
; Effects:      Starts another process under the Shell.
;
;
; External References:
;          Routines:    DOSCREATETHREAD
;                       DOSCREATEEVENTSEM
;                       DOSSYSTEMSERVICE
;                       DOS32STARTSESSION
;                       DOSPOSTEVENTSEM
;
;************************************************************************
ifdef I1
;
;
;   DOSCREATEEVEMTSEM   (\SEM32\VDMSTART\DONE)
;
;   REPEAT
;      DOSSYSTEMSERVICE (Wait for kernel notification of VDM START)
;      GET POINTERS
;      DOS32STARTSESSION
;      FILL IN RETURN CODE
;      DOSPOSTEVENTSEM (\SEM32\VDMSTART\DONE)
;   UNTIL   (Wait for next event)
;
;************************************************************************
else

.386P

   EXTRN DOS32CREATETHREAD     : NEAR         ; Create a new thread
   EXTRN DOS32CREATEEVENTSEM   : NEAR         ; Create event semaphore
   EXTRN DOS32POSTEVENTSEM     : NEAR         ; Post event semaphore
   EXTRN DOS32STARTSESSION     : NEAR         ; Start another session
   EXTRN DOSSYSTEMSERVICE      : FAR          ; Wait on kernel notification  for
                                              ; VDM Start
   EXTRN StartVDMSGID          : BYTE         ; VDM SGID who started ses 56655
   EXTRN VDMServerTID          : WORD         ; VDM SGID who started ses 56655
   EXTRN VDMCurDir             : DWORD        ; current VDM directory    58348
.xlist
.xcref
   INCL_DOSPROCESS      EQU     1
   INCL_DOSSEMAPHORES   EQU     1

   INCLUDE STRUC.INC
   INCLUDE BASEMACA.INC                             ; use LocalVar type
   INCLUDE THKMACS.INC                              ; Thunk macros
   INCLUDE DEMSMG.INC                               ; VDM STRUC
   INCLUDE SYSSERV.INC                              ; VDMStart services
.cref
.list


DATA32  SEGMENT DWORD USE32 PUBLIC 'DATA'


VDMActPacket     DD      0                          ; DosSystemService action pkt.
VDMResPacket     DD      0                          ; DosSystemService response pkt.
VDMData          DEMSTARTDATA    <>                 ; VDM STRUC

VDMStartDoneSem  DB      VDMStartDoneSem_name,0     ; Sem signal vdmstartsession done
VDMStartDoneHndl DD      0                          ; VDMSTARTDONE handle

DATA32  ENDS


;*************************************************************************
;*      32 Bit Code                                                      *
;*************************************************************************

CODE32_TUNE4  SEGMENT DWORD USE32 PUBLIC 'CODE'                         ;MDLL
        assume  cs:CODE32_TUNE4                                         ;MDLL


;**** Need DoCreateVDMServer defined here before 16 bit calls it. ****
;**** Causes Phase errors otherwise.                              ****

DOCREATEVDMSERVER:
   JMP  CREATEVDMSERVER


CODE32_TUNE4            ENDS                                            ;MDLL


;*************************************************************************
;*      16 Bit Code                                                      *
;*************************************************************************

CODE_TUNE4    SEGMENT WORD USE16 PUBLIC 'CODE'                          ;MDLL
        ASSUME  CS:CODE_TUNE4, DS:NOTHING                               ;MDLL

   PUBLIC DO32BITDOSCRTTHREAD
DO32BITDOSCRTTHREAD     PROC    FAR

   MOV  CX, DS                          ; Save DS
   MOV  AX, SS                          ; Convert ss:sp -> esp
   MOV  BX, AX                          ; Save SS
   SHR  AX, 3                           ; remove table/dpl bits
   ROL  EAX, 16                         ; swap words back
   MOV  AX, seg FLAT:DATA32
   MOV  SS, AX
   MOV  DS, AX
   MOV  AX, SP                          ; add offset
   MOV  ESP, EAX                        ; flat stack address
   JMP  FAR PTR FLAT:DOCREATEVDMSERVER

CREATE_RETURN:
   MOV  DS, CX                          ; Restore DS
   MOV  SS, BX                          ; Restore SS
   RET

DO32BITDOSCRTTHREAD     ENDP

CODE_TUNE4              ENDS                                            ;MDLL


;*************************************************************************
;*      32 Bit Code                                                      *
;*************************************************************************

CODE32_TUNE4  SEGMENT DWORD USE32 PUBLIC 'CODE'                         ;MDLL
        ASSUME  CS:FLAT, DS:FLAT


   PUBLIC CREATEVDMSERVER
CREATEVDMSERVER:

   Local_Bytes   EQU 4
   Local_Var1    EQU SS:[EBP][-4]       ; Local variable on stack

   ENTER Local_Bytes,0

   PUSH 4096                            ; Stack size
   PUSH 0                               ; No parms
   PUSH 0                               ; Start immediately, default stack
   LEA  EAX, DWORD PTR VDMSTARTSESSION  ; Thread address
   PUSH EAX
   LEA  EAX, Local_Var1                 ; Return thread id
   PUSH EAX
   CALL DOS32CREATETHREAD

   .IF  < zero EAX >                    ; If successful, save thread ID ;56655
     MOV  EAX, DWORD PTR Local_Var1                                     ;56655
     MOV  VDMServerTID, AX                                              ;56655
     XOR  EAX,EAX                                                       ;61998
   .ENDIF                                                               ;56655

   LEAVE
   JMP  FAR PTR CREATE_RETURN           ; Jump back to 16 bit


   PUBLIC VDMSTARTSESSION
VDMSTARTSESSION  PROC NEAR


   Local_Bytes1  EQU  0

   ENTER Local_Bytes1,0

   T32Beg

   PUSH 1                               ; initial state posted  ;65622;
   PUSH 0                               ; shared
   LEA  EAX, DWORD PTR VDMStartDoneHndl ; sem handle returned
   PUSH EAX
   LEA  EAX, DWORD PTR VDMStartDoneSem  ; Create \VDMStart\Done sem
   PUSH EAX
   CALL DOS32CREATEEVENTSEM             ; Create event sem
   ADD  ESP, 16                         ; Pop parms off stack

   .REPEAT

        MOV     [VDMResPacket],offset FLAT:VDMData  ; address of data in res pak
;------ Convert allocated VDMActPacket & VDMResPacket 0:32 ptr to 16:16 and push

        T32Bump                            ;Bump down stack if necessary
        MOV     EAX,ESP                    ;save current SS:ESP(ptr to 32bit stk
        PUSH    SS
        PUSH    EAX
        getRPL  DX,DS                      ; Get RPL for selectors
        MOV     AX,SysServ_VDMSta          ; Make VDMStart Services 16bit
        PUSH    AX
        LEA     EAX,VDMActPacket           ; Action packet address
        SEGPTR  EAX,EAX,DX                 ; 0:32 ptr to 16:16
        PUSH    EAX
        LEA     EAX,VDMResPacket           ; Response packet address
        SEGPTR  EAX,EAX,DX                 ; 0:32 ptr to 16:16
        PUSH    EAX
        T32Stack EAX,ESP,DX                ;Convert SS:ESP to 16-bit SS:SP
        JMP     FAR PTR API_16BIT_SERVICE  ;jump to 16bit DosSystemService

RETURN_32BIT:
        T32End                             ;Restore 32 bit SS:ESP

        or   eax,eax                                                    ;72098;
        jnz  SysServ_failed                                             ;72098;
        MOV  AL,[VDMData].demSS_DemScreen_group  ;Store sgid of VDM      ;56655
        MOV  StartVDMSGID,AL                     ;doing startsession     ;56655
        MOV  EAX,[VDMData].demSS_DemCurrentDirectory                     ;58348
        MOV  VDMCurDir,EAX                 ;Store current directory      ;58348

        PUSH offset FLAT:VDMData.demSS_demStartSession_pid  ; address of pid
        PUSH offset FLAT:VDMData.demSS_demStartSession_sid  ; address of sid
        PUSH offset FLAT:VDMData.demSS_Length               ; address of startdata
        CALL DOS32STARTSESSION             ; Start a session
        ADD  ESP, 12                       ; Pop parms off stack
SysServ_failed:                                                         ;72098;
        MOV  [VDMData].demSS_demStartSession_rc,EAX     ; VDMStartRC address

        MOV  EAX, DWORD PTR VDMStartDoneHndl ; sem handle returned
        PUSH EAX
        CALL DOS32POSTEVENTSEM              ; post VDMStartDone sem
        ADD  ESP, 4                         ; Pop parms off stack

   .UNTIL                                   ; Infinite loop


   LEAVE
VDMSTARTSESSION  ENDP

CODE32_TUNE4            ENDS                                            ;MDLL
endif


;--------------- Call 16 bit DosSystemService ----------------------------------

CODE_TUNE4              SEGMENT WORD USE16 PUBLIC 'CODE'                ;MDLL
                        ASSUME  CS:CODE_TUNE4, DS:NOTHING               ;MDLL

    PUBLIC API_16BIT_SERVICE
API_16BIT_SERVICE       PROC    FAR
                        CALL    FAR PTR DOSSYSTEMSERVICE  ;Wake SMG when a VDM Start is needed
                        JMP     FAR PTR FLAT:RETURN_32BIT ;jump back to 32bit code
API_16BIT_SERVICE       ENDP

CODE_TUNE4              ENDS                                            ;MDLL
   END
