Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

404 lines
10 KiB

title Path Searching Routines
;/*
; * Microsoft Confidential
; * Copyright (C) Microsoft Corporation 1993
; * All Rights Reserved.
; */
Page ,132
; PATH.ASM - Code to search the environment for a particular data string,
; and to search the path for a particular file. Adapted from the original
; COMMAND.COM version.
;
; Routines supported:
; Find_in_Environment - locate the start of a given string
; in the environment
; Path_Crunch - concantenates a file name with a directory path from
; the PATH environment variable
; Search - Finds executable or other files, given a base name
;
include dossym.inc
include curdir.inc
include find.inc
include pdb.inc
include syscall.inc
DATA segment para public 'DATA'
Path_str db "PATH="
Path_str_size equ $ - offset Path_Str
Comspec_str db "COMSPEC="
Comspec_str_size equ $ - offset Comspec_str
comext db ".COM",0
exeext db ".EXE",0
DATA ends
CODE segment para public 'CODE'
assume cs:CODE,ds:DATA
IFDEF DBCS
extrn IsDBCSLeadByte:near
ENDIF
;----------------------------------------------------------------------------
; Path_Crunch - takes a pointer into a environment PATH string and a file
; name, and sticks them together, for subsequent searching.
;
; ENTRY:
; BH -- additional terminator character (i.e., ';')
; DS:SI -- pointer into pathstring to be dissected
; ES:DI -- buffer to store target name
; DX -- pointer to filename
; EXIT:
; SI -- moves along pathstring from call to call
; ES:DI -- filled in with concatenated name
; Carry set if end of path string has been reached.
;
;---------------
Path_Crunch PROC NEAR
public Path_Crunch
;---------------
assume ds:nothing
assume es:DATA
IFDEF DBCS
xor cl,cl ; clear flag for later use 3/3/KK
ENDIF
path_cr_copy:
lodsb ; get a pathname byte
or al,al ; check for terminator(s)
jz path_seg ; null terminates segment & pathstring
cmp AL, BH
jz path_seg ; BH terminates a pathstring segment
IFDEF DBCS
invoke IsDBCSLeadByte ;
jnz NotKanj2 ;
stosb ;
movsb ;
MOV CL,1 ; CL=1 means latest stored char is DBCS
jmp path_cr_copy ;
NotKanj2: ;
xor cl,cl ; CL=0 means latest stored char is SBCS
ENDIF
stosb ; save byte in concat buffer
jmp path_cr_copy ; loop until we see a terminator
path_seg:
push si ; save resting place in env. seg.
mov BL, AL ; remember if we saw null or not...
path_cr_look: ; form complete pathname
mov al, '\' ; add pathname separator for suffix
IFDEF DBCS
or cl,cl ;
jnz path_cr_store ; this is a trailing byte of ECS code 3/3/KK
ENDIF
cmp al,es:byte ptr [di-1]
jz path_cr_l1
path_cr_store:
stosb
path_cr_l1:
mov SI, DX
path_cr_l2:
lods byte ptr es:[si] ; tack the stripped filename onto
stosb ; the end of the path, up to and
or AL, AL ; including the terminating null
jnz path_cr_l2
path_cr_leave:
or BL, BL ; did we finish off the pathstring?
clc
jnz path_cr_exit ; null in BL means all gone...
cmc
path_cr_exit:
pop si ; retrieve
ret
assume es:nothing
;---------------
Path_Crunch endp
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
; SEARCH, when given a pathname, attempts to find a file with
; one of the following extensions: .com, .exe (highest to
; lowest priority). Where conflicts arise, the extension with
; the highest priority is favored.
; ENTRY:
; DX -- pointer to null-terminated pathname
; BX -- dma buffer for findfirst/next
; AL -- 0 if we should look for .COM and .EXE extensions
; 1 if extensions is pre-specified
; EXIT:
; AX -- 8) file found with .com extension, or file with
; pre-specified extension found
; 4) file found with .exe extension
; 0) no such file to be found
; DX -- points to resolved path name
; DS -- DATA
; NOTES:
; 1) Requires caller to have allocated executed a setdma.
;
;---------------
; CONSTANTS:
;---------------
search_attr equ attr_read_only+attr_hidden
search_file_not_found equ 0
search_com equ 8
search_exe equ 4
fname_len equ 8
fname_max_len equ 23
dot equ '.'
wildchar equ '?'
search_best db (?)
;---------------
Search PROC NEAR
public Search
;---------------
push si ;
push ax ; save extension flag
mov DI, DX ; working copy of pathname
mov CX, search_attr ; filetypes to search for
mov ah, Find_First ; request first match, if any
int 21h
pop ax
jc search_no_file
or al,al ; looking for specific ext?
jz search_no_ext ; no, jump
mov search_best,search_com ; report we found best match
jmp short search_file_found ; yes, found it
search_no_ext:
mov search_best, search_file_not_found
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
cmp AL, search_com ; have we found the best of all?
je search_done
search_next: ; keep on looking
mov CX, search_attr
mov ah, Find_Next ; next match
int 21h
jnc search_loop
search_done: ; it's all over with...
cmp search_best, search_file_not_found
je search_no_file
cmp search_best, search_com
mov si, offset comext
je search_move_ext
mov si, offset exeext
search_move_ext:
mov di, dx
mov al, '.'
mov cx, DIRSTRLEN
rep scasb
dec di
movsw
movsw
search_file_found:
mov al, search_best
jmp short search_exit
search_no_file: ; couldn't find a match
mov AX, search_file_not_found
search_exit:
pop si
ret
Search endp
;----------------------------------------------------------------------------
;----------------------------------------------------------------------------
; SEARCH_FTYPE determines the type of a file by examining its extension.
; ENTRY:
; BX -- dma buffer containing filename
; EXIT:
; AL -- file code, as given in search header
;---------------
Search_Ftype PROC NEAR
public Search_Ftype
push DI
mov AL, search_file_not_found ; find the end of the filename
mov DI, BX
add di,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
;
; Scan backwards to find the start of the extension
;
dec di ; point back to null
mov cx, 5 ; . + E + X + T + null
std ; scan back
mov al, '.'
repnz scasb
jnz ftype_exit ; must not be any extension
inc di ; point to start of extension
cld
;
; Compare .COM
;
mov si,offset comext
mov ax,di
cmpsw
jnz ftype_exe
cmpsw
jnz ftype_exe
mov AL, search_com ; success!
jmp short ftype_exit
;
; Compare .EXE
;
ftype_exe: ; still looking... now for '.exe'
mov di,ax
mov si,offset exeext
cmpsw
jnz ftype_fail
cmpsw
jnz ftype_fail
mov AL, search_exe ; success!
jmp short ftype_exit
ftype_fail: ; file doesn't match what we need
mov al,search_file_not_found
ftype_exit:
pop DI
ret
Search_Ftype endp
;----------------------------------------------------------------------------
;
; Find_Comspec_In_Environment - find the beginning of the COMSPEC string
; Entry : DS = DATA
; ES = PSP
; Exit : ES:DI => start of Comspec path
;
FIND_COMSPEC_IN_environment PROC NEAR
public Find_Comspec_In_Environment
lea si,Comspec_str
mov cx,Comspec_str_size ; cx = length of name
jmp short Find_in_Environment
Find_Comspec_in_Environment endp
;----------------------------------------------------------------------------
;
; Find_Path_In_Environment - find the beginning of the PATH string
; Entry : DS = DATA
; ES = PSP
; Exit : ES:DI => start of Path directory list
;
FIND_PATH_IN_environment PROC NEAR
public Find_Path_In_Environment
lea si,Path_str
mov cx,Path_str_size ; cx = length of name
; fall through to following
Find_Path_in_Environment endp
; Find_In_Environment - locate a given string in the environment
;
; Input : SI = name to find in environment
; CX = length of name
; DS = DATA
; ES = PSP segment
;
; Output: ES:DI points to the arguments in the environment
; carry is set if name not found
;
Find_in_Environment PROC NEAR
public Find_In_Environment
cld
xor di,di
mov ax,es:[di].PDB_Environ
or ax,ax ; is there an environment?
jz find_nf_exit ; no, quit now
mov es,ax
assume es:nothing
find1:
push si
push cx ; save starting values
find11:
ifdef dbcs
lodsb
call IsDBCSLeadByte
jnz notkanj3
dec si
lodsw
inc di
inc di
cmp ax,es:[di-2]
jnz find12
dec cx
loop find11
jmp short find12
notkanj3:
inc di
cmp al,es:[di-1]
jnz find12
loop find11
else ;dbcs
repe cmpsb
endif ;dbcs
find12:
pop dx
pop si ; clear stack
jz find_exit
dec di
xor al,al ; scan for a nul
mov cx,100h ; arbitrary size
repnz scasb
cmp byte ptr es:[di],0 ; check for trailing null
mov cx,dx ; original count back in CX
jnz find1
find_nf_exit:
stc ; indicate not found
find_exit:
ret
Find_in_environment endp
CODE ends
end