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

;************************************************************************
;
; Source File Name:     SMGINIT.ASM
;
; Subroutine Name:      DOSSMSGINIT
;
; Descriptive Name:     Session Manager Initialization
;
; Function:     Allocate and initialize screen group queue, initialize
;               the screen switcher, and create required threads.
;
; Notes:
;       Dependencies:   None
;
;       Restrictions:   Maximum number of screen groups that can be
;                       supported without code modifications is 254.
;
; Change History:
;   @@A5  02/16/90  PTR B787589 - Use pause semaphore in SGCB
;   @CJ5  03/21/90  PTR HZ00417 Synchronize initialization for
;                   DosSMNotifyDD - set SMG_flags in DosSMNotifyDD2.
;   @TL7  04/05/90  PTR B712376 - Enable for MMIO
;   @CJ10 05/04/90  PTR B712103 Hot Keying performance too slow.
;   @D981 08/27/90  DCR 981 Notification for DLLs.
;   @MHW  09/13/90  PTR B715818 - Removed MMIO support.
;   CJ25  05/01/91  PTR B722318 Use local variables for thread stack address.
;   CJ26  05/12/91  PTR B722846 Free memory allocated for Cwait thread stack.
;   MD00  06/12/91  PTR B730585 Parse CMD.EXE from OS2_SHELL not PROTSHELL.
;   CJ56  02/29/92  PTR B733713 Don't import DLLs - dynmaically link.
;
; Entry Point:
;       Linkage:  EXTRN DOSSMSGINIT:FAR
;                       PUSH@   DWORD PMName      ; Name of PM DLL
;                       PUSH@   DWORD DefPgmName  ; Default Program Name
;                       CALL    DOSSMSGINIT
;
; Inputs:
;       DWORD   PMName        Address of the ASCIIZ string name of
;                             the Presentation Manager Dynalink, or
;                             DWORD of 0's, if no name.
;       DWORD   DefPgmName    Address of the default program name.
;
; Exit Normal:
;       AX      ReturnCode Value = 0, Initialization successful
;
; Exit Errors:
;       AX      ReturnCode error_scs_not_session_mgr
;                          error_smg_bad_reserve
;                          error_smg_invalid_call
;                          error_smg_no_hard_errors
;
;                          DOSEXECPGM       errors
;                          DOSGETENV        errors
;                          DOSSGSWITCHPROC2 errors
;                          DOSSMINITALLOC   errors
;                          DOSSMNEWTHREADS  errors
;                          DOSSSINIT        errors
;
; Effects:      All other registers preserved.
;
; Internal References:
;          Routines:    DOSSMINITALLOC
;                       DOSSMADDSGQUEUE
;                       DOSSMPARSEPATH
;                       DOSSMNEWTHREADS
;
;
; External References:
;          Routines:    DOSENTERCRITSEC
;                       VIOSHELLINIT
;                       KBDSHELLINIT
;                       DOSGETDBCSEV
;                       DOSGETINFOSEG
;                       DOSSGSWITCHME
;                       DOSSSINIT
;                       DOSSGDDNOTIFY
;                       KBDCHARIN
;                       DOSGETENV
;                       DOSEXITCRITSEC
;
;************************************************************************
ifdef I1
;
;   IF (first call to DOSSMSGINIT)
;      DOSSEMSET (Set popup semaphore for VIO)
;      DOSSGSWITCHME (Switch Shell/Session Manager into sg#1)
;      KBDSHELLINIT (Initialize KBD router)
;      DOSGETDBCSEV (Get DBCS environment vector)
;      DOSGETINFOSEG (Get informaiton segment selectors)
;      DOSSMINITALLOC (Pre-Allocate and initialize active queue)
;      IF (No_Error)
;        VIOSHELLINIT (Initialize VIO router)
;
;        IF (No_Error)
;           DOSSMOPENDD (Open registerd DDs and DLLs)
;           IF (Sesmgr is to do notifications)
;              Set flag that notification initailization done
;           ENDIF
;           DOSEXECPGM (Exec Harderr and Prt Scrn processes)
;           IF (No_Error)
;              DOSSGSWITCHPROC2 (Move hard error pid to sg#0)
;           ELSE
;              Set AX to 0 to allow further initialization
;           ENDIF
;        ENDIF
;
;        IF (No error)
;           DOSSSINIT
;           IF (No error)
;              DOSSGDDNOTIFY
;              KBDCHARIN (Wake up keyboard device driver)
;              DOSGETENV (Get Shell command line)
;              IF (No_Error)
;                 Parse PROTSHELL statement for command interpreter
;                 IF (protectonly)
;                    Set flag
;                 ENDIF
;                 IF (No_Error)
;                    DOSSMNEWTHREADS (Spawn required Session Manger threads)
;                 ENDIF
;              ENDIF
;           ENDIF
;        ENDIF
;
;        IF (Hard error pid ne 0)
;           DOSSEMSET (Set harderr semaphore)
;           DOSSYSTEMSERVICE (Thaw the Hard Error Process)
;           DOSSEMWAIT (Wait for harderr daemon to clear or time out)
;        ENDIF
;      ENDIF
;   ELSE
;      RC = Error_SMG_Invalid_Call
;   ENDIF
;************************************************************************
else

.386C
;   **************************************************
;   *  See SMGINIT.INC for all the EXTRN statements  *
;   **************************************************

    EXTRN HardError_Do_NotifyDD   : WORD ; Flag for who does notifcations @CJ10
    EXTRN DD_Handles              : WORD ; Array of Device Driver Handles @CJ10,@D1088
    EXTRN QHMOUSEHANDLE           : WORD                                 ;@CJ10
    EXTRN QHKEYBDHANDLE           : WORD                                 ;@CJ10
;   EXTRN DosGetDBCSEv_Ord        : WORD                                 ;MDLL
    EXTRN DOSGETDBCSEV            : FAR                                  ;MDLL
;   EXTRN NLS_Handle              : WORD                                 ;MDLL

;   EXTRN DOSWINPROC              : NEAR ; LoadModule and get proc addrs ;MDLL
    EXTRN DOSSMOPENDD             : FAR  ; Open any registered DDs/DLLs  ;@D981
.xlist
    INCLUDE INFOSEG.INC
    INCLUDE SMGINIT.INC
    INCLUDE SMRSGCB.INC
    INCLUDE SMRRDATA.INC
.xcref
    INCLUDE ERROR.INC
    INCLUDE ERROR2.INC
    INCLUDE STRUC.INC
.cref
.list

CODE SEGMENT WORD PUBLIC 'CODE' USE16
    ASSUME CS:CODE,DS:RDATA,SS:NOTHING,ES:NOTHING

    PUBLIC DOSSMSGINIT
DOSSMSGINIT PROC FAR

    Local_Bytes  EQU  0

    ENTER Local_Bytes,0
    PUSHA                               ; Save registers
    PUSH DS
    PUSH ES
    PUSH FS                                                             ;CJ56

    XOR  AX, AX                         ; Initialize error code
    .IF  < TotalScrnGrps ne 0 >         ; First call to initialize?
      MOV  AX, Error_SMG_Invalid_Call
    .ENDIF
;   ******************************************************************
;   *  Enter critical section to block any other Base Shell threads  *
;   ******************************************************************
    .IF  < AX eq No_Error > NEAR
      PUSH DS
      PUSH OFFSET PopVioRamSem
      CALL DOSSEMSET                    ; Set popup semaphore for VIO

;CJ10 PUSH 1                            ; Base Shell screen group ID
      PUSH DWORD PTR 10000H             ; Make screen group foreground  ;CJ10
      CALL DOSSGSWITCHME                ; Make sure in screen group 1

      CALL KBDSHELLINIT                 ; Initialize KBD router

;MDLL MOV  AX, RDATA                    ; Setup for DosWinProc          ;CJ56
;MDLL MOV  FS, AX                                                       ;CJ56
;MDLL MOV  CX, 1                        ; Set up loop - load only 1 proc;CJ56
;MDLL LEA  BX, DosGetDBCSEv_Ord                                         ;CJ56
;MDLL LEA  DX, DosGetDBCSEv             ; Identify ourselves to Doswinproc;CJ56
;MDLL LEA  SI, NLS_Handle               ; Pass module name/hdle loc     ;CJ56
;MDLL CALL DOSWINPROC                                                   ;CJ56

;MDLL .IF  < zero AX >                  ; If Error Loading PM           ;CJ56
        PUSH 16                         ; length of buffer
        PUSH DS                         ; Country code address
        PUSH OFFSET CountryCode
        PUSH DS                         ; DBCS environment vector address
        PUSH OFFSET DBCSVector
        CALL DOSGETDBCSEV                                               ;MDLL
;MDLL .ENDIF                                                            ;CJ56

;     *************************************************
;     *  Get the information segment (maximum screen  *
;     *  groups, process ID, real mode information)   *
;     *************************************************
      PUSH DS                           ; Global information selector
      PUSH OFFSET GlobalSelector
      PUSH DS                           ; Local information selector
      PUSH OFFSET LocalSelector
      CALL DOSGETINFOSEG
      MOV  ES, GlobalSelector

;     *******************************************
;     *  Allocate and initialize active screen  *
;     *  group queue and semaphores             *
;     *******************************************
      XOR  BH, BH                       ; Maximum number of screen groups
      MOV  BL, ES:SIS_MaxScrnGrp
      MOV  TotalScrnGrps, BX
      CALL DOSSMINITALLOC

      .IF  < zero AX >                                                  ;CJ10
        CALL VIOSHELLINIT               ; Initialize VIO and BVS

;       ************************************************
;       *  Create hard error and print screen process  *
;       ************************************************
        .IF  < zero AX >                                                ;CJ10

;         ***********************************************               ;@D981
;         * Open registered DDs and DLLs.  If sesmgr is *               ;@D981
;         * to do the notifications, then set flag that *               ;@D981
;         * notification initialization is done.        *               ;@D981
;         ***********************************************               ;@D981
          CALL DOSSMOPENDD              ; Open DDs/DLLs for notifies    ;@D981
         .IF  < HardError_Do_NotifyDD eq No >    ; Sesmgr to do notifies;@D981
           OR   SMG_Flags, Notify_Thread_Start   ; Turn Bit On          ;@D981
         .ENDIf                                                         ;@D981

;CJ10     PUSH 0
          PUSH DWORD PTR 0              ; address to ObjNameBuf         ;CJ10
;CJ10     PUSH 0                        ; ObjNameBufL
          PUSH DWORD PTR 5              ; async option (Frozen)         ;CJ10

          .IF  < <WORD PTR SS:[BP].InitPMName+2> ne NULL >
;CJ10       PUSH WORD PTR SS:[BP].InitPMName+2  ; PM DLL name
            PUSH DWORD PTR SS:[BP].InitPMName   ; name @                ;CJ10
          .ELSE                         ; PM not present
            PUSH DWORD PTR 0            ; Input argument string address ;CJ10
;CJ10       PUSH 0
          .ENDIF                        ; PM present test

          PUSH DWORD PTR 0              ; Inherit present environment   ;CJ10
;CJ10     PUSH 0
          PUSH DS                       ; Process ID address (Returned)
          PUSH OFFSET HardErrPID
          PUSH DS                       ; Program name addr
          PUSH OFFSET HdeProc
          CALL DOSEXECPGM               ; Start Harderr.Exe

          .IF  < zero AX >              ; Hard error exec ok            ;CJ10
            PUSH HardErrPID             ; Move HardError PID to
            PUSH 0                      ;     Screen group 0
            PUSH LIS_PT_FULLSCRN        ; Session type = Full
            CALL DOSSGSWITCHPROC2       ; Switch proc.

;           ************************************************
;           *  Indicate that the notify thread is started  *
;           ************************************************
;@CJ5****** OR   SMG_Flags, Notify_Thread_Start ; Turn Bit On
          .ELSE                         ; DOSEXECPGM Failed to start HardErr.Exe
            SUB  AX, AX                 ; Continue to initialize        ;CJ10
          .ENDIF                        ; DOSEXECPGM Test
        .ENDIF                          ; VIOSHELLINIT Test
      .ENDIF                            ; DOSSMINITALLOC Test

;     ****************************************
;     *  Initialize the screen switcher and  *
;     *  make Shell foreground screen group  *
;     ****************************************
      .IF  < zero AX > NEAR                                             ;CJ10
        CALL DOSSSINIT

        .IF  < zero AX > NEAR                                           ;CJ10
;CJ10     PUSH 8000H                    ; No screen group invalidation
          PUSH DWORD PTR 80008001H      ; Base Shell screen group ID    ;CJ10
          PUSH 0                        ; No Debugger
          CALL DOSSGDDNOTIFY            ; Notify device drivers

          PUSH DS                       ; Read nowait so KBDDD
          PUSH OFFSET CharData          ; buffers keystrokes
;CJ10     PUSH 1
          PUSH DWORD PTR 10000H         ; Dummy keyboard handle         ;CJ10
          CALL KBDCHARIN

;         *******************************************
;         *  Parse PROTSHELL statement for command  *
;         *  interpreter and default input args     *
;         *******************************************
          PUSH DS                       ; Address to return envir. sel.
          PUSH OFFSET CmdName[2]
          PUSH DS                       ; Addr. to return cmdline off.
          PUSH OFFSET CmdName           ; C:\CMD.EXE string
          CALL DOSGETENV

          .IF  < AX eq No_Error > NEAR
;           *****************************************************
;           *  Get @ of default program name from CONFIG.SYS    *
;           *****************************************************
            MOV  ES, DS:CmdName[2]      ; Environment selector
;           MOV  DI, DS:CmdName         ; command line offset             ;MD00
            MOV  CmdArgs[2], ES
            CLD                         ; Clear direction
; --------------------------------------------------------------------    ;MD00
            MOV  CX, DS:CmdName         ; length of environment           ;MD00
            MOV  DI, 00                 ; start  of environment           ;MD00
                                                                          ;MD00
MDstart:    MOV  AX, 0FF20H             ; Blank delimiter                 ;MD00
            CALL DOSSMREPE              ; DBCS scan, skip leading blanks  ;MD00
            DEC  DI                     ; Back up to first non blank      ;MD00
            inc  cx                     ;   and fix CX to correspond      ;MD00
            MOV  SI, OFFSET EnvName     ; address of start of string      ;MD00

            push cx                     ; save remaining env. length      ;MD00
            movzx cx, byte ptr DS:EnvNameLen   ; length of string to compare ;MD00
            repe cmpsb                  ; compare string v buffer         ;MD00
            pop  cx                     ; restore remaining env length    ;MD00
            jz   MDfound                ; zero flag set while =           ;MD00

            MOV  AX, 00                 ; Scan for                        ;MD00
            REPNE SCASB                 ;   NULL in buffer                ;MD00
            jcxz MDnotHere              ; CX = 0 so get out               ;MD00
            jmp  MDstart                ; go for next one                 ;MD00

MDfound:    inc  DI                     ; skip over =                     ;MD00
; --------------------------------------------------------------------    ;MD00
            MOV  AL, 0                  ; Scan for end of program name
;           MOV  CX, 0FFFFH                                               ;MD00
;           REPNE SCASB                                                   ;MD00

            PUSH DI                     ; Save start of inputs
            MOV  CX, 0FFFFH             ; Used to calculate len
            REPNE SCASB                 ; Scan for end of cmd line

            SUB  DI, 2                  ; Backup before 0
            INC  CX                     ; Calculate input length
            NEG  CX
            POP  DI                     ; Restore start of inputs
            MOV  AX, 0FF20H             ; Blank delimiter
            CALL DOSSMREPE              ; DBCS scan

            DEC  DI                     ; Back up to non blank
            INC  CX                     ; Adjust length
            MOV  CmdName, DI            ; Save interp offset

            PUSH DS                     ; Save DS
            LDS  BX, SS:[BP].InitDefPgmName
            MOV  [BX],    DI
            MOV  [BX][2], ES
            POP  DS                     ; Restore DS

;           ********************************************************
;           *  Get @ of default program arguments from CONFIG.SYS  *
;           ********************************************************
            CALL DOSSMREPNE             ; DBCS scan
            PUSH DI                     ; Save to create ASCIIZ
            DEC  DI                     ; Back up to non blank
            INC  CX                     ; Adjust length
            CALL DOSSMREPE              ; DBCS scan
            DEC  DI                     ; Back up to non blank
            MOV  CmdArgs, DI            ; Save argument off.

            POP  DI                     ; Offset to create ASCIIZ
            MOV  ES:BYTE PTR [DI-1], 0  ; ASCIIZ name

;           ****************************************************************
;           *  Create additional threads required for the Session Manager  *
;           ****************************************************************
            XOR  BX, BX                 ; Dummy result code
            XOR  DX, DX                 ; Dummy process ID
            MOV  CX, 4                  ; Four smg threads
            MOV  SI, OFFSET NewThreads  ; first thread

            .REPEAT
              PUSH CX                   ; Save loop counter
              XOR  CX, CX               ; Dummy Cwait action
              CALL DOSSMNEWTHREADS      ; Smg Threads
              POP  CX                   ; Restore loop counter
            .LEAVE <nonzero AX >        ; Exit if error                 ;CJ10
              ADD  SI, 8                ; next smg thread          ;CJ25,CJ26
            .LOOP
MDnotHere:
          .ENDIF
        .ENDIF
      .ENDIF
      PUSH AX                           ; Save return code

;@D981 COMMENTED OUT BECAUSE THIS IS DONE IN DOSSMOPENDD NOW
;@D981***********************************************************         @CJ10
;@D981* If Session Manager is to do the Notification IOCtls for *         @CJ10
;@D981* DDs then copy the keyboard and mouse handles into the   *         @CJ10
;@D981* array of device driver handles for notifications.       *         @CJ10
;@D981***********************************************************         @CJ10
;@D981.IF  < HardError_Do_NotifyDD eq No >                               ;@CJ10
;@D981  LEA  BX, DD_Handles                                              ;@CJ10
;@D981  MOV  AX, QHMOUSEHANDLE                                           ;@CJ10
;@D981  .IF  < nonzero AX >           ; If mouse handle exists           ;@CJ10
;@D981    MOV  [BX], AX               ; Copy it into DD_Handles array    ;@CJ10
;@D981    INC  BX                                                        ;@CJ10
;@D981  .ENDIF                                                           ;@CJ10
;@D981  MOV  AX, QHKEYBDHANDLE        ; Copy keyboard handle into        ;@CJ10
;@D981  MOV  [BX], AX                 ; DD_Handles array                 ;@CJ10
;@D981  OR   SMG_Flags, Notify_Thread_Start   ; Turn Bit On              ;@CJ10
;@D981.ENDIF                                                             ;@CJ10

      .IF  < HardErrPid ne Null >       ; If HardErr.Exe started ok
        PUSH DS
        PUSH OFFSET HdeSMGRamSem
        CALL DOSSEMSET

;       ************************************************
;       *  Thaw the Hard Error Process using it's PID  *
;       ************************************************
        MOV  StartActionPacket+2, 1          ; Thaw Process
        MOV  AX, HardErrPID                  ; Process to thaw
        MOV  StartActionPacket+4, AX

        PUSH 0                          ; Session Manager request
        PUSH DS                         ; Action packet
        PUSH OFFSET StartActionPacket
;CJ10   PUSH 0                          ; Null response packet
        PUSH DWORD PTR 0                                                ;CJ10
        CALL DOSSYSTEMSERVICE

        PUSH DS                         ; Wait for either
        PUSH OFFSET HdeSMGRamSem        ;   harderr daemon
;CJ10   PUSH 0                          ;   to clear the
        PUSH DWORD PTR 2710H            ;   semaphore or                ;CJ10
        CALL DOSSEMWAIT                 ;   time out
      .ENDIF                            ; HardErr.Exe started test

      POP  AX                           ; Restore return code
    .ENDIF                              ; Make sure we're only called once test

    .IF  <HdeRC ne 0>                   ; No harderr daemon?
      MOV  AX, HdeRC                    ; Return error to Shell
    .ENDIF

    MOV  AX_Reg[-Local_Bytes], AX       ; Place return code on stack

    POP  FS                                                             ;CJ56
    POP  ES                             ; Restore registers
    POP  DS
    POPA

    LEAVE
    RET  initfrmlen

DOSSMSGINIT ENDP

; ************************************************************************

    PUBLIC DOSSMHDEINIT
DOSSMHDEINIT PROC FAR

    ASSUME DS:NOTHING,ES:NOTHING

    ENTER 0,0                           ; Return address to ram

    PUSH DS                             ;  save regs
    PUSH SI

;   ***************************************************
;   *  Return the flag to indicate whether or not the *
;   *  harderror deamon has to spon the device driver *
;   *  notification thread.                           *
;   ***************************************************
    MOV  AX, RDATA                      ; Get addressability to Global data

    LDS  SI, [BP].HdeInitSemHandle      ; @ in harderror data segment
                                        ; to put array of semaphore @'s
    MOV  WORD PTR DS:[SI], OFFSET HdeSMGRamSem
    MOV  WORD PTR DS:[SI+2], AX

    MOV  DS, AX
    MOV  AX, HardError_Do_NotifyDD

    POP  SI
    POP  DS

    LEAVE
    RET

DOSSMHDEINIT ENDP

CODE ENDS
endif
    END
