Contributor: DESCLIN JEAN { Desclin Jeana 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.