;       SCCSID = @(#)smrnotdd.asm       6.1 90/11/18
;       SCCSID @(#)smrnotdd.asm 6.11 90/09/12
PAGE 60,132    ;
; ****************************************************************************
; *                                                                          *
; *                       IBM/Microsoft Confidential                         *
; *                                                                          *
; *                 Copyright (c) IBM Corporation  1987, 1990                *
; *                 Copyright (c) Microsoft Corp.  1987, 1990                *
; *                           All Rights Reserved                            *
; *                                                                          *
; ****************************************************************************

;************************************************************************
;
; Source File Name:     SMRNOTDD.ASM
;
; Subroutine Name:      DOSSMNOTIFYDD, DOSSMNOTIFYDD2 & DOSSMNOTIFYDD_LOOP
;
; Descriptive Name:     Session Manager Notify Device Drivers
;
; Function:     Wakes up harderror deamon to call DosSMNotifyDD2.  We run
;               under the harderror deamon since we can take advantage of
;               all it's free file handles.  DosSMNotifyDD2 then issues
;               an IOCTL to all registered device driver that want to be
;               notified of this screen switch/termination.
;
; Notes:
;       Dependencies:   None
;
;       Restrictions:   None
;
;       Change History:
;
;       @CJ5 - 03/21/90 - PTR HZ00417 Synchronize initialization for
;                         DosSMNotifyDD.
;       @CJ10  05/04/90   PTR B712103 Hot Keying performance too slow.
;       @D1088 07/07/90   DCR 1088 Add support for special needs.
;       @D981  08/27/90   DCR 981 Notification for DLLs.
;       @MHW   09/13/90   PTR B715818 In-line performance (MMIO) hooks
;       MDLL   01/10/94   BJN Page Tune segments for Merged DLL.
;
;************************************************************************
.386P                                                                   ;@D1088
    EXTRN SMG_Flags               : BYTE
    EXTRN DD_Bit_Maps             : WORD ; Array of Notification Bit_Maps
    EXTRN HardError_Do_NotifyDD   : WORD ; Flag for who does notifcations @CJ10
    EXTRN DD_Handles              : WORD ; Array of Device Driver Handles
    EXTRN NotDD_IOCtl_Error       : WORD ;                              ;@D1088
    EXTRN NotDD_DosDev_Data_Len   : WORD ; Data area for DosDevIOCTL ParmList
    EXTRN NotDD_Notification_Type : WORD
    EXTRN NotDD_Data_Address      : DWORD                               ;@D1088
    EXTRN Registered_DDs          : WORD ; # of Registered Device Drivers
    EXTRN SMG_DidNotifyDD         : DWORD ; Sem to wait on harderr for notifydd
    EXTRN SMG_DoNotifyDD          : DWORD ; Sem to wake up harderr for notifydd

    EXTRN DOSDEVIOCTL2 : FAR            ; Notify Device Drivers via IOCTL
    EXTRN DOSSEMCLEAR  : FAR            ; Release semaphore
    EXTRN DOSSEMSET    : FAR
    EXTRN DOSSEMWAIT   : FAR
    EXTRN DOSGETSEG    : FAR                                           ;@D1088
.xlist
.xcref
    INCLUDE STRUC.INC
    INCLUDE BSEERR.INC                                                 ;@D1088
    INCLUDE INFOSEG.INC                 ; needed by smmmpha.inc         ;MHW
    INCLUDE SMMMPHA.INC                 ; Performance hook macros       ;MHW
.cref
    INCLUDE SMRRDATA.INC                ; Global Data Segment & EQU definitions
.list

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

;************************************************************************
;
; Source File Name:     SMRNOTDD.ASM
;
; Subroutine Name:      DOSSMNOTIFYDD
;
; Descriptive Name:     Session Manager Notify Device Drivers
;
; Function:     Wakes up harderror deamon to call DosSMNotifyDD2.  We run
;               under the harderror deamon since we can take advantage of
;               all it's free file handles.
;
; Notes:
;       Dependencies:   None
;
;       Restrictions:   None
;
;       Change History:
;
; Entry Point:
;       Linkage:  EXTRN DOSSMNOTIFYDD : FAR
;                       PUSH    WORD   Notification Type
;                       PUSH    WORD   Incoming Screen Group
;                       PUSH    WORD   Current Screen Group
;                       CALL    DOSSMNOTIFYDD
;
; Inputs:
;       WORD    Notifcation Type  Value = 01, Pre Save
;                                 Value = 02, Post Save
;                                 Value = 04, Post Restore
;                                 Value = 08, Termination
;       WORD    Incoming SGID     SG # of new session if AX=02, 0 otherwise
;       WORD    Current SGID      Screen group number of current session
;
; Exit Normal:
;       AX      ReturnCode Value = 0, successful
; Exit Errors:
;       AX      Never.
;
; Effects:      All other registers preserved.
;
; Internal References:
;          Routines:    DOSSMNOTIFYDD_LOOP
;
; External References:
;          Routines:    DOSDEVIOCTL2
;
;************************************************************************
ifdef I1
;
;   IF (Initialization Done)
;     IF (not called by Sesmgr)              ; must be an AIM notification
;        IF (parm packet length ne AIM notification length)
;           RC = ERROR_SMG_INVALID_DATA_LENGTH
;        ELSEIF (Notification type not AIM_Pre_Save_Notifcation) or
;        IF     (Notification type not AIM_Post_Save_Activation)
;           RC = ERROR_SMG_INVALID_NOTIFICATION
;        ENDIF
;     ENDIF
;     IF (no error)
;        DosSemSet (DidNotifyDDSem)          ; Set sesmgr semaphore
;        DosSemClear (DodNotifyDDSem)        ; Wake up harderror
;        DosSemWait (DidNotifyDDSem)         ; Wait for harderror to finish
;        IF (Notification type = AIM_Pre_Save_Notification) and
;        IF (Invalid AIM parameter returned)
;           RC = ERROR_INVALID_PARAMETER
;        ELSEIF (error returned from DosSMNotifyDD2)
;           RC = error returned from DosSMNotifyDD2
;        ELSE
;           RC = no error
;        ENDIF
;     ENDIF
;   ENDIF
;
;************************************************************************
else

    Parm_Packet_Addr    EQU  (WORD PTR SS:[BP+6])                       ;@D1088

    PUBLIC DOSSMNOTIFYDD
    PUBLIC DOSSMNOTIFYDD_POSTDT
DOSSMNOTIFYDD PROC FAR

    ENTER 0, 0                          ; Stack Frame
    PUSH DS                             ; Save DS
    PUSH ES                             ; Save ES                        ;@D1088
    PUSH DI                             ; Save DI                        ;@D1088
    PUSH DX                             ; Save DX                        ;@D1088
    PUSH CX                             ; Save CX                        ;@D1088
    PUSH BX                             ; Save BX                        ;@D1088

    MOV  AX, RDATA                      ; Global Data Segment
    MOV  DS, AX

    MMPHPreDOSSMNotifyDD                ; Performance Hook (8014h)      ;MHW

;   ************************************************************
;   *  Make sure Notify_Thread_Start has been set in SMG_Flags *
;   *  and there are registered device drivers.                *
;   ************************************************************
    .IF  < bit SMG_Flags AND Notify_Thread_Start > NEAR ; NotifyDD2 started    ;@CJ5

      MOV  EAX, DWORD PTR Parm_Packet_Addr ; Get parm packet address    ;@D1088
      MOV  NotDD_Data_Address, EAX         ; Put in Global data         ;@D1088

      XOR  EAX, EAX                        ; Set EAX to no error        ;@D1088

;     ***************************************************************
;     * If selector for the Parm_Packet_Addr is not equal to RDATA, *
;     * then someone other than SesMgr called us so we have to      *
;     * validate the parameter length and notification type for     *
;     * AIM notification calls.                                     *
;     ***************************************************************
      LES  DI, NotDD_Data_Address          ; ES:DI -> NotifyDD data     ;@D1088
      MOV  BX, ES:[DI].notdd_AIM_Type      ; BX -> notification type    ;@D1088
      MOV  CX, ES                          ; Get data selector          ;@D1088
      .IF  < CX NE RDATA >                 ; If not equal to SesMgr DS  ;@D1088
                                           ; Test for AIM valid lengths ;@D1088
        .IF  < ES:[DI].notdd_AIM_Length NE AIM_Len >                    ;@D1088
          MOV AX, ERROR_SMG_INVALID_DATA_LENGTH                         ;@D1088
                                           ; Test for AIM valid types   ;@D1088
        .ELSEIF  < BX NE AIM_Pre_Save_Notification > AND                ;@D1088
        .IF      < BX NE AIM_Post_Save_Notification >                   ;@D1088
          MOV AX, ERROR_SMG_INVALID_NOTIFICATION                        ;@D1088
        .ENDIF                                                          ;@D1088
      .ENDIF                                                            ;@D1088

      .IF < ZERO AX >                      ; No invalid AIM data        ;@D1088

;     ****************************************************
;     *  If HardError is doing the Notification IOCtls,  *               ;@CJ10
;     *  wake up hard error (DosSMNotifyDD2) which will  *
;     *  then clear SMG_DidNotifyDD to wake us up.       *
;     ****************************************************
        .IF  < HardError_Do_NotifyDD eq Yes >                            ;@CJ10

;         ****************************************************
;         *  Wake up hard error (DosSMNotifyDD2) which will  *
;         *  then clear SMG_DidNotifyDD to wake us up.       *
;         ****************************************************
          PUSH DS                           ; Set a semaphore to wait on
          PUSH OFFSET SMG_DidNotifyDD
          CALL DosSemSet

          PUSH DS                           ; Wake up hard error
          PUSH OFFSET SMG_DoNotifyDD
          CALL DosSemClear

;         ***********************************************
;         *  Wait for hard error thread to wake us up.  *
;         ***********************************************
          PUSH DS                           ; Wait to be woken up by hard error thread
          PUSH OFFSET SMG_DidNotifyDD
          PUSH DWORD PTR -1                                              ;@CJ10
          CALL DosSemWait

;       **********************************************                   ;@CJ10
;       * Else Session Manager is doing Notification *                   ;@CJ10
;       * IOCtls, so just call DOSSMNOTIFYDD_LOOP.   *                   ;@CJ10
;       **********************************************                   ;@CJ10
        .ELSE                                                            ;@CJ10
          PUSH BX                         ; Save registers               ;@CJ10
          PUSH DI                                                        ;@CJ10
          PUSH SI                                                        ;@CJ10
          CALL DOSSMNOTIFYDD_LOOP         ; Do IOCtls                    ;@CJ10
          POP  SI                         ; Restore registers            ;@CJ10
          POP  DI                                                        ;@CJ10
          POP  BX                                                        ;@CJ10
        .ENDIF                                                           ;@CJ10

        Clear EAX                         ; no error                     ;@D1088

;       **********************************************                   ;@D1088
;       * Check for invalid parameter error returned *                   ;@D1088
;       * from IOCtl for AIM_Pre_Save_Notifications. *                   ;@D1088
;       **********************************************                   ;@D1088
        .IF  < NotDD_IOCtl_Error NE AX >  ; Error from IOCtl?            ;@D1088
          MOV  AX, NotDD_IOCtl_Error                                     ;@D1088
          MOV  NotDD_IOCtl_Error, 0                                      ;@D1088
        .ELSEIF  < BX EQ AIM_Pre_Save_Notification > AND  ; Notify type  ;@D1088
        .IF  < ES:[DI].notdd_AIM_Errors NE EAX >                         ;@D1088
          MOV  AX, ERROR_INVALID_PARAMETER                               ;@D1088
        .ENDIF                                                           ;@D1088

      .ENDIF                                                             ;@D1088
    .ENDIF

    POP  BX                               ; Restore registers            ;@D1088
    POP  CX                                                              ;@D1088
    POP  DX                                                              ;@D1088
    POP  DI                                                              ;@D1088
    POP  ES                                                              ;@D1088
    POP  DS

    MMPHPostDOSSMNotifyDD               ; Performance Hook (8094h)      ;MHW

    LEAVE
    DOSSMNOTIFYDD_POSTDT LABEL FAR
    RET  NotDDLen

DOSSMNOTIFYDD ENDP
endif

PAGE
;************************************************************************
;
; Source File Name:     SMRNOTDD.ASM
;
; Subroutine Name:      DOSSMNOTIFYDD2
;
; Descriptive Name:     Session Manager Notify Device Drivers
;
; Function:     Notifies Device Drivers of screen switches and termination.
;
; Notes:
;       Dependencies:   Called from harderror process so we can use its
;                       file handles.
;                       This procedure runs under the harderrors process.
;
;       Restrictions:   Can only be called if there are device drivers
;                       registered.
;
;       Change History:
;
; Entry Point:
;       Linkage:  EXTRN DOSSMNOTIFYDD2 : FAR
;                       MOV     SMG_Notification_Type, Notification Type
;                       MOV     SMG_Incoming_SG      , Incoming Screen Group
;                       MOV     SMG_Current_SG       , Current Screen Group
;                       CALL    DOSSMNOTIFYDD2
;
; Inputs:
;       WORD    SMG_Notification_Type Value = 01, Pre Save
;                                     Value = 02, Post Save
;                                     Value = 04, Post Restore
;                                     Value = 08, Termination
;       WORD    SMG_Incoming_SG       SG # of new session if AX=02, 0 otherwise
;       WORD    SMG_Current_SG        Screen group number of current session
;
; Exit Normal:
;       AX      ReturnCode Value = 0, successful
; Exit Errors:
;       AX      Never.
;
; Effects:      All other registers preserved.
;
; Internal References:
;          Routines:    DOSSMNOTIFYDD_LOOP
;
; External References:
;          Routines:    DOSDEVIOCTL2
;
;************************************************************************
ifdef I1
;
;   DOSSEMCLEAR (Wake up Hard Error initialization)
;   REPEAT
;     DOSSEMSET (Semaphore we'll wait on)
;     DOSSEMCLEAR (Wake up Session Manager)
;     DOSSEMWAIT (Wait for Session Manager to wake us up)
;
;     IF (Can't access parameter packet data selector)
;        DOSGETSEG (get access to parmeter packet)
;     ENDIF
;     IF (no error)
;        Get access to Registered Device Drivers Info Segment
;        CX = Device Driver Counter
;
;        WHILE (CX > 0)
;          IF (Valid device)
;             IF (Notification type match caller's request)
;                DOSDEVIOCTL2 (Notify device driver)
;                IF (Notification type = AIM_Pre_Save_Notification) and
;                IF (Invalid AIM parameter returned)
;                   Leave loop
;                ENDIF
;             ENDIF
;          ENDIF
;        ENDWHILE (DEC CX)
;
;     ELSE
;        Save error for Session Manager to return
;     ENDIF
;
;   UNTIL (Forever)
;
;************************************************************************
else

    PUBLIC DOSSMNOTIFYDD2
    PUBLIC DOSSMNOTIFYDD2_POSTDT
DOSSMNOTIFYDD2 PROC FAR
    ENTER 0, 0                          ; Stack Frame

    MOV  AX, RDATA                      ; Global Data Segment
    MOV  DS, AX

;   *************************************************************
;   *  Indicate that the notify thread is started and clear sem *
;   *************************************************************
    OR   SMG_Flags, Notify_Thread_Start ; Turn Bit On                     ;@CJ5
    PUSH ES                             ; Clear NotDDRamSem so harderror  ;@CJ5
    PUSH DI                             ; will continue initializing      ;@CJ5
    CALL DOSSEMCLEAR                                                      ;@CJ5

    .REPEAT
      MMPHPreDOSSMNotifyDD2             ; Performance Hook (8015h)      ;MHW

      PUSH DS                           ; Set a semaphore to wait on
      PUSH OFFSET SMG_DoNotifyDD
      CALL DosSemSet

      PUSH DS                           ; Wake up session manager
      PUSH OFFSET SMG_DidNotifyDD
      CALL DosSemClear

;     ********************************************
;     *  Wait for sesion manager to wake us up.  *
;     ********************************************
      PUSH DS                           ; Wait to be woken up by smgr
      PUSH OFFSET SMG_DoNotifyDD
      PUSH DWORD PTR -1                                                 ;@CJ10
      CALL DosSemWait

      CALL DOSSMNOTIFYDD_LOOP           ; Do IOCtls                      @CJ10

      MMPHPostDOSSMNotifyDD2            ; Performance Hook (8095h)      ;MHW
    .UNTIL                              ; Loop forever

    LEAVE                               ; Actually, we'll NEVER leave!
    DOSSMNOTIFYDD2_POSTDT LABEL FAR
    RET

DOSSMNOTIFYDD2 ENDP
endif

PAGE
;************************************************************************
;
; Source File Name:     SMRNOTDD.ASM
;
; Subroutine Name:      DOSSMNOTIFYDD_LOOP
;
; Descriptive Name:     Session Manager Notify Device Drivers Loop
;
; Function:     Loops doing IOCtls to notify device drivers of specific events.
;
; Notes:
;       Dependencies:   Can be called from Session Manager or the HardError
;                       process.
;
;       Restrictions:   Can only be called if there are device drivers
;                       registered.
;
;       Change History:
;
; Entry Point:
;       Linkage:  EXTRN DOSSMNOTIFYDD_LOOP : FAR
;                       CALL    DOSSMNOTIFYDD_LOOP
;
; Inputs: NotifyDD parameter packet
;
; Exit:
;       AX      DOSDEVIOCTL2 return code
;
; Effects:      BX, CX, DI, SI destroyed.
;
; Internal References:
;          Routines:
;
; External References:
;          Routines:    DOSDEVIOCTL2
;
;************************************************************************
ifdef I1
;
;     CX = Device Driver Counter
;
;     WHILE (CX > 0)
;       IF (Valid device)
;          IF (Notification type match caller's request)
;             IF (DLL)
;                call Ordinal 1 notification procedure
;             ELSE
;                DOSDEVIOCTL2 (Notify device driver)
;             ENDIF
;          ENDIF
;       ENDIF
;     ENDWHILE (DEC CX)
;
;************************************************************************
else

    PUBLIC DOSSMNOTIFYDD_LOOP
DOSSMNOTIFYDD_LOOP PROC

;     *****************************************************
;     *  Now we've been woken up by the session manager,  *
;     *  notify all registered Device Drivers.            *
;     *****************************************************

      Clear AX                             ; Set AX to no errors        ;@D1088

      MOV  BX, WORD PTR NotDD_Data_Address+2  ; Get data selector       ;@D1088
      VERW BX                                 ; Do we have access?      ;@D1088
      .IF  < nz >                             ; no, get access to it    ;@D1088
        PUSH  BX                                                        ;@D1088
        CALL  DosGetSeg                                                 ;@D1088
      .ENDIF                                                            ;@D1088

      .IF  < ZERO AX >
        LES  BX, NotDD_Data_Address       ; ES:[BX] --> Parmlist data   ;@D1088
        MOV  DX, ES:[BX].notdd_AIM_Length ; Bytes in ParmList           ;@D1088
        MOV  CX, Registered_DDs           ; # of Device Drivers Registered
        LEA  DI, DD_Bit_Maps              ; DS:[DI] --> Bit Map Array
        LEA  SI, DD_Handles               ; DS:[SI] --> Device Driver Handle Array

        .REPEAT                           ; While CX <> 0
          MOV  AX, ES:[BX].notdd_AIM_Type ; Get bit mask for type       ;@D1088
          PUSH BX                                                       ;@D1088
          MOV  BX, CX                     ; Use BX to index into Bitmap & Handle Arrays
          DEC  BX
          SHL  BX, 1                      ; Bit Map is a WORD Array
          AND  AX, [DI][BX]               ; See if DD wants this

          .IF  < nz > AND                 ; Notification type
          SHL  BX, 1                      ; Handle Array is DWORD Array  ;@D981
          .IF  < <DWORD PTR [SI][BX]> ne 0 >; And if Handle exists       ;@D981

;           *********************************************************    ;@D981
;           *  If the high word of DD Handle is not 0, then it must *    ;@D981
;           *  be the selector portion of a DLL to be notified.     *    ;@D981
;           *********************************************************    ;@D981
            .IF  < <WORD PTR [SI][BX][2]> ne 0 >; If DLL selector exists ;@D981
              PUSH NotDD_Data_Address           ; Notify data address    ;@D981
              CALL DWORD PTR [SI][BX]           ; Call DLL procedure     ;@D981

;           *******************************************                  ;@D981
;           *  Otherwise it must be a device driver.  *                  ;@D981
;           *******************************************                  ;@D981
            .ELSE                                                        ;@D981
              PUSH DWORD PTR 0              ; Dummy Data List            ;@D1088
              PUSH 0                        ; Length of Data List
              PUSH NotDD_Data_Address       ;                            ;@D1088
              PUSH DX                       ; Bytes in ParmList          ;@D1088
              PUSH DWORD PTR 41000BH        ; Category 0BH               ;CJ10
              PUSH [SI][BX]                 ; Device Handle in DD_Handles
              CALL DOSDEVIOCTL2
            .ENDIF                                                       ;@D981

;           **********************************************              ;@D1088
;           * Check for invalid parameter error returned *              ;@D1088
;           * for AIM_Pre_Save_Notifications.            *              ;@D1088
;           **********************************************              ;@D1088
            POP  BX                     ;restore parm data offset
            .IF  < ES:[BX].notdd_AIM_Type EQ AIM_Pre_Save_Notification > AND ;@D1088
            .IF  < ES:[BX].notdd_AIM_Errors NE 0 >                      ;@D1088
              .LEAVE                                                    ;@D1088
            .ENDIF                                                      ;@D1088
          .ELSE                         ;no notify for this type        ;@D1088
            POP  BX                     ;restore parm data offset       ;@D1088
          .ENDIF                                                        ;@D1088
        .LOOP                           ; Decrement counter & continue
      .ELSE                             ; Error returned from DosGetSeg ;@D1088
        MOV  NotDD_IOCtl_Error, AX                                      ;@D1088
      .ENDIF                                                            ;@D1088

      RET

DOSSMNOTIFYDD_LOOP ENDP

CODE_TUNE1 ENDS                                                         ;MDLL
endif
    END
