comparison USBLib/Windows/Devices/DeviceNode.cs @ 21:dcfec2be27c9

Added USBLib
author Ivo Smits <Ivo@UCIS.nl>
date Mon, 15 Apr 2013 01:04:59 +0200
parents
children 556b4fb511bd
comparison
equal deleted inserted replaced
20:c873e3dd73fe 21:dcfec2be27c9
1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Runtime.InteropServices;
5 using System.Text;
6 using Microsoft.Win32;
7 using UCIS.USBLib.Internal.Windows;
8
9 namespace UCIS.HWLib.Windows.Devices {
10 public class CMException : Exception {
11 internal CMException(CR result, String method)
12 : base(method + " returned " + result.ToString()) {
13 }
14 internal static void Throw(CR result, String method) {
15 if (result == CR.SUCCESS) return;
16 throw new CMException(result, method);
17 }
18 }
19 public class DeviceNode {
20 public static DeviceNode Root {
21 get {
22 UInt32 node;
23 CR ret = SetupApi.CM_Locate_DevNode(out node, null, 0);
24 CMException.Throw(ret, "CM_Locate_DevNode");
25 return new DeviceNode(node);
26 }
27 }
28 public static DeviceNode GetDevice(String deviceID) {
29 UInt32 node;
30 CR ret = SetupApi.CM_Locate_DevNode(out node, deviceID, 0);
31 CMException.Throw(ret, "CM_Locate_DevNode");
32 return new DeviceNode(node);
33 }
34 private static IList<DeviceNode> GetDevicesInSet(SafeDeviceInfoSetHandle dis) {
35 List<DeviceNode> list = new List<DeviceNode>();
36 if (dis.IsInvalid) throw new Win32Exception(Marshal.GetLastWin32Error());
37 SP_DEVINFO_DATA dd = new SP_DEVINFO_DATA(true);
38 for (int index = 0; ; index++) {
39 if (!SetupApi.SetupDiEnumDeviceInfo(dis, index, ref dd)) break;
40 list.Add(new DeviceNode(dd.DevInst));
41 }
42 return list;
43 }
44 public static IList<DeviceNode> GetDevices() {
45 using (SafeDeviceInfoSetHandle dis = SetupApi.SetupDiGetClassDevsA(IntPtr.Zero, null, IntPtr.Zero, DICFG.PRESENT | DICFG.ALLCLASSES)) {
46 return GetDevicesInSet(dis);
47 }
48 }
49 public static IList<DeviceNode> GetDevices(Guid classGuid) {
50 using (SafeDeviceInfoSetHandle dis = SetupApi.SetupDiGetClassDevsA(ref classGuid, null, IntPtr.Zero, DICFG.PRESENT | DICFG.DEVICEINTERFACE)) {
51 return GetDevicesInSet(dis);
52 }
53 }
54 public static IList<DeviceNode> GetDevices(String enumerator) {
55 using (SafeDeviceInfoSetHandle dis = SetupApi.SetupDiGetClassDevsA(IntPtr.Zero, enumerator, IntPtr.Zero, DICFG.PRESENT | DICFG.ALLCLASSES)) {
56 //using (SafeDeviceInfoSetHandle dis = SetupApi.SetupDiGetClassDevsA(IntPtr.Zero, enumerator, IntPtr.Zero, DICFG.ALLCLASSES | DICFG.DEVICEINTERFACE)) {
57 return GetDevicesInSet(dis);
58 }
59 }
60
61 public UInt32 DevInst { get; private set; }
62 private String _DeviceID = null;
63 internal DeviceNode(UInt32 node) {
64 DevInst = node;
65 }
66 public String DeviceID {
67 get {
68 if (_DeviceID == null) {
69 uint deviceidlen;
70 CR ret = SetupApi.CM_Get_Device_ID_Size(out deviceidlen, DevInst, 0);
71 CMException.Throw(ret, "CM_Get_Device_ID_Size");
72 StringBuilder deviceid = new StringBuilder((int)deviceidlen);
73 ret = SetupApi.CM_Get_Device_ID(DevInst, deviceid, deviceid.MaxCapacity, 0);
74 CMException.Throw(ret, "CM_Get_Device_ID");
75 _DeviceID = deviceid.ToString();
76 }
77 return _DeviceID;
78 }
79 }
80 public Byte[] GetProperty(SPDRP property) {
81 using (SafeDeviceInfoSetHandle dis = SetupApi.SetupDiGetClassDevsA(IntPtr.Zero, DeviceID, IntPtr.Zero, DICFG.DEVICEINTERFACE | DICFG.ALLCLASSES)) {
82 if (dis.IsInvalid) throw new Win32Exception(Marshal.GetLastWin32Error());
83 SP_DEVINFO_DATA dd = new SP_DEVINFO_DATA(true);
84 if (!SetupApi.SetupDiEnumDeviceInfo(dis, 0, ref dd))
85 return null;
86 //throw new Win32Exception(Marshal.GetLastWin32Error());
87 RegistryValueKind propertyType;
88 byte[] propBuffer = new byte[256];
89 int requiredSize;
90 if (!SetupApi.SetupDiGetDeviceRegistryProperty(dis, ref dd, property, out propertyType, propBuffer, propBuffer.Length, out requiredSize))
91 return null;
92 if (requiredSize > propBuffer.Length) {
93 propBuffer = new Byte[requiredSize];
94 if (!SetupApi.SetupDiGetDeviceRegistryProperty(dis, ref dd, property, out propertyType, propBuffer, propBuffer.Length, out requiredSize))
95 throw new Win32Exception(Marshal.GetLastWin32Error());
96 }
97 if (requiredSize < propBuffer.Length) Array.Resize(ref propBuffer, requiredSize);
98 return propBuffer;
99 }
100 }
101 public String GetPropertyString(SPDRP property) {
102 Byte[] buffer = GetProperty(property);
103 if (buffer == null) return null;
104 return SetupApi.GetAsString(buffer, buffer.Length);
105 }
106 public Byte[] GetProperty(CMRDP property) {
107 uint proplength = 0;
108 uint proptype;
109 CR ret = SetupApi.CM_Get_DevNode_Registry_Property(DevInst, property, out proptype, null, ref proplength, 0);
110 if (ret == CR.NO_SUCH_VALUE) return null;
111 if (ret != CR.BUFFER_SMALL) CMException.Throw(ret, "CM_Get_DevNode_Registry_Property");
112 Byte[] propbuffer = new Byte[proplength];
113 ret = SetupApi.CM_Get_DevNode_Registry_Property(DevInst, property, out proptype, propbuffer, ref proplength, 0);
114 CMException.Throw(ret, "CM_Get_DevNode_Registry_Property");
115 if (propbuffer.Length > proplength) Array.Resize(ref propbuffer, (int)proplength);
116 return propbuffer;
117 }
118 public String GetPropertyString(CMRDP property) {
119 Byte[] buffer = GetProperty(property);
120 if (buffer == null) return null;
121 return SetupApi.GetAsString(buffer, buffer.Length);
122 }
123 public String[] GetPropertyStringArray(CMRDP property) {
124 Byte[] buffer = GetProperty(property);
125 if (buffer == null) return null;
126 return SetupApi.GetAsStringArray(buffer, buffer.Length);
127 }
128
129 public Byte[] GetCustomProperty(String name) {
130 using (SafeDeviceInfoSetHandle dis = SetupApi.SetupDiGetClassDevsA(IntPtr.Zero, DeviceID, IntPtr.Zero, DICFG.DEVICEINTERFACE | DICFG.ALLCLASSES)) {
131 if (dis.IsInvalid) throw new Win32Exception(Marshal.GetLastWin32Error());
132 SP_DEVINFO_DATA dd = new SP_DEVINFO_DATA(true);
133 if (!SetupApi.SetupDiEnumDeviceInfo(dis, 0, ref dd))
134 return null;
135 //throw new Win32Exception(Marshal.GetLastWin32Error());
136 RegistryValueKind propertyType;
137 byte[] propBuffer = new byte[256];
138 int requiredSize;
139 if (!SetupApi.SetupDiGetCustomDeviceProperty(dis, ref dd, name, DICUSTOMDEVPROP.NONE, out propertyType, propBuffer, propBuffer.Length, out requiredSize))
140 return null;
141 if (requiredSize > propBuffer.Length) {
142 propBuffer = new Byte[requiredSize];
143 if (!SetupApi.SetupDiGetCustomDeviceProperty(dis, ref dd, name, DICUSTOMDEVPROP.NONE, out propertyType, propBuffer, propBuffer.Length, out requiredSize))
144 throw new Win32Exception(Marshal.GetLastWin32Error());
145 }
146 if (requiredSize < propBuffer.Length) Array.Resize(ref propBuffer, requiredSize);
147 return propBuffer;
148 }
149 }
150 public String GetCustomPropertyString(String name) {
151 Byte[] buffer = GetCustomProperty(name);
152 if (buffer == null) return null;
153 return SetupApi.GetAsString(buffer, buffer.Length);
154 }
155 public String[] GetCustomPropertyStringArray(String name) {
156 Byte[] buffer = GetCustomProperty(name);
157 if (buffer == null) return null;
158 return SetupApi.GetAsStringArray(buffer, buffer.Length);
159 }
160
161 public String DeviceDescription { get { return GetPropertyString(CMRDP.DEVICEDESC); } }
162 public String[] HardwareID { get { return GetPropertyStringArray(CMRDP.HARDWAREID); } }
163 public String[] CompatibleIDs { get { return GetPropertyStringArray(CMRDP.COMPATIBLEIDS); } }
164 public String Service { get { return GetPropertyString(CMRDP.SERVICE); } }
165 public String Class { get { return GetPropertyString(CMRDP.CLASS); } }
166 public String ClassGuid { get { return GetPropertyString(CMRDP.CLASSGUID); } }
167 public String DriverKey { get { return GetPropertyString(CMRDP.DRIVER); } }
168 public String Manufacturer { get { return GetPropertyString(CMRDP.MFG); } }
169 public String FriendlyName { get { return GetPropertyString(CMRDP.FRIENDLYNAME); } }
170 public String LocationInformation { get { return GetPropertyString(CMRDP.LOCATION_INFORMATION); } }
171 public String PhysicalDeviceObjectName { get { return GetPropertyString(CMRDP.PHYSICAL_DEVICE_OBJECT_NAME); } }
172 public Guid? BusTypeGuid { get { return SetupApi.GetAsGuid(GetProperty(CMRDP.BUSTYPEGUID)); } }
173 public Int32? BusNumber { get { return SetupApi.GetAsInt32(GetProperty(CMRDP.BUSNUMBER)); } }
174 public String EnumeratorName { get { return GetPropertyString(CMRDP.ENUMERATOR_NAME); } }
175
176 public String[] GetInterfaces(String classGuid) {
177 return GetInterfaces(new Guid(classGuid));
178 }
179 public String[] GetInterfaces(Guid classGuid) {
180 uint len;
181 CR ret = SetupApi.CM_Get_Device_Interface_List_Size(out len, ref classGuid, DeviceID, 0);
182 CMException.Throw(ret, "CM_Get_Device_Interface_List_Size");
183 if (len <= 1) return null;
184 Byte[] buffer = new Byte[2 * len];
185 ret = SetupApi.CM_Get_Device_Interface_List(ref classGuid, DeviceID, buffer, len, 0);
186 CMException.Throw(ret, "CM_Get_Device_Interface_List");
187 return SetupApi.GetAsStringArray(buffer, 2 * (int)len);
188 }
189 public Boolean SupportsInterface(Guid classGuid) {
190 uint len;
191 CR ret = SetupApi.CM_Get_Device_Interface_List_Size(out len, ref classGuid, DeviceID, 0);
192 CMException.Throw(ret, "CM_Get_Device_Interface_List_Size");
193 return len > 2;
194 }
195
196 public IList<DeviceNode> GetChildren() {
197 UInt32 child;
198 CR ret = SetupApi.CM_Get_Child(out child, DevInst, 0);
199 if (ret == CR.NO_SUCH_DEVNODE) return null;
200 CMException.Throw(ret, "CM_Get_Child");
201 List<DeviceNode> list = new List<DeviceNode>();
202 while (true) {
203 list.Add(new DeviceNode(child));
204 ret = SetupApi.CM_Get_Sibling(out child, child, 0);
205 if (ret == CR.NO_SUCH_DEVNODE) break;
206 CMException.Throw(ret, "CM_Get_Sibling");
207 }
208 return list;
209 }
210
211 public DeviceNode GetParent() {
212 UInt32 node;
213 CR ret = SetupApi.CM_Get_Parent(out node, DevInst, 0);
214 if (ret == CR.NO_SUCH_DEVNODE) return null;
215 CMException.Throw(ret, "CM_Get_Parent");
216 return new DeviceNode(node);
217 }
218
219 public Boolean Present {
220 get {
221 UInt32 status, problem;
222 CR ret = SetupApi.CM_Get_DevNode_Status(out status, out problem, DevInst, 0);
223 if (ret == CR.NO_SUCH_DEVNODE) return false;
224 CMException.Throw(ret, "CM_Get_DevNode_Status");
225 if (status == 25174016) return false;
226 return true;
227 }
228 }
229
230 public override bool Equals(object obj) {
231 DeviceNode other = obj as DeviceNode;
232 if (ReferenceEquals(other, null)) return false;
233 return DevInst == other.DevInst;
234 }
235 public override int GetHashCode() {
236 return (int)DevInst;
237 }
238 public static Boolean operator ==(DeviceNode x, DeviceNode y) {
239 if (ReferenceEquals(x, y)) return true;
240 if (ReferenceEquals(x, null)) return false;
241 if (ReferenceEquals(y, null)) return false;
242 return x.DevInst == y.DevInst;
243 }
244 public static Boolean operator !=(DeviceNode x, DeviceNode y) {
245 return !(x == y);
246 }
247
248 public void SetEnabled(Boolean enabled) {
249 using (SafeDeviceInfoSetHandle dis = SetupApi.SetupDiGetClassDevsA(IntPtr.Zero, DeviceID, IntPtr.Zero, DICFG.DEVICEINTERFACE | DICFG.ALLCLASSES)) {
250 if (dis.IsInvalid) throw new Win32Exception(Marshal.GetLastWin32Error());
251 SP_DEVINFO_DATA dd = new SP_DEVINFO_DATA(true);
252 if (!SetupApi.SetupDiEnumDeviceInfo(dis, 0, ref dd))
253 throw new Win32Exception(Marshal.GetLastWin32Error());
254 SP_PROPCHANGE_PARAMS PropChangeParams = new SP_PROPCHANGE_PARAMS();
255 PropChangeParams.ClassInstallHeader.cbSize = Marshal.SizeOf(PropChangeParams.ClassInstallHeader);
256 PropChangeParams.ClassInstallHeader.InstallFunction = UsbApi.DIF_PROPERTYCHANGE;
257 PropChangeParams.Scope = UsbApi.DICS_FLAG_GLOBAL; // or use DICS_FLAG_CONFIGSPECIFIC to limit to current HW profile
258 PropChangeParams.HwProfile = 0; //Current hardware profile
259 PropChangeParams.StateChange = enabled ? UsbApi.DICS_ENABLE : UsbApi.DICS_DISABLE;
260 if (!SetupApi.SetupDiSetClassInstallParams(dis, ref dd, ref PropChangeParams.ClassInstallHeader, Marshal.SizeOf(PropChangeParams)))
261 throw new Win32Exception(Marshal.GetLastWin32Error());
262 if (!SetupApi.SetupDiCallClassInstaller(UsbApi.DIF_PROPERTYCHANGE, dis, ref dd))
263 throw new Win32Exception(Marshal.GetLastWin32Error());
264 }
265 }
266 }
267 }