2012-02-16 3 views
2

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

я в основном нужно классифицировать все современные приводы к ним:

  • Фиксированный привод
  • Съемный диск
  • Медиа привод
  • Другое (см объяснение в коде)

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

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

codereview.stackexchange.com? –

+1

Есть двусмысленности. SCSI можно считать фиксированным или съемным, нет возможности различать SATA и eSATA и т. Д. Я думаю, это зависит от того, что вы пытаетесь выполнить и насколько точны вы хотите. – Luke

+0

@ Luke Да, я согласен, что SATA и eSATA будут двусмысленными. Итак, как насчет остальных? – ahmd0

ответ

2

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

+0

Извините, это нисходящее. GetDriveType работает надежно только для CD/DVD-приводов (см. Мой пример выше). В остальном он в основном возвращает DRIVE_FIXED (даже для очевидного USB-накопителя). – ahmd0

+0

@ ahmd0: Я думаю, кто-то уже указал, что eSATA является съемным. Для USB на самом деле есть USB-диски с фиксированным диском (которые имеют таблицу разделов) и формат гибких дисков. «фиксированный» диск не означает несъемный. –

+1

«Исправлено» означает (для Microsoft), что носитель установлен на диске, а не на жесткий диск, установленный на ПК (который, как указано, не может быть определен в любом случае). – MSalters

 Смежные вопросы

  • Нет связанных вопросов^_^