Leaked source code of windows server 2003
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.

471 lines
14 KiB

  1. page ,132
  2. ;/*
  3. ; * Microsoft Confidential
  4. ; * Copyright (C) Microsoft Corporation 1991
  5. ; * All Rights Reserved.
  6. ; */
  7. ; SCCSID = @(#)path2.asm 1.1 85/05/14
  8. ; SCCSID = @(#)path2.asm 1.1 85/05/14
  9. .sall
  10. .xlist
  11. .xcref
  12. include dossym.inc
  13. include syscall.inc
  14. include find.inc
  15. include comsw.asm
  16. include comseg.asm
  17. include comequ.asm
  18. .list
  19. .cref
  20. DATARES SEGMENT PUBLIC BYTE
  21. EXTRN FORFLAG:BYTE
  22. DATARES ENDS
  23. break <Path.Asm>
  24. ;----------------------------------------------------------------------------
  25. ; PATH.ASM contains the routines to perform pathname incovation. Path and
  26. ; Parse share a temporary buffer and argv[] definitions. <Path_Search>,
  27. ; given a pathname, attempts to find a corresponding executable or batch
  28. ; file on disk. Directories specified in the user's search path will be
  29. ; searched for a matching file, if a match is not found in the current
  30. ; directory and if the pathname is actually only an MSDOS filename.
  31. ; <Path_Search> assumes that the parsed command name can be found in
  32. ; argv[0] -- in other words, <Parseline> should be executed prior to
  33. ; <Path_Search>. Alternatively, the command name and appropriate
  34. ; information could be placed in argv[0], or <Path_Search> could be
  35. ; (easily) modified to make no assumptions about where its input is found.
  36. ; Please find enclosed yet another important routine, <Save_Args>, which
  37. ; places the entire arg/argv[]/argbuf structure on a piece of newly
  38. ; allocated memory. This is handy for for-loop processing, and anything
  39. ; else that wants to save the whole shebang and then process other command
  40. ; lines.
  41. ;
  42. ; Alan L, OS/MSDOS August 15, 1983
  43. ;
  44. ; ENTRY:
  45. ; <Path_Search>: argv[0].
  46. ; <Save_Args>: bytes to allocate in addition to arg structure
  47. ; EXIT:
  48. ; <Path_Search>: success flag, best pathname match in EXECPATH.
  49. ; <Save_Args>: success flag, segment address of new memory
  50. ; NOTE(S):
  51. ; * <Argv_calc> handily turns an array index into an absolute pointer.
  52. ; The computation depends on the size of an argv[] element (arg_ele).
  53. ; * <Parseline> calls <cparse> for chunks of the command line. <Cparse>
  54. ; does not function as specified; see <Parseline> for more details.
  55. ; * <Parseline> now knows about the flags the internals of COMMAND.COM
  56. ; need to know about. This extra information is stored in a switch_flag
  57. ; word with each command-line argument; the switches themselves will not
  58. ; appear in the resulting arg structure.
  59. ; * With the exception of CARRY, flags are generally preserved across calls.
  60. ;---------------
  61. ; CONSTANTS:
  62. ;---------------
  63. DEBUGx equ FALSE ; prints out debug info
  64. ;---------------
  65. ; DATA:
  66. ;---------------
  67. TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
  68. EXTRN arg:byte
  69. EXTRN BADPMES_ptr:word
  70. EXTRN curdrv:byte
  71. EXTRN EXECPATH:byte
  72. EXTRN ext_entered:byte ;AN005;
  73. EXTRN fbuf:byte
  74. EXTRN pathinfo:word
  75. EXTRN psep_char:byte
  76. EXTRN string_ptr_2:word
  77. EXTRN tpbuf:byte
  78. TRANSPACE ENDS
  79. TRANCODE SEGMENT PUBLIC BYTE ;AC000;
  80. assume cs:trangroup, ds:trangroup, es:trangroup, ss:nothing
  81. break <Search>
  82. ;----------------------------------------------------------------------------
  83. ; SEARCH, when given a pathname, attempts to find a file with
  84. ; one of the following extensions: .com, .exe, .bat (highest to
  85. ; lowest priority). Where conflicts arise, the extension with
  86. ; the highest priority is favored.
  87. ; ENTRY:
  88. ; DX -- pointer to null-terminated pathname
  89. ; fbuf -- dma buffer for findfirst/next
  90. ; EXIT:
  91. ; AX -- 8) file found with .com extension
  92. ; 4) file found with .exe extension
  93. ; 2) file found with .bat extension
  94. ; 0) no such file to be found
  95. ; (if AX is non-zero:)
  96. ; [search_best] identical to AX
  97. ; [search_best_buf] null-terminated filename
  98. ; NOTES:
  99. ; 1) Requires caller to have allocated a dma buffer and executed a setdma.
  100. ;---------------
  101. ; CONSTANTS:
  102. ;---------------
  103. search_file_not_found equ 0
  104. search_com equ 8
  105. search_exe equ 4
  106. search_bat equ 2
  107. fname_len equ 8
  108. fname_max_len equ 13
  109. dot equ '.'
  110. wildchar equ '?'
  111. ;---------------
  112. ; DATA:
  113. ;---------------
  114. TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
  115. EXTRN search_best:byte
  116. EXTRN search_best_buf:byte
  117. EXTRN search_curdir_buf:byte
  118. EXTRN search_error:word
  119. TRANSPACE ENDS
  120. ;---------------
  121. Procedure Search,NEAR
  122. ;---------------
  123. assume ds:trangroup, es:trangroup
  124. push CX
  125. push DX
  126. push DI
  127. push SI
  128. pushf
  129. push DX ; check drivespec (save pname ptr)
  130. mov DI, DX ; working copy of pathname
  131. mov SI, OFFSET TRANGROUP:search_curdir_buf
  132. xor DX, DX ; zero means current drive
  133. cmp BYTE PTR [DI+1],':' ; is there a drive spec?
  134. jne search_dir_check
  135. mov DL, [DI] ; get the drive byte
  136. and DL, NOT 20H ; uppercase it
  137. sub DL, '@' ; and convert to drive number
  138. search_dir_check:
  139. trap Current_Dir ; can we get the drive's current
  140. pop DX ; directory? If we can't we'll
  141. jc search_invalid_drive ; assume it's a bad drive...
  142. mov CX, search_attr ; filetypes to search for
  143. trap Find_First ; request first match, if any
  144. jc search_no_file
  145. mov search_best, search_file_not_found
  146. mov [search_best_buf], ANULL ; nothing's been found, yet
  147. search_loop:
  148. call search_ftype ; determine if .com, &c...
  149. cmp AL, search_best ; better than what we've found so far?
  150. jle search_next ; no, look for another
  151. mov search_best, AL ; found something... save its code
  152. mov SI, OFFSET TRANGROUP:fbuf.find_buf_pname
  153. mov DI, OFFSET TRANGROUP:search_best_buf
  154. mov CX, fname_max_len
  155. cld
  156. rep movsb ; save complete pathname representation
  157. cmp AL, search_com ; have we found the best of all?
  158. je search_done
  159. search_next: ; keep on looking
  160. mov CX, search_attr
  161. trap Find_Next ; next match
  162. jnc search_loop
  163. search_done: ; it's all over with...
  164. mov AL, search_best ; pick best to return with
  165. cmp ext_entered,1 ;AN005; Did user request a specific ext?
  166. jz search_exit ;AN005; no - exit
  167. mov al,ext_entered ;AN005; yes - get the real file type back
  168. mov search_best,al ;AN005; save the real file type
  169. jmp short search_exit
  170. search_invalid_drive: ; Tell the user path/drive
  171. mov DX, [search_error] ; appropriate error message
  172. invoke std_printf ; and pretend no file found
  173. search_no_file: ; couldn't find a match
  174. mov AX, search_file_not_found
  175. search_exit:
  176. popf
  177. pop SI
  178. pop DI
  179. pop DX
  180. pop CX
  181. ret
  182. ;---------------
  183. EndProc Search
  184. ;----------------------------------------------------------------------------
  185. break <Search_Ftype>
  186. ;----------------------------------------------------------------------------
  187. ; SEARCH_FTYPE determines the type of a file by examining its extension.
  188. ; ENTRY:
  189. ; fbuf -- dma buffer containing filename
  190. ; EXIT:
  191. ; AX -- file code, as given in search header
  192. ; NOTE(S):
  193. ; * Implicit assumption that NULL == search_file_not_found
  194. ;---------------
  195. ; DATA:
  196. ;---------------
  197. TRANDATA SEGMENT PUBLIC BYTE ;AC000;
  198. extrn comext:byte,exeext:byte,batext:byte
  199. trandata ends
  200. ;---------------
  201. Procedure Search_Ftype,NEAR
  202. ;---------------
  203. assume ds:trangroup, es:trangroup
  204. push DI
  205. push si
  206. mov AX, ANULL ; find the end of the filename
  207. mov DI, OFFSET TRANGROUP:fbuf.find_buf_pname
  208. mov CX, fname_max_len
  209. cld
  210. repnz scasb ; search for the terminating null
  211. jnz ftype_exit ; weird... no null byte at end
  212. sub di,5 ; . + E + X + T + NULL
  213. ;
  214. ; Compare .COM
  215. ;
  216. mov si,offset trangroup:comext
  217. mov ax,di
  218. cmpsw
  219. jnz ftype_exe
  220. cmpsw
  221. jnz ftype_exe
  222. mov AX, search_com ; success!
  223. jmp short ftype_exit
  224. ;
  225. ; Compare .EXE
  226. ;
  227. ftype_exe: ; still looking... now for '.exe'
  228. mov di,ax
  229. mov si,offset trangroup:exeext
  230. cmpsw
  231. jnz ftype_bat
  232. cmpsw
  233. jnz ftype_bat
  234. mov AX, search_exe ; success!
  235. jmp short ftype_exit
  236. ;
  237. ; Compare .BAT
  238. ;
  239. ftype_bat: ; still looking... now for '.bat'
  240. mov di,ax
  241. mov si,offset trangroup:batext
  242. cmpsw
  243. jnz ftype_fail
  244. cmpsw
  245. jnz ftype_fail
  246. mov AX, search_bat ; success!
  247. jmp short ftype_exit
  248. ftype_fail: ; file doesn't match what we need
  249. mov ax,ANULL
  250. ftype_exit:
  251. cmp ext_entered,1 ;AN005; was an extension entered?
  252. jz ftype_done ;AN005; no - exit
  253. cmp ax,ANULL ;AN005; was any match found
  254. jz ftype_done ;AN005; no - exit
  255. mov ext_entered,al ;AN005; save the match type found
  256. mov AX, search_com ;AN005; send back best was found to stop search
  257. ftype_done: ;AN005;
  258. pop SI
  259. pop DI
  260. ret
  261. ;---------------
  262. EndProc Search_Ftype
  263. ;----------------------------------------------------------------------------
  264. break <Strip>
  265. ;----------------------------------------------------------------------------
  266. ; STRIP copies the source string (argv[0]) into the destination buffer,
  267. ; replacing any extension with wildcards.
  268. ; ENTRY:
  269. ; BX -- maximum length of destination buffer
  270. ; DS:SI -- address of destination buffer
  271. ; argv[0] -- command name to be stripped
  272. ; EXIT:
  273. ; CF -- set if failure, clear if successful
  274. ; NOTE(S):
  275. ;---------------
  276. Procedure Strip,NEAR
  277. ;---------------
  278. assume ds:trangroup, es:trangroup
  279. push AX
  280. push BX
  281. push CX
  282. push DX
  283. push DI
  284. push SI
  285. pushf
  286. mov ext_entered,1 ;AN005; assume no extension on file name
  287. mov DX, DS:arg.argv[0].argpointer ; save pointer to beginning of argstring
  288. mov DI, DS:arg.argv[0].argstartel ; beginning of last pathname element
  289. cmp BYTE PTR [DI], 0 ; *STARTEL == NULL means no command
  290. jz strip_error
  291. mov CX, DX ; compute where end of argstring lies
  292. add CX, DS:arg.argv[0].arglen
  293. sub CX, DI ; and then find length of last element
  294. inc CX ; include null as well
  295. mov AL, dot ; let's find the filetype extension
  296. cld
  297. repnz scasb ; wind up pointing to either null or dot
  298. jcxz process_ext ;AN005; if no extension found, just continue
  299. mov ext_entered,0 ;AN005; we found an extension
  300. mov al,ANULL ;AN005; continue scanning until the
  301. repnz scasb ;AN005; end of line is reached.
  302. process_ext: ;AN005;
  303. mov CX, DI ; pointer to end of argstring yields
  304. sub CX, DX ; number of bytes to be copied
  305. sub BX, 4 ; can argstring fit into dest. buffer?
  306. cmp CX, BX
  307. jg strip_error ; if not, we must have a bad pathname
  308. mov DI, SI ; destination buffer
  309. mov SI, DX ; source is beginning of pathname
  310. cld
  311. rep movsb ; SI=arg,DI=buffer,CX=argend-argbeg
  312. cmp ext_entered,1 ;AN005; if an extension was entered
  313. jnz skip_wilds ;AN005; don't set up wildcard ext.
  314. dec DI ; overwrite null or dot
  315. stosb ; with a dot
  316. mov AL, wildchar ; now add wildcards
  317. stosb
  318. stosb
  319. stosb
  320. mov AL, ANULL ; and a terminating null
  321. stosb
  322. skip_wilds: ;AN005;
  323. popf
  324. clc ; chill out...
  325. jmp short strip_exit
  326. strip_error:
  327. popf
  328. stc
  329. strip_exit:
  330. pop SI
  331. pop DI
  332. pop DX
  333. pop CX
  334. pop BX
  335. pop AX
  336. ret
  337. ;---------------
  338. EndProc Strip
  339. ;----------------------------------------------------------------------------
  340. break <Save_Args>
  341. ;----------------------------------------------------------------------------
  342. ; SAVE_ARGS attempts to preserve the existing argv[]/argvcnt/argbuffer
  343. ; structure in newly allocated memory. The argv[] structure is found at the
  344. ; beginning of this area. The caller indicates how much extra space is
  345. ; needed in the resulting structure; Save_Args returns a segment number and
  346. ; an offset into that area, indicating where the caller may preserve its own
  347. ; data. Note that <argvcnt> can be found at <offset-2>.
  348. ; ENTRY:
  349. ; BX -- size (in bytes) of extra area to allocate
  350. ; EXIT:
  351. ; AX -- segment of new area.
  352. ; CF -- set if unable to save a copy.
  353. ; NOTE(S):
  354. ; 1) The allocated area will be AT LEAST the size requested -- since
  355. ; the underlying MSDOS call, <alloc> returns an integral number of
  356. ; paragraphs.
  357. ; 2) It is an error if MSDOS can't allocate AT LEAST as much memory
  358. ; as the caller of Save_Args requests.
  359. ; 3) AX is undefined if CF indicates an error.
  360. ;---------------
  361. Procedure Save_Args,NEAR
  362. ;---------------
  363. assume ds:trangroup, es:trangroup
  364. push BX
  365. push CX
  366. push DX
  367. push DI
  368. push SI
  369. push BP
  370. pushf
  371. add BX, SIZE arg_unit + 0FH ; space for arg structure, round up
  372. mov CL, 4 ; to paragraph size and convert
  373. shr BX, CL ; size in bytes to size in paragraphs
  374. trap Alloc
  375. jc save_error
  376. mov BP, AX ; save segment id
  377. push ES ; save TRANGROUP address
  378. mov ES, AX ; switch to new memory segment
  379. assume ES:nothing
  380. mov CX, SIZE arg_unit ; get back structure size
  381. xor DI, DI ; destination is new memory area
  382. mov SI, OFFSET TRANGROUP:arg ; source is arg structure
  383. rep movsb ; move it
  384. mov CX, arg.argvcnt ; adjust argv pointers
  385. xor AX, AX ; base address for argv_calc
  386. ; Bugbug: What did they mean by this?
  387. ; Note that the replacement line produces exactly the same code.
  388. ;; mov SI, OFFSET TRANGROUP:arg.argbuf - OFFSET arg_unit.argbuf
  389. mov SI, OFFSET TRANGROUP:arg
  390. save_ptr_loop:
  391. dec CX ; exhausted all args?
  392. jl save_done
  393. mov BX, CX ; get arg index and
  394. invoke argv_calc ; convert to a pointer
  395. mov DX, DS:arg.argv[BX].argpointer
  396. sub DX, SI ; adjust argpointer
  397. mov ES:argv[BX].argpointer, DX
  398. mov DX, DS:arg.argv[BX].argstartel
  399. sub DX, SI ; and adjust argstartel
  400. mov ES:argv[BX].argstartel, DX
  401. mov DX, DS:arg.argv[BX].arg_ocomptr
  402. sub DX, SI ; and adjust arg_ocomptr
  403. mov ES:argv[BX].arg_ocomptr, DX
  404. jmp save_ptr_loop
  405. save_done:
  406. pop ES ; back we go to TRANGROUP
  407. assume ES:trangroup
  408. mov AX, BP ; restore segment id
  409. jmp short save_ok
  410. save_error:
  411. popf
  412. stc
  413. jmp short save_exit
  414. save_ok:
  415. popf
  416. clc
  417. save_exit:
  418. pop BP
  419. pop SI
  420. pop DI
  421. pop DX
  422. pop CX
  423. pop BX
  424. ret
  425. ;---------------
  426. EndProc Save_Args
  427. ;----------------------------------------------------------------------------
  428. trancode ends
  429. END
  430.