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

;************************************************************************
;
; Source File Name:     SMRINIT.ASM
;
; Subroutine Name:      DOSSMINITIALIZE
;
; Descriptive Name:     Session Manager Router Initialization
;
; Function:     Initialize the Session Manager, save the Shell
;               notification semaphores, and allocate a segment
;               for DOSSMGETSTATUS.
; Notes:
;       Dependencies:   None
;
;       Restrictions:   None
;
; Change History:
;      @TL7   04/05/90  PTR B712376 - Enable for MMIO
;      @CJ10  05/04/90  PTR B712103 Hot Keying performance too slow.
;      @D1088 07/07/90  DCR 1088 Add support for special needs.
;      @MHW   09/13/90  PTR B715818 - Removed MMIO support.
;      CJ35   06/20/91  PTR B723977 Sync up with SysInit for it to die.
;
; Entry Point:
;       Linkage:  EXTRN DOSSMINITIALIZE : FAR
;                       PUSH@   Other  ShellData  ; Shell Notification
;                                                 ;       Semaphores
;                       CALL    DOSSMINITIALIZE
;
; Inputs:
;
;       Other   ShellData  A structure containing information that
;                          must be shared between the Shell and
;                          the Session Manager Router.
;       WORD    ShellLen   Length of ShellData in bytes (10, 14 or 16)
;       DWORD   RedrawSem  Address to a RAM semaphore to be
;                          cleared to notify the Shell that
;                          a screen refresh may be required.
;       DWORD   TermSem    Address to a RAM semaphore to be
;                          cleared to notify the Shell that
;                          a foreground session has terminated.
;       DWORD   Reserved   Reserve a double word on stack for
;                          future use.
;       WORD    PMExist    0 = Presentation Manager not present
;                          1 = Presentation Manager is present
;
; 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_invalid_data_length
;                          error_smg_no_hard_errors
;
;                          DOSREALLOCSEG    errors
;                          DOSSMSGINIT      errors
;                          DOSWINPROC       errors
;
; Effects:      All other registers preserved.
;
; Internal References:
;          Data:        RDATA - common data segment (Router data declarations)
;                       SESDATA - common data segment (Active session data)
;          Routines:    GETINFOSEGS
;
; External References:
;          Routines:    DOSSMSGINIT
;                       DOSSEMSET
;                       DOSSEMCLEAR
;                       DOSREALLOCSEG
;                       DOSFREESEG
;                       DOSGETSEG
;                       DOSSGDDNOTIFY
;
;************************************************************************
ifdef I1
;
;
;      IF (Correct input size) AND
;      IF (PM is present)
;         DOSWINPROC (Load PM modules)
;         IF (Error)
;            Set maximum DosStartSession parms = 30
;         ENDIF
;         DOSWINPROC
;      ELSE
;         Set maximum DosStartSession parms = 30
;      ENDIF
;   ENDIF
;
;   IF (sdlength e 1.0 size)
;      Push zeros for PM dynalink name
;   ELSEIF (sdlength e 1.1 size)
;      IF (PM Exists input parm set)
;        Push address of PM dynalink name
;      ELSE
;        Push zeros for PM dynalink name
;      ENDIF
;   ELSE
;     RC = Error_SMG_Invalid_Data_Length
;   ENDIF
;
;   IF (No_Error)
;     CALL  DOSSMSGINIT(Initialize the Session Manager)
;     Copy default program name to RDATA
;   ENDIF
;
;   IF (No_Error during initialization)
;      IF (ShellLen = 1.0 size) OR
;      IF (ShellLen = 1.1 size)
;         Save address of redraw notify semaphore
;         DOSSEMSET(Set Shell redraw semaphore)
;         Save address of terminate notify semaphore
;         DOSSEMSET(Set the redraw semaphore)
;         DOSSEMSET(Set Shell terminate semaphore)
;         GETINFOSEGS
;         IF (Bimodal configuration)
;            Flag no VDM's
;            IF (PM does not exist)
;               Disallow VMD & PM Starts
;            ENDIF
;         ENDIF
;         DOSSMNOTIFYDD (Notify Device Drivers of creation of SG 1)
;      ELSE
;         RC = Error_SMG_Invalid_Data_Length
;      ENDIF
;   ENDIF
;   DOSSEMCLEAR (Clear System Initialization Semaphore)
;
;************************************************************************
else

.386C
    EXTRN DOSWINPROC       : NEAR       ; Load winner & set up proc addresses ES
    EXTRN GETINFOSEGS      : NEAR       ; Get information segment selectors
    EXTRN DOSFREESEG       : FAR        ; Free Device Driver Names Segment
    EXTRN DOSSEMCLEAR      : FAR        ; Clear synchronization semaphore
    EXTRN DOSSEMSET        : FAR        ; Unconditionally set semaphore
    EXTRN DOSSMSGINIT      : FAR        ; Session Manager initialization
    EXTRN DOSGETSEG        : FAR        ; Get segment shared from sysinit
    EXTRN DOSSMNOTIFYDD    : FAR        ; Notify DD's from SG 0 to SG 1 switch
    EXTRN DOSSMREGISTERDD  : FAR        ; Register the keyboard for us

    INCLUDE SMRSTRSE.INC
    INCLUDE SMRDATA.INC                 ; Router data declarations
    INCLUDE SMRINIT.INC                 ; Stack frame definitions
    INCLUDE ERROR2.INC                  ; Error code equates
    INCLUDE INFOSEG.INC                 ; Information segment defintions
    INCLUDE STRUC.INC
.cref
.list


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

    PUBLIC DOSSMINITIALIZE
DOSSMINITIALIZE PROC FAR

    Local_Bytes  EQU 12
    Local_Var1   EQU SS:[BP][-4]
    Temp_RegDD   EQU SS:[BP][-12]

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

    MOV  AX, RDATA                      ; Addressability to common data
    MOV  DS, AX

;   ****************************************************
;   *  Initialize Session Manager and Screen Switcher  *
;   ****************************************************
    XOR  DX, DX                         ; Preset to No_Error
    XOR  AX, AX                         ; Set to good return code       ;@CJ10
    MOV  AX_Reg[-Local_Bytes], AX       ; assume no error

    LES  DI, SS:[BP].ShellSem           ; Get Shell notify semaphores
;   *********************************************************************
;   *  We now call DOSWINPROC to load the needed PM modules, and get a  *
;   *  handle to them.                                                  *
;   *********************************************************************
    .IF  < ES:[DI].SdLength eq ShellData_Size > AND
    .IF  < ES:[DI].SInitPMExists eq Present > ; PM is really there
      MOV  AX, RDATA
      MOV  FS, AX
      MOV  CX, PMProcs                ; Set up loop
      LEA  BX, WinInitSession_Name
      LEA  DX, WinInitSession         ; Identify ourselves to Doswinproc
      LEA  SI, Winner_Handle          ; Pass module name/hdle loc
      CALL DOSWINPROC

      .IF  < nonzero AX >             ; If Error Loading PM             ;@CJ10
        MOV  StartParmsMaxLen, Start_PgmType_Len
        XOR  AX, AX
      .ENDIF

      MOV  CX, PMVioProcs             ; Set up loop
      LEA  BX, WinCreateConsole_Name
      LEA  DX, WinCreateConsole       ; Identify ourselves to Doswinproc
      LEA  SI, PMVioP_Handle          ; Pass module name/hdle loc
      CALL DOSWINPROC

    .ELSE                             ; PM not there
      MOV  StartParmsMaxLen, Start_PgmType_Len
      XOR  AX, AX
    .ENDIF                            ; PM existence test
    MOV DX, AX                        ;

    .IF  <ES:[DI].SDLength e <Version1_0_Size> > ; If version 1.0
      PUSH DWORD PTR 0                  ; Presentaion Manager DLL Name  ;@CJ10
    .ELSEIF <ES:[DI].SDLength e ShellData_Size >
      .IF  < ES:[DI].SInitPMExists eq Present > ; PM is really there
        PUSH DS                         ; Presentaion Manager DLL Name Sel.
        PUSH OFFSET Winner_Module       ; Presentaion Manager DLL Name Off.
        MOV  PM_Present, Yes            ; Set flag for call to initialize
      .ELSE                             ; PM not present
        PUSH DWORD PTR 0                ; Specify no PM DLL             ;@CJ10
      .ENDIF                            ; PM present test
    .ELSE                               ; Illegal data length
      ADD  SP, 8                        ; Get parms & local data off stack
      MOV  DX, Error_SMG_Invalid_Data_Length
    .ENDIF

;   ********************************************************
;   *  Since the Keyboard initializes at ring 0, it can't  *
;   *  call DosSMRegisterDD.  So, we'll do it for them!    *
;   ********************************************************
    LEA  SI, Temp_RegDD             ; Structure for DosSMRegisterDD
    MOV  WORD PTR SS:[SI][0], 8     ; Length of structure
    MOV  WORD PTR SS:[SI][2], KBD_Notifications ; Notification Bitmap
    MOV  AX,  RDATA
    SHL  EAX, 16                    ; Selector in high word
    MOV  AX, OFFSET KeyFileName     ; Offset in low word
    MOV  DWORD PTR SS:[SI][4], EAX  ; Put @ in structure

    PUSH SS
    PUSH SI
    CALL DOSSMREGISTERDD

    CWDE                                                                ;@CJ10

    .IF  < zero DX >                                                    ;@CJ10
      LEA  BX, Local_Var1               ; BX --> local variable
      PUSH SS                           ; DOSSMSGINIT will return the @ of
      PUSH BX                           ; default program on the stack
      CALL DOSSMSGINIT

;     ****************************************************************
;     *  Get the address of the default program name off the stack.  *
;     ****************************************************************
      LDS  SI, Local_Var1               ; BX --> local variable
      .IF < AX eq Error_SMG_No_Hard_Errors >
        MOV  AX_Reg[-Local_Bytes], AX   ; Place return code on the stack
        XOR  AX, AX                     ; indicate no error             ;@CJ10
      .ENDIF

;     *************************************************
;     *  Copy the default program name to RDATA so    *
;     *  the high level code can use it when needed.  *
;     *************************************************
      MOV  DX, AX                       ; Save the return code
      PUSH ES                           ; Save registers
      PUSH DI

      MOV  AX, RDATA                    ; Put the ASCIIZ string here
      MOV  ES, AX
      MOV  DI, OFFSET DefPgmName

      .REPEAT
        LODSB                           ; Get byte into AX from DS:SI
        STOSB                           ; Copy into RDATA
      .UNTIL < AL eq 0 >                ; Stop when hit the 0

      POP  DI                           ; Restore registers
      POP  ES

      MOV  AX, RDATA                    ; Get DS pointing back to RDATA
      MOV  DS, AX
    .ENDIF                              ; AX ne 0 test
    MOV  AX, DX                         ; Get return code into AX

;   **********************************************************************
;   *  Session Manager initialized successfully, save shell semaphore @  *
;   **********************************************************************
    .IF  < zero AX >       near         ; Session Manager Initialized?  ;@CJ10
      .IF  < ES:[DI].SDLength eq ShellData_Size> OR NEAR ; Valid length?
      .IF  < ES:[DI].SDLength eq <Version1_0_Size>> NEAR
        MOV  EAX, DWORD PTR ES:[DI].SDRedrawSem ; Get redraw sem address;@CJ10
        MOV  DWORD PTR DS:ShellRedrawSem, EAX                           ;@CJ10
;CJ10   MOV  BX, ES:[DI+2].SDRedrawSem
;CJ10   MOV  DS:WORD PTR ShellRedrawSem[2], BX

;CJ10   PUSH BX                                 ; Set the redraw semaphore
        PUSH EAX                                                        ;@CJ10
        CALL DOSSEMSET

        MOV  EAX, DWORD PTR ES:[DI].SDTerminateSem ; Get term. sem address ;CJ10
        MOV  DWORD PTR DS:ShellTermSem, EAX                             ;CJ10
;CJ10   MOV  DX, ES:[DI+2].SDTerminateSem
;CJ10   MOV  DS:WORD PTR ShellTermSem[2], DX

;CJ10   PUSH DX                                 ; Set the terminate semaphore
        PUSH EAX                                                        ;CJ10
        CALL DOSSEMSET

        PUSH DS                         ; Save global data selector
        CALL GETINFOSEGS                ; Get information selectors

;CJ10   XOR  BH, BH
;CJ10   MOV  BL, DS:SIS_MaxScrnGrp      ; Get maximum # full screen SGs
        MOV  DX, ES:LIS_CurProcID       ; Get Shell process ID

        POP  ES                         ; ES --> RDATA

        .IF < DS:SIS_ProtMdOnly ne 0 >          ; Bimodal configuration?
          OR   ES:SMG_Flags, Protect_Mode_Only  ; Flag no VDMs
          .IF  < ES:PM_Present e No >           ; If PM not here either,
            MOV  ES:StartParmsMaxLen, Start_Inherit_Len  ; Disallow VDM & PM starts.
          .ENDIF
        .ENDIF

        MOV  AX, RDATA
        MOV  DS, AX
        MOV  ShellPID, DX               ; Save shell process ID

;       *********************************************************
;       *  Indicate that the session Manager has safely gotten  *
;       *  through initialization and is now ready for work.    *
;       *  And don't let any more device drivers register       *
;       *  themselves for screen switch notification.           *
;       *  Notify Device Drivers that we are in SG 1.           *
;       *                                                       *
;       *  NOTE: RC from DosSMNotifyDD is always 0, so, if we   *
;       *        move the call from here, make sure AX <-- 0!!  *
;       *********************************************************
        OR   SMG_Flags, InitDone        ; Turn Bit On

;@D1088 PUSH Post_Save_Notification     ; Not. Type
;@D1088 PUSH 1                          ; Incoming SG
;@D1088 PUSH 0                          ; Current SG

        MOV  NotDD_DosDev_Data_Len, Version_1_2_Len          ;data len  ;@D1088
        MOV  NotDD_Notification_Type, Post_Save_Notification ;type      ;@D1088
        MOV  NotDD_InSG_or_OutType, 1      ; Incoming SG                ;@D1088
        MOV  NotDD_InType_or_OutSG, 0      ; Outgoing SG                ;@D1088
        PUSH DS                            ; Address of NotifyDD data   ;@D1088
        PUSH OFFSET NotDD_DosDev_Data_Len                               ;@D1088
        CALL DOSSMNOTIFYDD
      .ELSE                             ; Invalid Length
        MOV  AX, Error_SMG_Invalid_Data_Length
      .ENDIF                            ; Length check
    .ENDIF

    .IF < nonzero AX >                                                  ;@CJ10
      MOV  AX_Reg[-Local_Bytes], AX     ; Place return code on the stack
    .ENDIF

;   ************************************************************
;   *  Clear Semaphore to allow System Initialization to die.  *
;   ************************************************************
    .IF <DS:PM_Present eq 0>                                            ;4Meg
      PUSH DS                           ; @ of SysInit_Semaphore
      PUSH OFFSET DOSSMSYSINIT                                          ;CJ35
      CALL DOSSEMCLEAR
    .ENDIF                                                              ;4Meg
    POP  GS                             ; Restore registers
    POP  FS
    POP  ES
    POP  DS
    POPA

    LEAVE
    RET  SMRInitLen

DOSSMINITIALIZE ENDP

CODE ENDS
endif
    END
