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.

667 lines
14 KiB

  1. page ,132
  2. ; SCCSID = @(#)tenv.asm 4.2 85/08/16
  3. ; SCCSID = @(#)tenv.asm 4.2 85/08/16
  4. TITLE Part6 COMMAND Transient routines.
  5. ;/*
  6. ; * Microsoft Confidential
  7. ; * Copyright (C) Microsoft Corporation 1991
  8. ; * All Rights Reserved.
  9. ; */
  10. ; Environment utilities and misc. routines
  11. ;
  12. ; Revision History
  13. ; ================
  14. ;
  15. ; M024 SR 9/5/90 Zero out comspec_flag to fix bug
  16. ; #710 about comspec getting trashed.
  17. ;
  18. INCLUDE comsw.asm
  19. .xlist
  20. .xcref
  21. include dossym.inc
  22. include syscall.inc
  23. include arena.inc
  24. include comseg.asm
  25. include comequ.asm
  26. include doscntry.inc ;an000;
  27. include resmsg.equ
  28. .list
  29. .cref
  30. DATARES SEGMENT PUBLIC BYTE ;AC000;
  31. EXTRN comdrv:byte
  32. EXTRN comspec_end:word
  33. EXTRN dbcs_vector_addr:dword ;AN000;
  34. EXTRN ENVIRSEG:WORD
  35. EXTRN fucase_addr:word ;AC000;
  36. EXTRN PutBackDrv:byte
  37. EXTRN PutBackComSpec:byte
  38. EXTRN RESTDIR:BYTE
  39. DATARES ENDS
  40. TRANDATA SEGMENT PUBLIC BYTE ;AC000;
  41. EXTRN arg_buf_ptr:word
  42. EXTRN comspec:byte
  43. EXTRN comspec_flag:byte
  44. EXTRN comspecstr:byte
  45. EXTRN ENVERR_PTR:WORD
  46. EXTRN PATH_TEXT:byte
  47. EXTRN PROMPT_TEXT:byte
  48. EXTRN SYNTMES_PTR:WORD
  49. TRANDATA ENDS
  50. TRANSPACE SEGMENT PUBLIC BYTE ;AC000;
  51. EXTRN Arg_Buf:BYTE
  52. EXTRN RESSEG:WORD
  53. EXTRN USERDIR1:BYTE
  54. TRANSPACE ENDS
  55. TRANCODE SEGMENT PUBLIC byte
  56. ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING
  57. EXTRN cerror:near
  58. PUBLIC add_name_to_environment
  59. PUBLIC add_prompt
  60. PUBLIC delete_path
  61. PUBLIC find_name_in_environment
  62. PUBLIC find_path
  63. PUBLIC find_prompt
  64. PUBLIC move_name
  65. PUBLIC restudir
  66. PUBLIC restudir1
  67. PUBLIC scan_double_null
  68. PUBLIC scasb2
  69. PUBLIC store_char
  70. PUBLIC Testkanj ;AN000; 3/3/KK
  71. PUBLIC upconv
  72. PUBLIC GETENVSIZ
  73. BREAK <Environment utilities>
  74. ASSUME DS:TRANGROUP
  75. break Prompt command
  76. assume ds:trangroup,es:trangroup
  77. ADD_PROMPT:
  78. CALL DELETE_PROMPT ; DELETE ANY EXISTING PROMPT
  79. CALL SCAN_DOUBLE_NULL
  80. ADD_PROMPT2:
  81. PUSH SI
  82. CALL GETARG
  83. POP SI
  84. retz ; PRE SCAN FOR ARGUMENTS
  85. CALL MOVE_NAME ; MOVE IN NAME
  86. CALL GETARG
  87. PUSH SI
  88. JMP SHORT ADD_NAME
  89. break The SET command
  90. assume ds:trangroup,es:trangroup
  91. ;
  92. ; Input: DS:SI points to a CR terminated string
  93. ; Output: carry flag is set if no room
  94. ; otherwise name is added to environment
  95. ;
  96. DISP_ENVj:
  97. jmp DISP_ENV
  98. ADD_NAME_TO_ENVIRONMENT:
  99. CALL GETARG
  100. JZ DISP_ENVj
  101. ;
  102. ; check if line contains exactly one equals sign
  103. ;
  104. XOR BX,BX ;= COUNT IS 0
  105. PUSH SI ;SAVE POINTER TO BEGINNING OF LINE
  106. EQLP:
  107. LODSB ;GET A CHAR
  108. CMP AL,13 ;IF CR WE'RE ALL DONE
  109. JZ QUEQ
  110. CMP AL,'=' ;LOOK FOR = SIGN
  111. JNZ EQLP ;NOT THERE, GET NEXT CHAR
  112. INC BL ;OTHERWISE INCREMENT EQ COUNT
  113. CMP BYTE PTR [SI],13 ;LOOK FOR CR FOLLOWING = SIGN
  114. JNZ EQLP
  115. INC BH ;SET BH=1 MEANS NO PARAMETERS
  116. JMP EQLP ;AND LOOK FOR MORE
  117. QUEQ:
  118. POP SI ;RESTORE BEGINNING OF LINE
  119. DEC BL ;ZERO FLAG MEANS ONLY ONE EQ
  120. JZ ONEQ ;GOOD LINE
  121. MOV DX,OFFSET TRANGROUP:SYNTMES_ptr
  122. JMP CERROR
  123. ONEQ:
  124. PUSH BX
  125. CALL DELETE_NAME_IN_ENVIRONMENT
  126. POP BX
  127. DEC BH
  128. retz
  129. CALL SCAN_DOUBLE_NULL
  130. mov bx,di ; Save ptr to beginning of env var name
  131. CALL MOVE_NAME
  132. push si
  133. xchg bx,di ; Switch ptrs to beginning and end of
  134. ; env var name
  135. ;
  136. ; We want to special-case COMSPEC. This is to reduce the amount of code
  137. ; necessary in the resident for re-reading the transient. Let's look for
  138. ; COMSPEC=
  139. ;
  140. mov comspec_flag,0 ; clear flag ; M024
  141. mov si,offset trangroup:comspecstr ; Load ptr to string "COMSPEC"
  142. mov cx,4 ; If the new env var is comspec, set
  143. repz cmpsw ; the comspec_flag
  144. ;
  145. ; Zero set => exact match
  146. ;
  147. jnz not_comspec
  148. inc comspec_flag ; comspec is changing ; M024
  149. not_comspec:
  150. mov di,bx ; Load ptr to end of env var name
  151. ADD_NAME: ; Add the value of the new env var
  152. pop si ; to the environment.
  153. push si
  154. add_name1:
  155. LODSB
  156. CMP AL,13
  157. jz add_name_ret
  158. CALL STORE_CHAR
  159. JMP ADD_NAME1
  160. add_name_ret:
  161. pop si
  162. cmp comspec_flag,0 ; If the new env var is comspec,
  163. retz ; copy the value into the
  164. ;
  165. ; We have changed the COMSPEC variable. We need to update the resident
  166. ; pieces necessary to reread in the info. First, skip all delimiters
  167. ;
  168. invoke ScanOff
  169. mov es,[resseg] ; comspec var in the resident
  170. assume es:resgroup
  171. ;
  172. ; Make sure that the printer knows where the beginning of the string is
  173. ;
  174. mov di,offset resgroup:comspec
  175. mov bx,di
  176. ;
  177. ; Generate drive letter for display
  178. ;
  179. xor ax,ax ;g assume no drive first
  180. mov comdrv,al ;g
  181. push ax ;AN000; 3/3/KK
  182. mov al,[si] ;AN000; 3/3/KK
  183. call testkanj ;AN000; 3/3/KK
  184. pop ax ;AN000; 3/3/KK
  185. jnz GotDrive
  186. cmp byte ptr [si+1],':' ; drive specified?
  187. jnz GotDrive
  188. mov al,[si] ; get his specified drive
  189. call UpConv ; convert to uppercase
  190. sub al,'A' ; convert to 0-based
  191. add di,2
  192. inc al ; convert to 1-based number
  193. mov comdrv,al
  194. ;
  195. ; Stick the drive letter in the prompt message. Nothing special needs to be
  196. ; done here..
  197. ;
  198. add al,'A'-1
  199. GotDrive: ;g
  200. mov PutBackComSpec.SubstPtr,di ;g point to beginning of name after drive
  201. mov es:PutBackDrv,al
  202. ;
  203. ; Copy chars until delim
  204. ;
  205. mov di,bx
  206. copy_comspec:
  207. lodsb
  208. invoke Delim
  209. jz CopyDone
  210. cmp al,13
  211. jz CopyDone
  212. stosb
  213. jmp short copy_comspec
  214. CopyDone:
  215. xor al,al ; Null terminate the string and quit
  216. stosb
  217. mov comspec_flag,0
  218. dec di
  219. mov comspec_end,di
  220. ret
  221. DISP_ENV:
  222. MOV DS,[RESSEG]
  223. ASSUME DS:RESGROUP
  224. MOV DS,[ENVIRSEG]
  225. ASSUME DS:NOTHING
  226. XOR SI,SI
  227. PENVLP:
  228. CMP BYTE PTR [SI],0
  229. retz
  230. mov di,offset trangroup:arg_buf
  231. PENVLP2:
  232. LODSB
  233. stosb
  234. OR AL,AL
  235. JNZ PENVLP2
  236. mov dx,offset trangroup:arg_buf_ptr
  237. push ds
  238. push es
  239. pop ds
  240. invoke printf_crlf
  241. pop ds
  242. JMP PENVLP
  243. ASSUME DS:TRANGROUP
  244. DELETE_PATH:
  245. MOV SI,OFFSET TRANGROUP:PATH_TEXT
  246. JMP SHORT DELETE_NAME_IN_environment
  247. DELETE_PROMPT:
  248. MOV SI,OFFSET TRANGROUP:PROMPT_TEXT
  249. DELETE_NAME_IN_environment:
  250. ;
  251. ; Input: DS:SI points to a "=" terminated string
  252. ; Output: carry flag is set if name not found
  253. ; otherwise name is deleted
  254. ;
  255. PUSH SI
  256. PUSH DS
  257. CALL FIND ; ES:DI POINTS TO NAME
  258. JC DEL1
  259. MOV SI,DI ; SAVE IT
  260. CALL SCASB2 ; SCAN FOR THE NUL
  261. XCHG SI,DI
  262. ;SR;
  263. ; If we have only one env string, then the double null is lost when the last
  264. ;string is deleted and we have an invalid empty environment with only a
  265. ;single null. To avoid this, we will look for the double null case and then
  266. ;move an extra null char.
  267. ; Bugbug: The only possible problem is that the last pathstring
  268. ;will be followed by a triple null. Is this really a problem?
  269. ;
  270. cmp byte ptr es:[si],0 ;null char?
  271. jnz not_dnull ;no, we are at a double null
  272. dec si ;point at the double null
  273. not_dnull:
  274. CALL GETENVSIZ
  275. SUB CX,SI
  276. PUSH ES
  277. POP DS ; ES:DI POINTS TO NAME, DS:SI POINTS TO NEXT NAME
  278. REP MOVSB ; DELETE THE NAME
  279. DEL1:
  280. POP DS
  281. POP SI
  282. return
  283. FIND_PATH:
  284. MOV SI,OFFSET TRANGROUP:PATH_TEXT
  285. JMP SHORT FIND_NAME_IN_environment
  286. FIND_PROMPT:
  287. MOV SI,OFFSET TRANGROUP:PROMPT_TEXT
  288. FIND_NAME_IN_environment:
  289. ;
  290. ; Input: DS:SI points to a "=" terminated string
  291. ; Output: ES:DI points to the arguments in the environment
  292. ; zero is set if name not found
  293. ; carry flag is set if name not valid format
  294. ;
  295. CALL FIND ; FIND THE NAME
  296. retc ; CARRY MEANS NOT FOUND
  297. JMP SCASB1 ; SCAN FOR = SIGN
  298. ;
  299. ; On return of FIND1, ES:DI points to beginning of name
  300. ;
  301. FIND:
  302. CLD
  303. CALL COUNT0 ; CX = LENGTH OF NAME
  304. MOV ES,[RESSEG]
  305. ASSUME ES:RESGROUP
  306. MOV ES,[ENVIRSEG]
  307. ASSUME ES:NOTHING
  308. XOR DI,DI
  309. FIND1:
  310. PUSH CX
  311. PUSH SI
  312. PUSH DI
  313. FIND11:
  314. LODSB
  315. CALL TESTKANJ
  316. JZ NOTKANJ3
  317. DEC SI
  318. LODSW
  319. INC DI
  320. INC DI
  321. CMP AX,ES:[DI-2]
  322. JNZ FIND12
  323. DEC CX
  324. LOOP FIND11
  325. JMP SHORT FIND12
  326. NOTKANJ3:
  327. CALL UPCONV
  328. INC DI
  329. CMP AL,ES:[DI-1]
  330. JNZ FIND12
  331. LOOP FIND11
  332. FIND12:
  333. POP DI
  334. POP SI
  335. POP CX
  336. retz
  337. PUSH CX
  338. CALL SCASB2 ; SCAN FOR A NUL
  339. POP CX
  340. CMP BYTE PTR ES:[DI],0
  341. JNZ FIND1
  342. STC ; INDICATE NOT FOUND
  343. return
  344. COUNT0:
  345. PUSH DS
  346. POP ES
  347. MOV DI,SI
  348. COUNT1:
  349. PUSH DI ; COUNT NUMBER OF CHARS UNTIL "="
  350. CALL SCASB1
  351. JMP SHORT COUNTX
  352. COUNT2:
  353. PUSH DI ; COUNT NUMBER OF CHARS UNTIL NUL
  354. CALL SCASB2
  355. COUNTX:
  356. POP CX
  357. SUB DI,CX
  358. XCHG DI,CX
  359. return
  360. MOVE_NAME:
  361. CMP BYTE PTR DS:[SI],13
  362. retz
  363. LODSB
  364. ;;;; IFDEF DBCS 3/3/KK
  365. CALL TESTKANJ
  366. JZ NOTKANJ1
  367. CALL STORE_CHAR
  368. LODSB
  369. CALL STORE_CHAR
  370. JMP SHORT MOVE_NAME
  371. NOTKANJ1:
  372. ;;;; ENDIF 3/3/KK
  373. CALL UPCONV
  374. CALL STORE_CHAR
  375. CMP AL,'='
  376. JNZ MOVE_NAME
  377. return
  378. GETARG:
  379. MOV SI,80H
  380. LODSB
  381. OR AL,AL
  382. retz
  383. invoke SCANOFF
  384. CMP AL,13
  385. return
  386. ;
  387. ; Point ES:DI to the final NULL string. Note that in an empty environment,
  388. ; there is NO double NULL, merely a string that is empty.
  389. ;
  390. SCAN_DOUBLE_NULL:
  391. MOV ES,[RESSEG]
  392. ASSUME ES:RESGROUP
  393. MOV ES,[ENVIRSEG]
  394. ASSUME ES:NOTHING
  395. XOR DI,DI
  396. ;
  397. ; Top cycle-point. If the string here is empty, then we are done
  398. ;
  399. SDN1:
  400. cmp byte ptr es:[di],0 ; nul string?
  401. retz ; yep, all done
  402. CALL SCASB2
  403. JMP SDN1
  404. SCASB1:
  405. MOV AL,'=' ; SCAN FOR AN =
  406. JMP SHORT SCASBX
  407. SCASB2:
  408. XOR AL,AL ; SCAN FOR A NUL
  409. SCASBX:
  410. MOV CX,1000H
  411. REPNZ SCASB
  412. return
  413. ;Bugbug: This is Kanji stuff - put it in conditionals
  414. TESTKANJ:
  415. push ds ;AN000; 3/3/KK
  416. push si ;AN000; 3/3/KK
  417. push ax ;AN000; 3/3/KK
  418. mov ds,cs:[resseg] ;AN000; Get resident segment
  419. assume ds:resgroup ;AN000;
  420. lds si,dbcs_vector_addr ;AN000; get DBCS vector
  421. ktlop: ;AN000; 3/3/KK
  422. cmp word ptr ds:[si],0 ;AN000; end of Table 3/3/KK
  423. je notlead ;AN000; 3/3/KK
  424. pop ax ;AN000; 3/3/KK
  425. push ax ;AN000; 3/3/KK
  426. cmp al, byte ptr ds:[si] ;AN000; 3/3/KK
  427. jb notlead ;AN000; 3/3/KK
  428. inc si ;AN000; 3/3/KK
  429. cmp al, byte ptr ds:[si] ;AN000; 3/3/KK
  430. jbe islead ;AN000; 3/3/KK
  431. inc si ;AN000; 3/3/KK
  432. jmp short ktlop ;AN000; try another range ; 3/3/KK
  433. Notlead: ;AN000; 3/3/KK
  434. xor ax,ax ;AN000; set zero 3/3/KK
  435. jmp short ktret ;AN000; 3/3/KK
  436. Islead: ;AN000; 3/3/KK
  437. xor ax,ax ;AN000; reset zero 3/3/KK
  438. inc ax ;AN000; 3/3/KK
  439. ktret: ;AN000; 3/3/KK
  440. pop ax ;AN000; 3/3/KK
  441. pop si ;AN000; 3/3/KK
  442. pop ds ;AN000; 3/3/KK
  443. return ;AN000; 3/3/KK
  444. ;------------------------------------- ;3/3/KK
  445. ; ****************************************************************
  446. ; *
  447. ; * ROUTINE: UPCONV (ADDED BY EMG 4.00)
  448. ; *
  449. ; * FUNCTION: This routine returns the upper case equivalent of
  450. ; * the character in AL from the file upper case table
  451. ; * in DOS if character if above ascii 128, else
  452. ; * subtracts 20H if between "a" and "z".
  453. ; *
  454. ; * INPUT: AL char to be upper cased
  455. ; * FUCASE_ADDR set to the file upper case table
  456. ; *
  457. ; * OUTPUT: AL upper cased character
  458. ; *
  459. ; ****************************************************************
  460. assume ds:trangroup ;AN000;
  461. upconv proc near ;AN000;
  462. cmp al,80h ;AN000; see if char is > ascii 128
  463. jb oth_fucase ;AN000; no - upper case math
  464. sub al,80h ;AN000; only upper 128 chars in table
  465. push ds ;AN000;
  466. push bx ;AN000;
  467. mov ds,[resseg] ;AN000; get resident data segment
  468. assume ds:resgroup ;AN000;
  469. lds bx,dword ptr fucase_addr+1 ;AN000; get table address
  470. add bx,2 ;AN000; skip over first word
  471. xlat ds:byte ptr [bx] ;AN000; convert to upper case
  472. pop bx ;AN000;
  473. pop ds ;AN000;
  474. assume ds:trangroup ;AN000;
  475. jmp short upconv_end ;AN000; we finished - exit
  476. oth_fucase: ;AN000;
  477. cmp al,small_a ;AC000; if between "a" and "z",
  478. jb upconv_end ;AC000; subtract 20h to get
  479. cmp al,small_z ;AC000; upper case equivalent.
  480. ja upconv_end ;AC000;
  481. sub al,20h ;AC000; Change lower-case to upper
  482. upconv_end: ;AN000;
  483. ret
  484. upconv endp ;AN000;
  485. ;
  486. ; STORE A CHAR IN environment, GROWING IT IF NECESSARY
  487. ;
  488. STORE_CHAR:
  489. PUSH CX
  490. PUSH BX
  491. PUSH ES ;AN056;
  492. PUSH DS ;AN056; Save local DS
  493. MOV DS,[RESSEG] ;AN056; Get resident segment
  494. ASSUME DS:RESGROUP ;AN056;
  495. MOV ES,[ENVIRSEG] ;AN056; Get environment segment
  496. ASSUME ES:NOTHING ;AN056;
  497. POP DS ;AN056; Get local segment back
  498. ASSUME DS:TRANGROUP ;AN056;
  499. CALL GETENVSIZ
  500. MOV BX,CX
  501. SUB BX,2 ; SAVE ROOM FOR DOUBLE NULL
  502. CMP DI,BX
  503. JB STORE1
  504. PUSH AX
  505. PUSH CX
  506. PUSH BX ; Save Size of environment
  507. invoke FREE_TPA
  508. POP BX
  509. ADD BX,2 ; Recover true environment size
  510. CMP BX, 8000H ; Don't let environment grow > 32K
  511. JB ENVSIZ_OK
  512. BAD_ENV_SIZE: ;AN056;
  513. STC
  514. JMP SHORT ENVNOSET
  515. ENVSIZ_OK:
  516. MOV CL,4
  517. SHR BX,CL ; Convert back to paragraphs
  518. INC BX ; Try to grow environment by one para
  519. MOV CX,ES ;AN056; Get environment segment
  520. ADD CX,BX ;AN056; Add in size of environment
  521. ADD CX,020H ;AN056; Add in some TPA
  522. MOV AX,CS ;AN056; Get the transient segment
  523. CMP CX,AX ;AN056; Are we hitting the transient?
  524. JNB BAD_ENV_SIZE ;AN056; Yes - don't do it!!!
  525. MOV AH,SETBLOCK
  526. INT 21h
  527. ENVNOSET:
  528. PUSHF
  529. PUSH ES
  530. MOV ES,[RESSEG]
  531. invoke ALLOC_TPA
  532. POP ES
  533. POPF
  534. POP CX
  535. POP AX
  536. JNC STORE1
  537. POP ES ;AN056;
  538. MOV DX,OFFSET TRANGROUP:ENVERR_ptr
  539. JMP CERROR
  540. STORE1:
  541. STOSB
  542. MOV WORD PTR ES:[DI],0 ; NULL IS AT END
  543. POP ES ;AN056;
  544. POP BX
  545. POP CX
  546. return
  547. GETENVSIZ:
  548. ;Get size of environment in bytes, rounded up to paragraph boundry
  549. ;ES has environment segment
  550. ;Size returned in CX, all other registers preserved
  551. PUSH ES
  552. PUSH AX
  553. MOV AX,ES
  554. DEC AX ;Point at arena
  555. MOV ES,AX
  556. MOV AX,ES:[arena_size]
  557. MOV CL,4
  558. SHL AX,CL ;Convert to bytes
  559. MOV CX,AX
  560. POP AX
  561. POP ES
  562. return
  563. ASSUME DS:TRANGROUP
  564. RESTUDIR1:
  565. PUSH DS
  566. MOV DS,[RESSEG]
  567. ASSUME DS:RESGROUP
  568. CMP [RESTDIR],0
  569. POP DS
  570. ASSUME DS:TRANGROUP
  571. retz
  572. RESTUDIR:
  573. MOV DX,OFFSET TRANGROUP:USERDIR1
  574. MOV AH,CHDIR
  575. INT 21h ; Restore users DIR
  576. XOR AL,AL
  577. invoke SETREST
  578. RET56:
  579. return
  580. trancode ends
  581. end
  582.