WindowsXP/Source/XPSP1/NT/base/mvdm/dpmi/dxfind.asm
2024-08-03 16:30:48 +02:00

432 lines
10 KiB
NASM

PAGE ,132
TITLE DXFIND.ASM -- Dos Extender Find File Routine
; Copyright (c) Microsoft Corporation 1988-1991. All Rights Reserved.
;***********************************************************************
;
; DXFIND.ASM -- Dos Extender Find File Routine
;
;-----------------------------------------------------------------------
;
; This module provides the locate file logic for the 286 DOS Extender.
;
;-----------------------------------------------------------------------
;
; 09/27/89 jimmat Original version -- considerable code taken from
; old GetChildName routine in dxinit.asm.
;
;***********************************************************************
.286p
; -------------------------------------------------------
; INCLUDE FILE DEFINITIONS
; -------------------------------------------------------
.xlist
.sall
include segdefs.inc
include gendefs.inc
.list
; -------------------------------------------------------
; GENERAL SYMBOL DEFINITIONS
; -------------------------------------------------------
; -------------------------------------------------------
; EXTERNAL SYMBOL DEFINITIONS
; -------------------------------------------------------
extrn strcpy:NEAR
extrn toupper:NEAR
; -------------------------------------------------------
; DATA SEGMENT DEFINITIONS
; -------------------------------------------------------
DXDATA segment
extrn segPSP:WORD
extrn rgbXfrBuf1:BYTE
DXDATA ends
; -------------------------------------------------------
; CODE SEGMENT VARIABLES
; -------------------------------------------------------
DXCODE segment
szPath db 'PATH',0
szWindir db 'WINDIR',0
DXCODE ends
; -------------------------------------------------------
subttl Find File Routine
page
; -------------------------------------------------------
; FIND FILE ROUTINE
; -------------------------------------------------------
DXCODE segment
assume cs:DXCODE
; -------------------------------------------------------
; FindFile -- This routine is used to locate a particular file.
; If successful, this routine will setup the buffer in rgbXfrBuf1
; at offset EXEC_PROGNAME with the string for the file name that
; can be used in a DOS open call.
;
; This routine searches for the file in the following sequence:
;
; 1) If the file name contains a relative or complete path
; component, only look for that particular file,
;
; otherwise:
;
; 1) Look int the environment for a WINDIR= variable, and if
; found, check that directory first.
; 2) Look in the directory the dos extender was loaded from
; 3) Look in the current directory
; 4) Look in all directories in the PATH environment variable
;
; NOTE: This routine must be called in real mode!
;
; Input: RELOC_BUFFER has the file name to search for.
; EXEC_DXNAME has the complete path the dos extender
; Output: EXEC_PROGNAME has complete path to child program.
; Errors: returns CY set if unable to find child
; Uses: All registers preserved
assume ds:DGROUP,es:NOTHING,ss:NOTHING
public FindFile
FindFile proc near
pusha
push ds
push es
push ds
pop es
assume es:DGROUP
; If the base file name contains a ':' '\' or '/', then we'll see if the
; file can be found with that name. This isn't exactly the way Windows wants
; us to search for kernel, but allows a user to specify a relative or complete
; path on the command line. If we get run for Windows/286 pMode, the base
; child name will not include any of these characters, so we will not make
; this check.
mov si,offset RELOC_BUFFER
@@: lodsb
or al,al
jz fndf20 ;no path characters, go do other search
cmp al,':'
jz fndf10
cmp al,'\'
jz fndf10
cmp al,'/'
jnz @b
; The name seems to include a path component. We just want to look for that
; file, and only that file.
fndf10: mov si,offset RELOC_BUFFER
mov di,offset EXEC_PROGNAME
mov dx,di
call strcpy
mov ax,4300h ;use get file attributes to check
int 21h
jmp fndf90 ;found it or not, either way we're done
; The file name doesn't include a path component. If we were run for pMode
; Windows, the environment should include a WINDIR= entry that points to
; the Windows directory. Look for this env variable, and check that directory
; first.
fndf20:
push es ;look for the
push cs ;WINDIR= env variable
pop es
assume es:NOTHING
mov di,offset DXCODE:szWindir
call GetEnv
pop es
assume ds:NOTHING,es:DGROUP
jnz fndf_dosx_dir
; Found WINDIR, copy over the path name, add child name and search
mov di,offset EXEC_PROGNAME ;copy WINDIR path
mov dx,di
call strcpy
cmp byte ptr es:[di-1],'\' ;add trailing \ if necessary
jz @f
mov byte ptr es:[di],'\'
inc di
@@:
push es ;ds back to DGROUP
pop ds
assume ds:DGROUP
mov si,offset RELOC_BUFFER ;add child name
call strcpy
mov ax,4300h ;use get file attributes to check
int 21h
jc fndf_dosx_dir ;no there, go do next check
jmp fndf90 ;found it!
; Next, we try looking in the directory that the Dos Extender was loaded
; from. Start with the complete path to the Dos Extender program file.
fndf_dosx_dir:
push es
pop ds
assume ds:DGROUP
mov si,offset EXEC_DXNAME
mov di,offset EXEC_PROGNAME
mov dx,di
call strcpy
; Now, search backward from the end of the string until we find the
; first backslash or colon. This will take us back past the file name
; and leave us with the raw path.
fndf24: dec di
cmp di,dx ;check if we have gone back past the start
; of the string. (DX still has the address
; of the start of the buffer from above)
jb fndf_cd ;and if so skip this part as the path is null.
mov al,es:[di]
cmp al,':'
jz fndf26
cmp al,'\'
jnz fndf24
; Add the file name string onto the raw path and see if the file exists.
fndf26: inc di
mov si,offset RELOC_BUFFER
call strcpy
mov ax,4300h ;use get file attributes to check
int 21h
jc fndf_cd
jmp fndf90
; We didn't find the file in the same directory as the Extender itself.
; Now, try looking for the file in the current directory!
fndf_cd:
mov di,offset EXEC_PROGNAME ;build current directory path string
dossvc 19h
add al,'A'
stosb ;drive letter
mov ax,'\:'
stosw
xor dl,dl
mov si,di
dossvc 47h ;current directory
mov al,es:[di] ;check if it's the root
or al,al ;empty string?
jz short fndf_cd_cpy ;yes, don't add another '\'
@@: lodsb ;find end of string
or al,al
jnz @b
mov byte ptr [si-1],'\' ;add ending \
fndf_cd_cpy:
mov di,si ;add base child name
mov si,offset RELOC_BUFFER
call strcpy
mov dx,offset EXEC_PROGNAME ;use get file attributes to check
mov ax,4300h
int 21h
jc fndf30
jmp short fndf90
; We didn't find it in the current directory, look at the PATH
; environment variable and see if the file can be found in any of
; its directories. First off, search for the PATH environment
; string.
fndf30:
push es
mov di,offset DXCODE:szPath ;point ES:DI to path str
push cs
pop es
assume es:NOTHING
call GetEnv ;find the path env var
assume ds:NOTHING
pop es
assume es:DGROUP
jnz fndf80 ;Z flag set if FOUND
; We are pointing at the beginning of the path environment variable. We need
; to loop for each directory specified to see if we can find the file in
; that directory.
mov bx,ds ;keep env segment in BX
fndf40: mov ds,bx ;environment segment to DS
assume ds:NOTHING
mov al,ds:[si]
or al,al ;check for end of path variable.
jz fndf80 ;if so, we didn't find any directory with
; the desired file in it.
mov di,offset EXEC_PROGNAME
fndf42: lods byte ptr [si]
cmp al,';' ;is it the separator between strings in
jz fndf52 ; the environment variable?
or al,al ;is it the 0 at the end of the environment
jz fndf50 ; string?
stos byte ptr [di]
jmp fndf42
fndf50: dec si
fndf52: push si ;save pointer to start of next string
mov al,'\'
cmp al,byte ptr es:[di-1] ;dir name already end with \ (root dir?)
jnz fndf54
dec di ; yes, don't make it two \'s
fndf54: stos byte ptr [di]
mov si,offset RELOC_BUFFER ;pointer to file base name
mov ax,es ;put our data segment address in DS
mov ds,ax
assume ds:DGROUP
call strcpy ;append file base name to path
mov ax,4300h ;use get file attributes to check
int 21h
pop si ;restore pointer to start of next string
jc fndf40
jmp short fndf90
; Unable to find the file
fndf80: stc
; Finished, successful or not
fndf90:
pop es
pop ds
popa
ret
FindFile endp
; -------------------------------------------------------
; GetEnv -- This routine searches the environment for a
; specific variable.
;
; Input: ES:DI - far pointer to wanted variable name
; Output: DS:SI - far pointer to variable value string
; Errors: return Z true if variable located
; Uses: DS:SI modified, all else preserved
assume ds:DGROUP,es:NOTHING,ss:NOTHING
public GetEnv
GetEnv proc near
push ax
push dx
push di
; Point DS:SI to our environment block
mov ds,segPSP
assume ds:PSPSEG
mov ds,segEnviron
xor si,si
assume ds:NOTHING
; See if DS:SI is pointing at desired environment variable
mov dx,di ;keep var name offset in dx
gete10:
cmp byte ptr es:[di],0 ;at end of variable name?
jz gete50 ; yes, go check '=' & optional blanks
gete20:
lodsb ;get variable char
call toupper ;just in case...
cmp al,es:[di] ;match desired name so far?
jnz gete30 ; no, go find the next var name
inc di ;bump var pointer
jmp short gete10 ; and keep on checking
gete30:
mov di,dx ;reset source name pointer
or al,al ;already at end of this env var?!
jz gete35
@@: lodsb
or al,al ;find next environment var name
jnz @b
gete35:
cmp byte ptr ds:[si],0 ;at end of environment?
jz gete80 ; yes, go fail the call
jmp short gete10 ; no, try try again
; Found the env variable, now skip the '=' and any spaces
gete50:
cmp byte ptr ds:[si],'=' ;when we get here, better be pointing
jnz gete30 ; at an '='
inc si
@@: cmp byte ptr ds:[si],' ' ;skip any optional blanks
jnz @f
inc si
jmp short @b
@@:
xor ax,ax ;set the Z flag
jmp short @f
gete80:
or ax,si ;pretty sure this clears Z
@@:
pop di
pop dx
pop ax
ret
GetEnv endp
; -------------------------------------------------------
DXCODE ends
;****************************************************************
end