enum.c
上传用户:gzccxsp
上传日期:2015-07-14
资源大小:182k
文件大小:50k
源码类别:

MacOS编程

开发平台:

Visual C++

  1. /*++
  2. Copyright (c) 1997-1998 Microsoft Corporation
  3. Module Name:
  4.     ENUM.C
  5. Abstract:
  6.     This source file contains the routines which enumerate the USB bus
  7.     and populate the TreeView control.
  8.     The enumeration process goes like this:
  9.     (1) Enumerate Host Controllers and Root Hubs
  10.     Host controllers currently have symbolic link names of the form HCDx,
  11.     where x starts at 0.  Use CreateFile() to open each host controller
  12.     symbolic link.  Create a node in the TreeView to represent each host
  13.     controller.
  14.     After a host controller has been opened, send the host controller an
  15.     IOCTL_USB_GET_ROOT_HUB_NAME request to get the symbolic link name of
  16.     the root hub that is part of the host controller.
  17.     (2) Enumerate Hubs (Root Hubs and External Hubs)
  18.     Given the name of a hub, use CreateFile() to hub the hub.  Send the
  19.     hub an IOCTL_USB_GET_NODE_INFORMATION request to get info about the
  20.     hub, such as the number of downstream ports.  Create a node in the
  21.     TreeView to represent each hub.
  22.     (3) Enumerate Downstream Ports
  23.     Given an handle to an open hub and the number of downstream ports on
  24.     the hub, send the hub an IOCTL_USB_GET_NODE_CONNECTION_INFORMATION
  25.     request for each downstream port of the hub to get info about the
  26.     device (if any) attached to each port.  If there is a device attached
  27.     to a port, send the hub an IOCTL_USB_GET_NODE_CONNECTION_NAME request
  28.     to get the symbolic link name of the hub attached to the downstream
  29.     port.  If there is a hub attached to the downstream port, recurse to
  30.     step (2).  Create a node in the TreeView to represent each hub port
  31.     and attached device.
  32. Environment:
  33.     user mode
  34. Revision History:
  35.     04-25-97 : created
  36. --*/
  37. //*****************************************************************************
  38. // I N C L U D E S
  39. //*****************************************************************************
  40. #include <windows.h>
  41. #include <basetyps.h>
  42. #include <winioctl.h>
  43. #include <string.h>
  44. #include "usbview.h"
  45. //*****************************************************************************
  46. // D E F I N E S
  47. //*****************************************************************************
  48. #define NUM_HCS_TO_CHECK 10
  49. //*****************************************************************************
  50. // L O C A L    F U N C T I O N    P R O T O T Y P E S
  51. //*****************************************************************************
  52. VOID
  53. EnumerateHub (
  54.     HTREEITEM                           hTreeParent,
  55.     PCHAR                               HubName,
  56.     PUSB_NODE_CONNECTION_INFORMATION    ConnectionInfo,
  57.     PUSB_DESCRIPTOR_REQUEST             ConfigDesc,
  58.     PSTRING_DESCRIPTOR_NODE             StringDescs,
  59.     PCHAR                               DeviceDesc
  60. );
  61. VOID
  62. EnumerateHubPorts (
  63.     HTREEITEM   hTreeParent,
  64.     HANDLE      hHubDevice,
  65.     ULONG       NumPorts
  66. );
  67. PCHAR GetRootHubName (
  68.     HANDLE HostController
  69. );
  70. PCHAR GetExternalHubName (
  71.     HANDLE  Hub,
  72.     ULONG   ConnectionIndex
  73. );
  74. PCHAR GetHCDDriverKeyName (
  75.     HANDLE  HCD
  76. );
  77. PCHAR GetDriverKeyName (
  78.     HANDLE  Hub,
  79.     ULONG   ConnectionIndex
  80. );
  81. PUSB_DESCRIPTOR_REQUEST
  82. GetConfigDescriptor (
  83.     HANDLE  hHubDevice,
  84.     ULONG   ConnectionIndex,
  85.     UCHAR   DescriptorIndex
  86. );
  87. BOOL
  88. AreThereStringDescriptors (
  89.     PUSB_DEVICE_DESCRIPTOR          DeviceDesc,
  90.     PUSB_CONFIGURATION_DESCRIPTOR   ConfigDesc
  91. );
  92. PSTRING_DESCRIPTOR_NODE
  93. GetAllStringDescriptors (
  94.     HANDLE                          hHubDevice,
  95.     ULONG                           ConnectionIndex,
  96.     PUSB_DEVICE_DESCRIPTOR          DeviceDesc,
  97.     PUSB_CONFIGURATION_DESCRIPTOR   ConfigDesc
  98. );
  99. PSTRING_DESCRIPTOR_NODE
  100. GetStringDescriptor (
  101.     HANDLE  hHubDevice,
  102.     ULONG   ConnectionIndex,
  103.     UCHAR   DescriptorIndex,
  104.     USHORT  LanguageID
  105. );
  106. PSTRING_DESCRIPTOR_NODE
  107. GetStringDescriptors (
  108.     HANDLE  hHubDevice,
  109.     ULONG   ConnectionIndex,
  110.     UCHAR   DescriptorIndex,
  111.     ULONG   NumLanguageIDs,
  112.     USHORT  *LanguageIDs,
  113.     PSTRING_DESCRIPTOR_NODE StringDescNodeTail
  114. );
  115. //*****************************************************************************
  116. // G L O B A L S    P R I V A T E    T O    T H I S    F I L E
  117. //*****************************************************************************
  118. PCHAR ConnectionStatuses[] =
  119. {
  120.     "NoDeviceConnected",
  121.     "DeviceConnected",
  122.     "DeviceFailedEnumeration",
  123.     "DeviceGeneralFailure",
  124.     "DeviceCausedOvercurrent",
  125.     "DeviceNotEnoughPower"
  126. };
  127. ULONG TotalDevicesConnected;
  128. //*****************************************************************************
  129. //
  130. // EnumerateHostControllers()
  131. //
  132. // hTreeParent - Handle of the TreeView item under which host controllers
  133. // should be added.
  134. //
  135. //*****************************************************************************
  136. VOID
  137. EnumerateHostControllers (
  138.     HTREEITEM  hTreeParent,
  139.     ULONG     *DevicesConnected
  140. )
  141. {
  142.     char        HCName[16];
  143.     int         HCNum;
  144.     HANDLE      hHCDev;
  145.     HTREEITEM   hHCItem;
  146.     PCHAR       rootHubName;
  147.     PCHAR       leafName;
  148.     TotalDevicesConnected = 0;
  149.     TotalHubs = 0;
  150.     // Iterate over some Host Controller names and try to open them.
  151.     //
  152.     for (HCNum = 0; HCNum < NUM_HCS_TO_CHECK; HCNum++)
  153.     {
  154.         wsprintf(HCName, "\\.\HCD%d", HCNum);
  155.         hHCDev = CreateFile(HCName,
  156.                             GENERIC_WRITE,
  157.                             FILE_SHARE_WRITE,
  158.                             NULL,
  159.                             OPEN_EXISTING,
  160.                             0,
  161.                             NULL);
  162.         // If the handle is valid, then we've successfully opened a Host
  163.         // Controller.  Display some info about the Host Controller itself,
  164.         // then enumerate the Root Hub attached to the Host Controller.
  165.         //
  166.         if (hHCDev != INVALID_HANDLE_VALUE)
  167.         {
  168.             PCHAR driverKeyName, deviceDesc;
  169.             driverKeyName = GetHCDDriverKeyName(hHCDev);
  170.             leafName = HCName + sizeof("\\.\") - sizeof("");
  171.             if (driverKeyName)
  172.             {
  173.                 deviceDesc = DriverNameToDeviceDesc(driverKeyName);
  174.                 if (deviceDesc)
  175.                 {
  176.                     leafName = deviceDesc;
  177.                 }
  178.                 FREE(driverKeyName);
  179.             }
  180.             hHCItem = AddLeaf(hTreeParent,
  181.                               0,
  182.                               leafName
  183.                              );
  184.             if (hHCItem)
  185.             {
  186.                 rootHubName = GetRootHubName(hHCDev); //Get the hub name.
  187.                 if (rootHubName != NULL)
  188.                 {
  189.                     EnumerateHub(hHCItem,
  190.                                  rootHubName,
  191.                                  NULL,      // ConnectionInfo
  192.                                  NULL,      // ConfigDesc
  193.                                  NULL,      // StringDescs
  194.                                  "RootHub"  // DeviceDesc
  195.                                 );
  196.                 }
  197.             }
  198.             CloseHandle(hHCDev);
  199.         }
  200.     }
  201.     *DevicesConnected = TotalDevicesConnected;
  202. }
  203. //*****************************************************************************
  204. //
  205. // EnumerateHub()
  206. //
  207. // hTreeParent - Handle of the TreeView item under which this hub should be
  208. // added.
  209. //
  210. // HubName - Name of this hub.  This pointer is kept so the caller can neither
  211. // free nor reuse this memory.
  212. //
  213. // ConnectionInfo - NULL if this is a root hub, else this is the connection
  214. // info for an external hub.  This pointer is kept so the caller can neither
  215. // free nor reuse this memory.
  216. //
  217. // ConfigDesc - NULL if this is a root hub, else this is the Configuration
  218. // Descriptor for an external hub.  This pointer is kept so the caller can
  219. // neither free nor reuse this memory.
  220. //
  221. //*****************************************************************************
  222. VOID
  223. EnumerateHub (
  224.     HTREEITEM                           hTreeParent,
  225.     PCHAR                               HubName,
  226.     PUSB_NODE_CONNECTION_INFORMATION    ConnectionInfo,
  227.     PUSB_DESCRIPTOR_REQUEST             ConfigDesc,
  228.     PSTRING_DESCRIPTOR_NODE             StringDescs,
  229.     PCHAR                               DeviceDesc
  230. )
  231. {
  232.     HANDLE          hHubDevice;
  233.     HTREEITEM       hItem;
  234.     PCHAR           deviceName;
  235.     BOOL            success;
  236.     ULONG           nBytes;
  237.     PUSBDEVICEINFO  info;
  238.     CHAR            leafName[512]; // XXXXX how big does this have to be?
  239.     // Initialize locals to not allocated state so the error cleanup routine
  240.     // only tries to cleanup things that were successfully allocated.
  241.     //
  242.     info        = NULL;
  243.     hHubDevice  = INVALID_HANDLE_VALUE;
  244.     // Allocate some space for a USBDEVICEINFO structure to hold the
  245.     // hub info, hub name, and connection info pointers.  GPTR zero
  246.     // initializes the structure for us.
  247.     //
  248.     info = (PUSBDEVICEINFO) ALLOC(sizeof(USBDEVICEINFO));
  249.     if (info == NULL)
  250.     {
  251.         OOPS();
  252.         goto EnumerateHubError;
  253.     }
  254.     // Keep copies of the Hub Name, Connection Info, and Configuration
  255.     // Descriptor pointers
  256.     //
  257.     info->HubName = HubName;
  258.     info->ConnectionInfo = ConnectionInfo;
  259.     info->ConfigDesc = ConfigDesc;
  260.     info->StringDescs = StringDescs;
  261.     // Allocate some space for a USB_NODE_INFORMATION structure for this Hub,
  262.     //
  263.     info->HubInfo = (PUSB_NODE_INFORMATION)ALLOC(sizeof(USB_NODE_INFORMATION));
  264.     if (info->HubInfo == NULL)
  265.     {
  266.         OOPS();
  267.         goto EnumerateHubError;
  268.     }
  269.     // Allocate a temp buffer for the full hub device name.
  270.     //
  271.     deviceName = (PCHAR)ALLOC(strlen(HubName) + sizeof("\\.\"));
  272.     if (deviceName == NULL)
  273.     {
  274.         OOPS();
  275.         goto EnumerateHubError;
  276.     }
  277.     // Create the full hub device name
  278.     //
  279.     strcpy(deviceName, "\\.\");
  280.     strcpy(deviceName + sizeof("\\.\") - 1, info->HubName);
  281.     // Try to hub the open device
  282.     //
  283.     hHubDevice = CreateFile(deviceName,  
  284.                             GENERIC_WRITE,
  285.                             FILE_SHARE_WRITE,
  286.                             NULL,
  287.                             OPEN_EXISTING,
  288.                             0,
  289.                             NULL);
  290.     // Done with temp buffer for full hub device name
  291.     //
  292.     FREE(deviceName);
  293.     if (hHubDevice == INVALID_HANDLE_VALUE)
  294.     {
  295.         OOPS();
  296.         goto EnumerateHubError;
  297.     }
  298.     //
  299.     // Now query USBHUB for the USB_NODE_INFORMATION structure for this hub.
  300.     // This will tell us the number of downstream ports to enumerate, among
  301.     // other things.
  302.     //
  303.     success = DeviceIoControl(hHubDevice,
  304.                               IOCTL_USB_GET_NODE_INFORMATION,
  305.                               info->HubInfo,
  306.                               sizeof(USB_NODE_INFORMATION),
  307.                               info->HubInfo,
  308.                               sizeof(USB_NODE_INFORMATION),
  309.                               &nBytes,
  310.                               NULL);
  311.     if (!success)
  312.     {
  313.         OOPS();
  314.         goto EnumerateHubError;
  315.     }
  316.     // Build the leaf name from the port number and the device description
  317.     //
  318.     if (ConnectionInfo)
  319.     {
  320.         wsprintf(leafName, "[Port%d] ", ConnectionInfo->ConnectionIndex);
  321.         strcat(leafName, ConnectionStatuses[ConnectionInfo->ConnectionStatus]);
  322.         strcat(leafName, " :  ");
  323.     }
  324.     else
  325.     {
  326.         leafName[0] = 0;
  327.     }
  328.     if (DeviceDesc)
  329.     {
  330.         strcat(leafName, DeviceDesc);
  331.     }
  332.     else
  333.     {
  334.         strcat(leafName, info->HubName);
  335.     }
  336.     // Now add an item to the TreeView with the PUSBDEVICEINFO pointer info
  337.     // as the LPARAM reference value containing everything we know about the
  338.     // hub.
  339.     //
  340.     hItem = AddLeaf(hTreeParent,
  341.                     (LPARAM)info,
  342.                     leafName);
  343.     if (hItem == NULL)
  344.     {
  345.         OOPS();
  346.         goto EnumerateHubError;
  347.     }
  348.     // Now recursively enumrate the ports of this hub.
  349.     //
  350.     EnumerateHubPorts(
  351.         hItem,
  352.         hHubDevice,
  353.         info->HubInfo->u.HubInformation.HubDescriptor.bNumberOfPorts
  354.         );
  355.     CloseHandle(hHubDevice);
  356.     return;
  357. EnumerateHubError:
  358.     //
  359.     // Clean up any stuff that got allocated
  360.     //
  361.     if (hHubDevice != INVALID_HANDLE_VALUE)
  362.     {
  363.         CloseHandle(hHubDevice);
  364.         hHubDevice = INVALID_HANDLE_VALUE;
  365.     }
  366.     if (info != NULL)
  367.     {
  368.         if (info->HubName != NULL)
  369.         {
  370.             FREE(info->HubName);
  371.             info->HubName = NULL;
  372.         }
  373.         if (info->HubInfo != NULL)
  374.         {
  375.             FREE(info->HubInfo);
  376.             info->HubInfo;
  377.         }
  378.         FREE(info);
  379.         info = NULL;
  380.     }
  381.     if (ConnectionInfo)
  382.     {
  383.         FREE(ConnectionInfo);
  384.     }
  385.     if (ConfigDesc)
  386.     {
  387.         FREE(ConfigDesc);
  388.     }
  389.     if (StringDescs != NULL)
  390.     {
  391.         PSTRING_DESCRIPTOR_NODE Next;
  392.         do {
  393.             Next = StringDescs->Next;
  394.             FREE(StringDescs);
  395.             StringDescs = Next;
  396.         } while (StringDescs != NULL);
  397.     }
  398. }
  399. //*****************************************************************************
  400. //
  401. // EnumerateHubPorts()
  402. //
  403. // hTreeParent - Handle of the TreeView item under which the hub port should
  404. // be added.
  405. //
  406. // hHubDevice - Handle of the hub device to enumerate.
  407. //
  408. // NumPorts - Number of ports on the hub.
  409. //
  410. //*****************************************************************************
  411. VOID
  412. EnumerateHubPorts (
  413.     HTREEITEM   hTreeParent,
  414.     HANDLE      hHubDevice,
  415.     ULONG       NumPorts
  416. )
  417. {
  418.     HTREEITEM   hItem;
  419.     ULONG       index;
  420.     BOOL        success;
  421.     PUSB_NODE_CONNECTION_INFORMATION    connectionInfo;
  422.     PUSB_DESCRIPTOR_REQUEST             configDesc;
  423.     PSTRING_DESCRIPTOR_NODE             stringDescs;
  424.     PUSBDEVICEINFO                      info;
  425.     PCHAR driverKeyName;
  426.     PCHAR deviceDesc;
  427.     CHAR  leafName[512]; // XXXXX how big does this have to be?
  428.     // Loop over all ports of the hub.
  429.     //
  430.     // Port indices are 1 based, not 0 based.
  431.     //
  432.     for (index=1; index <= NumPorts; index++)
  433.     {
  434.         ULONG nBytes;
  435.         // Allocate space to hold the connection info for this port.
  436.         // For now, allocate it big enough to hold info for 30 pipes.
  437.         //
  438.         // Endpoint numbers are 0-15.  Endpoint number 0 is the standard
  439.         // control endpoint which is not explicitly listed in the Configuration
  440.         // Descriptor.  There can be an IN endpoint and an OUT endpoint at
  441.         // endpoint numbers 1-15 so there can be a maximum of 30 endpoints
  442.         // per device configuration.
  443.         //
  444.         // Should probably size this dynamically at some point.
  445.         //
  446.         nBytes = sizeof(USB_NODE_CONNECTION_INFORMATION) +
  447.                  sizeof(USB_PIPE_INFO) * 30;
  448.         connectionInfo = (PUSB_NODE_CONNECTION_INFORMATION)ALLOC(nBytes);
  449.         if (connectionInfo == NULL)
  450.         {
  451.             OOPS();
  452.             break;
  453.         }
  454.         //
  455.         // Now query USBHUB for the USB_NODE_CONNECTION_INFORMATION structure
  456.         // for this port.  This will tell us if a device is attached to this
  457.         // port, among other things.
  458.         //
  459.         connectionInfo->ConnectionIndex = index;
  460.         success = DeviceIoControl(hHubDevice,
  461.                                   IOCTL_USB_GET_NODE_CONNECTION_INFORMATION,
  462.                                   connectionInfo,
  463.                                   nBytes,
  464.                                   connectionInfo,
  465.                                   nBytes,
  466.                                   &nBytes,
  467.                                   NULL);
  468.         if (!success)
  469.         {
  470.             FREE(connectionInfo);
  471.             continue;
  472.         }
  473.         // Update the count of connected devices
  474.         //
  475.         if (connectionInfo->ConnectionStatus == DeviceConnected)
  476.         {
  477.             TotalDevicesConnected++;
  478.         }
  479.         if (connectionInfo->DeviceIsHub)
  480.         {
  481.             TotalHubs++;
  482.         }
  483.         // If there is a device connected, get the Device Description
  484.         //
  485.         deviceDesc = NULL;
  486.         if (connectionInfo->ConnectionStatus != NoDeviceConnected)
  487.         {
  488.             driverKeyName = GetDriverKeyName(hHubDevice,
  489.                                              index);
  490.             if (driverKeyName)
  491.             {
  492.                 deviceDesc = DriverNameToDeviceDesc(driverKeyName);
  493.                 FREE(driverKeyName);
  494.             }
  495.         }
  496.         // If there is a device connected to the port, try to retrieve the
  497.         // Configuration Descriptor from the device.
  498.         //
  499.         if (gDoConfigDesc &&
  500.             connectionInfo->ConnectionStatus == DeviceConnected)
  501.         {
  502.             configDesc = GetConfigDescriptor(hHubDevice,
  503.                                              index,
  504.                                              0);
  505.         }
  506.         else
  507.         {
  508.             configDesc = NULL;
  509.         }
  510.         if (configDesc != NULL &&
  511.             AreThereStringDescriptors(&connectionInfo->DeviceDescriptor,
  512.                                       (PUSB_CONFIGURATION_DESCRIPTOR)(configDesc+1)))
  513.         {
  514.             stringDescs = GetAllStringDescriptors(
  515.                               hHubDevice,
  516.                               index,
  517.                               &connectionInfo->DeviceDescriptor,
  518.                               (PUSB_CONFIGURATION_DESCRIPTOR)(configDesc+1));
  519.         }
  520.         else
  521.         {
  522.             stringDescs = NULL;
  523.         }
  524.         // If the device connected to the port is an external hub, get the
  525.         // name of the external hub and recursively enumerate it.
  526.         //
  527.         if (connectionInfo->DeviceIsHub)
  528.         {
  529.             PCHAR extHubName;
  530.             extHubName = GetExternalHubName(hHubDevice,
  531.                                             index);
  532.             if (extHubName != NULL)
  533.             {
  534.                 EnumerateHub(hTreeParent, //hPortItem,
  535.                              extHubName,        //hub name.
  536.                              connectionInfo,
  537.                              configDesc,
  538.                              stringDescs,
  539.                              deviceDesc);
  540.                 // On to the next port
  541.                 //
  542.                 continue;
  543.             }
  544.         }
  545.         // Allocate some space for a USBDEVICEINFO structure to hold the
  546.         // hub info, hub name, and connection info pointers.  GPTR zero
  547.         // initializes the structure for us.
  548.         //
  549.         info = (PUSBDEVICEINFO) ALLOC(sizeof(USBDEVICEINFO));
  550.         if (info == NULL)
  551.         {
  552.             OOPS();
  553.             if (configDesc != NULL)
  554.             {
  555.                 FREE(configDesc);
  556.             }
  557.             FREE(connectionInfo);
  558.             break;
  559.         }
  560.         info->ConnectionInfo = connectionInfo;
  561.         info->ConfigDesc = configDesc;
  562.         info->StringDescs = stringDescs;
  563.         wsprintf(leafName, "[Port%d] ", index);
  564.         strcat(leafName, ConnectionStatuses[connectionInfo->ConnectionStatus]);
  565.         if (deviceDesc)
  566.         {
  567.             strcat(leafName, " :  ");
  568.             strcat(leafName, deviceDesc);
  569.         }
  570.         hItem = AddLeaf(hTreeParent, //hPortItem,
  571.                         (LPARAM)info,
  572.                         leafName);
  573.     }
  574. }
  575. //*****************************************************************************
  576. //
  577. // WideStrToMultiStr()
  578. //
  579. //*****************************************************************************
  580. PCHAR WideStrToMultiStr (PWCHAR WideStr)
  581. {
  582.     ULONG nBytes;
  583.     PCHAR MultiStr;
  584.     // Get the length of the converted string
  585.     //
  586.     nBytes = WideCharToMultiByte(
  587.                  CP_ACP,
  588.                  0,
  589.                  WideStr,
  590.                  -1,
  591.                  NULL,
  592.                  0,
  593.                  NULL,
  594.                  NULL);
  595.     if (nBytes == 0)
  596.     {
  597.         return NULL;
  598.     }
  599.     // Allocate space to hold the converted string
  600.     //
  601.     MultiStr = ALLOC(nBytes);
  602.     if (MultiStr == NULL)
  603.     {
  604.         return NULL;
  605.     }
  606.     // Convert the string
  607.     //
  608.     nBytes = WideCharToMultiByte(
  609.                  CP_ACP,
  610.                  0,
  611.                  WideStr,
  612.                  -1,
  613.                  MultiStr,
  614.                  nBytes,
  615.                  NULL,
  616.                  NULL);
  617.     if (nBytes == 0)
  618.     {
  619.         FREE(MultiStr);
  620.         return NULL;
  621.     }
  622.     return MultiStr;
  623. }
  624. //*****************************************************************************
  625. //
  626. // GetRootHubName()
  627. //
  628. //*****************************************************************************
  629. PCHAR GetRootHubName (
  630.     HANDLE HostController
  631. )
  632. {
  633.     BOOL                success;
  634.     ULONG               nBytes;
  635.     USB_ROOT_HUB_NAME   rootHubName;
  636.     PUSB_ROOT_HUB_NAME  rootHubNameW;
  637.     PCHAR               rootHubNameA;
  638.     rootHubNameW = NULL;
  639.     rootHubNameA = NULL;
  640.     // Get the length of the name of the Root Hub attached to the
  641.     // Host Controller
  642.     //
  643.     success = DeviceIoControl(HostController,
  644.                               IOCTL_USB_GET_ROOT_HUB_NAME,
  645.                               0,
  646.                               0,
  647.                               &rootHubName,
  648.                               sizeof(rootHubName),
  649.                               &nBytes,
  650.                               NULL);
  651.     if (!success)
  652.     {
  653.         OOPS();
  654.         goto GetRootHubNameError;
  655.     }
  656.     // Allocate space to hold the Root Hub name
  657.     //
  658.     nBytes = rootHubName.ActualLength;
  659.     rootHubNameW = ALLOC(nBytes);
  660.     if (rootHubNameW == NULL)
  661.     {
  662.         OOPS();
  663.         goto GetRootHubNameError;
  664.     }
  665.     // Get the name of the Root Hub attached to the Host Controller
  666.     //
  667.     success = DeviceIoControl(HostController,
  668.                               IOCTL_USB_GET_ROOT_HUB_NAME,
  669.                               NULL,
  670.                               0,
  671.                               rootHubNameW,
  672.                               nBytes,
  673.                               &nBytes,
  674.                               NULL);
  675.     if (!success)
  676.     {
  677.         OOPS();
  678.         goto GetRootHubNameError;
  679.     }
  680.     // Convert the Root Hub name
  681.     //
  682.     rootHubNameA = WideStrToMultiStr(rootHubNameW->RootHubName);
  683.     // All done, free the uncoverted Root Hub name and return the
  684.     // converted Root Hub name
  685.     //
  686.     FREE(rootHubNameW);
  687.     return rootHubNameA;
  688. GetRootHubNameError:
  689.     // There was an error, free anything that was allocated
  690.     //
  691.     if (rootHubNameW != NULL)
  692.     {
  693.         FREE(rootHubNameW);
  694.         rootHubNameW = NULL;
  695.     }
  696.     return NULL;
  697. }
  698. //*****************************************************************************
  699. //
  700. // GetExternalHubName()
  701. //
  702. //*****************************************************************************
  703. PCHAR GetExternalHubName (
  704.     HANDLE  Hub,
  705.     ULONG   ConnectionIndex
  706. )
  707. {
  708.     BOOL                        success;
  709.     ULONG                       nBytes;
  710.     USB_NODE_CONNECTION_NAME    extHubName;
  711.     PUSB_NODE_CONNECTION_NAME   extHubNameW;
  712.     PCHAR                       extHubNameA;
  713.     extHubNameW = NULL;
  714.     extHubNameA = NULL;
  715.     // Get the length of the name of the external hub attached to the
  716.     // specified port.
  717.     //
  718.     extHubName.ConnectionIndex = ConnectionIndex;
  719.     success = DeviceIoControl(Hub,
  720.                               IOCTL_USB_GET_NODE_CONNECTION_NAME,
  721.                               &extHubName,
  722.                               sizeof(extHubName),
  723.                               &extHubName,
  724.                               sizeof(extHubName),
  725.                               &nBytes,
  726.                               NULL);
  727.     if (!success)
  728.     {
  729.         OOPS();
  730.         goto GetExternalHubNameError;
  731.     }
  732.     // Allocate space to hold the external hub name
  733.     //
  734.     nBytes = extHubName.ActualLength;
  735.     if (nBytes <= sizeof(extHubName))
  736.     {
  737.         OOPS();
  738.         goto GetExternalHubNameError;
  739.     }
  740.     extHubNameW = ALLOC(nBytes);
  741.     if (extHubNameW == NULL)
  742.     {
  743.         OOPS();
  744.         goto GetExternalHubNameError;
  745.     }
  746.     // Get the name of the external hub attached to the specified port
  747.     //
  748.     extHubNameW->ConnectionIndex = ConnectionIndex;
  749.     success = DeviceIoControl(Hub,
  750.                               IOCTL_USB_GET_NODE_CONNECTION_NAME,
  751.                               extHubNameW,
  752.                               nBytes,
  753.                               extHubNameW,
  754.                               nBytes,
  755.                               &nBytes,
  756.                               NULL);
  757.     if (!success)
  758.     {
  759.         OOPS();
  760.         goto GetExternalHubNameError;
  761.     }
  762.     // Convert the External Hub name
  763.     //
  764.     extHubNameA = WideStrToMultiStr(extHubNameW->NodeName);
  765.     // All done, free the uncoverted external hub name and return the
  766.     // converted external hub name
  767.     //
  768.     FREE(extHubNameW);
  769.     return extHubNameA;
  770. GetExternalHubNameError:
  771.     // There was an error, free anything that was allocated
  772.     //
  773.     if (extHubNameW != NULL)
  774.     {
  775.         FREE(extHubNameW);
  776.         extHubNameW = NULL;
  777.     }
  778.     return NULL;
  779. }
  780. //*****************************************************************************
  781. //
  782. // GetDriverKeyName()
  783. //
  784. //*****************************************************************************
  785. PCHAR GetDriverKeyName (
  786.     HANDLE  Hub,
  787.     ULONG   ConnectionIndex
  788. )
  789. {
  790.     BOOL                                success;
  791.     ULONG                               nBytes;
  792.     USB_NODE_CONNECTION_DRIVERKEY_NAME  driverKeyName;
  793.     PUSB_NODE_CONNECTION_DRIVERKEY_NAME driverKeyNameW;
  794.     PCHAR                               driverKeyNameA;
  795.     driverKeyNameW = NULL;
  796.     driverKeyNameA = NULL;
  797.     // Get the length of the name of the driver key of the device attached to
  798.     // the specified port.
  799.     //
  800.     driverKeyName.ConnectionIndex = ConnectionIndex;
  801.     success = DeviceIoControl(Hub,
  802.                               IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME,
  803.                               &driverKeyName,
  804.                               sizeof(driverKeyName),
  805.                               &driverKeyName,
  806.                               sizeof(driverKeyName),
  807.                               &nBytes,
  808.                               NULL);
  809.     if (!success)
  810.     {
  811.         OOPS();
  812.         goto GetDriverKeyNameError;
  813.     }
  814.     // Allocate space to hold the driver key name
  815.     //
  816.     nBytes = driverKeyName.ActualLength;
  817.     if (nBytes <= sizeof(driverKeyName))
  818.     {
  819.         OOPS();
  820.         goto GetDriverKeyNameError;
  821.     }
  822.     driverKeyNameW = ALLOC(nBytes);
  823.     if (driverKeyNameW == NULL)
  824.     {
  825.         OOPS();
  826.         goto GetDriverKeyNameError;
  827.     }
  828.     // Get the name of the driver key of the device attached to
  829.     // the specified port.
  830.     //
  831.     driverKeyNameW->ConnectionIndex = ConnectionIndex;
  832.     success = DeviceIoControl(Hub,
  833.                               IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME,
  834.                               driverKeyNameW,
  835.                               nBytes,
  836.                               driverKeyNameW,
  837.                               nBytes,
  838.                               &nBytes,
  839.                               NULL);
  840.     if (!success)
  841.     {
  842.         OOPS();
  843.         goto GetDriverKeyNameError;
  844.     }
  845.     // Convert the driver key name
  846.     //
  847.     driverKeyNameA = WideStrToMultiStr(driverKeyNameW->DriverKeyName);
  848.     // All done, free the uncoverted driver key name and return the
  849.     // converted driver key name
  850.     //
  851.     FREE(driverKeyNameW);
  852.     return driverKeyNameA;
  853. GetDriverKeyNameError:
  854.     // There was an error, free anything that was allocated
  855.     //
  856.     if (driverKeyNameW != NULL)
  857.     {
  858.         FREE(driverKeyNameW);
  859.         driverKeyNameW = NULL;
  860.     }
  861.     return NULL;
  862. }
  863. //*****************************************************************************
  864. //
  865. // GetHCDDriverKeyName()
  866. //
  867. //*****************************************************************************
  868. PCHAR GetHCDDriverKeyName (
  869.     HANDLE  HCD
  870. )
  871. {
  872.     BOOL                    success;
  873.     ULONG                   nBytes;
  874.     USB_HCD_DRIVERKEY_NAME  driverKeyName;
  875.     PUSB_HCD_DRIVERKEY_NAME driverKeyNameW;
  876.     PCHAR                   driverKeyNameA;
  877.     driverKeyNameW = NULL;
  878.     driverKeyNameA = NULL;
  879.     // Get the length of the name of the driver key of the HCD
  880.     //
  881.     success = DeviceIoControl(HCD,
  882.                               IOCTL_GET_HCD_DRIVERKEY_NAME,
  883.                               &driverKeyName,
  884.                               sizeof(driverKeyName),
  885.                               &driverKeyName,
  886.                               sizeof(driverKeyName),
  887.                               &nBytes,
  888.                               NULL);
  889.     if (!success)
  890.     {
  891.         OOPS();
  892.         goto GetHCDDriverKeyNameError;
  893.     }
  894.     // Allocate space to hold the driver key name
  895.     //
  896.     nBytes = driverKeyName.ActualLength;
  897.     if (nBytes <= sizeof(driverKeyName))
  898.     {
  899.         OOPS();
  900.         goto GetHCDDriverKeyNameError;
  901.     }
  902.     driverKeyNameW = ALLOC(nBytes);
  903.     if (driverKeyNameW == NULL)
  904.     {
  905.         OOPS();
  906.         goto GetHCDDriverKeyNameError;
  907.     }
  908.     // Get the name of the driver key of the device attached to
  909.     // the specified port.
  910.     //
  911.     success = DeviceIoControl(HCD,
  912.                               IOCTL_GET_HCD_DRIVERKEY_NAME,
  913.                               driverKeyNameW,
  914.                               nBytes,
  915.                               driverKeyNameW,
  916.                               nBytes,
  917.                               &nBytes,
  918.                               NULL);
  919.     if (!success)
  920.     {
  921.         OOPS();
  922.         goto GetHCDDriverKeyNameError;
  923.     }
  924.     // Convert the driver key name
  925.     //
  926.     driverKeyNameA = WideStrToMultiStr(driverKeyNameW->DriverKeyName);
  927.     // All done, free the uncoverted driver key name and return the
  928.     // converted driver key name
  929.     //
  930.     FREE(driverKeyNameW);
  931.     return driverKeyNameA;
  932. GetHCDDriverKeyNameError:
  933.     // There was an error, free anything that was allocated
  934.     //
  935.     if (driverKeyNameW != NULL)
  936.     {
  937.         FREE(driverKeyNameW);
  938.         driverKeyNameW = NULL;
  939.     }
  940.     return NULL;
  941. }
  942. //*****************************************************************************
  943. //
  944. // GetConfigDescriptor()
  945. //
  946. // hHubDevice - Handle of the hub device containing the port from which the
  947. // Configuration Descriptor will be requested.
  948. //
  949. // ConnectionIndex - Identifies the port on the hub to which a device is
  950. // attached from which the Configuration Descriptor will be requested.
  951. //
  952. // DescriptorIndex - Configuration Descriptor index, zero based.
  953. //
  954. //*****************************************************************************
  955. PUSB_DESCRIPTOR_REQUEST
  956. GetConfigDescriptor (
  957.     HANDLE  hHubDevice,
  958.     ULONG   ConnectionIndex,
  959.     UCHAR   DescriptorIndex
  960. )
  961. {
  962.     BOOL    success;
  963.     ULONG   nBytes;
  964.     ULONG   nBytesReturned;
  965.     UCHAR   configDescReqBuf[sizeof(USB_DESCRIPTOR_REQUEST) +
  966.                              sizeof(USB_CONFIGURATION_DESCRIPTOR)];
  967.     PUSB_DESCRIPTOR_REQUEST         configDescReq;
  968.     PUSB_CONFIGURATION_DESCRIPTOR   configDesc;
  969.     // Request the Configuration Descriptor the first time using our
  970.     // local buffer, which is just big enough for the Cofiguration
  971.     // Descriptor itself.
  972.     //
  973.     nBytes = sizeof(configDescReqBuf);
  974.     configDescReq = (PUSB_DESCRIPTOR_REQUEST)configDescReqBuf;
  975.     configDesc = (PUSB_CONFIGURATION_DESCRIPTOR)(configDescReq+1);
  976.     // Zero fill the entire request structure
  977.     //
  978.     memset(configDescReq, 0, nBytes);
  979.     // Indicate the port from which the descriptor will be requested
  980.     //
  981.     configDescReq->ConnectionIndex = ConnectionIndex;
  982.     //
  983.     // USBHUB uses URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE to process this
  984.     // IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION request.
  985.     //
  986.     // USBD will automatically initialize these fields:
  987.     //     bmRequest = 0x80
  988.     //     bRequest  = 0x06
  989.     //
  990.     // We must inititialize these fields:
  991.     //     wValue    = Descriptor Type (high) and Descriptor Index (low byte)
  992.     //     wIndex    = Zero (or Language ID for String Descriptors)
  993.     //     wLength   = Length of descriptor buffer
  994.     //
  995.     configDescReq->SetupPacket.wValue = (USB_CONFIGURATION_DESCRIPTOR_TYPE << 8)
  996.                                         | DescriptorIndex;
  997.     configDescReq->SetupPacket.wLength = (USHORT)(nBytes - sizeof(USB_DESCRIPTOR_REQUEST));
  998.     // Now issue the get descriptor request.
  999.     //
  1000.     success = DeviceIoControl(hHubDevice,
  1001.                               IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION,
  1002.                               configDescReq,
  1003.                               nBytes,
  1004.                               configDescReq,
  1005.                               nBytes,
  1006.                               &nBytesReturned,
  1007.                               NULL);
  1008.     if (!success)
  1009.     {
  1010.         OOPS();
  1011.         return NULL;
  1012.     }
  1013.     if (nBytes != nBytesReturned)
  1014.     {
  1015.         OOPS();
  1016.         return NULL;
  1017.     }
  1018.     if (configDesc->wTotalLength < sizeof(USB_CONFIGURATION_DESCRIPTOR))
  1019.     {
  1020.         OOPS();
  1021.         return NULL;
  1022.     }
  1023.     // Now request the entire Configuration Descriptor using a dynamically
  1024.     // allocated buffer which is sized big enough to hold the entire descriptor
  1025.     //
  1026.     nBytes = sizeof(USB_DESCRIPTOR_REQUEST) + configDesc->wTotalLength;
  1027.     configDescReq = (PUSB_DESCRIPTOR_REQUEST)ALLOC(nBytes);
  1028.     if (configDescReq == NULL)
  1029.     {
  1030.         OOPS();
  1031.         return NULL;
  1032.     }
  1033.     configDesc = (PUSB_CONFIGURATION_DESCRIPTOR)(configDescReq+1);
  1034.     // Indicate the port from which the descriptor will be requested
  1035.     //
  1036.     configDescReq->ConnectionIndex = ConnectionIndex;
  1037.     //
  1038.     // USBHUB uses URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE to process this
  1039.     // IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION request.
  1040.     //
  1041.     // USBD will automatically initialize these fields:
  1042.     //     bmRequest = 0x80
  1043.     //     bRequest  = 0x06
  1044.     //
  1045.     // We must inititialize these fields:
  1046.     //     wValue    = Descriptor Type (high) and Descriptor Index (low byte)
  1047.     //     wIndex    = Zero (or Language ID for String Descriptors)
  1048.     //     wLength   = Length of descriptor buffer
  1049.     //
  1050.     configDescReq->SetupPacket.wValue = (USB_CONFIGURATION_DESCRIPTOR_TYPE << 8)
  1051.                                         | DescriptorIndex;
  1052.     configDescReq->SetupPacket.wLength = (USHORT)(nBytes - sizeof(USB_DESCRIPTOR_REQUEST));
  1053.     // Now issue the get descriptor request.
  1054.     //
  1055.     success = DeviceIoControl(hHubDevice,
  1056.                               IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION,
  1057.                               configDescReq,
  1058.                               nBytes,
  1059.                               configDescReq,
  1060.                               nBytes,
  1061.                               &nBytesReturned,
  1062.                               NULL);
  1063.     if (!success)
  1064.     {
  1065.         OOPS();
  1066.         FREE(configDescReq);
  1067.         return NULL;
  1068.     }
  1069.     if (nBytes != nBytesReturned)
  1070.     {
  1071.         OOPS();
  1072.         FREE(configDescReq);
  1073.         return NULL;
  1074.     }
  1075.     if (configDesc->wTotalLength != (nBytes - sizeof(USB_DESCRIPTOR_REQUEST)))
  1076.     {
  1077.         OOPS();
  1078.         FREE(configDescReq);
  1079.         return NULL;
  1080.     }
  1081.     return configDescReq;
  1082. }
  1083. //*****************************************************************************
  1084. //
  1085. // AreThereStringDescriptors()
  1086. //
  1087. // DeviceDesc - Device Descriptor for which String Descriptors should be
  1088. // checked.
  1089. //
  1090. // ConfigDesc - Configuration Descriptor (also containing Interface Descriptor)
  1091. // for which String Descriptors should be checked.
  1092. //
  1093. //*****************************************************************************
  1094. BOOL
  1095. AreThereStringDescriptors (
  1096.     PUSB_DEVICE_DESCRIPTOR          DeviceDesc,
  1097.     PUSB_CONFIGURATION_DESCRIPTOR   ConfigDesc
  1098. )
  1099. {
  1100.     PUCHAR                  descEnd;
  1101.     PUSB_COMMON_DESCRIPTOR  commonDesc;
  1102.     //
  1103.     // Check Device Descriptor strings
  1104.     //
  1105.     if (DeviceDesc->iManufacturer ||
  1106.         DeviceDesc->iProduct      ||
  1107.         DeviceDesc->iSerialNumber
  1108.        )
  1109.     {
  1110.         return TRUE;
  1111.     }
  1112.     //
  1113.     // Check the Configuration and Interface Descriptor strings
  1114.     //
  1115.     descEnd = (PUCHAR)ConfigDesc + ConfigDesc->wTotalLength;
  1116.     commonDesc = (PUSB_COMMON_DESCRIPTOR)ConfigDesc;
  1117.     while ((PUCHAR)commonDesc + sizeof(USB_COMMON_DESCRIPTOR) < descEnd &&
  1118.            (PUCHAR)commonDesc + commonDesc->bLength <= descEnd)
  1119.     {
  1120.         switch (commonDesc->bDescriptorType)
  1121.         {
  1122.             case USB_CONFIGURATION_DESCRIPTOR_TYPE:
  1123.                 if (commonDesc->bLength != sizeof(USB_CONFIGURATION_DESCRIPTOR))
  1124.                 {
  1125.                     OOPS();
  1126.                     break;
  1127.                 }
  1128.                 if (((PUSB_CONFIGURATION_DESCRIPTOR)commonDesc)->iConfiguration)
  1129.                 {
  1130.                     return TRUE;
  1131.                 }
  1132.                 (PUCHAR)commonDesc += commonDesc->bLength;
  1133.                 continue;
  1134.             case USB_INTERFACE_DESCRIPTOR_TYPE:
  1135.                 if (commonDesc->bLength != sizeof(USB_INTERFACE_DESCRIPTOR) &&
  1136.                     commonDesc->bLength != sizeof(USB_INTERFACE_DESCRIPTOR2))
  1137.                 {
  1138.                     OOPS();
  1139.                     break;
  1140.                 }
  1141.                 if (((PUSB_INTERFACE_DESCRIPTOR)commonDesc)->iInterface)
  1142.                 {
  1143.                     return TRUE;
  1144.                 }
  1145.                 (PUCHAR)commonDesc += commonDesc->bLength;
  1146.                 continue;
  1147.             default:
  1148.                 (PUCHAR)commonDesc += commonDesc->bLength;
  1149.                 continue;
  1150.         }
  1151.         break;
  1152.     }
  1153.     return FALSE;
  1154. }
  1155. //*****************************************************************************
  1156. //
  1157. // GetAllStringDescriptors()
  1158. //
  1159. // hHubDevice - Handle of the hub device containing the port from which the
  1160. // String Descriptors will be requested.
  1161. //
  1162. // ConnectionIndex - Identifies the port on the hub to which a device is
  1163. // attached from which the String Descriptors will be requested.
  1164. //
  1165. // DeviceDesc - Device Descriptor for which String Descriptors should be
  1166. // requested.
  1167. //
  1168. // ConfigDesc - Configuration Descriptor (also containing Interface Descriptor)
  1169. // for which String Descriptors should be requested.
  1170. //
  1171. //*****************************************************************************
  1172. PSTRING_DESCRIPTOR_NODE
  1173. GetAllStringDescriptors (
  1174.     HANDLE                          hHubDevice,
  1175.     ULONG                           ConnectionIndex,
  1176.     PUSB_DEVICE_DESCRIPTOR          DeviceDesc,
  1177.     PUSB_CONFIGURATION_DESCRIPTOR   ConfigDesc
  1178. )
  1179. {
  1180.     PSTRING_DESCRIPTOR_NODE supportedLanguagesString;
  1181.     PSTRING_DESCRIPTOR_NODE stringDescNodeTail;
  1182.     ULONG                   numLanguageIDs;
  1183.     USHORT                  *languageIDs;
  1184.     PUCHAR                  descEnd;
  1185.     PUSB_COMMON_DESCRIPTOR  commonDesc;
  1186.     //
  1187.     // Get the array of supported Language IDs, which is returned
  1188.     // in String Descriptor 0
  1189.     //
  1190.     supportedLanguagesString = GetStringDescriptor(hHubDevice,
  1191.                                                    ConnectionIndex,
  1192.                                                    0,
  1193.                                                    0);
  1194.     if (supportedLanguagesString == NULL)
  1195.     {
  1196.         return NULL;
  1197.     }
  1198.     numLanguageIDs = (supportedLanguagesString->StringDescriptor->bLength - 2) / 2;
  1199.     languageIDs = &supportedLanguagesString->StringDescriptor->bString[0];
  1200.     stringDescNodeTail = supportedLanguagesString;
  1201.     //
  1202.     // Get the Device Descriptor strings
  1203.     //
  1204.     if (DeviceDesc->iManufacturer)
  1205.     {
  1206.         stringDescNodeTail = GetStringDescriptors(hHubDevice,
  1207.                                                   ConnectionIndex,
  1208.                                                   DeviceDesc->iManufacturer,
  1209.                                                   numLanguageIDs,
  1210.                                                   languageIDs,
  1211.                                                   stringDescNodeTail);
  1212.     }
  1213.     if (DeviceDesc->iProduct)
  1214.     {
  1215.         stringDescNodeTail = GetStringDescriptors(hHubDevice,
  1216.                                                   ConnectionIndex,
  1217.                                                   DeviceDesc->iProduct,
  1218.                                                   numLanguageIDs,
  1219.                                                   languageIDs,
  1220.                                                   stringDescNodeTail);
  1221.     }
  1222.     if (DeviceDesc->iSerialNumber)
  1223.     {
  1224.         stringDescNodeTail = GetStringDescriptors(hHubDevice,
  1225.                                                   ConnectionIndex,
  1226.                                                   DeviceDesc->iSerialNumber,
  1227.                                                   numLanguageIDs,
  1228.                                                   languageIDs,
  1229.                                                   stringDescNodeTail);
  1230.     }
  1231.     //
  1232.     // Get the Configuration and Interface Descriptor strings
  1233.     //
  1234.     descEnd = (PUCHAR)ConfigDesc + ConfigDesc->wTotalLength;
  1235.     commonDesc = (PUSB_COMMON_DESCRIPTOR)ConfigDesc;
  1236.     while ((PUCHAR)commonDesc + sizeof(USB_COMMON_DESCRIPTOR) < descEnd &&
  1237.            (PUCHAR)commonDesc + commonDesc->bLength <= descEnd)
  1238.     {
  1239.         switch (commonDesc->bDescriptorType)
  1240.         {
  1241.             case USB_CONFIGURATION_DESCRIPTOR_TYPE:
  1242.                 if (commonDesc->bLength != sizeof(USB_CONFIGURATION_DESCRIPTOR))
  1243.                 {
  1244.                     OOPS();
  1245.                     break;
  1246.                 }
  1247.                 if (((PUSB_CONFIGURATION_DESCRIPTOR)commonDesc)->iConfiguration)
  1248.                 {
  1249.                     stringDescNodeTail = GetStringDescriptors(
  1250.                                              hHubDevice,
  1251.                                              ConnectionIndex,
  1252.                                              ((PUSB_CONFIGURATION_DESCRIPTOR)commonDesc)->iConfiguration,
  1253.                                              numLanguageIDs,
  1254.                                              languageIDs,
  1255.                                              stringDescNodeTail);
  1256.                 }
  1257.                 (PUCHAR)commonDesc += commonDesc->bLength;
  1258.                 continue;
  1259.             case USB_INTERFACE_DESCRIPTOR_TYPE:
  1260.                 if (commonDesc->bLength != sizeof(USB_INTERFACE_DESCRIPTOR) &&
  1261.                     commonDesc->bLength != sizeof(USB_INTERFACE_DESCRIPTOR2))
  1262.                 {
  1263.                     OOPS();
  1264.                     break;
  1265.                 }
  1266.                 if (((PUSB_INTERFACE_DESCRIPTOR)commonDesc)->iInterface)
  1267.                 {
  1268.                     stringDescNodeTail = GetStringDescriptors(
  1269.                                              hHubDevice,
  1270.                                              ConnectionIndex,
  1271.                                              ((PUSB_INTERFACE_DESCRIPTOR)commonDesc)->iInterface,
  1272.                                              numLanguageIDs,
  1273.                                              languageIDs,
  1274.                                              stringDescNodeTail);
  1275.                 }
  1276.                 (PUCHAR)commonDesc += commonDesc->bLength;
  1277.                 continue;
  1278.             default:
  1279.                 (PUCHAR)commonDesc += commonDesc->bLength;
  1280.                 continue;
  1281.         }
  1282.         break;
  1283.     }
  1284.     return supportedLanguagesString;
  1285. }
  1286. //*****************************************************************************
  1287. //
  1288. // GetStringDescriptor()
  1289. //
  1290. // hHubDevice - Handle of the hub device containing the port from which the
  1291. // String Descriptor will be requested.
  1292. //
  1293. // ConnectionIndex - Identifies the port on the hub to which a device is
  1294. // attached from which the String Descriptor will be requested.
  1295. //
  1296. // DescriptorIndex - String Descriptor index.
  1297. //
  1298. // LanguageID - Language in which the string should be requested.
  1299. //
  1300. //*****************************************************************************
  1301. PSTRING_DESCRIPTOR_NODE
  1302. GetStringDescriptor (
  1303.     HANDLE  hHubDevice,
  1304.     ULONG   ConnectionIndex,
  1305.     UCHAR   DescriptorIndex,
  1306.     USHORT  LanguageID
  1307. )
  1308. {
  1309.     BOOL    success;
  1310.     ULONG   nBytes;
  1311.     ULONG   nBytesReturned;
  1312.     UCHAR   stringDescReqBuf[sizeof(USB_DESCRIPTOR_REQUEST) +
  1313.                              MAXIMUM_USB_STRING_LENGTH];
  1314.     PUSB_DESCRIPTOR_REQUEST stringDescReq;
  1315.     PUSB_STRING_DESCRIPTOR  stringDesc;
  1316.     PSTRING_DESCRIPTOR_NODE stringDescNode;
  1317.     nBytes = sizeof(stringDescReqBuf);
  1318.     stringDescReq = (PUSB_DESCRIPTOR_REQUEST)stringDescReqBuf;
  1319.     stringDesc = (PUSB_STRING_DESCRIPTOR)(stringDescReq+1);
  1320.     // Zero fill the entire request structure
  1321.     //
  1322.     memset(stringDescReq, 0, nBytes);
  1323.     // Indicate the port from which the descriptor will be requested
  1324.     //
  1325.     stringDescReq->ConnectionIndex = ConnectionIndex;
  1326.     //
  1327.     // USBHUB uses URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE to process this
  1328.     // IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION request.
  1329.     //
  1330.     // USBD will automatically initialize these fields:
  1331.     //     bmRequest = 0x80
  1332.     //     bRequest  = 0x06
  1333.     //
  1334.     // We must inititialize these fields:
  1335.     //     wValue    = Descriptor Type (high) and Descriptor Index (low byte)
  1336.     //     wIndex    = Zero (or Language ID for String Descriptors)
  1337.     //     wLength   = Length of descriptor buffer
  1338.     //
  1339.     stringDescReq->SetupPacket.wValue = (USB_STRING_DESCRIPTOR_TYPE << 8)
  1340.                                         | DescriptorIndex;
  1341.     stringDescReq->SetupPacket.wIndex = LanguageID;
  1342.     stringDescReq->SetupPacket.wLength = (USHORT)(nBytes - sizeof(USB_DESCRIPTOR_REQUEST));
  1343.     // Now issue the get descriptor request.
  1344.     //
  1345.     success = DeviceIoControl(hHubDevice,
  1346.                               IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION,
  1347.                               stringDescReq,
  1348.                               nBytes,
  1349.                               stringDescReq,
  1350.                               nBytes,
  1351.                               &nBytesReturned,
  1352.                               NULL);
  1353.     //
  1354.     // Do some sanity checks on the return from the get descriptor request.
  1355.     //
  1356.     if (!success)
  1357.     {
  1358.         OOPS();
  1359.         return NULL;
  1360.     }
  1361.     if (nBytesReturned < 2)
  1362.     {
  1363.         OOPS();
  1364.         return NULL;
  1365.     }
  1366.     if (stringDesc->bDescriptorType != USB_STRING_DESCRIPTOR_TYPE)
  1367.     {
  1368.         OOPS();
  1369.         return NULL;
  1370.     }
  1371.     if (stringDesc->bLength != nBytesReturned - sizeof(USB_DESCRIPTOR_REQUEST))
  1372.     {
  1373.         OOPS();
  1374.         return NULL;
  1375.     }
  1376.     if (stringDesc->bLength % 2 != 0)
  1377.     {
  1378.         OOPS();
  1379.         return NULL;
  1380.     }
  1381.     //
  1382.     // Looks good, allocate some (zero filled) space for the string descriptor
  1383.     // node and copy the string descriptor to it.
  1384.     //
  1385.     stringDescNode = (PSTRING_DESCRIPTOR_NODE)ALLOC(sizeof(STRING_DESCRIPTOR_NODE) +
  1386.                                                     stringDesc->bLength);
  1387.     if (stringDescNode == NULL)
  1388.     {
  1389.         OOPS();
  1390.         return NULL;
  1391.     }
  1392.     stringDescNode->DescriptorIndex = DescriptorIndex;
  1393.     stringDescNode->LanguageID = LanguageID;
  1394.     memcpy(stringDescNode->StringDescriptor,
  1395.            stringDesc,
  1396.            stringDesc->bLength);
  1397.     return stringDescNode;
  1398. }
  1399. //*****************************************************************************
  1400. //
  1401. // GetStringDescriptors()
  1402. //
  1403. // hHubDevice - Handle of the hub device containing the port from which the
  1404. // String Descriptor will be requested.
  1405. //
  1406. // ConnectionIndex - Identifies the port on the hub to which a device is
  1407. // attached from which the String Descriptor will be requested.
  1408. //
  1409. // DescriptorIndex - String Descriptor index.
  1410. //
  1411. // NumLanguageIDs -  Number of languages in which the string should be
  1412. // requested.
  1413. //
  1414. // LanguageIDs - Languages in which the string should be requested.
  1415. //
  1416. //*****************************************************************************
  1417. PSTRING_DESCRIPTOR_NODE
  1418. GetStringDescriptors (
  1419.     HANDLE  hHubDevice,
  1420.     ULONG   ConnectionIndex,
  1421.     UCHAR   DescriptorIndex,
  1422.     ULONG   NumLanguageIDs,
  1423.     USHORT  *LanguageIDs,
  1424.     PSTRING_DESCRIPTOR_NODE StringDescNodeTail
  1425. )
  1426. {
  1427.     ULONG i;
  1428.     for (i=0; i<NumLanguageIDs; i++)
  1429.     {
  1430.         StringDescNodeTail->Next = GetStringDescriptor(hHubDevice,
  1431.                                                        ConnectionIndex,
  1432.                                                        DescriptorIndex,
  1433.                                                        *LanguageIDs);
  1434.         if (StringDescNodeTail->Next)
  1435.         {
  1436.             StringDescNodeTail = StringDescNodeTail->Next;
  1437.         }
  1438.         LanguageIDs++;
  1439.     }
  1440.     return StringDescNodeTail;
  1441. }
  1442. //*****************************************************************************
  1443. //
  1444. // CleanupItem()
  1445. //
  1446. //*****************************************************************************
  1447. VOID
  1448. CleanupItem (
  1449.     HWND      hTreeWnd,
  1450.     HTREEITEM hTreeItem
  1451. )
  1452. {
  1453.     TV_ITEM         tvi;
  1454.     PUSBDEVICEINFO  info;
  1455.     tvi.mask = TVIF_HANDLE | TVIF_PARAM;
  1456.     tvi.hItem = hTreeItem;
  1457.     TreeView_GetItem(hTreeWnd,
  1458.                      &tvi);
  1459.     info = (PUSBDEVICEINFO)tvi.lParam;
  1460.     if (info)
  1461.     {
  1462.         if (info->HubInfo != NULL)
  1463.         {
  1464.             FREE(info->HubInfo);
  1465.             info->HubInfo = NULL;
  1466.         }
  1467.         if (info->HubName != NULL)
  1468.         {
  1469.             FREE(info->HubName);
  1470.             info->HubName = NULL;
  1471.         }
  1472.         if (info->ConfigDesc != NULL)
  1473.         {
  1474.             FREE(info->ConfigDesc);
  1475.             info->ConfigDesc = NULL;
  1476.         }
  1477.         if (info->StringDescs != NULL)
  1478.         {
  1479.             PSTRING_DESCRIPTOR_NODE Next;
  1480.             do {
  1481.                 Next = info->StringDescs->Next;
  1482.                 FREE(info->StringDescs);
  1483.                 info->StringDescs = Next;
  1484.             } while (info->StringDescs != NULL);
  1485.         }
  1486.         if (info->ConnectionInfo != NULL)
  1487.         {
  1488.             FREE(info->ConnectionInfo);
  1489.             info->ConnectionInfo = NULL;
  1490.         }
  1491.         FREE(info);
  1492.         info = NULL;
  1493.     }
  1494. }