[Back to WIN-OS2 SWAG index] [Back to Main SWAG index] [Original]

    (*
            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.

[Back to WIN-OS2 SWAG index] [Back to Main SWAG index] [Original]