diff options
Diffstat (limited to 'private/mvdm/dpmi/dxfind.asm')
-rw-r--r-- | private/mvdm/dpmi/dxfind.asm | 426 |
1 files changed, 426 insertions, 0 deletions
diff --git a/private/mvdm/dpmi/dxfind.asm b/private/mvdm/dpmi/dxfind.asm new file mode 100644 index 000000000..205ecabe9 --- /dev/null +++ b/private/mvdm/dpmi/dxfind.asm @@ -0,0 +1,426 @@ + 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 short 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 + +@@: lodsb ;find end of string + or al,al + jnz @b + + mov byte ptr [si-1],'\' ;add ending \ + + 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 |