Ordinarily XInput controllers are identified simply using an index corresponding to the player number of the controller. Is there a way to obtain more information about a controller with a specific index, such as its vendor ID, product ID, or device name?
Even better would be a identifier that corresponds uniquely and consistently to just that controller so that it can be distinguished from all other XInput devices regardless of its index, including another controller that's an identical model (i.e. same product and vendor ID), similar to the instance GUID available using DirectInput.
Can this be accomplished using XInput or another Microsoft API? I'm also open to using undocumented functions if need be.
What XInput internally does is open a device, then call
DeviceIoControlon it every time it reads the joypad. (control code 0x8000e00c)You need to hook these functions imported by "XInput1_4.dll":
CreateFileWfrom "api-ms-win-core-file-l1-1-0.dll"DuplicateHandlefrom "api-ms-win-core-handle-l1-1-0.dll"CloseHandlefrom "api-ms-win-core-handle-l1-1-0.dll"DeviceIoControlfrom "api-ms-win-core-io-l1-1-0.dll"Using the hooks for
CreateFileW,DuplicateHandleandCloseHandle, you can keep track of what filename is associated with a handle.Then when you see a call to
DeviceIoControlwith control code 0x8000e00c, you will know what filename is being read.The first time you call
XInputGetState, it will open multiple devices, and callDeviceIoControlmultiple times, regardless of what player number you have asked for. You are only interested in the last filename seen byDeviceIoControlbeforeXInputGetStatereturns. And ifXInputGetStateindicates the controller is not plugged in, disregard the filename you have collected for that controller number.Examples of filenames I have seen on my own computer:
\\?\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}edit:
One more hook is required as well.
CoCreateInstancefrom "api-ms-win-core-com-l1-1-0.dll", to hook creating the undocumentedIDeviceBrokerCOM object. If it can successfully create anIDeviceBrokerCOM object, it will use that instead of the call toCreateFileW. Parameters will be:CLSID_DeviceBroker = {acc56a05-e277-4b1e-a43e-7a73e3cd6e6c},IID_IDeviceBroker = {8604b268-34a6-4b1a-a59f-cdbd8379fd98}. The methodOpenDeviceFromInterfacePathwill be called instead ofCreateFileW. Alternatively, you can make creating theIDeviceBrokerobject simply fail, and it will proceed to useCreateFileWas usual.