rob@cs.mu.oz.au (Robert Wallen) (07/31/90)
I'm writing a program that displays a window showing a list of "A:,B:, C: ..." for the user to select a drive from. Problem is how do you work out what drives are installed in a system. I can can get the number of floppies from the equipment list function. If I ask DOS the max. drive number I always get 5 drives. I have been thinking of reading the partition map to see how many drives are on 1 hard disk, but this seems like overkill and wouldn't work for machines that have 2 physical hard disks. It would also be possible to read a sector from each disk to see if the disk was there but this would take ages. What would you do to identify and networked volumes? Seems like someone must have done this before. Can anyone help? Thanks in advance, Rob Wallen
feit@cs.odu.edu (Mark A. Feit) (08/01/90)
In article <3102@murtoa.cs.mu.oz.au> rob@cs.mu.oz.au (Robert Wallen) writes: I'm writing a program that displays a window showing a list of "A:,B:, C: ..." for the user to select a drive from. Problem is how do you work out what drives are installed in a system. I can can get the number of floppies from the equipment list function. If I ask DOS the max. drive number I always get 5 drives. The five-drives thing is just how the user has MAXDRIVE set... We have ours set to 'n', which will yield 16. Obviously, this is no good. I have been thinking of reading the partition map to see how many drives are on 1 hard disk, but this seems like overkill and wouldn't work for machines that have 2 physical hard disks. That it is. It would also be possible to read a sector from each disk to see if the disk was there but this would take ages. What would you do to identify and networked volumes? No need to do anything special, really... IMHO, applications should be able to use networked drives just like anything else, so long as they're properly attached. Takes one more headache out of support when somebody calls up bawling "it won't work on my Novell system." Seems like someone must have done this before. Can anyone help? Yep on both counts. Try this on for size: -------------8<-----Trim Here------------------ #define DEBUGdrive_is_valid 0 /* 01 to show diags on stderr */ #define DR_INVALID 0 #define DR_VALID 1 #define DR_DONTREAD 2 /* drive_is_valid() * * Determine if a drive (named by 'drive') exists or not. If it's A or B, * go through the BIOS to see if it physically exists (avoiding DOS's "Insert * dist for drive B" messages). Otherwise, go through DOS. * * Return Value: DR_INVALID (0) if the drive is not valid. * DR_VALID if Valid. * Result will be ORed with DR_DONTREAD is the drive * is not able to be read bust exists anyway. */ static int drive_is_valid( char drive ) { union REGS regs; struct diskinfo_t disk_tee; unsigned i; #if DEBUGdrive_is_valid fprintf( stderr, "drive_is_valid( %c )\n", drive ); #endif drive = toupper( drive ); /* Check for physical A: or B:, go through DOS for anything else. */ if ( (drive == 'A') || (drive == 'B') ) { #if DEBUGdrive_is_valid fprintf( stderr, "drive_is_valid() Going through BIOS\n" ); #endif disk_tee.drive = toupper(drive) - 'A'; disk_tee.head = 1; disk_tee.track = 1; disk_tee.sector = 1; disk_tee.nsectors = 1; disk_tee.buffer = NULL; i = _bios_disk( _DISK_VERIFY, &disk_tee ) >> 8; #if DEBUGdrive_is_valid fprintf( stderr, "drive_is_valid() _bios_disk returned %04x\n", i ); #endif /* If error or invalid, try again */ switch ( i ) { /* Nada Problemo */ case 0x00: case 0x06: /* Disk's been changed, big deal */ #if DEBUGdrive_is_valid fprintf( stderr, "drive_is_valid() Drive OK (No error)\n" ); #endif return DR_VALID; /* Errors where the drive is invalid */ case 0x07: case 0x0C: case 0x20: case 0xBB: case 0xE0: #if DEBUGdrive_is_valid fprintf( stderr, "drive_is_valid() DRIVE IS INVALID.\n" ); #endif return DR_INVALID; /* Everything else (Not ready, etc.) */ default: { #if DEBUGdrive_is_valid fprintf( stderr, "drive_is_valid() Drive OK but not readable.\n" ); #endif } return DR_VALID|DR_DONTREAD; } } #if DEBUGdrive_is_valid fprintf( stderr, "drive_is_valid() Checking through DOS\n" ); #endif /* Check anything C: or greater by going through DOS */ regs.h.ah = 0x36; /* DOS Get diskfree */ regs.h.dl = drive - '@'; /* 0=Default, 1=A, etc */ int86( 0x21, ®s, ®s ); /* Call DOS */ #if DEBUGdrive_is_valid fprintf( stderr, "drive_is_valid() Drive is %s\n", ( regs.x.ax != 0xffff ? "VALID" : "INVALID" ) ); #endif return ( regs.x.ax != 0xffff ? DR_VALID : DR_INVALID ); } -------------8<-----Trim Here------------------ A little explanation is in order for this routine. First, it goes through the BIOS for A and B to see if the drives physically exist. I didn't want that "Insert disk for drive B, press ENTER" message to pop up on the screen and mess things up, so that's how that works. For anything C: or greater (okay, so I didn't take having three floppies into account, but that;s a rarity these days and this code will work with it anyway), it goes through DOS to get the free space. If it fails for any reason other than being invalid (not ready, etc), the routine will return DR_VALID ORed with DR_DONTREAD. Hope this helps. - Mark ................................... ................................... : Mark A. Feit : feit@cs.odu.edu : : Old Dominion University CS Dept. : feit@xanth.UUCP : : Norfolk, Virginia, U.S.A., Earth : "So where's my lunch, anyway?" : ................................... ................................... Y :)8 G-G-G-D-E-C -- - Mark ................................... ................................... : Mark A. Feit : feit@cs.odu.edu : : Old Dominion University CS Dept. : feit@xanth.UUCP : : Norfolk, Virginia, U.S.A., Earth : "So where's my lunch, anyway?" : ................................... ................................... Y :)8 G-G-G-D-E-C
gchamber@nfsun.UUCP (Glenn Chambers) (08/01/90)
In article <FEIT.90Jul31140200@oswald.cs.odu.edu> feit@cs.odu.edu (Mark A. Feit) writes: >A very nice bit of work to determine whether a drive exists or not. > >/* drive_is_valid() > * > * Determine if a drive (named by 'drive') exists or not. If it's A or B, > * go through the BIOS to see if it physically exists (avoiding DOS's "Insert > * dist for drive B" messages). Otherwise, go through DOS. > * > * Return Value: DR_INVALID (0) if the drive is not valid. > * DR_VALID if Valid. > * Result will be ORed with DR_DONTREAD is the drive > * is not able to be read bust exists anyway. > */ >static int drive_is_valid( char drive ) >{ > /* Code omitted for brevity. */ >} The code works quite nicely in a non-networked environment. I don't have access to a Novell net, so the following comments may not apply in that case. In PC-NFS networks (using in my case the software sold by Sun Microsystems) drives between the last physical drive, and drive 'V' are created by the network driver, then 'mounted' from the file server. This mount process assigns remote file systems to any unused device in the list. It is therefore possible to have the following as the 'valid' device list: A: C: D: E: N: O: V: (I.e. a floppy disk, 3-partition hard disk, "new software", "old software", and network printer (pc-nfs uses drives t-v to map lpt1-3)). Attempting to access an allocated but unmounted drive produces the dreaded 'Abort, Retry, Ignore' dialog. The solution involves writing a dummy Critical Error Handler for DOS, that always returns 'fail', instead of prompting the user. I wrote one once, but that project got shelved, and I can't lay my hands on the code at the moment. I'm sure one of the net.msdos.gods can provide details on how to write the beast. I seem to remember that MSC includes some type of support but I can't remember. If it's any consolation, the various WINDOWS versions we've played with over the years don't even try to get it right. They blithely display drive K in the directory window, even though there is nothing mounted on that drive. -------------- Glenn Chambers This is me speaking. Intelligent Technology Group If my company were speaking, Pittsburgh, PA. my lips wouldn't be moving. gchamber@nfsun.UUCP or ...!uunet!nfsun!gchamber
TOMIII@MTUS5.BITNET (Thomas Dwyer III) (08/01/90)
You can get gobs of neat information from INT 21, AH=52. To find the
number of block devices (drives) in a system, look at offset 20h from
the pointer returned by ES:BX.
Example:
#include <dos.h>
main()
{
union REGS regs;
struct SREGS sregs;
unsigned char far *ptr;
regs.h.ah = 0x52;
intdosx(®s, ®s, &sregs);
ptr = (unsigned char far *) (((unsigned long) sregs.es<<16)+regs.x.bx);
printf("Number of block devices: %d\n", (int) *(ptr+0x20));
printf("Value of LASTDRIVE: %d\n", (int) *(ptr+0x21));
return(0);
}