windows-nt/Source/XPSP1/NT/base/ntsetup/opktools/oformat/path.asm
2020-09-26 16:20:57 +08:00

404 lines
10 KiB
NASM
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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