;       SCCSID = @(#)smrregdd.asm       6.1 90/11/18
;       SCCSID @(#)smrregdd.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:     SMRREGDD.ASM
;
; Subroutine Name:      DOSSMREGISTERDD
;                       DOSREGISTERNOTIFICATION        **Undocumented**
;                       (NOTE: Two entry points for the same procedure)
;
; Descriptive Name:     Register Device Driver/DLL for Screen Group
;                       Notifications and changes to AIM Notifications.
;
; Function:     Allows Device Driver/DLL to register itself with the
;               Session Manager during initialization. The Session
;               Manager will then call the device driver/DLL during
;               Screen Group Save, Restore, Switch, Creation,
;               Termination and/or AIM pre/post save changes.
;
; Notes:
;       Dependencies:   The device driver/DLL code and data segments must
;                       be fixed to aviod possible segment swap during
;                       notification under a hard error condition.
;
;       Restrictions:   All calls to this API will be rejected after the
;                       Session Manager is initialized.
;
;  Change History:
;    @CJ9   04/24/90 PTR B712698 Keyboard not registered and can't register 16
;                    DD's.
;    @CJ10  05/04/90 PTR B712103 Hot Keying performance too slow.
;    @D1088 07/07/90 DCR 1088 Add support for special needs.
;    @D1180 08/14/90 DCR 1180 Delete SG_Type_Change_Notification.
;    @D981  08/27/90 DCR 981 Notification for DLLs.
;    @MHW   09/13/90 PTR B715818 In-line performance (MMIO) hooks added
;    46835  11/12/92 DEFECT - CJJ - moved allocation of DD_Names_Selector to
;                    a global initialization routine (SMGINITG.ASM
;
; Entry Point:
;       Linkage:  EXTRN DOSSMREGISTERDD : FAR
;                       PUSH@   Other  Data      ; Data Packet
;                       CALL    DOSSMREGISTERDD
;
;                 EXTRN DOSREGISTERNOTIFICATION : FAR
;                       PUSH@   Other  Data      ; Data Packet
;                       CALL    DOSREGISTERNOTIFICATION
;
; Inputs:
;       Data structure contains the following registration data requesting
;       for specific notification(s).
;
;       WORD     Length         Data structure length, including itself = 8
;       WORD     Notification   00000000 0000xxx1B  Pre-Save Notification
;                               00000000 0000xx1xB  Post-Save Notification
;                               00000000 0000x1xxB  Post-Restore Notification
;                               00000000 00001xxxB  Termination Notification
;                               00000000 0001xxxxB  Creation Notification
;                               00000000 001xxxxxB  Pre_Switch_Notification
;                               00000000 01xxxxxxB  Post_Switch_Notification
;                               00000000 1xxxxxxxB  AIM_Pre_Save_Notification  @D1088,@D1180
;                               00000001 xxxxxxxxB  AIM_Post_Save_Notification @D1088,@D1180
;       DWORD    RegisteredName Address of ASCIIZ device or DLL name       @D981
;
; Exit Normal:
;       AX      ReturnCode   Value = 0
; Exit Errors:
;       AX      ReturnCode   error_smg_invalid_call
;                            error_smg_invalid_data_length
;                            error_smg_invalid_notification
;
; Effects:      All other registers preserved.
;
; Internal References:
;          Routines:
;
; External References:
;          Routines:    DOSALLOCSEG
;
;************************************************************************
ifdef I1
;
;   IF (number of registered DD's < Max allowed)  OR
;   IF (called by session manager)
;      IF (Initialization_Done Flag not set)
;         IF (structure length = 1.2_Len)
;           IF (notification bits are valid)
;              DOSGETSEG (Get access to segment)
;              IF (No_Error)
;                 Copy notification bit mask
;                 Copy Device Driver ASCIIZ name
;                 RC = No_Error
;                 Increment Device Driver Counter
;              ENDIF
;            ELSE
;               RC = Error_SMG_Invalid_Notification
;            ENDIF
;         ELSE
;            RC = Error_SMG_Invalid_Data_Length
;         ENDIF
;      ELSE
;         RC = Error_SMG_Invalid_Call
;      ENDIF
;   ELSE
;      RC = Error_SMG_Too_Many_DDS
;   ENDIF
;
;************************************************************************
else

.386C
  EXTRN SMG_Flags             : BYTE    ; Session Manager Done Initializing
  EXTRN DD_Bit_Maps           : WORD    ; Array of Notification Bit_Maps
  EXTRN DD_Names_Selector     : WORD    ; Allocated Selector to ASCIIZ Names
  EXTRN Registered_DDs        : WORD    ; # of Registered Device Drivers
  EXTRN HardError_Do_NotifyDD : WORD    ; Flag for who does notifcations  @CJ10
  EXTRN MseFileName           : BYTE    ; Mouse device driver name        @CJ10
  EXTRN MseNameLen            : BYTE    ; Mouse device driver name        @CJ10
  EXTRN Max_Path_Length       : WORD    ; Max path length for DD/DLL name @D981

    EXTRN DOSALLOCSEG         : FAR     ; Allocate segment for ASCIIZ names
    EXTRN DOSGETSEG           : FAR
    EXTRN DOSQSYSINFO         : FAR     ; Query max path length           @D981
.xlist
.xcref
    INCLUDE STRUC.INC
    INCLUDE ERROR2.INC
    INCLUDE INFOSEG.INC                 ; needed by smmmpha.inc         ;MHW
    INCLUDE SMMMPHA.INC                 ; Performance hook macros       ;MHW
.cref
    INCLUDE SMRRDATA.INC                ; Global Data Segment & EQU definitions
    INCLUDE SMRREGDD.INC
.list

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

    PUBLIC DOSSMREGISTERDD
    PUBLIC DOSREGISTERNOTIFICATION                                       ;@D981
DOSSMREGISTERDD PROC FAR

DOSREGISTERNOTIFICATION         LABEL   FAR                              ;@D981

    ENTER 0,0                           ; Create Stack Frame
    PUSH ES                             ; Save ES
    MOV  AX, RDATA                      ; Global Data Segment
    MOV  ES, AX

    MMPHPreDOSSMRegisterDD              ; Performance Hook (8018h)      ;MHW

    .IF  < ES:Registered_DDs b (Max_Registered_DDs-1) > or NEAR ; If room  @CJ9
    MOV  AX, CS                         ; Sesmgr CS - check if returning   @CJ9
    .IF  < RegDD_RetCS eq AX > NEAR     ; to Sesmgr which means this       @CJ9
                                        ; must be a register for KBD$      @CJ9
;     ********************************************************************
;     *  The Session manager opens the Device Drivers during it's        *
;     *  initialization, and we can't have a Device Driver call this     *
;     *  routine after Session Manager has started issuing opens to the  *
;     *  Device Drivers, therefore, this call is allowed only until the  *
;     *  Session Manager has started its initialization.  After that,    *
;     *  this call will be rejected.                                     *
;     ********************************************************************
;@CJ10  TEST ES:SMG_Flags, InitDone
      TEST ES:SMG_Flags, Notify_Thread_Start                            ;@CJ10
      .IF  z  NEAR                      ; Ses Mgr Not Init'ed Yet. then ..
        PUSH DS                         ; Save Registers
        PUSH SI
        PUSH DI
        PUSH BX
        PUSH CX
        LDS  SI, RegDD_Data             ; DS:SI --> Data Packet
        .IF  < [SI].RegDD_Len e RegDD_Ver_1_2_Len > NEAR ; If Packet Len Is OK

;@D981    **************************************
;@D981    *  Copy Bit Map into Bit Map Array.  *
;@D981    **************************************
;@D981;;; LEA  DI, DD_Bit_Maps          ; 1st Device Driver's Bit Map
;@D981;;; MOV  BX, ES:Registered_DDs    ; # of Device Driver already registered
;@D981;;; SHL  BX, 1                    ; Calculate offset into WORD Array

          MOV  BX, [SI].Notification    ; Passed in Notification Bit Map ;@D981
          TEST BX, Invalid_Notification ; See if any bad bits are set    ;@D981
          .IF z  NEAR                   ; If no bad bits set
;@D981;;;;; MOV  ES:[DI][BX], AX        ; Store it in DD_Bit_Maps Array
;46835;;;;; Clear AX                    ; Preset to good return code

;           ********************************************************
;           *  If ASCIIZ segment hasn't been created, allocate it  *
;           *                                                      *
;           *  CODE moved to SMGINITG.ASM - now just need to get   *     ;46835
;           *  access to segment                                   *     ;46835
;           ********************************************************
            MOV  CX, ES:DD_Names_Selector                                ;@D981
            PUSH CX                                                      ;@D981
            CALL DOSGETSEG            ; Make sure we have access to selector

            MOV  ES, CX               ; ES:DI --> New Segment            ;@D981

;           ***********************************************
;           *  Copy bitmap and ASCIIZ DD/DLL name from    *
;           *  address caller passed in, into the special *
;           *  segment.  First calculate where to put it. *
;           ***********************************************
            .IF  < zero AX >            ; If AllocSeg worked (if we did it)
              PUSH DS                   ; Save
              MOV  CX, RDATA            ; Need addressability to RDATA   ;@D981
              MOV  DS, CX               ;   for Registered_DDs           ;@D981
;@D981;;;;;;; IMUL DI, Registered_DDs, Max_Name_Length
              MOV  AX, Max_Path_Length                                   ;@D981
              MUL  Registered_DDs                                        ;@D981
              MOV  DI, AX                                                ;@D981
              MOV  ES:[DI].reg_bitmap, BX ; Notification bitmap          ;@D981
              LEA  DI, ES:[DI].reg_name   ; ES:[DI] --> DD/DLL name      ;@D981

;@D981;;;;;;; MOV  CX, Max_Name_Length  ; So we don't GP fault
              MOV  CX, DS:Max_Path_Length  ; So we don't GP fault        ;@D981
;@D981;;;;;;; DEC  CX                   ; Garuantee a 0 at end of name
              SUB  CX, 6                ; 2 bytes each for flag, bitmap  ;@D981
                                        ; and zero at end of name        ;@D981

;             **************************************
;             *  Copy the device driver/DLL name.  *
;             **************************************
              POP  DS                   ; Restore DD Name Segment
              LDS  SI, [SI].DD_Name     ; DS:[SI] --> DD ASCIIZ Name

              .REPEAT
                LODSB                   ; MOV AL, DS:[SI]
                STOSB                   ; MOV ES:[DI], AL
              .LEAVE < AL eq 0 >        ; Until we get to 00H or CX = 0
              .LOOP

;@D981;;;;;;; COMMENTED OUT BECAUSE DONE IN DOSSMOPENDD NOW
;@D981;;;;;;; **********************************************************   @CJ10
;@D981;;;;;;; * If DD registering is not keyboard or mouse then set    *   @CJ10
;@D981;;;;;;; * the flag for Harderror to do the Notification IOCtl.   *   @CJ10
;@D981;;;;;;; * Session Manager can only do the IOCtl when just the    *   @CJ10
;@D981;;;;;;; * Keyboard and/or Mouse register because it can only use *   @CJ10
;@D981;;;;;;; * up 2 of the Shell's handles.                           *   @CJ10
;@D981;;;;;;; **********************************************************   @CJ10
;@D981;;;;;;; MOV  ES, BX                   ; ES = RDATA                   ;@CJ10
;@D981;;;;;;; .IF  < ES:HardError_Do_NotifyDD eq No > and ; Flag not set   @CJ10
;@D981;;;;;;; MOV  AX,CS                    ; Not keyboard if Session Mgr  @CJ10
;@D981;;;;;;; .IF  < RegDD_RetCS ne AX >    ; didn't call us               @CJ10
;@D981;;;;;;;   LEA  DI, ES:MseFileName     ; ES:DI -> mouse DD name       @CJ10
;@D981;;;;;;;   MOV  CL, ES:MseNameLen      ; Mouse DD name length         @CJ10
;@D981;;;;;;;   XOR  CH, CH                                               ;@CJ10
;@D981;;;;;;;   SUB  SI, CX                 ; Reset ptr to DD name         @CJ10
;@D981;;;;;;;   REPE CMPSB                  ; Is this mouse DD?            @CJ10
;@D981;;;;;;;   .IF  < nz >                 ; No, then HardError will      @CJ10
;@D981;;;;;;;     MOV  ES:HardError_Do_NotifyDD, Yes ; do the Notify IOCtl @CJ10
;@D981;;;;;;;   .ENDIF                                                    ;@CJ10
;@D981;;;;;;; .ENDIF                                                      ;@CJ10

              XOR  AX, AX               ; Set good return code
;             ****************************************************
;             *  Update Count of # of Registered Device Drivers  *
;             ****************************************************
              MOV  BX, RDATA            ; Get access to RDATA again      ;@D981
              MOV  DS, BX
              INC  Registered_DDs       ; Indicate 1 more Registered DD
            .ENDIF                      ; AllocSeg Test

          .ELSE                         ; Bad bit set in notification
            MOV  AX, Error_SMG_Invalid_Notification
          .ENDIF                        ; Legal Notification Test

        .ELSE                           ; Illegal Packet Len
          MOV  AX, Error_SMG_Invalid_Data_Length
        .ENDIF                          ; Packet Len Test

        POP  CX                         ; Restore Registers
        POP  BX
        POP  DI
        POP  SI
        POP  DS

      .ELSE                             ; Too Late - Initialized Already
        MOV  AX, Error_SMG_Invalid_Call ; Tell Caller He's Missed the Train
      .ENDIF                            ; Initialization Test

    .ELSE                               ; Max # already registered
      MOV  AX, Error_SMG_Too_Many_DDs
    .ENDIF                              ; Max registered test

    POP  ES                             ; Restore ES

    MMPHPostDOSSMRegisterDD             ; Performance Hook (8098h)      ;MHW

    LEAVE
    RET  RegDDLen

DOSSMREGISTERDD ENDP

CODE ENDS
endif
    END
