Esempio n. 1
0
File: USB.cs Progetto: rambom/Source
        /// <summary>
        /// 获取外接Hub设备路径
        /// </summary>
        /// <param name="hParentHubDevice">上层Hub设备句柄</param>
        /// <param name="ConnectionIndex">连接索引号</param>
        /// <returns>外接Hub设备路径</returns>
        public static String GetExternalHubPath(IntPtr hParentHubDevice, Int32 ConnectionIndex)
        {
            if (hParentHubDevice == IntPtr.Zero || ConnectionIndex <= 0)
            {
                return(null);
            }

            USB_NODE_CONNECTION_DRIVERKEY_NAME Buffer = new USB_NODE_CONNECTION_DRIVERKEY_NAME();

            Buffer.ConnectionIndex = ConnectionIndex;
            Int32   nBytesReturned;
            Boolean Status = DeviceIoControl(hParentHubDevice,
                                             IOCTL_USB_GET_NODE_CONNECTION_NAME,
                                             ref Buffer,
                                             Marshal.SizeOf(Buffer),
                                             ref Buffer,
                                             Marshal.SizeOf(Buffer),
                                             out nBytesReturned,
                                             IntPtr.Zero);

            if (Status)
            {
                return(Buffer.DriverKeyName);
            }
            else
            {
                return(null);
            }
        }
Esempio n. 2
0
 internal static extern Boolean DeviceIoControl(
     IntPtr hFile,
     Int32 dwIoControlCode,
     ref USB_NODE_CONNECTION_DRIVERKEY_NAME lpInBuffer,
     Int32 nInBufferSize,
     ref USB_NODE_CONNECTION_DRIVERKEY_NAME lpOutBuffer,
     Int32 nOutBufferSize,
     out Int32 lpBytesReturned,
     IntPtr lpOverlapped
     );
Esempio n. 3
0
File: USB.cs Progetto: rambom/Source
        /// <summary>
        /// 获取外接Hub设备路径
        /// </summary>
        /// <param name="ParentDevicePath">上层Hub设备路径</param>
        /// <param name="ConnectionIndex">连接索引号</param>
        /// <returns>外接Hub设备路径</returns>
        public static String GetExternalHubPath(String ParentDevicePath, Int32 ConnectionIndex)
        {
            if (String.IsNullOrEmpty(ParentDevicePath))
            {
                return(null);
            }

            // 打开设备文件
            IntPtr hParentHubDevice = Kernel32.CreateFile(
                "\\\\.\\" + ParentDevicePath,
                NativeFileAccess.GENERIC_WRITE,
                NativeFileShare.FILE_SHARE_WRITE,
                IntPtr.Zero,
                NativeFileMode.OPEN_EXISTING,
                IntPtr.Zero,
                IntPtr.Zero);

            if (hParentHubDevice == Kernel32.INVALID_HANDLE_VALUE)
            {
                return(null);
            }

            USB_NODE_CONNECTION_DRIVERKEY_NAME Buffer = new USB_NODE_CONNECTION_DRIVERKEY_NAME();

            Buffer.ConnectionIndex = ConnectionIndex;
            Int32   nBytesReturned;
            Boolean Status = DeviceIoControl(hParentHubDevice,
                                             IOCTL_USB_GET_NODE_CONNECTION_NAME,
                                             ref Buffer,
                                             Marshal.SizeOf(Buffer),
                                             ref Buffer,
                                             Marshal.SizeOf(Buffer),
                                             out nBytesReturned,
                                             IntPtr.Zero);

            // 关闭设备文件
            Kernel32.CloseHandle(hParentHubDevice);

            if (Status)
            {
                return(Buffer.DriverKeyName);
            }
            else
            {
                return(null);
            }
        }
        public USBDevice GetDevice()
        {
            if (!this.PortIsDeviceConnected)
            {
                return(null);
            }
            USBDevice uSBDevice = new USBDevice();

            uSBDevice.DevicePortNumber    = this.PortPortNumber;
            uSBDevice.DeviceHubDevicePath = this.PortHubDevicePath;
            uSBDevice.DeviceDescriptor    = this.PortDeviceDescriptor;
            uSBDevice.DeviceVID           = this.PortDeviceDescriptor.idVendor;
            uSBDevice.DevicePID           = this.PortDeviceDescriptor.idProduct;
            IntPtr intPtr = Acer_USB_Library.CreateFile(this.PortHubDevicePath, 1073741824, 2, IntPtr.Zero, 3, 0, IntPtr.Zero);

            if (intPtr.ToInt32() != -1)
            {
                int    num  = 2048;
                string s    = new string('\0', 2048 / Marshal.SystemDefaultCharSize);
                int    num2 = default(int);
                if (this.PortDeviceDescriptor.iManufacturer > 0)
                {
                    USB_DESCRIPTOR_REQUEST structure = default(USB_DESCRIPTOR_REQUEST);
                    structure.ConnectionIndex     = this.PortPortNumber;
                    structure.SetupPacket.wValue  = (short)(768 + this.PortDeviceDescriptor.iManufacturer);
                    structure.SetupPacket.wLength = (short)(num - Marshal.SizeOf(structure));
                    structure.SetupPacket.wIndex  = 1033;
                    IntPtr intPtr2 = Marshal.StringToHGlobalAuto(s);
                    Marshal.StructureToPtr(structure, intPtr2, true);
                    if (Acer_USB_Library.DeviceIoControl(intPtr, 2229264, intPtr2, num, intPtr2, num, out num2, IntPtr.Zero))
                    {
                        USB_STRING_DESCRIPTOR uSB_STRING_DESCRIPTOR = (USB_STRING_DESCRIPTOR)Marshal.PtrToStructure(new IntPtr(intPtr2.ToInt32() + Marshal.SizeOf(structure)), typeof(USB_STRING_DESCRIPTOR));
                        uSBDevice.DeviceManufacturer = uSB_STRING_DESCRIPTOR.bString;
                    }
                    Marshal.FreeHGlobal(intPtr2);
                }
                if (this.PortDeviceDescriptor.iProduct > 0)
                {
                    USB_DESCRIPTOR_REQUEST structure2 = default(USB_DESCRIPTOR_REQUEST);
                    structure2.ConnectionIndex     = this.PortPortNumber;
                    structure2.SetupPacket.wValue  = (short)(768 + this.PortDeviceDescriptor.iProduct);
                    structure2.SetupPacket.wLength = (short)(num - Marshal.SizeOf(structure2));
                    structure2.SetupPacket.wIndex  = 1033;
                    IntPtr intPtr3 = Marshal.StringToHGlobalAuto(s);
                    Marshal.StructureToPtr(structure2, intPtr3, true);
                    if (Acer_USB_Library.DeviceIoControl(intPtr, 2229264, intPtr3, num, intPtr3, num, out num2, IntPtr.Zero))
                    {
                        USB_STRING_DESCRIPTOR uSB_STRING_DESCRIPTOR2 = (USB_STRING_DESCRIPTOR)Marshal.PtrToStructure(new IntPtr(intPtr3.ToInt32() + Marshal.SizeOf(structure2)), typeof(USB_STRING_DESCRIPTOR));
                        uSBDevice.DeviceProduct = uSB_STRING_DESCRIPTOR2.bString;
                    }
                    Marshal.FreeHGlobal(intPtr3);
                }
                if (this.PortDeviceDescriptor.iSerialNumber > 0)
                {
                    USB_DESCRIPTOR_REQUEST structure3 = default(USB_DESCRIPTOR_REQUEST);
                    structure3.ConnectionIndex     = this.PortPortNumber;
                    structure3.SetupPacket.wValue  = (short)(768 + this.PortDeviceDescriptor.iSerialNumber);
                    structure3.SetupPacket.wLength = (short)(num - Marshal.SizeOf(structure3));
                    structure3.SetupPacket.wIndex  = 1033;
                    IntPtr intPtr4 = Marshal.StringToHGlobalAuto(s);
                    Marshal.StructureToPtr(structure3, intPtr4, true);
                    if (Acer_USB_Library.DeviceIoControl(intPtr, 2229264, intPtr4, num, intPtr4, num, out num2, IntPtr.Zero))
                    {
                        USB_STRING_DESCRIPTOR uSB_STRING_DESCRIPTOR3 = (USB_STRING_DESCRIPTOR)Marshal.PtrToStructure(new IntPtr(intPtr4.ToInt32() + Marshal.SizeOf(structure3)), typeof(USB_STRING_DESCRIPTOR));
                        uSBDevice.DeviceSerialNumber = uSB_STRING_DESCRIPTOR3.bString;
                    }
                    Marshal.FreeHGlobal(intPtr4);
                }
                USB_NODE_CONNECTION_DRIVERKEY_NAME uSB_NODE_CONNECTION_DRIVERKEY_NAME = default(USB_NODE_CONNECTION_DRIVERKEY_NAME);
                uSB_NODE_CONNECTION_DRIVERKEY_NAME.ConnectionIndex = this.PortPortNumber;
                num = Marshal.SizeOf(uSB_NODE_CONNECTION_DRIVERKEY_NAME);
                IntPtr intPtr5 = Marshal.AllocHGlobal(num);
                Marshal.StructureToPtr(uSB_NODE_CONNECTION_DRIVERKEY_NAME, intPtr5, true);
                if (Acer_USB_Library.DeviceIoControl(intPtr, 2229280, intPtr5, num, intPtr5, num, out num2, IntPtr.Zero))
                {
                    uSB_NODE_CONNECTION_DRIVERKEY_NAME = (USB_NODE_CONNECTION_DRIVERKEY_NAME)Marshal.PtrToStructure(intPtr5, typeof(USB_NODE_CONNECTION_DRIVERKEY_NAME));
                    uSBDevice.DeviceDriverKey          = uSB_NODE_CONNECTION_DRIVERKEY_NAME.DriverKeyName;
                    uSBDevice.DeviceName       = Acer_USB_Library.GetDescriptionByKeyName(uSBDevice.DeviceDriverKey);
                    uSBDevice.DeviceInstanceID = Acer_USB_Library.GetInstanceIDByKeyName(uSBDevice.DeviceDriverKey);
                }
                Marshal.FreeHGlobal(intPtr5);
                Acer_USB_Library.CloseHandle(intPtr);
            }
            return(uSBDevice);
        }
Esempio n. 5
0
            // return a down stream external hub
            public USBDevice GetDevice()
            {
                if (!PortIsDeviceConnected)
                {
                    return null;
                }
                USBDevice Device = new USBDevice();

                // Copy over some values from the Port class
                // Ya know, I've given some thought about making Device a derived class...
                Device.DevicePortNumber = PortPortNumber;
                Device.DeviceHubDevicePath = PortHubDevicePath;
                Device.DeviceDescriptor = PortDeviceDescriptor;

                // Open a handle to the Hub device
                IntPtr h = CreateFile(PortHubDevicePath, GENERIC_WRITE, FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
                if (h.ToInt32() != INVALID_HANDLE_VALUE)
                {
                    int nBytesReturned;
                    int nBytes = BUFFER_SIZE;
                    // We use this to zero fill a buffer
                    string NullString = new string((char)0, BUFFER_SIZE / Marshal.SystemDefaultCharSize);

                    // The iManufacturer, iProduct and iSerialNumber entries in the
                    // Device Descriptor are really just indexes.  So, we have to
                    // request a String Descriptor to get the values for those strings.

                    if (PortDeviceDescriptor.iManufacturer > 0)
                    {
                        // build a request for string descriptor
                        USB_DESCRIPTOR_REQUEST Request = new USB_DESCRIPTOR_REQUEST();
                        Request.ConnectionIndex = PortPortNumber;
                        Request.SetupPacket.wValue = (short)((USB_STRING_DESCRIPTOR_TYPE << 8) + PortDeviceDescriptor.iManufacturer);
                        Request.SetupPacket.wLength = (short)(nBytes - Marshal.SizeOf(Request));
                        Request.SetupPacket.wIndex = 0x409; // Language Code
                        // Geez, I wish C# had a Marshal.MemSet() method
                        IntPtr ptrRequest = Marshal.StringToHGlobalAuto(NullString);
                        Marshal.StructureToPtr(Request, ptrRequest, true);

                        // Use an IOCTL call to request the String Descriptor
                        if (DeviceIoControl(h, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, ptrRequest, nBytes, ptrRequest, nBytes, out nBytesReturned, IntPtr.Zero))
                        {
                            // The location of the string descriptor is immediately after
                            // the Request structure.  Because this location is not "covered"
                            // by the structure allocation, we're forced to zero out this
                            // chunk of memory by using the StringToHGlobalAuto() hack above
                            IntPtr ptrStringDesc = new IntPtr(ptrRequest.ToInt32() + Marshal.SizeOf(Request));
                            USB_STRING_DESCRIPTOR StringDesc = (USB_STRING_DESCRIPTOR)Marshal.PtrToStructure(ptrStringDesc, typeof(USB_STRING_DESCRIPTOR));
                            Device.DeviceManufacturer = StringDesc.bString;
                        }
                        Marshal.FreeHGlobal(ptrRequest);
                    }
                    if (PortDeviceDescriptor.iProduct > 0)
                    {
                        // build a request for string descriptor
                        USB_DESCRIPTOR_REQUEST Request = new USB_DESCRIPTOR_REQUEST();
                        Request.ConnectionIndex = PortPortNumber;
                        Request.SetupPacket.wValue = (short)((USB_STRING_DESCRIPTOR_TYPE << 8) + PortDeviceDescriptor.iProduct);
                        Request.SetupPacket.wLength = (short)(nBytes - Marshal.SizeOf(Request));
                        Request.SetupPacket.wIndex = 0x409; // Language Code
                        // Geez, I wish C# had a Marshal.MemSet() method
                        IntPtr ptrRequest = Marshal.StringToHGlobalAuto(NullString);
                        Marshal.StructureToPtr(Request, ptrRequest, true);

                        // Use an IOCTL call to request the String Descriptor
                        if (DeviceIoControl(h, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, ptrRequest, nBytes, ptrRequest, nBytes, out nBytesReturned, IntPtr.Zero))
                        {
                            // the location of the string descriptor is immediately after the Request structure
                            IntPtr ptrStringDesc = new IntPtr(ptrRequest.ToInt32() + Marshal.SizeOf(Request));
                            USB_STRING_DESCRIPTOR StringDesc = (USB_STRING_DESCRIPTOR)Marshal.PtrToStructure(ptrStringDesc, typeof(USB_STRING_DESCRIPTOR));
                            Device.DeviceProduct = StringDesc.bString;
                        }
                        Marshal.FreeHGlobal(ptrRequest);
                    }
                    if (PortDeviceDescriptor.iSerialNumber > 0)
                    {
                        // build a request for string descriptor
                        USB_DESCRIPTOR_REQUEST Request = new USB_DESCRIPTOR_REQUEST();
                        Request.ConnectionIndex = PortPortNumber;
                        Request.SetupPacket.wValue = (short)((USB_STRING_DESCRIPTOR_TYPE << 8) + PortDeviceDescriptor.iSerialNumber);
                        Request.SetupPacket.wLength = (short)(nBytes - Marshal.SizeOf(Request));
                        Request.SetupPacket.wIndex = 0x409; // Language Code
                        // Geez, I wish C# had a Marshal.MemSet() method
                        IntPtr ptrRequest = Marshal.StringToHGlobalAuto(NullString);
                        Marshal.StructureToPtr(Request, ptrRequest, true);

                        // Use an IOCTL call to request the String Descriptor
                        if (DeviceIoControl(h, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, ptrRequest, nBytes, ptrRequest, nBytes, out nBytesReturned, IntPtr.Zero))
                        {
                            // the location of the string descriptor is immediately after the Request structure
                            IntPtr ptrStringDesc = new IntPtr(ptrRequest.ToInt32() + Marshal.SizeOf(Request));
                            USB_STRING_DESCRIPTOR StringDesc = (USB_STRING_DESCRIPTOR)Marshal.PtrToStructure(ptrStringDesc, typeof(USB_STRING_DESCRIPTOR));
                            Device.DeviceSerialNumber = StringDesc.bString;
                        }
                        Marshal.FreeHGlobal(ptrRequest);
                    }

                    // Get the Driver Key Name (usefull in locating a device)
                    USB_NODE_CONNECTION_DRIVERKEY_NAME DriverKey = new USB_NODE_CONNECTION_DRIVERKEY_NAME();
                    DriverKey.ConnectionIndex = PortPortNumber;
                    nBytes = Marshal.SizeOf(DriverKey);
                    IntPtr ptrDriverKey = Marshal.AllocHGlobal(nBytes);
                    Marshal.StructureToPtr(DriverKey, ptrDriverKey, true);

                    // Use an IOCTL call to request the Driver Key Name
                    if (DeviceIoControl(h, IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME, ptrDriverKey, nBytes, ptrDriverKey, nBytes, out nBytesReturned, IntPtr.Zero))
                    {
                        DriverKey = (USB_NODE_CONNECTION_DRIVERKEY_NAME)Marshal.PtrToStructure(ptrDriverKey, typeof(USB_NODE_CONNECTION_DRIVERKEY_NAME));
                        Device.DeviceDriverKey = DriverKey.DriverKeyName;

                        // use the DriverKeyName to get the Device Description and Instance ID
                        Device.DeviceName = GetDescriptionByKeyName(Device.DeviceDriverKey);
                        Device.DeviceInstanceID = GetInstanceIDByKeyName(Device.DeviceDriverKey);
                    }
                    Marshal.FreeHGlobal(ptrDriverKey);
                    CloseHandle(h);
                }
                return Device;
            }
Esempio n. 6
0
 internal static extern Boolean DeviceIoControl(
     IntPtr hFile,
     Int32 dwIoControlCode,
     ref USB_NODE_CONNECTION_DRIVERKEY_NAME lpInBuffer,
     Int32 nInBufferSize,
     ref USB_NODE_CONNECTION_DRIVERKEY_NAME lpOutBuffer,
     Int32 nOutBufferSize,
     out Int32 lpBytesReturned,
     IntPtr lpOverlapped
     );
Esempio n. 7
0
        /// <summary>
        /// 获取外接Hub设备路径
        /// </summary>
        /// <param name="hParentHubDevice">上层Hub设备句柄</param>
        /// <param name="ConnectionIndex">连接索引号</param>
        /// <returns>外接Hub设备路径</returns>
        public static String GetExternalHubPath(IntPtr hParentHubDevice, Int32 ConnectionIndex)
        {
            if (hParentHubDevice == IntPtr.Zero || ConnectionIndex <= 0) return null;

            USB_NODE_CONNECTION_DRIVERKEY_NAME Buffer = new USB_NODE_CONNECTION_DRIVERKEY_NAME();
            Buffer.ConnectionIndex = ConnectionIndex;
            Int32 nBytesReturned;
            Boolean Status = DeviceIoControl(hParentHubDevice,
                    IOCTL_USB_GET_NODE_CONNECTION_NAME,
                    ref Buffer,
                    Marshal.SizeOf(Buffer),
                    ref Buffer,
                    Marshal.SizeOf(Buffer),
                    out nBytesReturned,
                    IntPtr.Zero);

            if (Status)
                return Buffer.DriverKeyName;
            else
                return null;
        }
Esempio n. 8
0
        /// <summary>
        /// 获取外接Hub设备路径
        /// </summary>
        /// <param name="ParentDevicePath">上层Hub设备路径</param>
        /// <param name="ConnectionIndex">连接索引号</param>
        /// <returns>外接Hub设备路径</returns>
        public static String GetExternalHubPath(String ParentDevicePath, Int32 ConnectionIndex)
        {
            if (String.IsNullOrEmpty(ParentDevicePath)) return null;

            // 打开设备文件
            IntPtr hParentHubDevice = Kernel32.CreateFile(
                "\\\\.\\" + ParentDevicePath,
                NativeFileAccess.GENERIC_WRITE,
                NativeFileShare.FILE_SHARE_WRITE,
                IntPtr.Zero,
                NativeFileMode.OPEN_EXISTING,
                IntPtr.Zero,
                IntPtr.Zero);
            if (hParentHubDevice == Kernel32.INVALID_HANDLE_VALUE) return null;

            USB_NODE_CONNECTION_DRIVERKEY_NAME Buffer = new USB_NODE_CONNECTION_DRIVERKEY_NAME();
            Buffer.ConnectionIndex = ConnectionIndex;
            Int32 nBytesReturned;
            Boolean Status = DeviceIoControl(hParentHubDevice,
                    IOCTL_USB_GET_NODE_CONNECTION_NAME,
                    ref Buffer,
                    Marshal.SizeOf(Buffer),
                    ref Buffer,
                    Marshal.SizeOf(Buffer),
                    out nBytesReturned,
                    IntPtr.Zero);

            // 关闭设备文件
            Kernel32.CloseHandle(hParentHubDevice);

            if (Status)
                return Buffer.DriverKeyName;
            else
                return null;
        }
Esempio n. 9
0
            // return a down stream external hub
            public USBDevice GetDevice()
            {
                if (!PortIsDeviceConnected)
                {
                    return(null);
                }

                // Copy over some values from the Port class
                // Ya know, I've given some thought about making Device a derived class...
                var Device = new USBDevice
                {
                    DevicePortNumber    = PortPortNumber,
                    DeviceHubDevicePath = PortHubDevicePath,
                    DeviceDescriptor    = PortDeviceDescriptor
                };

                // Open a handle to the Hub device
                var h = CreateFile(PortHubDevicePath, GENERIC_WRITE, FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);

                if (h.ToInt32() == INVALID_HANDLE_VALUE)
                {
                    return(Device);
                }

                int nBytesReturned;
                var nBytes = BUFFER_SIZE;
                // We use this to zero fill a buffer
                var NullString = new string((char)0, BUFFER_SIZE / Marshal.SystemDefaultCharSize);

                // The iManufacturer, iProduct and iSerialNumber entries in the
                // Device Descriptor are really just indexes.  So, we have to
                // request a String Descriptor to get the values for those strings.

                if (PortDeviceDescriptor.iManufacturer > 0)
                {
                    // build a request for string descriptor
                    var Request = new USB_DESCRIPTOR_REQUEST
                    {
                        ConnectionIndex = PortPortNumber,
                        SetupPacket     =
                        {
                            wValue =
                                (short)((USB_STRING_DESCRIPTOR_TYPE << 8) + PortDeviceDescriptor.iManufacturer)
                        }
                    };
                    Request.SetupPacket.wLength = (short)(nBytes - Marshal.SizeOf(Request));
                    Request.SetupPacket.wIndex  = 0x409; // Language Code
                    // Geez, I wish C# had a Marshal.MemSet() method
                    var ptrRequest = Marshal.StringToHGlobalAuto(NullString);
                    Marshal.StructureToPtr(Request, ptrRequest, true);

                    // Use an IOCTL call to request the String Descriptor
                    if (DeviceIoControl(h, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, ptrRequest, nBytes, ptrRequest, nBytes, out nBytesReturned, IntPtr.Zero))
                    {
                        // The location of the string descriptor is immediately after
                        // the Request structure.  Because this location is not "covered"
                        // by the structure allocation, we're forced to zero out this
                        // chunk of memory by using the StringToHGlobalAuto() hack above
                        var ptrStringDesc = new IntPtr(ptrRequest.ToInt32() + Marshal.SizeOf(Request));
                        var StringDesc    = (USB_STRING_DESCRIPTOR)Marshal.PtrToStructure(ptrStringDesc, typeof(USB_STRING_DESCRIPTOR));
                        Device.DeviceManufacturer = StringDesc.bString;
                    }
                    Marshal.FreeHGlobal(ptrRequest);
                }
                if (PortDeviceDescriptor.iProduct > 0)
                {
                    // build a request for string descriptor
                    var Request = new USB_DESCRIPTOR_REQUEST
                    {
                        ConnectionIndex = PortPortNumber,
                        SetupPacket     =
                        {
                            wValue = (short)((USB_STRING_DESCRIPTOR_TYPE << 8) + PortDeviceDescriptor.iProduct)
                        }
                    };
                    Request.SetupPacket.wLength = (short)(nBytes - Marshal.SizeOf(Request));
                    Request.SetupPacket.wIndex  = 0x409; // Language Code
                    // Geez, I wish C# had a Marshal.MemSet() method
                    var ptrRequest = Marshal.StringToHGlobalAuto(NullString);
                    Marshal.StructureToPtr(Request, ptrRequest, true);

                    // Use an IOCTL call to request the String Descriptor
                    if (DeviceIoControl(h, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, ptrRequest, nBytes, ptrRequest, nBytes, out nBytesReturned, IntPtr.Zero))
                    {
                        // the location of the string descriptor is immediately after the Request structure
                        var ptrStringDesc = new IntPtr(ptrRequest.ToInt32() + Marshal.SizeOf(Request));
                        var StringDesc    = (USB_STRING_DESCRIPTOR)Marshal.PtrToStructure(ptrStringDesc, typeof(USB_STRING_DESCRIPTOR));
                        Device.DeviceProduct = StringDesc.bString;
                    }
                    Marshal.FreeHGlobal(ptrRequest);
                }
                if (PortDeviceDescriptor.iSerialNumber > 0)
                {
                    // build a request for string descriptor
                    var Request = new USB_DESCRIPTOR_REQUEST
                    {
                        ConnectionIndex = PortPortNumber,
                        SetupPacket     =
                        {
                            wValue =
                                (short)((USB_STRING_DESCRIPTOR_TYPE << 8) + PortDeviceDescriptor.iSerialNumber)
                        }
                    };
                    Request.SetupPacket.wLength = (short)(nBytes - Marshal.SizeOf(Request));
                    Request.SetupPacket.wIndex  = 0x409; // Language Code
                    // Geez, I wish C# had a Marshal.MemSet() method
                    var ptrRequest = Marshal.StringToHGlobalAuto(NullString);
                    Marshal.StructureToPtr(Request, ptrRequest, true);

                    // Use an IOCTL call to request the String Descriptor
                    if (DeviceIoControl(h, IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, ptrRequest, nBytes, ptrRequest, nBytes, out nBytesReturned, IntPtr.Zero))
                    {
                        // the location of the string descriptor is immediately after the Request structure
                        var ptrStringDesc = new IntPtr(ptrRequest.ToInt32() + Marshal.SizeOf(Request));
                        var StringDesc    = (USB_STRING_DESCRIPTOR)Marshal.PtrToStructure(ptrStringDesc, typeof(USB_STRING_DESCRIPTOR));
                        Device.DeviceSerialNumber = StringDesc.bString;
                    }
                    Marshal.FreeHGlobal(ptrRequest);
                }

                // Get the Driver Key Name (usefull in locating a device)
                var DriverKey = new USB_NODE_CONNECTION_DRIVERKEY_NAME {
                    ConnectionIndex = PortPortNumber
                };

                nBytes = Marshal.SizeOf(DriverKey);
                var ptrDriverKey = Marshal.AllocHGlobal(nBytes);

                Marshal.StructureToPtr(DriverKey, ptrDriverKey, true);

                // Use an IOCTL call to request the Driver Key Name
                if (DeviceIoControl(h, IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME, ptrDriverKey, nBytes, ptrDriverKey, nBytes, out nBytesReturned, IntPtr.Zero))
                {
                    DriverKey = (USB_NODE_CONNECTION_DRIVERKEY_NAME)Marshal.PtrToStructure(ptrDriverKey, typeof(USB_NODE_CONNECTION_DRIVERKEY_NAME));
                    Device.DeviceDriverKey = DriverKey.DriverKeyName;

                    // use the DriverKeyName to get the Device Description and Instance ID
                    Device.DeviceName       = GetDescriptionByKeyName(Device.DeviceDriverKey);
                    Device.DeviceInstanceID = GetInstanceIDByKeyName(Device.DeviceDriverKey);
                }
                Marshal.FreeHGlobal(ptrDriverKey);
                CloseHandle(h);
                return(Device);
            }