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
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.