Back to home page

DOS ain't dead

Forum index page

Log in | Register

Back to the forum
Board view  Mix view

EDR-DOS bugs on int 21h functions 7142h and 71A6h (Announce)

posted by ecm Homepage E-mail, Düsseldorf, Germany, 12.08.2023, 21:13

> Is what I changed enough? Should I add anything else?

The problem is the calls to redir_dhndl_offer, on line 128 (of the 2011-07-21 WIP release) / label f7142_handle_ok as well as on line 335 / label f71a6_handle_ok.

Those branch into file redir.a86 line 125:

redir_dhndl_offer:
;================
; The FDOS has called this hook to see if we are operating on an MSNET drive.
; We return if we are not, or stay and process function here if we are
        test    es:byte ptr DHNDL_WATTR+1[bx],DHAT_REMOTE/100h
         jnz    redir_dhndl_accept
        ret
redir_dhndl_accept:


This eventually branches to line 263 / label redir_accept:

redir_accept:
;============
; We have decided to accept an FDOS function.
; Note by this time the functions have been validated as legal
        mov     file_attrib,16h         ; default search attribs to all
        pop     si                      ; discard the near return address
        mov     si,2[bp]                ; SI -> parameter block
        mov     si,ds:[si]              ; fdos code number
        add     si,si                   ; make it a word offset
        jmp     cs:redir_tbl-(39h*WORD)[si]     ; call the relevant function


It appears that the "fdos code number" is uninitialised (0). Perhaps the pointer expected in word [bp + 2] is uninitialised, too, it also reads as zero here when entered from the 7142h code.

This causes the table dispatch to jump to line 1537 of file funcs.fdo, below label fdos_select. For me, this happens to load a zero into AX and to then branch to fdos_select30, which is a retn instruction. This returns to pcmif.a86 line 292, after the label int21_e60. As AL is zero, this sets the application's AL to zero too.


The proper initialisation of the parameter block and FDOS code number appears to happen in fdos_entry, line 41 in file funcs.fdo. For example, disk.a86 line 676 label func40 calls the fdos_handle function, at line 723 in the same file, which chains to fdos_crit line 121 in file support.a86, which calls fdos_nocrit line 177 same file, which finally calls fdos_entry. Finally, the function 40h dispatches to file funcs.fdo function fdos_write (line 829), which calls vfy_dhndl_ptr and then redir_dhndl_offer.

The FD_FUNC field of fdos_data is populated by function set_retry, then fdos_nocrit passes the offset of fdos_data to fdos_entry which finally uses this code to read the parameter block and store some of it on the stack:

;==========
fdos_entry:                     ; FDOS module entry point
;==========
;       On Entry:
;               DS:DX -> parameter block
;       On exit:
;               AX = BX = return code
;               (DS/ES corrupted)
;       entry:  DS:DX = argument
;
;       exit:   AX,BX = return code

        mov     si,dx
        lodsw                           ; AX = FDOS number
        sub     ax,39h                  ; base it at zero
         jc     fd_error                ; stop if too low
        cmp     ax,FDOS_MAX             ; check if function in range
         jae    fd_error                ; yes, continue

        push    ds                      ; save parameter segment
        push    dx                      ; save parameter offset
        push    ax                      ; save sub-function
        mov     bp,sp                   ; SS:BP -> working variables
        mov     bx,ax
        add     bx,ax
        add     bx,ax
        call    fdos_tbl[bx]


The redir_dhndl_offer function reads word [bp + 2] which is the DX pushed by fdos_entry.

All this to say that redir_dhndl_offer should not be called from lfn.asm at any point, because it does not set up the FDOS stack frame and data structures. Both calls of this should go away.

However, you do not need most of the code that you copied from seekext. The call to vfy_dhndl_ptr_AX_call already sets up ES:BX -> the SFT entry. You can copy this line from the redir_dhndl_offer function to check for redirector SFTs:

         test    es:byte ptr DHNDL_WATTR+1[bx],DHAT_REMOTE/100h

Then branch to a part that sets DI to the passed BX value, and call the int 2Fh functions 11C2h and 1142h as you do already. I'm not quite sure how to pass errors back to the interrupt 21h dispatcher but you seem to have the correct code already in your attempt:

_iret_CF:
         jc     f71_error
        jmp     return_AX_CLC


(Just the label name is not accurate here, because this is not an IRET handler as such.)

The use of redir_dhndl_offer in f71a6_handle_ok is equally wrong. dosemu2 also has an extension function for this, at int 2Fh function 11A6h.

Additionally, the two checks for DHAT_DEV also seem wrong. They appear to return to the interrupt 21h dispatcher without properly setting up error codes, and neither do they fill in either of the passed buffers. (For comparison, in file funcs.fdo the label lseek_dev at line 1051 makes sure to return a new seek position of 0000_0000h for device handles, so presumably function 7142h should also zero the output buffer when called on a device.)

---
l

 

Complete thread:

Back to the forum
Board view  Mix view
22049 Postings in 2034 Threads, 396 registered users, 275 users online (0 registered, 275 guests)
DOS ain't dead | Admin contact
RSS Feed
powered by my little forum