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.
 
 
 
 
 
 

472 lines
14 KiB

page ,132
;/*
; * Microsoft Confidential
; * Copyright (C) Microsoft Corporation 1991
; * All Rights Reserved.
; */
; SCCSID = @(#)path2.asm 1.1 85/05/14
; SCCSID = @(#)path2.asm 1.1 85/05/14
.sall
.xlist
.xcref
include dossym.inc
include syscall.inc
include find.inc
include comsw.asm
include comseg.asm
include comequ.asm
.list
.cref
DATARES SEGMENT PUBLIC BYTE
EXTRN FORFLAG:BYTE
DATARES ENDS
break <Path.Asm>
;----------------------------------------------------------------------------
; PATH.ASM contains the routines to perform pathname incovation. Path and
; Parse share a temporary buffer and argv[] definitions. <Path_Search>,
; given a pathname, attempts to find a corresponding executable or batch
; file on disk. Directories specified in the user's search path will be
; searched for a matching file, if a match is not found in the current
; directory and if the pathname is actually only an MSDOS filename.
; <Path_Search> assumes that the parsed command name can be found in
; argv[0] -- in other words, <Parseline> should be executed prior to
; <Path_Search>. Alternatively, the command name and appropriate
; information could be placed in argv[0], or <Path_Search> could be
; (easily) modified to make no assumptions about where its input is found.
; Please find enclosed yet another important routine, <Save_Args>, which
; places the entire arg/argv[]/argbuf structure on a piece of newly
; allocated memory. This is handy for for-loop processing, and anything
; else that wants to save the whole shebang and then process other command
; lines.
;
; Alan L, OS/MSDOS August 15, 1983
;
; ENTRY:
; <Path_Search>: argv[0].
; <Save_Args>: bytes to allocate in addition to arg structure
; EXIT:
; <Path_Search>: success flag, best pathname match in EXECPATH.
; <Save_Args>: success flag, segment address of new memory
; NOTE(S):
; * <Argv_calc> handily turns an array index into an absolute pointer.
; The computation depends on the size of an argv[] element (arg_ele).
; * <Parseline> calls <cparse> for chunks of the command line. <Cparse>
; does not function as specified; see <Parseline> for more details.
; * <Parseline> now knows about the flags the internals of COMMAND.COM
; need to know about. This extra information is stored in a switch_flag
; word with each command-line argument; the switches themselves will not
; appear in the resulting arg structure.
; * With the exception of CARRY, flags are generally preserved across calls.
;---------------
; CONSTANTS:
;---------------
DEBUGx equ FALSE ; prints out debug info
;---------------
; DATA:
;---------------
TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
EXTRN arg:byte
EXTRN BADPMES_ptr:word
EXTRN curdrv:byte
EXTRN EXECPATH:byte
EXTRN ext_entered:byte ;AN005;
EXTRN fbuf:byte
EXTRN pathinfo:word
EXTRN psep_char:byte
EXTRN string_ptr_2:word
EXTRN tpbuf:byte
TRANSPACE ENDS
TRANCODE SEGMENT PUBLIC BYTE ;AC000;
assume cs:trangroup, ds:trangroup, es:trangroup, ss:nothing
break <Search>
;----------------------------------------------------------------------------
; SEARCH, when given a pathname, attempts to find a file with
; one of the following extensions: .com, .exe, .bat (highest to
; lowest priority). Where conflicts arise, the extension with
; the highest priority is favored.
; ENTRY:
; DX -- pointer to null-terminated pathname
; fbuf -- dma buffer for findfirst/next
; EXIT:
; AX -- 8) file found with .com extension
; 4) file found with .exe extension
; 2) file found with .bat extension
; 0) no such file to be found
; (if AX is non-zero:)
; [search_best] identical to AX
; [search_best_buf] null-terminated filename
; NOTES:
; 1) Requires caller to have allocated a dma buffer and executed a setdma.
;---------------
; CONSTANTS:
;---------------
search_file_not_found equ 0
search_com equ 8
search_exe equ 4
search_bat equ 2
fname_len equ 8
fname_max_len equ 13
dot equ '.'
wildchar equ '?'
;---------------
; DATA:
;---------------
TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
EXTRN search_best:byte
EXTRN search_best_buf:byte
EXTRN search_curdir_buf:byte
EXTRN search_error:word
TRANSPACE ENDS
;---------------
Procedure Search,NEAR
;---------------
assume ds:trangroup, es:trangroup
push CX
push DX
push DI
push SI
pushf
push DX ; check drivespec (save pname ptr)
mov DI, DX ; working copy of pathname
mov SI, OFFSET TRANGROUP:search_curdir_buf
xor DX, DX ; zero means current drive
cmp BYTE PTR [DI+1],':' ; is there a drive spec?
jne search_dir_check
mov DL, [DI] ; get the drive byte
and DL, NOT 20H ; uppercase it
sub DL, '@' ; and convert to drive number
search_dir_check:
trap Current_Dir ; can we get the drive's current
pop DX ; directory? If we can't we'll
jc search_invalid_drive ; assume it's a bad drive...
mov CX, search_attr ; filetypes to search for
trap Find_First ; request first match, if any
jc search_no_file
mov search_best, search_file_not_found
mov [search_best_buf], ANULL ; nothing's been found, yet
search_loop:
call search_ftype ; determine if .com, &c...
cmp AL, search_best ; better than what we've found so far?
jle search_next ; no, look for another
mov search_best, AL ; found something... save its code
mov SI, OFFSET TRANGROUP:fbuf.find_buf_pname
mov DI, OFFSET TRANGROUP:search_best_buf
mov CX, fname_max_len
cld
rep movsb ; save complete pathname representation
cmp AL, search_com ; have we found the best of all?
je search_done
search_next: ; keep on looking
mov CX, search_attr
trap Find_Next ; next match
jnc search_loop
search_done: ; it's all over with...
mov AL, search_best ; pick best to return with
cmp ext_entered,1 ;AN005; Did user request a specific ext?
jz search_exit ;AN005; no - exit
mov al,ext_entered ;AN005; yes - get the real file type back
mov search_best,al ;AN005; save the real file type
jmp short search_exit
search_invalid_drive: ; Tell the user path/drive
mov DX, [search_error] ; appropriate error message
invoke std_printf ; and pretend no file found
search_no_file: ; couldn't find a match
mov AX, search_file_not_found
search_exit:
popf
pop SI
pop DI
pop DX
pop CX
ret
;---------------
EndProc Search
;----------------------------------------------------------------------------
break <Search_Ftype>
;----------------------------------------------------------------------------
; SEARCH_FTYPE determines the type of a file by examining its extension.
; ENTRY:
; fbuf -- dma buffer containing filename
; EXIT:
; AX -- file code, as given in search header
; NOTE(S):
; * Implicit assumption that NULL == search_file_not_found
;---------------
; DATA:
;---------------
TRANDATA SEGMENT PUBLIC BYTE ;AC000;
extrn comext:byte,exeext:byte,batext:byte
trandata ends
;---------------
Procedure Search_Ftype,NEAR
;---------------
assume ds:trangroup, es:trangroup
push DI
push si
mov AX, ANULL ; find the end of the filename
mov DI, OFFSET TRANGROUP:fbuf.find_buf_pname
mov CX, fname_max_len
cld
repnz scasb ; search for the terminating null
jnz ftype_exit ; weird... no null byte at end
sub di,5 ; . + E + X + T + NULL
;
; Compare .COM
;
mov si,offset trangroup:comext
mov ax,di
cmpsw
jnz ftype_exe
cmpsw
jnz ftype_exe
mov AX, search_com ; success!
jmp short ftype_exit
;
; Compare .EXE
;
ftype_exe: ; still looking... now for '.exe'
mov di,ax
mov si,offset trangroup:exeext
cmpsw
jnz ftype_bat
cmpsw
jnz ftype_bat
mov AX, search_exe ; success!
jmp short ftype_exit
;
; Compare .BAT
;
ftype_bat: ; still looking... now for '.bat'
mov di,ax
mov si,offset trangroup:batext
cmpsw
jnz ftype_fail
cmpsw
jnz ftype_fail
mov AX, search_bat ; success!
jmp short ftype_exit
ftype_fail: ; file doesn't match what we need
mov ax,ANULL
ftype_exit:
cmp ext_entered,1 ;AN005; was an extension entered?
jz ftype_done ;AN005; no - exit
cmp ax,ANULL ;AN005; was any match found
jz ftype_done ;AN005; no - exit
mov ext_entered,al ;AN005; save the match type found
mov AX, search_com ;AN005; send back best was found to stop search
ftype_done: ;AN005;
pop SI
pop DI
ret
;---------------
EndProc Search_Ftype
;----------------------------------------------------------------------------
break <Strip>
;----------------------------------------------------------------------------
; STRIP copies the source string (argv[0]) into the destination buffer,
; replacing any extension with wildcards.
; ENTRY:
; BX -- maximum length of destination buffer
; DS:SI -- address of destination buffer
; argv[0] -- command name to be stripped
; EXIT:
; CF -- set if failure, clear if successful
; NOTE(S):
;---------------
Procedure Strip,NEAR
;---------------
assume ds:trangroup, es:trangroup
push AX
push BX
push CX
push DX
push DI
push SI
pushf
mov ext_entered,1 ;AN005; assume no extension on file name
mov DX, DS:arg.argv[0].argpointer ; save pointer to beginning of argstring
mov DI, DS:arg.argv[0].argstartel ; beginning of last pathname element
cmp BYTE PTR [DI], 0 ; *STARTEL == NULL means no command
jz strip_error
mov CX, DX ; compute where end of argstring lies
add CX, DS:arg.argv[0].arglen
sub CX, DI ; and then find length of last element
inc CX ; include null as well
mov AL, dot ; let's find the filetype extension
cld
repnz scasb ; wind up pointing to either null or dot
jcxz process_ext ;AN005; if no extension found, just continue
mov ext_entered,0 ;AN005; we found an extension
mov al,ANULL ;AN005; continue scanning until the
repnz scasb ;AN005; end of line is reached.
process_ext: ;AN005;
mov CX, DI ; pointer to end of argstring yields
sub CX, DX ; number of bytes to be copied
sub BX, 4 ; can argstring fit into dest. buffer?
cmp CX, BX
jg strip_error ; if not, we must have a bad pathname
mov DI, SI ; destination buffer
mov SI, DX ; source is beginning of pathname
cld
rep movsb ; SI=arg,DI=buffer,CX=argend-argbeg
cmp ext_entered,1 ;AN005; if an extension was entered
jnz skip_wilds ;AN005; don't set up wildcard ext.
dec DI ; overwrite null or dot
stosb ; with a dot
mov AL, wildchar ; now add wildcards
stosb
stosb
stosb
mov AL, ANULL ; and a terminating null
stosb
skip_wilds: ;AN005;
popf
clc ; chill out...
jmp short strip_exit
strip_error:
popf
stc
strip_exit:
pop SI
pop DI
pop DX
pop CX
pop BX
pop AX
ret
;---------------
EndProc Strip
;----------------------------------------------------------------------------
break <Save_Args>
;----------------------------------------------------------------------------
; SAVE_ARGS attempts to preserve the existing argv[]/argvcnt/argbuffer
; structure in newly allocated memory. The argv[] structure is found at the
; beginning of this area. The caller indicates how much extra space is
; needed in the resulting structure; Save_Args returns a segment number and
; an offset into that area, indicating where the caller may preserve its own
; data. Note that <argvcnt> can be found at <offset-2>.
; ENTRY:
; BX -- size (in bytes) of extra area to allocate
; EXIT:
; AX -- segment of new area.
; CF -- set if unable to save a copy.
; NOTE(S):
; 1) The allocated area will be AT LEAST the size requested -- since
; the underlying MSDOS call, <alloc> returns an integral number of
; paragraphs.
; 2) It is an error if MSDOS can't allocate AT LEAST as much memory
; as the caller of Save_Args requests.
; 3) AX is undefined if CF indicates an error.
;---------------
Procedure Save_Args,NEAR
;---------------
assume ds:trangroup, es:trangroup
push BX
push CX
push DX
push DI
push SI
push BP
pushf
add BX, SIZE arg_unit + 0FH ; space for arg structure, round up
mov CL, 4 ; to paragraph size and convert
shr BX, CL ; size in bytes to size in paragraphs
trap Alloc
jc save_error
mov BP, AX ; save segment id
push ES ; save TRANGROUP address
mov ES, AX ; switch to new memory segment
assume ES:nothing
mov CX, SIZE arg_unit ; get back structure size
xor DI, DI ; destination is new memory area
mov SI, OFFSET TRANGROUP:arg ; source is arg structure
rep movsb ; move it
mov CX, arg.argvcnt ; adjust argv pointers
xor AX, AX ; base address for argv_calc
; Bugbug: What did they mean by this?
; Note that the replacement line produces exactly the same code.
;; mov SI, OFFSET TRANGROUP:arg.argbuf - OFFSET arg_unit.argbuf
mov SI, OFFSET TRANGROUP:arg
save_ptr_loop:
dec CX ; exhausted all args?
jl save_done
mov BX, CX ; get arg index and
invoke argv_calc ; convert to a pointer
mov DX, DS:arg.argv[BX].argpointer
sub DX, SI ; adjust argpointer
mov ES:argv[BX].argpointer, DX
mov DX, DS:arg.argv[BX].argstartel
sub DX, SI ; and adjust argstartel
mov ES:argv[BX].argstartel, DX
mov DX, DS:arg.argv[BX].arg_ocomptr
sub DX, SI ; and adjust arg_ocomptr
mov ES:argv[BX].arg_ocomptr, DX
jmp save_ptr_loop
save_done:
pop ES ; back we go to TRANGROUP
assume ES:trangroup
mov AX, BP ; restore segment id
jmp short save_ok
save_error:
popf
stc
jmp short save_exit
save_ok:
popf
clc
save_exit:
pop BP
pop SI
pop DI
pop DX
pop CX
pop BX
ret
;---------------
EndProc Save_Args
;----------------------------------------------------------------------------
trancode ends
END