diff options
Diffstat (limited to 'v4.0/src/DOS/CTRLC.ASM')
| -rw-r--r-- | v4.0/src/DOS/CTRLC.ASM | 771 |
1 files changed, 771 insertions, 0 deletions
diff --git a/v4.0/src/DOS/CTRLC.ASM b/v4.0/src/DOS/CTRLC.ASM new file mode 100644 index 0000000..5a79e04 --- /dev/null +++ b/v4.0/src/DOS/CTRLC.ASM | |||
| @@ -0,0 +1,771 @@ | |||
| 1 | ; SCCSID = @(#)ctrlc.asm 1.4 85/08/16 | ||
| 2 | ; Low level routines for detecting special characters on CON input, | ||
| 3 | ; the ^C exit/int code, the Hard error INT 24 code, the | ||
| 4 | ; process termination code, and the INT 0 divide overflow handler. | ||
| 5 | ; | ||
| 6 | ; FATAL | ||
| 7 | ; FATAL1 | ||
| 8 | ; reset_environment | ||
| 9 | ; DSKSTATCHK | ||
| 10 | ; SPOOLINT | ||
| 11 | ; STATCHK | ||
| 12 | ; CNTCHAND | ||
| 13 | ; DIVOV | ||
| 14 | ; CHARHARD | ||
| 15 | ; HardErr | ||
| 16 | ; | ||
| 17 | ; Revision history: | ||
| 18 | ; | ||
| 19 | ; AN000 version 4.0 Jan 1988 | ||
| 20 | ; A002 PTM -- dir >lpt3 hangs | ||
| 21 | ; A003 PTM 3957- fake version for IBMCAHE.COM | ||
| 22 | |||
| 23 | ; | ||
| 24 | ; get the appropriate segment definitions | ||
| 25 | ; | ||
| 26 | .xlist | ||
| 27 | include dosseg.asm | ||
| 28 | |||
| 29 | CODE SEGMENT BYTE PUBLIC 'CODE' | ||
| 30 | ASSUME SS:DOSGROUP,CS:DOSGROUP | ||
| 31 | |||
| 32 | .xcref | ||
| 33 | INCLUDE DOSSYM.INC | ||
| 34 | INCLUDE DEVSYM.INC | ||
| 35 | include version.inc | ||
| 36 | .cref | ||
| 37 | .list | ||
| 38 | |||
| 39 | I_need SFN,WORD | ||
| 40 | I_NEED pJFN,DWORD | ||
| 41 | i_need DevIOBuf,BYTE | ||
| 42 | i_need DidCTRLC,BYTE | ||
| 43 | i_need INDOS,BYTE | ||
| 44 | i_need DSKSTCOM,BYTE | ||
| 45 | i_need DSKSTCALL,BYTE | ||
| 46 | i_need DSKSTST,WORD | ||
| 47 | i_need BCON,DWORD | ||
| 48 | i_need DSKCHRET,BYTE | ||
| 49 | i_need DSKSTCNT,WORD | ||
| 50 | i_need IDLEINT,BYTE | ||
| 51 | i_need CONSWAP,BYTE | ||
| 52 | i_need user_SS,WORD | ||
| 53 | i_need user_SP,WORD | ||
| 54 | i_need User_In_AX,WORD | ||
| 55 | i_need ERRORMODE,BYTE | ||
| 56 | i_need ConC_spsave,WORD | ||
| 57 | i_need Exit_type,BYTE | ||
| 58 | i_need PFLAG,BYTE | ||
| 59 | i_need ExitHold,DWORD | ||
| 60 | i_need WPErr,BYTE | ||
| 61 | i_need ReadOp,BYTE | ||
| 62 | i_need CONTSTK,WORD | ||
| 63 | i_need Exit_Code,WORD | ||
| 64 | i_need CurrentPDB,WORD | ||
| 65 | i_need DIVMES,BYTE | ||
| 66 | i_need DivMesLen,WORD | ||
| 67 | i_need ALLOWED,BYTE | ||
| 68 | i_need FAILERR,BYTE | ||
| 69 | i_need EXTERR,WORD | ||
| 70 | i_need ERR_TABLE_24,BYTE | ||
| 71 | I_need ErrMap24,BYTE | ||
| 72 | I_need ErrMap24End,BYTE | ||
| 73 | I_need fAborting,BYTE | ||
| 74 | I_need AUXStack,BYTE | ||
| 75 | I_need SCAN_FLAG,BYTE | ||
| 76 | I_need EXTOPEN_ON,BYTE ;AN000; DOS 4.0 | ||
| 77 | I_need InterCon,BYTE ;AN000; DOS 4.0 | ||
| 78 | I_need DOS34_FLAG,WORD ;AN000; DOS 4.0 | ||
| 79 | I_need ACT_PAGE,WORD ;AN000; DOS 4.0 | ||
| 80 | I_need Special_Version,WORD ;AN007; DOS 4.0 | ||
| 81 | if debug | ||
| 82 | I_need BugLev,WORD | ||
| 83 | I_need BugTyp,WORD | ||
| 84 | include bugtyp.asm | ||
| 85 | endif | ||
| 86 | IF BUFFERFLAG | ||
| 87 | extrn restore_user_map:near | ||
| 88 | ENDIF | ||
| 89 | |||
| 90 | Break <Checks for ^C in CON I/O> | ||
| 91 | |||
| 92 | ASSUME DS:NOTHING,ES:NOTHING | ||
| 93 | |||
| 94 | procedure DSKSTATCHK,NEAR ; Check for ^C if only one level in | ||
| 95 | CMP BYTE PTR [INDOS],1 | ||
| 96 | retnz ; Do NOTHING | ||
| 97 | PUSH CX | ||
| 98 | PUSH ES | ||
| 99 | PUSH BX | ||
| 100 | PUSH DS | ||
| 101 | PUSH SI | ||
| 102 | PUSH CS | ||
| 103 | POP ES | ||
| 104 | Context DS | ||
| 105 | DOSAssume CS,<DS>,"DskStatChk" | ||
| 106 | MOV BYTE PTR [DSKSTCOM],DEVRDND | ||
| 107 | MOV BYTE PTR [DSKSTCALL],DRDNDHL | ||
| 108 | MOV [DSKSTST],0 | ||
| 109 | IF DBCS ;AN000; | ||
| 110 | MOV AL, [InterCon] ;AN000;get type of status read 2/13/KK | ||
| 111 | MOV BYTE PTR [DSKCHRET],AL ;AN000; load interim flag into packet | ||
| 112 | ENDIF ;AN000; | ||
| 113 | MOV BX,OFFSET DOSGROUP:DSKSTCALL | ||
| 114 | LDS SI,[BCON] | ||
| 115 | ASSUME DS:NOTHING | ||
| 116 | invoke DEVIOCALL2 | ||
| 117 | TEST [DSKSTST],STBUI | ||
| 118 | JZ GotCh ; No characters available | ||
| 119 | XOR AL,AL ; Set zero | ||
| 120 | RET36: | ||
| 121 | POP SI | ||
| 122 | POP DS | ||
| 123 | POP BX | ||
| 124 | POP ES | ||
| 125 | POP CX | ||
| 126 | return | ||
| 127 | |||
| 128 | GotCh: | ||
| 129 | MOV AL,BYTE PTR [DSKCHRET] | ||
| 130 | DSK1: | ||
| 131 | CMP AL,"C"-"@" | ||
| 132 | JNZ RET36 | ||
| 133 | MOV BYTE PTR [DSKSTCOM],DEVRD | ||
| 134 | MOV BYTE PTR [DSKSTCALL],DRDWRHL | ||
| 135 | MOV BYTE PTR [DSKCHRET],CL | ||
| 136 | MOV [DSKSTST],0 | ||
| 137 | MOV [DSKSTCNT],1 | ||
| 138 | invoke DEVIOCALL2 ; Eat the ^C | ||
| 139 | POP SI | ||
| 140 | POP DS | ||
| 141 | POP BX ; Clean stack | ||
| 142 | POP ES | ||
| 143 | POP CX | ||
| 144 | JMP CNTCHAND | ||
| 145 | |||
| 146 | NOSTOP: | ||
| 147 | CMP AL,"P"-"@" | ||
| 148 | JNZ check_next | ||
| 149 | CMP BYTE PTR [SCAN_FLAG],0 ; ALT_Q ? | ||
| 150 | JZ INCHKJ ; no | ||
| 151 | return | ||
| 152 | check_next: | ||
| 153 | IF NOT TOGLPRN | ||
| 154 | CMP AL,"N"-"@" | ||
| 155 | JZ INCHKJ | ||
| 156 | ENDIF | ||
| 157 | |||
| 158 | CMP AL,"C"-"@" | ||
| 159 | JZ INCHKJ | ||
| 160 | check_end: | ||
| 161 | return | ||
| 162 | |||
| 163 | INCHKJ: | ||
| 164 | JMP INCHK | ||
| 165 | |||
| 166 | EndProc DSKSTATCHK | ||
| 167 | |||
| 168 | ; | ||
| 169 | ; SpoolInt - signal processes that the DOS is truly idle. We are allowed to | ||
| 170 | ; do this ONLY if we are working on a 1-12 system call AND if we are not in | ||
| 171 | ; the middle of an INT 24. | ||
| 172 | ; | ||
| 173 | procedure SPOOLINT,NEAR | ||
| 174 | PUSHF | ||
| 175 | test IdleInt,-1 | ||
| 176 | jz POPFRet | ||
| 177 | test ErrorMode,-1 | ||
| 178 | jnz POPFRet | ||
| 179 | ; | ||
| 180 | ; Note that we are going to allow an external program to issue system calls | ||
| 181 | ; at this time. We MUST preserve IdleInt across this. | ||
| 182 | ; | ||
| 183 | PUSH WORD PTR IdleInt | ||
| 184 | INT int_spooler | ||
| 185 | POP WORD PTR IdleInt | ||
| 186 | POPFRET: | ||
| 187 | POPF | ||
| 188 | return | ||
| 189 | EndProc SPOOLINT | ||
| 190 | |||
| 191 | procedure STATCHK,NEAR | ||
| 192 | |||
| 193 | invoke DSKSTATCHK ; Allows ^C to be detected under | ||
| 194 | ; input redirection | ||
| 195 | PUSH BX | ||
| 196 | XOR BX,BX | ||
| 197 | invoke GET_IO_SFT | ||
| 198 | POP BX | ||
| 199 | retc | ||
| 200 | MOV AH,1 | ||
| 201 | invoke IOFUNC | ||
| 202 | JZ SPOOLINT | ||
| 203 | CMP AL,"S"-"@" | ||
| 204 | JNZ NOSTOP | ||
| 205 | |||
| 206 | CMP BYTE PTR [SCAN_FLAG],0 ;AN000; ALT_R ? | ||
| 207 | JNZ check_end ;AN000; yes | ||
| 208 | XOR AH,AH | ||
| 209 | invoke IOFUNC ; Eat Cntrl-S | ||
| 210 | JMP SHORT PAUSOSTRT | ||
| 211 | PRINTOFF: | ||
| 212 | PRINTON: | ||
| 213 | NOT BYTE PTR [PFLAG] | ||
| 214 | PUSH BX | ||
| 215 | MOV BX,4 | ||
| 216 | invoke GET_IO_SFT | ||
| 217 | POP BX | ||
| 218 | retc | ||
| 219 | PUSH ES | ||
| 220 | PUSH DI | ||
| 221 | PUSH DS | ||
| 222 | POP ES | ||
| 223 | MOV DI,SI ; ES:DI -> SFT | ||
| 224 | TEST ES:[DI.sf_flags],sf_net_spool | ||
| 225 | JZ NORM_PR ; Not redirected, echo is OK | ||
| 226 | Callinstall NetSpoolEchoCheck,MultNet,38,<AX>,<AX> ; See if allowed | ||
| 227 | JNC NORM_PR ; Echo is OK | ||
| 228 | MOV BYTE PTR [PFLAG],0 ; If not allowed, disable echo | ||
| 229 | Callinstall NetSpoolClose,MultNet,36,<AX>,<AX> ; and close | ||
| 230 | JMP SHORT RETP6 | ||
| 231 | |||
| 232 | NORM_PR: | ||
| 233 | CMP BYTE PTR [PFLAG],0 | ||
| 234 | JNZ PRNOPN | ||
| 235 | invoke DEV_CLOSE_SFT | ||
| 236 | JMP SHORT RETP6 | ||
| 237 | |||
| 238 | PRNOPN: | ||
| 239 | invoke DEV_OPEN_SFT | ||
| 240 | RETP6: | ||
| 241 | POP DI | ||
| 242 | POP ES | ||
| 243 | return | ||
| 244 | |||
| 245 | PAUSOLP: | ||
| 246 | CALL SPOOLINT | ||
| 247 | PAUSOSTRT: | ||
| 248 | MOV AH,1 | ||
| 249 | invoke IOFUNC | ||
| 250 | JZ PAUSOLP | ||
| 251 | INCHK: | ||
| 252 | PUSH BX | ||
| 253 | XOR BX,BX | ||
| 254 | invoke GET_IO_SFT | ||
| 255 | POP BX | ||
| 256 | retc | ||
| 257 | XOR AH,AH | ||
| 258 | invoke IOFUNC | ||
| 259 | CMP AL,"P"-"@" | ||
| 260 | ;;;;; 7/14/86 ALT_Q key fix | ||
| 261 | |||
| 262 | JZ PRINTON ; no! must be CTRL_P | ||
| 263 | |||
| 264 | NOPRINT: | ||
| 265 | ;;;;; 7/14/86 ALT_Q key fix | ||
| 266 | IF NOT TOGLPRN | ||
| 267 | CMP AL,"N"-"@" | ||
| 268 | JZ PRINTOFF | ||
| 269 | ENDIF | ||
| 270 | CMP AL,"C"-"@" | ||
| 271 | retnz | ||
| 272 | EndProc STATCHK | ||
| 273 | |||
| 274 | procedure CNTCHAND,NEAR | ||
| 275 | ; Ctrl-C handler. | ||
| 276 | ; "^C" and CR/LF is printed. Then the user registers are restored and the | ||
| 277 | ; user CTRL-C handler is executed. At this point the top of the stack has 1) | ||
| 278 | ; the interrupt return address should the user CTRL-C handler wish to allow | ||
| 279 | ; processing to continue; 2) the original interrupt return address to the code | ||
| 280 | ; that performed the function call in the first place. If the user CTRL-C | ||
| 281 | ; handler wishes to continue, it must leave all registers unchanged and RET | ||
| 282 | ; (not IRET) with carry CLEAR. If carry is SET then an terminate system call | ||
| 283 | ; is simulated. | ||
| 284 | TEST [DOS34_FLAG],CTRL_BREAK_FLAG ;AN002; from RAWOUT | ||
| 285 | JNZ around_deadlock ;AN002; | ||
| 286 | MOV AL,3 ; Display "^C" | ||
| 287 | invoke BUFOUT | ||
| 288 | invoke CRLF | ||
| 289 | around_deadlock: ;AN002; | ||
| 290 | Context DS | ||
| 291 | CMP BYTE PTR [CONSWAP],0 | ||
| 292 | JZ NOSWAP | ||
| 293 | invoke SWAPBACK | ||
| 294 | NOSWAP: | ||
| 295 | CLI ; Prepare to play with stack | ||
| 296 | MOV SS,[user_SS] ; User stack now restored | ||
| 297 | ASSUME SS:NOTHING | ||
| 298 | MOV SP,[user_SP] | ||
| 299 | invoke restore_world ; User registers now restored | ||
| 300 | ASSUME DS:NOTHING | ||
| 301 | MOV BYTE PTR [INDOS],0 ; Go to known state | ||
| 302 | MOV BYTE PTR [ERRORMODE],0 | ||
| 303 | MOV [ConC_spsave],SP ; save his SP | ||
| 304 | CLC | ||
| 305 | INT int_ctrl_c ; Execute user Ctrl-C handler | ||
| 306 | ; | ||
| 307 | ; The user has returned to us. The circumstances we allow are: | ||
| 308 | ; | ||
| 309 | ; IRET We retry the operation by redispatching the system call | ||
| 310 | ; CLC/RETF POP the stack and retry | ||
| 311 | ; ... Exit the current process with ^C exit | ||
| 312 | ; | ||
| 313 | ; User's may RETURN to us and leave interrupts on. Turn 'em off just to be | ||
| 314 | ; sure | ||
| 315 | ; | ||
| 316 | CLI | ||
| 317 | MOV [user_IN_AX],ax ; save the AX | ||
| 318 | PUSHF ; and the flags (maybe new call) | ||
| 319 | POP AX | ||
| 320 | ; | ||
| 321 | ; See if the input stack is identical to the output stack | ||
| 322 | ; | ||
| 323 | CMP SP,[ConC_spsave] | ||
| 324 | JNZ ctrlc_try_new ; current SP not the same as saved SP | ||
| 325 | ; | ||
| 326 | ; Repeat the operation by redispatching the system call. | ||
| 327 | ; | ||
| 328 | ctrlc_repeat: | ||
| 329 | MOV AX,User_In_AX | ||
| 330 | transfer COMMAND | ||
| 331 | ; | ||
| 332 | ; The current SP is NOT the same as the input SP. Presume that he RETF'd | ||
| 333 | ; leaving some flags on the stack and examine the input | ||
| 334 | ; | ||
| 335 | ctrlc_try_new: | ||
| 336 | ADD SP,2 ; pop those flags | ||
| 337 | TEST AX,f_carry ; did he return with carry? | ||
| 338 | JZ Ctrlc_Repeat ; no carry set, just retry | ||
| 339 | ; | ||
| 340 | ; Well... time to abort the user. Signal a ^C exit and use the EXIT system | ||
| 341 | ; call.. | ||
| 342 | ; | ||
| 343 | ctrlc_abort: | ||
| 344 | MOV AX,(EXIT SHL 8) + 0 | ||
| 345 | MOV DidCTRLC,-1 | ||
| 346 | transfer COMMAND ; give up by faking $EXIT | ||
| 347 | |||
| 348 | EndProc CNTCHAND | ||
| 349 | |||
| 350 | Break <DIVISION OVERFLOW INTERRUPT> | ||
| 351 | |||
| 352 | ; Default handler for division overflow trap | ||
| 353 | procedure DIVOV,NEAR | ||
| 354 | ASSUME DS:NOTHING,ES:NOTHING,SS:NOTHING | ||
| 355 | MOV SI,OFFSET DOSGROUP:DIVMES | ||
| 356 | MOV BX,DivMesLen | ||
| 357 | MOV AX,CS | ||
| 358 | MOV SS,AX | ||
| 359 | MOV SP,OFFSET DOSGROUP:AUXSTACK ; Enough stack for interrupts | ||
| 360 | CALL OutMes | ||
| 361 | JMP ctrlc_abort ; Use Ctrl-C abort on divide overflow | ||
| 362 | EndProc DIVOV | ||
| 363 | |||
| 364 | ; | ||
| 365 | ; OutMes: perform message output | ||
| 366 | ; Inputs: SS:SI points to message | ||
| 367 | ; BX has message length | ||
| 368 | ; Outputs: message to BCON | ||
| 369 | ; | ||
| 370 | procedure OutMes,NEAR | ||
| 371 | |||
| 372 | Context ES ; get ES addressability | ||
| 373 | Context DS ; get DS addressability | ||
| 374 | |||
| 375 | MOV BYTE PTR [DskStCom],DevWrt | ||
| 376 | MOV BYTE PTR [DskStCall],DRdWrHL | ||
| 377 | MOV [DskSTST],0 | ||
| 378 | MOV [DskStCnt],BX | ||
| 379 | MOV BX,OFFSET DOSGROUP:DskStCall | ||
| 380 | MOV WORD PTR [DskChRet+1],SI ; transfer address (need an EQU) | ||
| 381 | LDS SI,[BCON] | ||
| 382 | ASSUME DS:NOTHING | ||
| 383 | invoke DEVIOCALL2 | ||
| 384 | MOV WORD PTR [DskChRet+1],OFFSET DOSGROUP:DevIOBuf | ||
| 385 | MOV [DskStCnt],1 | ||
| 386 | return | ||
| 387 | EndProc OutMes | ||
| 388 | |||
| 389 | Break <CHARHRD,HARDERR,ERROR -- HANDLE DISK ERRORS AND RETURN TO USER> | ||
| 390 | |||
| 391 | procedure CHARHARD,NEAR | ||
| 392 | ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGROUP | ||
| 393 | |||
| 394 | ; Character device error handler | ||
| 395 | ; Same function as HARDERR | ||
| 396 | |||
| 397 | OR AH,allowed_FAIL + allowed_IGNORE + allowed_RETRY | ||
| 398 | MOV Allowed,AH | ||
| 399 | MOV WORD PTR [EXITHOLD+2],ES | ||
| 400 | MOV WORD PTR [EXITHOLD],BP | ||
| 401 | PUSH SI | ||
| 402 | AND DI,STECODE | ||
| 403 | MOV BP,DS ; Device pointer is BP:SI | ||
| 404 | CALL FATALC | ||
| 405 | POP SI | ||
| 406 | return | ||
| 407 | EndProc CHARHARD | ||
| 408 | |||
| 409 | ; Hard disk error handler. Entry conditions: | ||
| 410 | ; DS:BX = Original disk transfer address | ||
| 411 | ; DX = Original logical sector number | ||
| 412 | ; CX = Number of sectors to go (first one gave the error) | ||
| 413 | ; AX = Hardware error code | ||
| 414 | ; DI = Original sector transfer count | ||
| 415 | ; ES:BP = Base of drive parameters | ||
| 416 | ; [READOP] = 0 for read, 1 for write | ||
| 417 | ; [ALLOWED] Set with allowed responses to this error (other bits MUST BE 0) | ||
| 418 | ; Output: | ||
| 419 | ; [FAILERR] will be set if user responded FAIL | ||
| 420 | |||
| 421 | procedure HardErr,NEAR | ||
| 422 | ASSUME DS:NOTHING,ES:NOTHING | ||
| 423 | |||
| 424 | XCHG AX,DI ; Error code in DI, count in AX | ||
| 425 | AND DI,STECODE ; And off status bits | ||
| 426 | CMP DI,error_I24_write_protect ; Write Protect Error? | ||
| 427 | JNZ NOSETWRPERR | ||
| 428 | PUSH AX | ||
| 429 | MOV AL,ES:[BP.dpb_drive] | ||
| 430 | MOV BYTE PTR [WPERR],AL ; Flag drive with WP error | ||
| 431 | POP AX | ||
| 432 | NOSETWRPERR: | ||
| 433 | SUB AX,CX ; Number of sectors successfully transferred | ||
| 434 | ADD DX,AX ; First sector number to retry | ||
| 435 | PUSH DX | ||
| 436 | MUL ES:[BP.dpb_sector_size] ; Number of bytes transferred | ||
| 437 | POP DX | ||
| 438 | ADD BX,AX ; First address for retry | ||
| 439 | XOR AH,AH ; Flag disk section in error | ||
| 440 | CMP DX,ES:[BP.dpb_first_FAT] ; In reserved area? | ||
| 441 | JB ERRINT | ||
| 442 | INC AH ; Flag for FAT | ||
| 443 | CMP DX,ES:[BP.dpb_dir_sector] ; In FAT? | ||
| 444 | JAE TESTDIR ; No | ||
| 445 | MOV ES:[BP.dpb_free_cnt],-1 ; Err in FAT must force recomp of freespace | ||
| 446 | JMP SHORT ERRINT | ||
| 447 | |||
| 448 | TESTDIR: | ||
| 449 | INC AH | ||
| 450 | CMP DX,ES:[BP.dpb_first_sector] ; In directory? | ||
| 451 | JB ERRINT | ||
| 452 | INC AH ; Must be in data area | ||
| 453 | ERRINT: | ||
| 454 | SHL AH,1 ; Make room for read/write bit | ||
| 455 | OR AH,BYTE PTR [READOP] ; Set bit 0 | ||
| 456 | ; If we have a write protect error when writing on a critical area on disk, | ||
| 457 | ; do not allow a retry as this may write out garbage on any subsequent disk. | ||
| 458 | ;test ah,1 | ||
| 459 | ;jz Not_Crit | ||
| 460 | ;cmp ah,5 | ||
| 461 | ;ja Not_Crit | ||
| 462 | ;and [ALLOWED],NOT Allowed_RETRY | ||
| 463 | Not_Crit: | ||
| 464 | OR AH,[ALLOWED] ; Set the allowed_ bits | ||
| 465 | entry FATAL | ||
| 466 | MOV AL,ES:[BP.dpb_drive] ; Get drive number | ||
| 467 | entry FATAL1 | ||
| 468 | MOV WORD PTR [EXITHOLD+2],ES | ||
| 469 | MOV WORD PTR [EXITHOLD],BP ; The only things we preserve | ||
| 470 | LES SI,ES:[BP.dpb_driver_addr] | ||
| 471 | MOV BP,ES ; BP:SI points to the device involved | ||
| 472 | ; | ||
| 473 | ; DI has the INT-24-style extended error. We now map the error code for this | ||
| 474 | ; into the normalized get extended error set by using the ErrMap24 table as an | ||
| 475 | ; translate table. Note that we translate ONLY the device returned codes and | ||
| 476 | ; leave all others beyond the look up table alone. | ||
| 477 | ; | ||
| 478 | FATALC: | ||
| 479 | call SET_I24_EXTENDED_ERROR | ||
| 480 | CMP DI,error_I24_gen_failure | ||
| 481 | JBE GOT_RIGHT_CODE ; Error codes above gen_failure get | ||
| 482 | MOV DI,error_I24_gen_failure ; mapped to gen_failure. Real codes | ||
| 483 | ; Only come via GetExtendedError | ||
| 484 | |||
| 485 | entry NET_I24_ENTRY | ||
| 486 | ; Entry point used by REDIRector on Network I 24 errors. | ||
| 487 | ; | ||
| 488 | ; ASSUME DS:NOTHING,ES:NOTHING,SS:DOSGROUP | ||
| 489 | ; | ||
| 490 | ; ALL I 24 regs set up. ALL Extended error info SET. ALLOWED Set. | ||
| 491 | ; EXITHOLD set for restore of ES:BP. | ||
| 492 | |||
| 493 | GOT_RIGHT_CODE: | ||
| 494 | CMP BYTE PTR [ERRORMODE],0 ; No INT 24s if already INT 24 | ||
| 495 | JZ NoSetFail | ||
| 496 | MOV AL,3 | ||
| 497 | JMP FailRet | ||
| 498 | NoSetFail: | ||
| 499 | IF BUFFERFLAG | ||
| 500 | invoke RESTORE_USER_MAP ;AN000;LB. restore user's EMS map | ||
| 501 | ENDIF | ||
| 502 | MOV [CONTSTK],SP | ||
| 503 | Context ES | ||
| 504 | fmt TypINT24,LevLog,<"INT 24: AX = $x DI = $x\n">,<AX,DI> | ||
| 505 | ; | ||
| 506 | ; Wango!!! We may need to free some user state info... In particular, we | ||
| 507 | ; may have locked down a JFN for a user and he may NEVER return to us. Thus, | ||
| 508 | ; we need to free it here and then reallocate it when we come back. | ||
| 509 | ; | ||
| 510 | CMP SFN,-1 | ||
| 511 | JZ NoFree | ||
| 512 | SaveReg <DS,SI> | ||
| 513 | LDS SI,pJFN | ||
| 514 | MOV BYTE PTR [SI],0FFH | ||
| 515 | RestoreReg <SI,DS> | ||
| 516 | NoFree: | ||
| 517 | CLI ; Prepare to play with stack | ||
| 518 | INC BYTE PTR [ERRORMODE] ; Flag INT 24 in progress | ||
| 519 | DEC BYTE PTR [INDOS] ; INT 24 handler might not return | ||
| 520 | ;; Extneded Open hooks | ||
| 521 | TEST [DOS34_FLAG],Force_I24_Fail ;AN000;IFS. form IFS Call Back ;AN000; | ||
| 522 | JNZ faili24 ;AN000;IFS. ;AN000; | ||
| 523 | TEST [EXTOPEN_ON],EXT_OPEN_I24_OFF ;AN000;IFS.I24 error disabled ;AN000; | ||
| 524 | JZ i24yes ;AN000;IFS.no ;AN000; | ||
| 525 | faili24: ;AN000; | ||
| 526 | MOV AL,3 ;AN000;IFS.fake fail ;AN000; | ||
| 527 | JMP passi24 ;AN000;IFS.exit ;AN000; | ||
| 528 | i24yes: ;AN000; | ||
| 529 | |||
| 530 | ;; Extended Open hooks | ||
| 531 | MOV SS,[user_SS] | ||
| 532 | ASSUME SS:NOTHING | ||
| 533 | MOV SP,ES:[user_SP] ; User stack pointer restored | ||
| 534 | INT int_fatal_abort ; Fatal error interrupt vector, must preserve ES | ||
| 535 | MOV ES:[user_SP],SP ; restore our stack | ||
| 536 | MOV ES:[user_SS],SS | ||
| 537 | MOV BP,ES | ||
| 538 | MOV SS,BP | ||
| 539 | ASSUME SS:DOSGROUP | ||
| 540 | passi24: ;AN000; | ||
| 541 | MOV SP,[CONTSTK] | ||
| 542 | INC BYTE PTR [INDOS] ; Back in the DOS | ||
| 543 | MOV BYTE PTR [ERRORMODE],0 ; Back from INT 24 | ||
| 544 | STI | ||
| 545 | ;; MOV [ACT_PAGE],-1 ;LB. invalidate DOS active page ;AN000; | ||
| 546 | ;; invoke SAVE_MAP ;LB. save user's EMS map ;AN000; | ||
| 547 | fmt TypINT24,LevLog,<"INT 24: User reply = $x\n">,<AX> | ||
| 548 | FAILRET: | ||
| 549 | LES BP,[EXITHOLD] | ||
| 550 | ASSUME ES:NOTHING | ||
| 551 | ; | ||
| 552 | ; Triage the user's reply. | ||
| 553 | ; | ||
| 554 | CMP AL,1 | ||
| 555 | JB CheckIgnore ; 0 => ignore | ||
| 556 | JZ CheckRetry ; 1 => retry | ||
| 557 | CMP AL,3 ; 3 => fail | ||
| 558 | JNZ DoAbort ; 2, invalid => abort | ||
| 559 | ; | ||
| 560 | ; The reply was fail. See if we are allowed to fail. | ||
| 561 | ; | ||
| 562 | TEST [ALLOWED],allowed_FAIL ; Can we? | ||
| 563 | JZ DoAbort ; No, do abort | ||
| 564 | DoFail: | ||
| 565 | MOV AL,3 ; just in case... | ||
| 566 | TEST [EXTOPEN_ON],EXT_OPEN_I24_OFF ;AN000;EO. I24 error disabled | ||
| 567 | JNZ cleanup ;AN000;EO. no | ||
| 568 | INC [FAILERR] ; Tell everybody | ||
| 569 | CleanUp: | ||
| 570 | MOV WpErr,-1 | ||
| 571 | CMP SFN,-1 | ||
| 572 | retz | ||
| 573 | SaveReg <DS,SI,AX> | ||
| 574 | MOV AX,SFN | ||
| 575 | LDS SI,pJFN | ||
| 576 | MOV [SI],AL | ||
| 577 | RestoreReg <AX,SI,DS> | ||
| 578 | return | ||
| 579 | ; | ||
| 580 | ; The reply was IGNORE. See if we are allowed to ignore. | ||
| 581 | ; | ||
| 582 | CheckIgnore: | ||
| 583 | TEST [ALLOWED],allowed_IGNORE ; Can we? | ||
| 584 | JZ DoFail ; No, do fail | ||
| 585 | JMP CleanUp | ||
| 586 | ; | ||
| 587 | ; The reply was RETRY. See if we are allowed to retry. | ||
| 588 | ; | ||
| 589 | CheckRetry: | ||
| 590 | TEST [ALLOWED],allowed_RETRY ; Can we? | ||
| 591 | JZ DoFail ; No, do fail | ||
| 592 | JMP CleanUp | ||
| 593 | ; | ||
| 594 | ; The reply was ABORT. | ||
| 595 | ; | ||
| 596 | DoAbort: | ||
| 597 | Context DS | ||
| 598 | CMP BYTE PTR [CONSWAP],0 | ||
| 599 | JZ NOSWAP2 | ||
| 600 | invoke SWAPBACK | ||
| 601 | NOSWAP2: | ||
| 602 | ; | ||
| 603 | ; See if we are to truly abort. If we are in the process of aborting, turn | ||
| 604 | ; this abort into a fail. | ||
| 605 | ; | ||
| 606 | TEST fAborting,-1 | ||
| 607 | JNZ DoFail | ||
| 608 | ; | ||
| 609 | ; Set return code | ||
| 610 | ; | ||
| 611 | MOV BYTE PTR [exit_Type],Exit_hard_error | ||
| 612 | XOR AL,AL | ||
| 613 | ; | ||
| 614 | ; we are truly aborting the process. Go restore information from the PDB as | ||
| 615 | ; necessary. | ||
| 616 | ; | ||
| 617 | Transfer exit_inner | ||
| 618 | ; | ||
| 619 | ; reset_environment checks the DS value against the CurrentPDB. If they are | ||
| 620 | ; different, then an old-style return is performed. If they are the same, | ||
| 621 | ; then we release jfns and restore to parent. We still use the PDB at DS:0 as | ||
| 622 | ; the source of the terminate addresses. | ||
| 623 | ; | ||
| 624 | ; Some subtlety: We are about to issue a bunch of calls that *may* generate | ||
| 625 | ; INT 24s. We *cannot* allow the user to restart the abort process; we may | ||
| 626 | ; end up aborting the wrong process or turn a terminate/stay/resident into a | ||
| 627 | ; normal abort and leave interrupt handlers around. What we do is to set a | ||
| 628 | ; flag that will indicate that if any abort code is seen, we just continue the | ||
| 629 | ; operation. In essence, we dis-allow the abort response. | ||
| 630 | ; | ||
| 631 | ; output: none. | ||
| 632 | ; | ||
| 633 | entry reset_environment | ||
| 634 | ASSUME DS:NOTHING,ES:NOTHING | ||
| 635 | |||
| 636 | invoke Reset_Version ;AN007;MS. reset version number | ||
| 637 | PUSH DS ; save PDB of process | ||
| 638 | |||
| 639 | ; | ||
| 640 | ; There are no critical sections in force. Although we may enter here with | ||
| 641 | ; critical sections locked down, they are no longer relevant. We may safely | ||
| 642 | ; free all allocated resources. | ||
| 643 | ; | ||
| 644 | MOV AH,82h | ||
| 645 | INT int_IBM | ||
| 646 | |||
| 647 | MOV fAborting,-1 ; signal abort in progress | ||
| 648 | |||
| 649 | CallInstall NetResetEnvironment, multNet, 34 ;DOS 4.00 doesn't need it | ||
| 650 | ; Allow REDIR to clear some stuff | ||
| 651 | ; On process exit. | ||
| 652 | MOV AL,int_Terminate | ||
| 653 | invoke $Get_interrupt_vector ; and who to go to | ||
| 654 | |||
| 655 | POP CX ; get ThisPDB | ||
| 656 | SaveReg <ES,BX> ; save return address | ||
| 657 | |||
| 658 | MOV BX,[CurrentPDB] ; get currentPDB | ||
| 659 | MOV DS,BX | ||
| 660 | MOV AX,DS:[PDB_Parent_PID] ; get parentPDB | ||
| 661 | |||
| 662 | ; | ||
| 663 | ; AX = parentPDB, BX = CurrentPDB, CX = ThisPDB | ||
| 664 | ; Only free handles if AX <> BX and BX = CX and [exit_code].upper is not | ||
| 665 | ; Exit_keep_process | ||
| 666 | ; | ||
| 667 | CMP AX,BX | ||
| 668 | JZ reset_return ; parentPDB = CurrentPDB | ||
| 669 | CMP BX,CX | ||
| 670 | JNZ reset_return ; CurrentPDB <> ThisPDB | ||
| 671 | PUSH AX ; save parent | ||
| 672 | CMP BYTE PTR [exit_type],Exit_keep_process | ||
| 673 | JZ reset_to_parent ; keeping this process | ||
| 674 | ; | ||
| 675 | ; We are truly removing a process. Free all allocation blocks belonging to | ||
| 676 | ; this PDB | ||
| 677 | ; | ||
| 678 | invoke arena_free_process | ||
| 679 | ; | ||
| 680 | ; Kill off remainder of this process. Close file handles and signal to | ||
| 681 | ; relevant network folks that this process is dead. Remember that CurrentPDB | ||
| 682 | ; is STILL the current process! | ||
| 683 | ; | ||
| 684 | invoke DOS_ABORT | ||
| 685 | |||
| 686 | reset_to_parent: | ||
| 687 | POP [CurrentPDB] ; set up process as parent | ||
| 688 | |||
| 689 | reset_return: ; come here for normal return | ||
| 690 | PUSH CS | ||
| 691 | POP DS | ||
| 692 | ASSUME DS:DOSGROUP | ||
| 693 | MOV AL,-1 | ||
| 694 | ; | ||
| 695 | ; make sure that everything is clean In this case ignore any errors, we cannot | ||
| 696 | ; "FAIL" the abort, the program being aborted is dead. | ||
| 697 | ; | ||
| 698 | EnterCrit critDisk | ||
| 699 | invoke FLUSHBUF | ||
| 700 | LeaveCrit critDisk | ||
| 701 | ; | ||
| 702 | ; Decrement open ref. count if we had done a virtual open earlier. | ||
| 703 | ; | ||
| 704 | invoke CHECK_VIRT_OPEN | ||
| 705 | IF BUFFERFLAG | ||
| 706 | invoke RESTORE_USER_MAP ;AN000;LB. restore user's EMS map | ||
| 707 | ENDIF | ||
| 708 | CLI | ||
| 709 | MOV BYTE PTR [INDOS],0 ; Go to known state | ||
| 710 | MOV BYTE PTR [WPERR],-1 ; Forget about WP error | ||
| 711 | MOV fAborting,0 ; let aborts occur | ||
| 712 | POP WORD PTR ExitHold | ||
| 713 | POP WORD PTR ExitHold+2 | ||
| 714 | ; | ||
| 715 | ; Snake into multitasking... Get stack from CurrentPDB person | ||
| 716 | ; | ||
| 717 | MOV DS,[CurrentPDB] | ||
| 718 | ASSUME DS:NOTHING | ||
| 719 | MOV SS,WORD PTR DS:[PDB_user_stack+2] | ||
| 720 | MOV SP,WORD PTR DS:[PDB_user_stack] | ||
| 721 | |||
| 722 | ASSUME SS:NOTHING | ||
| 723 | invoke restore_world | ||
| 724 | ASSUME ES:NOTHING | ||
| 725 | MOV User_SP,AX | ||
| 726 | POP AX ; suck off CS:IP of interrupt... | ||
| 727 | POP AX | ||
| 728 | POP AX | ||
| 729 | MOV AX,0F202h ; STI | ||
| 730 | PUSH AX | ||
| 731 | PUSH WORD PTR [EXITHOLD+2] | ||
| 732 | PUSH WORD PTR [EXITHOLD] | ||
| 733 | MOV AX,User_SP | ||
| 734 | IRET ; Long return back to user terminate address | ||
| 735 | EndProc HardErr | ||
| 736 | |||
| 737 | ; | ||
| 738 | ; This routine handles extended error codes. | ||
| 739 | ; Input : DI = error code from device | ||
| 740 | ; Output: All EXTERR fields are set | ||
| 741 | ; | ||
| 742 | Procedure SET_I24_EXTENDED_ERROR,NEAR | ||
| 743 | PUSH AX | ||
| 744 | MOV AX,OFFSET DOSGroup:ErrMap24End | ||
| 745 | SUB AX,OFFSET DOSGroup:ErrMap24 | ||
| 746 | ; | ||
| 747 | ; AX is the index of the first unavailable error. Do not translate if | ||
| 748 | ; greater or equal to AX. | ||
| 749 | ; | ||
| 750 | CMP DI,AX | ||
| 751 | MOV AX,DI | ||
| 752 | JAE NoTrans | ||
| 753 | MOV AL,ErrMap24[DI] | ||
| 754 | XOR AH,AH | ||
| 755 | NoTrans: | ||
| 756 | MOV [EXTERR],AX | ||
| 757 | POP AX | ||
| 758 | ; | ||
| 759 | ; Now Extended error is set correctly. Translate it to get correct error | ||
| 760 | ; locus class and recommended action. | ||
| 761 | ; | ||
| 762 | PUSH SI | ||
| 763 | MOV SI,OFFSET DOSGROUP:ERR_TABLE_24 | ||
| 764 | invoke CAL_LK ; Set other extended error fields | ||
| 765 | POP SI | ||
| 766 | ret | ||
| 767 | EndProc SET_I24_EXTENDED_ERROR | ||
| 768 | |||
| 769 | CODE ENDS | ||
| 770 | END | ||
| 771 | \ No newline at end of file | ||