Example #1
0
        private void GetUsbNodeInformation(IntPtr hubHandle)
        {
            var usbNodeInformation =
                new UsbIoControl.UsbNodeInformation {
                NodeType = UsbIoControl.UsbHubNode.UsbHub
            };

            int    nBytes      = usbNodeInformation.SizeOf;
            IntPtr ptrNodeInfo = IntPtr.Zero;

            try
            {
                ptrNodeInfo = Marshal.AllocHGlobal(nBytes);
                usbNodeInformation.MarshalTo(ptrNodeInfo, true);

                if (KernelApi.DeviceIoControl(hubHandle, UsbIoControl.IoctlUsbGetNodeInformation, ptrNodeInfo, nBytes, ptrNodeInfo,
                                              nBytes, out _, IntPtr.Zero))
                {
                    usbNodeInformation.MarshalFrom(ptrNodeInfo);
                    NodeInformation = usbNodeInformation;
                }
                else
                {
                    CoreTraceSource.Source.TraceEvent(TraceEventType.Error, CoreTraceSource.UsbHubSourceId,
                                                      $"[{nameof(KernelApi.DeviceIoControl)}] [{nameof(UsbIoControl.IoctlUsbGetNodeInformation)}] Result: [{KernelApi.GetLastError():X}]");
                }
            }
            finally
            {
                if (ptrNodeInfo != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(ptrNodeInfo);
                }
            }
        }
Example #2
0
        private void GetHubCapabilities(IntPtr hubHandle)
        {
            UsbApi.UsbHubCapabilitiesEx usbHubCapabilitiesEx = new UsbApi.UsbHubCapabilitiesEx();
            int    nBytes = Marshal.SizeOf(usbHubCapabilitiesEx);
            IntPtr ptrUsbHubCapabilitiesEx = IntPtr.Zero;

            try
            {
                ptrUsbHubCapabilitiesEx = Marshal.AllocHGlobal(nBytes);
                Marshal.StructureToPtr(usbHubCapabilitiesEx, ptrUsbHubCapabilitiesEx, true);

                if (KernelApi.DeviceIoControl(hubHandle, UsbIoControl.IoctlUsbGetHubCapabilitiesEx, ptrUsbHubCapabilitiesEx, nBytes,
                                              ptrUsbHubCapabilitiesEx, nBytes, out _, IntPtr.Zero))
                {
                    UsbHubCapabilitiesEx =
                        (UsbApi.UsbHubCapabilitiesEx)Marshal.PtrToStructure(ptrUsbHubCapabilitiesEx,
                                                                            typeof(UsbApi.UsbHubCapabilitiesEx));
                }
                else
                {
                    CoreTraceSource.Source.TraceEvent(TraceEventType.Error, CoreTraceSource.UsbHubSourceId,
                                                      $"[{nameof(KernelApi.DeviceIoControl)}] [{nameof(UsbIoControl.IoctlUsbGetHubCapabilitiesEx)}] Result: [{KernelApi.GetLastError():X}]");
                }
            }
            finally
            {
                if (ptrUsbHubCapabilitiesEx != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(ptrUsbHubCapabilitiesEx);
                }
            }
        }
Example #3
0
        private void GetUsbHubInformation(IntPtr hubHandle)
        {
            UsbIoControl.UsbHubInformationEx hubInfoEx =
                new UsbIoControl.UsbHubInformationEx();
            int    nBytes     = hubInfoEx.SizeOf;
            IntPtr ptrHubInfo = IntPtr.Zero;

            try
            {
                ptrHubInfo = Marshal.AllocHGlobal(nBytes);

                if (KernelApi.DeviceIoControl(hubHandle, UsbIoControl.IoctlUsbGetHubInformationEx, ptrHubInfo, nBytes, ptrHubInfo,
                                              nBytes, out _, IntPtr.Zero))
                {
                    hubInfoEx.MarshalFrom(ptrHubInfo);
                    HubInformation = hubInfoEx;
                }
                else
                {
                    CoreTraceSource.Source.TraceEvent(TraceEventType.Error, CoreTraceSource.UsbHubSourceId,
                                                      $"[{nameof(KernelApi.DeviceIoControl)}] [{nameof(UsbIoControl.IoctlUsbGetNodeInformation)}] Result: [{KernelApi.GetLastError():X}]");
                }
            }
            finally
            {
                if (ptrHubInfo != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(ptrHubInfo);
                }
            }
        }
        private void GetHostControllerPowerMap(IntPtr handle)
        {
            UsbUser.WdmusbPowerState powerState = UsbUser.WdmusbPowerState.WdmUsbPowerSystemWorking;

            for (; powerState <= UsbUser.WdmusbPowerState.WdmUsbPowerSystemShutdown; powerState++)
            {
                UsbUser.UsbuserPowerInfoRequest powerInfoRequest = new UsbUser.UsbuserPowerInfoRequest
                {
                    Header =
                    {
                        UsbUserRequest = UsbUser.UsbuserGetPowerStateMap,
                    },
                    PowerInformation = { SystemState = powerState }
                };

                powerInfoRequest.Header.RequestBufferLength = (uint)Marshal.SizeOf(powerInfoRequest);

                IntPtr ptrPowerInfoRequest = IntPtr.Zero;

                try
                {
                    //
                    // Now query USBHUB for the USB_POWER_INFO structure for this hub.
                    // For Selective Suspend support
                    //
                    int nBytes = Marshal.SizeOf(powerInfoRequest);
                    ptrPowerInfoRequest = Marshal.AllocHGlobal(nBytes);

                    Marshal.StructureToPtr(powerInfoRequest, ptrPowerInfoRequest, true);

                    var success = KernelApi.DeviceIoControl(handle,
                                                            UsbUser.IoctlUsbUserRequest,
                                                            ptrPowerInfoRequest,
                                                            nBytes,
                                                            ptrPowerInfoRequest,
                                                            nBytes,
                                                            out _,
                                                            IntPtr.Zero);

                    if (!success)
                    {
                        CoreTraceSource.Source.TraceEvent(TraceEventType.Error, CoreTraceSource.UsbControllerSourceId,
                                                          $"[{nameof(KernelApi.DeviceIoControl)}] Returned Error Code: [{KernelApi.GetLastError():X}]");
                    }
                    else
                    {
                        powerInfoRequest = (UsbUser.UsbuserPowerInfoRequest)Marshal.PtrToStructure(ptrPowerInfoRequest,
                                                                                                   typeof(UsbUser.UsbuserPowerInfoRequest));
                        PowerInfo.Add(powerInfoRequest.PowerInformation);
                    }
                }
                finally
                {
                    if (ptrPowerInfoRequest != IntPtr.Zero)
                    {
                        Marshal.FreeHGlobal(ptrPowerInfoRequest);
                    }
                }
            }
        }
        private void GetHostControllerInfo(IntPtr handle)
        {
            IntPtr ptrUsbControllerInfo0 = IntPtr.Zero;

            try
            {
                // set the header and request sizes
                UsbUser.UsbuserControllerInfo0 usbControllerInfo0 =
                    new UsbUser.UsbuserControllerInfo0 {
                    Header = { UsbUserRequest = UsbUser.UsbuserGetControllerInfo0 }
                };

                usbControllerInfo0.Header.RequestBufferLength = (uint)Marshal.SizeOf(usbControllerInfo0);

                //
                // Query for the USB_CONTROLLER_INFO_0 structure
                //
                int bytesRequested = Marshal.SizeOf(usbControllerInfo0);

                ptrUsbControllerInfo0 = Marshal.AllocHGlobal(bytesRequested);
                Marshal.StructureToPtr(usbControllerInfo0, ptrUsbControllerInfo0, true);

                if (KernelApi.DeviceIoControl(handle,
                                              UsbUser.IoctlUsbUserRequest,
                                              ptrUsbControllerInfo0,
                                              bytesRequested,
                                              ptrUsbControllerInfo0,
                                              bytesRequested,
                                              out _,
                                              IntPtr.Zero))
                {
                    CoreTraceSource.Source.TraceEvent(TraceEventType.Error, CoreTraceSource.UsbControllerSourceId,
                                                      $"[{nameof(KernelApi.DeviceIoControl)}] [{nameof(UsbUser.IoctlUsbUserRequest)}] Result: [{KernelApi.GetLastError():X}]");
                }
                else
                {
                    usbControllerInfo0 = (UsbUser.UsbuserControllerInfo0)Marshal.PtrToStructure(ptrUsbControllerInfo0,
                                                                                                typeof(UsbUser.UsbuserControllerInfo0));
                    ControllerInfo = usbControllerInfo0.Info0;
                }
            }
            finally
            {
                if (ptrUsbControllerInfo0 != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(ptrUsbControllerInfo0);
                }
            }
        }
Example #6
0
        private static bool GetUsbNodeConnectionName(uint portCount, IntPtr deviceHandle,
                                                     out UsbIoControl.UsbNodeConnectionName nodeConnectionName)
        {
            IntPtr structPtr = IntPtr.Zero;

            try
            {
                int bytesRequested = Marshal.SizeOf(typeof(UsbIoControl.UsbNodeConnectionName));

                structPtr          = Marshal.AllocHGlobal(bytesRequested);
                nodeConnectionName = new UsbIoControl.UsbNodeConnectionName()
                {
                    ConnectionIndex = portCount
                };

                Marshal.StructureToPtr(nodeConnectionName, structPtr, true);

                if (KernelApi.DeviceIoControl(deviceHandle, UsbIoControl.IoctlUsbGetNodeConnectionName,
                                              structPtr, bytesRequested, structPtr, bytesRequested, out _, IntPtr.Zero))
                {
                    nodeConnectionName =
                        (UsbIoControl.UsbNodeConnectionName)Marshal.PtrToStructure(structPtr,
                                                                                   typeof(UsbIoControl.UsbNodeConnectionName));
                }
                else
                {
                    CoreTraceSource.Source.TraceEvent(TraceEventType.Error, CoreTraceSource.DeviceFactorySourceId,
                                                      $"[{nameof(KernelApi.DeviceIoControl)}] [{nameof(UsbIoControl.IoctlUsbGetNodeConnectionName)}] Result: [{KernelApi.GetLastError():X}]");

                    return(false);
                }
            }
            finally
            {
                if (structPtr != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(structPtr);
                }
            }

            return(true);
        }
Example #7
0
        private static void GetNodeConnectionInformationExV2(uint portCount, IntPtr deviceHandle,
                                                             out UsbIoControl.UsbNodeConnectionInformationExV2 usbNodeConnectionInformationExV2)
        {
            IntPtr structPtr = IntPtr.Zero;

            try
            {
                int bytesRequested = Marshal.SizeOf(typeof(UsbIoControl.UsbNodeConnectionInformationExV2));

                structPtr = Marshal.AllocHGlobal(bytesRequested);
                usbNodeConnectionInformationExV2 =
                    new UsbIoControl.UsbNodeConnectionInformationExV2
                {
                    ConnectionIndex       = portCount,
                    SupportedUsbProtocols = UsbIoControl.UsbProtocols.Usb300,
                    Length = (uint)bytesRequested
                };

                Marshal.StructureToPtr(usbNodeConnectionInformationExV2, structPtr, true);

                if (KernelApi.DeviceIoControl(deviceHandle, UsbIoControl.IoctlUsbGetNodeConnectionInformationExV2,
                                              structPtr, bytesRequested, structPtr, bytesRequested, out _, IntPtr.Zero))
                {
                    usbNodeConnectionInformationExV2 =
                        (UsbIoControl.UsbNodeConnectionInformationExV2)Marshal.PtrToStructure(structPtr,
                                                                                              typeof(UsbIoControl.UsbNodeConnectionInformationExV2));
                }
                else
                {
                    CoreTraceSource.Source.TraceEvent(TraceEventType.Error, CoreTraceSource.DeviceFactorySourceId,
                                                      $"[{nameof(KernelApi.DeviceIoControl)}] [{nameof(UsbIoControl.IoctlUsbGetNodeConnectionInformationExV2)}] Result: [{KernelApi.GetLastError():X}]");
                }
            }
            finally
            {
                if (structPtr != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(structPtr);
                }
            }
        }
Example #8
0
        private static void GetUsbPortConnectorProperties(uint portCount, IntPtr deviceHandle,
                                                          out UsbIoControl.UsbPortConnectorProperties usbPortConnectorProperties)
        {
            IntPtr structPtr = IntPtr.Zero;

            try
            {
                int bytesRequested = Marshal.SizeOf(typeof(UsbIoControl.UsbPortConnectorProperties));

                structPtr = Marshal.AllocHGlobal(bytesRequested);
                usbPortConnectorProperties =
                    new UsbIoControl.UsbPortConnectorProperties()
                {
                    ConnectionIndex = portCount
                };
                Marshal.StructureToPtr(usbPortConnectorProperties, structPtr, true);

                if (KernelApi.DeviceIoControl(deviceHandle, UsbIoControl.IoctlUsbGetPortConnectorProperties,
                                              structPtr, bytesRequested, structPtr, bytesRequested, out _, IntPtr.Zero))
                {
                    usbPortConnectorProperties =
                        (UsbIoControl.UsbPortConnectorProperties)Marshal.PtrToStructure(structPtr,
                                                                                        typeof(UsbIoControl.UsbPortConnectorProperties));
                }
                else
                {
                    CoreTraceSource.Source.TraceEvent(TraceEventType.Error, CoreTraceSource.DeviceFactorySourceId,
                                                      $"[{nameof(KernelApi.DeviceIoControl)}] [{nameof(UsbIoControl.IoctlUsbGetPortConnectorProperties)}] Result: [{KernelApi.GetLastError():X}]");
                }
            }
            finally
            {
                if (structPtr != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(structPtr);
                }
            }
        }
Example #9
0
        /// <summary>
        /// Function to close the data store for writing.
        /// </summary>
        /// <param name="closingMessage">[Optional] The message to write when closing.</param>
        public void Close(string closingMessage = null)
        {
            if (Interlocked.Exchange(ref _hasConsole, 0) == 0)
            {
                return;
            }

            if (!string.IsNullOrWhiteSpace(closingMessage))
            {
                Console.ForegroundColor = ConsoleColor.White;
                Console.WriteLine(closingMessage);
            }

            Console.ResetColor();

            if (!_ownsConsole)
            {
                return;
            }

            Debug.Assert(KernelApi.FreeConsole() != 0);
            _ownsConsole = false;
        }
Example #10
0
        private void GetRootHubName(IntPtr hostControllerHandle)
        {
            UsbApi.UsbRootHubName rootHubName = new UsbApi.UsbRootHubName();
            int    nBytes         = Marshal.SizeOf(rootHubName);
            IntPtr ptrRootHubName = IntPtr.Zero;

            try
            {
                ptrRootHubName = Marshal.AllocHGlobal(nBytes);

                // Get the root hub name.
                if (KernelApi.DeviceIoControl(hostControllerHandle, UsbIoControl.IoctlUsbGetRootHubName, ptrRootHubName, nBytes,
                                              ptrRootHubName, nBytes, out _, IntPtr.Zero))
                {
                    rootHubName = (UsbApi.UsbRootHubName)Marshal.PtrToStructure(ptrRootHubName, typeof(UsbApi.UsbRootHubName));

                    if (rootHubName.ActualLength > 0)
                    {
                        IsRootHub         = true;
                        DeviceDescription = "RootHub";
                        DevicePath        = @"\\?\" + rootHubName.RootHubName;
                    }
                }
                else
                {
                    CoreTraceSource.Source.TraceEvent(TraceEventType.Error, CoreTraceSource.UsbHubSourceId,
                                                      $"[{nameof(KernelApi.DeviceIoControl)}] [{nameof(UsbIoControl.IoctlUsbGetRootHubName)}] Result: [{KernelApi.GetLastError():X}]");
                }
            }
            finally
            {
                if (ptrRootHubName != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(ptrRootHubName);
                }
            }
        }
Example #11
0
        /// <summary>
        /// Function to open the data store for writing.
        /// </summary>
        /// <param name="initialMessage">[Optional] The initial message to write.</param>
        public void Open(string initialMessage = null)
        {
            if (Interlocked.Exchange(ref _hasConsole, 1) == 1)
            {
                return;
            }

            // Check for an existing console first.
            using (Stream stdIn = Console.OpenStandardInput())
            {
                // If it does not exist, then create one.
                if (stdIn == Stream.Null)
                {
                    if (!KernelApi.AllocConsole())
                    {
                        return;
                    }

                    _ownsConsole = true;
                }
            }

            // If we have Enable Native Debugging turned on, all output is redirected to the debug window.
            // This will reset that back to our logging window.
            if (Console.IsOutputRedirected)
            {
                const uint genericRead  = 0x80000000;
                const uint genericWrite = 0x40000000;

                IntPtr filePtr = KernelApi.CreateFileW("CONOUT$",
                                                       (genericRead | genericWrite),
                                                       (uint)FileShare.ReadWrite,
                                                       IntPtr.Zero,
                                                       (uint)FileMode.Open,
                                                       0,
                                                       IntPtr.Zero);
                var handle = new SafeFileHandle(filePtr, true);
                if (handle.IsInvalid)
                {
                    handle.Dispose();
                    return;
                }

                KernelApi.SetStdHandle(KernelApi.StdOutputHandle, filePtr);

                var stream = new FileStream(handle, FileAccess.Write);
                var writer = new StreamWriter(stream, Encoding.Default)
                {
                    AutoFlush = true
                };
                Console.SetOut(writer);

                if (KernelApi.GetConsoleMode(filePtr, out uint consoleMode))
                {
                    KernelApi.SetConsoleMode(filePtr, consoleMode | 0x200);
                }
            }

            if (string.IsNullOrWhiteSpace(initialMessage))
            {
                return;
            }

            Console.ForegroundColor = ConsoleColor.White;
            Console.WriteLine(initialMessage);
            Console.ResetColor();
        }
Example #12
0
        /// <summary>
        /// Initializes a new instance of the <see cref="UsbHub"/> class.
        /// </summary>
        /// <param name="deviceDescriptor">The device descriptor.</param>
        /// <param name="devicePath">The device path.</param>
        public UsbHub(UsbSpec.UsbDeviceDescriptor deviceDescriptor, string devicePath)
            : base(deviceDescriptor, 0, devicePath)
        {
            DeviceDescription = "Standard-USB-Hub";
            DevicePath        = devicePath;

            IntPtr hostControllerHandle = IntPtr.Zero;

            try
            {
                hostControllerHandle = KernelApi.CreateFile(devicePath, UsbApi.GenericWrite, UsbApi.FileShareWrite, IntPtr.Zero, UsbApi.OpenExisting, 0, IntPtr.Zero);

                if (hostControllerHandle.ToInt64() != UsbApi.InvalidHandleValue)
                {
                    GetRootHubName(hostControllerHandle);

                    // TODO: Get the driver key name for the root hub.

                    IntPtr hubHandle = IntPtr.Zero;

                    try
                    {
                        // Now let's open the hub (based upon the hub name we got above).
                        hubHandle = KernelApi.CreateFile(DevicePath, UsbApi.GenericWrite, UsbApi.FileShareWrite, IntPtr.Zero, UsbApi.OpenExisting, 0, IntPtr.Zero);

                        if (hubHandle.ToInt64() != UsbApi.InvalidHandleValue)
                        {
                            GetUsbNodeInformation(hubHandle);

                            GetUsbHubInformation(hubHandle);

                            GetHubCapabilities(hubHandle);
                        }
                    }
                    finally
                    {
                        if (hubHandle != IntPtr.Zero)
                        {
                            KernelApi.CloseHandle(hubHandle);
                        }
                    }
                }
                else
                {
                    throw new UsbHubException("No port found!");
                }
            }
            finally
            {
                if (hostControllerHandle != IntPtr.Zero)
                {
                    KernelApi.CloseHandle(hostControllerHandle);
                }
            }

            for (uint index = 1; index <= PortCount; index++)
            {
                // Initialize a new port and save the port.
                try
                {
                    Devices.Add(DeviceFactory.BuildDevice(this, index, DevicePath));
                }
                catch (Exception e)
                {
                    CoreTraceSource.Source.TraceEvent(TraceEventType.Error, CoreTraceSource.UsbHubSourceId,
                                                      "Unhandled exception occurred: {0}", e);
                }
            }
        }
Example #13
0
        /// <summary>
        /// Builds the device.
        /// </summary>
        /// <param name="parent">The parent.</param>
        /// <param name="portCount">The port count.</param>
        /// <param name="devicePath">The device path.</param>
        /// <returns>The device.</returns>
        public static Device BuildDevice(Device parent, uint portCount, string devicePath)
        {
            Device device = null;

            // Open a handle to the Hub device
            IntPtr deviceHandle = KernelApi.CreateFile(devicePath, UsbApi.GenericWrite, UsbApi.FileShareWrite,
                                                       IntPtr.Zero,
                                                       UsbApi.OpenExisting, 0, IntPtr.Zero);

            try
            {
                if (deviceHandle.ToInt64() != UsbApi.InvalidHandleValue)
                {
                    if (GetNodeConnectionInformationEx(portCount, deviceHandle, out var nodeConnection))
                    {
                        if (nodeConnection.ConnectionStatus == UsbIoControl.UsbConnectionStatus.DeviceConnected)
                        {
                            GetUsbPortConnectorProperties(portCount, deviceHandle,
                                                          out var portConnectorProperties);

                            GetNodeConnectionInformationExV2(portCount, deviceHandle, out var nodeConnectionV2);

                            if (nodeConnection.DeviceDescriptor.bDeviceClass == UsbDesc.DeviceClassType.UsbHubDevice)
                            {
                                if (GetUsbNodeConnectionName(portCount, deviceHandle, out var connectionName))
                                {
                                    string name = @"\\?\" + connectionName.NodeName;

                                    device = new UsbHub(nodeConnection.DeviceDescriptor, name)
                                    {
                                        NodeConnectionInfo         = nodeConnection,
                                        NodeConnectionInfoV2       = nodeConnectionV2,
                                        UsbPortConnectorProperties = portConnectorProperties
                                    };
                                }
                            }
                            else
                            {
                                device = new UsbDevice(nodeConnection.DeviceDescriptor, portCount, devicePath)
                                {
                                    NodeConnectionInfo         = nodeConnection,
                                    NodeConnectionInfoV2       = nodeConnectionV2,
                                    UsbPortConnectorProperties = portConnectorProperties
                                };
                            }
                        }
                        else
                        {
                            device = new UsbDevice(null, portCount)
                            {
                                NodeConnectionInfo = nodeConnection
                            };
                        }
                    }
                }
            }
            finally
            {
                if (deviceHandle.ToInt64() != UsbApi.InvalidHandleValue)
                {
                    KernelApi.CloseHandle(deviceHandle);
                }
            }

            return(device);
        }
        private void Initalise(uint index)
        {
            IntPtr ptr = IntPtr.Zero;
            IntPtr deviceInfoHandle = IntPtr.Zero;

            try
            {
                ptr = Marshal.AllocHGlobal(UsbApi.MaxBufferSize);
                deviceInfoHandle = UsbApi.SetupDiGetClassDevs(ref _guid, 0, IntPtr.Zero,
                                                              UsbApi.DigcfPresent | UsbApi.DigcfDeviceinterface);

                // Create a device interface data structure
                UsbApi.SpDeviceInterfaceData deviceInterfaceData = new UsbApi.SpDeviceInterfaceData();
                deviceInterfaceData.CbSize = Marshal.SizeOf(deviceInterfaceData);

                // Start the enumeration.
                Boolean success =
                    UsbApi.SetupDiEnumDeviceInterfaces(deviceInfoHandle, IntPtr.Zero, ref _guid, (int)index,
                                                       ref deviceInterfaceData);
                if (success)
                {
                    // Build a DevInfo data structure.
                    UsbApi.SpDevinfoData deviceInfoData = new UsbApi.SpDevinfoData();
                    deviceInfoData.CbSize = Marshal.SizeOf(deviceInfoData);

                    // Build a device interface detail data structure.
                    UsbApi.SpDeviceInterfaceDetailData deviceInterfaceDetailData =
                        new UsbApi.SpDeviceInterfaceDetailData
                    {
                        CbSize = UIntPtr.Size == 8 ? 8 : (int)(4 + (uint)Marshal.SystemDefaultCharSize)
                    };

                    // Now we can get some more detailed informations.
                    int nRequiredSize = 0;
                    int nBytes        = UsbApi.MaxBufferSize;

                    if (UsbApi.SetupDiGetDeviceInterfaceDetail(deviceInfoHandle, ref deviceInterfaceData,
                                                               ref deviceInterfaceDetailData, nBytes, ref nRequiredSize, ref deviceInfoData))
                    {
                        DevicePath = deviceInterfaceDetailData.DevicePath;

                        ParseDevicePath(DevicePath);

                        // Get the device description and driver key name.
                        int requiredSize = 0;
                        int regType      = UsbApi.RegSz;

                        if (UsbApi.SetupDiGetDeviceRegistryProperty(deviceInfoHandle, ref deviceInfoData,
                                                                    (int)UsbApi.Spdrp.SpdrpDevicedesc,
                                                                    ref regType,
                                                                    ptr,
                                                                    UsbApi.MaxBufferSize, ref requiredSize))
                        {
                            DeviceDescription = Marshal.PtrToStringAuto(ptr);
                        }

                        if (UsbApi.SetupDiGetDeviceRegistryProperty(
                                deviceInfoHandle,
                                ref deviceInfoData,
                                (int)UsbApi.Spdrp.SpdrpDriver,
                                ref regType,
                                ptr,
                                UsbApi.MaxBufferSize,
                                ref requiredSize))
                        {
                            DriverKey = Marshal.PtrToStringAuto(ptr);
                        }
                    }

                    IntPtr hostControllerHandle = IntPtr.Zero;

                    try
                    {
                        hostControllerHandle = KernelApi.CreateFile(deviceInterfaceDetailData.DevicePath,
                                                                    UsbApi.GenericWrite,
                                                                    UsbApi.FileShareWrite, IntPtr.Zero,
                                                                    UsbApi.OpenExisting, 0, IntPtr.Zero);

                        if (deviceInfoHandle.ToInt64() != UsbApi.InvalidHandleValue)
                        {
                            GetHostControllerPowerMap(hostControllerHandle);

                            GetHostControllerInfo(hostControllerHandle);
                        }
                    }
                    finally
                    {
                        if (hostControllerHandle != IntPtr.Zero ||
                            deviceInfoHandle.ToInt64() != UsbApi.InvalidHandleValue)
                        {
                            KernelApi.CloseHandle(hostControllerHandle);
                        }
                    }

                    try
                    {
                        Devices.Add(new UsbHub(null, DevicePath));
                    }
                    catch (Exception ex)
                    {
                        CoreTraceSource.Source.TraceEvent(TraceEventType.Error, CoreTraceSource.UsbControllerSourceId,
                                                          "Unhandled exception occurred: {0}", ex);

                        throw new UsbControllerException("Unhandled exception occurred", ex);
                    }
                }
                else
                {
                    throw new UsbControllerException("No usb controller found!");
                }
            }
            finally
            {
                if (ptr != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(ptr);
                }

                if (deviceInfoHandle != IntPtr.Zero)
                {
                    UsbApi.SetupDiDestroyDeviceInfoList(deviceInfoHandle);
                }
            }
        }