;       SCCSID = @(#)smrrbalc.asm       6.2 91/06/11
;       SCCSID @(#)smrrbalc.asm 6.2 91/06/11
PAGE 60,132                             ;
; ****************************************************************************
; *                                                                          *
; *                       IBM/Microsoft Confidential                         *
; *                                                                          *
; *                 Copyright (c) IBM Corporation  1987, 1990                *
; *                 Copyright (c) Microsoft Corp.  1987, 1990                *
; *                           All Rights Reserved                            *
; *                                                                          *
; ****************************************************************************

;************************************************************************
;
; Source File Name:     SMRRBALC.ASM
;
; Subroutine Name:      REQUESTBLOCKALOC
;
; Descriptive Name:     Allocate a request block
;
; Function:     Allocate an application request block and initialize
;               the common request block header data.
;
; Notes:
;       Dependencies:   None
;
;       Restrictions:   None
;
; Change history:
;   @TL6 03/01/90  DCR 704 - Merge SMG/SSW instance data into OS2CHAR
;   CJ34 06/11/91  PTR B723282 Clear SGCB_ParentExit flag.
;   56655 11/21/92 CJJ Need to know session id who started the new session.
;   58348 02/22/93 CJJ Pass current directory to a VDM started VDM session.
;   MDLL  01/10/94 BJN Page Tune segments for Merged DLL.
;
; Entry Point:
;       Linkage:  EXTRN REQUESTBLOCKALOC:NEAR
;                       CALL    REQUESTBLOCKALOC
; Inputs:
;       BX      Reqbsize  Size of request block to allocate
;       AX      Flag      AL = 0 if this is NOT a start
;                            = 1 if this is a start
;                         AH = 0 if not related start
;                            = 1 if related start
;
; Exit Normal:
;       AX      ReturnCode Value = 0, Request block allocated
;       GS      LocalSel   Local information selector
;       FS      INSTANCE   Instance Data Segment
;       ES:DI   ReqBlock   @ of the request block
;
; Exit Errors:
;       AX      ReturnCode error_smg_invalid_call
;                          error_smg_process_not_parent
;                          error_smg_retry_sub_alloc
;
;                          DOSHOLDSIGNAL errors
;                          DOSSUBSET     errors
;                          DOSSUBALLOC   errors
;                          DOSEXITLIST   errors
;
; Effects:      All other registers preserved.
;
; Internal References:
;          Data:        reqblock (SMRREQB.INC)
;                       RDATA - Common data segment
;                               parentpidtbl - parent pid table (SMRPATBL.INC)
;                                  parentpid - process ID
;                               queuesegsize - Current size of queue segment
;          Routines:    PARENTEXITLIST
;
; External References:
;          Data:        Local information segment (LIS_CurScrnGrp,
;                       LIS_CurProcID)
;          Routines:    DOSEXITLIST
;                       DOSREALLOCSEG
;                       DOSSEMWAIT
;                       DOSSUBALLOC
;                       DOSSUBSET
;                       DOSHOLDSIGNAL
;                       DOSSEMSET
;
;************************************************************************
ifdef I1
;
;      IF (We have been initialized)
;        Get real session id from parent PID table
;        IF (Current sg e 1) OR
;        IF (Current sg above reserved sg) AND
;        IF (NOT detached) AND
;        IF (Below maximum)
;          IF (NOT in exitlist processing)
;            DOSEXITLIST (Add address to exit list)
;          ENDIF
;          DOSSMGETSGCB (Get pointer to calling session's sgcb)
;          IF (No error)
;            IF (Start request)
;              IF (Start related request)
;                IF (There is no parent pid)
;                  Set sg's parentpid to current pid
;                ELSEIF (Current pid is not parent pid)
;                  Set RC = Error_SMG_Process_Not_Parent
;                ENDIF
;              ENDIF
;            ELSEIF (Parent pid NOT e 0) AND
;            IF (Parent pid NOT e to current pid)
;              Set RC = Error_SMG_Process_Not_Parent
;            ENDIF
;          ELSE
;            Set RC = Error_SMG_Invalid_ Call
;          ENDIF
;        ELSE
;          Set RC = Error_SMG_Invalid_ Call
;        ENDIF
;        IF (No error)
;          DOSHOLDSIGNAL (Temporarily disable signals)
;          Get access to instance memory
;          DOSSMGETMEM (Get memory from Session Manager heap)
;          IF (No error)
;            DOSSEMSET (Set sem to be cleared by DoAppReq)
;          ENDIF
;          DOSHOLDSIGNAL (Temporarily reenable signals)
;        ENDIF
;      ELSE
;        Set RC = Error_SMG_Invalid_ Call
;      ENDIF
;
;
;
;************************************************************************
else

.386C
    EXTRN SMG_Flags      : BYTE         ; SESMGR done initiailizing
    EXTRN LocalSelector  : WORD         ; Selector to LDT
    EXTRN SGCB_ArraySize : DWORD        ; Maximum # of Sessions
    EXTRN SMG_INSTANCE   : DWORD        ; SMG/SSW instance data         ;@TL6
    EXTRN VDMServerTID   : WORD         ; Thread ID of VDM Server thread 56655
    EXTRN StartVDMSGID   : BYTE         ; VDM SGID who started new ses.  56655

    EXTRN PARENTEXITLIST : NEAR         ; Exit code
    EXTRN DOSEXITLIST    : FAR
    EXTRN DOSHOLDSIGNAL  : FAR
    EXTRN DOSSMGETSGCB   : FAR          ; Gets address of a SGCB
    EXTRN DOSSMGETMEM    : FAR          ; Get memory from Session Manager Heap
    EXTRN DOSSEMWAIT     : FAR          ; Wait for start semaphore to clear
    EXTRN DOSSEMSET      : FAR

    INCLUDE SMRREQB.INC                 ; Request block definitions
.xlist
    INCLUDE OS2INST.INC                 ; Instance data equates         ;@TL6
.xcref
    INCLUDE BSEERR.INC                  ; Error code equate for ERROR_INTERRUPT
    INCLUDE INFOSEG.INC                 ; Information segment definitions
    INCLUDE SMRRDATA.INC                ; Router data declarations
    INCLUDE STRUC.INC
    INCLUDE SMRSGCB.INC                 ; Structure and equates for sgcb
.cref
.list

;R3CODE SEGMENT WORD PUBLIC 'CODE' USE16                                ;@TL6
;R3CODE ENDS                                                            ;@TL6

CODE_TUNE1 SEGMENT WORD PUBLIC 'CODE' USE16                             ;MDLL
    ASSUME CS:CODE_TUNE1,DS:NOTHING,FS:NOTHING,GS:RDATA,SS:NOTHING,ES:RDATA

    PUBLIC REQUESTBLOCKALOC
REQUESTBLOCKALOC PROC NEAR

    Local_Bytes EQU 4
    Local_Var1 EQU  SS:[BP][-2]         ; Local variable on stack
    Local_Var2 EQU  SS:[BP][-4]         ; Local variable on stack
    ENTER Local_Bytes,0                 ; Get a word for a local variable

    PUSH BX                                                             ;@TL6
    PUSH CX                             ; Save registers
    PUSH DX
    PUSH SI
    PUSH DS

    MOV  CX, AX                         ; Save input parameter
    MOV  AX, RDATA                      ; Global data
    MOV  ES, AX

    Test ES:SMG_Flags, InitDone         ; If bit is set then
    .IF  nz  NEAR                       ;  we are initialized
      MOV  GS, ES:LocalSelector         ; @ of LDT

;     ******************************
;     *  Get real session ID from  *
;     *  parent PID table.         *
;     ******************************
      MOV  DX, GS:LIS_CurScrnGrp
      .IF  < DX e 1 > OR
      .IF  < DX ae First_Available_Session > AND NEAR ; Above reserved scrn grp #'s?
      .IF  < GS:LIS_ProcType ne LIS_PT_DETACHED > AND ; If not detached
      LFS  SI, ES:SGCB_ArraySize        ; FS:[SI] --> Max # of Sessions ;CJ10
      .IF  < DL b FS:[SI] >                           ; And below maximum ?

;       *********************************************************
;       *   If we are not in exitlist processing, then          *
;       *   register this pid with OS/2 so that it will run     *
;       *   PARENTEXITLIST when this process terminates.        *
;       *********************************************************
        TEST GS:LIS_ProcStatus, LIS_PS_EXITLIST ; See if in exitlist
        .IF  z                          ; If not in exitlist
          MOV  AX,1                                                     ;@TL6
          PUSH AX                       ; Add address to exit list      ;@TL6

;       *********************************************************
;         OR   AX,CODE                  ; Exitlist must be in Ring 3    ;MDLL
          OR   AX,CODE_TUNE1            ; Exitlist must be in Ring 3    ;MDLL
;       *********************************************************


          PUSH AX                                                       ;@TL6
          PUSH OFFSET PARENTEXITLIST    ; Offset of code to execute
          CALL DOSEXITLIST
        .ENDIF                          ; In exitlist processing test

;       **********************************************************************
;       *  If this is a Start Request, check to see if this process is the   *
;       *  parent process of this screen group.  Also make sure that the     *
;       *  process issuing the request is the parent of the target process.  *
;       **********************************************************************

;       ********************************************
;       *  Get a pointer to calling sessions SGCB  *
;       ********************************************
        LEA  SI, Local_Var2
        PUSH SS                         ; Selector of SGCB
        PUSH SI                         ; Offset
        PUSH DX                         ; SGID
        PUSH SGID_Lookup + 8000H        ; Look up SGID not PID and      ;CJ10
        CALL DOSSMGETSGCB               ;   don't serialize QueueRamSem

        .IF  < zero AX >                                                ;@TL6
          LDS  SI, DWORD PTR Local_Var2 ; DS:SI --> Calling SG's SGCB

;         *******************************************
;         *  Make sure this process is the one      *
;         *  and only parent for this screen group  *
;         *******************************************
          MOV  DX, GS:LIS_CurProcID     ; Current Process's ID
          .IF  < CL eq 1 >              ; Start Request ?
            .IF  < CH eq 1 >            ; Start Related Request ?
              .IF  < [SI].SGCB_ParentPID eq No > ; Is there a parent yet?
                MOV  [SI].SGCB_ParentPID, DX ; Set this SG's parentpid to this PID
                MOV  [SI].SGCB_ParentExit, 0 ; Clear parent exit        ;CJ34
              .ELSEIF < [SI].SGCB_ParentPID ne DX > ; Are we this SG's parent?
                MOV  AX, Error_SMG_Process_Not_Parent
              .ENDIF
            .ENDIF                      ; Related/Not related test

          .ELSEIF < [SI].SGCB_ParentPID ne 0 > AND ; Else, not a Start request
          .IF  < [SI].SGCB_ParentPID ne DX >
            MOV  AX, Error_SMG_Session_Not_Parent
          .ENDIF                        ; Check for Start Related Child Request

          MOV  SI, [SI].SGCB_ID         ; Save requesting sessionid

        .ELSE                           ; Running under an illegal session ID.
          MOV  AX, Error_SMG_Invalid_Call
        .ENDIF
      .ELSE
        MOV  AX, Error_SMG_Invalid_Call ; Illegal SG making this call
      .ENDIF                            ; DOSSMGETSGCB call

      .IF  < zero AX > NEAR                                             ;@TL6
        PUSH Disable_Signals            ; Specify to hold off signals
        CALL DOSHOLDSIGNAL              ; Temporarily disable signals

;       ******************************************************
;       *  Get access to INSTANCE DATA, and have DOSSMGETMEM *
;       *  return the address of the request block to the    *
;       *  next available slot in the INSTANCE DATA array.   *
;       *  NOTE:  There is no check to see if the array is   *
;       *  full.  This may cause problems later.             *
;       ******************************************************
        MOV  CX, BX                     ; Save size in CX               ;@TL6
        LFS  BX, ES:SMG_INSTANCE        ; ES --> INSTANCE DATA          ;@TL6
        MOV  DI, FS:[BX].Next_Slot      ; Get the next available slot   ;@TL6
        SHL  DI, 2                      ; Mult. by 4 for DWORD address
        ADD  DI, BX                     ;                               ;@TL6

        PUSH FS                         ; Put @ directly in INSTANCE data
        PUSH DI                         ; array (slot #) in INSTANCE data
        PUSH CX                         ; Size to allocate              ;@TL6
        CALL DOSSMGETMEM                ; Get memory from Session Manager Heap

        .IF  < zero AX >                ; DosSMGetMem worked (naturally);@TL6
          INC  FS:[BX].Next_Slot        ; Index to next available slot  ;@TL6

;         ***********************************
;         *  Fill in Request Block Header.  *
;         ***********************************
          LES  DI, FS:[DI]               ; Get @ of request block
          MOV  CX, DI                    ; Start of request block
          ADD  CX, OFFSET Req_SynchroSem ; Offset from ES
          PUSH ES                        ; Push Selector of req_synchrosem
          PUSH CX                        ; Push Offset
          CALL DOSSEMSET                 ; Set semaphore to be cleared by
                                         ; DoAppReq (Normal case)

          MOV  CX, RDATA                                                  ;56655
          MOV  DS, CX                                                     ;56655

          MOV  CX, GS:LIS_CurThrdID      ; Get requesting thread ID
;         **********************************************************      ;56655
;         *  Check if this is a request from a VDM to do a Start.  *      ;56655
;         *  If it is, then we need to set the requesting SGID,    *      ;56655
;         *  PID, etc. to the VDM who requested it so the session  *      ;56655
;         *  can be started in the foreground.                     *      ;56655
;         *                                                        *      ;56655
;         *  First check if StartVDMSGID is nonzero, this means a  *      ;56655
;         *  VDM StartSession is in progress.  Then check if we're *      ;56655
;         *  running under our thread that does VDM Starts.        *      ;56655
;         **********************************************************      ;56655
          .IF  < DS:StartVDMSGID ne 0 >  AND                              ;56655
          MOV  BX,SI                                                      ;56655
          .IF  < BL eq Shell_SG >        AND                              ;56655
          .IF  < DS:VDMServerTID eq CX >                                  ;56655
            OR   ES:[DI].ReqFlags, VDMStartedSession                      ;58348

            MOV  BL, DS:StartVDMSGID      ; VDM SGID requesting start     ;56655
            XOR  BH, BH                   ; Convert byte to word          ;56655
            MOV  DS:StartVDMSGID, 0       ; Reset VDM SGID                ;56655
            LEA  SI, Local_Var2                                           ;56655
            PUSH SS                       ; Selector of SGCB              ;56655
            PUSH SI                       ; Offset                        ;56655
            PUSH BX                       ; VDM SGID                      ;56655
            PUSH SGID_Lookup + 8000H      ; Look up SGID not PID and      ;56655
            CALL DOSSMGETSGCB             ;   don't serialize QueueRamSem ;56655
            LDS  SI, DWORD PTR Local_Var2                                 ;56655

            MOV  BX, DS:[SI].SGCB_ID      ; Get VDM SGID                  ;56655
            MOV  ES:[DI].ReqSessionID, BX ; Requestor's Session ID        ;56655

            MOV  BX, DS:[SI].SGCB_PID     ; Get VDM PID                   ;56655
            MOV  ES:[DI].ReqProcessID, BX ; Requestor's Process ID        ;56655
            MOV  ES:[DI].ReqThreadID, 1   ; Thread id -> don't care       ;56655

          .ELSE                                                           ;56655
            MOV  ES:[DI].ReqSessionID, SI ; Requestor's Session ID
            MOV  ES:[DI].ReqProcessID, DX ; Requestor's Process ID
            MOV  ES:[DI].ReqThreadID, CX  ; Thread id in request blockid
          .ENDIF                                                          ;56655

          MOV  ES:[DI].ReqLength, RB_Head_Len_Equ ; Length of RB Header
        .ENDIF                          ; DosSMGetMem Test

        PUSH AX                         ; Save return code
        PUSH Enable_Signals             ; Specify to allow signals
        CALL DOSHOLDSIGNAL              ; Temporarily enable signals

        POP  AX                         ; Restore meaningful return code
      .ENDIF                            ; Check for legal caller

    .ELSE                               ; SESMGR not initialized Yet
      MOV  AX, Error_SMG_Invalid_Call
    .ENDIF                              ; SESMGR initialization test

    POP  DS
    POP  SI
    POP  DX
    POP  CX
    POP  BX                                                             ;@TL6


    LEAVE
    RET

REQUESTBLOCKALOC ENDP

CODE_TUNE1 ENDS                                                         ;MDLL
endif
    END
