diff --git a/Source/Core/Core/USBUtils.cpp b/Source/Core/Core/USBUtils.cpp index b2edfd0b22..79b3a1958c 100644 --- a/Source/Core/Core/USBUtils.cpp +++ b/Source/Core/Core/USBUtils.cpp @@ -3,6 +3,7 @@ #include "Core/USBUtils.h" +#include #include #include #include @@ -21,9 +22,11 @@ #include #endif #ifdef _WIN32 -#include #include #include +#include +// initguid.h must be included before usbiodef.h +#include #include "Common/StringUtil.h" #include "Common/WindowsDevice.h" @@ -119,43 +122,36 @@ static std::optional GetDeviceNameUsingKnownDevices(u16 vid, u16 pi } #ifdef _WIN32 -static std::optional GetDeviceNameUsingSetupAPI(u16 vid, u16 pid) +static std::optional GetDeviceNameUsingCfgMgr32(u16 vid, u16 pid) { - std::optional device_name; + auto class_guid = GUID_DEVINTERFACE_USB_DEVICE; + const ULONG flags = CM_GET_DEVICE_INTERFACE_LIST_PRESENT; const std::wstring filter = fmt::format(L"VID_{:04X}&PID_{:04X}", vid, pid); - HDEVINFO dev_info = - SetupDiGetClassDevs(nullptr, nullptr, nullptr, DIGCF_PRESENT | DIGCF_ALLCLASSES); - if (dev_info == INVALID_HANDLE_VALUE) - return std::nullopt; - SP_DEVINFO_DATA dev_info_data; - dev_info_data.cbSize = sizeof(SP_DEVINFO_DATA); - - for (DWORD i = 0; SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data); ++i) + for (auto* iface : Common::GetDeviceInterfaceList(&class_guid, nullptr, flags)) { - TCHAR instance_id[MAX_DEVICE_ID_LEN]; - if (CM_Get_Device_ID(dev_info_data.DevInst, instance_id, MAX_DEVICE_ID_LEN, 0) != CR_SUCCESS) + if (!std::basic_string_view{iface}.contains(filter)) continue; - const std::wstring_view id_wstr(instance_id); - if (id_wstr.find(filter) == std::wstring::npos) - continue; + auto dev_inst_id = Common::GetDeviceInterfaceStringProperty(iface, &DEVPKEY_Device_InstanceId); + if (!dev_inst_id.has_value()) + return std::nullopt; - std::wstring property_value = - Common::GetDeviceProperty(dev_info, &dev_info_data, &DEVPKEY_Device_FriendlyName); - if (property_value.empty()) + DEVINST dev_inst{}; + if (CM_Locate_DevNode(&dev_inst, dev_inst_id->data(), CM_LOCATE_DEVNODE_NORMAL) != CR_SUCCESS) { - property_value = - Common::GetDeviceProperty(dev_info, &dev_info_data, &DEVPKEY_Device_DeviceDesc); + ERROR_LOG_FMT(COMMON, "CM_Locate_DevNode"); + return std::nullopt; } - if (!property_value.empty()) - device_name = WStringToUTF8(property_value); - break; + // FYI: BusReportedDeviceDesc seems to be more of a friendly name + // while DeviceDesc tends to be something more like "USB Input Device". + return Common::GetDevNodeStringProperty(dev_inst, &DEVPKEY_Device_BusReportedDeviceDesc) + .or_else(std::bind(Common::GetDevNodeStringProperty, dev_inst, &DEVPKEY_Device_DeviceDesc)) + .transform(WStringToUTF8); } - SetupDiDestroyDeviceInfoList(dev_info); - return device_name; + return std::nullopt; } #endif @@ -245,7 +241,7 @@ std::optional GetDeviceNameFromVIDPID(u16 vid, u16 pid) &GetDeviceNameUsingHWDB, #endif #ifdef _WIN32 - &GetDeviceNameUsingSetupAPI, + &GetDeviceNameUsingCfgMgr32, #endif #if defined(__LIBUSB__) && !defined(_WIN32) &GetDeviceNameUsingLibUSB,