[Back to DRIVES SWAG index] [Back to Main SWAG index] [Original]

    {
    Desclin Jean <desclinj@ulb.ac.be>

     a few days ago (sorry, I didn't write down the name of the person
     who posted the question :-(), someone asked how one could
     identify a drive as a ramdisk.
     Below is a solution, which I submit with the hope that someone
     else could show how to improve on it, since it is not 'fail-safe'.
     Here it comes...

    Modified after Michael Tischer: Turbo Pascal 6 System Programming
    ABACUS Publisher Grand Rapids, MI 49512  1991 ISBN 1-55755-124-3
    I had to write the procedure Getdrives twice in order to take into
    account the changes in the DPB structure which occurred from DOS
    4.0 onwards. Mostly, Ramdisks have only one File Allocation Table,
    whereas other drive types have two. That's what a procedure such
    as GetDiskClass of TurboPower Object Professional (usual disclaimer
    here ;-)) uses to decide whether the drive is a ramdisk or not. BUT
    BEWARE! This is not necessarily so! Norton mentions, in his 'disk
    companion', that depending on the device driver of the ramdisk, one
    or two FATS may be implemented. I could verify this on 'STACKED'
    ramdisks: they have two FATS, whereas only one FAT is present after
    'unSTACKING' :-(. Thus, the solution below is somewhat shaky.
    }

    program idramdsk;
    uses
      Dos;

    var
      ver : byte;

    procedure GetDrives1;
    type
      DPBPTR    = ^DPB;                 { pointer to a DOS Parameter Block }
      DPBPTRPTR = ^DPBPTR;              { pointer to a pointer to a DPB }
      DPB       = record                { recreation of a DOS Parameter Block }
        Code   : byte;                  { drive code (0=A, 1=B etc. }
        dummy1 : array [1..$07] of byte;{irrelevant bytes}
        FatNb  : byte;                  {Number of File Allocation Tables }
        dummy2 : array [9..$17] of byte;{irrelevant bytes}
        Next   : DPBPTR;                { pointer to next DPB }
      end;                              { xxxx:FFFF marks last DPB }

    var
      Regs     : Registers;             { register for interrupt call }
      CurrDpbP : DPBPTR;                { pointer to DPBs in memory }

    begin
      {-- get pointer to first DPB ------------------------------------}
      Regs.AH := $52; {function $52 returns ptr to DOS Information Block }
      MsDos(Regs);    {that's an UNDOCUMENTED DOS function !             }
      CurrDpbP := DPBPTRPTR(ptr(Regs.ES, Regs.BX))^;

      {-- follow the chain of DPBs--------------------------------------}
      repeat
        writeln(chr(ord('A') + CurrDpbP^.Code),     {display device code }
                  ':(FATS: ', CurrDpbP^.FatNb,')'); {and number of FATs  }

        CurrDpbP := CurrDpbP^.Next;   { set pointer to next DPB        }
      until (Ofs(CurrDpbP^) = $FFFF);  { until last DPB is reached }
    end;

    procedure GetDrives2;
    type
      DPBPTR    = ^DPB;                 { pointer to a DOS Parameter Block }
      DPBPTRPTR = ^DPBPTR;              { pointer to a pointer to a DPB }
      DPB       = record                { recreation of a DOS Parameter Block }
        Code   : byte;                  { drive code (0=A, 1=B etc. }
        dummy1 : array [1..$07] of byte;{irrelevant bytes}
        FatNb  : byte;                  { Number of File Allocation Tables}
        dummy2 : array [9..$18] of byte;{irrelevant bytes}
        Next   : DPBPTR;                { pointer to next DPB }
      end;                              { xxxx:FFFF marks last DPB }

    var
      Regs     : Registers;             { register for interrupt call }
      CurrDpbP : DPBPTR;                { pointer to DPBs in memory }

    begin
      {-- get pointer to first DPB-------------------------------------}
      Regs.AH := $52; {function $52 returns ptr to Dos Information Block }
      MsDos(Regs);    {that's an UNDOCUMENTED DOS function !             }
      CurrDpbP := DPBPTRPTR(ptr(Regs.ES, Regs.BX))^;

      {-- follow the chain of DPBs -------------------------------------}
      repeat
        {output device letter and number of FATs (1 for RAM disks)   }
        writeln(chr(ord('A') + CurrDpbP^.Code), ':(FATS: ', CurrDpbP^.FatNb, ')');
        CurrDpbP := CurrDpbP^.Next;    { set pointer to next DPB        }
      until (Ofs(CurrDpbP^) = $FFFF);  { until last DPB is reached }
    end;

    begin
      ver := Lo(DosVersion);
      writeln(#13#10'Installed drives: '#13#10);
      if ver < 4 then
        GetDrives1
      else
        GetDrives2
    end.

[Back to DRIVES SWAG index] [Back to Main SWAG index] [Original]