Contributor: ANDREW EIGUS { (replaces old DRIVE DETECT source posted and written by Andrew Eigus and placed in one of the last SWAG archives) Howdy Everyone! The DRVTYPES.PAS Borland (Turbo) Pascal 6+ code gives you a possibility to get the specified drive type. Version 1.1 currently supports detection of fixed, removable, remote, compressed, CD-ROM and RAM-emulated disk drives. Program DRIVES.PAS demonstrates the use of the DrvTypes unit. Code written by Mr. Byte (aeigus@fgate.castle.riga.lv) Stacker4 implementation and bug fixes by Bobby Z. RAM drive check code by Janis Smits All bugfix reports, comments, wishes, support code please send to: E-mail: aeigus@fgate.castle.riga.lv Mr. Byte Fido: 2:5100/33 Thanks and we hope you enjoy this code, Mr. Byte P.S. DISCLAIMER: NO WARRANTIES ARE PROVIDED, AND AS-IS BASIS IS ASSUMED. 23.01.95 DRVTYPES.PAS - a unit {$S-,R-,I-,X+} unit DrvTypes; { drive types } interface const dtError = $00; { Bad drive } dtFixed = $01; { Fixed drive } dtRemovable = $02; { Removeable (floppy) drive } dtRemote = $03; { Remote (network) drive } dtCDROM = $04; { MSCDEX V2.00+ driven CD-ROM drive } dtDblSpace = $05; { DoubleSpace compressed drive } dtSUBST = $06; { SUBST'ed drive } dtStacker4 = $07; { Stacker 4 compressed drive } dtRAM = $08; { RAM drive } function GetDriveType(Drive : Byte) : Byte; implementation type ControlBlk25 = record { control block for INT 25 extended call } StartSector : LongInt; { start sector to read } Count : Word; { number of sectors to read } BufferOffs : Word; { data buffer offset } BufferSeg : Word; { data buffer segment } end; const checkABforStacker : boolean = False; function checkStacker4( Drive : Byte ) : Boolean; assembler; { returns True if Drive is Stacker 4 compressed volume, False otherwise. This also may return True with previous versions of Stacker - I didn't check it. /Bobby Z. 29/11/94 } var CB : ControlBlk25; Boot : array[1..512] of Byte; asm push ds mov al,Drive or checkABforStacker,0 { check A: & B: for Stacker volume? } jnz @@1 cmp al,1 ja @@1 sub al,al jmp @@Q @@1: push ss pop ds lea bx,CB sub ax,ax mov word ptr ds:ControlBlk25[bx].StartSector,ax mov word ptr ds:ControlBlk25[bx].StartSector[2],ax mov word ptr ds:ControlBlk25[bx].Count,1 lea dx,Boot mov word ptr ds:ControlBlk25[bx].BufferOffs,dx mov word ptr ds:ControlBlk25[bx].BufferSeg,ds mov al,Drive sub cx,cx dec cx mov si,sp int 25h cli mov sp,si sti pushf lea si,Boot add si,1F0h { Stacker signature CD13CD14CD01CD03 should } sub al,al { appear at offset 1F0 of boot sector. } popf jc @@Q { was error reading boot sector - assume } { not Stacker drive } cmp word ptr ds:[si],13CDh jnz @@Q cmp word ptr ds:[si][2],14CDh jnz @@Q cmp word ptr ds:[si][4],01CDh jnz @@Q cmp word ptr ds:[si][6],03CDh jnz @@Q mov al,1 @@Q: pop ds end; function GetDriveType; assembler; { Detects the type of a specified drive. Drive is a drive number, where 0=default (current) drive, 1=drive A, 2=B, ... This function will return one of the dtXXX-constants. Note: Function will work under DOS version 3.1 or later THIS CODE IS PUBLIC DOMAIN Written by Mr. Byte, 12/08/94 Additions and fixes by Bobby Z., 29/11/94 RAM drive check code by Janis Smits, 07/12/94 } asm cmp Drive,0 jne @@1 mov ah,19h { get active drive number in al } int 21h inc al mov Drive,al @@1: mov ax,1500h { check for CD-ROM v2.00+ } sub bx,bx int 2Fh or bx,bx jz @@2 mov ax,150Bh sub ch,ch mov cl,Drive int 2Fh cmp bx,0ADADh jne @@2 or ax,ax jz @@2 mov bl,dtCDROM jmp @@7 @@2: mov ax,4409h { check for SUBST'ed drive } mov bl,Drive int 21h jc @@9 test dh,10000000b jz @@9 mov bl,dtSUBST jmp @@7 @@9: mov ax,4A11h { check for DoubleSpace drive } mov bx,1 mov dl,Drive dec dl int 2Fh sub cl,cl { mov cl,False } or ax,ax { is DoubleSpace loaded? } jnz @@3 cmp dl,bl { if a host drive equal to compressed, then get out... } je @@3 test bl,10000000b { bit 7=1: DL=compressed,BL=host =0: DL=host,BL=compressed } jz @@3 { so avoid host drives, assume host=fixed :) } inc dl cmp Drive,dl jne @@3 mov bl,dtDblSpace jmp @@7 @@3: mov ax,4409h { check for remote drive } mov bl,Drive int 21h jc @@5 and dx,1000h { this is correct way to check if drive is remote one, Andrew. Your version didn't work... /Bobby Z., 29/11/94 } jz @@4 mov bl,dtRemote jmp @@7 @@4: mov al,Drive { check for Stacker 4 volume } or al,al jz @@getDrv dec al @@goStac: push ax call checkStacker4 or al,al jz @@8 mov bl,dtStacker4 jmp @@7 @@8: mov ax,4408h { check for fixed (hard) drive } mov bl,Drive int 21h jc @@5 or al,al jz @@6 push ds { check for RAM drive } mov ax,ss mov ds,ax mov si,sp sub sp,28h { allocate 28h bytes on stack } mov dx,sp mov ax,440Dh { generic IOCTL } mov cx,860h { get device parameters } mov bl,Drive int 21h { RAMDrive and VDISK don't support this command } mov sp,si pop ds mov bl,dtRAM jc @@7 mov bl,dtFixed jmp @@7 @@5: sub bl,bl { mov bl,dtError cuz dtError=0 } jmp @@7 @@getDrv: mov ah,19h int 21h jmp @@goStac @@6: mov bl,dtRemovable { else - removeable media } @@7: mov al,bl end; { GetDriveType } end. {$S-,I-,R-} uses DrvTypes; var C : Char; function FloppyDrives : byte; assembler; asm int 11h test al,00000001b jz @@1 {$IFOPT G+} shr al,6 {$ELSE} mov cl,6 shr al,cl {$ENDIF} and al,3 inc al retn @@1: xor al,al end; begin WriteLn('Drive Map Version 1.1 Written by Andrew Eigus and Bobby Z.'#13#10); for C := 'A' to 'Z' do case GetDriveType(Byte(C)-Byte('A')+1) of dtCDROM: WriteLn('Drive ', C, ': is CD-ROM drive'); dtSUBST: WriteLn('Drive ',C,': is SUBST''ed drive'); dtRAM: WriteLn('Drive ', C, ': is RAM drive'); dtRemote: WriteLn('Drive ', C, ': is remote (network) drive'); dtFixed: WriteLn('Drive ', C, ': is local hard drive'); dtRemovable: if (Byte(C) - Byte('A') + 1) in [1..FloppyDrives] then WriteLn('Drive ', C, ': is removable (floppy) drive'); dtDblSpace: WriteLn('Drive ', C, ': is DoubleSpace compressed drive'); dtStacker4: WriteLn('Drive ', C, ': is ','Stacker 4 compressed drive'); end end.