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.

2695 lines
75 KiB

  1. page ,132
  2. title COMMAND Initialization
  3. ;/*
  4. ; * Microsoft Confidential
  5. ; * Copyright (C) Microsoft Corporation 1991
  6. ; * All Rights Reserved.
  7. ; */
  8. ;
  9. ; Revision History
  10. ; ================
  11. ; M002 SR 07/15/90 Resize right at the start because
  12. ; Carousel depends on it.
  13. ;
  14. ; M004 SR 07/17/90 Initialization reworked so that
  15. ; transient is now moved at EndInit.
  16. ; The old approach assumed that the
  17. ; biggest block is the one currently
  18. ; loaded in, an assumption not true
  19. ; for UMBs.
  20. ;
  21. ; M005 SR 07/20/90 Numerous hacks for Carousel
  22. ; 1. Set CurrentPDB to ours at start
  23. ; 2. Normalize cs:ip of int 2fh hook
  24. ; so that cs is different.
  25. ;
  26. ; M013 SR 08/06/90 Fixed Setup_res_end & Move_res_code
  27. ; to use new GetVersion call that
  28. ; returns info about whether DOS is in
  29. ; HMA or not.
  30. ;
  31. ; M015 SR 08/09/90 Increased default environment size to
  32. ; 256 bytes from 160 bytes
  33. ;
  34. ; M026 SR 9/12/90 Fixed environment trashing on second
  35. ; Command if new comspec is given.
  36. ;
  37. ; M030 SR 10/3/90 Before calling int 2fh 4a02h, set di
  38. ; to 0ffffh so that we are ok if no one
  39. ; answers this int 2fh.
  40. ;
  41. ; M042 SR 12/13/90 Bug #4660. Changed setup_res_end to
  42. ; take care of the dummy segment that
  43. ; adds a para to the resident size.
  44. ;
  45. .xlist
  46. .xcref
  47. include comsw.asm
  48. include dossym.inc
  49. include pdb.inc
  50. include mult.inc
  51. include syscall.inc
  52. include doscntry.inc
  53. include comseg.asm
  54. include comequ.asm
  55. include resmsg.equ
  56. include envdata.asm
  57. include xmm.inc
  58. include cmdsvc.inc
  59. include dossvc.inc
  60. .list
  61. .cref
  62. ENVBIG equ 32768
  63. ENVSML equ 256 ;Increased to 256 ; M015
  64. KOREA_COUNTRY_CODE equ 82
  65. CODERES segment public byte
  66. extrn ContC :near
  67. extrn DskErr :near
  68. extrn Int_2e :near
  69. extrn LodCom :near
  70. extrn MsgInt2fHandler :far
  71. extrn SetVect :near
  72. extrn ChkSum :near
  73. extrn CrLf :near
  74. extrn LoadCom :near
  75. extrn RPrint :near
  76. ifdef BILINGUAL
  77. extrn RPrint@ :near
  78. endif ; BILINGUAL
  79. extrn EndCode :byte
  80. extrn StartCode :byte
  81. ifdef DBCS
  82. extrn ItestKanj :near
  83. endif
  84. extrn BadMemErr :near
  85. CODERES ends
  86. DATARES segment public byte
  87. extrn Abort_Char :byte
  88. extrn AccDen :byte
  89. extrn Append_State :word
  90. extrn Batch :word
  91. extrn Com_Fcb1 :dword
  92. extrn Com_Fcb2 :dword
  93. extrn Com_Ptr :dword
  94. extrn ComDrv :byte
  95. extrn ComSpec :byte
  96. extrn ComSpec_End :word
  97. extrn Crit_Msg_Off :word
  98. extrn Crit_Msg_Seg :word
  99. extrn DataResEnd :byte
  100. extrn Dbcs_Vector_Addr :word
  101. extrn EchoFlag :byte
  102. extrn EnvirSeg :word
  103. extrn ExtMsgEnd :byte
  104. extrn fFail :byte
  105. extrn FUCase_addr :word
  106. extrn InitFlag :byte
  107. extrn Int2fHandler :dword
  108. extrn Io_Save :word
  109. extrn Io_Stderr :byte
  110. extrn LTpa :word
  111. extrn MemSiz :word
  112. extrn MySeg :word
  113. extrn MySeg1 :word
  114. extrn MySeg2 :word
  115. extrn MySeg3 :word
  116. extrn Nest :word
  117. extrn OldTerm :dword
  118. extrn Parent :word
  119. extrn ParseMes_Ptr :word
  120. extrn ParsMsgPtrs :word
  121. extrn PermCom :byte
  122. extrn PutBackDrv :byte
  123. extrn PutBackComSpec :byte
  124. extrn RDirChar :byte
  125. extrn Res_Tpa :word
  126. extrn ResMsgEnd :word
  127. extrn RSwitChar :byte
  128. extrn SingleCom :word
  129. extrn KSwitchFlag :byte
  130. extrn Sum :word
  131. extrn TrnSeg :word
  132. extrn TrnMvFlg :byte
  133. extrn ResSize :word
  134. extrn RStack :word
  135. extrn ComInHMA :byte ;flag set if in HMA
  136. extrn XMMCallAddr :dword ;far call address to XMM
  137. EXTRN SCS_CMDPROMPT :BYTE
  138. EXTRN SCS_DOSONLY :BYTE
  139. ;
  140. ;All far pointers to resident routines that are to be patched
  141. ;
  142. extrn Int2f_Entry :dword
  143. extrn Int2e_Entry :dword
  144. extrn Ctrlc_Entry :dword
  145. extrn CritErr_Entry :dword
  146. extrn Int2f_Trap :near
  147. extrn Int2e_Trap :near
  148. extrn Ctrlc_Trap :near
  149. extrn CritErr_Trap :near
  150. extrn LodCom_Trap :near
  151. EXTRN SCS_PAUSE:BYTE ; yst
  152. extrn EndInit :near
  153. extrn Carousel_i2f_Hook :byte ; M005
  154. extrn SCS_REENTERED :byte
  155. extrn SCS_FIRSTCOM :byte
  156. ifdef BETA3WARN
  157. %out Take this out before we ship
  158. extrn Beta3Warned:byte
  159. endif
  160. DATARES ends
  161. ;;ENVIRONMENT segment public para ; default COMMAND environment
  162. ;;
  163. ;; extrn EComSpec :byte
  164. ;; extrn EnvirEnd :byte
  165. ;; extrn PathString :byte
  166. ;;
  167. ;;ENVIRONMENT ends
  168. TAIL segment public para
  169. extrn TranStart :word
  170. TAIL ends
  171. TRANCODE segment public byte
  172. extrn DatInit :far
  173. TRANCODE ends
  174. TRANDATA segment
  175. extrn TranDataEnd :byte
  176. TRANDATA ends
  177. TRANSPACE segment public byte
  178. extrn TranSpaceEnd :byte
  179. TRANSPACE ends
  180. ; *******************************************************************
  181. ; START OF INIT PORTION
  182. ; This code is deallocated after initialization.
  183. INIT SEGMENT PUBLIC PARA
  184. ;NTVDM not used extrn AutoBat :byte
  185. extrn BadComAccMsg :byte
  186. extrn BadComLkMsg :byte
  187. extrn Badcspfl :byte
  188. extrn BadVerMsg :byte
  189. extrn Chuckenv :byte
  190. extrn Command_?_syn :byte
  191. extrn Command_c_syn :byte
  192. extrn Command_d_syn :byte
  193. extrn Command_e_syn :byte
  194. extrn Command_f_syn :byte
  195. extrn Command_k_syn :byte
  196. extrn Command_l_syn :byte
  197. extrn Command_l2_syn :byte
  198. extrn Command_m_syn :byte
  199. extrn Command_u_syn :byte
  200. extrn Command_p_syn :byte
  201. extrn Command_y_syn :byte
  202. extrn Command_z_syn :byte
  203. extrn Comnd1_syn :word
  204. extrn Comnd1_addr :dword
  205. extrn ComSpect :byte
  206. extrn ComspString :byte
  207. extrn CopyrightMsg :byte
  208. extrn Dswitch :byte
  209. ;; extrn Ecomloc :word
  210. extrn EnvMax :word
  211. extrn EnvSiz :word
  212. extrn EqualSign :byte
  213. extrn Eswitch :byte
  214. extrn Ext_msg :byte
  215. extrn HelpMsgs:word
  216. extrn InitAdd :dword
  217. extrn InitEnd :word
  218. extrn Init_Parse :dword
  219. extrn Internat_Info :byte
  220. ; NTVDM not used extrn KautoBat :byte
  221. extrn Lcasea :byte
  222. extrn Lcasez :byte
  223. extrn Num_positionals :word
  224. extrn OldEnv :word
  225. extrn Old_parse_ptr :word
  226. extrn OutEnvMsg :byte
  227. extrn Parse_command :byte
  228. extrn PrdAttm :byte
  229. extrn ResetEnv :word
  230. extrn Scswitch :byte
  231. extrn Skswitch :byte
  232. extrn Space :byte
  233. extrn Triage_Add :dword
  234. extrn TrnSize :word
  235. extrn Ucasea :byte
  236. extrn UsedEnv :word
  237. extrn PathString :byte
  238. extrn ComspString :byte
  239. extrn Reloc_Table :word
  240. extrn FirstCom :byte
  241. extrn ResJmpTable :dword
  242. extrn TriageError :near
  243. extrn NUM_RELOC_ENTRIES :abs
  244. extrn DevFlag :byte
  245. extrn PathFlag :byte
  246. PUBLIC ConProc
  247. PUBLIC Init_ContC_SpecialCase
  248. assume cs:ResGroup,ds:ResGroup,es:ResGroup,ss:ResGroup
  249. org 0
  250. ZERO = $
  251. ConProc:
  252. mov sp,offset ResGroup:RStack ; must be first instruction
  253. ;
  254. ; M005; We need to set the PSP to us right at start because Carousel needs
  255. ; M005; to be lied to and it does not set PSP when it transfers control to
  256. ; M005; us after loading us as an overlay. By setting PSP, we ensure that
  257. ; M005; command.com is also not lied to.
  258. ;
  259. mov ah,SET_CURRENT_PDB ; M005
  260. mov bx,es ; M005
  261. int 21h ; M005
  262. mov ah,GET_VERSION
  263. int 21h
  264. cmp ax,EXPECTED_VERSION
  265. je OkDos ; DOS version is ok
  266. mov dx,offset ResGroup:BadVerMsg ; DX = ptr to msg
  267. call RPrint
  268. mov ax,es
  269. cmp es:PDB_Parent_Pid,ax ; if COMMAND is own parent,
  270. Here: jnz GoExit ; loop forever
  271. SVC SVC_DEMEXITVDM
  272. GoExit:
  273. int 20h ; otherwise, exit
  274. okdos:
  275. ;
  276. ; Calculate and save the end of the INIT segment (which is also
  277. ; the beginning of TRANGROUP).
  278. ;
  279. mov dx,offset resgroup:TranStart+15 ;eg get end of init code
  280. mov cl,4 ;eg change to paragraphs
  281. shr dx,cl ;eg
  282. mov ax,cs ;eg get current segment
  283. add ax,dx ;eg calculate segment of end of init
  284. mov InitEnd,ax ;eg save this
  285. SAVE <SI,BP>
  286. xor si,si
  287. xor bp,bp
  288. mov al,5 ; query cmdprompt
  289. mov ah,setdpb
  290. int 21h
  291. mov byte ptr [scs_cmdprompt],al ; ds is resseg
  292. mov al,7 ; query DOSONLY bit
  293. mov ah,setdpb
  294. int 21h
  295. mov byte ptr [scs_dosonly],al ; ds is resseg
  296. RESTORE <BP,SI>
  297. ;
  298. ; Check for /? on the command line. If found, display help text
  299. ; and exit.
  300. ;
  301. ; NOTE: this routine may terminate the program, never returning.
  302. ;
  303. call CheckHelp
  304. call CheckZSwitch
  305. ;SR;
  306. ; We have to patch the segment values for the various interrupt entry points.
  307. ;This is because we need to have the default addresses of the handlers in our
  308. ;stub before the relocation is done. These values will then be changed once
  309. ;the resident is relocated
  310. ;
  311. call patch_segs
  312. ;
  313. ; Turn APPEND off during initialization processing
  314. ;
  315. mov ax,APPENDINSTALL ; see if append installed
  316. int 2fh ;
  317. cmp al,0 ; append installed?
  318. je set_msg_addr ; no - continue
  319. mov ax,APPENDDOS ; see if append DOS version right
  320. int 2fh ;
  321. cmp ax,-1 ; append version correct?
  322. jne set_msg_addr ; no - continue
  323. mov ax,APPENDGETSTATE ; Get the state of Append
  324. int 2fh ;
  325. mov Append_State,bx ; save append state
  326. xor bx,bx ; clear out state
  327. mov ax,APPENDSETSTATE ; Set the state of Append
  328. int 2fh ; set everything off
  329. set_msg_addr:
  330. mov di,offset resgroup:DataresEnd ; get address of resident end
  331. mov ResMsgEnd,di ; save it
  332. call get_XMMAddr ;get XMM call address
  333. ;
  334. ;Check if this is the first instance of command.com. If not, we just exit
  335. ;this routine without moving any code.
  336. ;After the int 2fh, ds:si points at the resident jump table in the previous
  337. ;stub. We just have to copy this over
  338. ;
  339. mov ax,GET_COMMAND_STATE
  340. int 2fh
  341. assume ds:nothing
  342. or ax,ax
  343. jnz first_com ;this is the first instance
  344. ifdef BETA3WARN
  345. %out Take this out before we ship
  346. mov es:Beta3Warned, 0ffh
  347. endif
  348. mov word ptr es:ResJmpTable,si ;save old stub jump table
  349. mov word ptr es:ResJmpTable+2,ds
  350. jmp short init_cntry
  351. first_com:
  352. mov es:FirstCom,1 ;indicate first command.com
  353. mov SCS_FIRSTCOM,1
  354. init_cntry:
  355. push es
  356. pop ds
  357. assume ds:RESGROUP
  358. mov ah,GETEXTCNTRY ; get extended country info
  359. mov al,4 ; get file ucase table
  360. mov dx,-1 ;
  361. mov bx,-1 ;
  362. mov cx,5 ; number of bytes we want
  363. mov di,offset resgroup:Fucase_addr ; buffer for address
  364. int 21h ;
  365. ; Bugbug: conditionalize dbcs_vector stuff?
  366. push ds ;
  367. mov ax, (ECS_CALL shl 8) or GETLEADBTBL ;
  368. int 21h ;
  369. mov bx,ds ; get segment to bx
  370. pop ds ;
  371. mov Dbcs_vector_addr,si ; save address of
  372. mov Dbcs_vector_addr+2,bx ; dbcs vector
  373. mov ax,word ptr ds:PDB_Parent_Pid ; Init PARENT so we can exit
  374. mov Parent,ax ; correctly.
  375. mov ax,word ptr ds:Pdb_Exit
  376. mov word ptr OldTerm,ax
  377. mov ax,word ptr ds:Pdb_Exit+2
  378. mov word ptr Oldterm+2,ax
  379. mov ax,offset ResGroup:EndCode + 15
  380. mov cl,4 ; ax = size of resident part of
  381. shr ax,cl ; command in paragraphs. Add
  382. mov cx,cs ; this to CS and you get the
  383. add ax,cx ; segment of the TPA.
  384. mov Res_tpa, ax ; Temporarily save the TPA segment
  385. and ax, 0f000h
  386. add ax, 01000h ; Round up to next 64K boundary
  387. jnc TpaSet ; Memory wrap if carry set
  388. mov ax, Res_tpa
  389. TpaSet:
  390. mov Ltpa,ax ; Good enough for the moment
  391. mov ax,word ptr ds:PDB_Block_Len ; ax = # of paras given to command
  392. mov Myseg1,ds ; These 3 variables are used as part of
  393. mov Myseg2,ds ; 3 long ptrs that the transient will
  394. mov Myseg,ds ; use to call resident routines.
  395. mov Myseg3,ds ; segment of msg retriever routine
  396. mov Memsiz,ax ; Needed for execing other programs
  397. ; M002;
  398. ; M002; First reallocate the COMMAND size to its memory image
  399. ; M002;
  400. push ax ; M002
  401. mov bx,offset RESGROUP:TranStart ; M002
  402. add bx,offset TRANGROUP:TranSpaceEnd; M002
  403. add bx,15 ; M002; round up the size
  404. mov cl,4 ; M002
  405. shr bx,cl ;size of command.com ; M002
  406. mov ah,SETBLOCK ;free all memory above pgm ; M002
  407. int 21h ; M002
  408. pop ax ; M002
  409. ;
  410. ; Compute maximum size of environment
  411. ;
  412. mov EnvMax,(Environsiz + 15) / 16 + (EnvMaximum-zero + 15)/16 - 1
  413. ;
  414. ; Compute minimum size of environment
  415. ;
  416. mov EnvSiz, ENVSML / 16
  417. mov dx,offset TranGroup:Transpaceend + 15 ; dx = size of transient
  418. mov cl,4 ; in paragraphs.
  419. shr dx,cl
  420. mov Trnsize,dx ;eg save size of transient in paragraphs
  421. sub ax,dx ; max seg addr - # para's needed for transient
  422. mov Trnseg,ax ; = seg addr to load the transient at.
  423. mov ax,ds:PDB_Environ ; ax = environment segment
  424. or ax,ax ; if there is no environment segment,
  425. jz buildenv ; go compute one.
  426. inc byte ptr Chuckenv ; flag no new environseg to set up
  427. jmp short environpassed ; otherwise one was passed to us.
  428. buildenv: ; (this label isn't very accurate)
  429. ;
  430. ;We allocate a buffer here just large enough to hold the 'PATH=' and
  431. ;the COMSPEC. After parsing, we will allocate an environment of the right
  432. ;size and free this buffer. We need this buffer because we no longer have an
  433. ;ENVIRONMENT segment but need a place to store the COMSPEC which can be
  434. ;given on the command line before we know the environment size. This routine
  435. ;will not return in case of an allocation error. It will either exit or hang
  436. ;depending on whether or not this is the first COMMAND.COM or not.
  437. ;
  438. call alloc_env ;try to allocate buffer
  439. ;; mov ax,offset ResGroup:PathString ; compute the segment of the
  440. ;; mov cl,4 ; environment and put it in
  441. ;; shr ax,cl ; ax.
  442. ;; mov dx,ds
  443. ;; add ax,dx
  444. environpassed:
  445. mov Envirseg,ax ; save the environment's segment and
  446. mov es,ax ; load into es.
  447. assume es:nothing
  448. gottheenvir:
  449. ;
  450. ; initialize the command drive
  451. ;
  452. mov ah,GET_DEFAULT_DRIVE
  453. int 21h
  454. inc al
  455. mov Comdrv,al
  456. mov al,byte ptr ds:Fcb ; al = default drive number for command
  457. or al,al
  458. jz nocomdrv ; no drive specified
  459. mov ah,':'
  460. mov Comdrv,al
  461. add al,40h ; convert number to uppercase character
  462. std
  463. cmp byte ptr Chuckenv,0 ; if a new environment is being built,
  464. jnz notwidenv ; move the default comspec string in it
  465. push ds ; 2 bytes to make room for a drivespec.
  466. push es ; the drivespec is in ax and is copied
  467. pop ds ; on to the front of the string.
  468. mov di,Env_Ecomspec + ENVIRONSIZ2 - 1 ;eg
  469. mov si,Env_Ecomspec + ENVIRONSIZ2 - 3 ;eg
  470. mov cx,ENVIRONSIZ2 - 2
  471. rep movsb
  472. pop ds
  473. mov word ptr es:Env_Ecomspec,ax
  474. notwidenv:
  475. cld ; add the drivespec to the string
  476. ; NTVDM not used
  477. ; mov word ptr AutoBat,ax ; used to reference autoexec.bat
  478. ; mov word ptr KautoBat,ax ; used to reference kautoexe.bat 3/3/kk
  479. nocomdrv:
  480. call setvect ; set interrupt vectors 22h, 23h, & 24h
  481. ;*********************************
  482. ; parsing starts here
  483. ;*********************************
  484. push cs ; get local segment
  485. push cs ; into ds,es
  486. pop ds ;
  487. pop es ;
  488. assume ds:ResGroup,es:ResGroup ;
  489. mov si,80h ; get command line
  490. lodsb ; get length of line
  491. mov di,si ; get line position in di
  492. xor ah,ah ; ax = length of command line
  493. ;
  494. ; insure that the command line correctly ends with a cr
  495. ;
  496. add di,ax ; go to end of command line
  497. mov byte ptr [di],0dh ; insert a carriage return
  498. xor cx,cx ; clear cx
  499. mov Num_positionals,cx ; initialize positionals
  500. ;
  501. ; Scan the command line looking for the parameters
  502. ;
  503. Parse_command_line:
  504. mov di,offset ResGroup:Parse_Command ; Get address of parse_command
  505. mov cx,Num_positionals ; Get number of positionals
  506. xor dx,dx ; clear dx
  507. mov Old_parse_ptr,si ; save position before calling parser
  508. call init_parse ; call parser
  509. mov Num_positionals,cx ; Save number of positionals
  510. cmp ax,END_OF_LINE ; are we at end of line?
  511. jnz SkipArgdsDoneJmp
  512. jmp ArgsDoneJ3 ; yes - exit
  513. SkipArgdsDoneJmp:
  514. cmp ax,RESULT_NO_ERROR ; did an error occur
  515. jz parse_cont ; no - continue
  516. ;
  517. ; Before issuing error message - make sure switch is not /C or /K
  518. ;
  519. parse_line_error:
  520. push si ; save line position
  521. push ax ; save error number
  522. cmp ax,BADSWT_PTR ; Was error invalid switch?
  523. jnz parse_line_error_disp ; No - just issue message
  524. mov di,si ; Get terminating pointer in DI
  525. mov si,Old_parse_ptr ; Get starting pointer in SI
  526. init_chk_delim:
  527. cmp si,di ; at end of parsed parameter?
  528. jz parse_line_error_disp ; Yes - just display message
  529. lodsb ;
  530. cmp al,Space ; Skip blank spaces
  531. jz init_chk_delim ;
  532. cmp al,TAB_CHR ; Skip tab characters
  533. jz init_chk_delim ;
  534. cmp al,Rswitchar ; Switch?
  535. jnz parse_line_error_disp ; No - just issue message
  536. lodsb ; Get the char after the switch
  537. ifdef DBCS
  538. call ItestKanj ; Is it DBCS?
  539. jnz parse_line_error_disp ; Yes - can't be /C or /K
  540. endif
  541. call iupconv ; upper case it
  542. cmp al,Scswitch ; it is /C?
  543. jz AltSetCSwitch
  544. cmp al,Skswitch ; it is /K?
  545. jz AltSetKSwitch
  546. jmp parse_line_error_disp ;
  547. AltSetCSwitch:
  548. pop dx ; even up stack
  549. pop dx ; even up stack
  550. jmp setSSwitch ; Yes - go set COMMAND /C
  551. AltSetKSwitch:
  552. pop dx ; even up stack
  553. pop dx ; even up stack
  554. jmp setKSwitch ; Yes - go set COMMAND /K
  555. parse_line_error_disp:
  556. pop ax ; restore error number
  557. pop si ; restore line position
  558. mov dx,ax ; get message number
  559. call RPrintParse
  560. call CrLf
  561. jmp short Parse_command_line ; continue parsing
  562. parse_cont:
  563. ;
  564. ; See if a switch was entered
  565. ;
  566. ; Bugbug: See if Comnd1_Syn can be moved into a reg. before the compare
  567. ;
  568. ; Several stub switches have been added below in order to provide improved
  569. ; compatibility with applications using unsupported switches in command.com
  570. ; The stubs generally do not do anything, but, they keep command.com
  571. ; from erroring out. In many cases, this is enough to keep the app working.
  572. ;
  573. ; STUB SWITCHES
  574. ; /LOW Force command.com to keep resident data in LOW memory.
  575. ; (does nothing)
  576. ; /Y Step through batch file specified by /c or /k
  577. ; (does nothing)
  578. ; /L:nnnn internal buffers size
  579. ; (does nothing)
  580. ; /U:nnn input buffers size
  581. ; (does nothing)
  582. ; /K command run batch file specified by command and continue
  583. ; turns on /P switch if not already specified.
  584. ;
  585. cmp Comnd1_Syn,offset ResGroup:Command_f_syn ; was /F entered?
  586. jnz NoFSwitch
  587. jmp SetFSwitch ; yes go set fail switch
  588. NoFSwitch:
  589. cmp Comnd1_Syn,offset resgroup:Command_p_syn ; was /P entered?
  590. jnz NoPSwitch
  591. jmp SetPSwitch ; yes go set up PERMCOM
  592. NoPSwitch:
  593. cmp Comnd1_Syn,offset resgroup:Command_d_syn ; was /D entered?
  594. jnz NoDSwitch
  595. jmp SetDSwitch ; yes go set date switch
  596. NoDSwitch:
  597. cmp Comnd1_Syn,offset resgroup:Command_c_syn ; was /C entered?
  598. jnz NoSSwitch
  599. jmp SetSSwitch ; yes go set up SINGLECOM
  600. NoSSwitch:
  601. cmp Comnd1_Syn,offset resgroup:Command_k_syn ; was /K entered?
  602. jnz NoKSwitch
  603. jmp SetKSwitch ; yes go set up environment
  604. NoKSwitch:
  605. cmp Comnd1_Syn,offset resgroup:Command_y_syn ; was /Y entered?
  606. jnz NoYSwitch
  607. jmp SetYSwitch ; yes go set up environment
  608. NoYSwitch:
  609. cmp Comnd1_Syn,offset resgroup:Command_e_syn ; was /E entered?
  610. jnz NoESwitch
  611. jmp SetESwitch ; yes go set up environment
  612. NoESwitch:
  613. cmp Comnd1_Syn,offset resgroup:Command_l_syn ; was /LOW entered?
  614. jnz NoLSwitch
  615. jmp SetLSwitch ; yes go set up message flag
  616. NoLSwitch:
  617. cmp Comnd1_Syn,offset resgroup:Command_l2_syn ; was /L entered?
  618. jnz NoL2Switch
  619. jmp SetL2Switch ; yes go set up environment
  620. NoL2Switch:
  621. cmp Comnd1_Syn,offset resgroup:Command_m_syn ; was /MSG entered?
  622. jnz NoMSwitch
  623. jmp SetMSwitch ; yes go set up message flag
  624. NoMSwitch:
  625. cmp Comnd1_Syn,offset resgroup:Command_u_syn ; was /U entered?
  626. jnz NoUSwitch
  627. jmp SetUSwitch ; yes go set up message flag
  628. NoUSwitch:
  629. jmp ChkOtherArgs ; Must be something else
  630. ArgsdoneJ3: ; long jump needed
  631. jmp ArgsDone ;
  632. SetFSwitch:
  633. cmp fFail,-1 ; has fail switch been set?
  634. jnz failok ; no - set it
  635. mov ax,Moreargs_ptr ; set up too many arguments
  636. jmp parse_line_error ; go issue error message
  637. failok:
  638. mov fFail,-1 ; fail all INT 24s.
  639. jmp Parse_command_line ;
  640. SetPSwitch:
  641. ;
  642. ; We have a permanent COMMAND switch /P. Flag this and stash the
  643. ; termination address.
  644. ;
  645. cmp PermCom,0 ; has /p switch been set?
  646. jz permcomok ; no - set it
  647. mov ax,moreargs_ptr ; set up too many arguments
  648. jmp parse_line_error ; go issue error message
  649. permcomok:
  650. inc PermCom
  651. mov word ptr OldTerm,offset DATARES:LodCom_Trap
  652. mov word ptr OldTerm+2,ds
  653. ;
  654. ; make sure that we display the date and time. if the flag was not
  655. ; initialized, set it to indicate yes, do prompt.
  656. ;
  657. cmp Comnd1_Syn,offset resgroup:Command_k_syn
  658. jnz RealPSwitch
  659. jmp ArgsDone
  660. RealPSwitch:
  661. cmp byte ptr PrdAttm,-1
  662. jnz Parse_command_line_jmp ; keep parsing
  663. mov byte ptr PrdAttm,0 ; if not set explicit, set to prompt
  664. Parse_command_line_jmp: ;
  665. jmp parse_command_line ; keep parsing
  666. ArgsDoneJump:
  667. jmp ArgsDone
  668. SetDSwitch:
  669. ;
  670. ; Flag no date/time prompting.
  671. ;
  672. cmp Dswitch,0 ; has /D switch been set?
  673. jz setdateok ; no - set it
  674. mov ax,Moreargs_ptr ; set up too many arguments
  675. jmp parse_line_error ; go issue error message
  676. setdateok:
  677. inc Dswitch ; indicate /D entered
  678. mov byte ptr PrdAttm,1 ; user explicitly says no date time
  679. jmp Parse_command_line ; continue parsing
  680. SetYSwitch:
  681. ;
  682. ; Y switch is ignored. Present to keep apps that actually use it in a
  683. ; static create process or something from having problems
  684. ; (important after a win9xupg.)
  685. ;
  686. jmp Parse_command_line ; continue parsing
  687. SetKSwitch:
  688. ;
  689. ; Treat this just like /C, just keep going
  690. ;
  691. mov KSwitchFlag,1
  692. jmp SetSSwitch
  693. ;
  694. ; Look for environment-size setting switch
  695. ;
  696. ; The environment size is represented in decimal bytes and is
  697. ; converted into pargraphs (rounded up to the next paragraph).
  698. ;
  699. SetSSwitch:
  700. ;
  701. ; Set up pointer to command line, flag no date/time and turn off singlecom.
  702. ;
  703. mov SingleCom,si ; point to the rest of the command line
  704. mov Permcom,0 ; a singlecom must not be a permcom
  705. mov byte ptr PrdAttm,1 ; no date or time either, explicit
  706. jmp ArgsDone
  707. ;
  708. ; Look for environment-size setting switch
  709. ;
  710. ; The environment size is represented in decimal bytes and is
  711. ; converted into pargraphs (rounded up to the next paragraph).
  712. ;
  713. SetESwitch:
  714. cmp Eswitch,0 ; has fail switch been set?
  715. jz eswitchok ; no - set it
  716. mov ax,Moreargs_ptr ; set up too many arguments
  717. jmp Parse_line_error ; go issue error message
  718. eswitchok:
  719. inc Eswitch ; indicate /E entered
  720. mov di,offset ResGroup:Comnd1_Addr ; get number returned
  721. mov bx,word ptr [di] ; into bx
  722. add bx, 0fh ; Round up to next paragraph
  723. mov cl,4 ; convert to pargraphs
  724. shr bx, cl ; by right 4
  725. mov EnvSiz,BX ; EnvSiz is in paragraphs
  726. jmp Parse_command_line ; continue parsing command line
  727. SetL2Switch:
  728. Jmp Parse_Command_Line
  729. SetMSwitch:
  730. cmp Ext_msg,SET_EXTENDED_MSG ; has /MSG switch been set?
  731. jnz setMswitchok ; no - set it
  732. mov ax,Moreargs_ptr ; set up too many arguments
  733. jmp Parse_line_error ; go issue error message
  734. setMswitchok:
  735. mov Ext_msg,SET_EXTENDED_MSG ; set /MSG switch
  736. jmp Parse_command_line ; keep parsing
  737. SetLSwitch:
  738. jmp Parse_Command_Line
  739. SetUSwitch:
  740. Jmp Parse_Command_Line
  741. ArgsDoneJ:
  742. jmp ArgsDone
  743. ;
  744. ; We have a non-switch character here.
  745. ;
  746. ChkOtherArgs:
  747. push ds ;
  748. push si ; save place in command line
  749. lds si,Comnd1_Addr ; get address of filespec
  750. assume ds:nothing ;
  751. mov dx,si ; put in dx also
  752. mov ax,(OPEN shl 8) or 2 ; Read and write
  753. int 21h
  754. jc ChkSrchSpec ; Wasn't a file
  755. mov bx,ax
  756. mov ax,IOCTL shl 8
  757. int 21h
  758. test dl,80h
  759. jnz IsaDevice
  760. BadSetCon: ;
  761. mov ah,CLOSE ; Close initial handle, wasn't a device
  762. int 21h
  763. jmp short ChkSrchSpec
  764. IsaDevice:
  765. xor dh,dh
  766. or dl,3 ; Make sure has CON attributes
  767. mov ax,(IOCTL shl 8) or 1
  768. int 21h
  769. jc BadSetCon ; Can't set attributes - quit
  770. mov dx,bx ; Save new handle
  771. cmp es:DevFlag,1
  772. jz DevErr
  773. push cx
  774. mov cx,3
  775. xor bx,bx
  776. rcclloop: ; Close 0,1 and 2
  777. mov ah,CLOSE
  778. int 21h
  779. inc bx
  780. loop rcclloop
  781. mov bx,dx ; New device handle
  782. mov ah,XDUP
  783. int 21h ; Dup to 0
  784. mov ah,XDUP
  785. int 21h ; Dup to 1
  786. mov ah,XDUP
  787. int 21h ; Dup to 2
  788. mov ah,CLOSE
  789. int 21h ; Close initial handle
  790. pop cx
  791. pop si ; restore position of command line
  792. pop ds ;
  793. ;SR;
  794. ; Register the fact that we already have redirected the output and cannot do
  795. ;it again
  796. ;
  797. inc es:DevFlag ;
  798. jmp Parse_command_line ; continue parsing
  799. DevErr:
  800. pop si
  801. pop ds
  802. mov dx,1
  803. call RPrintParse ;"Too many parameters"
  804. call CrLf
  805. jmp Parse_command_line
  806. ChkSrchSpec: ; Not a device, so must be directory spec
  807. cmp es:PathFlag,1 ;already set COMSPEC?
  808. jz DevErr ;yes, error
  809. inc es:PathFlag ;mark that we have a path
  810. ;
  811. ;We do not have an ENVIRONMENT segment any more so we need to allocate a
  812. ;temporary buffer to hold the COMSPEC. Later, this buffer will be freed and
  813. ;its contents moved to the final location of the environment. If there was
  814. ;no environment passed before, then a buffer has already been allocated and
  815. ;so we check for this case. Fortunately, Chuckenv would have been previously
  816. ;set if we had been passed an environment.
  817. ;
  818. mov ax,EnvirSeg
  819. cmp byte ptr Chuckenv,1 ;passed environment?
  820. mov byte ptr Chuckenv,0 ;ignore passed environment
  821. jne no_alloc ;no, default, dont allocate
  822. ;
  823. ;We have to override the passed environment. Allocate a buffer for use now.
  824. ;This buffer will later be replaced by a proper environment
  825. ;
  826. call alloc_env ;allocate env buffer
  827. ;; mov ax,offset ResGroup:PathString ; Figure environment pointer
  828. ;; mov cl,4
  829. ;; shr ax,cl
  830. ;; mov dx,cs ;
  831. ;; add ax,dx
  832. mov EnvirSeg,ax
  833. no_alloc:
  834. mov es,ax
  835. assume es:nothing
  836. push si ; remember location of file
  837. xor cx,cx ; clear cx for counting
  838. countloop:
  839. lodsb ; get a character
  840. inc cx ; increment counter
  841. cmp al,END_OF_LINE_OUT ; are we at end of line?
  842. jnz countloop ; no - keep counting
  843. mov al,Space
  844. dec si ; move back one
  845. mov byte ptr [si],al ; put a space at end of line
  846. pop si ; get location back
  847. mov di,Env_Ecomspec ; get location of COMSPEC
  848. ComtrLoop:
  849. lodsb
  850. dec cx
  851. cmp al,Space
  852. jz SetComsr
  853. stosb
  854. ifdef DBCS
  855. xor ah,ah
  856. endif
  857. jcxz setcomsr
  858. ifdef DBCS
  859. push ds ; Make sure we have
  860. push cs ; local DS for
  861. pop ds ; ItestKanj
  862. call ItestKanj
  863. pop ds ; restore parser ds
  864. jz ComtrLoop
  865. dec cx
  866. movsb
  867. inc ah
  868. jcxz setcomsr
  869. endif
  870. jmp short comtrloop
  871. setcomsr:
  872. push cx
  873. push cs ; Get local segment
  874. pop ds ;
  875. assume ds:ResGroup ;
  876. push ds
  877. mov si,offset ResGroup:ComSpect
  878. mov cx,14
  879. mov al,es:[di-1]
  880. ifdef DBCS
  881. or ah,ah
  882. jnz iNotRoot ; Last char was KANJI second byte, might be '\'
  883. endif
  884. cmp al,RDirChar
  885. jnz iNotRoot
  886. inc si ; Don't make a double /
  887. dec cx
  888. iNotRoot:
  889. rep movsb
  890. mov dx,Env_Ecomspec ; Now lets make sure its good!
  891. push es
  892. pop ds
  893. mov ax,OPEN shl 8
  894. int 21h ; Open COMMAND.COM
  895. pop ds
  896. jc SetComsrBad ; No COMMAND.COM here
  897. mov bx,ax ; Handle
  898. mov ah,CLOSE
  899. int 21h ; Close COMMAND.COM
  900. SetComsrRet:
  901. pop cx
  902. pop si
  903. pop ds ;
  904. assume ds:ResGroup ;
  905. ArgsDoneJ2:
  906. push cs ; Make sure local ES is
  907. pop es ; restored
  908. jmp Parse_command_line ; continue parsing command line
  909. SetComsrBad:
  910. mov dx,offset ResGroup:BadComlkMsg ; dx = ptr to msg
  911. ; Note: we're about to make a near call to TriageError, which
  912. ; lives in a different segment and group. Some linkers will
  913. ; generate a warning like "Possible fix-up overflow". We're
  914. ; ok, though, because we all fit in 64 KB and, at init time,
  915. ; we're still all together.
  916. call triageError
  917. cmp ax, 65
  918. jnz doprt
  919. mov dx,offset ResGroup:BadComaccMsg ; dx = ptr to msg
  920. DoPrt:
  921. call RPrint
  922. mov si,offset ResGroup:ComSpect
  923. mov di,Env_Ecomspec
  924. mov cx,14
  925. rep movsb ; get my default back
  926. jmp short SetComsrRet
  927. ;*********************************
  928. ; Parsing Ends Here
  929. ;*********************************
  930. ArgsDone:
  931. mov es,EnvirSeg ; get environment back
  932. assume es:nothing ;
  933. cmp PermCom,0
  934. jz ComReturns
  935. push es ; Save environment pointer
  936. mov ah,SET_CURRENT_PDB
  937. mov bx,ds
  938. mov es,bx
  939. int 21h ; current process is me
  940. mov di,PDB_EXIT ; Diddle the addresses in my header
  941. mov ax,offset DATARES:LodCom_Trap
  942. stosw
  943. mov ax,ds
  944. stosw
  945. mov ax,offset DATARES:Ctrlc_Trap
  946. stosw
  947. mov ax,ds
  948. stosw
  949. mov ax,offset DATARES:CritErr_Trap
  950. stosw
  951. mov ax,ds
  952. stosw
  953. mov word ptr ds:PDB_Parent_Pid,ds ; Parent is me forever
  954. mov dx,offset DATARES:Int2e_Trap
  955. mov ax,(SET_INTERRUPT_VECTOR shl 8) or 02eh
  956. int 21h ;set magic interrupt
  957. pop es ;Remember environment
  958. ComReturns:
  959. mov ax,word ptr ds:PDB_Parent_Pid
  960. mov Parent,ax ; Save parent
  961. mov word ptr ds:PDB_Parent_Pid,ds ; Parent is me
  962. mov ax,word ptr ds:PDB_Jfn_Table
  963. mov Io_save,ax ; Get the default stdin and out
  964. mov al,byte ptr ds:[PDB_Jfn_Table+2]
  965. mov Io_Stderr,al ; Get the default stdin and out
  966. mov word ptr Com_ptr+2,ds ; set all these to resident
  967. mov word ptr Com_fcb1+2,ds
  968. mov word ptr Com_fcb2+2,ds
  969. mov di,offset ResGroup:ComSpec
  970. mov si,Env_Ecomspec
  971. cmp byte ptr Chuckenv,0
  972. mov ax,ds ; Xchg es,ds
  973. push es
  974. pop ds
  975. mov es,ax
  976. jz CopyComsp ; All set up for copy
  977. push cs
  978. pop ds
  979. mov si,offset ResGroup:ComspString
  980. push es
  981. push di
  982. call IfindE
  983. mov si,di
  984. push es
  985. pop ds
  986. pop di
  987. pop es
  988. jnc CopyComsp
  989. ComSpecNofnd:
  990. mov si,Env_Ecomspec ;
  991. push cs
  992. pop ds
  993. assume es:ResGroup
  994. CopyComsp:
  995. mov es:PutBackComSpec.SubstPtr,di ; Save ptr to beginning of comspec path
  996. cmp byte ptr [si+1],':' ; Is there a drive specifier in comspec
  997. jnz CopyComspLoop ; If not, do not skip over first 2 bytes
  998. add es:PutBackComSpec.SubstPtr,2
  999. CopyComspLoop:
  1000. lodsb
  1001. stosb
  1002. or al,al
  1003. jnz CopyComspLoop
  1004. mov es:Comspec_end,di ; Save ptr to end of comspec path
  1005. dec es:Comspec_end
  1006. mov ah,es:comdrv
  1007. add ah,'A'-1
  1008. mov es:PutBackDrv,ah ; save drive letter
  1009. call setup_for_messages ; set up parse and extended error messages
  1010. ;SR;
  1011. ;The routine below sets up the exact resident size of COMMAND. If this is not
  1012. ;the first COMMAND, then the resident code is not duplicated and the resident
  1013. ;size is just the data. If we are the first COMMAND, it checks if we are to
  1014. ;be loaded into HIMEM. If not, then the resident size includes the code and
  1015. ;the data otherwise it is just the data.
  1016. ;
  1017. call Setup_res_end ;put resident size in ResSize
  1018. push cs
  1019. pop ds
  1020. assume ds:RESGROUP
  1021. ;; if we are the permanent one, tell ntvdm the real comspec.
  1022. cmp PermCom, 0
  1023. je comspec_to_32_done
  1024. push ax
  1025. mov dx, offset RESGROUP:ComSpec
  1026. CMDSVC SVC_CMDCOMSPEC
  1027. mov SCS_PAUSE,al ; yst 4-5-93
  1028. pop ax
  1029. comspec_to_32_done:
  1030. ;; mov bx,ResMsgEnd ; get end of resident
  1031. ;; add bx,15
  1032. ;; mov cl,4
  1033. ;; shr bx,cl
  1034. Public EnvMaximum
  1035. EnvMaximum:
  1036. ;;;
  1037. ;;; NOTE: The transient has to loaded directly after shrinking to the
  1038. ;;; resident size.
  1039. ;;; There is an assumption made when loading the transient that it
  1040. ;;; still intact after the resident portion.
  1041. ;;; If any other ALLOC/DEALLOC/SETBLOCK operations are performed
  1042. ;;; inbetween, then there is a real good chance that the non-resident
  1043. ;;; portion will be overwritten by arena information.
  1044. ;SR;
  1045. ;Do not shrink to the resident now. We will then be running in deallocated
  1046. ;memory and BAAADNESS! can ensue.
  1047. ;
  1048. ;; mov ah,SETBLOCK
  1049. ;; int 21h ; shrink to the resident only
  1050. ;
  1051. ; Load in the transient and compute the checksum. We may do this in one of
  1052. ; two ways: First, cheat and use the transient loading code that exists in
  1053. ; the resident piece. This may be OK except that it will hit the disk.
  1054. ;
  1055. ; But we do not need to hit the disk! The transient is already loaded but is
  1056. ; in the wrong place. We need to block transfer it up to the correct spot.
  1057. ;
  1058. ;
  1059. ; M004; Start of changes
  1060. ;
  1061. ;
  1062. ; Compute checksum right now before we can get corrupted and save it
  1063. ;
  1064. mov si,offset RESGROUP:TranStart
  1065. add si,100h
  1066. mov cx,offset TRANGROUP:TranDataEnd - 100H
  1067. cld
  1068. shr cx,1
  1069. xor dx,dx
  1070. Ichksum:
  1071. lodsw
  1072. add dx,ax
  1073. adc dx,0
  1074. loop Ichksum
  1075. mov Sum,dx ;store checksum
  1076. ;
  1077. ; M004; End of changes
  1078. ;
  1079. cmp byte ptr PrdAttm,0 ;eg
  1080. jnz NoBatchSeg ;eg don't do autoexec or date time
  1081. ;
  1082. ; allocate batch segment for d:/autoexec.bat + no arguments
  1083. ;
  1084. ; NTVDM temp name of the batch file may be up to 63 bytes, plus NULL
  1085. ; mov bx,((SIZE BatchSegment) + 15 + 1 + 0fh)/16 ;eg
  1086. mov bx,((SIZE BatchSegment) + 64 + 0fh)/16 ;eg
  1087. mov ah,ALLOC ;eg
  1088. int 21h ;eg
  1089. jc NoBatchSeg ;eg didn't allocate - pretend no batch
  1090. mov Batch,ax ;eg save batch segment
  1091. nobatchseg:
  1092. ;; mov bx, 0ffffh ; get size of largest block for env
  1093. ;; mov ah, ALLOC
  1094. ;; int 21h
  1095. ;;
  1096. ;;; only allocate maximum 64k worth of environment
  1097. ;;
  1098. ;; sub bx,TrnSize ;eg subtract # of transient paragraphs
  1099. ;; sub bx,128 ;eg make sure we have 2k left
  1100. ;; mov EnvMax, bx
  1101. ;; cmp bx, 4096 ; 64k = 4096 paragraphs
  1102. ;; jb maxok
  1103. ;; mov bx, 4096-1
  1104. ;; mov EnvMax, bx
  1105. ;;maxok:
  1106. ;;
  1107. ;; mov ah, ALLOC ; get max size
  1108. ;; int 21h
  1109. ;;
  1110. mov bx,EnvirSeg ;g get old environment segment
  1111. mov OldEnv,bx ;g save it
  1112. mov UsedEnv,0 ;g initialize env size counter
  1113. mov ds,bx
  1114. assume ds:nothing
  1115. ;; mov EnvirSeg,ax
  1116. ;;;Bugbug: There is no need to initialize es at this point-- no string moves
  1117. ;; mov es,ax
  1118. xor si,si
  1119. mov di,si
  1120. ;SR;
  1121. ;This is the maximum allowed size for the environment
  1122. ;
  1123. mov bx,4096 - 1 ; max. allowed env. size
  1124. mov EnvMax,bx
  1125. shl bx,1
  1126. shl bx,1
  1127. shl bx,1
  1128. shl bx,1
  1129. mov EnvMax, bx ; convert envmax to bytes
  1130. dec bx ; dec by one to leave room for double 0
  1131. xor dx,dx ; use dx to indicate that there was
  1132. ; no environment size error.
  1133. public NxtStr
  1134. NxtStr:
  1135. call GetStrLen ; get the size of the current env string
  1136. ;Bugbug: Can use ss here to address UsedEnv
  1137. push ds ;g get addressability to environment
  1138. push cs ;g counter
  1139. pop ds ;g
  1140. assume ds:ResGroup
  1141. add UsedEnv,cx ;g add the string length to env size
  1142. pop ds ;g
  1143. assume ds:nothing
  1144. cmp cx,1 ; end of environment was encountered.
  1145. jz EnvExit
  1146. sub bx,cx
  1147. jae OkCpyStr ; can't fit in all of enviroment.
  1148. inc dx ; out of env space msg must be displayed
  1149. jmp short EnvExit
  1150. OkCpyStr:
  1151. jmp NxtStr
  1152. EnvExit:
  1153. push cs
  1154. pop ds
  1155. assume ds:ResGroup
  1156. or dx,dx ; dx will be non-zero if error
  1157. jz EnvNoErr
  1158. mov dx,offset ResGroup:OutEnvMsg ; dx = ptr to msg
  1159. call RPrint
  1160. EnvNoErr:
  1161. mov ax,EnvSiz ;env size previously set
  1162. mov cl,4
  1163. shl ax,cl ;get size in bytes
  1164. cmp ax,UsedEnv ;is it a new env?
  1165. ja st_envsize ;yes, store the size
  1166. mov ax,UsedEnv
  1167. add ax,15 ;round up
  1168. st_envsize:
  1169. shr ax,cl
  1170. mov EnvSiz,ax ;store env size needed(paras)
  1171. ;;;
  1172. ;;; bx now has the left over size of the maximum environment
  1173. ;;; we want to shrink the environment down to the minimum size
  1174. ;;; set the environment size to max(envsiz,env used)
  1175. ;; mov cx, EnvMax
  1176. ;; sub cx, bx ; cx now has the environment used
  1177. ;; add cx, 16 ; round up to next paragraph
  1178. ;; shr cx, 1
  1179. ;; shr cx, 1
  1180. ;; shr cx, 1
  1181. ;; shr cx, 1
  1182. ;; cmp cx, EnvSiz ; is environment used > envsiz
  1183. ;; jb EnvSet
  1184. ;; mov EnvSiz, cx
  1185. ;;EnvSet:
  1186. ;; mov bx, EnvSiz ; set environment to size needed
  1187. ;; mov ax,es ;eg get environment segment
  1188. ;; add ax,bx ;eg add number of environment paragraphs
  1189. ;; cmp ax,InitEnd ;eg does this go past end of init?
  1190. ;; ja EnvSetOk ;eg yes - do the setblock
  1191. ;; mov ax,es ;eg no - get back the environment segment
  1192. ;; mov bx,InitEnd ;eg get the segment at end of init
  1193. ;; sub bx,ax ;eg setblock envir segment to end of init code
  1194. ;; mov ResetEnv,1 ;eg set flag so we know to set envir later
  1195. ;;
  1196. ;;envsetok:
  1197. ;; mov ah, setblock
  1198. ;; int 21h
  1199. ifndef NEC_98
  1200. cmp SCS_FIRSTCOM,1
  1201. jz nophead ; don't print header for first instance
  1202. else ;NEC_98
  1203. endif ;NEC_98
  1204. cmp SCS_CMDPROMPT,1
  1205. je nophead
  1206. cmp SingleCom,0
  1207. jnz nophead ; don't print header if singlecom
  1208. mov dx,offset ResGroup:CopyrightMsg ; dx = ptr to msg
  1209. call RPrint
  1210. nophead:
  1211. cmp Batch,0 ;eg did we set up a batch segment?
  1212. jnz DoDate ;eg yes - go initialize it
  1213. jmp NoDttm ; don't do autoexec or date time
  1214. ;
  1215. ; allocate batch segment for d:/autoexec.bat + no arguments
  1216. ;
  1217. DoDate:
  1218. mov ax,Batch ;eg get batch segment
  1219. mov EchoFlag,3 ; set batch echo
  1220. mov Nest,1 ; g set nest flag to 1 batch
  1221. mov es,ax
  1222. ;
  1223. ; initialize the segment
  1224. ;
  1225. xor di,di
  1226. mov al,BATCHTYPE
  1227. stosb
  1228. mov al,1 ; g initialize echo for batch exit
  1229. stosb ; g
  1230. ;SR;
  1231. ; Hosebag! This guy does not use the struct fields to init the BatchSegment
  1232. ;
  1233. xor ax,ax ; initialize to zero
  1234. stosb ; clear out BatchEOF
  1235. stosw ; g batch segment of last job - batlast
  1236. stosw ; g segment for for
  1237. stosb ; g for flag
  1238. stosw ; position in file - batseek
  1239. stosw
  1240. ;
  1241. ; clean out the parameters
  1242. ;
  1243. mov ax,-1 ; initialize to no parameters
  1244. mov cx,10
  1245. rep stosw
  1246. ;
  1247. ; NTVDM Get temp file name from 32 bit command.lib
  1248. ;
  1249. if 0
  1250. ;
  1251. ; decide whether we should grab the default drive
  1252. ;
  1253. cmp byte ptr AutoBat,0
  1254. jnz NoAutSet
  1255. mov ah,GET_DEFAULT_DRIVE
  1256. int 21h
  1257. add al,Ucasea
  1258. mov AutoBat,al
  1259. mov KautoBat,al ; 3/3/kk
  1260. NoAutSet:
  1261. ;
  1262. ; copy in the batch file name (including nul)
  1263. ;
  1264. mov si,offset ResGroup:AutoBat
  1265. mov cx,8
  1266. rep movsw
  1267. movsb ; move in carriage return to terminate string
  1268. endif
  1269. push es
  1270. pop ds
  1271. assume ds:nothing
  1272. mov dx, di
  1273. CMDSVC SVC_GETAUTOEXECBAT
  1274. ;NTVDM not used mov dx,offset ResGroup:AutoBat
  1275. mov ax,OPEN shl 8
  1276. int 21h ; see if autoexec.bat exists
  1277. push cs
  1278. pop ds
  1279. assume ds:ResGroup
  1280. jc NoAbat
  1281. mov bx,ax
  1282. mov ah,CLOSE
  1283. int 21h
  1284. ifndef NEC_98
  1285. jmp Drv0 ; go process autoexec
  1286. else ;NEC_98
  1287. jmp short Drv0 ; NEC01 91/07/30 Warning Error Del
  1288. endif ;NEC_98
  1289. noabat:
  1290. push ax
  1291. call Setup_Seg
  1292. mov word ptr Triage_Add+2,ax
  1293. pop ax
  1294. call Triage_Add
  1295. cmp ax, 65
  1296. jz AccDenErr ; was network access denied
  1297. ; NTVDM we don't do kautoexe.bat
  1298. if 0
  1299. ; If AUTOEXEC.BAT is not found, then check for KAUTOEXE.BAT. Changed
  1300. ; by Ellen to check only when in Korea. The country information
  1301. ; returned will overlay the old parse data area, but we don't care
  1302. ; since we won't need the parse information or country information.
  1303. ; We only care about the country code returned in BX.
  1304. mov dx,offset ResGroup:Internat_Info ; set up internat vars
  1305. mov ax,INTERNATIONAL shl 8 ; get country dependent info
  1306. int 21h ;
  1307. jc NoKabat ; error - don't bother with it
  1308. cmp bx,KOREA_COUNTRY_CODE ; are we speaking korean?
  1309. jnz OpenErr ; no, don't check for kautoexe
  1310. mov di,BatFile ; 3/3/kk
  1311. mov si,offset ResGroup:KautoBat ; another trial to do 3/3/kk
  1312. mov cx,8 ; auto execution for the 3/3/kk
  1313. rep movsw ; non-english country 3/3/kk
  1314. movsb ; move in carraige return to terminate string
  1315. mov dx,offset ResGroup:KautoBat ; 3/3/kk
  1316. mov ax,OPEN shl 8 ; 3/3/kk
  1317. int 21h ; see if kautoexe.bat exists 3/3/kk
  1318. jc NoKabat ; 3/3/kk
  1319. mov bx,ax ; 3/3/kk
  1320. mov ah,CLOSE ; 3/3/kk
  1321. int 21h ; 3/3/kk
  1322. jmp short Drv0 ; 3/3/kk
  1323. NoKabat: ; 3/3/kk
  1324. call Triage_Add ; get extended error
  1325. cmp ax, 65 ; network access denied?
  1326. jnz OpenErr ; no - go deallocate batch
  1327. endif
  1328. AccDenErr: ; yes - put out message
  1329. mov dx,offset ResGroup:AccDen ; dx = ptr to msg
  1330. call RPrint
  1331. OpenErr:
  1332. mov es,Batch ; not found--turn off batch job
  1333. mov ah,DEALLOC
  1334. int 21h
  1335. mov Batch,0 ; after dealloc in case of ^c
  1336. mov EchoFlag,1
  1337. mov Nest,0 ;g indicate no batch in progress
  1338. DoDttm:
  1339. mov ax,offset TranGroup:Datinit
  1340. mov word ptr InitAdd,ax
  1341. ;;;M004 mov ax,TrnSeg
  1342. ;
  1343. ; M004; We cant use TrnSeg now because it is not initialized. We now that
  1344. ; M004; the transient starts on a para boundary at the label TranStart.
  1345. ; M004; We use TranStart to get the start of the transient segment.
  1346. ;
  1347. mov ax,offset RESGROUP:TranStart ; M004
  1348. mov cl,4 ; M004
  1349. shr ax,cl ; get relative seg ; M004
  1350. mov cx,cs
  1351. add ax,cx ; ax = transient seg ; M004
  1352. mov word ptr InitAdd+2,ax
  1353. ; call dword ptr InitAdd
  1354. NoDttm:
  1355. Copyright:
  1356. public Copyright
  1357. ; Bugbug: remove Copyright label.
  1358. ;if IBMVER
  1359. ; cmp SingleCom,0
  1360. ; jnz Drv0 ; don't print header if singlecom
  1361. ; mov dx,offset ResGroup:CopyrightMsg ; dx = ptr to msg
  1362. ; call RPrint
  1363. ;endif
  1364. Drv0: ; Reset APPEND state
  1365. push ds ; save data segment
  1366. push cs ; Get local segment into DS
  1367. pop ds ;
  1368. mov ax,APPENDSETSTATE ; Set the state of Append
  1369. mov bx,Append_State ; back to the original state
  1370. int 2fh ;
  1371. pop ds ; get data segment back
  1372. ;
  1373. ;Check FirstCom set previously to see if this is the first instance of
  1374. ;command.com. If not, we do not move command.com. Instead, we copy over the
  1375. ;jump table from the previous stub to the current stub.
  1376. ;
  1377. cmp FirstCom,1 ;first command.com?
  1378. jz move_code ;yes, move it
  1379. push es
  1380. push ds
  1381. push ds
  1382. pop es
  1383. mov di,offset DATARES:Int2f_Entry
  1384. mov ds,word ptr es:ResJmpTable+2 ;get segment address
  1385. mov si,word ptr es:ResJmpTable ;get offset address
  1386. mov cx,NUM_RELOC_ENTRIES ;number of dword ptrs
  1387. shl cx,1
  1388. shl cx,1 ;size of table in bytes
  1389. cld
  1390. rep movsb ;copy the jump table
  1391. ;
  1392. ;Check if the resident code is in HMA. We assume that it is in HMA if its
  1393. ;code segment > 0f000h. If in HMA, we set the ComInHMA flag
  1394. ;
  1395. cmp es:[di-2],0f000h ;is resident code in HMA?
  1396. jb res_low ;no, dont set flag
  1397. mov es:ComInHMA,1 ;indicate code in HMA
  1398. res_low:
  1399. pop ds
  1400. pop es
  1401. jmp short finish_init
  1402. ;
  1403. ;Now, we can move the resident code to its final location, either to HIMEM
  1404. ;or to overlay the messages in the data segment if the user has not used the
  1405. ;/msg switch.
  1406. ;
  1407. move_code:
  1408. call Move_res_code ;move the code
  1409. finish_init:
  1410. jmp RESGROUP:EndInit ;g finish initializing
  1411. ;
  1412. ; Get length of string pointed to by DS:SI. Length includes NULL.
  1413. ; Length is returned in CX
  1414. ;
  1415. GetStrLen:
  1416. xor cx,cx
  1417. NxtChar:
  1418. lodsb
  1419. inc cx
  1420. or al,al
  1421. jnz NxtChar
  1422. ret
  1423. ;
  1424. ; If the transient has been loaded in TranSeg, then we need to use that
  1425. ; segment for calls to routines in the transient area. Otherwise, the current
  1426. ; code segment is used
  1427. ; Segment returned in AX.
  1428. ;
  1429. Setup_Seg:
  1430. mov ax,TrnSeg
  1431. cmp TrnMvFlg, 1 ; Has transient portion been moved
  1432. jz setup_end
  1433. push bx
  1434. mov bx,cs
  1435. mov ax,offset ResGroup:TranStart
  1436. shr ax,1
  1437. shr ax,1
  1438. shr ax,1
  1439. shr ax,1
  1440. add ax,bx
  1441. pop bx
  1442. setup_end:
  1443. ret
  1444. ;*** RPrintParse - display parse error message
  1445. ;
  1446. ; ENTRY DX = parse error #
  1447. ;
  1448. ; EXIT nothing
  1449. ;
  1450. ; USED flags
  1451. ;
  1452. ; EFFECTS
  1453. ; Message is displayed on stdout.
  1454. RPrintParse proc
  1455. assume ds:ResGroup,ss:ResGroup
  1456. push dx ; preserve DX
  1457. xchg bx,dx ; bx = parse error #
  1458. ; dx = saved BX
  1459. ifdef BILINGUAL
  1460. push ax
  1461. push bx
  1462. mov ax,4f01h ; get code page
  1463. xor bx,bx
  1464. int 2fh
  1465. ifdef JAPAN
  1466. cmp bx,932
  1467. endif ; JAPAN
  1468. ifdef KOREA
  1469. cmp bx,949
  1470. endif ; KOREA
  1471. ifdef TAIWAN
  1472. cmp bx,950
  1473. endif ; TAIWAN
  1474. ifdef PRC
  1475. cmp bx,936
  1476. endif ; TAIWAN
  1477. pop bx
  1478. pop ax
  1479. jz @f ; if DBCS code page
  1480. add bx,11
  1481. @@:
  1482. endif ; BILINGUAL
  1483. dec bx ; bx = parse error index, from 0
  1484. shl bx,1 ; bx = offset in word table
  1485. mov bx,ParsMsgPtrs[bx] ; bx = ptr to error msg
  1486. xchg bx,dx ; dx = ptr to error msg
  1487. ; bx = restored
  1488. ifdef BILINGUAL
  1489. call RPrint@ ; print the message
  1490. else ; !BILINGUAL
  1491. call RPrint ; print the message
  1492. endif ; !BILINGUAL
  1493. pop dx ; restore DX
  1494. ret
  1495. RPrintParse endp
  1496. IfindE:
  1497. call ifind ; find the name
  1498. jc ifind2 ; carry means not found
  1499. jmp short Iscasb1 ; scan for = sign
  1500. ;
  1501. ; on return of find1, es:di points to beginning of name
  1502. ;
  1503. ifind:
  1504. cld
  1505. call Icount0 ; cx = length of name
  1506. mov es,EnvirSeg
  1507. xor di,di
  1508. ifind1:
  1509. push cx
  1510. push si
  1511. push di
  1512. Ifind11:
  1513. lodsb
  1514. ifdef DBCS
  1515. call ItestKanj
  1516. jz NotKanj4
  1517. dec si
  1518. lodsw
  1519. inc di
  1520. inc di
  1521. cmp ax,es:[di-2]
  1522. jnz Ifind12
  1523. dec cx
  1524. loop Ifind11
  1525. jmp short Ifind12
  1526. NotKanj4:
  1527. endif
  1528. call IupConv
  1529. inc di
  1530. cmp al,es:[di-1]
  1531. jnz Ifind12
  1532. loop Ifind11
  1533. Ifind12:
  1534. pop di
  1535. pop si
  1536. pop cx
  1537. jz Ifind2
  1538. push cx
  1539. call Iscasb2 ; scan for a nul
  1540. pop cx
  1541. cmp byte ptr es:[di],0
  1542. jnz Ifind1
  1543. stc ; indicate not found
  1544. Ifind2:
  1545. ret
  1546. Icount0:
  1547. push ds
  1548. pop es
  1549. mov di,si
  1550. push di ; count number of chars until "="
  1551. call Iscasb1
  1552. jmp short Icountx
  1553. push di ; count number of chars until nul
  1554. call Iscasb2
  1555. Icountx:
  1556. pop cx
  1557. sub di,cx
  1558. xchg di,cx
  1559. ret
  1560. Iscasb1:
  1561. mov al,Equalsign ; scan for an =
  1562. jmp short Iscasbx
  1563. Iscasb2:
  1564. xor al,al ; scan for a nul
  1565. Iscasbx:
  1566. mov cx,100h
  1567. repnz scasb
  1568. ret
  1569. ; ****************************************************************
  1570. ; *
  1571. ; * ROUTINE: IUPCONV (ADDED BY EMG 4.00)
  1572. ; *
  1573. ; * FUNCTION: This routine returns the upper case equivalent of
  1574. ; * the character in AL from the file upper case table
  1575. ; * in DOS if character if above ascii 128, else
  1576. ; * subtracts 20H if between "a" and "z".
  1577. ; *
  1578. ; * INPUT: DS set to resident
  1579. ; * AL char to be upper cased
  1580. ; * FUCASE_ADDR set to the file upper case table
  1581. ; *
  1582. ; * OUTPUT: AL upper cased character
  1583. ; *
  1584. ; ****************************************************************
  1585. IupConv proc near
  1586. assume ds:ResGroup ;
  1587. cmp al,80h ; see if char is > ascii 128
  1588. jb other_fucase ; no - upper case math
  1589. sub al,80h ; only upper 128 chars in table
  1590. push ds ;
  1591. push bx ;
  1592. lds bx,dword ptr fucase_addr+1 ; get table address
  1593. add bx,2 ; skip over first word
  1594. xlat ds:byte ptr [bx] ; convert to upper case
  1595. pop bx ;
  1596. pop ds ;
  1597. jmp short iupconv_end ; we finished - exit
  1598. other_fucase: ;
  1599. cmp al,Lcasea ; if between "a" and "z",
  1600. jb iupconv_end ; subtract 20h to get
  1601. cmp al,Lcasez ; upper case equivalent.
  1602. ja iupconv_end ;
  1603. sub al,20h ; Change lower-case to upper
  1604. iupconv_end: ;
  1605. ret
  1606. IupConv endp ;
  1607. init_contc_specialcase:
  1608. ; This routine is called if control-C
  1609. add sp,6 ; is type during the date/time prompt
  1610. push si ; at initialization time. The desired
  1611. mov si,dx ; response is to make it look like the
  1612. mov word ptr [si+1],0d00h ; user typed <CR> by "popping" the
  1613. pop si ; INT 21h stuff off the stack, putting
  1614. iret ; a <CR> in the user's buffer, and
  1615. ; returning directly to the user.
  1616. ; In this case the user is TCODE.
  1617. ; ****************************************************************
  1618. ; *
  1619. ; * ROUTINE: Setup_for_messages
  1620. ; *
  1621. ; * FUNCTION: Sets up system for PARSE and EXTENDED ERROR
  1622. ; * messages as follows:
  1623. ; *
  1624. ; * IF /P and /MSG are entered
  1625. ; * keep PARSE and EXTENDED ERRORS in memory
  1626. ; * ELSE IF /P is entered
  1627. ; * use PARSE and EXTENDED ERRORS on disk
  1628. ; * remove PARSE ERRORS from memory
  1629. ; * ELSE
  1630. ; * remove PARSE ERRORS from memory
  1631. ; * ENDIF
  1632. ; *
  1633. ; * INPUT: PERMCOM Set up with user input
  1634. ; * EXT_MSG Set up with user input
  1635. ; * System set up to retain PARSE ERRORS
  1636. ; *
  1637. ; * OUTPUT: registers unchanged
  1638. ; *
  1639. ; ****************************************************************
  1640. setup_for_messages proc near
  1641. push bx
  1642. push ds ; save data segment
  1643. push es ; save environment segment
  1644. push ax ;
  1645. push dx ;
  1646. push di ;
  1647. mov ax,cs ; get local segment to ES and DS
  1648. mov ds,ax ;
  1649. mov es,ax ;
  1650. cmp PermCom,0 ; was permcom set?
  1651. jz no_permcom ; No - don't worry about messages
  1652. ;* We're permanent. Install our message services int 2f handler.
  1653. push es
  1654. mov ax,(GET_INTERRUPT_VECTOR shl 8) or 2Fh
  1655. int 21h
  1656. mov word ptr Int2fHandler,bx
  1657. mov word ptr Int2fHandler+2,es
  1658. pop es
  1659. ; DS = RESGROUP seg addr
  1660. ;
  1661. ; M005; We will not hook int 2fh on any command.com other than the first.
  1662. ; M005; Carousel loads as a permanent command.com and when we exit Carousel,
  1663. ; M005; it just wipes our arena out. So, int 2fh is still hooked and the
  1664. ; M005; first int 2fh call after exit from Carousel (from the DOS terminate
  1665. ; M005; call) goes off into space.
  1666. ;
  1667. cmp FirstCom,0 ; M005
  1668. je no_msg_hook ; M005
  1669. ;
  1670. ; M005; !!!SLIMIEST CAROUSEL HACK OFF ALL!!!
  1671. ; M005; Carousel plays around with the interrupt vector tables. He saves it
  1672. ; M005; before loading a new command.com. Then, it takes hold of the current
  1673. ; M005; command.com's PSP and then looks at all interrupt vectors whose
  1674. ; M005; segment matches the command.com PSP and then updates these segments
  1675. ; M005; to the new command.com's PSP in his saved vector table. Whenever we
  1676. ; M005; we pop into his menu, he puts this saved table into the vector table.
  1677. ; M005; If we now quit, Carousel just wipes out command.com's arena and then
  1678. ; M005; issues a terminate. Unfortunately, the int 2fh vector is pointing at
  1679. ; M005; the command.com that was wiped out and so the next int 2fh call will
  1680. ; M005; bomb. To prevent Carousel from doing this clever(1**$$#) patching, we
  1681. ; M005; renormalize our int 2fh pointer so that its cs is not the same as the
  1682. ; M005; command.com PSP. Now, he does no such patching and our int 2fh vector
  1683. ; M005; remains nice and happy. The renormalized pointer points at a far
  1684. ; M005; jump to the actual int 2fh entry point.
  1685. ;
  1686. push ds ; M005
  1687. mov dx,offset DATARES:Carousel_i2f_Hook ; M005
  1688. sub dx,10h ; renormalize offset; M005
  1689. mov ax,ds ; M005
  1690. inc ax ; Relocated cs ; M005
  1691. mov ds,ax ; M005
  1692. mov ax,(SET_INTERRUPT_VECTOR shl 8) or 2Fh
  1693. int 21h
  1694. pop ds ; M005
  1695. mov word ptr Carousel_i2f_Hook+3,ds ; M005
  1696. ; patch in the cs for jump
  1697. no_msg_hook: ; M005
  1698. cmp Ext_Msg,SET_EXTENDED_MSG
  1699. jne short permcom_end ; no /msg - exit
  1700. permcom_slash_msg: ; Keep messages in memory
  1701. mov di,offset ResGroup:ExtMsgEnd ; get address of resident end
  1702. mov ResMsgEnd,di ; save it
  1703. jmp short permcom_end ; exit
  1704. no_permcom:
  1705. cmp Ext_msg,SET_EXTENDED_MSG ; was /msg specified?
  1706. jnz permcom_end ; no - no error
  1707. mov dx,LessArgs_Ptr ; get message number for "Required parameter missing"
  1708. call RPrintParse
  1709. permcom_end:
  1710. pop di ;
  1711. pop dx ;
  1712. pop ax ;
  1713. pop es ; get environment back
  1714. pop ds ;
  1715. pop bx
  1716. ret ;
  1717. setup_for_messages endp
  1718. ;*** CheckHelp - print help text and exit if /? is on command line
  1719. ;
  1720. ; ENTRY command-line tail at 81h
  1721. ;
  1722. ; EXIT return if /? not found
  1723. ; terminate if /? found
  1724. ;
  1725. ; USED AX,BX,CX,DX,SI,DI
  1726. ;
  1727. ; EFFECTS Help text displayed if /? found on command line
  1728. CheckHelp proc
  1729. assume cs:RESGROUP,ds:RESGROUP,es:RESGROUP,ss:RESGROUP
  1730. mov si,81h ; DS:SI = ptr to command-line tail
  1731. mov di,offset RESGROUP:Parse_Command
  1732. ; ES:DI = ptr to primary parse block
  1733. xor cx,cx ; CX = # positional param's found
  1734. xor dx,dx ; DX will be ptr to result buffer
  1735. chParse:
  1736. call Init_Parse ; call system parser
  1737. cmp ax,END_OF_LINE
  1738. je chRet ; end of command line, no /? found
  1739. cmp ax,RESULT_NO_ERROR
  1740. je chWhich ; valid syntax element found
  1741. jmp chParse ; go parse more
  1742. chWhich:
  1743. cmp Comnd1_Syn,offset RESGROUP:Command_?_Syn
  1744. je chHelp ; /? found - display help & exit
  1745. cmp Comnd1_Syn,offset RESGROUP:Command_C_Syn
  1746. je chRet ; /c found - ignore rest of line
  1747. cmp Comnd1_Syn,offset RESGROUP:Command_K_Syn
  1748. je chRet ; /k found - ignore rest of line
  1749. cmp Comnd1_Syn,offset RESGROUP:Command_z_Syn
  1750. je chRet ; /c found - ignore rest of line
  1751. jmp chParse ; anything else - ignore, keep looking
  1752. chHelp:
  1753. mov si,offset RESGROUP:HelpMsgs ; SI = ptr to msg ptr list
  1754. chHelpNext:
  1755. lodsw ; AX = ptr to msg
  1756. or ax,ax
  1757. jz chHelpDone ; end of list - all done
  1758. mov dx,ax ; DX = ptr to msg
  1759. call RPrint ; display msg
  1760. jmp chHelpNext ; go do next msg
  1761. chHelpDone:
  1762. int 20h ; terminate program
  1763. chRet: ret
  1764. CheckHelp endp
  1765. st_invalid macro
  1766. mov ax,0ffffh
  1767. push ax
  1768. push ax
  1769. endm
  1770. st_valid macro
  1771. push bx
  1772. push cx
  1773. endm
  1774. CleanForStd macro
  1775. add sp,12
  1776. endm
  1777. ;*** CheckZSwitch - Handle special /Z switch of command.com.
  1778. ; This switch has been added for SCS functionality
  1779. ; such that DOS apps can exec non-dos apps and
  1780. ; still leave DOS in a consistant state such that
  1781. ; it can be re-entered.
  1782. ;
  1783. ; ENTRY command-line tail at 81h
  1784. ;
  1785. ; EXIT non-dos binary is execed and command.com terminates after
  1786. ; non-dos binary completes.
  1787. ;
  1788. ; EFFECTS
  1789. CheckZSwitch proc
  1790. assume cs:RESGROUP,ds:RESGROUP,es:RESGROUP,ss:RESGROUP
  1791. mov si,81h ; DS:SI = ptr to command-line tail
  1792. mov di,offset RESGROUP:Parse_Command
  1793. ; ES:DI = ptr to primary parse block
  1794. xor cx,cx ; CX = # positional param's found
  1795. xor dx,dx ; DX will be ptr to result buffer
  1796. czParse:
  1797. call Init_Parse ; call system parser
  1798. cmp ax,END_OF_LINE
  1799. je czRet ; end of command line, no /? found
  1800. cmp ax,RESULT_NO_ERROR
  1801. je czWhich ; valid syntax element found
  1802. jmp short czRet
  1803. czWhich:
  1804. cmp Comnd1_Syn,offset RESGROUP:Command_z_Syn
  1805. je czSwitch
  1806. jmp short czRet
  1807. czSwitch:
  1808. push bp
  1809. xor bx,bx
  1810. mov si,bx
  1811. mov bp,bx
  1812. mov ax,5303h
  1813. int 21h
  1814. jnc st_stdin
  1815. st_invalid
  1816. jmp short go_stdout
  1817. st_stdin:
  1818. st_valid
  1819. go_stdout:
  1820. mov bx,1
  1821. mov ax,5303h
  1822. int 21h
  1823. jnc st_stdout
  1824. st_invalid
  1825. jmp short go_stderr
  1826. st_stdout:
  1827. st_valid
  1828. go_stderr:
  1829. mov bx,2
  1830. mov ax,5303h
  1831. int 21h
  1832. jnc st_stderr
  1833. st_invalid
  1834. jmp short std_done
  1835. st_stderr:
  1836. st_valid
  1837. std_done:
  1838. mov ah,19h
  1839. int 21h
  1840. mov si,84h ; 84h because that is where the real
  1841. ; command starts (i.e. 7/z\bfoo.exe)
  1842. mov bx,ds:2ch
  1843. mov bp,sp
  1844. push es
  1845. mov es,bx
  1846. xor ah,ah ; no "cmd /c"
  1847. CMDSVC SVC_CMDEXEC ; Exec non-dos binary
  1848. pop es ; ds:si is command tail (DOS_style)
  1849. ; es is env segment
  1850. ; al = current drive
  1851. ; ss:bp = std handles
  1852. ; returns al = return code
  1853. lahf
  1854. CleanForStd
  1855. pop bp
  1856. sahf
  1857. jc czReEnter
  1858. mov ah,4ch
  1859. int 21h
  1860. czRet: ret
  1861. czReEnter:
  1862. xor ah,ah
  1863. mov [SCS_REENTERED],3
  1864. mov byte ptr ds:80h,0
  1865. ret
  1866. CheckZSwitch endp
  1867. ;***** Setup_res_end -- This routine determines the resident size of COMMAND.
  1868. ; It determines based on 2 factors:
  1869. ; 1. Is this is the first COMMAND?
  1870. ; 2. Is COMMAND to be loaded into HIMEM?
  1871. ; The strategy works as follows:
  1872. ;
  1873. ; if ( First COMMAND)
  1874. ; then if (COMMAND in HIMEM)
  1875. ; ResSize = resident_data;
  1876. ; else
  1877. ; ResSize = resident_data + resident_code;
  1878. ; else
  1879. ; ResSize = resident_data;
  1880. ;
  1881. ; Int 2fh calls have been added to determine whether or not we are the first
  1882. ;COMMAND and whether DOS is in HIMEM.
  1883. ;
  1884. ; ENTRY: ResMsgEnd = resident size of data in paras
  1885. ;
  1886. ; EXIT: ResSize = resident size in low memory
  1887. ;
  1888. ; REGISTERS AFFECTED: ax,cx,dx
  1889. ;
  1890. ; NTVDM use diff al value so we don't confuse dos 5.0
  1891. ; NTVDM command.com GET_COMMAND_STATE equ 5500h
  1892. GET_COMMAND_STATE equ 5501h
  1893. GET_HMA_ADDR equ 4a02h
  1894. Setup_res_end proc near
  1895. push ds
  1896. mov ax,cs
  1897. mov ds,ax ;ds = RESGROUP
  1898. assume ds:RESGROUP
  1899. mov cx,ResMsgEnd ;set resident size = data
  1900. ;M042 -- Begin changes
  1901. ;If messages are to be kept behind, we need to round up the messages to
  1902. ;the next para boundary. This is because we have a dummy segment between the
  1903. ;data and the resident code segment so that the code segment starts on a
  1904. ;para boundary
  1905. ;
  1906. cmp cx,offset RESGROUP: ExtMsgEnd ;messages to be resident?
  1907. jne calc_res ;no, continue
  1908. add cx,15 ;round up
  1909. and cx,0fff0h
  1910. calc_res:
  1911. ;
  1912. ;M042 -- End changes
  1913. ;
  1914. xor ax,ax
  1915. cmp FirstCom,1 ;is it first command.com?
  1916. jnz not_first ;no, do not keep code
  1917. ;
  1918. ;We issue a version check call with al=01 to detect if DOS is in HMA. If so,
  1919. ;bit 4 of dh is set
  1920. ;
  1921. push bx
  1922. push cx
  1923. mov ax,(SET_CTRL_C_TRAPPING shl 8) or 06h ;is DOS in HIMEM? ;M013
  1924. int 21h
  1925. pop cx
  1926. ;bugbug: remove version check after testing
  1927. cmp bl,5 ;bl has true version ; M013
  1928. jb oldver
  1929. xor ax,ax
  1930. and dh,10h ;is DOS in HMA ; M013
  1931. pop bx
  1932. jnz not_first ;DOS in HIMEM, code not
  1933. ; resident
  1934. mov ax,offset CODERES: EndCode ;size of code in bytes
  1935. not_first:
  1936. ;
  1937. ;Note that ax = 0(side effect of int 2fh), if the code is not to be retained
  1938. ;
  1939. add cx,ax
  1940. add cx,15 ;round up to next para
  1941. shr cx,1
  1942. shr cx,1
  1943. shr cx,1
  1944. shr cx,1 ;ax = para size of res code
  1945. mov ResSize,cx ;store resident size
  1946. pop ds
  1947. assume ds:nothing
  1948. ret
  1949. ;bugbug: remove this code (for version independent COMMAND) after testing
  1950. oldver:
  1951. pop bx
  1952. mov ax,offset CODERES: EndCode ;size of code in bytes
  1953. jmp short not_first
  1954. setup_res_end endp
  1955. ;*** Move_res_code -- This routine moves the resident code to its final
  1956. ; location. We check if DOS is in HIMEM. If so, we try to load ourselves
  1957. ; in HIMEM. If we fail, then we remain low and update ResSize to reflect
  1958. ; the correct resident size. When remaining low, we have to check if we
  1959. ; need to overlay the messages part of the data segment which is determined
  1960. ; by the /msg switch.
  1961. ;
  1962. ; ENTRY: ResMsgEnd = end of resident data
  1963. ;
  1964. ; EXIT: The resident code is either up high or in its final location
  1965. ; down low.
  1966. ;
  1967. ; REGISTERS AFFECTED: ax,bx,cx,dx,si,di
  1968. ;
  1969. Move_res_code proc near
  1970. push ds
  1971. push es
  1972. mov ax,cs
  1973. mov ds,ax
  1974. assume ds:RESGROUP
  1975. mov ax,(SET_CTRL_C_TRAPPING shl 8) or 06h ; M013
  1976. int 21h ;DOS in HIMEM?
  1977. and dh,10h ; M013
  1978. jnz move_high ;yes, move code high
  1979. ;
  1980. ;Check if messages have been discarded or not
  1981. ;
  1982. load_low:
  1983. push ds
  1984. pop es ;es = RESGROUP
  1985. mov di,ResMsgEnd ;end offset in DATARES
  1986. mov bx,offset RESGROUP: ExtMsgEnd ;end offset of messages
  1987. cmp di,bx ;are messages to be kept?
  1988. jz no_move ;yes, dont move code
  1989. jmp short setup_move ;es:di points at dest.
  1990. move_high:
  1991. ;
  1992. ;We have to call DOS to get the load address in HIMEM for COMMAND
  1993. ;We pass in bx the number of bytes we need
  1994. ;
  1995. mov bx,offset CODERES: EndCode
  1996. ;M030;
  1997. ; Set di=0ffffh so that we load low in case no one answers this int 2fh
  1998. ;
  1999. mov di,0ffffh ;DT - in case no-one handles
  2000. ;this ; M030
  2001. mov ax,GET_HMA_ADDR
  2002. int 2fh
  2003. ;
  2004. ;If the offset = 0xffff, then no HMA available
  2005. ;
  2006. cmp di,0ffffh ;HMA available?
  2007. mov ComInHMA,1 ;assume command.com in HMA
  2008. jnz setup_move ;no error, es:di = memory
  2009. mov ComInHMA,0 ;could not load in HMA
  2010. ;
  2011. ;Zero means that we do not have enough HIMEM. Remain low and update
  2012. ;ResSize to reflect this
  2013. ;
  2014. mov cx,ResMsgEnd ;size of data in bytes
  2015. mov ax,offset CODERES: EndCode ;size of code in bytes
  2016. add cx,ax
  2017. add cx,15 ;round up to next para
  2018. shr cx,1
  2019. shr cx,1
  2020. shr cx,1
  2021. shr cx,1 ;ax = para size of res code
  2022. mov ResSize,cx ;store resident size
  2023. jmp short load_low ;let code remain low
  2024. no_move:
  2025. mov cl,4
  2026. add di,0fh
  2027. and di,0fff0h ;round it to a para offset
  2028. jmp short patch_up
  2029. setup_move:
  2030. mov si,offset RESGROUP: StartCode
  2031. mov cx,offset CODERES: EndCode ;cx = bytes to move
  2032. cld
  2033. push di ;need di for patching offset
  2034. rep movsb
  2035. pop di
  2036. patch_up:
  2037. call patch_stub
  2038. pop es
  2039. pop ds
  2040. assume ds:nothing
  2041. ret
  2042. Move_res_code endp
  2043. ;*** Alloc_env -- This routine allocates the temporary environment for the
  2044. ; Init code to initialize the COMSPEC. This is not a complete environment.
  2045. ; Later on, at EndInit time, a proper sized environment is allocated and
  2046. ; the contents of this temporary environment are copied to it. This routine
  2047. ; will not be called in case a valid environment is passed to command.com
  2048. ;
  2049. ; ENTRY: None
  2050. ;
  2051. ; EXIT: ax = segment of allocated environment segment
  2052. ;
  2053. ; REGISTERS AFFECTED: ax,bx,cx
  2054. ;
  2055. Alloc_env proc near
  2056. push ds
  2057. push es
  2058. push si
  2059. push di
  2060. ;
  2061. ;Allocate default environment size
  2062. ;
  2063. mov bx,SIZE Environment / 16 ;temp env size in paras
  2064. mov ah,ALLOC
  2065. int 21h
  2066. jc init_nomem ;insufficient memory, error
  2067. mov es,ax
  2068. assume es:nothing ;es = temp env segment
  2069. xor di,di
  2070. mov ax,di
  2071. ;
  2072. ;First clear out the entire buffer
  2073. ;
  2074. mov cx,SIZE Environment
  2075. rep stosb
  2076. ;
  2077. ;Init. the path string (PATH=) first
  2078. ;
  2079. push ss ; M026
  2080. pop ds ; ds = RESGROUP ; M026
  2081. assume ds:RESGROUP ; M026
  2082. mov si,offset RESGROUP: PathString ;ds:si = "PATH=\0"
  2083. mov di,Env_Pathstring ;offset of Path in env seg
  2084. pathlp:
  2085. lodsb
  2086. stosb
  2087. or al,al ;end of string?
  2088. jnz pathlp ;no, continue transfer
  2089. ;
  2090. ;Init. the Comspec string
  2091. ;
  2092. mov si,offset RESGROUP: ComspString ;"COMSPEC=\COMMAND.COM\0"
  2093. mov di,Env_Comstring ;location of Comspec string
  2094. comsplp:
  2095. lodsb
  2096. stosb
  2097. or al,al ;end of string?
  2098. jnz comsplp
  2099. mov ax,es ;return env seg in ax
  2100. pop di
  2101. pop si
  2102. pop es
  2103. pop ds
  2104. assume ds:nothing
  2105. ret
  2106. init_nomem:
  2107. ;
  2108. ;We call the error routine from here. This routine never returns. It either
  2109. ;terminates COMMAND with error( if it is not the first invocation ) or hangs
  2110. ;the system ( if it is the first COMMAND.COM ).
  2111. ;
  2112. call alloc_error
  2113. Alloc_env endp
  2114. ;*** Alloc_error: This routine just jumps to the actual label where we
  2115. ; check if this is a permanent or secondary command.com and take the
  2116. ; appropriate action.
  2117. ;
  2118. ; ENTRY: ds = RESGROUP = DATARES
  2119. ;
  2120. ; EXIT: None - does not return
  2121. ;
  2122. ; REGISTERS AFFECTED: Does not matter
  2123. ;
  2124. public Alloc_error
  2125. Alloc_error proc near
  2126. jmp RESGROUP:BadMemErr
  2127. Alloc_error endp
  2128. ;*** Patch_stub -- This routine patches in the segment and offset values in
  2129. ; the stub table of the various entry points in the resident code segment.
  2130. ; Some of them are interrupt entry points and some of them are entries from
  2131. ; the transient to the resident code segment.
  2132. ;
  2133. ; ENTRY: ds = RESGROUP
  2134. ; es:di = segment:offset of final location of resident code
  2135. ;
  2136. ; EXIT: All segments and offsets patched into the stub table
  2137. ;
  2138. ; REGISTERS AFFECTED: ax, bx, cx, dx, si, di
  2139. ;
  2140. ;
  2141. Patch_stub proc near
  2142. assume ds:RESGROUP
  2143. push es
  2144. mov bx,es ;bx = resident code segment
  2145. mov dx,di
  2146. mov di,offset DATARES:Int2f_Entry
  2147. mov si,offset RESGROUP:Reloc_Table
  2148. push ds
  2149. pop es ;es = RESGROUP = DATARES
  2150. ;
  2151. ;bx:dx = segment:offset of resident code segment
  2152. ;es:di = entry point table in stub
  2153. ;ds:si = offset table in INIT segment -- offsets of code entry points now
  2154. ;
  2155. mov cx,NUM_RELOC_ENTRIES ;number of entry points
  2156. patchlp:
  2157. lodsw ;get current offset
  2158. add ax,dx ;offset it by code seg location
  2159. stosw ;store offset
  2160. mov ax,bx
  2161. stosw ;store segment
  2162. loop patchlp
  2163. pop es
  2164. ret
  2165. Patch_stub endp
  2166. ;*** Patch_segs -- This routine patches the segment values in the dword
  2167. ; pointers that the stub uses to jump to the actual handler. These values
  2168. ; are temporarily needed to handle these interrupts if they occur before
  2169. ; the resident is relocated to its final position and all the addresses of
  2170. ; the handlers have been updated.
  2171. ;
  2172. ; ENTRY: es = PSP segment = code segment
  2173. ;
  2174. ; EXIT: Current segment values patched into the jump table in the
  2175. ; stub.
  2176. ;
  2177. ; REGISTERS AFFECTED: ax, cx, di
  2178. ;
  2179. Patch_segs proc near
  2180. mov di,offset RESGROUP:Int2f_Entry
  2181. mov cx,4 ;we have to patch 4 handlers
  2182. add di,2
  2183. mov ax,es
  2184. pseglp:
  2185. stosw ;store the segment value
  2186. add di,2 ;skip the next offset value
  2187. loop pseglp
  2188. ret
  2189. Patch_segs endp
  2190. ;*** get_XMMAddr -- This routine gets the call address for the XMM driver
  2191. ; by issuing the appropriate int 2fh. This is stored in a stub variable
  2192. ; and is used by the stub when we have to jump to the resident in HMA
  2193. ;
  2194. ; ENTRY: ds = RESGROUP
  2195. ;
  2196. ; EXIT: XMMCallAddr = XMM driver far call address
  2197. ;
  2198. ; REGISTERS AFFECTED:
  2199. ;
  2200. get_XMMAddr proc near
  2201. assume ds:RESGROUP
  2202. push es
  2203. mov ax,XMM_MULTIPLEX SHL 8 + XMM_INSTALL_CHECK
  2204. int 2Fh
  2205. cmp al,80h ; Q: installed
  2206. jne short cXMMexit ; N: set error, quit
  2207. ;
  2208. ; get the XMM control functions entry point, save it, we
  2209. ; need to call it later.
  2210. ;
  2211. mov ax,XMM_MULTIPLEX SHL 8 + XMM_FUNCTION_ADDR
  2212. int 2Fh
  2213. mov word ptr [XMMCallAddr], bx
  2214. mov word ptr [XMMCallAddr+2],es
  2215. cXMMexit:
  2216. pop es
  2217. ret ; done
  2218. get_XMMAddr endp
  2219. ; IRename
  2220. ; Input : ds:dx - Existing File
  2221. ; ds:di - NewFile
  2222. ; Output None
  2223. ;
  2224. IRename proc near
  2225. mov ah,56h
  2226. push ds
  2227. pop es
  2228. int 21h
  2229. ret
  2230. IRename endp
  2231. ; IAccess
  2232. ; Input : ds:dx - file name
  2233. ; Output CY Set if file not found
  2234. ; CY Clear if file found
  2235. IAccess proc near
  2236. mov ax,4300h
  2237. int 21h
  2238. ret
  2239. IAccess endp
  2240. ; IDelete
  2241. ; Input ds:dx - file to delete
  2242. ; Output None
  2243. IDelete proc near
  2244. mov ah,41h
  2245. int 21h
  2246. ret
  2247. IDelete endp
  2248. INIT ENDS
  2249. END
  2250.