1

我遇到了大量非托管 C++/MFC 示例,这些示例显示人们试图通过其 DOS 路径确定驱动器的类型,但对于应该如何完成似乎存在很多困惑。所以我试图将所有信息整合到一个功能中,并做微软很久以前应该为我们做的事情。

我基本上需要将所有现代驱动器分类为:

  • 固定驱动器
  • 可移动驱动器
  • 媒体驱动器
  • 其他(见代码中的解释)

有人可以在下面检查我的代码吗?

enum DRIVE_TYPE2{
    DT2_ERROR,
    DT2_FIXED_DRIVE,    //Any internal drive that cannot be removed while system is running, like a hard drive
    DT2_REMOVABLE_DRIVE,    //Removable drive. Example: Any USB drive
    DT2_MEDIA_DRIVE,    //CD/DVD drive, or a floppy drive
    DT2_OTHER,      //Other (rare) types, like virtual drive, RAM drive, etc.
};

static DRIVE_TYPE2 getDriveType(LPCTSTR pStrDriveDosPath)
{
    //Determine the drive type by its DOS path
    //'pStrDriveDosPath' = Path to the drive (example: "c:" or "d:") -- must be only a local drive letter!
    //RETURN:
    //      = One of the values from the DRIVE_TYPE2 enum
    ASSERT(pStrDriveDosPath);
    DRIVE_TYPE2 res = DT2_ERROR;

    //Make path
    CString strPath;
    strPath.Format(_T("\\\\.\\%s"), pStrDriveDosPath);

    HANDLE hDevice = CreateFile(strPath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE,
                                NULL, OPEN_EXISTING, 0, NULL);

    if ( hDevice != INVALID_HANDLE_VALUE ) 
    {
        //First check for floppy discs
        DISK_GEOMETRY Geom[20];
        DWORD cb;

        if(DeviceIoControl(hDevice, IOCTL_DISK_GET_MEDIA_TYPES, 0, 0, Geom, sizeof(Geom), &cb, 0)
            && cb > 0)
        {
            switch (Geom[0].MediaType)
            {
            case F5_1Pt2_512:   // 5.25 1.2MB floppy
            case F5_360_512:    // 5.25 360K  floppy
            case F5_320_512:    // 5.25 320K  floppy
            case F5_320_1024:   // 5.25 320K  floppy
            case F5_180_512:    // 5.25 180K  floppy
            case F5_160_512:    // 5.25 160K  floppy
            case F5_640_512:    //5.25", 640 KB, 512 bytes/sector media
            case F5_720_512:    //5.25", 720 KB, 512 bytes/sector media
            case F5_1Pt23_1024: //5.25", 1.23 MB, 1024 bytes/sector media
            case F3_1Pt44_512:  // 3.5 1.44MB floppy
            case F3_2Pt88_512:  // 3.5 2.88MB floppy
            case F3_20Pt8_512:  // 3.5 20.8MB floppy
            case F3_720_512:    // 3.5 720K   floppy
            case F3_120M_512:   //3.5", 120 MB media
            case F3_640_512:    //3.5", 640 KB, 512 bytes/sector media
            case F3_1Pt2_512:   //3.5", 1.2 MB, 512 bytes/sector media
            case F3_1Pt23_1024: //3.5", 1.23 MB, 1024 bytes/sector media
            case F3_128Mb_512:  //3.5" magneto-optical (MO), 128 MB, 512 bytes/sector media
            case F3_230Mb_512:  //3.5" magneto-optical (MO), 230 MB, 512 bytes/sector media
            case F8_256_128:    //8", 256 KB, 128 bytes/sector media
            case RemovableMedia:
                res = DT2_MEDIA_DRIVE;
                break;
            }
        }


        //Did we get the type?
        if(res == DT2_ERROR)
        {
            //Check for CD/DVD drive
            UINT nDrvType = GetDriveType(pStrDriveDosPath + CString(_T("\\")));
            switch(nDrvType)
            {
            case DRIVE_CDROM:
                //Media drive
                res = DT2_MEDIA_DRIVE;
                break;
            }


            //Did we get the type?
            if(res == DT2_ERROR)
            {
                //Then try by bus type

                DWORD dwOutBytes = 0;           // IOCTL output length
                STORAGE_PROPERTY_QUERY Query;   // input param for query

                // specify the query type
                Query.PropertyId = StorageDeviceProperty;
                Query.QueryType = PropertyStandardQuery;

                char OutBuf[1024] = {0};  // good enough, usually about 100 bytes
                PSTORAGE_DEVICE_DESCRIPTOR pDevDesc = (PSTORAGE_DEVICE_DESCRIPTOR)OutBuf;
                pDevDesc->Size = sizeof(OutBuf);

                // Query using IOCTL_STORAGE_QUERY_PROPERTY 
                if(DeviceIoControl(hDevice,                     // device handle
                                IOCTL_STORAGE_QUERY_PROPERTY,             // info of device property
                                &Query, sizeof(STORAGE_PROPERTY_QUERY),  // input data buffer
                                pDevDesc, pDevDesc->Size,               // output data buffer
                                &dwOutBytes,                           // out's length
                                (LPOVERLAPPED)NULL))
                {
                    //See by type
                    switch(pDevDesc->BusType)
                    {
                    case BusTypeAtapi:
                    case BusTypeAta:
                    case BusTypeRAID:
                    case BusTypeSas:
                    case BusTypeSata:
                        //Fixed
                        res = DT2_FIXED_DRIVE;
                        break;

                    case BusTypeScsi:
                    case BusType1394:   //Firewire
                    case BusTypeSsa:
                    case BusTypeFibre:
                    case BusTypeUsb:
                    case BusTypeiScsi:
                    case BusTypeSd:
                    case BusTypeMmc:
                        //Removable
                        res = DT2_REMOVABLE_DRIVE;
                        break;

                    case BusTypeVirtual:
                    case BusTypeFileBackedVirtual:
                        //Other
                        res = DT2_OTHER;
                        break;

                    default:
                        //Error
                        ASSERT(pDevDesc->BusType == BusTypeUnknown);
                        res = DT2_ERROR;
                        break;
                    }
                }

            }

        }

        //Close drive handle
        CloseHandle(hDevice);
    }

    return res;

}
4

1 回答 1

2

微软已经准确地编写了该功能(尽管他们没有以完全相同的方式分解类别)

于 2012-02-16T03:52:58.363 回答