Regarding guidInstance in DIDEVICEINSTANCE
Microsoft says:
Unique identifier for the instance of the device. An application can save the instance globally unique identifier (GUID) into a configuration file and use it at a later time. Instance GUIDs are specific to a particular computer. An instance GUID obtained from one computer is unrelated to instance GUIDs on another.
So, if I connect my device to the computer and my program does enumeration and finds the guid, do I ever have to enumerate again? Even if the user plugs and unplugs the device. If another device of the same type is plugged in, does it still recognize that the second device is not the same as the first and therefore requires a different guid? Should I just renumerate all the interfaces all the time my program runs to find my device or is once enough for a given pc?
Thanks.
I'm actually trying to solve a similar problem. According to the MSDN here, it looks like InstanceGUID is supposed to always be the same on the same computer. I've verified that if I unplug my USB device and plug it into a different port, it does indeed keep the same Instance GUID. However, if a different user logs into the same PC, DirectInput shows the same device having a different InstanceGUID!! I can't find any acknowledgement from Microsoft that this is a known problem.
So, I can partially answer your question. If you have two identical devices, you will get different InstanceGUIDs, and identical ProductGUIDs. Those InstanceGUIDs will stay consistent if you unplug your devices and move them to different USB ports. HOWEVER you will get different InstanceGUIDs if a different user logs in. At least I can verify that this is an issue on Windows 7 64bit.
The InstanceGuid will always be a unique identifier for every device plugged in - but if you remove the installation information (e.g. uninstalling a usb device) you also lose that InstanceGuid. The device will get some new unpredictable Guid when plugged in again.
The ProductGuid will always be the same for one device, since it's stored in the devices USB HID chip. It may happen though that two devices of the exact same type have the same ProductGuid. If they do, you can only identify them by their InstanceGuid (which may become invalid in some cases, as written above...).
Related
I've been exploring the MIDI APIs available on macOS and Windows recently (Core MIDI and Windows Multimedia, respectively) and noticed:
On MacOS, after querying for the number of available sources, each source can be uniquely identified by checking the value of the property kMIDIPropertyUniqueID.
On Win32, I can't find a clear alternative - it seems that an input device's "ID" is no more than the index into the list of connected devices, which could change at any time as new devices are connected and disconnected. Information in the capabilities structure one can request from a device is also not particularly distinctive, as using two of the same MIDI keyboard at once would result in two identical capability sets right down to the product name.
Is there some way to uniquely identify these devices in WinMM?
Short answer is no.
ID of a device in WinMM is indeed just an index in the devices list. So if you unplug one device and plug another one with the same properties (name, for example), you won't be able to determine whether the device you work with is the old one or new. Name, of course, can be the same, so that's not an option.
So from programming side there is no way to distinguish two MIDI devices with the same properties in Windows. In an app you can provide a button like "Refresh devices" or "Test device" to be up to date with current devices and to be able to determine which object in GUI corresponds to a MIDI device to.
As for macOS, kMIDIPropertyUniqueID is an option, BUT there are nuances. From the documentation on the constant:
The system assigns unique IDs to all objects. You may set this
property on virtual endpoints; however, doing so may fail if the ID
isn’t unique.
So in some cases you can get not unique value. In my opinion, the most reliable way to identify a device in macOS is to use its reference. For example, when you get a source device with MIDIGetSource you get MIDIEndpointRef as the result. In fact it's a UInt32 number which is truly unique in the scope of the system.
So I in my .NET library DryWetMIDI rely on MIDIEndpointRef to distinguish MIDI devices in macOS. Also it's possible to provide MIDI devices watching (adding/removing). But for Windows it's not possible unfortunately.
Unfortunately there is no equivalent in WinMM.
The best you can do is open the device to get a handle to it. The handle will be unique and will always refer to the opened device, even if other devices are added and removed.
Once you have the handle, you can use midiInGetID() or midiOutGetID() to get the ID in case it has changed.
I want to create an application or modify USB in a way so that, upon insertion into any PC, I can get the information that PC was inserted.
eg. upon insertion, I can read PC name and make an API call with this as post data so I'm able to know that my USB was inserted in some PC. But this should happen right away as USB is read by the machine, so even if the user formats it thereafter, it should not matter.
If it was earlier windows, I could write autorun and that would work. But I want this detection mechanism for Windows 7 and above.
I have done some research on the topic but could not find any reliable content. Some articles were related to USB based hacking attacks by changing wiring (USB hardware, to harm the computer) or something like that. But I totally don't want to do that. Just the detection, that USB was used.
I am using DirectInput8 in a project at work that monitors various components of the pc. To monitor joysticks we use DirectInput8. The data is retrieved by enumerating all joysticks with DI8DEVCLASS_GAMECTRL as the type and DIEDFL_ATTACHEDONLY as a flag. Recently it was brought to my attention that we were having multiple joysticks showing up. First I looked at the xml file we store the components in between reboots. There were two entries for the joysticks, Logitech Extreme 3d pro, and each had a unique product guid. I backed the file up and removed it, effectively forcing a rescan of the machine next time the app started after I rebooted the machine. I was able to get the same problem to occur and logged out the guids and they are different for each. The system only has a single joystick plugged in however it plugs in through a usb hub. Is the hub affecting the guids I am seeing? I could also only get this to occur maybe 1 out of 5 attempts.
Example:
Joystick Product GUID: 3C6A972000000000504944564944
Joystick Instance GUID: 3C6A972097C11E3800144455354
Joystick Product GUID: DA83AFB000000000504944564944
Joystick Instance GUID: DA83AFB0D7B211E2800144455354
Had a similar issue... I just exported the DirectInput registry settings for the VID/PIDs I wanted to replicate GUIDs across machines.
So, in regedit navigate to:
[HKEY_CURRENT_USER\System\CurrentControlSet\Control\MediaProperties\PrivateProperties\DirectInput\VID_[Whatever]&PID_[Whatever]\
Right click, choose Export to create the .reg file, the move it to the machine you want and double click.
This was a pain to find but after watching our testers I found they were logging into multiple user accounts and the GUID returned was different per user which is what caused the problem, would be nice if the documentation would be updated to reflect this.
I'm having the exact same problem as the original poster. To clarify his answer, its the instance GUID that is different for each user. And here is the MSDN documentation that incorrectly asserts that the InstanceGUID should stay the same on a given computer. Without someone from Mircosoft weighing in I don't know that I'll ever know the answer why this is - is it a bug or is the documentation incorrect.
The bottom line is you'll have a heck of a time sharing keybindings for a joystick among multiple users without a solution to this problem, which is my situation.
The function midiOutGetDevCaps returns a structure MIDIOUTCAPS.
I'd need more specific information when querying a usb midi device on windows xp, in particular I'd need the information displayed under "Location" when opening the respective device using the Device Manager.
I need this information in order to programmatically distinguish between several MIDI Interfaces connected to a computer. Using midiOutGetDevCaps, I uniformly get "USB Audio Device" for every midi usb interface connected to the computer, so distinguishing between the interfaces is impossible.
To make matters worse, this string is localized, so e.g. on a German Windows you'll get "USB Audiogerät" instead of "USB Audio Device".
I guess it depends on how desperate you are. I've had my own run in with USB devices. In my case I needed to enumerate certain USB COM port related devices . . . regardless if they are currently attached to the system or not.
It is all company proprietary code, sorry I cannot post it, but the search for all information regarding USB related devices starts here (Perl):
$hostnamePrefix = "//$hostname/";
my $baseKey = "${hostnamePrefix}HKEY_LOCAL_MACHINE/System/CurrentControlSet/";
my $regVidList = Win32::TieRegistry->new("${baseKey}Enum/USB/", $optionsRef);
If memory serves me it is a reasonably straight forward structure. I believe you actually have to loop through two separate sections of the registry to get everything you need . . . if you are desperate enough to attempt this, I'm happy to answer questions where I can, but posting code would required approval from our legal department. (Not impossible, but it would take weeks to obtain.)
Also, while this will work on XP . . . I have no idea how it will work on Win7. (I don't know either way, nobody has tried it yet that I am aware of.)
Coding this was not that bad (resulting Perl Script is around 1000 lines of code which is almost 50% comments), but working out all the relationships between the keys and the special cases took several days.
We have an auto update for our software that is installed via USB key (with the auto run). If I wanted to ensure that only authorized USB Keys were used, what's the best way?
Our installer is already signed, and it won't run otherwise. But I'm more wanting to inspect the USB Key for a signed installer, and if it's not there, just ignore, or even "Eject" the USB device.
And I should be able to tell the difference (in code) between a usb storage device, and say a camera, or keyboard.
I'm only wanting to disable non-authorized storage devices.
Thank you for your ideas.
non-authorized storage devices? This depends on how secure you want it to be. For the most secure level, it would consist of:
special firmware written to the flash drive to get extra "meta info" (read: expensive custom manufacturing of flash drives)
special windows driver to read that meta info from the flash drive
your program talking to that device driver to confirm it's authorized.
Or to the least secure level you have these options:
using a hidden file and a special key(possibly hashed time of last filesystem modification or something?) (dd breakable)
dropping below the filesystem level and recreating your own very simple filesystem.. (more security through obscurity though and dd could break that)
Also, for the "most secure" option, you really need a more secure way of running the program than auto-run and a device driver(which could be half-baked to make anything appear authorized). Why do you want it to only update from an authorized flash drive anyway?
You might be able to read the USB drive's serial number (assuming you get USB drives that have serial numbers; not all do). Then your application could call home to get the latest list of authorized serial numbers, and check to see if there is a match.
Earlz response is good, though I don't think you'd need custom manufacturing of flash drives... you would just need flash drives with some sort of unique firmware encrypted identifier. Perhaps something in the Kingston Data Traveler Line might do the trick. (I've never actually used one of these encrypted usb sticks, so I'm a bit foggy on the actual implementation details).