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.

403 lines
10 KiB

  1. title Path Searching Routines
  2. ;/*
  3. ; * Microsoft Confidential
  4. ; * Copyright (C) Microsoft Corporation 1993
  5. ; * All Rights Reserved.
  6. ; */
  7. Page ,132
  8. ; PATH.ASM - Code to search the environment for a particular data string,
  9. ; and to search the path for a particular file. Adapted from the original
  10. ; COMMAND.COM version.
  11. ;
  12. ; Routines supported:
  13. ; Find_in_Environment - locate the start of a given string
  14. ; in the environment
  15. ; Path_Crunch - concantenates a file name with a directory path from
  16. ; the PATH environment variable
  17. ; Search - Finds executable or other files, given a base name
  18. ;
  19. include dossym.inc
  20. include curdir.inc
  21. include find.inc
  22. include pdb.inc
  23. include syscall.inc
  24. DATA segment para public 'DATA'
  25. Path_str db "PATH="
  26. Path_str_size equ $ - offset Path_Str
  27. Comspec_str db "COMSPEC="
  28. Comspec_str_size equ $ - offset Comspec_str
  29. comext db ".COM",0
  30. exeext db ".EXE",0
  31. DATA ends
  32. CODE segment para public 'CODE'
  33. assume cs:CODE,ds:DATA
  34. IFDEF DBCS
  35. extrn IsDBCSLeadByte:near
  36. ENDIF
  37. ;----------------------------------------------------------------------------
  38. ; Path_Crunch - takes a pointer into a environment PATH string and a file
  39. ; name, and sticks them together, for subsequent searching.
  40. ;
  41. ; ENTRY:
  42. ; BH -- additional terminator character (i.e., ';')
  43. ; DS:SI -- pointer into pathstring to be dissected
  44. ; ES:DI -- buffer to store target name
  45. ; DX -- pointer to filename
  46. ; EXIT:
  47. ; SI -- moves along pathstring from call to call
  48. ; ES:DI -- filled in with concatenated name
  49. ; Carry set if end of path string has been reached.
  50. ;
  51. ;---------------
  52. Path_Crunch PROC NEAR
  53. public Path_Crunch
  54. ;---------------
  55. assume ds:nothing
  56. assume es:DATA
  57. IFDEF DBCS
  58. xor cl,cl ; clear flag for later use 3/3/KK
  59. ENDIF
  60. path_cr_copy:
  61. lodsb ; get a pathname byte
  62. or al,al ; check for terminator(s)
  63. jz path_seg ; null terminates segment & pathstring
  64. cmp AL, BH
  65. jz path_seg ; BH terminates a pathstring segment
  66. IFDEF DBCS
  67. invoke IsDBCSLeadByte ;
  68. jnz NotKanj2 ;
  69. stosb ;
  70. movsb ;
  71. MOV CL,1 ; CL=1 means latest stored char is DBCS
  72. jmp path_cr_copy ;
  73. NotKanj2: ;
  74. xor cl,cl ; CL=0 means latest stored char is SBCS
  75. ENDIF
  76. stosb ; save byte in concat buffer
  77. jmp path_cr_copy ; loop until we see a terminator
  78. path_seg:
  79. push si ; save resting place in env. seg.
  80. mov BL, AL ; remember if we saw null or not...
  81. path_cr_look: ; form complete pathname
  82. mov al, '\' ; add pathname separator for suffix
  83. IFDEF DBCS
  84. or cl,cl ;
  85. jnz path_cr_store ; this is a trailing byte of ECS code 3/3/KK
  86. ENDIF
  87. cmp al,es:byte ptr [di-1]
  88. jz path_cr_l1
  89. path_cr_store:
  90. stosb
  91. path_cr_l1:
  92. mov SI, DX
  93. path_cr_l2:
  94. lods byte ptr es:[si] ; tack the stripped filename onto
  95. stosb ; the end of the path, up to and
  96. or AL, AL ; including the terminating null
  97. jnz path_cr_l2
  98. path_cr_leave:
  99. or BL, BL ; did we finish off the pathstring?
  100. clc
  101. jnz path_cr_exit ; null in BL means all gone...
  102. cmc
  103. path_cr_exit:
  104. pop si ; retrieve
  105. ret
  106. assume es:nothing
  107. ;---------------
  108. Path_Crunch endp
  109. ;----------------------------------------------------------------------------
  110. ;----------------------------------------------------------------------------
  111. ; SEARCH, when given a pathname, attempts to find a file with
  112. ; one of the following extensions: .com, .exe (highest to
  113. ; lowest priority). Where conflicts arise, the extension with
  114. ; the highest priority is favored.
  115. ; ENTRY:
  116. ; DX -- pointer to null-terminated pathname
  117. ; BX -- dma buffer for findfirst/next
  118. ; AL -- 0 if we should look for .COM and .EXE extensions
  119. ; 1 if extensions is pre-specified
  120. ; EXIT:
  121. ; AX -- 8) file found with .com extension, or file with
  122. ; pre-specified extension found
  123. ; 4) file found with .exe extension
  124. ; 0) no such file to be found
  125. ; DX -- points to resolved path name
  126. ; DS -- DATA
  127. ; NOTES:
  128. ; 1) Requires caller to have allocated executed a setdma.
  129. ;
  130. ;---------------
  131. ; CONSTANTS:
  132. ;---------------
  133. search_attr equ attr_read_only+attr_hidden
  134. search_file_not_found equ 0
  135. search_com equ 8
  136. search_exe equ 4
  137. fname_len equ 8
  138. fname_max_len equ 23
  139. dot equ '.'
  140. wildchar equ '?'
  141. search_best db (?)
  142. ;---------------
  143. Search PROC NEAR
  144. public Search
  145. ;---------------
  146. push si ;
  147. push ax ; save extension flag
  148. mov DI, DX ; working copy of pathname
  149. mov CX, search_attr ; filetypes to search for
  150. mov ah, Find_First ; request first match, if any
  151. int 21h
  152. pop ax
  153. jc search_no_file
  154. or al,al ; looking for specific ext?
  155. jz search_no_ext ; no, jump
  156. mov search_best,search_com ; report we found best match
  157. jmp short search_file_found ; yes, found it
  158. search_no_ext:
  159. mov search_best, search_file_not_found
  160. search_loop:
  161. call search_ftype ; determine if .com, &c...
  162. cmp AL, search_best ; better than what we've found so far?
  163. jle search_next ; no, look for another
  164. mov search_best, AL ; found something... save its code
  165. cmp AL, search_com ; have we found the best of all?
  166. je search_done
  167. search_next: ; keep on looking
  168. mov CX, search_attr
  169. mov ah, Find_Next ; next match
  170. int 21h
  171. jnc search_loop
  172. search_done: ; it's all over with...
  173. cmp search_best, search_file_not_found
  174. je search_no_file
  175. cmp search_best, search_com
  176. mov si, offset comext
  177. je search_move_ext
  178. mov si, offset exeext
  179. search_move_ext:
  180. mov di, dx
  181. mov al, '.'
  182. mov cx, DIRSTRLEN
  183. rep scasb
  184. dec di
  185. movsw
  186. movsw
  187. search_file_found:
  188. mov al, search_best
  189. jmp short search_exit
  190. search_no_file: ; couldn't find a match
  191. mov AX, search_file_not_found
  192. search_exit:
  193. pop si
  194. ret
  195. Search endp
  196. ;----------------------------------------------------------------------------
  197. ;----------------------------------------------------------------------------
  198. ; SEARCH_FTYPE determines the type of a file by examining its extension.
  199. ; ENTRY:
  200. ; BX -- dma buffer containing filename
  201. ; EXIT:
  202. ; AL -- file code, as given in search header
  203. ;---------------
  204. Search_Ftype PROC NEAR
  205. public Search_Ftype
  206. push DI
  207. mov AL, search_file_not_found ; find the end of the filename
  208. mov DI, BX
  209. add di,Find_Buf_Pname
  210. mov CX, fname_max_len
  211. cld
  212. repnz scasb ; search for the terminating null
  213. jnz ftype_exit ; weird... no null byte at end
  214. ;
  215. ; Scan backwards to find the start of the extension
  216. ;
  217. dec di ; point back to null
  218. mov cx, 5 ; . + E + X + T + null
  219. std ; scan back
  220. mov al, '.'
  221. repnz scasb
  222. jnz ftype_exit ; must not be any extension
  223. inc di ; point to start of extension
  224. cld
  225. ;
  226. ; Compare .COM
  227. ;
  228. mov si,offset comext
  229. mov ax,di
  230. cmpsw
  231. jnz ftype_exe
  232. cmpsw
  233. jnz ftype_exe
  234. mov AL, search_com ; success!
  235. jmp short ftype_exit
  236. ;
  237. ; Compare .EXE
  238. ;
  239. ftype_exe: ; still looking... now for '.exe'
  240. mov di,ax
  241. mov si,offset exeext
  242. cmpsw
  243. jnz ftype_fail
  244. cmpsw
  245. jnz ftype_fail
  246. mov AL, search_exe ; success!
  247. jmp short ftype_exit
  248. ftype_fail: ; file doesn't match what we need
  249. mov al,search_file_not_found
  250. ftype_exit:
  251. pop DI
  252. ret
  253. Search_Ftype endp
  254. ;----------------------------------------------------------------------------
  255. ;
  256. ; Find_Comspec_In_Environment - find the beginning of the COMSPEC string
  257. ; Entry : DS = DATA
  258. ; ES = PSP
  259. ; Exit : ES:DI => start of Comspec path
  260. ;
  261. FIND_COMSPEC_IN_environment PROC NEAR
  262. public Find_Comspec_In_Environment
  263. lea si,Comspec_str
  264. mov cx,Comspec_str_size ; cx = length of name
  265. jmp short Find_in_Environment
  266. Find_Comspec_in_Environment endp
  267. ;----------------------------------------------------------------------------
  268. ;
  269. ; Find_Path_In_Environment - find the beginning of the PATH string
  270. ; Entry : DS = DATA
  271. ; ES = PSP
  272. ; Exit : ES:DI => start of Path directory list
  273. ;
  274. FIND_PATH_IN_environment PROC NEAR
  275. public Find_Path_In_Environment
  276. lea si,Path_str
  277. mov cx,Path_str_size ; cx = length of name
  278. ; fall through to following
  279. Find_Path_in_Environment endp
  280. ; Find_In_Environment - locate a given string in the environment
  281. ;
  282. ; Input : SI = name to find in environment
  283. ; CX = length of name
  284. ; DS = DATA
  285. ; ES = PSP segment
  286. ;
  287. ; Output: ES:DI points to the arguments in the environment
  288. ; carry is set if name not found
  289. ;
  290. Find_in_Environment PROC NEAR
  291. public Find_In_Environment
  292. cld
  293. xor di,di
  294. mov ax,es:[di].PDB_Environ
  295. or ax,ax ; is there an environment?
  296. jz find_nf_exit ; no, quit now
  297. mov es,ax
  298. assume es:nothing
  299. find1:
  300. push si
  301. push cx ; save starting values
  302. find11:
  303. ifdef dbcs
  304. lodsb
  305. call IsDBCSLeadByte
  306. jnz notkanj3
  307. dec si
  308. lodsw
  309. inc di
  310. inc di
  311. cmp ax,es:[di-2]
  312. jnz find12
  313. dec cx
  314. loop find11
  315. jmp short find12
  316. notkanj3:
  317. inc di
  318. cmp al,es:[di-1]
  319. jnz find12
  320. loop find11
  321. else ;dbcs
  322. repe cmpsb
  323. endif ;dbcs
  324. find12:
  325. pop dx
  326. pop si ; clear stack
  327. jz find_exit
  328. dec di
  329. xor al,al ; scan for a nul
  330. mov cx,100h ; arbitrary size
  331. repnz scasb
  332. cmp byte ptr es:[di],0 ; check for trailing null
  333. mov cx,dx ; original count back in CX
  334. jnz find1
  335. find_nf_exit:
  336. stc ; indicate not found
  337. find_exit:
  338. ret
  339. Find_in_environment endp
  340. CODE ends
  341. end
  342.