	PAGE	90,132			;A2
	TITLE	COPYINIT -- DISKCOPY INITIALIZATION PROGRAM
;****************** START OF SPECIFICATIONS *****************************
; MODULE NAME: COPYINIT

; DESCRIPTIVE NAME: Initialization for Diskette to diskette copy Utility

;FUNCTION: DISKCOPY is to copy the contents of the diskette in the
;	   specified source drive to the diskette in the target
;	   drive.  If necessary, the target diskette is also
;	   formatted.

;	   Multiple copies may be performed with one load of DISKCOPY.
;	   A prompt, "Copy another (Y/N)?" permits additional
;	   executions, all with the same drive specifications.

; ENTRY POINT: "DISKCOPY" at ORG 100h, jumps to "BEGIN".

; INPUT: (DOS command line parameters)
;	 [d:][path]DISKCOPY [d: [D:]][/1]

;	 Where

;	 [d:][path] before DISKCOPY to specify the drive and path that
;		    contains the DISKCOPY command file.

;	 [d:]	    to specify the source drive id

;	 [D:]	    to specify the destination drive id

;	 [/1]	    to request single sided operations only

; 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 copied, including the unused
;	   sectors.  There is no awareness of the separate files
;	   involved.  A unique volume serial number is generated
;	   for the target diskette.

; INCLUDED FILES:
;	INCLUDE DCPYMACR.INC
;	INCLUDE DISKCOPY.EQU
;	INCLUDE PATHMAC.INC		;PATHGEN MACRO

; INTERNAL REFERENCES:
;    ROUTINES:
;	INIT - INITIALIZATION ROUTINE, MAIN PROGRAM
;	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 LOG. DRIV NO. WHO OWNS 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:
;	 DCOPYSM.SAL - Defines the control blocks that describe the messages
;	 DCOPYPAR.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 COPYINIT,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 DISKCOPY.

;PROGRAM AUTHOR: Original written by: JK
;		 4.00 modifications by: EMK
;****************** END OF SPECIFICATIONS *****************************
	IF1
	    %OUT    COMPONENT=DISKCOPY, MODULE=COPYINIT.SAL
	ENDIF

;DATE:	 9-22-83
;TIME:	 8:00 PM
;DATE:	 10-30-84 - chk_para routine added. many parts are modified to
;	 permit DISKCOPY /1, DISKCOPY D: /1 cases. Restore diskbase
;	 before return to DOS when invalid DOS version occurs.
;DATE:	 3-27-85  MAIN PARTS OF DISKCOPY PROGRAM HAS BEEN REWRITTEN
;	 TO USE NEW IOCTL FUNCTION CALLS - READ, WRITE AND FORMAT.

	INCLUDE DCPYMACR.INC
	INCLUDE PATHMAC.INC		;AN015;PATHGEN MACRO

CSEG	SEGMENT PARA PUBLIC 'CODE'	;AN000;
	ASSUME	CS:CSEG, DS:CSEG, ES:CSEG, SS:CSEG

	INCLUDE DISKCOPY.EQU
;$salut (4,2,9,41)
;****************************************************************************
;									    *
;			 EXTERNAL VARIABLES				    *
;									    *
;****************************************************************************

 EXTRN	PARSER:NEAR			;DCOPYPAR.SAL - DRIVES SYS PARSER	;AN000;

 EXTRN	RECOMMENDED_BYTES_SECTOR:WORD	;SOURCE DRIVE DEFAULT BYTES/SECTOR
 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	MSGNUM_INVALID_DRV:BYTE 	;"INVALID DRIVE SPECIFICATION"		;AC000;
 EXTRN	MSGNUM_NOT_COMPATIBLE :BYTE	;"DEVICE TYPE OF DISKETTE TYPES NOT COMPATIBLE";AC000;
 EXTRN	MSGNUM_DRV_REDIRECTED:BYTE	;"INVALID, DRIVE REDIRECTED"		;AC000;


 EXTRN	SUBLIST_8	     :WORD	;					;AN000;
 EXTRN	SUBLIST_9	     :WORD	;					;AN000;
 EXTRN	SUBLIST_13	     :WORD	;					;AN000;
 EXTRN	SUBLIST_17A	     :WORD	;					;AN000;
 EXTRN	SUBLIST_17B	     :WORD	;					;AN000;
 EXTRN	SUBLIST_17C	     :WORD	;					;AN000;
 EXTRN	SUBLIST_19C	     :WORD	;					;AN000;
 EXTRN	SUBLIST_19D	     :WORD	;					;AN000;
 EXTRN	SUBLIST_19E	     :WORD	;					;AN000;
 EXTRN	SUBLIST_26A	     :WORD	;					;AN001;
 EXTRN	SUBLIST_26B	     :WORD	;					;AN001;
 EXTRN	SUBLIST_PARSE:WORD		;PARSE ERROR XX - %0			     ;AN003;

.XLIST
;EXTRN	MSG_INVALID_PARM_PTR:BYTE	;"INVALID PARAMETER"
;EXTRN	MSG_INVALID_DOS :BYTE		;"INVALID DOS"
.LIST
 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	SOURCE_DRIVE :BYTE		;SRC DRV LOGICAL NUMBER
 EXTRN	TARGET_DRIVE :BYTE		;TARGET DRV LOGICAL NUMBER
 EXTRN	COPY_TYPE :BYTE 		;1 = 1-DRIVE COPY  2 = 2-DRIVE COPY
 EXTRN	USER_OPTION :BYTE		;NO OPTION (-1)  /1 (1), INVALID (9)
 EXTRN	BUFFER_BEGIN :WORD		;STARTING BUFFER @ FOR LOADING
 EXTRN	BUFFER_END :WORD		;ENDING BUFFER @ FOR LOADING
 EXTRN	MAIN_EXIT :WORD 		;EXIT ADDRESS FOR CONTROL-BREAK

 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	GENERIC_IOCTL :NEAR
 EXTRN	SET_LOGICAL_DRIVE :NEAR

;		   $salut (4,20,24,41)	;					;AN000;
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 TOTAL # OF SECTORS
					;   INC. BOOT SECT, DIRECTORIES
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


;****************************************************************************
;									    *
;			 VARIABLE DECLARATIONS				    *
;									    *
;****************************************************************************
DRIVE_VALID	   DW  ?		;DRIVE VALIDITY INDICATOR
DEFAULT_DRV	   DB  ?		;DEFAULT DRIVE ID (0=A,1=B,ETC)
NUMBER_OF_DRV	   DB  ?		;TOTAL # OF DISKT DRIVES ON THE SYS
					;(NUMBER_OF_DRV = 0 ---> 1 DRIVE)
ASCII_DRIVE_LETTER DB  " :",0
		   PATHLABL COPYINIT	;AN015;
		   HEADER <INIT - INITIALIZATION ROUTINE, MAIN PROGRAM> ;	;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

;		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		;AN000;
	MOV   SUBLIST_8.SUB_VALUE_SEG,AX ;					;AN000;
	MOV   SUBLIST_9.SUB_VALUE_SEG,AX ;					;AN000;
	MOV   SUBLIST_13.SUB_VALUE_SEG,AX ;					;AN000;
	MOV   SUBLIST_17A.SUB_VALUE_SEG,AX ;					;AN000;
	MOV   SUBLIST_17B.SUB_VALUE_SEG,AX ;					;AN000;
	MOV   SUBLIST_17C.SUB_VALUE_SEG,AX ;					;AN000;
	MOV   SUBLIST_19C.SUB_VALUE_SEG,AX ;					;AN000;
	MOV   SUBLIST_19D.SUB_VALUE_SEG,AX ;					;AN000;
	MOV   SUBLIST_19E.SUB_VALUE_SEG,AX ;					;AN000;
	MOV   SUBLIST_26A.SUB_VALUE_SEG,AX ;					;AN001;
	MOV   SUBLIST_26B.SUB_VALUE_SEG,AX ;					;AN001;
	MOV   SUBLIST_PARSE.SUB_VALUE_SEG,AX ;					;AN003;

	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
;	 CALL  CHK_PARA 		 ; GENERAL SYNTAX CHECK
.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	;SET UP TO USE THE DRIVE LETTERS	;AN000;

	    CALL  TEST_DRIVE_VALIDITY

	    CMP   DX,FINE
;	    $IF   E			;					;AN000;
	    JNE $$IF2
		CALL  DISKETTE_DRV_TYPE ;SOURCE & TARGET DRIVE TYPES

		CMP   DX,FINE		;IF FINE & DANDY
;		$IF   E 		;					;AN000;
		JNE $$IF3
		    CALL  BUFFER_SIZE	;GET BUFFER SIZE FOR COPYING

;		$ENDIF			;					;AN000;
$$IF3:
;	    $ENDIF			;					;AN000;
$$IF2:
;	$ENDIF				;					;AN000;
$$IF1:
EXIT_INIT:				;DX <-- 1  IF INIT OK
	RET				;DX <-- ERROR OFFSET IF NOT OK
					;RETURN TO CALLER
INIT	ENDP				;END INITIALLIZATION PROGRAM

.XLIST
;	 HEADER <SCREENING - CHECK DOS VERSION, SYNTAX PARMS>
;******************************************************************************
; SUBROUTINE NAME :  SCREENING	- CHECKS THE FOLLOWING: 		      *
;				  - DOS VERSION 			      *
;				  - GENERAL SYNTAX CHECKING FOR PARAMETERS    *
; INPUT 	  :  NONE						      *
; 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)
					;NOTE: BX IS DESTROYED
;	XCHG	AH,AL			;AH=MAJOR VER, AL=MINOR VER
;	 CMP   AX,expected_version	 ;IF DOS MAJOR VERSION LESS THAN 3.00
;	 $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			 ;EXIT TO DOS
;	 $ELSE				 ;VERSION OK
;	     CALL  CHK_PARA		 ;GENERAL SYNTAX CHECK
;	 $ENDIF 			 ;END VERSION TEST
;	 RET
;SCREENING ENDP
;	 HEADER <CHK_PARA - SYNTAX PARMS, OPTION /1>
;**************************************************************************

;kiser: this proc is to be deleted

;CHK_PARA PROC NEAR
;	CHECK SYNTAX OF THE ENTERED PARAMETERS				  *
;	ALSO, DETERMINE THE USER OPTION "/1" IS ENTERED OR NOT. 	  *
;  INPUT: DX = FINE							  *
;	  IF /1 HAS BEEN ENTERED, THE VARIABLE USER_OPTION = OPTION_1	  *
;	  ELSE USER_OPTION = NO_OPTION. 				  *
;  OUTPUT: DX = FINE	- NO ERROR					  *
;	   OTHERWISE DX POINTS TO ERROR MSG				  *
;**************************************************************************
;	 PUSH  CX
;	 MOV   USER_OPTION, NO_OPTION	 ;ASSUME NO /1 IS ENTERED.
;	 XOR   CX, CX
;	 MOV   CL, BYTE PTR DS:BEGIN_UNFORM_AREA ;GET # OF CHR
;	 CMP   CL, 0
;	 $IF   NZ
;	     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
;
;	     $IF   NZ			 ;SOMETHING OTHER THAN BLANKS
;					 ; ARE ENTERED
;		 CALL  CHK_SLASH_ONE	 ;IS NEXT WORD /1 ?
;
;		 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. DISKCOPY D:)
;		 CALL  CHK_SLASH_ONE	 ;IS NEXT WORD /1 ?
;
;		 JNC   SLASH_ONE	 ;YES.(EX. DISKCOPY 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. DISKCOPY D:  )
;		 CALL  CHK_SLASH_ONE	 ;IS IT A /1 ?
;
;		 JNC   SLASH_ONE	 ;YES. (EX. DISKCOPY D:  /1)
;		 CALL  CHK_DRV_SPEC	 ;IF NOT /1, 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. DISKCOPY D: D:)
;		 CALL  CHK_SLASH_ONE	 ;OTHERWISE, IT SHOULD BE /1.
;
;		 JNC   SLASH_ONE	 ;YES, /1. JMP TO SLASH_ONE
;		 JMP   INVALID_PARA	 ;PARAMETER ERROR.
;SLASH_ONE:
;		 MOV   USER_OPTION, OPTION_1 ;YES, /1 HAS BEEN ENTERED.
;		 CALL  SKIP_BLANKS	 ;/1 SHOULD BE END OF PARAMETERS, OR ONLY BLANKS CAN FOLLOW.
;
;		 $IF   NZ
;INVALID_PARA:
;		     MOV   DX,OFFSET MSG_INVALID_PARM_PTR ;WRONG PARM ENTERED MSG
;		 $ENDIF
;	     $ENDIF
;	 $ENDIF
;CHK_PARA_EXIT:
;	 POP   CX
;
;	 RET
;CHK_PARA ENDP
;	 HEADER <SKIP_BLANKS - IGNORE BLANKS/TABS IN PARMS PARSING>
;***************************************************************************
;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.	   *
;***************************************************************************
;	 $DO
;	     MOV   AL, 20H		 ;20H=BLANK
;	     CLD			 ;CLEAR DIRECTION
;	     REPE  SCASB
;	 $LEAVE Z			 ;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
;	 $LEAVE NZ			 ;IF THE NON_BLANK CHR IS NOT A TAB THEN EXIT
;	     INC   DI			 ;ELSE TRY SKIP AGAIN
;	     DEC   CX
;	 $ENDDO
;	 RET
;SKIP_BLANKS ENDP
;	 HEADER <CHK_SLASH - IS CURRENT PARM /1>
;***************************************************************************

;kiser: this proc is to be deleted

;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.
;	 $IF   NL,AND			 ;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 ?
;	 $IF   Z			 ;IF NOT, THEN SET CARRY AND EXIT
;	     INC   DI			 ;ADJUST CX, DI TO THE NEXT CHR
;	     INC   DI
;	     DEC   CX
;	     DEC   CX
;	     CMP   CX, 0		 ;IF NO MORE CHR, THEN SET ZERO FLAG.
;	 $ELSE
;	     STC			 ;NOT FOUND, SET CARRY FLAG.
;	 $ENDIF
;	 RET
;CHK_SLASH_ONE ENDP
;	 HEADER <CHK_DRV - CURRENT PARM CHAR IS DRIVE AND COLON?>
;***************************************************************************

;kiser: this proc is to be deleted

;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.
;	 $IF   NL,AND			 ;IF NOT LESS THAN 2, THEN FOUND
;					 ;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'
;	 $IF   NB,AND			 ;NOT BELOW 'A', THEN MAYBE FOUND OK
;
;	 CMP   AL, 'Z'
;	 $IF   NA,AND			 ;NOT ABOVE 'Z', THEN FOUND
;
;	 MOV   AL, ES:BYTE PTR [DI+1]	 ;LOOK AHEAD THE FOLLOWING CHR.
;	 CMP   AL, ':'			 ;SHOULD BE A COLON.
;	 $IF   Z			 ;IF 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.
;	 $ELSE
;	     STC			 ;SET CARRY
;	 $ENDIF
;	 RET
;CHK_DRV_SPEC ENDP
;	 HEADER <CHK_BLANK - IS CURRENT CHAR IN PARM BLANK OR TAB>
;***************************************************************************

;kiser: this proc is to be deleted

;CHK_BLANK PROC NEAR
;; ** CHECK THE CURRENT CHR IS A BLANK OR 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.
;	 $IF   L,OR			 ;GO SET CARRY AND EXIT
;
;	 MOV   AL, ES:BYTE PTR [DI]	 ;GET CURRENT CHR
;	 CMP   AL, 020H 		 ;020H=BLANK CHR
;	 $IF   NZ,AND			 ;NOT FOUND
;	 CMP   AL, 09H			 ;09H=TAB CHR
;	 $IF   NZ			 ;NOT FOUND EITHER
;
;					 ;THEN NOT FOUND
;	     STC			 ;SET CARRY
;	 $ELSE				 ;CHAR MUST BE EITHER TAB OR BLANK
;	     INC   DI			 ;FOUND. ADJUST DI, CX
;	     DEC   CX
;	 $ENDIF
;	 RET
;CHK_BLANK ENDP
.LIST
	HEADER <SOURCE_TARGET_DRV - CONV. SRC/TARGET DRV TO BIOS VALUES> ;	;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			      *
;			  2 = DRV B	     3 = DRV C ETC		      *
;									      *
;									      *
; OUTPUT	  :  DEFAULT_DRV: CURRENT DEFAULT DRIVE 		      *
;			   0 - DRIVE A		 1 - DRIVE B		      *
;			   2 - DRIVE C		 3 - DRIVE D		      *
;									      *
;		  :  SOURCE_DRIVE	   1 = DRIVE A	  2 = DRIVE B  ETC.   *
;		  :  TARGET_DRIVE	   1 = DRIVE A	  2 = DRIVE B  ETC.   *
;		       (UNCHANGED)					      *
;******************************************************************************
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
	INC   AL			;NOW A=1, B=2, ETC			;AN000;
	CMP   SOURCE_DRIVE,ZERO 	;FIRST DRV ENTERED?			;AC000;
;	$IF   E 			;NO DRIVE LETTER ENTERED
	JNE $$IF7
	    MOV   SOURCE_DRIVE,AL	;USE DEFAULT DRIVE AS SOURCE		;AC000;
	    MOV   TARGET_DRIVE,AL	; AND AS TARGET 			;AC000;
;	$ELSE
	JMP SHORT $$EN7
$$IF7:
	    CMP   TARGET_DRIVE,ZERO	;WAS THE SECOND DRIVE ID SPECIFIED?	;AC000;
;	    $IF   E			;NO, SO TARGET DRV IS DEFAULT		;AC000;
	    JNE $$IF9
		MOV   TARGET_DRIVE,AL	;USE DEFAULT DRIVE AS TARGET		;AC000;
;	    $ENDIF
$$IF9:
;	$ENDIF
$$EN7:
	MOV   AX,WORD PTR SOURCE_DRIVE	;SOURCE TO AL, TARGET TO AH		;AC000;
	ADD   ASCII_DRV1_ID,AL		;MAKE THE DRIVE ALPHABET READABLE
	ADD   ASCII_DRV2_ID,AH		;IN THE MESSAGE

	RET

SOURCE_TARGET_DRV ENDP
	HEADER <TEST_DRIVE_VALIDITY - ARE SOURCE/TARGET DRIVES VALID?> ;	;AN000;
;******************************************************************************
; SUBROUTINE NAME :  TEST_DRIVE_VALIDITY--MAKE SURE SOURCE AND TARGET DRIVES  *
;		     SPECIFIED BY USER ARE VALID FOR DISKCOPY		      *
;									      *
; INPUT 	  :  SOURCE_DRIVE:BYTE, TARGET_DRIVE:BYTE		      *
;									      *
; OUTPUT	  :  DX='FINE' IF DRIVES ARE VALID, ELSE DX CONTAINS MSG 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 $$IF12

	MOV   BL,SOURCE_DRIVE
	CALL  CHECK_REDIRECTION

	CMP   DX,FINE
;	$IF   E,AND			;					;AC000;
	JNE $$IF12

	MOV   BL,TARGET_DRIVE
	CALL  CHECK_REDIRECTION

	CMP   DX,FINE
;	$IF   E,AND			;					;AC000;
	JNE $$IF12

	MOV   BL,SOURCE_DRIVE
	CALL  CHECK_SERVER

	CMP   DX,FINE
;	$IF   E,AND			;					;AC000;
	JNE $$IF12

	MOV   BL,TARGET_DRIVE
	CALL  CHECK_SERVER

	CMP   DX,FINE
;	$IF   E,AND			;					;AC000;
	JNE $$IF12

	CALL  TEST_REMOVABLE

	CMP   DX,FINE
;	$IF   E 			;					;AC000;
	JNE $$IF12

	    CALL  CHK_SINGLE_DRV_OP	;CHECK IF IT IS
					; ONE PHYSICAL DRIVE OPERATION
;	$ENDIF				;					;AC000;
$$IF12:
	RET

TEST_DRIVE_VALIDITY ENDP
	HEADER <DOS_DRIVE_VALIDITY - CHECK DOS DRIVE VALIDITY BYTE> ;		;AN000;
;******************************************************************************
; SUBROUTINE NAME :  DOS_DRIVE_VALIDITY -- CHECK DOS DRIVE VALIDITY BYTE      *
;									      *
; INPUT 	  :  DRIVE_VALID:BYTE					      *
;									      *
; OUTPUT	  :  DX="FINE" IF DRIVES ARE VALID ELSE DX CONTAINS MESSAGE PTR *
;******************************************************************************

DOS_DRIVE_VALIDITY PROC NEAR

	CMP   DRIVE_VALID,0		;SEE IF DRIVES ARE VALID DOS DEVICE
;	$IF   NE
	JE $$IF14
	    MOV   DX,OFFSET MSGNUM_INVALID_DRV ;				;AC000;
;	$ENDIF
$$IF14:
	RET

DOS_DRIVE_VALIDITY ENDP
	HEADER <TEST_REMOVABLE - IS SPECIFIED DRIVE REMOVABLE?> ;		;AN000;
;******************************************************************************
; 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

	MOV   BL,SOURCE_DRIVE		;GET PARM 1 DRIVE ID

	MOV   AX,DRIVE_CHECK		;CHECK FOR REMOVABLE DRIVE = 4408h
	INT   21H			;IOCTL CALL
;	$IF   NC			;IF DRIVE ID IS WITHIN RANGE
	JC $$IF16
	    CMP   AX,REMOVABLE		;THEN IF SOURCE DRIVE IS FIXED
;	    $IF   NE			;  THEN
	    JE $$IF17
		MOV   DX,OFFSET MSGNUM_INVALID_DRV ;GENERATE HARD		;AC000;
					; DRIVE ERROR MESSAGE
;	    $ELSE			;ELSE, SRC IS REMOVABLE;
	    JMP SHORT $$EN17
$$IF17:
		MOV   BL,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 $$IF19
		    CMP   AX,REMOVABLE	;THEN TGT DRV IS FIXED
;		    $IF   NE		;     THEN
		    JE $$IF20
			MOV   DX,OFFSET MSGNUM_INVALID_DRV ;GENERATE HARD	;AC000;
					; DRV ERROR MSG
;		    $ENDIF		;END TEST IF TGT DRV IS FIXED
$$IF20:
;		$ELSE			;TGT DRV OUT OF RANGE.	EX. DRIVE X:
		JMP SHORT $$EN19
$$IF19:
		    MOV   DX,OFFSET MSGNUM_INVALID_DRV ;			;AC000;
;		$ENDIF			;END TEST IF TGT WITHIN RANGE
$$EN19:
;	    $ENDIF			;END IF SRC IS REMOVABLE
$$EN17:
;	$ELSE				;ELSE,	SRC DRV OUT OF RANGE
	JMP SHORT $$EN16
$$IF16:
	    MOV   DX,OFFSET MSGNUM_INVALID_DRV ;PRINT ERROR MSG 		;AC000;
;	$ENDIF				;END TEST IF SRC DRV WITHIN RANGE
$$EN16:
	RET

TEST_REMOVABLE ENDP
	HEADER <CHK_SINGLE_DRIV_OP - IS TARGET DRIVE SAME AS SOURCE?> ; 	;AN000;
;******************************************************************************
; SUBROUTINE NAME :  CHK_SINGLE_DRV_OP					      *
;									      *
; INPUT 	  :  SOURCE_DRIVE - LOGICAL DRIVE NUMBER		      *
;		     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

	PUSH  AX

	MOV   BL,SOURCE_DRIVE
	CALL  GET_LOGICAL_DRIVE

	MOV   S_OWNER_SAVED, AL 	;SAVE CURRENT OWNER DRIVE LETTER.
	MOV   BL, TARGET_DRIVE
	CALL  GET_LOGICAL_DRIVE

	MOV   T_OWNER_SAVED, AL 	;SAVE CURRENT OWNER
	MOV   BL, SOURCE_DRIVE
	CALL  SET_LOGICAL_DRIVE

	MOV   BL, TARGET_DRIVE
	CALL  SET_LOGICAL_DRIVE

	MOV   BL, SOURCE_DRIVE
	CALL  GET_LOGICAL_DRIVE 	;CHECK SOURCE DRV LETTER
					; STILL HAS A OWNERSHIP.

	CMP   AL, SOURCE_DRIVE		;
;	$IF   NE			;IF IT DOES NOT, THEN A
	JE $$IF27
					; SINGLE DRIVE COPY.
	    MOV   COPY_TYPE, ONE
	    MOV   BL, SOURCE_DRIVE
	    MOV   TARGET_DRIVE, BL	;SET TARGET DRV LETTER
					; TO THAT OF SOURCE
	    MOV   BL, ASCII_DRV1_ID
	    MOV   ASCII_DRV2_ID, BL
	    MOV   BL, SOURCE_DRIVE
	    CALL  SET_LOGICAL_DRIVE	;SET THE OWNER BACK TO
					; SOURCE DRV LETTER

;	$ELSE
	JMP SHORT $$EN27
$$IF27:
	    CMP   AL, TARGET_DRIVE	;SOURCE DRV LETTER = TARGET DRV
					; LETTER CASE, FOR EX. DISKCOPY A: A:
;	    $IF   E
	    JNE $$IF29
		MOV   COPY_TYPE, ONE
;	    $ELSE
	    JMP SHORT $$EN29
$$IF29:
		MOV   COPY_TYPE, TWO
;	    $ENDIF
$$EN29:
;	$ENDIF
$$EN27:

	POP   AX

	RET
CHK_SINGLE_DRV_OP ENDP
	HEADER <GET_LOGICAL_DRIVE - GET LOG. DRIV NO. WHO OWNS PHYS. DRIVE> ;AN000;
;******************************************************************************
GET_LOGICAL_DRIVE PROC NEAR
;	*** 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 $$IF33
	    MOV   AL, BL		;THEN SET THE INPUT DRIVE NUMBER TO AL.
;	$ENDIF
$$IF33:

	RET

GET_LOGICAL_DRIVE ENDP
	HEADER <DISKETTE_DRV_TYPE - CHECK COMPATABILITY SOURCE/TARGET DRIVES> ; ;AN000;
;******************************************************************************
; SUBROUTINE NAME :  DISKETTE_DRV_TYPE DOES THE FOLLOWING:		      *
;		     - GETS SOURCE, TARGET DRIVE INFORMATION		      *
;		     - CHECK REMOVABLE DRIVE				      *
; *** REMARK: WILL NOT ALLOW DISKCOPY BETWEEN 5.25" AND 3.5" DRIVES.	      *
; *** ALSO, IN THE MAIN PROGRAM, SOURCE MEDIA BPB INFORMATIONS (# OF SEC/TRK, *
; *** # OF TRACKS) SHOULD BE CHECKED AGAINST TARGET DEVICE INFORMATIONS.      *
; *** IF # OF SECT/TRACK, # OF TRACKS OF TARGET DEVICE ARE EQUAL TO, OR       *
; *** GREATER THAN THOSE OF THE SOURCE MEDIA BPB, THEN IT IS OK. OTHERWISE    *
; *** DEVICE NOT COMPATIBLE.						      *
; *** IF THIS DOES NOT GAURANTEES COMPATIBILITY BETWEEN SOURCE AND TARGET     *
; *** DEVICE OR MEDIA, EVENTUALLY, FAILURE TO FORMAT THE TARGET WILL	      *
; *** TELL THAT SOURCE, TARGET DEVICE OR MEDIA ARE NOT COMPATIBLE.	      *
;									      *
;******************************************************************************
DISKETTE_DRV_TYPE PROC NEAR
	PUSH  AX

	xor   bx, bx
	MOV   BL, SOURCE_DRIVE
	MOV   CL, GETDEVPARM		;=60h
	MOV   DX, OFFSET DS_IOCTL_DRV_PARM ;POINTER TO THE CONTROL STRING
	CALL  GENERIC_IOCTL		;GET DEFAULT DEVICE PARM.

	TEST  DS_deviceAttributes, 0001h ;CHECK REMOVABLE. 0001 = NOT REMOVABLE
;	$IF   E,AND			;NO, CONTINUE				;AC000;
	JNE $$IF35

	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, TARGET_DRIVE
	MOV   CL, GETDEVPARM
	MOV   DX, OFFSET DT_IOCTL_DRV_PARM
	CALL  GENERIC_IOCTL		;GET DEFAULT DEVICE PARM.

	TEST  DT_deviceAttributes, 0001h ;FIXED DISK?
;	$IF   Z 			;TARGET IS NOT FIXED DISK, OK		;AC000;
	JNZ $$IF35

	    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

;**NOW, CHECK SOURCE, TARGET 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 $$IF36
					; 720KB, 3.5 SOURCE, TARGET

		CMP   DT_deviceType, DRV_720 ;target = 720KB also?
;		$IF   NE		;					;AC000;
		JE $$IF37
		    MOV   DX, OFFSET MSGNUM_NOT_COMPATIBLE ;AC000;
;		$ENDIF			;					;AC000;
$$IF37:
;	    $ELSE			;SINCE SOURCE NOT 720			;AC000;
	    JMP SHORT $$EN36
$$IF36:
		CMP   DT_deviceType, DRV_720 ;SOURCE IS NOT 720kb,
					; IS TARGET 720?
;		$IF   E 		;IF SO, THEN				;AC000;
		JNE $$IF40
					;DDT IS NOT COMPATIBLE
		    MOV   DX, OFFSET MSGNUM_NOT_COMPATIBLE ;			;AC000;
;		$ENDIF			;					;AC000;
$$IF40:
;	    $ENDIF			;					;AC000;
$$EN36:
;	$ELSE				;SINCE SOURCE IS FIXED DISK, ERROR	;AC000;
	JMP SHORT $$EN35
$$IF35:
	    MOV   DX, OFFSET MSGNUM_INVALID_DRV ;ISSUE BAD DRV MSG		;AC000;
;	$ENDIF				;					;AC000;
$$EN35:
	POP   AX
	RET

DISKETTE_DRV_TYPE ENDP
	HEADER <CHECK_REDIRECTION - IS DEVICE REDIRECTED?> ;			;AN000;
;******************************************************************************
; 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

	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 $$IF45
	    MOV   CX,OFFSET MSGNUM_INVALID_DRV ;REDIR INVALID			;AC000;

;	$ELSE
	JMP SHORT $$EN45
$$IF45:
	    TEST  DX,REMOTE_DRV 	;IF DRIVE IS REDIRECTED
;	    $IF   NZ
	    JZ $$IF47

		MOV   CX,OFFSET MSGNUM_DRV_REDIRECTED ; 			;AC000;
;	    $ENDIF
$$IF47:
;	$ENDIF
$$EN45:
	MOV   DX,CX			;GET ERROR MSG @

	POP   CX			;RESTORE REGISTERS
	POP   BX
	POP   AX
	RET				;RETURN TO CALLER
CHECK_REDIRECTION ENDP
	HEADER <BUFFER_SIZE - FINDS START AND END OF BUFFER> ;			;AN000;
;******************************************************************************
; SUBROUTINE NAME :  BUFFER_SIZE    DETERMINES WHERE BUFFER STARTS & ENDS     *
; INPUT 	  :  NONE						      *
;									      *
; OUTPUT	  :  BUFFER_BEGIN ADDRESS				      *
;		  :  BUFFER_END   ADDRESS				      *
;******************************************************************************
BUFFER_SIZE PROC NEAR


	PUSH  AX			;SAVE REGISTERS
	PUSH  BX
	PUSH  CX
	MOV   BX, offset init		;GET ADDR OF INIT + 1024 AS
					; A START OF BUFFER
	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+1024@ 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
					;(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 - SETUP THE CTRL-BREAK VECTOR> ;		;AN000;
;******************************************************************************
SETUP_CTRL_BREAK PROC NEAR		;SETUP CTRL-BREAK VECTOR
;******************************************************************************
	PUSH  AX
	PUSH  BX
	PUSH  DX
	PUSH  ES

	MOV   AX,SET_CTL_BREAK_VECT	;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 - IS SERVER OR REDIRECTOR LOADED?> ;		;AN000;
;******************************************************************************
CHECK_SERVER PROC NEAR			;SEE IF SERVER OR REDIRECTOR IS IN++
;
; INPUT: BL = DRIVE NUMBER (1=A,2=B ETC....)
;******************************************************************************
	MOV   AH,0			;SEE IF SERVER LOADED
	INT   SERVER
	CMP   AH,0
;	$IF   E
	JNE $$IF50
	    MOV   DX,FINE
;	$ELSE
	JMP SHORT $$EN50
$$IF50:
	    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 $$IF52
		MOV   DX,OFFSET MSGNUM_DRV_REDIRECTED ; 			;AC000;
;	    $ELSE
	    JMP SHORT $$EN52
$$IF52:
		MOV   DX,FINE
;	    $ENDIF
$$EN52:
;	$ENDIF
$$EN50:
	RET
CHECK_SERVER ENDP

COPYINIT_END LABEL NEAR
	PUBLIC COPYINIT_END

	PATHLABL COPYINIT		;AN015;

CSEG	ENDS
	END
