using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using Microsoft.Win32;

namespace QC.QMSCT;

public class USBEnumerator
{
	public delegate void UpdateUSBDetectionLogEvent(string information);

	[StructLayout(LayoutKind.Sequential)]
	public class OSVersionInfo
	{
		public int OSVersionInfoSize;

		public int MajorVersion;

		public int MinorVersion;

		public int BuildNumber;

		public int PlatformId;

		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
		public string versionString;
	}

	internal enum USB_HUB_NODE : uint
	{
		UsbHub,
		UsbMIParent
	}

	[StructLayout(LayoutKind.Sequential, Pack = 1)]
	internal struct USB_HUB_DESCRIPTOR
	{
		public byte bDescriptorLength;

		public byte bDescriptorType;

		public byte bNumberOfPorts;

		public short wHubCharacteristics;

		public byte bPowerOnToPowerGood;

		public byte bHubControlCurrent;

		[MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
		public byte[] bRemoveAndPowerMask;
	}

	internal struct USB_HUB_INFORMATION
	{
		public USB_HUB_DESCRIPTOR HubDescriptor;

		public byte HubIsBusPowered;
	}

	internal struct USB_MI_PARENT_INFORMATION
	{
		public int NumberOfInterfaces;
	}

	[StructLayout(LayoutKind.Explicit)]
	internal struct UsbNodeUnion
	{
		[FieldOffset(0)]
		public USB_HUB_INFORMATION HubInformation;

		[FieldOffset(0)]
		public USB_MI_PARENT_INFORMATION MiParentInformation;
	}

	internal struct USB_NODE_INFORMATION
	{
		public USB_HUB_NODE NodeType;

		public UsbNodeUnion u;
	}

	internal enum USB_CONNECTION_STATUS
	{
		NoDeviceConnected,
		DeviceConnected,
		DeviceFailedEnumeration,
		DeviceGeneralFailure,
		DeviceCausedOvercurrent,
		DeviceNotEnoughPower,
		DeviceNotEnoughBandwidth,
		DeviceHubNestedTooDeeply,
		DeviceInLegacyHub
	}

	[StructLayout(LayoutKind.Sequential, Pack = 1)]
	internal struct USB_DEVICE_DESCRIPTOR
	{
		public byte bLength;

		public byte bDescriptorType;

		public ushort bcdUSB;

		public byte bDeviceClass;

		public byte bDeviceSubClass;

		public byte bDeviceProtocol;

		public byte bMaxPacketSize0;

		public ushort idVendor;

		public ushort idProduct;

		public ushort bcdDevice;

		public byte iManufacturer;

		public byte iProduct;

		public byte iSerialNumber;

		public byte bNumConfigurations;
	}

	[StructLayout(LayoutKind.Sequential, Pack = 1)]
	internal struct USB_ENDPOINT_DESCRIPTOR
	{
		public byte bLength;

		public byte bDescriptorType;

		public byte bEndpointAddress;

		public byte bmAttributes;

		public ushort wMaxPacketSize;

		public byte bInterval;
	}

	[StructLayout(LayoutKind.Sequential, Pack = 1)]
	internal struct USB_PIPE_INFO
	{
		public USB_ENDPOINT_DESCRIPTOR EndpointDescriptor;

		public uint ScheduleOffset;
	}

	[StructLayout(LayoutKind.Sequential, Pack = 1)]
	internal struct USB_NODE_CONNECTION_INFORMATION_EX
	{
		public int ConnectionIndex;

		public USB_DEVICE_DESCRIPTOR DeviceDescriptor;

		public byte CurrentConfigurationValue;

		public byte Speed;

		public byte DeviceIsHub;

		public short DeviceAddress;

		public int NumberOfOpenPipes;

		public USB_CONNECTION_STATUS ConnectionStatus;

		[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
		public USB_PIPE_INFO[] PipeList;
	}

	[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
	internal struct USB_NODE_CONNECTION_DRIVERKEY_NAME
	{
		public int ConnectionIndex;

		public int ActualLength;

		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 255)]
		public string DriverKeyName;
	}

	internal struct SP_DEVINFO_DATA
	{
		public uint cbSize;

		public Guid ClassGuid;

		public int DevInst;

		public IntPtr Reserved;
	}

	public class USBPortDetails
	{
		public string PortDescription = "";

		public string PortPhysicalAddress = "";

		public string UDEDevice = "";

		public USBPortDetails(string portDescription, string portPhysicalAddress, string udeDeviceDescription = "")
		{
			PortDescription = portDescription;
			PortPhysicalAddress = portPhysicalAddress;
			UDEDevice = udeDeviceDescription;
		}

		public USBPortDetails(USBPortDetails usbPortDetails)
		{
			PortDescription = usbPortDetails.PortDescription;
			PortPhysicalAddress = usbPortDetails.PortPhysicalAddress;
			UDEDevice = usbPortDetails.UDEDevice;
		}
	}

	public class USB_PORT_INFO_LIST
	{
		private Dictionary<int, USBPortDetails> USBPortTable = new Dictionary<int, USBPortDetails>();

		public USBPortDetails this[int portno] => USBPortTable[portno];

		public Dictionary<int, USBPortDetails>.KeyCollection PortNumbers => USBPortTable.Keys;

		public Dictionary<int, USBPortDetails>.ValueCollection PortDetails => USBPortTable.Values;

		public int Count
		{
			get
			{
				try
				{
					return USBPortTable.Count;
				}
				catch
				{
					return 0;
				}
			}
		}

		public bool ContainsPortNumber(int portNumber)
		{
			return USBPortTable.ContainsKey(portNumber);
		}

		public int FirstCOMNumberByPortDetails(USBPortDetails portDetails)
		{
			if (portDetails == null)
			{
				return -1;
			}
			foreach (int key in USBPortTable.Keys)
			{
				bool flag = true;
				if (portDetails.PortDescription != null && USBPortTable[key].PortDescription != portDetails.PortDescription)
				{
					flag = false;
				}
				if (portDetails.PortPhysicalAddress != null && USBPortTable[key].PortPhysicalAddress != portDetails.PortPhysicalAddress)
				{
					flag = false;
				}
				if (flag)
				{
					return key;
				}
			}
			return -1;
		}

		public void Add(USB_PORT_INFO_LIST list, int portNumber)
		{
			USBPortTable.Add(portNumber, new USBPortDetails(list[portNumber]));
		}

		public void Add(int portNumber, string portDescription, string portPhysicalAddress)
		{
			USBPortTable.Add(portNumber, new USBPortDetails(portDescription, portPhysicalAddress));
		}

		public void Add(string udeDevice, string portPhysicalAddress)
		{
			USBPortTable.Add(0, new USBPortDetails("Primary Bootloader", portPhysicalAddress, udeDevice));
		}

		public bool SearchPhysicalAddress(string udeDevice, string physicalAddress)
		{
			bool result = false;
			foreach (int key in USBPortTable.Keys)
			{
				if (USBPortTable[key].PortPhysicalAddress.StartsWith(physicalAddress))
				{
					result = true;
					USBPortTable[key].UDEDevice = udeDevice;
					USBPortTable[key].PortPhysicalAddress = physicalAddress;
				}
			}
			return result;
		}

		public void Clear()
		{
			USBPortTable.Clear();
		}

		public IEnumerator GetEnumerator()
		{
			try
			{
				return USBPortTable.GetEnumerator();
			}
			catch
			{
				return null;
			}
		}

		public bool IsSameAs(USB_PORT_INFO_LIST obj)
		{
			if (USBPortTable.Count != obj.Count)
			{
				return false;
			}
			foreach (int key in USBPortTable.Keys)
			{
				if (obj.FirstCOMNumberByPortDetails(USBPortTable[key]) != key)
				{
					return false;
				}
			}
			return true;
		}
	}

	public const int INVALID_HANDLE_VALUE = -1;

	public const string REGSTR_KEY_USB = "USB";

	public const string REGSTR_KEY_PCI = "PCI";

	public const string REGSTR_KEY_PCMCIA = "PCMCIA";

	public const uint SPDRP_DEVICEDESC = 0u;

	public const uint SPDRP_HARDWAREID = 1u;

	public const uint SPDRP_COMPATIBLEIDS = 2u;

	public const uint SPDRP_UNUSED0 = 3u;

	public const uint SPDRP_SERVICE = 4u;

	public const uint SPDRP_UNUSED1 = 5u;

	public const uint SPDRP_UNUSED2 = 6u;

	public const uint SPDRP_CLASS = 7u;

	public const uint SPDRP_CLASSGUID = 8u;

	public const uint SPDRP_DRIVER = 9u;

	public const uint SPDRP_CONFIGFLAGS = 10u;

	public const uint SPDRP_MFG = 11u;

	public const uint SPDRP_FRIENDLYNAME = 12u;

	public const uint SPDRP_LOCATION_INFORMATION = 13u;

	public const uint SPDRP_PHYSICAL_DEVICE_OBJECT_NAME = 14u;

	public const uint SPDRP_CAPABILITIES = 15u;

	public const uint SPDRP_UI_NUMBER = 16u;

	public const uint SPDRP_UPPERFILTERS = 17u;

	public const uint SPDRP_LOWERFILTERS = 18u;

	public const uint SPDRP_BUSTYPEGUID = 19u;

	public const uint SPDRP_LEGACYBUSTYPE = 20u;

	public const uint SPDRP_BUSNUMBER = 21u;

	public const uint SPDRP_ENUMERATOR_NAME = 22u;

	public const uint SPDRP_SECURITY = 23u;

	public const uint SPDRP_SECURITY_SDS = 24u;

	public const uint SPDRP_DEVTYPE = 25u;

	public const uint SPDRP_EXCLUSIVE = 26u;

	public const uint SPDRP_CHARACTERISTICS = 27u;

	public const uint SPDRP_ADDRESS = 28u;

	public const uint SPDRP_UI_NUMBER_DESC_FORMAT = 29u;

	public const uint SPDRP_DEVICE_POWER_DATA = 30u;

	public const uint SPDRP_REMOVAL_POLICY = 31u;

	public const uint SPDRP_REMOVAL_POLICY_HW_DEFAULT = 32u;

	public const uint SPDRP_REMOVAL_POLICY_OVERRIDE = 33u;

	public const uint SPDRP_INSTALL_STATE = 34u;

	public const uint SPDRP_LOCATION_PATHS = 35u;

	public const uint SPDRP_BASE_CONTAINERID = 36u;

	public const uint DIGCF_DEFAULT = 1u;

	public const uint DIGCF_PRESENT = 2u;

	public const uint DIGCF_ALLCLASSES = 4u;

	public const uint DIGCF_PROFILE = 8u;

	public const uint DIGCF_DEVICEINTERFACE = 16u;

	public const int BUFFER_SIZE = 2048;

	public const uint REG_SZ = 1u;

	internal const uint GENERIC_WRITE = 1073741824u;

	internal const uint FILE_SHARE_WRITE = 2u;

	internal const uint OPEN_EXISTING = 3u;

	internal const int MAXIMUM_USB_STRING_LENGTH = 255;

	internal const int IOCTL_USB_GET_NODE_INFORMATION = 2229256;

	internal const int IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX = 2229320;

	internal const int IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME = 2229280;

	public const int CR_SUCCESS = 0;

	public const int CM_DRP_CLASSGUID = 9;

	public const int CM_DRP_DRIVER = 10;

	public const string GUID_ADB = "{3f966bd9-fa04-4ec5-991c-d326973b5128}";

	public const string GUID_PORT = "{4D36E978-E325-11CE-BFC1-08002BE10318}";

	public const string GUID_HUB = "{36fc9e60-c465-11cf-8056-444553540000}";

	public const string GUID_HUB_DRIVER = "{f18a0e88-c30c-11d0-8815-00a0c906bed8}";

	private const string RegexUDE = ".*? UDE Device .*?";

	public UpdateUSBDetectionLogEvent UpdateUSBDetectionLogCallback;

	private List<string> PORT_KEY = new List<string>();

	private bool PORT_KEY_CASE_SENS;

	public List<string> PortKeyWord
	{
		get
		{
			return PORT_KEY;
		}
		set
		{
			PORT_KEY = value;
		}
	}

	public bool PortKeyWordCaseSensitive
	{
		get
		{
			return PORT_KEY_CASE_SENS;
		}
		set
		{
			PORT_KEY_CASE_SENS = value;
		}
	}

	private void UpdateUSBDetectionLog(string information)
	{
		if (UpdateUSBDetectionLogCallback != null)
		{
			UpdateUSBDetectionLogCallback(information);
		}
	}

	[DllImport("kernel32.dll", SetLastError = true)]
	public static extern bool GetVersionEx([In][Out] OSVersionInfo osvi);

	[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
	internal static extern bool DeviceIoControl(IntPtr hFile, int dwIoControlCode, ref USB_NODE_INFORMATION lpInBuffer, int nInBufferSize, ref USB_NODE_INFORMATION lpOutBuffer, int nOutBufferSize, out int lpBytesReturned, IntPtr lpOverlapped);

	[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
	internal static extern bool DeviceIoControl(IntPtr hFile, int dwIoControlCode, ref USB_NODE_CONNECTION_INFORMATION_EX lpInBuffer, int nInBufferSize, ref USB_NODE_CONNECTION_INFORMATION_EX lpOutBuffer, int nOutBufferSize, out int lpBytesReturned, IntPtr lpOverlapped);

	[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
	internal static extern bool DeviceIoControl(IntPtr hFile, int dwIoControlCode, ref USB_NODE_CONNECTION_DRIVERKEY_NAME lpInBuffer, int nInBufferSize, ref USB_NODE_CONNECTION_DRIVERKEY_NAME lpOutBuffer, int nOutBufferSize, out int lpBytesReturned, IntPtr lpOverlapped);

	[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
	internal static extern IntPtr CreateFile([MarshalAs(UnmanagedType.LPTStr)] string filename, [MarshalAs(UnmanagedType.U4)] uint access, [MarshalAs(UnmanagedType.U4)] uint share, IntPtr securityAttributes, [MarshalAs(UnmanagedType.U4)] uint creationDisposition, [MarshalAs(UnmanagedType.U4)] uint flagsAndAttributes, IntPtr templateFile);

	[DllImport("kernel32.dll", SetLastError = true)]
	internal static extern bool CloseHandle(IntPtr hHandle);

	[DllImport("setupapi.dll", CharSet = CharSet.Auto)]
	internal static extern IntPtr SetupDiGetClassDevs(ref Guid ClassGuid, int Enumerator, IntPtr hwndParent, uint Flags);

	[DllImport("setupapi.dll", CharSet = CharSet.Auto)]
	internal static extern IntPtr SetupDiGetClassDevs(int ClassGuid, string Enumerator, IntPtr hwndParent, uint Flags);

	[DllImport("setupapi.dll", SetLastError = true)]
	internal static extern bool SetupDiDestroyDeviceInfoList(IntPtr DeviceInfoSet);

	[DllImport("setupapi.dll", SetLastError = true)]
	internal static extern bool SetupDiEnumDeviceInfo(IntPtr DeviceInfoSet, uint MemberIndex, ref SP_DEVINFO_DATA DeviceInfoData);

	[DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
	internal static extern bool SetupDiGetDeviceRegistryProperty(IntPtr DeviceInfoSet, ref SP_DEVINFO_DATA DeviceInfoData, uint Property, ref uint PropertyRegDataType, IntPtr PropertyBuffer, uint PropertyBufferSize, ref uint RequiredSize);

	[DllImport("setupapi.dll", SetLastError = true)]
	internal static extern int CM_Get_Parent(ref int pdnDevInst, int dnDevInst, int ulFlags);

	[DllImport("setupapi.dll", SetLastError = true)]
	internal static extern int CM_Get_Child(ref int pdnDevInst, int dnDevInst, int ulFlags);

	[DllImport("setupapi.dll", SetLastError = true)]
	internal static extern int CM_Get_Sibling(ref int pdnDevInst, int dnDevInst, int ulFlags);

	[DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
	internal static extern int CM_Get_Device_ID(int dnDevInst, IntPtr Buffer, int BufferLen, int ulFlags);

	[DllImport("setupapi.dll", SetLastError = true)]
	public static extern int CM_Get_DevNode_Registry_Property(int dnDevInst, int ulProperty, out RegistryValueKind pulRegDataType, IntPtr Buffer, ref uint pulLength, int ulFlags);

	public void GetUSBDevicePhysicalAddressByName(string strDeviceName, ref List<string> strPhysicalAddressCollection)
	{
		if (strPhysicalAddressCollection == null)
		{
			return;
		}
		strPhysicalAddressCollection.Clear();
		string enumerator = "USB";
		UpdateUSBDetectionLog("Searching Device Name:" + strDeviceName);
		IntPtr deviceInfoSet = SetupDiGetClassDevs(0, enumerator, IntPtr.Zero, 6u);
		if (deviceInfoSet.ToInt32() == -1)
		{
			return;
		}
		bool flag = true;
		uint num = 0u;
		while (flag)
		{
			SP_DEVINFO_DATA DeviceInfoData = default(SP_DEVINFO_DATA);
			DeviceInfoData.cbSize = (uint)Marshal.SizeOf((object)DeviceInfoData);
			flag = SetupDiEnumDeviceInfo(deviceInfoSet, num, ref DeviceInfoData);
			if (flag)
			{
				string deviceDescription = GetDeviceDescription(deviceInfoSet, DeviceInfoData);
				if (deviceDescription != null && deviceDescription.IndexOf(strDeviceName) > 0)
				{
					string physicalAddress = GetPhysicalAddress(deviceInfoSet, DeviceInfoData);
					if (physicalAddress != null)
					{
						if (!strPhysicalAddressCollection.Contains(physicalAddress))
						{
							strPhysicalAddressCollection.Add(physicalAddress);
						}
					}
					else
					{
						UpdateUSBDetectionLog("Fail to get Physical Address of devInst:" + DeviceInfoData.DevInst);
					}
				}
				else
				{
					UpdateUSBDetectionLog("Fail to get Device Description of devInst:" + DeviceInfoData.DevInst);
				}
			}
			num++;
		}
		SetupDiDestroyDeviceInfoList(deviceInfoSet);
	}

	public void GetUSBDevicePhysicalAddressByGuid(List<string> guidCollection, ref List<string> strPhysicalAddressCollection, ref List<List<int>> intPortNumberCollection)
	{
		if (strPhysicalAddressCollection == null)
		{
			return;
		}
		string enumerator = "USB";
		strPhysicalAddressCollection.Clear();
		foreach (string item in guidCollection)
		{
			UpdateUSBDetectionLog("Searching GUID:" + item);
			IntPtr deviceInfoSet = SetupDiGetClassDevs(0, enumerator, IntPtr.Zero, 6u);
			if (deviceInfoSet.ToInt32() == -1)
			{
				continue;
			}
			bool flag = true;
			uint num = 0u;
			while (flag)
			{
				SP_DEVINFO_DATA DeviceInfoData = default(SP_DEVINFO_DATA);
				DeviceInfoData.cbSize = (uint)Marshal.SizeOf((object)DeviceInfoData);
				flag = SetupDiEnumDeviceInfo(deviceInfoSet, num, ref DeviceInfoData);
				if (flag)
				{
					string classGUID = GetClassGUID(deviceInfoSet, DeviceInfoData);
					if (classGUID != null && classGUID.ToLower() == item.ToLower())
					{
						string physicalAddress = GetPhysicalAddress(deviceInfoSet, DeviceInfoData);
						if (physicalAddress != null)
						{
							if (item == "{4D36E978-E325-11CE-BFC1-08002BE10318}")
							{
								UpdateUSBDetectionLog("Port Class Found on:" + physicalAddress);
								int comPortNumber = GetComPortNumber(deviceInfoSet, DeviceInfoData);
								if (comPortNumber != 0)
								{
									UpdateUSBDetectionLog("Port Number:" + comPortNumber);
									if (!strPhysicalAddressCollection.Contains(physicalAddress))
									{
										strPhysicalAddressCollection.Add(physicalAddress);
										if (intPortNumberCollection != null)
										{
											intPortNumberCollection.Add(new List<int>());
										}
									}
									int num2 = strPhysicalAddressCollection.IndexOf(physicalAddress);
									if (num2 < 0)
									{
										UpdateUSBDetectionLog("Out of bounds!!!!");
									}
									else if (intPortNumberCollection != null)
									{
										List<int> list = intPortNumberCollection[num2];
										if (!list.Contains(comPortNumber))
										{
											list.Add(comPortNumber);
										}
									}
								}
								else
								{
									UpdateUSBDetectionLog("Fail to get port number on:" + physicalAddress + ",ignored");
								}
							}
							else if (!strPhysicalAddressCollection.Contains(physicalAddress))
							{
								strPhysicalAddressCollection.Add(physicalAddress);
								if (intPortNumberCollection != null)
								{
									intPortNumberCollection.Add(new List<int>());
								}
							}
						}
						else
						{
							UpdateUSBDetectionLog("Fail to get Physical Address of devInst:" + DeviceInfoData.DevInst);
						}
					}
				}
				num++;
			}
			SetupDiDestroyDeviceInfoList(deviceInfoSet);
		}
	}

	public void GetPortNumberByUSBDevicePhysicalAddress(string strPhysicalAddress, ref List<int> intPortNumberCollection)
	{
		if (strPhysicalAddress == null)
		{
			return;
		}
		string enumerator = "USB";
		string text = "{4D36E978-E325-11CE-BFC1-08002BE10318}";
		UpdateUSBDetectionLog("Searching physical address:" + strPhysicalAddress);
		IntPtr deviceInfoSet = SetupDiGetClassDevs(0, enumerator, IntPtr.Zero, 6u);
		if (deviceInfoSet.ToInt32() == -1)
		{
			return;
		}
		bool flag = true;
		uint num = 0u;
		while (flag)
		{
			SP_DEVINFO_DATA DeviceInfoData = default(SP_DEVINFO_DATA);
			DeviceInfoData.cbSize = (uint)Marshal.SizeOf((object)DeviceInfoData);
			flag = SetupDiEnumDeviceInfo(deviceInfoSet, num, ref DeviceInfoData);
			if (flag)
			{
				string classGUID = GetClassGUID(deviceInfoSet, DeviceInfoData);
				if (classGUID != null && classGUID.ToLower() == text.ToLower())
				{
					string physicalAddress = GetPhysicalAddress(deviceInfoSet, DeviceInfoData);
					if (physicalAddress != null && physicalAddress.IndexOf(strPhysicalAddress) == 0)
					{
						int comPortNumber = GetComPortNumber(deviceInfoSet, DeviceInfoData);
						if (comPortNumber > 0)
						{
							UpdateUSBDetectionLog("Port Number:" + comPortNumber);
							intPortNumberCollection.Add(comPortNumber);
						}
						else
						{
							UpdateUSBDetectionLog("Fail to get port number on:" + physicalAddress + ",ignored");
						}
					}
					else
					{
						UpdateUSBDetectionLog("Fail to get Physical Address of devInst:" + DeviceInfoData.DevInst);
					}
				}
			}
			num++;
		}
		SetupDiDestroyDeviceInfoList(deviceInfoSet);
	}

	public void GetPortNumberListWithInformation(ref USB_PORT_INFO_LIST lstUSBPortInformationCollection)
	{
		GetPortNumberListWithInformationNonUDE(ref lstUSBPortInformationCollection);
		GetPortNumberListWithInformationUDE(ref lstUSBPortInformationCollection, "PCI");
	}

	internal void GetPortNumberListWithInformationUDE(ref USB_PORT_INFO_LIST lstUSBPortInformationCollection, string DevEnum)
	{
		if (lstUSBPortInformationCollection == null)
		{
			return;
		}
		IntPtr deviceInfoSet = SetupDiGetClassDevs(0, DevEnum, IntPtr.Zero, 6u);
		if (deviceInfoSet.ToInt32() == -1)
		{
			return;
		}
		bool flag = true;
		uint num = 0u;
		while (flag)
		{
			SP_DEVINFO_DATA DeviceInfoData = default(SP_DEVINFO_DATA);
			DeviceInfoData.cbSize = (uint)Marshal.SizeOf((object)DeviceInfoData);
			string text = "{36fc9e60-c465-11cf-8056-444553540000}";
			flag = SetupDiEnumDeviceInfo(deviceInfoSet, num, ref DeviceInfoData);
			if (flag)
			{
				string classGUID = GetClassGUID(deviceInfoSet, DeviceInfoData);
				if (classGUID != null && classGUID.ToLower() == text.ToLower())
				{
					string deviceDescription = GetDeviceDescription(deviceInfoSet, DeviceInfoData, ignoreKey: true);
					if (deviceDescription != null)
					{
						UpdateUSBDetectionLog("Get device:" + deviceDescription);
						Match match = Regex.Match(deviceDescription, ".*? UDE Device .*?");
						if (match.Success)
						{
							UpdateUSBDetectionLog("Found UDE device:" + deviceDescription);
							if (!TestPortUnderUDE(deviceInfoSet, DeviceInfoData, deviceDescription, lstUSBPortInformationCollection))
							{
								UpdateUSBDetectionLog("Invalid Configuration of UDE device:" + deviceDescription);
							}
						}
					}
				}
			}
			num++;
		}
		SetupDiDestroyDeviceInfoList(deviceInfoSet);
	}

	internal void GetPortNumberListWithInformationNonUDE(ref USB_PORT_INFO_LIST lstUSBPortInformationCollection)
	{
		if (lstUSBPortInformationCollection == null)
		{
			return;
		}
		lstUSBPortInformationCollection.Clear();
		string enumerator = "USB";
		IntPtr deviceInfoSet = SetupDiGetClassDevs(0, enumerator, IntPtr.Zero, 6u);
		if (deviceInfoSet.ToInt32() == -1)
		{
			return;
		}
		bool flag = true;
		uint num = 0u;
		while (flag)
		{
			SP_DEVINFO_DATA DeviceInfoData = default(SP_DEVINFO_DATA);
			DeviceInfoData.cbSize = (uint)Marshal.SizeOf((object)DeviceInfoData);
			string text = "{4D36E978-E325-11CE-BFC1-08002BE10318}";
			flag = SetupDiEnumDeviceInfo(deviceInfoSet, num, ref DeviceInfoData);
			if (flag)
			{
				string classGUID = GetClassGUID(deviceInfoSet, DeviceInfoData);
				if (classGUID != null && classGUID.ToLower() == text.ToLower())
				{
					string PortDescription = "";
					int portNumberWithDescription = GetPortNumberWithDescription(deviceInfoSet, DeviceInfoData, ref PortDescription);
					if (portNumberWithDescription > 0)
					{
						string physicalAddress = GetPhysicalAddress(deviceInfoSet, DeviceInfoData);
						if (physicalAddress != null)
						{
							if (!lstUSBPortInformationCollection.ContainsPortNumber(portNumberWithDescription))
							{
								lstUSBPortInformationCollection.Add(portNumberWithDescription, PortDescription, physicalAddress);
							}
							else
							{
								UpdateUSBDetectionLog("Multiply port contains same port number:COM" + portNumberWithDescription);
							}
						}
						else
						{
							UpdateUSBDetectionLog("Fail to get Physical Address of devInst:" + DeviceInfoData.DevInst);
						}
					}
					else
					{
						UpdateUSBDetectionLog("Fail to get Port Number of devInst:" + DeviceInfoData.DevInst);
					}
				}
			}
			num++;
		}
		SetupDiDestroyDeviceInfoList(deviceInfoSet);
	}

	public void GetPortNumberList(ref List<int> intPortNumberCollection)
	{
		if (intPortNumberCollection == null)
		{
			return;
		}
		USB_PORT_INFO_LIST lstUSBPortInformationCollection = new USB_PORT_INFO_LIST();
		GetPortNumberListWithInformation(ref lstUSBPortInformationCollection);
		foreach (int portNumber in lstUSBPortInformationCollection.PortNumbers)
		{
			intPortNumberCollection.Add(portNumber);
		}
	}

	internal bool TestPortUnderUDE(IntPtr deviceInfoSet, SP_DEVINFO_DATA deviceInfoData, string description, USB_PORT_INFO_LIST lstUSBPortInformationCollection)
	{
		IntPtr intPtr = Marshal.AllocHGlobal(2048);
		Marshal.PtrToStringAuto(intPtr);
		int pdnDevInst = -1;
		int pdnDevInst2 = -1;
		int num = 0;
		int devInst = deviceInfoData.DevInst;
		if (num == 0 && devInst != -1)
		{
			UpdateUSBDetectionLog("Parent node device:" + devInst);
			if (CM_Get_Child(ref pdnDevInst, devInst, 0) == 0 && pdnDevInst != -1)
			{
				if (CM_Get_Child(ref pdnDevInst2, pdnDevInst, 0) == 0 && pdnDevInst2 != -1)
				{
					if (CM_Get_Device_ID(pdnDevInst, intPtr, 2048, 0) == 0)
					{
						string text = Marshal.PtrToStringAuto(intPtr);
						if (text != null)
						{
							return lstUSBPortInformationCollection.SearchPhysicalAddress(description, text);
						}
						UpdateUSBDetectionLog("Fail to get ude device physical address(" + pdnDevInst2 + ") driver key name of devInst:" + deviceInfoData.DevInst);
					}
					else
					{
						UpdateUSBDetectionLog("Fail to get ude device physical address(" + pdnDevInst2 + ") driver key name of devInst:" + deviceInfoData.DevInst);
					}
				}
				else if (CM_Get_Device_ID(pdnDevInst, intPtr, 2048, 0) == 0)
				{
					string text2 = Marshal.PtrToStringAuto(intPtr);
					if (text2 != null)
					{
						lstUSBPortInformationCollection.Add(description, text2);
						return true;
					}
					UpdateUSBDetectionLog("Fail to get ude device physical address(" + pdnDevInst2 + ") driver key name of devInst:" + deviceInfoData.DevInst);
				}
				else
				{
					UpdateUSBDetectionLog("Fail to get ude device physical address(" + pdnDevInst2 + ") driver key name of devInst:" + deviceInfoData.DevInst);
				}
			}
			else
			{
				UpdateUSBDetectionLog("CM Fail to get Root Hub");
			}
		}
		else
		{
			UpdateUSBDetectionLog("Invalid device:" + devInst);
		}
		Marshal.FreeHGlobal(intPtr);
		return false;
	}

	internal string GetPhysicalAddress(IntPtr DeviceInfoSet, SP_DEVINFO_DATA DeviceInfoData)
	{
		SP_DEVINFO_DATA DeviceInfoData2 = DeviceInfoData;
		IntPtr intPtr = Marshal.AllocHGlobal(2048);
		uint RequiredSize = 0u;
		uint PropertyRegDataType = 1u;
		string text = null;
		OSVersionInfo oSVersionInfo = new OSVersionInfo();
		oSVersionInfo.OSVersionInfoSize = Marshal.SizeOf((object)oSVersionInfo);
		GetVersionEx(oSVersionInfo);
		double num = (double)oSVersionInfo.MajorVersion + (double)oSVersionInfo.MinorVersion * 0.1;
		if (num < 0.0)
		{
			if (SetupDiGetDeviceRegistryProperty(DeviceInfoSet, ref DeviceInfoData2, 35u, ref PropertyRegDataType, intPtr, 2048u, ref RequiredSize))
			{
				text = Marshal.PtrToStringAuto(intPtr);
				if (SetupDiGetDeviceRegistryProperty(DeviceInfoSet, ref DeviceInfoData, 13u, ref PropertyRegDataType, intPtr, 2048u, ref RequiredSize))
				{
					string input = Marshal.PtrToStringAuto(intPtr);
					try
					{
						Match match = Regex.Match(input, "Port_#[0-9|A-F]{4}.Hub_#[0-9|A-F]{4}");
						if (!match.Success)
						{
							UpdateUSBDetectionLog("A interface device, format physical address of partent");
							text = GetParentDevicePhysicalAddress(text);
						}
					}
					catch
					{
						UpdateUSBDetectionLog("type unknown device, format physical address of partent");
						text = GetParentDevicePhysicalAddress(text);
					}
				}
				else
				{
					UpdateUSBDetectionLog("Fail to get Location Information of devInst:" + DeviceInfoData2.DevInst);
				}
			}
			else
			{
				UpdateUSBDetectionLog("Fail to get Location Path of devInst:" + DeviceInfoData2.DevInst);
			}
		}
		else if (CM_Get_Device_ID(DeviceInfoData2.DevInst, intPtr, 2048, 0) == 0)
		{
			string input2 = Marshal.PtrToStringAuto(intPtr);
			int pdnDevInst = -1;
			int num2 = 0;
			int pdnDevInst2 = -1;
			try
			{
				Match match2 = Regex.Match(input2, "VID_[0-9|A-F]{4}&PID_[0-9|A-F]{4}&MI_[0-9|A-F]{2}");
				if (match2.Success)
				{
					UpdateUSBDetectionLog("A interface device, try get parent node device");
					num2 = CM_Get_Parent(ref pdnDevInst2, DeviceInfoData2.DevInst, 0);
				}
				else
				{
					pdnDevInst2 = DeviceInfoData2.DevInst;
				}
			}
			catch
			{
				pdnDevInst2 = DeviceInfoData2.DevInst;
			}
			if (num2 == 0 && pdnDevInst2 != -1)
			{
				UpdateUSBDetectionLog("Parent node device:" + pdnDevInst2);
				if (CM_Get_Parent(ref pdnDevInst, pdnDevInst2, 0) == 0 && pdnDevInst != -1)
				{
					if (CM_Get_Device_ID(pdnDevInst, intPtr, 2048, 0) == 0)
					{
						string text2 = Marshal.PtrToStringAuto(intPtr);
						string text3 = "{f18a0e88-c30c-11d0-8815-00a0c906bed8}";
						string devicePath = "\\\\.\\" + text2.Replace('\\', '#') + "#" + text3;
						string cMPropertyString = GetCMPropertyString(pdnDevInst2, 10);
						if (cMPropertyString != null)
						{
							int connectionIndex = GetConnectionIndex(devicePath, cMPropertyString);
							if (connectionIndex > 0)
							{
								text = text2 + "\\PORT" + Convert.ToString(connectionIndex);
							}
							else
							{
								UpdateUSBDetectionLog("Fail to get parent(" + pdnDevInst + ") connection index of devInst:" + DeviceInfoData2.DevInst);
							}
						}
						else
						{
							UpdateUSBDetectionLog("Fail to get parent(" + pdnDevInst + ") driver key name of devInst:" + DeviceInfoData2.DevInst);
						}
					}
					else
					{
						UpdateUSBDetectionLog("Fail to get parent(" + pdnDevInst + ") device ID of devInst:" + DeviceInfoData2.DevInst);
					}
				}
				else
				{
					UpdateUSBDetectionLog("CM Fail to get parent device");
				}
			}
			else
			{
				UpdateUSBDetectionLog("CM Fail to get parent node device:" + pdnDevInst2);
			}
		}
		else
		{
			UpdateUSBDetectionLog("Fail to get device ID of devInst:" + DeviceInfoData2.DevInst);
		}
		Marshal.FreeHGlobal(intPtr);
		return text;
	}

	internal string GetCMPropertyString(int ptrDevice, int cmProperty)
	{
		string result = null;
		uint pulLength = 0u;
		IntPtr intPtr = Marshal.AllocHGlobal(2048);
		CM_Get_DevNode_Registry_Property(ptrDevice, cmProperty, out var pulRegDataType, IntPtr.Zero, ref pulLength, 0);
		if (pulLength != 0 && pulRegDataType == RegistryValueKind.String && CM_Get_DevNode_Registry_Property(ptrDevice, cmProperty, out pulRegDataType, intPtr, ref pulLength, 0) == 0)
		{
			result = Marshal.PtrToStringAnsi(intPtr);
		}
		Marshal.FreeHGlobal(intPtr);
		return result;
	}

	internal string GetClassGUID(IntPtr DeviceInfoSet, SP_DEVINFO_DATA DeviceInfoData)
	{
		SP_DEVINFO_DATA DeviceInfoData2 = DeviceInfoData;
		IntPtr intPtr = Marshal.AllocHGlobal(2048);
		uint RequiredSize = 0u;
		uint PropertyRegDataType = 1u;
		string result = null;
		if (SetupDiGetDeviceRegistryProperty(DeviceInfoSet, ref DeviceInfoData2, 8u, ref PropertyRegDataType, intPtr, 2048u, ref RequiredSize))
		{
			result = Marshal.PtrToStringAuto(intPtr);
		}
		Marshal.FreeHGlobal(intPtr);
		return result;
	}

	internal string GetDeviceDescription(IntPtr DeviceInfoSet, SP_DEVINFO_DATA DeviceInfoData, bool ignoreKey = false)
	{
		SP_DEVINFO_DATA DeviceInfoData2 = DeviceInfoData;
		IntPtr intPtr = Marshal.AllocHGlobal(2048);
		uint RequiredSize = 0u;
		uint PropertyRegDataType = 1u;
		string text = null;
		try
		{
			if (SetupDiGetDeviceRegistryProperty(DeviceInfoSet, ref DeviceInfoData2, 12u, ref PropertyRegDataType, intPtr, 2048u, ref RequiredSize))
			{
				text = Marshal.PtrToStringAuto(intPtr);
			}
			else if (SetupDiGetDeviceRegistryProperty(DeviceInfoSet, ref DeviceInfoData2, 0u, ref PropertyRegDataType, intPtr, 2048u, ref RequiredSize))
			{
				text = Marshal.PtrToStringAuto(intPtr);
			}
			if (text != null)
			{
				bool flag = false;
				if (ignoreKey || PORT_KEY.Count == 0)
				{
					flag = true;
				}
				else
				{
					foreach (string item in PORT_KEY)
					{
						Match match = ((!PORT_KEY_CASE_SENS) ? Regex.Match(text.ToLower(), item.ToLower()) : Regex.Match(text, item));
						if (match.Success)
						{
							flag = true;
						}
					}
				}
				if (!flag)
				{
					text = null;
				}
			}
		}
		catch (Exception)
		{
			text = null;
		}
		finally
		{
			Marshal.FreeHGlobal(intPtr);
		}
		return text;
	}

	internal int GetPortNumberWithDescription(IntPtr DeviceInfoSet, SP_DEVINFO_DATA DeviceInfoData, ref string PortDescription)
	{
		IntPtr hglobal = Marshal.AllocHGlobal(2048);
		string value = "0";
		try
		{
			string deviceDescription = GetDeviceDescription(DeviceInfoSet, DeviceInfoData);
			if (deviceDescription != null)
			{
				Match match = Regex.Match(deviceDescription, "(COM[0-9])");
				if (match.Success)
				{
					string text = "(COM";
					int num = deviceDescription.IndexOf(text) + text.Length;
					int num2 = deviceDescription.LastIndexOf(")");
					value = deviceDescription.Substring(num, num2 - num);
				}
				if (PortDescription != null)
				{
					PortDescription = deviceDescription;
				}
			}
		}
		catch (Exception)
		{
		}
		finally
		{
			Marshal.FreeHGlobal(hglobal);
		}
		return Convert.ToInt32(value);
	}

	internal int GetComPortNumber(IntPtr DeviceInfoSet, SP_DEVINFO_DATA DeviceInfoData)
	{
		string PortDescription = null;
		return GetPortNumberWithDescription(DeviceInfoSet, DeviceInfoData, ref PortDescription);
	}

	internal string GetParentDevicePhysicalAddress(string devicePhysicalAddress)
	{
		return devicePhysicalAddress.Substring(0, devicePhysicalAddress.LastIndexOf('#'));
	}

	internal int GetConnectionIndex(string DevicePath, string DriverKeyName)
	{
		int result = 0;
		IntPtr intPtr = CreateFile(DevicePath, 1073741824u, 2u, IntPtr.Zero, 3u, 0u, IntPtr.Zero);
		if (intPtr.ToInt32() != -1)
		{
			int num = 0;
			USB_NODE_INFORMATION lpInBuffer = default(USB_NODE_INFORMATION);
			if (DeviceIoControl(intPtr, 2229256, ref lpInBuffer, Marshal.SizeOf((object)lpInBuffer), ref lpInBuffer, Marshal.SizeOf((object)lpInBuffer), out var lpBytesReturned, IntPtr.Zero))
			{
				if (lpInBuffer.NodeType == USB_HUB_NODE.UsbHub)
				{
					num = lpInBuffer.u.HubInformation.HubDescriptor.bNumberOfPorts;
				}
				else
				{
					num = 0;
					UpdateUSBDetectionLog("Device is not a Hub, devInst:" + intPtr);
				}
				for (int i = 1; i <= num; i++)
				{
					USB_NODE_CONNECTION_DRIVERKEY_NAME lpInBuffer2 = default(USB_NODE_CONNECTION_DRIVERKEY_NAME);
					lpInBuffer2.ConnectionIndex = i;
					if (DeviceIoControl(intPtr, 2229280, ref lpInBuffer2, Marshal.SizeOf((object)lpInBuffer2), ref lpInBuffer2, Marshal.SizeOf((object)lpInBuffer2), out lpBytesReturned, IntPtr.Zero))
					{
						if (lpInBuffer2.DriverKeyName == DriverKeyName)
						{
							result = lpInBuffer2.ConnectionIndex;
						}
					}
					else
					{
						UpdateUSBDetectionLog("Fail to get connection drivery key name of devInst:" + intPtr + "connection index:" + i);
					}
				}
			}
			else
			{
				UpdateUSBDetectionLog("Fail to get Node Type of devInst:" + intPtr);
			}
			CloseHandle(intPtr);
		}
		return result;
	}
}
