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

page ,132
title Localizable code for resident COMMAND
;/*
; * Microsoft Confidential
; * Copyright (C) Microsoft Corporation 1991
; * All Rights Reserved.
; */
;
; Revision History
; ================
; M003 SR 07/16/90 Added routines Lh_Off, Lh_Unlink &
; Lh_OffUnlink for UMB support
;
; M009 SR 08/01/90 Rewrote Lh_OffUnlink to restore the
; initial UMB state. Removed Lh_off
; and Lh_Unlink.
;
.xlist
.xcref
include dossym.inc
include syscall.inc
include filemode.inc
include pdb.inc
include mult.inc
include doscntry.inc
include devsym.inc
include comsw.asm
include comseg.asm
include comequ.asm
include resmsg.equ
include arena.inc ; M003
.list
.cref
DATARES segment public byte
extrn Abort_Char:byte
extrn BadFatMsg:byte
extrn BadFatSubst:byte
extrn Batch_Abort:byte
extrn BlkDevErr:byte
extrn BlkDevErrRw:byte
extrn BlkDevErrSubst:byte
extrn CDevAt:byte
extrn CharDevErr:byte
extrn CharDevErrRw:byte
extrn CharDevErrSubst:byte
extrn ComSpec:byte
extrn Crit_Err_Info:byte
extrn Crit_Msg_Off:word
extrn Crit_Msg_Seg:word
extrn CritMsgPtrs:word
extrn Dbcs_Vector_Addr:dword
extrn DevName:byte
extrn DrvLet:byte
extrn EndBatMes:byte
extrn ErrCd_24:word
extrn ErrType:byte
extrn Fail_Char:byte
extrn fFail:byte
extrn ForFlag:byte
extrn Ignore_Char:byte
extrn InitFlag:byte
extrn In_Batch:byte
extrn Int2fHandler:dword
extrn Loading:byte
extrn MsgBuffer:byte
extrn MsgPtrLists:dword
extrn MRead:byte
extrn MWrite:byte
extrn NeedVol:dword
extrn NeedVolMsg:byte
extrn NeedVolSubst:byte
extrn Newlin:byte
extrn No_Char:byte
extrn NUMEXTMSGS:abs
extrn NUMPARSMSGS:abs
extrn OldErrNo:word
extrn Parent:word
extrn ParsMsgPtrs:word
extrn Patricide:byte
extrn PermCom:byte
extrn Retry_Char:byte
extrn Req_Abort:byte
extrn Req_End:byte
extrn Req_Fail:byte
extrn Req_Ignore:byte
extrn Req_Retry:byte
extrn ResMsgEnd:word
extrn PipeFlag:byte
extrn SingleCom:word
extrn VolName:byte
extrn Yes_Char:byte
extrn OldDS:word
extrn Int2f_Entry:dword
DATARES ends
; NTVDM use diff al value so we don't confuse dos 5.0
; NTVDM command.com GET_COMMAND_STATE equ 5500h
GET_COMMAND_STATE equ 5501h
CODERES segment public byte
extrn GetComDsk2:near
public AskEnd
public Crlf
public DskErr
public MsgInt2fHandler
public MsgRetriever
public RPrint
ifdef BILINGUAL
public RPrint@
endif
ifdef DBCS
public ITestKanj
endif
; Bugbug: Move rest of PUBLIC declarations up here.
assume cs:CODERES,ds:NOTHING,es:NOTHING,ss:NOTHING
;*** AskEnd - ask user to confirm batch file termination
;
; Confirm with user before freeing batch ...
;
; ENTRY nothing
;
; EXIT CY = set if batch termination is confirmed
;
; CY = clear if batch should continue
;
; USED AX,DX,...
; Bugbug: move this to transient, copy to batch segment.
; Bugbug: or move it to command1 1st.
; Bugbug: No_Char and Yes_Char should be constants.
AskEnd proc
assume ds:DATARES
mov dx,offset DATARES:EndBatMes ; DX = message #
call RPrint
mov ax,(STD_CON_INPUT_FLUSH shl 8) + STD_CON_INPUT
int 21h
call CharToUpper ; change to upper case
cmp al,No_Char
je aeRet ; answer is no (CY is clear)
cmp al,Yes_Char
jne AskEnd ; invalid response, try again
stc ; answer is yes
aeRet: ret
AskEnd endp
;*** DskErr - critical error handler
;
; Default critical error handler unless user intercepts int 24h.
;
; ENTRY int 24h
;
; EXIT
;
; USED
;
; EFFECTS
;
;SR;
; The stub is going to push the old ds value and the resident data segment
;onto the stack in that order. Get it off the stack
;
DskErr proc far
assume ds:NOTHING,es:NOTHING,ss:NOTHING
pop ds ;ds = DATARES
assume ds:DATARES
pop OldDS ;save old ds value
sti
push es
push si
push cx
push di
push cx
push ax
push ds ;save our data segment
pop es ;es = DATARES
mov ds,bp
assume ds:nothing
mov ax,[si].SDEVATT
mov es:CDevAt,ah
;; push cs
;; pop es
mov di,offset DATARES:DevName
mov cx,8
add si,SDEVNAME ; save device name (even for block device)
cld
rep movsb
pop ax
pop cx
pop di
; Stack still contains DS and ES.
;SR;
; We need ds = DATARES for SavHand
;
push es
pop ds
assume ds:DATARES
invoke SavHand ; save user's stdin/out, set to our stderr
;; push cs
;; pop ds ; set up local data segment
;; assume ds:resgroup
push dx
call Crlf
pop dx
; Bugbug: rename Crit_Err_Info to CritErrAH?
mov Crit_Err_Info,ah ; save critical error flags
; Compute and save ASCII drive letter (nonsense for char devices)
add al,'A'
mov DrvLet,al
; Bugbug: These labels are awful. Change, especially 'NoHardE'.
test ah,80h
jz NoHardE ; it's a disk-device error
test CDevAt,DEVTYP shr 8
jnz NoHardE ; it's a character device
jmp FatErr ; it's a FAT error
NoHardE:
mov si,offset DATARES:MRead ; SI = "read" msg #
test ah,1
jz SavMes ; it's a read error
mov si,offset DATARES:MWrite ; SI = "write" msg #
SavMes:
mov OldErrNo,di ; save critical error code
; Bugbug: don't need to save/restore all here?
push es
push ds ; GetExtendedError likes to STOMP
push bp
push si
push dx
push cx
push bx
mov ah,GetExtendedError ; get extended error info
int 21h
pop bx
pop cx
pop dx
pop si
pop bp
pop ds
mov word ptr NeedVol,di ; save possible ptr to volume label
mov word ptr NeedVol+2,es
pop es
; Bugbug: AX has extended error code, so no need to zero AH?
xor ah,ah
mov di,ax ; DI = error code
; Bugbug: somewhat obsolete documentation?
;
; DI is now the correct error code. Classify things to see what we are
; allowed to report. We convert DI into a 0-based index into a message table.
; This presumes that the int 24 errors (oldstyle) and new errors (sharing and
; the like) are contiguous.
;
; Bugbug: simplify following code by cmp'ing instead of sub'ing.
; Check use of ErrCd_24, though.
sub di,ERROR_WRITE_PROTECT
jae HavCod
; Bugbug wouldn't it be better to display the original error msg,
; even though it's not a critical error?
mov di,ERROR_GEN_FAILURE - ERROR_WRITE_PROTECT
;
; DI now has the mapped error code. Old style errors are:
; FOOBAR <read|writ>ing drive ZZ.
; New style errors are:
; FOOBAR
; We need to figure out which the particular error belongs to.
;
HavCod:
mov ErrType,0 ; assume old style
cmp di,ERROR_FCB_UNAVAILABLE - ERROR_WRITE_PROTECT
je SetStyle
cmp di,ERROR_SHARING_BUFFER_EXCEEDED - ERROR_WRITE_PROTECT
jne GotStyle
SetStyle:
; Bugbug: use INC
mov ErrType,1 ; must be new type
GotStyle:
mov [ErrCd_24],di
cmp di,ERROR_HANDLE_DISK_FULL - ERROR_WRITE_PROTECT
; If the error message is unknown
jbe NormalError ; redirector, continue. Otherwise,
;
; We do not know how to handle this error. Ask IFSFUNC if she knows
; how to handle things
;
;input to IFSFUNC: AL=1
; BX=extended error number
;
;output from IFSFUNC: AL=error type (0 or 1)
; 0=<message> error (read/writ)ing (drive/device) xxx
; Abort, Retry, Ignore
; 1=<message>
; Abort, Retry, Ignore
; ES:DI=pointer to message text
; carry set=>no message
mov di,ax ; retrieve correct extended error...
mov ax,0500h ; is the redir there?
int 2fh
cmp al,0ffh
jne NoHandler ; no, go to NoHandler
push bx
mov bx,di ; get ErrType and ptr to error msg
mov ax,0501h
int 2fh
pop bx
jc NoHandler
; Bugbug: need to record error type?
mov ErrType,al
push ds
push es
pop ds
mov dx,di
mov cx,-1 ; find end of msg
xor al,al
cld
repnz scasb
; Bugbug: we can do better than this.
mov byte ptr [di-1],'$'
mov ah,STD_CON_STRING_OUTPUT ; print the message
int 21h
mov byte ptr [di-1],0 ; restore terminal byte
pop ds ; clean up and continue
jmp short CheckErrType
;* Redir isn't available or doesn't recognize the error.
; Restore regs to unextended error.
NoHandler:
mov ErrType,0
; Bugbug: won't this break, since we add error_write_protect back in?
mov di,OldErrNo
mov ErrCd_24,di
NormalError:
add di,ERROR_WRITE_PROTECT
xchg di,dx ; may need dx later
call RPrintCrit ; print error type
CheckErrType:
cmp ErrType,0 ; Check error style...
je ContOld
call CrLf ; if new style then done printing
jmp short Ask
ContOld:
inc si ; DS:SI = ptr to asciiz string
; Bugbug: combine some of the following two sections?
test [CDevAt],DEVTYP shr 8
jz BlkErr
mov dx,offset DATARES:CharDevErr ; DX = ptr to device message
mov CharDevErrRw.SubstPtr,si ; point to read/write string
mov si,offset DATARES:CharDevErrSubst; SI = ptr to subst block
call RPrint ; print the message
jmp short Ask ; don't ralph on command
BlkErr:
mov dx,offset DATARES:BlkDevErr ; DX = error msg #
mov BlkDevErrRw.SubstPtr,si ; "reading","writing" ptr
mov si,offset DATARES:BlkDevErrSubst ; SI = ptr to subst block
call RPrint
cmp Loading,0
jz Ask
invoke RestHand
jmp GetComDsk2 ; if error loading COMMAND, re-prompt
Ask:
cmp [ErrCd_24],15 ; error 15 has an extra message
jne Not15 ; not error 15
;* For error 15, tell the user which volume/serial # are needed.
push cx
; Bugbug: does this push/pop need to be done?
push ds
pop es
lds si,NeedVol
assume ds:NOTHING
push di
mov di,offset DATARES:VolName
mov cx,16 ; copy volume name & serial #
cld
rep movsb
pop di
push es
pop ds
pop cx
assume ds:DATARES
mov dx,offset DATARES:NeedVolMsg ; DX = ptr to msg
mov si,offset DATARES:NeedVolSubst ; DS:SI = ptr to subst block
call RPrint
Not15:
;* Print abort, retry, ignore, fail message.
; Print only options that are valid.
; Bugbug: sizzle this.
mov dx,offset DATARES:Req_Abort
call RPrint
test Crit_Err_Info,RETRY_ALLOWED
jz Try_Ignore
mov dx,offset DATARES:Req_Retry
call RPrint
Try_Ignore:
test Crit_Err_Info,IGNORE_ALLOWED
jz Try_Fail
mov dx,offset DATARES:Req_Ignore
call RPrint
Try_Fail:
test Crit_Err_Info,FAIL_ALLOWED
jz Term_Question
mov dx,offset DATARES:Req_Fail
call RPrint
Term_Question:
mov dx,offset DATARES:Req_End
call RPrint
; If the /f switch was given, we fail all requests.
test fFail,-1
jz DoPrompt
mov ah,3 ; signal fail
jmp EExit
DoPrompt:
mov ax,(STD_CON_INPUT_FLUSH shl 8) + STD_CON_INPUT
int 21h ; get response
; Bugbug: can Kanji code be conditional?
ifdef DBCS
invoke TestKanjR ; 3/3/KK
jz NotKanj ; 3/3/KK
mov ax,(STD_CON_INPUT shl 8) ; eat the 2nd byte of ECS code 3/3/KK
int 21h ; 3/3/KK
call Crlf ; 3/3/KK
jmp Ask ; 3/3/KK
NotKanj: ; 3/3/KK
endif
call Crlf
call CharToUpper ; convert to upper case
mov ah,0 ; return code for ignore
test Crit_Err_Info,IGNORE_ALLOWED ; is ignore allowed?
jz user_retry
cmp al,Ignore_Char ; ignore?
jz EExitJ
; Bugbug: optimize following code.
User_Retry:
inc ah ; return code for retry
test Crit_Err_Info,RETRY_ALLOWED ; is retry allowed?
jz User_Abort
cmp al,Retry_Char ; retry?
jz EExitJ
User_Abort:
inc ah ; return code for abort
; (abort always allowed)
cmp al,Abort_Char ; abort?
jz Abort_Process ; exit user program
inc ah ; return code for fail
test Crit_Err_Info,FAIL_ALLOWED ; is fail allowed?
jz AskJ
cmp al,Fail_Char ; fail?
jz EExitJ
AskJ:
jmp Ask
EExitJ:
jmp short EExit
Abort_Process:
test InitFlag,INITINIT ; COMMAND init interrupted?
jz AbortCont ; no, handle it normally
cmp PermCom,0 ; are we top level process?
jz JustExit ; yes, just exit
mov dx,offset DATARES:Patricide ; no, load ptr to error msg
call RPrint ; print it
DeadInTheWater:
jmp DeadInTheWater ; loop until the user reboots
JustExit:
assume ds:DATARES
mov ax,Parent ; load real parent pid
mov word ptr ds:Pdb_Parent_Pid,ax ; put it back where it belongs
mov ax,(EXIT shl 8) or 255
int 21h
AbortCont:
test byte ptr In_Batch,-1 ; Are we accessing a batch file?
jz Not_Batch_Abort
mov byte ptr Batch_Abort,1 ; set flag for abort
Not_Batch_Abort:
mov dl,PipeFlag
invoke ResPipeOff
or dl,dl
je CheckForA
cmp SingleCom,0
je CheckForA
mov SingleCom,-1 ; make sure singlecom exits
CheckForA:
cmp ErrCd_24,0 ; write protect?
je AbortFor
cmp ErrCd_24,2 ; drive not ready?
jne EExit ; don't abort the FOR
abortfor:
mov ForFlag,0 ; abort a FOR in progress
cmp SingleCom,0
je EExit
mov SingleCom,-1 ; make sure singlecom exits
EExit:
mov al,ah
mov dx,di
RestHd:
invoke RestHand
pop cx
pop si ; restore registers
pop es
;; pop ds
;SR;
; ds has to be got from the variable we saved it in
;
mov ds,OldDS ;restore old value of ds
; pop ds
assume ds:nothing
iret
FatErr:
mov dx,offset DATARES:BadFatMsg
mov si,offset DATARES:BadFatSubst
call RPrint
mov al,2 ; abort
jmp RestHd
DskErr endp
;*** RPrint - print message
;*** Crlf - display cr/lf
;
; ENTRY DS:DX = ptr to count byte, followed by message text
; DS:SI = ptr to 1st substitution block for this msg, if any
; variable fields related to substitution blocks are set
;
; EXIT nothing
;
; USED flags
;
; EFFECTS
; Message is displayed on stdout.
;
; NOTE
; Number of substitutions (%1, %2,...) in message text must not
; be greater than number of substition blocks present.
Crlf:
mov dx,offset DATARES:Newlin ; cheap newline
RPrint proc
assume ds:DATARES,ss:DATARES
; Bugbug: do we need to save all reg's?
push si ; preserve registers
push ax
push bx
push cx
push dx
mov bx,si ; DS:BX = ptr to subst block
mov si,dx ; DS:SI = ptr to count byte
lodsb ; AL = message length
; DS:SI = ptr to message text
xor cx,cx
mov cl,al ; CX = message length
ifdef BILINGUAL
call IsDBCSCodePage
jnz rp_us ; if not DBCS code page
push ax
push si
xor cx,cx
@@:
lodsb
inc cx
or al,al
jnz @b
dec cx
pop si
pop ax
jmp short rp_next
rp_us:
push ax
@@:
lodsb
dec cx
or al,al
jnz @b
pop ax
rp_next:
endif
jcxz rpRet
call RDispMsg
rpRet: pop dx
pop cx
pop bx
pop ax
pop si
ret
RPrint endp
ifdef BILINGUAL
RPrint@ proc
push ax
push bx
push cx
push si
mov bx,si ; DS:BX = ptr to subst block
mov si,dx ; DS:SI = ptr to count byte
lodsb ; AL = message length
; DS:SI = ptr to message text
xor cx,cx
mov cl,al ; CX = message length
jcxz @f
call RDispMsg
@@:
pop si
pop cx
pop bx
pop ax
ret
RPrint@ endp
endif
;*** RPrintCrit - print critical error message
;
; ENTRY DX = extended error # (19-39)
;
; EXIT nothing
;
; USED flags
;
; EFFECTS
; Message is displayed on stdout
RPrintCrit proc
assume ds:DATARES,ss:DATARES
push dx ; preserve DX
xchg bx,dx ; BX = extended error #
; DX = saved BX
sub bx,19 ; BX = critical error index, from 0
ifdef BILINGUAL
call IsDBCSCodePage
jz rpc_next ; if Kanji mode
add bx,21
push ax
@@:
lodsb
or al,al
jnz @b
pop ax
dec si
rpc_next:
endif
shl bx,1 ; BX = offset in word table
mov bx,CritMsgPtrs[bx] ; BX = ptr to error msg
xchg bx,dx ; DX = ptr to error msg
; BX = restored
ifdef BILINGUAL
call RPrint@ ; print the message
else
call RPrint ; print the message
endif
pop dx ; restore DX
ret
RPrintCrit endp
;*** RDispMsg - display message
;
; Display message, with substitutions, for RPrint.
;
; ENTRY DS:SI = ptr to message text
; CX = message length
; DS:BX = ptr to substitution block, if any
;
; EXIT nothing
;
; USED AX,CX,DX,SI
RDispMsg proc
assume ds:DATARES,ss:DATARES
rdNextChar:
lodsb ; AL = next char
cmp al,'%'
jne rdOutChar ; not a substitution
mov dl,ds:[si] ; DL = possible '1' - '9'
sub dl,'1' ; DL = 0 - 8 = '1' - '9'
cmp dl,9
jae rdOutChar ; not a substitution
;* A substitution code %1 - %9 has been encountered.
; DL = 0-8, indicating %1-%9
; DS:BX = ptr to substitution block
call SubstMsg ; display the substitution
inc si ; SI = ptr past %n
dec cx ; count extra character in %n
jmp short rdCharDone
;* Normal character output.
rdOutChar:
mov dl,al ; DL = char
mov ah,2 ; AH = DOS Character Output code
int 21h ; call DOS
rdCharDone:
loop rdNextChar
ret
RDispMsg endp
;*** SubstMsg - display message substitution
;
; Display a substitution string within a message.
; Substitution can be a char, an ASCIIZ string, or
; a word to be displayed as hex digits.
;
; ENTRY DL = substitution index 0-8 (for codes %1-%9)
; DS:BX = ptr to substitution block
;
; EXIT nothing
;
; USED AX,DX
SubstMsg proc
assume ds:DATARES,ss:DATARES
push bx ; preserve BX
push cx ; preserve CX
mov al,size SUBST ; AL = size of substitution block
mul dl ; AX = offset of desired subst block
add bx,ax ; DS:BX = ptr to desired subst block
mov al,[bx].SubstType ; AX = substitution type flag
mov bx,[bx].SubstPtr ; BX = ptr to char, str, or hex value
; AL = 1, 2, or 3 for char, string, or hex type
dec al
jz smChar
dec al
jz smStr
;* Hex number substitution.
mov ax,ds:[bx] ; AX = word value
mov cx,4 ; CX = # digits to display
smDigit:
rol ax,1
rol ax,1
rol ax,1
rol ax,1 ; AL<3:0> = next digit
push ax ; save other digits
and al,0Fh ; AL = binary digit
add al,'0' ; AL = ascii digit if 0-9
cmp al,'9'
jbe @F ; it's 0-9
add al,'A' - '0' - 10 ; AL = ascii digit A-F
@@:
mov dl,al ; DL = ascii digit
mov ah,2
int 21h ; output the ascii digit
pop ax ; restore all digits
loop smDigit
jmp short smRet
;* Char substitution.
smChar:
mov dl,ds:[bx] ; DL = char to output
mov ah,2
int 21h
jmp short smRet
;* String substitution.
smStr:
mov dl,ds:[bx] ; DL = next char
or dl,dl
jz smRet ; null char - we're done
mov ah,2
int 21h ; display char
inc bx ; DS:BX = ptr to next char
jmp smStr
smRet: pop cx
pop bx
ret
SubstMsg endp
;*** CharToUpper - convert character to uppercase
;
; ENTRY AL = char
;
; EXIT AL = uppercase char
;
; USED AX
CharToUpper proc
assume ds:DATARES
push ax ; put char on stack as arg to int 2F
mov ax,1213h ; AX = DOS int 2F 'Convert Char to Uppercase'
int 2Fh
inc sp ; throw away old char on stack
inc sp
ret
CharToUpper endp
ifdef DBCS
;*** ITestKanj - DBCS lead byte check
ITestKanj:
TestKanjR: ; 3/3/KK
push ds
push si
push ax
lds si,Dbcs_Vector_Addr
ktLop:
cmp word ptr ds:[si],0 ; end of Lead Byte Table
je NotLead
pop ax
push ax
cmp al, byte ptr ds:[si]
jb NotLead
inc si
cmp al, byte ptr ds:[si]
jbe IsLead
inc si
jmp short ktLop ; try another range
NotLead:
xor ax,ax ; set zero
jmp short ktRet
Islead:
xor ax,ax ; reset zero
inc ax
ktRet:
pop ax
pop si
pop ds
ret
endif
;*** MsgInt2fHandler - int 2f handler for message retrieval
;
; ENTRY If we handle it -
; AX = ((MULTDOS shl 8) or MESSAGE_2F) = 122Eh
; DL = operation =
; 0 = get extended error messages
; 1 = set extended error messages
; 2 = get parse error messages
; 3 = set parse error messages
; 4 = get critical error messages
; 5 = set critical error messages
; 6 = get file system error messages
; 7 = set file system error messages
; 8 = get disk retriever routine
; 9 = set disk retriever routine
; ES:DI = address for 'set' operations
;
; EXIT ES:DI = ptr to list of message ptrs, for 'get' operations
;
; NOTE
; This handler replaces the one that used to reside in DOS.
; 'Set' operations are ignored.
; 'File system error messages' are not supported.
;SR;
; At the int 2fh entry point we push the old ds value and the resident data
;segment address. Get them off the stack
;
MsgInt2fHandler proc far
assume cs:CODERES,ds:NOTHING,es:NOTHING,ss:NOTHING
pop ds ;ds = DATARES
assume ds:DATARES
; pop OldDS ;save old value of ds
cmp ax,(MULTDOS shl 8) or MESSAGE_2F
je miOurs ; it's ours
cmp ax, GET_COMMAND_STATE
je fcOurs
;SR;
; We cannot do a far jump any more because cs cannot be used. Push the cs:ip
;onto the stack and do a far return to jump to the next 2fh handler.
;Our old ds is on the stack. We need to restore it but we cannot lose the
;current value of ds as it points at the data segment. So we do some kinky
;stack manipulations.
;
push ax
push ax ;create 2 words on stack for retf
push bp
push ax
mov bp,sp ;bp can be used to address stack
;
;Swap the old ds value with the second dummy word on the stack. Now, we can
;do a 'pop ds' at the end to restore our ds
;
mov ax,[bp+8] ;ax = old ds value
mov [bp+4],ax
mov ax,word ptr ds:Int2fHandler+2
mov [bp+8],ax ;put segment address
mov ax,word ptr ds:Int2fHandler
mov [bp+6],ax ;put offset address
pop ax
pop bp
pop ds
retf ;chain on to next handler
;; jmp Int2fHandler ; hand off to next 2f handler
fcOurs:
;
;We have to clear ax, and return in ds:si a pointer to the stub jump table
;
pop ax ;discard ds currently on stack
push ds ;store our data segment
mov si,offset DATARES:Int2f_Entry ;start of table
xor ax,ax ;indicate COMMAND present
jmp short miRet ;return to caller
miOurs:
test dl,1
jnz miRet ; ignore 'set' operations
push bx ; preserve BX
mov bx,dx
xor bh,bh ; BX = index in word table
shl bx,1 ; BX = index in dword table
les di,MsgPtrLists[bx] ; ES:DI = ptr to msg ptr list
pop bx ; restore BX
miRet:
; mov ds,OldDS ;restore ds
pop ds
assume ds:nothing
iret
MsgInt2fHandler endp
;*** MsgRetriever - message retrieval routine for utilities
;
; Address of this routine is passed to utility programs via
; message services int 2f. We try to find the desired message
; in memory or in our disk image.
;
; ENTRY AX = message #
; DI = offset in RESGROUP of msg ptr list
; ComSpec = asciiz pathname to our disk image
;
; EXIT CY clear for success
; ES:DI = ptr to count byte, followed by message text
;
; CY set for failure
;
; USED flags
;
; NOTE
; The message # in AX is used to compute an offset into
; the message ptr list pointed to by DI. The lists must
; start with message # 1 and proceed through consecutive
; message #'s.
;
; It is assumed that the msg ptr list is either ParsMsgPtrs or
; ExtMsgPtrs. We use NUMPARSEMSGS and NUMEXTMSGS to check for
; valid message #. ;M033
;
; List positions with no corresponding message text are
; indicated by null pointers, which this routine detects.
;SR; This routine will be called directly by the utilities. So, we have
; trap for it in the stub. The stub pushes the old value of ds and the
; DATARES value on the stack. We get them off the stack to setup ds here
;
MsgRetriever proc far
assume cs:CODERES,ds:NOTHING,es:NOTHING,ss:NOTHING
pop ds ;ds = DATARES
assume ds:DATARES
; pop OldDS ;save old ds
push ax ; preserve registers
push bx
push cx
push dx
push si
;; push ds
;; push cs
;; pop ds ; DS = DATARES seg addr
;; assume ds:RESGROUP
;; push cs
push ds ; get es from ds
pop es ; ES = DATARES seg addr
; Begin modification M033.
; Make sure msg # is valid.
; Assume msg ptr list is either ParsMsgPtrs or ExtMsgPtrs.
mov bx,NUMPARSMSGS ; BX = # parse error msgs in list
cmp di,offset DATARES:ParsMsgPtrs
je @f ; it's ParsMsgPtrs
mov bx,NUMEXTMSGS ; BX = # extended error msgs in list
@@: cmp bx,ax
jc mrRet ; msg # too high, return carry
; Msg # is valid.
; End modification M033.
dec ax
shl ax,1 ; AX = offset into msg ptr list
add di,ax ; DI = ptr to msg ptr
cmp di,ResMsgEnd
jb mrInMem ; ptr (and message) in memory
;* Retrieve message from disk.
; Read once to get the ptr to the message, then again for the message.
mov si,offset DATARES:ComSpec ; DS:SI = ptr to pathname
mov dx,EXT_EXISTS_OPEN ; DX = 'open existing file'
mov bx,INT_24_ERROR ; BX = 'fail on crit error'
mov ax,EXTOPEN shl 8 ; AX = 'Extended Open File'
int 21h ; call DOS
jc mrRet ; return failure
mov bx,ax ; BX = file handle
mov dx,di ; DX = ptr to msg ptr
xor si,si ; SI = read count
mrRead:
sub dx,100h ; DX = LSW of file offset
xor cx,cx ; CX = MSW of file offset
mov ax,LSEEK shl 8 ; AX = 'Set File Pointer'
int 21h ; call DOS
jc mrCloseFile ; handle error
mov dx,offset DATARES:MsgBuffer ; DS:DX = input buffer
mov cx,64 ; CX = # bytes to read
mov ah,READ ; AH = 'Read File'
int 21h ; call DOS
jc mrCloseFile ; handle error
or si,si ; (CY cleared)
jnz mrCloseFile ; 2nd time thru - we're done
inc si ; mark one read done
mov dx,word ptr MsgBuffer ; DX = ptr to message
or dx,dx
jnz mrRead ; go read the message
stc ; null ptr found- no msg
mrCloseFile:
pushf ; save success/failure (CY)
mov ah,CLOSE ; AH = 'Close File'
int 21h ; call DOS
; Bugbug: should we avoid this popf?
popf ; CY = success/failure
mov di,dx ; ES:DI = ptr to msg, if successful
jmp short mrRet ; we're done
;* Message ptr is in memory.
; If ptr is in memory, assume message is in memory (/msg).
mrInMem:
mov di,es:[di] ; ES:DI = ptr to msg
or di,di ; (CY cleared)
jnz mrRet ; found message
stc ; null ptr found- no message
mrRet:
pop si ;restore all registers
pop dx
pop cx
pop bx
pop ax
; mov ds,OldDS ;restore ds
pop ds
assume ds:nothing
ret
MsgRetriever endp
;
; M003; Start of changes for UMB support
;
;*** Lh_OffUnlink -- Restore allocation strat and link state
;
; ENTRY al = Saved alloc strat and link state
; b0 = 1 if alloc strat to restore is HighFirst
; b1 = 1 if link state to restore is Linked
;
; EXIT None
;
; USED ax, bx, cx
;
;
public Lh_OffUnlink
Lh_OffUnlink proc far
mov ch,al
mov cl,al
mov ax,(ALLOCOPER shl 8) OR 0
int 21h
mov bx,ax
ror cl,1 ;b7 = HighFirst bit
and cl,80h ;mask off b6-b0
and bl,7fh ;mask off HighFirst bit
or bl,cl ;set HighFirst bit state
mov ax,(ALLOCOPER shl 8) OR 1
int 21h ;set alloc strat
mov bl,ch
shr bl,1
xor bh,bh ;bx = linkstate
mov ax,(ALLOCOPER shl 8) OR 3
int 21h ;set linkstate
ret
Lh_OffUnlink endp
;
; M003; End of changes for UMB support
;
ifdef BILINGUAL
IsDBCSCodePage proc near
push ax
push bx
mov ax,4f01h ; get code page
xor bx,bx
int 2fh
ifdef JAPAN
cmp bx,932
endif
ifdef KOREA
cmp bx,949
endif
ifdef TAIWAN
cmp bx,950
endif
ifdef PRC
cmp bx,936
endif
pop bx
pop ax
ret
IsDBCSCodePage endp
endif
public EndCode
EndCode label byte
CODERES ends
end