From 330d420b0204c6f1542b5a526a64e4fe9eb29ed7 Mon Sep 17 00:00:00 2001 From: "E. C. Masloch" Date: Fri, 22 Aug 2025 16:13:33 +0200 Subject: [PATCH 1/5] entry.asm: fix Critical Error caller 386 registers Fixes #210, fixes #212 --- hdr/stacks.inc | 10 ++++++++-- kernel/entry.asm | 19 ++++++++++++++++++- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/hdr/stacks.inc b/hdr/stacks.inc index f8be91e2..f4fcabbc 100644 --- a/hdr/stacks.inc +++ b/hdr/stacks.inc @@ -135,6 +135,8 @@ irp_hi equ 26 ; error 1 2 3 %macro Protect386Registers 0 %endmacro + + %assign Size386Registers 0 %macro RestoreSP 0 mov sp, bp @@ -151,8 +153,10 @@ irp_hi equ 26 push gs %endmacro + %assign Size386Registers 4 + %macro RestoreSP 0 - lea sp, [bp-4] + lea sp, [bp - Size386Registers] %endmacro %macro Restore386Registers 0 @@ -176,8 +180,10 @@ irp_hi equ 26 pop dx %endmacro + %assign Size386Registers 6 + %macro RestoreSP 0 - lea sp, [bp-6] + lea sp, [bp - Size386Registers] %endmacro %macro Restore386Registers 0 diff --git a/kernel/entry.asm b/kernel/entry.asm index 47316d62..aec68174 100644 --- a/kernel/entry.asm +++ b/kernel/entry.asm @@ -611,6 +611,8 @@ CritErr05: mov bp,sp push si push di + Protect386Registers + ; ; Get parameters ; @@ -659,6 +661,13 @@ CritErr05: ; cld cli + Protect386Registers + ; ecm: The extended stack frame must be restored here + ; in case the response isn't Abort. The int 21h handler + ; will expect the extended stack frame to be still + ; intact, but the stack written by the int 24h (even + ; only the int instruction) will have overwritten it. + mov bp, [cs:_DGROUP_] mov ds,bp mov ss,bp @@ -672,7 +681,13 @@ CritErr05: pop word [es:PSP_USERSP] pop word [es:PSP_USERSS] mov bp, sp - mov ah, byte [bp+4+4] ; restore old AH from nFlags + mov ah, byte [bp + 4 + 4 + Size386Registers] + ; restore old AH from nFlags + ; ecm: One 4 is the displacement of nFlags from the + ; usual bp, the other 4 accounts for the si and di + ; on the stack, the Size386Registers is added to + ; skip the fs and gs (OpenWatcom 386 build) or high + ; words that are a part of the stack frame, if any. sti ; Enable interrupts ; ; clear flags @@ -715,6 +730,8 @@ CritErr30: CritErrExit: xor ah,ah ; clear out top for return + + Restore386Registers pop di pop si pop bp From 49432dfc79303323223aa7c52be3989a296af757 Mon Sep 17 00:00:00 2001 From: "E. C. Masloch" Date: Fri, 22 Aug 2025 16:25:35 +0200 Subject: [PATCH 2/5] entry.asm: fix int 24h stack changes to ensure interrupt lockout (#213) --- kernel/entry.asm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/entry.asm b/kernel/entry.asm index aec68174..1785d694 100644 --- a/kernel/entry.asm +++ b/kernel/entry.asm @@ -646,8 +646,8 @@ CritErr05: ; ; switch to user's stack ; - mov ss,[es:PSP_USERSS] mov bp,[es:PSP_USERSP] + mov ss,[es:PSP_USERSS] RestoreSP Restore386Registers mov bp,cx @@ -747,9 +747,9 @@ CritErrAbort: mov al,FAIL jz CritErrExit cli - mov bp,word [_user_r+2] ;Get frame - mov ss,bp + mov ax,word [_user_r+2] ;Get frame mov bp,word [_user_r] + mov ss,ax mov sp,bp mov byte [_ErrorMode],1 ; flag abort mov ax,4C00h From 4fea8ad549358e453c4677f955121ff3b830df96 Mon Sep 17 00:00:00 2001 From: "E. C. Masloch" Date: Fri, 22 Aug 2025 16:31:46 +0200 Subject: [PATCH 3/5] entry.asm: allow critical error Abort on self-parented process Fixes #213 --- kernel/entry.asm | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/kernel/entry.asm b/kernel/entry.asm index 1785d694..b77f3145 100644 --- a/kernel/entry.asm +++ b/kernel/entry.asm @@ -741,11 +741,16 @@ CritErrExit: ; Abort processing. ; CritErrAbort: +%if 0 mov ax,[_cu_psp] mov es,ax cmp ax,[es:PSP_PARENT] mov al,FAIL jz CritErrExit + ; ecm: This check is done by (E)DR-DOS, but not MS-DOS. + ; Therefore, disable it and terminate the self-parented + ; process here like any other. +%endif cli mov ax,word [_user_r+2] ;Get frame mov bp,word [_user_r] From 4d3094369de50ecc1d91fffbd2d8033835ed2636 Mon Sep 17 00:00:00 2001 From: "E. C. Masloch" Date: Fri, 22 Aug 2025 17:43:07 +0200 Subject: [PATCH 4/5] rename byte [SDA + 25Ch] from _tsr to _term_type, fix int 24h rc This fixes int 24h abort to set the return code to 200h. The ErrorMode misuse is apparently necessary, but was not sufficient to set the return code. --- kernel/entry.asm | 9 ++++++--- kernel/globals.h | 2 +- kernel/inthndlr.c | 17 +++++------------ kernel/kernel.asm | 8 ++++++-- kernel/procsupt.asm | 7 +++++++ kernel/task.c | 2 +- 6 files changed, 26 insertions(+), 19 deletions(-) diff --git a/kernel/entry.asm b/kernel/entry.asm index b77f3145..d0950bfd 100644 --- a/kernel/entry.asm +++ b/kernel/entry.asm @@ -41,6 +41,7 @@ segment HMA_TEXT extern _user_r extern _ErrorMode extern _InDOS + extern _term_type %IFDEF WIN31SUPPORT extern _winInstanced %ENDIF ; WIN31SUPPORT @@ -264,11 +265,11 @@ reloc_call_int21_handler: ; NB: At this point, SS != DS and won't be set that way ; until later when which stack to run on is determined. ; -int21_reentry: - Protect386Registers mov dx,[cs:_DGROUP_] mov ds,dx - + mov byte [_term_type], 0 ; reset termination type +int21_reentry: ; entered here from int 24h abort, ds = dx => DGROUP + Protect386Registers cmp ah,33h je int21_user cmp ah,50h @@ -760,4 +761,6 @@ CritErrAbort: mov ax,4C00h mov [bp+reg_ax],ax sti + mov byte [_term_type], 2 ; set int 24h abort error + mov dx, ds jmp int21_reentry ; restart the system call diff --git a/kernel/globals.h b/kernel/globals.h index ac21eca9..d2ee463c 100644 --- a/kernel/globals.h +++ b/kernel/globals.h @@ -307,7 +307,7 @@ extern BYTE ASM internal_data[], /* sda areas */ ASM swap_always[], /* " " */ ASM swap_indos[], /* " " */ - ASM tsr, /* true if program is TSR */ + ASM term_type, /* 0 normal, 1 ^C, 2 int 24h, 3 TSR */ ASM break_flg, /* true if break was detected */ ASM break_ena; /* break enabled flag */ extern void FAR * ASM dta; /* Disk transfer area (kludge) */ diff --git a/kernel/inthndlr.c b/kernel/inthndlr.c index 40209fea..46422c82 100644 --- a/kernel/inthndlr.c +++ b/kernel/inthndlr.c @@ -811,7 +811,7 @@ VOID ASMCFUNC int21_service(iregs FAR * r) case 0x31: DosMemChange(cu_psp, lr.DX < 6 ? 6 : lr.DX, 0); return_code = lr.AL | 0x300; - tsr = TRUE; + term_type = 3; /* ecm: TSR terminate */ return_user(); break; @@ -1104,18 +1104,11 @@ VOID ASMCFUNC int21_service(iregs FAR * r) /* End Program */ case 0x4c: - tsr = FALSE; - rc = 0; - if (ErrorMode) - { - ErrorMode = FALSE; - rc = 0x200; - } - else if (break_flg) - { + if (break_flg) { break_flg = FALSE; - rc = 0x100; + term_type = 1; } + rc = term_type << 8; return_code = lr.AL | rc; if (DosMemCheck() != SUCCESS) panic("MCB chain corrupted"); @@ -1784,7 +1777,7 @@ VOID INRPT FAR int23_handler(int es, int ds, int di, int si, int bp, int sp, int bx, int dx, int cx, int ax, int ip, int cs, int flags) { - tsr = FALSE; + term_type = 1; return_mode = 1; return_code = -1; mod_sto(CTL_C); diff --git a/kernel/kernel.asm b/kernel/kernel.asm index dd891654..40e92583 100644 --- a/kernel/kernel.asm +++ b/kernel/kernel.asm @@ -838,8 +838,12 @@ _Server_Call db 0 ;252 - Server call Func 5D sub 0 ; Pad to 05CCh times (25ch - ($ - _internal_data)) db 0 - global _tsr ; used by break and critical error -_tsr db 0 ;25C - handlers during termination + global _term_type ; used by break and critical error +_term_type db 0 ;25C - handlers during termination + ; ecm: 00h = normal terminate, + ; 01h = control-c terminate, + ; 02h = critical error abort, + ; 03h = TSR terminate db 0 ;25D - padding global term_psp term_psp dw 0 ;25E - 0?? diff --git a/kernel/procsupt.asm b/kernel/procsupt.asm index 623caf6a..c382ae6e 100644 --- a/kernel/procsupt.asm +++ b/kernel/procsupt.asm @@ -34,6 +34,7 @@ extern _user_r extern _break_flg ; break detected flag + extern _term_type extern _int21_handler ; far call system services %include "stacks.inc" @@ -257,6 +258,12 @@ _spawn_int23: push ds ;; we need DGROUP mov ds, [cs:_DGROUP_] inc byte [_break_flg] + mov byte [_term_type], 1 + ; ecm: This is overwritten in the int 21h handler, + ; but is passed from the int 23h caller to the + ; terminate code in MS-DOS by writing this. + ; For us, break_flg is used in function 4Ch to + ; re-set term_type to 1 later. pop ds xor ah, ah ;; clear ah --> perform DOS-00 --> terminate diff --git a/kernel/task.c b/kernel/task.c index 8ddb6e31..6311b3a6 100644 --- a/kernel/task.c +++ b/kernel/task.c @@ -593,7 +593,7 @@ VOID return_user(void) /* might be a good idea to do that after closing but doesn't help NET either TE */ - if (!tsr && p->ps_parent != cu_psp) + if (term_type != 3 && p->ps_parent != cu_psp) { network_redirector(REM_CLOSEALL); for (i = 0; i < p->ps_maxfiles; i++) From 811708f7a3548e5189f6af86669c308d7dc8663f Mon Sep 17 00:00:00 2001 From: "E. C. Masloch" Date: Fri, 22 Aug 2025 17:57:01 +0200 Subject: [PATCH 5/5] set byte [SDA + 39h] during process termination, turn abort to fail This is compatible to lMS-DOS which sets the flag before running int 2Fh function 1122h [1] and clears it after closing handles and freeing memory [2], before branching to the Parent Return Address. The flag turns any int 24h abort response into a fail instead, to avoid iterating infinitely during file handle closing. [1]: https://hg.pushbx.org/ecm/msdos4/file/c057c6a1c9ad/src/DOS/ctrlc.nas#l752 [2]: https://hg.pushbx.org/ecm/msdos4/file/c057c6a1c9ad/src/DOS/ctrlc.nas#l829 --- kernel/entry.asm | 4 ++++ kernel/globals.h | 1 + kernel/kernel.asm | 1 + kernel/task.c | 4 ++++ 4 files changed, 10 insertions(+) diff --git a/kernel/entry.asm b/kernel/entry.asm index d0950bfd..ebceaad9 100644 --- a/kernel/entry.asm +++ b/kernel/entry.asm @@ -42,6 +42,7 @@ segment HMA_TEXT extern _ErrorMode extern _InDOS extern _term_type + extern _abort_progress %IFDEF WIN31SUPPORT extern _winInstanced %ENDIF ; WIN31SUPPORT @@ -742,6 +743,9 @@ CritErrExit: ; Abort processing. ; CritErrAbort: + test byte [_abort_progress], -1 + mov al, FAIL + jnz CritErrExit %if 0 mov ax,[_cu_psp] mov es,ax diff --git a/kernel/globals.h b/kernel/globals.h index d2ee463c..14d0b5c7 100644 --- a/kernel/globals.h +++ b/kernel/globals.h @@ -308,6 +308,7 @@ extern BYTE ASM swap_always[], /* " " */ ASM swap_indos[], /* " " */ ASM term_type, /* 0 normal, 1 ^C, 2 int 24h, 3 TSR */ + ASM abort_progress, /* set during process termination */ ASM break_flg, /* true if break was detected */ ASM break_ena; /* break enabled flag */ extern void FAR * ASM dta; /* Disk transfer area (kludge) */ diff --git a/kernel/kernel.asm b/kernel/kernel.asm index 40e92583..1590b5c5 100644 --- a/kernel/kernel.asm +++ b/kernel/kernel.asm @@ -796,6 +796,7 @@ _DayOfWeek db 2 ; 36 - day of week _console_swap db 0 ; 37 console swapped during read from dev global _dosidle_flag _dosidle_flag db 1 ; 38 - safe to call int28 if nonzero + global _abort_progress _abort_progress db 0 ; 39 - abort in progress global _CharReqHdr _CharReqHdr: diff --git a/kernel/task.c b/kernel/task.c index 6311b3a6..1f31b926 100644 --- a/kernel/task.c +++ b/kernel/task.c @@ -588,6 +588,8 @@ VOID return_user(void) setvec(0x23, p->ps_isv23); setvec(0x24, p->ps_isv24); + abort_progress = -1; + /* And free all process memory if not a TSR return */ network_redirector(REM_PROCESS_END); /* might be a good idea to do that after closing @@ -607,6 +609,8 @@ VOID return_user(void) cu_psp = p->ps_parent; q = MK_FP(cu_psp, 0); + abort_progress = 0; + irp = (iregs FAR *) q->ps_stack; irp->CS = FP_SEG(p->ps_isv22);