diff USBLib/Windows/Devices/DeviceNode.cs @ 50:556b4fb511bd

Added HWLib and USBLib functions to support USB Driver Installer
author Ivo Smits <Ivo@UCIS.nl>
date Mon, 30 Sep 2013 19:23:09 +0200
parents dcfec2be27c9
children d4778c3232ad
line wrap: on
line diff
--- a/USBLib/Windows/Devices/DeviceNode.cs	Tue Jul 16 13:16:04 2013 +0200
+++ b/USBLib/Windows/Devices/DeviceNode.cs	Mon Sep 30 19:23:09 2013 +0200
@@ -1,9 +1,11 @@
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
+using System.Reflection;
 using System.Runtime.InteropServices;
 using System.Text;
 using Microsoft.Win32;
+using Microsoft.Win32.SafeHandles;
 using UCIS.USBLib.Internal.Windows;
 
 namespace UCIS.HWLib.Windows.Devices {
@@ -52,7 +54,10 @@
 			}
 		}
 		public static IList<DeviceNode> GetDevices(String enumerator) {
-			using (SafeDeviceInfoSetHandle dis = SetupApi.SetupDiGetClassDevsA(IntPtr.Zero, enumerator, IntPtr.Zero, DICFG.PRESENT | DICFG.ALLCLASSES)) {
+			return GetDevices(enumerator, true);
+		}
+		public static IList<DeviceNode> GetDevices(String enumerator, Boolean present) {
+			using (SafeDeviceInfoSetHandle dis = SetupApi.SetupDiGetClassDevsA(IntPtr.Zero, enumerator, IntPtr.Zero, (present ? DICFG.PRESENT : 0) | DICFG.ALLCLASSES)) {
 			//using (SafeDeviceInfoSetHandle dis = SetupApi.SetupDiGetClassDevsA(IntPtr.Zero, enumerator, IntPtr.Zero, DICFG.ALLCLASSES | DICFG.DEVICEINTERFACE)) {
 				return GetDevicesInSet(dis);
 			}
@@ -126,6 +131,17 @@
 			return SetupApi.GetAsStringArray(buffer, buffer.Length);
 		}
 
+		public void SetProperty(SPDRP property, Byte[] value) {
+			using (SafeDeviceInfoSetHandle dis = SetupApi.SetupDiGetClassDevsA(IntPtr.Zero, DeviceID, IntPtr.Zero, DICFG.DEVICEINTERFACE | DICFG.ALLCLASSES)) {
+				if (dis.IsInvalid) throw new Win32Exception(Marshal.GetLastWin32Error());
+				SP_DEVINFO_DATA dd = new SP_DEVINFO_DATA(true);
+				if (!SetupApi.SetupDiEnumDeviceInfo(dis, 0, ref dd))
+					throw new Win32Exception(Marshal.GetLastWin32Error());
+				if (!SetupApi.SetupDiSetDeviceRegistryProperty(dis, ref dd, property, value, (uint)value.Length))
+					throw new Win32Exception(Marshal.GetLastWin32Error());
+			}
+		}
+
 		public Byte[] GetCustomProperty(String name) {
 			using (SafeDeviceInfoSetHandle dis = SetupApi.SetupDiGetClassDevsA(IntPtr.Zero, DeviceID, IntPtr.Zero, DICFG.DEVICEINTERFACE | DICFG.ALLCLASSES)) {
 				if (dis.IsInvalid) throw new Win32Exception(Marshal.GetLastWin32Error());
@@ -158,6 +174,63 @@
 			return SetupApi.GetAsStringArray(buffer, buffer.Length);
 		}
 
+		public RegistryKey OpenRegistryKey(UInt32 scope, UInt32 hwProfile, UInt32 keyType, UInt32 samDesired) {
+			using (SafeDeviceInfoSetHandle dis = SetupApi.SetupDiGetClassDevsA(IntPtr.Zero, DeviceID, IntPtr.Zero, DICFG.DEVICEINTERFACE | DICFG.ALLCLASSES)) {
+				if (dis.IsInvalid) throw new Win32Exception(Marshal.GetLastWin32Error());
+				SP_DEVINFO_DATA dd = new SP_DEVINFO_DATA(true);
+				if (!SetupApi.SetupDiEnumDeviceInfo(dis, 0, ref dd))
+					return null;
+				IntPtr handle = SetupApi.SetupDiOpenDevRegKey(dis, ref dd, scope, hwProfile, keyType, samDesired);
+				if (handle == (IntPtr)(-1)) return null;
+				return RegistryKeyFromHandle(handle, true, (samDesired & (0x00000002 | 0x00000004 | 0x00000020)) != 0);
+			}
+		}
+
+		private RegistryKey RegistryKeyFromHandle(IntPtr hKey, bool writable, bool ownsHandle) {
+			BindingFlags privateConstructors = BindingFlags.Instance | BindingFlags.NonPublic;
+			Type safeRegistryHandleType = typeof(SafeHandleZeroOrMinusOneIsInvalid).Assembly.GetType("Microsoft.Win32.SafeHandles.SafeRegistryHandle");
+			Type[] safeRegistryHandleCtorTypes = new Type[] { typeof(IntPtr), typeof(bool) };
+			ConstructorInfo safeRegistryHandleCtorInfo = safeRegistryHandleType.GetConstructor(privateConstructors, null, safeRegistryHandleCtorTypes, null);
+			Object safeHandle = safeRegistryHandleCtorInfo.Invoke(new Object[] { hKey, ownsHandle });
+			Type registryKeyType = typeof(RegistryKey);
+			Type[] registryKeyConstructorTypes = new Type[] { safeRegistryHandleType, typeof(bool) };
+			ConstructorInfo registryKeyCtorInfo = registryKeyType.GetConstructor(privateConstructors, null, registryKeyConstructorTypes, null);
+			RegistryKey resultKey = (RegistryKey)registryKeyCtorInfo.Invoke(new Object[] { safeHandle, writable });
+			return resultKey;
+		}
+
+		public Byte[] GetDeviceProperty(Guid fmtid, UInt32 pid) {
+			using (SafeDeviceInfoSetHandle dis = SetupApi.SetupDiGetClassDevsA(IntPtr.Zero, DeviceID, IntPtr.Zero, DICFG.DEVICEINTERFACE | DICFG.ALLCLASSES)) {
+				if (dis.IsInvalid) throw new Win32Exception(Marshal.GetLastWin32Error());
+				SP_DEVINFO_DATA dd = new SP_DEVINFO_DATA(true);
+				if (!SetupApi.SetupDiEnumDeviceInfo(dis, 0, ref dd))
+					return null;
+				byte[] propBuffer = new byte[256];
+				UInt32 requiredSize;
+				UInt32 propertyType;
+				DEVPROPKEY propertyKey = new DEVPROPKEY() { fmtid = fmtid, pid = pid };
+				if (!SetupApi.SetupDiGetDeviceProperty(dis, ref dd, ref propertyKey, out propertyType, propBuffer, (uint)propBuffer.Length, out requiredSize, 0))
+					return null;
+				if (requiredSize > propBuffer.Length) {
+					propBuffer = new Byte[requiredSize];
+					if (!SetupApi.SetupDiGetDeviceProperty(dis, ref dd, ref propertyKey, out propertyType, propBuffer, (uint)propBuffer.Length, out requiredSize, 0))
+						throw new Win32Exception(Marshal.GetLastWin32Error());
+				}
+				if (requiredSize < propBuffer.Length) Array.Resize(ref propBuffer, (int)requiredSize);
+				return propBuffer;
+			}
+		}
+		public String GetDevicePropertyString(Guid fmtid, UInt32 pid) {
+			Byte[] buffer = GetDeviceProperty(fmtid, pid);
+			if (buffer == null) return null;
+			return SetupApi.GetAsString(buffer, buffer.Length);
+		}
+
+		public void Reenumerate(UInt32 flags) {
+			CR ret = SetupApi.CM_Reenumerate_DevNode(DevInst, flags);
+			CMException.Throw(ret, "CM_Reenumerate_DevNode");
+		}
+
 		public String DeviceDescription { get { return GetPropertyString(CMRDP.DEVICEDESC); } }
 		public String[] HardwareID { get { return GetPropertyStringArray(CMRDP.HARDWAREID); } }
 		public String[] CompatibleIDs { get { return GetPropertyStringArray(CMRDP.COMPATIBLEIDS); } }