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.
 
 
 
 
 
 

667 lines
14 KiB

page ,132
; SCCSID = @(#)tenv.asm 4.2 85/08/16
; SCCSID = @(#)tenv.asm 4.2 85/08/16
TITLE Part6 COMMAND Transient routines.
;/*
; * Microsoft Confidential
; * Copyright (C) Microsoft Corporation 1991
; * All Rights Reserved.
; */
; Environment utilities and misc. routines
;
; Revision History
; ================
;
; M024 SR 9/5/90 Zero out comspec_flag to fix bug
; #710 about comspec getting trashed.
;
INCLUDE comsw.asm
.xlist
.xcref
include dossym.inc
include syscall.inc
include arena.inc
include comseg.asm
include comequ.asm
include doscntry.inc ;an000;
include resmsg.equ
.list
.cref
DATARES SEGMENT PUBLIC BYTE ;AC000;
EXTRN comdrv:byte
EXTRN comspec_end:word
EXTRN dbcs_vector_addr:dword ;AN000;
EXTRN ENVIRSEG:WORD
EXTRN fucase_addr:word ;AC000;
EXTRN PutBackDrv:byte
EXTRN PutBackComSpec:byte
EXTRN RESTDIR:BYTE
DATARES ENDS
TRANDATA SEGMENT PUBLIC BYTE ;AC000;
EXTRN arg_buf_ptr:word
EXTRN comspec:byte
EXTRN comspec_flag:byte
EXTRN comspecstr:byte
EXTRN ENVERR_PTR:WORD
EXTRN PATH_TEXT:byte
EXTRN PROMPT_TEXT:byte
EXTRN SYNTMES_PTR:WORD
TRANDATA ENDS
TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
EXTRN Arg_Buf:BYTE
EXTRN RESSEG:WORD
EXTRN USERDIR1:BYTE
TRANSPACE ENDS
TRANCODE SEGMENT PUBLIC byte
ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
EXTRN cerror:near
PUBLIC add_name_to_environment
PUBLIC add_prompt
PUBLIC delete_path
PUBLIC find_name_in_environment
PUBLIC find_path
PUBLIC find_prompt
PUBLIC move_name
PUBLIC restudir
PUBLIC restudir1
PUBLIC scan_double_null
PUBLIC scasb2
PUBLIC store_char
PUBLIC Testkanj ;AN000; 3/3/KK
PUBLIC upconv
PUBLIC GETENVSIZ
BREAK <Environment utilities>
ASSUME DS:TRANGROUP
break Prompt command
assume ds:trangroup,es:trangroup
ADD_PROMPT:
CALL DELETE_PROMPT ; DELETE ANY EXISTING PROMPT
CALL SCAN_DOUBLE_NULL
ADD_PROMPT2:
PUSH SI
CALL GETARG
POP SI
retz ; PRE SCAN FOR ARGUMENTS
CALL MOVE_NAME ; MOVE IN NAME
CALL GETARG
PUSH SI
JMP SHORT ADD_NAME
break The SET command
assume ds:trangroup,es:trangroup
;
; Input: DS:SI points to a CR terminated string
; Output: carry flag is set if no room
; otherwise name is added to environment
;
DISP_ENVj:
jmp DISP_ENV
ADD_NAME_TO_ENVIRONMENT:
CALL GETARG
JZ DISP_ENVj
;
; check if line contains exactly one equals sign
;
XOR BX,BX ;= COUNT IS 0
PUSH SI ;SAVE POINTER TO BEGINNING OF LINE
EQLP:
LODSB ;GET A CHAR
CMP AL,13 ;IF CR WE'RE ALL DONE
JZ QUEQ
CMP AL,'=' ;LOOK FOR = SIGN
JNZ EQLP ;NOT THERE, GET NEXT CHAR
INC BL ;OTHERWISE INCREMENT EQ COUNT
CMP BYTE PTR [SI],13 ;LOOK FOR CR FOLLOWING = SIGN
JNZ EQLP
INC BH ;SET BH=1 MEANS NO PARAMETERS
JMP EQLP ;AND LOOK FOR MORE
QUEQ:
POP SI ;RESTORE BEGINNING OF LINE
DEC BL ;ZERO FLAG MEANS ONLY ONE EQ
JZ ONEQ ;GOOD LINE
MOV DX,OFFSET TRANGROUP:SYNTMES_ptr
JMP CERROR
ONEQ:
PUSH BX
CALL DELETE_NAME_IN_ENVIRONMENT
POP BX
DEC BH
retz
CALL SCAN_DOUBLE_NULL
mov bx,di ; Save ptr to beginning of env var name
CALL MOVE_NAME
push si
xchg bx,di ; Switch ptrs to beginning and end of
; env var name
;
; We want to special-case COMSPEC. This is to reduce the amount of code
; necessary in the resident for re-reading the transient. Let's look for
; COMSPEC=
;
mov comspec_flag,0 ; clear flag ; M024
mov si,offset trangroup:comspecstr ; Load ptr to string "COMSPEC"
mov cx,4 ; If the new env var is comspec, set
repz cmpsw ; the comspec_flag
;
; Zero set => exact match
;
jnz not_comspec
inc comspec_flag ; comspec is changing ; M024
not_comspec:
mov di,bx ; Load ptr to end of env var name
ADD_NAME: ; Add the value of the new env var
pop si ; to the environment.
push si
add_name1:
LODSB
CMP AL,13
jz add_name_ret
CALL STORE_CHAR
JMP ADD_NAME1
add_name_ret:
pop si
cmp comspec_flag,0 ; If the new env var is comspec,
retz ; copy the value into the
;
; We have changed the COMSPEC variable. We need to update the resident
; pieces necessary to reread in the info. First, skip all delimiters
;
invoke ScanOff
mov es,[resseg] ; comspec var in the resident
assume es:resgroup
;
; Make sure that the printer knows where the beginning of the string is
;
mov di,offset resgroup:comspec
mov bx,di
;
; Generate drive letter for display
;
xor ax,ax ;g assume no drive first
mov comdrv,al ;g
push ax ;AN000; 3/3/KK
mov al,[si] ;AN000; 3/3/KK
call testkanj ;AN000; 3/3/KK
pop ax ;AN000; 3/3/KK
jnz GotDrive
cmp byte ptr [si+1],':' ; drive specified?
jnz GotDrive
mov al,[si] ; get his specified drive
call UpConv ; convert to uppercase
sub al,'A' ; convert to 0-based
add di,2
inc al ; convert to 1-based number
mov comdrv,al
;
; Stick the drive letter in the prompt message. Nothing special needs to be
; done here..
;
add al,'A'-1
GotDrive: ;g
mov PutBackComSpec.SubstPtr,di ;g point to beginning of name after drive
mov es:PutBackDrv,al
;
; Copy chars until delim
;
mov di,bx
copy_comspec:
lodsb
invoke Delim
jz CopyDone
cmp al,13
jz CopyDone
stosb
jmp short copy_comspec
CopyDone:
xor al,al ; Null terminate the string and quit
stosb
mov comspec_flag,0
dec di
mov comspec_end,di
ret
DISP_ENV:
MOV DS,[RESSEG]
ASSUME DS:RESGROUP
MOV DS,[ENVIRSEG]
ASSUME DS:NOTHING
XOR SI,SI
PENVLP:
CMP BYTE PTR [SI],0
retz
mov di,offset trangroup:arg_buf
PENVLP2:
LODSB
stosb
OR AL,AL
JNZ PENVLP2
mov dx,offset trangroup:arg_buf_ptr
push ds
push es
pop ds
invoke printf_crlf
pop ds
JMP PENVLP
ASSUME DS:TRANGROUP
DELETE_PATH:
MOV SI,OFFSET TRANGROUP:PATH_TEXT
JMP SHORT DELETE_NAME_IN_environment
DELETE_PROMPT:
MOV SI,OFFSET TRANGROUP:PROMPT_TEXT
DELETE_NAME_IN_environment:
;
; Input: DS:SI points to a "=" terminated string
; Output: carry flag is set if name not found
; otherwise name is deleted
;
PUSH SI
PUSH DS
CALL FIND ; ES:DI POINTS TO NAME
JC DEL1
MOV SI,DI ; SAVE IT
CALL SCASB2 ; SCAN FOR THE NUL
XCHG SI,DI
;SR;
; If we have only one env string, then the double null is lost when the last
;string is deleted and we have an invalid empty environment with only a
;single null. To avoid this, we will look for the double null case and then
;move an extra null char.
; Bugbug: The only possible problem is that the last pathstring
;will be followed by a triple null. Is this really a problem?
;
cmp byte ptr es:[si],0 ;null char?
jnz not_dnull ;no, we are at a double null
dec si ;point at the double null
not_dnull:
CALL GETENVSIZ
SUB CX,SI
PUSH ES
POP DS ; ES:DI POINTS TO NAME, DS:SI POINTS TO NEXT NAME
REP MOVSB ; DELETE THE NAME
DEL1:
POP DS
POP SI
return
FIND_PATH:
MOV SI,OFFSET TRANGROUP:PATH_TEXT
JMP SHORT FIND_NAME_IN_environment
FIND_PROMPT:
MOV SI,OFFSET TRANGROUP:PROMPT_TEXT
FIND_NAME_IN_environment:
;
; Input: DS:SI points to a "=" terminated string
; Output: ES:DI points to the arguments in the environment
; zero is set if name not found
; carry flag is set if name not valid format
;
CALL FIND ; FIND THE NAME
retc ; CARRY MEANS NOT FOUND
JMP SCASB1 ; SCAN FOR = SIGN
;
; On return of FIND1, ES:DI points to beginning of name
;
FIND:
CLD
CALL COUNT0 ; CX = LENGTH OF NAME
MOV ES,[RESSEG]
ASSUME ES:RESGROUP
MOV ES,[ENVIRSEG]
ASSUME ES:NOTHING
XOR DI,DI
FIND1:
PUSH CX
PUSH SI
PUSH DI
FIND11:
LODSB
CALL TESTKANJ
JZ NOTKANJ3
DEC SI
LODSW
INC DI
INC DI
CMP AX,ES:[DI-2]
JNZ FIND12
DEC CX
LOOP FIND11
JMP SHORT FIND12
NOTKANJ3:
CALL UPCONV
INC DI
CMP AL,ES:[DI-1]
JNZ FIND12
LOOP FIND11
FIND12:
POP DI
POP SI
POP CX
retz
PUSH CX
CALL SCASB2 ; SCAN FOR A NUL
POP CX
CMP BYTE PTR ES:[DI],0
JNZ FIND1
STC ; INDICATE NOT FOUND
return
COUNT0:
PUSH DS
POP ES
MOV DI,SI
COUNT1:
PUSH DI ; COUNT NUMBER OF CHARS UNTIL "="
CALL SCASB1
JMP SHORT COUNTX
COUNT2:
PUSH DI ; COUNT NUMBER OF CHARS UNTIL NUL
CALL SCASB2
COUNTX:
POP CX
SUB DI,CX
XCHG DI,CX
return
MOVE_NAME:
CMP BYTE PTR DS:[SI],13
retz
LODSB
;;;; IFDEF DBCS 3/3/KK
CALL TESTKANJ
JZ NOTKANJ1
CALL STORE_CHAR
LODSB
CALL STORE_CHAR
JMP SHORT MOVE_NAME
NOTKANJ1:
;;;; ENDIF 3/3/KK
CALL UPCONV
CALL STORE_CHAR
CMP AL,'='
JNZ MOVE_NAME
return
GETARG:
MOV SI,80H
LODSB
OR AL,AL
retz
invoke SCANOFF
CMP AL,13
return
;
; Point ES:DI to the final NULL string. Note that in an empty environment,
; there is NO double NULL, merely a string that is empty.
;
SCAN_DOUBLE_NULL:
MOV ES,[RESSEG]
ASSUME ES:RESGROUP
MOV ES,[ENVIRSEG]
ASSUME ES:NOTHING
XOR DI,DI
;
; Top cycle-point. If the string here is empty, then we are done
;
SDN1:
cmp byte ptr es:[di],0 ; nul string?
retz ; yep, all done
CALL SCASB2
JMP SDN1
SCASB1:
MOV AL,'=' ; SCAN FOR AN =
JMP SHORT SCASBX
SCASB2:
XOR AL,AL ; SCAN FOR A NUL
SCASBX:
MOV CX,1000H
REPNZ SCASB
return
;Bugbug: This is Kanji stuff - put it in conditionals
TESTKANJ:
push ds ;AN000; 3/3/KK
push si ;AN000; 3/3/KK
push ax ;AN000; 3/3/KK
mov ds,cs:[resseg] ;AN000; Get resident segment
assume ds:resgroup ;AN000;
lds si,dbcs_vector_addr ;AN000; get DBCS vector
ktlop: ;AN000; 3/3/KK
cmp word ptr ds:[si],0 ;AN000; end of Table 3/3/KK
je notlead ;AN000; 3/3/KK
pop ax ;AN000; 3/3/KK
push ax ;AN000; 3/3/KK
cmp al, byte ptr ds:[si] ;AN000; 3/3/KK
jb notlead ;AN000; 3/3/KK
inc si ;AN000; 3/3/KK
cmp al, byte ptr ds:[si] ;AN000; 3/3/KK
jbe islead ;AN000; 3/3/KK
inc si ;AN000; 3/3/KK
jmp short ktlop ;AN000; try another range ; 3/3/KK
Notlead: ;AN000; 3/3/KK
xor ax,ax ;AN000; set zero 3/3/KK
jmp short ktret ;AN000; 3/3/KK
Islead: ;AN000; 3/3/KK
xor ax,ax ;AN000; reset zero 3/3/KK
inc ax ;AN000; 3/3/KK
ktret: ;AN000; 3/3/KK
pop ax ;AN000; 3/3/KK
pop si ;AN000; 3/3/KK
pop ds ;AN000; 3/3/KK
return ;AN000; 3/3/KK
;------------------------------------- ;3/3/KK
; ****************************************************************
; *
; * ROUTINE: UPCONV (ADDED BY EMG 4.00)
; *
; * FUNCTION: This routine returns the upper case equivalent of
; * the character in AL from the file upper case table
; * in DOS if character if above ascii 128, else
; * subtracts 20H if between "a" and "z".
; *
; * INPUT: AL char to be upper cased
; * FUCASE_ADDR set to the file upper case table
; *
; * OUTPUT: AL upper cased character
; *
; ****************************************************************
assume ds:trangroup ;AN000;
upconv proc near ;AN000;
cmp al,80h ;AN000; see if char is > ascii 128
jb oth_fucase ;AN000; no - upper case math
sub al,80h ;AN000; only upper 128 chars in table
push ds ;AN000;
push bx ;AN000;
mov ds,[resseg] ;AN000; get resident data segment
assume ds:resgroup ;AN000;
lds bx,dword ptr fucase_addr+1 ;AN000; get table address
add bx,2 ;AN000; skip over first word
xlat ds:byte ptr [bx] ;AN000; convert to upper case
pop bx ;AN000;
pop ds ;AN000;
assume ds:trangroup ;AN000;
jmp short upconv_end ;AN000; we finished - exit
oth_fucase: ;AN000;
cmp al,small_a ;AC000; if between "a" and "z",
jb upconv_end ;AC000; subtract 20h to get
cmp al,small_z ;AC000; upper case equivalent.
ja upconv_end ;AC000;
sub al,20h ;AC000; Change lower-case to upper
upconv_end: ;AN000;
ret
upconv endp ;AN000;
;
; STORE A CHAR IN environment, GROWING IT IF NECESSARY
;
STORE_CHAR:
PUSH CX
PUSH BX
PUSH ES ;AN056;
PUSH DS ;AN056; Save local DS
MOV DS,[RESSEG] ;AN056; Get resident segment
ASSUME DS:RESGROUP ;AN056;
MOV ES,[ENVIRSEG] ;AN056; Get environment segment
ASSUME ES:NOTHING ;AN056;
POP DS ;AN056; Get local segment back
ASSUME DS:TRANGROUP ;AN056;
CALL GETENVSIZ
MOV BX,CX
SUB BX,2 ; SAVE ROOM FOR DOUBLE NULL
CMP DI,BX
JB STORE1
PUSH AX
PUSH CX
PUSH BX ; Save Size of environment
invoke FREE_TPA
POP BX
ADD BX,2 ; Recover true environment size
CMP BX, 8000H ; Don't let environment grow > 32K
JB ENVSIZ_OK
BAD_ENV_SIZE: ;AN056;
STC
JMP SHORT ENVNOSET
ENVSIZ_OK:
MOV CL,4
SHR BX,CL ; Convert back to paragraphs
INC BX ; Try to grow environment by one para
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 BAD_ENV_SIZE ;AN056; Yes - don't do it!!!
MOV AH,SETBLOCK
INT 21h
ENVNOSET:
PUSHF
PUSH ES
MOV ES,[RESSEG]
invoke ALLOC_TPA
POP ES
POPF
POP CX
POP AX
JNC STORE1
POP ES ;AN056;
MOV DX,OFFSET TRANGROUP:ENVERR_ptr
JMP CERROR
STORE1:
STOSB
MOV WORD PTR ES:[DI],0 ; NULL IS AT END
POP ES ;AN056;
POP BX
POP CX
return
GETENVSIZ:
;Get size of environment in bytes, rounded up to paragraph boundry
;ES has environment segment
;Size returned in CX, all other registers preserved
PUSH ES
PUSH AX
MOV AX,ES
DEC AX ;Point at arena
MOV ES,AX
MOV AX,ES:[arena_size]
MOV CL,4
SHL AX,CL ;Convert to bytes
MOV CX,AX
POP AX
POP ES
return
ASSUME DS:TRANGROUP
RESTUDIR1:
PUSH DS
MOV DS,[RESSEG]
ASSUME DS:RESGROUP
CMP [RESTDIR],0
POP DS
ASSUME DS:TRANGROUP
retz
RESTUDIR:
MOV DX,OFFSET TRANGROUP:USERDIR1
MOV AH,CHDIR
INT 21h ; Restore users DIR
XOR AL,AL
invoke SETREST
RET56:
return
trancode ends
end