;       SCCSID`= @(#)smropndd.asm	6.3 91/05/30
;       SCCSID @(#)smropndd.asm	6.3 91/05/30
PAGE 60,132    ;
; ****************************************************************************
; *                                                                          *
; *                       IBM/Microsoft Confidential                         *
; *                                                                          *
; *                 Copyright (c) IBM Corporation  1987, 1990                *
; *                 Copyright (c) Microsoft Corp.  1987, 1990                *
; *                           All Rights Reserved                            *
; *                                                                          *
; ****************************************************************************

;************************************************************************
;
; Source File Name:     SMROPNDD.ASM
;
; Subroutine Name:      DOSSMOPENDD
;
; Descriptive Name:     Session Manager Open Registered Device Drivers/DLLs.
;
; Function:     Opens Registered Device Drivers/DLLs and stores their
;               handles/procedure addresses.  Sesmgr and harderror can
;               call this procedure.  Sesmgr calls first.  If device
;               drivers other than keyboard and mouse have registered,
;               then harderror will call this procedure and do the
;               notifications.  Otherwise sesmgr will do the notifications.
;
; Notes:
;       Dependencies:   None
;
;       Restrictions:   None
;
; 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.
;    @D981 08/27/90  DCR 981 Notification for DLLs.
;     CJ24 04/05/91  PTR J200215 Fix problems opening registered DLLs.
;     CJ28 05/30/91  PTR J200265 Fix to allow DBCS monitor installation.
;
; Entry Point:
;       Linkage:  EXTRN DOSSMOPENYDD : FAR
;                       CALL    DOSSMNOTIFYDD
;
; Inputs:
;       None
;
; Exit Normal:
;       AX      ReturnCode Value = 0, successful
; Exit Errors:
;       AX      Never
;
; Effects:      All other registers preserved.
;
; Internal References:
;          Routines:
;
; External References:
;          Routines:    DOSOPEN
;
;************************************************************************
ifdef I1
;
;   CX = Device Driver Counter
;   IF (Harderror is to do the notifications)
;      DOSSETMAXFH (Increase maximum file handles to 30)
;      DOSGETSEG (Get segment that holds ASCIIZ names of device drivers/DLLs)
;   ENDIF
;   REPEAT
;      IF (Sesmgr is to do notifications)
;         IF (registered DD is keyboard DD)
;            Store keyboard bitmap in DD_Bit_Maps Array
;            Store QHKEYBDHANDLE in DD_Handle Array
;         ENDIF
;         IF (More registered DDs/DLLs)
;            IF (registered DD is mouse DD)
;               Store mouse bitmap in DD_Bit_Maps Array
;               Store QHMOUSEHANDLE in DD_Handle Array
;            ENDIF
;         ENDIF
;      ENDIF
;      IF (More registered DDs/DLLs)
;        Store bitmap in DD_Bit_Maps Array
;        Open the registered DD/DLL (Saves Handle in DD_Handle Array)
;        IF (No error)
;           DOSQHANDTYPE (See if device driver or DLL)
;           IF (No error)
;              IF (Handle is not a device driver)
;                 Set DLL flag in registered data
;                 DOSCLOSE (DLL)
;              ELSE
;                 IF (Sesmgr is to do notifications)
;                    Set flag for Harderror to do notifications
;                    Reset counter to stop repeat loop
;                    Reset ES for check below
;                    Invalidate bitmap in DD_Bit_Maps
;                 ELSE
;                    Decrement index into DD/DLL Arrays
;                 ENDIF
;              ENDIF
;           ENDIF
;        ENDIF
;        IF (Error)
;           Zero out mask to invalidate device
;        ENDIF
;      ENDIF
;   LOOP
;
;   IF (ES nonzero)
;      IF (Not all registered DDs/DLLs opened)
;         REPEAT
;            IF (registered DLL)
;               DOSLOADMODULE (Load DLL)
;               IF (No error)
;                  DOSGETPROCADDR (Get Ordinal 1 procedure address
;                                  and store in DD_Handle Array   )
;                  IF (Error)
;                     DOSFREEMODULE
;                  ELSE
;                     Store Bitmap in DD_Bit_Maps Array
;                  ENDIF
;               ENDIF
;            ENDIF
;         LOOP
;      ENDIF
;      DOSFREESEG (Deallocate the Device Driver ASCIIZ Name segment)
;   ENDIF
;
;************************************************************************
else

.386C
    EXTRN DD_Bit_Maps           : WORD ; Array of Notification Bit_Maps
    EXTRN DD_Handles            : WORD ; Array of Device Driver Handles
    EXTRN DD_Names_Selector     : WORD ; Selector for sharable segment
    EXTRN Registered_DDs        : WORD ; # of Registered Device Drivers
    EXTRN Registered_DLLs       : WORD ; Flag for registered DLLs        ;CJ28
    EXTRN Max_Path_Length       : WORD ; Max path length for DD/DLL name ;@D981
    EXTRN HardError_Do_NotifyDD : WORD ; Flag for who does notifcations  ;@D981
    EXTRN QHMOUSEHANDLE         : WORD ; Mouse DD handle                 ;@D981
    EXTRN QHKEYBDHANDLE         : WORD ; Keyboard DD handle              ;@D981
    EXTRN KeyFileName           : BYTE ; Keyboard device driver name     ;@D981
    EXTRN KeyNameLen            : BYTE ; Length of Keyboard DD name      ;@D981
    EXTRN MseFileName           : BYTE ; Mouse device driver name        ;@D981
    EXTRN MseNameLen            : BYTE ; Length of Mouse DD name         ;@D981

    EXTRN DOSOPEN           : FAR       ; Open Device Drivers via IOCTL
    EXTRN DOSCLOSE          : FAR       ; Close DLL file                 ;@D981
    EXTRN DOSSMNOTIFYDD     : FAR       ; Notify DD's from SG 0 to SG 1 switch
    EXTRN DOSGETSEG         : FAR       ; Get sharable segment
    EXTRN DOSFREESEG        : FAR       ; Free sharable segment
    EXTRN DOSSETMAXFH       : FAR       ; Set Max File Handles           ;@CJ9
    EXTRN DOSQHANDTYPE      : FAR       ; Query handle type              ;@D981
    EXTRN DOSLOADMODULE     : FAR       ; Load DLL module                ;@D981
    EXTRN DOSFREEMODULE     : FAR       ; Free DLL module                ;@D981
    EXTRN DOSGETPROCADDR    : FAR       ; Get DLL procedure address      ;@D981
.xlist
.xcref
    INCLUDE STRUC.INC
.cref
    INCLUDE SMRRDATA.INC                ; Global Data Segment & EQU definitions
.list

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

    PUBLIC DOSSMOPENDD

DOSSMOPENDD PROC FAR
    Local_Bytes   EQU 2                 ; 2 words from stack             ;@D981
    Handle_Index  EQU SS:[BP][-2]       ; index in DD_Handle array       ;@D981

    ENTER Local_Bytes,0                 ; 2 words for local variables    ;@D981

    PUSHA                               ; Save all registers
    PUSH DS                             ; Save DS
    PUSH ES                             ; Save ES                        ;@D981
    MOV  AX, RDATA                      ; Global Data Segment
    MOV  DS, AX

;   *****************************************************
;   *  Open any Device Drivers and DLLs that Registered *
;   *  with us, and store their Handle in DD_Handles.   *
;   *****************************************************
    MOV  CX, Registered_DDs             ; # of Device Drivers Registered
    MOV  Handle_Index, CX               ; Index into DD_Handles          ;@D981
    DEC  WORD PTR Handle_Index          ; Dec for zero based             ;@D981

;   ****************************************************                 ;@D981
;   * If HardError called us then increase max file    *                 ;@D981
;   * handles in case max # of device drivers register *                 ;@D981
;   * and get access to registered DD and DLL data.    *                 ;@D981
;   ****************************************************                 ;@D981
    .IF  < HardError_Do_NotifyDD eq Yes >                                ;@D981
      PUSH Max_File_Handles             ; Increase max to 30             ;@CJ9
      CALL DOSSETMAXFH                                                   ;@CJ9

      PUSH DD_Names_Selector            ; Get the sharable segment
      CALL DOSGETSEG
    .ENDIF                                                               ;@D981

    MOV  ES, DD_Names_Selector        ; ES --> ASCIIZ Selector           ;CJ10

;   ***********************************************************          ;@D981
;   * Loop through registered data (going from last to first) *          ;@D981
;   * to get device driver handles.  Device drivers must be   *          ;@D981
;   * notified before DLLs so DLLS are done later.            *          ;@D981
;   ***********************************************************          ;@D981
    .REPEAT                           ; While CX <> 0
      MOV  AX, CX                     ; # of Registered DDs/DLLs         ;@D981
      DEC  AX                         ; Adjust for 0 base                ;@D981
      MUL  Max_Path_Length            ; Index into registered data       ;@D981
      MOV  DI, AX                                                        ;@D981

;     ****************************************************               ;@D981
;     * If sesmgr is doing the notifications, then check *               ;@D981
;     * for Keyboard and Mouse to reuse handles.         *               ;@D981
;     ****************************************************               ;@D981
      .IF  < HardError_Do_NotifyDD eq No > NEAR                          ;@D981
        PUSH CX                       ; Save registerd DD/DLL index      ;@D981
        MOV  DX, DI                   ; Save offset to DD/DLL data in DX ;@D981

        LEA  DI, ES:[DI].reg_name     ; Get offset to reg'd DD/DLL name  ;@D981
        MOV  BX, DI                   ; Save offset in BX                ;@D981
        LEA  SI, KeyFileName          ; DS:SI -> keybd DD name           ;@D981
        MOV  CL, KeyNameLen           ; Keybd DD name length             ;@D981
        REPE CMPSB                    ; Is this keybd DD?                ;@D981
        .IF  < z >                    ; Yes, save handle and bitmap      ;@D981
          LEA  SI, DD_Bit_Maps        ; DS:[SI] --> DD/DLL Bitmap Array  ;@D981
          MOV  AX, WORD PTR Handle_Index ; Index to DD/DLL Array         ;@D981
          SHL  AX, 1                  ; Bitmap is word array             ;@D981
          ADD  SI, AX                 ; Add index to Bitmap array offset ;@D981
          MOV  DI, DX                 ; Get offset to reg'd DD data      ;@D981
          MOV  BX, ES:[DI].reg_bitmap ; Store keyboard bitmap            ;@D981
          MOV  [SI], BX               ; in Bitmap array                  ;@D981
          SHL  AX, 1                  ; Adjust index for DWORD array     ;@D981
          LEA  SI, DD_Handles         ; DS:[SI] --> DD/DLL Handle Array  ;@D981
          ADD  SI, AX                 ; Add index to Handle array offset ;@D981
          MOV  AX, QHKEYBDHANDLE      ; Store keyboard handle            ;@D981
          MOV  [SI], AX               ; in Handle array                  ;@D981
          DEC  WORD PTR Handle_Index  ; Dec array index to next DD/DLL   ;@D981
          SUB  DX, Max_Path_Length    ; Offset to previous DD/DLL data   ;@D981
          MOV  DI, DX                                                    ;@D981
          LEA  DI, ES:[DI].reg_name   ; Get offset to reg'd DD/DLL name  ;@D981
          POP  CX                     ; Registered DD/DLL index          ;@D981
          DEC  CX                     ; Dec to previous index            ;@D981
        .ELSE                         ; Not keyboard DD                  ;@D981
          POP  CX                     ; Restore reg'd DD/DLL index       ;@D981
          MOV  DI, BX                 ; Restore offset to DD/DLL name    ;@D981
        .ENDIF
        .IF < NCXZ >  near            ; More reg'd DDs/DLLs to go        ;@D981
          PUSH CX                     ; Save registerd DD/DLL index      ;@D981
          LEA  SI, MseFileName        ; DS:SI -> mouse DD name           ;@D981
          MOV  CL, MseNameLen         ; Mouse DD name length             ;@D981
          REPE CMPSB                  ; Is this mouse DD?                ;@D981
          .IF  < z >                  ; Yes, save handle and bitmap      ;@D981
            LEA  SI, DD_Bit_Maps      ; DS:[SI] --> DD/DLL Bitmap Array  ;@D981
            MOV  AX, WORD PTR Handle_Index ; Index to DD/DLL Array       ;@D981
            SHL  AX, 1                ; Bitmap is word array             ;@D981
            ADD  SI, AX               ; Add index to Bitmap array offset ;@D981
            MOV  DI, DX               ; Get offset to reg'd DD data      ;@D981
            MOV  BX, ES:[DI].reg_bitmap ; Store mouse bitmap             ;@D981
            MOV  [SI], BX             ; in Bitmap array                  ;@D981
            SHL  AX, 1                ; Adjust index for DWORD array     ;@D981
            LEA  SI, DD_Handles       ; DS:[SI] --> DD/DLL Handle Array  ;@D981
            ADD  SI, AX               ; Add index to Handle array offset ;@D981
            MOV  AX, QHMOUSEHANDLE    ; Store mouse handle               ;@D981
            MOV  [SI], AX             ; in Handle array                  ;@D981
            DEC  WORD PTR Handle_Index; Dec array index to next DD/DLL   ;@D981
            SUB  DX, Max_Path_Length  ; Offset to previous DD/DLL data   ;@D981
            POP  CX                   ; Registered DD/DLL index          ;@D981
            DEC  CX                   ; Dec to previous index            ;@D981
          .ELSE                       ; Not mouse DD                     ;@D981
            POP  CX                   ; Restore reg'd DD/DLL index       ;@D981
          .ENDIF                                                         ;@D981
        .ENDIF                                                           ;@D981
        MOV  DI, DX                   ; Restore reg'd DD/DLL name offset ;@D981
      .ENDIF                                                             ;@D981

;     *****************************************************              ;@D981
;     * Open DD/DLL.  If device driver, store it's bitmap *              ;@D981
;     * and handle.  If DLL, set flag in registered data. *              ;@D981
;     *****************************************************              ;@D981
      .IF < NCXZ >  near              ; More reg'd DDs/DLLs to go        ;@D981
        LEA  SI, DD_Bit_Maps          ; DS:[SI] --> DD/DLL Bitmap Array  ;@D981
        MOV  AX, WORD PTR Handle_Index  ; Index to DD/DLL Array          ;@D981
        SHL  AX, 1                    ; Bitmap is word array             ;@D981
        ADD  SI, AX                   ; Add index to Bitmap array offset ;@D981
        MOV  DX, SI                   ; Save offset in DX                ;@D981
        MOV  BX, ES:[DI].reg_bitmap   ; Store bitmap                     ;@D981
        MOV  [SI], BX                 ; in Bitmap array                  ;@D981
        SHL  AX, 1                    ; Adjust index for DWORD array     ;@D981
        LEA  SI, DD_Handles           ; DS:[SI] --> DD/DLL Handle Array  ;@D981
        ADD  SI, AX                   ; Add index to Handle array offset ;@D981

;       **************************************************************
;       *  Open the Device Driver & store it's handle in DD_Handles  *
;       **************************************************************
        PUSH 0                          ; Temp. Storage for ActionTaken Result
        MOV  BX, SP                     ; Get offset of Temp. Storage    ;@D981

        PUSH ES                         ; DD/DLL ASCIIZ Name             ;@D981
        LEA  AX, ES:[DI].reg_name                                        ;@D981
        PUSH AX                                                          ;@D981
        PUSH DS                         ; Handle Address in Array = DS:[SI]
        PUSH SI
        PUSH SS                         ; ActionTaken = SS:BX            ;@D981
        PUSH BX                                                          ;@D981
        PUSH DWORD PTR 0                ; Dummy File Size                ;CJ10
        PUSH DWORD PTR 1                ; Open Flag = open if it exists  ;CJ10
        PUSH 20C0H                      ; Open Mode = Deny None Access Rd;CJ24
        PUSH DWORD PTR 0                ; Reserved DWORD                 ;CJ10
        CALL DOSOPEN

;       *********************************************                    ;@D981
;       *  Query the handle type to see if it's a   *                    ;@D981
;       *  device driver. If not, it must be a DLL. *                    ;@D981
;       *********************************************                    ;@D981
        .IF  < zero AX >                ; If no error                    ;@D981
          PUSH 0                        ; Temp. Storage                  ;@D981
          MOV  AX, SP                   ; Get offset of Temp. Storage    ;@D981

          PUSH WORD PTR DS:[SI]         ; Handle from open               ;@D981
          PUSH SS                       ; Handle Type returned           ;@D981
          PUSH BX                                                        ;@D981
          PUSH SS                       ; DD attribute (don't care)      ;@D981
          PUSH AX                                                        ;@D981
          CALL DOSQHANDTYPE             ; Query handle type              ;@D981

          .IF  < zero AX >              ; If no error                    ;@D981
            TEST WORD PTR SS:[BX], Char_DD ; Character DD?               ;@D981
;           ***********************************                          ;@D981
;           * Registered Dynamic Link Library *                          ;@D981
;           ***********************************                          ;@D981
            .IF  < zero >               ; Not DD so must be DLL          ;@D981
;CJ24;;;;;;;;;INC  ES:[DI].reg_DLL      ; Set DLL flag                   ;@D981
              PUSH WORD PTR DS:[SI]     ; Close DLL file                 ;@D981
              CALL DOSCLOSE                                              ;@D981
              INC  AX                   ; inc for nonzero AX             ;CJ24

;           **************************************************************;@D981
;           * Registered Device Driver                                   *;@D981
;           * Not keyboard or mouse so Harderror has to do notifcations. *;@D981
;           **************************************************************;@D981
            .ELSE                                                         ;@D981
              .IF < Harderror_Do_NotifyDD eq No > ; Sesmgr called us?     ;@D981
                MOV  Harderror_Do_NotifyDD, Yes ; Reset flag for harderror;@D981
                MOV  CX, 1                      ; Stop REPEAT loop        ;@D981
                MOV  BX, 0                      ; Reset ES for check below;@D981
                MOV  ES, BX                                               ;@D981
                MOV  SI, DX                     ; Offset in Bitmap array  ;@D981
                MOV  WORD PTR [SI], 0           ; Invalidate Bit Mask     ;@D981
              .ELSE                             ; Valid DD entry          ;@D981
                DEC  WORD PTR Handle_Index ; Dec array index to next DD   ;@D981
              .ENDIF                                                      ;@D981
            .ENDIF                                                        ;@D981
          .ENDIF                                                          ;@D981

          POP  BX                       ; Free temp storage              ;@D981
        .ENDIF                                                           ;@D981

        POP  BX                         ; Get ActionTaken off Stack      ;@D981
        .IF  < nonzero AX >             ; Error returned or DLL          ;CJ10
          INC  ES:[DI].reg_DLL          ; Set DLL flag               ;@D981;CJ24
          MOV  SI, DX                   ; Offset in Bitmap Array
          MOV  WORD PTR [SI], 0         ; Invalidate Bit Mask
        .ENDIF
        DEC  CX                         ; Decrement DD/DLL counter       ;@D981
      .ENDIF                                                             ;@D981
    .UNTIL < z > NEAR                   ; End of repeat                  ;@D981

;   ******************************************************************** ;@D981
;   * ES is set to zero when Sesmgr called this procedure but an extra * ;@D981
;   * DD was found so Harderror will have to do the notifications so   * ;@D981
;   * this procedure will be called again but from Harderror.          * ;@D981
;   *                                                                  * ;@D981
;   * If ES is nonzero, we have to check for DLLs to get their         * ;@D981
;   * addresses and we also have to free the registered DD/DLL data.   * ;@D981
;   ******************************************************************** ;@D981
    MOV  BX, ES                                                          ;@D981
    .IF < nonzero BX >  NEAR                                             ;@D981

;     ****************************************************               ;@D981
;     * If Handle_Index = -1, then only device drivers   *               ;@D981
;     * registered so there's no need to check for DLLs. *               ;@D981
;     * Otherwise, load the DLL and get the address to   *               ;@D981
;     * it's ordinal 1 procedure.                        *               ;@D981
;     ****************************************************               ;@D981
      .IF < <WORD PTR Handle_Index> ne -1 >                              ;@D981
        MOV  WORD PTR Handle_Index, 0   ; Index for 1st entry in array   ;@D981
        MOV  CX, Registered_DDs         ; # of registered DDs/DLLs       ;@D981
        MOV  DI, 0                      ; Index for registered data      ;@D981

        .REPEAT                         ; Loop thru all reg'd DDs/DLLs   ;@D981
          .IF < ES:[DI].reg_DLL ne 0 >  ; Is this a DLL?                 ;@D981
            PUSH 0                      ; Temp. Storage                  ;@D981
            MOV  BX, SP                 ; Get offset of Temp. Storage    ;@D981

            PUSH 0                      ; Object buffer (don't care)     ;@D981
            PUSH DWORD PTR 0                                             ;@D981        ;CJ10
            PUSH ES                     ; DLL name                       ;@D981
            LEA  AX, ES:[DI].reg_name                                    ;@D981
            PUSH AX                                                      ;@D981
            PUSH SS                     ; Handle returned                ;@D981
            PUSH BX                                                      ;@D981
            CALL DOSLOADMODULE          ; Load DLL                       ;@D981

            .IF  < zero AX >            ; If no error                    ;@D981
              LEA  SI, DD_Handles       ; DS:[SI] --> DD/DLL Handle array;@D981
              MOV  DX, WORD PTR Handle_Index ; Index to DD/DLL array     ;@D981
              SHL  DX, 2                ; Adjust index for DWORD         ;@D981
              ADD  SI, DX               ; Add index to Handle array offst;@D981

              PUSH SS:[BX]              ; module handle                  ;@D981
              PUSH DWORD PTR 1          ; Ordinal #1 procedure           ;@D981
              PUSH DS                   ; Put address in Handle array    ;@D981
              PUSH SI                                                    ;@D981
              CALL DOSGETPROCADDR       ; Get Ord 1 procedure address    ;@D981

              .IF  <nonzero AX>         ; If we get an error             ;@D981
                PUSH SS:[BX]            ; then free the DLL module       ;@D981
                CALL DOSFREEMODULE                                       ;@D981
              .ELSE                     ; No error                       ;@D981
                LEA  SI, DD_Bit_Maps    ; DS:[SI] --> DD/DLL Bitmap array;@D981
                SHR  DX, 1              ; Adjust index for word array    ;@D981
                ADD  SI, DX             ; Add index to Bitmap array offst;@D981
                MOV  AX, ES:[DI].reg_bitmap ; Store bitmap               ;@D981
                MOV  [SI], AX               ; in Bitmap array            ;@D981
                INC  WORD PTR Handle_Index  ; Inc DD/DLL index           ;@D981
                INC  WORD PTR Registered_DLLs ;Set flag for reg'd DLL    ;CJ28
              .ENDIF                                                     ;@D981
            .ENDIF                                                       ;@D981

            POP  BX                     ; Free temp stack storage        ;@D981
          .ENDIF                                                         ;@D981
          ADD  DI, Max_Path_Length      ; Next reg'd DD/DLL data offset  ;@D981
          DEC  CX                       ; Dec counter                    ;@D981
        .UNTIL < z >                                                     ;@D981
      .ENDIF                                                             ;@D981

;     ****************************************************************
;     *  Free the segment that we got during system initialization.  *
;     ****************************************************************
      PUSH ES                           ; Segment to free
      CALL DOSFREESEG                   ; Free ASCIIZ Name Segment
    .ENDIF                                                               ;@D981

    POP  ES                             ; Restore ES                     ;@D981
    POP  DS                             ; Restore DS
    POPA                                ; Restore all registers
    XOR  AX, AX                         ; Always set good return code

    LEAVE
    RET

DOSSMOPENDD ENDP

CODE ENDS
endif
    END
