我正在将一个应用程序从DirectInput切换到RawInput以进行游戏手柄处理,我想为每个游戏手柄提供一个人类可读的描述。理想的是设备管理器中出现的设备文本,但USB产品描述也可以。任何方法都应在没有管理员权限的情况下工作。
到目前为止,我发现了一个set of clues:HKLM\SYSTEM\CurrentControlSet\Control\MediaProperties\PrivateProperties\Joystick\OEM
下的注册表中似乎有一个文本字段,与DirectInput提供的名称相同。这并不完美 - 我有一个在设备管理器中以英文显示的游戏手柄,但在注册表中列为氀。
有没有办法从WM_INPUT
提供的HANDLE到设备管理器描述? HidD_GetProductString
看起来很有希望,但我不知道如何从RawInput句柄中获取Hid顶级集合句柄。
编辑:我有一个设备实例路径(例如。\\?\HID#VID_1267&PID_A001#8&1d630df6&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}
,这可能足以从SetupAPI中提取我需要的信息。有人知道如何在给定实例路径的情况下达到此目的吗?
答案 0 :(得分:3)
我遇到了类似的问题,并相信我找到了一个潜在的解决方案。
似乎您必须使用CreateFile
作为GetRawInputDeviceInfo
参数的参数调用RIDI_DEVICENAME
来调用uiCommand
并使用RawInput提供的名称。这将为您提供设备的句柄,您可以使用该句柄调用HidD_GetProductString
。
wchar_t DeviceName[126];
HANDLE HIDHandle = CreateFile(RawInputDeviceName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL);
if(HIDHandle)
{
BOOLEAN Result = HidD_GetProductString(HIDHandle, DeviceName, sizeof(wchar_t) * 126);
CloseHandle(HIDHandle);
}
然而,似乎HidD_GetProductString
在我的系统上连接的大多数设备上都失败了,而且我的USB键盘和网络摄像头似乎只有成功。我的USB鼠标没有成功。我还没有发现为什么会这样,但也许我的进步会帮助你。
答案 1 :(得分:0)
您可以获得顶级集合的句柄,如下所述:https://msdn.microsoft.com/en-us/library/windows/hardware/ff538731%28v=vs.85%29.aspx
答案 2 :(得分:0)
对于HID设备,您可以使用HidD_GetProductString
,但键盘和鼠标不能通过Windows上的HID API使用,并且可以作为单独的设备类型显示:GUID_DEVINTERFACE_KEYBOARD / GUID_DEVINTERFACE_MOUSE(无法直接读取)用户模式的应用程序(出于安全原因)。
您可以从设备界面符号链接中获取其设备信息,如下所示:
将CM_Get_Device_Interface_Property
或SetupDiGetDeviceInterfaceProperty
与DEVPKEY_Device_InstanceId
一起使用以获取设备实例ID(一个设备可以具有多个接口)。
有了设备实例ID后,可以将CM_Get_DevNode_Property
或SetupDiGetDeviceProperty
与DEVPKEY_NAME
一起使用,以获取设备的本地化友好名称(在设备管理器中显示)。 / p>
以下是来自my test repo的CM_*
API的示例代码:
bool FillDeviceInfo(const std::wstring& deviceInterfaceName)
{
// you need to provide deviceInterfaceName
// example from my system: `\\?\HID#VID_203A&PID_FFFC&MI_01#7&2de99099&0&0000#{378de44c-56ef-11d1-bc8c-00a0c91405dd}`
DEVPROPTYPE propertyType;
ULONG propertySize = 0;
CONFIGRET cr = ::CM_Get_Device_Interface_PropertyW(deviceInterfaceName.c_str(), &DEVPKEY_Device_InstanceId, &propertyType, nullptr, &propertySize, 0);
if (cr != CR_BUFFER_SMALL)
return false;
std::wstring deviceId;
deviceId.resize(propertySize);
cr = ::CM_Get_Device_Interface_PropertyW(deviceInterfaceName.c_str(), &DEVPKEY_Device_InstanceId, &propertyType, (PBYTE)deviceId.data(), &propertySize, 0);
if (cr != CR_SUCCESS)
return false;
// here is deviceId will contain device instance id
// example from my system: `HID\VID_203A&PID_FFFC&MI_01\7&2de99099&0&0000`
DEVINST devInst;
cr = ::CM_Locate_DevNodeW(&devInst, (DEVINSTID_W)deviceId.c_str(), CM_LOCATE_DEVNODE_NORMAL);
if (cr != CR_SUCCESS)
return false;
propertySize = 0;
cr = ::CM_Get_DevNode_PropertyW(devInst, &DEVPKEY_NAME, &propertyType, nullptr, &propertySize, 0);
if (cr != CR_BUFFER_SMALL)
return false;
std::wstring friendlyString;
friendlyString.resize(propertySize);
cr = ::CM_Get_DevNode_PropertyW(devInst, &DEVPKEY_NAME, &propertyType, (PBYTE)friendlyString.data(), &propertySize, 0);
// here is friendlyString will contain localized device friendly name
propertySize = 0;
cr = ::CM_Get_DevNode_PropertyW(devInst, &DEVPKEY_Device_Manufacturer, &propertyType, nullptr, &propertySize, 0);
if (cr != CR_BUFFER_SMALL)
return false;
std::wstring manufacturer;
manufacturer.resize(propertySize);
cr = ::CM_Get_DevNode_PropertyW(devInst, &DEVPKEY_Device_Manufacturer, &propertyType, (PBYTE)manufacturer.data(), &propertySize, 0);
// here is manufacturer will contain localized device "manufacturer-identifier"
return true;
}