summaryrefslogtreecommitdiff
path: root/v4.0/src/DOS/CTRLC.ASM
blob: 5a79e045980af38e6221f30a36b9b82924e814a1 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
;	SCCSID = @(#)ctrlc.asm	1.4 85/08/16
; Low level routines for detecting special characters on CON input,
;	the ^C exit/int code, the Hard error INT 24 code, the
;	process termination code, and the INT 0 divide overflow handler.
;
;   FATAL
;   FATAL1
;   reset_environment
;   DSKSTATCHK
;   SPOOLINT
;   STATCHK
;   CNTCHAND
;   DIVOV
;   CHARHARD
;   HardErr
;
;   Revision history:
;
;	AN000	version 4.0   Jan 1988
;	A002	PTM    -- dir >lpt3 hangs
;	A003	PTM 3957- fake version for IBMCAHE.COM

;
; get the appropriate segment definitions
;
.xlist
include dosseg.asm

CODE	SEGMENT BYTE PUBLIC  'CODE'
	ASSUME	SS:DOSGROUP,CS:DOSGROUP

.xcref
INCLUDE DOSSYM.INC
INCLUDE DEVSYM.INC
include version.inc
.cref
.list

	I_need	SFN,WORD
	I_NEED	pJFN,DWORD
	i_need	DevIOBuf,BYTE
	i_need	DidCTRLC,BYTE
	i_need	INDOS,BYTE
	i_need	DSKSTCOM,BYTE
	i_need	DSKSTCALL,BYTE
	i_need	DSKSTST,WORD
	i_need	BCON,DWORD
	i_need	DSKCHRET,BYTE
	i_need	DSKSTCNT,WORD
	i_need	IDLEINT,BYTE
	i_need	CONSWAP,BYTE
	i_need	user_SS,WORD
	i_need	user_SP,WORD
	i_need	User_In_AX,WORD
	i_need	ERRORMODE,BYTE
	i_need	ConC_spsave,WORD
	i_need	Exit_type,BYTE
	i_need	PFLAG,BYTE
	i_need	ExitHold,DWORD
	i_need	WPErr,BYTE
	i_need	ReadOp,BYTE
	i_need	CONTSTK,WORD
	i_need	Exit_Code,WORD
	i_need	CurrentPDB,WORD
	i_need	DIVMES,BYTE
	i_need	DivMesLen,WORD
	i_need	ALLOWED,BYTE
	i_need	FAILERR,BYTE
	i_need	EXTERR,WORD
	i_need	ERR_TABLE_24,BYTE
	I_need	ErrMap24,BYTE
	I_need	ErrMap24End,BYTE
	I_need	fAborting,BYTE
	I_need	AUXStack,BYTE
	I_need	SCAN_FLAG,BYTE
	I_need	EXTOPEN_ON,BYTE 	      ;AN000; DOS 4.0
	I_need	InterCon,BYTE		      ;AN000; DOS 4.0
	I_need	DOS34_FLAG,WORD 	      ;AN000; DOS 4.0
	I_need	ACT_PAGE,WORD		      ;AN000; DOS 4.0
	I_need	Special_Version,WORD	      ;AN007; DOS 4.0
if debug
	I_need	BugLev,WORD
	I_need	BugTyp,WORD
include bugtyp.asm
endif
IF	BUFFERFLAG
	extrn	restore_user_map:near
ENDIF

Break	<Checks for ^C in CON I/O>

ASSUME	DS:NOTHING,ES:NOTHING

	procedure   DSKSTATCHK,NEAR	; Check for ^C if only one level in
	CMP	BYTE PTR [INDOS],1
	retnz				; Do NOTHING
	PUSH	CX
	PUSH	ES
	PUSH	BX
	PUSH	DS
	PUSH	SI
	PUSH	CS
	POP	ES
	Context DS
	DOSAssume   CS,<DS>,"DskStatChk"
	MOV	BYTE PTR [DSKSTCOM],DEVRDND
	MOV	BYTE PTR [DSKSTCALL],DRDNDHL
	MOV	[DSKSTST],0
 IF  DBCS				;AN000;
	MOV	AL, [InterCon]		;AN000;get type of status read 2/13/KK
	MOV	BYTE PTR [DSKCHRET],AL	;AN000; load interim flag into packet
 ENDIF					;AN000;
	MOV	BX,OFFSET DOSGROUP:DSKSTCALL
	LDS	SI,[BCON]
ASSUME	DS:NOTHING
	invoke	DEVIOCALL2
	TEST	[DSKSTST],STBUI
	JZ	GotCh			; No characters available
	XOR	AL,AL			; Set zero
RET36:
	POP	SI
	POP	DS
	POP	BX
	POP	ES
	POP	CX
	return

GotCh:
	MOV	AL,BYTE PTR [DSKCHRET]
DSK1:
	CMP	AL,"C"-"@"
	JNZ	RET36
	MOV	BYTE PTR [DSKSTCOM],DEVRD
	MOV	BYTE PTR [DSKSTCALL],DRDWRHL
	MOV	BYTE PTR [DSKCHRET],CL
	MOV	[DSKSTST],0
	MOV	[DSKSTCNT],1
	invoke	DEVIOCALL2		; Eat the ^C
	POP	SI
	POP	DS
	POP	BX			; Clean stack
	POP	ES
	POP	CX
	JMP	CNTCHAND

NOSTOP:
	CMP	AL,"P"-"@"
	JNZ	check_next
	CMP	BYTE PTR [SCAN_FLAG],0	      ; ALT_Q ?
	JZ	INCHKJ			      ; no
	return
check_next:
	IF	NOT TOGLPRN
	CMP	AL,"N"-"@"
	JZ	INCHKJ
	ENDIF

	CMP	AL,"C"-"@"
	JZ	INCHKJ
check_end:
	return

INCHKJ:
	JMP	INCHK

EndProc DSKSTATCHK

;
; SpoolInt - signal processes that the DOS is truly idle.  We are allowed to
; do this ONLY if we are working on a 1-12 system call AND if we are not in
; the middle of an INT 24.
;
procedure   SPOOLINT,NEAR
	PUSHF
	test	IdleInt,-1
	jz	POPFRet
	test	ErrorMode,-1
	jnz	POPFRet
;
; Note that we are going to allow an external program to issue system calls
; at this time.  We MUST preserve IdleInt across this.
;
	PUSH	WORD PTR IdleInt
	INT	int_spooler
	POP	WORD PTR IdleInt
POPFRET:
	POPF
	return
EndProc SPOOLINT

	procedure   STATCHK,NEAR

	invoke	DSKSTATCHK		; Allows ^C to be detected under
					; input redirection
	PUSH	BX
	XOR	BX,BX
	invoke	GET_IO_SFT
	POP	BX
	retc
	MOV	AH,1
	invoke	IOFUNC
	JZ	SPOOLINT
	CMP	AL,"S"-"@"
	JNZ	NOSTOP

	CMP	BYTE PTR [SCAN_FLAG],0	      ;AN000; ALT_R ?
	JNZ	check_end		      ;AN000; yes
	XOR	AH,AH
	invoke	IOFUNC			; Eat Cntrl-S
	JMP	SHORT PAUSOSTRT
PRINTOFF:
PRINTON:
	NOT	BYTE PTR [PFLAG]
	PUSH	BX
	MOV	BX,4
	invoke	GET_IO_SFT
	POP	BX
	retc
	PUSH	ES
	PUSH	DI
	PUSH	DS
	POP	ES
	MOV	DI,SI			; ES:DI -> SFT
	TEST	ES:[DI.sf_flags],sf_net_spool
	JZ	NORM_PR 		; Not redirected, echo is OK
	Callinstall NetSpoolEchoCheck,MultNet,38,<AX>,<AX> ; See if allowed
	JNC	NORM_PR 		; Echo is OK
	MOV	BYTE PTR [PFLAG],0	; If not allowed, disable echo
	Callinstall NetSpoolClose,MultNet,36,<AX>,<AX> ; and close
	JMP	SHORT RETP6

NORM_PR:
	CMP	BYTE PTR [PFLAG],0
	JNZ	PRNOPN
	invoke	DEV_CLOSE_SFT
	JMP	SHORT RETP6

PRNOPN:
	invoke	DEV_OPEN_SFT
RETP6:
	POP	DI
	POP	ES
	return

PAUSOLP:
	CALL	SPOOLINT
PAUSOSTRT:
	MOV	AH,1
	invoke	IOFUNC
	JZ	PAUSOLP
INCHK:
	PUSH	BX
	XOR	BX,BX
	invoke	GET_IO_SFT
	POP	BX
	retc
	XOR	AH,AH
	invoke	IOFUNC
	CMP	AL,"P"-"@"
;;;;;  7/14/86	ALT_Q key fix

	JZ	PRINTON 		      ; no! must be CTRL_P

NOPRINT:
;;;;;  7/14/86	ALT_Q key fix
	IF	NOT TOGLPRN
	CMP	AL,"N"-"@"
	JZ	PRINTOFF
	ENDIF
	CMP	AL,"C"-"@"
	retnz
EndProc STATCHK

	procedure   CNTCHAND,NEAR
; Ctrl-C handler.
; "^C" and CR/LF is printed.  Then the user registers are restored and the
; user CTRL-C handler is executed.  At this point the top of the stack has 1)
; the interrupt return address should the user CTRL-C handler wish to allow
; processing to continue; 2) the original interrupt return address to the code
; that performed the function call in the first place.	If the user CTRL-C
; handler wishes to continue, it must leave all registers unchanged and RET
; (not IRET) with carry CLEAR.	If carry is SET then an terminate system call
; is simulated.
	TEST	[DOS34_FLAG],CTRL_BREAK_FLAG  ;AN002; from RAWOUT
	JNZ	around_deadlock 	      ;AN002;
	MOV	AL,3			; Display "^C"
	invoke	BUFOUT
	invoke	CRLF
around_deadlock:			      ;AN002;
	Context DS
	CMP	BYTE PTR [CONSWAP],0
	JZ	NOSWAP
	invoke	SWAPBACK
NOSWAP:
	CLI				; Prepare to play with stack
	MOV	SS,[user_SS]		; User stack now restored
ASSUME	SS:NOTHING
	MOV	SP,[user_SP]
	invoke	restore_world		; User registers now restored
ASSUME	DS:NOTHING
	MOV	BYTE PTR [INDOS],0	; Go to known state
	MOV	BYTE PTR [ERRORMODE],0
	MOV	[ConC_spsave],SP	; save his SP
	CLC
	INT	int_ctrl_c		; Execute user Ctrl-C handler
;
; The user has returned to us.	The circumstances we allow are:
;
;   IRET	We retry the operation by redispatching the system call
;   CLC/RETF	POP the stack and retry
;   ... 	Exit the current process with ^C exit
;
; User's may RETURN to us and leave interrupts on.  Turn 'em off just to be
; sure
;
	CLI
	MOV	[user_IN_AX],ax 	; save the AX
	PUSHF				; and the flags (maybe new call)
	POP	AX
;
; See if the input stack is identical to the output stack
;
	CMP	SP,[ConC_spsave]
	JNZ	ctrlc_try_new		; current SP not the same as saved SP
;
; Repeat the operation by redispatching the system call.
;
ctrlc_repeat:
	MOV	AX,User_In_AX
	transfer    COMMAND
;
; The current SP is NOT the same as the input SP.  Presume that he RETF'd
; leaving some flags on the stack and examine the input
;
ctrlc_try_new:
	ADD	SP,2			; pop those flags
	TEST	AX,f_carry		; did he return with carry?
	JZ	Ctrlc_Repeat		; no carry set, just retry
;
; Well...  time to abort the user.  Signal a ^C exit and use the EXIT system
; call..
;
ctrlc_abort:
	MOV	AX,(EXIT SHL 8) + 0
	MOV	DidCTRLC,-1
	transfer    COMMAND		; give up by faking $EXIT

EndProc CNTCHAND

Break	<DIVISION OVERFLOW INTERRUPT>

; Default handler for division overflow trap
	procedure   DIVOV,NEAR
ASSUME	DS:NOTHING,ES:NOTHING,SS:NOTHING
	MOV	SI,OFFSET DOSGROUP:DIVMES
	MOV	BX,DivMesLen
	MOV	AX,CS
	MOV	SS,AX
	MOV	SP,OFFSET DOSGROUP:AUXSTACK ; Enough stack for interrupts
	CALL	OutMes
	JMP	ctrlc_abort		; Use Ctrl-C abort on divide overflow
EndProc DIVOV

;
; OutMes: perform message output
; Inputs:   SS:SI points to message
;	    BX has message length
; Outputs:  message to BCON
;
procedure   OutMes,NEAR

	Context ES			; get ES addressability
	Context DS			; get DS addressability

	MOV	BYTE PTR [DskStCom],DevWrt
	MOV	BYTE PTR [DskStCall],DRdWrHL
	MOV	[DskSTST],0
	MOV	[DskStCnt],BX
	MOV	BX,OFFSET DOSGROUP:DskStCall
	MOV	WORD PTR [DskChRet+1],SI    ; transfer address (need an EQU)
	LDS	SI,[BCON]
ASSUME	DS:NOTHING
	invoke	DEVIOCALL2
	MOV	WORD PTR [DskChRet+1],OFFSET DOSGROUP:DevIOBuf
	MOV	[DskStCnt],1
	return
EndProc OutMes

Break	<CHARHRD,HARDERR,ERROR -- HANDLE DISK ERRORS AND RETURN TO USER>

	procedure   CHARHARD,NEAR
ASSUME	DS:NOTHING,ES:NOTHING,SS:DOSGROUP

; Character device error handler
; Same function as HARDERR

	OR	AH,allowed_FAIL + allowed_IGNORE + allowed_RETRY
	MOV	Allowed,AH
	MOV	WORD PTR [EXITHOLD+2],ES
	MOV	WORD PTR [EXITHOLD],BP
	PUSH	SI
	AND	DI,STECODE
	MOV	BP,DS			; Device pointer is BP:SI
	CALL	FATALC
	POP	SI
	return
EndProc CHARHARD

; Hard disk error handler. Entry conditions:
;	DS:BX = Original disk transfer address
;	DX = Original logical sector number
;	CX = Number of sectors to go (first one gave the error)
;	AX = Hardware error code
;	DI = Original sector transfer count
;	ES:BP = Base of drive parameters
;	[READOP] = 0 for read, 1 for write
;	[ALLOWED] Set with allowed responses to this error (other bits MUST BE 0)
; Output:
;	[FAILERR] will be set if user responded FAIL

	procedure   HardErr,NEAR
	ASSUME	DS:NOTHING,ES:NOTHING

	XCHG	AX,DI			; Error code in DI, count in AX
	AND	DI,STECODE		; And off status bits
	CMP	DI,error_I24_write_protect ; Write Protect Error?
	JNZ	NOSETWRPERR
	PUSH	AX
	MOV	AL,ES:[BP.dpb_drive]
	MOV	BYTE PTR [WPERR],AL	; Flag drive with WP error
	POP	AX
NOSETWRPERR:
	SUB	AX,CX			; Number of sectors successfully transferred
	ADD	DX,AX			; First sector number to retry
	PUSH	DX
	MUL	ES:[BP.dpb_sector_size] ; Number of bytes transferred
	POP	DX
	ADD	BX,AX			; First address for retry
	XOR	AH,AH			; Flag disk section in error
	CMP	DX,ES:[BP.dpb_first_FAT]    ; In reserved area?
	JB	ERRINT
	INC	AH			; Flag for FAT
	CMP	DX,ES:[BP.dpb_dir_sector]   ; In FAT?
	JAE	TESTDIR 		; No
	MOV	ES:[BP.dpb_free_cnt],-1 ; Err in FAT must force recomp of freespace
	JMP	SHORT ERRINT

TESTDIR:
	INC	AH
	CMP	DX,ES:[BP.dpb_first_sector] ; In directory?
	JB	ERRINT
	INC	AH			; Must be in data area
ERRINT:
	SHL	AH,1			; Make room for read/write bit
	OR	AH,BYTE PTR [READOP]	; Set bit 0
; If we have a write protect error when writing on a critical area on disk,
; do not allow a retry as this may write out garbage on any subsequent disk.
	;test	ah,1
	;jz	Not_Crit
	;cmp	ah,5
	;ja	Not_Crit
	;and	[ALLOWED],NOT Allowed_RETRY
Not_Crit:
	OR	AH,[ALLOWED]		; Set the allowed_ bits
	entry	FATAL
	MOV	AL,ES:[BP.dpb_drive]	; Get drive number
	entry	FATAL1
	MOV	WORD PTR [EXITHOLD+2],ES
	MOV	WORD PTR [EXITHOLD],BP	; The only things we preserve
	LES	SI,ES:[BP.dpb_driver_addr]
	MOV	BP,ES			; BP:SI points to the device involved
;
; DI has the INT-24-style extended error.  We now map the error code for this
; into the normalized get extended error set by using the ErrMap24 table as an
; translate table.  Note that we translate ONLY the device returned codes and
; leave all others beyond the look up table alone.
;
FATALC:
	call	SET_I24_EXTENDED_ERROR
	CMP	DI,error_I24_gen_failure
	JBE	GOT_RIGHT_CODE		; Error codes above gen_failure get
	MOV	DI,error_I24_gen_failure ; mapped to gen_failure. Real codes
					;  Only come via GetExtendedError

	entry	NET_I24_ENTRY
; Entry point used by REDIRector on Network I 24 errors.
;
;	ASSUME	DS:NOTHING,ES:NOTHING,SS:DOSGROUP
;
; ALL I 24 regs set up. ALL Extended error info SET. ALLOWED Set.
;     EXITHOLD set for restore of ES:BP.

GOT_RIGHT_CODE:
	CMP	BYTE PTR [ERRORMODE],0	; No INT 24s if already INT 24
	JZ	NoSetFail
	MOV	AL,3
	JMP	FailRet
NoSetFail:
IF	BUFFERFLAG
	invoke	RESTORE_USER_MAP		;AN000;LB. restore user's EMS map
ENDIF
	MOV	[CONTSTK],SP
	Context ES
	fmt TypINT24,LevLog,<"INT 24: AX = $x DI = $x\n">,<AX,DI>
;
; Wango!!!  We may need to free some user state info...  In particular, we
; may have locked down a JFN for a user and he may NEVER return to us.	Thus,
; we need to free it here and then reallocate it when we come back.
;
	CMP	SFN,-1
	JZ	NoFree
	SaveReg <DS,SI>
	LDS	SI,pJFN
	MOV	BYTE PTR [SI],0FFH
	RestoreReg  <SI,DS>
NoFree:
	CLI				; Prepare to play with stack
	INC	BYTE PTR [ERRORMODE]	; Flag INT 24 in progress
	DEC	BYTE PTR [INDOS]	; INT 24 handler might not return
;; Extneded Open hooks
	TEST	[DOS34_FLAG],Force_I24_Fail   ;AN000;IFS. form IFS Call Back	      ;AN000;
	JNZ	faili24 		      ;AN000;IFS.			      ;AN000;
	TEST	[EXTOPEN_ON],EXT_OPEN_I24_OFF ;AN000;IFS.I24 error disabled	      ;AN000;
	JZ	i24yes			      ;AN000;IFS.no			      ;AN000;
faili24:				      ;AN000;
	MOV	AL,3			      ;AN000;IFS.fake fail		      ;AN000;
	JMP	passi24 		      ;AN000;IFS.exit			      ;AN000;
i24yes: 				      ;AN000;

;; Extended Open hooks
	MOV	SS,[user_SS]
ASSUME	SS:NOTHING
	MOV	SP,ES:[user_SP] 	; User stack pointer restored
	INT	int_fatal_abort 	; Fatal error interrupt vector, must preserve ES
	MOV	ES:[user_SP],SP 	; restore our stack
	MOV	ES:[user_SS],SS
	MOV	BP,ES
	MOV	SS,BP
ASSUME	SS:DOSGROUP
passi24:				;AN000;
	MOV	SP,[CONTSTK]
	INC	BYTE PTR [INDOS]	; Back in the DOS
	MOV	BYTE PTR [ERRORMODE],0	; Back from INT 24
	STI
;;	MOV	[ACT_PAGE],-1		;LB. invalidate DOS active page 	;AN000;
;;	invoke	SAVE_MAP		;LB. save user's EMS map                ;AN000;
	fmt TypINT24,LevLog,<"INT 24: User reply = $x\n">,<AX>
FAILRET:
	LES	BP,[EXITHOLD]
ASSUME	ES:NOTHING
;
; Triage the user's reply.
;
	CMP	AL,1
	JB	CheckIgnore		; 0 => ignore
	JZ	CheckRetry		; 1 => retry
	CMP	AL,3			; 3 => fail
	JNZ	DoAbort 		; 2, invalid => abort
;
; The reply was fail.  See if we are allowed to fail.
;
	TEST	[ALLOWED],allowed_FAIL	; Can we?
	JZ	DoAbort 		; No, do abort
DoFail:
	MOV	AL,3			; just in case...
	TEST	[EXTOPEN_ON],EXT_OPEN_I24_OFF ;AN000;EO. I24 error disabled
	JNZ	cleanup 		      ;AN000;EO. no
	INC	[FAILERR]		; Tell everybody
CleanUp:
	MOV	WpErr,-1
	CMP	SFN,-1
	retz
	SaveReg <DS,SI,AX>
	MOV	AX,SFN
	LDS	SI,pJFN
	MOV	[SI],AL
	RestoreReg  <AX,SI,DS>
	return
;
; The reply was IGNORE.  See if we are allowed to ignore.
;
CheckIgnore:
	TEST	[ALLOWED],allowed_IGNORE ; Can we?
	JZ	DoFail			; No, do fail
	JMP	CleanUp
;
; The reply was RETRY.	See if we are allowed to retry.
;
CheckRetry:
	TEST	[ALLOWED],allowed_RETRY ; Can we?
	JZ	DoFail			; No, do fail
	JMP	CleanUp
;
; The reply was ABORT.
;
DoAbort:
	Context DS
	CMP	BYTE PTR [CONSWAP],0
	JZ	NOSWAP2
	invoke	SWAPBACK
NOSWAP2:
;
; See if we are to truly abort.  If we are in the process of aborting, turn
; this abort into a fail.
;
	TEST	fAborting,-1
	JNZ	DoFail
;
; Set return code
;
	MOV	BYTE PTR [exit_Type],Exit_hard_error
	XOR	AL,AL
;
; we are truly aborting the process.  Go restore information from the PDB as
; necessary.
;
	Transfer    exit_inner
;
; reset_environment checks the DS value against the CurrentPDB.  If they are
; different, then an old-style return is performed.  If they are the same,
; then we release jfns and restore to parent.  We still use the PDB at DS:0 as
; the source of the terminate addresses.
;
; Some subtlety:  We are about to issue a bunch of calls that *may* generate
; INT 24s.  We *cannot* allow the user to restart the abort process; we may
; end up aborting the wrong process or turn a terminate/stay/resident into a
; normal abort and leave interrupt handlers around.  What we do is to set a
; flag that will indicate that if any abort code is seen, we just continue the
; operation.  In essence, we dis-allow the abort response.
;
; output:   none.
;
	entry	reset_environment
	ASSUME	DS:NOTHING,ES:NOTHING

	invoke	Reset_Version		;AN007;MS. reset version number
	PUSH	DS			; save PDB of process

;
; There are no critical sections in force.  Although we may enter here with
; critical sections locked down, they are no longer relevant.  We may safely
; free all allocated resources.
;
	MOV	AH,82h
	INT	int_IBM

	MOV	fAborting,-1		; signal abort in progress

	CallInstall NetResetEnvironment, multNet, 34  ;DOS 4.00 doesn't need it
					; Allow REDIR to clear some stuff
					;   On process exit.
	MOV	AL,int_Terminate
	invoke	$Get_interrupt_vector	; and who to go to

	POP	CX			; get ThisPDB
	SaveReg <ES,BX> 		; save return address

	MOV	BX,[CurrentPDB] 	; get currentPDB
	MOV	DS,BX
	MOV	AX,DS:[PDB_Parent_PID]	; get parentPDB

;
; AX = parentPDB, BX = CurrentPDB, CX = ThisPDB
; Only free handles if AX <> BX and BX = CX and [exit_code].upper is not
; Exit_keep_process
;
	CMP	AX,BX
	JZ	reset_return		; parentPDB = CurrentPDB
	CMP	BX,CX
	JNZ	reset_return		; CurrentPDB <> ThisPDB
	PUSH	AX			; save parent
	CMP	BYTE PTR [exit_type],Exit_keep_process
	JZ	reset_to_parent 	; keeping this process
;
; We are truly removing a process.  Free all allocation blocks belonging to
; this PDB
;
	invoke	arena_free_process
;
; Kill off remainder of this process.  Close file handles and signal to
; relevant network folks that this process is dead.  Remember that CurrentPDB
; is STILL the current process!
;
	invoke	DOS_ABORT

reset_to_parent:
	POP	[CurrentPDB]		; set up process as parent

reset_return:				; come here for normal return
	PUSH	CS
	POP	DS
	ASSUME	DS:DOSGROUP
	MOV	AL,-1
;
; make sure that everything is clean In this case ignore any errors, we cannot
; "FAIL" the abort, the program being aborted is dead.
;
	EnterCrit   critDisk
	invoke	FLUSHBUF
	LeaveCrit   critDisk
;
; Decrement open ref. count if we had done a virtual open earlier.
;
	invoke	CHECK_VIRT_OPEN
IF	BUFFERFLAG
	invoke	RESTORE_USER_MAP		;AN000;LB. restore user's EMS map
ENDIF
	CLI
	MOV	BYTE PTR [INDOS],0	; Go to known state
	MOV	BYTE PTR [WPERR],-1	; Forget about WP error
	MOV	fAborting,0		; let aborts occur
	POP	WORD PTR ExitHold
	POP	WORD PTR ExitHold+2
;
; Snake into multitasking... Get stack from CurrentPDB person
;
	MOV	DS,[CurrentPDB]
	ASSUME	DS:NOTHING
	MOV	SS,WORD PTR DS:[PDB_user_stack+2]
	MOV	SP,WORD PTR DS:[PDB_user_stack]

	ASSUME	SS:NOTHING
	invoke	restore_world
	ASSUME	ES:NOTHING
	MOV	User_SP,AX
	POP	AX			; suck off CS:IP of interrupt...
	POP	AX
	POP	AX
	MOV	AX,0F202h		; STI
	PUSH	AX
	PUSH	WORD PTR [EXITHOLD+2]
	PUSH	WORD PTR [EXITHOLD]
	MOV	AX,User_SP
	IRET				; Long return back to user terminate address
EndProc HardErr

;
; This routine handles extended error codes.
; Input : DI = error code from device
; Output: All EXTERR fields are set
;
Procedure SET_I24_EXTENDED_ERROR,NEAR
	PUSH	AX
	MOV	AX,OFFSET DOSGroup:ErrMap24End
	SUB	AX,OFFSET DOSGroup:ErrMap24
;
; AX is the index of the first unavailable error.  Do not translate if
; greater or equal to AX.
;
	CMP	DI,AX
	MOV	AX,DI
	JAE	NoTrans
	MOV	AL,ErrMap24[DI]
	XOR	AH,AH
NoTrans:
	MOV	[EXTERR],AX
	POP	AX
;
; Now Extended error is set correctly.	Translate it to get correct error
; locus class and recommended action.
;
	PUSH	SI
	MOV	SI,OFFSET DOSGROUP:ERR_TABLE_24
	invoke	CAL_LK			; Set other extended error fields
	POP	SI
	ret
EndProc SET_I24_EXTENDED_ERROR

CODE	ENDS
    END