?
Solved

DeviceIOControl Problem

Posted on 2007-08-02
24
Medium Priority
?
2,687 Views
Last Modified: 2012-05-05
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!!!
0
Comment
Question by:Yeavis
  • 11
  • 10
22 Comments
 
LVL 96

Expert Comment

by:Bob Learned
ID: 19622137
What version of .NET do you have?  If you have 2005, is it SP1?  Where are you getting the exception?

Bob
0
 

Author Comment

by:Yeavis
ID: 19624476
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
 
LVL 96

Expert Comment

by:Bob Learned
ID: 19625044
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
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:Yeavis
ID: 19625526
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
 
LVL 96

Expert Comment

by:Bob Learned
ID: 19626941
I have been working on this same thing, and here is what I came up with:
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 19626942
// 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
 
LVL 96

Expert Comment

by:Bob Learned
ID: 19626954
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
 

Author Comment

by:Yeavis
ID: 19627792
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
 
LVL 96

Expert Comment

by:Bob Learned
ID: 19627816
>.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
 

Author Comment

by:Yeavis
ID: 19627876
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
 

Author Comment

by:Yeavis
ID: 19639602
TheLearnedOne,
      Can you provide any help with my last comment? I would really appreciate your expertise...

Yeavis
0
 

Author Comment

by:Yeavis
ID: 19641248
Increasing the point value...
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 19642994
I don't see how this will get you Host Control and Port number.

Bob
0
 

Author Comment

by:Yeavis
ID: 19643472
I already have the host controller portion working.... this part will get me the device information for each port on that host controller.
0
 

Author Comment

by:Yeavis
ID: 19647159
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 19647382
What are you calling GetDriverKeyName with (IntPtr, int)?

Bob
0
 

Author Comment

by:Yeavis
ID: 19648408
Yes, am I not supposed to??
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 19648421
Sorry, what are you passing into GetDriverKeyName?  Where are those values coming from?

Bob
0
 

Author Comment

by:Yeavis
ID: 19649752
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
 
LVL 96

Expert Comment

by:Bob Learned
ID: 19656230
So, where are you getting HubHandle from?

Bob
0
 

Author Comment

by:Yeavis
ID: 19817273
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
 
LVL 1

Accepted Solution

by:
Computer101 earned 0 total points
ID: 19946243
PAQed with points refunded (500)

Computer101
EE Admin
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Summary: Persistence is the capability of an application to store the state of objects and recover it when necessary. This article compares the two common types of serialization in aspects of data access, readability, and runtime cost. A ready-to…
We all know that functional code is the leg that any good program stands on when it comes right down to it, however, if your program lacks a good user interface your product may not have the appeal needed to keep your customers happy. This issue can…
Is your data getting by on basic protection measures? In today’s climate of debilitating malware and ransomware—like WannaCry—that may not be enough. You need to establish more than basics, like a recovery plan that protects both data and endpoints.…
Is your OST file inaccessible, Need to transfer OST file from one computer to another? Want to convert OST file to PST? If the answer to any of the above question is yes, then look no further. With the help of Stellar OST to PST Converter, you can e…
Suggested Courses

840 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question