2025-04-27 07:49:33 -04:00

1826 lines
55 KiB
NASM
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

page ,132
; SCCSID = @(#)tcode.asm 1.1 85/05/14
; SCCSID = @(#)tcode.asm 1.1 85/05/14
TITLE Part1 COMMAND Transient Routines
;/*
; * Microsoft Confidential
; * Copyright (C) Microsoft Corporation 1991
; * All Rights Reserved.
; */
;
; Revision History
; ================
;
; M025 SR 9/12/90 Removed calls to SetStdInOn,SetStdInOff
; SetStdOutOn & SetStdOutOff.
;
.xlist
.xcref
include comsw.asm
include dossym.inc
include syscall.inc
include comseg.asm
include comequ.asm
include cmdsvc.inc
include mult.inc
ifdef NEC_98
include pdb.inc
endif ;NEC_98
include vint.inc
.list
.cref
Prompt32 equ 1
Start16 equ 0
Return16 equ 1
DOSONLY_YES equ 1
FOR_TSR equ 0
FOR_SHELLOUT equ 1
CODERES SEGMENT PUBLIC BYTE ;AC000;
EXTRN EXEC_WAIT:NEAR
CODERES ENDS
DATARES SEGMENT PUBLIC BYTE ;AC000;
EXTRN BATCH:WORD
EXTRN CALL_BATCH_FLAG:byte
EXTRN CALL_FLAG:BYTE
EXTRN ECHOFLAG:BYTE
EXTRN envirseg:word
EXTRN EXTCOM:BYTE
EXTRN FORFLAG:BYTE
EXTRN IFFLAG:BYTE
EXTRN next_batch:word
EXTRN nullflag:byte
EXTRN PIPEFILES:BYTE
EXTRN PIPEFLAG:BYTE
EXTRN RE_OUT_APP:BYTE
EXTRN RE_OUTSTR:BYTE
EXTRN RESTDIR:BYTE
EXTRN SINGLECOM:WORD
EXTRN KSWITCHFLAG:BYTE
EXTRN VERVAL:WORD
EXTRN SCS_Is_First:BYTE
EXTRN SCS_PAUSE:BYTE
EXTRN SCS_REENTERED:BYTE
EXTRN SCS_FIRSTCOM:BYTE
EXTRN SCS_CMDPROMPT:BYTE
EXTRN SCS_DOSONLY:BYTE
EXTRN SCS_PROMPT16:BYTE
EXTRN SCS_FIRSTTSR:BYTE
EXTRN RES_RDRINFO:DWORD
EXTRN RES_BATSTATUS:BYTE
EXTRN crit_msg_off:word ;AC000;
EXTRN crit_msg_seg:word ;AC000;
EXTRN OldTerm:DWORD
EXTRN PARENT:WORD
extrn RetCode:word
extrn Io_Save:word
extrn Io_Stderr:byte
extrn RES_TPA:WORD ; YST
extrn LTPA:WORD ; YST
DATARES ENDS
TRANDATA SEGMENT PUBLIC BYTE ;AC000;
EXTRN BadNam_Ptr:word ;AC000;
EXTRN comspec:byte
EXTRN NT_INTRNL_CMND:byte
TRANDATA ENDS
TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
EXTRN APPEND_EXEC:BYTE ;AN041;
EXTRN ARG1S:WORD
EXTRN ARG2S:WORD
EXTRN ARGTS:WORD
EXTRN BYTCNT:WORD
EXTRN COMBUF:BYTE
EXTRN COMSW:WORD
EXTRN CURDRV:BYTE
EXTRN HEADCALL:DWORD
EXTRN IDLEN:BYTE
EXTRN INTERNATVARS:BYTE
EXTRN PARM1:BYTE
EXTRN PARM2:BYTE
EXTRN RE_INSTR:BYTE
EXTRN RESSEG:WORD
EXTRN SPECDRV:BYTE
EXTRN STACK:WORD
EXTRN SWITCHAR:BYTE
EXTRN TPA:WORD
EXTRN UCOMBUF:BYTE
EXTRN USERDIR1:BYTE
IF IBM
EXTRN ROM_CALL:BYTE
EXTRN ROM_CS:WORD
EXTRN ROM_IP:WORD
ENDIF
EXTRN ENV_PTR_SEG:WORD
EXTRN ENV_SIZE:WORD
EXTRN SCS_TSREXIT:WORD
EXTRN CMD_PTR_SEG:WORD
EXTRN CMD_PTR_OFF:WORD
EXTRN CMD_SIZE:WORD
EXTRN SCS_EXIT_CODE:WORD
EXTRN SCS_RDRINFO:DWORD
EXTRN SCS_BATSTATUS:DWORD
EXTRN SCS_NUM_DRIVES:WORD
EXTRN SCS_CUR_DRIVE:WORD
EXTRN SCS_CODEPAGE:WORD
EXTRN SCS_STD_HANDLE:WORD
EXTRN SCS_STD_BITS:BYTE
EXTRN EXECPATH_SEG:WORD
EXTRN EXECPATH_OFF:WORD
EXTRN EXECPATH_SIZE:WORD
EXTRN EXECPATH:BYTE
EXTRN TRAN_TPA:WORD
extrn transpaceend:byte ; (YST)
TRANSPACE ENDS
; (YST)
TAIL segment public para
extrn TranStart:word
TAIL ENDS
; End of (YST)
; ********************************************************************
; START OF TRANSIENT PORTION
; This code is loaded at the end of memory and may be overwritten by
; memory-intensive user programs.
TRANCODE SEGMENT PUBLIC BYTE ;AC000;
ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
EXTRN $EXIT:NEAR
EXTRN DRVBAD:NEAR
EXTRN EXTERNAL:NEAR
EXTRN FNDCOM:NEAR
EXTRN FORPROC:NEAR
EXTRN PIPEPROC:NEAR
EXTRN PIPEPROCSTRT:NEAR
EXTRN GETENVSIZ:near
PUBLIC COMMAND
PUBLIC DOCOM
PUBLIC DOCOM1
PUBLIC NOPIPEPROC
PUBLIC TCOMMAND
IF IBM
PUBLIC ROM_EXEC
PUBLIC ROM_SCAN
ENDIF
; NTVDM use diff al value so we don't confuse dos 5.0
; NTVDM command.com GET_COMMAND_STATE equ 5500h
GET_COMMAND_STATE equ 5501h
NLSFUNC_installed equ 0ffh
KEYB16_installed equ 0ffh ; (YST)
CHECK_KEYB16 equ 0AD80h ; (YST)
set_global_cp equ 2
get_global_cp equ 1
ORG 0
ZERO = $
ORG 100H ; Allow for 100H parameter area
SETDRV:
MOV AH,SET_DEFAULT_DRIVE
INT 21h
;
; TCOMMAND is the recycle point in COMMAND. Nothing is known here.
; No registers (CS:IP) no flags, nothing.
;
TCOMMAND:
MOV DS,[RESSEG]
ASSUME DS:RESGROUP
MOV AX,-1
XCHG AX,[VERVAL]
CMP AX,-1
JZ NOSETVER2
MOV AH,SET_VERIFY_ON_WRITE ; AL has correct value
INT 21h
NOSETVER2:
CALL [HEADCALL] ; Make sure header fixed
XOR BP,BP ; Flag transient not read
CMP [SINGLECOM],-1
JNZ COMMAND
$EXITPREP:
PUSH CS
POP DS
JMP $EXIT ; Have finished the single command
ASSUME DS:NOTHING
;
; Main entry point from resident portion.
;
; If BP <> 0, then we have just loaded transient portion otherwise we are
; just beginning the processing of another command.
;
COMMAND:
;
; We are not always sure of the state of the world at this time. We presume
; worst case and initialize the relevant registers: segments and stack.
;
ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
CLD
MOV AX,CS
FCLI
MOV SS,AX
ASSUME SS:TRANGROUP
MOV SP,OFFSET TRANGROUP:STACK
FSTI
MOV ES,AX
MOV DS,AX ;AN000; set DS to transient
ASSUME ES:TRANGROUP,DS:TRANGROUP ;AC000;
invoke TSYSLOADMSG ;AN000; preload messages
mov append_exec,0 ;AN041; set internal append state off
MOV DS,[RESSEG]
ASSUME DS:RESGROUP
MOV [UCOMBUF],COMBUFLEN ; Init UCOMBUF
MOV [COMBUF],COMBUFLEN ; Init COMBUF (Autoexec doing DATE)
mov [EXECPATH_SIZE], 0 ; ntvdm execpath extended
;
; If we have just loaded the transient, then we do NOT need to initialize the
; command buffer. ???? DO WE NEED TO RESTORE THE USERS DIRECTORY ???? I
; guess not: the only circumstances in which we reload the command processor
; is after a transient program execution. In this case, we let the current
; directory lie where it may.
;
OR BP,BP ; See if just read
JZ TESTRDIR ; Not read, check user directory
MOV WORD PTR [UCOMBUF+1],0D01H ; Reset buffer
JMP SHORT NOSETBUF
TESTRDIR:
CMP [RESTDIR],0
JZ NOSETBUF ; User directory OK
PUSH DS
;
; We have an unusual situation to handle. The user *may* have changed his
; directory as a result of an internal command that got aborted. Restoring it
; twice may not help us: the problem may never go away. We just attempt it
; once and give up.
;
MOV [RESTDIR],0 ; Flag users dirs OK
PUSH CS
POP DS
ASSUME DS:TRANGROUP
MOV DX,OFFSET TRANGROUP:USERDIR1
MOV AH,CHDIR
INT 21h ; Restore users directory
POP DS
ASSUME DS:RESGROUP
NOSETBUF:
CMP [PIPEFILES],0
JZ NOPCLOSE ; Don't bother if they don't exist
CMP [PIPEFLAG],0
JNZ NOPCLOSE ; Don't del if still piping
INVOKE PIPEDEL
NOPCLOSE:
MOV [EXTCOM],0 ; Flag internal command
MOV AX,CS ; Get segment we're in
MOV DS,AX
ASSUME DS:TRANGROUP
PUSH AX
MOV DX,OFFSET TRANGROUP:INTERNATVARS
MOV AX,INTERNATIONAL SHL 8
INT 21H
POP AX
SUB AX,[TPA] ; AX=size of TPA in paragraphs
PUSH BX
MOV BX,16
MUL BX ; DX:AX=size of TPA in bytes
POP BX
OR DX,DX ; See if over 64K
JZ SAVSIZ ; OK if not
MOV AX,-1 ; If so, limit to 65535 bytes
SAVSIZ:
;
; AX is the number of bytes free in the buffer between the resident and the
; transient with a maximum of 64K-1. We round this down to a multiple of 512.
;
CMP AX,512
JBE GotSize
AND AX,0FE00h ; NOT 511 = NOT 1FF
GotSize:
MOV [BYTCNT],AX ; Max no. of bytes that can be buffered
MOV DS,[RESSEG] ; All batch work must use resident seg.
ASSUME DS:RESGROUP
TEST [ECHOFLAG],1
JZ GETCOM ; Don't do the CRLF
INVOKE SINGLETEST
JB GETCOM
TEST [PIPEFLAG],-1
JNZ GETCOM
TEST [FORFLAG],-1 ; G Don't print prompt in FOR
JNZ GETCOM ; G
TEST [BATCH], -1 ; G Don't print prompt if in batch
JNZ GETCOM ; G
; INVOKE CRLF2
GETCOM:
MOV CALL_FLAG,0 ; G Reset call flags
MOV CALL_BATCH_FLAG,0 ; G
MOV AH,GET_DEFAULT_DRIVE
INT 21h
MOV [CURDRV],AL
TEST [PIPEFLAG],-1 ; Pipe has highest presedence
JZ NOPIPE
JMP PIPEPROC ; Continue the pipeline
NOPIPE:
TEST [ECHOFLAG],1
JZ NOPDRV ; No prompt if echo off
INVOKE SINGLETEST
JB NOPDRV
TEST [FORFLAG],-1 ; G Don't print prompt in FOR
JNZ NOPDRV ; G
TEST [BATCH], -1 ; G Don't print prompt if in batch
JNZ TESTFORBAT ; G
; INVOKE PRINT_PROMPT ; Prompt the user
NOPDRV:
TEST [FORFLAG],-1 ; FOR has next highest precedence
JZ TESTFORbat
JMP FORPROC ; Continue the FOR
TESTFORBAT:
MOV [RE_INSTR],0 ; Turn redirection back off
MOV [RE_OUTSTR],0
MOV [RE_OUT_APP],0
MOV IFFlag,0 ; no more ifs...
TEST [BATCH],-1 ; Batch has lowest precedence
JZ ISNOBAT
; Bugbug: MULT_SHELL_GET no longer used?
push es ;AN000; save ES
push ds ;AN000; save DS
mov ax,mult_shell_get ;AN000; check to see if SHELL has command
mov es,[batch] ;AN000; get batch segment
mov di,batfile ;AN000; get batch file name
push cs ;AN000; get local segment to DS
pop ds ;AN000;
mov dx,offset trangroup:combuf ;AN000; pass communications buffer
int 2fh ;AN000; call the shell
cmp al,shell_action ;AN000; does shell have a commmand?
pop ds ;AN000; restore DS
pop es ;AN000; restore ES
jz jdocom1 ;AN000; yes - go process command
PUSH DS ;G
INVOKE READBAT ; Continue BATCH
POP DS ;G
mov nullflag,0 ;G reset no command flag
TEST [BATCH],-1 ;G
JNZ JDOCOM1 ;G if batch still in progress continue
MOV BX,NEXT_BATCH ;G
CMP BX,0 ;G see if there is a new batch file
JZ JDOCOM1 ;G no - go do command
MOV BATCH,BX ;G get segment of next batch file
MOV NEXT_BATCH,0 ;G reset next batch
JDOCOM1:
PUSH CS ;G
POP DS ;G
JMP DoCom1 ; echoing already done
ISNOBAT:
CMP [SINGLECOM],0
JZ REGCOM
MOV SI,-1
CMP KSWITCHFLAG,0
JE NO_K_SWITCH
INC SI
MOV KSWITCHFLAG,0
NO_K_SWITCH:
XCHG SI,[SINGLECOM]
MOV DI,OFFSET TRANGROUP:COMBUF + 2
XOR CX,CX
SINGLELOOP:
LODSB
STOSB
INC CX
CMP AL,0DH
JNZ SINGLELOOP
DEC CX
PUSH CS
POP DS
ASSUME DS:TRANGROUP
MOV [COMBUF + 1],CL
;
; do NOT issue a trailing CRLF...
;
JMP DOCOM1
;
; We have a normal command.
; Printers are a bizarre quantity. Sometimes they are a stream and
; sometimes they aren't. At this point, we automatically close all spool
; files and turn on truncation mode.
;
REGCOM:
MOV AX,(ServerCall SHL 8) + 9
INT 21h
MOV AX,(ServerCall SHL 8) + 8
MOV DL,1
INT 21h
MOV DS,cs:[RESSEG]
ASSUME DS:RESGROUP
cmp byte ptr [SCS_FIRSTCOM],0
jnz first_inst ;this is the first instance
jmp DoReEnter
DRE_RET:
MOV DS,cs:[RESSEG]
ASSUME DS:RESGROUP
xor ax,ax
jmp short do_again
first_inst:
mov [SCS_PAUSE],0 ; yst 4-5-93
cmp [SCS_Is_First],1
jne cont_scs
mov [SCS_Is_First],0
SAVE <SI,BP>
xor si,si
xor bp,bp
mov al,2
mov ah,setdpb
int 21h ; resets the TSR bit
RESTORE <BP,SI>
xor ax,ax
jmp short do_again
cont_scs:
SAVE <AX,SI,BP>
xor si,si
xor bp,bp
mov al,2
mov ah,setdpb
int 21h ; resets the TSR bit
RESTORE <BP,SI,AX>
jnc cont_scs2
cont_tsr:
jmp tsr_loop
tsr_loop_ret:
jmp short cont_scs1
cont_scs2:
cmp byte ptr [scs_firsttsr],1
je cont_scs1
jmp short cont_tsr
cont_scs1:
; call free_con
MOV DS,cs:[RESSEG]
ASSUME DS:RESGROUP
mov ax,[retcode]
do_again:
ifdef NEC_98
jmp ClrFky
FKY_OFF DB 1Bh,'[>1h$' ;ESC sequence of FKY off
Clrfky: push ds
push cs
pop ds
push cx
push ax
push dx
mov cl,10H
mov ah,01H
mov dx,offset FKY_OFF
int 0DCH ;FKY off
pop dx
pop ax
pop cx
pop ds
endif ;NEC_98
MOV DS,cs:[RESSEG]
ASSUME DS:RESGROUP
push es
mov es,[envirseg]
mov [ENV_PTR_SEG],es
call GETENVSIZ
pop es
push cs
pop ds
ASSUME DS:TRANGROUP
mov [ENV_SIZE],cx
;; williamh - Jan 11 1993
;; nt expects 16bits exit code while DOS has only 8 bits
;; clear the high byte so that things won't go wrong
xor ah, ah
MOV [SCS_EXIT_CODE],ax
mov ah,19h
int 21h
xor ah,ah
mov [SCS_CUR_DRIVE], ax ; a= 0 , b = 1 etc
mov [CMD_SIZE],COMBUFLEN
MOV DX,OFFSET TRANGROUP:UCOMBUF
if 0
; Try to read interactive command line via DOSKey.
; If that fails, use DOS Buffered Keyboard Input.
mov ax,4810h ; AX = DOSKey Read Line function
int 2fh
or ax,ax
jz GotCom ; DOSKey gave us a command line
else
mov [CMD_PTR_SEG],ds
mov [CMD_PTR_OFF],dx
mov dx,OFFSET TRANGROUP:EXECPATH
mov [EXECPATH_SEG], ds
mov [EXECPATH_OFF], dx
mov [EXECPATH_SIZE], EXECPATHLEN
push es
mov es,cs:[RESSEG]
ASSUME es:RESGROUP
mov dx,word ptr es:[RES_RDRINFO]
mov word ptr ds:[SCS_RDRINFO],dx
mov dx,word ptr es:[RES_RDRINFO+2]
mov word ptr ds:[SCS_RDRINFO+2],dx
pop es
ASSUME ES:TRANGROUP
MOV DX,OFFSET TRANGROUP:ENV_PTR_SEG
CMDSVC SVC_CMDGETNEXTCMD ; DS:DX is the buffer
jnc run_cmd
; If carry is set that means our enviornment buffer was smaller. So get
; a big enough buffer and get the command again.
cmp ax,32*1024 ; Env size cannot be more than 32k.
jae op_fail
push ax ; the new size in bytes for env in bytes
invoke FREE_TPA
pop bx
MOV CL,4
SHR BX,CL ; Convert back to paragraphs
inc bx ; an extra para
push es
push ds
MOV DS,cs:[RESSEG]
ASSUME DS:RESGROUP
mov es,[envirseg]
pop ds
ASSUME DS:TRANGROUP
MOV CX,ES ;AN056; Get environment segment
ADD CX,BX ;AN056; Add in size of environment
ADD CX,020H ;AN056; Add in some TPA
MOV AX,CS ;AN056; Get the transient segment
CMP CX,AX ;AN056; Are we hitting the transient?
JNB blk_xxx ;AN056; Yes - don't do it!!!
push bx
MOV AH,SETBLOCK
INT 21h
pop bx
jnc blk_xxx
mov ah,ALLOC
int 21h
jc blk_xxx
push ax
mov ah,DEALLOC
int 21h
pop ax
push ds
MOV DS,cs:[RESSEG]
ASSUME DS:RESGROUP
mov [envirseg],ax
pop ds
ASSUME DS:TRANGROUP
clc
blk_xxx:
lahf
push ax
MOV ES,cs:[RESSEG]
invoke ALLOC_TPA
pop ax
sahf
JC op_fail1
pop es
xor ax,ax ; error code zero, its important
jmp do_again
op_fail1:
pop es
op_fail:
mov ax,error_not_enough_memory
jmp do_again
run_cmd:
push es
mov es,cs:[RESSEG]
ASSUME es:RESGROUP
mov ax,word ptr ds:[SCS_RDRINFO]
mov word ptr es:[RES_RDRINFO],ax
mov ax,word ptr ds:[SCS_RDRINFO+2]
mov word ptr es:[RES_RDRINFO+2],ax
mov ax,word ptr ds:[SCS_BATSTATUS]
mov byte ptr es:[RES_BATSTATUS],al
pop es
ASSUME ES:TRANGROUP
test [SCS_STD_HANDLE],ALL_HANDLES
jz no_rdr
test [SCS_STD_HANDLE],MASK_STDIN
jz scs_std_out
xor cx,cx ; CX = HANDLE_STDIN
call alloc_con
jnc scs_std_out
rdr_err:
call free_con
mov ax,error_not_enough_memory
jmp do_again
scs_std_out:
; Make Sure Stdout is checked before stderr. Its very important.
test [SCS_STD_HANDLE],MASK_STDOUT
jz scs_std_err
mov cx,HANDLE_STDOUT
call alloc_con
jc rdr_err
scs_std_err:
test [SCS_STD_HANDLE],MASK_STDERR
jz no_rdr
mov cx,HANDLE_STDERR
call alloc_con
jc rdr_err
no_rdr:
ifdef NEC_98
push ds
push cx
push ax
push dx
CMDSVC SVC_GETCURSORPOS ;gets bios cursor position
;now dx=offset on TEXT VRAM
mov ax,dx
mov cl,160
div cl
mov dh,al
xor dl,dl
mov cl,10h
mov ah,03h
int 0DCH ;set cursor position for DOS
jmp DspFky
FKY_ON DB 1Bh,'[>1l$' ;ESC sequence of FKY on
Dspfky: push cs
pop ds
mov cl,10H
mov ah,01H
mov dx,offset FKY_ON
int 0DCH ;FKY on
pop dx
pop ax
pop cx
pop ds
endif ;NEC_98
mov ah,GetSetCdPg
mov al,1
int 21h
jc cdpg_done
cmp bx,[SCS_CODEPAGE]
jz cdpg_done
mov ah,NLSFUNC ; see if NLSFUNC installed
mov al,0 ;
int 2fh ;
cmp al,NLSFUNC_installed ;
jnz no_nlsf_msg ; NO NLSFUNC ; Print message
; jz got_nls ; Yes - continue
; mov dx,offset trangroup:NLSFUNC_ptr ; no - set up error message
; jmp short cp_error ; error exit
mov bx,[SCS_CODEPAGE] ;SCS Code page
mov ah,getsetcdpg ;set global code page function
mov al,set_global_cp ;minor - set
int 21h
jnc cdpg_done ;no error - exit
nlsf_failed:
; BUGBUG Sudeepb 28-Apr-1992 Putup a message saying NLSFunc failed
no_nlsf_msg:
; BUGBUG Sudeepb 28-Apr-1992 Putup a message saying NLSFunc not installed
cdpg_done:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; (YST) 08-Jan-1993 Checking and installing 16-bit KEYB.COM ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
jmp YST_beg
;; Data for KB16
KEY_LINE db 128 dup (0) ; "d:\nt\system32\kb16.com", 0
YST_ARG db 128 dup (0) ; 32, " XX,,d:\nt\system32\keyboard.sys", 0DH
YPAR dw 0
dd 0
dw 005ch, 0
dw 006ch, 0
KEEP_SS dw 0
KEEP_SP dw 0
YST_beg:
SAVE <BX, ES, DS> ; save all regs for INT 2FH
mov ax, CHECK_KEYB16 ; see if KEYB16 installed
int 2fh
xor dx,dx
cmp al, KEYB16_installed
jne keyb_cont ; KEYB16 not installed, DX == 0
inc dx ; installed DX == 1
keyb_cont:
RESTORE <DS, ES, BX>
push ds
push cs
pop ds
mov si, offset KEY_LINE ; name of KB16.COM
mov cx, offset YST_ARG ; command line
CMDSVC SVC_GETKBDLAYOUT ; Call 32-bit API for checking
; and installing correct layout
or dx,dx ; if DX != 0 after BOP then we need
pop ds ; to install 16-bit KEYB.COM
jnz run_keyb
jmp End_keyb ; No installation of KB16.COM
run_keyb:
;; This part run KB16.COM
SAVE <DS, BX>
PUSH ES ; free TPA for running KB16
MOV ES,[TRAN_TPA]
MOV AH,DEALLOC
INT 21h ; Now running in "free" space
push cs
pop ds
push cs
pop es
mov dx, offset KEY_LINE ; file name
mov YPAR+0, 0000H ; keep current enviroment
mov YPAR+2, offset YST_ARG ; arguments (options) for KB16.COM
mov YPAR+4, ds
mov bx, offset YPAR
mov KEEP_SS, ss ; Peter Norton suggests to keep
mov KEEP_SP, sp ; SS and SP
mov ah, 4bh
xor al, al
int 21h ; RUN!
mov ss, cs:KEEP_SS ; Restore SS and SP
mov sp, cs:KEEP_SP
POP ES
SAVE <BP> ; We need to restore TSR bit
xor si,si ; for running next app.
xor bp,bp ; use "undocumented" call.
mov al,2
mov ah,setdpb
int 21h ; resets the TSR bit
RESTORE <BP>
; Allocate transient again after runnig KB16.
; Copied from TBATCH.ASM
; Modify AX,BX,DX,flags
;
ASSUME DS:TRANGROUP,ES:RESGROUP
PUSH ES
MOV ES,cs:[RESSEG]
MOV BX,0FFFFH ; Re-allocate the transient
MOV AH,ALLOC
INT 21h
PUSH BX ; Save size of block
MOV AH,ALLOC
INT 21h
;
; Attempt to align TPA on 64K boundary
;
POP BX ; Restore size of block
MOV [RES_TPA], AX ; Save segment to beginning of block
MOV [TRAN_TPA], AX
;
; Is the segment already aligned on a 64K boundary
;
MOV DX, AX ; Save segment
AND AX, 0FFFH ; Test if above boundary
JNZ Calc_TPA
MOV AX, DX
AND AX, 0F000H ; Test if multiple of 64K
JNZ NOROUND
Calc_TPA:
MOV AX, DX
AND AX, 0F000H
ADD AX, 01000H ; Round up to next 64K boundary
JC NOROUND ; Memory wrap if carry set
;
; Make sure that new boundary is within allocated range
;
MOV DX, [RES_TPA]
ADD DX, BX ; Compute maximum address
CMP DX, AX ; Is 64K address out of range?
JB NOROUND
;
; Make sure that we won't overwrite the transient
;
MOV BX, CS ; CS is beginning of transient
CMP BX, AX
JB NOROUND
;
; The area from the 64K boundary to the beginning of the transient must
; be at least 64K.
;
SUB BX, AX
CMP BX, 4096 ; Size greater than 64K?
JAE ROUNDDONE
NOROUND:
MOV AX, [RES_TPA]
ROUNDDONE:
MOV [LTPA],AX ; Re-compute everything
MOV [TPA],AX
MOV BX,AX
MOV AX,CS
SUB AX,BX
PUSH BX
MOV BX,16
MUL BX
POP BX
OR DX,DX
JZ SAVSIZ2
MOV AX,-1
SAVSIZ2:
;
; AX is the number of bytes free in the buffer between the resident and the
; transient with a maximum of 64K-1. We round this down to a multiple of 512.
;
CMP AX,512
JBE GotSize1
AND AX,0FE00h ; NOT 511 = NOT 1FF
GotSize1:
MOV [BYTCNT],AX
POP ES
; End Alloc_TPA
RESTORE <BX, DS>
CMDSVC SVC_CMDINITCONSOLE ; make sure console is turned on
End_keyb:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; End of (YST) 08-Jan-1993 Checking and installing 16-bit KEYB.COM ;;
;; ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mov dx,[SCS_CUR_DRIVE]
mov [curdrv],dl
mov ah,0eh
int 21h
push cs
pop ds
MOV DX,OFFSET TRANGROUP:UCOMBUF
endif
GotCom:
MOV CL,[UCOMBUF]
XOR CH,CH
ADD CX,3
MOV SI,OFFSET TRANGROUP:UCOMBUF
MOV DI,OFFSET TRANGROUP:COMBUF
REP MOVSB ; Transfer it to the cooked buffer
;---------------
transpace segment
extrn arg:byte ; the arg structure!
transpace ends
;---------------
DOCOM:
; INVOKE CRLF2
DOCOM1:
INVOKE PRESCAN ; Cook the input buffer
JZ NOPIPEPROC
JMP PIPEPROCSTRT ; Fire up the pipe
nullcomj:
jmp nullcom
NOPIPEPROC:
invoke parseline
jnc OkParse ; user error? or maybe we goofed?
BadParse:
PUSH CS
POP DS
MOV DX,OFFSET TRANGROUP:BADNAM_ptr
INVOKE std_eprintf
JMP TCOMMAND
OkParse:
test arg.argv[0].argflags, MASK wildcard
jnz BadParse ; ambiguous commands not allowed
cmp arg.argvcnt, 0 ; there WAS a command, wasn't there?
jz nullcomj
cmp arg.argv[0].arglen, 0 ; probably an unnecessary check...
jz nullcomj ; guarantees argv[0] at least x<NULL>
MOV SI,OFFSET TRANGROUP:COMBUF+2
MOV DI,OFFSET TRANGROUP:IDLEN
MOV AX,(PARSE_FILE_DESCRIPTOR SHL 8) OR 01H ; Make FCB with blank scan-off
INT 21h
mov BX, arg.argv[0].argpointer
cmp WORD PTR [BX], 05c5ch ; leading "\\" means UNC name
je IsUncName
cmp BYTE PTR [BX+1],':' ; was a drive specified?
jne short drvgd ; no, use default of zero...
mov DL, BYTE PTR [BX] ; pick-up drive letter
and DL, NOT 20H ; uppercase it
sub DL, capital_A ; convert it to a drive number, A=0
CMP AL,-1 ; See what PARSE said about our drive letter.
JZ drvbadj2 ; It was invalid.
IsUncName:
mov DI, arg.argv[0].argstartel
cmp BYTE PTR [DI], 0 ; is there actually a command there?
jnz drvgd ; if not, we have: "d:", "d:\", "d:/"
jmp setdrv ; and set drive to new drive spec
drvbadj2:
jmp drvbad
DRVGD:
MOV AL,[DI]
MOV [SPECDRV],AL
MOV AL,' '
MOV CX,9
INC DI
REPNE SCASB ; Count no. of letters in command name
MOV AL,8
SUB AL,CL
MOV [IDLEN],AL ; IDLEN is truly the length
MOV DI,81H
PUSH SI
mov si, OFFSET TRANGROUP:COMBUF+2 ; Skip over all leading delims
invoke scanoff
;SR;
; We are going to skip over the first char always. The logic is that the
;command tail can never start from the first character. The code below is
;trying to figure out the command tail and copy it to the command line
;buffer in the PSP. However, if the first character happens to be a switch
;character and the user given command line is a full 128 bytes, we try to
;copy 128 bytes to the PSP while it can take only 127 chars. This extra
;char overwrites the code and leads to a crash on future commands.
;
inc si
do_skipcom:
lodsb ; move command line pointer over
invoke delim ; pathname -- have to do it ourselves
jz do_skipped ; 'cause parse_file_descriptor is dumb
cmp AL, 0DH ; can't always depend on argv[0].arglen
jz do_skipped ; to be the same length as the user-
cmp AL, [SWITCHAR] ; specified command string
jnz do_skipcom
do_skipped:
dec SI
; jarbats 11-20-2000
; failing to decrease SI results in missing leading space for command tail
; which upsets many old dos apps which assume there is a space at the beginning and start at the second char
;do_skipped1:
XOR CX,CX
COMTAIL:
LODSB
STOSB ; Move command tail to 80H
CMP AL,13
LOOPNZ COMTAIL
DEC DI
MOV BP,DI
NOT CL
MOV BYTE PTR DS:[80H],CL
POP SI
;-----
; Some of these comments are sadly at odds with this brave new code.
;-----
; If the command has 0 parameters must check here for
; any switches that might be present.
; SI -> first character after the command.
mov DI, arg.argv[0].argsw_word
mov [COMSW], DI ; ah yes, the old addressing mode problem...
mov SI, arg.argv[1 * SIZE argv_ele].argpointer ; s = argv[1];
OR SI,SI ; if (s == NULL)
JNZ DoParse
MOV SI,BP ; s = bp; (buffer end)
DoParse:
MOV DI,FCB
MOV AX,(PARSE_FILE_DESCRIPTOR SHL 8) OR 01H
INT 21h
MOV [PARM1],AL ; Save result of parse
mov DI, arg.argv[1*SIZE argv_ele].argsw_word
mov [ARG1S], DI
mov SI, arg.argv[2*SIZE argv_ele].argpointer ; s = argv[2];
OR SI,SI ; if (s == NULL)
JNZ DoParse2
MOV SI,BP ; s = bp; (bufend)1
DoParse2:
MOV DI,FCB+10H
MOV AX,(PARSE_FILE_DESCRIPTOR SHL 8) OR 01H
INT 21h ; Parse file name
MOV [PARM2],AL ; Save result
mov DI, arg.argv[2*SIZE argv_ele].argsw_word
mov [ARG2S], DI
mov DI, arg.argv[0].argsw_word
not DI ; ARGTS doesn't include the flags
and DI, arg.argswinfo ; from COMSW...
mov [ARGTS], DI
MOV AL,[IDLEN]
MOV DL,[SPECDRV]
or DL, DL ; if a drive was specified...
jnz externalj1 ; it MUST be external, by this time
dec al ; (I don't know why -- old code did it)
jmp fndcom ; otherwise, check internal com table
externalj1:
jmp external
nullcom:
mov [EXECPATH_SIZE], 0
MOV DS,cs:[RESSEG]
ASSUME DS:RESGROUP
TEST [BATCH], -1 ;G Are we in a batch file?
JZ nosetflag ;G only set flag if in batch
mov nullflag,nullcommand ;G set flag to indicate no command
nosetflag:
CMP [SINGLECOM],-1
JZ EXITJ
JMP GETCOM
EXITJ:
JMP $EXITPREP
IF IBM
include vector.inc
include pdb.inc
include arena.inc
include mshalo.asm
ENDIF
std_invalid macro
mov ax,0ffffh
push ax
push ax
endm
std_valid macro
push bx
push cx
endm
CleanForStd macro
add sp,12
endm
DoReEnter:
ASSUME DS:RESGROUP
cmp byte ptr [scs_reentered],3
jne reent_chk
; Control comes here after command /z ran a non-dos binary and
; we re-entered. We just make scs_reentered as 2 indicating that on next
; time we need to return the exit code to 32bit side.
mov byte ptr [scs_reentered],2
jmp reent
reent_chk:
cmp byte ptr [scs_reentered],2
jne reent_cont
jmp retcode32
reent_cont:
cmp byte ptr [scs_reentered],0
je exec_comspec
jmp reent_ret
; Control comes here when we have to exec either command.com or
; cmd.exe. This decision depends on scs_cmdprompt. Here we
; mark scs_reentered state as 1 indicating on return to handle
; exit code.
exec_comspec:
mov byte ptr [scs_reentered],1
cmp byte ptr [scs_cmdprompt],Prompt32
je do32bitprompt
mov al,Start16 ; parameter to put prompt
mov ah,FOR_SHELLOUT
call Do16BitPrompt ; ds is resseg here on return its transseg
or al,al ; return al=0 to run 16bit binary al=1 getnextvdmcommand
jz dos_only
jmp reent
dos_only:
jmp GotCom ; go run through int21/exec
do32BitPrompt:
SAVE <bp,bx,si>
xor bx,bx
mov si,bx
mov bp,bx
mov ax,5303h
int 21h
jnc st_stdin
std_invalid
jmp short go_stdout
st_stdin:
std_valid
go_stdout:
mov bx,1
mov ax,5303h
int 21h
jnc st_stdout
std_invalid
jmp short go_stderr
st_stdout:
std_valid
go_stderr:
mov bx,2
mov ax,5303h
int 21h
jnc st_stderr
std_invalid
jmp short std_done
st_stderr:
std_valid
std_done:
mov bp,sp
push es
mov es,[envirseg]
mov ah,19h
int 21h
CMDSVC SVC_EXECCOMSPEC32
pop es
mov bp,ax
lahf
CleanForStd
sahf
mov ax,bp
RESTORE <si,bx,bp>
jc reent
jmp reent_exit
reent_ret:
; ds is already set to RESSEG
cmp byte ptr [scs_cmdprompt],Prompt32
je retcode32
mov al,return16
mov ah,FOR_SHELLOUT
call Do16BitPrompt ; ds = resseg , on return its transseg
or al,al ; return al=0 to run 16bit binary al=1 getnextvdmcommand
jnz reent
jmp dos_only
retcode32:
mov dx,ds:[retcode]
mov ah,19h
int 21h ; al = cur drive
mov cx,word ptr ds:[RES_RDRINFO]
mov bx,word ptr ds:[RES_RDRINFO+2] ; bx:cx - rdrinfo
CMDSVC SVC_RETURNEXITCODE
mov ds:[retcode],0
jnc reent_exit
reent:
push cs
pop ds
assume ds:trangroup
mov [scs_tsrexit],0
jmp DRE_RET
reent_exit:
ASSUME DS:RESGROUP
push ax
mov ax,(multdos shl 8 or message_2f);AN060; reset parse message pointers
mov dl,set_critical_msg ;AN000; set up critical error message address
mov di,crit_msg_off ;AN000; old offset of critical messages
mov es,crit_msg_seg ;AN000; old segment of critical messages
int 2fh ;AN000; go set it
push cs
pop ds
assume ds:trangroup ;AN000;
; Restore user directory if the restore flag is set. RestUDir1 checks for
; this, restores user dir if flag is set and resets the flag.
invoke RestUDir1 ;restore user dir if needed ;M040
MOV ES,cs:[RESSEG]
assume es:resgroup
MOV AX,[PARENT]
MOV WORD PTR ES:[PDB_Parent_PID],AX
MOV AX,WORD PTR OldTerm
MOV WORD PTR ES:[PDB_Exit],AX
MOV AX,WORD PTR OldTerm+2
MOV WORD PTR ES:[PDB_Exit+2],AX
PUSH ES
MOV ES,[TRAN_TPA]
MOV AH,DEALLOC
INT 21h ; Now running in "free" space
POP ES
pop ax
MOV AH,Exit
INT 21h
; Entry al = Start16 means put the command.com prompt, get the command
; return16 means return the exit code if needed
; ah = FOR_SHELLOUT means came from shellout code (DoReEnter)
; ah = FOR_TSR means came from TSR (tsr_loop)
;
; Exit al = 0 means run 16bit binary
; al = 1 means do getnextvdmcommand
; if came with FOR_TSR, then additionaly
; ah = 1 means returning on exit command
; ah = 0 means otherwise
Do16BitPrompt:
push es
push ax
mov es,cs:[RESSEG] ; es is resident group
ASSUME ES:resgroup
PUSH CS
POP DS ; Need local segment to point to buffer
assume ds:trangroup
cmp al,Start16
ifdef DBCS
je @F
jmp d16_ret
@@:
else ; !DBCS
jne d16_ret
endif ; !DBCS
d16_loop:
ifdef DBCS
;;; williamh Sept 24 1993, removed it. Not necessary to show two line feed
;;; for every command.
;;; yasuho 12/9/93 It is necessary. for example, if previous command
;;; didn't follow CR+LF before terminate, prompt will show on the strange
;;; position.
endif ; DBCS
INVOKE CRLF2
INVOKE PRINT_PROMPT ; put the prompt
ifdef DBCS ;; this should go to US build also
;; reset the title
xor al, al
CMDSVC SVC_SETWINTITLE
endif ; DBCS
MOV DX,OFFSET TRANGROUP:UCOMBUF
mov ah,STD_CON_STRING_INPUT ; AH = Buffered Keyboard Input
int 21h ; call DOS
ifdef DBCS_NT31J
;; special case for CR was added the original source.
;; this code doesn't need. 04/07/94 (hiroh)
;; #3920: CR+LFs are needed when using 32bit command
;; 12/9/93 yasuho
;; not necessary CR+LF if nothing to do
push bx
mov bx, dx
cmp byte ptr [bx + 1], 0 ; only CR ?
pop bx
je @F ; yes. no neccessary CRLF
INVOKE CRLF2
@@:
endif ; DBCS_NT31J
push si
mov si,dx
inc si
inc si
INVOKE SCANOFF ; eat leading delimeters
cmp byte ptr ds:[si],0dh ; special case CR
jne d16_gotcom
pop si
jmp d16_loop
d16_gotcom:
ifdef DBCS ;; this should go to US build also
;; update the new command to the title
mov al, 1
CMDSVC SVC_SETWINTITLE
endif ; DBCS
INVOKE CRLF2
call check_command ; check for exit and cd
pop si
jnc d16_run
or al,al
ifdef DBCS
jnz @F
jmp d16_exit
@@:
else ; !DBCS
jz d16_exit
endif ; !DBCS
d16_dosonly:
mov byte ptr es:[scs_prompt16],0
pop ax
xor ax,ax ; go run the command
pop es
ret
d16_run:
cmp byte ptr es:[scs_dosonly], DOSONLY_YES
je d16_dosonly
push es
push bp
push si
mov ax,0ffffh
push ax ; no standard handle to pass
push ax
push ax
push ax
push ax
push ax
mov bp,sp ; ss:bp is standard handles
mov es,es:[envirseg]
mov si,dx
add si,2 ; first two bytes are the count, after that real command
mov ah,19h
int 21h ; al = cur drive
ifdef NEC_98
jmp Clrfky2
FKY_OFF2 DB 1Bh,'[>1h$' ;ESC sequence of FKY off
Clrfky2: push ds
push cs
pop ds
push cx
push ax
push dx
mov cl,10H
mov ah,01H
mov dx,offset FKY_OFF2
int 0DCH ;FKY off
pop dx
pop ax
pop cx
pop ds
endif ;NEC_98
mov ah,1 ; do cmd /c
CMDSVC SVC_CMDEXEC ; Exec through cmd
ifdef NEC_98
pushf
push ds
push cx
push ax
push dx
CMDSVC SVC_GETCURSORPOS ;gets bios cursor position
;now dx=offset on TEXT VRAM
mov ax,dx
mov cl,160
div cl
mov dh,al
xor dl,dl
mov cl,10h
mov ah,03h
int 0DCH ;set cursor position for DOS
jmp Dspfky2
FKY_ON2 DB 1Bh,'[>1l$' ;ESC sequence of FKY on
Dspfky2: push cs
pop ds
mov cl,10H
mov ah,01H
mov dx,offset FKY_ON2
int 0DCH ;FKY on
pop dx
pop ax
pop cx
pop ds
popf
endif ;NEC_98
lahf
add sp,12 ; recover std handle space
pop si
pop bp
pop es
sahf
ifndef NEC_98
jnc d16_loop ; command completed, go put the prompt
else ;NEC_98
jc @F
jmp d16_loop
@@:
endif ;NEC_98
; carry set means re-entered
d16_retback:
mov byte ptr es:[scs_prompt16],1 ; mark that on return we have
; to go to 32bit with retcode
pop ax
mov ax,1 ; go do getnextvdmcommand
pop es
ret
d16_ret:
cmp byte ptr es:[scs_prompt16],0 ; mark 0 to mean to come back
; and put prompt fro next command
ifdef DBCS
jne @F
jmp d16_loop
@@:
else ; !DBCS
je d16_loop
endif ; !DBCS
d16_return32:
push dx
mov dx,es:[retcode]
mov ah,19h
int 21h ; al = cur drive
mov cx,word ptr es:[RES_RDRINFO]
mov bx,word ptr es:[RES_RDRINFO+2] ; bx:cx - rdrinfo
CMDSVC SVC_RETURNEXITCODE
pop dx
mov es:[retcode],0
jc d16_retback
mov byte ptr es:[scs_prompt16],0
jmp d16_loop
d16_exit:
; exit command was given, turn off the lights
pop ax
cmp ah,FOR_TSR
je d16_exittsr
jmp reent_exit
d16_exittsr:
mov ah,1
pop es
ret
; check if the typed command is one of the commands in NT_INTRL_CMND, if
; so return carry set plus al = 0 if the command was "exit".
;
; input ds:si is the command buffer
; si can be trashed.
check_command:
SAVE <CX,DI,ES>
cmp byte ptr ds:[si+1],':' ; special case drive change i.e C:
jne cc_0
mov al,byte ptr ds:[si+2]
cmp al,0dh ; DELIM for some reason does'nt
je ok_delim ; include 0d
invoke DELIM
jnz no_match
ok_delim:
mov al,1 ; Not exit command
ok_xt:
stc ; Carry means command found
jmp short cc_ret
no_match:
clc ; Carry clear, command not found
cc_ret:
RESTORE <ES,DI,CX>
ret
cc_0:
push si
xor cx,cx
; Convert the source string to upper case and get the length
cc_1:
mov al,byte ptr ds:[si]
invoke DELIM
jz go_look
invoke MOREDELIM
jz go_look
INVOKE UPCONV
mov byte ptr ds:[si],al
inc si
inc cx
jmp short cc_1
go_look:
pop si
jcxz no_match ; zero length, go fail
mov di, OFFSET TRANGROUP:NT_INTRNL_CMND
push cs
pop es
; search through the commands in the table
cc_5:
push si
push di
push cx
cmp cl, byte ptr es:[di]
jne try_next
inc di
repz cmpsb
jnz try_next
jmp short cc_found
try_next:
pop cx
pop di
pop si
mov al,byte ptr es:[di]
or al,al
jz no_match
xor ah,ah
add ax,di
mov di,ax
add di,2
jmp short cc_5
cc_found:
mov al, byte ptr es:[di] ; Is it exit command
pop cx
pop di
pop si
jmp short ok_xt
;
; Input: AL is character to classify
; Output: Z set if delimiter
; NZ set otherwise
; Registers modified: none
;
MOREDELIM:
cmp al,0dh
retz
cmp al,'/'
retz
cmp al,'\'
retz
cmp al,'.'
retz
cmp al,'<'
retz
cmp al,'>'
retz
cmp al,'|'
retz
cmp al,'"'
retz
cmp al,'+'
retz
cmp al,':'
retz
cmp al,';'
retz
cmp al,'['
retz
cmp al,']'
return
free_con:
push ds
MOV DS,cs:[RESSEG]
ASSUME DS:RESGROUP
xor bx,bx ; BX = handle = 0
mov cx,Io_Save ; CX = original stdin, stdout
mov dx,word ptr ds:Pdb_Jfn_Table ; DX = current stdin, stdout
cmp cl,dl
je Chk1 ; stdin matches
mov ah,CLOSE
int 21h ; close stdin
mov ds:Pdb_Jfn_Table,cl ; restore stdin
Chk1:
inc bx ; BX = handle = 1
cmp ch,dh
je Chk2 ; stdout matches
mov ah,CLOSE
int 21h ; close stdout
mov ds:Pdb_Jfn_Table+1,ch ; restore stdout
Chk2:
inc bx ; BX = handle = 2
mov dl,byte ptr ds:[Pdb_Jfn_Table+2] ; Dl = current stderr
mov cl,Io_Stderr ; Cl = original stderr
cmp dl,cl
je chk_x ; stderr matches
mov ah,CLOSE
int 21h ; close stderr
mov ds:Pdb_Jfn_Table+2,cl ; restore stderr
chk_x:
pop ds
ret
alloc_con:
SAVE <DX,SI,BP,BX,DS>
MOV DS,cs:[RESSEG]
ASSUME DS:RESGROUP
push cx
pop ax
mov bx, offset Pdb_Jfn_Table
add bx,ax
mov al,byte ptr ds:[bx]
push ax
push bx
mov byte ptr ds:[bx],0ffh
mov bx,word ptr ds:[RES_RDRINFO]
mov ax,word ptr ds:[RES_RDRINFO+2]
CMDSVC SVC_GETSTDHANDLE ; std hanlde in bx:cx
jc alloc_err
;; bx:cx = nt file handle
;; dx:ax = file size
push di
mov di, ax
xor si,si
xor bp,bp
mov al,0 ; free original console
mov ah,setdpb
int 21h
pop di
jc alloc_err
pop bx
pop ax
RESTORE <DS,BX,BP,SI,DX>
ret
alloc_err:
pop bx
pop ax
mov byte ptr ds:[bx],al
RESTORE <DS,BX,BP,SI,DX>
ret
; ds for tsr_loop is resseg on entry on exit transseg
ASSUME DS:RESGROUP
tsr_loop:
cmp byte ptr ds:[scs_cmdprompt],Prompt32
je tsr_ret
cmp byte ptr ds:[res_batstatus],0
je short tsr_nobat
cmp byte ptr ds:[scs_firsttsr],1
jne short tsr_retcode
jmp tsr_ret
tsr_nobat:
CMDSVC SVC_GETSTARTINFO ; return al = 1, if vdm has to
; terminate on app exit.
or al,al
jne tsr_ret
cmp byte ptr [scs_firsttsr],1
jne tsr_retcode
cmp word ptr ds:[RES_RDRINFO],0
je tsr_nordr
cmp word ptr ds:[RES_RDRINFO+2],0
jne tsr_ret
tsr_nordr:
mov byte ptr ds:[scs_firsttsr],0
mov al,Start16 ; parameter to put prompt
mov ah,FOR_TSR
call Do16BitPrompt ; ds is resseg here on return its transseg
or ah,ah
jnz tsr_exit
or al,al ; return al=0 to run 16bit binary al=1 getnextvdmcommand
jz tsr_dosonly
jmp tsr_ret
tsr_dosonly:
jmp GotCom ; go run through int21/exec
tsr_retcode:
mov al,return16 ; parameter to retun exit code if needed
mov ah,FOR_TSR
call Do16BitPrompt ; ds = resseg , on return its transseg
or ah,ah
jnz tsr_exit
or al,al ; return al=0 to run 16bit binary al=1 getnextvdmcommand
jnz tsr_ret
jmp GotCom
tsr_exit:
push cs
pop ds
assume ds:trangroup
mov [scs_tsrexit],1
tsr_ret:
jmp tsr_loop_ret
TRANCODE ENDS
END