page ,132 ; SCCSID = @(#)tcmd2a.asm 4.1 85/06/25 ; SCCSID = @(#)tcmd2a.asm 4.1 85/06/25 TITLE PART5 COMMAND Transient routines. ;/* ; * Microsoft Confidential ; * Copyright (C) Microsoft Corporation 1991 ; * All Rights Reserved. ; */ ; Revision History ; ================ ; M01 md 7/13/90 Changed CLS to access ROM BIOS data directly ; ; M013 SR 08/06/90 Changed Version to use new call to ; get info about DOS in HMA or ROM. ; M018 md 08/12/90 Increment screen height by 1 when ; obtained from ROM BIOS. ; M022 md 08/29/80 Set correct video page in REG_CLS INCLUDE comsw.asm .xlist .xcref include dossym.inc include bpb.inc include syscall.inc include filemode.inc include sf.inc include comequ.asm include comseg.asm include ioctl.inc include rombios.inc ;M01 .list .cref CODERES SEGMENT PUBLIC BYTE ;AC000; CODERES ENDS DATARES SEGMENT PUBLIC BYTE ;AC000; DATARES ENDS TRANDATA SEGMENT PUBLIC BYTE ;AC000; EXTRN arg_buf_ptr:word EXTRN BadCurDrv:byte ;AC000; EXTRN clsstring:byte EXTRN dback_ptr:word EXTRN display_ioctl:word ;AN000; EXTRN display_width:word ;AN000; EXTRN DosHma_Ptr:word EXTRN DosLow_Ptr:word EXTRN DosRev_Ptr:word EXTRN DosRom_Ptr:word EXTRN Extend_buf_ptr:word ;AN049; EXTRN linperpag:word ;AN000; EXTRN msg_disp_class:byte ;AN049; EXTRN nulpath_ptr:word EXTRN Parse_Ver:byte EXTRN prompt_table:word EXTRN string_buf_ptr:word ;AC000; EXTRN vermes_ptr:word TRANDATA ENDS TRANSPACE SEGMENT PUBLIC BYTE ;AC000; EXTRN Arg_Buf:byte EXTRN bwdbuf:byte EXTRN curdrv:byte EXTRN dirchar:byte EXTRN major_ver_num:word EXTRN minor_ver_num:word EXTRN One_Char_Val:byte EXTRN srcxname:byte ;AN049; EXTRN string_ptr_2:word TRANSPACE ENDS TRANCODE SEGMENT PUBLIC BYTE ASSUME CS:TRANGROUP,DS:NOTHING,ES:NOTHING,SS:NOTHING ;--------------- TRANSPACE SEGMENT PUBLIC BYTE ;AC000; EXTRN arg:byte ; the arg structure! transpace ends ;--------------- EXTRN cerror:near ;AN049; EXTRN crlf2:near EXTRN drvbad:near EXTRN std_printf:near PUBLIC build_dir_for_chdir PUBLIC build_dir_for_prompt PUBLIC build_dir_string PUBLIC cls PUBLIC path PUBLIC print_char PUBLIC print_drive PUBLIC print_version PUBLIC print_b PUBLIC print_back PUBLIC print_eq PUBLIC print_esc PUBLIC print_g PUBLIC print_l PUBLIC print_prompt PUBLIC version break Version ;*** Version - display DOS version ; ; SYNTAX ver [/debug] ; ; /debug - display additional DOS configuration info ; ; ENTRY command-line tail is in PSP ; ; EXIT if successful, nothing ; if parse fails, ; parse error message is set up (for Std_EPrintf) ; AX = system parser error code ; DX = ptr to message block ; we jump to CError ; ; EFFECTS ; If parse fails, a parse error message is displayed. ; Otherwise, version message is displayed. ; If /debug is specified, additional DOS info is displayed. Version: assume ds:TRANGROUP,es:TRANGROUP ; Parse command line for /debug switch. mov si,81h ; DS:SI = ptr to command tail mov di,offset TRANGROUP:Parse_Ver ; ES:DI = ptr to parse block xor cx,cx ; CX = # positional param's found invoke Parse_With_Msg mov bl,1 ; BL = flag = /debug present cmp ax,RESULT_NO_ERROR je verPrintVer ; something parsed - must be /debug dec bl ; BL = flag = no /debug present cmp ax,END_OF_LINE je verPrintVer ; reached end of line - ok ; The parse failed. Error message has been set up. jmp CError verPrintVer: push bx ; save /debug flag call Crlf2 call Print_Version call Crlf2 pop bx ; BL = /debug flag or bl,bl jz verDone ; /debug is false - we're done ;* For /debug, display DOS internal revision and DOS location ; (low memory, HMA, or ROM). ; Bugbug: use symbols for bitmasks below. mov ax,(SET_CTRL_C_TRAPPING shl 8) + 6 ; M013 int 21h mov al,dl ;revision number in dl; M013 mov bh,dh ;flags in dh now; M013 ;M032 and al,7 ; AL = DOS internal revision cmp al,'Z'-'A' ;M032 ; revision in A-to-Z range? jbe @f ;M032 ; A-to-Z revision ok mov al,'*'-'A' ;M032 ; beyond Z, just say revision * @@: add al,'A' ; AL = DOS internal rev letter mov One_Char_Val,al mov dx,offset TRANGROUP:DosRev_Ptr invoke Std_Printf ; print DOS internal revision mov cl,4 shr bh,cl ; CY = DOS in ROM jc verRom shr bh,1 ; CY = DOS in HMA jc verHma ; DOS isn't in ROM or HMA, so it must be in lower memory. mov dx,offset TRANGROUP:DosLow_Ptr jmp short verPrintLoc verRom: mov dx,offset TRANGROUP:DosRom_Ptr jmp short verPrintLoc verHma: mov dx,offset TRANGROUP:DosHma_Ptr verPrintLoc: invoke Std_Printf verDone: jmp Crlf2 Print_Version: mov ah,GET_VERSION int 21h push ax xor ah,ah mov Major_Ver_Num,ax pop ax xchg ah,al xor ah,ah mov Minor_Ver_Num,ax mov dx,offset TRANGROUP:VerMes_Ptr jmp Std_Printf assume ds:TRANGROUP,es:TRANGROUP print_prompt: push ds push cs pop ds ; MAKE SURE DS IS IN TRANGROUP push es invoke find_prompt ; LOOK FOR PROMPT STRING jc PP0 ; CAN'T FIND ONE cmp byte ptr es:[di],0 jnz PP1 PP0: call print_drive ; USE DEFAULT PROMPT mov al,sym call print_char jmp short PP5 PP1: mov al,es:[di] ; GET A CHAR inc di or al,al jz PP5 ; NUL TERMINATED cmp al,dollar ; META CHARACTER? jz PP2 ; NOPE PPP1: call print_char jmp PP1 PP2: mov al,es:[di] inc di mov bx,offset trangroup:prompt_table-3 or al,al jz PP5 PP3: add bx,3 invoke upconv cmp al,[bx] jz PP4 cmp byte ptr [bx],0 jnz PP3 jmp PP1 PP4: push es push di push cs pop es call [bx+1] pop di pop es jmp PP1 PP5: pop es ; RESTORE SEGMENTS pop ds return print_back: mov dx,offset trangroup:dback_ptr jmp std_printf print_EQ: mov al,'=' jmp short print_char print_esc: mov al,1BH jmp short print_char print_G: mov al,rabracket jmp short print_char print_L: mov al,labracket jmp short print_char print_B: mov al,vbar print_char: ; Bugbug: Why bother with ds,es here? push es push ds pop es push di push dx mov dl,al ;AC000; Get char into al mov ah,Std_CON_output ;AC000; print the char to stdout int 21h ;AC000; pop dx pop di pop es ret print_drive: mov ah,Get_Default_drive int 21h add al,capital_A call print_char ret ASSUME DS:TRANGROUP,ES:TRANGROUP build_dir_for_prompt: xor dl,dl mov si,offset trangroup:bwdbuf mov di,SI mov al,CurDrv add al,'A' mov ah,':' stosw mov al,[dirchar] stosb xchg si,di mov string_ptr_2,di mov ah,Current_dir int 21h mov dx,offset trangroup:string_buf_ptr jnc DoPrint mov dx,offset trangroup:BadCurDrv DoPrint: call std_printf ret build_dir_for_chdir: call build_dir_string mov dx,offset trangroup:bwdbuf mov string_ptr_2,dx mov dx,offset trangroup:string_buf_ptr call std_printf ret build_dir_string: mov dl,ds:[FCB] mov al,DL add al,'@' cmp al,'@' jnz gotdrive add al,[CURDRV] inc al gotdrive: push ax mov si,offset trangroup:bwdbuf+3 mov ah,Current_dir int 21h jnc dpbisok push cs pop ds jmp drvbad dpbisok: mov di,offset trangroup:bwdbuf mov dx,di pop ax mov ah,':' stosw mov al,[dirchar] stosb ret break Path assume ds:trangroup,es:trangroup PATH: xor al,al ;AN049; Set up holding buffer mov di,offset Trangroup:srcxname ;AN049; for PATH while parsing stosb ;AN049; Initialize PATH to null dec di ;AN049; point to the start of buffer invoke PGetarg ; Pre scan for arguments jz disppath ; Print the current path cmp al,semicolon ;AC049; NUL path argument? jnz pathslp ;AC049; inc si ;AN049; point past semicolon jmp short scan_white ;AC049; Yes - make sure nothing else on line pathslp: ; Get the user specified path lodsb ; Get a character cmp al,end_of_line_in ;AC049; Is it end of line? jz path_eol ;AC049; yes - end of command invoke testkanj ;See if DBCS jz notkanj2 ;No - continue stosb ;AC049; Yes - store the first byte lodsb ;skip second byte of DBCS path_hold: ;AN049; stosb ;AC049; Store a byte in the PATH buffer jmp short pathslp ;continue parsing notkanj2: invoke upconv ;upper case the character cmp al,semicolon ;AC049; ';' not a delimiter on PATH jz path_hold ;AC049; go store it invoke delim ;delimiter? jnz path_hold ;AC049; no - go store character scan_white: ;AN049; make sure were at EOL lodsb ;AN049; get a character cmp al,end_of_line_in ;AN049; end of line? jz path_eol ;AN049; yes - go set path cmp al,blank ;AN049; whitespace? jz scan_white ;AN049; yes - continue scanning cmp al,tab_chr ;AN049; whitespace? jz scan_white ;AN049; yes - continue scanning mov dx,offset TranGroup:Extend_Buf_ptr ;AN049; no - set up error message mov Extend_Buf_ptr,MoreArgs_ptr ;AN049; get "Too many parameters" message number mov msg_disp_class,parse_msg_class ;AN049; set up parse error msg class jmp cerror ;AN049; path_eol: ;AN049; Parsing was clean xor al,al ;AN049; null terminate the PATH stosb ;AN049; buffer invoke find_path ;AN049; Find PATH in environment invoke delete_path ;AC049; Delete any offending name invoke scan_double_null ;AC049; Scan to end of environment invoke move_name ;AC049; move in PATH= mov si,offset Trangroup:srcxname ;AN049; Set up source as PATH buffer store_path: ;AN049; Store the PATH in the environment lodsb ;AN049; Get a character cmp al,end_of_line_out ;AN049; null character? jz got_paths ;AN049; yes - exit invoke store_char ;AN049; no - store character jmp short store_path ;AN049; continue got_paths: ;AN049; we're finished xor ax,ax ;null terminate the PATH in stosw ; the environment return disppath: invoke find_path ;AN049; call print_path call crlf2 return print_path: cmp byte ptr es:[di],0 jnz path1 path0: mov dx,offset trangroup:nulpath_ptr push cs pop es push cs pop ds jmp std_printf path1: push es pop ds sub di,5 mov si,di ASSUME DS:RESGROUP xor al,al ; count str len to copy mov cx,128 ; up to arg_bug len repnz scasb mov cx,di sub cx,si push cs pop es mov di,offset trangroup:arg_buf rep movsb mov dx,offset trangroup:arg_buf_ptr push cs pop ds jmp std_printf ASSUME DS:TRANGROUP break Cls ; **************************************************************** ; * ; * ROUTINE: CLS ; * ; * FUNCTION: Clear the screen using INT 10h. If ANSI.SYS is ; * installed, send a control string to clear the ; * screen. ; * ; * INPUT: command line at offset 81H ; * ; * OUTPUT: none ; * ; **************************************************************** assume ds:trangroup,es:trangroup ANSI_installed equ 0ffh CLS: mov ah,Mult_ANSI ;AN000; see if ANSI.SYS installed mov al,0 ;AN000; int 2fh ;AN000; cmp al,ANSI_installed ;AN000; jz ansicls ;AN000; installed - go do ANSI CLS check_lines: mov ax,(IOCTL SHL 8) + generic_ioctl_handle ;AN000; get lines per page on display mov bx,stdout ;AN000; lines for stdout mov ch,ioc_sc ;AN000; type is display mov cl,get_generic ;AN000; get information mov dx,offset trangroup:display_ioctl ;AN000; int 21h ;AN000; jc no_variable ;AN000; function had error, use default mov ax,linperpag ;AN000; get number of rows returned mov dh,al ;AN000; set number of rows mov ax,display_width ;AN000; get number of columns returned mov dl,al ;AN000; set number of columns jmp short regcls ;AN000; go do cls no_variable: mov bx,stdout ;AC000; set handle as stdout mov ax,IOCTL SHL 8 ;AC000; do ioctl - get device int 21h ;AC000; info test dl,devid_ISDEV ;AC000; is handle a device jz ANSICLS ;AC000; If a file put out ANSI test dl,devid_SPECIAL ;AC000; jnz cls_normal ;AC000; If not special CON, do ANSI ansicls: call ansi_cls ;AN000; clear the screen jmp short cls_ret ;AN000; exit ; ; Get video mode ; cls_normal: ;AC000; mov ah,get_video_state ;AC000; set up to get video state int video_io_int ;AC000; do int 10h - BIOS video IO cmp al,video_alpha ;AC000; see if in text mode jbe DoAlpha cmp al,video_bw ;AC000; see if black & white card jz DoAlpha ; ; We are in graphics mode. Bogus IBM ROM does not scroll correctly. We will ; be just as bogus and set the mode that we just got. This will blank the ; screen too. ; mov ah,set_video_mode ;AC000; set video mode call int video_io_int ;AC000; do int 10h - BIOS video IO jmp short cls_ret ;AC000; exit DoAlpha: ; ; Get video mode and number of columns to scroll ; ;M01 - INT 10 Function 0F doesn't reliably return the number of rows on some ;M01 adaptors. We circumvent this by reaching directly into the BIOS data ;M01 area ;M01 Commented out code here is the original ;M01 mov ah,get_video_state ;AC000; set up to get current video state ;M01 int video_io_int ;AC000; do int 10h - BIOS video IO ;M01 mov dl,ah ;M01 mov dh,linesperpage ;AC000; have 25 rows on the screen ;M01 Following code lifted from a fix Compaq applied to ANSI push ds MOV AX,ROMBIOS_DATA ; GET ROM Data segment M01 MOV DS,AX ; * M01 Assume DS:ROMBIOS_DATA mov dx,CRT_Cols ; Get Columns - assume < 256 M01 MOV dh,CRT_Rows ; GET MAX NUM OF ROWS M01 pop ds ; M01 Assume DS:Trangroup or dh,dh ; Q:ZERO M01 jnz regcls ; *JMP IF NO M01 MOV dh,LINESPERPAGE ; SET TO 24 ROWS M01 regcls: inc dh ; height+1 M018 call reg_cls ; go clear the screen cls_ret: ret ; exit ; **************************************************************** ; * ; * ROUTINE: REG_CLS ; * ; * FUNCTION: Clear the screen using INT 10H. ; * ; * INPUT: DL = NUMBER OF COLUMNS ; * DH = NUMBER OF ROWS ; * ; * OUTPUT: none ; * ; **************************************************************** reg_cls proc near ; ; Set overscan to black. ; dec dh ; decrement rows and columns dec dl ; to zero base push dx ; save rows,columns mov ah,set_color_palette ; set up to set the color to blank xor bx,bx int video_io_int ; do int 10h - BIOS video IO pop dx ; retore rows,colums xor ax,ax ; zero out ax mov CX,ax ; an cx ; ; Scroll active page ; mov ah,scroll_video_page ; set up to scroll page up mov bh,video_attribute ; attribute for blank line xor bl,bl ; set BL to 0 int video_io_int ; do int 10h - BIOS video IO ; ; Seek to cursor to 0,0 ; ;M022 following two lines added mov ah,get_video_state ; get current video page in BH int video_io_int mov ah,set_cursor_position ; set up to set cursor position xor dx,dx ; row and column 0 ;M022 mov bh.0 int video_io_int ; do into 10h - BIOS video IO ret reg_cls endp ; **************************************************************** ; * ; * ROUTINE: ANSI_CLS ; * ; * FUNCTION: Clear the screen using by writing a control code ; * to STDOUT. ; * ; * INPUT: none ; * ; * OUTPUT: none ; * ; **************************************************************** ansi_cls proc near ;AC000; mov si,offset trangroup:clsstring lodsb mov cl,al xor ch,ch mov ah,Raw_CON_IO clrloop: lodsb mov DL,al int 21h loop clrloop return ansi_cls endp ;AC000; trancode ends end