⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 diskinfo.c

📁 Dos6.0
💻 C
📖 第 1 页 / 共 3 页
字号:
/*********************************************************************
 * 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 + -