21
|
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 } |