none
why the SetupDiGetDevicePropertyW function back to false? RRS feed

  • Question

  • I want to use the SetupDiGetDevicePropertyW function to get DEVPKEY_Device_LocationInfo information for HID devices(Location Info: Port_ 0003. Hub_ 0003), I use the SetupDiGetDevicePropertyW function, but the functions   back to false. Can anyone help me see it? The main code is as follows:

    [DllImport("hid.dll", SetLastError = true)] public static extern IntPtr HidD_GetHidGuid(ref Guid gClass); [DllImport("setupapi.dll", SetLastError = true)] public static extern IntPtr SetupDiGetClassDevs(ref Guid gClass, UInt32 iEnumerator, IntPtr hParent, DiGetClassFlags nFlags); [DllImport("setupapi.dll", SetLastError = true)] public static extern bool SetupDiEnumDeviceInfo( IntPtr DeviceInfoSet, UInt32 MemberIndex, ref SP_DEVINFO_DATA DeviceInterfaceData); [DllImport("setupapi.dll", SetLastError = true)] static extern bool SetupDiGetDevicePropertyW( IntPtr deviceInfoSet, [In] ref SP_DEVINFO_DATA DeviceInfoData, [In] ref DEVPROPKEY propertyKey, [Out] out UInt32 propertyType, byte[] propertyBuffer, UInt32 propertyBufferSize, out UInt32 requiredSize, UInt32 flags); Guid myguid; myguid = new Guid(); IntPtr result; result = HidD_GetHidGuid(ref myguid); IntPtr DeviceInfoSet; DeviceInfoSet = SetupDiGetClassDevs(ref myguid, 0, IntPtr.Zero, DiGetClassFlags.DIGCF_PRESENT | DiGetClassFlags.DIGCF_DEVICEINTERFACE); SP_DEVINFO_DATA deviceInfoData = new SP_DEVINFO_DATA(); deviceInfoData.cbSize = (uint)Marshal.SizeOf(typeof(SP_DEVINFO_DATA)); bool success = SetupDiEnumDeviceInfo(DeviceInfoSet, iMemberIndex, ref deviceInfoData); DeviceInfo deviceInfo = new UsbEnumHelper.DeviceInfo(); byte[] ptrBuf = new byte[BUFFER_SIZE]; uint propRegDataType; uint RequiredSize;

    DevicePortDesc = new DEVPROPKEY(); DevicePortDesc.fmtid = new Guid(0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0); DevicePortDesc.pid = 15 bool success = SetupDiGetDevicePropertyW(hDeviceInfoSet, ref deviceInfoData, ref DevicePortDesc, out propRegDataType, ptrBuf, BUFFER_SIZE, out RequiredSize, 0);




    • Edited by twohorses111 Thursday, August 1, 2019 2:03 AM edit
    Thursday, August 1, 2019 1:58 AM

Answers

  • If you have the device identifier (the HID\xxx string), you can use CM_Locate_DevNode to fetch a DEVINST handle, then CM_Get_Parent to fetch the parent, then CM_Get_DevNode_Property to fetch the location.

    Tim Roberts | Driver MVP Emeritus | Providenza & Boekelheide, Inc.

    • Marked as answer by twohorses111 Tuesday, August 6, 2019 8:04 AM
    Friday, August 2, 2019 9:26 PM

All replies

  • Since you've specified SetLastError=true in your import signature, you should be able to call Marshal.GetLastWin32Error() to retrieve the error code and determine what happened. (Refer to setupapi.h in SDK or here to see the value of constants.)
    Thursday, August 1, 2019 3:59 AM
    Answerer
  • Thank you. I'll try.
    Thursday, August 1, 2019 9:42 AM
  • The error you're getting is ERROR_NOT_FOUND.  By passing the HID device interface GUID into SetupDiGetClassDevs, you are fetching the HID device (that is, HID\VID_xxxx&PID_xxxx&...).  HID devices do not have location info.  You need to query the USB device that is the parent of the HID device.  Instead of searching for the HID device interface, you should search for the HIDCLASS device class.  In C++ you would do

        SetupDiGetClassDevs( &GUID_DEVCLASS_HIDCLASS, 0, 0, DIGCF_PRESENT );

    Note that I have not included DIGCF_DEVICEINTERFACE.  You ought to be able to find GUID_DEVCLASS_HIDCLASS in a p/Invoke site somewhere.  It starts with 745a17a0.


    Tim Roberts | Driver MVP Emeritus | Providenza & Boekelheide, Inc.

    Thursday, August 1, 2019 6:49 PM
  • The error you're getting is ERROR_NOT_FOUND.  By passing the HID device interface GUID into SetupDiGetClassDevs, you are fetching the HID device (that is, HID\VID_xxxx&PID_xxxx&...).  HID devices do not have location info.  You need to query the USB device that is the parent of the HID device.  Instead of searching for the HID device interface, you should search for the HIDCLASS device class.  In C++ you would do

        SetupDiGetClassDevs( &GUID_DEVCLASS_HIDCLASS, 0, 0, DIGCF_PRESENT );

    Note that I have not included DIGCF_DEVICEINTERFACE.  You ought to be able to find GUID_DEVCLASS_HIDCLASS in a p/Invoke site somewhere.  It starts with 745a17a0.


    Tim Roberts | Driver MVP Emeritus | Providenza & Boekelheide, Inc.

    I want to get the port number of the HID device to distinguish multiple identical devices. I used this guide ("a5dcbf10-6530-11d2-901f-00c04fb951ed") to find loacation info, but I can't match this USB device with his Child Device Hid device.

    Is there any way to find his parent USB through the HID device? The following is the information shown in UsbTreeView . How can we find the corresponding relationship between the HID device under the partition line(******) and the USB device above? The information I want to get is the content of the  Loation Info ("Port_ 0003. Hub_ 0003").


    Friday, August 2, 2019 3:19 AM
  • If you have the device identifier (the HID\xxx string), you can use CM_Locate_DevNode to fetch a DEVINST handle, then CM_Get_Parent to fetch the parent, then CM_Get_DevNode_Property to fetch the location.

    Tim Roberts | Driver MVP Emeritus | Providenza & Boekelheide, Inc.

    • Marked as answer by twohorses111 Tuesday, August 6, 2019 8:04 AM
    Friday, August 2, 2019 9:26 PM
  • If you have the device identifier (the HID\xxx string), you can use CM_Locate_DevNode to fetch a DEVINST handle, then CM_Get_Parent to fetch the parent, then CM_Get_DevNode_Property to fetch the location.

    Tim Roberts | Driver MVP Emeritus | Providenza & Boekelheide, Inc.

       One message missing,I can't send pictures, I can only send text.The following is the information shown in UsbTreeView ,The information I want to get is the content of the  Loation Info ("Port_ 0003. Hub_ 0003").

    ======================== USB Device ========================

            +++++++++++++++++ Device Information ++++++++++++++++++
    Device Description       : USB 输入设备
    Device Path              : \\?\usb#vid_0318&pid_0636#s#{a5dcbf10-6530-11d2-901f-00c04fb951ed}
    Device ID                : USB\VID_0318&PID_0636\S
    Hardware IDs             : USB\VID_0318&PID_0636&REV_0200 USB\VID_0318&PID_0636
    Driver KeyName           : {745a17a0-74d3-11d0-b6fe-00a0c90f57da}\0042 (GUID_DEVCLASS_HIDCLASS)
    Driver                   : system32\DRIVERS\hidusb.sys (Version: 6.1.7601.17514  Date: 2010-11-21)
    Driver Inf               : C:\Windows\inf\input.inf
    Legacy BusType           : PNPBus
    Class                    : HIDClass
    Class GUID               : {745a17a0-74d3-11d0-b6fe-00a0c90f57da} (GUID_DEVCLASS_HIDCLASS)
    Interface GUID           : {a5dcbf10-6530-11d2-901f-00c04fb951ed} (GUID_DEVINTERFACE_USB_DEVICE)
    Service                  : HidUsb
    Enumerator               : USB
    Location Info            : Port_#0003.Hub_#0003   +++++++++++++++++++++++++
    Location IDs             : PCIROOT(0)#PCI(1300)#USBROOT(0)#USB(3)
    Container ID             : {26cb9062-d98d-5780-8339-77b1d86e2628}
    Manufacturer Info        : (标准系统设备)
    Capabilities             : 0x94 (Removable, UniqueID, SurpriseRemovalOK)
    Status                   : 0x0180600A (DN_DRIVER_LOADED, DN_STARTED, DN_DISABLEABLE, DN_REMOVABLE, DN_NT_ENUMERATOR, DN_NT_DRIVER)
    Problem Code             : 0
    Power State              : D0 (supported: D0, D2, D3, wake from D0, wake from D2)
    ************************************************************************
     Child Device 1          : HID-compliant device
      DevicePath             : \\?\HID#VID_0318&PID_0636#6&31faab91&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}
      KernelName             : \Device\0000007d
      Device ID              : HID\VID_0318&PID_0636\6&31FAAB91&0&0000
      Class                  : HIDClass


    Monday, August 5, 2019 12:49 AM
  • Right.  I just told you how to do that.

    Tim Roberts | Driver MVP Emeritus | Providenza & Boekelheide, Inc.

    Monday, August 5, 2019 5:19 AM
  • As Tim Roberts said, use CM_* APIs

    I tested with :

           [DllImport("CfgMgr32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            public static extern int CM_Get_Parent(ref IntPtr pdnDevInst, IntPtr dnDevInst, uint ulFlags);
    
           [DllImport("CfgMgr32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            public static extern int CM_Get_DevNode_Registry_Property(IntPtr dnDevInst, uint ulProperty, ref uint pulRegDataType, IntPtr Buffer, ref uint pulLength, uint ulFlags);
    

    and it works (on Windows 10, VS 2015)

    I get on my HID class : Port_#0008.Hub_#0003

    Monday, August 5, 2019 9:04 AM
  • As Tim Roberts said, use CM_* APIs

    I tested with :

           [DllImport("CfgMgr32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            public static extern int CM_Get_Parent(ref IntPtr pdnDevInst, IntPtr dnDevInst, uint ulFlags);
    
           [DllImport("CfgMgr32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            public static extern int CM_Get_DevNode_Registry_Property(IntPtr dnDevInst, uint ulProperty, ref uint pulRegDataType, IntPtr Buffer, ref uint pulLength, uint ulFlags);

    and it works (on Windows 10, VS 2015)

    I get on my HID class : Port_#0008.Hub_#0003

    Why didn't my code succeed? Is there a problem with this parameter? I don't know how to get the deviceId parameter(CM_Locate_DevNode(ref IntPtr deviceHandle,uint deviceId,
                uint flags);). Here's my code. Can I see the code you tested?

    SP_DEVINFO_DATA deviceInfoData = new SP_DEVINFO_DATA(); deviceInfoData.cbSize = (uint)Marshal.SizeOf(typeof(SP_DEVINFO_DATA)); bool success = SetupDiEnumDeviceInfo(DeviceInfoSet, iMemberIndex, ref deviceInfoData);

    uint dnDevInst = 0; int result = CM_Locate_DevNode(ref dnDevInst, deviceInfoData.DevInst, 0); uint cmret = 0; uint pdnDevInst = 0; cmret = CM_Get_Parent(out pdnDevInst, dnDevInst, 0);




    Tuesday, August 6, 2019 2:03 AM
  • You aren't reading the documentation.  CM_Locate_DevNode takes a STRING and converts it into a DEVINST handle.  If you already have a DEVINST handle, which you do, you don't need CM_Locate_DevNode.  Just pass the handle into CM_Get_Parent.

    That's one of the problems of doing this kind of stuff in C# with P/Invoke; the compiler doesn't point out your silly type errors.


    Tim Roberts | Driver MVP Emeritus | Providenza & Boekelheide, Inc.

    Tuesday, August 6, 2019 3:30 AM
  • You aren't reading the documentation.  CM_Locate_DevNode takes a STRING and converts it into a DEVINST handle.  If you already have a DEVINST handle, which you do, you don't need CM_Locate_DevNode.  Just pass the handle into CM_Get_Parent.

    That's one of the problems of doing this kind of stuff in C# with P/Invoke; the compiler doesn't point out your silly type errors.


    Tim Roberts | Driver MVP Emeritus | Providenza & Boekelheide, Inc.

    My mother tongue is not English, so I don't understand the document very well. I can't find some simple problems. Thank you for your help. I just succeeded. Thank you again!
    Tuesday, August 6, 2019 8:04 AM
  • Thank you for your help
    Wednesday, August 7, 2019 3:14 AM