(* Extended GetDriveType for Windows 3.0/3.1. Code ported the C in Microsoft PSS document Q105922. Doug Wegscheid 3/22/94. *) {$DEFINE TEST} { undefine to make a unit } {$IFDEF TEST} program drivetyp; uses wincrt, windos, winprocs, wintypes; {$ELSE TEST} unit drivetyp; interface {$ENDIF} { Return values of GetDriveTypeEx(). } const EX_DRIVE_INVALID = 0; EX_DRIVE_REMOVABLE = 1; EX_DRIVE_FIXED = 2; EX_DRIVE_REMOTE = 3; EX_DRIVE_CDROM = 4; EX_DRIVE_FLOPPY = 5; EX_DRIVE_RAMDISK = 6; {$IFNDEF TEST} function GetDriveTypeEx (nDrive : integer) : integer; implementation uses windos, winprocs, wintypes; {$ENDIF} { See the "MS-DOS Programmer's Reference" for further information about this structure. It is the structure returned with an IOCTL $0D function, $60 subfunction (get device parameters). } type DeviceParams = record bSpecFunc : byte; { Special functions } bDevType : byte; { Device type } wDevAttr : word; { Device attributes } wCylinders : word; { Number of cylinders } bMediaType : byte; { Media type } { Beginning of BIOS parameter block (BPB) } wBytesPerSec : word; { Bytes per sector } bSecPerClust : byte; { Sectors per cluster } wResSectors : word; { Number of reserved sectors } bFATs : byte; { Number of FATs } wRootDirEnts : word; { Number of root-directory entries } wSectors : word; { Total number of sectors } bMedia : byte; { Media descriptor } wFATsecs : word; { Number of sectors per FAT } wSecPerTrack : word; { Number of sectors per track } wHeads : word; { Number of heads } dwHiddenSecs : longint; { Number of hidden sectors } dwHugeSectors : longint; { Number of sectors if wSectors == 0 } { End of BIOS parameter block (BPB) } end; function GetDeviceParameters (nDrive : integer; var dp : DeviceParams) : boolean; (* //----------------------------------------------------------------- // GetDeviceParameters() // // Fills a DeviceParams struct with info about the given drive. // Calls DOS IOCTL Get Device Parameters (440Dh, 60h) function. // // Parameters // nDrive Drive number 0 = A, 1 = B, 2 = C, and so on. // dp A structure that will contain the drive's parameters. // // Returns TRUE if it succeeded, FALSE if it failed. //----------------------------------------------------------------- *) var r : TRegisters; begin fillchar(r,sizeof(r),#0); { clean up registers to avoid GPF } r.ax := $440d; { IOCTL } r.ch := $08; { block device } r.cl := $60; { get device parameters } r.bx := nDrive + 1; { 1 = A:, 2 = B:, etc... } r.ds := seg(dp); r.dx := ofs(dp); { where... } msdos(r); GetDeviceParameters := (r.flags and fCarry) = 0 end; function IsCDRomDrive (nDrive : integer) : boolean; (* //----------------------------------------------------------------- // IsCDRomDrive() // // Determines if a drive is a CD-ROM. Calls MSCDEX and checks // that MSCDEX is loaded, and that MSCDEX reports the drive is a // CD-ROM. // // Parameters // nDrive Drive number 0 = A, 1 = B, 2 = C, and so forth. // // Returns TRUE if nDrive is a CD-ROM drive, FALSE if it isn't. //----------------------------------------------------------------- *) var r : TRegisters; begin fillchar(r,sizeof(r),#0); { clean up registers to avoid GPF and to ensure that BX = $ADAD would not be by accident } r.ax := $150b; { MSCDEX installation check } { This function returns whether or not a drive letter is a CD-ROM drive supported by MSCDEX. If the extensions are installed, BX will be set to ADADh. If the drive letter is supported by MSCDEX, then AX is set to a non-zero value. AX is set to zero if the drive is not supported. One must be sure to check the signature word to know that MSCDEX is installed and that AX has not been modified by another INT 2Fh handler. } r.cx := nDrive; { 0 = A:, 1 = B:, etc... } intr ($2f, r); { do it } IsCDRomDrive := (r.bx = $adad) and (r.ax <> 0) end; (* //----------------------------------------------------------------- // GetDriveTypeEx() // // Determines the type of a drive. Calls Windows's GetDriveType // to determine if a drive is valid, fixed, remote, or removeable, // then breaks down these categories further to specific device // types. // // Parameters // nDrive Drive number 0 = A, 1 = B, 2 = C, etc. // // Returns one of: // EX_DRIVE_INVALID -- Drive not detected // EX_DRIVE_REMOVABLE -- Unknown removable-media type drive // EX_DRIVE_FIXED -- Hard disk drive // EX_DRIVE_REMOTE -- Remote drive on a network // EX_DRIVE_CDROM -- CD-ROM drive // EX_DRIVE_FLOPPY -- Floppy disk drive // EX_DRIVE_RAMDISK -- RAM disk //----------------------------------------------------------------- *) function GetDriveTypeEx (nDrive : Integer) : integer; var dp : DeviceParams; utype : integer; begin fillchar (dp, sizeof(dp), #0); { clear the DPB } uType := GetDriveType(nDrive); { make a rough guess } case uType of DRIVE_REMOTE: { GetDriveType() reports CD-ROMs as Remote drives. Need to see if the drive is a CD-ROM or a network drive. } if IsCDRomDrive (nDrive) then GetDriveTypeEx := EX_DRIVE_CDROM else GetDriveTypeEx := EX_DRIVE_REMOTE; DRIVE_REMOVABLE: { Check for a floppy disk drive. If it isn't, then we don't know what kind of removable media it is. For example, could be a Bernoulli box or something new... DOS 6.0 Reference says devicetype 0=320/360kb floppy, 1=1.2Mb, 2=720kb, 3=8" single density, 4=8" double density, 7=1.44Mb, 8=optical, 9=2.88Mb. Code in Q105922 didn't pick up bDevType=9. } if GetDeviceParameters (nDrive, dp) and (dp.bDevType in [0..4,7..9]) then GetDriveTypeEx := EX_DRIVE_FLOPPY else GetDriveTypeEx := EX_DRIVE_REMOVABLE; DRIVE_FIXED: { GetDeviceParameters returns a device type of 0x05 for hard disks. Because hard disks and RAM disks are the two types of fixed-media drives, we assume that any fixed- media drive that isn't a hard disk is a RAM disk. } if GetDeviceParameters (nDrive, dp) and (dp.bDevType = 5) then GetDriveTypeEx := EX_DRIVE_FIXED else GetDriveTypeEx := EX_DRIVE_RAMDISK; else GetDriveTypeEx := EX_DRIVE_INVALID end end; {$IFDEF TEST} var i, d : integer; begin for i := 0 to 25 do begin d := GetDriveTypeEx(i); if d <> EX_DRIVE_INVALID then begin write (chr(i + ord('A')), ': '); case GetDriveTypeEx(i) of EX_DRIVE_REMOVABLE: Writeln ('Removable'); EX_DRIVE_FIXED: Writeln ('Harddisk'); EX_DRIVE_REMOTE: Writeln ('Network'); EX_DRIVE_CDROM: Writeln ('CDROM'); EX_DRIVE_FLOPPY: Writeln ('Floppy'); EX_DRIVE_RAMDISK: Writeln ('RAMdisk') end end end {$ENDIF} end.