private static void RetrieveProperties(string hash, ref PortDefinition pd, AsyncUsbStream s) { IDictionaryEnumerator dict; dict = s_textProperties.GetEnumerator(); while (dict.MoveNext()) { pd.Properties.Add(dict.Key, s.RetrieveStringFromDevice((int)dict.Value)); } dict = s_digitProperties.GetEnumerator(); while (dict.MoveNext()) { pd.Properties.Add(dict.Key, s.RetrieveIntegerFromDevice((int)dict.Value)); } }
// The following procedure works with the USB device driver; upon finding all instances of USB devices // that match the requested Guid, the procedure checks the corresponding registry keys to find the unique // serial number to show to the user; the serial number is decided by the device driver at installation // time and stored in a registry key whose name is the hash of the laser etched security key of the device private static void EnumeratePorts(Guid inquiriesInterface, string driverVersion, SortedList lst) { IntPtr devInfo = Native.SetupDiGetClassDevs(ref inquiriesInterface, null, 0, Native.DIGCF_DEVICEINTERFACE | Native.DIGCF_PRESENT); if (devInfo == Native.INVALID_HANDLE_VALUE) { return; } Native.SP_DEVICE_INTERFACE_DATA interfaceData = new Native.SP_DEVICE_INTERFACE_DATA(); interfaceData.cbSize = Marshal.SizeOf(interfaceData); int index = 0; while (Native.SetupDiEnumDeviceInterfaces(devInfo, 0, ref inquiriesInterface, index++, ref interfaceData)) { Native.SP_DEVICE_INTERFACE_DETAIL_DATA detail = new Native.SP_DEVICE_INTERFACE_DETAIL_DATA(); // explicit size of unmanaged structure must be provided, because it does not include transfer buffer // for whatever reason on 64 bit machines the detail size is 8 rather than 5, likewise the interfaceData.cbSize // is 32 rather than 28 for non 64bit machines, therefore, we make the detemination of the size based // on the interfaceData.cbSize (kind of hacky but it works). if (interfaceData.cbSize == 32) { detail.cbSize = 8; } else { detail.cbSize = 5; } if (Native.SetupDiGetDeviceInterfaceDetail(devInfo, ref interfaceData, ref detail, Marshal.SizeOf(detail) * 2, 0, 0)) { string port = detail.DevicePath.ToLower(); AsyncUsbStream s = null; try { s = new AsyncUsbStream(port); string displayName = s.RetrieveStringFromDevice(IOCTL_SPOTUSB_DISPLAY_NAME); string hash = s.RetrieveStringFromDevice(IOCTL_SPOTUSB_DEVICE_HASH); string operationalPort = s.RetrieveStringFromDevice(IOCTL_SPOTUSB_PORT_NAME); if ((operationalPort == null) || (displayName == null) || (hash == null)) { continue; } // convert kernel format to user mode format // kernel : @"\??\USB#Vid_beef&Pid_0009#5&4162af8&0&1#{09343630-a794-10ef-334f-82ea332c49f3}" // user : @"\\?\usb#vid_beef&pid_0009#5&4162af8&0&1#{09343630-a794-10ef-334f-82ea332c49f3}" StringBuilder operationalPortUser = new StringBuilder(); operationalPortUser.Append(@"\\?"); operationalPortUser.Append(operationalPort.Substring(3)); PortDefinition pd = PortDefinition.CreateInstanceForUsb(displayName + "_" + hash, operationalPortUser.ToString()); RetrieveProperties(hash, ref pd, s); lst.Add(pd.DisplayName, pd); } catch { } finally { if (s != null) s.Close(); } } } Native.SetupDiDestroyDeviceInfoList(devInfo); }