Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

745 lines
21 KiB

page ,132
title COMMAND - resident code for COMMAND.COM
name COMMAND
;/*
; * Microsoft Confidential
; * Copyright (C) Microsoft Corporation 1991
; * All Rights Reserved.
; */
;*****************************************************************************
;
; MODULE: COMMAND.COM
;
; DESCRIPTIVE NAME: Default DOS command interpreter
;
; FUNCTION: This version of COMMAND is divided into three distinct
; parts. First is the resident portion, which includes
; handlers for interrupts 23H (Cntrl-C), 24H (fatal
; error), and 2EH (command line execute); it also has
; code to test and, if necessary, reload the transient
; portion. Following the resident is the init code, which
; is overwritten after use. Then comes the transient
; portion, which includes all command processing (whether
; internal or external). The transient portion loads at
; the end of physical memory, and it may be overlayed by
; programs that need as much memory as possible. When the
; resident portion of command regains control from a user
; program, a check sum is performed on the transient
; portion to see if it must be reloaded. Thus programs
; which do not need maximum memory will save the time
; required to reload COMMAND when they terminate.
;
; ENTRY POINT: PROGSTART
;
; INPUT: command line at offset 81H
;
; EXIT_NORMAL: No exit from root level command processor. Can exit
; from a secondary command processor via the EXIT
; internal command.
;
; EXIT_ERROR: Exit to prior command processor if possible, otherwise
; hang the system.
;
; INTERNAL REFERENCES:
;
; ROUTINES: See the COMMAND Subroutine Description Document
; (COMMAND.DOC)
;
; DATA AREAS: See the COMMAND Subroutine Description Document
; (COMMAND.DOC)
;
; EXTERNAL REFERENCES:
;
; ROUTINES: none
;
; DATA AREAS: none
;
;*****************************************************************************
;
; REVISION HISTORY
; ----------------
;
; DOS 1.00 to DOS 3.30
; --------------------------
; SEE REVISION LOG IN COPY.ASM ALSO
;
; REV 1.17
; 05/19/82 Fixed bug in BADEXE error (relocation error must return to
; resident since the EXELOAD may have overwritten the transient.
;
; REV 1.18
; 05/21/82 IBM version always looks on drive A
; MSVER always looks on default drive
;
; REV 1.19
; 06/03/82 Drive spec now entered in command line
; 06/07/82 Added VER command (print DOS version number) and VOL command
; (print volume label)
;
; REV 1.20
; 06/09/82 Prints "directory" after directories
; 06/13/82 MKDIR, CHDIR, PWD, RMDIR added
;
; REV 1.50
; Some code for new 2.0 DOS, sort of HACKey. Not enough time to
; do it right.
;
; REV 1.70
; EXEC used to fork off new processes
;
; REV 1.80
; C switch for single command execution
;
; REV 1.90
; Batch uses XENIX
;
; Rev 2.00
; Lots of neato stuff
; IBM 2.00 level
;
; Rev 2.01
; 'D' switch for date time suppression
;
; Rev 2.02
; Default userpath is NUL rather than BIN
; same as IBM
; COMMAND split into pieces
;
; Rev 2.10
; INTERNATIONAL SUPPORT
;
; Rev 2.50
; all the 2.x new stuff -MU
;
; Rev 3.30 (Ellen G)
; CALL internal command (TBATCH2.ASM)
; CHCP internal command (TCMD2B.ASM)
; INT 24H support of abort, retry, ignore, and fail prompt
; @ sign suppression of batch file line
; Replaceable environment value support in batch files
; INT 2FH calls for APPEND
; Lots of PTR fixes!
;
; Beyond 3.30 to forever (Ellen G)
; ----------------------
;
; A000 DOS 4.00 - Use SYSPARSE for internal commands
; Use Message Retriever services
; /MSG switch for resident extended error msg
; Convert to new capitalization support
; Better error recovery on CHCP command
; Code page file tag support
; TRUENAME internal command
; Extended screen line support
; /P switch on DEL/ERASE command
; Improved file redirection error recovery
; (removed) Improved batch file performance
; Unconditional DBCS support
; Volume serial number support
; (removed) COMMENT=?? support
;
; A001 PTM P20 Move system_cpage from TDATA to TSPC
;
; A002 PTM P74 Fix PRESCAN so that redirection symbols do not
; require delimiters.
;
; A003 PTM P5,P9,P111 Included in A000 development
;
; A004 PTM P86 Fix IF command to turn off piping before
; executing
;
; A005 DCR D17 If user specifies an extension on the command
; line search for that extension only.
;
; A006 DCR D15 New message for MkDir - "Directory already
; exists"
;
; A007 DCR D2 Change CTTY so that a write is done before XDUP
;
; A008 PTM P182 Change COPY to set default if invalid function
; returned from code page call.
;
; A009 PTM P179 Add CRLF to invalid disk change message
;
; A010 DCR D43 Allow APPEND to do a far call to SYSPARSE in
; transient COMMAND.
;
; A011 DCR D130 Change redirection to overwrite an EOF mark
; before appending to a file.
;
; A012 PTM P189 Fix redirection error recovery.
;
; A013 PTM P330 Change date format
;
; A014 PTM P455 Fix echo parsing
;
; A015 PTM P517 Fix DIR problem with * vs *.
;
; A016 PTM P354 Fix extended error message addressing
;
; A017 PTM P448 Fix appending to 0 length files
;
; A018 PTM P566,P3903 Fix parse error messages to print out parameter
; the parser fails on. Fail on duplicate switches.
;
; A019 PTM P542 Fix device name to be printed correctly during
; critical error
;
; A020 DCR D43 Set append state off while in DIR
;
; A021 PTM P709 Fix CTTY printing ascii characters.
;
; A022 DCR D209 Enhanced error recovery
;
; A023 PTM P911 Fix ANSI.SYS IOCTL structure.
;
; A024 PTM P899 Fix EXTOPEN open modes.
;
; A025 PTM P922 Fix messages and optimize PARSE switches
;
; A026 DCR D191 Change redirection error recovery support.
;
; A027 PTM P991 Fix so that KAUTOBAT & AUTOEXEC are terminated
; with a carriage return.
;
; A028 PTM P1076 Print a blank line before printing invalid
; date and invalid time messages.
;
; A029 PTM P1084 Eliminate calls to parse_check_eol in DATE
; and TIME.
;
; A030 DCR D201 New extended attribute format.
;
; A031 PTM P1149 Fix DATE/TIME add blank before prompt.
;
; A032 PTM P931 Fix =ON, =OFF for BREAK, VERIFY, ECHO
;
; A033 PTM P1298 Fix problem with system crashes on ECHO >""
;
; A034 PTM P1387 Fix COPY D:fname+,, to work
;
; A035 PTM P1407 Fix so that >> (appending) to a device does
; do a read to determine eof.
;
; A036 PTM P1406 Use 69h instead of 44h to get volume serial
; so that ASSIGN works correctly.
;
; A037 PTM P1335 Fix COMMAND /C with FOR
;
; A038 PTM P1635 Fix COPY so that it doesn't accept /V /V
;
; A039 DCR D284 Change invalid code page tag from -1 to 0.
;
; A040 PTM P1787 Fix redirection to cause error when no file is
; specified.
;
; A041 PTM P1705 Close redirected files after internal APPEND
; executes.
;
; A042 PTM P1276 Fix problem of APPEND paths changes in batch
; files causing loss of batch file.
;
; A043 PTM P2208 Make sure redirection is not set up twice for
; CALL'ed batch files.
;
; A044 PTM P2315 Set switch on PARSE so that 0ah is not used
; as an end of line character
;
; A045 PTM P2560 Make sure we don't lose parse, critical error,
; and extended message pointers when we EXIT if
; COMMAND /P is the top level process.
;
; A046 PTM P2690 Change COPY message "fn File not found" to
; "File not found - fn"
;
; A047 PTM P2819 Fix transient reload prompt message
;
; A048 PTM P2824 Fix COPY path to be upper cased. This was broken
; when DBCS code was added.
;
; A049 PTM P2891 Fix PATH so that it doesn't accept extra characters
; on line.
;
; A050 PTM P3030 Fix TYPE to work properly on files > 64K
;
; A051 PTM P3011 Fix DIR header to be compatible with prior releases.
;
; A052 PTM P3063,P3228 Fix COPY message for invalid filename on target.
;
; A053 PTM P2865 Fix DIR to work in 40 column mode.
;
; A054 PTM P3407 Code reduction and critical error on single line
; PTM P3672 (Change to single parser exported under P3407)
;
; A055 PTM P3282 Reset message service variables in INT 23h to fix
; problems with breaking out of INT 24h
;
; A056 PTM P3389 Fix problem of environment overlaying transient.
;
; A057 PTM P3384 Fix COMMAND /C so that it works if there is no space
; before the "string". EX: COMMAND /CDIR
;
; A058 PTM P3493 Fix DBCS so that CPARSE eats second character of
; DBCS switch.
;
; A059 PTM P3394 Change the TIME command to right align the display of
; the time.
;
; A060 PTM P3672 Code reduction - change PARSE and EXTENDED ERROR
; messages to be disk based. Only keep them if /MSG
; is used.
;
; A061 PTM P3928 Fix so that transient doesn't reload when breaking
; out of internal commands, due to substitution blocks
; not being reset.
;
; A062 PTM P4079 Fix segment override for fetching address of environment
; of parent copy of COMMAND when no COMSPEC exists in
; secondary copy of environment. Change default slash in
; default comspec string to backslash.
;
; A063 PTM P4140 REDIRECTOR and IFSFUNC changed interface for getting
; text for critical error messages.
;
; A064 PTM P4934 Multiplex number for ANSI.SYS changed due to conflict
; 5/20/88 with Microsoft product already shipped.
;
; A065 PTM P4935 Multiplex number for SHELL changed due to conflict
; 5/20/88 with Microsoft product already shipped.
;
; A066 PTM P4961 DIR /W /P scrolled first line off the screen in some
; 5/24/88 cases; where the listing would barely fit without the
; header and space remaining.
;
; A067 PTM P5011 For /E: values of 993 to 1024 the COMSPEC was getting
; 6/6/88 trashed. Turns out that the SETBLOCK for the new
; environment was putting a "Z block" marker in the old
; environment. The fix is to move to the old environment
; to the new environment before doing the SETBLOCK.
;
; A068 PTM P5568 IR79754 APPEND /x:on not working properly with DIR/VOL
; 09/19/88 because the check for APPEND needed to be performed
; before the DIR's findfirst.
;
; A069 PTM P5726 IR80540 COMSPEC_flag not properly initialized and
; 10/30/88 executed. Causing AUSTIN problem testing LAN/DW4 re-
; loading trans w/new comspec with no user change comspec.
;
; A070 PTM P5734 IR80484 Batch file causes sys workspace to be corrupted.
; 11/05/88 Expansion of environment variables into batch line of
; 128 chars was not being counted and "%" which should be
; ignored were being counted.
;
; A071 PTM P5854 IR82061 Invalid COMMAND.COM when Word Perfect, Prompt
; 03/02/89 used. Comspec_flag was not in protected data file be-
; ing included in checksum and was being overwritten by
; WP. Moved var from Tspc to Tdata so Trans would reload.
; Also removed fix A069 (because flag now protected).
;
; C001 VERSION 4.1 Add new internal command - SERVICE - to display the DOS
; 07/25/89 version and CSD version in U.S. date format. Files
; changed - TRANMSG,.SKL,COMMAND1,TDATA,TCMD2A,USA.MSG
;
;***********************************************************************************
;
; Revision History
; ================
;
; M021 SR 08/23/90 Fixed Ctrl-C handler to handle Ctrl-C
; at init time (date/time prompt)
;
.xcref
.xlist
include dossym.inc ; basic DOS symbol set
include syscall.inc ; DOS function names
include comsw.asm ; build version info
include comequ.asm ; common command.com symbols
include resmsg.equ ; resident message names
include comseg.asm ;segment ordering
.list
.cref
CODERES segment public byte
CODERES ends
DATARES segment public byte
extrn AccDen:byte
extrn Batch:word
extrn EchoFlag:byte
extrn ExeBad:byte
extrn ExecEMes:byte
extrn ExecErrSubst:byte
extrn ExtCom:byte
extrn ForFlag:byte
extrn IfFlag:byte
extrn InitFlag:BYTE
extrn Nest:word
extrn PipeFlag:byte
extrn RBadNam:byte
extrn RetCode:word
extrn SingleCom:word
extrn TooBig:byte
extrn OldDS:word
EXTRN SCS_REENTERED:BYTE
EXTRN SCS_CMDPROMPT:BYTE
DATARES ends
INIT segment public para
extrn ConProc:near
extrn Init_Contc_SpecialCase:near
INIT ends
include envdata.asm
Prompt32 equ 1
;*** START OF RESIDENT PORTION
CODERES segment public byte
public Ext_Exec
public ContC
public Exec_Wait
public Exec_Ret
assume cs:CODERES,ds:NOTHING,es:NOTHING,ss:NOTHING
extrn LodCom:near
extrn LodCom1:near
org 0
Zero = $
;; org 80h - 1
;;ResCom label byte
;; public ResCom
;; org 100h
public StartCode
StartCode:
;; jmp RESGROUP:ConProc
;*** EXEC error handling
;
; COMMAND has issued an EXEC system call and it has returned an error.
; We examine the error code and select an appropriate message.
; Bugbug: optimize reg usage in following code? Careful of DX!
; Condense the error scan?
; RBADNAM is checked by transient, no need here?
; Move below Ext_Exec.
Exec_Err:
;SR;
; ds,es are setup when the transient jumps to Ext_Exec. So segment regs are
;in order here
assume ds:DATARES,es:DATARES
; Bugbug: can we use byte compares here?
; Might be able to use byte msg#s, too.
; Store errors in a 3 or 4 byte table. Msg #s in another.
; Speed not high priority here.
; Move this to transient.
mov bx,offset DATARES:RBadNam
cmp al,ERROR_FILE_NOT_FOUND
je GotExecEMes ; bad command
mov bx,offset DATARES:TooBig
cmp al,ERROR_NOT_ENOUGH_MEMORY
je GotExecEMes ; file not found
mov bx,offset DATARES:ExeBad
cmp al,ERROR_BAD_FORMAT
je GotExecEMes ; bad exe file
mov bx,offset DATARES:AccDen
cmp al,ERROR_ACCESS_DENIED
je GotExecEMes ; access denied
Default_Message:
mov bx,offset DATARES:ExecEMes ; default message
mov si,offset DATARES:ExecErrSubst ; get address of subst block
GotExecEMes:
mov dx,bx ; DX = ptr to msg
;; williamh: no reason of doing this. When command.com receives a command,
;; it means the VDM process has been created successfully and there
;; is no way for the parent process to know that we are not able
;; to launch the program and therefore, it won't display any error
;; message for us.
;; cmp byte ptr [scs_reentered],1
;; jne NoErrMsg
;; cmp byte ptr [scs_cmdprompt],Prompt32
;; je NoErrMsg
invoke RPrint
NoErrMsg:
jmp short NoExec
;*** EXEC call
;
; The transient has set up everything for an EXEC system call.
; For cleanliness, we issue the EXEC here in the resident
; so that we may be able to recover cleanly upon success.
;
; CS,DS,ES,SS = DATARES seg addr
Ext_Exec:
;SR;
; The words put on the stack by the stub will be popped off when we finally
;jump to LodCom ( by LodCom).
;
;; int 21h ; do the exec
Exec_Ret:
jc Exec_Err ; exec failed
; The exec has completed. Retrieve the exit code.
Exec_Wait:
mov ah,WAITPROCESS ; get errorlevel
int 21h ; get the return code
mov RetCode,ax
; See if we can reload the transient. The external command
; may have overwritten part of the transient.
NoExec:
;SR;
; ds = es = ss = DATARES when we jump to LodCom
;
jmp LodCom
;*** Int 23 (ctrl-c) handler
;
; This is the default system INT 23 handler. All processes
; (including COMMAND) get it by default. There are some
; games that are played: We ignore ^C during most of the
; INIT code. This is because we may perform an ALLOC and
; diddle the header! Also, if we are prompting for date/time
; in the init code, we are to treat ^C as empty responses.
; Bugbug: put init ctrl-c handling in init module.
;SR;
; The stub has pushed the previous ds and DATARES onto the stack. We get
;both these values off the stack now
;
ContC proc far
assume cs:CODERES,ds:NOTHING,es:NOTHING,ss:NOTHING
pop ds ;ds = DATARES
assume ds:DATARES
; pop OldDS ;OldDS = old ds
test InitFlag,INITINIT ; in initialization?
jz NotAtInit ; no
test InitFlag,INITSPECIAL ; doing special stuff?
jz CmdIRet ; no, ignore ^C
pop ds ; restore before jumping; M021
jmp RESGROUP:Init_ContC_SpecialCase ; Yes, go handle it
CmdIret:
;SR;
; Restore ds to its previous value
;
; mov ds,OLdDS ;
pop ds
iret ; yes, ignore the ^C
NotAtInit:
test InitFlag,INITCTRLC ; are we already in a ^C?
jz NotInit ; nope too.
;* We are interrupting ourselves in this ^C handler. We need
; to set carry and return to the user sans flags only if the
; system call was a 1-12 one. Otherwise, we ignore the ^C.
cmp ah,1
jb CmdIRet
cmp ah,12
ja CmdIRet
pop ds ;restore ds to old value
add sp,6 ; remove int frame
stc
; mov ds,OldDS ;restore ds to its old value
ret 2 ; remove those flags...
NotInit:
;* We have now received a ^C for some process (maybe ourselves
; but not at INIT).
;
; Note that we are running on the user's stack!!! Bad news if
; any of the system calls below go and issue another INT
; 24... Massive stack overflow! Another bad point is that
; SavHand will save an already saved handle, thus losing a
; possible redirection...
;
; All we need to do is set the flag to indicate nested ^C.
; The above code will correctly flag the ^C diring the
; message output and prompting while ignoring the ^C the rest
; of the time.
;
; Clean up: flush disk. If we are in the middle of a batch
; file, we ask if he wants to terminate it. If he does, then
; we turn off all internal flags and let the DOS abort.
or InitFlag,INITCTRLC ; nested ^c is on
sti
;; push cs ; el yucko! change the user's ds!!
;; pop ds
;; assume ds:RESGROUP
pop ax ;discard the old ds value
mov ax,SingleCom
or ax,ax
jnz NoReset
push ax
mov ah,DISK_RESET
int 21h ; reset disks in case files were open
pop ax
NoReset:
; In the generalized version of FOR, PIPE and BATCH, we would
; walk the entire active list and free each segment. Here,
; we just free the single batch segment.
test Batch,-1
jz ContCTerm
or ax,ax
jnz ContCTerm
invoke SavHand
invoke AskEnd ; ask if user wants to end batch
; If the carry flag is clear, we do NOT free up the batch file
jnc ContBatch
mov cl,EchoFlag ; get current echo flag
push bx
ClearBatch:
mov es,Batch ; get batch segment
mov di,BatFile ; get offset of batch file name
; Bugbug: verify the following shell interface still works
;; mov ax,MULT_SHELL_BRK ; does the SHELL want this terminated?
;; int 2Fh ; call the SHELL
;; cmp al,SHELL_ACTION ; does shell want this batch?
;; je Shell_Bat_Cont ; yes - keep it
mov bx,es:BatForPtr ; get old FOR segment
cmp bx,0 ; is a FOR in progress
je no_bat_for ; no - don't deallocate
push es ;
mov es,bx ; yes - free it up...
mov ah,DEALLOC ;
int 21h ;
pop es ; restore to batch segment
No_Bat_For:
mov cl,es:BatEchoFlag ; get old echo flag
mov bx,es:BatLast ; get old batch segment
mov ah,DEALLOC ; free it up...
int 21h
mov Batch,bx ; get ready to deallocate next batch
dec nest ; is there another batch file?
jnz ClearBatch ; keep going until no batch file
; We are terminating a batch file; restore the echo status
Shell_Bat_Cont: ; continue batch for SHELL
pop bx
mov EchoFlag,cl ; reset echo status
mov PipeFlag,0 ; turn off pipeflag
ContBatch:
invoke Crlf ; print out crlf before returning
invoke RestHand
; Yes, we are terminating. Turn off flags and allow the DOS to abort.
ContCTerm:
xor ax,ax ; indicate no read
mov bp,ax
; The following resetting of the state flags is good for the
; generalized batch processing.
mov IfFlag,al ; turn off iffing
mov ForFlag,al ; turn off for processing
call ResPipeOff
cmp SingleCom,ax ; see if we need to set singlecom
jz NoSetSing
mov SingleCom,-1 ; cause termination on
; pipe, batch, for
NoSetSing:
; If we are doing an internal command, go through the reload process.
; If we are doing an external, let DOS abort the process.
; In both cases, we are now done with the ^C processing.
and InitFlag,not INITCTRLC
cmp ExtCom,al
jnz DoDAb ; internal ^c
jmp LodCom1
DoDAb:
stc ; tell dos to abort
;SR;
;We dont need to restore ds here because we are forcing DOS to do an abort
;by setting carry and leaving flags on the stack
;
ret ; Leave flags on stack
ContC endp
;SR;
; ds = DATARES on entry. This routine is called from DskErr and LodCom1 and
;both have ds = DATARES
;
ResPipeOff:
public ResPipeOff
assume ds:DATARES,es:NOTHING
savereg <ax>
xor ax,ax
xchg PipeFlag,al
or al,al
jz NoPipePop
shr EchoFlag,1
NoPipePop:
restorereg <ax>
return
CODERES ends
end