C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
11,480 questions
This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
Hello,
I am a developer working with IOCTL calls in Windows, and I am trying to understand the correct way to access IOCTL_USB_GET_NODE_CONNECTION_SUPERSPEEDPLUS_INFORMATION.
Is there a difference between using kernel32.dll
and kernelbase.dll
when making this call? What is the recommended module to use when calling DeviceIoControl
to issue this IOCTL?
I did this test (test in a Button Click) and I get 0 for speeds, but it seems normal as I'm on Windows 10 :
public partial class Form1 : Form
{
[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern IntPtr CreateFile(string lpFileName, uint dwDesiredAccess, int dwShareMode, IntPtr lpSecurityAttributes, int dwCreationDisposition, int dwFlagsAndAttributes, IntPtr hTemplateFile);
public IntPtr INVALID_HANDLE_VALUE = (IntPtr)(-1);
[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool CloseHandle(IntPtr hObject);
[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool DeviceIoControl(IntPtr hDevice, uint dwIoControlCode, IntPtr lpInBuffer, uint nInBufferSize, IntPtr lpOutBuffer, int nOutBufferSize, out int lpBytesReturned, IntPtr lpOverlapped);
internal static uint CTL_CODE(uint deviceType, uint function, uint method, uint access)
{
return (deviceType << 16) | (access << 14) | (function << 2) | method;
}
public static uint FILE_DEVICE_UNKNOWN = 0x22;
public static uint FILE_DEVICE_USB = FILE_DEVICE_UNKNOWN;
public static uint USB_GET_NODE_INFORMATION = 258;
public static uint USB_GET_NODE_CONNECTION_SUPERSPEEDPLUS_INFORMATION = 289;
public static uint METHOD_BUFFERED = 0;
public static uint METHOD_IN_DIRECT = 1;
public static uint METHOD_OUT_DIRECT = 2;
public static uint METHOD_NEITHER = 3;
public static uint FILE_ANY_ACCESS = 0;
public static uint FILE_SPECIAL_ACCESS = (FILE_ANY_ACCESS);
public static uint FILE_READ_ACCESS = ( 0x0001 ); // file & pipe
public static uint FILE_WRITE_ACCESS = ( 0x0002 ); // file & pipe
public static uint IOCTL_USB_GET_NODE_INFORMATION => (uint)CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_INFORMATION, 0, 0);
public static uint IOCTL_USB_GET_NODE_CONNECTION_SUPERSPEEDPLUS_INFORMATION =>
CTL_CODE(FILE_DEVICE_USB, USB_GET_NODE_CONNECTION_SUPERSPEEDPLUS_INFORMATION, METHOD_BUFFERED, FILE_ANY_ACCESS);
[DllImport("Setupapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern IntPtr SetupDiGetClassDevs(ref Guid ClassGuid, IntPtr Enumerator, IntPtr hWndParent, int Flags);
[DllImport("Setupapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool SetupDiGetDeviceInterfaceDetail(IntPtr DeviceInfoSet, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData, ref SP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData, int DeviceInterfaceDetailDataSize, ref int RequiredSize, ref SP_DEVINFO_DATA DeviceInfoData);
[DllImport("Setupapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool SetupDiGetDeviceInterfaceDetail(IntPtr DeviceInfoSet, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData, IntPtr Ptr, int DeviceInterfaceDetailDataSize, ref int RequiredSize, IntPtr PtrInfo);
[DllImport("Setupapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool SetupDiEnumDeviceInterfaces(IntPtr DeviceInfoSet, IntPtr DeviceInfoData, ref Guid InterfaceClassGuid, int MemberIndex, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData);
[DllImport("Setupapi.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern bool SetupDiGetDeviceRegistryProperty(IntPtr DeviceInfoSet, ref SP_DEVINFO_DATA DeviceInfoData, uint Property,
uint PropertyRegDataType, StringBuilder PropertyBuffer, uint PropertyBufferSize, IntPtr RequiredSize);
#if WIN64
public const int PACK_SIZE = 8;
#else
public const int PACK_SIZE = 1;
#endif
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = PACK_SIZE)]
public struct SP_DEVINFO_DATA
{
public int cbSize;
public Guid ClassGuid;
public int DevInst;
public IntPtr Reserved;
}
[StructLayout(LayoutKind.Sequential)]
public struct SP_DEVICE_INTERFACE_DATA
{
public int cbSize;
public Guid InterfaceClassGuid;
public int Flags;
public IntPtr Reserved;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct SP_DEVICE_INTERFACE_DETAIL_DATA
{
public int cbSize;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)]
public string DevicePath;
}
[DllImport("Setupapi.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
public static extern bool SetupDiDestroyDeviceInfoList(IntPtr DeviceInfoSet);
public const int DIGCF_PRESENT = 0x00000002;
public const int DIGCF_DEVICEINTERFACE = 0x00000010;
public const int ERROR_INSUFFICIENT_BUFFER = 122;
public const int MAX_PATH = 260;
public const int SPDRP_DEVICEDESC = (0x00000000); // DeviceDesc (R/W)
public const int SPDRP_FRIENDLYNAME = (0x0000000C); // FriendlyName (R/W)
public const int SPDRP_LOCATION_INFORMATION = (0x0000000D); // LocationInformation (R/W)
Guid GUID_DEVINTERFACE_USB_HUB = new Guid("f18a0e88-c30c-11d0-8815-00a0c906bed8");
public enum USB_HUB_NODE
{
UsbHub,
UsbMIParent
}
[StructLayout(LayoutKind.Sequential)]
public struct USB_HUB_DESCRIPTOR
{
public byte bDescriptorLength;
public byte bDescriptorType;
public byte bNumberOfPorts;
public short wHubCharacteristics;
public byte bPowerOnToPowerGood;
public byte bHubControlCurrent;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
public byte[] DeviceRemovable;
}
[StructLayout(LayoutKind.Sequential)]
public struct USB_HUB_INFORMATION
{
public USB_HUB_DESCRIPTOR HubDescriptor;
[MarshalAs(UnmanagedType.Bool)]
public bool HubIsBusPowered;
}
[StructLayout(LayoutKind.Sequential)]
public struct USB_MI_PARENT_INFORMATION
{
public int NumberOfInterfaces;
}
[StructLayout(LayoutKind.Explicit)]
public struct USB_NODE_INFORMATION
{
[FieldOffset(0)]
public USB_HUB_NODE NodeType;
[FieldOffset(4)]
public USB_HUB_INFORMATION HubInformation;
[FieldOffset(4)]
public USB_MI_PARENT_INFORMATION MiParentInformation;
}
[StructLayout(LayoutKind.Sequential)]
public struct USB_NODE_CONNECTION_SUPERSPEEDPLUS_INFORMATION
{
public uint ConnectionIndex;
public uint Length;
public USB_DEVICE_CAPABILITY_SUPERSPEEDPLUS_SPEED RxSuperSpeedPlus;
public uint RxLaneCount;
public USB_DEVICE_CAPABILITY_SUPERSPEEDPLUS_SPEED TxSuperSpeedPlus;
public uint TxLaneCount;
}
[StructLayout(LayoutKind.Sequential)]
public struct USB_DEVICE_CAPABILITY_SUPERSPEEDPLUS_SPEED
{
public uint Speed;
}
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Guid guid = GUID_DEVINTERFACE_USB_HUB;
IntPtr hDeviceInfoSet = SetupDiGetClassDevs(ref guid, IntPtr.Zero, IntPtr.Zero, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
if (hDeviceInfoSet != IntPtr.Zero)
{
var did = new SP_DEVICE_INTERFACE_DATA() { cbSize = Marshal.SizeOf(typeof(SP_DEVICE_INTERFACE_DATA)) };
for (var nIndex = 0; SetupDiEnumDeviceInterfaces(hDeviceInfoSet, IntPtr.Zero, ref guid, nIndex, ref did); nIndex++)
{
int dwBytes = 0;
bool bRet = SetupDiGetDeviceInterfaceDetail(hDeviceInfoSet, ref did, IntPtr.Zero, 0, ref dwBytes, IntPtr.Zero);
if (!bRet && Marshal.GetLastWin32Error() == ERROR_INSUFFICIENT_BUFFER)
{
SP_DEVICE_INTERFACE_DETAIL_DATA didd = new SP_DEVICE_INTERFACE_DETAIL_DATA();
didd.cbSize = IntPtr.Size == 8 ? 8 : 6;
SP_DEVINFO_DATA dd = new SP_DEVINFO_DATA();
dd.cbSize = Marshal.SizeOf(dd);
bRet = SetupDiGetDeviceInterfaceDetail(hDeviceInfoSet, ref did, ref didd, dwBytes, ref dwBytes, ref dd);
if (bRet)
{
StringBuilder sbDeviceName = new StringBuilder(260);
bRet = SetupDiGetDeviceRegistryProperty(hDeviceInfoSet, ref dd, SPDRP_FRIENDLYNAME, 0, sbDeviceName, (uint)sbDeviceName.Capacity, IntPtr.Zero);
if (bRet)
{
System.Diagnostics.Debug.WriteLine($"Device Name : {sbDeviceName.ToString()}");
}
else
{
bRet = SetupDiGetDeviceRegistryProperty(hDeviceInfoSet, ref dd, SPDRP_DEVICEDESC, 0, sbDeviceName, (uint)sbDeviceName.Capacity, IntPtr.Zero);
if (bRet)
{
System.Diagnostics.Debug.WriteLine($"Device Name (Description) : {sbDeviceName.ToString()}");
}
}
string sDevicePath = null;
sDevicePath = didd.DevicePath;
System.Diagnostics.Debug.WriteLine($"\tDevice Path : {sDevicePath}");
IntPtr hHub = CreateFile(sDevicePath, (uint)FileAccess.ReadWrite, (int)FileShare.ReadWrite, IntPtr.Zero, (int)FileMode.Open, 0, IntPtr.Zero);
if (hHub != INVALID_HANDLE_VALUE)
{
USB_NODE_INFORMATION nodeInfo = new USB_NODE_INFORMATION();
nodeInfo.NodeType = USB_HUB_NODE.UsbHub;
int nNodeInfoSize = Marshal.SizeOf(typeof(USB_NODE_INFORMATION));
IntPtr nodeInfoPtr = Marshal.AllocHGlobal(nNodeInfoSize);
Marshal.StructureToPtr(nodeInfo, nodeInfoPtr, false);
int nBytesReturned = 0;
bool bResult = DeviceIoControl(hHub,
IOCTL_USB_GET_NODE_INFORMATION,
nodeInfoPtr,
(uint)nNodeInfoSize,
nodeInfoPtr,
nNodeInfoSize,
out nBytesReturned,
IntPtr.Zero);
if (bResult)
{
nodeInfo = Marshal.PtrToStructure<USB_NODE_INFORMATION>(nodeInfoPtr);
for (uint port = 1; port <= nodeInfo.HubInformation.HubDescriptor.bNumberOfPorts; port++)
{
USB_NODE_CONNECTION_SUPERSPEEDPLUS_INFORMATION ssInfo = new USB_NODE_CONNECTION_SUPERSPEEDPLUS_INFORMATION();
ssInfo.ConnectionIndex = port;
int nSSSize = Marshal.SizeOf(ssInfo);
IntPtr ssPtr = Marshal.AllocHGlobal(nSSSize);
Marshal.StructureToPtr(ssInfo, ssPtr, false);
if (DeviceIoControl(hHub, IOCTL_USB_GET_NODE_CONNECTION_SUPERSPEEDPLUS_INFORMATION, ssPtr, (uint)nSSSize, ssPtr, nSSSize, out nBytesReturned, IntPtr.Zero))
{
ssInfo = Marshal.PtrToStructure<USB_NODE_CONNECTION_SUPERSPEEDPLUS_INFORMATION>(ssPtr);
System.Diagnostics.Debug.WriteLine($"\tPort {port}: Rx={ssInfo.RxSuperSpeedPlus.Speed}, Tx={ssInfo.TxSuperSpeedPlus.Speed}");
}
Marshal.FreeHGlobal(ssPtr);
}
}
Marshal.FreeHGlobal(nodeInfoPtr);
CloseHandle(hHub);
}
}
}
}
SetupDiDestroyDeviceInfoList(hDeviceInfoSet);
}
}
}