diff options
Diffstat (limited to 'usb/driver/driver_registry.c')
-rw-r--r-- | usb/driver/driver_registry.c | 376 |
1 files changed, 376 insertions, 0 deletions
diff --git a/usb/driver/driver_registry.c b/usb/driver/driver_registry.c new file mode 100644 index 0000000..3b0c67d --- /dev/null +++ b/usb/driver/driver_registry.c @@ -0,0 +1,376 @@ +/* libusb-win32, Generic Windows USB Library + * Copyright (c) 2002-2005 Stephan Meyer <ste_meyer@web.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "libusb_driver.h" +#include "lusb_defdi_guids.h" + +/* missing in mingw's ddk headers */ +#ifndef PLUGPLAY_REGKEY_DEVICE +#define PLUGPLAY_REGKEY_DEVICE 1 +#endif + +#define LIBUSB_REG_SURPRISE_REMOVAL_OK L"SurpriseRemovalOK" +#define LIBUSB_REG_INITIAL_CONFIG_VALUE L"InitialConfigValue" +#define LIBUSB_REG_DEVICE_INTERFACE_GUIDS L"DeviceInterfaceGUIDs" + +static bool_t reg_get_property(DEVICE_OBJECT *physical_device_object, + int property, char *data, int size); + +static bool_t reg_get_property(DEVICE_OBJECT *physical_device_object, + int property, char *data, int size) +{ + WCHAR tmp[512]; + ULONG ret; + ULONG i; + + if (!physical_device_object || !data || !size) + { + return FALSE; + } + + memset(data, 0, size); + memset(tmp, 0, sizeof(tmp)); + + if (NT_SUCCESS(IoGetDeviceProperty(physical_device_object, + property, + sizeof(tmp) - 2, + tmp, + &ret)) && ret) + { + /* convert unicode string to normal character string */ + for (i = 0; (i < ret/2) && (i < ((ULONG)size - 1)); i++) + { + data[i] = (char)tmp[i]; + } + + _strlwr(data); + + return TRUE; + } + + return FALSE; +} + + +bool_t reg_get_properties(libusb_device_t *dev) +{ + HANDLE key = NULL; + PVOID keyObject = NULL; + NTSTATUS status; + UNICODE_STRING surprise_removal_ok_name; + UNICODE_STRING initial_config_value_name; + UNICODE_STRING device_interface_guids; + UNICODE_STRING device_interface_guid_value; + KEY_VALUE_FULL_INFORMATION *info; + ULONG pool_length; + ULONG length; + ULONG val; + LPWSTR valW; + + if (!dev->physical_device_object) + { + return FALSE; + } + + /* default settings */ + dev->surprise_removal_ok = FALSE; + dev->is_filter = TRUE; + dev->initial_config_value = SET_CONFIG_ACTIVE_CONFIG; + + status = IoOpenDeviceRegistryKey(dev->physical_device_object, + PLUGPLAY_REGKEY_DEVICE, + STANDARD_RIGHTS_ALL, + &key); + if (NT_SUCCESS(status)) + { + RtlInitUnicodeString(&surprise_removal_ok_name, + LIBUSB_REG_SURPRISE_REMOVAL_OK); + + RtlInitUnicodeString(&initial_config_value_name, + LIBUSB_REG_INITIAL_CONFIG_VALUE); + + RtlInitUnicodeString(&device_interface_guids, + LIBUSB_REG_DEVICE_INTERFACE_GUIDS); + + pool_length = sizeof(KEY_VALUE_FULL_INFORMATION) + 512; + + info = ExAllocatePool(NonPagedPool, pool_length); + if (!info) + { + ZwClose(key); + USBERR("ExAllocatePool failed allocating %d bytes\n", pool_length); + return FALSE; + } + + + // get surprise_removal_ok + // get is_filter + length = pool_length; + memset(info, 0, length); + + status = ZwQueryValueKey(key, &surprise_removal_ok_name, + KeyValueFullInformation, info, length, &length); + + if (NT_SUCCESS(status) && (info->Type == REG_DWORD)) + { + val = *((ULONG *)(((char *)info) + info->DataOffset)); + + dev->surprise_removal_ok = val ? TRUE : FALSE; + dev->is_filter = FALSE; + } + + if (!dev->is_filter) + { + // get device interface guid + length = pool_length; + memset(info, 0, length); + + status = ZwQueryValueKey(key, &device_interface_guids, + KeyValueFullInformation, info, length, &length); + + if (NT_SUCCESS(status) && (info->Type == REG_MULTI_SZ)) + { + valW = ((LPWSTR)(((char *)info) + info->DataOffset)); + RtlInitUnicodeString(&device_interface_guid_value,valW); + status = RtlGUIDFromString(&device_interface_guid_value, &dev->device_interface_guid); + if (NT_SUCCESS(status)) + { + if (IsEqualGUID(&dev->device_interface_guid, &LibusbKDeviceGuid)) + { + USBWRN0("libusbK default device DeviceInterfaceGUID found. skippng..\n"); + RtlInitUnicodeString(&device_interface_guid_value,Libusb0DeviceGuidW); + } + else if (IsEqualGUID(&dev->device_interface_guid, &Libusb0FilterGuid)) + { + USBWRN0("libusb0 filter DeviceInterfaceGUID found. skippng..\n"); + RtlInitUnicodeString(&device_interface_guid_value,Libusb0DeviceGuidW); + } + else if (IsEqualGUID(&dev->device_interface_guid, &Libusb0DeviceGuid)) + { + USBWRN0("libusb0 device DeviceInterfaceGUID found. skippng..\n"); + RtlInitUnicodeString(&device_interface_guid_value,Libusb0DeviceGuidW); + } + else + { + USBMSG0("found user specified device interface guid.\n"); + dev->device_interface_in_use = TRUE; + } + } + else + { + USBERR0("invalid user specified device interface guid."); + } + } + if (!dev->device_interface_in_use) + { + RtlInitUnicodeString(&device_interface_guid_value,Libusb0DeviceGuidW); + } + } + else + { + RtlInitUnicodeString(&device_interface_guid_value,Libusb0FilterGuidW); + } + + if (!dev->device_interface_in_use) + { + status = RtlGUIDFromString(&device_interface_guid_value, &dev->device_interface_guid); + if (NT_SUCCESS(status)) + { + USBMSG0("using default device interface guid.\n"); + dev->device_interface_in_use = TRUE; + } + else + { + USBERR0("failed using default device interface guid.\n"); + } + } + + // get initial_config_value + length = pool_length; + memset(info, 0, length); + + status = ZwQueryValueKey(key, &initial_config_value_name, + KeyValueFullInformation, info, length, &length); + + if (NT_SUCCESS(status) && (info->Type == REG_DWORD)) + { + val = *((ULONG *)(((char *)info) + info->DataOffset)); + dev->initial_config_value = (int)val; + } + + status = ObReferenceObjectByHandle(key, KEY_READ, NULL, KernelMode, &keyObject, NULL); + if (NT_SUCCESS(status)) + { + length = pool_length; + memset(info, 0, length); + status = ObQueryNameString(keyObject, (POBJECT_NAME_INFORMATION)info, length, &length); + if (NT_SUCCESS(status)) + { + PWSTR nameW =((POBJECT_NAME_INFORMATION)info)->Name.Buffer; + PSTR nameA = dev->objname_plugplay_registry_key; + + val=0; + while (nameW[val] && val < (length/2)) + { + *nameA=(char)nameW[val]; + nameA++; + val++; + } + *nameA='\0'; + + USBDBG("reg-key-name=%s\n",dev->objname_plugplay_registry_key); + } + else + { + USBERR("ObQueryNameString failed. status=%Xh\n",status); + } + + ObDereferenceObject(keyObject); + } + else + { + USBERR("ObReferenceObjectByHandle failed. status=%Xh\n",status); + } + + ZwClose(key); + ExFreePool(info); + } + + return TRUE; +} + +bool_t reg_get_hardware_id(DEVICE_OBJECT *physical_device_object, + char *data, int size) +{ + if (!physical_device_object || !data || !size) + { + return FALSE; + } + + return reg_get_property(physical_device_object, DevicePropertyHardwareID, + data, size); +} + +bool_t reg_get_compatible_id(DEVICE_OBJECT *physical_device_object, + char *data, int size) +{ + if (!physical_device_object || !data || !size) + { + return FALSE; + } + + return reg_get_property(physical_device_object, DevicePropertyCompatibleIDs, + data, size); +} +/* +Gets a device property for the device_object. + +Returns: NTSTATUS code from IoGetDeviceProperty + STATUS_INVALID_PARAMETER +*/ +NTSTATUS reg_get_device_property(PDEVICE_OBJECT device_object, + int property, + char* data_buffer, + int data_length, + int* actual_length) +{ + NTSTATUS status = STATUS_INVALID_PARAMETER; + + if (!device_object || !data_buffer || !data_length || !actual_length) + return status; + + // clear data + memset(data_buffer, 0, data_length); + *actual_length=0; + + // get device property + status = IoGetDeviceProperty( + device_object, property, data_length, data_buffer, (PULONG)actual_length); + + return status; +} + +/* +Gets a property from the device registry key of the device_object. + +Returns: NTSTATUS from ZwQueryValueKey + NTSTATUS from IoOpenDeviceRegistryKey if the device registry + key could not be opened. +*/ +NTSTATUS reg_get_custom_property(PDEVICE_OBJECT device_object, + char *data_buffer, + unsigned int data_length, + unsigned int name_offset, + int* actual_length) +{ + HANDLE key = NULL; + NTSTATUS status; + UNICODE_STRING name; + KEY_VALUE_FULL_INFORMATION *info; + ULONG length; + + status = IoOpenDeviceRegistryKey(device_object, PLUGPLAY_REGKEY_DEVICE, KEY_READ, &key); + if (NT_SUCCESS(status)) + { + RtlInitUnicodeString(&name, (WCHAR*)(&data_buffer[name_offset])); + length = sizeof(KEY_VALUE_FULL_INFORMATION) + name.MaximumLength + data_length; + info = ExAllocatePool(NonPagedPool, length); + if (info) + { + memset(info, 0, length); + status = ZwQueryValueKey(key, &name, KeyValueFullInformation, info, length, &length); + if (NT_SUCCESS(status)) + { + data_length = (info->DataLength > data_length) ? data_length : info->DataLength; + memcpy(data_buffer, (((char *)info) + info->DataOffset),data_length); + *actual_length=data_length; + } + ExFreePool(info); + } + ZwClose(key); + } + return status; +} + +VOID set_filter_interface_key(libusb_device_t *dev, ULONG id) +{ + if (dev->device_interface_in_use) + { + HANDLE hKey=NULL; + if (NT_SUCCESS(IoOpenDeviceInterfaceRegistryKey(&dev->device_interface_name,KEY_ALL_ACCESS,&hKey))) + { + UNICODE_STRING valueName; + RtlInitUnicodeString(&valueName, L"LUsb0"); + + if (NT_SUCCESS(ZwSetValueKey(hKey,&valueName, 0, REG_DWORD, &id,sizeof(ULONG)))) + { + USBMSG("updated interface registry with LUsb0 direct-access symbolic link. id=%d\n",id); + } + else + { + USBERR0("IoOpenDeviceInterfaceRegistryKey:ZwSetValueKey failed\n"); + } + ZwClose(hKey); + } + else + { + USBERR0("IoOpenDeviceInterfaceRegistryKey failed\n"); + } + } +}
\ No newline at end of file |