/// <summary>
        /// Returns a sorted list of all computer's devices
        /// </summary>
        /// <returns></returns>
        public string[] GetDevicesList()
        {
            List <string> HWList = new List <string>();

            try
            {
                Guid   myGUID   = System.Guid.Empty;
                IntPtr hDevInfo = Native.SetupDiGetClassDevs(ref myGUID, 0, IntPtr.Zero, Native.DIGCF_ALLCLASSES | Native.DIGCF_PRESENT);
                if (hDevInfo.ToInt32() == Native.INVALID_HANDLE_VALUE)
                {
                    throw new Exception("Invalid Handle");
                }
                Native.SP_DEVINFO_DATA DeviceInfoData;
                DeviceInfoData        = new Native.SP_DEVINFO_DATA();
                DeviceInfoData.cbSize = Marshal.SizeOf(DeviceInfoData);                 // JDA 28;
                //is devices exist for class
                DeviceInfoData.devInst   = 0;
                DeviceInfoData.classGuid = System.Guid.Empty;
                DeviceInfoData.reserved  = 0;
                UInt32        i;
                StringBuilder DeviceName = new StringBuilder("");
                DeviceName.Capacity = Native.MAX_DEV_LEN;

                if (!Native.SetupDiEnumDeviceInfo(hDevInfo, 0, DeviceInfoData))
                {
                    throw new Exception("No device found, are you kidding? " + Native.GetLastError());
                }

                for (i = 0; Native.SetupDiEnumDeviceInfo(hDevInfo, i, DeviceInfoData); i++)
                {
                    //Declare vars
                    while (!Native.SetupDiGetDeviceRegistryProperty(hDevInfo,
                                                                    DeviceInfoData,
                                                                    Native.SPDRP_DEVICEDESC,
                                                                    0,
                                                                    DeviceName,
                                                                    Native.MAX_DEV_LEN,
                                                                    IntPtr.Zero))
                    {
                        //Skip
                    }
                    HWList.Add(DeviceName.ToString());
                }
                HWList.Sort();
                Native.SetupDiDestroyDeviceInfoList(hDevInfo);
            }
            catch (Exception ex)
            {
                throw new Exception("Failed to enumerate device tree!", ex);
            }
            return(HWList.ToArray());
        }
        private bool RestartDevice(IntPtr hDevInfo, Native.SP_DEVINFO_DATA devInfoData)
        {
            int    szOfPcp;
            IntPtr ptrToPcp;
            int    szDevInfoData;
            IntPtr ptrToDevInfoData;

            Native.SP_PROPCHANGE_PARAMS pcp = new Native.SP_PROPCHANGE_PARAMS();
            pcp.ClassInstallHeader.cbSize          = Marshal.SizeOf(typeof(Native.SP_CLASSINSTALL_HEADER));
            pcp.ClassInstallHeader.InstallFunction = Native.DIF_PROPERTYCHANGE;
            pcp.StateChange = Native.DICS_PROPCHANGE;             // for reset
            pcp.Scope       = Native.DICS_FLAG_CONFIGSPECIFIC;
            pcp.HwProfile   = 0;

            szOfPcp  = Marshal.SizeOf(pcp);
            ptrToPcp = Marshal.AllocHGlobal(szOfPcp);
            Marshal.StructureToPtr(pcp, ptrToPcp, true);
            szDevInfoData    = Marshal.SizeOf(devInfoData);
            ptrToDevInfoData = Marshal.AllocHGlobal(szDevInfoData);
            Marshal.StructureToPtr(devInfoData, ptrToDevInfoData, true);

            bool rslt1 = Native.SetupDiSetClassInstallParams(hDevInfo, ptrToDevInfoData, ptrToPcp, Marshal.SizeOf(typeof(Native.SP_PROPCHANGE_PARAMS)));

            if (!rslt1)
            {
                throw new Exception("SetupDiSetClassInstallParams failed " + Native.GetLastError());
            }

            bool rstl2 = Native.SetupDiCallClassInstaller(Native.DIF_PROPERTYCHANGE, hDevInfo, ptrToDevInfoData);

            if (!rstl2)
            {
                throw new Exception("SetupDiCallClassInstaller failed" + Native.GetLastError());
            }

            if (rslt1 && rstl2)
            {
                return(true);
            }


            return(false);
        }
		private bool ActionOnDevice(string deviceName, DeviceAction action)
		{
			bool bFound = false;
			
			Guid myGUID = System.Guid.Empty;
			IntPtr hDevInfo = Native.SetupDiGetClassDevs(ref myGUID, 0, IntPtr.Zero, Native.DIGCF_ALLCLASSES | Native.DIGCF_PRESENT);
			if (hDevInfo.ToInt32() == Native.INVALID_HANDLE_VALUE)
			{
				throw new Exception("Failed to open the device manager");
				return false;
			}
			Native.SP_DEVINFO_DATA DeviceInfoData;
			DeviceInfoData = new Native.SP_DEVINFO_DATA();
			DeviceInfoData.cbSize = Marshal.SizeOf(DeviceInfoData); // JDA 28;
			//is devices exist for class
			DeviceInfoData.devInst = 0;
			DeviceInfoData.classGuid = System.Guid.Empty;
			DeviceInfoData.reserved = 0;
			UInt32 i;
			StringBuilder DeviceName = new StringBuilder("");
			DeviceName.Capacity = Native.MAX_DEV_LEN;
			for (i = 0; Native.SetupDiEnumDeviceInfo(hDevInfo, i, DeviceInfoData); i++)
			{
				//Declare vars
				while (!Native.SetupDiGetDeviceRegistryProperty(hDevInfo, DeviceInfoData, Native.SPDRP_DEVICEDESC, 0, DeviceName, Native.MAX_DEV_LEN, IntPtr.Zero))
				{
					//Skip
				}
				if (DeviceName.ToString().ToLower().Contains(deviceName.ToLower()))
				{
					bFound = true;
					
					switch (action)
					{
						case DeviceAction.Disable :
							if (!EnableOrDisableDevice(hDevInfo, DeviceInfoData, false))
								throw new Exception("Failed to disable the device");
							break;
						case DeviceAction.Enable :
							if (!EnableOrDisableDevice(hDevInfo, DeviceInfoData, true))
								throw new Exception("Failed to enable the device");
							break;
						case DeviceAction.Reset :
							if (!RestartDevice(hDevInfo, DeviceInfoData))
								throw new Exception("Failed to reset the device");
							break;
							default :
								throw new Exception("Invalid action.");
					}
					break;
				}
			}
			Native.SetupDiDestroyDeviceInfoList(hDevInfo);

			if (!bFound)
				throw new Exception("Device not found");
			
			return true;
		}
		/// <summary>
		/// Returns a sorted list of all computer's devices
		/// </summary>
		/// <returns></returns>
		public string[] GetDevicesList()
		{
			List<string> HWList = new List<string>();
			
			try
			{
				Guid myGUID = System.Guid.Empty;
				IntPtr hDevInfo = Native.SetupDiGetClassDevs(ref myGUID, 0, IntPtr.Zero, Native.DIGCF_ALLCLASSES | Native.DIGCF_PRESENT);
				if (hDevInfo.ToInt32() == Native.INVALID_HANDLE_VALUE)
				{
					throw new Exception("Invalid Handle");
				}
				Native.SP_DEVINFO_DATA DeviceInfoData;
				DeviceInfoData = new Native.SP_DEVINFO_DATA();
				DeviceInfoData.cbSize = Marshal.SizeOf(DeviceInfoData); // JDA 28;
				//is devices exist for class
				DeviceInfoData.devInst = 0;
				DeviceInfoData.classGuid = System.Guid.Empty;
				DeviceInfoData.reserved = 0;
				UInt32 i;
				StringBuilder DeviceName = new StringBuilder("");
				DeviceName.Capacity = Native.MAX_DEV_LEN;
				
				if (!Native.SetupDiEnumDeviceInfo(hDevInfo, 0, DeviceInfoData))
				{
					throw new Exception("No device found, are you kidding? " + Native.GetLastError());
				}
				
				for (i = 0; Native.SetupDiEnumDeviceInfo(hDevInfo, i, DeviceInfoData); i++)
				{
					
					//Declare vars
					while (!Native.SetupDiGetDeviceRegistryProperty(hDevInfo,
					                                                DeviceInfoData,
					                                                Native.SPDRP_DEVICEDESC,
					                                                0,
					                                                DeviceName,
					                                                Native.MAX_DEV_LEN,
					                                                IntPtr.Zero))
					{
						//Skip
					}
					HWList.Add(DeviceName.ToString());
				}
				HWList.Sort();
				Native.SetupDiDestroyDeviceInfoList(hDevInfo);
			}
			catch (Exception ex)
			{
				throw new Exception("Failed to enumerate device tree!",ex);
			}
			return HWList.ToArray();
		}
        private bool ActionOnDevice(string deviceName, DeviceAction action)
        {
            bool bFound = false;

            Guid   myGUID   = System.Guid.Empty;
            IntPtr hDevInfo = Native.SetupDiGetClassDevs(ref myGUID, 0, IntPtr.Zero, Native.DIGCF_ALLCLASSES | Native.DIGCF_PRESENT);

            if (hDevInfo.ToInt32() == Native.INVALID_HANDLE_VALUE)
            {
                throw new Exception("Failed to open the device manager");
                return(false);
            }
            Native.SP_DEVINFO_DATA DeviceInfoData;
            DeviceInfoData        = new Native.SP_DEVINFO_DATA();
            DeviceInfoData.cbSize = Marshal.SizeOf(DeviceInfoData);             // JDA 28;
            //is devices exist for class
            DeviceInfoData.devInst   = 0;
            DeviceInfoData.classGuid = System.Guid.Empty;
            DeviceInfoData.reserved  = 0;
            UInt32        i;
            StringBuilder DeviceName = new StringBuilder("");

            DeviceName.Capacity = Native.MAX_DEV_LEN;
            for (i = 0; Native.SetupDiEnumDeviceInfo(hDevInfo, i, DeviceInfoData); i++)
            {
                //Declare vars
                while (!Native.SetupDiGetDeviceRegistryProperty(hDevInfo, DeviceInfoData, Native.SPDRP_DEVICEDESC, 0, DeviceName, Native.MAX_DEV_LEN, IntPtr.Zero))
                {
                    //Skip
                }
                if (DeviceName.ToString().ToLower().Contains(deviceName.ToLower()))
                {
                    bFound = true;

                    switch (action)
                    {
                    case DeviceAction.Disable:
                        if (!EnableOrDisableDevice(hDevInfo, DeviceInfoData, false))
                        {
                            throw new Exception("Failed to disable the device");
                        }
                        break;

                    case DeviceAction.Enable:
                        if (!EnableOrDisableDevice(hDevInfo, DeviceInfoData, true))
                        {
                            throw new Exception("Failed to enable the device");
                        }
                        break;

                    case DeviceAction.Reset:
                        if (!RestartDevice(hDevInfo, DeviceInfoData))
                        {
                            throw new Exception("Failed to reset the device");
                        }
                        break;

                    default:
                        throw new Exception("Invalid action.");
                    }
                    break;
                }
            }
            Native.SetupDiDestroyDeviceInfoList(hDevInfo);

            if (!bFound)
            {
                throw new Exception("Device not found");
            }

            return(true);
        }
        private bool EnableOrDisableDevice(IntPtr hDevInfo, Native.SP_DEVINFO_DATA devInfoData, bool bEnable)
        {
            try
            {
                //Marshalling vars
                int    szOfPcp;
                IntPtr ptrToPcp;
                int    szDevInfoData;
                IntPtr ptrToDevInfoData;

                Native.SP_PROPCHANGE_PARAMS pcp = new Native.SP_PROPCHANGE_PARAMS();
                if (bEnable)
                {
                    pcp.ClassInstallHeader.cbSize          = Marshal.SizeOf(typeof(Native.SP_CLASSINSTALL_HEADER));
                    pcp.ClassInstallHeader.InstallFunction = Native.DIF_PROPERTYCHANGE;
                    pcp.StateChange = Native.DICS_ENABLE;
                    pcp.Scope       = Native.DICS_FLAG_GLOBAL;
                    pcp.HwProfile   = 0;

                    //Marshal the params
                    szOfPcp  = Marshal.SizeOf(pcp);
                    ptrToPcp = Marshal.AllocHGlobal(szOfPcp);
                    Marshal.StructureToPtr(pcp, ptrToPcp, true);
                    szDevInfoData    = Marshal.SizeOf(devInfoData);
                    ptrToDevInfoData = Marshal.AllocHGlobal(szDevInfoData);

                    if (Native.SetupDiSetClassInstallParams(hDevInfo, ptrToDevInfoData, ptrToPcp, Marshal.SizeOf(typeof(Native.SP_PROPCHANGE_PARAMS))))
                    {
                        Native.SetupDiCallClassInstaller(Native.DIF_PROPERTYCHANGE, hDevInfo, ptrToDevInfoData);
                    }
                    pcp.ClassInstallHeader.cbSize          = Marshal.SizeOf(typeof(Native.SP_CLASSINSTALL_HEADER));
                    pcp.ClassInstallHeader.InstallFunction = Native.DIF_PROPERTYCHANGE;
                    pcp.StateChange = Native.DICS_ENABLE;
                    pcp.Scope       = Native.DICS_FLAG_CONFIGSPECIFIC;
                    pcp.HwProfile   = 0;
                }
                else
                {
                    pcp.ClassInstallHeader.cbSize          = Marshal.SizeOf(typeof(Native.SP_CLASSINSTALL_HEADER));
                    pcp.ClassInstallHeader.InstallFunction = Native.DIF_PROPERTYCHANGE;
                    pcp.StateChange = Native.DICS_DISABLE;
                    pcp.Scope       = Native.DICS_FLAG_CONFIGSPECIFIC;
                    pcp.HwProfile   = 0;
                }
                //Marshal the params
                szOfPcp  = Marshal.SizeOf(pcp);
                ptrToPcp = Marshal.AllocHGlobal(szOfPcp);
                Marshal.StructureToPtr(pcp, ptrToPcp, true);
                szDevInfoData    = Marshal.SizeOf(devInfoData);
                ptrToDevInfoData = Marshal.AllocHGlobal(szDevInfoData);
                Marshal.StructureToPtr(devInfoData, ptrToDevInfoData, true);

                bool rslt1 = Native.SetupDiSetClassInstallParams(hDevInfo, ptrToDevInfoData, ptrToPcp, Marshal.SizeOf(typeof(Native.SP_PROPCHANGE_PARAMS)));
                bool rstl2 = Native.SetupDiCallClassInstaller(Native.DIF_PROPERTYCHANGE, hDevInfo, ptrToDevInfoData);
                if ((!rslt1) || (!rstl2))
                {
                    throw new Exception("Unable to change device state!");
                    return(false);
                }
                else
                {
                    return(true);
                }
            }
            catch (Exception ex)
            {
                return(false);
            }
        }