2

I have been trying to interface to a device driver for a GPS interface card. The examples that I have from the vendor are in C++. I am trying to get it working in C# using pinvoke

class HaveQuick
{
    [DllImport("setupapi.dll", CharSet = CharSet.Auto)]
    static extern IntPtr SetupDiGetClassDevs(
        ref Guid ClassGuid,
        IntPtr Enumerator,
        IntPtr hwndParent,
        uint Flags
        );

    [DllImport(@"setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern Boolean SetupDiEnumDeviceInterfaces(
       IntPtr hDevInfo,
       ref SP_DEVINFO_DATA devInfo,
       ref Guid interfaceClassGuid,
       UInt32 memberIndex,
       ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData
    );

        Guid GUID_DEVINTERFACE_IPHQT = new Guid(0x13ff045f, 0xe9d2, 0x479c, 0xb3, 0x90, 0x8c, 0xae, 0xc7, 0xd1, 0x1c, 0xc4);
        hDeviceInfo = SetupDiGetClassDevs(ref GUID_DEVINTERFACE_IPHQT, IntPtr.Zero, IntPtr.Zero, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
        if (hDeviceInfo == IntPtr.Zero)
        {
            lastError = Marshal.GetLastWin32Error();
            Console.WriteLine("**Error: couldn't get class info error code = {0}\n");
            return;
        }

             // Find the interface for device
        devNum = 0x0000;    
        SP_DEVICE_INTERFACE_DATA interfaceData = new SP_DEVICE_INTERFACE_DATA();                // Interface data for this device
        interfaceData.cbSize = (uint)Marshal.SizeOf(interfaceData);
        SP_DEVINFO_DATA deviceInfoData = new SP_DEVINFO_DATA();
        deviceInfoData.cbSize = (uint)Marshal.SizeOf(deviceInfoData);
        success = SetupDiEnumDeviceInterfaces(hDeviceInfo, ref deviceInfoData, ref GUID_DEVINTERFACE_IPHQT, devNum, ref interfaceData);
        if (!success)
        {
            lastError = Marshal.GetLastWin32Error();
            Console.WriteLine("**Error: couldn't enum device error number = {0}\n", lastError);

}

When I run the code I get lasterror = 87 which is Invalid Parameter

If I replace with this line of code success = SetupDiEnumDeviceInterfaces(hDeviceInfo, IntPtr.Zero, ref GUID_DEVINTERFACE_IPHQT, devNum, ref interfaceData);

I get lasterror = 1784 Invlid user buffer.

Thanks for the help

ed askew
  • 123
  • 1
  • 10
  • If you want help with the Invalid user buffer error, you probably should post a new question. Include the C++ prototypes for the functions, and the C++ and C# versions of the structures you're using. – Jim Mischel Nov 27 '12 at 15:23

1 Answers1

0

Your SetupDiGetClassDevs prototype doesn't have SetLastError=true. So the call to Marshal.GetLastWin32Error might not be getting the correct value. Also, you shouldn't check the last error unless the value returned from the call is invalid.

As the documentation for GetLastError says:

You should call the GetLastError function immediately when a function's return value indicates that such a call will return useful data.

So the pattern to use Marshal.GetLastWin32Error should be:

IntPtr hDeviceInfo = SetupDiGetClassDevs( ... );
if (hDeviceInfo == IntPtr.Zero)
{
    // error here
    lastError = Marshal.GetLastWin32Error();
}

If you check the last error when there was no error, there's no telling what value you'll get. Not all functions call SetLastError with a value of 0 when they succeed. So you might be getting an error from long ago.

Jim Mischel
  • 131,090
  • 20
  • 188
  • 351
  • Thanks @Jim Mischel That was it. So my problem is then when I get the Device interface – ed askew Nov 27 '12 at 15:03
  • By the way, `IntPtr.Zero` might not be the value to check for. Some functions use `-1` as the invalid handle value (because 0 can be a valid handle in some cases). – Jim Mischel Nov 27 '12 at 15:19