1 PAGE
90,132 ;\ f\eA\b\e2
2 TITLE COPYINIT
-- DISKCOPY INITIALIZATION PROGRAM
3 ;****************** START OF SPECIFICATIONS *****************************
4 ; MODULE NAME: COPYINIT
6 ; DESCRIPTIVE NAME: Initialization for Diskette to diskette copy Utility
8 ;FUNCTION: DISKCOPY is to copy the contents of the diskette in the
9 ; specified source drive to the diskette in the target
10 ; drive. If necessary, the target diskette is also
13 ; Multiple copies may be performed with one load of DISKCOPY.
14 ; A prompt, "Copy another (Y/N)?" permits additional
15 ; executions, all with the same drive specifications.
17 ; ENTRY POINT: "DISKCOPY" at ORG 100h, jumps to "BEGIN".
19 ; INPUT: (DOS command line parameters)
20 ; [d:][path]DISKCOPY [d: [D:]][/1]
24 ; [d:][path] before DISKCOPY to specify the drive and path that
25 ; contains the DISKCOPY command file.
27 ; [d:] to specify the source drive id
29 ; [D:] to specify the destination drive id
31 ; [/1] to request single sided operations only
33 ; EXIT-NORMAL: Errorlevel = 0
34 ; Function completed successfully.
36 ; EXIT-ERROR: Errorlevel = 1
37 ; Abnormal termination due to error, wrong DOS,
38 ; invalid parameters, unrecoverable I/O errors on
41 ; EFFECTS: The entire source diskette is copied, including the unused
42 ; sectors. There is no awareness of the separate files
43 ; involved. A unique volume serial number is generated
44 ; for the target diskette.
47 ; INCLUDE DCPYMACR.INC
48 ; INCLUDE DISKCOPY.EQU
49 ; INCLUDE PATHMAC.INC ;PATHGEN MACRO
51 ; INTERNAL REFERENCES:
53 ; INIT - INITIALIZATION ROUTINE, MAIN PROGRAM
54 ; SOURCE_TARGET_DRV - CONVERT SOURCE/TARGET DRIVE TO BIOS VALUES
55 ; TEST_DRIVE_VALIDITY - ARE SOURCE/TARGET DRIVES VALID?
56 ; DOS_DRIVE_VALIDITY - CHECK DOS DRIVE VALIDITY BYTE
57 ; TEST_REMOVABLE - IS SPECIFIED DRIVE REMOVABLE?
58 ; CHK_SINGLE_DRIV_OP - IS TARGET DRIVE SAME AS SOURCE?
59 ; GET_LOGICAL_DRIVE - GET LOG. DRIV NO. WHO OWNS PHYSICAL DRIVE
60 ; DISKETTE_DRV_TYPE - CHECK COMPATABILITY SOURCE/TARGET DRIVES
61 ; CHECK_REDIRECTION - IS DEVICE REDIRECTED?
62 ; BUFFER_SIZE - FINDS START AND END OF BUFFER
63 ; SETUP_CTRL_BREAK - SETUP THE CTRL-BREAK VECTOR
64 ; CHECK_SERVER - IS SERVER OR REDIRECTOR LOADED?
67 ; PSP - Contains the DOS command line parameters.
68 ; WORKAREA - Temporary storage
70 ; EXTERNAL REFERENCES:
72 ; SYSDISPMSG - Uses the MSG parm lists to construct the messages
74 ; SYSLOADMSG - Loads messages, makes them accessable.
75 ; PARSER - Processes the DOS Command line, finds parms.
78 ; DCOPYSM.SAL - Defines the control blocks that describe the messages
79 ; DCOPYPAR.SAL - Defines the control blocks that describe the
80 ; DOS Command line parameters.
83 ; This module should be processed with the SALUT preprocessor
84 ; with the re-alignment not requested, as:
88 ; To assemble these modules, the alphabetical or sequential
89 ; ordering of segments may be used.
91 ; For instructions as to how to LINK, see prolog for DISKCOPY.
93 ;PROGRAM AUTHOR: Original written by: JK
94 ; 4.00 modifications by: EMK
95 ;****************** END OF SPECIFICATIONS *****************************
97 %
OUT COMPONENT
=DISKCOPY
, MODULE
=COPYINIT
.SAL
102 ;DATE: 10-30-84 - chk_para routine added. many parts are modified to
103 ; permit DISKCOPY /1, DISKCOPY D: /1 cases. Restore diskbase
104 ; before return to DOS when invalid DOS version occurs.
105 ;DATE: 3-27-85 MAIN PARTS OF DISKCOPY PROGRAM HAS BEEN REWRITTEN
106 ; TO USE NEW IOCTL FUNCTION CALLS - READ, WRITE AND FORMAT.
109 INCLUDE PATHMAC
.INC ;AN015;PATHGEN MACRO
111 CSEG
SEGMENT PARA
PUBLIC 'CODE' ;AN000;
112 ASSUME
CS:CSEG
, DS:CSEG
, ES:CSEG
, SS:CSEG
116 ;****************************************************************************
118 ; EXTERNAL VARIABLES *
120 ;****************************************************************************
122 EXTRN PARSER
:NEAR ;DCOPYPAR.SAL - DRIVES SYS PARSER ;AN000;
124 EXTRN RECOMMENDED_BYTES_SECTOR
:WORD ;SOURCE DRIVE DEFAULT BYTES/SECTOR
125 EXTRN S_OWNER_SAVED
:BYTE
126 EXTRN T_OWNER_SAVED
:BYTE
127 EXTRN ASCII_DRV1_ID
:BYTE ;40H SOURCE DRIVE ID IN ASCII
128 EXTRN ASCII_DRV2_ID
:BYTE ;40H TARGET DRIVE ID IN ASCII
129 EXTRN MSGNUM_INVALID_DRV
:BYTE ;"INVALID DRIVE SPECIFICATION" ;AC000;
130 EXTRN MSGNUM_NOT_COMPATIBLE
:BYTE ;"DEVICE TYPE OF DISKETTE TYPES NOT COMPATIBLE";AC000;
131 EXTRN MSGNUM_DRV_REDIRECTED
:BYTE ;"INVALID, DRIVE REDIRECTED" ;AC000;
134 EXTRN SUBLIST_8
:WORD ; ;AN000;
135 EXTRN SUBLIST_9
:WORD ; ;AN000;
136 EXTRN SUBLIST_13
:WORD ; ;AN000;
137 EXTRN SUBLIST_17A
:WORD ; ;AN000;
138 EXTRN SUBLIST_17B
:WORD ; ;AN000;
139 EXTRN SUBLIST_17C
:WORD ; ;AN000;
140 EXTRN SUBLIST_19C
:WORD ; ;AN000;
141 EXTRN SUBLIST_19D
:WORD ; ;AN000;
142 EXTRN SUBLIST_19E
:WORD ; ;AN000;
143 EXTRN SUBLIST_26A
:WORD ; ;AN001;
144 EXTRN SUBLIST_26B
:WORD ; ;AN001;
145 EXTRN SUBLIST_PARSE
:WORD ;PARSE ERROR XX - %0 ;AN003;
148 ;EXTRN MSG_INVALID_PARM_PTR:BYTE ;"INVALID PARAMETER"
149 ;EXTRN MSG_INVALID_DOS :BYTE ;"INVALID DOS"
151 EXTRN S_DRV_SECT_TRACK
:BYTE ;SECT/TRACK
152 EXTRN S_DRV_HEADS
:BYTE ;# OF HEADS
153 EXTRN S_DRV_TRACKS
:BYTE ;# OF TRACKS
154 EXTRN T_DRV_SECT_TRACK
:BYTE
155 EXTRN T_DRV_HEADS
:BYTE
156 EXTRN T_DRV_TRACKS
:BYTE
157 EXTRN SOURCE_DRIVE
:BYTE ;SRC DRV LOGICAL NUMBER
158 EXTRN TARGET_DRIVE
:BYTE ;TARGET DRV LOGICAL NUMBER
159 EXTRN COPY_TYPE
:BYTE ;1 = 1-DRIVE COPY 2 = 2-DRIVE COPY
160 EXTRN USER_OPTION
:BYTE ;NO OPTION (-1) /1 (1), INVALID (9)
161 EXTRN BUFFER_BEGIN
:WORD ;STARTING BUFFER @ FOR LOADING
162 EXTRN BUFFER_END
:WORD ;ENDING BUFFER @ FOR LOADING
163 EXTRN MAIN_EXIT
:WORD ;EXIT ADDRESS FOR CONTROL-BREAK
167 EXTRN DS_IOCTL_DRV_PARM
:BYTE ;PLACE HOLDER FOR DEFAULT SOURCE DRV PARM
168 EXTRN DT_IOCTL_DRV_PARM
:BYTE ;PLACE HOLDER FOR DEFAULT TARGET DRV PARM
169 EXTRN DS_specialFunctions
:BYTE ;AND THEIR CONTENTS
170 EXTRN DT_specialFunctions
:BYTE
171 EXTRN DS_deviceType
:BYTE
172 EXTRN DT_deviceType
:BYTE
173 EXTRN DS_deviceAttributes
:WORD
174 EXTRN DT_deviceAttributes
:WORD
175 EXTRN DS_numberOfCylinders
:WORD
176 EXTRN DT_numberOfCylinders
:WORD
177 EXTRN DS_mediaType
:BYTE
178 EXTRN DT_mediaType
:BYTE
179 EXTRN DS_BPB_PTR
:BYTE
180 EXTRN DT_BPB_PTR
:BYTE
182 EXTRN MS_IOCTL_DRV_PARM
:BYTE ;DRIVE PARM FROM SOURCE MEDIUM
183 EXTRN MT_IOCTL_DRV_PARM
:BYTE
185 EXTRN GENERIC_IOCTL
:NEAR
186 EXTRN SET_LOGICAL_DRIVE
:NEAR
188 ; $salut (4,20,24,41) ; ;AN000;
190 CBYTE_SECT
DW 0 ; 200H BYTES / SECTOR
191 CSECT_CLUSTER
DB 0 ; 2h SECTORS / CLUSTER
192 CRESEV_SECT
DW 0 ; 1h RESERVED SECTORS
193 CFAT
DB 0 ; 2h # OF FATS
194 CROOTENTRY
DW 0 ; 70h # OF ROOT ENTRIES
195 CTOTSECT
DW 0 ; 02D0h TOTAL # OF SECTORS
196 ; INC. BOOT SECT, DIRECTORIES
197 MEDIA_DESCRIP
DB 0 ;0FDh MEDIA DISCRIPTOR
198 CSECT_FAT
DW 0 ; 2h SECTORS / FAT
207 ;****************************************************************************
209 ; VARIABLE DECLARATIONS *
211 ;****************************************************************************
212 DRIVE_VALID
DW ?
;DRIVE VALIDITY INDICATOR
213 DEFAULT_DRV
DB ?
;DEFAULT DRIVE ID (0=A,1=B,ETC)
214 NUMBER_OF_DRV
DB ?
;TOTAL # OF DISKT DRIVES ON THE SYS
215 ;(NUMBER_OF_DRV = 0 ---> 1 DRIVE)
216 ASCII_DRIVE_LETTER
DB " :",0
217 PATHLABL COPYINIT
;AN015;
218 HEADER
<INIT
- INITIALIZATION ROUTINE
, MAIN PROGRAM
> ; ;AN000;
219 ; $salut (4,9,15,41) ; ;AN000;
220 ;#############################################################################
221 ; INITIALIZATION ROUTINE - MAIN PROGRAM
223 PUBLIC INIT
;MAKE ENTRY IN LINK MAP ;AN000;
225 ;OUTPUT: DX = EXIT CODE, "FINE"
226 ;#############################################################################
228 MOV DRIVE_VALID
,AX ;SAVE DRIVE VALIDITY BYTE
230 ; REPLACE THE "FILL_SEG" IN THE SUBLIST MESSAGE CONTROL BLOCKS.
232 ; BECAUSE THIS IS A .COM STYLE FILE, THESE SEGID VALUES CANNOT
233 ; BE PROVIDED BY THE DOS SYSTEM LOADER, BUT MUST BE DYNAMICALLY
234 ; PERFORMED AT EXECUTION TIME AS PART OF A .COM FILE'S OBLIGATION
235 ; TO BE "SELF-RELOCATING".
237 MOV AX,CS ;GET SEGID OF COMMON SEGMENT ;AN000;
238 MOV SUBLIST_8
.SUB_VALUE_SEG
,AX ; ;AN000;
239 MOV SUBLIST_9
.SUB_VALUE_SEG
,AX ; ;AN000;
240 MOV SUBLIST_13
.SUB_VALUE_SEG
,AX ; ;AN000;
241 MOV SUBLIST_17A
.SUB_VALUE_SEG
,AX ; ;AN000;
242 MOV SUBLIST_17B
.SUB_VALUE_SEG
,AX ; ;AN000;
243 MOV SUBLIST_17C
.SUB_VALUE_SEG
,AX ; ;AN000;
244 MOV SUBLIST_19C
.SUB_VALUE_SEG
,AX ; ;AN000;
245 MOV SUBLIST_19D
.SUB_VALUE_SEG
,AX ; ;AN000;
246 MOV SUBLIST_19E
.SUB_VALUE_SEG
,AX ; ;AN000;
247 MOV SUBLIST_26A
.SUB_VALUE_SEG
,AX ; ;AN001;
248 MOV SUBLIST_26B
.SUB_VALUE_SEG
,AX ; ;AN001;
249 MOV SUBLIST_PARSE
.SUB_VALUE_SEG
,AX ; ;AN003;
251 CALL SETUP_CTRL_BREAK
;STEALS CTRL_BREAK
252 CLD ;CLEAR DIRECTION FLAG
253 MOV DX,FINE
;ASSUME EVERYTHING IS FINE
255 ; CALL SCREENING ;CHECK DOS VERSION AND INPUT PARMS
256 ; CALL CHK_PARA ; GENERAL SYNTAX CHECK
258 CALL PARSER
;LOOK AT DOS COMMAND LINE ;AN000;
260 CMP DX,FINE
;IF ALL OK ;AN000;
263 CALL SOURCE_TARGET_DRV
;SET UP TO USE THE DRIVE LETTERS ;AN000;
265 CALL TEST_DRIVE_VALIDITY
270 CALL DISKETTE_DRV_TYPE
;SOURCE & TARGET DRIVE TYPES
272 CMP DX,FINE
;IF FINE & DANDY
275 CALL BUFFER_SIZE
;GET BUFFER SIZE FOR COPYING
283 EXIT_INIT: ;DX <-- 1 IF INIT OK
284 RET ;DX <-- ERROR OFFSET IF NOT OK
286 INIT ENDP
;END INITIALLIZATION PROGRAM
289 ; HEADER <SCREENING - CHECK DOS VERSION, SYNTAX PARMS>
290 ;******************************************************************************
291 ; SUBROUTINE NAME : SCREENING - CHECKS THE FOLLOWING: *
293 ; - GENERAL SYNTAX CHECKING FOR PARAMETERS *
295 ; OUTPUT : DX : FINE - NO ERROR *
296 ; (OTHERS)- ERROR MSG OFFSET *
297 ;******************************************************************************
301 ; MOV AH,DOSVER_FUNC ;SEE IF CORRECT DOS VERSION
302 ; INT 21H ;FUNCTION CALL (AL <- DOS VERSION)
303 ;NOTE: BX IS DESTROYED
304 ; XCHG AH,AL ;AH=MAJOR VER, AL=MINOR VER
305 ; CMP AX,expected_version ;IF DOS MAJOR VERSION LESS THAN 3.00
306 ; $IF NE ;THEN ISSUE ERROR MSG
307 ; MOV DX,OFFSET MSG_INVALID_DOS
308 ; MOV AH,PRINT_FUNC ;USE PRINT FUNCTION TO TELL USER
309 ; INT 21H ;THAT HE IS USING THE OLD VERSION
310 ; INT 20H ;EXIT TO DOS
312 ; CALL CHK_PARA ;GENERAL SYNTAX CHECK
313 ; $ENDIF ;END VERSION TEST
316 ; HEADER <CHK_PARA - SYNTAX PARMS, OPTION /1>
317 ;**************************************************************************
319 ;kiser: this proc is to be deleted
322 ; CHECK SYNTAX OF THE ENTERED PARAMETERS *
323 ; ALSO, DETERMINE THE USER OPTION "/1" IS ENTERED OR NOT. *
325 ; IF /1 HAS BEEN ENTERED, THE VARIABLE USER_OPTION = OPTION_1 *
326 ; ELSE USER_OPTION = NO_OPTION. *
327 ; OUTPUT: DX = FINE - NO ERROR *
328 ; OTHERWISE DX POINTS TO ERROR MSG *
329 ;**************************************************************************
331 ; MOV USER_OPTION, NO_OPTION ;ASSUME NO /1 IS ENTERED.
333 ; MOV CL, BYTE PTR DS:BEGIN_UNFORM_AREA ;GET # OF CHR
336 ; CLD ;CLEAR DIRECTION
337 ; MOV DI, BEGIN_UNFORM_AREA+2 ;STARTING POINT OF PARA
338 ; DEC CL ;TO IGNORE LAST CHR (0DH)
339 ; CALL SKIP_BLANKS ;SKIP BLANKS, IF ANY. THE POINTER
340 ; ; WILL POINT TO THE NEXT NON_BLANK CHR
342 ; $IF NZ ;SOMETHING OTHER THAN BLANKS
344 ; CALL CHK_SLASH_ONE ;IS NEXT WORD /1 ?
347 ; CALL CHK_DRV_SPEC ;IS IT A DRIVE SPECIFICATION LIKE d: ?
349 ; JC INVALID_PARA ;IF NOT, THEN ERROR
350 ; JZ CHK_PARA_EXIT ;NO MORE CHR? THEN, OK. (EX. DISKCOPY D:)
351 ; CALL CHK_SLASH_ONE ;IS NEXT WORD /1 ?
353 ; JNC SLASH_ONE ;YES.(EX. DISKCOPY D:/1)
354 ; CALL CHK_BLANK ;IF NOT, NEXT CHR SHOULD BE A BLANK.
356 ; JC INVALID_PARA ;OTHERWISE, ERROR.
357 ; CALL SKIP_BLANKS ;SKIP BLANKS, IF ANY.
359 ; JZ CHK_PARA_EXIT ;(EX. DISKCOPY D: )
360 ; CALL CHK_SLASH_ONE ;IS IT A /1 ?
362 ; JNC SLASH_ONE ;YES. (EX. DISKCOPY D: /1)
363 ; CALL CHK_DRV_SPEC ;IF NOT /1, THEN IS IT A DRV SPEC?
365 ; JC INVALID_PARA ;OTHERWISE, ERROR.
366 ; CALL SKIP_BLANKS ;SKIP BLANKS, IF ANY.
368 ; JZ CHK_PARA_EXIT ;NO MORE CHR. (EX. DISKCOPY D: D:)
369 ; CALL CHK_SLASH_ONE ;OTHERWISE, IT SHOULD BE /1.
371 ; JNC SLASH_ONE ;YES, /1. JMP TO SLASH_ONE
372 ; JMP INVALID_PARA ;PARAMETER ERROR.
374 ; MOV USER_OPTION, OPTION_1 ;YES, /1 HAS BEEN ENTERED.
375 ; CALL SKIP_BLANKS ;/1 SHOULD BE END OF PARAMETERS, OR ONLY BLANKS CAN FOLLOW.
379 ; MOV DX,OFFSET MSG_INVALID_PARM_PTR ;WRONG PARM ENTERED MSG
388 ; HEADER <SKIP_BLANKS - IGNORE BLANKS/TABS IN PARMS PARSING>
389 ;***************************************************************************
390 ;SKIP_BLANKS PROC NEAR
391 ; ** SKIP BLANKS, OR TABS IF ANY, IN THE PARAMETER STRING. *
392 ; INPUT: ES:DI POINTS TO THE CURRENT CHR. *
393 ; CX - # OF REMAINING CHR IN THE STRING. *
394 ; OUTPUT: ES:DI POINT TO THE NEXT NON_BLANK CHR. *
395 ; CX IS ADJUSTED ACCORINGLY. *
396 ; IF THE CURRENT CHR IS NOT A BLANK, THEN DI, CX VALUE NOT CHANGED.*
397 ; IF CX = 0, THEN ZERO FLAG WILL BE SET AND EXIT THIS PROC. *
398 ;***************************************************************************
400 ; MOV AL, 20H ;20H=BLANK
401 ; CLD ;CLEAR DIRECTION
403 ; $LEAVE Z ;IF NOT FOUND A NON_BLANK CHR YET, AND CX=0, EXIT THIS ROUTINE.
404 ; DEC DI ;OTHERWISE, RESTORE DI TO THE NON_BLANK POSITION.
405 ; INC CX ; AND RESTORE CX TO WHERE IT WAS AT NON_BLANK CHR
406 ; ;(IF FOUND A NON_BLANK CHR, ZERO FLAG WOULD NOT BE SET)
407 ; MOV AL, ES:BYTE PTR [DI]
408 ; CMP AL, 09H ;09H=TAB
409 ; $LEAVE NZ ;IF THE NON_BLANK CHR IS NOT A TAB THEN EXIT
410 ; INC DI ;ELSE TRY SKIP AGAIN
415 ; HEADER <CHK_SLASH - IS CURRENT PARM /1>
416 ;***************************************************************************
418 ;kiser: this proc is to be deleted
420 ;CHK_SLASH_ONE PROC NEAR
421 ; ** CHECK CURRENT CHR IS / FOLLOWED BY 1. *
422 ; INPUT: ES:DI POINTS TO THE CURRENT CHR TO BE CHECKED. *
423 ; CX REPRESENTS THE # OF CHR'S IN THE STRING. *
424 ; OUTPUT: FOUND - DI POINTS TO THE NEXT CHR. CX CHANGED ACCORDINGLY. *
425 ; IF THIS HAD BEEN A LAST WORD, ZERO FLAG WILL BE SET. *
426 ; NOT FOUND - CARRY IS SET. DI, CX UNCHANGED. *
427 ;***************************************************************************
429 ; CLC ;CLEAR CARRY FLAG
430 ; CMP CX, 2 ;# OF CHR IN THE STRING.
431 ; $IF NL,AND ;IF LESS THAN 2, THEN SET CARRY AND EXIT.
433 ; MOV AX, ES:WORD PTR [DI] ;GET CURRENT WORD IN AX
434 ; CMP AX, '1/' ;IS IT /1 ?
435 ; $IF Z ;IF NOT, THEN SET CARRY AND EXIT
436 ; INC DI ;ADJUST CX, DI TO THE NEXT CHR
440 ; CMP CX, 0 ;IF NO MORE CHR, THEN SET ZERO FLAG.
442 ; STC ;NOT FOUND, SET CARRY FLAG.
446 ; HEADER <CHK_DRV - CURRENT PARM CHAR IS DRIVE AND COLON?>
447 ;***************************************************************************
449 ;kiser: this proc is to be deleted
451 ;CHK_DRV_SPEC PROC NEAR
452 ; ** CHECK CURRENT CHR IS ALPHA CHR FOLLOWED BY COLON. *
453 ; INPUT: ES:DI POINTS TO THE CURRENT CHR TO BE CHECKED. *
454 ; CX -- # OF CHR IN THE STRING. *
455 ; OUTPUT: FOUND - DI POINTS TO THE NEXT CHR. CX ADJUSTED ACCORDINGLY. *
456 ; IF THIS HAD BEEN A LAST WORD, ZERO FLAG WILL BE SET. *
457 ; NOT FOUND - CARRY IS SET. DI, CX UNCHANGED. *
458 ;***************************************************************************
461 ; CMP CX, 2 ;# OF CHR REMAINING IN THE STRING.
462 ; $IF NL,AND ;IF NOT LESS THAN 2, THEN FOUND
463 ; ;IF LESS THAN 2, THEN NOT FOUND - SET CARRY AND EXIT.
464 ; MOV AL, ES:BYTE PTR [DI] ;GET CURRENT CHR
465 ; AND AL, 11011111B ;CHANGE IT TO UPPER_CASE CHR.
467 ; $IF NB,AND ;NOT BELOW 'A', THEN MAYBE FOUND OK
470 ; $IF NA,AND ;NOT ABOVE 'Z', THEN FOUND
472 ; MOV AL, ES:BYTE PTR [DI+1] ;LOOK AHEAD THE FOLLOWING CHR.
473 ; CMP AL, ':' ;SHOULD BE A COLON.
475 ; INC DI ;FOUND. ADJUST CX, DI TO THE NEXT CHR.
479 ; CMP CX, 0 ;IF NO MORE CHR, THAN SET THE ZERO FLAG.
485 ; HEADER <CHK_BLANK - IS CURRENT CHAR IN PARM BLANK OR TAB>
486 ;***************************************************************************
488 ;kiser: this proc is to be deleted
491 ;; ** CHECK THE CURRENT CHR IS A BLANK OR TAB *
492 ;; INPUT: ES:DI POINTS TO THE CURRENT CHR. *
493 ; CX - # OF CHR IN THE STRING. *
494 ; OUTPUT: FOUND - DI MOVES TO THE NEXT CHR. CX DECREASES BY 1. *
495 ; NOT FOUND - CARRY IS SET. DI, CX UNCHANGED. *
496 ;***************************************************************************
499 ; CMP CX, 1 ;IF LESS THAN 1, NOT FOUND.
500 ; $IF L,OR ;GO SET CARRY AND EXIT
502 ; MOV AL, ES:BYTE PTR [DI] ;GET CURRENT CHR
503 ; CMP AL, 020H ;020H=BLANK CHR
504 ; $IF NZ,AND ;NOT FOUND
505 ; CMP AL, 09H ;09H=TAB CHR
506 ; $IF NZ ;NOT FOUND EITHER
510 ; $ELSE ;CHAR MUST BE EITHER TAB OR BLANK
511 ; INC DI ;FOUND. ADJUST DI, CX
517 HEADER
<SOURCE_TARGET_DRV
- CONV
. SRC
/TARGET DRV TO BIOS VALUES
> ; ;AN000;
518 ;******************************************************************************
519 ; SUBROUTINE NAME : SOURCE_TARGET_DRV DETERMINES SOURCE & TARGET DRIVES & *
520 ; CONVERT THEM FROM DOS TO BIOS VALUE *
521 ; INPUT : SOURCE_DRIVE & TARGET_DRIVE HAVE DOS DRIVE ID'S: *
522 ; 0 = DEFAULT 1 = DRV A *
523 ; 2 = DRV B 3 = DRV C ETC *
526 ; OUTPUT : DEFAULT_DRV: CURRENT DEFAULT DRIVE *
527 ; 0 - DRIVE A 1 - DRIVE B *
528 ; 2 - DRIVE C 3 - DRIVE D *
530 ; : SOURCE_DRIVE 1 = DRIVE A 2 = DRIVE B ETC. *
531 ; : TARGET_DRIVE 1 = DRIVE A 2 = DRIVE B ETC. *
533 ;******************************************************************************
534 SOURCE_TARGET_DRV PROC
NEAR
535 PUBLIC SOURCE_TARGET_DRV
;MAKE ENTRY IN LINK MAP ;AN000;
536 ;GET CURRENT DEFAULT DRIVE
537 MOV AH,CURRENTDRV_FUNC
;FUNCTION CALL (19H)
538 ;(AL <- CURRENT DEFAULT DRV
539 INT 21H
;0 = A, 1 = B, ETC)
541 MOV DEFAULT_DRV
,AL ;SAVE IT
542 INC AL ;NOW A=1, B=2, ETC ;AN000;
543 CMP SOURCE_DRIVE
,ZERO
;FIRST DRV ENTERED? ;AC000;
544 ; $IF E ;NO DRIVE LETTER ENTERED
546 MOV SOURCE_DRIVE
,AL ;USE DEFAULT DRIVE AS SOURCE ;AC000;
547 MOV TARGET_DRIVE
,AL ; AND AS TARGET ;AC000;
551 CMP TARGET_DRIVE
,ZERO
;WAS THE SECOND DRIVE ID SPECIFIED? ;AC000;
552 ; $IF E ;NO, SO TARGET DRV IS DEFAULT ;AC000;
554 MOV TARGET_DRIVE
,AL ;USE DEFAULT DRIVE AS TARGET ;AC000;
559 MOV AX,WORD PTR SOURCE_DRIVE
;SOURCE TO AL, TARGET TO AH ;AC000;
560 ADD ASCII_DRV1_ID
,AL ;MAKE THE DRIVE ALPHABET READABLE
561 ADD ASCII_DRV2_ID
,AH ;IN THE MESSAGE
565 SOURCE_TARGET_DRV ENDP
566 HEADER
<TEST_DRIVE_VALIDITY
- ARE SOURCE
/TARGET DRIVES VALID?
> ; ;AN000;
567 ;******************************************************************************
568 ; SUBROUTINE NAME : TEST_DRIVE_VALIDITY--MAKE SURE SOURCE AND TARGET DRIVES *
569 ; SPECIFIED BY USER ARE VALID FOR DISKCOPY *
571 ; INPUT : SOURCE_DRIVE:BYTE, TARGET_DRIVE:BYTE *
573 ; OUTPUT : DX='FINE' IF DRIVES ARE VALID, ELSE DX CONTAINS MSG PTR *
574 ;******************************************************************************
576 TEST_DRIVE_VALIDITY PROC
NEAR
577 PUBLIC TEST_DRIVE_VALIDITY
;MAKE ENTRY IN LINK MAP ;AN000;
579 CALL DOS_DRIVE_VALIDITY
582 ; $IF E,AND ; ;AC000;
586 CALL CHECK_REDIRECTION
589 ; $IF E,AND ; ;AC000;
593 CALL CHECK_REDIRECTION
596 ; $IF E,AND ; ;AC000;
603 ; $IF E,AND ; ;AC000;
610 ; $IF E,AND ; ;AC000;
619 CALL CHK_SINGLE_DRV_OP
;CHECK IF IT IS
620 ; ONE PHYSICAL DRIVE OPERATION
625 TEST_DRIVE_VALIDITY ENDP
626 HEADER
<DOS_DRIVE_VALIDITY
- CHECK DOS DRIVE VALIDITY
BYTE> ; ;AN000;
627 ;******************************************************************************
628 ; SUBROUTINE NAME : DOS_DRIVE_VALIDITY -- CHECK DOS DRIVE VALIDITY BYTE *
630 ; INPUT : DRIVE_VALID:BYTE *
632 ; OUTPUT : DX="FINE" IF DRIVES ARE VALID ELSE DX CONTAINS MESSAGE PTR *
633 ;******************************************************************************
635 DOS_DRIVE_VALIDITY PROC
NEAR
637 CMP DRIVE_VALID
,0 ;SEE IF DRIVES ARE VALID DOS DEVICE
640 MOV DX,OFFSET MSGNUM_INVALID_DRV
; ;AC000;
645 DOS_DRIVE_VALIDITY ENDP
646 HEADER
<TEST_REMOVABLE
- IS SPECIFIED DRIVE REMOVABLE?
> ; ;AN000;
647 ;******************************************************************************
648 ; SUBROUTINE NAME : TEST_REMOVABLE -- CHECK IF DRIVES SPECIFED ARE REMOVABLE *
650 ; INPUT : SOURCE_DRIVE:BYTE, TARGET_DRIVE:BYTE *
652 ; OUTPUT : DX=FILE IF DRIVES ARE VALID ELSE DX CONTAINS MESSAGE PTR *
653 ;******************************************************************************
655 TEST_REMOVABLE PROC
NEAR
657 MOV BL,SOURCE_DRIVE
;GET PARM 1 DRIVE ID
659 MOV AX,DRIVE_CHECK
;CHECK FOR REMOVABLE DRIVE = 4408h
661 ; $IF NC ;IF DRIVE ID IS WITHIN RANGE
663 CMP AX,REMOVABLE
;THEN IF SOURCE DRIVE IS FIXED
666 MOV DX,OFFSET MSGNUM_INVALID_DRV
;GENERATE HARD ;AC000;
667 ; DRIVE ERROR MESSAGE
668 ; $ELSE ;ELSE, SRC IS REMOVABLE;
671 MOV BL,TARGET_DRIVE
;NOW GO CHECK TARGET
673 MOV AX,DRIVE_CHECK
;CHECK FOR REMOVABLE DRIVE
675 ; $IF NC ;IF DRV WITHIN RANGE
677 CMP AX,REMOVABLE
;THEN TGT DRV IS FIXED
680 MOV DX,OFFSET MSGNUM_INVALID_DRV
;GENERATE HARD ;AC000;
682 ; $ENDIF ;END TEST IF TGT DRV IS FIXED
684 ; $ELSE ;TGT DRV OUT OF RANGE. EX. DRIVE X:
687 MOV DX,OFFSET MSGNUM_INVALID_DRV
; ;AC000;
688 ; $ENDIF ;END TEST IF TGT WITHIN RANGE
690 ; $ENDIF ;END IF SRC IS REMOVABLE
692 ; $ELSE ;ELSE, SRC DRV OUT OF RANGE
695 MOV DX,OFFSET MSGNUM_INVALID_DRV
;PRINT ERROR MSG ;AC000;
696 ; $ENDIF ;END TEST IF SRC DRV WITHIN RANGE
701 HEADER
<CHK_SINGLE_DRIV_OP
- IS TARGET DRIVE SAME
AS SOURCE?
> ; ;AN000;
702 ;******************************************************************************
703 ; SUBROUTINE NAME : CHK_SINGLE_DRV_OP *
705 ; INPUT : SOURCE_DRIVE - LOGICAL DRIVE NUMBER *
708 ; OUTPUT : COPY_TYPE WILL BE SET TO ONE OR TWO DEPENDING ON THE *
709 ; TEST RESULT. IF IT IS A SINGLE DRIVE COPY, THEN *
710 ; TARGET DRIVE LETTER WILL BE CHANGED TO THAT OF SOURCE. *
711 ; THE OWNERSHIP OF THE SOURCE AND TARGET DRIVE LETTER *
712 ; MIGHT HAVE BEEN CHANGED. *
713 ; SO, BEFORE EXIT TO DOS, THEY SHOULD BE RESET TO THE SAVED*
714 ; ONE USING S_OWNER_SAVED AND T_OWNER_SAVED UNLESS THEY *
715 ; ARE EQUAL TO 0. (0 MEANS ONLY ONE DRIVE LETTER ASSIGNED.)*
716 ; ASCII_DRV1_ID, ASCII_DRV2_ID MAY BE CHANGED ACCORDINGLY. *
717 ;******************************************************************************
719 CHK_SINGLE_DRV_OP PROC
NEAR
724 CALL GET_LOGICAL_DRIVE
726 MOV S_OWNER_SAVED
, AL ;SAVE CURRENT OWNER DRIVE LETTER.
728 CALL GET_LOGICAL_DRIVE
730 MOV T_OWNER_SAVED
, AL ;SAVE CURRENT OWNER
732 CALL SET_LOGICAL_DRIVE
735 CALL SET_LOGICAL_DRIVE
738 CALL GET_LOGICAL_DRIVE
;CHECK SOURCE DRV LETTER
739 ; STILL HAS A OWNERSHIP.
741 CMP AL, SOURCE_DRIVE
;
742 ; $IF NE ;IF IT DOES NOT, THEN A
747 MOV TARGET_DRIVE
, BL ;SET TARGET DRV LETTER
749 MOV BL, ASCII_DRV1_ID
750 MOV ASCII_DRV2_ID
, BL
752 CALL SET_LOGICAL_DRIVE
;SET THE OWNER BACK TO
758 CMP AL, TARGET_DRIVE
;SOURCE DRV LETTER = TARGET DRV
759 ; LETTER CASE, FOR EX. DISKCOPY A: A:
775 CHK_SINGLE_DRV_OP ENDP
776 HEADER
<GET_LOGICAL_DRIVE
- GET LOG
. DRIV NO
. WHO OWNS PHYS
. DRIVE
> ;AN000;
777 ;******************************************************************************
778 GET_LOGICAL_DRIVE PROC
NEAR
779 ; *** GET THE LOGICAL DRIVE NUMBER WHO HAS THE OWNERSHIP OF THE PHYSICAL
781 ; INPUT: BL = DRIVE NUMBER (0=DEFAULT, 1=A, 2=B...)
782 ; OUTPUT: AL = DRIVE NUMBER (0= ONLY ONE DRIVE LETTER ASSIGNED TO THE
783 ; BLOCK DEVICE. OTHERWISE, 1=A, 2=B...)
785 ;******************************************************************************
788 MOV AL, 0EH ; GET THE OWNER OF LOGICAL DRIVE NUMBER
790 CMP AL, 0 ;ONLY ONE DRIVE LETTER ASSIGNED?
793 MOV AL, BL ;THEN SET THE INPUT DRIVE NUMBER TO AL.
799 GET_LOGICAL_DRIVE ENDP
800 HEADER
<DISKETTE_DRV_TYPE
- CHECK COMPATABILITY SOURCE
/TARGET DRIVES
> ; ;AN000;
801 ;******************************************************************************
802 ; SUBROUTINE NAME : DISKETTE_DRV_TYPE DOES THE FOLLOWING: *
803 ; - GETS SOURCE, TARGET DRIVE INFORMATION *
804 ; - CHECK REMOVABLE DRIVE *
805 ; *** REMARK: WILL NOT ALLOW DISKCOPY BETWEEN 5.25" AND 3.5" DRIVES. *
806 ; *** ALSO, IN THE MAIN PROGRAM, SOURCE MEDIA BPB INFORMATIONS (# OF SEC/TRK, *
807 ; *** # OF TRACKS) SHOULD BE CHECKED AGAINST TARGET DEVICE INFORMATIONS. *
808 ; *** IF # OF SECT/TRACK, # OF TRACKS OF TARGET DEVICE ARE EQUAL TO, OR *
809 ; *** GREATER THAN THOSE OF THE SOURCE MEDIA BPB, THEN IT IS OK. OTHERWISE *
810 ; *** DEVICE NOT COMPATIBLE. *
811 ; *** IF THIS DOES NOT GAURANTEES COMPATIBILITY BETWEEN SOURCE AND TARGET *
812 ; *** DEVICE OR MEDIA, EVENTUALLY, FAILURE TO FORMAT THE TARGET WILL *
813 ; *** TELL THAT SOURCE, TARGET DEVICE OR MEDIA ARE NOT COMPATIBLE. *
815 ;******************************************************************************
816 DISKETTE_DRV_TYPE PROC
NEAR
821 MOV CL, GETDEVPARM
;=60h
822 MOV DX, OFFSET DS_IOCTL_DRV_PARM
;POINTER TO THE CONTROL STRING
823 CALL GENERIC_IOCTL
;GET DEFAULT DEVICE PARM.
825 TEST DS_deviceAttributes
, 0001h ;CHECK REMOVABLE. 0001 = NOT REMOVABLE
826 ; $IF E,AND ;NO, CONTINUE ;AC000;
829 MOV AX, DS_numberOfCylinders
;CURRENTLY IGNORE AH. ASSUME LESS
832 MOV BX, OFFSET DS_BPB_PTR
835 MOV AX, [BX].CSECT_TRACK
836 MOV S_DRV_SECT_TRACK
, AL
837 MOV AX, [BX].CBYTE_SECT
;RECOMMENDED BYTES/SECTOR
838 MOV RECOMMENDED_BYTES_SECTOR
, AX
843 MOV DX, OFFSET DT_IOCTL_DRV_PARM
844 CALL GENERIC_IOCTL
;GET DEFAULT DEVICE PARM.
846 TEST DT_deviceAttributes
, 0001h ;FIXED DISK?
847 ; $IF Z ;TARGET IS NOT FIXED DISK, OK ;AC000;
850 MOV AX, DT_numberOfCylinders
852 MOV BX, OFFSET DT_BPB_PTR
855 MOV AX, [BX].CSECT_TRACK
856 MOV T_DRV_SECT_TRACK
, AL
858 ;**NOW, CHECK SOURCE, TARGET DEVICE COMPATIBILITY
859 MOV DX, FINE
;GUESS, ALL WILL BE OK
860 ; DX MAY BE CHANGED TO REFLECT ERROR
861 CMP DS_deviceType
, DRV_720
;0 - 48 TPI, 5.25", 96 TPI,
862 ; 5.25", 2 - 720kb, 3.5"
863 ; $IF E ;WILL ONLY ALLOW DISKCOPY BETWEEN ;AC000;
865 ; 720KB, 3.5 SOURCE, TARGET
867 CMP DT_deviceType
, DRV_720
;target = 720KB also?
870 MOV DX, OFFSET MSGNUM_NOT_COMPATIBLE
;AC000;
873 ; $ELSE ;SINCE SOURCE NOT 720 ;AC000;
876 CMP DT_deviceType
, DRV_720
;SOURCE IS NOT 720kb,
878 ; $IF E ;IF SO, THEN ;AC000;
880 ;DDT IS NOT COMPATIBLE
881 MOV DX, OFFSET MSGNUM_NOT_COMPATIBLE
; ;AC000;
886 ; $ELSE ;SINCE SOURCE IS FIXED DISK, ERROR ;AC000;
889 MOV DX, OFFSET MSGNUM_INVALID_DRV
;ISSUE BAD DRV MSG ;AC000;
895 DISKETTE_DRV_TYPE ENDP
896 HEADER
<CHECK_REDIRECTION
- IS DEVICE REDIRECTED?
> ; ;AN000;
897 ;******************************************************************************
898 ; SUBROUTINE NAME : CHECK_REDIRECTION FIND OUT IF DEVICE IS REDIRECTED *
899 ; IF IT IS, GENERATE ERROR MSG & EXIT *
900 ; INPUT : BL - DRIVE TO BE TESTED *
901 ; : AL : CURRENT DEFAULT DRIV *
903 ; OUTPUT : DX = LOCAL_DRV (-1) *
904 ; = DIRECTED ( ERROR MSG OFFSET) *
905 ; = INVALID_DRIVE (ERROR MSG OFFSET) *
906 ;******************************************************************************
907 CHECK_REDIRECTION PROC
NEAR
909 PUSH AX ;SAVE REGISTERS
913 MOV CX,DX ;SAVE RET TEMPORARILY
914 MOV AH,IOCTL_FUNC
;GET IOCTL FUNTION &
915 MOV AL,REDIRECTED_FUNC
;IOCTL SUB-FUNCTION ******CHECK***
917 INT 21H
;AND GO FIND OUT IF IT'S LOCAL
920 MOV CX,OFFSET MSGNUM_INVALID_DRV
;REDIR INVALID ;AC000;
925 TEST DX,REMOTE_DRV
;IF DRIVE IS REDIRECTED
929 MOV CX,OFFSET MSGNUM_DRV_REDIRECTED
; ;AC000;
934 MOV DX,CX ;GET ERROR MSG @
936 POP CX ;RESTORE REGISTERS
939 RET ;RETURN TO CALLER
940 CHECK_REDIRECTION ENDP
941 HEADER
<BUFFER_SIZE
- FINDS START
AND END OF BUFFER
> ; ;AN000;
942 ;******************************************************************************
943 ; SUBROUTINE NAME : BUFFER_SIZE DETERMINES WHERE BUFFER STARTS & ENDS *
946 ; OUTPUT : BUFFER_BEGIN ADDRESS *
947 ; : BUFFER_END ADDRESS *
948 ;******************************************************************************
949 BUFFER_SIZE PROC
NEAR
952 PUSH AX ;SAVE REGISTERS
955 MOV BX, offset init
;GET ADDR OF INIT + 1024 AS
957 add bx, 1024 ;(OFFSET FROM CS, IN BYTES)
958 MOV CL,4 ;CONVERT OFFSET INTO SEGMT BY DIVIDING
961 MOV AX,CS ;CS + OFFSET => INIT+1024@ IN SEGMENT
962 ADD BX,AX ;WHERE BUFFER CAN START
964 ;NEED TO START AT A NEW SECTOR ==>
965 AND BL,CLEAR_SEGMENT
;TRUNCATE TO PREVIOUS 512 BYTE BOUNDRY
966 ;(GET PREVIOUS SECTOR NUMBER)
967 ADD BX,20H
;THEN, ADVANCE TO THE BEGINNING OF
968 ;NEXT SECTOR (SINCE PART OF PREVIOUS
971 MOV BUFFER_BEGIN
,BX ;SAVE OUR BUFFER START SEGMENT ADDR
972 ;(AT THE BEGINNING OF A SECTOR WITH
973 ;SEGMENT BITS CLEARED)
975 MOV BX,DS:TWO
;GET ADDR WHERE BUFFER ENDS
976 MOV BUFFER_END
,BX ;(TOP OF MEMORY, OFFSET 2 IN PSP)
978 POP CX ;RESTORE REGISTERS
981 RET ;RETURN TO CALLER
983 HEADER
<SETUP_CTRL_BREAK
- SETUP THE CTRL
-BREAK VECTOR
> ; ;AN000;
984 ;******************************************************************************
985 SETUP_CTRL_BREAK PROC
NEAR ;SETUP CTRL-BREAK VECTOR
986 ;******************************************************************************
992 MOV AX,SET_CTL_BREAK_VECT
;SET THE CTRL-BREAK VECTOR
993 MOV DX,OFFSET MAIN_EXIT
1002 SETUP_CTRL_BREAK ENDP
1003 HEADER
<CHECK_SERVER
- IS SERVER
OR REDIRECTOR LOADED?
> ; ;AN000;
1004 ;******************************************************************************
1005 CHECK_SERVER PROC
NEAR ;SEE IF SERVER OR REDIRECTOR IS IN++
1007 ; INPUT: BL = DRIVE NUMBER (1=A,2=B ETC....)
1008 ;******************************************************************************
1009 MOV AH,0 ;SEE IF SERVER LOADED
1019 ADD BL,"A" ;CONVERT TO ASCII DRIVE LETTER
1020 MOV ASCII_DRIVE_LETTER
,BL ;PUT IN ASCIIZ STRING
1021 MOV SI,OFFSET ASCII_DRIVE_LETTER
1027 MOV DX,OFFSET MSGNUM_DRV_REDIRECTED
; ;AC000;
1039 COPYINIT_END
LABEL NEAR
1042 PATHLABL COPYINIT
;AN015;