;*******************************************************************************
;
;  COPYPROC.ASM - companion assembly routines for COPYDISK.C
;
;  Procedures:
;
;	 unsigned volcopy (int source, int target)
;
;	    Duplicates volume label from the source drive to the target
;	    drive.  If the source drive has no label, the procedure
;	    will delete any existing label from the target.
;
;	 int drvinfo (unsigned char drive, struct drvinfo_t * drv)
;
;	    Returns a boolian value indicating the validity of the
;	    specified drive.  If valid, fills the structure pointed to
;	    by the drv parameter with information about the drive's
;	    media type, total diskspace, total allocation and free
;	    space.
;
;	 void setint24 (int *)
;
;	    Installs an interrupt 24 critical error handler.
;
;	 void restint24 (void);
;
;	    Restores old interrupt 24 critical error handler.
;
;
;*******************************************************************************

	 TITLE COPYPROC

	 .MODEL SMALL,C

	 .DATA

xfcb	 db    255		 ;xfcb flag
	 db    5 dup (0)	 ;reserved
	 db    8		 ;volume attribute byte
	 db    1		 ;drive code (0 = current)
	 db    11 dup ('?')	 ;wildcard filename and extension
	 db    25 dup (0)	 ;remainder of FCB (not used)

dtabuff  db    64 dup (0)	 ;new dta: receives search results





	 .CODE

int24	 dd    0		 ; address of original
				 ; critical error handler

cerror	 dd    0		 ; far pointer to caller's
				 ; critical error flag

drvstruct dd   0		 ; far pointer to caller's
				 ; drive info structure

cr    equ   0dh
lf    equ   0ah

prompt	 db    cr,lf,'Non-maskable Critical Error',cr,lf,'$'


volcopy  PROC USES si di ds es, Drive1:WORD, Drive2:WORD
	 ;mov	dx,seg dtabuff
	 ;mov	ds,dx
	 mov   dx,offset dtabuff
	 mov   ah,1ah		    ; set new dta address
	 int   21h

	 mov   bx,Drive2	    ; store target drive drive number (1 byte)
	 mov   xfcb+7,bl	    ; to xFCB offset 7
	 mov   dx,offset xfcb
	 mov   ah,13H		    ; Delete volume from target drive
	 int   21H

	 mov   bx,Drive1	    ; store source drive drive number
	 mov   xfcb+7,bl	    ; to xFCB offset 7
	 mov   dx,offset xfcb
	 mov   ah,11h		    ; dos find first
	 int   21h

	 cld
	 mov   cx,11		    ; max size of vol name
	 mov   si,offset dtabuff + 8  ;pos of vol name in dta
	 mov   di,offset xfcb+8
	 rep   movsb		    ; copy volume name from dta to xfcb

	 mov   bx,Drive2
	 mov   xfcb+7,bl

	 mov   dx,offset xfcb	    ; Create the new volume label file
	 mov   ah,16H		    ; on target disk
	 int   21H
	 cmp   al,00h		    ; error, prob empty volume name
	 jne   novol
	 mov   dx,offset xfcb	    ; Close the file
	 mov   ah,10H
	 int   21H
novol:	 mov   ah,0
	 ret
volcopy  ENDP

drvinfo  PROC USES bx ds di si, Drive:BYTE, DrvStru:PTR WORD
	 mov   ax,DrvStru
	 mov   word ptr cs:drvstruct,ax
	 mov   word ptr cs:drvstruct+2,ds

	 mov   dl,Drive
	 mov   ah,1ch		       ; get drive type
	 int   21h
	 cmp   al,0ffh		       ; invalid drive or critical error?
	 je    error

	 sub   ax,ax
	 mov   al,byte ptr ds:[bx]     ; points to media type info
	 lds   bx,cs:drvstruct
	 mov   word ptr ds:[bx],ax     ; store drive type in info structure

	 mov   ah,36h		       ; get drive allocation information
	 mov   dl,Drive
	 int   21h
	 cmp   ax,0ffffh	       ; invalid drive or critical error?
	 jne   szok
error:	 cld
	 mov   ax,0		       ; reset info structure to NULLs
	 mov   cx,7
	 mov   di,word ptr cs:drvstruct
	 rep   stosw
	 jmp   errexit		       ; return FALSE

szok:	 ; get total disk size
	 push  ax		       ; sectors per cluster
	 push  bx		       ; available clusters
	 push  dx		       ; clusters per drive
	 pop   bx
	 mul   cx
	 mul   bx
	 lds   bx,cs:drvstruct
	 mov   word ptr ds:[bx+2], ax  ; lDiskSpace   (ax * cx * dx)
	 mov   word ptr ds:[bx+4], dx

	 ; get total free
	 pop   bx
	 pop   ax
	 mul   cx
	 mul   bx
	 lds   bx,cs:drvstruct
	 mov   word ptr ds:[bx+10], ax ; lDiskFree    (ax * bx * cx)
	 mov   word ptr ds:[bx+12], dx

	 ; calculate total allocated
	 mov   ax,word ptr ds:[bx+4]
	 sub   ax,word ptr ds:[bx+12]
	 xchg  ax,dx
	 mov   ax,word ptr ds:[bx+2]
	 sub   ax,word ptr ds:[bx+10]
	 jnc   skip
	 dec   dx
skip:	 mov   word ptr ds:[bx+6], ax  ; lDataSize
	 mov   word ptr ds:[bx+8], dx

	 mov   ax,1		       ; return TRUE
errexit: ret

drvinfo ENDP

setint24 PROC USES ds di si, cflag:PTR WORD
	 mov   ax,cflag
	 mov   word ptr cs:cerror,ax
	 mov   word ptr cs:cerror+2,ds

	 mov   ax,3524h 	       ; get critical error interrupt vector
	 int   21h

	 mov   word ptr cs:int24,bx
	 mov   word ptr cs:int24+2,es

	 push  cs
	 pop   ds
	 mov   dx,offset @code:criterr ; install our handler
	 mov   ax,2524h
	 int   21h

	 ret
setint24 ENDP

restint24 PROC USES ds di si
	 lds   dx,cs:int24
	 mov   ax,2524h 	       ; restore int 24 handler
	 int   21h
	 ret
restint24 ENDP

criterr  proc  far
	 push  bx
	 push  cx
	 push  dx
	 push  si
	 push  di
	 push  bp
	 push  ds
	 push  es
	 test  ah, 00000001b	       ; test for non-disk error (e.g. re-
	 jz    setflag		       ; direction to off-line printer, etc)
abort:	 mov   ax,seg prompt
	 mov   ds,ax
	 mov   es,ax
	 mov   dx,offset prompt        ; display prompt
	 mov   ah,9
	 int   21h
	 mov   al,2		       ; return ABORT code to dos kernel
	 jmp   exit
setflag: lds   bx,cs:cerror	       ; set critical error flag
	 mov   word ptr ds:[bx],1
ignore:  mov   al,0		       ; return IGNORE code to dos kernel
exit:	 pop   es
	 pop   ds
	 pop   bp
	 pop   di
	 pop   si
	 pop   dx
	 pop   cx
	 pop   bx
	 iret
criterr  endp

	 END
