SetupDiEnumDeviceInterfaces Fails with Error 259, and a Solution
Last updated : 27-May-2019
If you reached this page, you've been trying to get SetupDiEnumDeviceInterfaces to work, and you're probably tearing your hair out by now.
The problem
When working with USB devices, it's often needed to identify the device path and other parameters. Various SetupDi_ API functions are called in sequence to do this.
SetupDiEnumDeviceInterfaces args appear to be correct, the Device Manager reports the device(s) as functional, but the call always fails with error 259.
Let's see if we can clarify this for you!
Suppose that we want to identify all the cameras in the Imaging Devices class, with the aim of getting the device path strings.
The usual calling sequence starts with
SetupDiGetClassDevs(...)
This gets the HDEVINFO to a list of the devices. This is where the problem starts...the GUID used (or not used) has to be correct, and the Microsoft help is particularly unclear.
Include file devguid.h contains a set of GUID_DEVCLASS values. These are NOT the same as GUID_DEVINTERFACE_* values which are the one you need. GUID_DEVCLASS values are used when installing devices.
You can use the Device Manager to get the Device Class GUID for a USB device. For Imaging Device class devices, this is the same value found in devguid.h.
Look at the content of devguid.h we can see that GUIDs
GUID_DEVCLASS_IMAGE and GUID_DEVCLASS_MEDIA
are relevent to Imaging devices.
Consider this code fragment:
|
SetupDiEnumDeviceInterfaces returns FALSE and dwError = 259 ( "No more data is available" )
What's wrong?
The problem here is the GUID used in SetupDiGetClassDevs , with the DIGCF_DEVICEINTERFACE flag.
guid has to be a GUID_DEVINTERFACE value, NOT a GUID_DEVCLASS value. Looking in usbiodef.h we find GUID_DEVINTERFACE_USB_HUB, GUID_DEVINTERFACE_USB_DEVICE, and GUID_DEVINTERFACE_USB_HOST_CONTROLLER.
The correct code is
|
which now returns TRUE and fills ifData because guid is the correct one when the DIGCF_DEVICEINTERFACE flag is used.
Locating all the devices requires a loop on SetupDiEnumDeviceInterfaces , and calling SetupDiGetDeviceInterfaceDetail internally.
e.g. repeated calls to SetupDiEnumDeviceInterfaces gets device info until an error occurs and the loop exits.
|
Discussion:
If you are working with HID devices, then we can call
HidD_GetHidGuid(&guid); which returns the HID device interface class GUID.
hidGuid {4D1E55B2-F16F-11CF-88CB-001111000030}
found
in the
Registry, also see below
testGuid {745A17A0-74D3-11D0-B6FE-00A0C90F57DA}
found in devguid.h
The first arg for SetupDiGetClassDevs is
The clue here (and poorly explained in the function help) is that you can use values that are mutually exclusive. If you are calling
Poking around with Regedit can be instructive too. See
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\DeviceDisplayObjects and sub keys.
The returned value of hidGuid, as above, is found in
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\DeviceClasses. In hidGuid key we find entries like
##?#HID#VID_0483&PID_5750#6&137c9d83&0&0000#{4d1e55b2-f16f-11cf-88cb-001111000030} i.e. an HID device, as expected.
Let's define vidGuid for our video devices. We can search for the camera VID/PID entry, and we find
vidGuid = {65E8773D-8F56-11D0-A3B9-00A0C9223196};
with subkeys of all the video devices. Put another way, {65E8773D-8F56-11D0-A3B9-00A0C9223196} is the Windows Imaging Devices device interface class GUID.
You would think this GUID is declared in an
include file, and sure enough it is. See ksuuids.h it's declared as
AM_KSCATEGORY_CAPTURE
here "AM" refers to "ActiveMovie", now known as
DirectShow.
Add
#include <uuids.h> to your code. ksuuids.h is included by this.Here's a couple of helper functions for the Imaging Device class, similar to HidD_GetHidGuid(GUID*);
|
Copyright © 2012-2019 PiXCL Automation Technologies Inc, Canada. All Rights Reserved.