struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id) { BOOL res; struct hid_device_info *root = NULL; /* return object */ struct hid_device_info *cur_dev = NULL; /* Windows objects for interacting with the driver. */ GUID InterfaceClassGuid = {0x4d1e55b2, 0xf16f, 0x11cf, {0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30} }; SP_DEVINFO_DATA devinfo_data; SP_DEVICE_INTERFACE_DATA device_interface_data; SP_DEVICE_INTERFACE_DETAIL_DATA_A *device_interface_detail_data = NULL; HDEVINFO device_info_set = INVALID_HANDLE_VALUE; int device_index = 0; int i; if (hid_init() < 0) return NULL; /* Initialize the Windows objects. */ memset(&devinfo_data, 0x0, sizeof(devinfo_data)); devinfo_data.cbSize = sizeof(SP_DEVINFO_DATA); device_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); /* Get information for all the devices belonging to the HID class. */ device_info_set = SetupDiGetClassDevsA(&InterfaceClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); /* Iterate over each device in the HID class, looking for the right one. */ for (;;) { HANDLE write_handle = INVALID_HANDLE_VALUE; DWORD required_size = 0; HIDD_ATTRIBUTES attrib; res = SetupDiEnumDeviceInterfaces(device_info_set, NULL, &InterfaceClassGuid, device_index, &device_interface_data); if (!res) { /* A return of FALSE from this function means that there are no more devices. */ break; } /* Call with 0-sized detail size, and let the function tell us how long the detail struct needs to be. The size is put in &required_size. */ res = SetupDiGetDeviceInterfaceDetailA(device_info_set, &device_interface_data, NULL, 0, &required_size, NULL); /* Allocate a long enough structure for device_interface_detail_data. */ device_interface_detail_data = (SP_DEVICE_INTERFACE_DETAIL_DATA_A*) malloc(required_size); device_interface_detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); /* Get the detailed data for this device. The detail data gives us the device path for this device, which is then passed into CreateFile() to get a handle to the device. */ res = SetupDiGetDeviceInterfaceDetailA(device_info_set, &device_interface_data, device_interface_detail_data, required_size, NULL, NULL); if (!res) { /* register_error(dev, "Unable to call SetupDiGetDeviceInterfaceDetail"); Continue to the next device. */ goto cont; } /* Make sure this device is of Setup Class "HIDClass" and has a driver bound to it. */ for (i = 0; ; i++) { char driver_name[256]; /* Populate devinfo_data. This function will return failure when there are no more interfaces left. */ res = SetupDiEnumDeviceInfo(device_info_set, i, &devinfo_data); if (!res) goto cont; res = SetupDiGetDeviceRegistryPropertyA(device_info_set, &devinfo_data, SPDRP_CLASS, NULL, (PBYTE)driver_name, sizeof(driver_name), NULL); if (!res) goto cont; if (strcmp(driver_name, "HIDClass") == 0) { /* See if there's a driver bound. */ res = SetupDiGetDeviceRegistryPropertyA(device_info_set, &devinfo_data, SPDRP_DRIVER, NULL, (PBYTE)driver_name, sizeof(driver_name), NULL); if (res) break; } } //wprintf(L"HandleName: %s\n", device_interface_detail_data->DevicePath); /* Open a handle to the device */ write_handle = open_device(device_interface_detail_data->DevicePath, TRUE); /* Check validity of write_handle. */ if (write_handle == INVALID_HANDLE_VALUE) { /* Unable to open the device. */ //register_error(dev, "CreateFile"); goto cont_close; } /* Get the Vendor ID and Product ID for this device. */ attrib.Size = sizeof(HIDD_ATTRIBUTES); HidD_GetAttributes(write_handle, &attrib); //wprintf(L"Product/Vendor: %x %x\n", attrib.ProductID, attrib.VendorID); /* Check the VID/PID to see if we should add this device to the enumeration list. */ if ((vendor_id == 0x0 || attrib.VendorID == vendor_id) && (product_id == 0x0 || attrib.ProductID == product_id)) { #define WSTR_LEN 512 const char *str; struct hid_device_info *tmp; PHIDP_PREPARSED_DATA pp_data = NULL; HIDP_CAPS caps; BOOLEAN res; NTSTATUS nt_res; wchar_t wstr[WSTR_LEN]; /* TODO: Determine Size */ size_t len; /* VID/PID match. Create the record. */ tmp = (struct hid_device_info*) calloc(1, sizeof(struct hid_device_info)); if (cur_dev) { cur_dev->next = tmp; } else { root = tmp; } cur_dev = tmp; /* Get the Usage Page and Usage for this device. */ res = HidD_GetPreparsedData(write_handle, &pp_data); if (res) { nt_res = HidP_GetCaps(pp_data, &caps); if (nt_res == HIDP_STATUS_SUCCESS) { cur_dev->usage_page = caps.UsagePage; cur_dev->usage = caps.Usage; } HidD_FreePreparsedData(pp_data); } /* Fill out the record */ cur_dev->next = NULL; str = device_interface_detail_data->DevicePath; if (str) { len = strlen(str); cur_dev->path = (char*) calloc(len+1, sizeof(char)); strncpy(cur_dev->path, str, len+1); cur_dev->path[len] = '\0'; } else cur_dev->path = NULL; /* Serial Number */ res = HidD_GetSerialNumberString(write_handle, wstr, sizeof(wstr)); wstr[WSTR_LEN-1] = 0x0000; if (res) { cur_dev->serial_number = _wcsdup(wstr); } /* Manufacturer String */ res = HidD_GetManufacturerString(write_handle, wstr, sizeof(wstr)); wstr[WSTR_LEN-1] = 0x0000; if (res) { cur_dev->manufacturer_string = _wcsdup(wstr); } /* Product String */ res = HidD_GetProductString(write_handle, wstr, sizeof(wstr)); wstr[WSTR_LEN-1] = 0x0000; if (res) { cur_dev->product_string = _wcsdup(wstr); } /* VID/PID */ cur_dev->vendor_id = attrib.VendorID; cur_dev->product_id = attrib.ProductID; /* Release Number */ cur_dev->release_number = attrib.VersionNumber; /* Interface Number. It can sometimes be parsed out of the path on Windows if a device has multiple interfaces. See http://msdn.microsoft.com/en-us/windows/hardware/gg487473 or search for "Hardware IDs for HID Devices" at MSDN. If it's not in the path, it's set to -1. */ cur_dev->interface_number = -1; if (cur_dev->path) { char *interface_component = strstr(cur_dev->path, "&mi_"); if (interface_component) { char *hex_str = interface_component + 4; char *endptr = NULL; cur_dev->interface_number = strtol(hex_str, &endptr, 16); if (endptr == hex_str) { /* The parsing failed. Set interface_number to -1. */ cur_dev->interface_number = -1; } } } } cont_close: CloseHandle(write_handle); cont: /* We no longer need the detail data. It can be freed */ free(device_interface_detail_data); device_index++; } /* Close the device information handle. */ SetupDiDestroyDeviceInfoList(device_info_set); return root; }
/*! \brief Enumerate Xsens USB devices If the OS already has drivers running for a device, the device should already have been found by xsEnumerateSerialPorts(). \param[in,out] ports The list of serial ports to append to */ bool xsEnumerateUsbDevices(XsPortInfoList& ports) { XsPortInfo current; #ifdef USE_WINUSB BOOL bResult = FALSE; ULONG length; ULONG requiredLength=0; // {FD51225C-700A-47e5-9999-B2D9031B88ED} GUID guid = { 0xfd51225c, 0x700a, 0x47e5, { 0x99, 0x99, 0xb2, 0xd9, 0x3, 0x1b, 0x88, 0xed } }; HDEVINFO deviceInfo; SP_DEVICE_INTERFACE_DATA interfaceData; PSP_DEVICE_INTERFACE_DETAIL_DATA_A detailData = NULL; deviceInfo = SetupDiGetClassDevs(&guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); // Initialize variables. interfaceData.cbSize = sizeof(SP_INTERFACE_DEVICE_DATA); int port = 0; for (DWORD dwIndex = 0; port == 0; ++dwIndex) { BOOL bRet = SetupDiEnumDeviceInterfaces( deviceInfo, NULL, &guid, dwIndex, &interfaceData); if (!bRet) { if (GetLastError() == ERROR_NO_MORE_ITEMS) break; } else { if (!SetupDiGetDeviceInterfaceDetail(deviceInfo, &interfaceData, NULL, 0, &requiredLength, NULL)) { if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { SetupDiDestroyDeviceInfoList(deviceInfo); return false; } } detailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA_A)LocalAlloc(LMEM_FIXED, requiredLength); if (NULL == detailData) { SetupDiDestroyDeviceInfoList(deviceInfo); return false; } detailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); length = requiredLength; SP_DEVINFO_DATA DevInfoData; DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA); bResult = SetupDiGetDeviceInterfaceDetailA(deviceInfo, &interfaceData, detailData, length, &requiredLength, &DevInfoData); if (!bResult) { LocalFree(detailData); SetupDiDestroyDeviceInfoList(deviceInfo); return false; } unsigned char serialNumber[256]; char* ptrEnd, *ptrStart = strchr(detailData->DevicePath, '#'); if (!ptrStart) continue; ptrStart = strchr(ptrStart+1, '#'); if (!ptrStart) continue; ptrEnd = strchr(ptrStart+1, '#'); if (!ptrEnd) continue; strncpy((char*)serialNumber, ptrStart+1, ptrEnd-ptrStart-1); serialNumber[ptrEnd-ptrStart-1] = '\0'; current.setPortName(detailData->DevicePath); int id = 0; sscanf((const char *)serialNumber, "%X", &id); current.setDeviceId((uint32_t) id); ports.push_back(current); } } SetupDiDestroyDeviceInfoList(deviceInfo); return true; #elif defined(HAVE_LIBUSB) XsLibUsb libUsb; libusb_context *context; int result = libUsb.init(&context); if (result != LIBUSB_SUCCESS) return true; libusb_device **deviceList; ssize_t deviceCount = libUsb.get_device_list(context, &deviceList); for (ssize_t i = 0; i < deviceCount; i++) { libusb_device *device = deviceList[i]; libusb_device_descriptor desc; result = libUsb.get_device_descriptor(device, &desc); if (result != LIBUSB_SUCCESS) continue; if (desc.idVendor != XSENS_VENDOR_ID && desc.idVendor != ATMEL_VENDOR_ID) continue; libusb_device_handle *handle; result = libUsb.open(device, &handle); if (result != LIBUSB_SUCCESS) continue; unsigned char serialNumber[256]; result = libUsb.get_string_descriptor_ascii(handle, desc.iSerialNumber, serialNumber, 256); if (desc.idVendor == ATMEL_VENDOR_ID && desc.idProduct == ATMEL_BORROWED_PRODUCT_ID) { unsigned char productName[256]; result = libUsb.get_string_descriptor_ascii(handle, desc.iProduct, productName, 256); if (strcmp("Xsens COM port", (const char *)productName) != 0) { libUsb.close(handle); continue; } } libusb_config_descriptor *configDesc; result = libUsb.get_active_config_descriptor(device, &configDesc); if (result != LIBUSB_SUCCESS) { libUsb.close(handle); continue; } bool kernelActive = false; for (uint8_t ifCount = 0; ifCount < configDesc->bNumInterfaces; ++ifCount) { int res = libUsb.kernel_driver_active(handle, ifCount); kernelActive |= (res == 1); } libUsb.free_config_descriptor(configDesc); if (!kernelActive) { char name[256]; sprintf(name, "USB%03u:%03u", libUsb.get_bus_number(device), libUsb.get_device_address(device)); current.setPortName(name); int id = 0; sscanf((const char *)serialNumber, "%X", &id); current.setDeviceId((uint32_t) id); ports.push_back(current); } else { JLDEBUG(gJournal, "Kernel driver active on USB" << libUsb.get_bus_number(device) << ":" << libUsb.get_device_address(device) << " device " << serialNumber); } libUsb.close(handle); } libUsb.free_device_list(deviceList, 1); libUsb.exit(context); return true; #else (void)ports; return false; #endif }
/* * Refresh the list of USB devices */ BOOL GetUSBDevices(DWORD devnum) { // The first two are standard Microsoft drivers (including the Windows 8 UASP one). // The rest are the vendor UASP drivers I know of so far - list may be incomplete! const char* storage_name[] = { "USBSTOR", "UASPSTOR", "VUSBSTOR", "ETRONSTOR", "ASUSSTPT" }; const char* scsi_name = "SCSI"; const char* usb_speed_name[USB_SPEED_MAX] = { "USB", "USB 1.0", "USB 1.1", "USB 2.0", "USB 3.0" }; // Hash table and String Array used to match a Device ID with the parent hub's Device Interface Path htab_table htab_devid = HTAB_EMPTY; StrArray dev_if_path; char letter_name[] = " (?:)"; char uefi_togo_check[] = "?:\\EFI\\Rufus\\ntfs_x64.efi"; BOOL r = FALSE, found = FALSE, is_SCSI; HDEVINFO dev_info = NULL; SP_DEVINFO_DATA dev_info_data; SP_DEVICE_INTERFACE_DATA devint_data; PSP_DEVICE_INTERFACE_DETAIL_DATA_A devint_detail_data; DEVINST parent_inst, grandparent_inst, device_inst; DWORD size, i, j, k, l, datatype, drive_index; ULONG list_size[ARRAYSIZE(storage_name)] = { 0 }, list_start[ARRAYSIZE(storage_name)] = { 0 }, full_list_size, ulFlags; HANDLE hDrive; LONG maxwidth = 0; int s, score, drive_number; char drive_letters[27], *device_id, *devid_list = NULL, entry_msg[128]; char *label, *entry, buffer[MAX_PATH], str[MAX_PATH], *method_str; usb_device_props props; IGNORE_RETVAL(ComboBox_ResetContent(hDeviceList)); StrArrayClear(&DriveID); StrArrayClear(&DriveLabel); StrArrayCreate(&dev_if_path, 128); // Add a dummy for string index zero, as this is what non matching hashes will point to StrArrayAdd(&dev_if_path, ""); device_id = (char*)malloc(MAX_PATH); if (device_id == NULL) goto out; // Build a hash table associating a CM Device ID of an USB device with the SetupDI Device Interface Path // of its parent hub - this is needed to retrieve the device speed dev_info = SetupDiGetClassDevsA(&_GUID_DEVINTERFACE_USB_HUB, NULL, NULL, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE); if (dev_info != INVALID_HANDLE_VALUE) { if (htab_create(DEVID_HTAB_SIZE, &htab_devid)) { dev_info_data.cbSize = sizeof(dev_info_data); for (i=0; SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data); i++) { if (usb_debug) uprintf("Processing Hub %d:", i + 1); devint_detail_data = NULL; devint_data.cbSize = sizeof(devint_data); // Only care about the first interface (MemberIndex 0) if ( (SetupDiEnumDeviceInterfaces(dev_info, &dev_info_data, &_GUID_DEVINTERFACE_USB_HUB, 0, &devint_data)) && (!SetupDiGetDeviceInterfaceDetailA(dev_info, &devint_data, NULL, 0, &size, NULL)) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER) && ((devint_detail_data = (PSP_DEVICE_INTERFACE_DETAIL_DATA_A)calloc(1, size)) != NULL) ) { devint_detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); if (SetupDiGetDeviceInterfaceDetailA(dev_info, &devint_data, devint_detail_data, size, &size, NULL)) { // Find the Device IDs for all the children of this hub if (CM_Get_Child(&device_inst, dev_info_data.DevInst, 0) == CR_SUCCESS) { device_id[0] = 0; s = StrArrayAdd(&dev_if_path, devint_detail_data->DevicePath); if ((s>= 0) && (CM_Get_Device_IDA(device_inst, device_id, MAX_PATH, 0) == CR_SUCCESS)) { if ((k = htab_hash(device_id, &htab_devid)) != 0) { htab_devid.table[k].data = (void*)(uintptr_t)s; } if (usb_debug) uprintf(" Found ID[%03d]: %s", k, device_id); while (CM_Get_Sibling(&device_inst, device_inst, 0) == CR_SUCCESS) { device_id[0] = 0; if (CM_Get_Device_IDA(device_inst, device_id, MAX_PATH, 0) == CR_SUCCESS) { if ((k = htab_hash(device_id, &htab_devid)) != 0) { htab_devid.table[k].data = (void*)(uintptr_t)s; } if (usb_debug) uprintf(" Found ID[%03d]: %s", k, device_id); } } } } } free(devint_detail_data); } } } SetupDiDestroyDeviceInfoList(dev_info); } free(device_id); // Build a single list of Device IDs from all the storage enumerators we know of full_list_size = 0; ulFlags = CM_GETIDLIST_FILTER_SERVICE; if (nWindowsVersion >= WINDOWS_7) ulFlags |= CM_GETIDLIST_FILTER_PRESENT; for (s=0; s<ARRAYSIZE(storage_name); s++) { // Get a list of device IDs for all USB storage devices // This will be used to find if a device is UASP if (CM_Get_Device_ID_List_SizeA(&list_size[s], storage_name[s], ulFlags) != CR_SUCCESS) list_size[s] = 0; if (list_size[s] != 0) full_list_size += list_size[s]-1; // remove extra NUL terminator } devid_list = NULL; if (full_list_size != 0) { full_list_size += 1; // add extra NUL terminator devid_list = (char*)malloc(full_list_size); if (devid_list == NULL) { uprintf("Could not allocate Device ID list\n"); return FALSE; } for (s=0, i=0; s<ARRAYSIZE(storage_name); s++) { list_start[s] = i; if (list_size[s] > 1) { if (CM_Get_Device_ID_ListA(storage_name[s], &devid_list[i], list_size[s], ulFlags) != CR_SUCCESS) continue; if (usb_debug) { uprintf("Processing IDs belonging to %s:", storage_name[s]); for (device_id = &devid_list[i]; *device_id != 0; device_id += strlen(device_id) + 1) uprintf(" %s", device_id); } // The list_size is sometimes larger than required thus we need to find the real end for (i += list_size[s]; i > 2; i--) { if ((devid_list[i-2] != '\0') && (devid_list[i-1] == '\0') && (devid_list[i] == '\0')) break; } } } } // Now use SetupDi to enumerate all our storage devices dev_info = SetupDiGetClassDevsA(&_GUID_DEVINTERFACE_DISK, NULL, NULL, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE); if (dev_info == INVALID_HANDLE_VALUE) { uprintf("SetupDiGetClassDevs (Interface) failed: %s\n", WindowsErrorString()); goto out; } dev_info_data.cbSize = sizeof(dev_info_data); for (i=0; SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data); i++) { memset(buffer, 0, sizeof(buffer)); method_str = ""; if (!SetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_ENUMERATOR_NAME, &datatype, (LPBYTE)buffer, sizeof(buffer), &size)) { uprintf("SetupDiGetDeviceRegistryProperty (Enumerator Name) failed: %s\n", WindowsErrorString()); continue; } // UASP drives are listed under SCSI (along with regular SYSTEM drives => "DANGER, WILL ROBINSON!!!") is_SCSI = (safe_stricmp(buffer, scsi_name) == 0); if ((safe_stricmp(buffer, storage_name[0]) != 0) && (!is_SCSI)) continue; // We can't use the friendly name to find if a drive is a VHD, as friendly name string gets translated // according to your locale, so we poke the Hardware ID memset(&props, 0, sizeof(props)); memset(buffer, 0, sizeof(buffer)); props.is_VHD = SetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_HARDWAREID, &datatype, (LPBYTE)buffer, sizeof(buffer), &size) && IsVHD(buffer); if (usb_debug) uprintf("Processing Device: '%s'", buffer); memset(buffer, 0, sizeof(buffer)); if (!SetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_FRIENDLYNAME, &datatype, (LPBYTE)buffer, sizeof(buffer), &size)) { uprintf("SetupDiGetDeviceRegistryProperty (Friendly Name) failed: %s\n", WindowsErrorString()); // We can afford a failure on this call - just replace the name with "USB Storage Device (Generic)" safe_strcpy(buffer, sizeof(buffer), lmprintf(MSG_045)); } else if ((!props.is_VHD) && (devid_list != NULL)) { // Get the properties of the device. We could avoid doing this lookup every time by keeping // a lookup table, but there shouldn't be that many USB storage devices connected... // NB: Each of these Device IDs have an _only_ child, from which we get the Device Instance match. for (device_id = devid_list; *device_id != 0; device_id += strlen(device_id) + 1) { if ( (CM_Locate_DevNodeA(&parent_inst, device_id, 0) == CR_SUCCESS) && (CM_Get_Child(&device_inst, parent_inst, 0) == CR_SUCCESS) && (device_inst == dev_info_data.DevInst) ) { // If we're not dealing with the USBSTOR part of our list, then this is an UASP device props.is_UASP = ((((uintptr_t)device_id)+2) >= ((uintptr_t)devid_list)+list_start[1]); // Now get the properties of the device, and its Device ID, which we need to populate the properties j = htab_hash(device_id, &htab_devid); if (usb_debug) uprintf(" Matched with ID[%03d]: %s", j, device_id); // If the hash didn't match a populated string in dev_if_path[] (htab_devid.table[j].data > 0), // we might have an extra vendor driver in between (e.g. "ASUS USB 3.0 Boost Storage Driver" // for UASP devices in ASUS "Turbo Mode" or "Apple Mobile Device USB Driver" for iPods) // so try to see if we can match the grandparent. if ( ((uint32_t)htab_devid.table[j].data == 0) && (CM_Get_Parent(&grandparent_inst, parent_inst, 0) == CR_SUCCESS) && (CM_Get_Device_IDA(grandparent_inst, str, MAX_PATH, 0) == CR_SUCCESS) ) { device_id = str; method_str = "[GP]"; j = htab_hash(device_id, &htab_devid); if (usb_debug) uprintf(" Matched with (GP) ID[%03d]: %s", j, device_id); } if ((uint32_t)htab_devid.table[j].data > 0) GetUSBProperties(dev_if_path.String[(uint32_t)htab_devid.table[j].data], device_id, &props); if (usb_debug) uprintf(" Props VID:PID = %04X:%04X", props.vid, props.pid); // If previous calls still didn't succeed, try reading the VID:PID from the device_id if ((props.vid == 0) && (props.pid == 0)) { BOOL post_backslash = FALSE; method_str = "[ID]"; for (j=0, k=0; (j<strlen(device_id))&&(k<2); j++) { // The ID is in the form USB_VENDOR_BUSID\VID_xxxx&PID_xxxx\... if (device_id[j] == '\\') post_backslash = TRUE; if (!post_backslash) continue; if (device_id[j] == '_') { props.pid = (uint16_t)strtoul(&device_id[j+1], NULL, 16); if (k++==0) props.vid = props.pid; } } } } } } if (props.is_VHD) { uprintf("Found VHD device '%s'", buffer); } else { if ((props.vid == 0) && (props.pid == 0)) { if (is_SCSI) { // If we have an SCSI drive and couldn't get a VID:PID, we are most likely // dealing with a system drive => eliminate it! if (usb_debug) uprintf(" Non USB => Eliminated"); continue; } safe_strcpy(str, sizeof(str), "????:????"); // Couldn't figure VID:PID } else { static_sprintf(str, "%04X:%04X", props.vid, props.pid); } if (props.speed >= USB_SPEED_MAX) props.speed = 0; uprintf("Found %s%s%s device '%s' (%s) %s\n", props.is_UASP?"UAS (":"", usb_speed_name[props.speed], props.is_UASP?")":"", buffer, str, method_str); if (props.is_LowerSpeed) uprintf("NOTE: This device is an USB 3.0 device operating at lower speed..."); } devint_data.cbSize = sizeof(devint_data); hDrive = INVALID_HANDLE_VALUE; devint_detail_data = NULL; for (j=0; ;j++) { safe_closehandle(hDrive); safe_free(devint_detail_data); if (!SetupDiEnumDeviceInterfaces(dev_info, &dev_info_data, &_GUID_DEVINTERFACE_DISK, j, &devint_data)) { if(GetLastError() != ERROR_NO_MORE_ITEMS) { uprintf("SetupDiEnumDeviceInterfaces failed: %s\n", WindowsErrorString()); } else { uprintf("A device was eliminated because it didn't report itself as a disk\n"); } break; } if (!SetupDiGetDeviceInterfaceDetailA(dev_info, &devint_data, NULL, 0, &size, NULL)) { if(GetLastError() == ERROR_INSUFFICIENT_BUFFER) { devint_detail_data = (PSP_DEVICE_INTERFACE_DETAIL_DATA_A)calloc(1, size); if (devint_detail_data == NULL) { uprintf("Unable to allocate data for SP_DEVICE_INTERFACE_DETAIL_DATA\n"); continue; } devint_detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); } else { uprintf("SetupDiGetDeviceInterfaceDetail (dummy) failed: %s\n", WindowsErrorString()); continue; } } if (devint_detail_data == NULL) { uprintf("SetupDiGetDeviceInterfaceDetail (dummy) - no data was allocated\n"); continue; } if(!SetupDiGetDeviceInterfaceDetailA(dev_info, &devint_data, devint_detail_data, size, &size, NULL)) { uprintf("SetupDiGetDeviceInterfaceDetail (actual) failed: %s\n", WindowsErrorString()); continue; } hDrive = CreateFileA(devint_detail_data->DevicePath, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if(hDrive == INVALID_HANDLE_VALUE) { uprintf("Could not open '%s': %s\n", devint_detail_data->DevicePath, WindowsErrorString()); continue; } drive_number = GetDriveNumber(hDrive, devint_detail_data->DevicePath); if (drive_number < 0) continue; drive_index = drive_number + DRIVE_INDEX_MIN; if (!IsMediaPresent(drive_index)) { uprintf("Device eliminated because it appears to contain no media\n"); safe_closehandle(hDrive); safe_free(devint_detail_data); break; } if (GetDriveLabel(drive_index, drive_letters, &label)) { if ((!enable_HDDs) && (!props.is_VHD) && ((score = IsHDD(drive_index, (uint16_t)props.vid, (uint16_t)props.pid, buffer)) > 0)) { uprintf("Device eliminated because it was detected as an USB Hard Drive (score %d > 0)\n", score); uprintf("If this device is not an USB Hard Drive, please e-mail the author of this application\n"); uprintf("NOTE: You can enable the listing of USB Hard Drives in 'Advanced Options' (after clicking the white triangle)"); safe_closehandle(hDrive); safe_free(devint_detail_data); break; } // The empty string is returned for drives that don't have any volumes assigned if (drive_letters[0] == 0) { entry = lmprintf(MSG_046, label, drive_number, SizeToHumanReadable(GetDriveSize(drive_index), FALSE, use_fake_units)); } else { // Find the UEFI:TOGO partition(s) (and eliminate them form our listing) for (k=0; drive_letters[k]; k++) { uefi_togo_check[0] = drive_letters[k]; if (PathFileExistsA(uefi_togo_check)) { for (l=k; drive_letters[l]; l++) drive_letters[l] = drive_letters[l+1]; k--; } } // We have multiple volumes assigned to the same device (multiple partitions) // If that is the case, use "Multiple Volumes" instead of the label safe_strcpy(entry_msg, sizeof(entry_msg), ((drive_letters[0] != 0) && (drive_letters[1] != 0))? lmprintf(MSG_047):label); for (k=0; drive_letters[k]; k++) { // Append all the drive letters we detected letter_name[2] = drive_letters[k]; if (right_to_left_mode) safe_strcat(entry_msg, sizeof(entry_msg), RIGHT_TO_LEFT_MARK); safe_strcat(entry_msg, sizeof(entry_msg), letter_name); if (drive_letters[k] == (PathGetDriveNumberU(app_dir) + 'A')) break; } // Repeat as we need to break the outside loop if (drive_letters[k] == (PathGetDriveNumberU(app_dir) + 'A')) { uprintf("Removing %c: from the list: This is the disk from which " APPLICATION_NAME " is running!\n", app_dir[0]); safe_closehandle(hDrive); safe_free(devint_detail_data); break; } safe_sprintf(&entry_msg[strlen(entry_msg)], sizeof(entry_msg) - strlen(entry_msg), "%s [%s]", (right_to_left_mode)?RIGHT_TO_LEFT_MARK:"", SizeToHumanReadable(GetDriveSize(drive_index), FALSE, use_fake_units)); entry = entry_msg; } // Must ensure that the combo box is UNSORTED for indexes to be the same StrArrayAdd(&DriveID, buffer); StrArrayAdd(&DriveLabel, label); IGNORE_RETVAL(ComboBox_SetItemData(hDeviceList, ComboBox_AddStringU(hDeviceList, entry), drive_index)); maxwidth = max(maxwidth, GetEntryWidth(hDeviceList, entry)); safe_closehandle(hDrive); safe_free(devint_detail_data); break; } } } SetupDiDestroyDeviceInfoList(dev_info); // Adjust the Dropdown width to the maximum text size SendMessage(hDeviceList, CB_SETDROPPEDWIDTH, (WPARAM)maxwidth, 0); if (devnum >= DRIVE_INDEX_MIN) { for (i=0; i<ComboBox_GetCount(hDeviceList); i++) { if ((DWORD)ComboBox_GetItemData(hDeviceList, i) == devnum) { found = TRUE; break; } } } if (!found) i = 0; IGNORE_RETVAL(ComboBox_SetCurSel(hDeviceList, i)); SendMessage(hMainDialog, WM_COMMAND, (CBN_SELCHANGE<<16) | IDC_DEVICE, 0); SendMessage(hMainDialog, WM_COMMAND, (CBN_SELCHANGE<<16) | IDC_FILESYSTEM, ComboBox_GetCurSel(hFileSystem)); r = TRUE; out: // Set 'Start' as the selected button, so that tab selection works SendMessage(hMainDialog, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hMainDialog, IDC_START), TRUE); safe_free(devid_list); StrArrayDestroy(&dev_if_path); htab_destroy(&htab_devid); return r; }
struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id) { BOOL res; struct hid_device_info *root = NULL; // return object struct hid_device_info *cur_dev = NULL; #ifndef HIDAPI_USE_DDK if (!initialized) lookup_functions(); #endif // Windows objects for interacting with the driver. GUID InterfaceClassGuid = {0x4d1e55b2, 0xf16f, 0x11cf, {0x88, 0xcb, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30} }; SP_DEVINFO_DATA devinfo_data; SP_DEVICE_INTERFACE_DATA device_interface_data; SP_DEVICE_INTERFACE_DETAIL_DATA_A *device_interface_detail_data = NULL; HDEVINFO device_info_set = INVALID_HANDLE_VALUE; // Initialize the Windows objects. devinfo_data.cbSize = sizeof(SP_DEVINFO_DATA); device_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); // Get information for all the devices belonging to the HID class. device_info_set = SetupDiGetClassDevsA(&InterfaceClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); // Iterate over each device in the HID class, looking for the right one. int device_index = 0; for (;;) { HANDLE write_handle = INVALID_HANDLE_VALUE; DWORD required_size = 0; res = SetupDiEnumDeviceInterfaces(device_info_set, NULL, &InterfaceClassGuid, device_index, &device_interface_data); if (!res) { // A return of FALSE from this function means that // there are no more devices. break; } // Call with 0-sized detail size, and let the function // tell us how long the detail struct needs to be. The // size is put in &required_size. res = SetupDiGetDeviceInterfaceDetailA(device_info_set, &device_interface_data, NULL, 0, &required_size, NULL); // Allocate a long enough structure for device_interface_detail_data. device_interface_detail_data = (SP_DEVICE_INTERFACE_DETAIL_DATA_A*) malloc(required_size); device_interface_detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); // Get the detailed data for this device. The detail data gives us // the device path for this device, which is then passed into // CreateFile() to get a handle to the device. res = SetupDiGetDeviceInterfaceDetailA(device_info_set, &device_interface_data, device_interface_detail_data, required_size, NULL, NULL); if (!res) { //register_error(dev, "Unable to call SetupDiGetDeviceInterfaceDetail"); // Continue to the next device. goto cont; } //wprintf(L"HandleName: %s\n", device_interface_detail_data->DevicePath); // Open a handle to the device write_handle = CreateFileA(device_interface_detail_data->DevicePath, GENERIC_WRITE |GENERIC_READ, 0x0, /*share mode*/ NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED,//FILE_ATTRIBUTE_NORMAL, 0); // Check validity of write_handle. if (write_handle == INVALID_HANDLE_VALUE) { // Unable to open the device. //register_error(dev, "CreateFile"); goto cont_close; } // Get the Vendor ID and Product ID for this device. HIDD_ATTRIBUTES attrib; attrib.Size = sizeof(HIDD_ATTRIBUTES); HidD_GetAttributes(write_handle, &attrib); //wprintf(L"Product/Vendor: %x %x\n", attrib.ProductID, attrib.VendorID); // Check the VID/PID to see if we should add this // device to the enumeration list. if ((vendor_id == 0x0 && product_id == 0x0) || (attrib.VendorID == vendor_id && attrib.ProductID == product_id)) { #define WSTR_LEN 512 const char *str; struct hid_device_info *tmp; HIDP_PREPARSED_DATA *pp_data = NULL; HIDP_CAPS caps; BOOLEAN res; NTSTATUS nt_res; wchar_t wstr[WSTR_LEN]; // TODO: Determine Size size_t len; /* VID/PID match. Create the record. */ tmp = (hid_device_info*) calloc(1, sizeof(struct hid_device_info)); if (cur_dev) { cur_dev->next = tmp; } else { root = tmp; } cur_dev = tmp; // Get the Usage Page and Usage for this device. res = HidD_GetPreparsedData(write_handle, &pp_data); if (res) { nt_res = HidP_GetCaps(pp_data, &caps); if (nt_res == HIDP_STATUS_SUCCESS) { cur_dev->usage_page = caps.UsagePage; cur_dev->usage = caps.Usage; } HidD_FreePreparsedData(pp_data); } /* Fill out the record */ cur_dev->next = NULL; str = device_interface_detail_data->DevicePath; if (str) { len = strlen(str); cur_dev->path = (char*) calloc(len+1, sizeof(char)); strncpy(cur_dev->path, str, len+1); cur_dev->path[len] = '\0'; } else cur_dev->path = NULL; /* Serial Number */ res = HidD_GetSerialNumberString(write_handle, wstr, sizeof(wstr)); wstr[WSTR_LEN-1] = 0x0000; if (res) { cur_dev->serial_number = _wcsdup(wstr); } /* Manufacturer String */ res = HidD_GetManufacturerString(write_handle, wstr, sizeof(wstr)); wstr[WSTR_LEN-1] = 0x0000; if (res) { cur_dev->manufacturer_string = _wcsdup(wstr); } /* Product String */ res = HidD_GetProductString(write_handle, wstr, sizeof(wstr)); wstr[WSTR_LEN-1] = 0x0000; if (res) { cur_dev->product_string = _wcsdup(wstr); } /* VID/PID */ cur_dev->vendor_id = attrib.VendorID; cur_dev->product_id = attrib.ProductID; /* Release Number */ cur_dev->release_number = attrib.VersionNumber; /* Interface Number (Unsupported on Windows)*/ cur_dev->interface_number = -1; } cont_close: CloseHandle(write_handle); cont: // We no longer need the detail data. It can be freed free(device_interface_detail_data); device_index++; } // Close the device information handle. SetupDiDestroyDeviceInfoList(device_info_set); return root; }
/* * Refresh the list of USB devices */ BOOL GetDevices(DWORD devnum) { // List of USB storage drivers we know - list may be incomplete! const char* usbstor_name[] = { // Standard MS USB storage driver "USBSTOR", // USB card readers, with proprietary drivers (Realtek,etc...) // Mostly "guessed" from http://www.carrona.org/dvrref.php "RTSUER", "CMIUCR", "EUCR", // UASP Drivers *MUST* be listed after this, starting with "UASPSTOR" // (which is Microsoft's native UASP driver for Windows 8 and later) // as we use "UASPSTOR" as a delimiter "UASPSTOR", "VUSBSTOR", "ETRONSTOR", "ASUSSTPT" }; // These are the generic (non USB) storage enumerators we also test const char* genstor_name[] = { // Generic storage drivers (Careful now!) "SCSI", // "STORAGE", // "STORAGE" is used by 'Storage Spaces" and stuff => DANGEROUS! // Non-USB card reader drivers - This list *MUST* start with "SD" (delimiter) // See http://itdoc.hitachi.co.jp/manuals/3021/30213B5200e/DMDS0094.HTM // Also http://www.carrona.org/dvrref.php. NB: These should be reported // as enumerators by Rufus when Enum Debug is enabled "SD", "PCISTOR", "RTSOR", "JMCR", "JMCF", "RIMMPTSK", "RIMSPTSK", "RISD", "RIXDPTSK", "TI21SONY", "ESD7SK", "ESM7SK", "O2MD", "O2SD", "VIACR" }; // Oh, and we also have card devices (e.g. 'SCSI\DiskO2Micro_SD_...') under the SCSI enumerator... const char* scsi_disk_prefix = "SCSI\\Disk"; const char* scsi_card_name[] = { "_SD_", "_SDHC_", "_MMC_", "_MS_", "_MSPro_", "_xDPicture_", "_O2Media_" }; const char* usb_speed_name[USB_SPEED_MAX] = { "USB", "USB 1.0", "USB 1.1", "USB 2.0", "USB 3.0" }; // Hash table and String Array used to match a Device ID with the parent hub's Device Interface Path htab_table htab_devid = HTAB_EMPTY; StrArray dev_if_path; char letter_name[] = " (?:)"; char drive_name[] = "?:\\"; char uefi_togo_check[] = "?:\\EFI\\Rufus\\ntfs_x64.efi"; char scsi_card_name_copy[16]; BOOL r = FALSE, found = FALSE, post_backslash; HDEVINFO dev_info = NULL; SP_DEVINFO_DATA dev_info_data; SP_DEVICE_INTERFACE_DATA devint_data; PSP_DEVICE_INTERFACE_DETAIL_DATA_A devint_detail_data; DEVINST parent_inst, grandparent_inst, device_inst; DWORD size, i, j, k, l, datatype, drive_index; DWORD uasp_start = ARRAYSIZE(usbstor_name), card_start = ARRAYSIZE(genstor_name); ULONG list_size[ARRAYSIZE(usbstor_name)] = { 0 }, list_start[ARRAYSIZE(usbstor_name)] = { 0 }, full_list_size, ulFlags; HANDLE hDrive; LONG maxwidth = 0; int s, score, drive_number, remove_drive; char drive_letters[27], *device_id, *devid_list = NULL, entry_msg[128]; char *p, *label, *entry, buffer[MAX_PATH], str[MAX_PATH], *method_str, *hub_path; usb_device_props props; IGNORE_RETVAL(ComboBox_ResetContent(hDeviceList)); StrArrayClear(&DriveID); StrArrayClear(&DriveLabel); StrArrayClear(&DriveHub); StrArrayCreate(&dev_if_path, 128); // Add a dummy for string index zero, as this is what non matching hashes will point to StrArrayAdd(&dev_if_path, "", TRUE); device_id = (char*)malloc(MAX_PATH); if (device_id == NULL) goto out; // Build a hash table associating a CM Device ID of an USB device with the SetupDI Device Interface Path // of its parent hub - this is needed to retrieve the device speed dev_info = SetupDiGetClassDevsA(&_GUID_DEVINTERFACE_USB_HUB, NULL, NULL, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE); if (dev_info != INVALID_HANDLE_VALUE) { if (htab_create(DEVID_HTAB_SIZE, &htab_devid)) { dev_info_data.cbSize = sizeof(dev_info_data); for (i=0; SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data); i++) { uuprintf("Processing Hub %d:", i + 1); devint_detail_data = NULL; devint_data.cbSize = sizeof(devint_data); // Only care about the first interface (MemberIndex 0) if ( (SetupDiEnumDeviceInterfaces(dev_info, &dev_info_data, &_GUID_DEVINTERFACE_USB_HUB, 0, &devint_data)) && (!SetupDiGetDeviceInterfaceDetailA(dev_info, &devint_data, NULL, 0, &size, NULL)) && (GetLastError() == ERROR_INSUFFICIENT_BUFFER) && ((devint_detail_data = (PSP_DEVICE_INTERFACE_DETAIL_DATA_A)calloc(1, size)) != NULL) ) { devint_detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); if (SetupDiGetDeviceInterfaceDetailA(dev_info, &devint_data, devint_detail_data, size, &size, NULL)) { // Find the Device IDs for all the children of this hub if (CM_Get_Child(&device_inst, dev_info_data.DevInst, 0) == CR_SUCCESS) { device_id[0] = 0; s = StrArrayAdd(&dev_if_path, devint_detail_data->DevicePath, TRUE); uuprintf(" Hub[%d] = '%s'", s, devint_detail_data->DevicePath); if ((s>= 0) && (CM_Get_Device_IDA(device_inst, device_id, MAX_PATH, 0) == CR_SUCCESS)) { ToUpper(device_id); if ((k = htab_hash(device_id, &htab_devid)) != 0) { htab_devid.table[k].data = (void*)(uintptr_t)s; } uuprintf(" Found ID[%03d]: %s", k, device_id); while (CM_Get_Sibling(&device_inst, device_inst, 0) == CR_SUCCESS) { device_id[0] = 0; if (CM_Get_Device_IDA(device_inst, device_id, MAX_PATH, 0) == CR_SUCCESS) { ToUpper(device_id); if ((k = htab_hash(device_id, &htab_devid)) != 0) { htab_devid.table[k].data = (void*)(uintptr_t)s; } uuprintf(" Found ID[%03d]: %s", k, device_id); } } } } } free(devint_detail_data); } } } SetupDiDestroyDeviceInfoList(dev_info); } free(device_id); // Build a single list of Device IDs from all the storage enumerators we know of full_list_size = 0; ulFlags = CM_GETIDLIST_FILTER_SERVICE | CM_GETIDLIST_FILTER_PRESENT; for (s=0; s<ARRAYSIZE(usbstor_name); s++) { // Get a list of device IDs for all USB storage devices // This will be used to find if a device is UASP // Also compute the uasp_start index if (strcmp(usbstor_name[s], "UASPSTOR") == 0) uasp_start = s; if (CM_Get_Device_ID_List_SizeA(&list_size[s], usbstor_name[s], ulFlags) != CR_SUCCESS) list_size[s] = 0; if (list_size[s] != 0) full_list_size += list_size[s]-1; // remove extra NUL terminator } // Compute the card_start index for (s=0; s<ARRAYSIZE(genstor_name); s++) { if (strcmp(genstor_name[s], "SD") == 0) card_start = s; } // Better safe than sorry. And yeah, we could have used arrays of // arrays to avoid this, but it's more readable this way. assert((uasp_start > 0) && (uasp_start < ARRAYSIZE(usbstor_name))); assert((card_start > 0) && (card_start < ARRAYSIZE(genstor_name))); devid_list = NULL; if (full_list_size != 0) { full_list_size += 1; // add extra NUL terminator devid_list = (char*)malloc(full_list_size); if (devid_list == NULL) { uprintf("Could not allocate Device ID list\n"); goto out; } for (s=0, i=0; s<ARRAYSIZE(usbstor_name); s++) { list_start[s] = i; if (list_size[s] > 1) { if (CM_Get_Device_ID_ListA(usbstor_name[s], &devid_list[i], list_size[s], ulFlags) != CR_SUCCESS) continue; if (usb_debug) { uprintf("Processing IDs belonging to '%s':", usbstor_name[s]); for (device_id = &devid_list[i]; *device_id != 0; device_id += strlen(device_id) + 1) uprintf(" %s", device_id); } // The list_size is sometimes larger than required thus we need to find the real end for (i += list_size[s]; i > 2; i--) { if ((devid_list[i-2] != '\0') && (devid_list[i-1] == '\0') && (devid_list[i] == '\0')) break; } } } } // Now use SetupDi to enumerate all our disk storage devices dev_info = SetupDiGetClassDevsA(&_GUID_DEVINTERFACE_DISK, NULL, NULL, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE); if (dev_info == INVALID_HANDLE_VALUE) { uprintf("SetupDiGetClassDevs (Interface) failed: %s\n", WindowsErrorString()); goto out; } dev_info_data.cbSize = sizeof(dev_info_data); for (i=0; SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data); i++) { memset(buffer, 0, sizeof(buffer)); memset(&props, 0, sizeof(props)); method_str = ""; hub_path = NULL; if (!SetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_ENUMERATOR_NAME, &datatype, (LPBYTE)buffer, sizeof(buffer), &size)) { uprintf("SetupDiGetDeviceRegistryProperty (Enumerator Name) failed: %s\n", WindowsErrorString()); continue; } for (j = 0; j < ARRAYSIZE(usbstor_name); j++) { if (safe_stricmp(buffer, usbstor_name[0]) == 0) { props.is_USB = TRUE; if ((j != 0) && (j < uasp_start)) props.is_CARD = TRUE; break; } } // UASP drives are listed under SCSI, and we also have non USB card readers to populate for (j = 0; j < ARRAYSIZE(genstor_name); j++) { if (safe_stricmp(buffer, genstor_name[j]) == 0) { props.is_SCSI = TRUE; if (j >= card_start) props.is_CARD = TRUE; break; } } uuprintf("Processing '%s' device:", buffer); if ((!props.is_USB) && (!props.is_SCSI)) { uuprintf(" Disabled by policy"); continue; } // We can't use the friendly name to find if a drive is a VHD, as friendly name string gets translated // according to your locale, so we poke the Hardware ID memset(buffer, 0, sizeof(buffer)); props.is_VHD = SetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_HARDWAREID, &datatype, (LPBYTE)buffer, sizeof(buffer), &size) && IsVHD(buffer); // Additional detection for SCSI card readers if ((!props.is_CARD) && (safe_strnicmp(buffer, scsi_disk_prefix, sizeof(scsi_disk_prefix)-1) == 0)) { for (j = 0; j < ARRAYSIZE(scsi_card_name); j++) { static_strcpy(scsi_card_name_copy, scsi_card_name[j]); if (safe_strstr(buffer, scsi_card_name_copy) != NULL) { props.is_CARD = TRUE; break; } // Also test for "_SD&" instead of "_SD_" and so on to allow for devices like // "SCSI\DiskRicoh_Storage_SD&REV_3.0" to be detected. scsi_card_name_copy[strlen(scsi_card_name_copy) - 1] = '&'; if (safe_strstr(buffer, scsi_card_name_copy) != NULL) { props.is_CARD = TRUE; break; } } } uuprintf(" Hardware ID: '%s'", buffer); memset(buffer, 0, sizeof(buffer)); props.is_Removable = SetupDiGetDeviceRegistryPropertyA(dev_info, &dev_info_data, SPDRP_REMOVAL_POLICY, &datatype, (LPBYTE)buffer, sizeof(buffer), &size) && IsRemovable(buffer); memset(buffer, 0, sizeof(buffer)); if (!SetupDiGetDeviceRegistryPropertyU(dev_info, &dev_info_data, SPDRP_FRIENDLYNAME, &datatype, (LPBYTE)buffer, sizeof(buffer), &size)) { uprintf("SetupDiGetDeviceRegistryProperty (Friendly Name) failed: %s\n", WindowsErrorString()); // We can afford a failure on this call - just replace the name with "USB Storage Device (Generic)" static_strcpy(buffer, lmprintf(MSG_045)); } else if ((!props.is_VHD) && (devid_list != NULL)) { // Get the properties of the device. We could avoid doing this lookup every time by keeping // a lookup table, but there shouldn't be that many USB storage devices connected... // NB: Each of these Device IDs should have a child, from which we get the Device Instance match. for (device_id = devid_list; *device_id != 0; device_id += strlen(device_id) + 1) { if (CM_Locate_DevNodeA(&parent_inst, device_id, 0) != CR_SUCCESS) { uuprintf("Could not locate device node for '%s'", device_id); continue; } if (CM_Get_Child(&device_inst, parent_inst, 0) != CR_SUCCESS) { uuprintf("Could not get children of '%s'", device_id); continue; } if (device_inst != dev_info_data.DevInst) { // Try the siblings while (CM_Get_Sibling(&device_inst, device_inst, 0) == CR_SUCCESS) { if (device_inst == dev_info_data.DevInst) { uuprintf("NOTE: Matched instance from sibling for '%s'", device_id); break; } } if (device_inst != dev_info_data.DevInst) continue; } post_backslash = FALSE; method_str = ""; // If we're not dealing with the USBSTOR part of our list, then this is an UASP device props.is_UASP = ((((uintptr_t)device_id)+2) >= ((uintptr_t)devid_list)+list_start[uasp_start]); // Now get the properties of the device, and its Device ID, which we need to populate the properties ToUpper(device_id); j = htab_hash(device_id, &htab_devid); uuprintf(" Matched with ID[%03d]: %s", j, device_id); // Try to parse the current device_id string for VID:PID // We'll use that if we can't get anything better for (k = 0, l = 0; (k<strlen(device_id)) && (l<2); k++) { // The ID is in the form USB_VENDOR_BUSID\VID_xxxx&PID_xxxx\... if (device_id[k] == '\\') post_backslash = TRUE; if (!post_backslash) continue; if (device_id[k] == '_') { props.pid = (uint16_t)strtoul(&device_id[k + 1], NULL, 16); if (l++ == 0) props.vid = props.pid; } } if (props.vid != 0) method_str = "[ID]"; // If the hash didn't match a populated string in dev_if_path[] (htab_devid.table[j].data > 0), // we might have an extra vendor driver in between (e.g. "ASUS USB 3.0 Boost Storage Driver" // for UASP devices in ASUS "Turbo Mode" or "Apple Mobile Device USB Driver" for iPods) // so try to see if we can match the grandparent. if ( ((uintptr_t)htab_devid.table[j].data == 0) && (CM_Get_Parent(&grandparent_inst, parent_inst, 0) == CR_SUCCESS) && (CM_Get_Device_IDA(grandparent_inst, str, MAX_PATH, 0) == CR_SUCCESS) ) { device_id = str; method_str = "[GP]"; ToUpper(device_id); j = htab_hash(device_id, &htab_devid); uuprintf(" Matched with (GP) ID[%03d]: %s", j, device_id); } if ((uintptr_t)htab_devid.table[j].data > 0) { uuprintf(" Matched with Hub[%d]: '%s'", (uintptr_t)htab_devid.table[j].data, dev_if_path.String[(uintptr_t)htab_devid.table[j].data]); if (GetUSBProperties(dev_if_path.String[(uintptr_t)htab_devid.table[j].data], device_id, &props)) { method_str = ""; hub_path = dev_if_path.String[(uintptr_t)htab_devid.table[j].data]; } #ifdef FORCED_DEVICE props.vid = FORCED_VID; props.pid = FORCED_PID; static_strcpy(buffer, FORCED_NAME); #endif } break; } } if (props.is_VHD) { uprintf("Found VHD device '%s'", buffer); } else if ((props.is_CARD) && ((!props.is_USB) || ((props.vid == 0) && (props.pid == 0)))) { uprintf("Found card reader device '%s'", buffer); } else if ((!props.is_USB) && (!props.is_UASP) && (props.is_Removable)) { if (!list_non_usb_removable_drives) { uprintf("Found non-USB removable device '%s' => Eliminated", buffer); uuprintf("If you *REALLY* need, you can enable listing of this device with <Ctrl><Alt><F>"); continue; } uprintf("Found non-USB removable device '%s'", buffer); } else { if ((props.vid == 0) && (props.pid == 0)) { if (!props.is_USB) { // If we have a non removable SCSI drive and couldn't get a VID:PID, // we are most likely dealing with a system drive => eliminate it! uuprintf("Found non-USB non-removable device '%s' => Eliminated", buffer); continue; } static_strcpy(str, "????:????"); // Couldn't figure VID:PID } else { static_sprintf(str, "%04X:%04X", props.vid, props.pid); } if (props.speed >= USB_SPEED_MAX) props.speed = 0; uprintf("Found %s%s%s device '%s' (%s) %s\n", props.is_UASP?"UAS (":"", usb_speed_name[props.speed], props.is_UASP?")":"", buffer, str, method_str); if (props.is_LowerSpeed) uprintf("NOTE: This device is an USB 3.0 device operating at lower speed..."); } devint_data.cbSize = sizeof(devint_data); hDrive = INVALID_HANDLE_VALUE; devint_detail_data = NULL; for (j=0; ;j++) { safe_closehandle(hDrive); safe_free(devint_detail_data); if (!SetupDiEnumDeviceInterfaces(dev_info, &dev_info_data, &_GUID_DEVINTERFACE_DISK, j, &devint_data)) { if(GetLastError() != ERROR_NO_MORE_ITEMS) { uprintf("SetupDiEnumDeviceInterfaces failed: %s\n", WindowsErrorString()); } else { uprintf("A device was eliminated because it didn't report itself as a disk\n"); } break; } if (!SetupDiGetDeviceInterfaceDetailA(dev_info, &devint_data, NULL, 0, &size, NULL)) { if(GetLastError() == ERROR_INSUFFICIENT_BUFFER) { devint_detail_data = (PSP_DEVICE_INTERFACE_DETAIL_DATA_A)calloc(1, size); if (devint_detail_data == NULL) { uprintf("Unable to allocate data for SP_DEVICE_INTERFACE_DETAIL_DATA\n"); continue; } devint_detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); } else { uprintf("SetupDiGetDeviceInterfaceDetail (dummy) failed: %s\n", WindowsErrorString()); continue; } } if (devint_detail_data == NULL) { uprintf("SetupDiGetDeviceInterfaceDetail (dummy) - no data was allocated\n"); continue; } if(!SetupDiGetDeviceInterfaceDetailA(dev_info, &devint_data, devint_detail_data, size, &size, NULL)) { uprintf("SetupDiGetDeviceInterfaceDetail (actual) failed: %s\n", WindowsErrorString()); continue; } hDrive = CreateFileA(devint_detail_data->DevicePath, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if(hDrive == INVALID_HANDLE_VALUE) { uprintf("Could not open '%s': %s\n", devint_detail_data->DevicePath, WindowsErrorString()); continue; } drive_number = GetDriveNumber(hDrive, devint_detail_data->DevicePath); if (drive_number < 0) continue; drive_index = drive_number + DRIVE_INDEX_MIN; if (!IsMediaPresent(drive_index)) { uprintf("Device eliminated because it appears to contain no media\n"); safe_closehandle(hDrive); safe_free(devint_detail_data); break; } if (GetDriveSize(drive_index) < (MIN_DRIVE_SIZE*MB)) { uprintf("Device eliminated because it is smaller than %d MB\n", MIN_DRIVE_SIZE); safe_closehandle(hDrive); safe_free(devint_detail_data); break; } if (GetDriveLabel(drive_index, drive_letters, &label)) { if ((props.is_SCSI) && (!props.is_UASP) && (!props.is_VHD)) { if (!props.is_Removable) { // Non removables should have been eliminated above, but since we // are potentially dealing with system drives, better safe than sorry safe_closehandle(hDrive); safe_free(devint_detail_data); break; } if (!list_non_usb_removable_drives) { // Go over the mounted partitions and find if GetDriveType() says they are // removable. If they are not removable, don't allow the drive to be listed for (p = drive_letters; *p; p++) { drive_name[0] = *p; if (GetDriveTypeA(drive_name) != DRIVE_REMOVABLE) break; } if (*p) { uprintf("Device eliminated because it contains a mounted partition that is set as non-removable"); safe_closehandle(hDrive); safe_free(devint_detail_data); break; } } } if ((!enable_HDDs) && (!props.is_VHD) && (!props.is_CARD) && ((score = IsHDD(drive_index, (uint16_t)props.vid, (uint16_t)props.pid, buffer)) > 0)) { uprintf("Device eliminated because it was detected as a Hard Drive (score %d > 0)", score); if (!list_non_usb_removable_drives) uprintf("If this device is not a Hard Drive, please e-mail the author of this application"); uprintf("NOTE: You can enable the listing of Hard Drives under 'advanced drive properties'"); safe_closehandle(hDrive); safe_free(devint_detail_data); break; } // The empty string is returned for drives that don't have any volumes assigned if (drive_letters[0] == 0) { entry = lmprintf(MSG_046, label, drive_number, SizeToHumanReadable(GetDriveSize(drive_index), FALSE, use_fake_units)); } else { // Find the UEFI:TOGO partition(s) (and eliminate them form our listing) for (k=0; drive_letters[k]; k++) { uefi_togo_check[0] = drive_letters[k]; if (PathFileExistsA(uefi_togo_check)) { for (l=k; drive_letters[l]; l++) drive_letters[l] = drive_letters[l+1]; k--; } } // We have multiple volumes assigned to the same device (multiple partitions) // If that is the case, use "Multiple Volumes" instead of the label static_strcpy(entry_msg, (((drive_letters[0] != 0) && (drive_letters[1] != 0))? lmprintf(MSG_047):label)); for (k=0, remove_drive=0; drive_letters[k] && (!remove_drive); k++) { // Append all the drive letters we detected letter_name[2] = drive_letters[k]; if (right_to_left_mode) static_strcat(entry_msg, RIGHT_TO_LEFT_MARK); static_strcat(entry_msg, letter_name); if (drive_letters[k] == (PathGetDriveNumberU(app_dir) + 'A')) remove_drive = 1; if (drive_letters[k] == (PathGetDriveNumberU(system_dir) + 'A')) remove_drive = 2; } // Make sure that we don't list any drive that should not be listed if (remove_drive) { uprintf("Removing %C: from the list: This is the %s!", drive_letters[--k], (remove_drive==1)?"disk from which " APPLICATION_NAME " is running":"system disk"); safe_closehandle(hDrive); safe_free(devint_detail_data); break; } safe_sprintf(&entry_msg[strlen(entry_msg)], sizeof(entry_msg) - strlen(entry_msg), "%s [%s]", (right_to_left_mode)?RIGHT_TO_LEFT_MARK:"", SizeToHumanReadable(GetDriveSize(drive_index), FALSE, use_fake_units)); entry = entry_msg; } // Must ensure that the combo box is UNSORTED for indexes to be the same StrArrayAdd(&DriveID, buffer, TRUE); StrArrayAdd(&DriveLabel, label, TRUE); if ((hub_path != NULL) && (StrArrayAdd(&DriveHub, hub_path, TRUE) >= 0)) DrivePort[DriveHub.Index - 1] = props.port; IGNORE_RETVAL(ComboBox_SetItemData(hDeviceList, ComboBox_AddStringU(hDeviceList, entry), drive_index)); maxwidth = max(maxwidth, GetEntryWidth(hDeviceList, entry)); safe_closehandle(hDrive); safe_free(devint_detail_data); break; } } } SetupDiDestroyDeviceInfoList(dev_info); // Adjust the Dropdown width to the maximum text size SendMessage(hDeviceList, CB_SETDROPPEDWIDTH, (WPARAM)maxwidth, 0); if (devnum >= DRIVE_INDEX_MIN) { for (i=0; i<ComboBox_GetCount(hDeviceList); i++) { if ((DWORD)ComboBox_GetItemData(hDeviceList, i) == devnum) { found = TRUE; break; } } } if (!found) i = 0; IGNORE_RETVAL(ComboBox_SetCurSel(hDeviceList, i)); SendMessage(hMainDialog, WM_COMMAND, (CBN_SELCHANGE<<16) | IDC_DEVICE, 0); r = TRUE; out: // Set 'Start' as the selected button, so that tab selection works SendMessage(hMainDialog, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hMainDialog, IDC_START), TRUE); safe_free(devid_list); StrArrayDestroy(&dev_if_path); htab_destroy(&htab_devid); return r; }
BOOL GetOpticalMedia(IMG_SAVE* img_save) { static char str[MAX_PATH]; static char label[33]; int k; BYTE geometry[256], *buffer = NULL; PDISK_GEOMETRY_EX DiskGeometry = (PDISK_GEOMETRY_EX)(void*)geometry; DWORD i, j, size, datatype; HDEVINFO dev_info = NULL; SP_DEVINFO_DATA dev_info_data; SP_DEVICE_INTERFACE_DATA devint_data; PSP_DEVICE_INTERFACE_DETAIL_DATA_A devint_detail_data; HANDLE hDrive = INVALID_HANDLE_VALUE; LARGE_INTEGER li; dev_info = SetupDiGetClassDevsA(&_GUID_DEVINTERFACE_CDROM, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); if (dev_info == INVALID_HANDLE_VALUE) { uprintf("SetupDiGetClassDevs (Interface) failed: %s\n", WindowsErrorString()); return FALSE; } dev_info_data.cbSize = sizeof(dev_info_data); for (i = 0; SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data); i++) { memset(str, 0, sizeof(str)); if (!SetupDiGetDeviceRegistryPropertyU(dev_info, &dev_info_data, SPDRP_FRIENDLYNAME, &datatype, (LPBYTE)str, sizeof(str), &size)) { uprintf("SetupDiGetDeviceRegistryProperty (Friendly Name) failed: %s\n", WindowsErrorString()); static_strcpy(str, "Generic Optical Drive"); } uprintf("Found '%s' optical device", str); devint_data.cbSize = sizeof(devint_data); devint_detail_data = NULL; for (j = 0; ; j++) { safe_closehandle(hDrive); safe_free(devint_detail_data); safe_free(buffer); if (!SetupDiEnumDeviceInterfaces(dev_info, &dev_info_data, &_GUID_DEVINTERFACE_CDROM, j, &devint_data)) { if (GetLastError() != ERROR_NO_MORE_ITEMS) { uprintf("SetupDiEnumDeviceInterfaces failed: %s\n", WindowsErrorString()); } break; } if (!SetupDiGetDeviceInterfaceDetailA(dev_info, &devint_data, NULL, 0, &size, NULL)) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { devint_detail_data = (PSP_DEVICE_INTERFACE_DETAIL_DATA_A)calloc(1, size); if (devint_detail_data == NULL) { uprintf("Unable to allocate data for SP_DEVICE_INTERFACE_DETAIL_DATA\n"); continue; } devint_detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); } else { uprintf("SetupDiGetDeviceInterfaceDetail (dummy) failed: %s\n", WindowsErrorString()); continue; } } if (devint_detail_data == NULL) { uprintf("SetupDiGetDeviceInterfaceDetail (dummy) - no data was allocated\n"); continue; } if (!SetupDiGetDeviceInterfaceDetailA(dev_info, &devint_data, devint_detail_data, size, &size, NULL)) { uprintf("SetupDiGetDeviceInterfaceDetail (actual) failed: %s\n", WindowsErrorString()); continue; } // Get the size of the inserted media (if any) hDrive = CreateFileA(devint_detail_data->DevicePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL); if (hDrive == INVALID_HANDLE_VALUE) continue; if (!DeviceIoControl(hDrive, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, NULL, 0, geometry, sizeof(geometry), &size, NULL)) continue; // Rewritable media usually has a one sector if (DiskGeometry->DiskSize.QuadPart <= 4096) continue; // Read the label directly, since it's a massive PITA to get it from Windows li.QuadPart = 0x8000LL; buffer = malloc(2048); if ((buffer != NULL) && (SetFilePointerEx(hDrive, li, NULL, FILE_BEGIN)) && ReadFile(hDrive, buffer, 2048, &size, NULL) && (size == 2048)) { memcpy(label, &buffer[0x28], sizeof(label) - 1); label[sizeof(label) - 1] = 0; for (k = (int)strlen(label) - 1; (k >= 0) && (label[k] == 0x20); k--) label[k] = 0; img_save->Label = label; } static_strcpy(str, devint_detail_data->DevicePath); img_save->DevicePath = str; img_save->DeviceSize = DiskGeometry->DiskSize.QuadPart; safe_closehandle(hDrive); safe_free(devint_detail_data); safe_free(buffer); return TRUE; } } return FALSE; }
//--------------------------------------------------------------------------- // 获取指定盘符的序列号(针对USB优盘有效) // char cDiskID: 指定盘符,如 'L' // LPSTR lpPID : 序列号存放的缓冲,如char szPID[32] // by ccrun(老妖) [email protected] //--------------------------------------------------------------------------- bool CUDiskAuth::GetUSBDiskID(char cDiskID) { char szDrv[4]; sprintf_s(szDrv, 4, "%c:\\", cDiskID); if(GetDriveType(szDrv) != DRIVE_REMOVABLE) { return false; } char lpRegPath[512] = { 0 }; char lpRegValue[256] = { 0 }; sprintf_s(lpRegPath, 512, "SYSTEM\\MountedDevices"); sprintf_s(lpRegValue, 256, "\\DosDevices\\%c:", cDiskID); // DWORD dwDataSize(0); DWORD dwRegType(REG_BINARY); LPBYTE lpRegBinData(NULL); LPSTR lpUSBKeyData(NULL); // 查询注册表中映射驱动器的设备信息 HKEY hKey; long lRet = ::RegOpenKeyEx( HKEY_LOCAL_MACHINE, // root key lpRegPath, // 要访问的键的位置 0, // KEY_READ, // 以查询的方式访问注册表 &hKey); // hKEY保存此函数所打开的键的句柄 if(lRet != ERROR_SUCCESS) return false; else { lRet = ::RegQueryValueEx(hKey, // 所打开的键的句柄 lpRegValue, // 要查询的键值名 NULL, &dwRegType, // 查询数据的类型 lpRegBinData, // 保存所查询的数据 &dwDataSize); // 预设置的数据长度 if(lRet != ERROR_SUCCESS) { ::RegCloseKey(hKey); return false; } else { lpRegBinData = new BYTE[dwDataSize]; lpUSBKeyData = new char[dwDataSize]; memset(lpUSBKeyData, 0, dwDataSize); lRet = ::RegQueryValueEx(hKey, lpRegValue, NULL, &dwRegType, lpRegBinData, &dwDataSize); if(lRet != ERROR_SUCCESS) { delete []lpRegBinData; delete []lpUSBKeyData; ::RegCloseKey(hKey); return false; } } } ::RegCloseKey(hKey); // 过滤二进制串中的无用信息(将0x0字符去除) int j = 0; for(DWORD i=0; i<dwDataSize; i++) { if(lpRegBinData[i] != 0x0) { lpUSBKeyData[j] = lpRegBinData[i]; j++; } } delete []lpRegBinData; // 截取lpUSBKeyData中的有用信息, 例: 7&100a16f&0 // \??\STORAGE#RemovableMedia#7&100a16f&0&RM#{53f5630d-b6bf-11d0-94f2-00a0c91efb8b} // 63 63 72 75 6E 2E 63 6F 6D LPSTR lpPos1 = strstr(lpUSBKeyData, "#RemovableMedia#") + 16; LPSTR lpPos2 = strstr(lpUSBKeyData, "RM"); strncpy_s(lpUSBKeyData, dwDataSize, lpPos1, int(lpPos2) - int(lpPos1)); lpUSBKeyData[int(lpPos2) - int(lpPos1) - 1] = 0x0; strcpy_s(lpUSBKeyData, dwDataSize, _strupr(lpUSBKeyData)); // Disk Device(磁盘设备)的GUID GUID guidUSB; CLSIDFromString(L"{53f56307-b6bf-11d0-94f2-00a0c91efb8b}", &guidUSB); HDEVINFO hUSB; // // HDEVINFO hUSB = SetupDiGetClassDevs( // &guidUSB, NULL, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); if(hUSB == INVALID_HANDLE_VALUE) { delete []lpUSBKeyData; return false; } // int nDevIndex = 0; bool bSuccess; SP_DEVINFO_DATA DevData; SP_DEVICE_INTERFACE_DATA DevIntData; PSP_DEVICE_INTERFACE_DETAIL_DATA lpDevIntDetailData; DWORD dwBytesReturned; BOOL validUDisk = FALSE; // 遍历磁盘设备 do { DevIntData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); // bSuccess = SetupDiEnumDeviceInterfaces(hUSB, NULL, &guidUSB, // nDevIndex, &DevIntData) > 0; // 本文转自 C++Builder研究 - http://www.ccrun.com/article.asp?i=1021&d=fgp83l if(bSuccess) { // 获取接口详细信息 DevData.cbSize = sizeof(SP_DEVINFO_DATA); dwBytesReturned = 0; //anzhsoft // SetupDiGetDeviceInterfaceDetailA(hUSB, &DevIntData, // NULL, 0, &dwBytesReturned, &DevData); if(dwBytesReturned != 0 && GetLastError() == ERROR_INSUFFICIENT_BUFFER) { lpDevIntDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA) GlobalAlloc(GMEM_FIXED, dwBytesReturned); lpDevIntDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); if(SetupDiGetDeviceInterfaceDetailA(hUSB, &DevIntData, lpDevIntDetailData, dwBytesReturned, &dwBytesReturned, &DevData)) { // 取得设备接口详细信息并根据转化后的路径在注册表中查询 LPSTR lpPathTemp = new char[strlen(lpDevIntDetailData->DevicePath) + 256]; strcpy_s(lpRegPath, 512, "SYSTEM\\CurrentControlSet\\Enum\\"); strcpy_s(lpPathTemp, strlen(lpDevIntDetailData->DevicePath) + 256, lpDevIntDetailData->DevicePath); lpPos1 = LPSTR(int(lpPathTemp) + 4); lpPos2 = LPSTR(int(strstr(lpPathTemp, "{")) - 1); strncpy_s(lpPathTemp, strlen(lpDevIntDetailData->DevicePath) + 256, lpPos1, int(lpPos2) - int(lpPos1)); char buf[100]={0}; strncpy_s(buf, 100, lpPathTemp,7); buf[strlen(buf)]='\0'; // cout<<buf<<endl;; // AfxMessageBox(buf); if (strcmp(buf, strlwr(HANLINHEAD))==0) { //usbstor#disk&ven_linux&prod_file-stor_gadget&rev_0319#3238204e6f char productName[6]={0},PID[10]={0},VID[17]={0},ID[14]={0}; strncpy_s(productName, 6, lpPathTemp+17,5); strncpy_s(VID, 17, lpPathTemp+28,16); strncpy_s(PID, 10, lpPathTemp+49,4); strncpy_s(ID, 14, lpPathTemp+54,12); strcpy_s(ID, 14,_strupr(ID)); // cout<<ID<<endl; if (strcmp(productName,(HANLINNAME))==0 &&strcmp(VID,HANLINVID)==0 &&(strcmp(PID,HANLINPID_V3)==0 ||strcmp(PID,HANLINPID_V30)==0) &&ID[0] &&(strcmp(UserName,"anzhsoft")==0 ||strcmp(UserName,"faintfaint")==0 ||strcmp(UserName,"marklee") ==0 ||strcmp(UserName,"start_dzh") ==0) ) { // cout<<"here\n"; validUDisk = TRUE; strcpy(uDiskAuthInfo.DevName,productName); strcpy(uDiskAuthInfo.PID,PID); strcpy(uDiskAuthInfo.VID,VID); uDiskAuthInfo.diskFlag = cDiskID; uDiskAuthInfo.flag = TRUE; // AfxMessageBox(VID); } // cout<<"&*)(&^*(*(*("<<lpPathTemp<<endl<<endl; } // AfxMessageBox(lpPathTemp); lpPathTemp[int(lpPos2) - int(lpPos1)] = 0x0; CrnReplaceString(lpPathTemp, '#', '\\'); strcat(lpRegPath, lpPathTemp); // if(RegOpenKeyEx( HKEY_LOCAL_MACHINE, lpRegPath, 0, KEY_READ, &hKey) == ERROR_SUCCESS) { dwRegType = REG_SZ; LPSTR lpRegSzData = NULL; dwDataSize = 0; lRet = ::RegQueryValueEx(hKey, "ParentIdPrefix", NULL, &dwRegType, (LPBYTE)lpRegSzData, &dwDataSize); if(lRet == ERROR_SUCCESS) { lpRegSzData = new char[dwDataSize]; lRet = ::RegQueryValueEx(hKey, "ParentIdPrefix", NULL, &dwRegType, (LPBYTE)lpRegSzData, &dwDataSize); if(lRet == ERROR_SUCCESS) { strcpy(lpRegSzData, strupr(lpRegSzData)); if(!strcmp(lpUSBKeyData, lpRegSzData)) { // 经比对,找到要查询的磁盘设备 strcpy(lpPathTemp, LPSTR(int(strstr( lpDevIntDetailData->DevicePath, "#")) + 1)); lpPos1 = LPSTR(int(strstr(lpPathTemp, "#")) + 1); lpPos2 = LPSTR(int(strstr(lpPathTemp, "#{"))); strncpy(lpPathTemp, lpPos1, int(lpPos2) - int(lpPos1)); lpPathTemp[int(lpPos2) - int(lpPos1)] = 0x0; // 获取最终的磁盘序列号 CrnReplaceString(lpPathTemp, '&', 0x00); char buf[100]; strncpy(buf, strupr(lpPathTemp), 32); if (validUDisk) { strcpy(uDiskAuthInfo.ID,buf); } // delete []lpRegSzData; delete []lpPathTemp; GlobalFree(lpDevIntDetailData); ::RegCloseKey(hKey); break; } } delete []lpRegSzData; } ::RegCloseKey(hKey); } delete []lpPathTemp; nDevIndex++; } GlobalFree(lpDevIntDetailData); } } }while(bSuccess); //anzhsoft for paltform //SetupDiDestroyDeviceInfoList(hUSB); delete []lpUSBKeyData; return validUDisk; }
void NiashLibUsbInit(TFnReportDevice* const pfnReportDevice) { class HDEVINFODeleter //RAII wrapper { public: typedef HDEVINFO pointer; void operator()(HDEVINFO h) {::SetupDiDestroyDeviceInfoList(h);} }; //Get device std::unique_ptr<HDEVINFO, HDEVINFODeleter> hDevInfo(SetupDiGetClassDevs(&s_NiashInterfaceClassGUID, NULL, NULL, DIGCF_PRESENT|DIGCF_PROFILE|DIGCF_DEVICEINTERFACE)); if(hDevInfo.get() == INVALID_HANDLE_VALUE) { wprintf_s(L"SetupDiGetClassDevs: %s\n", _com_error(GetLastError()).ErrorMessage()); return; } //Get device info for the devices SP_DEVINFO_DATA DeviceInfoData; DeviceInfoData.cbSize = sizeof(DeviceInfoData); SetupDiEnumDeviceInfo(hDevInfo.get(),0,&DeviceInfoData); if(GetLastError()==ERROR_NO_MORE_ITEMS) { puts("No devices with the driver installed found."); } else { wprintf_s(L"SetupDiEnumDeviceInfo: %s\n", _com_error(GetLastError()).ErrorMessage()); } //Get the first matching device interface of that device SP_DEVICE_INTERFACE_DATA DeviceInterfaceData; DeviceInterfaceData.cbSize = sizeof(DeviceInterfaceData); if(!SetupDiEnumDeviceInterfaces(hDevInfo.get(), &DeviceInfoData, &s_NiashInterfaceClassGUID, 0, &DeviceInterfaceData)) { wprintf_s(L"SetupDiEnumDeviceInterfaces: %s\n", _com_error(GetLastError()).ErrorMessage()); return; } //Get size of detailed device interface data DWORD dwRequiredSize; if(!SetupDiGetDeviceInterfaceDetail(hDevInfo.get(), &DeviceInterfaceData, nullptr, 0, &dwRequiredSize, nullptr) && GetLastError() != ERROR_INSUFFICIENT_BUFFER) { wprintf_s(L"SetupDiGetDeviceInterfaceDetail: %s\n", _com_error(GetLastError()).ErrorMessage()); return; } //SP_DEVICE_INTERFACE_DETAIL_DATA's actual size isn't declared std::unique_ptr<SP_DEVICE_INTERFACE_DETAIL_DATA_A> pInterfaceDetailData(reinterpret_cast<SP_DEVICE_INTERFACE_DETAIL_DATA_A*>(new BYTE[dwRequiredSize])); pInterfaceDetailData->cbSize = sizeof(*pInterfaceDetailData); if(!SetupDiGetDeviceInterfaceDetailA(hDevInfo.get(), &DeviceInterfaceData, pInterfaceDetailData.get(), dwRequiredSize, nullptr, nullptr)) { wprintf_s(L"SetupDiGetDeviceInterfaceDetail: %s\n", _com_error(GetLastError()).ErrorMessage()); return; } //Get name size ULONG ulPropType = DEVPROP_TYPE_STRING; if(!SetupDiGetDeviceProperty(hDevInfo.get(), &DeviceInfoData, &DEVPKEY_NAME, &ulPropType, nullptr, 0, &dwRequiredSize, 0) && GetLastError() != ERROR_INSUFFICIENT_BUFFER) { wprintf_s(L"SetupDiGetDeviceProperty: %s\n", _com_error(GetLastError()).ErrorMessage()); return; } //Get device name std::vector<TCHAR> Buf(dwRequiredSize); if(!SetupDiGetDeviceProperty(hDevInfo.get(), &DeviceInfoData, &DEVPKEY_NAME, &ulPropType, reinterpret_cast<PBYTE>(Buf.data()), dwRequiredSize, 0, 0)) { wprintf_s(L"SetupDiGetDeviceProperty: %s\n", _com_error(GetLastError()).ErrorMessage()); return; } wprintf_s(L"Found device: %s ", Buf.data()); printf_s("%s\n", pInterfaceDetailData->DevicePath); //Let driver recognize the device so it knows what parameters to use int vid = 0; int pid = 0; if(sscanf_s(pInterfaceDetailData->DevicePath,"\\\\?\\usb#vid_%x&pid_%x#", &vid, &pid) == 2 && MatchUsbDevice(vid,pid,&s_pScannerModel)) { pfnReportDevice(s_pScannerModel, pInterfaceDetailData->DevicePath); } }