Synchronize with trunk revision 59636 (just before Alex's CreateProcess revamp).
[reactos.git] / drivers / usb / usbccgp / descriptor.c
index b7395b5..37c496e 100644 (file)
@@ -94,6 +94,64 @@ USBCCGP_GetDescriptor(
     return Status;
 }
 
+NTSTATUS
+NTAPI
+USBCCGP_GetStringDescriptor(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN ULONG DescriptorLength,
+    IN UCHAR DescriptorIndex,
+    IN LANGID LanguageId,
+    OUT PVOID *OutDescriptor)
+{
+    NTSTATUS Status;
+    PUSB_STRING_DESCRIPTOR StringDescriptor;
+    ULONG Size;
+    PVOID Buffer;
+
+    // retrieve descriptor
+    Status = USBCCGP_GetDescriptor(DeviceObject, USB_STRING_DESCRIPTOR_TYPE, DescriptorLength, DescriptorIndex, LanguageId, OutDescriptor);
+    if (!NT_SUCCESS(Status))
+    {
+        // failed
+        return Status;
+    }
+
+    // get descriptor structure
+    StringDescriptor = (PUSB_STRING_DESCRIPTOR)*OutDescriptor;
+
+    // sanity check
+    ASSERT(StringDescriptor->bLength < DescriptorLength - 2);
+
+    if (StringDescriptor->bLength == 2)
+    {
+        // invalid descriptor
+        FreeItem(StringDescriptor);
+        return STATUS_DEVICE_DATA_ERROR;
+    }
+
+    // calculate size
+    Size = StringDescriptor->bLength + sizeof(WCHAR);
+
+    // allocate buffer
+    Buffer = AllocateItem(NonPagedPool, Size);
+    if (!Buffer)
+    {
+        // no memory
+        FreeItem(StringDescriptor);
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    // copy result
+    RtlCopyMemory(Buffer, StringDescriptor->bString, Size - FIELD_OFFSET(USB_STRING_DESCRIPTOR, bString));
+
+    // free buffer
+    FreeItem(StringDescriptor);
+
+    // store result
+    *OutDescriptor = (PVOID)Buffer;
+    return STATUS_SUCCESS;
+}
+
 
 NTSTATUS
 USBCCGP_GetDescriptors(
@@ -162,76 +220,32 @@ USBCCGP_GetDescriptors(
      return Status;
 }
 
-ULONG
-CountInterfaceDescriptors(
-    IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
-{
-    PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
-    PVOID CurrentPosition;
-    ULONG Count = 0;
-
-    //
-    // enumerate all interfaces
-    //
-    CurrentPosition = ConfigurationDescriptor;
-    do
-    {
-        //
-        // find next descriptor
-        //
-        InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, CurrentPosition, -1, -1, -1, -1, -1);
-        if (!InterfaceDescriptor)
-            break;
-
-        //
-        // advance to next descriptor
-        //
-        CurrentPosition = (PVOID)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength);
-
-        //
-        // increment descriptor count
-        //
-        Count++;
-
-    }while(TRUE);
-
-    //
-    // done
-    //
-    return Count;
-}
-
 NTSTATUS
 AllocateInterfaceDescriptorsArray(
     IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
     OUT PUSB_INTERFACE_DESCRIPTOR **OutArray)
 {
     PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
-    PVOID CurrentPosition;
     ULONG Count = 0;
     PUSB_INTERFACE_DESCRIPTOR *Array;
 
-    Count = CountInterfaceDescriptors(ConfigurationDescriptor);
-    ASSERT(Count);
-
     //
     // allocate array
     //
-    Array = AllocateItem(NonPagedPool, sizeof(PUSB_INTERFACE_DESCRIPTOR) * Count);
+    Array = AllocateItem(NonPagedPool, sizeof(PUSB_INTERFACE_DESCRIPTOR) * ConfigurationDescriptor->bNumInterfaces);
     if (!Array)
         return STATUS_INSUFFICIENT_RESOURCES;
 
     //
     // enumerate all interfaces
     //
-    CurrentPosition = ConfigurationDescriptor;
     Count = 0;
     do
     {
         //
         // find next descriptor
         //
-        InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, CurrentPosition, -1, -1, -1, -1, -1);
+        InterfaceDescriptor = USBD_ParseConfigurationDescriptorEx(ConfigurationDescriptor, ConfigurationDescriptor, Count, 0, -1, -1, -1);
         if (!InterfaceDescriptor)
             break;
 
@@ -241,11 +255,6 @@ AllocateInterfaceDescriptorsArray(
         Array[Count] = InterfaceDescriptor;
         Count++;
 
-        //
-        // advance to next descriptor
-        //
-        CurrentPosition = (PVOID)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength);
-
     }while(TRUE);
 
     //
@@ -259,6 +268,39 @@ AllocateInterfaceDescriptorsArray(
     return STATUS_SUCCESS;
 }
 
+VOID
+DumpFullConfigurationDescriptor(
+    IN PFDO_DEVICE_EXTENSION FDODeviceExtension,
+    IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
+{
+    PUSB_COMMON_DESCRIPTOR Descriptor;
+
+    Descriptor = (PUSB_COMMON_DESCRIPTOR)ConfigurationDescriptor;
+
+    DbgPrint("Bogus ConfigurationDescriptor Found\n");
+    DbgPrint("InterfaceCount %x\n", ConfigurationDescriptor->bNumInterfaces);
+
+    do
+    {
+        if (((ULONG_PTR)Descriptor) >= ((ULONG_PTR)ConfigurationDescriptor + ConfigurationDescriptor->wTotalLength))
+            break;
+
+        DbgPrint("Descriptor Type %x Length %lu Offset %lu\n", Descriptor->bDescriptorType, Descriptor->bLength, ((ULONG_PTR)Descriptor - (ULONG_PTR)ConfigurationDescriptor));
+
+        // check for invalid descriptors
+        if (!Descriptor->bLength) 
+        {
+            DbgPrint("Bogus Descriptor!!!\n");
+            break;
+        }
+
+        // advance to next descriptor
+        Descriptor = (PUSB_COMMON_DESCRIPTOR)((ULONG_PTR)Descriptor + Descriptor->bLength);
+
+    }while(TRUE);
+
+
+}
 
 
 NTSTATUS
@@ -269,7 +311,6 @@ USBCCGP_ScanConfigurationDescriptor(
 {
     PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
     ULONG InterfaceIndex = 0;
-    PVOID CurrentPosition;
     ULONG DescriptorCount;
 
     //
@@ -281,7 +322,7 @@ USBCCGP_ScanConfigurationDescriptor(
     //
     // count all interface descriptors
     //
-    DescriptorCount = CountInterfaceDescriptors(ConfigurationDescriptor);
+    DescriptorCount = ConfigurationDescriptor->bNumInterfaces;
 
     //
     // allocate array holding the interface descriptors
@@ -295,7 +336,6 @@ USBCCGP_ScanConfigurationDescriptor(
         return STATUS_INSUFFICIENT_RESOURCES;
     }
 
-    CurrentPosition = ConfigurationDescriptor;
     do
     {
         //
@@ -309,7 +349,18 @@ USBCCGP_ScanConfigurationDescriptor(
             //
             FDODeviceExtension->InterfaceList[FDODeviceExtension->InterfaceListCount].InterfaceDescriptor = InterfaceDescriptor;
             FDODeviceExtension->InterfaceListCount++;
-            CurrentPosition = (PVOID)((ULONG_PTR)InterfaceDescriptor + InterfaceDescriptor->bLength);
+        }
+        else
+        {
+            DumpConfigurationDescriptor(ConfigurationDescriptor);
+            DumpFullConfigurationDescriptor(FDODeviceExtension, ConfigurationDescriptor);
+
+            //
+            // see issue
+            // CORE-6574 Test 3 (USB Web Cam)
+            //
+            if (FDODeviceExtension->DeviceDescriptor && FDODeviceExtension->DeviceDescriptor->idVendor == 0x0458 && FDODeviceExtension->DeviceDescriptor->idProduct == 0x705f)
+                ASSERT(FALSE);
         }
 
         //
@@ -333,15 +384,15 @@ USBCCGP_ScanConfigurationDescriptor(
 VOID
 DumpConfigurationDescriptor(PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor)
 {
-    DPRINT1("Dumping ConfigurationDescriptor %x\n", ConfigurationDescriptor);
-    DPRINT1("bLength %x\n", ConfigurationDescriptor->bLength);
-    DPRINT1("bDescriptorType %x\n", ConfigurationDescriptor->bDescriptorType);
-    DPRINT1("wTotalLength %x\n", ConfigurationDescriptor->wTotalLength);
-    DPRINT1("bNumInterfaces %x\n", ConfigurationDescriptor->bNumInterfaces);
-    DPRINT1("bConfigurationValue %x\n", ConfigurationDescriptor->bConfigurationValue);
-    DPRINT1("iConfiguration %x\n", ConfigurationDescriptor->iConfiguration);
-    DPRINT1("bmAttributes %x\n", ConfigurationDescriptor->bmAttributes);
-    DPRINT1("MaxPower %x\n", ConfigurationDescriptor->MaxPower);
+    DbgPrint("Dumping ConfigurationDescriptor %x\n", ConfigurationDescriptor);
+    DbgPrint("bLength %x\n", ConfigurationDescriptor->bLength);
+    DbgPrint("bDescriptorType %x\n", ConfigurationDescriptor->bDescriptorType);
+    DbgPrint("wTotalLength %x\n", ConfigurationDescriptor->wTotalLength);
+    DbgPrint("bNumInterfaces %x\n", ConfigurationDescriptor->bNumInterfaces);
+    DbgPrint("bConfigurationValue %x\n", ConfigurationDescriptor->bConfigurationValue);
+    DbgPrint("iConfiguration %x\n", ConfigurationDescriptor->iConfiguration);
+    DbgPrint("bmAttributes %x\n", ConfigurationDescriptor->bmAttributes);
+    DbgPrint("MaxPower %x\n", ConfigurationDescriptor->MaxPower);
 }
 
 NTSTATUS
@@ -356,7 +407,7 @@ USBCCGP_SelectInterface(
     //
     // allocate urb
     //
-    Urb = AllocateItem(NonPagedPool, sizeof(struct _URB_SELECT_INTERFACE));
+    Urb = AllocateItem(NonPagedPool, GET_SELECT_INTERFACE_REQUEST_SIZE(DeviceExtension->InterfaceList[InterfaceIndex].InterfaceDescriptor->bNumEndpoints));
     if (!Urb)
     {
         //
@@ -370,11 +421,6 @@ USBCCGP_SelectInterface(
     //
     UsbBuildSelectInterfaceRequest(Urb, GET_SELECT_INTERFACE_REQUEST_SIZE(DeviceExtension->InterfaceList[InterfaceIndex].InterfaceDescriptor->bNumEndpoints), DeviceExtension->ConfigurationHandle, DeviceExtension->InterfaceList[InterfaceIndex].InterfaceDescriptor->bInterfaceNumber, DeviceExtension->InterfaceList[InterfaceIndex].InterfaceDescriptor->bAlternateSetting);
 
-    //
-    // copy interface information structure back - as offset for SelectConfiguration / SelectInterface request do differ
-    //
-    RtlCopyMemory(&Urb->UrbSelectInterface.Interface, DeviceExtension->InterfaceList[InterfaceIndex].Interface, DeviceExtension->InterfaceList[InterfaceIndex].Interface->Length);
-
     //
     // now select the interface
     //