PAGE 90,132 ;A2 title LABEL.SAL - DOS LABEL COMMAND ;***************************************************************************** ;* * ;* MODULE NAME: LABEL * ;* * ;* DESCRIPTIVE NAME: LABEL a diskette or disk * ;* * ;* FUNCTION: Create, change or delete a volume label on a disk. * ;* * ;* ENTRY POINT: Start * ;* * ;* INPUT: (DOS command line parameters) * ;* [d:][path]LABEL [d:][volume label] * ;* where: * ;* [d:][path] before LABEL specifies the drive and path that contains * ;* the LABEL command file. * ;* * ;* [d:][volume label] specifies the volume label. Volume labels are * ;* used to identify a disk. They can be up to 11 characters and are in * ;* the same format as volume labels created by FORMAT/V. * ;* * ;* EXIT-NORMAL: ERRORLEVEL 0 - Normal completion * ;* * ;* EXIT-ERROR: ERRORLEVEL 1 - Any error * ;* * ;* EFFECTS: The volume label is set to the indicated string. The volume * ;* serial number, if present, is also displayed. * ;* * ;* INCLUDED FILES: None * ;* * ;* INTERNAL REFERENCES: * ;* * ;* Routines: * ;* CHARACTER_CHECK - See if char is valid for filename * ;* CHECK_DELETE - Get user Y/N if to delete old label * ;* CHECK_FOR_DRIVE_LETTER - Parse for drive in string * ;* CHECK_TRANSLATE_DRIVE - See if drive is SUBST or ASSIGN * ;* CHK_DBCS -See if specified byte is a DBCS lead byte * ;* CHK_DBCS_BLANK - Process DBCS blank char * ;* CREATE_NEW_LABEL - Output new vol label * ;* DATA AREAS - STACK, buffers, FCB'S, message sublists * ;* DELETE_OLD_LABEL - Delete original volume label * ;* DISPLAY_MSG - Send msg to system message handler * ;* DRIVE_SETUP - Verify drive, get default, setup drive ID * ;* ERROR_EXIT - Abnormal return to DOS * ;* FIND_FIRST_CHAR - Locate first non blank in input * ;* FIND_OLD_LABEL - Get the existing volume label * ;* GET_NEW_LABEL - Parse new vol label name into path * ;* GET_SERIAL_NUM - Get vol ser number from "GET_MEDIA_ID" * ;* GET_USER_INPUT - Read from user new vol label * ;* MAIN CODE - PSP, entry point * ;* MAIN_BEGIN - High level function control * ;* OUTPUT_OLD_LABEL - Display the original vol label * ;* PRELOAD_MESSAGES - Set up sys msgs, DOS version check * ;* PROCESS_STRING - Mov string to buf, check bad chars * ;* SETUP_CRLF - Carriage return, line feed * ;* SETUP_DELLABEL - "Delete current volume label (Y/N)?" * ;* SETUP_HASLABEL - "Volume in drive %1 is %2" * ;* SETUP_INVCHAR - "Invalid characters in volume label" * ;* SETUP_INVDRIVE - "Invalid drive specification" * ;* SETUP_NETDRIVE - "Cannot %1 a Network drive" * ;* SETUP_NEWLABEL - "Volume label (11 characters, ENTER for none)?" * ;* SETUP_NOLABEL - "Volume in drive %1 has no label" * ;* SETUP_NOROOM - "Cannot make directory entry" * ;* SETUP_SERIALNUM - "Volume Serial Number is %1-%2" * ;* SETUP_SUBSTASGN - "Cannot %1 a SUBSTed or ASSIGNed drive" * ;* SETUP_TOOMANY - "Too many files open" * ;* * ;* Data Areas: * ;* CONTROL BLOCKS - SUBLISTS for message parameters * ;* BUFFERS - For GET_MEDIA_ID, several FCB'S * ;* PSP - Contains the DOS command line parameters. * ;* STACK - Temporary save area * ;* * ;* EXTERNAL REFERENCES: * ;* * ;* Routines: * ;* SYSDISPMSG (NEAR) - Message display routine * ;* SYSLOADMSG (NEAR) - System message loader * ;* * ;* Data Areas: * ;* DTA - defined for the DOS FINDFIRST function. * ;* * ;* NOTES: LABEL should not be used with SUBSTed drives. The root directory * ;* of the actual drive will be the target of LABEL. LABEL should * ;* not be used with ASSIGNed drives or to label network drives. * * ;* * ;* This module should be processed with the SALUT pre-processor * ;* with the re-alignment not requested, as: * ;* * ;* SALUT LABEL,NUL * ;* * ;* To assemble these modules, the sequential or alphabetical * ;* ordering of segments may be used. * ;* * ;* Sample LINK command: * ;* * ;* LINK @LABEL.ARF * ;* * ;* Where the LABEL.ARF is defined as: * ;* * ;* LABEL+ * ;* LABELM * ;* * ;* These modules should be linked in this order. The load module is * ;* a COM file. It should be converted via EXE2BIN to a .COM file. * ;* * ;* REVISION HISTORY: * ;* * ;* AN000;D DBCS Support (New LOC) 06/87 S. Maes * ;* AN000;M Message service routine (New LOC) 06/87 S. Maes * ;* AC000;M Message service routine (Changed LOC) 06/87 S. Maes * ;* AN000;S Serial Number (New LOC) 06/87 S. Maes * ;* AC000;K SALUT 08/87 E. Kiser * ;* Ax001; DCR0524 - enable deletion of labelID 04/88 S. Maes * ;* Ax002; PTM4282 - parse complete line for invalids 04/88 S. Maes * ;* AN003; PTM4588 - scan entire line fails DBCS 05/88 S. Maes * ;* * ;* COPYRIGHT: The following notice is found in the OBJ code generated * ;* in the LABELM.SAL module. * ;* * ;* "Version 4.00 (C)Copyright 1988 Microsoft ;* "Licensed Material - Program Property of Microsoft" * ;* * ;***************************************************************************** HEADER IF1 %OUT COMPONENT=LABEL, MODULE=LABEL.SAL ENDIF HEADER MACRO TEXT .XLIST SUBTTL &TEXT .LIST PAGE ENDM ;***************************************************************************** ; Equate Area ;***************************************************************************** ; $SALUT (4,20,25,36) ;AN000;K ; DOS FUNCTION CALLS FCB_SEARCH equ 11h FCB_DELETE equ 13h GET_DEFAULT equ 19h SET_DTA equ 1Ah CLOSE equ 3Eh READ equ 3Fh IOCTL equ 44h LOC_OR_NET equ 9h ;AN000;K Local or network, subfunc of IOCTL EXIT equ 4Ch CREATE_FILE equ 5Bh YN_CHECK equ 6523h ;AN001; 65=GetExtCtry 23=Y/NCheck GET_MEDIA_ID equ 6900h ;AN000;S Int 21 for Serial Number GET_DBCS_ENV equ 6300h ;AN000;D DBCS support XNAMETRANS equ 60h ;AN000; ; DBCS SPECIAL CHARACTER DEFINITIONS DBCSBLK_BYTEONE equ 81h ;AN000;D 1st byte of DBCS blank DBCSBLK_BYTETWO equ 40h ;AN000;D 2nd byte of DBCS blank SBCSBLANKS equ 2020h ;AN000;D 2 SBCS blanks ; MISCELLANEOUS EQUATES ASCII_DRV equ "A"-1 ;AN000;D Convert to Ascii drive BLANK equ " " CHAR_ZERO equ "0" ;AN000;K Padding for serial number COLON equ ":" DEFAULT_DRIVE equ 0 DOT_LOCATION equ 8 DRIVE_INVALID equ 0FFh END_OF_STRING equ 0 MAX_CHARS equ 11 MAX_INPUT equ 100h-81h ;Size of input buffer NO equ 0 ;AN001; Compare for Y/N response PERIOD equ "." YES equ 1 ;AN001; Compare for Y/N response ZERO equ 0 ; ERROR LEVEL RETURN CODES ERRORLEVEL_0 equ 0 ERRORLEVEL_1 equ 1 ; ATTRIBUTE OF DIRECTORY ENTRY VOL_ATTRIBUTE equ 8 ; ERROR CODES FROM DOS FUNCTIONS VOL_NOT_FOUND equ 0FFh TOO_MANY_FILES equ 4 ; ID IF MESSAGES DISPLAYED BY "LABEL" TOO_MANY_MSG equ 1 ;AN000;M Too many files open NO_ROOM_MSG equ 2 ;AN000;M Cannot make directory entry INV_CHAR_MSG equ 3 ;AN000;M Invalid characters in volume label NEW_LABEL_MSG equ 4 ;AN000;M Vol label (11 chars, ENTER for none)? INV_DRIVE_MSG equ 5 ;AN000;M Invalid drive specification NETWORKDRIVEMSG equ 6 ;AN000;M Cannot %1 a Network drive SUBSTASSIGNMSG equ 7 ;AN000;M Cannot %1 a SUBSTed or ASSIGNed drive NO_LABEL_MSG equ 8 ;AN000;M Volume in drive %1 has no label SERIAL_NUM_MSG equ 9 ;AN000;M Volume Serial Number is %1 HAS_LABEL_MSG equ 10 ;AN000;M Volume in Drive %1 is %2 DEL_LABEL_MSG equ 11 ;AN001;M Delete current volume label (Y/N)? CRLF_MSG equ 12 ;AN001;M CR,LF ; DEFINITIONS OF FIELDS WITHIN MSG SUBLISTS MAXWIDTH equ 0 ;AN000;M 0 will ensure no padding MINWIDTH equ 1 ;AN000;M At least 1 char to insert in msg STR_INPUT equ 16 ;AN000;M Byte definition for s?_flags SUBLIST_LENGTH equ 11 ;AN000;M Length of sublist structure RESERVED equ 0 ;AN000;M Reserved byte field CR equ 0Dh ;Carriage Return NO_INPUT equ 00h ;AN000;M No input characters DOS_CON_INPUT equ 00C8h ;AN000;M No input characters EXT_ERR_CLASS equ 01h ;AN000;M DOS Extended error class UTILITY_MSG_CLASS equ 0FFh ;AN000;M Utility message class STDIN equ 0000h ;File handle STDOUT equ 0001h ;Standard Output device handle STDERR equ 0002h ;Standard Error Output device handle BIN_HEX_WORD equ 23h ;AN000;M a0100011 RIGHT_ALIGN equ 80h ;AN000;M 10xxxxxx CHAR_FIELD_CHAR equ 0 ;AN000;M a0000000 HEADER
CSEG segment public ASSUME cs:CSEG,ds:CSEG,es:CSEG,ss:CSEG EXTRN SYSDISPMSG:NEAR ;SYSTEM DISPLAY MESSAGE ROUTINE EXTRN SYSLOADMSG:NEAR ;SYSTEM MESSAGE LOADER ROUTINE org 5Ch FCB1 label byte org 80h Num_Parms label byte org 81h Parm_Area label byte org 100h Start: ;DOS ENTRY POINT jmp Main_Begin ;SKIP CONSTANTS HEADER EVEN Stack_Area db 512 dup ("S") ;Added in DOS 3.20 to support hardware requiring End_Stack_Area db 0 ;large stacks. DO NOT PUT DATA ABOVE THIS ! New_Vol_Path db " :\" ;Path for new vol label New_Vol_Name db " " ;Where first 8 chars go New_Vol_Ext db ". ",0 ;Dot and extension End_Parameters dw 0 ;End of input string Program_Flag db 0 ;Status Flag USER_INPUT equ 01h ;User has input already LABEL_FND equ 02h ;Volume label found NO_DELETE equ 04h ;No need for label delete GET_INPUT equ 08h ;Need user input CHAR_BAD equ 10h ;Invalid character in string FOUND_DBCS equ 20h ;AN000;K in process of handling DBCS chars Vol_FCB db 0FFh ;Extended FCB db 0,0,0,0,0 db VOL_ATTRIBUTE ;Attribute for vol label FCB_Drive db 0 ;Drive number Vol_Name db "???????????" ;Match any vol name found db 25 dup (0) ;Rest of the opened FCB Label_Name db "???????????",0 ;AN000; FCB_Drive_Char db " " ;AN000;K printable version of FCB_Drive above TranSrc db "A:CON",0,0 ;AN000;A Device so we don't hit the drive TranDst db 64 dup(' ') ;AN000;A Label_Word db "LABEL",0 ;AN000;M Message substitution parm Del_FCB db 0FFh ;Extended FCB db 0,0,0,0,0 db VOL_ATTRIBUTE ;Attribute for vol label Del_Drive db 0 ;Drive number Del_Name db "???????????" ;Match any vol name found ; MESSAGE SUBLIST STRUCTURES Sublist1 Label Dword ;AN000;M Substitution list s1_nxtlst db SUBLIST_LENGTH ;AN000;M (11)Ptr to next sublist s1_reserve db RESERVED ;AN000;M (0)Reserved s1_offset dw ? ;AN000;M Time/date or data pointer s1_segment dw ? ;AN000;M Time/date or data pointer s1_id db 1 ;AN000;M N of %n s1_flags db ? ;AN000;M Data-type flags (a0sstttt) s1_maxwidth db ? ;AN000;M Maximum field width s1_minwidth db ? ;AN000;M Minimum field width s1_padchar db ? ;AN000;M Char to pad field Sublist2 Label Dword ;AN000;M Substitution list s2_nxtlst db SUBLIST_LENGTH ;AN000;M (11)Ptr to next sublist s2_reserve db RESERVED ;AN000;M (0)Reserved s2_offset dw ? ;AN000;M Time/date or data pointer s2_segment dw ? ;AN000;M Time/date or data pointer s2_id db 2 ;AN000;M N of %n s2_flags db ? ;AN000;M Data-type flags (a0sstttt) s2_maxwidth db ? ;AN000;M Maximum field width s2_minwidth db ? ;AN000;M Minimum field width s2_padchar db ? ;AN000;M Char to pad field ; GET_MEDIA_ID STRUCTURE SerNumBuf Label Byte ;AN000;S GET_MEDIA_ID buffer dw 0 ;AN000;S Info level (set on input) SerNum dd 0 ;AN000;S Serial # db 11 DUP(' ') ;AN000;S Volume label db 8 DUP(' ') ;AN000;S File system type ; CHK_DBCS STRUCTURE DBCSev_Off dw 0 ;AC000;D offset of DBCS EV DBCSev_Seg dw 0 ;AC000;D segment of DBCS EV HEADER ; $SALUT (4,4,9,36) ;AN000;K ;***************************************************************************** ;* * ;* SUBROUTINE NAME: main_begin * ;* * ;* SUBROUTINE FUNCTION: Preload message file and check DOS version * ;* by calling SYSLOADMSG * ;* Get the command line parameters * ;* Parse command line * ;* Verify the correctness of the parameters * ;* Get label if exists * ;* Get serial number if exists * ;* Get new volume name * ;* Make new volume file * ;* Print messages by calling SYSDISPMSG * ;* * ;* EXTERNAL ROUTINES: SYSDISPMSG * ;* SYSLOADMSG * ;* * ;* INTERNAL ROUTINES: Character_Check Main_Begin * ;* Check_Delete Output_Old_Label * ;* Check_For_Drive_Letter Preload_Messages * ;* Check_Trans_Drive Process_String * ;* Chk_DBCS Setup_CRLF * ;* Chk_DBCS_Blank Setup_DelLabel * ;* Create_New_Label Setup_HasLabel * ;* Delete_Old_Label Setup_InvChar * ;* Display_Msg Setup_InvDrive * ;* Drive_Setup Setup_NetDrive * ;* Error_Exit Setup_NewLabel * ;* Find_First_Char Setup_NoLabel * ;* Find_Old_Label Setup_NoRoom * ;* Get_New_Label Setup_SerialNum * ;* Get_Serial_Num Setup_SubstAsgn * ;* Get_User_Input Setup_TooMany * ;* * ;***************************************************************************** PUBLIC MAIN_BEGIN Main_Begin Proc Near mov sp,offset End_Stack_Area ;Move stack to user area(Added in DOS 3.20) cld call Preload_Messages ;AN000;M Check DOS version & load msgs call Drive_Setup ;Get Drive letters call Find_Old_Label ;Get label if exist call Get_New_Label ;Get New Name call Check_Delete ;AN001; See if delete needed or wanted call Delete_Old_Label ;Del the old label if it exists call Create_New_Label ;Make new Vol file mov ax,(EXIT shl 8)+ERRORLEVEL_0 ;all done, pass back zero ret code INT 21H Main_Begin ENDP HEADER ;***************************************************************************** ; Verify specified drive, get default if needed, setup drive letters ;***************************************************************************** PUBLIC DRIVE_SETUP Drive_Setup PROC NEAR cmp al,DRIVE_INVALID ;Was specified drive ok ? ; $if e ;AN000;K No JNE $$IF1 mov ax,INV_DRIVE_MSG ;Nope, tell & quit call Setup_InvDrive ;AN000;M call Display_Msg ;AN000;M Set up msg & display call Error_Exit ; $endif ;AN000;K $$IF1: ; Get_Drive: mov al,FCB1 ;Get specified drive cmp al,DEFAULT_DRIVE ;Was drive given ? ; $if e ;AN000;K No JNE $$IF3 mov ah,GET_DEFAULT ;No, get default drive INT 21H inc al ;Get a: based on 1, not 0 ; $endif ;AN000;K $$IF3: ; Drive_Letter: mov FCB_Drive,al ;Put drive number in FCB mov Del_Drive,al ;Put drive number in FCB mov bl,al mov al,FCB_Drive ;AN000;K get numeric value of drive letter add al,ASCII_DRV ;AN000;M ("A"-1) mov FCB_Drive_Char,al ;AN000;K make drive printable mov ax,(IOCTL SHL 8)+LOC_OR_NET ;(4409h)determine drive type INT 21H test dx,1000h ;bit 12 on means network drive ; $if nz ;AN000;K JZ $$IF5 mov ax,NETWORKDRIVEMSG call Setup_NetDrive ;AN000;M call Display_Msg ;AN000;M First display the msg call Error_Exit ; $endif ;AN000;K $$IF5: call Check_Trans_Drive ;AN000;A Is drv SUBSTed/ASSIGNed? ; $if nz ;AN000;K Yes JZ $$IF7 mov ax,SUBSTASSIGNMSG ;AN000;A Prepare SUBST/ASSIGN msg call Setup_SubstAsgn ;AN000;M call Display_Msg ;AN000;A Display the message call Error_Exit ;AN000;A Then exit ; $endif ;AN000;K $$IF7: mov al,Del_Drive add al,ASCII_DRV ;AN000;K ("A"-1) Convert to Ascii mov New_Vol_Path,al ;Put drive letter in path ret Drive_Setup ENDP HEADER ;***************************************************************************** ; Routine name: Check_Translate_Drive ;***************************************************************************** ; Descr: Do a name translate call on the drive letter to see if it is ; assigned by SUBST or ASSIGN ; Input: Drive PUBLIC CHECK_TRANS_DRIVE Check_Trans_Drive PROC NEAR ;AN000;A mov bl,FCB_Drive_Char ;AN000;A Get drive mov byte ptr [TranSrc],bl ;AN000;A Make string "x:\" mov si,offset TranSrc ;AN000;A Point to translate string mov di,offset TranDst ;AN000;A Point at output buffer mov ah,XNAMETRANS ;AN000;A (60H) Get real path INT 21H ;AN000;A mov bl,byte ptr [TranSrc] ;AN000;A Get drive letter from path cmp bl,byte ptr [TranDst] ;AN000;A Did drive letter change? ret ;AN000;A Check_Trans_Drive ENDP ;AN000;A HEADER ;***************************************************************************** ; Find old volume label ;***************************************************************************** ; Input: VOL_FCB set to find any vol label ; Output: VOL_FCB has label name if one found ; PROGRAM_FLAG = LABEL_FND if one is found ; LABEL_NAME gets found label name PUBLIC FIND_OLD_LABEL Find_Old_Label PROC NEAR mov dx,offset Vol_FCB ;Point at FCB to find vol mov ah,SET_DTA ;(1AH) INT 21H mov dx,offset Vol_FCB ;Point at FCB to find vol mov ah,FCB_SEARCH ;(11H) INT 21H ;Find vol label cmp al,VOL_NOT_FOUND ;Find one ; $if ne ;AN000;K Yes JE $$IF9 or Program_Flag,LABEL_FND ;Yes, set flag mov si,offset Vol_Name ;Found name mov di,offset Label_Name ;Where to put it mov cx,MAX_CHARS ;How many characters rep movsb ;Move the string ; $endif ;AN000;K $$IF9: ; Find_Return: ret Find_Old_Label ENDP HEADER ;***************************************************************************** ; Parse new volume label name into path. ;***************************************************************************** ; Input: PARM_AREA has input string ; Output: NEW_VOL_NAME has ASCIIZ string for new label, or an END_OF_STRING ; if nothing entered PUBLIC GET_NEW_LABEL Get_New_Label PROC NEAR ; $do ;AN000;K $$DO11: xor cx,cx ;Zero counter mov si,offset Parm_Area ;Input buffer mov di,offset New_Vol_Name ;Target Buffer call Find_First_Char ;Get first not blank char test Program_Flag,GET_INPUT ;Find input? jnz Need_User_Input ;No, go get it call Process_String ;Scan string, move it test Program_Flag,CHAR_BAD ;Invalid characters? jnz Need_User_Input ;Yes, get user to input mov al,END_OF_STRING ;Mark end of ASCIIZ string stosb cmp New_Vol_Name,END_OF_STRING ;Any chars entered? ; $leave ne ;Yes, all done here JNE $$EN11 test Program_Flag,USER_INPUT ;See if command line parse ; $leave nz ;No, user had his chance JNZ $$EN11 Need_User_Input: test Program_Flag,USER_INPUT ;Is this the first time here? ; $if z ;AN000;K Yes, label not already gone out JNZ $$IF14 call Output_Old_Label ;Yes, print current vol label ; $endif ;AN000;K $$IF14: Input_New_Label: call Get_User_Input ;Get new string ; $enddo ;AN000;K Go parse it again JMP SHORT $$DO11 $$EN11: ret Get_New_Label ENDP HEADER ;***************************************************************************** ; Find the first non blank character in input string ;***************************************************************************** ; Input: SI = pointer to next character ; Output: PROGRAM_FLAG = GET_INPUT if user input needed ; AL = First not blank character ; Notes: GET_INPUT set if nothing follows drive letter PUBLIC FIND_FIRST_CHAR Find_First_Char PROC NEAR ; $do ;AN000;K $$DO17: and Program_Flag,not GET_INPUT ;Clear flag lodsb ;Get char call Chk_DBCS ;AN000;D Check DBCS env ; $if c ;AN000;K JNC $$IF18 call Chk_DBCS_Blank ;AN000;D Is it a DBCS blank? ; $endif ;AN000;K $$IF18: cmp al,BLANK ;Is it a blank? ; $enddo ne ;AN000;K No, quit JE $$DO17 call Check_For_Drive_Letter ;Parse out drive letter call Chk_DBCS ;AN000;D Check DBCS env ; $if c ;AN000;K JNC $$IF21 call Chk_DBCS_Blank ;AN000;D Is it a DBCS blank? and Program_Flag,not FOUND_DBCS ;AN000;K forget this was a dbcs for now ; $endif ;AN000;K $$IF21: cmp al,BLANK ;Blank following drive letter? ; $if e ;AN000;K JNE $$IF23 or Program_Flag,GET_INPUT ; $endif ;AN000;K $$IF23: ret Find_First_Char ENDP HEADER ;***************************************************************************** ; Check DBCS environment ;***************************************************************************** ; Function: Check if a specified byte is in ranges of the DBCS lead bytes ; Input: AL = Code to be examined ; Output: If CF is on then a lead byte of DBCS ; Register: FL is used for the output, others are unchanged. PUBLIC CHK_DBCS Chk_DBCS PROC ;AC000;D push ds ;AC000;D save regs, about to be clobbered push si ;AC000;D cmp DBCSev_Seg,ZERO ;AC000;D Already set ? ; $if e ;AN000;K if the vector not yet found JNE $$IF25 push ax ;AC000;D mov ax,GET_DBCS_ENV ;AC000;D GET DBCS EV call INT 21H ;AC000;D ds:si points to the dbcs vector ASSUME ds:NOTHING ;AN000;K that function clobbered old DS mov DBCSev_Off,si ;AC000;D remem where dbcs vector is so next mov DBCSev_Seg,ds ;AC000;D time don't have to look for it pop ax ;AC000;D ; $endif ;AN000;K $$IF25: mov si,DBCSev_Off ;AC000;D set DS:SI to point to mov ds,DBCSev_Seg ;AC000;D the dbcs vector ; $search ;AN000;K $$DO27: cmp word ptr [si],ZERO ;AC000;D vec ends with nul terminator entry ; $leave e ;AN000;K if that was terminator entry, quit JE $$EN27 cmp al,[si] ;AC000;D look at LOW value of vector ; $exitif nb,and ;AN000;K if this byte in range of LOW JB $$IF27 cmp al,[si+1] ;AC000;D look at HIGH value of vector ; $exitif na ;AN000;K if this byte is still in range JA $$IF27 or Program_Flag,FOUND_DBCS ;AN000;K remember we found one of a pair stc ;AC000;D set flag to say, found a DBCS char ; $orelse ;AN000;K since char not in this vector JMP SHORT $$SR27 $$IF27: add si,2 ;AC000;D go look at next vec in dbcs table ; $endloop ;AN000;K go back and ck out new vector entry JMP SHORT $$DO27 $$EN27: clc ;AC000;D set flag to say not a DBCS char ; $endsrch ;AN000;K $$SR27: pop si ;AC000;D restore the regs pop ds ;AC000;D ASSUME ds:CSEG ;AN000;K tell masm, DS back to normal ret ;AC000;D Chk_DBCS ENDP ;AC000;D HEADER ;***************************************************************************** ; Check DBCS char for a blank (8140) ;***************************************************************************** ; Function: Check if a specified byte is a DBCS blank ; Input: AL = Byte to be examined ; SI = Points to next byte ; Output: SI = UNchanged PUBLIC CHK_DBCS_BLANK Chk_DBCS_Blank PROC NEAR ;AN000;D cmp al,DBCSBLK_BYTEONE ;AN000;D Is the leading byte 81h? ; $if e,and ;AN000;K JNE $$IF33 cmp byte ptr [si],DBCSBLK_BYTETWO ;AN000;D Is the 2nd byte 40h? ; $if e ;AN000;K Yes, change to 2 SBCS blanks JNE $$IF33 ; Convert_DBCS_Blank: ;AN000;D mov word ptr es:[si]-1,SBCSBLANKS ;AN000;D Fill it up with blank-blank mov al,BLANK ;AN000;K pretend this char is a blank ; $endif ;AN000;K $$IF33: ; DBCS_Blank_Exit: ;AN000;D ret ;AN000;D And leave Chk_DBCS_Blank ENDP ;AN000;D HEADER ;***************************************************************************** ; Parse a drive letter out of the string [Check_For_Drive_Letter] ;***************************************************************************** ; Input: SI = pointer to next character ; CX = character count ; Output: SI = SI+1 if drive letter entered PUBLIC CHECK_FOR_DRIVE_LETTER Check_For_Drive_Letter PROC NEAR test Program_Flag,USER_INPUT ;Input not from command line? ; $if z ;AN000;K JNZ $$IF35 cmp cx,END_OF_STRING ;Anything parsed yet ; $if e ;AN000; JNE $$IF36 cmp al,CR ;First char a CR ? ; $if ne JE $$IF37 cmp byte ptr [si],COLON ;Drive letter entered? ; $if e ;AN000;K JNE $$IF38 inc si ;Yes, point past the colon lodsb ;And get next character ; $endif ;AN000;K $$IF38: ; $endif ;AN000;K $$IF37: ; $endif ;AN000;K $$IF36: ; $endif ;AN000;K $$IF35: Drive_Letter_Ret: ret Check_For_Drive_Letter ENDP HEADER ;***************************************************************************** ; Move the input string into buffer, checking for bad characters ;***************************************************************************** ; Input: SI = pointer to next character ; DI = pointer to buffer ; AL = current character in string ; Output: PROGRAM_FLAG = CHAR_BAD if invalid char in string (Flag set in ; called Character_Check routine) ; Notes: Insert a "." in string to seperate 8th and 9th characters so ; ASCIIZ string is the result. PUBLIC PROCESS_STRING Process_String PROC NEAR cmp al,CR ;is it an ENTER ? ; $if e JNE $$IF43 test Program_Flag,USER_INPUT ;has user been told to provide input? ; $if nz ;If user has been prompted for input JZ $$IF44 cmp cx,ZERO ;And he said - nothing ; $if e JNE $$IF45 jmp Process_String_Return ;AN001; ENTER is acceptable ; $endif $$IF45: ; $endif $$IF44: ; $else ;Since got other than just ENTER JMP SHORT $$EN43 $$IF43: test Program_Flag,FOUND_DBCS ;AN000;K If prev char not 1st of DBCS pair jz Do_More_Check ;AN000;K then go check it out and Program_Flag,not FOUND_DBCS ;AN000; Reset flag, found its partner cmp cx,11 ;AC003; Continue to check chars but don't jge Scan_Continue ;AC003; store anything more jmp short Got_Ok_Character ;AN000; Partner is ok Do_More_Check: call Chk_DBCS ;AN000;D Check DBCS env jnc Check_Char ;AN000;D If carry, it's a DBCS char cmp cx,10 ;AC003; If previous char was the 10th jge Scan_Continue ;AC003; then there is no room for 11th DBCS call Chk_DBCS_Blank ;AN000;D Is it a DBCS blank? jmp Got_Ok_Character ;AN000;D Check_Char: call Character_Check ;Is it a valid char ? test Program_Flag,CHAR_BAD jnz Process_String_Return ;Flag was set, char was invalid cmp cx,11 ;AN003; Continue to check chars but don't jge Scan_Continue ;AN003; store anything more Got_Ok_Character: stosb ;Good char, store it Scan_Continue: ;AN003; Skip storing chars since past limit inc cx ;Inc character count cmp cx,DOT_LOCATION ;Do we need "." for extension? jne Get_Next_Char ;No mov al,PERIOD ;Get a "." for extension stosb ;And save it Get_Next_Char: lodsb ;Get next character cmp cx,MAX_INPUT ;AN002; Have we reached end? jne Process_String ;No, go diddle with it ; $endif $$EN43: Process_String_Return: ret Process_String ENDP HEADER ;***************************************************************************** ; See if a character is valid for filename [Character_Check] ;***************************************************************************** ; Input: AL = character to be checked ; Output: AL = character ; PROGRAM_FLAG = CHAR_BAD if invalid characters found PUBLIC CHARACTER_CHECK Character_Check PROC NEAR or Program_Flag,CHAR_BAD ;Assume bad character cmp al,"*" je Char_Check_Done cmp al,"?" je Char_Check_Done cmp al,"[" je Char_Check_Done cmp al,"]" je Char_Check_Done cmp al,":" je Char_Check_Done cmp al,"<" je Char_Check_Done cmp al,"|" je Char_Check_Done cmp al,">" je Char_Check_Done cmp al,"+" je Char_Check_Done cmp al,"=" je Char_Check_Done cmp al,";" je Char_Check_Done cmp al,"," je Char_Check_Done cmp al,"/" je Char_Check_Done cmp al,"\" je Char_Check_Done cmp al,'.' je Char_Check_Done cmp al,'"' je Char_Check_Done cmp al," " jb Char_Check_Done and Program_Flag,not CHAR_BAD ;Char is ok Char_Check_Done: ret Character_Check ENDP HEADER ;***************************************************************************** ; Print the old volume label ;***************************************************************************** ; Input: PROGRAM_FLAG = LABEL_FND if there is a label ; Output: None ; Notes: Print the volume label PUBLIC OUTPUT_OLD_LABEL Output_Old_Label PROC NEAR mov ax,HAS_LABEL_MSG ;Assume label call Setup_HasLabel ;AN000;M test Program_Flag,LABEL_FND ;Is there one? ; $if z ;AN000;K If no label found, then JNZ $$IF50 mov ax,NO_LABEL_MSG ;No, other message call Setup_NoLabel ;AN000;M ; $endif ;AN000;K $$IF50: call Display_Msg ;AC000;M Set up msg and display call Get_Serial_Num ;AN000;S Since LABEL_FND, ck for SN ; $if nc ;AN000;K SN must be known JC $$IF52 mov ax,SERIAL_NUM_MSG ;AN000;S Prepare for SN message call Setup_SerialNum ;AN000;M call Display_Msg ;AC000;M Set up msg and display ; $endif ;AN000;K $$IF52: ret Output_Old_Label ENDP HEADER ;***************************************************************************** ; Get the volume serial number ;***************************************************************************** ; Input: FCB_Drive ; Output: SerNum if no carry ; Notes: Only DOS Version 4.0 and above will contain serial numbers PUBLIC GET_SERIAL_NUM Get_Serial_Num PROC NEAR ;AN000;S mov ax,GET_MEDIA_ID ;AN000;S mov bh,0 ;AN000;S mov bl,FCB_Drive ;AN000;S Which drive to check lea dx,SerNumBuf ;AN000;S Pt to the buffer INT 21H ;AN000;S Make the call ret ;AN000;S Get_Serial_Num ENDP ;AN000;S HEADER ;***************************************************************************** ; Input from user a new volume label string ;***************************************************************************** ; Input: PROGRAM_FLAG = CHAR_BAD if there were invalid characters in string ; Output: New string placed in PARM_AREA ; Notes: Print bad character message if needed and prompt and get user input PUBLIC GET_USER_INPUT Get_User_Input PROC NEAR test Program_Flag,CHAR_BAD ;Do we need bad char message ; $if nz ;AN000;K JZ $$IF54 mov ax,INV_CHAR_MSG ;Yes call Setup_InvChar ;AN000;M call Display_Msg ;AC000;M Set up msg and display and Program_Flag,not CHAR_BAD ;Char is ok ; $endif ;AN000;K $$IF54: mov ax,NEW_LABEL_MSG ;Tell user to input new label call Setup_NewLabel ;AN000;M call Display_Msg ;AC000;M Set up msg and display mov dx,offset Parm_Area ;Point where to put new name mov cx,MAX_INPUT ;Number of characters to read mov bx,STDIN ;Read from keyboard mov ah,READ ;(3FH) INT 21H or Program_Flag,USER_INPUT ;Indicate user input has been received ret Get_User_Input ENDP HEADER ;***************************************************************************** ; Check to see if old label should be deleted ;***************************************************************************** ; Input: PROGRAM_FLAG = LABEL_FND if there is a label ; Output: PROGRAM_FLAG = NO_DELETE if label should not be deleted ; Notes: Get user Y/N if to delete previous label PUBLIC CHECK_DELETE Check_Delete PROC NEAR test Program_Flag,LABEL_FND ;AN001; Is there a vol label jz Check_Delete_Return ;AN001; No, no need for prompt cmp New_Vol_Name,END_OF_STRING ;AN001; Did user enter label jne Check_Delete_Return ;AN001; Yes, no need for prompt Delete_Prompt: ;AN001; mov ax,DEL_LABEL_MSG ;AN001; Point at Y/N prompt call Setup_DelLabel ;AN001;M Prepare message call Display_Msg ;AN001;M Call to Sysdispmsg mov dx,ax ;AN001; Char ret'd, prep for ck mov ax,YN_CHECK ;AN001; GetExtCtry,Y/NCheck INT 21H ;AN001; cmp ax,YES ;AN001; Delete label ? je Check_Delete_Return ;AN001; Yes cmp ax,NO ;AN001; Delete label ? je Delete_Label ;AN001; Yes jne Delete_Prompt ;AN001; No, try again Delete_Label: ;AN001; or Program_Flag,NO_DELETE ;AN001; Yes, set flag Check_Delete_Return: ;AN001; mov ax,CRLF_MSG ;AN001; Point at CRLF message call Setup_CRLF ;AN001;M Prepare message call Display_Msg ;AN001;M Call to Sysdispmsg ret ;AN001; Check_Delete ENDP HEADER ;***************************************************************************** ; Delete old volume label ;***************************************************************************** ; Input: VOL_FCB has name of label if one found ; PROGRAM_FLAG = NO_DELETE if label doesn't need to be deleted ; Output: Vol label deleted if it exists and user say's it is okay ; Notes: Ask user if old label should be deleted. PUBLIC DELETE_OLD_LABEL Delete_Old_Label PROC NEAR test Program_Flag,NO_DELETE ;Need to delete label ? ; $if z ;AN000;K JNZ $$IF56 lea dx,Del_FCB ;Point at FCB to delete vol mov ah,FCB_DELETE ;(13H) label and delete it INT 21H ;Can't use handle cause Chmod won't find it ; $endif ;AN000;K $$IF56: ret Delete_Old_Label ENDP HEADER ;***************************************************************************** ; Create new volume label file if user specified one ;***************************************************************************** PUBLIC CREATE_NEW_LABEL Create_New_Label PROC NEAR cmp New_Vol_Name,END_OF_STRING ;Did user enter a vol label ; $if ne ;AN000;K JE $$IF58 mov dx,offset New_Vol_Path ;Point at path for file mov cx,VOL_ATTRIBUTE ;Set it as a volume label mov ah,CREATE_FILE ;(5BH) Go make it INT 21H ; $if nc ;AN000;K JC $$IF59 mov bx,ax ;shift file handle mov ah,CLOSE ;And close the file INT 21H ; $else ;AN000;K since there was creation error, JMP SHORT $$EN59 $$IF59: cmp ax,TOO_MANY_FILES ;Is it ; $if ne ;AN000;K if not "too many files", then JE $$IF61 mov ax,NO_ROOM_MSG ;AN000;M call Setup_NoRoom ;AN000;M call Display_Msg ;AN000;M test Program_Flag,LABEL_FND ;AN000;K was an old label found? ; $if ne ;AN000;K if there was an old one, JE $$IF62 ;need to restore the previous label ;because the new one did not stick mov si,offset Label_Name ;AN000;K where old name was kept mov di,offset New_Vol_Name ;AN000;K where to put old name mov cx,8 ;AN000;K count of filename up to "." rep movsb ;AN000;K inc di ;AN000;K skip the "." mov cx,3 ;AN000;K length of extension rep movsb ;AN000;K mov dx,offset New_Vol_Path ;AN000;K drive\path\filename mov cx,VOL_ATTRIBUTE ;AN000;K make it a label mov ah,CREATE_FILE ;AN000;K make a label INT 21H ;AN000;K at least, try to, anyway... ; $endif ;AN000;K old label? $$IF62: ; $else ;AN000;K since is "too many files", then... JMP SHORT $$EN61 $$IF61: mov ax,TOO_MANY_MSG ;AN000;M call Setup_TooMany ;AN000;M call Display_Msg ;AN000;M ; $endif ;AN000;K $$EN61: jmp Error_Exit ;Tell user bad news and quit ; $endif ;AN000;K $$EN59: ; $endif ;AN000;K $$IF58: ret Create_New_Label ENDP HEADER ;***************************************************************************** ; Preload utility messages ;***************************************************************************** ; Input: None ; Output: None ; Notes: Checks DOS version, if incorrect, or if error loading messages, will ; display error message and terminate PUBLIC PRELOAD_MESSAGES Preload_Messages PROC NEAR ;AN000;M push ax ;AN000;M push bp ;AN000;M mov bp,sp ;AN000;M push di ;AN000;M push si ;AN000;M call SYSLOADMSG ;AN000;M Load msgs & chk DOS ver ; $if c ;AN000;K JNC $$IF68 call SYSDISPMSG ;AN000;M pop si ;AN000;M pop di ;AN000;M mov sp,bp ;AN000;M pop bp ;AN000;M pop ax ;AN000;M call Error_Exit ;AN000;M ; $endif ;AN000;K $$IF68: pop si ;AN000;M pop di ;AN000;M mov sp,bp ;AN000;M pop bp ;AN000;M pop ax ;AN000;M ret ;AN000;M Preload_Messages ENDP ;AN000;M HEADER ;***************************************************************************** ; Display utility messages ;***************************************************************************** ; Input: dx contains the messsage to display ; Output: None ; Notes: The message called is displayed to stdout/stderr unless AX returns ; with error code (then setup for extended error to display) PUBLIC DISPLAY_MSG Display_Msg PROC NEAR ;AN000;M push bp ;AN000;M mov bp,sp ;AN000;M push di ;AN000;M push si ;AN000;M call SYSDISPMSG ;AN000;M Now display the message ; $if c ;AN000;K if there was a problem, then... JNC $$IF70 mov bx,STDERR ;AN000;M Error msg, so stderr mov cx,0 ;AN000;M Substitution count mov dl,NO_INPUT ;AN000;M No input characters mov dh,EXT_ERR_CLASS ;AN000;M DOS Extended error class call SYSDISPMSG ;AN000;M Now display the extended error pop si ;AN000;M pop di ;AN000;M mov sp,bp ;AN000;M pop bp ;AN000;M call Error_Exit ;AN000;M Nothing we can do so leave ; $endif ;AN000;K $$IF70: ; Done: ;AN000;M pop si ;AN000;M pop di ;AN000;M mov sp,bp ;AN000;M pop bp ;AN000;M ret ;AN000;M Bye,bye Display_Msg ENDP ;AN000;M HEADER ;***************************************************************************** ; Setup for utility messages ;***************************************************************************** ; Input: None ; Output: None PUBLIC SETUP_TOOMANY Setup_TooMany PROC NEAR ;AN000;M mov ax,4 ;AN000;M Utility's message number mov bx,STDERR ;AN000;M Error msg, so stderr mov cx,0 ;AN000;M Substitution count mov dl,NO_INPUT ;AN000;M No input characters mov dh,EXT_ERR_CLASS ;AN000;M DOS Extended error class ret ;AN000;M Now display the message Setup_TooMany ENDP ;AN000;M HEADER ;***************************************************************************** ; Setup for utility messages ;***************************************************************************** ; Input: None ; Output: None PUBLIC SETUP_NOROOM Setup_NoRoom PROC NEAR ;AN000;M mov ax,82 ;AN000;M Utility's message number mov bx,STDERR ;AN000;M Error msg, so stderr mov cx,0 ;AN000;M Substitution count mov dl,NO_INPUT ;AN000;M No input characters mov dh,EXT_ERR_CLASS ;AN000;M DOS Extended error class ret ;AN000;M Setup_NoRoom ENDP HEADER ;***************************************************************************** ; Setup for utility messages ;***************************************************************************** ; Input: None ; Output: None PUBLIC SETUP_INVCHAR Setup_InvChar PROC NEAR ;AN000;M mov ax,3 ;AN000;M Utility's message number mov bx,STDERR ;AN000;M Error msg, so stderr mov cx,0 ;AN000;M Substitution count mov dl,NO_INPUT ;AN000;M No input characters mov dh,UTILITY_MSG_CLASS ;AN000;M Utility message class ret ;AN000;M Setup_InvChar ENDP ;AN000;M HEADER ;***************************************************************************** ; Setup for utility messages ;***************************************************************************** ; Input: None ; Output: None PUBLIC SETUP_NEWLABEL Setup_NewLabel PROC NEAR ;AN000;M mov ax,6 ;AN000;M Utility's message number mov bx,STDOUT ;AN000;M Info msg, so stdout mov cx,0 ;AN000;M Substitution count mov dl,NO_INPUT ;AN000;M No input characters mov dh,UTILITY_MSG_CLASS ;AN000;M Utility message class ret ;AN000;M Setup_NewLabel ENDP ;AN000;M HEADER ;***************************************************************************** ; Setup for utility messages ;***************************************************************************** ; Input: None ; Output: None PUBLIC SETUP_INVDRIVE Setup_InvDrive PROC NEAR ;AN000;M mov s1_offset,offset FCB_Drive_Char ;AN000;M mov s1_segment,ds ;AN000;M Setup segment mov s1_flags,CHAR_FIELD_CHAR ;AN000;M Set up the parm formatting mov s1_maxwidth,MAXWIDTH ;AN000;M 0 ensures no padding mov s1_minwidth,MINWIDTH ;AN000;M At least 1 char to insert mov s1_padchar,BLANK ;AN000;M In case, pad with blanks mov ax,15 ;AN000;M Utility's message number mov bx,STDERR ;AN000;M Error msg, so stderr lea si,sublist1 ;AN000;M Display invalid drive mov cx,0 ;AN000;M Substitution count mov dl,NO_INPUT ;AN000;M No input characters mov dh,EXT_ERR_CLASS ;AN000;M DOS Extended error class ret ;AN000;M Setup_InvDrive ENDP ;AN000;M HEADER ;***************************************************************************** ; Setup for utility messages ;***************************************************************************** ; Input: None ; Output: None PUBLIC SETUP_NETDRIVE Setup_NetDrive PROC NEAR ;AN000;M mov s1_offset,offset Label_Word ;AN000;M Cannot LABEL a network... mov s1_segment,ds ;AN000;M Setup segment mov s1_flags,STR_INPUT ;AN000;M Set up the parm formatting mov s1_maxwidth,MAXWIDTH ;AN000;M 0 ensures no padding mov s1_minwidth,MINWIDTH ;AN000;M At least 1 char to insert mov s1_padchar,BLANK ;AN000;M In case, pad with blanks mov ax,8 ;AN000;M Utility's message number mov bx,STDERR ;AN000;M Error msg, so stderr lea si,sublist1 ;AN000;M Display network drive msg mov cx,1 ;AN000;M Substitution count mov dl,NO_INPUT ;AN000;M No input characters mov dh,UTILITY_MSG_CLASS ;AN000;M Utility message class ret ;AN000;M Setup_NetDrive ENDP ;AN000;M HEADER ;***************************************************************************** ; Setup for utility messages ;***************************************************************************** ; Input: None ; Output: None PUBLIC SETUP_SUBSTASGN Setup_SubstAsgn PROC NEAR ;AN000;M mov s1_offset,offset Label_Word ;AN000;M Cannot LABEL a SUBSTed... mov s1_segment,ds ;AN000;M Setup segment mov s1_flags,STR_INPUT ;AN000;M Set up the parm formatting mov s1_maxwidth,MAXWIDTH ;AN000;M 0 ensures no padding mov s1_minwidth,MINWIDTH ;AN000;M At least 1 char to insert mov s1_padchar,BLANK ;AN000;M In case, pad with blanks mov ax,2 ;AN000;M Utility's message number mov bx,STDERR ;AN000;M Error msg, so stderr lea si,sublist1 ;AN000;M Display SUBST/ASSIGN drive ,dh mov cx,1 ;AN000;M Substitution count mov dl,NO_INPUT ;AN000;M No input characters mov dh,UTILITY_MSG_CLASS ;AN000;M Utility message class ret ;AN000;M Setup_SubstAsgn ENDP ;AN000;M HEADER ;***************************************************************************** ; Setup for utility messages ;***************************************************************************** ; Input: None ; Output: None PUBLIC SETUP_NOLABEL Setup_NoLabel PROC NEAR ;AN000;M mov s1_offset,offset FCB_Drive_Char ;AN000;M mov s1_segment,ds ;AN000;M Setup segment mov s1_flags,CHAR_FIELD_CHAR ;AN000;M Set up the parm formatting mov s1_maxwidth,MAXWIDTH ;AN000;M 0 ensures no padding mov s1_minwidth,MINWIDTH ;AN000;M At least 1 char to insert mov s1_padchar,BLANK ;AN000;M In case, pad with blanks mov ax,4 ;AN000;M Utility's message number mov bx,STDOUT ;AN000;M Info msg, so stdout lea si,sublist1 ;AN000;M Display drive mov cx,1 ;AN000;M Substitution count mov dl,NO_INPUT ;AN000;M No input characters mov dh,UTILITY_MSG_CLASS ;AN000;M Utility message class ret ;AN000;M Setup_NoLabel ENDP ;AN000;M HEADER ;***************************************************************************** ; Setup for utility messages ;***************************************************************************** ; Input: None ; Output: None PUBLIC SETUP_SERIALNUM Setup_SerialNum PROC NEAR ;AN000;M mov s1_offset,offset SerNum+2 ;AN000;M mov s1_segment,ds ;AN000;M Setup segment mov s1_flags,BIN_HEX_WORD+RIGHT_ALIGN ;AN000;M Set up the parm formatting mov s1_maxwidth,DWORD ;AN000;M 0 ensures no padding mov s1_minwidth,DWORD ;AN000;M At least 1 char to insert mov s1_padchar,CHAR_ZERO ;AN000;M In case, pad with ZERO CHAR mov s2_offset,offset SerNum ;AN000;M mov s2_segment,ds ;AN000;M Setup segment mov s2_flags,BIN_HEX_WORD+RIGHT_ALIGN ;AN000;M Set up the parm formatting mov s2_maxwidth,DWORD ;AN000;M 0 ensures no padding mov s2_minwidth,DWORD ;AN000;M At least 1 char to insert mov s2_padchar,CHAR_ZERO ;AN000;M In case, pad with ZERO CHAR mov ax,7 ;AN000;M Utility's message number mov bx,STDOUT ;AN000;M Info msg, so stdout lea si,sublist1 ;AN000;M Display serial number mov cx,2 ;AN000;M Substitution count mov dl,NO_INPUT ;AN000;M No input characters mov dh,UTILITY_MSG_CLASS ;AN000;M Utility message class ret ;AN000;M Setup_SerialNum ENDP ;AN000;M HEADER ;***************************************************************************** ; Setup for utility messages ;***************************************************************************** ; Input: None ; Output: None PUBLIC SETUP_HASLABEL Setup_HasLabel PROC NEAR ;AN000;M mov s1_offset,offset FCB_Drive_Char ;AN000;M mov s1_segment,ds ;AN000;M Setup segment mov s1_flags,CHAR_FIELD_CHAR ;AN000;M Set up the parm formatting mov s1_maxwidth,MAXWIDTH ;AN000;M 0 ensures no padding mov s1_minwidth,MINWIDTH ;AN000;M At least 1 char to insert mov s1_padchar,BLANK ;AN000;M In case, pad with blanks mov s2_offset,offset Label_Name ;AN000;M mov s2_segment,ds ;AN000;M Setup segment mov s2_flags,STR_INPUT ;AN000;M Set up the parm formatting mov s2_maxwidth,MAXWIDTH ;AN000;M 0 ensures no padding mov s2_minwidth,MINWIDTH ;AN000;M At least 1 char to insert mov s2_padchar,BLANK ;AN000;M In case, pad with blanks mov ax,5 ;AN000;M Utility's message number mov bx,STDOUT ;AN000;M Info msg, so stdout lea si,sublist1 ;AN000;M Display drive then label mov cx,2 ;AN000;M Substitution count mov dl,NO_INPUT ;AN000;M No input characters mov dh,UTILITY_MSG_CLASS ;AN000;M Utility message class ret ;AN000;M Setup_HasLabel ENDP ;AN000;M HEADER ;***************************************************************************** ; Setup for utility messages ;***************************************************************************** ; Input: None ; Output: None PUBLIC SETUP_DELLABEL Setup_DelLabel PROC NEAR ;AN001;M mov ax,9 ;AN001;M Utility's message number mov bx,STDOUT ;AN001;M Info msg, so stdout mov cx,0 ;AN001;M Substitution count mov dl,DOS_CON_INPUT ;AN001;M Input Y/N character mov dh,UTILITY_MSG_CLASS ;AN001;M Utility message class ret ;AN001;M Setup_DelLabel ENDP ;AN001;M HEADER ;***************************************************************************** ; Setup for utility messages ;***************************************************************************** ; Input: None ; Output: None PUBLIC SETUP_CRLF Setup_CRLF PROC NEAR ;AN001;M mov ax,10 ;AN001;M Utility's message number mov bx,STDOUT ;AN001;M Info msg, so stdout mov cx,0 ;AN001;M Substitution count mov dl,NO_INPUT ;AN001;M Input Y/N character mov dh,UTILITY_MSG_CLASS ;AN001;M No input characters ret ;AN001;M Setup_CRLF ENDP ;AN001;M HEADER ;***************************************************************************** ; Error on exit ;***************************************************************************** PUBLIC ERROR_EXIT Error_Exit PROC NEAR ;AC000;M mov ax,(EXIT SHL 8)+ERRORLEVEL_1 ;AN000;K Terminate, with ret code INT 21H Error_Exit ENDP ;AN000;M End_Of_Program label byte Public End_Of_Program CSEG ends end Start