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

590 lines
15 KiB
NASM
Raw 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 = @(#)tucode.asm 4.2 85/05/31
; SCCSID = @(#)tucode.asm 4.2 85/05/31
Title COMMAND Language midifiable Code Transient
;/*
; * Microsoft Confidential
; * Copyright (C) Microsoft Corporation 1991
; * All Rights Reserved.
; */
.xlist
.xcref
include dossym.inc
include syscall.inc
include comsw.asm
include comseg.asm
include comequ.asm
.list
.cref
DATARES SEGMENT PUBLIC BYTE ;AC000;
EXTRN ECHOFLAG:BYTE
DATARES ENDS
TRANDATA SEGMENT PUBLIC BYTE ;AC000;
EXTRN BAD_ON_OFF_ptr:word
EXTRN ctrlcmes_ptr:word
EXTRN DEL_Y_N_PTR:WORD
EXTRN ECHOMES_ptr:word
EXTRN extend_buf_ptr:word ;AC000;
EXTRN offmes_ptr:word
EXTRN onmes_ptr:word
EXTRN PARSE_BREAK:BYTE ;AN000;
EXTRN promptdat_moday:word ;AC000;
EXTRN promptdat_ptr:word ;AC000;
EXTRN promptdat_yr:word ;AC000;
EXTRN string_buf_ptr:word
EXTRN SUREMES_ptr:word
EXTRN VERIMES_ptr:BYTE
EXTRN WeekTab:word
TRANDATA ENDS
TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
EXTRN arg_buf:byte
EXTRN BWDBUF:BYTE
EXTRN DEST:BYTE
EXTRN destdir:byte
EXTRN dirchar:byte
EXTRN PARSE1_CODE:BYTE ;AN000;
EXTRN RESSEG:WORD
EXTRN string_ptr_2:word
TRANSPACE ENDS
TRANCODE SEGMENT PUBLIC BYTE
EXTRN CERROR:NEAR
EXTRN CRLF2:NEAR
EXTRN extend_setup:near ;AN022;
PUBLIC CNTRLC
PUBLIC ECHO
PUBLIC GetDate
PUBLIC NOTEST2
PUBLIC PRINT_DATE
PUBLIC SLASHP_ERASE ;AN000;
PUBLIC VERIFY
ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:TRANGROUP,SS:NOTHING
; ****************************************************************
; *
; * ROUTINE: NOTEST2 - execution of DEL/ERASE command
; *
; * FUNCTION: Delete files based on user parsed input. Prompt
; * user for Y/N if necessary. If an error occurs,
; * set up an error message and go to CERROR.
; *
; * INPUT: FCB at 5ch set up with filename(s) entered
; * Current directory set to entered directory
; *
; * OUTPUT: none
; *
; ****************************************************************
;
; ARE YOU SURE prompt when deleting *.*
NOTEST2:
MOV CX,11
MOV SI,FCB+1
AMBSPEC:
LODSB
CMP AL,'?'
JNZ ALLFIL
LOOP AMBSPEC
ALLFIL:
CMP CX,0
JNZ NOPRMPT
ASKAGN:
MOV DX,OFFSET TRANGROUP:SUREMES_ptr ; "Are you sure (Y/N)?"
invoke std_printf
MOV SI,80H
MOV DX,SI
MOV WORD PTR [SI],120 ; zero length
MOV AX,(STD_CON_INPUT_FLUSH SHL 8) OR STD_CON_STRING_INPUT
INT 21H
LODSW
OR AH,AH
JZ ASKAGN
INVOKE SCANOFF
call char_in_xlat ;G Convert to upper case
retc ;AN000; return if function not supported
CMP AL,CAPITAL_N ;G
retz
CMP AL,CAPITAL_Y ;G
PUSHF
CALL CRLF2
POPF
JNZ ASKAGN
NOPRMPT:
MOV AH,FCB_DELETE
MOV DX,FCB
INT 21H
INC AL
jz eraerr
invoke RESTUDIR
ret ; If no error, return
eraerr:
invoke set_ext_error_msg ;AN022; set up the extended error
push dx ;AN022; save message
invoke RESTUDIR
pop dx ;AN022; restore message
cmp word ptr extend_buf_ptr,error_no_more_files ;AN022; convert no more files to
jnz cerrorj2 ;AN022; file not found
mov Extend_Buf_ptr,error_file_not_found ;AN000; get message number in control block
cerrorj2:
jmp cerror
; ****************************************************************
; *
; * ROUTINE: SLASHP_ERASE - execution of DEL/ERASE /P
; *
; * FUNCTION: Delete files based on user parsed input. Prompt
; * user for Y/N where necessary. If an error occurs
; * set up and error message and transfer control
; * to CERROR.
; *
; * INPUT: FCB at 5ch set up with filename(s) entered
; * Current directory set to entered directory
; *
; * OUTPUT: none
; *
; ****************************************************************
ASSUME CS:TRANGROUP,DS:TRANGROUP,ES:TRANGROUP,SS:NOTHING
SLASHP_ERASE: ;AN000; entry point
invoke build_dir_string ;AN000; set up current directory string for output
mov ah,Set_DMA ;AN000; issue set dta int 21h
mov dx,offset trangroup:destdir ;AN000; use Destdir for target
int 21H ;AN000;
mov ah,Dir_Search_First ;AN000; do dir search first int 21h
mov dx,FCB ;AN000; use FCB at 5Ch for target
int 21H ;AN000;
inc al ;AN000; did an error occur
jz eraerr ;AN022; go to error exit
delete_prompt_loop: ;AN000;
mov si,offset trangroup:destdir+1 ;AN000; set up FCB as source
mov di,offset trangroup:dest ;AN000; set up dest as target
mov al,dirchar ;AN000; store a "\" in the first char
stosb ;AN000; of DEST
invoke fcb_to_ascz ;AN000; convert filename from FCB to ASCIIZ string
slashp_askagn: ;AN000;
call crlf2 ;AN000; print out carriage return, line feed
mov dx,offset trangroup:bwdbuf ;AN000; print out current directory string
mov bx,dx ;AN000; get string pointer in bx
cmp byte ptr [bx+3],end_of_line_out ;AN000; see if only D:\,0
jnz not_del_root ;AN000; no continue
mov byte ptr [bx+2],end_of_line_out ;AN000; yes, get rid of \
Not_del_root: ;AN000;
mov string_ptr_2,dx ;AN000;
mov dx,offset trangroup:string_buf_ptr ;AN000;
invoke std_printf ;AN000;
mov dx,offset trangroup:dest ;AN000; print out file name string
mov string_ptr_2,dx ;AN000;
mov dx,offset trangroup:string_buf_ptr ;AN000;
invoke std_printf ;AN000;
mov dx,offset trangroup:Del_Y_N_Ptr ;AN000; issue ", Delete (Y/N)?" message
invoke std_printf ;AN000;
;;M029 mov si,80H ;AN000; set up buffer for input
;;M029 mov dx,si ;AN000;
;;M029 mov word ptr [si],combuflen ;AN000;
;;M029 mov ax,(std_con_input_flush shl 8) or std_con_string_input ;AN000;
;;M029 int 21h ;AN000; get input from the user
;;M029 lodsw ;AN000;
;;M029 or ah,ah ;AN000; was a character entered?
;;M029 jz slashp_askagn ;AN000; no - ask again
;;M029 invoke scanoff ;AN000; scan off leading delimiters
; Get a single character input.
mov ax,(std_con_input_flush shl 8) or std_con_input ;M029
int 21h ;M029
call char_in_xlat ;AN000; yes - upper case it
retc ;AN000; return if function not supported
cmp al,capital_n ;AN000; was it no?
jz next_del_file ;AN000; yes - don't delete file
cmp al,capital_y ;AN000; was it yes?
jz delete_this_file ;AN000; yes - delete the file
jmp short slashp_askagn ;AN000; it was neither - ask again
delete_this_file: ;AN000;
mov ah,fcb_delete ;AN000; delete the file
mov dx,offset trangroup:destdir ;AN000; use Destdir for target
int 21h ;AN000;
inc al ;AN000; did an error occur?
jnz next_del_file ;AN000; no - get next file
;
;M041; Begin changes
; We got an error deleting the file. If this is access denied, we can go on
;to the next file after printing an error message.
;
invoke Get_ext_error_number ;see what error we got
cmp ax,error_access_denied ;is it access denied?
jne stop_del ;no, some other error
invoke CrLf2 ;print a CR-LF
invoke set_ext_error_msg ;error message
invoke std_eprintf ;"Access denied"
jmp short next_del_file ;try next file
stop_del:
;
;M041; End changes
;
jmp eraerr ;AN022; go to error exit - need long jmp
next_del_file: ;AN000;
;
; M050 - begin
; Norton Utilities 5.0 has a bug. DiskMon when invoked
; with /protect+ and /light+ makes it intercept all
; deletes. This hook does not save and restore the DTA correctly.
; They save the DWORD in a WORD by mistake! They save both the
; segment and the offset in the SAME variable (WORD)!!!
;
mov ah,Set_DMA
mov dx,offset trangroup:destdir
int 21H
;
; M050 - end
mov ah,dir_search_next ;AN000; search for another file
mov dx,FCB ;AN000;
int 21h ;AN000;
inc al ;AN000; was a file found?
jz slash_p_exit ;AN000; no - exit
jmp delete_prompt_loop ;AN000; yes - continue (need long jump)
slash_p_exit:
invoke get_ext_error_number ;AN022; get the extended error number
cmp ax,error_no_more_files ;AN022; was error file not found?
jz good_erase_exit ;AN022; yes - clean exit
jmp extend_setup ;AN022; go issue error message
good_erase_exit:
invoke restudir ;AN000; we're finished - restore user's dir
call crlf2 ;AN000; print out carriage return, line feed
ret ;AN000; exit
;************************************************
; ECHO, BREAK, and VERIFY commands. Check for "ON" and "OFF"
break Echo
assume ds:trangroup,es:trangroup
ECHO:
CALL ON_OFF
JC DOEMES
MOV DS,[RESSEG]
ASSUME DS:RESGROUP
JNZ ECH_OFF
OR [ECHOFLAG],1
RET
ECH_OFF:
AND [ECHOFLAG],NOT 1
RET
CERRORJ:
JMP CERROR
;
; There was no discrenable ON or OFF after the ECHO. If there is nothing but
; delimiters on the command line, we issue the ECHO is ON/OFF message.
;
ASSUME DS:TRANGROUP
DOEMES:
cmp cl,0 ;AC000; was anything on the line?
jz PEcho ; just display current state.
MOV DX,82H ; Skip one char after "ECHO"
invoke CRPRINT
JMP CRLF2
PECHO:
MOV DS,[RESSEG]
ASSUME DS:RESGROUP
MOV BL,[ECHOFLAG]
PUSH CS
POP DS
ASSUME DS:TRANGROUP
AND BL,1
MOV DX,OFFSET TRANGROUP:ECHOMES_ptr
JMP SHORT PYN
break Break
assume ds:trangroup,es:trangroup
CNTRLC:
CALL ON_OFF
MOV AX,(SET_CTRL_C_TRAPPING SHL 8) OR 1
JC PCNTRLC
JNZ CNTRLC_OFF
MOV DL,1
INT 21H ; Set ^C
RET
CNTRLC_OFF:
XOR DL,DL
INT 21H ; Turn off ^C check
RET
PCNTRLC:
CMP CL,0 ;AC000; rest of line blank?
JNZ CERRORJ ; no, oops!
pccont:
XOR AL,AL
INT 21H
MOV BL,DL
MOV DX,OFFSET TRANGROUP:CTRLCMES_ptr
PYN:
mov si,offset trangroup:onmes_ptr ;AC000; get ON pointer
OR BL,BL
JNZ PRINTVAL
mov si,offset trangroup:offmes_ptr ;AC000; get OFF pointer
PRINTVAL:
push dx ;AN000; save offset of message block
mov bx,dx ;AN000; save offset value
lodsw ;AN000; get message number of on or off
mov dh,util_msg_class ;AN000; this is a utility message
invoke Tsysgetmsg ;AN000; get the address of the message
add bx,ptr_off_pos ;AN000; point to offset of ON/OFF
mov word ptr [bx],si ;AN000; put the offset in the message block
pop dx ;AN000; get message back
invoke std_printf ;AC000; go print message
mov word ptr [bx],0 ;AN000; zero out message pointer
ret ;AN000; exit
break Verify
assume ds:trangroup,es:trangroup
VERIFY:
CALL ON_OFF
MOV AX,(SET_VERIFY_ON_WRITE SHL 8) OR 1
JC PVERIFY
JNZ VER_OFF
INT 21H ; Set verify
RET
VER_OFF:
DEC AL
INT 21H ; Turn off verify after write
RET
PVERIFY:
CMP CL,0 ;AC000; is rest of line blank?
JNZ CERRORJ ; nope...
MOV AH,GET_VERIFY_ON_WRITE
INT 21H
MOV BL,AL
MOV DX,OFFSET TRANGROUP:VERIMES_ptr
JMP PYN
; ****************************************************************
; *
; * ROUTINE: ON_OFF
; *
; * FUNCTION: Parse the command line for an optional ON or
; * OFF string for the BREAK, VERIFY, and ECHO
; * routines.
; *
; * INPUT: command line at offset 81H
; * PARSE_BREAK control block
; *
; * OUTPUT: If carry is clear
; * If ON is found
; * Zero flag set
; * If OFF is found
; * Zero flag clear
; * If carry set
; * If nothing on command line
; * CL set to zero
; * If error
; * CL contains error value from parse
; *
; ****************************************************************
assume ds:trangroup,es:trangroup
ON_OFF:
MOV SI,81h
scan_on_off: ;AN032; scan off leading blanks & equal
lodsb ;AN032; get a char
cmp al,blank ;AN032; if whitespace
jz scan_on_off ;AN032; keep scanning
cmp al,tab_chr ;AN032; if tab
jz scan_on_off ;AN032; keep scanning
cmp al,equal_chr ;AN032; if equal char
jz parse_on_off ;AN032; start parsing
dec si ;AN032; if none of above - back up
parse_on_off: ;AN032; and start parsing
mov di,offset trangroup:parse_break ;AN000; Get adderss of PARSE_BREAK
xor cx,cx ;AN000; clear cx,dx
xor dx,dx ;AN000;
invoke cmd_parse ;AC000; call parser
cmp ax,end_of_line ;AC000; are we at end of line?
jz BADONF ;AC000; yes, return error
cmp ax,result_no_error ;AN000; did an error occur
jz on_off_there ;AN000; no - continue
mov cx,ax ;AN000; yes - set cl to error code
jmp short BADONF ;AN000; return error
on_off_there:
cmp parse1_code,-1 ;AN014; was a valid positional present?
jnz good_on_off ;AN014; yes - continue
mov cx,badparm_ptr ;AN014; something other than ON/OFF
jmp short BADONF ;AN014; return error
good_on_off: ;AN014;
xor ax,ax ;AC000; set up return code for
or al,parse1_code ;AC000; ON or OFF in AX
pushf ;AN000; save flags
mov di,offset trangroup:parse_break ;AN000; Get adderss of PARSE_BREAK
xor dx,dx ;AN000;
invoke cmd_parse ;AN000; call parser
cmp ax,end_of_line ;AN000; are we at end of line?
jnz BADONF_flags ;AN000; NO, return error
popf ;AN000; restore flags
clc ;AC000; no error
jmp short on_off_end ;AN000; return to caller
BADONF_flags:
mov cx,ax
popf
;
; No discernable ON or OFF has been found. Put an error message pointer in DX
; and return the error
;
BADONF:
MOV DX,OFFSET TRANGROUP:BAD_ON_OFF_ptr
STC
ON_OFF_END:
RET
;*************************************************************************
; print date
PRINT_DATE:
PUSH ES
PUSH DI
PUSH CS
POP ES
CALL GetDate ; get date
xchg dh,dl ;AN000; switch month & day
mov promptDat_yr,cx ;AC000; put year into message control block
mov promptDat_moday,dx ;AC000; put month and day into message control block
mov dx,offset trangroup:promptDat_ptr ;AC000; set up message for output
invoke std_printf
;AD061; mov promptDat_yr,0 ;AC000; reset year, month and day
;AD061; mov promptDat_moday,0 ;AC000; pointers in control block
POP DI ;AC000; restore di,es
POP ES ;AC000;
return
;
; Do GET DATE system call and set up 3 character day of week in ARG_BUF
; for output. Date will be returned in CX,DX.
;
GetDate:
mov di,offset trangroup:arg_buf ;AC000; target for day of week
MOV AH,GET_DATE ;AC000; get current date
INT 21h ;AC000; Get date in CX:DX
CBW ;AC000;
push cx ;AN000; save date returned in
push dx ;AN000; CX:DX
MOV SI,AX
IFNDEF DBCS
SHL SI,1
ADD SI,AX ; SI=AX*3
ELSE
ifdef JAPAN ; MSKK01 07/14/89
shl si,1
shl si,1 ; SI=AX*4
endif
IFDEF TAIWAN
SHL SI,1
ADD SI,AX
SHL SI,1 ; SI=AX*6
ENDIF
ifdef KOREA
shl si,1
endif
ENDIF
mov cx,si ;AN000; save si
mov ax,weektab ;AN000; get message number of weektab
mov dh,util_msg_class ;AN000; this is a utility message
push di ;AN000; save argument buffer
invoke Tsysgetmsg ;AN000; get the address of the message
pop di ;AN000; retrieve argument buffer
add si,cx ;AC000; get day of week
IFNDEF DBCS
MOV CX,3
ELSE
ifdef JAPAN ; MSKK01 07/14/89
mov cx,4
endif
IFDEF TAIWAN
MOV CX,6
ENDIF
ifdef KOREA
mov cx,2 ; MSCH 90/9/6
endif
ENDIF
REP MOVSB
mov al,end_of_line_out ;AC000; terminate the string
stosb
pop dx ;AN000; get back date
pop cx ;AN000;
return
;g
;g This routine determines whether the character in AL is a
;g Yes or No character. On return, if AL=0, the character is
;g No, if AL=1, the character is Yes.
;g
assume ds:trangroup
char_in_xlat proc near
mov dl,al ;AC000; get character into DX
xor dh,dh ;AC000;
mov ax,(getextcntry SHL 8) + 35 ;AC000; Yes/No char call
int 21h ;AC000;
ret
char_in_xlat endp
TRANCODE ENDS
END