Programming Environment: Windows XP
Compilers: Borland C++ Builder 6 (Personal)/Borland C++ 5.5 (freebie)

This is a routine that queries the logical drives in the system, along with their device types, local/network status and whether or not the devices are removable. Once the data are gathered, the caller's selection parameters are matched against the device data and those matching devices and their characteristics are returned to the caller.

#if !defined(__DEVTAB_I)
#define __DEVTAB_I
#include <windows.h> // For GetDriveTypeA()
#include <dos.h>
// It's a personal quirk - My private includes are all .i rather than .h
#include "initarr.i" // initialize array (name,#elements,value)
#include "curdrvs.i" // List of current drives from GetLogicalDrives()
                     // This routine is included here at the bottom
#include "diskdata.i"// getdfree() + enhancements (used for bytes/sector)

// Minimum call to devtab fills drive numbers (0-25) and types (1-4)
// Call may be made with 3, 4 or 5 arguments
// network/local status and removability can be requested
int devtab(int type,int dskid[],int drtyp[],int drnet[]);
int devtab(int type,int dskid[],int drtyp[]);

// The base routine assumes all 4 types of info requested
// dskid values are 0-25, drtyp values are 1-4,
// drnet values are 0/1,  drrmv values are 0/1
int devtab(int type,int dskid[],int drtyp[],int drnet[],int drrmv[])
{
// Return types from GetDriveTypeA()
const int Unknown     = 0;
const int NoRootDrive = 1;
const int Removable   = 2; 
const int LocalDisk   = 3; 
const int Network     = 4; 
const int CDrom       = 5; 
const int RAMDrive    = 6;
// Windows.h Drive Type Defines
// #define DRIVE_UNKNOWN     0
// #define DRIVE_NO_ROOT_DIR 1
// #define DRIVE_REMOVABLE   2
// #define DRIVE_FIXED       3
// #define DRIVE_REMOTE      4
// #define DRIVE_CDROM       5
// #define DRIVE_RAMDISK     6

// My drive type designations
const int Floppy      = 1;
const int Disk        = 2;
const int Cd          = 3;
const int Usb         = 4; // Non-floppy removable disks = USB

int i,j,k;
int numdisk;
int bs;
char drv[27];
int typ;
char drive[4]="?:\\"; // Data format for call to GetDriveInfoA

int FLOP=1,DISK=2,CD=4,USB=8,ALL=16,REMOVABLE=32,LOCAL=64,NETWORK=128;
// Calls here are in the form: drvcnt = devtab(LOCAL|DISK,a,b,c,d)
//                                    = devtab(NETWORK|CD, ......
//                                    = devtab(CD|USB|FLOP, ......

// Set drives to ALL if no drive specifcation (type = 0)
typ = type;
typ = typ & (NETWORK-1); 
typ = typ & (LOCAL-1);
if (typ == 0)
   type = type | ALL;

// If neither LOCAL nor NETWORK specified, default to both
if ((type & NETWORK) != NETWORK && (type & LOCAL) != LOCAL)
   {
   type = type | NETWORK;
   type = type | LOCAL;
   }

initarr(dskid,26,0);
initarr(drtyp,26,0);
initarr(drnet,26,0);
initarr(drrmv,26,0);

// Retrieve a list of drive letters in the system
// Fill all available drive data
// Next step filters from these what the caller wants to see
numdisk = getdrv(drv);

for (i=0; i<numdisk; i++)
   {
   dskid[i] = drv[i]-'A'; // Just return drive number, not letter
   drive[0] = drv[i];
   drrmv[i] = 0;
   drnet[i] = 0;
   k = GetDriveTypeA(drive);
   if (k == DRIVE_FIXED)
      drtyp[i] = Disk;
   else
   if (k == DRIVE_REMOTE)
      {
      drtyp[i] = Disk; // Assume disk
      drnet[i] = 1;
      getdiskdata(drv[i]-'A'+1,NULL,NULL,NULL,&bs); // Get bytes/sector
      // Network attached CDs show up as Disks according to GetDriveTypeA
      if (bs != 512) // Disks are 512 bytes/sector.
         drtyp[i] = Cd; 
      // Could also call GetVolumeInformationA() and check filesystem
      }
   else
   if (k == DRIVE_CDROM)
      drtyp[i] = Cd;
   else
   if (k == DRIVE_REMOVABLE)
      {
      if (i > 1)
         drtyp[i] = Usb;
      else
         drtyp[i] = Floppy;
      drrmv[i] = 1;
      }
         
   }
// Select the drives matching the caller's criteria
j = -1;
for (i=0; i<numdisk; i++)
   {
   // Get a match on device type
   if (
      ((type & ALL) == ALL ||
      (type & FLOP) ==  FLOP && drtyp[i]  == Floppy ||
      (type & DISK) ==  DISK && drtyp[i]  == Disk ||
      (type & CD) ==  CD && drtyp[i]  == Cd ||
      (type & USB) == USB && drtyp[i] == Usb ||
      (type & REMOVABLE) == REMOVABLE && drrmv[i])
      &&
      ((type & NETWORK) == NETWORK && drnet[i] ||
       (type & LOCAL) == LOCAL && !drnet[i])
      )
      {
      j++;
      dskid[j] = dskid[i];
      drtyp[j] = drtyp[i];
      drnet[j] = drnet[i];
      drrmv[j] = drrmv[i];
      }
   }
return j+1; // actual number of drives being returned
}
// User doesn't want removable status, make call using dummy remove array
int devtab(int type,int diskno[],int drtype[],int remote[])
{
int remove[26]; // dummy so far as caller is concerned
return(devtab(type,diskno,drtype,remote,remove));
}
// User only wants drive numbers and types. Make full call with dummy arrays
int devtab(int type,int diskno[],int drtype[])
{
int remote[26]; // dummy
int remove[26]; // dummy
return(devtab(type,diskno,drtype,remote,remove));
}
#endif

// Here's the routine that gets the list of logical drives
#if !defined(__GETDRV_I)
#define __GETDRV_I
#include <direct.h>
#include <dos.h>
#include <windows.h> // For GetLogicalDrives()
// Take advantage of overloading to allow calls with different data types
// to routines with the same names.
int getdrv(int drv[]); // INT  prototype
int getdrv(char drv[]);// CHAR prototype

int getdrv(int drv[]) // Fill int array with drive letters (0-25 +'A')
{
int drvs = GetLogicalDrives();
// low order bit on = drive A present, etc.
// 1101 = Drives D:, C: and A:, no B: drive.
// DCBA
int i,j,k;


i=-1; // drive #
j=-1; // array index
while(drvs)
   {
   i++;
   if (drvs & 1)
      {
      j++;
      drv[j] = i+'A';
      }
   drvs >>=1;
   }
return j+1;
}
int getdrv(char drv[]) // Fill string with drive letters
{
int drvs = GetLogicalDrives();
int i,j;


i=-1;
j=-1;
while(drvs)
   {
   i++;
   if (drvs & 1)
      {
      j++;
      drv[j] = i+'A';
      }
   drvs >>=1;
   }
drv[j+1] = '\0'; // Terminate string
return j+1;
}
#endif

#include "curdrvs.i" should be ignored. It is no longer used by devtab. It should be changed to #include "getdrv.i"