1 /* libusb-win32, Generic Windows USB Library
2 * Copyright (c) 2002-2005 Stephan Meyer <ste_meyer@web.de>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18
19
20 #include "libusb_driver.h"
21 #include "lusb_defdi_guids.h"
22
23 /* missing in mingw's ddk headers */
24 #ifndef PLUGPLAY_REGKEY_DEVICE
25 #define PLUGPLAY_REGKEY_DEVICE 1
26 #endif
27
28 #define LIBUSB_REG_SURPRISE_REMOVAL_OK L"SurpriseRemovalOK"
29 #define LIBUSB_REG_INITIAL_CONFIG_VALUE L"InitialConfigValue"
30 #define LIBUSB_REG_DEVICE_INTERFACE_GUIDS L"DeviceInterfaceGUIDs"
31
32 static bool_t reg_get_property(DEVICE_OBJECT *physical_device_object,
33 int property, char *data, int size);
34
reg_get_property(DEVICE_OBJECT * physical_device_object,int property,char * data,int size)35 static bool_t reg_get_property(DEVICE_OBJECT *physical_device_object,
36 int property, char *data, int size)
37 {
38 WCHAR tmp[512];
39 ULONG ret;
40 ULONG i;
41
42 if (!physical_device_object || !data || !size)
43 {
44 return FALSE;
45 }
46
47 memset(data, 0, size);
48 memset(tmp, 0, sizeof(tmp));
49
50 if (NT_SUCCESS(IoGetDeviceProperty(physical_device_object,
51 property,
52 sizeof(tmp) - 2,
53 tmp,
54 &ret)) && ret)
55 {
56 /* convert unicode string to normal character string */
57 for (i = 0; (i < ret/2) && (i < ((ULONG)size - 1)); i++)
58 {
59 data[i] = (char)tmp[i];
60 }
61
62 _strlwr(data);
63
64 return TRUE;
65 }
66
67 return FALSE;
68 }
69
70
reg_get_properties(libusb_device_t * dev)71 bool_t reg_get_properties(libusb_device_t *dev)
72 {
73 HANDLE key = NULL;
74 PVOID keyObject = NULL;
75 NTSTATUS status;
76 UNICODE_STRING surprise_removal_ok_name;
77 UNICODE_STRING initial_config_value_name;
78 UNICODE_STRING device_interface_guids;
79 UNICODE_STRING device_interface_guid_value;
80 KEY_VALUE_FULL_INFORMATION *info;
81 ULONG pool_length;
82 ULONG length;
83 ULONG val;
84 LPWSTR valW;
85
86 if (!dev->physical_device_object)
87 {
88 return FALSE;
89 }
90
91 /* default settings */
92 dev->surprise_removal_ok = FALSE;
93 dev->is_filter = TRUE;
94 dev->initial_config_value = SET_CONFIG_ACTIVE_CONFIG;
95
96 status = IoOpenDeviceRegistryKey(dev->physical_device_object,
97 PLUGPLAY_REGKEY_DEVICE,
98 STANDARD_RIGHTS_ALL,
99 &key);
100 if (NT_SUCCESS(status))
101 {
102 RtlInitUnicodeString(&surprise_removal_ok_name,
103 LIBUSB_REG_SURPRISE_REMOVAL_OK);
104
105 RtlInitUnicodeString(&initial_config_value_name,
106 LIBUSB_REG_INITIAL_CONFIG_VALUE);
107
108 RtlInitUnicodeString(&device_interface_guids,
109 LIBUSB_REG_DEVICE_INTERFACE_GUIDS);
110
111 pool_length = sizeof(KEY_VALUE_FULL_INFORMATION) + 512;
112
113 info = ExAllocatePool(NonPagedPool, pool_length);
114 if (!info)
115 {
116 ZwClose(key);
117 USBERR("ExAllocatePool failed allocating %d bytes\n", pool_length);
118 return FALSE;
119 }
120
121
122 // get surprise_removal_ok
123 // get is_filter
124 length = pool_length;
125 memset(info, 0, length);
126
127 status = ZwQueryValueKey(key, &surprise_removal_ok_name,
128 KeyValueFullInformation, info, length, &length);
129
130 if (NT_SUCCESS(status) && (info->Type == REG_DWORD))
131 {
132 val = *((ULONG *)(((char *)info) + info->DataOffset));
133
134 dev->surprise_removal_ok = val ? TRUE : FALSE;
135 dev->is_filter = FALSE;
136 }
137
138 if (!dev->is_filter)
139 {
140 // get device interface guid
141 length = pool_length;
142 memset(info, 0, length);
143
144 status = ZwQueryValueKey(key, &device_interface_guids,
145 KeyValueFullInformation, info, length, &length);
146
147 if (NT_SUCCESS(status) && (info->Type == REG_MULTI_SZ))
148 {
149 valW = ((LPWSTR)(((char *)info) + info->DataOffset));
150 RtlInitUnicodeString(&device_interface_guid_value,valW);
151 status = RtlGUIDFromString(&device_interface_guid_value, &dev->device_interface_guid);
152 if (NT_SUCCESS(status))
153 {
154 if (IsEqualGUID(&dev->device_interface_guid, &LibusbKDeviceGuid))
155 {
156 USBWRN0("libusbK default device DeviceInterfaceGUID found. skippng..\n");
157 RtlInitUnicodeString(&device_interface_guid_value,Libusb0DeviceGuidW);
158 }
159 else if (IsEqualGUID(&dev->device_interface_guid, &Libusb0FilterGuid))
160 {
161 USBWRN0("libusb0 filter DeviceInterfaceGUID found. skippng..\n");
162 RtlInitUnicodeString(&device_interface_guid_value,Libusb0DeviceGuidW);
163 }
164 else if (IsEqualGUID(&dev->device_interface_guid, &Libusb0DeviceGuid))
165 {
166 USBWRN0("libusb0 device DeviceInterfaceGUID found. skippng..\n");
167 RtlInitUnicodeString(&device_interface_guid_value,Libusb0DeviceGuidW);
168 }
169 else
170 {
171 USBMSG0("found user specified device interface guid.\n");
172 dev->device_interface_in_use = TRUE;
173 }
174 }
175 else
176 {
177 USBERR0("invalid user specified device interface guid.");
178 }
179 }
180 if (!dev->device_interface_in_use)
181 {
182 RtlInitUnicodeString(&device_interface_guid_value,Libusb0DeviceGuidW);
183 }
184 }
185 else
186 {
187 RtlInitUnicodeString(&device_interface_guid_value,Libusb0FilterGuidW);
188 }
189
190 if (!dev->device_interface_in_use)
191 {
192 status = RtlGUIDFromString(&device_interface_guid_value, &dev->device_interface_guid);
193 if (NT_SUCCESS(status))
194 {
195 USBMSG0("using default device interface guid.\n");
196 dev->device_interface_in_use = TRUE;
197 }
198 else
199 {
200 USBERR0("failed using default device interface guid.\n");
201 }
202 }
203
204 // get initial_config_value
205 length = pool_length;
206 memset(info, 0, length);
207
208 status = ZwQueryValueKey(key, &initial_config_value_name,
209 KeyValueFullInformation, info, length, &length);
210
211 if (NT_SUCCESS(status) && (info->Type == REG_DWORD))
212 {
213 val = *((ULONG *)(((char *)info) + info->DataOffset));
214 dev->initial_config_value = (int)val;
215 }
216
217 status = ObReferenceObjectByHandle(key, KEY_READ, NULL, KernelMode, &keyObject, NULL);
218 if (NT_SUCCESS(status))
219 {
220 length = pool_length;
221 memset(info, 0, length);
222 status = ObQueryNameString(keyObject, (POBJECT_NAME_INFORMATION)info, length, &length);
223 if (NT_SUCCESS(status))
224 {
225 PWSTR nameW =((POBJECT_NAME_INFORMATION)info)->Name.Buffer;
226 PSTR nameA = dev->objname_plugplay_registry_key;
227
228 val=0;
229 while (nameW[val] && val < (length/2))
230 {
231 *nameA=(char)nameW[val];
232 nameA++;
233 val++;
234 }
235 *nameA='\0';
236
237 USBDBG("reg-key-name=%s\n",dev->objname_plugplay_registry_key);
238 }
239 else
240 {
241 USBERR("ObQueryNameString failed. status=%Xh\n",status);
242 }
243
244 ObDereferenceObject(keyObject);
245 }
246 else
247 {
248 USBERR("ObReferenceObjectByHandle failed. status=%Xh\n",status);
249 }
250
251 ZwClose(key);
252 ExFreePool(info);
253 }
254
255 return TRUE;
256 }
257
reg_get_hardware_id(DEVICE_OBJECT * physical_device_object,char * data,int size)258 bool_t reg_get_hardware_id(DEVICE_OBJECT *physical_device_object,
259 char *data, int size)
260 {
261 if (!physical_device_object || !data || !size)
262 {
263 return FALSE;
264 }
265
266 return reg_get_property(physical_device_object, DevicePropertyHardwareID,
267 data, size);
268 }
269
reg_get_compatible_id(DEVICE_OBJECT * physical_device_object,char * data,int size)270 bool_t reg_get_compatible_id(DEVICE_OBJECT *physical_device_object,
271 char *data, int size)
272 {
273 if (!physical_device_object || !data || !size)
274 {
275 return FALSE;
276 }
277
278 return reg_get_property(physical_device_object, DevicePropertyCompatibleIDs,
279 data, size);
280 }
281 /*
282 Gets a device property for the device_object.
283
284 Returns: NTSTATUS code from IoGetDeviceProperty
285 STATUS_INVALID_PARAMETER
286 */
reg_get_device_property(PDEVICE_OBJECT device_object,int property,char * data_buffer,int data_length,int * actual_length)287 NTSTATUS reg_get_device_property(PDEVICE_OBJECT device_object,
288 int property,
289 char* data_buffer,
290 int data_length,
291 int* actual_length)
292 {
293 NTSTATUS status = STATUS_INVALID_PARAMETER;
294
295 if (!device_object || !data_buffer || !data_length || !actual_length)
296 return status;
297
298 // clear data
299 memset(data_buffer, 0, data_length);
300 *actual_length=0;
301
302 // get device property
303 status = IoGetDeviceProperty(
304 device_object, property, data_length, data_buffer, (PULONG)actual_length);
305
306 return status;
307 }
308
309 /*
310 Gets a property from the device registry key of the device_object.
311
312 Returns: NTSTATUS from ZwQueryValueKey
313 NTSTATUS from IoOpenDeviceRegistryKey if the device registry
314 key could not be opened.
315 */
reg_get_custom_property(PDEVICE_OBJECT device_object,char * data_buffer,unsigned int data_length,unsigned int name_offset,int * actual_length)316 NTSTATUS reg_get_custom_property(PDEVICE_OBJECT device_object,
317 char *data_buffer,
318 unsigned int data_length,
319 unsigned int name_offset,
320 int* actual_length)
321 {
322 HANDLE key = NULL;
323 NTSTATUS status;
324 UNICODE_STRING name;
325 KEY_VALUE_FULL_INFORMATION *info;
326 ULONG length;
327
328 status = IoOpenDeviceRegistryKey(device_object, PLUGPLAY_REGKEY_DEVICE, KEY_READ, &key);
329 if (NT_SUCCESS(status))
330 {
331 RtlInitUnicodeString(&name, (WCHAR*)(&data_buffer[name_offset]));
332 length = sizeof(KEY_VALUE_FULL_INFORMATION) + name.MaximumLength + data_length;
333 info = ExAllocatePool(NonPagedPool, length);
334 if (info)
335 {
336 memset(info, 0, length);
337 status = ZwQueryValueKey(key, &name, KeyValueFullInformation, info, length, &length);
338 if (NT_SUCCESS(status))
339 {
340 data_length = (info->DataLength > data_length) ? data_length : info->DataLength;
341 memcpy(data_buffer, (((char *)info) + info->DataOffset),data_length);
342 *actual_length=data_length;
343 }
344 ExFreePool(info);
345 }
346 ZwClose(key);
347 }
348 return status;
349 }
350
set_filter_interface_key(libusb_device_t * dev,ULONG id)351 VOID set_filter_interface_key(libusb_device_t *dev, ULONG id)
352 {
353 if (dev->device_interface_in_use)
354 {
355 HANDLE hKey=NULL;
356 if (NT_SUCCESS(IoOpenDeviceInterfaceRegistryKey(&dev->device_interface_name,KEY_ALL_ACCESS,&hKey)))
357 {
358 UNICODE_STRING valueName;
359 RtlInitUnicodeString(&valueName, L"LUsb0");
360
361 if (NT_SUCCESS(ZwSetValueKey(hKey,&valueName, 0, REG_DWORD, &id,sizeof(ULONG))))
362 {
363 USBMSG("updated interface registry with LUsb0 direct-access symbolic link. id=%d\n",id);
364 }
365 else
366 {
367 USBERR0("IoOpenDeviceInterfaceRegistryKey:ZwSetValueKey failed\n");
368 }
369 ZwClose(hKey);
370 }
371 else
372 {
373 USBERR0("IoOpenDeviceInterfaceRegistryKey failed\n");
374 }
375 }
376 }