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

;************************************************************************
;
; Source File Name:     SMRAPGET.ASM
;
; Subroutine Name:      DOSSMGETAPPREQ
;
; Descriptive Name:     Get an Application Session Request
;
; Function:     Receive an application request to start, switch,
;               terminate, or set a session status and returns an
;               address to the application request block.
;
; Notes:
;       Dependencies:   None
;
;       Restrictions:   Only the Shell can call this procedure.
;                       It is invalid for the Shell to call
;                       this procedure after DOSSMSERVEAPPREQ
;                       has been called.
;
;Change History:
;  @TL7 04/05/90 PTR B712376 - Enable for MMIO
;  @MHW 09/13/90 PTR B715818 - Removed MMIO support
;  CJ54 02/24/92 PTR B733559 Check DosGetSeg error.
;  MDLL 01/10/94  BJN Page Tune segments for Merged DLL.
;
; Entry Point:
;       Linkage: EXTRN  DOSSMGETAPPREQ:FAR
;                       PUSH@   DWORD  ReqBlock   ; Request Block Addr.
;                                                 ;     (returned)
;                       CALL    DOSSMGETAPPREQ
; Inputs:
;       DWORD   ReqBlock   Double word where the far address to an
;                          application request block will be returned.
;
; Exit Normal:
;       AX      ReturnCode Value = 0, Request block received
;       DWORD   ReqBlock   Far address to the application request
;                          block
;
; Exit Errors:
;       AX      ReturnCode error_smg_invalid_call
;                          error_smg_not_baseshell
;
;                          DOSCREATEQUEUE errors
;                          DOSREADQUEUE   errors
;                          DOSREALLOCSEG  errors
;                          DOSSUBSET      errors
;
; Effects:      All other registers preserved.
;
; Internal References:
;          Data:        RDATA - common data segment
;                               shellpid - Shell process ID (DOSSMINITIALIZE)
;                               appreqqueue - Application request queue handle
;                       QDATA - common data segment used for application
;                               request queue (First realloc = 2K)
;          Routines:    GETINFOSEGS
;
; External References:
;          Data:        Local information segment (LIS_CurProcID,
;                       LIS_CurThrdID)
;          Routines:    DOSREALLOCSEG
;                       DOSSUBSET
;                       DOSCREATEQUEUE
;                       DOSREADQUEUE
;                       DOSSEMCLEAR
;
;************************************************************************
ifdef I1
;
;  IF (Caller is Shell)
;    IF (serviceappthd e 0) OR
;    IF (serviceappthd e LIS_CurThrdID)
;      IF (appreqqueue e 0)
;         DOSCREATEQUEUE (Create app request queue)
;      ENDIF
;      IF (No_Error)
;        DOSREADQUEUE (Wait for application request)
;        DOSGETSEG (Get access to the selector)
;        IF (No error)
;          Get RC from DosReadQueue
;        ENDIF
;        IF (No error)
;          IF (owning process died)
;            DOSSEMCLEAR (Release req_synchrosem for parent exit)
;            indicate process died
;          ENDIF
;        ENDIF
;      ENDIF
;    ELSE
;      RC = Error_SMG_Invalid_Call
;    ENDIF
;  ELSE
;      RC = Error_SMG_Not_BaseShell
;   ENDIF
;
;************************************************************************
else

.386C
    EXTRN AppReqQueueName  : BYTE       ; App. request queue name
    EXTRN RequestPty       : BYTE       ; Specified priority
    EXTRN AppReqQueue      : WORD       ; App. request queue handle
    EXTRN LocalSelector    : WORD       ; Selector to LDT
    EXTRN RequestLen       : WORD       ; Request block length
    EXTRN Requestor        : WORD       ; Application process ID
    EXTRN ServiceAppThd    : WORD       ; Service app req. thread ID
    EXTRN ShellPID         : WORD       ; Shell process ID

    EXTRN DOSCREATEQUEUE   : FAR        ; Create app. request queue
    EXTRN DOSREADQUEUE     : FAR        ; Get application request
    EXTRN DOSREALLOCSEG    : FAR        ; Reallocate queue segment
    EXTRN DOSGETSEG        : FAR
    EXTRN DOSSUBSET        : FAR        ; Suballocation initialize
    EXTRN DOSSEMCLEAR      : FAR        ; Clear semaphores
.xlist
    INCLUDE SMRAPGET.INC                ; Get app. request stack frame
.xcref
    INCLUDE ERROR2.INC                  ; Error code equates
    INCLUDE INFOSEG.INC                 ; Information segment defintions
    INCLUDE SMRRDATA.INC                ; Router data segment definition
    INCLUDE SMRREQB.INC                 ; Request Block data structure
    INCLUDE STRUC.INC
.cref
.list
;**************************************************************************

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

    PUBLIC DOSSMGETAPPREQ
    PUBLIC DOSSMGETAPPREQ_POSTDT
DOSSMGETAPPREQ PROC FAR

    Local_Bytes  EQU  0

    ENTER Local_Bytes,0
    PUSH AX                             ; Put AX on stack for RASTRACE
    PUSH DX                             ; Save registers
    PUSH DS
    PUSH ES
    PUSH SI                                                             ;CJ54

;   **********************************************
;   *  Get address of local information segment  *
;   **********************************************
    MOV  AX, RDATA                      ; Addressability to global data
    MOV  DS, AX
    MOV  ES, DS:LocalSelector

    MOV  AX, ShellPid
    .IF  < ES:LIS_CurProcID eq AX > NEAR

;     *********************************************
;     *  Verify Shell Service Application request *
;     *  or valid get app request call.           *
;     *********************************************
      MOV  AX, ES:LIS_CurThrdID
      .IF  < DS:ServiceAppThd eq No >  OR   ; DOSSMSERVEAPPREQ not called
      .IF  < DS:ServiceAppThd eq AX > NEAR  ; Service application request
        SUB  AX, AX                                                     ;CJ10
        .IF  < DS:AppReqQueue eq AX >   ; Queue created and initialized?;CJ10
          PUSH DS                       ; App request queue handle
          PUSH OFFSET AppReqQueue
          PUSH 0                        ; FIFO
          PUSH DS                       ; App request queue name
          PUSH OFFSET AppReqQueueName
          CALL DOSCREATEQUEUE
        .ENDIF

;       ********************************************
;       *  Wait for the next application request.  *
;       ********************************************
        .IF  < zero AX >                                                ;CJ10
          PUSH DS:AppReqQueue           ; Queue handle
          PUSH DS
          PUSH OFFSET Requestor         ; PID and request type
          PUSH DS
          PUSH OFFSET RequestLen        ; Length of request block
          PUSH SS:WORD PTR [BP].GetReqBlock+2 ; Req. block
          PUSH SS:WORD PTR [BP].GetReqBlock
          PUSH DWORD PTR 0              ; Wait for data                 ;CJ10
          PUSH DS                       ; Priority data
          PUSH OFFSET RequestPty
          PUSH DWORD PTR 0              ; data, we pass zeroes          ;CJ10
          CALL DOSREADQUEUE

;CJ54;;;; MOV  DX, AX                   ; Save DosReadQueue RC
;         ***********************************************************
;         *  Check to see if parentexitlist set the termination     *
;         *  flag in this request block.  If it is set, clear       *
;         *  synchrosem to allow parentexitlist to continue, and    *
;         *  set a special return code for DOSSMSERVAPPREQ, so it   *
;         *  will just ignore this request block, and read the next *
;         *  one.                                                   *
;         ***********************************************************
;CJ54;;;; PUSH DS
;CJ54;;;; PUSH SI

          .IF  < zero AX >              ; If no error from DosReadQ     CJ54
            LDS  SI, SS:[BP].GetReqBlock ; DS:SI --> @ of RB
;           ***************************************************
;           *  Make sure we have access to the Request Block  *
;           ***************************************************
            PUSH DS:[SI][2]             ; Get access to the selector
            CALL DOSGETSEG

;CJ54;;;; LDS  SI, DWORD PTR DS:[SI]    ; DS:SI --> request block

;CJ54;;;; .IF  < zero AX >              ; If no error from DosGetSeg    ;CJ10
;CJ54;;;;   MOV  AX, DX                 ; Get DosReadQueue RC
;CJ54;;;; .ENDIF

            .IF  < zero AX >                        ; Set qread flag      ;CJ10
              LDS  SI, DWORD PTR DS:[SI]    ; DS:SI --> request block     ;CJ54
              MOV  DS:[SI].ReqQueueStatus, RqRead   ; If qread was success
              .IF  < DS:[SI].ReqTermFlag e 1 > ; If owning process died
                MOV  AX, OFFSET Req_SynchroSem ; Calculate offset of
                ADD  AX, SI                 ; semaphore
                PUSH DS                     ; Selector of semaphore
                PUSH AX                     ; Offset of semaphore
                CALL DOSSEMCLEAR            ; Allow parentexitlist
                MOV  AX, 0DEADH             ; Indicate process died
              .ENDIF                        ; Process died test
            .ENDIF                          ; GetSeg success test
          .ENDIF                            ; ReadQ success test        ;CJ54

;CJ54;;;; POP  SI                       ; Restore SI
;CJ54;;;; POP  DS                       ; Restore DS
        .ENDIF

      .ELSE                             ; SMRAPSRV already started
        MOV  AX, Error_SMG_Invalid_Call ; Thread not allowed
      .ENDIF                            ; SMRAPSRV started test
    .ELSE                               ; Not shell thread
      MOV  AX, Error_SMG_Not_Baseshell  ; Not base shell calling
    .ENDIF                              ; Check for shell

    MOV  AX_Reg[-Local_Bytes], AX       ; Save AX on stack for RASTRACE

    POP  SI                             ; Restore registers             ;CJ54
    POP  ES                             ; Restore registers
    POP  DS
    POP  DX
    POP  AX                             ; Restore return code

    LEAVE
    DOSSMGETAPPREQ_POSTDT LABEL FAR
    RET  apgetlen

DOSSMGETAPPREQ ENDP

CODE_TUNE1 ENDS                                                         ;MDLL
endif
    END
