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.

1004 lines
21 KiB

  1. page ,132
  2. title COMMAND2 - resident code for COMMAND.COM part II
  3. name COMMAND2
  4. ;/*
  5. ; * Microsoft Confidential
  6. ; * Copyright (C) Microsoft Corporation 1991
  7. ; * All Rights Reserved.
  8. ; */
  9. ;
  10. ; Revision History
  11. ; ================
  12. ;
  13. ; M038 SR 11/5/90 Changed stuff for Novell RPL. These guys cannot
  14. ; reserve memory by changing int 12h and then give it
  15. ; back to DOS by changing arenas in autoexec.bat.
  16. ; This makes command.com reload transient and this
  17. ; cannot be done at this stage.
  18. ;
  19. ;
  20. .xcref
  21. .xlist
  22. include dossym.inc
  23. include pdb.inc
  24. include syscall.inc
  25. include comsw.asm
  26. include comequ.asm
  27. include resmsg.equ
  28. include comseg.asm
  29. .list
  30. .cref
  31. DATARES segment public byte
  32. extrn Append_State:word
  33. extrn Append_Flag:byte
  34. extrn BMemMes:byte
  35. extrn ComBad:byte
  36. extrn ComDrv:byte
  37. extrn ComSpec:byte
  38. extrn EnvirSeg:word
  39. extrn ExtCom:byte
  40. extrn FRetMes:byte
  41. extrn HaltMes:byte
  42. extrn Handle01:word
  43. extrn InitFlag:BYTE
  44. extrn Int_2e_Ret:dword
  45. extrn Io_Save:word
  46. extrn Io_Stderr:byte
  47. extrn Loading:byte
  48. extrn LTpa:word
  49. extrn MemSiz:word
  50. extrn NoHandMes:byte
  51. extrn OldTerm:dword
  52. extrn Parent:word
  53. extrn PermCom:byte
  54. extrn Prompt:byte
  55. extrn PutBackDrv:byte
  56. extrn PutBackMsg:byte
  57. extrn PutBackSubst:byte
  58. extrn Res_Tpa:word
  59. extrn RetCode:word
  60. extrn Save_Pdb:word
  61. extrn SingleCom:word
  62. extrn Sum:word
  63. extrn Trans:dword
  64. extrn TranVarEnd:byte
  65. extrn TranVars:byte
  66. extrn TrnSeg:word
  67. extrn VerVal:word
  68. extrn ResSize:word
  69. extrn OldDS:word
  70. extrn RStack:word
  71. extrn Ctrlc_Trap:near
  72. extrn CritErr_Trap:near
  73. extrn LodCom_Trap:near
  74. DATARES ends
  75. ;;ENVARENA segment public para
  76. ;;ENVARENA ends
  77. ;;ENVIRONMENT segment public para ; default COMMAND environment
  78. ;;ENVIRONMENT ends
  79. INIT segment public para
  80. extrn EnvSiz:word
  81. extrn OldEnv:word
  82. extrn ResetEnv:byte
  83. extrn UsedEnv:word
  84. extrn Chuckenv:byte
  85. INIT ends
  86. TRANDATA segment public byte
  87. extrn trandataend:byte
  88. TRANDATA ends
  89. TRANSPACE segment public byte
  90. extrn transpaceend:byte
  91. extrn headcall:dword
  92. TRANSPACE ends
  93. CODERES segment public byte
  94. public BadMemErr
  95. public ChkSum
  96. ;; public EndInit
  97. public GetComDsk2
  98. public Int_2e
  99. public LoadCom
  100. public LodCom
  101. public LodCom1
  102. public RestHand
  103. public SavHand
  104. public SetVect
  105. public THeadFix
  106. public TRemCheck
  107. public TJmp
  108. assume cs:CODERES,ds:NOTHING,es:NOTHING,ss:NOTHING
  109. extrn ContC:near
  110. extrn DskErr:near
  111. extrn Alloc_error:near
  112. ;* If we cannot allocate enough memory for the transient or there
  113. ; was some other allocation error, we display a message and
  114. ; then die.
  115. ;SR;
  116. ; We will have to make sure that at this entry point and at FatalC,
  117. ;ds = DATARES. All jumps to these points are made from only within this file
  118. ;and so we should be able to do this
  119. assume ds:DATARES
  120. BadMemErr:
  121. mov dx,offset DATARES:BMemMes ; DX = ptr to msg
  122. FatalC:
  123. ;; push cs
  124. ;; pop ds
  125. ;; assume ds:ResGroup
  126. invoke RPrint
  127. ; If this is NOT a permanent (top-level) COMMAND, then we exit;
  128. ; we can't do anything else!
  129. cmp PermCom,0
  130. je FatalRet
  131. ; We are a permanent command. If we are in the process of the
  132. ; magic interrupt (Singlecom) then exit too.
  133. cmp SingleCom,0 ; if permcom and singlecom
  134. jne FatalRet ; must take int_2e exit
  135. ; Permanent command. We can't do ANYthing except halt.
  136. mov dx,offset DATARES:HaltMes ; DX = ptr to msg
  137. invoke RPrint
  138. sti
  139. Stall:
  140. jmp Stall ; crash the system nicely
  141. FatalRet:
  142. mov dx,offset DATARES:FRetMes ; DX = ptr to msg
  143. invoke RPrint
  144. FatalRet2:
  145. cmp PermCom,0 ; if we get here and permcom,
  146. jne Ret_2e ; must be int_2e
  147. ; Bugbug: this is where we'd want to unhook int 2F, *if* we
  148. ; were a non-permanent COMMAND that had hooked it! (Just in
  149. ; case we decide to do that.)
  150. mov ax,Parent
  151. mov word ptr ds:Pdb_Parent_Pid,ax
  152. mov ax,word ptr OldTerm
  153. mov word ptr ds:Pdb_Exit,ax
  154. mov ax,word ptr OldTerm+2
  155. mov word ptr ds:Pdb_Exit+2,ax
  156. mov ax,(EXIT shl 8) ; return to lower level
  157. int 21h
  158. Ret_2e:
  159. ;SR;
  160. ; We will ensure that ds = DATARES for all entries to this place
  161. ;
  162. ;; push cs
  163. ;; pop ds
  164. ;; assume ds:resgroup,es:nothing,ss:nothing
  165. assume ds:DATARES
  166. mov SingleCom,0 ; turn off singlecom
  167. mov es,Res_Tpa
  168. mov ah,DEALLOC
  169. int 21h ; free up space used by transient
  170. mov bx,Save_Pdb
  171. mov ah,SET_CURRENT_PDB
  172. int 21h ; current process is user
  173. mov ax,RetCode
  174. cmp ExtCom,0
  175. jne GotECode
  176. xor ax,ax ; internals always return 0
  177. GotECode:
  178. mov ExtCom,1 ; force external
  179. ;SR; This is actually returning to the caller. However, the old code had
  180. ;ds = RESGROUP so I guess we can keep ds = DATARES for us.
  181. ;Yes, int 2eh can corrupt all registers so we are ok.
  182. ;
  183. jmp Int_2e_Ret ;"iret"
  184. ;*** Int_2e, magic command executer
  185. Int_2e:
  186. assume ds:NOTHING,es:NOTHING,ss:NOTHING
  187. ;SR;
  188. ; We are going to come here from the stub with the old ds and DATARES value
  189. ;pushed on the stack in that order. Pick up this stuff off the stack
  190. ;
  191. pop ds ;ds = DATARES
  192. assume ds:DATARES
  193. pop ax
  194. ; pop ds:OldDS ;Save old value of ds
  195. pop word ptr Int_2e_Ret
  196. pop word ptr [Int_2e_Ret+2] ; store return address
  197. ;pop ax ; chuck flags
  198. add sp,2
  199. ;; push cs
  200. ;; pop es
  201. push ds
  202. pop es ;es = DATARES
  203. ; mov ds,OldDS
  204. mov ds,ax
  205. assume ds:nothing ;ds = old value
  206. mov di,80h
  207. mov cx,64
  208. ; Bugbug: cld
  209. rep movsw
  210. mov ah,GET_CURRENT_PDB
  211. int 21h ; get user's header
  212. mov es:Save_Pdb,bx
  213. mov ah,SET_CURRENT_PDB
  214. ;; mov bx,cs
  215. ;SR;
  216. ; Set ds = DATARES because BadMemErr expects this
  217. ;
  218. push es
  219. pop ds
  220. assume ds:DATARES
  221. mov bx,ds ;es = our PSP now
  222. int 21h ; current process is me
  223. mov SingleCom,81h
  224. mov ExtCom,1 ; make sure this case forced
  225. ;SR;
  226. ; We can enter LodCom directly after a command shell is terminated or we
  227. ;can fall thru from above. When we enter directly from the stub, the stack
  228. ;has the old ds value and the data seg value on the stack, so that ds can
  229. ;be properly set. To fake this, we push dummy values here.
  230. ;
  231. push ds ;old value of ds
  232. push ds ;data seg value, ds = DATARES
  233. LodCom: ; termination handler
  234. pop ds ;ds = DATARES
  235. assume ds:DATARES
  236. add sp,2
  237. ; pop OldDS ;store old ds
  238. cmp ExtCom,0
  239. jne @f ; internal cmd - memory allocated
  240. jmp LodCom1
  241. @@:
  242. mov bx,0FFFFh
  243. mov ah,ALLOC
  244. int 21h
  245. call SetSize
  246. add ax,20h
  247. cmp bx,ax
  248. jnc MemOk ; > 512 byte buffer - good enough
  249. BadMemErrJ:
  250. jmp BadMemErr ; not enough memory
  251. ;*** SetSize - get transient size in paragraphs
  252. SetSize proc
  253. assume ds:NOTHING,es:NOTHING
  254. mov ax,offset TRANGROUP:TranSpaceEnd + 15
  255. mov cl,4
  256. shr ax,cl
  257. ret
  258. SetSize endp
  259. MemOk:
  260. assume ds:DATARES ;we have set ds = DATARES
  261. mov ah,ALLOC
  262. int 21h
  263. jc BadMemErrJ ; memory arenas probably trashed
  264. mov ExtCom,0 ; flag not to alloc again
  265. mov Res_Tpa,ax ; save current tpa segment
  266. and ax, 0F000h
  267. add ax, 01000h ; round up to next 64k boundary
  268. jc Bad_Tpa ; memory wrap if carry set
  269. ; Make sure that new boundary is within allocated range
  270. mov dx,Res_Tpa
  271. add dx,bx ; compute maximum address
  272. cmp dx,ax ; is 64k address out of range?
  273. jbe Bad_Tpa
  274. ; Must have 64K of usable space.
  275. sub dx,ax ; compute the usable space
  276. cmp dx,01000h ; is space >= 64k ?
  277. jae LTpaSet
  278. Bad_Tpa:
  279. mov ax,Res_Tpa
  280. LTpaSet:
  281. mov LTpa,ax ; usable tpa is 64k buffer aligned
  282. mov ax,Res_Tpa ; actual tpa is buffer allocated
  283. add bx,ax
  284. mov MemSiz,bx
  285. call SetSize
  286. sub bx,ax
  287. ;
  288. ;M038; Start of changes
  289. ; Changes for Novell RPL. These guys reserve memory for themselves by
  290. ;reducing int 12h size and add this memory to the system at autoexec time by
  291. ;running a program that changes arenas. This changes the largest block that
  292. ;command.com gets and so changes the transient segment. So, command.com does
  293. ;a checksum at the wrong address and thinks that the transient is destroyed
  294. ;and tries to reload it. At this point, no Comspec is defined and so the
  295. ;reload fails, hanging the system. To get around this we just copy the
  296. ;transient from the previous address to the new address(if changed) and
  297. ;then let command.com do the checksum. So, if the transient area is not
  298. ;corrupted, there will not be any reload. In Novell's case, the transient
  299. ;is not really corrupted and so this should work.
  300. ;
  301. cmp bx,TrnSeg ;Segment still the same?
  302. je LodCom1 ;yes, dont copy
  303. ;
  304. ;Check if the new segment is above or below the current move. If the new
  305. ;segment is above(i.e new block is larger than previous block), then we
  306. ;have to move in the reverse direction
  307. ;
  308. mov cx,offset TRANGROUP:TranSpaceEnd ;cx = length to move
  309. ja mov_down ;new seg > old seg, reverse move
  310. xor si,si ;normal move
  311. mov di,si
  312. cld
  313. jmp short copy_trans
  314. mov_down:
  315. mov si,cx ;reverse move, start from end
  316. dec si
  317. mov di,si
  318. std
  319. copy_trans:
  320. push ds
  321. push es
  322. mov es,bx ;dest segment
  323. mov ds,TrnSeg ;source segment
  324. assume ds:nothing
  325. rep movsb ;copy transient
  326. cld
  327. pop es
  328. pop ds
  329. assume ds:DATARES
  330. ;
  331. ;M038; End of changes
  332. ;
  333. mov TrnSeg,bx ;new location of transient
  334. LodCom1:
  335. ;; mov ax,cs
  336. ;; mov ss,ax
  337. ;SR; At this point ds = DATARES which is where the stack is located
  338. ;
  339. mov ax,ds
  340. mov ss,ax
  341. assume ss:DATARES
  342. mov sp,offset DATARES:RStack
  343. ;; mov ds,ax
  344. assume ds:DATARES
  345. call HeadFix ; close files, restore stdin, stdout
  346. xor bp,bp ; flag command ok
  347. mov ax,-1
  348. xchg ax,VerVal
  349. cmp ax,-1
  350. je NoSetVer
  351. mov ah,SET_VERIFY_ON_WRITE ; AL has correct value
  352. int 21h
  353. NoSetVer:
  354. cmp SingleCom,-1
  355. jne NoSng
  356. jmp FatalRet2 ; we have finished the single command
  357. NoSng:
  358. call ChkSum ; check the transient
  359. cmp dx,Sum
  360. je HavCom ; transient ok
  361. Bogus_Com:
  362. mov Loading,1 ; flag DskErr routine
  363. call LoadCom
  364. ChkSame:
  365. call ChkSum
  366. cmp dx,Sum
  367. jz HavCom ; same command
  368. Also_Bogus:
  369. call WrongCom
  370. jmp short ChkSame
  371. HavCom:
  372. mov Loading,0 ; flag to DskErr
  373. mov si,offset DATARES:TranVars
  374. mov di,offset TRANGROUP:HeadCall
  375. mov es,TrnSeg
  376. cld
  377. mov cx,offset DATARES:TranVarEnd
  378. sub cx,si
  379. rep movsb ; transfer info to transient
  380. mov ax,MemSiz
  381. mov word ptr ds:Pdb_Block_Len,ax ; adjust my own header
  382. ;*** TJmp - jump-off to transient
  383. ;
  384. ; Public label so debugger can find this spot.
  385. TJmp:
  386. jmp Trans
  387. ;*** TRemCheck - far version of RemCheck for transient
  388. TRemCheck proc far
  389. pop ds ;ds = DATARES
  390. add sp,2 ;discard old value of ds
  391. call RemCheck
  392. ret
  393. TRemCheck endp
  394. ;*** RemCheck
  395. ;
  396. ; ENTRY AL = drive (0=default, 1=A, ...)
  397. ;
  398. ; EXIT ZR set if removeable media
  399. ; ZR clear if fixed media
  400. ;
  401. ; USED none
  402. RemCheck:
  403. savereg <ax,bx>
  404. mov bx,ax
  405. mov ax,(IOCTL shl 8) + 8
  406. int 21h
  407. jnc rcCont
  408. ; If an error occurred, assume the media is non-removable.
  409. ; AX contains the non-zero error code from the int 21, so
  410. ; 'or ax,ax; sets non-zero. This behavior makes network drives
  411. ; appear to be non-removable.
  412. or ax,ax
  413. jmp short ResRegs
  414. rcCont:
  415. and ax,1
  416. not ax
  417. ResRegs:
  418. restorereg <bx,ax>
  419. ret
  420. ;*** THeadFix
  421. ;
  422. ; Far version of HeadFix, called from transient.
  423. THeadFix proc far
  424. pop ds ;ds = DATARES
  425. add sp,2 ;discard old ds value on stack
  426. call HeadFix
  427. ret
  428. THeadFix endp
  429. ;*** HeadFix
  430. HeadFix:
  431. call SetVect ; set vectors to our values
  432. ; Clean up header
  433. ; Bugbug: optimize:
  434. ; mov word ptr ds:Pdb_Jfn_Table,cx instead of separate bytes
  435. xor bx,bx ; BX = handle = 0
  436. mov cx,Io_Save ; CX = original stdin, stdout
  437. mov dx,word ptr ds:Pdb_Jfn_Table ; DX = current stdin, stdout
  438. cmp cl,dl
  439. je Chk1 ; stdin matches
  440. mov ah,CLOSE
  441. int 21h ; close stdin
  442. mov ds:Pdb_Jfn_Table,cl ; restore stdin
  443. Chk1:
  444. inc bx ; BX = handle = 1
  445. cmp ch,dh
  446. je ChkStderr ; stdout matches
  447. mov ah,CLOSE
  448. int 21h ; close stdout
  449. mov ds:Pdb_Jfn_Table+1,ch ; restore stdout
  450. ChkStderr:
  451. inc bx ; BX = handle = 2
  452. mov dl,byte ptr ds:[Pdb_Jfn_Table+2] ; Dl = current stderr
  453. mov cl,Io_Stderr ; Cl = original stderr
  454. cmp dl,cl
  455. je ChkOtherHand ; stderr matches
  456. mov ah,CLOSE
  457. int 21h ; close stderr
  458. mov ds:Pdb_Jfn_Table+2,cl ; restore stderr
  459. ChkOtherHand:
  460. add bx,3 ; skip handles 3,4
  461. ifdef NEC_98
  462. add bx,4 ; skip handles 2,3,4
  463. endif ;NEC_98
  464. mov cx,FILPERPROC - 5 ; CX = # handles to close
  465. ; (handles 0-4 already done)
  466. ;; williamh: March 30, 1993, don't close invalid handle , save some time
  467. push si
  468. mov si, pdb_jfn_table ;go to the handle table
  469. CloseLoop:
  470. cmp byte ptr [bx][si], 0ffh
  471. je Skip_this_handle
  472. mov ah,CLOSE
  473. int 21h ; close each handle
  474. Skip_this_handle:
  475. inc bx
  476. loop CloseLoop
  477. pop si
  478. ; Bugbug: since this is for transient code, move it there
  479. ; M012: remove this CS -> DS. Must've been missed during
  480. ; purification.
  481. ;; push ds ; save data segment
  482. ;; push cs ; get local segment into DS
  483. ;; pop ds ;
  484. cmp Append_Flag,-1 ; do we need to reset APPEND?
  485. jne Append_Fix_End ; no - just exit
  486. mov ax,AppendSetState ; set the state of Append
  487. mov bx,Append_State ; back to the original state
  488. int 2Fh ;
  489. mov Append_Flag,0 ; set append flag to invalid
  490. Append_Fix_End: ;
  491. ;; pop ds ; get data segment back
  492. ret
  493. ;*** SavHand - save current program's stdin/out & set to our stderr
  494. ;
  495. ; ENTRY nothing
  496. ;
  497. ; EXIT nothing
  498. ;
  499. ; USED flags
  500. ;
  501. ; EFFECTS
  502. ; Handle01 = current program's stdin,stdout JFN entries
  503. ; current program's stdin,stdout set to our stderr
  504. ;
  505. ;SR;
  506. ; Changed ds = DATARES. We need it to access our JFN_Table
  507. ; Called from ContC ( ds = DATARES ) and DskErr ( ds = DATARES ).
  508. ;
  509. SavHand proc
  510. assume ds:DATARES,es:NOTHING,ss:NOTHING
  511. push bx ;preserve registers
  512. push ax
  513. push es
  514. push ds ; save DATARES value
  515. mov ah,GET_CURRENT_PDB
  516. int 21h ; BX = user's header seg addr
  517. mov ds,bx ; DS = user's header seg addr
  518. lds bx,ds:PDB_JFN_POINTER ; DS:BX = ptr to JFN table
  519. mov ax,word ptr ds:[bx] ; AX = stdin,stdout JFN's
  520. pop es ;es = DATARES
  521. push es ;save it back on stack
  522. mov es:Handle01,ax ; save user's stdin, stdout
  523. ;SR;
  524. ; Use es to address Handle01 & our JFN_Table
  525. ;
  526. mov al,es:[PDB_JFN_TABLE+2] ; AL = COMMAND stderr
  527. mov ah,al ; AH = COMMAND stderr
  528. mov word ptr ds:[bx],ax ; set user's stdin/out to our stderr
  529. pop ds ; restore registers
  530. pop es
  531. pop ax
  532. pop bx
  533. ret
  534. SavHand endp
  535. assume ds:DATARES
  536. GetComDsk2:
  537. call GetComDsk
  538. jmp LodCom1 ; memory already allocated
  539. RestHand:
  540. push ds
  541. push bx ; restore stdin, stdout to user
  542. push ax
  543. mov ah,GET_CURRENT_PDB
  544. int 21h ; point to user's header
  545. mov ax,Handle01
  546. mov ds,bx
  547. assume ds:NOTHING
  548. lds bx,ds:Pdb_Jfn_Pointer ; DS:BX = ptr to jfn table
  549. mov word ptr ds:[bx],ax ; stuff his old 0 and 1
  550. pop ax
  551. pop bx
  552. pop ds
  553. ret
  554. assume ds:DATARES,ss:DATARES
  555. Hopeless:
  556. mov dx,offset DATARES:ComBad
  557. jmp FatalC
  558. GetComDsk:
  559. mov al,ComDrv
  560. call RemCheck
  561. jnz Hopeless ; non-removable media
  562. GetComDsk3:
  563. cmp dx,offset DATARES:ComBad
  564. jnz GetComDsk4
  565. mov dx,offset DATARES:ComBad ; DX = ptr to msg
  566. invoke RPrint ; say COMMAND is invalid
  567. GetComDsk4:
  568. ; Bugbug: there's always a drive here? No need to check?
  569. cmp PutBackDrv,0 ; is there a drive in the comspec?
  570. jnz Users_Drive ; yes - use it
  571. mov ah,GET_DEFAULT_DRIVE ; use default drive
  572. int 21h
  573. add al,"A" ; convert to ascii
  574. mov PutBackDrv,al ; put in message to print out
  575. Users_Drive:
  576. mov dx,offset DATARES:PutBackMsg ; prompt for diskette
  577. mov si,offset DATARES:PutBackSubst ; containing COMMAND
  578. invoke RPrint
  579. mov dx,offset DATARES:Prompt ; "Press any key"
  580. invoke RPrint
  581. call GetRawFlushedByte
  582. ret
  583. ;*** GetRawFlushedByte - flush world and get raw input
  584. GetRawFlushedByte:
  585. mov ax,(STD_CON_INPUT_FLUSH shl 8) or RAW_CON_INPUT
  586. int 21h ; get char without testing or echo
  587. mov ax,(STD_CON_INPUT_FLUSH shl 8) + 0
  588. int 21h
  589. ; Bugbug: get rid of this return and the following retz.
  590. return
  591. ;*** LoadCom - load in transient
  592. LoadCom:
  593. inc bp ; flag command read
  594. mov dx,offset DATARES:ComSpec
  595. mov ax,OPEN shl 8
  596. int 21h ; open command.com
  597. jnc ReadCom
  598. cmp ax,ERROR_TOO_MANY_OPEN_FILES
  599. jnz TryDoOpen
  600. mov dx,offset DATARES:NoHandMes
  601. jmp FatalC ; will never find a handle
  602. TryDoOpen:
  603. call GetComDsk
  604. jmp LoadCom
  605. ReadCom:
  606. mov bx,ax ; BX = handle
  607. mov dx,offset RESGROUP:TranStart
  608. xor cx,cx ; CX:DX = seek loc
  609. mov ax,LSEEK shl 8
  610. int 21h
  611. jc WrongCom1
  612. mov cx,offset TRANGROUP:TranSpaceEnd - 100h
  613. push ds
  614. mov ds,TrnSeg
  615. assume ds:NOTHING
  616. mov dx,100h
  617. mov ah,READ
  618. int 21h
  619. pop ds
  620. assume ds:DATARES
  621. WrongCom1:
  622. pushf
  623. push ax
  624. mov ah,CLOSE
  625. int 21h ; close command.com
  626. pop ax
  627. popf
  628. jc WrongCom ; error on read
  629. cmp ax,cx
  630. retz ; size matched
  631. WrongCom:
  632. mov dx,offset DATARES:ComBad
  633. call GetComDsk
  634. jmp LoadCom ; try again
  635. ;*** ChkSum - compute transient checksum
  636. ChkSum:
  637. push ds
  638. mov ds,TrnSeg
  639. mov si,100h
  640. mov cx,offset TRANGROUP:TranDataEnd - 100H
  641. Check_Sum:
  642. cld
  643. shr cx,1
  644. xor dx,dx
  645. Chk:
  646. lodsw
  647. add dx,ax
  648. adc dx,0
  649. loop Chk
  650. pop ds
  651. ret
  652. ;*** SetVect - set interrupt vectors
  653. SetVect:
  654. mov dx,offset DATARES:LodCom_Trap
  655. mov ax,(SET_INTERRUPT_VECTOR shl 8) or 22h
  656. mov word ptr ds:Pdb_Exit,dx
  657. mov word ptr ds:Pdb_Exit+2,ds
  658. int 21h
  659. mov dx,offset DATARES:Ctrlc_Trap
  660. inc al
  661. int 21h
  662. mov dx,offset DATARES:CritErr_Trap
  663. inc al
  664. int 21h
  665. ret
  666. ;SR;
  667. ; We have this to take care of the extra values pushed on the stack by
  668. ;the stub before jumping to LodCom1. We set up ds here and then jump to
  669. ;Lodcom1
  670. ;
  671. public TrnLodCom1
  672. TrnLodCom1:
  673. pop ds ;ds = DATARES
  674. add sp,2
  675. ; pop ds:OldDS
  676. jmp LodCom1
  677. ;*** EndInit - end up initialization sequence
  678. ;
  679. ; Move the environment to a newly allocated segment.
  680. ;;EndInit:
  681. ;; push ds ; save segments
  682. ;; push es ;
  683. ;; push cs ; get resident segment to DS
  684. ;; pop ds ;
  685. ;; assume ds:RESGROUP
  686. ;; mov cx,UsedEnv ; get number of bytes to move
  687. ;; mov es,EnvirSeg ; get target environment segment
  688. ;; assume es:NOTHING
  689. ;;
  690. ;; mov ds:Pdb_Environ,es ; put new environment in my header
  691. ;; mov ds,OldEnv ; source environment segment
  692. ;; assume ds:NOTHING
  693. ;; xor si,si ; set up offsets to start of segments
  694. ;; xor di,di
  695. ;; cld
  696. ;; rep movsb ; move it
  697. ;; xor ax,ax
  698. ;; stosb ; make sure it ends with double-null
  699. ;;
  700. ;; cmp ResetEnv,1 ; do we need to setblock to env end?
  701. ;; jne NoReset ; no - we already did it
  702. ;; mov bx,EnvSiz ; BX = size of environ in paragraphs
  703. ;; push es ; save environment - just to be sure
  704. ;; mov ah,SETBLOCK ;
  705. ;; int 21h
  706. ;; pop es
  707. ;;
  708. ;;NoReset:
  709. ;; mov InitFlag,FALSE ; turn off init flag
  710. ;; pop es
  711. ;; pop ds
  712. ;; jmp LodCom ; allocate transient
  713. ;
  714. ;The init code has been changed to take care of the new way in which the
  715. ;environment segment is allocated.
  716. ;NB: We can use all the init variables at this point because they are all in
  717. ;RESGROUP
  718. ;Bugbug: The above approach will not work for ROMDOS
  719. ;
  720. IF 0
  721. EndInit:
  722. push ds
  723. push es ;save segments
  724. push cs
  725. pop ds
  726. assume ds:RESGROUP
  727. ;
  728. ;Chuckenv flag signals whether it is a passed environment or not
  729. ;
  730. mov bx,ds
  731. mov es,bx ;es = RESGROUP
  732. ;
  733. ;ResSize is the actual size to be retained -- only data for HIMEM COMMAND,
  734. ; code + data for low COMMAND
  735. ;
  736. mov bx,ResSize ;Total size of resident
  737. mov ah,SETBLOCK
  738. int 21h ;Set block to resident size
  739. ;
  740. ;Allocate the correct size for the environment
  741. ;
  742. mov bx,EnvSiz ;bx = env size in paras
  743. mov ah,ALLOC
  744. int 21h ;get memory
  745. jc nomem_err ;out of memory,signal error
  746. mov EnvirSeg,ax ;Store new environment segment
  747. mov ds:PDB_Environ,ax ;Put new env seg in PSP
  748. mov es,ax ;es = address of allocated memory
  749. assume es:nothing
  750. ;
  751. ;Copy the environment to the newly allocated segment
  752. ;
  753. mov cx,UsedEnv ;number of bytes to move
  754. push ds
  755. mov ds,OldEnv ;ds = Old environment segment
  756. assume ds:nothing
  757. xor si,si
  758. mov di,si ;Start transfer from 0
  759. cld
  760. rep movsb ;Do the copy
  761. xor ax,ax
  762. stosb ;Make it end with double-null
  763. pop ds ;ds = RESGROUP
  764. assume ds:RESGROUP
  765. ;
  766. ;We have to free the old environment block if it was allocated by INIT
  767. ;
  768. cmp Chuckenv,0 ;has env been allocated by INIT?
  769. jne no_free ;no, do not free it
  770. mov ax,OldEnv ;Get old environment
  771. mov es,ax
  772. mov ah,DEALLOC
  773. int 21h ;Free it
  774. no_free:
  775. mov InitFlag,FALSE ;indicate INIT is done
  776. pop es
  777. pop ds
  778. assume ds:nothing
  779. jmp LodCom ;allocate transient
  780. nomem_err:
  781. ;
  782. ;We call the error routine which will never return. It will either exit
  783. ;with an error ( if not the first COMMAND ) or just hang after an error
  784. ;message ( if first COMMAND )
  785. ;
  786. call Alloc_error
  787. ENDIF
  788. CODERES ends
  789. ; This TAIL segment is used to produce a PARA aligned label in
  790. ; the resident group which is the location where the transient
  791. ; segments will be loaded initial.
  792. TAIL segment public para
  793. org 0
  794. TranStart label word
  795. public TranStart
  796. TAIL ends
  797. ; This TAIL segment is used to produce a PARA aligned label in
  798. ; the transient group which is the location where the exec
  799. ; segments will be loaded initial.
  800. ;
  801. ; Bugbug: Is TRANTAIL used anymore?
  802. TRANTAIL segment public para
  803. org 0
  804. ExecStart label word
  805. TRANTAIL ends
  806. end
  807.