DeviceIOControl Problem

Experts,
     Can someone please help me figure out why this code isn't working? I am getting two different error messages depending on how I change the parameters, but either way it doesn't work.

private string GetDriverKeyName(IntPtr hHubDevice, int connectionIndex)
            {
                // pointers
                IntPtr ptrDriverKey;

                // integers
                int nBytesDx = 0;
                int nBytesReturnedDx = 0;

                // strings
                string DeviceDriverKey = null;

                try
                {
                    USB_NODE_CONNECTION_DRIVERKEY_NAME driverKeyName = new USB_NODE_CONNECTION_DRIVERKEY_NAME();
                    driverKeyName.ConnectionIndex = connectionIndex;
                    nBytesDx = Marshal.SizeOf(driverKeyName);
                    ptrDriverKey = Marshal.AllocHGlobal(nBytesDx);
                    Marshal.StructureToPtr(driverKeyName, ptrDriverKey, true);

                    if (DeviceIoControl(hHubDevice, USB_IOCTL_CODES.IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME, ptrDriverKey, Marshal.SizeOf(ptrDriverKey), ptrDriverKey, Marshal.SizeOf(ptrDriverKey), out nBytesReturnedDx, IntPtr.Zero))
                    {
                        nBytesDx = driverKeyName.ActualLength;

                        if (DeviceIoControl(hHubDevice, USB_IOCTL_CODES.IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME, ptrDriverKey, nBytesDx, ptrDriverKey, nBytesDx, out nBytesReturnedDx, IntPtr.Zero))
                        {
                            driverKeyName = (USB_NODE_CONNECTION_DRIVERKEY_NAME)Marshal.PtrToStructure(ptrDriverKey, typeof(USB_NODE_CONNECTION_DRIVERKEY_NAME));
                            DeviceDriverKey = driverKeyName.DriverKeyName;
                        }
                    }
                    else
                    {
                        throw new Win32Exception(Marshal.GetLastWin32Error());
                    }

                    Marshal.FreeHGlobal(ptrDriverKey);
                    CloseHandle(hHubDevice);

                    return DeviceDriverKey;
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.ToString());
                    return null;
                }
            }

I either get a "parameter passed is is too small for system call" or "invalid parameter"...  any help would be greatly appreciated!!!
YeavisAsked:
Who is Participating?
 
Computer101Commented:
PAQed with points refunded (500)

Computer101
EE Admin
0
 
Bob LearnedCommented:
What version of .NET do you have?  If you have 2005, is it SP1?  Where are you getting the exception?

Bob
0
 
YeavisAuthor Commented:
Yes, I am running 2005 Professional SP1. I am getting the exceptions at this line...

if (DeviceIoControl(hHubDevice, USB_IOCTL_CODES.IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME, ptrDriverKey, nBytesDx, ptrDriverKey, nBytesDx, out nBytesReturnedDx, IntPtr.Zero))
0
Cloud Class® Course: CompTIA Healthcare IT Tech

This course will help prep you to earn the CompTIA Healthcare IT Technician certification showing that you have the knowledge and skills needed to succeed in installing, managing, and troubleshooting IT systems in medical and clinical settings.

 
Bob LearnedCommented:
1) I am curious what this code is attempting to achieve.

2) What does the signature for DeviceIoControl look like?

3) Does it look anything like this?

[DllImport("Kernel32.dll", SetLastError = false, CharSet = CharSet.Auto)]
    public static extern bool DeviceIoControl(
        Microsoft.Win32.SafeHandles.SafeFileHandle hDevice,
        EIOControlCode IoControlCode,
        [MarshalAs(UnmanagedType.AsAny)]
        [In] object InBuffer,
        uint nInBufferSize,
        [MarshalAs(UnmanagedType.AsAny)]
        [out] object OutBuffer,
        uint nOutBufferSize,
        ref uint pBytesReturned,
        [In] ref System.Threading.NativeOverlapped Overlapped
    );

Bob
0
 
YeavisAuthor Commented:
This code is just a snippet from the overall program. What I'm doing is enumerating all USB root hubs, and then this code is supposed to return a driverkeyname that I can match up with my WMI information to know what USB device is located in what USB port. (sorry, confusing!!)

[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool DeviceIoControl(IntPtr hDevice, USB_IOCTL_CODES dwIoControlCode, IntPtr lpInBuffer, int nInBufferSize, IntPtr lpOutBuffer, int nOutBufferSize, out int lpBytesReturned, IntPtr lpOverlapped);

Your help is greately appreciated!!
0
 
Bob LearnedCommented:
I have been working on this same thing, and here is what I came up with:
0
 
Bob LearnedCommented:
// Source:
// http://www.codeproject.com/useritems/usbeject.asp

using System;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.Text;
using System.Collections.Generic;

[Flags]
public enum DeviceCapabilities
{
    Unknown = 0x00000000,
    // matches cfmgr32.h CM_DEVCAP_* definitions

    LockSupported = 0x00000001,
    EjectSupported = 0x00000002,
    Removable = 0x00000004,
    DockDevice = 0x00000008,
    UniqueId = 0x00000010,
    SilentInstall = 0x00000020,
    RawDeviceOk = 0x00000040,
    SurpriseRemovalOk = 0x00000080,
    HardwareDisabled = 0x00000100,
    NonDynamic = 0x00000200,
}

public class UsbDevices
{
    public static List<Device> EnumerateUsbDevices()
    {
        VolumeDeviceClass volumeDeviceClass = new VolumeDeviceClass();
        List<Device> list = new List<Device>();
        foreach (Device device in volumeDeviceClass.Devices)
        {
            if (device.IsUsb)
                list.Add(device);
        }
        return list;
    }
}

/// <summary>
/// A generic base class for physical devices.
/// </summary>
[TypeConverter(typeof(ExpandableObjectConverter))]
public class Device : IComparable
{
    private string _path;
    private DeviceClass _deviceClass;
    private string _description;
    private string _class;
    private string _classGuid;
    private Device _parent;
    private int _index;
    private DeviceCapabilities _capabilities = DeviceCapabilities.Unknown;
    private List<Device> _removableDevices;
    private string _friendlyName;
    private Native.SP_DEVINFO_DATA _deviceInfoData;

    internal Device(DeviceClass deviceClass, Native.SP_DEVINFO_DATA deviceInfoData, string path, int index)
    {
        if (deviceClass == null)
            throw new ArgumentNullException("deviceClass");

        if (deviceInfoData == null)
            throw new ArgumentNullException("deviceInfoData");

        _deviceClass = deviceClass;
        _path = path; // may be null
        _deviceInfoData = deviceInfoData;
        _index = index;
    }

    /// <summary>
    /// Gets the device's index.
    /// </summary>
    public int Index
    {
        get { return _index; }
    }

    /// <summary>
    /// Gets the device's class instance.
    /// </summary>
    [Browsable(false)]
    public DeviceClass DeviceClass
    {
        get { return _deviceClass; }
    }

    /// <summary>
    /// Gets the device's path.
    /// </summary>
    public string Path
    {
        get { return _path; }
    }

    /// <summary>
    /// Gets the device's instance handle.
    /// </summary>
    public int InstanceHandle
    {
        get { return _deviceInfoData.devInst; }
    }

    /// <summary>
    /// Gets the device's class name.
    /// </summary>
    public string Class
    {
        get
        {
            if (_class == null)
            {
                _class = _deviceClass.GetProperty(_deviceInfoData, Native.SPDRP_CLASS, null);
            }
            return _class;
        }
    }

    /// <summary>
    /// Gets the device's class Guid as a string.
    /// </summary>
    public string ClassGuid
    {
        get
        {
            if (_classGuid == null)
            {
                _classGuid = _deviceClass.GetProperty(_deviceInfoData, Native.SPDRP_CLASSGUID, null);
            }
            return _classGuid;
        }
    }

    /// <summary>
    /// Gets the device's description.
    /// </summary>
    public string Description
    {
        get
        {
            if (_description == null)
            {
                _description = _deviceClass.GetProperty(_deviceInfoData, Native.SPDRP_DEVICEDESC, null);
            }
            return _description;
        }
    }

    /// <summary>
    /// Gets the device's friendly name.
    /// </summary>
    public string FriendlyName
    {
        get
        {
            if (_friendlyName == null)
            {
                _friendlyName = _deviceClass.GetProperty(_deviceInfoData, Native.SPDRP_FRIENDLYNAME, null);
            }
            return _friendlyName;
        }
    }

    /// <summary>
    /// Gets the device's capabilities.
    /// </summary>
    public DeviceCapabilities Capabilities
    {
        get
        {
            if (_capabilities == DeviceCapabilities.Unknown)
            {
                _capabilities = (DeviceCapabilities)_deviceClass.GetProperty(_deviceInfoData, Native.SPDRP_CAPABILITIES, 0);
            }
            return _capabilities;
        }
    }

    /// <summary>
    /// Gets a value indicating whether this device is a USB device.
    /// </summary>
    public virtual bool IsUsb
    {
        get
        {
            if (Class == "USB")
                return true;

            if (Parent == null)
                return false;

            return Parent.IsUsb;
        }
    }

    /// <summary>
    /// Gets the device's parent device or null if this device has not parent.
    /// </summary>
    public Device Parent
    {
        get
        {
            if (_parent == null)
            {
                int parentDevInst = 0;
                int hr = Native.CM_Get_Parent(ref parentDevInst, _deviceInfoData.devInst, 0);
                if (hr == 0)
                {
                    _parent = new Device(_deviceClass, _deviceClass.GetInfo(parentDevInst), null, -1);
                }
            }
            return _parent;
        }
    }

    /// <summary>
    /// Gets this device's list of removable devices.
    /// Removable devices are parent devices that can be removed.
    /// </summary>
    public virtual List<Device> RemovableDevices
    {
        get
        {
            if (_removableDevices == null)
            {
                _removableDevices = new List<Device>();

                if ((Capabilities & DeviceCapabilities.Removable) != 0)
                {
                    _removableDevices.Add(this);
                }
                else
                {
                    if (Parent != null)
                    {
                        foreach (Device device in Parent.RemovableDevices)
                        {
                            _removableDevices.Add(device);
                        }
                    }
                }
            }
            return _removableDevices;
        }
    }

    /// <summary>
    /// Ejects the device.
    /// </summary>
    /// <param name="allowUI">Pass true to allow the Windows shell to display any related UI element, false otherwise.</param>
    /// <returns>null if no error occured, otherwise a contextual text.</returns>
    public string Eject(bool allowUI)
    {
        foreach (Device device in RemovableDevices)
        {
            if (allowUI)
            {
                Native.CM_Request_Device_Eject_NoUi(device.InstanceHandle, IntPtr.Zero, null, 0, 0);
                // don't handle errors, there should be a UI for this
            }
            else
            {
                StringBuilder sb = new StringBuilder(1024);

                Native.PNP_VETO_TYPE veto;
                int hr = Native.CM_Request_Device_Eject(device.InstanceHandle, out veto, sb, sb.Capacity, 0);
                if (hr != 0)
                    throw new Win32Exception(hr);

                if (veto != Native.PNP_VETO_TYPE.Ok)
                    return veto.ToString();
            }

        }
        return null;
    }

    /// <summary>
    /// Compares the current instance with another object of the same type.
    /// </summary>
    /// <param name="obj">An object to compare with this instance.</param>
    /// <returns>A 32-bit signed integer that indicates the relative order of the comparands.</returns>
    public virtual int CompareTo(object obj)
    {
        Device device = obj as Device;
        if (device == null)
            throw new ArgumentException();

        return Index.CompareTo(device.Index);
    }
}

/// <summary>
/// A generic base class for physical device classes.
/// </summary>
public abstract class DeviceClass : IDisposable
{
    private IntPtr _deviceInfoSet;
    private Guid _classGuid;
    private List<Device> _devices;

    protected DeviceClass(Guid classGuid)
        : this(classGuid, IntPtr.Zero)
    {
    }

    internal virtual Device CreateDevice(DeviceClass deviceClass, Native.SP_DEVINFO_DATA deviceInfoData, string path, int index)
    {
        return new Device(deviceClass, deviceInfoData, path, index);
    }

    /// <summary>
    /// Initializes a new instance of the DeviceClass class.
    /// </summary>
    /// <param name="classGuid">A device class Guid.</param>
    /// <param name="hwndParent">The handle of the top-level window to be used for any user interface or IntPtr.Zero for no handle.</param>
    protected DeviceClass(Guid classGuid, IntPtr hwndParent)
    {
        _classGuid = classGuid;

        _deviceInfoSet = Native.SetupDiGetClassDevs(ref _classGuid, 0, hwndParent, Native.DIGCF_DEVICEINTERFACE | Native.DIGCF_PRESENT);
        if (_deviceInfoSet.ToInt32() == Native.INVALID_HANDLE_VALUE)
            throw new Win32Exception(Marshal.GetLastWin32Error());
    }

    /// <summary>
    /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
    /// </summary>
    public void Dispose()
    {
        if (_deviceInfoSet != IntPtr.Zero)
        {
            Native.SetupDiDestroyDeviceInfoList(_deviceInfoSet);
            _deviceInfoSet = IntPtr.Zero;
        }
    }

    /// <summary>
    /// Gets the device class's guid.
    /// </summary>
    public Guid ClassGuid
    {
        get
        {
            return _classGuid;
        }
    }

    /// <summary>
    /// Gets the list of devices of this device class.
    /// </summary>
    public List<Device> Devices
    {
        get
        {
            if (_devices == null)
            {
                _devices = new List<Device>();
                int index = 0;
                while (true)
                {
                    Native.SP_DEVICE_INTERFACE_DATA interfaceData = new Native.SP_DEVICE_INTERFACE_DATA();

                    if (!Native.SetupDiEnumDeviceInterfaces(_deviceInfoSet, null, ref _classGuid, index, interfaceData))
                    {
                        int error = Marshal.GetLastWin32Error();
                        if (error != Native.ERROR_NO_MORE_ITEMS)
                            throw new Win32Exception(error);
                        break;
                    }

                    Native.SP_DEVINFO_DATA devData = new Native.SP_DEVINFO_DATA();
                    int size = 0;
                    if (!Native.SetupDiGetDeviceInterfaceDetail(_deviceInfoSet, interfaceData, IntPtr.Zero, 0, ref size, devData))
                    {
                        int error = Marshal.GetLastWin32Error();
                        if (error != Native.ERROR_INSUFFICIENT_BUFFER)
                            throw new Win32Exception(error);
                    }

                    IntPtr buffer = Marshal.AllocHGlobal(size);
                    Native.SP_DEVICE_INTERFACE_DETAIL_DATA detailData = new Native.SP_DEVICE_INTERFACE_DETAIL_DATA();
                    detailData.cbSize = Marshal.SizeOf(typeof(Native.SP_DEVICE_INTERFACE_DETAIL_DATA));
                    Marshal.StructureToPtr(detailData, buffer, false);

                    if (!Native.SetupDiGetDeviceInterfaceDetail(_deviceInfoSet, interfaceData, buffer, size, ref size, devData))
                    {
                        Marshal.FreeHGlobal(buffer);
                        throw new Win32Exception(Marshal.GetLastWin32Error());
                    }

                    IntPtr pDevicePath = (IntPtr)((int)buffer + Marshal.SizeOf(typeof(int)));
                    string devicePath = Marshal.PtrToStringAuto(pDevicePath);
                    Marshal.FreeHGlobal(buffer);

                    Device device = CreateDevice(this, devData, devicePath, index);
                    _devices.Add(device);

                    index++;
                }
                _devices.Sort();
            }
            return _devices;
        }
    }

    internal Native.SP_DEVINFO_DATA GetInfo(int dnDevInst)
    {
        StringBuilder sb = new StringBuilder(1024);
        int hr = Native.CM_Get_Device_ID(dnDevInst, sb, sb.Capacity, 0);
        if (hr != 0)
            throw new Win32Exception(hr);

        Native.SP_DEVINFO_DATA devData = new Native.SP_DEVINFO_DATA();
        devData.cbSize = Marshal.SizeOf(typeof(Native.SP_DEVINFO_DATA));
        if (!Native.SetupDiOpenDeviceInfo(_deviceInfoSet, sb.ToString(), IntPtr.Zero, 0, devData))
            throw new Win32Exception(Marshal.GetLastWin32Error());

        return devData;
    }

    internal string GetProperty(Native.SP_DEVINFO_DATA devData, int property, string defaultValue)
    {
        if (devData == null)
            throw new ArgumentNullException("devData");

        int propertyRegDataType = 0;
        int requiredSize;
        int propertyBufferSize = 1024;

        IntPtr propertyBuffer = Marshal.AllocHGlobal(propertyBufferSize);
        if (!Native.SetupDiGetDeviceRegistryProperty(_deviceInfoSet,
            devData,
            property,
            out propertyRegDataType,
            propertyBuffer,
            propertyBufferSize,
            out requiredSize))
        {
            Marshal.FreeHGlobal(propertyBuffer);
            int error = Marshal.GetLastWin32Error();
            if (error != Native.ERROR_INVALID_DATA)
                throw new Win32Exception(error);
            return defaultValue;
        }

        string value = Marshal.PtrToStringAuto(propertyBuffer);
        Marshal.FreeHGlobal(propertyBuffer);
        return value;
    }

    internal int GetProperty(Native.SP_DEVINFO_DATA devData, int property, int defaultValue)
    {
        if (devData == null)
            throw new ArgumentNullException("devData");

        int propertyRegDataType = 0;
        int requiredSize;
        int propertyBufferSize = Marshal.SizeOf(typeof(int));

        IntPtr propertyBuffer = Marshal.AllocHGlobal(propertyBufferSize);
        if (!Native.SetupDiGetDeviceRegistryProperty(_deviceInfoSet,
            devData,
            property,
            out propertyRegDataType,
            propertyBuffer,
            propertyBufferSize,
            out requiredSize))
        {
            Marshal.FreeHGlobal(propertyBuffer);
            int error = Marshal.GetLastWin32Error();
            if (error != Native.ERROR_INVALID_DATA)
                throw new Win32Exception(error);
            return defaultValue;
        }

        int value = (int)Marshal.PtrToStructure(propertyBuffer, typeof(int));
        Marshal.FreeHGlobal(propertyBuffer);
        return value;
    }

    internal Guid GetProperty(Native.SP_DEVINFO_DATA devData, int property, Guid defaultValue)
    {
        if (devData == null)
            throw new ArgumentNullException("devData");

        int propertyRegDataType = 0;
        int requiredSize;
        int propertyBufferSize = Marshal.SizeOf(typeof(Guid));

        IntPtr propertyBuffer = Marshal.AllocHGlobal(propertyBufferSize);
        if (!Native.SetupDiGetDeviceRegistryProperty(_deviceInfoSet,
            devData,
            property,
            out propertyRegDataType,
            propertyBuffer,
            propertyBufferSize,
            out requiredSize))
        {
            Marshal.FreeHGlobal(propertyBuffer);
            int error = Marshal.GetLastWin32Error();
            if (error != Native.ERROR_INVALID_DATA)
                throw new Win32Exception(error);
            return defaultValue;
        }

        Guid value = (Guid)Marshal.PtrToStructure(propertyBuffer, typeof(Guid));
        Marshal.FreeHGlobal(propertyBuffer);
        return value;
    }

}

/// <summary>
/// The device class for disk devices.
/// </summary>
public class DiskDeviceClass : DeviceClass
{
    /// <summary>
    /// Initializes a new instance of the DiskDeviceClass class.
    /// </summary>
    public DiskDeviceClass()
        : base(new Guid(Native.GUID_DEVINTERFACE_DISK))
    {
    }
}

internal sealed class Native
{
    // from winuser.h
    internal const int WM_DEVICECHANGE = 0x0219;

    // from winbase.h
    internal const int INVALID_HANDLE_VALUE = -1;
    internal const int GENERIC_READ = unchecked((int)0x80000000);
    internal const int FILE_SHARE_READ = 0x00000001;
    internal const int FILE_SHARE_WRITE = 0x00000002;
    internal const int OPEN_EXISTING = 3;

    [DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)]
    internal static extern bool GetVolumeNameForVolumeMountPoint(
        string volumeName,
        StringBuilder uniqueVolumeName,
        int uniqueNameBufferCapacity);

    [DllImport("Kernel32.dll", SetLastError = true)]
    internal static extern IntPtr CreateFile(string lpFileName, int dwDesiredAccess, int dwShareMode, IntPtr lpSecurityAttributes, int dwCreationDisposition, int dwFlagsAndAttributes, IntPtr hTemplateFile);

    [DllImport("Kernel32.dll", SetLastError = true)]
    internal static extern bool DeviceIoControl(IntPtr hDevice, int dwIoControlCode, IntPtr lpInBuffer, int nInBufferSize, IntPtr lpOutBuffer, int nOutBufferSize, out int lpBytesReturned, IntPtr lpOverlapped);

    [DllImport("Kernel32.dll", SetLastError = true)]
    internal static extern bool CloseHandle(IntPtr hObject);

    // from winerror.h
    internal const int ERROR_NO_MORE_ITEMS = 259;
    internal const int ERROR_INSUFFICIENT_BUFFER = 122;
    internal const int ERROR_INVALID_DATA = 13;

    // from winioctl.h
    internal const string GUID_DEVINTERFACE_VOLUME = "53f5630d-b6bf-11d0-94f2-00a0c91efb8b";
    internal const string GUID_DEVINTERFACE_DISK = "53f56307-b6bf-11d0-94f2-00a0c91efb8b";
    internal const int IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS = 0x00560000;

    [StructLayout(LayoutKind.Sequential)]
    internal struct DISK_EXTENT
    {
        internal int DiskNumber;
        internal long StartingOffset;
        internal long ExtentLength;
    }

    // from cfg.h
    internal enum PNP_VETO_TYPE
    {
        Ok,

        TypeUnknown,
        LegacyDevice,
        PendingClose,
        WindowsApp,
        WindowsService,
        OutstandingOpen,
        Device,
        Driver,
        IllegalDeviceRequest,
        InsufficientPower,
        NonDisableable,
        LegacyDriver,
    }

    // from cfgmgr32.h
    [DllImport("setupapi.dll")]
    internal static extern int CM_Get_Parent(
        ref int pdnDevInst,
        int dnDevInst,
        int ulFlags);

    [DllImport("setupapi.dll")]
    internal static extern int CM_Get_Device_ID(
        int dnDevInst,
        StringBuilder buffer,
        int bufferLen,
        int ulFlags);

    [DllImport("setupapi.dll")]
    internal static extern int CM_Request_Device_Eject(
        int dnDevInst,
        out PNP_VETO_TYPE pVetoType,
        StringBuilder pszVetoName,
        int ulNameLength,
        int ulFlags
        );

    [DllImport("setupapi.dll", EntryPoint = "CM_Request_Device_Eject")]
    internal static extern int CM_Request_Device_Eject_NoUi(
        int dnDevInst,
        IntPtr pVetoType,
        StringBuilder pszVetoName,
        int ulNameLength,
        int ulFlags
        );

    // from setupapi.h
    internal const int DIGCF_PRESENT = (0x00000002);
    internal const int DIGCF_DEVICEINTERFACE = (0x00000010);

    internal const int SPDRP_DEVICEDESC = 0x00000000;
    internal const int SPDRP_CAPABILITIES = 0x0000000F;
    internal const int SPDRP_CLASS = 0x00000007;
    internal const int SPDRP_CLASSGUID = 0x00000008;
    internal const int SPDRP_FRIENDLYNAME = 0x0000000C;

    [StructLayout(LayoutKind.Sequential)]
    internal class SP_DEVINFO_DATA
    {
        internal int cbSize = Marshal.SizeOf(typeof(SP_DEVINFO_DATA));
        internal Guid classGuid = Guid.Empty; // temp
        internal int devInst = 0; // dumy
        internal int reserved = 0;
    }

    [StructLayout(LayoutKind.Sequential, Pack = 2)]
    internal struct SP_DEVICE_INTERFACE_DETAIL_DATA
    {
        internal int cbSize;
        internal short devicePath;
    }

    [StructLayout(LayoutKind.Sequential)]
    internal class SP_DEVICE_INTERFACE_DATA
    {
        internal int cbSize = Marshal.SizeOf(typeof(SP_DEVICE_INTERFACE_DATA));
        internal Guid interfaceClassGuid = Guid.Empty; // temp
        internal int flags = 0;
        internal int reserved = 0;
    }

    [DllImport("setupapi.dll")]
    internal static extern IntPtr SetupDiGetClassDevs(
        ref Guid classGuid,
        int enumerator,
        IntPtr hwndParent,
        int flags);

    [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
    internal static extern bool SetupDiEnumDeviceInterfaces(
        IntPtr deviceInfoSet,
        SP_DEVINFO_DATA deviceInfoData,
        ref Guid interfaceClassGuid,
        int memberIndex,
        SP_DEVICE_INTERFACE_DATA deviceInterfaceData);

    [DllImport("setupapi.dll")]
    internal static extern bool SetupDiOpenDeviceInfo(
        IntPtr deviceInfoSet,
        string deviceInstanceId,
        IntPtr hwndParent,
        int openFlags,
        SP_DEVINFO_DATA deviceInfoData
        );

    [DllImport("setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
    internal static extern bool SetupDiGetDeviceInterfaceDetail(
        IntPtr deviceInfoSet,
        SP_DEVICE_INTERFACE_DATA deviceInterfaceData,
        IntPtr deviceInterfaceDetailData,
        int deviceInterfaceDetailDataSize,
        ref int requiredSize,
        SP_DEVINFO_DATA deviceInfoData);

    [DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
    internal static extern bool SetupDiGetDeviceRegistryProperty(
        IntPtr deviceInfoSet,
        SP_DEVINFO_DATA deviceInfoData,
        int property,
        out int propertyRegDataType,
        IntPtr propertyBuffer,
        int propertyBufferSize,
        out int requiredSize
        );

    [DllImport("setupapi.dll")]
    internal static extern uint SetupDiDestroyDeviceInfoList(
        IntPtr deviceInfoSet);

    private Native()
    {
    }
}

/// <summary>
/// A volume device.
/// </summary>
public class Volume : Device, IComparable
{
    private string _volumeName;
    private string _logicalDrive;
    private int[] _diskNumbers;
    private List<Device> _disks;
    private List<Device> _removableDevices;

    internal Volume(DeviceClass deviceClass, Native.SP_DEVINFO_DATA deviceInfoData, string path, int index)
        : base(deviceClass, deviceInfoData, path, index)
    {
    }

    /// <summary>
    /// Gets the volume's name.
    /// </summary>
    public string VolumeName
    {
        get
        {
            if (_volumeName == null)
            {
                StringBuilder sb = new StringBuilder(1024);
                if (!Native.GetVolumeNameForVolumeMountPoint(Path + "\\", sb, sb.Capacity))
                {
                    // throw new Win32Exception(Marshal.GetLastWin32Error());

                }

                if (sb.Length > 0)
                {
                    _volumeName = sb.ToString();
                }
            }
            return _volumeName;
        }
    }

    /// <summary>
    /// Gets the volume's logical drive in the form [letter]:\
    /// </summary>
    public string LogicalDrive
    {
        get
        {
            if ((_logicalDrive == null) && (VolumeName != null))
            {
                ((VolumeDeviceClass)DeviceClass)._logicalDrives.TryGetValue(VolumeName, out _logicalDrive);
            }
            return _logicalDrive;
        }
    }

    /// <summary>
    /// Gets a value indicating whether this volume is a based on USB devices.
    /// </summary>
    public override bool IsUsb
    {
        get
        {
            if (Disks != null)
            {
                foreach (Device disk in Disks)
                {
                    if (disk.IsUsb)
                        return true;
                }
            }
            return false;
        }
    }

    /// <summary>
    /// Gets a list of underlying disks for this volume.
    /// </summary>
    public List<Device> Disks
    {
        get
        {
            if (_disks == null)
            {
                _disks = new List<Device>();

                if (DiskNumbers != null)
                {
                    DiskDeviceClass disks = new DiskDeviceClass();
                    foreach (int index in DiskNumbers)
                    {
                        if (index < disks.Devices.Count)
                        {
                            _disks.Add(disks.Devices[index]);
                        }
                    }
                }
            }
            return _disks;
        }
    }

    private int[] DiskNumbers
    {
        get
        {
            if (_diskNumbers == null)
            {
                List<int> numbers = new List<int>();
                if (LogicalDrive != null)
                {

                    IntPtr hFile = Native.CreateFile(@"\\.\" + LogicalDrive, Native.GENERIC_READ, Native.FILE_SHARE_READ | Native.FILE_SHARE_WRITE, IntPtr.Zero, Native.OPEN_EXISTING, 0, IntPtr.Zero);
                    if (hFile.ToInt32() == Native.INVALID_HANDLE_VALUE)
                        throw new Win32Exception(Marshal.GetLastWin32Error());

                    int size = 0x400; // some big size
                    IntPtr buffer = Marshal.AllocHGlobal(size);
                    int bytesReturned = 0;
                    try
                    {
                        if (!Native.DeviceIoControl(hFile, Native.IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, IntPtr.Zero, 0, buffer, size, out bytesReturned, IntPtr.Zero))
                        {
                            // do nothing here on purpose
                        }
                    }
                    finally
                    {
                        Native.CloseHandle(hFile);
                    }

                    if (bytesReturned > 0)
                    {
                        int numberOfDiskExtents = (int)Marshal.PtrToStructure(buffer, typeof(int));
                        for (int i = 0; i < numberOfDiskExtents; i++)
                        {
                            IntPtr extentPtr = new IntPtr(buffer.ToInt32() + Marshal.SizeOf(typeof(long)) + i * Marshal.SizeOf(typeof(Native.DISK_EXTENT)));
                            Native.DISK_EXTENT extent = (Native.DISK_EXTENT)Marshal.PtrToStructure(extentPtr, typeof(Native.DISK_EXTENT));
                            numbers.Add(extent.DiskNumber);
                        }
                    }
                    Marshal.FreeHGlobal(buffer);
                }

                _diskNumbers = new int[numbers.Count];
                numbers.CopyTo(_diskNumbers);
            }
            return _diskNumbers;
        }
    }

    /// <summary>
    /// Gets a list of removable devices for this volume.
    /// </summary>
    public override List<Device> RemovableDevices
    {
        get
        {
            if (_removableDevices == null)
            {
                _removableDevices = new List<Device>();
                if (Disks == null)
                {
                    _removableDevices = base.RemovableDevices;
                }
                else
                {
                    foreach (Device disk in Disks)
                    {
                        foreach (Device device in disk.RemovableDevices)
                        {
                            _removableDevices.Add(device);
                        }
                    }
                }
            }
            return _removableDevices;
        }
    }

    /// <summary>
    /// Compares the current instance with another object of the same type.
    /// </summary>
    /// <param name="obj">An object to compare with this instance.</param>
    /// <returns>A 32-bit signed integer that indicates the relative order of the comparands.</returns>
    public override int CompareTo(object obj)
    {
        Volume device = obj as Volume;
        if (device == null)
            throw new ArgumentException();

        if (LogicalDrive == null)
            return 1;

        if (device.LogicalDrive == null)
            return -1;

        return LogicalDrive.CompareTo(device.LogicalDrive);
    }
}

/// <summary>
/// The device class for volume devices.
/// </summary>
public class VolumeDeviceClass : DeviceClass
{
    internal SortedDictionary<string, string> _logicalDrives = new SortedDictionary<string, string>();

    /// <summary>
    /// Initializes a new instance of the VolumeDeviceClass class.
    /// </summary>
    public VolumeDeviceClass()
        : base(new Guid(Native.GUID_DEVINTERFACE_VOLUME))
    {
        foreach (string drive in Environment.GetLogicalDrives())
        {
            StringBuilder sb = new StringBuilder(1024);
            if (Native.GetVolumeNameForVolumeMountPoint(drive, sb, sb.Capacity))
            {
                _logicalDrives[sb.ToString()] = drive.Replace("\\", "");
            }
        }
    }

    internal override Device CreateDevice(DeviceClass deviceClass, Native.SP_DEVINFO_DATA deviceInfoData, string path, int index)
    {
        return new Volume(deviceClass, deviceInfoData, path, index);
    }
}
0
 
Bob LearnedCommented:
Sample:
            List<Device> deviceList = UsbDevices.EnumerateUsbDevices();
            foreach (Device device in deviceList)
                if (device.Parent.FriendlyName == "ChipsBnk Flash Disk USB Device")
                    Console.WriteLine(device.Parent.FriendlyName);

Bob
0
 
YeavisAuthor Commented:
Isn't that the code from the USBEject app off of CodeProject.com?? I actually have implemented quite a bit of that into my current application and I use the exact same code to eject devices. Now I am trying to find a way to display what Host Controller and Port number each device is attached too. The code I provided before actually go through 2 or 3 steps before it gets to that point, and everything is working except for this last deviceiocontrol call. Did you see any problems with the code I provided??
0
 
Bob LearnedCommented:
>.Isn't that the code from the USBEject app off of CodeProject.com??
Yes, the first comment in the class mentions that fact.

Why would you need Host Controller and Port number, pray tell?

Bob
0
 
YeavisAuthor Commented:
Sorry... I skimmed right over that comment! I need this information for my application because when a device "fails" the operators need to have a consistent way to know which USB device had the problem. They will be physical removing the device and I need a way to actually map the device listed in my application to a physical port.

Anyhow, thanks again for the help. Your time really is appreciated! Here is the code I am trying to convert - from UsbView.exe

PCHAR GetDriverKeyName (
    HANDLE  Hub,
    ULONG   ConnectionIndex
)
{
    BOOL                                success;
    ULONG                               nBytes;
    USB_NODE_CONNECTION_DRIVERKEY_NAME  driverKeyName;
    PUSB_NODE_CONNECTION_DRIVERKEY_NAME driverKeyNameW;
    PCHAR                               driverKeyNameA;

    driverKeyNameW = NULL;
    driverKeyNameA = NULL;

    // Get the length of the name of the driver key of the device attached to
    // the specified port.
    //
    driverKeyName.ConnectionIndex = ConnectionIndex;

    success = DeviceIoControl(Hub,
                              IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME,
                              &driverKeyName,
                              sizeof(driverKeyName),
                              &driverKeyName,
                              sizeof(driverKeyName),
                              &nBytes,
                              NULL);

    if (!success)
    {
        OOPS();
        goto GetDriverKeyNameError;
    }

    // Allocate space to hold the driver key name
    //
    nBytes = driverKeyName.ActualLength;

    if (nBytes <= sizeof(driverKeyName))
    {
        OOPS();
        goto GetDriverKeyNameError;
    }

    driverKeyNameW = ALLOC(nBytes);

    if (driverKeyNameW == NULL)
    {
        OOPS();
        goto GetDriverKeyNameError;
    }

    // Get the name of the driver key of the device attached to
    // the specified port.
    //
    driverKeyNameW->ConnectionIndex = ConnectionIndex;

    success = DeviceIoControl(Hub,
                              IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME,
                              driverKeyNameW,
                              nBytes,
                              driverKeyNameW,
                              nBytes,
                              &nBytes,
                              NULL);

    if (!success)
    {
        OOPS();
        goto GetDriverKeyNameError;
    }

    // Convert the driver key name
    //
    driverKeyNameA = WideStrToMultiStr(driverKeyNameW->DriverKeyName);

    // All done, free the uncoverted driver key name and return the
    // converted driver key name
    //
    FREE(driverKeyNameW);

    return driverKeyNameA;


GetDriverKeyNameError:
    // There was an error, free anything that was allocated
    //
    if (driverKeyNameW != NULL)
    {
        FREE(driverKeyNameW);
        driverKeyNameW = NULL;
    }

    return NULL;
}
 
0
 
YeavisAuthor Commented:
TheLearnedOne,
      Can you provide any help with my last comment? I would really appreciate your expertise...

Yeavis
0
 
YeavisAuthor Commented:
Increasing the point value...
0
 
Bob LearnedCommented:
I don't see how this will get you Host Control and Port number.

Bob
0
 
YeavisAuthor Commented:
I already have the host controller portion working.... this part will get me the device information for each port on that host controller.
0
 
YeavisAuthor Commented:
0
 
Bob LearnedCommented:
What are you calling GetDriverKeyName with (IntPtr, int)?

Bob
0
 
YeavisAuthor Commented:
Yes, am I not supposed to??
0
 
Bob LearnedCommented:
Sorry, what are you passing into GetDriverKeyName?  Where are those values coming from?

Bob
0
 
YeavisAuthor Commented:
Here is what I am using for reference...  I have changed my code to follow this and I am still running into issues in the same spot.

http://www.intel.com/intelpress/usb/examples/DUSBVC.PDF
0
 
Bob LearnedCommented:
So, where are you getting HubHandle from?

Bob
0
 
YeavisAuthor Commented:
I apologize I haven't posted sooner, I figured this out on my own. My solution was to use a C-sharp version of the USBView program from this web site: http://www.lvr.com/usb.htm

Here is the c-sharp version of the usb view program that helped me solve my problem: http://home.hot.rr.com/graye/Programs/USBView.zip

Thanks for all your help Bob, your time is greately appreciated.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.