3

I am tasked with finding a way to detect a faulty or missing driver so that my program can then install a better one that will work with my system. Things I have been trying include using setupapi.dll to get values from the Registry and try to find some flag that will let me know there is a problem with the driver. On MSDN I found that the Class GUID for "Other Devices" is 4d36e97e-e325-11ce-bfc1-08002be10318. However if I try to enumerate those devices I get nothing, even if I see devices in that category under the device manager. Is there another Windows API that could give me some way of identifying devices in this category or driver errors in general? My code looks like:

static void Main(string[] args)
{
    Guid displayClass = new Guid("4d36e97e-e325-11ce-bfc1-08002be10318");
    SafeDevInfoHandle hDevInfo = NativeMethods.SetupDiGetClassDevs(ref displayClass,
                null, IntPtr.Zero, DIGetClassFlags.DIGCF_PRESENT);

    if (hDevInfo.IsInvalid)
        throw new Win32Exception();

    DevInfoData did = new DevInfoData();
    did.size = Marshal.SizeOf(did);

    for (uint i = 0; NativeMethods.SetupDiEnumDeviceInfo(hDevInfo, i, ref did); i++)
    {
        if (NativeMethods.SetupDiBuildDriverInfoList(hDevInfo, ref did, DriverType.SPDIT_COMPATDRIVER))
        {
            DriverInfoData drvData = new DriverInfoData();
            drvData.Size = Marshal.SizeOf(drvData);

            for (uint j = 0; NativeMethods.SetupDiEnumDriverInfo(hDevInfo, ref did, DriverType.SPDIT_COMPATDRIVER, j, ref drvData); j++)
            {
                Console.WriteLine(drvData.ToString());
            }
        }
        else
        {
            throw new Win32Exception();
        }
    }
}

I've also tried using SetupDiGetDeviceRegistryProperty to get specific properties, but for a lot of devices not all properties are present. I would love to be able to make a call to this and have it return SPDRP_INSTALL_STATE but I've yet to receive an actual response with this call.

Thomas Weller
  • 55,411
  • 20
  • 125
  • 222
  • To clarify, is the problem that the call to `SetupDiEnumDeviceInfo` returns `FALSE` on the first call (when `i` is zero) with error code `ERROR_NO_MORE_ITEMS` ? Have you tried with a known GUID, e.g., `GUID_DEVCLASS_MOUSE`, to make sure you code is working as expected? – Harry Johnston May 21 '15 at 22:15
  • You can enumerate all devices by using the `DIGCF_ALLCLASSES` and passing `NULL` for the GUID. If you can find your device that way, you can look up the GUID to see what it is. Another thought: it might be `DIGCF_PRESENT` that's messing you up; I'm not sure whether a device with no driver is considered to be "present" or not in this context. – Harry Johnston May 21 '15 at 22:18
  • @HarryJohnston I think you may be right about `DIGCF_PRESENT` not applying to missing drivers, but if I try to use `DIGCF_ALLCLASSES` it doesn't seem to return a valid device handle. As to your first question the call to `SetupDiEnumDeviceInfo` returns true and works just fine with the GUID's I pass in, except for when I try to enumerate info for "Other Devices", or the "Unknown" class nothing comes up. – Drew-Sypher May 26 '15 at 20:32
  • `DIGCF_ALLCLASSES` seems to be working fine for me, see http://www.cms.waikato.ac.nz/~harry/allclasses.c – Harry Johnston May 26 '15 at 21:48
  • @HarryJohnston Ok I got that working however it returns every driver I have installed on my machine. I'm looking to see devices in the "Unknown" category, devices that may not have a driver installed. – Drew-Sypher May 27 '15 at 16:07
  • The code I posted doesn't enumerate drivers, it enumerates devices. On my test machine, at least, it seems to include devices with no driver installed. (Specifically: there were a few devices with no driver installed, for reasons that don't matter right now. I ran my code before and after installing drivers, and the list was the same - except that installing the USB3 driver added the root hub as a new device, but that's to be expected.) – Harry Johnston May 27 '15 at 21:01

1 Answers1

2

The documentation for SetupDiGetClassDevs contains sample code (example 5) for enumerating "Other Devices" and contains the following note:

You cannot set the ClassGuid parameter to GUID_DEVCLASS_UNKNOWN to detect devices with an unknown setup class. Instead, you must follow this example.

Looking up GUID_DEVCLASS_UNKNOWN in the DDK, it is the same GUID in your posted code. So the approach you were trying to use is documented to not work.

Instead, enumerate all devices using the DIGCF_ALLCLASSES option, and look up the device class for each one. According to the example code, for the devices you're interested in, looking up the device class will fail with ERROR_NOT_FOUND.

(Depending on what exactly you're trying to achieve, there may be other approaches that would work better, e.g., you could try looking up DEVPKEY_Device_ProblemCode for each device. I'm not really familiar with all of the possibilities.)

Harry Johnston
  • 35,639
  • 6
  • 68
  • 158