📄 diskinfo.c
字号:
/*********************************************************************
* Microsoft Diagnostics Version 2.0
*
* A diagnostic utility to detect as much useful information about a
* customer's computer system as is possible.
*
* Microsoft Diagnostics: We detect the World.
*
* DISKINFO.C - Source file for obtaining disk drive information.
********************************************************************/
/* Include Files */
#include "msd.h"
/*********************************************************************
* GetDiskInfo - Gets the disk information.
*
* pDisk - Pointer to disk information structure.
* fMinimumInfo - TRUE if minimum info is requested.
*
* Returns: TRUE if an error occured.
*********************************************************************/
BOOL GetDiskInfo (DISK_STRUCT *pDisk, BOOL fMinimumInfo)
{
BYTE i; /* Looping variable */
BYTE bCurrentDrive; /* Stores the current drive number */
BYTE bLastDrive; /* Last drive number in the system */
WORD wDriveIndex; /* Index to the table of drive info */
union REGS inregs, outregs; /* Register structures for int86() calls */
struct SREGS sregs; /* Segment registers for int86x() calls */
BOOL fSingleFloppy; /* TRUE if there is only one floppy drive */
BOOL fSkipSizeTest; /* TRUE if size test should be skipped */
BOOL fUseBiosCall = TRUE; /* IOCTL 0Dh failed, use BIOS call */
BYTE FAR *fbSingleFloppyIsB = (BYTE FAR *) 0x00400104;
/* if on a single floppy system, this */
/* byte is == 1 if the floppy is acting */
/* as drive B: */
WORD wDosVersion; /* DOS Version (ie 3.30 == 330) */
WORD wDriveType; /* Local variable for drive type */
WORD wNmbrFloppies = 0; /* Number of floppies (for INT 13h) */
WORD wNmbrFixedDisks = 0; /* Number of hard disks (for INT 13h) */
/* Set the local DOS version variable */
wDosVersion = wDosMajor * 100 + wDosMinor;
/* Zero out the disk drive information structure */
memset (pDisk, '\0', sizeof (DISK_STRUCT));
/* Get the list of installed programs and data */
if (fMinimumInfo == FALSE)
GetDiskProgList (pDisk, wDosVersion);
/* Determine the number of physical floppies in the A:-B: range */
int86 (0x11, &inregs, &outregs);
/* Bit 0 is a flag indicating if floppies are present. If set, */
/* bits 6-7 show the count of floppies in the system. */
if ((outregs.x.ax & 0x0001) && (outregs.x.ax & 0x00C0) == 0x0000)
fSingleFloppy = TRUE;
else
fSingleFloppy = FALSE;
/* Store the current drive number */
bCurrentDrive = DosGetCurrentDrive();
pDisk->chCurrentDrive = (CHAR) (bCurrentDrive + 'A');
/* Determine the last valid drive to check */
bLastDrive = DosSetCurrentDrive (bCurrentDrive);
pDisk->chLastDrive = (CHAR) (bLastDrive + 'A' - 1);
/* Begin counting up the valid drives */
for (i = 0; i < bLastDrive; ++i)
if (ValidDrive (i))
{
/* Default to performing the size test */
fSkipSizeTest = FALSE;
/* If this is a single floppy, and it's acting as B: */
/* skip the A: check. */
if (fSingleFloppy && *fbSingleFloppyIsB == 1 && i == 0)
continue;
/* If this is a single floppy, and it's acting as A: */
/* skip the B: check. */
if (fSingleFloppy && *fbSingleFloppyIsB != 1 && i == 1)
continue;
/* Bump the count of valid drives */
wDriveIndex = (WORD) (pDisk->wNmbrDrives)++;
/* Store the drive letter of the valid drive */
pDisk->asdi[wDriveIndex].chDriveLetter = (CHAR) (i + 'A');
/* Check to see if drives are removable or not */
inregs.x.ax = 0x4408;
inregs.h.bl = (BYTE) (i + 1);
int86 (0x21, &inregs, &outregs);
/* CF is clear if IOCTL call was successful */
if (outregs.x.cflag == 0)
{
/* AX == 0000h means it's a removable drive */
if (outregs.x.ax == 0x0000)
{
pDisk->asdi[wDriveIndex].wDriveType = DISK_FLOPPY_DRIVE;
strcpy (pDisk->asdi[wDriveIndex].szDriveType,
paszDriveTypes[DISK_FLOPPY_DRIVE]);
}
else
{
pDisk->asdi[wDriveIndex].wDriveType = DISK_FIXED_DISK;
strcpy (pDisk->asdi[wDriveIndex].szDriveType,
paszDriveTypes[DISK_FIXED_DISK]);
}
}
else
{
/* Something went wrong. If this is DOS 3.0 assume */
/* it as a "Remote Drive" */
if (wDosVersion == 300)
{
pDisk->asdi[wDriveIndex].wDriveType = DISK_REMOTE_DRIVE;
strcpy (pDisk->asdi[wDriveIndex].szDriveType,
paszDriveTypes[DISK_REMOTE_DRIVE]);
}
}
/* If this is DOS 3.1 or better, we can tell for sure if it's */
/* a remote drive. */
if (wDosVersion >= 310)
{
inregs.x.ax = 0x4409;
inregs.h.bl = (BYTE) (i + 1);
int86 (0x21, &inregs, &outregs);
/* CF is clear if IOCTL call was successful */
if (outregs.x.cflag == 0)
{
if (outregs.x.dx & 0x8000)
{
/* Drive is SUBSTutited */
pDisk->asdi[wDriveIndex].wDriveType = DISK_SUBST_DRIVE;
strcpy (pDisk->asdi[wDriveIndex].szDriveType,
paszDriveTypes[DISK_SUBST_DRIVE]);
pDisk->fSubstInstalled = TRUE;
}
else if (outregs.x.dx & 0x1000)
{
/* Check to see if this is a MSCDEX CD-ROM drive */
inregs.x.ax = 0x150B;
inregs.x.cx = i;
int86 (0x2F, &inregs, &outregs);
if (outregs.x.bx == 0xADAD && outregs.x.ax != 0x0000)
{
/* Drive is a CD-ROM drive */
pDisk->asdi[wDriveIndex].wDriveType =
DISK_CD_ROM_DRIVE;
strcpy (pDisk->asdi[wDriveIndex].szDriveType,
paszDriveTypes[DISK_CD_ROM_DRIVE]);
}
else
{
/* Drive is remote */
pDisk->asdi[wDriveIndex].wDriveType =
DISK_REMOTE_DRIVE;
strcpy (pDisk->asdi[wDriveIndex].szDriveType,
paszDriveTypes[DISK_REMOTE_DRIVE]);
}
}
if (outregs.x.dx & 0x0200)
{
/* Direct access is not allowed. Skip the size test */
fSkipSizeTest = TRUE;
}
}
}
/* That's all for minimum info */
if (fMinimumInfo)
continue;
/* If this is DOS 3.2 or better, we can use IOCTL call 0Dh, */
/* Generic Block Device Request. This is where a great */
/* deal of useful information can be found. Unfortunately */
/* this call may require that the disk be "hit." */
if (wDosVersion >= 320)
{
BYTE abParamBlock[256]; /* Parameter block buffer */
BYTE FAR *fbByte = NULL; /* Far pointer to a byte */
WORD *pwWord = NULL; /* WORD pointer */
/* Prepare for the Generic Block Device Request */
fbByte = abParamBlock;
/* Clear out the register structure */
memset (&inregs, '\0', sizeof (union REGS));
inregs.x.ax = 0x440D;
inregs.h.bl = (BYTE) (i + 1);
inregs.x.cx = 0x0860;
sregs.ds = FP_SEG (fbByte);
inregs.x.si = FP_SEG (fbByte);
inregs.x.dx = FP_OFF (fbByte);
inregs.x.di = FP_OFF (fbByte);
int86x (0x21, &inregs, &outregs, &sregs);
/* CF is clear if IOCTL call was successful */
if (outregs.x.cflag == 0)
{
/* Set the disk type */
if (pDisk->asdi[wDriveIndex].wDriveType != DISK_SUBST_DRIVE &&
abParamBlock[1] < 0x0A)
{
wDriveType = abParamBlock[1] + 2;
pDisk->asdi[wDriveIndex].wDriveType = wDriveType;
strcpy (pDisk->asdi[wDriveIndex].szDriveType,
paszDriveTypes[wDriveType]);
}
/* Set the number of cylinders */
pwWord = (WORD *) &abParamBlock[4];
pDisk->asdi[wDriveIndex].wCylinders = *pwWord;
/* Set the bytes per sector */
pwWord = (WORD *) &abParamBlock[7];
pDisk->asdi[wDriveIndex].wBytesPerSector = *pwWord;
/* Set the sectors per track */
pwWord = (WORD *) &abParamBlock[20];
pDisk->asdi[wDriveIndex].wSectorsPerTrack = *pwWord;
/* Set the number of heads */
pwWord = (WORD *) &abParamBlock[22];
pDisk->asdi[wDriveIndex].wHeads = *pwWord;
/* BIOS Call is not necessary, we have the data */
fUseBiosCall = FALSE;
}
else if (pDisk->asdi[wDriveIndex].wDriveType ==
DISK_FLOPPY_DRIVE)
{
/* The IOCTL call failed on a floppy drive. */
/* Use the BIOS call instead */
fUseBiosCall = TRUE;
}
else if (pDisk->asdi[wDriveIndex].wDriveType ==
DISK_FIXED_DISK)
{
/* This is a special case drive. For now, I'll */
/* assume all special case drives are RAM Disks */
pDisk->asdi[wDriveIndex].wDriveType = DISK_RAM_DISK;
strcpy (pDisk->asdi[wDriveIndex].szDriveType,
paszDriveTypes[DISK_RAM_DISK]);
/* BIOS call will not be used on this drive type */
fUseBiosCall = FALSE;
}
}
if (wDosVersion < 320)
{
/* This is DOS 3.1 or lower. Use the BIOS call */
fUseBiosCall = TRUE;
}
/* BIOS Call to determine disk characteristics */
if (fUseBiosCall)
{
if (pDisk->asdi[wDriveIndex].wDriveType == DISK_FLOPPY_DRIVE)
{
/* Get the info for the floppy drive */
inregs.h.ah = 0x08;
inregs.h.dl = (BYTE) wNmbrFloppies;
int86x (0x13, &inregs, &outregs, &sregs);
if (outregs.x.cflag == 0 &&
outregs.h.dl > (BYTE) wNmbrFloppies);
{
/* Award and AMI BIOS may have bits 10-11 */
/* of cylinder number in DH bits 6-7 */
pDisk->asdi[wDriveIndex].wHeads =
outregs.h.dh & 0x3F + 1;
pDisk->asdi[wDriveIndex].wCylinders =
(WORD) outregs.h.ch +
((((WORD) outregs.h.cl) & 0xC0) << 2) + 1;
/* Set the floppy type */
switch (outregs.h.bl)
{
case 1:
pDisk->asdi[wDriveIndex].wDriveType =
DISK_525_360K;
strcpy (pDisk->asdi[wDriveIndex].szDriveType,
paszDriveTypes[DISK_525_360K]);
break;
case 2:
pDisk->asdi[wDriveIndex].wDriveType =
DISK_525_12M;
strcpy (pDisk->asdi[wDriveIndex].szDriveType,
paszDriveTypes[DISK_525_12M]);
break;
case 3:
pDisk->asdi[wDriveIndex].wDriveType =
DISK_35_720K;
strcpy (pDisk->asdi[wDriveIndex].szDriveType,
paszDriveTypes[DISK_35_720K]);
break;
case 4:
pDisk->asdi[wDriveIndex].wDriveType =
DISK_35_144M;
strcpy (pDisk->asdi[wDriveIndex].szDriveType,
paszDriveTypes[DISK_35_144M]);
break;
}
}
}
else
{
/* This is a fixed disk. Check to see if */
/* SWBIOS is installed for this drive */
inregs.h.ah = 0xF9;
inregs.h.dl = (BYTE) (wNmbrFixedDisks & 0x80);
int86 (0x13, &inregs, &outregs);
if (outregs.x.cflag == 0);
{
/* Find out the true number of cylinders */
/* for this fixed disk */
inregs.h.ah = 0xFE;
inregs.h.dl = (BYTE) (wNmbrFixedDisks + 0x80);
int86 (0x13, &inregs, &outregs);
/* True cylinder count is in DX */
pDisk->asdi[wDriveIndex].wCylinders =
outregs.x.dx + 1;
}
/* Call INT 13h/AH=08h to determine disk information */
inregs.h.ah = 0x08;
inregs.h.dl = (BYTE) (wNmbrFixedDisks + 0x80);
int86 (0x13, &inregs, &outregs);
if (outregs.x.cflag == 0 &&
outregs.h.dl > (BYTE) wNmbrFixedDisks);
{
/* Award and AMI BIOS may have bits 10-11 */
/* of cylinder number in DH bits 6-7 */
pDisk->asdi[wDriveIndex].wHeads =
outregs.h.dh & 0x3F + 1;
/* If the SWBIOS call didn't tell us the number */
/* of cylinders, get it from this call */
if (pDisk->asdi[wDriveIndex].wCylinders == 0)
{
pDisk->asdi[wDriveIndex].wCylinders =
((WORD) outregs.h.ch) +
((((WORD) outregs.h.cl) & 0xC0) << 2) +
((((WORD) outregs.h.dh) & 0xC0) << 4) + 1;
}
}
}
}
/* Free space isn't checked on floppy drives */
wDriveType = pDisk->asdi[wDriveIndex].wDriveType;
if (wDriveType == DISK_FLOPPY_DRIVE ||
wDriveType == DISK_525_360K ||
wDriveType == DISK_525_12M ||
wDriveType == DISK_35_720K ||
wDriveType == DISK_SINGLE_DENSITY_8_INCH ||
wDriveType == DISK_DOUBLE_DENSITY_8_INCH ||
wDriveType == DISK_35_144M ||
wDriveType == DISK_35_288M)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -