|
|
page ,132 ; SCCSID = @(#)tcmd2b.asm 4.1 85/09/22 ; SCCSID = @(#)tcmd2b.asm 4.1 85/09/22 TITLE PART5 COMMAND Transient routines. ;/* ; * Microsoft Confidential ; * Copyright (C) Microsoft Corporation 1991 ; * All Rights Reserved. ; */
.xlist .xcref include comsw.asm include dossym.inc include syscall.inc include pdb.inc include mult.inc include comseg.asm include comequ.asm include cmdsvc.inc .list .cref
;;CODERES SEGMENT PUBLIC BYTE ;AC000; ;; EXTRN LODCOM1:NEAR ;;CODERES ENDS
DATARES SEGMENT PUBLIC BYTE ;AC000; EXTRN crit_msg_off:word ;AC000; EXTRN crit_msg_seg:word ;AC000; EXTRN IO_SAVE:WORD EXTRN OldTerm:DWORD EXTRN PARENT:WORD ;AD060; EXTRN pars_msg_off:word ;AC000; ;AD060; EXTRN pars_msg_seg:word ;AC000; EXTRN PERMCOM:BYTE ;AN045; EXTRN RetCode:WORD EXTRN SingleCom:word
extrn TrnLodCom1_Trap:far
DATARES ENDS
TRANDATA SEGMENT PUBLIC BYTE ;AC000; EXTRN ACRLF_PTR:WORD ;AN007; EXTRN baddev_ptr:word EXTRN CP_active_Ptr:word EXTRN CP_not_all_Ptr:word EXTRN CP_not_set_Ptr:word EXTRN Extend_buf_ptr:word ;AN000; EXTRN Extend_buf_sub:byte ;AN000; EXTRN inv_code_page:word ;AC000; EXTRN msg_disp_class:byte ;AN000; EXTRN NLSFUNC_Ptr:word ;AC000; EXTRN parse_chcp:byte ;AC000; EXTRN parse_chdir:byte ;AC000; EXTRN parse_ctty:byte ;AC000; EXTRN string_buf_ptr:word ;AC000;
extrn NoCntry_Ptr:word ;M045
TRANDATA ENDS
TRANSPACE SEGMENT PUBLIC BYTE ;AC000; EXTRN COMBUF:BYTE EXTRN parse_last:word ;AN018; EXTRN parse1_addr:dword ;AC000; EXTRN parse1_type:byte ;AC000; EXTRN RESSEG:WORD EXTRN srcbuf:byte EXTRN srcxname:byte ;AC000; EXTRN string_ptr_2:word EXTRN system_cpage:word EXTRN TRAN_TPA:WORD TRANSPACE ENDS
TRANCODE SEGMENT PUBLIC BYTE
ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
;---------------
TRANSPACE SEGMENT PUBLIC BYTE ;AC000; EXTRN arg:byte ; the arg structure! TRANSPACE ENDS ;---------------
EXTRN cerror:near extrn TCommand:near
PUBLIC $exit PUBLIC chcp PUBLIC ctty PUBLIC parse_check_eol ;AN000; PUBLIC parse_with_msg ;AN018; PUBLIC setup_parse_error_msg ;AN018; PUBLIC truename ;AN000;
break Ctty assume ds:trangroup,es:trangroup
; **************************************************************** ; * ; * ROUTINE: CTTY - Change console ; * ; * SYNTAX: CTTY device ; * ; * FUNCTION: If a valid console device is specified, CTTY will ; * duplicate the device handle to STDIN, STDOUT and ; * STDERR. This routine returns to LODCOM1. ; * ; * INPUT: command line at offset 81H ; * ; * OUTPUT: none ; * ; ****************************************************************
CTTY: push ds ;AN000; Get local ES pop es ;AN000; mov si,81H ;AC000; Get command argument for CTTY
mov di,offset trangroup:parse_ctty ;AC000; Get adderss of PARSE_CTTY xor cx,cx ;AC000; clear cx,dx xor dx,dx ;AC000; invoke cmd_parse ;AC000; call parser cmp ax,end_of_line ;AN000; are we at end of line? jz ctty_error ;AN000; yes - error cmp ax,result_no_error ;AN000; did an error occur jnz ctty_error ;AN000; YES -ERROR
push si ;AN000; save position in line lds si,parse1_addr ;AN000; get address of filespec mov di,offset trangroup:srcbuf ;AN000; get address of srcbuf
ctty_move_filename: ;AN000; put filespec in srcbuf lodsb ;AN000; get a char from buffer stosb ;AN000; store in srcbuf cmp al,end_of_line_out ;AN000; it char a terminator? jnz ctty_move_filename ;AN000; no - keep moving pop si ;AN000; get line position back mov di,offset trangroup:parse_ctty ;AC000; Get adderss of PARSE_CTTY ifndef NEC_98 call parse_check_eol ;AN000; are we at end of line? else ;NEC_98 ; call parse_check_eol ;AN000; are we at end of line? ; NEC01 91/07/31 Del
xor dx,dx ;AN000; ; NEC01 91/07/31 mov [parse_last],si ;AN018; save start of parameter ; NEC01 91/07/31 invoke cmd_parse ;AN000; call parser ; NEC01 91/07/31 cmp al,end_of_line ;AN000; Are we at end of line? ; NEC01 91/07/31 endif ;NEC_98 jz nocolon ;AN000; yes - continue
ctty_error: jmp short isbaddev ;AC000; yes - exit
nocolon: mov dx,offset trangroup:srcbuf ;AN000; get address of srcbuf MOV AX,(OPEN SHL 8) OR 2 ; Read and write INT 21h ; Open new device JC ISBADDEV MOV BX,AX MOV AX,IOCTL SHL 8 INT 21h TEST DL,80H JNZ DEVISOK
CLOSEDEV: ;AN007; MOV AH,CLOSE ; Close initial handle INT 21h
ISBADDEV: MOV DX,OFFSET TRANGROUP:BADDEV_ptr invoke std_printf JMP SHORT RESRET
DEVISOK: push dx ;AN007; save device info mov ax,acrlf_ptr ;AN021; get message number for 0d, 0a mov dh,util_msg_class ;AN021; this is a utility message push bx ;AN021; save handle invoke Tsysgetmsg ;AN021; get the address of the message mov dx,si ;AN021; get address into dx mov ax,(write shl 8) ;AN007; write to device mov cx,2 ;AN007; write two bytes int 21h ;AN007; pop bx ;AN021; get back handle pop dx ;AN007; get back device info jc closedev ;AN007; if error, quit XOR DH,DH OR DL,3 ; Make sure has CON attributes MOV AX,(IOCTL SHL 8) OR 1 INT 21h PUSH BX ; Save handle MOV CX,3 XOR BX,BX
ICLLOOP: ; Close basic handles MOV AH,CLOSE INT 21h INC BX LOOP ICLLOOP POP BX ; Get handle MOV AH,XDUP INT 21h ; Dup it to 0 MOV AH,XDUP INT 21h ; Dup to 1 MOV AH,XDUP INT 21h ; Dup to 2 MOV AH,CLOSE ; Close initial handle INT 21h
RESRET: MOV DS,[RESSEG] ASSUME DS:RESGROUP PUSH DS MOV AX,WORD PTR DS:[PDB_JFN_Table] ; Get new 0 and 1 MOV [IO_SAVE],AX MOV AX,OFFSET DATARES:TrnLodCom1_Trap PUSH AX
ZMMMM PROC FAR RET ; Force header to be checked ZMMMM ENDP
break Chcp
;**************************************************************** ;* ;* ROUTINE: CHCP - Change code page internal command ;* (added DOS 3.30 07/21/86) ;* ;* SYNTAX: CHCP [xxx] ;* where xxx is a valid code page ;* ;* FUNCTION: If xxx is specified, CHCP will use INT 21H function ;* 6402H to set the code page to xxxx. If no parameters ;* are specified, CHCP will use INT 21H function 6401H ;* to get global code page and display it to the user. ;* ;* INPUT: command line at offset 81H ;* ;* OUTPUT: none ;* ;****************************************************************
NLSFUNC_installed equ 0ffh set_global_cp equ 2 get_global_cp equ 1
assume ds:trangroup,es:trangroup
CHCP: push ds ;AN000; Get local ES pop es ;AN000; mov si,81H ;AC000; Get command argument for CHCP
mov di,offset trangroup:parse_chcp ;AN000; Get adderss of PARSE_CHCP xor cx,cx ;AC000; clear cx,dx xor dx,dx ;AC000; call parse_with_msg ;AC018; call parser cmp ax,end_of_line ;AN000; are we at end of line?
;; jnz setcp ;AC000; no go get number & set code page jz getcp ;AC000; yes - no parm - get code page
setcp: cmp ax,result_no_error ;AN000; did we have an error? jne cp_error ;AC018; yes - go issue message
push cx ;AN000; save positional count mov bx,offset trangroup:parse1_addr ;AN000; get number returned mov cx,word ptr [bx] ;AN000; into cx mov system_cpage,cx ;AN000; save user input number pop cx ;AC000; restore positional count mov di,offset trangroup:parse_chcp ;AN000; Get adderss of PARSE_CHCP call parse_check_eol ;AN000; are we at end of line? jnz cp_error ;AC000; no - exit
okset: mov ah,NLSFUNC ;AN000; see if NLSFUNC installed mov al,0 ;AN000; int 2fh ;AN000; cmp al,NLSFUNC_installed ;AN000; jz got_NLS ;AN000; Yes - continue mov dx,offset trangroup:NLSFUNC_ptr ;AN000; no - set up error message jmp short cp_error ;AN000; error exit
got_NLS: mov bx,system_cpage ;AN000; get user input code page mov ah,getsetcdpg ;get/set global code page function mov al,set_global_cp ;minor - set int 21h jnc chcp_return ;no error - exit ; ;added for p716 ; cmp ax,error_file_not_found ;p716 was the error file not found? jnz chcp_other_error ;no - country.sys was found
mov ah,GetExtendedError ;p850 see if error is invalid data xor bx,bx ; which is file was found but CP int 21h ; information was not found. cmp ax,error_invalid_data ;AC000; invalid code page jnz no_countrysys ;no - use file not found mov dx,offset trangroup:inv_code_page ;AN000; get message jmp short cp_error ;AC000; error exit
no_countrysys: ;M045; mov msg_disp_class,ext_msg_class ;AN000; set up extended error msg class ;M045; mov dx,offset TranGroup:Extend_Buf_ptr ;AC000; get extended message pointer ;M045; mov Extend_Buf_ptr,error_file_not_found ;AN000; get message number in control block mov dx,offset TRANGROUP:NoCntry_Ptr ;M045
jmp short cp_error ;AC000; error exit
chcp_other_error: ; ; end of p716 ; mov ah,GetExtendedError ;error - see what it is xor bx,bx int 21h cmp ax,65 ;was it access denied? jnz none_set ;no - assume all failed mov dx,offset trangroup:cp_not_all_ptr ;set up message jmp short cp_error ;AC000; error exit
none_set: mov dx,offset trangroup:cp_not_set_ptr ;set up message cp_error: ;AN000; jmp cerror ;exit
getcp: mov ah,getsetcdpg ;get/set global code page function mov al,get_global_cp ;minor - get int 21h mov system_cpage,bx ;get active cp for output mov dx,offset trangroup:cp_active_ptr invoke std_printf ;print it out
chcp_return:
RET
break TRUENAME ;AN000;
; **************************************************************** ; * ; * ROUTINE: TRUENAME ; * ; * FUNCTION: Entry point for the internal TRUENAME command. ; * Parses the command line. If a path is found, set ; * SRCXNAME to path. If only a drive letter is ; * found, set SRCXNAME to the drive letter. If ; * no path is found, set the path of SRCXNAME to ; * dot (.) for current directory. Use the NAME ; * TRANSLATE system call to get the real name and ; * then display the real name. If an error occurs ; * issue an error message and transfer control to ; * CERROR. ; * ; * INPUT: command line at offset 81H ; * ; * OUTPUT: none ; * ; ****************************************************************
assume ds:trangroup,es:trangroup ;AN000;
TRUENAME: ;AN000; TRUENAME entry point push ds ;AN000; Get local ES pop es ;AN000; mov si,81H ;AN000; Get command line mov di,offset trangroup:parse_chdir ;AN000; Get adderss of PARSE_CHDIR xor cx,cx ;AN000; clear cx,dx xor dx,dx ;AN000; call parse_with_msg ;AC018; call parser
mov di,offset trangroup:srcxname ;AN000; get address of srcxname cmp ax,end_of_line ;AN000; are we at end of line? je tn_eol ;AN000; yes - go process cmp ax,result_no_error ;AN000; did we have an error? jne tn_parse_error ;AN000; yes - go issue message cmp parse1_type,result_drive ;AN000; was a drive entered? je tn_drive ;AN000; yes - go process jmp short tn_filespec ;AN000; nothing else - must be filespec
tn_eol: ;AN000; no parameters on line mov ah,end_of_line_out ;AN000; set buffer to . mov al,dot_chr ;AN000; for current dir stosw ;AN000; store in srcxname jmp short tn_doit ;AN000; go do command
tn_drive: ;AN000; a drive was entered push si ;AN000; save position in line mov si,offset trangroup:parse1_addr ;AN000; get address of drive lodsb ;AN000; get the drive number add al,"A"-1 ;AN000; convert it to char stosb ;AN000; store it in srcxname mov ax,dot_colon ;AN000; get colon and . and stosw ;AN000; store in srcxname mov al,end_of_line_out ;AN000; put a terminator char stosb ;AN000; pop si ;AN000; get line position back jmp short tn_check_eol ;AN000; check to make sure eol
tn_filespec: ;AN000; a filespec was entered push si ;AN000; save position in line lds si,parse1_addr ;AN000; get address of filespec
tn_move_filename: ;AN000; put filespec in srcxname lodsb ;AN000; get a char from buffer stosb ;AN000; store in srcxname cmp al,end_of_line_out ;AN000; it char a terminator? jnz tn_move_filename ;AN000; no - keep moving pop si ;AN000; get line position back
tn_check_eol: ;AN000; make sure no extra parms mov di,offset trangroup:parse_chdir ;AN000; get address of parse_chdir call parse_check_eol ;AN000; are we at end of line? je tn_doit ;AN000; Yes - do the command
tn_parse_error: ;AN000; A parse error occurred jmp cerror ;AN000; Go to error routine
tn_doit: ;AN000; mov si,offset trangroup:srcxname ;AN000; set up srcxname as source mov di,offset trangroup:combuf ;AN000; set up combuf as target (need big target) mov ah,xnametrans ;AN000; do name translate call int 21h ;AN000; jnc tn_print_xname ;AN000; If no error - print result
invoke Set_ext_error_msg ;AN000; get extended message mov string_ptr_2,offset trangroup:srcxname ;AN000; get address of failed string mov Extend_buf_sub,one_subst ;AN000; put number of subst in control block jmp cerror ;AN000; Go to error routine
tn_print_xname: ;AN000; mov string_ptr_2,offset Trangroup:combuf ;AN000; Set up address of combuf mov dx,offset trangroup:string_buf_ptr ;AN000; Set up address of print control block invoke crlf2 ;AN000; print a crlf invoke printf_crlf ;AN000; print it out
ret ;AN000;
break $Exit
assume ds:trangroup,es:trangroup
$EXIT: push ds ;AN000; save data segment mov ds,[resseg] ;AN000; get resident data segment
assume ds:resgroup ;AN000;
cmp [permcom],0 ;AN045; is this a permanent COMMAND? jz free_com ;AN045; no - free everything
; We're a permanent command. ; Unless this is a singlecom (int 2Eh), don't deallocate transient.
cmp [singlecom],-1 ;M034 je no_reset ;M034 ;exit singlecom
; jmp TCommand ;permanent command, recycle
;Sudeepb 05-Jul-1991; Removed above jmp to terminate the top level ; command.com. CMDSVC SVC_CMDEXITVDM ; Never returns
;AD060; mov ah,multdos ;AN000; reset parse message pointers ;AD060; mov al,message_2f ;AN000; call for message retriever ;AD060; mov dl,set_parse_msg ;AN000; set up parse message address ;AD060; mov di,pars_msg_off ;AN000; old offset of parse messages ;AD060; mov es,pars_msg_seg ;AN000; old segment of parse messages ;AD060; int 2fh ;AN000; go set it
;AD060; mov ah,multdos ;AN000; set up to call DOS through int 2fh ;AD060; mov al,message_2f ;AN000; call for message retriever
free_com: 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 no_reset: ;AN045; pop ds ;AN000; restore local data segment
assume ds:trangroup ;AN000; ; ;M040 ; 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,[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
MOV AH,Exit MOV AL,BYTE PTR RetCode INT 21h
; **************************************************************** ; * ; * ROUTINE: PARSE_CHECK_EOL ; * ; * FUNCTION: Calls parser to see if end of line occurred. ; * If not end of line, set up to print parse ; * error message. ASSUMES NO MORE PARAMETERS ARE ; * EXPECTED! ; * ; * INPUT: DS:SI last output from parser ; * ES:DI points to parse block ; * CX last output from parser ; * ; * OUTPUT: AX parser return code ; * ; * if end of line found ; * zero flag set ; * else ; * MSG_DISPLAY_CLASS set to parse error ; * ; ****************************************************************
ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:NOTHING ;AN000;
parse_check_eol Proc near ;AN000;
xor dx,dx ;AN000; mov [parse_last],si ;AN018; save start of parameter invoke cmd_parse ;AN000; call parser cmp al,end_of_line ;AN000; Are we at end of line? jz parse_good_eol ;AN000; yes - no problem
cmp ax,result_no_error ;AN018; was any error found? jnz ok_to_setup_pmsg ;AN018; yes - continue inc ax ;AN018; set AX to 1 and turn off zero flag
ok_to_setup_pmsg: call setup_parse_error_msg ;AN018; go set up error message
parse_good_eol: ret ;AN000;
parse_check_eol endp ;AN000;
; **************************************************************** ; * ; * ROUTINE: PARSE_WITH_MSG ; * ; * FUNCTION: Calls parser. If an error occurred, the error ; * message is set up. ; * ; * INPUT: DS:SI last output from parser ; * ES:DI points to parse block ; * CX last output from parser ; * ; * OUTPUT: AX parser return code ; * ; * if no error ; * outputs from parser ; * else ; * MSG_DISPLAY_CLASS set to parse error ; * error message set up for STD_PRINTF ; * ; ****************************************************************
ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:NOTHING ;AN018;
parse_with_msg Proc near ;AN018;
mov [parse_last],si ;AN018; save start of parameter invoke cmd_parse ;AN018; call parser cmp al,end_of_line ;AN018; Are we at end of line? jz parse_msg_good ;AN018; yes - no problem cmp ax,result_no_error ;AN018; did an error occur jz parse_msg_good ;AN018; yes - no problem
call setup_parse_error_msg ;AN018; go set up error message
parse_msg_good: ret ;AN018;
parse_with_msg endp ;AN018;
; **************************************************************** ; * ; * ROUTINE: SETUP_PARSE_ERROR_MSG ; * ; * FUNCTION: Calls parser. If an error occurred, the error ; * message is set up. ; * ; * INPUT: AX Parse error number ; * SI Set to past last parameter ; * Parse_last Set to start of last parameter ; * ; * OUTPUT: MSG_DISPLAY_CLASS set to parse error ; * error message set up for STD_PRINTF ; * ; ****************************************************************
ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:NOTHING ;AN018;
SETUP_PARSE_ERROR_MSG Proc near ;AN018;
mov msg_disp_class,parse_msg_class ;AC018; Set up parse message class mov dx,offset TranGroup:Extend_Buf_ptr ;AC018; get extended message pointer mov byte ptr [si],end_of_line_out ;AC018; terminate the parameter string mov Extend_Buf_ptr,ax ;AC018; get message number in control block cmp ax,lessargs_ptr ;AC018; if required parameter missing jz Setup_parse_msg_ret ;AN018; no subst mov si,[parse_last] ;AC018; get start of parameter mov string_ptr_2,si ;AC018; get address of failed string mov Extend_buf_sub,one_subst ;AC018; put number of subst in control block
setup_parse_msg_ret: inc si ;AN018; make sure zero flag not set
ret ;AC018;
SETUP_PARSE_ERROR_MSG Endp ;AN018;
trancode ends end
|