;       SCCSID = @(#)smrgetcb.asm       6.3 91/07/11
;       SCCSID @(#)smrgetcb.asm 6.3 91/07/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:     SMRGETCB.ASM
;
; Subroutine Name:      DOSSMGETSGCB
;
; Descriptive Name:     Returns the address of a Screen Group Control Block
;
; Function:     Locates and returns the address of the SGCB for the
;               requested session.
;
; Notes:
;       Dependencies:   None.
;
;       Restrictions:   None.
;
; Change History:
;
;   @T52 02/09/90 TPL  DCR 704 work
;   @@A4 02/15/90 CJJ,JP B711479 Don't clear hi byte of pid.
;   @@A7 02/20/90 HZ00416 - Clear EDI before using it
;   @T18 04/30/90 B712103 - Optimize screen switching by saving the
;                           Array selector in the instance data seg.
;   CJ26 05/12/91 PTR B722846 Free memory allocated for Cwait thread stack.
;   CJ39 07/11/91 PTR B724633 Use DosHoldSignal to avoid dying while owning
;                             SMQueueRamSem.
;   MDLL 01/10/94 BJN  Page Tune segments for Merged DLL.
;
; Entry Point:
;       Linkage:  EXTRN DOSSMGETSGCB:FAR
;                       PUSH@   DWORD  Address (Returned)
;                       PUSH    WORD   SGID/PID
;                       PUSH    WORD   INDICATOR
;                       CALL    DOSSMGETSGCB
;
; Inputs:
;       WORD    Address     Address to put new Selector:Offset in.
;       WORD    ID          SGID or PID of the SGCB to return
;       WORD    INDICATOR   Specifies to look up based on SGID or PID
;                           0 = Look up SGID
;                           1 = Look up PID
;                           2 = Look up SGID, but return NEXT SGCB.
;                       8000h = Skip DosFSRamSemRequest
; Exit Normal:
;       AX      ReturnCode Value = 0, memory allocated
;
; Exit Errors:
;       AX      ReturnCode            Error_SMG_Invalid_SGID
;                                     Error_SMG_Session_Not_Found
;
;
; Effects:      All other registers preserved.
;
; Internal References:
;
;          Routines:
;
; External References:
;          Routines:
;
;***************************************************************************
ifdef I1
;
;   Do OS2CHAR initialization if not already done
;   DOSSFRAMSEMREQUEST (QueueRamSem)
;   DOSGETSEG (Array of SGCB addresses)
;   If searching on SGID
;     Get SGCB address out of Array of addresses
;   Else                                ; PID Lookup
;     Repeat
;       Leave If we found the PID
;     Until we point past last PID
;
;     If Didn't find the PID
;       RC = Error_SMG_Session_Not_Found
;     EndIf
;   EndIf                               ; SGID/PID Lookup Test
;
;   If No Error
;     Make sure caller has access to selector
;     CALL DOSGETSEG (SGCB)
;     Give address to caller
;   Else
;     RC = Error_SMG_Session_Not_Found
;   EndIf
;
;   DOSFSRAMSEMCLEAR (QueueRamSem )
;
;***************************************************************************
else

.386C

    SESMGR  EQU  -1                    ; Needed for pmshl.inc

    EXTRN DOSGETSEG          : FAR
    EXTRN DOSFSRAMSEMREQUEST : FAR
    EXTRN DOSFSRAMSEMCLEAR   : FAR
    EXTRN DOSSMGETMEM        : FAR
    EXTRN DOSHOLDSIGNAL      : FAR      ; Hold off signals              ;CJ39

    EXTRN ArraySeg:WORD                                                 ;@T18

    INCLUDE OS2CHAR.INC                 ; Data definitions
.xlist
    INCLUDE SMRGETCB.INC
    INCLUDE SMRSGCB.INC
.xcref
    INCLUDE ERROR2.INC
    INCLUDE STRUC.INC
.cref
.list

_DATA   SEGMENT WORD PUBLIC 'FAR_DATA' USE16                       ;@T18;MDLL
_DATA   ENDS                                                            ;@T18

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

    PUBLIC DOSSMGETSGCB
DOSSMGETSGCB PROC FAR

    Local_Bytes EQU  0
    ENTER Local_Bytes,0

    PUSH BX                             ; Save Registers
    PUSH DX                                                             ;@T18
    PUSH DI                                                             ;@T18
    PUSH DS
    PUSH ES

    MOV  AX, CDATA                                                      ;@T52
    MOV  DS, AX

    MOV  AX, _DATA                      ; Gain access to instance data  ;@T18
    MOV  ES, AX                                                         ;@T18

;   ******************************************
;   *  Initialize SGCB data if not done yet  *
;   ******************************************
    .IF  < SMInitialized e No >
      CALL FAR PTR DOSSMINITSGCB
    .ENDIF

    MOV  BX, SS:[BP].GetSGCB_ID         ; SGID in BX

    TEST SS:[BP].GetSGCB_SearchType, 8000H                              ;@T18
    .IF  < z >                          ; Skip serialization?           ;@T18
      PUSH 1                            ; Disable signals so won't die  ;CJ39
      CALL DOSHOLDSIGNAL                ; owning SMQueueRamSem          ;CJ39

      PUSH DS                           ; Queue access semaphore
      PUSH OFFSET SMQueueRamSem
      PUSH DWORD PTR -1                 ; Wait until queue available    ;@T18
;     PUSH -1                                                           ;@T18
      CALL DOSFSRAMSEMREQUEST
    .ENDIF                                                              ;@T18

    MOV  DX, WORD PTR SMArray[2]        ; Get Array selector            ;@T18
    SUB  AX, AX                         ; Clear RC                      ;@T18
    .IF  <ES:ArraySeg ne DX>            ; Do not have access?           ;@T18
      PUSH DX                           ; Selector of Array             ;@T18
      CALL DOSGETSEG
      MOV  ES:ArraySeg, DX              ; Save it                       ;@T18
    .ENDIF                                                              ;@T18

;   *******************************************
;   *  If we're looking up on the PID, look   *
;   *  in PIDArray for the PID, & the offset  *
;   *  into PIDArray gives us the SGID        *
;   *******************************************
    .IF  < <BYTE PTR SS:[BP].GetSGCB_SearchType> e PID_Lookup > ; Search PID?
      LES  DI, SMPIDArray               ; ES:[DI] --> Array of PIDs
      INC  DI                           ; Skip over reserved word
      INC  DI
      XOR  AX, AX                       ; Use AX as a counter

      .REPEAT
        INC  DI                         ; Check another PID
        INC  DI
        INC  AX                         ; Use AX as a counter
      .UNTIL < AL ae SMArraySize > OR   ; Stop when at end
      .UNTIL < ES:[DI] e BX >           ; If we found the PID

      .IF  < AL ae SMArraySize >        ; Didn't find the PID
        MOV  AX, Error_SMG_Session_Not_Found
      .ELSE                             ; Found the PID
        MOV  BX, AX                     ; SG # in BX
        XOR  AX, AX                     ; Set good RC
      .ENDIF
    .ENDIF                              ; PID Lookup Test
    XOR  BH, BH                         ; Use only SG number and not type @@A4

    .IF  < zero AX >                                                    ;@T18
;     ************************************************
;     *  Get SGCB address out of Array of addresses  *
;     ************************************************
      LES  DI, SMArray                  ; ES:[DI] --> Array of addresses
      SHL  BX, 3                        ; 8 BYTEs per SGCB entry        ;CJ26
      ADD  BX, 2                        ; Because 1st word of Array is reserved

      MOV  AX, WORD PTR ES:[DI][BX+2]   ; Get SGCB selector             ;@T18
      .IF  < nonzero AX >               ; Valid SGCB selector?          ;@T18
        .IF  < DX ne AX >               ; Do not have access to SGCB?   ;@T18
;       *********************************************
;       *  Make sure caller has access to selector  *
;       *********************************************
          PUSH AX                       ; Get access to selector        ;@T18
          CALL DOSGETSEG                ; Get selector into our LDT
        .ENDIF
        MOV  EAX, DWORD PTR ES:[DI][BX] ; Get SGCB address              ;@T18

        LES  BX, SS:[BP].GetSGCB_Address ; ES:[BX] --> Caller's output
        MOV  ES:[BX], EAX               ; Return SGCB ptr to caller
        SUB  EAX, EAX                   ; Clear return code             ;@T18
      .ELSE                             ; Invalid Session
        MOV  AX, Error_SMG_Session_Not_Found
      .ENDIF                            ; Valid Session Test from SGID
    .ENDIF                              ; Valid Session Test from PID

;   *****************************
;   *  Free the SGCB semaphore  *
;   *****************************
    TEST SS:[BP].GetSGCB_SearchType,8000H                               ;@T18
    .IF  < z >                          ; Skip serialization?           ;@T18
      PUSH AX                           ; Save meaningful return code
      PUSH DS                           ; Queue access semaphore
      PUSH OFFSET SMQueueRamSem
      CALL DOSFSRAMSEMCLEAR

      PUSH 0                            ; Re-enable signals             ;CJ39
      CALL DOSHOLDSIGNAL                                                ;CJ39

      POP  AX                           ; Restore meaningful return code
    .ENDIF                                                              ;@T18

    POP  ES                             ; Restore Registers
    POP  DS
    POP  DI                                                             ;@T18
    POP  DX                                                             ;@T18
    POP  BX

    LEAVE
    RET  SMGetSGCB_Len                  ; Return to caller

DOSSMGETSGCB ENDP

CODE_TUNE1   ENDS                                                       ;MDLL


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

;***************************************************************************
;*                                                                         *
;*  DOSSMINITSGCB                                                          *
;*                                                                         *
;*  Initializes memory for the SGCBs.                                      *
;*                                                                         *
;***************************************************************************

    Initial_SGs EQU 25

PUBLIC DOSSMINITSGCB
DOSSMINITSGCB PROC FAR
    ASSUME CS:_TEXT,DS:CDATA,SS:NOTHING,ES:NOTHING                      ;@T52

;   ENTER 0,0                                                           ;@T18

    PUSH DS
    PUSH ES                                                             ;@T18

    MOV  AX, CDATA                                                      ;@T52
    MOV  DS, AX

    MOV  AX, _DATA                                                      ;@T18
    MOV  ES, AX                                                         ;@T18

;   *******************************
;   *  Create Array and PIDArray  *
;   *******************************
    PUSH DS                             ; CDATA                         ;@T52
    PUSH OFFSET SMArray                 ; Address of Array
    PUSH 8 * Initial_SGs                ; 25 SGCB addresses             ;CJ26
    CALL DOSSMGETMEM

    MOV  AX, WORD PTR SMArray[2]        ; Record array selector to      ;@T18
    MOV  ES:ArraySeg, AX                ;   avoid unnecessary GetSegs   ;@T18

    MOV  SMArraySize, Initial_SGs       ; Number of SGCB addresses in Array

    PUSH DS                             ; CDATA                         ;@T52
    PUSH OFFSET SMPIDArray              ; Address of PIDArray
    PUSH 2 * Initial_SGs                ; 10 PIDs
    CALL DOSSMGETMEM

;   **********************************
;   *  Create Screen Groups 0 and 3  *
;   **********************************
;   ****************************************
;   *  Allocate memory for SGCB 0 and put  *
;   *  it's address directly in Array      *
;   ****************************************
    LES  DI, SMArray
    ADD  DI, 2                          ; Point past reserved WORD
    PUSH ES                             ; ES:[DI] --> 1st address in Array
    PUSH DI                             ; Point to SG0's offset in Array
    PUSH SGCB_Size                      ; Number of bytes to allocate
    CALL DOSSMGETMEM                    ; Allocate some memory

;   *****************************************
;   *  Allocate memory for SGCB 3 and put   *
;   *  it's address directly in Array       *
;   *****************************************
    ADD  DI, 3*8                        ; Point to 3rd SGCB entry       ;CJ26
    PUSH ES                             ; ES:[DI] --> 3rd address in Array
    PUSH DI                             ; Point to SG3's offset in Array
    PUSH SGCB_Size                      ; Number of bytes to allocate
    CALL DOSSMGETMEM                    ; Allocate some memory

;   ***********************************************
;   *  Put SGID and Session type in SGCB 0 and 3  *
;   ***********************************************
    LES  DI, ES:[DI]                    ; @ of SGCB 3
    MOV  ES:[DI].SGCB_ID, 103h          ; Session ID
    MOV  ES:[DI].SGCB_Type, FS_Type     ; Session Type

    LES  DI, SMArray                    ; Get @ for SGCB 0
    LES  DI, ES:[DI][2]                 ; @ of SGCB 0
    MOV  ES:[DI].SGCB_ID, 100h          ; Session ID
    MOV  ES:[DI].SGCB_Type, FS_Type     ; Session Type

    MOV  SMInitialized, Yes               ; Say we're done!

    POP  ES                                                             ;@T18
    POP  DS                             ; Restore caller's DS
;   LEAVE                                                               ;@T18
    RET

DOSSMINITSGCB ENDP


_TEXT   ENDS                                                            ;@T52
endif
    END
