kooijman@duteca (Richard Kooijman) (10/19/90)
How do you find out what the actual number of drives is on a MS-DOS computer? I have programmed a utility like NCD. It searches all disks on the computer to build a database of directories. Later this database can be used to switch quickly to another directory. The problem is that I haven't found a descent way to search all drives. I program in Turbo C and I have used setdisk(drive) which returns the number of logical drives. On my system (40Mb harddisk with 2 partitions C: & D: and NO ramdisk) it returns 5, so it includes a drive E:. I know I can set LASTDRIVE=D: in my CONFIG.SYS, but I don't want to do that. Later I tried the function biosequip(), but it returns the number of physical drives, in my case 3 (A: B: C: or \x00, \x01, \x80 actually). I have the utility working by just trying to get the current directory of the drives, and when this fails it stops, starting at drive C: of course. Who knows a better way, thanks in advance. Richard.
dwatney@pine.circa.ufl.edu (Marshall Sutherland) (10/20/90)
In article <1085@duteca4.UUCP>, kooijman@duteca (Richard Kooijman) writes... >How do you find out what the actual number of drives is on a MS-DOS computer? The best way I have found so far is to use setdisk() and then use getdisk() to see if it was successful (if you try to go to drive D, but find you are still on drive C, then there isnt a drive D). However, this still has problems. My most common problem with it is getting the infamous Abort, Retry, Ignore when i had an external floppy D drive with no disk in it (although, I'm sure there is a way to suppress that). Other possible problems (which had never occured to me until writing this) are how to treat SUBSTed drives. Since I would start at C and go until it failed, I assume that if you had SUBSTed drives which were labeled to follow immediately after your real drives, they would get counted, while those that arent contiguous would not. Whether you want to count these as drives or not depends on your application. Well, having nearly totally undermined my method, I too, would be interested in seeing a better method, :) ----- Marshall Sutherland, Partner/Consultant, Digital Magic Computer Consulting dwatney@pine.circa.ufl.edu, dwatney@ufpine.bitnet Sysop, Farthinghale Arms BBS, (904) 378-4861
geoff@bodleian.East.Sun.COM (Geoff Arnold @ Sun BOS - R.H. coast near the top) (10/20/90)
The following little program is derived from the material in the Ralf Brown "interrupt list". It shows how to prowl the Logical Drive Table and GetRedirList outputs. Depending on your system and network, drives may show up on either or both of these. Sorry about the cryptic output: the "V" bit in the LDT means that the drive is valid. Also, you MUST compile with /AL, or all of the pointer will be screwed up. The code will adjust for DOS 3.x or 4.x correctly. Enjoy Geoff ---------------------------------------------------------------------- /* * SYS_SCAN.C * Compile with "cl /AL sys_scan.c". I use MSC5.0. */ #include <dos.h> #include <io.h> #include <stdio.h> /* The following requires that we compile with /Zp for * packed structures, or use the pragmas */ #pragma pack(1) struct dpb { unsigned char d_number; unsigned char d_unit; unsigned int d_secsize; unsigned char d_secpercl; unsigned char d_allocshf; unsigned int d_rsvsec; unsigned char d_fatnum; unsigned int d_roots; unsigned int d_data1; unsigned int d_lastcl; unsigned char d_fatsize; unsigned int d_root1; void far * d_blkdev_p; unsigned char d_mediad; unsigned char d_mediaf; struct dpb far * d_next; }; struct ldt3 { char p_path[67]; unsigned int p_flags; struct dpb far * p_dpb_p; unsigned int p_seek; unsigned int p_unknown1; unsigned int p_unknown2; unsigned int p_substptr; }; #define NETWORK_DRIVE 0x8000 #define VALID_DRIVE 0x4000 #define JOINED_DRIVE 0x2000 #define SUBST_DRIVE 0x1000 #define DRIVE_UNUSED 0 #define DRIVE_REDIRECTED 1 #define DRIVE_PERMANENT 2 #define DRIVE_INVALID 3 struct ldt4 { char p_path[67]; unsigned int p_flags; struct dpb far * p_dpb_p; unsigned int p_seek; unsigned int p_unknown1; unsigned int p_unknown2; unsigned int p_substptr; unsigned char p_unknown3[7]; }; struct dbuf { struct dpb far * s_dpb_p; void far * s_oft_p; void far * s_clkdev_p; void far * s_condev_p; unsigned int s_maxlogsec; void far * s_sbs_p; struct ldt3 far * s_ldt_p; void far * s_fcb_p; int s_fcbs; unsigned char s_logdrv; unsigned char s_lastdrv; }; static struct dbuf far * buf_p; static struct dpb far * dpb_p; static struct ldt3 far * ldt_p; static int onetime = 1; static int lastdrive; static unsigned int dos_major_version; /* * static prototypes */ static void setup_pointers(void ); static struct ldt3 far *find_drive(int n); static char get_redir_device[128]; static char get_redir_info[128]; static void display_redir_list() { int index; union REGS inregs; union REGS outregs; struct SREGS segregs; char far *dev_p; char far *info_p; printf("\n\nGetRedirectionList output:\n\n"); index = 0; dev_p = &get_redir_device[0]; info_p = &get_redir_info[0]; while(1) { inregs.h.ah = 0x5f; inregs.h.al = 2; segregs.ds = FP_SEG(dev_p); inregs.x.si = FP_OFF(dev_p); segregs.es = FP_SEG(info_p); inregs.x.di = FP_OFF(info_p); inregs.x.bx = index; intdosx(&inregs, &outregs, &segregs); if (outregs.x.cflag) break; if(outregs.h.bh & 1) printf("Entry %2d: (invalid)\n", index); else printf("Entry %2d: Type=%02X Status=%02X User=%04X Device=%s\n Info=%s\n", index, outregs.h.bl, outregs.h.bh, outregs.x.cx, get_redir_device, get_redir_info); index++; } printf("GetRedirectionList terminated after %2d entries with Error=%04X\n", index, outregs.x.ax); if(outregs.x.ax == 1) printf(" (Network not installed)\n"); if(outregs.x.ax == 18) printf(" (No more entries)\n"); } /* * -- setup_pointers -- setup_pointers -- setup_pointers -- * * setup_pointers() * */ static void setup_pointers() { union REGS inregs; union REGS outregs; struct SREGS segregs; inregs.h.ah = 0x30; /* get dos version */ intdos(&inregs, &outregs); dos_major_version = outregs.h.al; inregs.h.ah = 0x52; /* get address of list of lists */ intdosx(&inregs, &outregs, &segregs); FP_OFF(buf_p) = outregs.x.bx; FP_SEG(buf_p) = segregs.es; lastdrive = buf_p->s_lastdrv; dpb_p = buf_p->s_dpb_p; ldt_p = buf_p->s_ldt_p; onetime = 0; } /* * -- find_drive -- find_drive -- find_drive -- * * find_drive(n) * */ static struct ldt3 far * find_drive(n) int n; { struct ldt4 far *p4; if (dos_major_version == 3) return(&ldt_p[n]); p4 = (struct ldt4 far *)ldt_p; p4 = &p4[n]; return((struct ldt3 far *)p4); } main() { int i; struct ldt3 far * lp; printf("SYS_SCAN 1.0 - display key device info\n\n"); printf("Logical Drive Table\n\n"); setup_pointers(); printf("Home:%04X:%04X LDT:%04X:%04X DPB:%04X:%04X DosMaj=%d LastDrive=%d\n", FP_SEG(buf_p), FP_OFF(buf_p), FP_SEG(ldt_p), FP_OFF(ldt_p), FP_SEG(dpb_p), FP_OFF(dpb_p), dos_major_version, lastdrive); for(i = 0; i < lastdrive; i++) { lp = find_drive(i); printf("%04X:%04X %c: Flags=%04X=%c%c%c%c DPB:%04X:%04X Seek=%04X ?1=%04X ?2=%04X Subst=%04X\n", FP_SEG(lp), FP_OFF(lp), 'A'+i, lp->p_flags, (lp->p_flags & NETWORK_DRIVE ? 'N' : '-'), (lp->p_flags & VALID_DRIVE ? 'V' : '-'), (lp->p_flags & JOINED_DRIVE ? 'J' : '-'), (lp->p_flags & SUBST_DRIVE ? 'S' : '-'), FP_SEG(lp->p_dpb_p), FP_OFF(lp->p_dpb_p), lp->p_seek, lp->p_unknown1, lp->p_unknown2, lp->p_substptr); if(lp->p_flags & VALID_DRIVE) printf(".... Path=%s\n", lp->p_path); } display_redir_list(); } ---------------------------------------------------------------------- -- Geoff Arnold, PC-NFS architect, Sun Microsystems. (geoff@East.Sun.COM) -- *** "Now is no time to speculate or hypothecate, but rather a time *** *** for action, or at least not a time to rule it out, though not *** *** necessarily a time to rule it in, either." - George Bush ***
richard@calvin.spp.cornell.edu (Richard Brittain - VOS hacker) (10/20/90)
In article <1085@duteca4.UUCP> kooijman@duteca (Richard Kooijman) writes: >How do you find out what the actual number of drives is on a MS-DOS computer? >I have programmed a utility like NCD. It searches all disks on the computer >to build a database of directories. Later this database can be used to switch >quickly to another directory. The setdisk() function returns the number corresponding to the LASTDRIVE= line in config.sys, which defaults to 5 (A-E) if not given. If your definition of "drive" means any logical/physical/virtual/networked/subst/joined entity that can legally be addressed as a block device, then I recommend you test all the drives up to the LASTDRIVE= using the ioctl call for "test for fixed or removable media". This gives an error code for drives which are bogus, and a valid return for all other (real, networked, virtual, RAM, subst, etc.). Best of all though, it makes no disc access to do this, so it is very fast and never trips the critical error interrupt. I don't have my references handy, but it should be listed in any of the standard books - it's even documented!. -- Richard Brittain, School of Elect. Eng., Upson Hall Cornell University, Ithaca, NY 14853 ARPA: richard@calvin.spp.cornell.edu UUCP: {uunet,uw-beaver,rochester,cmcl2}!cornell!calvin!richard
ted@arsocomvax.socom.mil (Ted Nolan) (10/22/90)
Here's a little program we use from batch files to see if a drive is valid; with a little modification, it should do what you want. It works with MIX C, and presumably with turbo and msc. It stats a file on a disk and sees if you would have gotten "abort,retry,ignore". Ted Nolan ted@usasoc.soc.mil ---------------------------------------CUT HERE------------------------------- #include <stdio.h> #include <stdlib.h> #include <dos.h> #include <sys\stat.h> int dstatus = 0; main(int argc, char **argv) { int harderror(int error, int ax, int bp, int si); char path[15]; struct stat statbuf; if( argc != 2) { fprintf(stderr,"Usage %s d\n",argv[0]); fprintf(stderr,"Where d is a drive letter\n"); exit(1); } sprintf(path,"%s:\\foo\\bar",argv[1]); harderr(harderror); (void) stat(path,&statbuf); exit(dstatus); } int harderror(int error, int ax, int bp, int si) { dstatus = 1; hardresume(0); }