2017-12-13 1 views
2

새로운 장치 연결에 대한 정보를 얻기 위해 USB 드라이브를 처리하는 프로그램을 작성 중이며 WM_DEVICECHANGE라는 창 메시지에 가입했습니다. 그러나 물론 프로그램을 시작하기 전에 연결된 장치에 대한 메시지는받지 못합니다. 이러한 장치를 처리하기 위해 검색 기능을 작성했지만 이상한 결과가 나타납니다. 내 플래시 드라이브를 찾았지만 이동식으로 인식하지 못합니다. 왜? 기능Windows에서 연결된 모든 이동식 USB 저장 장치를 찾는 방법은 무엇입니까?

bool FindConnectedRemovableUsbstorDevices(std::list<std::wstring>& UsbList) 
{ 
    std::wstring ClassGuidString(L"{53F56307-B6BF-11D0-94F2-00A0C91EFB8B}"); 
    GUID ClassGuid; 
    BYTE buf[1024]; 
    PSP_DEVICE_INTERFACE_DETAIL_DATA_W pspdidd =   reinterpret_cast<PSP_DEVICE_INTERFACE_DETAIL_DATA_W>(buf); 
    SP_DEVICE_INTERFACE_DATA spdid; 
    SP_DEVINFO_DATA spdd; 
    DWORD size; 
    SP_DEVINFO_DATA dev_data; 
    DWORD properties; 


    if(NOERROR != CLSIDFromString(ClassGuidString.c_str(), &ClassGuid)) 
     return false; 

    HDEVINFO dev_info = INVALID_HANDLE_VALUE; 
    dev_info = SetupDiGetClassDevs(&ClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); 

    if (dev_info == INVALID_HANDLE_VALUE) 
     return false; 

    DWORD index = 0; 
    BOOL ret = FALSE; 

    spdid.cbSize = sizeof(spdid); 

    while (true) 
    { 
     ret = SetupDiEnumDeviceInterfaces(dev_info, NULL, &ClassGuid, index, &spdid); 
    if (!ret) 
     break; 

    size = 0; 
    SetupDiGetDeviceInterfaceDetail(dev_info, &spdid, NULL, 0, &size, NULL); 
    //Get required size 

    if (size == 0 || size >= sizeof(buf)) 
     continue; 
    //prepare structs 
    ZeroMemory(reinterpret_cast<PVOID>(pspdidd), 1024); 
    pspdidd->cbSize = sizeof(*pspdidd); // 5 Bytes! 

    ZeroMemory(reinterpret_cast<PVOID>(&spdd), sizeof(spdd)); 
    spdd.cbSize = sizeof(spdd); 

    BOOL res = SetupDiGetDeviceInterfaceDetail(dev_info, &spdid, pspdidd, size, &size, &spdd); 
    //Get info 
    if (!res) 
     continue; 

    HANDLE drive = CreateFileW(pspdidd->DevicePath, FILE_READ_ATTRIBUTES, 
     FILE_SHARE_READ | FILE_SHARE_WRITE, 
     NULL, OPEN_EXISTING, 0, NULL);//open device 
    if (drive == INVALID_HANDLE_VALUE) 
     continue; 

    printf("\n%S\r\n", pspdidd->DevicePath); 

    DWORD bytes_returned = 0; 
    BOOL b = DeviceIoControl(drive, IOCTL_STORAGE_CHECK_VERIFY2, NULL, 0, NULL, 0, &bytes_returned, NULL); 
    if (!b) //check is card reader? 
    { 
     printf("IOCTL_STORAGE_CHECK_VERIFY2 error = %d\r\n", GetLastError()); 
     goto stop_process_device; 
    } 

    bytes_returned = 0; 
    STORAGE_DEVICE_NUMBER sdn; 
    //Get Drive number 
    b = DeviceIoControl(drive, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof(sdn), &bytes_returned, NULL); 
    if (!b) 
     goto stop_process_device; 
    RtlZeroMemory(&dev_data, sizeof(SP_DEVINFO_DATA)); 
    dev_data.cbSize = sizeof(dev_data); 
    if (SetupDiEnumDeviceInfo(dev_info, sdn.DeviceNumber, &dev_data)) 
    { 
     //check property 
     b = SetupDiGetDeviceRegistryProperty(dev_info, &dev_data, SPDRP_REMOVAL_POLICY, NULL, 
      reinterpret_cast<PBYTE>(&properties), sizeof(properties), NULL); 
     if (b && properties != CM_REMOVAL_POLICY_EXPECT_NO_REMOVAL) 
     { 
      UsbList.push_back(pspdidd->DevicePath); 
      printf("REMOVAL\r\n"); 
     } 
    } 
stop_process_device: 
     CloseHandle(drive); 
     index++; 
    } 
    SetupDiDestroyDeviceInfoList(dev_info); 
    return true; 
} 

그리고 출력

\\?\usbstor#disk&ven_generic-&prod_ms#ms-pro#hg&rev_1.00#20090703819900000&1#{53f56307-b6bf-11d0-94f2-00a0c91efb8b} 
IOCTL_STORAGE_CHECK_VERIFY2 error = 21 
\\?\ide#diskst3500418as_____________________________cc38____#5&5c6cfd6&0&1.0.0#{53f56307-b6bf-11d0-94f2-00a0c91efb8b} 
REMOVAL 
\\?\usbstor#disk&ven_generic-&prod_sd#mmc&rev_1.00#20090703819900000&0#{53f56307-b6bf-11d0-94f2-00a0c91efb8b} 
IOCTL_STORAGE_CHECK_VERIFY2 error = 21 
\\?\scsi#disk&ven_ocz&prod_revodrive3_x2#5&19ad1f72&0&000000#{53f56307-b6bf-11d0-94f2-00a0c91efb8b} 
\\?\ide#diskst1000lm014-1ej164______________________sm30____#5&2ea7e938&0&0.1.0#{53f56307-b6bf-11d0-94f2-00a0c91efb8b} 
\\?\usbstor#disk&ven_sandisk&prod_extreme&rev_0001#aa010823150434152862&0#{53f56307-b6bf-11d0-94f2-00a0c91efb8b} 
\\?\ide#diskwdc_wd1002fbys-02a6b0___________________03.00c06#5&2ea7e938&0&0.0.0#{53f56307-b6bf-11d0-94f2-00a0c91efb8b} 
REMOVAL 

오류 (21)는 빈 카드 리더입니다. 샌 디스크가 제 플래시입니다. 디버그에서 그 재산 CM_REMOVAL_POLICY_EXPECT_NO_REMOVAL을 반환 SetupDiGetDeviceRegistryProperty 보았다,하지만 난 정말

+1

'GetDriveType()'은이 드라이브에서 무엇을 반환합니까? – zett42

+1

'GetDriveType'은 이름에 후행 백 슬래시를 기다리므로 이러한 경로로 직접 작업하지 않을 것입니다. 그러나 특별한 것은 없습니다 - 이름으로 파일을 열고'FileFsDeviceInformation'을'ZwQueryVolumeInformationFile'로 쿼리하십시오. 'FILE_FS_DEVICE_INFORMATION.DeviceType'을 기반으로 리턴 - 이것은 정말로 제거 감지와 관련이 없습니다. 'StorageDeviceProperty'와 함께'IOCTL_STORAGE_QUERY_PROPERTY'를 더 잘 사용하고'STORAGE_DEVICE_DESCRIPTOR.RemovableMedia' 필드를 찾으십시오. – RbMm

+0

zett42 - GetDriveType은 내 장치 이름에 대해 1 (DRIVE_NO_ROOT_DIR)을 반환합니다. – drem1lin

답변

0

이동식 미디어 감지 fisrt 메서드가 이상하게 작동하는 이유는 모르지만 RbMm 메서드는 훌륭하게 작동합니다. 나는 발견 된 모든 장치에 IOCTL_STORAGE_QUERY_PROPERTY과 함께 StorageDeviceProperty의 IOCTL 쿼리를 보내고 STORAGE_DEVICE_DESCRIPTOR.RemovableMedia 필드를 찾습니다. 모든 장치가 성공적으로 올바르게 인식되었습니다.

0

방금 ​​연결된 이동식 장치를 찾으려면이 GetLogicalDriveStrings()GetDriveType()를 사용하여 훨씬 간단 대안이 왜 모르겠어 ... :

#define MAX_DRIVES 256 

bool FindConnectedRemovableUsbstorDevices(std::list<std::wstring>& UsbList) 
{ 
    wchar_t drives[MAX_DRIVES]; 
    wchar_t* temp = drives; 

    if (GetLogicalDriveStringsW(MAX_DRIVES, drives) == 0) 
     return false; 

    while (*temp != NULL) 
    { 
     if (GetDriveTypeW(temp) == 2 /* DRIVE_REMOVABLE */) 
      UsbList.push_back(temp); 

     // Go to the next drive 
     temp += lstrlenW(temp) + 1; 
    } 

    return true; 
} 
+0

나는이 방법을 안다. 그러나 내 프로그램은 마운트 된 장치와도 작동해야한다. – drem1lin

관련 문제