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.

1329 lines
27 KiB

  1. page ,132
  2. title Localizable code for resident COMMAND
  3. ;/*
  4. ; * Microsoft Confidential
  5. ; * Copyright (C) Microsoft Corporation 1991
  6. ; * All Rights Reserved.
  7. ; */
  8. ;
  9. ; Revision History
  10. ; ================
  11. ; M003 SR 07/16/90 Added routines Lh_Off, Lh_Unlink &
  12. ; Lh_OffUnlink for UMB support
  13. ;
  14. ; M009 SR 08/01/90 Rewrote Lh_OffUnlink to restore the
  15. ; initial UMB state. Removed Lh_off
  16. ; and Lh_Unlink.
  17. ;
  18. .xlist
  19. .xcref
  20. include dossym.inc
  21. include syscall.inc
  22. include filemode.inc
  23. include pdb.inc
  24. include mult.inc
  25. include doscntry.inc
  26. include devsym.inc
  27. include comsw.asm
  28. include comseg.asm
  29. include comequ.asm
  30. include resmsg.equ
  31. include arena.inc ; M003
  32. .list
  33. .cref
  34. DATARES segment public byte
  35. extrn Abort_Char:byte
  36. extrn BadFatMsg:byte
  37. extrn BadFatSubst:byte
  38. extrn Batch_Abort:byte
  39. extrn BlkDevErr:byte
  40. extrn BlkDevErrRw:byte
  41. extrn BlkDevErrSubst:byte
  42. extrn CDevAt:byte
  43. extrn CharDevErr:byte
  44. extrn CharDevErrRw:byte
  45. extrn CharDevErrSubst:byte
  46. extrn ComSpec:byte
  47. extrn Crit_Err_Info:byte
  48. extrn Crit_Msg_Off:word
  49. extrn Crit_Msg_Seg:word
  50. extrn CritMsgPtrs:word
  51. extrn Dbcs_Vector_Addr:dword
  52. extrn DevName:byte
  53. extrn DrvLet:byte
  54. extrn EndBatMes:byte
  55. extrn ErrCd_24:word
  56. extrn ErrType:byte
  57. extrn Fail_Char:byte
  58. extrn fFail:byte
  59. extrn ForFlag:byte
  60. extrn Ignore_Char:byte
  61. extrn InitFlag:byte
  62. extrn In_Batch:byte
  63. extrn Int2fHandler:dword
  64. extrn Loading:byte
  65. extrn MsgBuffer:byte
  66. extrn MsgPtrLists:dword
  67. extrn MRead:byte
  68. extrn MWrite:byte
  69. extrn NeedVol:dword
  70. extrn NeedVolMsg:byte
  71. extrn NeedVolSubst:byte
  72. extrn Newlin:byte
  73. extrn No_Char:byte
  74. extrn NUMEXTMSGS:abs
  75. extrn NUMPARSMSGS:abs
  76. extrn OldErrNo:word
  77. extrn Parent:word
  78. extrn ParsMsgPtrs:word
  79. extrn Patricide:byte
  80. extrn PermCom:byte
  81. extrn Retry_Char:byte
  82. extrn Req_Abort:byte
  83. extrn Req_End:byte
  84. extrn Req_Fail:byte
  85. extrn Req_Ignore:byte
  86. extrn Req_Retry:byte
  87. extrn ResMsgEnd:word
  88. extrn PipeFlag:byte
  89. extrn SingleCom:word
  90. extrn VolName:byte
  91. extrn Yes_Char:byte
  92. extrn OldDS:word
  93. extrn Int2f_Entry:dword
  94. DATARES ends
  95. ; NTVDM use diff al value so we don't confuse dos 5.0
  96. ; NTVDM command.com GET_COMMAND_STATE equ 5500h
  97. GET_COMMAND_STATE equ 5501h
  98. CODERES segment public byte
  99. extrn GetComDsk2:near
  100. public AskEnd
  101. public Crlf
  102. public DskErr
  103. public MsgInt2fHandler
  104. public MsgRetriever
  105. public RPrint
  106. ifdef BILINGUAL
  107. public RPrint@
  108. endif
  109. ifdef DBCS
  110. public ITestKanj
  111. endif
  112. ; Bugbug: Move rest of PUBLIC declarations up here.
  113. assume cs:CODERES,ds:NOTHING,es:NOTHING,ss:NOTHING
  114. ;*** AskEnd - ask user to confirm batch file termination
  115. ;
  116. ; Confirm with user before freeing batch ...
  117. ;
  118. ; ENTRY nothing
  119. ;
  120. ; EXIT CY = set if batch termination is confirmed
  121. ;
  122. ; CY = clear if batch should continue
  123. ;
  124. ; USED AX,DX,...
  125. ; Bugbug: move this to transient, copy to batch segment.
  126. ; Bugbug: or move it to command1 1st.
  127. ; Bugbug: No_Char and Yes_Char should be constants.
  128. AskEnd proc
  129. assume ds:DATARES
  130. mov dx,offset DATARES:EndBatMes ; DX = message #
  131. call RPrint
  132. mov ax,(STD_CON_INPUT_FLUSH shl 8) + STD_CON_INPUT
  133. int 21h
  134. call CharToUpper ; change to upper case
  135. cmp al,No_Char
  136. je aeRet ; answer is no (CY is clear)
  137. cmp al,Yes_Char
  138. jne AskEnd ; invalid response, try again
  139. stc ; answer is yes
  140. aeRet: ret
  141. AskEnd endp
  142. ;*** DskErr - critical error handler
  143. ;
  144. ; Default critical error handler unless user intercepts int 24h.
  145. ;
  146. ; ENTRY int 24h
  147. ;
  148. ; EXIT
  149. ;
  150. ; USED
  151. ;
  152. ; EFFECTS
  153. ;
  154. ;SR;
  155. ; The stub is going to push the old ds value and the resident data segment
  156. ;onto the stack in that order. Get it off the stack
  157. ;
  158. DskErr proc far
  159. assume ds:NOTHING,es:NOTHING,ss:NOTHING
  160. pop ds ;ds = DATARES
  161. assume ds:DATARES
  162. pop OldDS ;save old ds value
  163. sti
  164. push es
  165. push si
  166. push cx
  167. push di
  168. push cx
  169. push ax
  170. push ds ;save our data segment
  171. pop es ;es = DATARES
  172. mov ds,bp
  173. assume ds:nothing
  174. mov ax,[si].SDEVATT
  175. mov es:CDevAt,ah
  176. ;; push cs
  177. ;; pop es
  178. mov di,offset DATARES:DevName
  179. mov cx,8
  180. add si,SDEVNAME ; save device name (even for block device)
  181. cld
  182. rep movsb
  183. pop ax
  184. pop cx
  185. pop di
  186. ; Stack still contains DS and ES.
  187. ;SR;
  188. ; We need ds = DATARES for SavHand
  189. ;
  190. push es
  191. pop ds
  192. assume ds:DATARES
  193. invoke SavHand ; save user's stdin/out, set to our stderr
  194. ;; push cs
  195. ;; pop ds ; set up local data segment
  196. ;; assume ds:resgroup
  197. push dx
  198. call Crlf
  199. pop dx
  200. ; Bugbug: rename Crit_Err_Info to CritErrAH?
  201. mov Crit_Err_Info,ah ; save critical error flags
  202. ; Compute and save ASCII drive letter (nonsense for char devices)
  203. add al,'A'
  204. mov DrvLet,al
  205. ; Bugbug: These labels are awful. Change, especially 'NoHardE'.
  206. test ah,80h
  207. jz NoHardE ; it's a disk-device error
  208. test CDevAt,DEVTYP shr 8
  209. jnz NoHardE ; it's a character device
  210. jmp FatErr ; it's a FAT error
  211. NoHardE:
  212. mov si,offset DATARES:MRead ; SI = "read" msg #
  213. test ah,1
  214. jz SavMes ; it's a read error
  215. mov si,offset DATARES:MWrite ; SI = "write" msg #
  216. SavMes:
  217. mov OldErrNo,di ; save critical error code
  218. ; Bugbug: don't need to save/restore all here?
  219. push es
  220. push ds ; GetExtendedError likes to STOMP
  221. push bp
  222. push si
  223. push dx
  224. push cx
  225. push bx
  226. mov ah,GetExtendedError ; get extended error info
  227. int 21h
  228. pop bx
  229. pop cx
  230. pop dx
  231. pop si
  232. pop bp
  233. pop ds
  234. mov word ptr NeedVol,di ; save possible ptr to volume label
  235. mov word ptr NeedVol+2,es
  236. pop es
  237. ; Bugbug: AX has extended error code, so no need to zero AH?
  238. xor ah,ah
  239. mov di,ax ; DI = error code
  240. ; Bugbug: somewhat obsolete documentation?
  241. ;
  242. ; DI is now the correct error code. Classify things to see what we are
  243. ; allowed to report. We convert DI into a 0-based index into a message table.
  244. ; This presumes that the int 24 errors (oldstyle) and new errors (sharing and
  245. ; the like) are contiguous.
  246. ;
  247. ; Bugbug: simplify following code by cmp'ing instead of sub'ing.
  248. ; Check use of ErrCd_24, though.
  249. sub di,ERROR_WRITE_PROTECT
  250. jae HavCod
  251. ; Bugbug wouldn't it be better to display the original error msg,
  252. ; even though it's not a critical error?
  253. mov di,ERROR_GEN_FAILURE - ERROR_WRITE_PROTECT
  254. ;
  255. ; DI now has the mapped error code. Old style errors are:
  256. ; FOOBAR <read|writ>ing drive ZZ.
  257. ; New style errors are:
  258. ; FOOBAR
  259. ; We need to figure out which the particular error belongs to.
  260. ;
  261. HavCod:
  262. mov ErrType,0 ; assume old style
  263. cmp di,ERROR_FCB_UNAVAILABLE - ERROR_WRITE_PROTECT
  264. je SetStyle
  265. cmp di,ERROR_SHARING_BUFFER_EXCEEDED - ERROR_WRITE_PROTECT
  266. jne GotStyle
  267. SetStyle:
  268. ; Bugbug: use INC
  269. mov ErrType,1 ; must be new type
  270. GotStyle:
  271. mov [ErrCd_24],di
  272. cmp di,ERROR_HANDLE_DISK_FULL - ERROR_WRITE_PROTECT
  273. ; If the error message is unknown
  274. jbe NormalError ; redirector, continue. Otherwise,
  275. ;
  276. ; We do not know how to handle this error. Ask IFSFUNC if she knows
  277. ; how to handle things
  278. ;
  279. ;input to IFSFUNC: AL=1
  280. ; BX=extended error number
  281. ;
  282. ;output from IFSFUNC: AL=error type (0 or 1)
  283. ; 0=<message> error (read/writ)ing (drive/device) xxx
  284. ; Abort, Retry, Ignore
  285. ; 1=<message>
  286. ; Abort, Retry, Ignore
  287. ; ES:DI=pointer to message text
  288. ; carry set=>no message
  289. mov di,ax ; retrieve correct extended error...
  290. mov ax,0500h ; is the redir there?
  291. int 2fh
  292. cmp al,0ffh
  293. jne NoHandler ; no, go to NoHandler
  294. push bx
  295. mov bx,di ; get ErrType and ptr to error msg
  296. mov ax,0501h
  297. int 2fh
  298. pop bx
  299. jc NoHandler
  300. ; Bugbug: need to record error type?
  301. mov ErrType,al
  302. push ds
  303. push es
  304. pop ds
  305. mov dx,di
  306. mov cx,-1 ; find end of msg
  307. xor al,al
  308. cld
  309. repnz scasb
  310. ; Bugbug: we can do better than this.
  311. mov byte ptr [di-1],'$'
  312. mov ah,STD_CON_STRING_OUTPUT ; print the message
  313. int 21h
  314. mov byte ptr [di-1],0 ; restore terminal byte
  315. pop ds ; clean up and continue
  316. jmp short CheckErrType
  317. ;* Redir isn't available or doesn't recognize the error.
  318. ; Restore regs to unextended error.
  319. NoHandler:
  320. mov ErrType,0
  321. ; Bugbug: won't this break, since we add error_write_protect back in?
  322. mov di,OldErrNo
  323. mov ErrCd_24,di
  324. NormalError:
  325. add di,ERROR_WRITE_PROTECT
  326. xchg di,dx ; may need dx later
  327. call RPrintCrit ; print error type
  328. CheckErrType:
  329. cmp ErrType,0 ; Check error style...
  330. je ContOld
  331. call CrLf ; if new style then done printing
  332. jmp short Ask
  333. ContOld:
  334. inc si ; DS:SI = ptr to asciiz string
  335. ; Bugbug: combine some of the following two sections?
  336. test [CDevAt],DEVTYP shr 8
  337. jz BlkErr
  338. mov dx,offset DATARES:CharDevErr ; DX = ptr to device message
  339. mov CharDevErrRw.SubstPtr,si ; point to read/write string
  340. mov si,offset DATARES:CharDevErrSubst; SI = ptr to subst block
  341. call RPrint ; print the message
  342. jmp short Ask ; don't ralph on command
  343. BlkErr:
  344. mov dx,offset DATARES:BlkDevErr ; DX = error msg #
  345. mov BlkDevErrRw.SubstPtr,si ; "reading","writing" ptr
  346. mov si,offset DATARES:BlkDevErrSubst ; SI = ptr to subst block
  347. call RPrint
  348. cmp Loading,0
  349. jz Ask
  350. invoke RestHand
  351. jmp GetComDsk2 ; if error loading COMMAND, re-prompt
  352. Ask:
  353. cmp [ErrCd_24],15 ; error 15 has an extra message
  354. jne Not15 ; not error 15
  355. ;* For error 15, tell the user which volume/serial # are needed.
  356. push cx
  357. ; Bugbug: does this push/pop need to be done?
  358. push ds
  359. pop es
  360. lds si,NeedVol
  361. assume ds:NOTHING
  362. push di
  363. mov di,offset DATARES:VolName
  364. mov cx,16 ; copy volume name & serial #
  365. cld
  366. rep movsb
  367. pop di
  368. push es
  369. pop ds
  370. pop cx
  371. assume ds:DATARES
  372. mov dx,offset DATARES:NeedVolMsg ; DX = ptr to msg
  373. mov si,offset DATARES:NeedVolSubst ; DS:SI = ptr to subst block
  374. call RPrint
  375. Not15:
  376. ;* Print abort, retry, ignore, fail message.
  377. ; Print only options that are valid.
  378. ; Bugbug: sizzle this.
  379. mov dx,offset DATARES:Req_Abort
  380. call RPrint
  381. test Crit_Err_Info,RETRY_ALLOWED
  382. jz Try_Ignore
  383. mov dx,offset DATARES:Req_Retry
  384. call RPrint
  385. Try_Ignore:
  386. test Crit_Err_Info,IGNORE_ALLOWED
  387. jz Try_Fail
  388. mov dx,offset DATARES:Req_Ignore
  389. call RPrint
  390. Try_Fail:
  391. test Crit_Err_Info,FAIL_ALLOWED
  392. jz Term_Question
  393. mov dx,offset DATARES:Req_Fail
  394. call RPrint
  395. Term_Question:
  396. mov dx,offset DATARES:Req_End
  397. call RPrint
  398. ; If the /f switch was given, we fail all requests.
  399. test fFail,-1
  400. jz DoPrompt
  401. mov ah,3 ; signal fail
  402. jmp EExit
  403. DoPrompt:
  404. mov ax,(STD_CON_INPUT_FLUSH shl 8) + STD_CON_INPUT
  405. int 21h ; get response
  406. ; Bugbug: can Kanji code be conditional?
  407. ifdef DBCS
  408. invoke TestKanjR ; 3/3/KK
  409. jz NotKanj ; 3/3/KK
  410. mov ax,(STD_CON_INPUT shl 8) ; eat the 2nd byte of ECS code 3/3/KK
  411. int 21h ; 3/3/KK
  412. call Crlf ; 3/3/KK
  413. jmp Ask ; 3/3/KK
  414. NotKanj: ; 3/3/KK
  415. endif
  416. call Crlf
  417. call CharToUpper ; convert to upper case
  418. mov ah,0 ; return code for ignore
  419. test Crit_Err_Info,IGNORE_ALLOWED ; is ignore allowed?
  420. jz user_retry
  421. cmp al,Ignore_Char ; ignore?
  422. jz EExitJ
  423. ; Bugbug: optimize following code.
  424. User_Retry:
  425. inc ah ; return code for retry
  426. test Crit_Err_Info,RETRY_ALLOWED ; is retry allowed?
  427. jz User_Abort
  428. cmp al,Retry_Char ; retry?
  429. jz EExitJ
  430. User_Abort:
  431. inc ah ; return code for abort
  432. ; (abort always allowed)
  433. cmp al,Abort_Char ; abort?
  434. jz Abort_Process ; exit user program
  435. inc ah ; return code for fail
  436. test Crit_Err_Info,FAIL_ALLOWED ; is fail allowed?
  437. jz AskJ
  438. cmp al,Fail_Char ; fail?
  439. jz EExitJ
  440. AskJ:
  441. jmp Ask
  442. EExitJ:
  443. jmp short EExit
  444. Abort_Process:
  445. test InitFlag,INITINIT ; COMMAND init interrupted?
  446. jz AbortCont ; no, handle it normally
  447. cmp PermCom,0 ; are we top level process?
  448. jz JustExit ; yes, just exit
  449. mov dx,offset DATARES:Patricide ; no, load ptr to error msg
  450. call RPrint ; print it
  451. DeadInTheWater:
  452. jmp DeadInTheWater ; loop until the user reboots
  453. JustExit:
  454. assume ds:DATARES
  455. mov ax,Parent ; load real parent pid
  456. mov word ptr ds:Pdb_Parent_Pid,ax ; put it back where it belongs
  457. mov ax,(EXIT shl 8) or 255
  458. int 21h
  459. AbortCont:
  460. test byte ptr In_Batch,-1 ; Are we accessing a batch file?
  461. jz Not_Batch_Abort
  462. mov byte ptr Batch_Abort,1 ; set flag for abort
  463. Not_Batch_Abort:
  464. mov dl,PipeFlag
  465. invoke ResPipeOff
  466. or dl,dl
  467. je CheckForA
  468. cmp SingleCom,0
  469. je CheckForA
  470. mov SingleCom,-1 ; make sure singlecom exits
  471. CheckForA:
  472. cmp ErrCd_24,0 ; write protect?
  473. je AbortFor
  474. cmp ErrCd_24,2 ; drive not ready?
  475. jne EExit ; don't abort the FOR
  476. abortfor:
  477. mov ForFlag,0 ; abort a FOR in progress
  478. cmp SingleCom,0
  479. je EExit
  480. mov SingleCom,-1 ; make sure singlecom exits
  481. EExit:
  482. mov al,ah
  483. mov dx,di
  484. RestHd:
  485. invoke RestHand
  486. pop cx
  487. pop si ; restore registers
  488. pop es
  489. ;; pop ds
  490. ;SR;
  491. ; ds has to be got from the variable we saved it in
  492. ;
  493. mov ds,OldDS ;restore old value of ds
  494. ; pop ds
  495. assume ds:nothing
  496. iret
  497. FatErr:
  498. mov dx,offset DATARES:BadFatMsg
  499. mov si,offset DATARES:BadFatSubst
  500. call RPrint
  501. mov al,2 ; abort
  502. jmp RestHd
  503. DskErr endp
  504. ;*** RPrint - print message
  505. ;*** Crlf - display cr/lf
  506. ;
  507. ; ENTRY DS:DX = ptr to count byte, followed by message text
  508. ; DS:SI = ptr to 1st substitution block for this msg, if any
  509. ; variable fields related to substitution blocks are set
  510. ;
  511. ; EXIT nothing
  512. ;
  513. ; USED flags
  514. ;
  515. ; EFFECTS
  516. ; Message is displayed on stdout.
  517. ;
  518. ; NOTE
  519. ; Number of substitutions (%1, %2,...) in message text must not
  520. ; be greater than number of substition blocks present.
  521. Crlf:
  522. mov dx,offset DATARES:Newlin ; cheap newline
  523. RPrint proc
  524. assume ds:DATARES,ss:DATARES
  525. ; Bugbug: do we need to save all reg's?
  526. push si ; preserve registers
  527. push ax
  528. push bx
  529. push cx
  530. push dx
  531. mov bx,si ; DS:BX = ptr to subst block
  532. mov si,dx ; DS:SI = ptr to count byte
  533. lodsb ; AL = message length
  534. ; DS:SI = ptr to message text
  535. xor cx,cx
  536. mov cl,al ; CX = message length
  537. ifdef BILINGUAL
  538. call IsDBCSCodePage
  539. jnz rp_us ; if not DBCS code page
  540. push ax
  541. push si
  542. xor cx,cx
  543. @@:
  544. lodsb
  545. inc cx
  546. or al,al
  547. jnz @b
  548. dec cx
  549. pop si
  550. pop ax
  551. jmp short rp_next
  552. rp_us:
  553. push ax
  554. @@:
  555. lodsb
  556. dec cx
  557. or al,al
  558. jnz @b
  559. pop ax
  560. rp_next:
  561. endif
  562. jcxz rpRet
  563. call RDispMsg
  564. rpRet: pop dx
  565. pop cx
  566. pop bx
  567. pop ax
  568. pop si
  569. ret
  570. RPrint endp
  571. ifdef BILINGUAL
  572. RPrint@ proc
  573. push ax
  574. push bx
  575. push cx
  576. push si
  577. mov bx,si ; DS:BX = ptr to subst block
  578. mov si,dx ; DS:SI = ptr to count byte
  579. lodsb ; AL = message length
  580. ; DS:SI = ptr to message text
  581. xor cx,cx
  582. mov cl,al ; CX = message length
  583. jcxz @f
  584. call RDispMsg
  585. @@:
  586. pop si
  587. pop cx
  588. pop bx
  589. pop ax
  590. ret
  591. RPrint@ endp
  592. endif
  593. ;*** RPrintCrit - print critical error message
  594. ;
  595. ; ENTRY DX = extended error # (19-39)
  596. ;
  597. ; EXIT nothing
  598. ;
  599. ; USED flags
  600. ;
  601. ; EFFECTS
  602. ; Message is displayed on stdout
  603. RPrintCrit proc
  604. assume ds:DATARES,ss:DATARES
  605. push dx ; preserve DX
  606. xchg bx,dx ; BX = extended error #
  607. ; DX = saved BX
  608. sub bx,19 ; BX = critical error index, from 0
  609. ifdef BILINGUAL
  610. call IsDBCSCodePage
  611. jz rpc_next ; if Kanji mode
  612. add bx,21
  613. push ax
  614. @@:
  615. lodsb
  616. or al,al
  617. jnz @b
  618. pop ax
  619. dec si
  620. rpc_next:
  621. endif
  622. shl bx,1 ; BX = offset in word table
  623. mov bx,CritMsgPtrs[bx] ; BX = ptr to error msg
  624. xchg bx,dx ; DX = ptr to error msg
  625. ; BX = restored
  626. ifdef BILINGUAL
  627. call RPrint@ ; print the message
  628. else
  629. call RPrint ; print the message
  630. endif
  631. pop dx ; restore DX
  632. ret
  633. RPrintCrit endp
  634. ;*** RDispMsg - display message
  635. ;
  636. ; Display message, with substitutions, for RPrint.
  637. ;
  638. ; ENTRY DS:SI = ptr to message text
  639. ; CX = message length
  640. ; DS:BX = ptr to substitution block, if any
  641. ;
  642. ; EXIT nothing
  643. ;
  644. ; USED AX,CX,DX,SI
  645. RDispMsg proc
  646. assume ds:DATARES,ss:DATARES
  647. rdNextChar:
  648. lodsb ; AL = next char
  649. cmp al,'%'
  650. jne rdOutChar ; not a substitution
  651. mov dl,ds:[si] ; DL = possible '1' - '9'
  652. sub dl,'1' ; DL = 0 - 8 = '1' - '9'
  653. cmp dl,9
  654. jae rdOutChar ; not a substitution
  655. ;* A substitution code %1 - %9 has been encountered.
  656. ; DL = 0-8, indicating %1-%9
  657. ; DS:BX = ptr to substitution block
  658. call SubstMsg ; display the substitution
  659. inc si ; SI = ptr past %n
  660. dec cx ; count extra character in %n
  661. jmp short rdCharDone
  662. ;* Normal character output.
  663. rdOutChar:
  664. mov dl,al ; DL = char
  665. mov ah,2 ; AH = DOS Character Output code
  666. int 21h ; call DOS
  667. rdCharDone:
  668. loop rdNextChar
  669. ret
  670. RDispMsg endp
  671. ;*** SubstMsg - display message substitution
  672. ;
  673. ; Display a substitution string within a message.
  674. ; Substitution can be a char, an ASCIIZ string, or
  675. ; a word to be displayed as hex digits.
  676. ;
  677. ; ENTRY DL = substitution index 0-8 (for codes %1-%9)
  678. ; DS:BX = ptr to substitution block
  679. ;
  680. ; EXIT nothing
  681. ;
  682. ; USED AX,DX
  683. SubstMsg proc
  684. assume ds:DATARES,ss:DATARES
  685. push bx ; preserve BX
  686. push cx ; preserve CX
  687. mov al,size SUBST ; AL = size of substitution block
  688. mul dl ; AX = offset of desired subst block
  689. add bx,ax ; DS:BX = ptr to desired subst block
  690. mov al,[bx].SubstType ; AX = substitution type flag
  691. mov bx,[bx].SubstPtr ; BX = ptr to char, str, or hex value
  692. ; AL = 1, 2, or 3 for char, string, or hex type
  693. dec al
  694. jz smChar
  695. dec al
  696. jz smStr
  697. ;* Hex number substitution.
  698. mov ax,ds:[bx] ; AX = word value
  699. mov cx,4 ; CX = # digits to display
  700. smDigit:
  701. rol ax,1
  702. rol ax,1
  703. rol ax,1
  704. rol ax,1 ; AL<3:0> = next digit
  705. push ax ; save other digits
  706. and al,0Fh ; AL = binary digit
  707. add al,'0' ; AL = ascii digit if 0-9
  708. cmp al,'9'
  709. jbe @F ; it's 0-9
  710. add al,'A' - '0' - 10 ; AL = ascii digit A-F
  711. @@:
  712. mov dl,al ; DL = ascii digit
  713. mov ah,2
  714. int 21h ; output the ascii digit
  715. pop ax ; restore all digits
  716. loop smDigit
  717. jmp short smRet
  718. ;* Char substitution.
  719. smChar:
  720. mov dl,ds:[bx] ; DL = char to output
  721. mov ah,2
  722. int 21h
  723. jmp short smRet
  724. ;* String substitution.
  725. smStr:
  726. mov dl,ds:[bx] ; DL = next char
  727. or dl,dl
  728. jz smRet ; null char - we're done
  729. mov ah,2
  730. int 21h ; display char
  731. inc bx ; DS:BX = ptr to next char
  732. jmp smStr
  733. smRet: pop cx
  734. pop bx
  735. ret
  736. SubstMsg endp
  737. ;*** CharToUpper - convert character to uppercase
  738. ;
  739. ; ENTRY AL = char
  740. ;
  741. ; EXIT AL = uppercase char
  742. ;
  743. ; USED AX
  744. CharToUpper proc
  745. assume ds:DATARES
  746. push ax ; put char on stack as arg to int 2F
  747. mov ax,1213h ; AX = DOS int 2F 'Convert Char to Uppercase'
  748. int 2Fh
  749. inc sp ; throw away old char on stack
  750. inc sp
  751. ret
  752. CharToUpper endp
  753. ifdef DBCS
  754. ;*** ITestKanj - DBCS lead byte check
  755. ITestKanj:
  756. TestKanjR: ; 3/3/KK
  757. push ds
  758. push si
  759. push ax
  760. lds si,Dbcs_Vector_Addr
  761. ktLop:
  762. cmp word ptr ds:[si],0 ; end of Lead Byte Table
  763. je NotLead
  764. pop ax
  765. push ax
  766. cmp al, byte ptr ds:[si]
  767. jb NotLead
  768. inc si
  769. cmp al, byte ptr ds:[si]
  770. jbe IsLead
  771. inc si
  772. jmp short ktLop ; try another range
  773. NotLead:
  774. xor ax,ax ; set zero
  775. jmp short ktRet
  776. Islead:
  777. xor ax,ax ; reset zero
  778. inc ax
  779. ktRet:
  780. pop ax
  781. pop si
  782. pop ds
  783. ret
  784. endif
  785. ;*** MsgInt2fHandler - int 2f handler for message retrieval
  786. ;
  787. ; ENTRY If we handle it -
  788. ; AX = ((MULTDOS shl 8) or MESSAGE_2F) = 122Eh
  789. ; DL = operation =
  790. ; 0 = get extended error messages
  791. ; 1 = set extended error messages
  792. ; 2 = get parse error messages
  793. ; 3 = set parse error messages
  794. ; 4 = get critical error messages
  795. ; 5 = set critical error messages
  796. ; 6 = get file system error messages
  797. ; 7 = set file system error messages
  798. ; 8 = get disk retriever routine
  799. ; 9 = set disk retriever routine
  800. ; ES:DI = address for 'set' operations
  801. ;
  802. ; EXIT ES:DI = ptr to list of message ptrs, for 'get' operations
  803. ;
  804. ; NOTE
  805. ; This handler replaces the one that used to reside in DOS.
  806. ; 'Set' operations are ignored.
  807. ; 'File system error messages' are not supported.
  808. ;SR;
  809. ; At the int 2fh entry point we push the old ds value and the resident data
  810. ;segment address. Get them off the stack
  811. ;
  812. MsgInt2fHandler proc far
  813. assume cs:CODERES,ds:NOTHING,es:NOTHING,ss:NOTHING
  814. pop ds ;ds = DATARES
  815. assume ds:DATARES
  816. ; pop OldDS ;save old value of ds
  817. cmp ax,(MULTDOS shl 8) or MESSAGE_2F
  818. je miOurs ; it's ours
  819. cmp ax, GET_COMMAND_STATE
  820. je fcOurs
  821. ;SR;
  822. ; We cannot do a far jump any more because cs cannot be used. Push the cs:ip
  823. ;onto the stack and do a far return to jump to the next 2fh handler.
  824. ;Our old ds is on the stack. We need to restore it but we cannot lose the
  825. ;current value of ds as it points at the data segment. So we do some kinky
  826. ;stack manipulations.
  827. ;
  828. push ax
  829. push ax ;create 2 words on stack for retf
  830. push bp
  831. push ax
  832. mov bp,sp ;bp can be used to address stack
  833. ;
  834. ;Swap the old ds value with the second dummy word on the stack. Now, we can
  835. ;do a 'pop ds' at the end to restore our ds
  836. ;
  837. mov ax,[bp+8] ;ax = old ds value
  838. mov [bp+4],ax
  839. mov ax,word ptr ds:Int2fHandler+2
  840. mov [bp+8],ax ;put segment address
  841. mov ax,word ptr ds:Int2fHandler
  842. mov [bp+6],ax ;put offset address
  843. pop ax
  844. pop bp
  845. pop ds
  846. retf ;chain on to next handler
  847. ;; jmp Int2fHandler ; hand off to next 2f handler
  848. fcOurs:
  849. ;
  850. ;We have to clear ax, and return in ds:si a pointer to the stub jump table
  851. ;
  852. pop ax ;discard ds currently on stack
  853. push ds ;store our data segment
  854. mov si,offset DATARES:Int2f_Entry ;start of table
  855. xor ax,ax ;indicate COMMAND present
  856. jmp short miRet ;return to caller
  857. miOurs:
  858. test dl,1
  859. jnz miRet ; ignore 'set' operations
  860. push bx ; preserve BX
  861. mov bx,dx
  862. xor bh,bh ; BX = index in word table
  863. shl bx,1 ; BX = index in dword table
  864. les di,MsgPtrLists[bx] ; ES:DI = ptr to msg ptr list
  865. pop bx ; restore BX
  866. miRet:
  867. ; mov ds,OldDS ;restore ds
  868. pop ds
  869. assume ds:nothing
  870. iret
  871. MsgInt2fHandler endp
  872. ;*** MsgRetriever - message retrieval routine for utilities
  873. ;
  874. ; Address of this routine is passed to utility programs via
  875. ; message services int 2f. We try to find the desired message
  876. ; in memory or in our disk image.
  877. ;
  878. ; ENTRY AX = message #
  879. ; DI = offset in RESGROUP of msg ptr list
  880. ; ComSpec = asciiz pathname to our disk image
  881. ;
  882. ; EXIT CY clear for success
  883. ; ES:DI = ptr to count byte, followed by message text
  884. ;
  885. ; CY set for failure
  886. ;
  887. ; USED flags
  888. ;
  889. ; NOTE
  890. ; The message # in AX is used to compute an offset into
  891. ; the message ptr list pointed to by DI. The lists must
  892. ; start with message # 1 and proceed through consecutive
  893. ; message #'s.
  894. ;
  895. ; It is assumed that the msg ptr list is either ParsMsgPtrs or
  896. ; ExtMsgPtrs. We use NUMPARSEMSGS and NUMEXTMSGS to check for
  897. ; valid message #. ;M033
  898. ;
  899. ; List positions with no corresponding message text are
  900. ; indicated by null pointers, which this routine detects.
  901. ;SR; This routine will be called directly by the utilities. So, we have
  902. ; trap for it in the stub. The stub pushes the old value of ds and the
  903. ; DATARES value on the stack. We get them off the stack to setup ds here
  904. ;
  905. MsgRetriever proc far
  906. assume cs:CODERES,ds:NOTHING,es:NOTHING,ss:NOTHING
  907. pop ds ;ds = DATARES
  908. assume ds:DATARES
  909. ; pop OldDS ;save old ds
  910. push ax ; preserve registers
  911. push bx
  912. push cx
  913. push dx
  914. push si
  915. ;; push ds
  916. ;; push cs
  917. ;; pop ds ; DS = DATARES seg addr
  918. ;; assume ds:RESGROUP
  919. ;; push cs
  920. push ds ; get es from ds
  921. pop es ; ES = DATARES seg addr
  922. ; Begin modification M033.
  923. ; Make sure msg # is valid.
  924. ; Assume msg ptr list is either ParsMsgPtrs or ExtMsgPtrs.
  925. mov bx,NUMPARSMSGS ; BX = # parse error msgs in list
  926. cmp di,offset DATARES:ParsMsgPtrs
  927. je @f ; it's ParsMsgPtrs
  928. mov bx,NUMEXTMSGS ; BX = # extended error msgs in list
  929. @@: cmp bx,ax
  930. jc mrRet ; msg # too high, return carry
  931. ; Msg # is valid.
  932. ; End modification M033.
  933. dec ax
  934. shl ax,1 ; AX = offset into msg ptr list
  935. add di,ax ; DI = ptr to msg ptr
  936. cmp di,ResMsgEnd
  937. jb mrInMem ; ptr (and message) in memory
  938. ;* Retrieve message from disk.
  939. ; Read once to get the ptr to the message, then again for the message.
  940. mov si,offset DATARES:ComSpec ; DS:SI = ptr to pathname
  941. mov dx,EXT_EXISTS_OPEN ; DX = 'open existing file'
  942. mov bx,INT_24_ERROR ; BX = 'fail on crit error'
  943. mov ax,EXTOPEN shl 8 ; AX = 'Extended Open File'
  944. int 21h ; call DOS
  945. jc mrRet ; return failure
  946. mov bx,ax ; BX = file handle
  947. mov dx,di ; DX = ptr to msg ptr
  948. xor si,si ; SI = read count
  949. mrRead:
  950. sub dx,100h ; DX = LSW of file offset
  951. xor cx,cx ; CX = MSW of file offset
  952. mov ax,LSEEK shl 8 ; AX = 'Set File Pointer'
  953. int 21h ; call DOS
  954. jc mrCloseFile ; handle error
  955. mov dx,offset DATARES:MsgBuffer ; DS:DX = input buffer
  956. mov cx,64 ; CX = # bytes to read
  957. mov ah,READ ; AH = 'Read File'
  958. int 21h ; call DOS
  959. jc mrCloseFile ; handle error
  960. or si,si ; (CY cleared)
  961. jnz mrCloseFile ; 2nd time thru - we're done
  962. inc si ; mark one read done
  963. mov dx,word ptr MsgBuffer ; DX = ptr to message
  964. or dx,dx
  965. jnz mrRead ; go read the message
  966. stc ; null ptr found- no msg
  967. mrCloseFile:
  968. pushf ; save success/failure (CY)
  969. mov ah,CLOSE ; AH = 'Close File'
  970. int 21h ; call DOS
  971. ; Bugbug: should we avoid this popf?
  972. popf ; CY = success/failure
  973. mov di,dx ; ES:DI = ptr to msg, if successful
  974. jmp short mrRet ; we're done
  975. ;* Message ptr is in memory.
  976. ; If ptr is in memory, assume message is in memory (/msg).
  977. mrInMem:
  978. mov di,es:[di] ; ES:DI = ptr to msg
  979. or di,di ; (CY cleared)
  980. jnz mrRet ; found message
  981. stc ; null ptr found- no message
  982. mrRet:
  983. pop si ;restore all registers
  984. pop dx
  985. pop cx
  986. pop bx
  987. pop ax
  988. ; mov ds,OldDS ;restore ds
  989. pop ds
  990. assume ds:nothing
  991. ret
  992. MsgRetriever endp
  993. ;
  994. ; M003; Start of changes for UMB support
  995. ;
  996. ;*** Lh_OffUnlink -- Restore allocation strat and link state
  997. ;
  998. ; ENTRY al = Saved alloc strat and link state
  999. ; b0 = 1 if alloc strat to restore is HighFirst
  1000. ; b1 = 1 if link state to restore is Linked
  1001. ;
  1002. ; EXIT None
  1003. ;
  1004. ; USED ax, bx, cx
  1005. ;
  1006. ;
  1007. public Lh_OffUnlink
  1008. Lh_OffUnlink proc far
  1009. mov ch,al
  1010. mov cl,al
  1011. mov ax,(ALLOCOPER shl 8) OR 0
  1012. int 21h
  1013. mov bx,ax
  1014. ror cl,1 ;b7 = HighFirst bit
  1015. and cl,80h ;mask off b6-b0
  1016. and bl,7fh ;mask off HighFirst bit
  1017. or bl,cl ;set HighFirst bit state
  1018. mov ax,(ALLOCOPER shl 8) OR 1
  1019. int 21h ;set alloc strat
  1020. mov bl,ch
  1021. shr bl,1
  1022. xor bh,bh ;bx = linkstate
  1023. mov ax,(ALLOCOPER shl 8) OR 3
  1024. int 21h ;set linkstate
  1025. ret
  1026. Lh_OffUnlink endp
  1027. ;
  1028. ; M003; End of changes for UMB support
  1029. ;
  1030. ifdef BILINGUAL
  1031. IsDBCSCodePage proc near
  1032. push ax
  1033. push bx
  1034. mov ax,4f01h ; get code page
  1035. xor bx,bx
  1036. int 2fh
  1037. ifdef JAPAN
  1038. cmp bx,932
  1039. endif
  1040. ifdef KOREA
  1041. cmp bx,949
  1042. endif
  1043. ifdef TAIWAN
  1044. cmp bx,950
  1045. endif
  1046. ifdef PRC
  1047. cmp bx,936
  1048. endif
  1049. pop bx
  1050. pop ax
  1051. ret
  1052. IsDBCSCodePage endp
  1053. endif
  1054. public EndCode
  1055. EndCode label byte
  1056. CODERES ends
  1057. end