From 5f068a7aed7cfa73519dc01c76fb92c5ebaee720 Mon Sep 17 00:00:00 2001 From: Richard Pasek Date: Tue, 30 Jul 2019 17:19:11 -0400 Subject: [PATCH 1/2] Some bugfixes to get devices with multiple configurations to function correctly --- driver/stub/stub_devconf.c | 7 +----- driver/stub/stub_usbd.c | 48 ++++++++++++++++++++++++-------------- 2 files changed, 31 insertions(+), 24 deletions(-) diff --git a/driver/stub/stub_devconf.c b/driver/stub/stub_devconf.c index 0d419622..f792b7a2 100644 --- a/driver/stub/stub_devconf.c +++ b/driver/stub/stub_devconf.c @@ -6,8 +6,6 @@ #include "stub_usbd.h" #include "devconf.h" -PUSB_CONFIGURATION_DESCRIPTOR get_usb_dsc_conf(usbip_stub_dev_t *devstub, UCHAR bVal); - #ifdef DBG const char * @@ -56,18 +54,15 @@ dup_info_intf(PUSBD_INTERFACE_INFORMATION info_intf) static BOOLEAN build_infos_intf(devconf_t *devconf, PUSBD_INTERFACE_INFORMATION infos_intf) { - PUSBD_INTERFACE_INFORMATION info_intf; unsigned i; - info_intf = infos_intf; for (i = 0; i < devconf->bNumInterfaces; i++) { - PUSBD_INTERFACE_INFORMATION info_intf_copied = dup_info_intf(info_intf); + PUSBD_INTERFACE_INFORMATION info_intf_copied = dup_info_intf(&infos_intf[i]); if (info_intf_copied == NULL) { DBGE(DBG_GENERAL, "build_infos_intf: out of memory\n"); return FALSE; } devconf->infos_intf[i] = info_intf_copied; - info_intf = (PUSBD_INTERFACE_INFORMATION)((PUCHAR)info_intf + INFO_INTF_SIZE(info_intf)); } return TRUE; } diff --git a/driver/stub/stub_usbd.c b/driver/stub/stub_usbd.c index a204f8c3..744e44f3 100644 --- a/driver/stub/stub_usbd.c +++ b/driver/stub/stub_usbd.c @@ -174,24 +174,24 @@ get_usb_device_desc(usbip_stub_dev_t* devstub, PUSB_DEVICE_DESCRIPTOR pdesc) return get_usb_desc(devstub, USB_DEVICE_DESCRIPTOR_TYPE, 0, 0, pdesc, &len); } -static BOOLEAN +static INT find_usb_dsc_conf(usbip_stub_dev_t *devstub, UCHAR bVal, PUSB_CONFIGURATION_DESCRIPTOR dsc_conf) { USB_DEVICE_DESCRIPTOR DevDesc; UCHAR i; if (!get_usb_device_desc(devstub, &DevDesc)) { - return FALSE; + return -1; } for (i = 0; i < DevDesc.bNumConfigurations; i++) { ULONG len = sizeof(USB_CONFIGURATION_DESCRIPTOR); if (get_usb_desc(devstub, USB_CONFIGURATION_DESCRIPTOR_TYPE, i, 0, dsc_conf, &len)) { if (dsc_conf->bConfigurationValue == bVal) - return TRUE; + return i; } } - return FALSE; + return -1; } PUSB_CONFIGURATION_DESCRIPTOR @@ -200,8 +200,10 @@ get_usb_dsc_conf(usbip_stub_dev_t *devstub, UCHAR bVal) USB_CONFIGURATION_DESCRIPTOR ConfDesc; PUSB_CONFIGURATION_DESCRIPTOR dsc_conf; ULONG len; - - if (!find_usb_dsc_conf(devstub, bVal, &ConfDesc)) + INT iConfiguration; + + iConfiguration = find_usb_dsc_conf(devstub, bVal, &ConfDesc); + if (iConfiguration == -1) return NULL; dsc_conf = ExAllocatePoolWithTag(NonPagedPool, ConfDesc.wTotalLength, USBIP_STUB_POOL_TAG); @@ -209,7 +211,7 @@ get_usb_dsc_conf(usbip_stub_dev_t *devstub, UCHAR bVal) return NULL; len = ConfDesc.wTotalLength; - if (!get_usb_desc(devstub, USB_CONFIGURATION_DESCRIPTOR_TYPE, ConfDesc.iConfiguration, 0, dsc_conf, &len)) { + if (!get_usb_desc(devstub, USB_CONFIGURATION_DESCRIPTOR_TYPE, (UCHAR)iConfiguration, 0, dsc_conf, &len)) { ExFreePoolWithTag(dsc_conf, USBIP_STUB_POOL_TAG); return NULL; } @@ -225,6 +227,9 @@ build_default_intf_list(PUSB_CONFIGURATION_DESCRIPTOR dsc_conf) size = sizeof(USBD_INTERFACE_LIST_ENTRY) * (dsc_conf->bNumInterfaces + 1); pintf_list = ExAllocatePoolWithTag(NonPagedPool, size, USBIP_STUB_POOL_TAG); + if (pintf_list == NULL) + return NULL; + RtlZeroMemory(pintf_list, size); for (i = 0; i < dsc_conf->bNumInterfaces; i++) { @@ -244,7 +249,8 @@ select_usb_conf(usbip_stub_dev_t *devstub, USHORT bVal) PURB purb; PUSBD_INTERFACE_LIST_ENTRY pintf_list; NTSTATUS status; - + struct _URB_SELECT_CONFIGURATION *purb_selc; + dsc_conf = get_usb_dsc_conf(devstub, (UCHAR)bVal); if (dsc_conf == NULL) { DBGE(DBG_GENERAL, "select_usb_conf: non-existent configuration descriptor: index: %hu\n", bVal); @@ -252,33 +258,39 @@ select_usb_conf(usbip_stub_dev_t *devstub, USHORT bVal) } pintf_list = build_default_intf_list(dsc_conf); + if (pintf_list == NULL) { + DBGE(DBG_GENERAL, "select_usb_conf: out of memory: pintf_list\n"); + ExFreePoolWithTag(dsc_conf, USBIP_STUB_POOL_TAG); + return FALSE; + } status = USBD_SelectConfigUrbAllocateAndBuild(devstub->hUSBD, dsc_conf, pintf_list, &purb); if (NT_ERROR(status)) { DBGE(DBG_GENERAL, "select_usb_conf: failed to selectConfigUrb: %s\n", dbg_ntstatus(status)); ExFreePoolWithTag(pintf_list, USBIP_STUB_POOL_TAG); + ExFreePoolWithTag(dsc_conf, USBIP_STUB_POOL_TAG); return FALSE; } status = call_usbd(devstub, purb); - if (NT_SUCCESS(status)) { - struct _URB_SELECT_CONFIGURATION *purb_selc = &purb->UrbSelectConfiguration; - - if (devstub->devconf) - free_devconf(devstub->devconf); - devstub->devconf = create_devconf(purb_selc->ConfigurationDescriptor, purb_selc->ConfigurationHandle, &purb_selc->Interface); + if (NT_ERROR(status)) { + DBGI(DBG_GENERAL, "select_usb_conf: failed to select configuration: %s\n", dbg_devstub(devstub)); USBD_UrbFree(devstub->hUSBD, purb); ExFreePoolWithTag(pintf_list, USBIP_STUB_POOL_TAG); ExFreePoolWithTag(dsc_conf, USBIP_STUB_POOL_TAG); - return TRUE; + return FALSE; } - else { - DBGI(DBG_GENERAL, "select_usb_conf: failed to select configuration: %s\n", dbg_devstub(devstub)); + + purb_selc = &purb->UrbSelectConfiguration; + + if (devstub->devconf) { + free_devconf(devstub->devconf); } + devstub->devconf = create_devconf(purb_selc->ConfigurationDescriptor, purb_selc->ConfigurationHandle, &purb_selc->Interface); USBD_UrbFree(devstub->hUSBD, purb); ExFreePoolWithTag(pintf_list, USBIP_STUB_POOL_TAG); ExFreePoolWithTag(dsc_conf, USBIP_STUB_POOL_TAG); - return FALSE; + return TRUE; } BOOLEAN From 35b0c116734957a6d0a4cde217b09a45a0593bd8 Mon Sep 17 00:00:00 2001 From: Richard Pasek Date: Tue, 30 Jul 2019 23:29:33 -0400 Subject: [PATCH 2/2] Using pintf_list instead of purb_selc->Interface as the source for building the interface list. --- driver/stub/stub_devconf.c | 8 ++++---- driver/stub/stub_devconf.h | 2 +- driver/stub/stub_usbd.c | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/driver/stub/stub_devconf.c b/driver/stub/stub_devconf.c index f792b7a2..0ad303a5 100644 --- a/driver/stub/stub_devconf.c +++ b/driver/stub/stub_devconf.c @@ -52,12 +52,12 @@ dup_info_intf(PUSBD_INTERFACE_INFORMATION info_intf) } static BOOLEAN -build_infos_intf(devconf_t *devconf, PUSBD_INTERFACE_INFORMATION infos_intf) +build_infos_intf(devconf_t *devconf, PUSBD_INTERFACE_LIST_ENTRY pintf_list) { unsigned i; for (i = 0; i < devconf->bNumInterfaces; i++) { - PUSBD_INTERFACE_INFORMATION info_intf_copied = dup_info_intf(&infos_intf[i]); + PUSBD_INTERFACE_INFORMATION info_intf_copied = dup_info_intf(pintf_list[i].Interface); if (info_intf_copied == NULL) { DBGE(DBG_GENERAL, "build_infos_intf: out of memory\n"); return FALSE; @@ -68,7 +68,7 @@ build_infos_intf(devconf_t *devconf, PUSBD_INTERFACE_INFORMATION infos_intf) } devconf_t * -create_devconf(PUSB_CONFIGURATION_DESCRIPTOR dsc_conf, USBD_CONFIGURATION_HANDLE hconf, PUSBD_INTERFACE_INFORMATION infos_intf) +create_devconf(PUSB_CONFIGURATION_DESCRIPTOR dsc_conf, USBD_CONFIGURATION_HANDLE hconf, PUSBD_INTERFACE_LIST_ENTRY pintf_list) { devconf_t *devconf; int size_devconf; @@ -93,7 +93,7 @@ create_devconf(PUSB_CONFIGURATION_DESCRIPTOR dsc_conf, USBD_CONFIGURATION_HANDLE devconf->hConf = hconf; RtlZeroMemory(devconf->infos_intf, sizeof(PUSBD_INTERFACE_INFORMATION) * devconf->bNumInterfaces); - if (!build_infos_intf(devconf, infos_intf)) { + if (!build_infos_intf(devconf, pintf_list)) { free_devconf(devconf); return NULL; } diff --git a/driver/stub/stub_devconf.h b/driver/stub/stub_devconf.h index 17811432..5c5875b5 100644 --- a/driver/stub/stub_devconf.h +++ b/driver/stub/stub_devconf.h @@ -15,7 +15,7 @@ typedef struct { PUSBD_INTERFACE_INFORMATION infos_intf[1]; } devconf_t; -devconf_t *create_devconf(PUSB_CONFIGURATION_DESCRIPTOR dsc_conf, USBD_CONFIGURATION_HANDLE hconf, PUSBD_INTERFACE_INFORMATION infos_intf); +devconf_t *create_devconf(PUSB_CONFIGURATION_DESCRIPTOR dsc_conf, USBD_CONFIGURATION_HANDLE hconf, PUSBD_INTERFACE_LIST_ENTRY pintf_list); void free_devconf(devconf_t *devconf); void update_devconf(devconf_t *devconf, PUSBD_INTERFACE_INFORMATION info_intf); diff --git a/driver/stub/stub_usbd.c b/driver/stub/stub_usbd.c index 744e44f3..2eb22278 100644 --- a/driver/stub/stub_usbd.c +++ b/driver/stub/stub_usbd.c @@ -286,7 +286,7 @@ select_usb_conf(usbip_stub_dev_t *devstub, USHORT bVal) if (devstub->devconf) { free_devconf(devstub->devconf); } - devstub->devconf = create_devconf(purb_selc->ConfigurationDescriptor, purb_selc->ConfigurationHandle, &purb_selc->Interface); + devstub->devconf = create_devconf(purb_selc->ConfigurationDescriptor, purb_selc->ConfigurationHandle, pintf_list); USBD_UrbFree(devstub->hUSBD, purb); ExFreePoolWithTag(pintf_list, USBIP_STUB_POOL_TAG); ExFreePoolWithTag(dsc_conf, USBIP_STUB_POOL_TAG);