;       SCCSID = @(#)smghdeui.asm       6.16 92/03/24
;       SCCSID @(#)smghdeui.asm 6.16 92/03/24
PAGE 60,132    ;
; ****************************************************************************
; *                                                                          *
; *                       IBM/Microsoft Confidential                         *
; *                                                                          *
; *                 Copyright (c) IBM Corporation  1987, 1990                *
; *                 Copyright (c) Microsoft Corp.  1987, 1990                *
; *                           All Rights Reserved                            *
; *                                                                          *
; ****************************************************************************

;***************************************************************************
;
; Source File Name:     SMGHDEUI.ASM
;
; Subroutine Name:      DOSSMHDERRUSRI
;
; Descriptive Name:     Get user input during hard error
;
; Function:     The hard error handler calls this procedure to get
;               the user's response to a hard error.
;
; Notes:
;       Dependencies:   None
;
;       Restrictions:   None
;
; Change History:
;   @CJ8  04/14/90 PTR B788565 Message text displayed incorrectly.
;   @CJ10 05/04/90 PTR B712103 Hot Keying performance too slow.
;   @D969 06/18/90 DCR 969 Add help option to harderrors.
;   CB25  05/12/91 PTR B722902 Check <18 rows to add blank line after msg.
;   CJ30  06/04/91 PTR B723593 Avoid infinite loop for error from DosGetMessage.
;   CJ36  06/25/91 PTR B724377 Use Lazywriter title.
;   @PMH  04/29/91 WorkPlace Shell PM HARDERR.
;   CJ43  09/11/91 PTR B726659 Use error #s 37-49 for 19-31.  DELETED by CJ44
;   CJ44  09/25/91 PTR B727240 Bind in msgs 19-31 rather than CJ43 fix.
;   VR1   10/04/91 PTR B727832 Disable PMHardErr Processing
;   D1536 10/21/91 Display Register dump info to a separete screen, and
;                  re-enable PM_HARD_ERROR.
;   CJ51  01/26/92 PTR B732076 Delete msg #1797 which is no longer used.
;   CJ57  03/02/92 PTR B733974 Trap in DosSubFree.
;   JW01  03/13/92 PTR B734224 Handle multi-line SG title by stripping LF.
;   NUSWAP 03/16/92 PTR B734649 New option for swapper to display FS harderr.
;   CJ60  03/19/92 PTR B734870 Trap accessing Titlelen.
;   NUSWAP 03/24/92 PTR B735055 Bind new swapper message.
;   VR3   10/27/92  DEFECT 55012 ENABLE HARDERROR POPUP USING MMIOPH OF SHAPI
;   66717 03/11/93  CJJ Fix problem with titles > 1 line.
;   WS01  04/18/93  DEFECT 63011 - mouse enable full screen harderror popup
;   @JK1  08/17/94  Def 93876  18-line hard error exceeds message box size
;
; Entry Point:
;       Linkage:  EXTRN DOSSMHDERRUSRI:NEAR
;                       CALL    DOSSMHDERRUSRI
;
; Inputs:
;       DS:DI   ResPacket   Response packet (SGID, error code,
;                           valid responses, suggested response)
;       ES      SDATA       Global hard error data
;       AX      DefAction   Default action to be taken
;       DX      #Responses  Number of valid responses
;
; Exit Normal:
;       AX      Action      System action to be taken
;
; Exit Errors:
;       AX      DefAction   Default action to be taken
;
; Effects:      All other registers preserved.
;
; Internal References:
;                       The following data is in a shared data segment(SDATA)
;
;                       respacket    - parameter
;                                      hdeerrorcode
;                                      hdesgid
;                       errorfile    - ASCIIZ string 'OSO001.MSG'
;                       outputmessage- buffer to hold generated error message
;                       outputmsglen - total length of error message buffer
;                       errormsglen  - length of generated message
;                       modedata     - mode data characteristics
;                       cell         - scroll fill character and attribute
;                       chardata     - KBDCHARIN data structure
;
;          Routines:    DOSSMSGSWITCH
;
; External References:
;          Routines:    DOSSEMREQUEST
;                       DOSSEMSET
;                       DOSSEMWAIT
;                       DOSENTERCRITSEC
;                       DOSGETMESSAGE
;                       DOSSGSWITCHME
;                       VIOGETMODE
;                       VIOSETMODE
;                       VIOSCROLLDN
;                       VIOSETCURPOS
;                       VIOWRTTTY
;                       VIOWRTNATTR
;                       KBDCHARIN
;                       DOSEXITCRITSEC
;                       DOSOPENSEM
;                       DOSCLOSESEM
;                       DOSSEMSET
;                       DOSSEMCLEAR
;                       DOSSEMWAIT
;                       DOSSUBALLOC
;                       DOSSUBFREE
;
;****************************************************************************

ifdef I1
;
;   WHILE (Not all strings have been processed) AND
;   WHILE (BX b 9 [maximum number of replacement strings])
;      Set up pointers to replacement strings
;   ENDWHILE
;
;   IF (hdeerrorcode ne HDE_MESSAGE_TEMPLATE)
;      DOSGETMESSAGE (Get harderr message from OSO001.MSG)
;   ELSE
;      DOSINSMESSAGE (Insert harderr message into template)
;   ENDIF
;
;   DOSGETMESSAGE (Read initial harderr message format)
;
;   IF (No_Error)
;      BX = sg in which hard error occurred
;      CX = Maximum title length
;
;      IF (BX e 3)
;         SI = popuptitle
;         BX = total screen groups
;
;      ELSEIF (DX b 8000H [detached process]) AND
;      IF (BX ne 0)
;         IF (PM is present)
;            WINQUERYTASKTITLE (Get title from Shell)
;         ELSE
;            Calculate title offset
;         ENDIF
;
;      ELSE
;         SI = detach title
;         BX = total screen groups
;      ENDIF
;
;      Copy screen group title
;      IF (Detached process) AND
;      IF (Room for ASCII PID in session title)
;         Convert PID to ASCII
;      ENDIF
;                                                                      ; ->@PMH
;      IF (ForeGround SG not SHELL)
;        GOTO USEVIOHARDERR
;      ENDIF
;
;      DOSOPENSEM (Open SEM used as PMSHAPI hard error trigger)
;      IF (Error)
;        GOTO USEVIOHARDERR
;      ENDIF
;
;      BUILDMSGFORPM (Build error message for PM Hard Error)
;
;      DOSOPENSEM (Open SEM used to signal that PMSHAPI's finished)
;      DOSSEMSET (Set it)
;
;      DOSSEMCLEAR (Clear PMSHAPI's hard error SEM to trigger execution of
;                   waiting thread)
;
;      DOSSEMWAIT (Wait for PMSHAPI to signal that its finished)
;      DOSCLOSESEM (Close PMSHAPI finished semaphore)
;
;      DOSSUBFREE (Deallocate title string)
;      DOSSUBFREE (Deallocate message string)
;
;      Get number of options
;      REPEAT
;        DOSSUBFREE (Deallocate option string
;      LOOP (Until all options deallocated)
;
;      AX = Return user's response to base sesmgr
;      Restore registers
;      GOTO ENDPMHARDERR
;
; USEVIOHARDERR:                                                       ; @PMH<-
;      VIOPOPUP (Display hard error popup)
;      VIOGETMODE (Get mode data for 80x25 text mode)
;      VIOSETMODE (Set sg 0 into 80 col text mode and clr scrn)
;      VIOSCROLLDN (Scroll entire page)
;      VIOSETCURPOS (Position cursor to upper left)
;      VIOSETCURTYPE (Hide cursor for hard errors)
;
;      Replace variables 4 through 7 using overlay method
;      Copy real error message into menu and adjust size of menu
;      VIOWRTTY (Display message and wait for a valid response)
;
;      REPEAT
;         VIOWRTNATTR (Highlight possible response)
;         VIOSETCURPOS (Set cursor position into hilite)
;         KBDCHARIN (Wait for user input)
;
;         IF (User response received)
;            Get response string offset
;         ELSEIF (up/Down arrow key depressed)
;            VIOWRTNATTR (Highlight appropriate bar)
;         ELSE
;            AL = -1 (Not response to error)
;         ENDIF
;
;      UNTIL (User response)
;      VIOENDPOPUP (Restore foreground screen group)
;
; ENDPMHARDERR:                                                          ; @PMH
;   ELSE
;      RC = Default response
;   ENDIF
;***************************************************************************
else

.386C
.xlist
   INCLUDE SMGHDEPK.INC
   INCLUDE SMRSGCB.INC
   INCLUDE UTILMIDS.INC
   INCLUDE UTILMID.INC                                                    ;@D969
   INCLUDE BASEMID.INC                  ; Message number equates
   INCL_DOSSEMAPHORES EQU 1                                            ; ->@PMH
   INCLUDE BSEDOS.INC                   ; Semaphore defines
   INCLUDE INFOSEG.INC                                                 ; <-@PMH
.xcref
   INCLUDE ERROR2.INC
;@D969   INCLUDE SMRRDATA.INC
   INCLUDE SMGHDEUI.INC                 ; SDATA seg with msgs with no hlp ;@D969
   INCLUDE SMREQUS.INC                  ; General Equates                 ;@D969
   INCLUDE STRUC.INC
.cref
.list


;***************************************************************************
M32 EQU MSG_SHARING_VIOLATION
M33 EQU MSG_LOCK_VIOLATION
M34 EQU MSG_INVALID_DISK_CHANGE
M35 EQU MSG_35
M36 EQU MSG_SHARING_BUFF_OFLOW

M19 EQU MSG_ATT_WRITE_PROT                                              ;CJ44
M20 EQU MSG_UNKNOWN_UNIT                                                ;CJ44
M21 EQU MSG_DRIVE_NOT_READY                                             ;CJ44
M22 EQU MSG_UNKNOWN_COMMAND                                             ;CJ44
M23 EQU MSG_DATA_ERROR                                                  ;CJ44
M24 EQU MSG_BAD_REQ_STRUCTURE                                           ;CJ44
M25 EQU MSG_SEEK_ERROR                                                  ;CJ44
M26 EQU MSG_UNKNOWN_MEDIA                                               ;CJ44
M27 EQU MSG_SECTOR_NOT_FOUND                                            ;CJ44
M28 EQU MSG_OUT_OF_PAPER                                                ;CJ44
M29 EQU MSG_WRITE_FAULT                                                 ;CJ44
M30 EQU MSG_READ_FAULT                                                  ;CJ44
M31 EQU MSG_GENERAL_FAILURE                                             ;CJ44

; use messages 37-49 instead of 19-31 for device names in messages
M37 EQU MSG_ERROR_WRITE_PROTECT
M38 EQU MSG_ERROR_BAD_UNIT
M39 EQU MSG_ERROR_NOT_READY
M40 EQU MSG_ERROR_BAD_COMMAND
M41 EQU MSG_ERROR_CRC
M42 EQU MSG_ERROR_BAD_LENGTH
M43 EQU MSG_ERROR_SEEK
M44 EQU MSG_ERROR_NOT_DOS_DISK
M45 EQU MSG_ERROR_SECTOR_NOT_FOUND
M46 EQU MSG_ERROR_OUT_OF_PAPER
M47 EQU MSG_ERROR_WRITE_FAULT
M48 EQU MSG_ERROR_READ_FAULT
M49 EQU MSG_ERROR_GEN_FAILURE

M99  EQU MSG_DEVICE_IN_USE
M106 EQU MSG_ERROR_DISK_CHANGE
M108 EQU MSG_DRIVE_LOCKED
M1477 EQU MSG_SM_OUT_OF_SWAFILE                                         ;NUSWAP
M1493 EQU MSG_HELP_NO_HELP                                              ;@D969
M1924 EQU MSG_INTERRUPTS_DISABLED
M1926 EQU MSG_GEN_PROT_FAULT
M1927 EQU MSG_CHANGE_INT_VECTOR
M1928 EQU MSG_NOMEM_FOR_RELOAD
M1930 EQU MSG_TRAP0
M1931 EQU MSG_TRAP1
M1932 EQU MSG_TRAP2
M1933 EQU MSG_TRAP3
M1934 EQU MSG_TRAP4
M1935 EQU MSG_TRAP5
M1936 EQU MSG_TRAP6
M1937 EQU MSG_TRAP7
M1938 EQU MSG_TRAP8
M1939 EQU MSG_TRAP9
M1940 EQU MSG_TRAPA
M1941 EQU MSG_TRAPB
M1942 EQU MSG_TRAPC
M1943 EQU MSG_TRAPD
M1950 EQU MSG_NPXIEMSG
M1951 EQU MSG_NPXDEMSG
M1952 EQU MSG_NPXZEMSG
M1953 EQU MSG_NPXOEMSG
M1954 EQU MSG_NPXUEMSG
M1955 EQU MSG_NPXPEMSG
M2070 EQU MSG_DEMAND_LOAD_FAILED
M50 EQU MSG_NET_REQ_NOT_SUPPORT
M51 EQU MSG_NET_REMOTE_NOT_ONLINE
M52 EQU MSG_NET_DUP_FILENAME
M53 EQU MSG_NET_PATH_NOT_FOUND
M54 EQU MSG_NET_BUSY
M55 EQU MSG_NET_DEV_NOT_INSTALLED
M56 EQU MSG_NET_BIOS_LIMIT_REACHED
M57 EQU MSG_NET_ADAPT_HRDW_ERROR
M58 EQU MSG_NET_INCORRECT_RESPONSE
M59 EQU MSG_NET_UNEXPECT_ERROR
M60 EQU MSG_NET_REMOT_ADPT_INCOMP
M61 EQU MSG_NET_PRINT_Q_FULL
M62 EQU MSG_NET_NO_SPACE_TO_PRINT_FL
M63 EQU MSG_NET_PRINT_FILE_DELETED
M64 EQU MSG_NET_NAME_DELETED
M65 EQU MSG_NET_ACCESS_DENIED
M66 EQU MSG_NET_DEV_TYPE_INVALID
M67 EQU MSG_NET_NAME_NOT_FOUND
M68 EQU MSG_NET_NAME_LIMIT_EXCEED
M69 EQU MSG_NET_BIOS_LIMIT_EXCEED
M70 EQU MSG_NET_TEMP_PAUSED
M71 EQU MSG_NET_REQUEST_DENIED
M72 EQU MSG_NET_PRT_DSK_REDIR_PAUSE
M88 EQU MSG_NET_DATA_FAULT

;CJ51 M1797 EQU MSG_VLPT_NO_SPOOL
;***************************************************************************

   EXTRN BlankReplace      : BYTE       ; Blank replacement text
   EXTRN Cell              : BYTE       ; Fill char/attr for scroll
   EXTRN CharData          : BYTE       ; User response character
   EXTRN ErrorFile         : BYTE       ; ASCIIZ string 'OSO001.MSG'
   EXTRN ErrorMessage      : BYTE       ; Hard error message text
   EXTRN HdeRespPacket     : BYTE       ; Hard error response packet
   EXTRN HiliteAttr        : BYTE       ; Highlight attribute
   EXTRN IvSGTitle         : BYTE       ; Screen group title buffer
   EXTRN ModeData          : BYTE       ; Mode data characteristics
   EXTRN NormalAttr        : BYTE       ; Normal attribute
   EXTRN OutputMessage     : BYTE       ; Generated error msg buffer
   EXTRN Winner_Present    : BYTE
   EXTRN CursorData        : WORD       ; Hide the cursor
   EXTRN DetachTitle       : WORD       ; Detached process title
   EXTRN LazyWrt_Title     : WORD       ; Lazywriter process title
   EXTRN ErrorMsgLen       : WORD       ; Length of generated message
   EXTRN IvCount           : WORD       ; Replacement text count
   EXTRN IvTable           : WORD       ; Replacement text table
   EXTRN IvTable3          : WORD       ; Replacement text table (Opt)
   EXTRN MaxOptionLength   : WORD       ; Maximum hard error opt length
   EXTRN RBoxLeftCol       : WORD       ; Response box left boundary      ;WS01
   EXTRN RBoxRightCol      : WORD       ; Response box right boundary     ;WS01
   EXTRN RBoxMidCol        : WORD       ; Response box middle column      ;WS01
   EXTRN RBoxSelectRow     : WORD       ; Response box highligted row     ;WS01
   EXTRN RBoxUpperRow      : WORD       ; Response box upper row          ;WS01
   EXTRN RBoxLowerRow      : WORD       ; Response box lower row          ;WS01
   EXTRN MouseHandle       : WORD       ; Mouse handle                    ;WS01
   EXTRN MouseRow          : WORD       ; Current mouse row               ;WS01
   EXTRN Last_FS           : WORD       ; Last mouse event                ;WS01
   EXTRN OutputMsgLen      : WORD       ; Length of error msg buffer
   EXTRN PopUpTitle        : WORD       ; Popup process title
   EXTRN PopUpWait         : WORD       ; Popup wait flags
   EXTRN SGTitleSeg        : WORD       ; Session title selector
   EXTRN TotalScrnGrps     : WORD       ; Maximum screen groups
   EXTRN WinQueryTaskTitle : DWORD      ; Get session title
;D1536   EXTRN HelpRequest : WORD       ; Help requested                ;@D969
   EXTRN UserRequest       : WORD       ; User requested option         ;D1536
   EXTRN RegErrorCode      : WORD       ; Register dump message #       ;D1536
   EXTRN RegDumpCnt        : WORD       ; # of messages with reg dumps  ;D1536
   EXTRN RegDumpErrs       : WORD       ; Array of msg #'s with reg dumps ;D1536
   EXTRN RegDumpErrs2      : WORD       ; Array of reg dump msg #'s     ;D1536
   EXTRN RegisterMsg       : WORD       ; Register dump option address  ;D1536
   EXTRN ReturnToError     : WORD       ; Register dump option address  ;D1536
   EXTRN HelpMessage       : WORD       ; Help message option address   ;@D969
   EXTRN HelpFile          : BYTE       ; Help file name (OSO001H.MSG)  ;@D969
   EXTRN BootDrive         : WORD       ; Boot drive attributes         ;@D969
                                                                       ; ->@PMH
   EXTRN GlobalSelector    : WORD       ; Selector for Global Info Seg
   EXTRN PMHardErrSel      : WORD       ; Selector for PM Hard Error Shared Seg
   EXTRN PMHardErrSeg      : BYTE       ; Name of PM Hard Error Shared Seg
   EXTRN PMHardErrHeader   : WORD       ; Offset of PM Hard Error Header
   EXTRN PMHardErrTemp     : WORD       ; Temporary holder for suballoc offsets
   EXTRN PMHardErrTempSize : WORD       ; Temporary holder for suballoc lengths
   EXTRN SemHandle         : DWORD      ; Sem for triggering PM Hard Error
   EXTRN SemName           : BYTE       ; Name of PM Hard Error Sem
   EXTRN Sem2Handle        : DWORD      ; Sem for triggering SMG Hard Error completion
   EXTRN Sem2Name          : BYTE       ; Name of SMG completion Sem
   EXTRN TitleLen          : WORD       ; Actual SG title length

   EXTRN DOSOPENSEM        : FAR        ; Checks for existence of PM HardErr Thread
   EXTRN DOSCLOSESEM       : FAR        ; Closes sem after usage
   EXTRN DOSSEMSET         : FAR        ; SMG/PMSHAPI timing considerations ...
   EXTRN DOSSEMCLEAR       : FAR        ;     "         "           "
   EXTRN DOSSEMWAIT        : FAR        ;     "         "           "
   EXTRN DOSSUBALLOC       : FAR        ; Shared segment (with PMSHAPI) info
   EXTRN DOSSUBFREE        : FAR        ;   "       "      "      "      "
                                                                       ; @PMH<-
   EXTRN DOSGETMESSAGE     : FAR        ; Retrieve error message
   EXTRN DOSINSMESSAGE     : FAR        ; Fill in error msg template
   EXTRN KBDCHARIN         : FAR        ; Receive user input
   EXTRN VIOGETMODE        : FAR        ; Set text mode
   EXTRN VIOPOPUP          : FAR        ; Hard error popup
   EXTRN VIOENDPOPUP       : FAR        ; End hard error popup
   EXTRN VIOSCROLLDN       : FAR        ; Clear the screen
   EXTRN VIOSETCURPOS      : FAR        ; Set cursor position
   EXTRN VIOSETCURTYPE     : FAR        ; Hide the cursor
   EXTRN VIOSETMODE        : FAR        ; Set text mode
   EXTRN VIOWRTNATTR       : FAR        ; Display attribute
   EXTRN VIOWRTTTY         : FAR        ; Display error message
   EXTRN MOUREADEVENTQUE   : FAR        ; Mouse read event queue          ;WS01
   EXTRN MOUGETPTRPOS      : FAR        ; Mouse get pointer position      ;WS01
   EXTRN MOUSETPTRPOS      : FAR        ; Mouse set pointer position      ;WS01
   EXTRN DOSDEVIOCTL       : FAR        ; dos dev ioctl                   ;WS01
   EXTRN DOSSLEEP          : FAR        ; dos sleep                       ;WS01
   EXTRN VIOSETCP          : FAR        ; Set code page
   EXTRN VIOGETCP          : FAR        ; Get code page
   EXTRN DOSSMREPNE        : NEAR       ; DBCS scan

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

   PUBLIC DOSSMHDERRUSRI
DOSSMHDERRUSRI PROC NEAR

   ENTER 0,0
   PUSH DS                            ; ES = Response packet selector    ;@CJ8
   POP  ES                                                               ;@CJ8
   PUSH DI

;  **************************************************************
;  *  Insert text from DOSSYSTEMSERVICE into the error message  *
;  **************************************************************
   MOV  SI, DI                          ; (DS:SI) -> response packet
   ADD  DI, OFFSET HdeIvBuffer          ; (DS:DI) -> hard error buffer
   XOR  BX, BX                          ; Initialize number of replace. strings
   XOR  AX, AX                          ; Scan for end of ASCIIZ string
   MOV  CX, DS:[SI].HdeIvBufLen         ; (CX) =- hard error buf length

   .WHILE <BX b DS:[SI].HdeIvStrings> AND ; All strings processed?
   .WHILE <BX b HDE_MAXSUBS>            ; Maximum allowed replacement strings?
     SHL  BX, 2                         ; Double word addresses
     MOV  DS:[BX+SI].HdeIvTable, DI     ; Offset to replace. strg
     MOV  DS:[BX+SI+2].HdeIvTable, DS   ; Sel. to replace. strg
     SHR  BX, 2                         ; Save number of replacement strings
     INC  BX                            ; Next replacement string
     PUSH CX                            ; Save hard error buffer length
     REPNE SCASB                        ; Locate next replacement string
     POP  CX                            ; Restore hard error buffer length
   .ENDWHILE

;  *************************************************************************
;  *  Get screen group title for text replacement into the error message.  *
;  *************************************************************************
   MOV  DI,SI
   PUSH DS                              ; Save response packet address
   PUSH DI
   MOV  BX, DS:[DI].HdeSGID             ; SG hard error occurred in
   MOV  AX, DS:[DI].HdePID              ; Hard error process ID
   MOV  CX, SGCB_TitleLen               ; Max title length
   INC  DX                              ; Account for help              ;@D969
   PUSH DX                              ; Save # of valid responses
   PUSH AX                              ; Save hard error pid
   MOV  DX, DS:[DI].HdeValidResp        ; Get for checking
   MOV  DI, OFFSET IvSGTitle            ; Offset to copy title
   MOV  SI, DI
;@CJ8   PUSH DS                              ; Selector to copy title
;@CJ8   POP  ES

   .IF  <BX eq 3>
     MOV  SI, DS:PopUpTitle
     MOV  BX, DS:TotalScrnGrps
   .ELSEIF <DX b 400H> AND              ; Check if Lazywrite or Detached;CJ36
   .IF  <BX ne 0>
     .IF  <ES:Winner_Present e 1>
       PUSH ES                          ;VR3
       MOV  CX, ShellTitleLen+1         ; Max title length
       PUSH BX                          ; Hard error sgid
       PUSH DS
       PUSH DI                          ; Offset to copy title
       PUSH ShellTitleLen-1             ; Buffer length
       CALL WINQUERYTASKTITLE           ;Get title from shell
       POP  ES                          ;VR3
     .ELSE
       MOV  AX, BX                      ; Calculate title offset
       MUL  CL
       MOV  DS, DS:SGTitleSeg
       MOV  SI, AX                      ; SG title offset
       INC  SI                          ; Bump offset past length
     .ENDIF

   .ELSE
     TEST  DX, 400H                                                     ;CJ36
     .IF nz                                                             ;CJ36
       MOV  SI, OFFSET DS:LazyWrt_Title                                 ;CJ36
     .ELSE                                                              ;CJ36
       MOV  SI, DS:DetachTitle
     .ENDIF                                                             ;CJ36
     MOV  BX, DS:TotalScrnGrps
   .ENDIF

   SUB  CL, 2                           ; Skip trailing zero and length

   MOV  ES:TitleLen, CX                 ; Save MaxTitleLen may be 31 or 61 ;JW01;CJ60

   CLD
   .REPEAT                              ; Copy screen group title
     LODSB
     STOSB
   .LEAVE <AL eq 0>
   .LOOP

   MOV  AX, ES:TitleLen                 ; Calculate actual title length  ;JW01;CJ60
   SUB  AX, CX                          ; and                            ;JW01
   MOV  ES:TitleLen, AX                 ; save it.                   ;JW01;CJ60

   TEST DX, 8000H                       ; High Bit on = Detached Process
   .IF  nz AND                          ; If this is a detached PID AND
   .IF  <CL ae 6>                       ; Room for ASCII PID number
     MOV  DS:BYTE PTR [DI-1], ' '
     POP  SI                            ; Restore hard error packet offset
     PUSH SI                            ; Save hard error packet offset
     POP  AX                            ; Restore hard error pid

     XOR  CX, CX                        ;
     MOV  BX, 10                        ; Base 10
     .REPEAT                            ; Loop until quotient = 0
       XOR  DX, DX                      ;
       DIV  BX                          ; Divide by 10
       PUSH DX                          ; Save remainder
       INC  CX                          ; Bump counter
     .UNTIL < zero AX >                                                 ;CJ10

     .REPEAT                            ; Loop until all digits popped
       POP  AX                          ; Get leftmost digit
       ADD  AL, 30H                     ; Convert to ASCII
       STOSB                            ; Store in session title
     .LOOP

     MOV  DS:BYTE PTR [DI], 0
   .ELSE
     POP  AX                            ; Clear stack
   .ENDIF

   POP  DX                              ; Restore # of valid responses
   POP  DI                              ; Restore hard error packet address
   POP  DS

;  *****************************************************************    ;D1536
;  *  If error has a register dump, get the register dump message. *    ;D1536
;  *  For messages 3170-3192 --> just add 300 to get dump msg #,   *    ;D1536
;  *  otherwise need to get dump msg # from array.                 *    ;D1536
;  *****************************************************************    ;D1536
   .IF  <bit DS:[DI].HdeValidResp AND ALLOWED_REGDUMP>;Display Reg Dump ;D1536
     MOV  AX, DS:[DI].HdeErrorCode      ; Get error code                ;D1536
     .IF  <AX a 3169>  AND              ; If between 3169 and 3193      ;D1536
     .IF  <AX b 3193>                                                   ;D1536
       ADD  AX, 300                     ; Add 300 to get dump msg #     ;D1536
     .ELSE                                                              ;D1536
       PUSH DI                          ; Save hde packet offset        ;D1536
       LEA  DI, RegDumpErrs             ; Array of msgs with reg dumps  ;D1536
       MOV  CX, RegDumpCnt              ; # of msgs with reg dumps      ;D1536
       REPNE  SCASW                     ; Scan if in array then get     ;D1536
       .IF  <z>                         ;    register dump message #    ;D1536
         INC  CX                        ; Inc CX cause dec'd by REPNE   ;D1536
         MOV  BX, RegDumpCnt            ; # of msgs in array            ;D1536
         SUB  BX, CX                    ; # of msgs - (loop counter+1)  ;D1536
         SHL  BX, 1                     ; Multiply by 2 for word offset ;D1536
         MOV  AX, RegDumpErrs2[BX]      ; Get msg # from 2nd array      ;D1536
         POP  DI                        ; Restore hde packet offset     ;D1536
       .ELSE                            ; Message # not found           ;D1536
         POP  DI                        ; Restore hde packed offset     ;D1536
         XOR  DS:[DI].HdeValidResp, 0020h ; Disallow reg dump option    ;D1536
         DEC  DX                        ; Dec valid # of responses      ;D1536
         XOR  AX, AX                    ; Zero out reg dump msg #       ;D1536
       .ENDIF                                                           ;D1536
     .ENDIF                                                             ;D1536
     MOV  RegErrorCode, AX              ; Store reg dump message #      ;D1536
   .ENDIF                                                               ;D1536

;*-------------------------------------------------------------------  ->@PMH *
;* BEGIN: PM Hard Error Processing                                            *
;*----------------------------------------------------------------------------*

;  ****************************************************************************
;  *  If SHELL in foreground, use PM HardErr else use old FS HardErr.         *
;  ****************************************************************************

   MOV  ES, DS:GlobalSelector
   .IF  <ES:SIS_CurScrnGrp ne Shell_SG>   ; Current ForeGround SG not SHELL
     JMP  USEVIOHARDERR                   ; Use VIO Popup Hard Error
   .ENDIF

   .IF  <bit DS:[DI].HdeValidResp AND ALLOWED_FULLSCREEN>               ;NUSWAP
     XOR  DS:[DI].HdeValidResp, ALLOWED_FULLSCREEN                      ;NUSWAP
     JMP  USEVIOHARDERR                   ; Use VIO Popup Hard Error    ;NUSWAP
   .ENDIF                                                               ;NUSWAP

   PUSH DS
   PUSH OFFSET SemHandle
   PUSH DS
   PUSH OFFSET SemName                  ; \\SEM\\pmhderr.sem
   CALL DOSOPENSEM                      ; Open SEM used as PMSHAPI hard error
                                        ; trigger ...
   .IF  <nonzero AX>                    ; Check to see if any errors ...
     JMP  USEVIOHARDERR                 ; Use VIO Popup Hard Error
   .ENDIF

   CALL BUILDMSGFORPM                   ; Build error message for PM Hard Error

   PUSH DS
   PUSH OFFSET Sem2Handle
   PUSH DS
   PUSH OFFSET Sem2Name                 ; \\SEM\\smgcont.sem
   CALL DOSOPENSEM                      ; Open SEM used to signal that PMSHAPI's
                                        ; finished (continuation semaphore) ...
   PUSH Sem2Handle
   CALL DOSSEMSET                       ; Set continuation semaphore

   PUSH SemHandle
   CALL DOSSEMCLEAR                     ; Clear PMSHAPI's hard error SEM to
                                        ; trigger execution of waiting thread ...
   PUSH Sem2Handle
   PUSH DWORD PTR SEM_INDEFINITE_WAIT
   CALL DOSSEMWAIT                      ; Wait for PMSHAPI to signal that its
                                        ; finished ...
   PUSH Sem2Handle
   CALL DOSCLOSESEM                     ; Close continuation semaphore ...

;  ****************************************************************************
;  *  Deallocate all error info in the PM Hard Error shared segment           *
;  ****************************************************************************

   MOV  AX,PMHardErrSel
   MOV  ES,AX
   MOV  BX, PMHardErrHeader

   PUSH ES                              ; PM Hard Error Selector
   PUSH ES:[BX].pmhdetitle              ; Title offfset
   PUSH ES:[BX].pmhdetitlesize          ; Title length
   CALL DOSSUBFREE

   PUSH ES                              ; PM Hard Error Selector
   PUSH ES:[BX].pmhdemessage            ; Message offfset
   PUSH ES:[BX].pmhdemessagesize        ; Message length
   CALL DOSSUBFREE

   MOV  AX, ES:[BX].pmhdehelpsize       ; Help length
   .IF  <nonzero AX>                    ; Help message allocated?
     PUSH ES                            ; PM Hard Error Selector
     PUSH ES:[BX].pmhdehelp             ; Help message
     PUSH AX                            ; Help length
     CALL DOSSUBFREE
   .ENDIF

   MOV  AX, ES:[BX].pmhderegmsgsize     ; Register dump message         ;D1536
   .IF  <nonzero AX>                    ; allocated?                    ;D1536
     PUSH ES                            ; PM Hard Error Selector        ;D1536
     PUSH ES:[BX].pmhderegmsg           ; Register message              ;D1536
     PUSH AX                            ; length                        ;D1536
     CALL DOSSUBFREE                                                    ;D1536
   .ENDIF                                                               ;D1536

   MOV  CX, ES:[BX].pmhdeoptioncount    ; Get number of options

   .REPEAT
     MOV  SI, CX
     DEC  SI                            ; 1st option count starts at 0   ;CJ57
     SHL  SI, 1
     PUSH ES                            ; PM Hard Error Selector
     PUSH ES:[BX+SI].pmhdeoptions       ; Option offfset
     PUSH ES:[BX+SI].pmhdeoptionssize   ; Option length
     CALL DOSSUBFREE
   .LOOP

   MOV  AX, ES:[BX].pmhdeuserresponse   ; Return user's response to base sesmgr
   JMP  ENDPMHARDERR

;*----------------------------------------------------------------------------*
;* END: PM Hard Error Processing                                              *
;*------------------------------------------------------------------- @PMH<-- *
;
;  ***********************************************************************
;  *  Save foreground screen group so hard error popup may be displayed  *
;  ***********************************************************************

USEVIOHARDERR:                                                           ; @PMH

   PUSH DS
   PUSH OFFSET PopUpWait
   PUSH 0
   CALL VIOPOPUP

;  ************************************************************************
;  *  Place screen group 0 into 80 column text mode and clear the screen  *
;  ************************************************************************
   MOV  ModeData,12                     ; Get basic mode data             ;WS01
   MOV  SI, OFFSET ModeData             ; Get mode data offset
   PUSH DS                              ; Mode data, 80x25 text mode
   PUSH SI
   PUSH 0                               ; Dummy handle
   CALL VIOGETMODE

   MOV  ModeData,3                      ; only change the text mode       ;WS01
   AND  DS:BYTE PTR [SI+2], 5           ; Text mode
   PUSH DS                              ; Mode data, 80x25 text mode
   PUSH SI
   PUSH 0                               ; Dummy handle
   CALL VIOSETMODE

   CALL NotifyMou                       ; notify mouse of video mode    ;WS01

   .REPEAT                                                              ;@D969

     PUSH DI                            ; Save response packet offset   ;@D969
     PUSH DX                            ; Save # valid responses        ;@D969
     CALL BUILDMSGBOX                   ; Build error/help panel for    ;@D969
                                        ; critical error

;    PUSH 0                             ; First row                       ;CJ10
     PUSH DWORD PTR 0                   ; First column
;    PUSH -1                            ; Last row                        ;CJ10
     PUSH DWORD PTR 0FFFFFFFFH          ; Last column                     ;CJ10
     PUSH -1                            ; Scroll entire page
     PUSH DS                            ; Blank character/attribute
     PUSH OFFSET cell
     PUSH 0                             ; Dummy handle
     CALL VIOSCROLLDN

     PUSH DWORD PTR 0                   ; Position cursor to upper left   ;CJ10
;    PUSH 0                                                               ;CJ10
     PUSH 0
     CALL VIOSETCURPOS

     PUSH DS                            ; Hide cursor for hard errors
     PUSH OFFSET CursorData
     PUSH 0
     CALL VIOSETCURTYPE

;    *********************************************************************
;    *  Display the message and wait for a valid response from the user  *
;    *********************************************************************
     PUSH DS
     PUSH DI
     PUSH DS:OutputMsgLen
     PUSH 0
     CALL VIOWRTTTY

;    *********************************************************************
;    *  Get user selected response action/option                         *
;    *********************************************************************

     CALL GETREQUEST                                                      ;WS01

;D1536     XOR  HelpRequest,1           ; Set/Reset Help                ;@D969
     MOV  AX,UserRequest                ; Get requested option          ;WS01
     POP  DX                            ; Restore # valid responses     ;@D969
     POP  DI                            ; Restore response packet offset;@D969
   .UNTIL <AL b 5> NEAR                 ; Don't return on help/return from help ;@D969

;  *************************************
;  *  Restore foreground screen group  *
;  *************************************
   PUSH AX                              ; Save hard error action
   PUSH 0
   CALL VIOENDPOPUP
   POP  AX                              ; Restore hard error action

ENDPMHARDERR:                                                            ; @PMH

;  ****************************************************************
;  *  Unblock other Session Manager threads and clear semaphores  *
;  ****************************************************************
   POP  DI                              ; Restore response packet offset

   LEAVE
   RET                                  ; Return to caller

DOSSMHDERRUSRI ENDP

   ASSUME CS:CODE,DS:SDATA,SS:NOTHING,ES:NOTHING

;------------------------------------------------------------------------------
; Notify mouse of video mode
; - This would be best done in the base, but to change the base at this point
;   was too risky. This approach is safer. We are doing the IOCTLs that the
;   base video system would have done if the check in BVSINIT would not prevent
;   mou_notify being set as a special SG 0 case.
;
; note: this whole routine has been added under ;WS01
;------------------------------------------------------------------------------
public NotifyMou
NotifyMou proc
   MOV  AX, MouseHandle
   .IF  <NONZERO AX>          ; if we have a mouse

; notify mouse.sys of start of video mode change

      MOV  ModeData,12                     ; Set to whole length
      PUSH 0               ; no data area
      PUSH 0
      PUSH DS              ; parmlist is vio get video mode buffer
      LEA  AX,ModeData
      PUSH AX
      PUSH 051h            ; function
      PUSH 7               ; category
      PUSH MouseHandle     ; handle
      CALL DOSDEVIOCTL

; notify mouse.sys of end  of video mode change

      PUSH 0               ; no data area
      PUSH 0
      PUSH 0               ; no parmlist
      PUSH 0
      PUSH 05Dh            ; function
      PUSH 7               ; category
      PUSH MouseHandle     ; handle
      CALL DOSDEVIOCTL
   .ENDIF
   RET
NotifyMou endp

;------------------------------------------------------------------------------
; Get user selected response action/option
;
; note: this whole routine has been added under ;WS01
;
; input
;  cx = begining col of responses
;  bx = row of response to initially highlight
;  dh = 0 based response number to be hightlighted
;  dl = 0 based total number of responses
; returns
;  ax = action code of response
;------------------------------------------------------------------------------
PUBLIC GETREQUEST
GETREQUEST  PROC

; figure out boundaries of the response selection box

     MOV  AX,3                  ; Set left column boundary
     MOV  RBoxLeftCol, AX
     ADD  AX,MaxOptionLength    ; Set right column boundary
     DEC  AX
     MOV  RBoxRightCol, AX
     SAR  AX,1                  ; Set middle column
     MOV  RBoxMidCol,AX
     MOV  AX,BX                 ; Set upper row boundary
     SUB  AL,DH
     MOV  RBoxUpperRow, AX
     ADD  AL,DL                 ; Set lower row boundary
     MOV  RBoxLowerRow, AX

; highlight the default response

     CALL HIGHLIGHTROW_INIT     ; bx = row to highlight
     CALL SetMouRow             ; initialize mouse pointer position
     MOV  Last_FS,0             ; initialize mouse button state

; poll mouse and keyboard, processing each, until response is selected

     .REPEAT
        CALL PROCESS_MOU        ; process mouse input
        .LEAVE <ZERO AX>

        CALL PROCESS_KBD        ; process keyboard input
        .LEAVE <ZERO AX>

        PUSH 0                  ; get rest of system some time between polls
        PUSH 10
        CALL DOSSLEEP

     .UNTIL
     RET
GETREQUEST  ENDP

;------------------------------------------------------------------------------
; Respond to up and down keys to move the high lighted response. The enter
; key selects the currently hilighted response.
;
; returns
; ax = 0 = finished, UserRequest updated up selected option
;     !0 = run out of keystrokes
;
; note: this whole routine has been added under ;WS01
;------------------------------------------------------------------------------
PUBLIC PROCESS_KBD
PROCESS_KBD   PROC NEAR

; poll for input, return if none
; note: KbdCharin does not return a return code indicating that the buffer is
;       empty, so, the buffer is set to zero, an invalid character value, and
;       checked to see if it changed in order to tell if input occured.

  .REPEAT
     MOV  WORD PTR CharData,0 ; init to zero
     PUSH DS
     PUSH OFFSET CharData   ; data buffer
     PUSH 1                 ; return if no data
     PUSH 0                 ; use handle zero
     CALL KBDCHARIN
     .LEAVE <NONZERO AX>    ; ran out, or some other error
     MOV  AX,1
     MOV  SI, OFFSET CharData ; Offset to character data
     .LEAVE <<word ptr [SI]> eq 0> ; no character was returned

; got something, if its an 'enter' then we are done!

     MOV  AX, DS:[SI]         ; Get user response

     .IF  <AL eq 0DH>
        MOV  AX, RBoxSelectRow           ; calc 0 based response number
        SUB  AX, RBoxUpperRow
        MOV  SI, OFFSET IvTable3       ; First option addr
        SHL  AX, 2                     ; Array of double word addresses
        ADD  SI, AX                    ; Offset to response addr
        MOV  SI, DS:[SI]               ; Get response string offset
        MOV  AL, DS:[SI-1]             ; First byte = action code
        MOV  UserRequest,AX            ; Set requested option
        XOR  AX,AX                     ; signal done
        .LEAVE
     .ENDIF

; if its an up or down, move the selection around

     MOV BX,RBoxSelectRow
     .IF <AX eq 5000H> OR     ; Down arrow pressed
     .IF <AX eq 50E0H>
       .IF  <BX B RBoxLowerRow>; Not at last option
         INC  BX              ; Bump row to highlight
       .ENDIF
     .ELSEIF <AX eq 4800H> OR ; Up arrow pressed
     .IF     <AX eq 48E0H>
       .IF  <BX A RBoxUpperRow> ; Not a 1st available opt.
         DEC  BX              ; Row to highlight
       .ENDIF
     .ENDIF                   ; Not key of interest

     CALL  HighLightRow       ; bx = row to hightlight
     CALL  SetMouRow          ; fix up mouse position

  .UNTIL                      ; get another key
  ret
PROCESS_KBD   ENDP

;------------------------------------------------------------------------------
; Respond to mouse movement. High light the response under the mouse and select
; on any button up.
;
; returns
; ax = 0 = finished, UserRequest updated up selected option
;     !0 = run out of mou moves
;
; note: this whole routine has been added under ;WS01
;------------------------------------------------------------------------------
readType     equ  word ptr bp-12   ; ReadType
MI           equ  word ptr bp-10   ; MouseInfo packet
MI_fs        equ  word ptr bp-10   ; MouseInfo - state of mouse
MI_time1     equ  word ptr bp-8    ; MouseInfo - millisecond of event dword
MI_time2     equ  word ptr bp-6    ; MouseInfo - millisecond of event dword
MI_row       equ  word ptr bp-4    ; MouseInfo - row
MI_col       equ  word ptr bp-2    ; MouseInfo - col

PUBLIC PROCESS_MOU
PROCESS_MOU   PROC NEAR

; just return if no mouse handle

   MOV  AX, MouseHandle
   .IF  <ZERO AX>
      MOV AX,1
      RET
   .ENDIF

; We have a mouse, lets get some input
; note: if seems that the mouse does not return an error when polling for
;       input and the queue is empty. But it does zero the packet, so we
;       check for zero time which is impossible when valid data comes back.

   ENTER 12,0
   MOV  [readType],word ptr 0 ; set parm to 'don't wait'

   .REPEAT

      PUSH SS                ; pass address of mouse info buffer
      LEA  AX,[MI]
      PUSH AX
      PUSH SS                ; pass address of read type
      LEA  AX,[readType]
      PUSH AX
      PUSH MouseHandle
      CALL MOUREADEVENTQUE
      .LEAVE <NONZERO AX> OR ; ran out, or some other error
      MOV  AX,1
      .LEAVE <<word ptr[MI_time1]> eq 0> AND ; time packet zero, no packet
      .LEAVE <<word ptr[MI_time2]> eq 0>

; only process event if mouse location is in the response box
;   bx = current row
;   dh = 0 based response number of row

      MOV  DX,[MI_fs]          ; mouse button state
      MOV  AX,[MI_col]
      .IF  <AX ge RBoxLeftCol>  AND
      .IF  <AX le RBoxRightCol> AND
      MOV  BX,[MI_row]
      MOV  MouseRow,BX
      .IF  <BX ge RBoxUpperRow> AND
      .IF  <BX le RBoxLowerRow>
         CALL HighLightRow         ; bx = row to hightlight
         .IF <bit DX z 07Eh> AND ; buttons up now but
         .IF <bit <WORD PTR Last_FS> nz 07Eh> ; was down before
            MOV  AX, RBoxSelectRow         ; calc 0 based response number
            SUB  AX, RBoxUpperRow
            MOV  SI, OFFSET IvTable3       ; First option addr
            SHL  AX, 2                     ; Array of double word addresses
            ADD  SI, AX                    ; Offset to response addr
            MOV  SI, DS:[SI]               ; Get response string offset
            MOV  AL, DS:[SI-1]             ; First byte = action code
            MOV  UserRequest,AX            ; Set requested option
            XOR  AX,AX                     ; signal we are done
            .LEAVE
         .ENDIF
      .ELSE
         CALL SetMouRow  ; set the current mouse position back inside the box
      .ENDIF
      MOV  Last_FS,DX          ; save for next time
   .UNTIL                      ; do until run out or valid button down
   LEAVE
   RET
PROCESS_MOU   ENDP

;------------------------------------------------------------------------------
; Move mouse position to high lighted row
;
; note: this whole routine has been added under ;WS01
;------------------------------------------------------------------------------

PTRLOC       equ  word ptr bp-4    ; Pointer location packet
PL_row       equ  word ptr bp-4    ; Pointer location - row
PL_col       equ  word ptr bp-2    ; Pointer location - col

PUBLIC SetMouRow
SetMouRow    PROC
   MOV  AX, MouseHandle
   .IF  <NONZERO AX>          ; if we have a mouse
      ENTER 4,0
      MOV  BX,RBoxSelectRow   ; highlight row
      MOV  [PL_row],BX
      mov  AX, RBoxMidCol
      MOV  [PL_col],ax

      PUSH SS
      LEA  AX,[PTRLOC]
      PUSH AX
      PUSH MouseHandle
      CALL MOUSETPTRPOS

      MOV  MouseRow,BX
      LEAVE
   .ENDIF
   RET
SetMouRow    ENDP

;------------------------------------------------------------------------------
; Hightlight arow, if not already highlighted
; bx = row to high light
;
; note: this whole routine has been added under ;WS01
;------------------------------------------------------------------------------
PUBLIC HighLightRow
HighLightRow PROC
     .IF <BX ne RBoxSelectRow>
       PUSH DS
       PUSH OFFSET NormalAttr
       PUSH DS:MaxOptionLength
       PUSH RBoxSelectRow
       PUSH RBoxLeftCol
       PUSH 0
       CALL VIOWRTNATTR             ; Remove current highlight

; For first time calling when no row needs to be unhighlighted
; bx = row to high light
HIGHLIGHTROW_INIT:
       PUSH DS
       PUSH OFFSET HiliteAttr
       PUSH MaxOptionLength
       PUSH BX
       PUSH RBoxLeftCol
       PUSH 0
       CALL VIOWRTNATTR           ; set string to high lighted

       PUSH BX
       PUSH RBoxLeftCol
       PUSH 0
       CALL VIOSETCURPOS          ; set cursor position

       MOV  RBoxSelectRow, BX       ; save new high lighted row
     .ENDIF

     RET
HighLightRow ENDP
   ASSUME CS:CODE,DS:NOTHING,SS:NOTHING,ES:NOTHING

   PUBLIC BUILDMSGBOX                                                   ;@D969
BUILDMSGBOX PROC NEAR                                                   ;@D969

   MOV  CX, DS:[DI].HdeIvStrings        ; Number of variables           ;@D969
   MOV  BX, DS:[DI].HdeErrorCode        ; (BX) == error code

   MOV  AX,SDATA                        ; Check that message has a help ;@D969
   MOV  ES,AX                           ; otherwise display no_help msg ;@D969
;D1536  .IF <HelpRequest ne 0>          ; If displaying Help message    ;@D969
   .IF <UserRequest eq Help_Option>     ; If displaying Help message    ;D1536
     .IF <ES:Errcount ne 0>             ; Count of msgs with no help    ;@D969
       PUSH DI                                                          ;@D969
       LEA  DI,ES:PromptErrs            ; Array of msgs with no help    ;@D969
       MOV  AX,BX                       ; Msg # to be displayed         ;@D969
       PUSH CX                          ; Save # of variables           ;@D969
       MOV  CX,ES:Errcount              ; # of msgs with no help        ;@D969
       REPNE  SCASW                     ; Scan if in array then no help ;@D969
       POP  CX                                                          ;@D969
       .IF <Zero>                       ; So display No Help message    ;@D969
         MOV  BX,MSG_HELP_NO_HELP                                       ;@D969
         XOR  CX, CX                    ; Zero # of variables           ;@D969
       .ENDIF                                                           ;@D969
       POP  DI                                                          ;@D969
     .ENDIF                                                             ;@D969
   .ELSEIF <UserRequest eq Reg_Option>  ; Display Reg Dump              ;D1536
     MOV  BX, RegErrorCode              ; Get Reg Dump message          ;D1536
   .ENDIF                                                               ;@D969

   XOR  AX, AX                          ; AX == no error
   .REPEAT                                                              ;@D969

     .IF <nonzero AX> AND               ; Error trying to get help      ;@D969
     .IF <UserRequest eq Help_Option>                                   ;D1536
;D1536 .IF <HelpRequest ne 0>                                           ;@D969
       XOR CX, CX                       ; No replacement text           ;@D969
       MOV BX, MSG_HELP_NO_HELP         ; General help failure message  ;@D969
     .ENDIF                                                             ;@D969

     MOV  SI, DI                        ; (DS:SI) -> response packet
     ADD  SI, OFFSET HdeIvTable         ; (DS:SI) -> replacement text
     MOV  DS:ErrorMsgLen, 1024          ; Reset size of message buffer
     PUSH DS                            ; Variables to insert
     PUSH SI
     PUSH CX                            ; Number of variables           ;@D969

     .IF  <BX eq HDE_MESSAGE_TEMPLATE>
       MOV  SI, DI                      ; (DS:SI) -> response packet
       ADD  SI, OFFSET HdeMessage       ; (DS:SI) -> template
       PUSH DS                          ; message template
       PUSH SI                          ;
       PUSH DS:[DI].HdeMsgLen           ; message template length
     .ENDIF
     PUSH DS                            ; Message to be displayed
     PUSH OFFSET ErrorMessage
     PUSH ErrorMsgLen                   ; Output message buffer length

     .IF  <BX ne HDE_MESSAGE_TEMPLATE>
       PUSH BX                          ; Error message number to retrieve
       PUSH DS                          ; Hard error message file (OSO001.MSG)
;D1536;.IF <HelpRequest eq 0> OR                                        ;@D969
       .IF <UserRequest ne Help_Option> OR  ; Not Help option           ;D1536
       .IF <BX eq MSG_HELP_NO_HELP>                                     ;@D969
           PUSH OFFSET ErrorFile        ; File (OSO001.MSG)
       .ELSE                                                            ;@D969
           PUSH OFFSET HelpFile         ; File (OSO001H.MSG)            ;@D969
       .ENDIF                                                           ;@D969
     .ENDIF
     PUSH DS                            ; Length of hard error message
     PUSH OFFSET ErrorMsgLen

     .IF  <BX ne HDE_MESSAGE_TEMPLATE>
       CALL DOSGETMESSAGE               ; message file number
     .ELSE
       CALL DOSINSMESSAGE               ; message template
     .ENDIF

   .UNTIL <zero AX> OR                  ; DosxxxMessage call worked  ;@D969
   .UNTIL <BX eq MSG_HELP_NO_HELP> OR   ; No help message            ;@D969;CJ30
   .UNTIL <UserRequest ne Help_Option>  ; DosGetMessage error  ;@D969;CJ30;D1536
;D1536  .UNTIL <HelpRequest eq 0>       ; Error from DosGetMessage   ;@D969;CJ30

;  ********************************************
;  *  Read initial hard error message format  *
;  ********************************************
   MOV  DS:OutputMsgLen, 2048           ; Length of buffer
   PUSH DS                              ; Variables to insert
   PUSH OFFSET IvTable
   PUSH DS:IvCount                      ; Number of variables
   PUSH DS                              ; Message to be displayed
   PUSH OFFSET OutputMessage
   PUSH OutputMsgLen                    ; Output message buffer length
   PUSH MSG_SES_MGR_MENU                ; Error msg number to retrieve
   PUSH DS                              ; Hard error msg file (OSO001.MSG)
   PUSH OFFSET ErrorFile
   PUSH DS                              ; Length of hard error message
   PUSH OFFSET OutputMsgLen
   CALL DOSGETMESSAGE


;  *****************************************
;  *  Replace variables 4 through 7 using  *
;  *  overlay technique versus insert.     *
;  *****************************************
   PUSH DI                                                              ;@D969
   MOV  SI, OFFSET IvTable3             ; Replace text vector

   ;  *********************************************                     ;@D969
   ;  * Insert help option only if boot drive was *                     ;@D969
   ;  * a fixed disk, otherwise can get an error  *                     ;@D969
   ;  * while trying to get to the message file.  *                     ;@D969
   ;  *********************************************                     ;@D969
   .IF  <BX ne HDE_MESSAGE_TEMPLATE> and  ; Not message box and boot    ;@D969
   .IF  <bit ES:BootDrive AND Fixed_Disk> ; drive is not removable      ;@D969
;D1536     MOV  BX, HelpRequest           ; Help on = 1/off = 0           ;@D969
;D1536     SHL  BX, 2                                                     ;@D969
;D1536     MOV  DI, OFFSET HelpMessage                                    ;@D969
;D1536     ADD  DI, BX                                                    ;@D969
;D1536     MOV  BX, DX                    ; Get loc to insert help option ;@D969
;D1536     DEC  BX                                                        ;@D969
;D1536     SHL  BX, 2                                                     ;@D969
;D1536     PUSH DS:[DI]                   ; Set real option vectors for   ;@D969
;D1536     PUSH DS:[DI+2]                 ; GetMessage in DOSSMHDERRUSERI ;@D969
;D1536     POP  DS:[BX+SI+2]                                              ;@D969
;D1536     POP  DS:[BX+SI]                                                ;@D969

     MOV  BX, DX                   ; Get location to insert help option ;D1536
     DEC  BX                       ; (# of options -1) *4               ;D1536
     SHL  BX, 2                    ; place to store last option address ;D1536
     MOV  DS:[BX+SI+2], DS                                              ;D1536
     .IF  <UserRequest eq Help_Option>  ; If Help option selected       ;D1536
       MOV  AX, ReturnToError           ; display Return to Error       ;D1536
       MOV  DS:[BX+SI], AX                                              ;D1536
     .ELSE                              ; Else                          ;D1536
       MOV  AX, HelpMessage             ; display Display help          ;D1536
       MOV  DS:[BX+SI], AX                                              ;D1536
     .ENDIF                                                             ;D1536

   .ELSE                                                                ;@D969
     DEC  DX                       ; Reduce available options (No help) ;@D969
     MOV  BX, DX                   ; Setup location for Register Dump   ;D1536
     SHL  BX, 2                                                         ;D1536
   .ENDIF                                                               ;@D969

   ;  *******************************************                       ;D1536
   ;  * Insert register dump option if bit set  *                       ;D1536
   ;  * that error contains register dump info. *                       ;D1536
   ;  *******************************************                       ;D1536
   .IF  <bit DS:[DI].HdeValidResp AND ALLOWED_REGDUMP>                  ;D1536
     SUB  BX, 4                        ; location for option above help ;D1536
     MOV  DS:[BX+SI+2], DS             ; to store option address        ;D1536
     .IF  <UserRequest eq Reg_Option>  ; If register dump requested     ;D1536
       MOV  AX, ReturnToError          ; display Return to Error        ;D1536
       MOV  DS:[BX+SI], AX                                              ;D1536
     .ELSE                             ; Else                           ;D1536
       MOV  AX, RegisterMsg                                             ;D1536
       MOV  DS:[BX+SI], AX                                              ;D1536
     .ENDIF                                                             ;D1536
   .ENDIF                                                               ;D1536

   POP  DI                                                              ;@D969
   MOV  BX, DS:[DI].HdeDefaultResp      ; Default response
   MOV  DI, OFFSET OutputMessage        ; Offset of error menu
   MOV  CX, 6                           ; Insert hard error options     ;@D969
   MOV  AL, '%'                         ; %% = location to replace text

   .REPEAT NEAR
     PUSH AX                            ; Save search character(%)
     PUSH CX                            ; Save loop counter
     MOV  CX, DS:OutputMsgLen           ; Length of message
     ADD  CX, OFFSET OutputMessage      ; Calculate
     SUB  CX, DI                        ; remaining length
     CALL DOSSMREPNE
     OR   CX, CX                        ; Set Z flag
     POP  CX                            ; Restore loop counter

     .IF  <nz>   NEAR                   ; The end of message ?
       .IF  <<DS:BYTE PTR [DI]> eq '%'> ; '%%' found?
         DEC  DI                        ; Start replacing over 1st %
         MOV  DS:WORD PTR[DI], '  '     ; Single byte blank
         .IF  <CX ne 6>                 ; Not SG title entry            ;@D969
           PUSH SI                      ; Save vector offset
           MOV  SI, DS:[SI]             ; Off of replace string
           .IF  <SI ne <OFFSET BlankReplace>> AND ;
           .IF  <DS:[SI-1] eq BL>       ; Text for def. resp.?
             MOV  BL, 5                 ; Yes, BX=0,1,2,3,4 used        ;@D969
             SUB  BL, CL                ; to calc. hilite col.
           .ENDIF

         .ELSE                          ; SG title entry
           SUB  SI, 4                   ; Adjust SI for ADD below
           PUSH SI                      ; Save first option offset
           MOV  SI, DS:IvTable          ; Off of SG title

;          ****************************************************         JW01
;          * Replace line feeds and carriage returns with     *
;          * spaces. Needed for titles with > 1 line of text. *
;          ****************************************************

           PUSH CX                      ; Save regs and prepare
           PUSH ES                      ; for stripping LF from
           PUSH DI                      ; SG title
           PUSH AX

           MOV  CX, TitleLen            ; Get actual SG title length
           MOV  AX, DS
           MOV  ES, AX                  ; es:di => SG title
           MOV  DI, SI
           XOR  AX, AX
           MOV  AL, 10                  ; al = LF, the char we want to strip

           .REPEAT                      ; Strip every LF in SG title
             CALL DOSSMREPNE            ; Find LF in SG title
             .IF <ncxz>                 ; If found, i.e., cx > 0
               MOV  BYTE PTR DS:[DI-1], " "  ; Replace LF with blank (' ') 66717
             .ENDIF
           .UNTIL <cxz>

           MOV  CX, TitleLen            ; Get actual SG title length       66717
           MOV  DI, SI                                                    ;66717
           MOV  AL, 0DH                 ; al = CR, the char to strip       66717

           .REPEAT                      ; Strip every CR in SG title       66717
             CALL DOSSMREPNE            ; Find CR in SG title              66717
             .IF <ncxz>                 ; If found, i.e., cx > 0           66717
               MOV  BYTE PTR DS:[DI-1], " "  ; Replace LF with blank (' ') 66717
             .ENDIF                                                       ;66717
           .UNTIL <cxz>                                                   ;66717

           POP  AX                      ; Restore regs
           POP  DI
           POP  ES
           POP  CX

         .ENDIF

         XOR  AH, AH                    ; Init. number of chars copied
         .REPEAT                        ; Copy option string into msg
           LODSB
         .LEAVE <AL eq 0>               ; End of string
           STOSB
           INC  AH                      ; Bump number of chars copied
         .UNTIL

         TEST AH, 1                     ; If an odd # chars copied
         .IF  <nz>                      ; yes?
           MOV  DS:BYTE PTR[DI], ' '    ; Single byte blank
         .ENDIF

         POP  SI                        ; Get offset to next option
         ADD  SI, 4
       .ELSE                            ; Not a text replacement
         INC  CX                        ; Adjust loop counter
       .ENDIF
     .ELSE                              ; The end of message!
       MOV  CX, 1                       ; Fall through the LOOP
     .ENDIF
     POP  AX                            ; Restore search character
     DEC  CX                            ;JW01
   .UNTIL <cxz> NEAR            ;JW01

;  ***************************************************************
;  *  Copy real error message into menu and adjust size of menu  *
;  ***************************************************************
   PUSH BX                              ; Save default response
   PUSH DX                              ; Save number of options available
   MOV  DX, 4                           ; Place real error on line 4    ;@D969
   MOV  SI, OFFSET ErrorMessage         ; Offset of true error
   MOV  DI, OFFSET OutputMessage        ; Offset of error menu

   .IF  <<DS:BYTE PTR [DI+7]> eq ':'>
     ADD  DI, 9                         ; Bump ptr past message number text
   .ENDIF
   ADD  DI, 247                         ; Offset of row 4, col 5        ;@D969
   MOV  CX, DS:ErrorMsgLen              ; Length to scan for CR
   MOV  AL, 0DH                         ; Scan character

   .REPEAT
     PUSH DI                            ; Save offset of last row,col
     PUSH DI                            ; Save offset of last row,col
     PUSH SI                            ; Save offset of new line
     MOV  DI, SI                        ; Set register for scan
     MOV  BX, CX                        ; Save total length remaining
     CALL DOSSMREPNE
     SUB  BX, CX                        ; Calculate length of row
     POP  SI                            ; Restore offset of new line
     POP  DI                            ; Restore offset of last row,col
     PUSH CX                            ; Save total lenth remaining
     MOV  CX, BX                        ; Copy line of message to menu
     DEC  CX
     REP  MOVSB

     TEST BL, 1                         ; If an odd # chars copied
     .IF  <z>                           ; yes?
       MOV  DS:BYTE PTR [DI], ' '       ; Copy single byte blank
     .ENDIF

     POP  CX                            ; Restore remaining length
     POP  DI                            ; Restore offset of last row,col
     ADD  DI, 81                        ; Bump pointer to next row
     INC  DX                            ; Increment # rows in message
   .LEAVE < cxz >                       ; Leave loop if full msg scanned  ;CJ10
     ADD  SI, 2                         ; Skip CR/LF
   .LOOP

   INC  DX                              ; Insert blank line after error ;CB25
   .IF  <DX a 18>                       ; If error message is too long  ;@JK1
     MOV  AX, 18                        ;   Truncate to 18 lines        ;@JK1
   .ELSE                                                                ;@JK1
     MOV  AX, DX                        ; Last row of real error msg
   .ENDIF

   POP  DX                              ; Restore # of response options
   PUSH AX                              ; Save # of rows in message
   MOV  BL, 81                          ; Calculate offset to move options
   MUL  BL
   MOV  DI, OFFSET OutputMessage

   .IF  <<DS:BYTE PTR [DI+7]> eq ':'>
     ADD  DI, 9                         ; Bump ptr past message number text
   .ENDIF

   PUSH DI                              ; Save offset of message
   MOV  SI, DI
   ADD  DI, AX
   ADD  SI, 1458                        ; Offset of last 5 rows         ;@D969
   MOV  CX, 567                         ; Length of last 5 rows         ;@D969
   REP  MOVSB                           ; Move last 3 rows of menu
   POP  DI                              ; Get offset of message
   POP  BX                              ; Restore # rows in error message

   INC  BX                              ; Increment number of rows
   MOV  AX, 81                          ; Calculate length of msg menu
   MUL  BL
   ADD  AX, 484                                                         ;@D969
   MOV  DS:OutputMsgLen, AX
   POP  CX                              ; Restore default response
   MOV  DH, CL                          ; Default response index
   DEC  DL                              ; Adjust # of responses to 0 base

   .IF  <DH a DL>                       ; Default reponse # > # responses
     MOV  DH, DL                        ; Adjust invalid default response
     MOV  CL, DH                        ; Set new default response
   .ENDIF

   ADD  BX, CX                          ; Row to hilite
   MOV  CX, 3                           ; Column to hilite              ;@D969

   RET

BUILDMSGBOX ENDP

;*-------------------------------------------------------------------  ->@PMH *
;* Build Error Info message specifically for PM ...                           *
;*----------------------------------------------------------------------------*
   PUBLIC BUILDMSGFORPM
BUILDMSGFORPM PROC NEAR

   PUSH DX                              ; Save # valid responses
   PUSH DI                              ; Save response packet offset

   MOV  CX, DS:[DI].HdeIvStrings        ; Number of variables           ;@D969
   MOV  BX, DS:[DI].HdeErrorCode        ; (BX) == error code

   MOV  SI, DI                          ; (DS:SI) -> response packet
   ADD  SI, OFFSET HdeIvTable           ; (DS:SI) -> replacement text
   MOV  DS:ErrorMsgLen, 1024            ; Reset size of message buffer
   PUSH DS                              ; Variables to insert
   PUSH SI
   PUSH CX                              ; Number of variables           ;@D969

   .IF  <BX eq HDE_MESSAGE_TEMPLATE>
     MOV  SI, DI                        ; (DS:SI) -> response packet
     ADD  SI, OFFSET HdeMessage         ; (DS:SI) -> template
     PUSH DS                            ; message template
     PUSH SI                            ;
     PUSH DS:[DI].HdeMsgLen             ; message template length
   .ENDIF

   PUSH DS                              ; Message to be displayed
   PUSH OFFSET ErrorMessage
   PUSH ErrorMsgLen                     ; Output message buffer length

   .IF  <BX ne HDE_MESSAGE_TEMPLATE>
     PUSH BX                            ; Error message number to retrieve
     PUSH DS                            ; Hard error message file (OSO001.MSG)
     PUSH OFFSET ErrorFile
   .ENDIF

   PUSH DS                              ; Length of hard error message
   PUSH OFFSET ErrorMsgLen

   .IF  <BX ne HDE_MESSAGE_TEMPLATE>
     CALL DOSGETMESSAGE                 ; message file number
   .ELSE
     CALL DOSINSMESSAGE                 ; message template
   .ENDIF

;  ****************************************************************************
;  *  Save default (response) option in the PM Hard Error shared segment      *
;  ****************************************************************************
   MOV  AX,PMHardErrSel                 ; Place everything in the PM Hard Error
   MOV  ES,AX                           ; shared segment
   MOV  AX, DS:[DI].HdeDefaultResp      ; Default response

   MOV  SI, PMHardErrHeader
   MOV  ES:[SI].pmhdedefaultoption, AX  ; Save default option
   MOV  ES:[SI].pmhdeuserresponse, AX   ; Save default option for user response
   MOV  ES:[SI].pmhdeoptioncount, 0     ; Reset option count

   MOV  CX, 5                           ; Insert hard error options + title
   MOV  SI, OFFSET IvTable3             ; Replace text vector

;  ****************************************************************************
;  *  Save title and options in the PM Hard Error shared segment              *
;  ****************************************************************************

   PUSH  DI                             ; Save response packet offset   ;D1536
   .REPEAT

;D1536 OR   CX, CX
;D1536 .IF  <nz>                          ; The end of message ?

       .IF  <CX ne 5>                   ; Not SG title entry            ;@D969
         PUSH SI                        ; Save vector offset
         MOV  SI, DS:[SI]               ; Offset of option string
       .ELSE                            ; SG title entry
         SUB  SI, 4                     ; Adjust SI for ADD below
         PUSH SI                        ; Save first option offset
         MOV  SI, DS:IvTable            ; Offset of SG title string
       .ENDIF

       .IF  <SI ne <OFFSET BlankReplace>>  AND  ; Not blank option      ;D1536
       .IF  <SI ne RegisterMsg>   OR            ; Only allow reg option ;D1536
       .IF  <RegErrorCode ne 0>                 ; If valid reg dump msg ;D1536

         MOV  AX, CX                    ; Get option count              ;D1536
         PUSH CX                        ; Save option count
         XOR  CX, CX

;        ********************************************************       ;D1536
;        * Store return value for DosSysServ along with the     *       ;D1536
;        * option.  The return value is 1 byte before the       *       ;D1536
;        * option text.  Need to store it separate from storing *       ;D1536
;        * text because the first value is 0 and that would     *       ;D1536
;        * stop the repeat loop.                                *       ;D1536
;        ********************************************************       ;D1536
         .IF  <AX ne 5>                 ; Not SG title entry            ;D1536
           DEC  SI                      ; Get option value for          ;D1536
           PUSH SI                      ; Save option pointer           ;D1536
           LODSB                        ; DosSysServ return             ;D1536
           INC  CX                      ; Count as part of string       ;D1536
         .ELSE                                                          ;D1536
           PUSH SI                      ; Save option pointer
         .ENDIF                                                         ;D1536

         .REPEAT                        ; Determine length of string
           LODSB
         .LEAVE <AL eq 0>               ; NULL (End of String)
           INC  CX                      ; No, count as part of string
         .UNTIL
         POP  SI                        ; Restore option pointer

         INC  CX                        ; Include NULL in count
         MOV  PMHardErrTempSize, CX     ; Save string size

         PUSH ES                        ; PM Hard Error Selector
         PUSH DS
         PUSH OFFSET PMHardErrTemp      ; Temp location for offset
         PUSH CX                        ; Size
         CALL DOSSUBALLOC               ; Allocate storage for string
;        OR   AX,AX
;        JNZ  ERROR_EXIT


         MOV  DI, PMHardErrTemp         ; Save string in PM Hard Err shared seg
         REP  MOVSB

         POP  CX                        ; Restore option count
         PUSH BX
         MOV  BX, PMHardErrHeader       ; PM Hard Error header offset
         MOV  DX, PMHardErrTemp         ; Offset to string
         .IF  <CX ne 5>                 ; Not SG title entry
           MOV  SI, ES:[BX].pmhdeoptioncount     ; Current number of options
           SHL  SI, 1                            ; Compensate for offset length
           MOV  ES:[BX+SI].pmhdeoptions, DX      ; Save option string offset
           MOV  AX, PMHardErrTempSize            ; Restore string size
           MOV  ES:[BX+SI].pmhdeoptionssize, AX  ; Save option string length
           INC  ES:[BX].pmhdeoptioncount         ; Inc option count
         .ELSE
           MOV  ES:[BX].pmhdetitle, DX          ; Save title string offset
           MOV  AX, PMHardErrTempSize           ; Restore string size
           MOV  ES:[BX].pmhdetitlesize, AX      ; Save title string length
         .ENDIF
         POP  BX
       .ENDIF

       POP  SI                          ; Get offset to next option
       ADD  SI, 4

     DEC  CX                            ; Dec loop counter              ;D1536
   .UNTIL < z > NEAR                    ; End of repeat                 ;D1536

;D1536.ELSE                             ; The end of message!
;D1536   MOV  CX, 1                     ; Fall through the LOOP
;D1536 .ENDIF
;D1536.LOOP

;  ****************************************************************************
;  *  Save error message text in the PM Hard Error shared segment             *
;  ****************************************************************************
   MOV  SI, PMHardErrHeader

   PUSH PMHardErrSel                    ; PM Hard Error Selector
   PUSH DS
   PUSH OFFSET PMHardErrTemp            ; Temp location for offset
   PUSH ErrorMsgLen                     ; Size
   CALL DOSSUBALLOC                     ; Allocate storage for message string
;  OR   AX, AX
;  JNZ  ERROR_EXIT

   MOV  CX, ErrorMsgLen                 ; Size
   MOV  ES:[SI].pmhdemessagesize, CX    ; Save for DOSSUBFREE usage
   MOV  SI, OFFSET ErrorMessage         ; Replace text vector
   MOV  DI, PMHardErrTemp               ; Save string in PM Hard Err shared seg
   REP  MOVSB

   MOV  SI, PMHardErrHeader             ; PM Hard Error header offset
   MOV  DX, PMHardErrTemp               ; Offset to string
   MOV  ES:[SI].pmhdemessage, DX        ; Save message string offset

;  ****************************************************************************
;  *  Save Register dump message in the PM Hard Error shared segment    D1536 *
;  ****************************************************************************
   POP   DI                             ; Restore response packet offset ;D1536
   .IF  <bit DS:[DI].HdeValidResp AND ALLOWED_REGDUMP> NEAR              ;D1536
     MOV  CX, DS:[DI].HdeIvStrings        ; Number of variables          ;D1536

     MOV  AX, DI                          ; (DS:SI) -> response packet   ;D1536
     ADD  AX, OFFSET HdeIvTable           ; (DS:SI) -> replacement text  ;D1536
     MOV  DS:ErrorMsgLen, 1024            ; Reset size of message buffer ;D1536
     PUSH DS                              ; Variables to insert          ;D1536
     PUSH AX                                                             ;D1536
     PUSH CX                              ; Number of variables          ;D1536

     PUSH DS                              ; Message to be displayed      ;D1536
     PUSH OFFSET ErrorMessage                                            ;D1536
     PUSH ErrorMsgLen                     ; Output message buffer length ;D1536

     PUSH RegErrorCode                    ; Get register dump message    ;D1536
     PUSH DS                              ; error msg file (OSO001.MSG)  ;D1536
     PUSH OFFSET ErrorFile                                               ;D1536

     PUSH DS                              ; Length of hard error message ;D1536
     PUSH OFFSET ErrorMsgLen                                             ;D1536
     CALL DOSGETMESSAGE                                                  ;D1536

     .IF  <zero AX>                                                      ;D1536
       MOV  DI, PMHardErrHeader                                          ;D1536

       PUSH PMHardErrSel                  ; PM Hard Error Selector       ;D1536
       PUSH DS                                                           ;D1536
       PUSH OFFSET PMHardErrTemp          ; Temp location for offset     ;D1536
       PUSH ErrorMsgLen                   ; Size                         ;D1536
       CALL DOSSUBALLOC                   ; Allocate storage for msg str ;D1536
;      OR   AX, AX                                                       ;D1536
;      JNZ  ERROR_EXIT                                                   ;D1536

       MOV  CX, ErrorMsgLen               ; Size                         ;D1536
       MOV  ES:[DI].pmhderegmsgsize, CX   ; Save for DOSSUBFREE usage    ;D1536
       MOV  SI, OFFSET ErrorMessage       ; Replace text vector          ;D1536
       MOV  DI, PMHardErrTemp             ; Save string in shared seg    ;D1536
       REP  MOVSB                                                        ;D1536

       MOV  DI, PMHardErrHeader           ; PM Hard Error header offset  ;D1536
       MOV  DX, PMHardErrTemp             ; Offset to string             ;D1536
       MOV  ES:[DI].pmhderegmsg, DX       ; Save message string offset   ;D1536

       XOR  CX, CX                                                       ;D1536
       MOV  SI, ReturnToError                                            ;D1536
       .REPEAT                            ; Determine length of string   ;D1536
         LODSB                                                           ;D1536
       .LEAVE <AL eq 0>                   ; NULL (End of String)         ;D1536
         INC  CX                          ; No, count as part of string  ;D1536
       .UNTIL                                                            ;D1536
       MOV  SI, ReturnToError                                            ;D1536

       INC  CX                            ; Include NULL in count        ;D1536
       MOV  PMHardErrTempSize, CX         ; Save string size             ;D1536

       PUSH ES                            ; PM Hard Error Selector       ;D1536
       PUSH DS                                                           ;D1536
       PUSH OFFSET PMHardErrTemp          ; Temp location for offset     ;D1536
       PUSH CX                            ; Size                         ;D1536
       CALL DOSSUBALLOC                   ; Allocate storage for string  ;D1536
;      OR   AX,AX                                                        ;D1536
;      JNZ  ERROR_EXIT                                                   ;D1536

       MOV  DI, PMHardErrTemp             ; Save string in shared seg    ;D1536
       REP  MOVSB                                                        ;D1536

       MOV  BX, PMHardErrHeader              ; PM Hard Error header ofst ;D1536
       MOV  DX, PMHardErrTemp                ; Offset to string          ;D1536
       MOV  SI, ES:[BX].pmhdeoptioncount     ; Current number of options ;D1536
       SHL  SI, 1                            ; Compensate for offset len ;D1536
       MOV  ES:[BX+SI].pmhdeoptions, DX      ; Save option string offset ;D1536
       MOV  AX, PMHardErrTempSize            ; Restore string size       ;D1536
       MOV  ES:[BX+SI].pmhdeoptionssize, AX  ; Save option string length ;D1536
       INC  ES:[BX].pmhdeoptioncount         ; Bump option count         ;D1536

     .ELSE                                                               ;D1536
       MOV  ES:[SI].pmhderegmsg, 0                                       ;D1536
     .ENDIF                                                              ;D1536
   .ELSE                                                                 ;D1536
     MOV  ES:[SI].pmhderegmsg, 0                                         ;D1536
   .ENDIF                                                                ;D1536


;  ****************************************************************************
;  *  Save help message text in the PM Hard Error shared segment              *
;  ****************************************************************************

   POP  DI                            ; Restore offset to response packet
   PUSH DI                            ; Push back on stack
   MOV  BX, DS:[DI].HdeErrorCode        ; (BX) == error code

   MOV  AX, SDATA                       ; Check to see if message has associated
   MOV  ES, AX                          ; help text ...
   .IF <ES:Errcount ne 0>  NEAR         ; Count of msgs with no help
     LEA  DI, ES:PromptErrs             ; Array of msgs with no help
     MOV  AX, BX                        ; Msg # to be displayed
     MOV  CX, ES:Errcount               ; # of msgs with no help
     REPNE  SCASW                       ; Scan,  if in array then no help
     MOV  ES, PMHardErrSel                ; PM Hard Error Selector
     .IF <Zero>                         ; Help available? (Help on = 1/off = 0)
       MOV  ES:[SI].pmhdehelpsize, 0      ; Otherwise, indicate no help

     .ELSE
       POP  DI                            ; Restore offset to response packet
       PUSH DI                            ; Push back on stack
       MOV  CX, DS:[DI].HdeIvStrings       ; Number of replacement strings
       ADD  DI, OFFSET HdeIvTable         ; Replacement strings
       PUSH DS                            ; Address of replacement strings
       PUSH DI
       PUSH CX                            ; Number of replacement strings

       MOV  DS:ErrorMsgLen, 1024          ; Reset size of message buffer
       PUSH DS                            ; Message to be displayed
       PUSH OFFSET ErrorMessage
       PUSH ErrorMsgLen                   ; Output message buffer length

       PUSH BX                            ; Error message number to retrieve
       PUSH DS                            ; Hard error message file
       PUSH OFFSET HelpFile               ; File (OSO001H.MSG)
       PUSH DS                            ; Length of hard error help
       PUSH OFFSET ErrorMsgLen
       CALL DOSGETMESSAGE                 ; message file number

       .IF  <zero AX>
         PUSH PMHardErrSel                ; PM Hard Error Selector
         PUSH DS
         PUSH OFFSET PMHardErrTemp        ; Temp location for offset
         PUSH ErrorMsgLen                 ; Size
         CALL DOSSUBALLOC                 ; Allocate storage for message string

         .IF  <zero AX>
           MOV  DI, PMHardErrHeader             ; PM Hard Error header offset   ;D1536
           MOV  CX, ErrorMsgLen           ; Size
           MOV  ES:[DI].pmhdehelpsize, CX ; Save for DOSSUBFREE usage
           MOV  SI, OFFSET ErrorMessage   ; Replace text vector
           MOV  DI, PMHardErrTemp         ; Save string in PM Hard Err shared seg
           REP  MOVSB

           MOV  SI, PMHardErrHeader       ; PM Hard Error header offset
           MOV  DX, PMHardErrTemp         ; Offset to string
           MOV  ES:[SI].pmhdehelp, DX     ; Save help string offset
         .ENDIF
       .ENDIF

       .IF  <nonzero AX>                  ; Error trying to get help message
         MOV  ES:[SI].pmhdehelpsize, 0    ; Indicate no help
       .ENDIF

     .ENDIF
   .ENDIF

;  ****************************************************************************
;  *  Set default option to 0 if only 1 option ...                            *
;  ****************************************************************************
   .IF  <ES:[SI].pmhdeoptioncount eq 1>
     MOV  ES:[SI].pmhdedefaultoption, 0 ; If only 1 option, reset to first
     MOV  ES:[SI].pmhdeuserresponse, 0  ; and set default user resp accordingly
   .ENDIF

   POP  DI                              ; Restore response packet offset
   POP  DX                              ; Restore # valid responses

   RET

BUILDMSGFORPM ENDP                                                  ; @PMH<-


CODE ENDS
endif
   END
