Попытка написать всеобъемлющий метод для определения типа диска Windows, используя C ++ - PullRequest
1 голос
/ 16 февраля 2012

Я встречал тонну неуправляемых C ++ / MFC примеров людей, пытающихся определить тип диска по его пути DOS, но, похоже, существует много путаницы по поводу того, как это должно быть сделано.Поэтому я пытаюсь объединить всю информацию в одну функцию и сделать то, что Microsoft должна была сделать для нас давным-давно.

Мне в основном нужно отнести все современные диски к этим:

  • Фиксированный диск
  • Съемный диск
  • Носитель
  • Другое (см. Пояснения в коде)

Может кто-нибудь проверить мой кодниже?

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;

}

1 Ответ

2 голосов
/ 16 февраля 2012

Microsoft уже написала именно эту функцию (хотя они не разбили категории по-разному)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...