1

ドライブのタイプを DOS パスで判別しようとしている管理されていない C++/MFC の例をたくさん見てきましたが、その方法については多くの混乱があるようです。そこで私は、すべての情報を 1 つの機能に統合し、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;

}
4

1 に答える 1

2

Microsoftはすでにその関数を正確に記述しています(ただし、カテゴリをまったく同じように分類していませんでした)

于 2012-02-16T03:52:58.363 に答える