Program Listing for File dev_path_to_name.hpp

Return to documentation for file (include/input/windows/dev_path_to_name.hpp)

#pragma once

#include <setupapi.h>
#include <string>
#include <vector>
#include <windows.h>
#pragma comment(lib, "setupapi.lib")

inline std::wstring
NormalizeNt(std::wstring p)
{
    if (p.rfind(L"\\??\\", 0) == 0)
        p.replace(0, 4, L"\\\\?\\");
    return p;
}

// HID interface path(\\?\HID#...) -> FriendlyName or DeviceDesc
static std::wstring
GetFriendlyNameFromHidPath(const std::wstring &rawPath)
{
    const std::wstring path = NormalizeNt(rawPath);

    HDEVINFO hset = SetupDiCreateDeviceInfoList(nullptr, nullptr);
    if (hset == INVALID_HANDLE_VALUE)
        return L"";

    SP_DEVICE_INTERFACE_DATA ifd{ sizeof(ifd) };
    if (!SetupDiOpenDeviceInterfaceW(hset, path.c_str(), 0, &ifd)) {
        SetupDiDestroyDeviceInfoList(hset);
        return L"";
    }

    // get SP_DEVINFO_DATA
    DWORD need = 0;
    SetupDiGetDeviceInterfaceDetailW(hset, &ifd, nullptr, 0, &need, nullptr);
    std::vector<BYTE> buf(need);
    auto             *det =
        reinterpret_cast<SP_DEVICE_INTERFACE_DETAIL_DATA_W *>(buf.data());
    det->cbSize = sizeof(*det);
    SP_DEVINFO_DATA dev{ sizeof(dev) };
    if (!SetupDiGetDeviceInterfaceDetailW(
            hset, &ifd, det, need, nullptr, &dev)) {
        SetupDiDestroyDeviceInfoList(hset);
        return L"";
    }
    // get friendly name first
    wchar_t name[512];
    if (SetupDiGetDeviceRegistryPropertyW(hset,
                                          &dev,
                                          SPDRP_FRIENDLYNAME,
                                          nullptr,
                                          reinterpret_cast<PBYTE>(name),
                                          sizeof(name),
                                          nullptr) ||
        SetupDiGetDeviceRegistryPropertyW(hset,
                                          &dev,
                                          SPDRP_DEVICEDESC,
                                          nullptr,
                                          reinterpret_cast<PBYTE>(name),
                                          sizeof(name),
                                          nullptr)) {
        SetupDiDestroyDeviceInfoList(hset);
        return name;
    }

    SetupDiDestroyDeviceInfoList(hset);
    return L"";
}