是否可以获得XInput设备的名称,产品ID,供应商ID或其他某种唯一标识符?

问题描述

通常,仅使用与控制器的播放器编号相对应的索引来标识XInput控制器。有没有办法获取有关具有特定索引的控制器的更多信息,例如其供应商ID,产品ID或设备名称

更好的是,标识符唯一且一致地仅与该控制器相对应,以便可以将其与所有其他XInput设备区分开来,而不管其索引如何,包括具有相同型号(即相同产品和供应商ID)的另一个控制器,类似于可使用DirectInput的实例GUID。

这可以使用XInput或其他Microsoft API完成吗?如果需要,我也愿意使用未记录的功能

解决方法

XInput 内部所做的是打开一个设备,然后在每次读取游戏手柄时调用它的 DeviceIoControl。 (控制码0x8000e00c)

需要hook这些由“XInput1_4.dll”导入的函数:

  • CreateFileW 来自“api-ms-win-core-file-l1-1-0.dll”
  • DuplicateHandle 来自“api-ms-win-core-handle-l1-1-0.dll”
  • CloseHandle 来自“api-ms-win-core-handle-l1-1-0.dll”
  • DeviceIoControl 来自“api-ms-win-core-io-l1-1-0.dll”

使用 CreateFileWDuplicateHandleCloseHandle 的挂钩,您可以跟踪与句柄关联的文件名。

然后,当您看到控制代码为 0x8000e00c 的对 DeviceIoControl 的调用时,您就会知道正在读取的文件名。


第一次调用 XInputGetState 时,它会打开多个设备,并多次调用 DeviceIoControl,无论您请求的是哪个玩家号码。您只对 DeviceIoControlXInputGetState 返回之前看到的最后一个文件名感兴趣。如果 XInputGetState 表示控制器未插入,请忽略您为该控制器编号收集的文件名。


我在自己的计算机上看到的文件名示例:

  • \\?\hid#{00001124-0000-1000-8000-00805f9b34fb}&vid_045e&pid_02e0&ig_00#8&7074921&2&0000#{ec87f1e3-c13b-4100-b5f7-8b84d54260cb}
  • \\?\usb#vid_045e&pid_028e#1&1a590e2c&1&01#{ec87f1e3-c13b-4100-b5f7-8b84d54260cb}

编辑:

还需要一个钩子。

  • CoCreateInstance 来自“api-ms-win-core-com-l1-1-0.dll”,用于挂钩创建未记录的 IDeviceBroker COM 对象。如果它可以成功创建一个 IDeviceBroker COM 对象,它将使用该对象而不是对 CreateFileW 的调用。参数将为:CLSID_DeviceBroker = {acc56a05-e277-4b1e-a43e-7a73e3cd6e6c}IID_IDeviceBroker = {8604b268-34a6-4b1a-a59f-cdbd8379fd98}。将调用方法 OpenDeviceFromInterfacePath 而不是 CreateFileW。或者,您可以简单地创建 IDeviceBroker 对象失败,它会继续像往常一样使用 CreateFileW