PAGE 90,132 ;A2 TITLE COMPINIT -- DISKCOMP INITIALIZATION PROGRAM ;****************** START OF SPECIFICATIONS ***************************** ; MODULE NAME: COMPINIT ; DESCRIPTIVE NAME: Initialization for Diskette to diskette copy Utility ;FUNCTION: DISKCOMP is to compare the contents of the diskette in the ; specified source drive to the diskette in the target ; drive. If necessary for the diskettes to use volume serial ; numbers, the actual value of those number is ignored. ; Multiple compares may be performed with one load of DISKCOMP. ; A prompt, "Compare another (Y/N)?" permits additional ; executions, all with the same drive specifications. ; ENTRY POINT: "DISKCOMP" at ORG 100h, jumps to "BEGIN". ; INPUT: (DOS command line parameters) ; [d:][path] DISKCOMP [d: [d:]] [/1] [/8] ; WHERE ; [d:][path] - Path where the DISKCOMP command resides. ; [d:] - To specify the Source drive ; ; [d:] - To specify the Target drive ; ; [/1] - To compare only the first side of the diskette, ; regardless of the diskette or drive type. ; [/8] - To compare only the first 8 sectors per track, ; even if the first diskette contains 9/15 sectors ; per track. ; ; EXIT-NORMAL: Errorlevel = 0 ; Function completed successfully. ; EXIT-ERROR: Errorlevel = 1 ; Abnormal termination due to error, wrong DOS, ; invalid parameters, unrecoverable I/O errors on ; the diskette. ; EFFECTS: The entire source diskette is compared, including the unused ; sectors. There is no awareness of the separate files ; involved. A unique volume serial number, if present, ; is ignored in the comparison process. ; INCLUDED FILES: ; PATHMAC.INC - PATHGEN MACRO ; INCLUDE DCMPMACR.INC ;(FORMERLY CALLED MACRO.DEF) ; INTERNAL REFERENCES: ; ROUTINES: ; INIT - initialization main routine ; SOURCE_TARGET_DRV - convert source/target drive to bios values ; TEST_DRIVE_VALIDITY - are source/target drives valid? ; DOS_DRIVE_VALIDITY -- check dos drive validity byte ; TEST_REMOVABLE - is specified drive removable? ; CHK_SINGLE_DRIV_OP - is target drive same as source? ; GET_LOGICAL_DRIVE - get logical drive who owns the physical drive ; DISKETTE_DRV_TYPE - check compatability source/target drives ; CHECK_REDIRECTION - is device redirected? ; BUFFER_SIZE - finds start and end of buffer ; SETUP_CTRL_BREAK - setup the ctrl-break vector ; CHECK_SERVER - is server or redirector loaded? ; DATA AREAS: ; PSP - Contains the DOS command line parameters. ; WORKAREA - Temporary storage ; EXTERNAL REFERENCES: ; ROUTINES: ; SYSDISPMSG - Uses the MSG parm lists to construct the messages ; on STDOUT. ; SYSLOADMSG - Loads messages, makes them accessable. ; PARSER - Processes the DOS Command line, finds parms. ; DATA AREAS: ; DCOMPSM.SAL - Defines the control blocks that describe the messages ; DCOMPPAR.SAL - Defines the control blocks that describe the ; DOS Command line parameters. ; NOTES: ; This module should be processed with the SALUT preprocessor ; with the re-alignment not requested, as: ; SALUT COMPINIT,NUL ; To assemble these modules, the alphabetical or sequential ; ordering of segments may be used. ; For instructions as to how to LINK, see prolog for DISKCOMP. ;PROGRAM AUTHOR: Original written by: Jin K. ; 4.00 modifications by: Edwin M. K. ;****************** END OF SPECIFICATIONS ***************************** IF1 %OUT COMPONENT=DISKCOMP, MODULE=COMPINIT.SAL ENDIF ;REVISION HISTORY: ;DATE: 10-30-84 - chk_para routine added. Many parts are modified to ; permit DISKCOMP /1, DISKCOMP D: /1 cases. Restore diskbase ; before return to DOS when invalid DOS version occurs. ;DATE: 3-27-85 MAIN PARTS OF DISKCOMP PROGRAM HAS BEEN REWRITTEN ; TO USE NEW IOCTL FUNCTIONS 'READ', 'GET_DEVICE_PARAMETERS'. ; A000 - Change spelling of "LOCAL" to "LOCALX" to make MASM 3 happy. INCLUDE PATHMAC.INC ;AN013; INCLUDE DCMPMACR.INC ;(FORMERLY CALLED MACRO.DEF) CSEG SEGMENT PARA PUBLIC 'CODE' ; ;AC000; ASSUME CS:CSEG, DS:CSEG, ES:CSEG, SS:CSEG INCLUDE DISKCOMP.EQU NOOP EQU 90H ;NO-OPERTION INSTRUCTION, USED TO DELETE ;AN001; ; 386 SUPPORT ;AN001; ;$salut (4,2,9,41) ;**************************************************************************** ; * ; EXTERNAL VARIABLES * ; * ;**************************************************************************** EXTRN PARSER:NEAR ;DCOPYPAR.SAL - DRIVES SYS PARSER ;AN000; EXTRN RECOMMENDED_BYTES_SECTOR:WORD EXTRN S_OWNER_SAVED:BYTE EXTRN T_OWNER_SAVED:BYTE EXTRN ASCII_DRV1_ID:BYTE ;40H SOURCE DRIVE ID IN ASCII EXTRN ASCII_DRV2_ID:BYTE ;40H TARGET DRIVE ID IN ASCII EXTRN SUBLIST_78 :WORD ; ;AN000; EXTRN SUBLIST_11 :WORD ; ;AN000; EXTRN SUBLIST_15A :WORD ; ;AN000; EXTRN SUBLIST_15B :WORD ; ;AN000; EXTRN SUBLIST_15C :WORD ; ;AN000; EXTRN SUBLIST_17B :WORD ; ;AN000; EXTRN SUBLIST_17C :WORD ; ;AN000; EXTRN SUBLIST_17D :WORD ; ;AN000; EXTRN SUBLIST_PARSE:WORD ;PARSE ERROR XX - %0 ;AN004; EXTRN MSGNUM_INVALID_PARM:BYTE ;"INVALID PARAMETER" ;AC000; EXTRN MSGNUM_INVALID_DRV:BYTE ;"INVALID DRIVE SPECIFICATION" ;AC000; EXTRN MSGNUM_DRV_REDIRECTED:BYTE ;"INVALID, DRIVE REDIRECTED" ;AC000; EXTRN MSGNUM_NOT_COMPATIBLE:BYTE ;"DEVICE OR DISKETTE TYPES NOT COMPATIBLE";AC000; .XLIST ;EXTRN MSG_INVALID_DOS :BYTE ;MSG FOR DOS1.0 AND 1.1 .LIST EXTRN TRACK_TO_READ :BYTE EXTRN SIDE:BYTE EXTRN S_DRV_SECT_TRACK :BYTE ;SECT/TRACK EXTRN S_DRV_HEADS :BYTE ;# OF HEADS EXTRN S_DRV_TRACKS :BYTE ;# OF TRACKS EXTRN T_DRV_SECT_TRACK :BYTE EXTRN T_DRV_HEADS :BYTE EXTRN T_DRV_TRACKS :BYTE EXTRN COPY_TYPE :BYTE ;1 = 1-DRIVE COPY 2 = 2-DRIVE COPY EXTRN USER_OPTION :BYTE ;NO OPTION (-1) /1 (1), INVALID (9) EXTRN USER_OPTION_8 :BYTE ;NO OPTION (-1) /8 (1), INVALID (9) EXTRN BUFFER_BEGIN :WORD ;STARTING BUFFER @ FOR LOADING EXTRN BUFFER_END :WORD ;ENDING BUFFER @ FOR LOADING EXTRN START_BUFFER :WORD ;START OF BUFFER SPACE EXTRN MAIN_EXIT :WORD ;EXIT ADDRESS FOR CONTROL-BREAK EXTRN ORG_SOURCE_DRIVE:BYTE ;LOGICAL SOURCE DRIVE NUMBER EXTRN ORG_TARGET_DRIVE:BYTE ; TARGET EXTRN SOURCE_DRIVE:BYTE ;AS SPECIFIED BY USER PARMS, DR NUM ;AN000; EXTRN TARGET_DRIVE:BYTE ;AS SPECIFIED BY USER PARMS, DR NUM ;AN000; EXTRN IO_ERROR :BYTE EXTRN DS_IOCTL_DRV_PARM :BYTE ;PLACE HOLDER FOR DEFAULT SOURCE DRV PARM EXTRN DT_IOCTL_DRV_PARM :BYTE ;PLACE HOLDER FOR DEFAULT TARGET DRV PARM EXTRN DS_specialFunctions :BYTE ;AND THEIR CONTENTS EXTRN DT_specialFunctions :BYTE EXTRN DS_deviceType:BYTE EXTRN DT_deviceType:BYTE EXTRN DS_deviceAttributes :WORD EXTRN DT_deviceAttributes :WORD EXTRN DS_numberOfCylinders :WORD EXTRN DT_numberOfCylinders :WORD EXTRN DS_mediaType :BYTE EXTRN DT_mediaType :BYTE EXTRN DS_BPB_PTR :BYTE EXTRN DT_BPB_PTR :BYTE EXTRN MS_IOCTL_DRV_PARM :BYTE ;DRIVE PARM FROM SOURCE MEDIUM EXTRN MT_IOCTL_DRV_PARM :BYTE EXTRN PATCH_386:BYTE ;PATCH AREA, CHANGED TO NOOP IF NOT 386 ;AN001; EXTRN GENERIC_IOCTL :NEAR EXTRN SET_LOGICAL_DRIVE :NEAR ; $salut (4,24,28,41) MY_BPB STRUC CBYTE_SECT DW 0 ; 200H BYTES / SECTOR CSECT_CLUSTER DB 0 ; 2h SECTORS / CLUSTER CRESEV_SECT DW 0 ; 1h RESERVED SECTORS CFAT DB 0 ; 2h # OF FATS CROOTENTRY DW 0 ; 70h # OF ROOT ENTRIES CTOTSECT DW 0 ; 02D0h TOT. # OF SECT. ; INCL BOOT SECT, DIRS MEDIA_DESCRIP DB 0 ;0FDh MEDIA DISCRIPTOR CSECT_FAT DW 0 ; 2h SECTORS / FAT CSECT_TRACK DW 0 ; CHEAD DW 0 ; CHIDDEN_SECT DD 0 ; BIG_TOT_SECT DD 0 ; DB 6 DUP (0) ; MY_BPB ENDS ;USED TO CHECK FOR PRESENCE OF 386 MACHINE: BIOS_SYSTEM_DESCRIPTOR struc ;SYSTEM TYPE STRUC ;AN001; bios_SD_leng dw ? ;VECTOR LENGTH ;AN001; bios_SD_modelbyte db ? ;SYSTEM MODEL TYPE ;AN001; bios_SD_scnd_modelbyte db ? ; ;AN001; db ? ; ;AN001; bios_SD_featurebyte1 db ? ; ;AN001; db 4 dup (?) ; ;AN001; BIOS_SYSTEM_DESCRIPTOR ends ;END OF STRUC ;AN001; ;**************************************************************************** ; * ; VARIABLE DECLARATIONS * ; * ;**************************************************************************** DRIVE_VALID DW ? ;DRIVE VALIDITY BYTE DEFAULT_DRV DB ? ;DEFAULT DRIVE ID NUMBER_OF_DRV DB ? ;TOTAL # OF DISKT DRIVES ON THE SYS ;(NUMBER_OF_DRV = 0 ---> 1 DRIVE) ASCII_DRIVE_LETTER DB " :",0 PATHLABL COMPINIT ;AN013; HEADER ; ;AN000; ; $salut (4,9,15,41) ; ;AN000; ;############################################################################# ; INITIALIZATION ROUTINE - MAIN PROGRAM INIT PROC NEAR PUBLIC INIT ;MAKE ENTRY IN LINK MAP ;AN000; ;OUTPUT: DX = EXIT CODE, "FINE" ;############################################################################# MOV DRIVE_VALID,AX ;SAVE DRIVE VALIDITY BYTE CALL PC_386_CHK ;SEE IF THIS IS A 386 MACHINE ;AN001; ; REPLACE THE "FILL_SEG" IN THE SUBLIST MESSAGE CONTROL BLOCKS. ; BECAUSE THIS IS A .COM STYLE FILE, THESE SEGID VALUES CANNOT ; BE PROVIDED BY THE DOS SYSTEM LOADER, BUT MUST BE DYNAMICALLY ; PERFORMED AT EXECUTION TIME AS PART OF A .COM FILE'S OBLIGATION ; TO BE "SELF-RELOCATING". MOV AX,CS ;GET SEGID OF COMMON SEGMENT MOV SUBLIST_78.SUB_VALUE_SEG,AX ; ;AN000; MOV SUBLIST_11.SUB_VALUE_SEG,AX ; ;AN000; MOV SUBLIST_15A.SUB_VALUE_SEG,AX ; ;AN000; MOV SUBLIST_15B.SUB_VALUE_SEG,AX ; ;AN000; MOV SUBLIST_15C.SUB_VALUE_SEG,AX ; ;AN000; MOV SUBLIST_17B.SUB_VALUE_SEG,AX ; ;AN000; MOV SUBLIST_17C.SUB_VALUE_SEG,AX ; ;AN000; MOV SUBLIST_17D.SUB_VALUE_SEG,AX ; ;AN000; MOV SUBLIST_PARSE.SUB_VALUE_SEG,AX ; ;AN004; CALL SETUP_CTRL_BREAK ;STEALS CTRL_BREAK CLD ;CLEAR DIRECTION FLAG MOV DX,FINE ;ASSUME EVERYTHING IS FINE .XLIST ; CALL SCREENING ;CHECK DOS VERSION AND INPUT PARMS ; CMP DX,FINE ;IF FINE & DANDY ; JNE EXIT_INIT .LIST CALL PARSER ;LOOK AT DOS COMMAND LINE ;AN000; CMP DX,FINE ;IF ALL OK ;AN000; ; $IF E ; ;AN000; JNE $$IF1 CALL SOURCE_TARGET_DRV ;DETERMINE SOURCE AND TARGET DRV ; $ENDIF ; ;AN000; $$IF1: CMP DX,FINE ;IF STILL FINE AND DANDY ;AN000; ; $IF E ; ;AN000; JNE $$IF3 CALL TEST_DRIVE_VALIDITY CMP DX,FINE ; $IF E ; ;AN000; JNE $$IF4 CALL DISKETTE_DRV_TYPE ;SOURCE & TARGET DRIVE TYPES CMP DX,FINE ;IF FINE & DANDY ; $IF E ; ;AN000; JNE $$IF5 CALL BUFFER_SIZE ;GET BUFFER SIZE FOR COPYING ; $ENDIF ; ;AN000; $$IF5: ; $ENDIF ; ;AN000; $$IF4: ; $ENDIF ; ;AN000; $$IF3: RET ;RETURN TO CALLER INIT ENDP ;END INITIALLIZATION PROGRAM ;############################################################################# .XLIST ; HEADER ;****************************************************************************** ; SUBROUTINE NAME : SCREENING - CHECKS THE FOLLOWING: * ; - DOS VERSION * ; - DRIVE ID VALIDITY * ; - FILE NAME ENTERED BY MISTAKE? * ; INPUT : BL : DRIVE VALIDITY BYTE * ; OUTPUT : DX : FINE - NO ERROR * ; (OTHERS)- ERROR MSG OFFSET * ;****************************************************************************** ;SCREENING PROC NEAR ;CHECK DOS VERSION: ; MOV AH,DOSVER_FUNC ;SEE IF CORRECT DOS VERSION ; INT 21H ;FUNCTION CALL (AL <- DOS VERSION) ;; XCHG AH,AL ;AH=MAJOR VER, AL=MINOR VER ; CMP AX,expected_version ;IF DOS MAJOR VERSION LESS THAN 2.0 ; $IF NE ;THEN ISSUE ERROR MSG ; MOV DX,OFFSET MSG_INVALID_DOS ; MOV AH,PRINT_FUNC ;USE PRINT FUNCTION TO TELL USER ; INT 21H ;THAT HE IS USING THE OLD VERSION ; INT 20H ; $ELSE ;VERSION OK ; CALL CHK_PARA ;GENERAL SYNTAX CHECK ; $ENDIF ;END VERSION TEST ; RET ;SCREENING ENDP ; HEADER ;;************************************************************************** ;CHK_PARA PROC NEAR ;; CHECK SYNTAX OF THE ENTERED PARAMETERS * ;; ALSO, DETERMINE THE USER OPTION "/1" AND/OR "/8" IS ENTERED. * ;; INPUT: DX = FINE * ;; IF /1 HAS BEEN ENTERED, THE VARIABLE USER_OPTION = OPTION_1 * ;; ELSE USER_OPTION = NO_OPTION. * ;; IF /8 HAS BEEN ENTERED, THE USER_OPTION_8 WILL BE ON * ;; OUTPUT: DX = FINE - NO ERROR * ;; OTHERWISE DX POINTS TO ERROR MSG * ;;************************************************************************** ; PUSH CX ; MOV USER_OPTION, NO_OPTION ;ASSUME NO /1 IS ENTERED. ; MOV USER_OPTION_8, OFF ;ASSUME /8 IS NOT ENTERED. ; XOR CX, CX ; MOV CL, BYTE PTR DS:BEGIN_UNFORM_AREA ;GET # OF CHR ; CMP CL, 0 ; JZ CHK_PARA_EXIT ; CLD ;CLEAR DIRECTION ; MOV DI, BEGIN_UNFORM_AREA+2 ;STARTING POINT OF PARA ; DEC CL ;TO IGNORE LAST CHR (0DH) ; CALL SKIP_BLANKS ;SKIP BLANKS, IF ANY. THE POINTER WILL POINT TO THE NEXT NON_BLANK CHR ; JZ CHK_PARA_EXIT ;ONLY BLANKS ARE ENTERED. ; CALL CHK_SLASH_ONE ;IS NEXT WORD /1 OR /8 ? ; JNC SLASH_ONE ;YES ; CALL CHK_DRV_SPEC ;IS IT A DRIVE SPECIFICATION LIKE d: ? ; JC INVALID_PARA ;IF NOT, THEN ERROR ; JZ CHK_PARA_EXIT ;NO MORE CHR? THEN, OK. (EX. DISKCOMP D:) ; CALL CHK_SLASH_ONE ;IS NEXT WORD /1 OR /8 ? ; JNC SLASH_ONE ;YES.(EX. DISKCOMP D:/1) ; CALL CHK_BLANK ;IF NOT, NEXT CHR SHOULD BE A BLANK. ; JC INVALID_PARA ;OTHERWISE, ERROR. ; CALL SKIP_BLANKS ;SKIP BLANKS, IF ANY. ; JZ CHK_PARA_EXIT ;(EX. DISKCOMP D: ) ; CALL CHK_SLASH_ONE ;IS IT /1 OR /8 ? ; JNC SLASH_ONE ;YES. (EX. DISKCOMP D: /1) ; CALL CHK_DRV_SPEC ;IF NOT /1 OR /8, THEN IS IT A DRV SPEC? ; JC INVALID_PARA ;OTHERWISE, ERROR. ; CALL SKIP_BLANKS ;SKIP BLANKS, IF ANY. ; JZ CHK_PARA_EXIT ;NO MORE CHR. (EX. DISKCOMP D: D:) ; CALL CHK_SLASH_ONE ;OTHERWISE, /1 AND/OR /8 SHOULD BE FOLLOWED. ; JNC SLASH_ONE ;YES, /1 OR /8. JMP TO SLASH_ONE ; JMP INVALID_PARA ;PARAMETER ERROR. ;SLASH_ONE: ;YES, FOUND EITHER OF /1 OR /8. ; CALL SKIP_BLANKS ;/1 SHOULD BE END OF PARAMETERS, OR ONLY BLANKS CAN FOLLOW. ; JZ CHK_PARA_EXIT ;NO MORE CHR? THEN OK. ; CMP USER_OPTION, OPTION_1 ;WAS IT /1? ; JZ SLASH_8 ;THEN CHECK WHETHER NEXT IS /8. ; CALL CHK_SLASH_ONE ;OTHERWISE, IT WAS /8. NOW CHECK /1. ; JC INVALID_PARA ;NOT FOUND, ERROR ; CMP USER_OPTION, OPTION_1 ; JZ CHK_PRE_EXIT ;YES, IT IS /1 ; JMP INVALID_PARA ;OTHERWISE, FOUND /8 AGAIN. ERROR ;SLASH_8: ; CALL CHK_SLASH_ONE ;CHECK IT IS /8 ; JC INVALID_PARA ;NOT FOUND? ERROR ; CMP USER_OPTION_8, ON ; JZ CHK_PRE_EXIT ;YES. IT IS /8 ; JMP INVALID_PARA ;OTHERWISE, FOUND /1 AGAIN. ERROR ;CHK_PRE_EXIT: ; CALL SKIP_BLANKS ;SKIP BLANKS IF ANY. ; JZ CHK_PARA_EXIT ;THERE SHOULD NOT BE ANY MORE PARAMETER. ;INVALID_PARA: ; MOV DX,OFFSET MSG_INVALID_PARM_PTR ;WRONG PARM ENTERED MSG ;CHK_PARA_EXIT: ; POP CX ; ; RET ;CHK_PARA ENDP ; HEADER ;*************************************************************************** ;SKIP_BLANKS PROC NEAR ; ** SKIP BLANKS OR TABS, IF ANY, IN THE PARAMETER STRING. * ; INPUT: ES:DI POINTS TO THE CURRENT CHR. * ; CX - # OF REMAINING CHR IN THE STRING. * ; OUTPUT: ES:DI POINT TO THE NEXT NON_BLANK CHR. * ; CX IS ADJUSTED ACCORINGLY. * ; IF THE CURRENT CHR IS NOT A BLANK, THEN DI, CX VALUE NOT CHANGED.* ; IF CX = 0, THEN ZERO FLAG WILL BE SET AND EXIT THIS PROC. * ;*************************************************************************** ;SKIP_AGAIN: ; MOV AL, 20H ;20H=BLANK ; CLD ;CLEAR DIRECTION ; REPE SCASB ; JZ SK_BL_1 ;IF NOT FOUND A NON_BLANK CHR YET, AND CX=0, EXIT THIS ROUTINE. ; DEC DI ;OTHERWISE, RESTORE DI TO THE NON_BLANK POSITION. ; INC CX ; AND RESTORE CX TO WHERE IT WAS AT NON_BLANK CHR ; ;(IF FOUND A NON_BLANK CHR, ZERO FLAG WOULD NOT BE SET) ; MOV AL, ES:BYTE PTR [DI] ; CMP AL, 09H ;09H=TAB ; JNZ SK_BL_1 ;IF THE NON_BLANK CHR IS NOT A TAB THEN EXIT ; INC DI ;ELSE TRY SKIP AGAIN. ; DEC CX ; JMP SKIP_AGAIN ;SK_BL_1: ; RET ;SKIP_BLANKS ENDP ; HEADER ;;*************************************************************************** ;CHK_SLASH_ONE PROC NEAR ; ** CHECK CURRENT CHR IS / FOLLOWED BY 1. * ; INPUT: ES:DI POINTS TO THE CURRENT CHR TO BE CHECKED. * ; CX REPRESENTS THE # OF CHR'S IN THE STRING. * ; OUTPUT: FOUND - DI POINTS TO THE NEXT CHR. CX CHANGED ACCORDINGLY. * ; IF THIS HAD BEEN A LAST WORD, ZERO FLAG WILL BE SET. * ; NOT FOUND - CARRY IS SET. DI, CX UNCHANGED. * ;*************************************************************************** ; CLC ;CLEAR CARRY FLAG ; CMP CX, 2 ;# OF CHR IN THE STRING. ; JL CK_SL_0 ;IF LESS THAN 2, THEN SET CARRY AND EXIT. ; MOV AX, ES:WORD PTR [DI] ;GET CURRENT WORD IN AX ; CMP AX, '1/' ;IS IT /1 ? ; JZ CK_SL_1 ;YES. SET USER_OPTION ; CMP AX, '8/' ;IS IT /8 THEN ? ; JZ CK_SL_2 ;YES. SET USER_OPTION_8 ;CK_SL_0: ; STC ;OTHERWISE, NOT FOUND. SET CARRY ; JMP CK_SL_4 ; AND RETURN ;CK_SL_1: ; MOV USER_OPTION, OPTION_1 ; JMP CK_SL_3 ;CK_SL_2: ; MOV USER_OPTION_8, ON ;CK_SL_3: ;ADJUST CX, DI TO THE NEXT CHR. ; INC DI ; INC DI ; DEC CX ; DEC CX ; CMP CX, 0 ;SET ZERO FLAG IF NO MORE CHR. ;CK_SL_4: ; RET ;CHK_SLASH_ONE ENDP ; HEADER ;;*************************************************************************** ;CHK_DRV_SPEC PROC NEAR ; ** CHECK CURRENT CHR IS ALPHA CHR FOLLOWED BY COLON. * ; INPUT: ES:DI POINTS TO THE CURRENT CHR TO BE CHECKED. * ; CX -- # OF CHR IN THE STRING. * ; OUTPUT: FOUND - DI POINTS TO THE NEXT CHR. CX ADJUSTED ACCORDINGLY. * ; IF THIS HAD BEEN A LAST WORD, ZERO FLAG WILL BE SET. * ; NOT FOUND - CARRY IS SET. DI, CX UNCHANGED. * ;*************************************************************************** ; CLC ;CLEAR CARRY ; CMP CX, 2 ;# OF CHR REMAINING IN THE STRING. ; JL CK_DR_1 ;IF LESS THAN 2, THEN NOT FOUND - SET CARRY AND EXIT. ; MOV AL, ES:BYTE PTR [DI] ;GET CURRENT CHR ; AND AL, 11011111B ;CHANGE IT TO UPPER_CASE CHR. ; CMP AL, 'A' ; JB CK_DR_1 ;LESS THAN 'A', THEN NOT FOUND. ; CMP AL, 'Z' ; JA CK_DR_1 ;ABOVE 'Z', THEN NOT FOUND. ; MOV AL, ES:BYTE PTR [DI+1] ;LOOK AHEAD THE FOLLOWING CHR. ; CMP AL, ':' ;SHOULD BE A COLON. ; JNZ CK_DR_1 ;NOT FOUND. ; INC DI ;FOUND. ADJUST CX, DI TO THE NEXT CHR. ; INC DI ; DEC CX ; DEC CX ; CMP CX, 0 ;IF NO MORE CHR, THAN SET THE ZERO FLAG. ; JMP CK_DR_2 ;CK_DR_1: ; STC ;SET CARRY ;CK_DR_2: ; RET ;CHK_DRV_SPEC ENDP ; HEADER ;;*************************************************************************** ;CHK_BLANK PROC NEAR ;; ** CHECK THE CURRENT CHR IS A BLANK OR A TAB. * ;; INPUT: ES:DI POINTS TO THE CURRENT CHR. * ;; CX - # OF CHR IN THE STRING. * ;; OUTPUT: FOUND - DI MOVES TO THE NEXT CHR. CX DECREASES BY 1. * ;; NOT FOUND - CARRY IS SET. DI, CX UNCHANGED. * ;;*************************************************************************** ; ; CLC ;CLEAR CARRY ; CMP CX, 1 ;IF LESS THAN 1, NOT FOUND. ; JL CK_BL_0 ;SET CARRY AND EXIT ; MOV AL, ES:BYTE PTR [DI] ;GET CURRENT CHR ; CMP AL, 020H ;020H=BLANK CHR ; JZ CK_BL_1 ;FOUND ; CMP AL, 09H ;09H=TAB CHR ; JZ CK_BL_1 ;FOUND ;CK_BL_0: ; STC ;NOT FOUND. SET CARRY ; JMP CK_BL_2 ;CK_BL_1: ; INC DI ;FOUND. ADJUST DI, CX ; DEC CX ;CK_BL_2: ; RET ;CHK_BLANK ENDP .LIST HEADER ; QUERIES THE BIOS TO DETERMINE WHAT TYPE OF ; MACHINE WE ARE ON. WE ARE LOOKING FOR A 386. ; THIS WILL BE USED TO DETERMINE IF A DOUBLE WORD MOVE ; IS TO BE PERFORMED. ; ; INPUTS : NONE ; ; OUTPUTS : IF A 386 NOT PRESENT, CODE IS ; *** P A T C H E D *** ; TO NO-OP THE SUPPORT FOR THE DOUBLE WORD MOVE ;========================================================================= PC_386_CHK PROC NEAR ;DETERMINE MACHINE TYPE ;AN001; PUSH AX ;SAVE AFFECTED REGS ;AN001; PUSH BX ; ;AN001; PUSH ES ; ;AN001; MOV AH,0C0H ;RETURN SYSTEM CONFIGURATION ;AN001; INT 15H ;ES:[BX] POINTS TO BIOS ;AN001; ; SYSTEM DESCRIPTOR ASSUME ES:NOTHING ;AN001; ; $IF C,OR ;IF NOT A GOOD RETURN, OR... ;AN001; JC $$LL9 CMP AH,0 ;IS IT NEW FORMAT FOR CONFIG. ;AN001; ; $IF NE,OR ;NO, OR... ;AN001; JNE $$LL9 CMP ES:[BX].BIOS_SD_MODELBYTE,0F8H ;CHECK MODEL ;AN001; ; $IF NE ;IF IT IS NOT A 386 MACHINE? ;AN001; JE $$IF9 $$LL9: ;PATCH OUT THE 386 CODE MOV AL,NOOP ;WITH A NO-OP INSTRUCTION ;AN001; MOV PATCH_386,AL ; ;AN001; MOV PATCH_386+1,AL ; ;AN001; MOV PATCH_386+2,AL ; ;AN001; ; $ENDIF ; ;AN001; $$IF9: POP ES ;RESTORE REGS. ;AN001; ASSUME ES:CSEG ;BACK TO USUAL ;AN001; POP BX ; ;AN001; POP AX ; ;AN001; RET ; ;AN001; PC_386_CHK ENDP ; ;AN001; HEADER ; ;AN000; ;****************************************************************************** ; SUBROUTINE NAME : SOURCE_TARGET_DRV DETERMINES SOURCE & TARGET DRIVES & * ; CONVERT THEM FROM DOS TO BIOS VALUE * ; INPUT : SOURCE_DRIVE & TARGET_DRIVE HAVE DOS DRIVE ID'S: * ; 0 = DEFAULT 1 = DRV A ETC. * ; * ; OUTPUT : ORG_SOURCE_DRIVE 1 = DRIVE A 2 = DRIVE B ETC. * ; : ORG_TARGET_DRIVE 1 = DRIVE A 2 = DRIVE B ETC. * ; * ; : COPY_TYPE 1 = SINGLE DRV COPY, 2 = 2 DRIVE COPY * ; : DX : FINE - NO ERROR * ;****************************************************************************** SOURCE_TARGET_DRV PROC NEAR PUBLIC SOURCE_TARGET_DRV ;MAKE ENTRY IN LINK MAP ;AN000; ;GET CURRENT DEFAULT DRIVE MOV AH,CURRENTDRV_FUNC ;FUNCTION CALL (19H) ;(AL <- CURRENT DEFAULT DRV INT 21H ;0 = A, 1 = B, ETC) MOV DEFAULT_DRV,AL ;SAVE IT CMP SOURCE_DRIVE,ZERO ;FIRST DRV ENTERED? ;AC000; ; $IF E ;NO DRIVE LETTER ENTERED JNE $$IF11 MOV CH, DEFAULT_DRV ;SET SOURCE, TARGET DRIVE TO INC CH MOV ORG_SOURCE_DRIVE, CH ;DEFAULT DRIVE MOV CL, CH MOV ORG_TARGET_DRIVE, CL ; $ELSE JMP SHORT $$EN11 $$IF11: MOV CH,SOURCE_DRIVE ;GET SOURCE DRIVE FROM SPECIFIED PARM ;AC000; MOV ORG_SOURCE_DRIVE, CH CMP TARGET_DRIVE,ZERO ;WAS A SECOND DRIVE SPECIFIED ;AC000; ; $IF E ;TARGET DRIVE IS DEFAULT JNE $$IF13 MOV CL, DEFAULT_DRV INC CL ;MAKE IT A LOGICAL DRIVE NUMBER MOV ORG_TARGET_DRIVE, CL ; $ELSE JMP SHORT $$EN13 $$IF13: MOV CL, TARGET_DRIVE ;USE USER SPECIFIED TARGET DRIVE ;AC000; MOV ORG_TARGET_DRIVE, CL ; $ENDIF $$EN13: ; $ENDIF $$EN11: ADD ASCII_DRV1_ID,CH ;SETUP DRIVE ID ALPHABET IN THE ADD ASCII_DRV2_ID,CL ;MESSAGES RET SOURCE_TARGET_DRV ENDP HEADER ; ;AN000; ;****************************************************************************** ; SUBROUTINE NAME : TEST_DRIVE_VALIDITY--MAKE SURE SOURCE AND TARGET DRIVES * ; SPECIFIED BY USER ARE VALID FOR DISKCOPY * ; * ; INPUT : ORG_SOURCE_DRIVE:BYTE, ORG_TARGET_DRIVE:BYTE * ; * ; OUTPUT : DX=FILE IF DRIVES ARE VALID ELSE DX CONTAINS MESSAGE PTR * ;****************************************************************************** TEST_DRIVE_VALIDITY PROC NEAR PUBLIC TEST_DRIVE_VALIDITY ;MAKE ENTRY IN LINK MAP ;AN000; CALL DOS_DRIVE_VALIDITY CMP DX,FINE ; $IF E,AND ; ;AC000; JNE $$IF17 MOV BL,ORG_SOURCE_DRIVE CALL CHECK_REDIRECTION CMP DX,FINE ; $IF E,AND ; ;AC000; JNE $$IF17 MOV BL,ORG_TARGET_DRIVE CALL CHECK_REDIRECTION CMP DX,FINE ; $IF E,AND ; ;AC000; JNE $$IF17 MOV BL,ORG_SOURCE_DRIVE CALL CHECK_SERVER CMP DX,FINE ; $IF E,AND ; ;AC000; JNE $$IF17 MOV BL,ORG_TARGET_DRIVE CALL CHECK_SERVER CMP DX,FINE ; $IF E,AND ; ;AC000; JNE $$IF17 CALL TEST_REMOVABLE CMP DX,FINE ; $IF E ; ;AC000; JNE $$IF17 CALL CHK_SINGLE_DRV_OP ;CHECK IF IT IS ; ONE PHYSICAL DRIVE OPERATION ; $ENDIF ; ;AC000; $$IF17: RET TEST_DRIVE_VALIDITY ENDP HEADER ;****************************************************************************** ; SUBROUTINE NAME : DOS_DRIVE_VALIDITY -- CHEKC DOS DRIVE VALIDITY BYTE * ; * ; INPUT : DRIVE_VALID:BYTE * ; THIS IS THE ORIGINAL VALUE PRESENTED IN AX BY DOS LOADER * ; * ; OUTPUT : DX=FILE IF DRIVES ARE VALID ELSE DX CONTAINS MESSAGE PTR * ;****************************************************************************** DOS_DRIVE_VALIDITY PROC NEAR PUBLIC DOS_DRIVE_VALIDITY ;MAKE ENTRY IN LINK MAP ;AN000; CMP DRIVE_VALID,0 ;SEE IF DRIVES ARE VALID DOS DEVICE ; $IF NE JE $$IF19 MOV DX,OFFSET MSGNUM_INVALID_DRV ;AC000; ; $ENDIF $$IF19: RET DOS_DRIVE_VALIDITY ENDP HEADER ;****************************************************************************** ; SUBROUTINE NAME : TEST_REMOVABLE -- CHECK IF DRIVES SPECIFED ARE REMOVABLE * ; * ; INPUT : SOURCE_DRIVE:BYTE, TARGET_DRIVE:BYTE * ; * ; OUTPUT : DX=FILE IF DRIVES ARE VALID ELSE DX CONTAINS MESSAGE PTR * ;****************************************************************************** TEST_REMOVABLE PROC NEAR PUBLIC TEST_REMOVABLE ;MAKE ENTRY IN LINK MAP ;AN000; MOV BL,ORG_SOURCE_DRIVE ;GET PARM 1 DRIVE ID MOV AX,DRIVE_CHECK ;CHECK FOR REMOVABLE DRIVE INT 21H ;IOCTL CALL ; $IF NC ;IF DRIVE ID IS WITHIN RANGE JC $$IF21 CMP AX,REMOVABLE ;THEN IF SOURCE DRIVE IS FIXED ; $IF NE ; THEN JE $$IF22 MOV DX,OFFSET MSGNUM_INVALID_DRV ;GENERATE ;AC000; ; HARD DRIVE ERROR MESSAGE ; $ELSE ;ELSE, SRC IS REMOVABLE; JMP SHORT $$EN22 $$IF22: MOV BL,ORG_TARGET_DRIVE ;NOW GO CHECK TARGET MOV AX,DRIVE_CHECK ;CHECK FOR REMOVABLE DRIVE INT 21H ;IOCTL CALL ; $IF NC ;IF DRV WITHIN RANGE JC $$IF24 CMP AX,REMOVABLE ;THEN TGT DRV IS FIXED ; $IF NE ; THEN JE $$IF25 MOV DX,OFFSET MSGNUM_INVALID_DRV ;GENERATE ;AC000; ; HARD DRV ERROR MSG ; $ENDIF ;END TEST IF TGT DRV IS FIXED $$IF25: ; $ELSE ;TGT DRV OUT OF RANGE. EX. DRIVE X: JMP SHORT $$EN24 $$IF24: MOV DX,OFFSET MSGNUM_INVALID_DRV ;GENERATE ;AC000; ; HARD DRV ERROR MSG ; $ENDIF ;END TEST IF TGT WITHIN RANGE $$EN24: ; $ENDIF ;END IF SRC IS REMOVABLE $$EN22: ; $ELSE ;ELSE, SRC DRV OUT OF RANGE JMP SHORT $$EN21 $$IF21: MOV DX,OFFSET MSGNUM_INVALID_DRV ;PRINT ERROR MSG ;AC000; ; $ENDIF ;END TEST IF SRC DRV WITHIN RANGE $$EN21: RET TEST_REMOVABLE ENDP HEADER ;****************************************************************************** ; SUBROUTINE NAME : CHK_SINGLE_DRV_OP * ; * ; INPUT : ORG_SOURCE_DRIVE - LOGICAL DRIVE NUMBER * ; ORG_TARGET_DRIVE * ; * ; OUTPUT : COPY_TYPE WILL BE SET TO ONE OR TWO DEPENDING ON THE * ; TEST RESULT. IF IT IS A SINGLE DRIVE COPY, THEN * ; TARGET DRIVE LETTER WILL BE CHANGED TO THAT OF SOURCE. * ; THE OWNERSHIP OF THE SOURCE AND TARGET DRIVE LETTER * ; MIGHT HAVE BEEN CHANGED. * ; SO, BEFORE EXIT TO DOS, THEY SHOULD BE RESET TO THE SAVED* ; ONE USING S_OWNER_SAVED AND T_OWNER_SAVED UNLESS THEY * ; ARE EQUAL TO 0. (0 MEANS ONLY ONE DRIVE LETTER ASSIGNED.)* ; ASCII_DRV1_ID, ASCII_DRV2_ID MAY BE CHANGED ACCORDINGLY. * ;****************************************************************************** CHK_SINGLE_DRV_OP PROC NEAR PUBLIC CHK_SINGLE_DRV_OP ;MAKE ENTRY IN LINK MAP ;AN000; PUSH AX MOV BL,ORG_SOURCE_DRIVE CALL GET_LOGICAL_DRIVE MOV S_OWNER_SAVED, AL ;SAVE CURRENT OWNER DRIVE LETTER. MOV BL, ORG_TARGET_DRIVE CALL GET_LOGICAL_DRIVE MOV T_OWNER_SAVED, AL ;SAVE CURRENT OWNER MOV BL, ORG_SOURCE_DRIVE CALL SET_LOGICAL_DRIVE MOV BL, ORG_TARGET_DRIVE CALL SET_LOGICAL_DRIVE MOV BL, ORG_SOURCE_DRIVE CALL GET_LOGICAL_DRIVE ;CHECK IF SOURCE DRIVE OWNERSHIP HAS NOT BEEN CHAGNED? CMP AL, ORG_SOURCE_DRIVE ; $IF NE ;IF IT HAS BEEN CHANGED TO TARGET, THEN A SINGLE DRIVE COMPARE. JE $$IF32 MOV COPY_TYPE, ONE MOV BL, ORG_SOURCE_DRIVE MOV ORG_TARGET_DRIVE, BL ;SET TARGET DRV LETTER TO THE SOURCE. MOV BL, ASCII_DRV1_ID MOV ASCII_DRV2_ID, BL MOV BL, ORG_SOURCE_DRIVE CALL SET_LOGICAL_DRIVE ;SET THE OWNER BACK TO SOURCE DRV LETTER ; $ELSE JMP SHORT $$EN32 $$IF32: CMP AL, ORG_TARGET_DRIVE ; SOURCE DRV LETTER = TARGET DRV LETTER CASE, FOR EX. DISKCOMP A: A: ; $IF E JNE $$IF34 MOV COPY_TYPE, ONE ; $ELSE JMP SHORT $$EN34 $$IF34: MOV COPY_TYPE, TWO ; $ENDIF $$EN34: ; $ENDIF $$EN32: POP AX RET CHK_SINGLE_DRV_OP ENDP HEADER ;****************************************************************************** GET_LOGICAL_DRIVE PROC NEAR PUBLIC GET_LOGICAL_DRIVE ;MAKE ENTRY IN LINK MAP ;AN000; ; *** GET THE LOGICAL DRIVE NUMBER WHO HAS THE OWNERSHIP OF THE PHYSICAL ; DRIVE. ; INPUT: BL = DRIVE NUMBER (0=DEFAULT, 1=A, 2=B...) ; OUTPUT: AL = DRIVE NUMBER (0= ONLY ONE DRIVE LETTER ASSIGNED TO THE ; BLOCK DEVICE. OTHERWISE, 1=A, 2=B...) ; ;****************************************************************************** MOV AH, 44H MOV AL, 0EH ; GET THE OWNER OF LOGICAL DRIVE NUMBER INT 21H CMP AL, 0 ;ONLY ONE DRIVE LETTER ASSIGNED? ; $IF E JNE $$IF38 MOV AL, BL ;THEN SET IT TO THE INPUT DRIVE LETTER ; $ENDIF $$IF38: RET GET_LOGICAL_DRIVE ENDP HEADER ;****************************************************************************** ; SUBROUTINE NAME : DISKETTE_DRV_TYPE DOES THE FOLLOWING: * ; - GETS SOURCE, TARGET DRIVE INFORMATIONS * ; - CHECK IF IT IS A REMOVABLE DRIVE. * ; INPUT : SOURCE_DRIVE & TARGET_DRIVE * ; 1 = DRIVE A 2 = DRIVE B, ETC. * ; * ; OUTPUT : DX : FINE - NO ERROR * ; (OTHERS)- ERROR MSG OFFSET * ;****************************************************************************** DISKETTE_DRV_TYPE PROC NEAR PUBLIC DISKETTE_DRV_TYPE ;MAKE ENTRY IN LINK MAP ;AN000; PUSH AX XOR BX,BX MOV BL, ORG_SOURCE_DRIVE MOV CL, GETDEVPARM ;=60h MOV DX, OFFSET DS_IOCTL_DRV_PARM ;POINTER TO THE CONTROL STRING CALL GENERIC_IOCTL ;GET DEVICE PARM. TEST DS_deviceAttributes, 0001h ;CHECK REMOVABLE. 0001 = NOT REMOVABLE ; $IF E,AND ;NO, CONTINUE ;AC000; JNE $$IF40 MOV AX, DS_numberOfCylinders ;CURRENTLY IGNORE AH. ASSUME LESS ; THAN TWO BYTES MOV S_DRV_TRACKS, AL MOV BX, OFFSET DS_BPB_PTR MOV AX, [BX].CHead MOV S_DRV_HEADS, AL MOV AX, [BX].CSECT_TRACK MOV S_DRV_SECT_TRACK, AL MOV AX, [BX].CBYTE_SECT ;RECOMMENDED BYTES/SECTOR MOV RECOMMENDED_BYTES_SECTOR, AX XOR BX,BX MOV BL, ORG_TARGET_DRIVE MOV CL, GETDEVPARM MOV DX, OFFSET DT_IOCTL_DRV_PARM CALL GENERIC_IOCTL TEST DT_deviceAttributes, 0001h ; $IF Z ;TARGET IS NOT FIXED DISK, OK ;AC000; JNZ $$IF40 MOV AX, DT_numberOfCylinders MOV T_DRV_TRACKS, AL MOV BX, OFFSET DT_BPB_PTR MOV AX, [BX].CHead MOV T_DRV_HEADS, AL MOV AX, [BX].CSECT_TRACK MOV T_DRV_SECT_TRACK, AL ;*** CHECK DEVICE COMPATIBILITY MOV DX, FINE ;GUESS, ALL WILL BE OK ; DX MAY BE CHANGED TO REFLECT ERROR CMP DS_deviceType, DRV_720 ;0 - 48 TPI, 5.25", 96 TPI, ; 5.25", 2 - 720kb, 3.5" ; $IF E ;WILL ONLY ALLOW DISKCOPY BETWEEN ;AC000; JNE $$IF41 ; 720KB, 3.5 SOURCE, TARGET CMP DT_deviceType, DRV_720 ;target = 720KB also? ; $IF NE ; ;AC000; JE $$IF42 MOV DX, OFFSET MSGNUM_NOT_COMPATIBLE ; ;AC000; ; $ENDIF ; ;AC000; $$IF42: ; $ELSE ;SINCE SOURCE NOT 720 ;AC000; JMP SHORT $$EN41 $$IF41: CMP DT_deviceType, DRV_720 ;SOURCE IS NOT 720kb, ; IS TARGET 720? ; $IF E ;IF SO, THEN ;AC000; JNE $$IF45 ;DDT IS NOT COMPATIBLE MOV DX, OFFSET MSGNUM_NOT_COMPATIBLE ; ;AC000; ; $ENDIF ; ;AC000; $$IF45: ; $ENDIF ; ;AC000; $$EN41: ; $ELSE ;SINCE SOURCE IS FIXED DISK, ERROR ;AC000; JMP SHORT $$EN40 $$IF40: MOV DX, OFFSET MSGNUM_INVALID_DRV ;ISSUE INVALID DRV MSG ;AC000; ; $ENDIF ; ;AC000; $$EN40: POP AX RET DISKETTE_DRV_TYPE ENDP HEADER ;****************************************************************************** ; SUBROUTINE NAME : CHECK_REDIRECTION FIND OUT IF DEVICE IS REDIRECTED * ; IF IT IS, GENERATE ERROR MSG & EXIT * ; INPUT : BL - DRIVE TO BE TESTED * ; : AL : CURRENT DEFAULT DRIV * ; * ; OUTPUT : DX = LOCAL_DRV (-1) * ; = DIRECTED ( ERROR MSG OFFSET) * ; = INVALID_DRIVE (ERROR MSG OFFSET) * ;****************************************************************************** CHECK_REDIRECTION PROC NEAR PUBLIC CHECK_REDIRECTION ;MAKE ENTRY IN LINK MAP ;AN000; PUSH AX ;SAVE REGISTERS PUSH BX PUSH CX MOV CX,DX ;SAVE RET TEMPORARILY MOV AH,IOCTL_FUNC ;GET IOCTL FUNTION & MOV AL,REDIRECTED_FUNC ;IOCTL SUB-FUNCTION ******CHECK*** INT 21H ;AND GO FIND OUT IF IT'S LOCAL ; $IF C JNC $$IF50 MOV CX,OFFSET MSGNUM_INVALID_DRV ;REDIR INVALID ;AC000; ; $ELSE JMP SHORT $$EN50 $$IF50: TEST DX,REMOTE_DRV ;IF DRIVE IS REDIRECTED ; $IF NZ JZ $$IF52 MOV CX,OFFSET MSGNUM_DRV_REDIRECTED ; ;AC000; ; $ENDIF $$IF52: ; $ENDIF $$EN50: MOV DX,CX ;GET ERROR MSG @ POP CX ;RESTORE REGISTERS POP BX POP AX RET ;RETURN TO CALLER CHECK_REDIRECTION ENDP HEADER ;****************************************************************************** ; SUBROUTINE NAME : BUFFER_SIZE DETERMINES WHERE BUFFER STARTS & ENDS * ; INPUT : NONE * ; * ; OUTPUT : BUFFER_BEGIN ADDRESS * ; : BUFFER_END ADDRESS * ; : START_BUFFER ADDRESS ;****************************************************************************** BUFFER_SIZE PROC NEAR PUBLIC BUFFER_SIZE ;MAKE ENTRY IN LINK MAP ;AN000; PUSH AX ;SAVE REGISTERS PUSH BX PUSH CX MOV BX,OFFSET init ;GET ADDR OF INIT+1024 AS A FREE MEMORY add bx, 1024 ;(OFFSET FROM CS, IN BYTES) MOV CL,4 ;CONVERT OFFSET INTO SEGMT BY DIVIDING SHR BX,CL ;IT BY 16 MOV AX,CS ;CS + OFFSET => INIT @ IN SEGMENT ADD BX,AX ;WHERE BUFFER CAN START ;NEED TO START AT A NEW SECTOR ==> AND BL,CLEAR_SEGMENT ;TRUNCATE TO PREVIOUS 512 BYTE BOUNDRY ;(GET PREVIOUS SECTOR NUMBER) ADD BX,20H ;THEN, ADVANCE TO THE BEGINNING OF ;NEXT SECTOR (SINCE PART OF PREVIOUS ;SECTOR WAS USED) MOV BUFFER_BEGIN,BX ;SAVE OUR BUFFER START SEGMENT ADDR MOV START_BUFFER,BX ;SAVE IT AGAIN ELSEWHERE ;(AT THE BEGINNING OF A SECTOR WITH ;SEGMENT BITS CLEARED) MOV BX,DS:TWO ;GET ADDR WHERE BUFFER ENDS MOV BUFFER_END,BX ;(TOP OF MEMORY, OFFSET 2 IN PSP) POP CX ;RESTORE REGISTERS POP BX POP AX RET ;RETURN TO CALLER BUFFER_SIZE ENDP HEADER ;****************************************************************************** SETUP_CTRL_BREAK PROC NEAR ;SETUP CTRL-BREAK VECTOR PUBLIC SETUP_CTRL_BREAK ;MAKE ENTRY IN LINK MAP ;AN000; ;****************************************************************************** PUSH AX PUSH BX PUSH DX PUSH ES MOV AX,2523H ;SET THE CTRL-BREAK VECTOR MOV DX,OFFSET MAIN_EXIT INT 21H POP ES POP DX POP BX POP AX RET SETUP_CTRL_BREAK ENDP HEADER ;****************************************************************************** CHECK_SERVER PROC NEAR ;SEE IF SERVER OR REDIRECTOR IS IN++ PUBLIC CHECK_SERVER ;MAKE ENTRY IN LINK MAP ;AN000; ; ; INPUT: BL = DRIVE NUMBER (1=A,2=B ETC....) ;****************************************************************************** MOV AH,0 ;SEE IF SERVER LOADED INT SERVER CMP AH,0 ; $IF E JNE $$IF55 MOV DX,FINE ; $ELSE JMP SHORT $$EN55 $$IF55: DEC BL ADD BL,"A" ;CONVERT TO ASCII DRIVE LETTER MOV ASCII_DRIVE_LETTER,BL ;PUT IN ASCIIZ STRING MOV SI,OFFSET ASCII_DRIVE_LETTER MOV AH,SHARED CLC INT SERVER ; $IF C JNC $$IF57 MOV DX,OFFSET MSGNUM_DRV_REDIRECTED ;AC000; ; $ELSE JMP SHORT $$EN57 $$IF57: MOV DX,FINE ; $ENDIF $$EN57: ; $ENDIF $$EN55: RET CHECK_SERVER ENDP Public INIT_END INIT_END LABEL BYTE PATHLABL COMPINIT ;AN013; CSEG ENDS END