Как проверить наличие карты памяти в картридере?

Тема в разделе "WASM.WIN32", создана пользователем drem1lin, 12 дек 2017.

Метки:
  1. drem1lin

    drem1lin Member

    Публикаций:
    0
    Регистрация:
    17 мар 2009
    Сообщения:
    288
    Всем привет, пишу программу, которая при включении смотрит подключенные съемные USB устройства хранения. И в результате, список устройств с именами я получаю (использую SetupApi) и кроме флэшек я, также, нахожу еще два картридера (которые пустые), как программно отличить пустой картридер от флэшки? Самый банальный путь я знаю - попробовать считать или записать что-то, но он мне не нравится. Наверняка должно быть более красивое решение.
     
  2. Thetrik

    Thetrik UA6527P

    Публикаций:
    0
    Регистрация:
    25 июл 2011
    Сообщения:
    423
    1. GetVolumeInformation и GetLastError() == ERROR_NOT_READY
    2. IOCTL_STORAGE_CHECK_VERIFY
     
    drem1lin нравится это.
  3. drem1lin

    drem1lin Member

    Публикаций:
    0
    Регистрация:
    17 мар 2009
    Сообщения:
    288
    Благодарю.
     
  4. drem1lin

    drem1lin Member

    Публикаций:
    0
    Регистрация:
    17 мар 2009
    Сообщения:
    288
    Что бы не плодить дополнительных тем... В общем я написал сканер устройств и который проверяет, что это накопитель, и что его можно извлечь, но работает все очень странно... Моя флэшка определяется как не извлекаемое устройство, да и картридеры определяются один как извлекаемый, а второй нет.
    Написал вот такую большую функцию
    Код (C):
    1. bool FindConnectedRemovableUsbstorDevices(std::list<std::wstring>& UsbList)
    2. {
    3.     std::wstring ClassGuidString(L"{53F56307-B6BF-11D0-94F2-00A0C91EFB8B}");
    4.     GUID ClassGuid;
    5.     BYTE buf[1024];
    6.     PSP_DEVICE_INTERFACE_DETAIL_DATA_W pspdidd = reinterpret_cast<PSP_DEVICE_INTERFACE_DETAIL_DATA_W>(buf);
    7.     SP_DEVICE_INTERFACE_DATA spdid;
    8.     SP_DEVINFO_DATA spdd;
    9.     DWORD size;
    10.     SP_DEVINFO_DATA dev_data;
    11.     DWORD properties;
    12.  
    13.  
    14.     if(NOERROR != CLSIDFromString(ClassGuidString.c_str(), &ClassGuid))
    15.         return false;
    16.  
    17.     HDEVINFO dev_info = INVALID_HANDLE_VALUE;
    18.     dev_info = SetupDiGetClassDevs(&ClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
    19.  
    20.     if (dev_info == INVALID_HANDLE_VALUE)
    21.         return false;
    22.  
    23.     DWORD index = 0;
    24.     BOOL ret = FALSE;
    25.  
    26.     spdid.cbSize = sizeof(spdid);
    27.  
    28.     while (true)
    29.     {
    30.         ret = SetupDiEnumDeviceInterfaces(dev_info, NULL, &ClassGuid, index, &spdid);
    31.         if (!ret)
    32.             break;
    33.  
    34.         size = 0;
    35.         SetupDiGetDeviceInterfaceDetail(dev_info, &spdid, NULL, 0, &size, NULL);
    36.         //Get required size
    37.  
    38.         if (size == 0 || size >= sizeof(buf))
    39.             continue;
    40.         //prepare structs
    41.         ZeroMemory(reinterpret_cast<PVOID>(pspdidd), 1024);
    42.         pspdidd->cbSize = sizeof(*pspdidd); // 5 Bytes!
    43.  
    44.         ZeroMemory(reinterpret_cast<PVOID>(&spdd), sizeof(spdd));
    45.         spdd.cbSize = sizeof(spdd);
    46.  
    47.         BOOL res = SetupDiGetDeviceInterfaceDetail(dev_info, &spdid, pspdidd, size, &size, &spdd);
    48.         //Get info
    49.         if (!res)
    50.             continue;
    51.  
    52.         HANDLE drive = CreateFileW(pspdidd->DevicePath, FILE_READ_ATTRIBUTES,
    53.             FILE_SHARE_READ | FILE_SHARE_WRITE,
    54.             NULL, OPEN_EXISTING, 0, NULL);//open device
    55.         if (drive == INVALID_HANDLE_VALUE)
    56.             continue;
    57.  
    58.         printf("\n%S\r\n", pspdidd->DevicePath);
    59.        
    60.         DWORD bytes_returned = 0;
    61.         BOOL b = DeviceIoControl(drive, IOCTL_STORAGE_CHECK_VERIFY2, NULL, 0, NULL, 0, &bytes_returned, NULL);
    62.         if (!b) //check is card reader?
    63.         {
    64.             printf("IOCTL_STORAGE_CHECK_VERIFY2 error = %d\r\n", GetLastError());
    65.             goto stop_process_device;
    66.         }
    67.  
    68.         bytes_returned = 0;
    69.         STORAGE_DEVICE_NUMBER sdn;
    70.         //Get Drive number
    71.         b = DeviceIoControl(drive, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof(sdn), &bytes_returned, NULL);
    72.         if (!b)
    73.             goto stop_process_device;
    74.         RtlZeroMemory(&dev_data, sizeof(SP_DEVINFO_DATA));
    75.         dev_data.cbSize = sizeof(dev_data);
    76.         if (SetupDiEnumDeviceInfo(dev_info, sdn.DeviceNumber, &dev_data))
    77.         {
    78.             //check property
    79.             b = SetupDiGetDeviceRegistryProperty(dev_info, &dev_data, SPDRP_REMOVAL_POLICY, NULL,
    80.                 reinterpret_cast<PBYTE>(&properties), sizeof(properties), NULL);
    81.             if (b && properties != CM_REMOVAL_POLICY_EXPECT_NO_REMOVAL)
    82.             {
    83.                 UsbList.push_back(pspdidd->DevicePath);
    84.                 printf("REMOVAL\r\n");
    85.             }
    86.         }
    87. stop_process_device:
    88.         CloseHandle(drive);
    89.         index++;
    90.     }
    91.     SetupDiDestroyDeviceInfoList(dev_info);
    92.     return true;
    93. }
    94.  
    И вот такой вывод она дает
    Мне кажется я фундаментально чего то не понимаю, и прошу подсказать, в чем я косячнул...
     
  5. Thetrik

    Thetrik UA6527P

    Публикаций:
    0
    Регистрация:
    25 июл 2011
    Сообщения:
    423
    Для начала, что говорит GetDriveType?
     
  6. drem1lin

    drem1lin Member

    Публикаций:
    0
    Регистрация:
    17 мар 2009
    Сообщения:
    288
    GetDriveType для подобных имен возвращает DRIVE_NO_ROOT_DIR.

    Мне подсказали правильный способ обработать накопители. Надо вызвать DeviceIoControl с параметром IOCTL_STORAGE_QUERY_PROPERTY и посмотреть StorageDeviceProperty, в вернувшемся буфере смотреть параметр STORAGE_DEVICE_DESCRIPTOR.RemovableMedia. Так все распознаклось корректно