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.
 
 
 
 
 
 

817 lines
22 KiB

page ,132
title COMMAND Resident DATA
;/*
; * Microsoft Confidential
; * Copyright (C) Microsoft Corporation 1991
; * All Rights Reserved.
; */
;
; Revision History
; ================
; M003 SR 07/16/90 Added LoadHiFlg for LoadHigh support
;
; M004 SR 07/17/90 Transient is now moved to its final
; location at EndInit time by allocating
; the largest available block, moving
; the transient to the top of the block
; and then freeing up the block.
;
; M027 SR 9/20/90 Fixed bug #2827. EndInit was using
; INIT seg variables after INIT seg
; had been freed.
;
; M036 SR 11/1/90 Free up environment segment passed
; by Exec always.
;
.xlist
.xcref
include dossym.inc
include pdb.inc
include syscall.inc
include comsw.asm
include comseg.asm
include resmsg.equ
include comequ.asm
include cmdsvc.inc
.list
.cref
; Equates for initialization (from COMEQU)
;
; Bugbug: Toss these after putting ctrl-c handler in init module.
INITINIT equ 01h ; initialization in progress
INITSPECIAL equ 02h ; in initialization time/date routine
INITCTRLC equ 04h ; already in ^C handler
CODERES segment public byte
extrn Ext_Exec:near
extrn MsgRetriever:far
extrn TRemCheck:near
;SR;
; The stack has no right to be in the code segment. Moved it to DATARES
;
; bugbug: Why this odd stack size? And what should stack size be?
;; db (80h - 3) dup (?)
;;RStack label word
;; public RStack
CODERES ends
INIT segment
extrn ConProc:near
extrn Chuckenv:byte
extrn UsedEnv:word
extrn OldEnv:word
extrn EnvSiz:word
extrn TrnSize:word ; M004
INIT ends
TAIL segment
extrn TranStart :word
TAIL ends
TRANCODE segment public byte
extrn Command:near
TRANCODE ends
TRANSPACE segment
extrn TranSpaceEnd :byte
TRANSPACE ends
;SR;
; All the routines below are entry points into the stub from the transient.
;The stub will then transfer control to the appropriate routines in the
;resident code segment, wherever it is present.
;
DATARES segment
extrn Exec_Trap :near
extrn RemCheck_Trap :near
extrn MsgRetrv_Trap :near
extrn HeadFix_Trap :near
extrn Issue_Exec_Call :near
DATARES ends
DATARES segment public byte
assume cs:DATARES
Org 0
ZERO = $
;; Org 100h
;;ProgStart:
;; jmp RESGROUP:ConProc
public Abort_Char
public Append_Flag
public Append_State
public BadFatSubst
public Batch
public Batch_Abort
public BlkDevErrRw
public BlkDevErrSubst
public Call_Batch_Flag
public Call_Flag
public CDevAt
public CharDevErrSubst
public CharDevErrRw
public Com_Fcb1
public Com_Fcb2
public Com_Ptr
public ComDrv
public ComSpec
public ComSpec_End
public Crit_Err_Info
public Crit_Msg_Off
public Crit_Msg_Seg
public CritMsgPtrs
public DataResEnd
public Dbcs_Vector_Addr
public DevName
public DrvLet
public EchoFlag
public EnvirSeg
public ErrCd_24
public ErrType
public Exec_block
public ExecErrSubst
public Extcom
public ExtMsgEnd
public Fail_Char
public fFail
public ForFlag
public ForPtr
public FUCase_Addr
public Handle01
public IfFlag
public Ignore_Char
public In_Batch
public InitFlag
public InPipePtr
public Int_2e_Ret
public Int2fHandler
public Io_Save
public Io_Stderr
public LenMsgOrPathBuf
public Loading
public LTpa
public MemSiz
public MsgBuffer
public MsgPtrLists
public MySeg
public MySeg1
public MySeg2
public MySeg3
public NeedVol
public NeedVolSubst
public Nest
public Next_Batch
public No_Char
public NullFlag
public NUMEXTMSGS
public NUMPARSMSGS
public OldErrNo
public OldTerm
public OutPipePtr
public Parent
public ParsMsgPtrs
public PermCom
public Pipe1
;;; public Pipe1T
public Pipe2
;;; public Pipe2T
public PipeFiles
public PipeFlag
public PipePtr
public PipeStr
public KSwitchFlag
public PutBackComSpec
public PutBackDrv
public PutBackSubst
public RDirChar
public Re_Out_App
public Re_OutStr
public ResMsgEnd
public Res_Tpa
public RestDir
public ResTest
public RetCode
public Retry_Char
public RSwitChar
public SafePathBuffer ; MSKK01 07/14/89
public Save_Pdb
public SingleCom
public Sum
public Suppress
public Trans
public TranVarEnd
public TranVars
public TrnSeg
public TrnMvFlg
public VerVal
public VolName
public VolSer
public Yes_Char
public ResSize
public RStack
public OldDS
public LoadHiFlg ;For LoadHigh support ; M003
public SCS_Is_First
public SCS_REENTERED
public SCS_FIRSTCOM
public SCS_PAUSE
public SCS_CMDPROMPT
public SCS_DOSONLY
public SCS_PROMPT16
public SCS_FIRSTTSR
public RES_RDRINFO
public RES_BATSTATUS
extrn LodCom_Trap:near
extrn Alloc_error:near
;*** Message substitution blocks
BlkDevErrSubst label byte
BlkDevErrRw subst <STRING,> ; "reading" or "writing"
subst <CHAR,DATARES:DrvLet> ; block device drive letter
DrvLet db 'A' ; drive letter
CharDevErrSubst label byte
CharDevErrRw subst <STRING,> ; "reading" or "writing"
CharDevErrDev subst <STRING,DATARES:DevName> ; character device name
DevName db 8 dup (?),0 ; device name, asciiz
NeedVolSubst label byte
subst <STRING,DATARES:VolName> ; volume name
subst <HEX,DATARES:VolSer+2> ; hi word of serial #
subst <HEX,DATARES:VolSer> ; lo word of serial #
; NOTE: VolName and VolSer must be adjacent
VolName db 11 dup (?),0 ; volume name
VolSer dd 0 ; volume serial #
CDevAt db ?
BadFatSubst label byte
subst <CHAR,DATARES:DrvLet> ; drive letter
PutBackSubst label byte
PutBackComSpec subst <STRING,> ; comspec string
subst <CHAR,DATARES:PutBackDrv> ; drive to put it in
PutBackDrv db ' ' ; drive letter
ExecErrSubst subst <STRING,DATARES:SafePathBuffer>
NeedVol dd ? ; ptr to volume name from get ext err
ErrType db ? ; critical error message style, 0=old, 1=new
Int_2e_Ret dd ? ; magic command executer return address
Save_Pdb dw ?
Parent dw ?
OldTerm dd ?
ErrCd_24 dw ?
Handle01 dw ?
Loading db 0
Batch dw 0 ; assume no batch mode initially
;;;;SR;
;;;; This flag has been added for a gross hack introduced in batch processing.
;;;;We use it to indicate that this batch file has no CR-LF before EOF and that
;;;;we need to fake the CR-LF for the line to be properly processed
;;;;
;;;BatchEOF db 0
; Bugbug: ComSpec should be 64+3+12+1?
; What's this comspec_end about?
ComSpec db 64 dup (0)
ComSpec_End dw ?
Trans label dword
dw TRANGROUP:Command
TrnSeg dw ?
TrnMvFlg db 0 ; set if transient portion has been moved
In_Batch db 0 ; set if we are in batch processing mode
Batch_Abort db 0 ; set if user wants to abort from batch mode
ComDrv db ? ; drive spec to load autoexec and command
MemSiz dw ?
Sum dw ?
ExtCom db 1 ; for init, pretend just did an external
RetCode dw ?
Crit_Err_Info db ? ; hold critical error flags for r,i,f
; The echo flag needs to be pushed and popped around pipes and batch files.
; We implement this as a bit queue that is shr/shl for push and pop.
EchoFlag db 00000001b ; low bit true => echo commands
Suppress db 1 ; used for echo, 1=echo line
Io_Save dw ?
Io_Stderr db ?
RestDir db 0
PermCom db 0 ; true => permanent command
SingleCom dw 0 ; true => single command version
KSwitchFlag db 0
VerVal dw -1
fFail db 0 ; true => fail all int 24s
IfFlag db 0 ; true => IF statement in progress
ForFlag db 0 ; true => FOR statement in progress
ForPtr dw 0
Nest dw 0 ; nested batch file counter
Call_Flag db 0 ; no CALL (batch command) in progress
Call_Batch_Flag db 0
Next_Batch dw 0 ; address of next batch segment
NullFlag db 0 ; flag if no command on command line
FUCase_Addr db 5 dup (0) ; buffer for file ucase address
; Bugbug: don't need crit_msg_ anymore?
Crit_Msg_Off dw 0 ; saved critical error message offset
Crit_Msg_Seg dw 0 ; saved critical error message segment
Dbcs_Vector_Addr dw 0 ; DBCS vector offset
dw 0 ; DBCS vector segment
Append_State dw 0 ; current state of append
; (if Append_Flag is set)
Append_Flag db 0 ; set if append state is valid
SCS_PAUSE db 0 ; yst 4-5-93
Re_Out_App db 0
Re_OutStr db 64+3+13 dup (?)
SCS_Is_First db 1
SCS_REENTERED db 0
SCS_FIRSTCOM db 0
SCS_CMDPROMPT db 0 ; means on TSR/Shell out use command.com
SCS_DOSONLY db 0 ; means by default run all binaries
; when at command.com prompt. if 1 means
; allow only dos binaries.
SCS_PROMPT16 db 0
SCS_FIRSTTSR db 1
RES_RDRINFO DD 0
RES_BATSTATUS db 0
; We flag the state of COMMAND in order to correctly handle the ^Cs at
; various times. Here is the breakdown:
;
; INITINIT We are in the init code.
; INITSPECIAL We are in the date/time prompt
; INITCTRLC We are handling a ^C already.
;
; If we get a ^C in the initialization but not in the date/time prompt, we
; ignore the ^C. This is so the system calls work on nested commands.
;
; If we are in the date/time prompt at initialization, we stuff the user's
; input buffer with a CR to pretend an empty response.
;
; If we are already handling a ^C, we set the carry bit and return to the user
; (ourselves). We can then detect the carry set and properly retry the
; operation.
InitFlag db INITINIT
; Note: these two bytes are referenced as a word
PipeFlag db 0
PipeFiles db 0
;--- 2.x data for piping
;
; All the "_" are substituted later, the one before the : is substituted
; by the current drive, and the others by the CreateTemp call with the
; unique file name. Note that the first 0 is the first char of the pipe
; name. -MU
;
;--- Order-dependent, do not change
;;;Pipe1 db "_:/"
;;;Pipe1T db 0
;;; db "_______.___",0
;;;Pipe2 db "_:/"
;;;Pipe2T db 0
;;; db "_______.___",0
;SR
; Pipe1 & Pipe2 now need to store full-fledged pathnames
;
; Bugbug: can we find any way around maintaining these
; large buffers?
Pipe1 db 67+12 dup (?)
Pipe2 db 67+12 dup (?)
PipePtr dw ?
PipeStr db 129 dup (?)
EndPipe label byte ; marks end of buffers; M004
;SR;
; We can move our EndInit code into above buffers. This way, the code will
;automatically be discarded after init.
;
; M004; We overlap our code with the Pipe buffers located above by changing
; M004; the origin.
;
ORG Pipe1 ; M004
; Bugbug: really need a procedure header for EndInit, describing
; what it expects, what it does.
Public EndInit
EndInit:
push ds
push es ;save segments
push cs
pop ds
assume ds:RESGROUP
;
; M004; Save size of transient here before INIT segment is deallocated
;
mov dx,TrnSize ; M004
;M027
; These variables are also defined in the INIT segment and need to be saved
;before we resize
;
mov ax,OldEnv ; Old Environment seg ;M027
mov bx,EnvSiz ; Size of new environment ;M027
mov cx,UsedEnv ; Size of old environment ;M027
push ax ; Save all these values ;M027
push bx ; M027
push cx ; M027
; Bugbug: push ds, pop es here.
mov bx,ds
mov es,bx ;es = RESGROUP
;
;ResSize is the actual size to be retained -- only data for HIMEM COMMAND,
; code + data for low COMMAND
;
mov bx,ResSize ;Total size of resident
mov ah,SETBLOCK
int 21h ;Set block to resident size
;
;We check if this is for autoexec.bat (PermCom = 1). If so, we then
;allocate a new batch segment, copy the old one into new batchseg and free
;the old batchseg. Remember that the old batchseg was allocated on top of the
;transient and we will leave a big hole if TSRs are loaded by autoexec.bat
;
; Bugbug: also describe why we alloc & copy batch seg BEFORE environment.
cmp PermCom,1 ;permanent command.com?
jne adjust_env ;no, do not free batchseg
cmp Batch,0 ;was there a valid batchseg?
je adjust_env ;no, dont juggle
; NTVDM temp name of the batch file may be up to 63 bytes, plus NULL
; mov bx,((SIZE BatchSegment) + 15 + 1 + 0fh)/16 ;batchseg size
mov bx,((SIZE BatchSegment) + 64 + 1 + 0fh)/16 ;batchseg size
mov ah,ALLOC
int 21h
; Bugbug: I just had a thought. If DOS or SHARE or somebody leaves
; a hole, the batch segment COULD already be in the ideal place. We
; could be making it worse! We're second-guessing where memory
; allocations go, which might not be such a great idea. Is there
; a strategy, short of doing something even worse like diddling
; arena headers, where we can minimize the possibility of fragmentation
; under all cases? Hmm..
jc adjust_env ;no memory, use old batchseg
mov es,ax ;es = New batch segment
xor di,di
xor si,si
push ds
mov ds,Batch ;ds = Old Batch Segment
assume ds:nothing
mov cx,SIZE BatchSegment
; NTVDM temp name of the batch file may be up to 63 bytes, plus NULL
; add cx,16 ;for the filename
add cx,64
; Bugbug: 16? Shouldn't this be a common equate or something?
; It's sure be bad if we copied more bytes than the batch segment
; holds!
cld
rep movsb
pop ds
assume ds:RESGROUP
mov cx,es ;save new batch segment
mov es,Batch
mov ah,DEALLOC
int 21h ;free the old batch segment
; Bugbug: should we check for error?
mov Batch,cx ;store new batch segment address
adjust_env:
pop cx ;cx = size of old env ;M027
pop bx ;bx = size of new env needed ;M027
pop bp ;bp = old env seg ;M027
;
;Allocate the correct size for the environment
;
mov ah,ALLOC
int 21h ;get memory
jc init_env_err ;out of memory,signal error
; Bugbug: why not continue, leaving environment where it is?
mov EnvirSeg,ax ;Store new environment segment
mov ds:PDB_Environ,ax ;Put new env seg in PSP
mov es,ax ;es = address of allocated memory
assume es:nothing
cmp PermCom, 1
jne copy_old_env
;
; First get the size of 32bit env
;
push bx
mov bx, 0
CMDSVC SVC_GETINITENVIRONMENT
mov ax, bx
pop bx
cmp ax, 0 ;bx returns 0, use old environment
je copy_old_env
;
; now compute the new size
; [ax] = size of 32 bit env
;
add bx, ax
mov ah, DEALLOC ;free the block
int 21h
mov ah, ALLOC ;and get a new block(don't use realloc please)
int 21h
jc nomem_err
mov EnvirSeg,ax ;Store new environment segment
mov ds:PDB_Environ,ax ;Put new env seg in PSP
mov es,ax ;es = address of allocated memory
mov EnvSiz, bx ;new size
push bx
CMDSVC SVC_GETINITENVIRONMENT ;get new environment
pop ax
cmp bx, ax
jbe adjust_env_done
init_env_err:
jmp short nomem_err
copy_old_env:
;
;Copy the environment to the newly allocated segment
;
push ds
mov ds, bp ;ds = Old environment segment
assume ds:nothing
xor si,si
mov di,si ;Start transfer from 0
cld
rep movsb ;Do the copy
pop ds ;ds = RESGROUP
assume ds:RESGROUP
adjust_env_done:
;
;We have to free the old environment block if it was allocated by INIT
;
; Bugbug: is this only for the case when we were NOT passed an environment,
; or does it also apply to passed environments?
;M036
; Free up old env segment always because this is a copy passed by Exec and
;takes up memory that is never used
;
;M044
;Go back to the old strategy of not freeing the environment. Freeing it leaves
;a hole behind that Ventura does not like. Basically, Ventura gives strange
;errors if it gets a memory alloc that it is below its load segment. The
;freed environment creates a large enough hole for some of its allocs to fit
;in
;
cmp Chuckenv,0 ;has env been allocated by INIT?
jne no_free ;no, do not free it
mov es,bp
mov ah,DEALLOC
int 21h ;Free it
no_free:
;
; M004; Start of changes
;
;
; Move the transient now. We will allocate the biggest block available
; now and move the transient to the top of the block. We will then
; deallocate this block. When the resident starts executing, it will
; hopefully allocate this block again and find the transient intact.
;
MOV TrnMvFlg, 1 ; Indicate that transient has been moved
push es
mov si,offset ResGroup:TranStart
mov di,0
mov cx,offset TranGroup:TranSpaceEnd ;size to move
;
; Find the largest block available
;
mov bx,0ffffh
mov ah,ALLOC
int 21h
;
; dx = size of transient saved previously
;
cmp bx,dx ;enough memory?
jb nomem_err ;not enough memory for transient
mov ah,ALLOC
int 21h ;get the largest block
jc nomem_err ;something is really messed up
push ax ;save memory address
add ax,bx ;ax = top of my memory block
sub ax,dx ;less size of transient
mov TrnSeg,ax ;save transient segment
mov es,ax ;
pop ax ;restore our seg addr
;
; Everything is set for a move. We need to move in the reverse direction to
; make sure we dont overwrite ourselves while copying
;
add si,cx
dec si
add di,cx
dec di
std
rep movsb
cld
;
; Now we have to free up this block so that resident can get hold of it
;
mov es,ax
mov ah,DEALLOC
int 21h ;release the memory block
;
; M004; End of changes
;
mov InitFlag,FALSE ;indicate INIT is done
pop es
pop ds
; Bugbug: did we need to save & restore seg reg's during EndInit?
assume ds:nothing
jmp LodCom_Trap ;allocate transient
nomem_err:
;
;We call the error routine which will never return. It will either exit
;with an error ( if not the first COMMAND ) or just hang after an error
;message ( if first COMMAND )
;
jmp Alloc_error
public EndCodeInit ; M004
EndCodeInit label byte ; M004
;
; M004; Check if the EndInit code will fit into the Pipe buffers above.
; M004; If not, we signal an assembly error
;
IF2
IF ($ GT EndPipe)
.err
%out "ENDINIT CODE TOO BIG"
ENDIF
ENDIF
;
; M004; Set the origin back to what it was at the end of the buffers
;
ORG EndPipe ; M004
InPipePtr dw offset DATARES:Pipe1
OutPipePtr dw offset DATARES:Pipe2
Exec_Block label byte ; the data block for exec calls
EnvirSeg dw ?
Com_Ptr label dword
dw 80h ; point at unformatted parameters
dw ?
Com_Fcb1 label dword
dw 5Ch
dw ?
Com_Fcb2 label dword
dw 6Ch
dw ?
; variables passed to transient
TranVars label byte
dw offset DATARES:HeadFix_Trap
MySeg dw 0 ; put our own segment here
LTpa dw 0 ; will store tpa segment here
RSwitChar db "/"
RDirChar db "\"
dw offset DATARES:Issue_Exec_Call
MySeg1 dw ?
dw offset DATARES:RemCheck_Trap
MySeg2 dw 0
ResTest dw 0
Res_Tpa dw 0 ; original tpa (not rounded to 64k)
TranVarEnd label byte
OldErrNo dw ?
;* NOTE: MsgBuffer and SafePathBuffer use the same
; memory. MsgBuffer is only used while a command
; is being executed. SafePathBuffer is no longer
; needed, since it is used for unsuccessful program
; launches.
MsgBuffer label byte ; buffer for messages from disk
SafePathBuffer label byte ; resident pathname for EXEC
; db 128 dup (0) ; path + 'd:\' 'file.ext' + null
db EXECPATHLEN dup (0) ; MAX_PATH+13 ntvdm extended
LenMsgOrPathBuf equ $ - MsgBuffer
Int2fHandler dd ? ; address of next int 2f handler
ResMsgEnd dw 0 ; holds offset of msg end (end of resident)
;SR;
; The three vars below have been added for a pure COMMAND.COM
;
ResSize dw ?
;SR;
; Moved the stack here from the code segment
;
; bugbug: Why this odd stack size? And what should stack size be?
db (80h - 3) dup (?)
RStack label word
OldDS dw ? ;keeps old ds value when jumping to
;resident code segments
LoadHiFlg db 0 ;Flag set to 1 if UMB loading enabled ; M003
ifdef BETA3WARN
%out Take this out before we ship
public Beta3Warned
Beta3Warned db 0
endif
;*** MESSAGES
; and other translatable text
include comrmsg.inc ;M00
DATARES ends
end