Help With PInvoke and SetupDiEnumDriverInfo/SP_DRVINFO_DATA

R

Rymfax

I would really appreciate it if someone could help me figure out what
I'm doing wrong trying to PInvoke SetupDiEnumDriverInfo. All the
other PInvokes i've done up to this point work fine. Whenver I
PInvoke SetupDiEnumDriverInfo though, I get winerror.h code of 1784L,
which basically says it doesn't like my buffer, which I assume is the
structure.

Below is my PInvoke, my structure and a sample of my code. Please,
please PLEASE help me!

[DllImport("setupapi.dll", SetLastError = true)]
private static extern bool SetupDiEnumDriverInfo(IntPtr
DeviceInfoSet,
ref SP_DEVINFO_DATA DeviceInfoData, int DriverType, int
MemberIndex,
ref SP_DRVINFO_DATA DriverInfoData);

[StructLayout(LayoutKind.Sequential)]
public struct SP_DRVINFO_DATA
{
public int cbSize;
public int DriverType;
public IntPtr Reserved;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string Description;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string MfgName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string ProviderName;
public System.Runtime.InteropServices.ComTypes.FILETIME
DriverDate;
public long DriverVersion;
}

void EnumerateDriverList(IntPtr devInfoSet, SP_DEVINFO_DATA
devInfoData)
{
int memIndex = 0;
int drvErr = 0;
SP_DRVINFO_DATA drvData = new SP_DRVINFO_DATA();
drvData.cbSize = Marshal.SizeOf(typeof(SP_DRVINFO_DATA));
bool enumResult = SetupDiEnumDriverInfo(devInfoSet, ref
devInfoData, SPDIT_COMPATDRIVER,
memIndex, ref drvData);
if(!enumResult) drvErr = Marshal.GetLastWin32Error();
while (enumResult && drvErr != ERROR_NO_MORE_ITEMS)
{
// Never Gets to this point.
}
}
 
W

Willy Denoyette [MVP]

Rymfax said:
I would really appreciate it if someone could help me figure out what
I'm doing wrong trying to PInvoke SetupDiEnumDriverInfo. All the
other PInvokes i've done up to this point work fine. Whenver I
PInvoke SetupDiEnumDriverInfo though, I get winerror.h code of 1784L,
which basically says it doesn't like my buffer, which I assume is the
structure.

Below is my PInvoke, my structure and a sample of my code. Please,
please PLEASE help me!

[DllImport("setupapi.dll", SetLastError = true)]
private static extern bool SetupDiEnumDriverInfo(IntPtr
DeviceInfoSet,
ref SP_DEVINFO_DATA DeviceInfoData, int DriverType, int
MemberIndex,
ref SP_DRVINFO_DATA DriverInfoData);

[StructLayout(LayoutKind.Sequential)]
public struct SP_DRVINFO_DATA
{
public int cbSize;
public int DriverType;
public IntPtr Reserved;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string Description;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string MfgName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string ProviderName;
public System.Runtime.InteropServices.ComTypes.FILETIME
DriverDate;
public long DriverVersion;
}

void EnumerateDriverList(IntPtr devInfoSet, SP_DEVINFO_DATA
devInfoData)
{
int memIndex = 0;
int drvErr = 0;
SP_DRVINFO_DATA drvData = new SP_DRVINFO_DATA();
drvData.cbSize = Marshal.SizeOf(typeof(SP_DRVINFO_DATA));
bool enumResult = SetupDiEnumDriverInfo(devInfoSet, ref
devInfoData, SPDIT_COMPATDRIVER,
memIndex, ref drvData);
if(!enumResult) drvErr = Marshal.GetLastWin32Error();
while (enumResult && drvErr != ERROR_NO_MORE_ITEMS)
{
// Never Gets to this point.
}
}



Try using the Unicode function by specifying [DllImport( setupapi), CharSet =
CharSet.Unicode,..]
and do the same to your structure declarations...
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]

Willy.
 
R

Rymfax

Willy,

I made that change and I still get the 1784L error. I'm wondering if
the problem is not with SP_DRVINFO_DATA (cause I have written that
thing every possible way I can think of), but with some other
structure or DllImport I'm using further up the chain. I'm literally
at my whits end on this. I have very similar code in C++ that works
just fine. I'm posting a C# class that has everything I'm doing in
it. I would be VERY grateful if you could take a look at it and see
if you see a problem. As above, everything works fine until it gets
to SetupDiEnumDriverInfo.

Thanks a ton!


--- CODE START ----
class GroupExample
{
public const int CR_SUCCESS = (0x00000000);
public const int DIGCF_PRESENT = (0x00000002);
public const int DIGCF_ALLCLASSES = (0x00000004);

public const int ERROR_NO_MORE_ITEMS = 259;

public const int SPDIT_COMPATDRIVER = (0x00000002);
public const int SPDIT_CLASSDRIVER = (0x00000001);

[StructLayout(LayoutKind.Sequential, CharSet =
CharSet.Unicode)]
public struct SP_DEVINFO_DATA
{
public int cbSize;
public Guid ClassGuid;
public IntPtr DevInst;
public int Reserved;
}

[StructLayout(LayoutKind.Sequential, CharSet =
CharSet.Unicode)]
public struct SP_DRVINSTALL_PARAMS
{
public int cbSize;
public int Rank;
public int Flags;
public int PrivateData;
public int Reserved;
}
[StructLayout(LayoutKind.Sequential, CharSet =
CharSet.Unicode)]
public struct SP_DEVINSTALL_PARAMS
{
public int cbSize;
public int Flags;
public int FlagsEx;
public IntPtr HwndParent;
public IntPtr InstallMsgHandler;
public IntPtr InstallMsgHandlerContext;
public IntPtr FileQueue;
public ulong CallInstallReserved;
public int Reserved;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string DriverPath;

}

[StructLayout(LayoutKind.Sequential, CharSet =
CharSet.Unicode)]
public struct SP_DRVINFO_DATA
{
public int cbSize;
public int DriverType;
public ulong Reserved;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string Description;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string MfgName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string ProviderName;
public System.Runtime.InteropServices.ComTypes.FILETIME
DriverDate;
public ulong DriverVersion;
}

[DllImport("setupapi.dll", SetLastError = true, CharSet =
CharSet.Unicode)]
public static extern Boolean
SetupDiDestroyDeviceInfoList(IntPtr DeviceInfoSet);

[DllImport("setupapi.dll", SetLastError = true, CharSet =
CharSet.Unicode)]
public static extern IntPtr SetupDiGetClassDevs(ref Guid
ClassGuid, IntPtr Enumerator,
IntPtr hwndParent, int Flags);

[DllImport("setupapi.dll", SetLastError = true, CharSet =
CharSet.Unicode)]
public static extern bool SetupDiEnumDeviceInfo(IntPtr
DeviceInfoSet, int MemberIndex,
ref SP_DEVINFO_DATA DeviceInfoData);

[DllImport("cfgmgr32.dll", SetLastError = true, CharSet =
CharSet.Unicode)]
private static extern int CM_Get_DevNode_Status(ref ulong
status, ref ulong probNum,
IntPtr devInst, int Flag);

[DllImport("setupapi.dll", SetLastError = true, CharSet =
CharSet.Unicode)]
public static extern bool
SetupDiGetDeviceRegistryProperty(IntPtr DeviceInfoSet,
ref SP_DEVINFO_DATA DeviceInfoData, int Property, ref int
PropertyRegDataType,
StringBuilder PropertyBuffer, int PropertyBufferSize, ref
int RequiredSize);

[DllImport("setupapi.dll", SetLastError = true, CharSet =
CharSet.Unicode)]
public static extern bool SetupDiGetDeviceInstallParams(IntPtr
DeviceInfoSet,
ref SP_DEVINFO_DATA DeviceInfoData, ref
SP_DEVINSTALL_PARAMS DeviceInstallParams);

[DllImport("setupapi.dll", SetLastError = true, CharSet =
CharSet.Unicode)]
private static extern bool SetupDiDestroyDriverInfoList(IntPtr
DeviceInfoSet,
ref SP_DEVINFO_DATA DeviceInfoData, int DriverType);

[DllImport("setupapi.dll", SetLastError = true, CharSet =
CharSet.Unicode)]
private static extern bool SetupDiBuildDriverInfoList(IntPtr
DeviceInfoSet,
ref SP_DEVINFO_DATA DeviceInfoData, int DriverType);

[DllImport("setupapi.dll", SetLastError = true, CharSet =
CharSet.Unicode)]
private static extern bool SetupDiEnumDriverInfo(IntPtr
DeviceInfoSet,
ref SP_DEVINFO_DATA DeviceInfoData, int DriverType, int
MemberIndex,
ref SP_DRVINFO_DATA DriverInfoData);

public void RunExample()
{
Guid newG = Guid.Empty;
IntPtr NewDeviceInfoSet = SetupDiGetClassDevs(ref newG,
IntPtr.Zero, IntPtr.Zero,
DIGCF_ALLCLASSES);
SP_DEVINFO_DATA DeviceInfoData = new SP_DEVINFO_DATA();
DeviceInfoData.cbSize =
Marshal.SizeOf(typeof(SP_DEVINFO_DATA));
int deviceCounter = 0;
bool devInfoRetVal =
SetupDiEnumDeviceInfo(NewDeviceInfoSet, deviceCounter, ref
DeviceInfoData);
int devInfoErr = Marshal.GetLastWin32Error();
while (devInfoRetVal && devInfoErr != ERROR_NO_MORE_ITEMS
&& deviceCounter < 3) // < 3 is to keep the loop short for testing
{
ulong status = 0;
ulong problem = 0;
if (CM_Get_DevNode_Status(ref status, ref problem,
DeviceInfoData.DevInst, 0) == CR_SUCCESS)
{
StringBuilder sbDesc = new StringBuilder("");
int MAX_LEN = 512;
int propRegDataType = 0;
sbDesc.Capacity = MAX_LEN;
int reqSize = 0;
SetupDiGetDeviceRegistryProperty(NewDeviceInfoSet,
ref DeviceInfoData,
(int)Setup.SPDRPCodes.SPDRP_FRIENDLYNAME, ref
propRegDataType, sbDesc,
MAX_LEN, ref reqSize);
if (sbDesc.ToString() == "")
{

SetupDiGetDeviceRegistryProperty(NewDeviceInfoSet, ref DeviceInfoData,
(int)Setup.SPDRPCodes.SPDRP_DEVICEDESC,
ref propRegDataType, sbDesc,
MAX_LEN, ref reqSize);
}
if (sbDesc.ToString() == "")
sbDesc.Append("Unknown Description");
StringBuilder sbHWID = new StringBuilder("");
sbHWID.Capacity = MAX_LEN;
SetupDiGetDeviceRegistryProperty(NewDeviceInfoSet,
ref DeviceInfoData,
(int)Setup.SPDRPCodes.SPDRP_HARDWAREID, ref
propRegDataType, sbHWID,
MAX_LEN, ref reqSize);
ScanResults scanResult = new
ScanResults(sbHWID.ToString(), sbDesc.ToString());
Console.WriteLine("Device Detected: {0} - {1}",
sbDesc.ToString(), sbHWID.ToString());

SP_DEVINSTALL_PARAMS deviceInstallParams = new
SP_DEVINSTALL_PARAMS();
deviceInstallParams.cbSize =
Marshal.SizeOf(typeof(SP_DEVINSTALL_PARAMS));
SetupDiGetDeviceInstallParams(NewDeviceInfoSet,
ref DeviceInfoData,
ref deviceInstallParams);
deviceInstallParams.DriverPath = @"C:
\MyDriverPath";
if (!SetupDiBuildDriverInfoList(NewDeviceInfoSet,
ref DeviceInfoData, SPDIT_COMPATDRIVER))
{
int eCode = Marshal.GetLastWin32Error();
Console.WriteLine("\tError Building Driver
Info List. Code: {0}", eCode);
}
int memIndex = 0;
int drvErr = 0;
SP_DRVINFO_DATA drvData = new SP_DRVINFO_DATA();
drvData.cbSize =
Marshal.SizeOf(typeof(SP_DRVINFO_DATA));
bool enumResult =
SetupDiEnumDriverInfo(NewDeviceInfoSet, ref DeviceInfoData,
SPDIT_COMPATDRIVER,
memIndex, ref drvData);
if (!enumResult)
{
drvErr = Marshal.GetLastWin32Error();
Console.WriteLine("\tError Enumerating Driver
Info. Code: {0}", drvErr);
}
while (enumResult && drvErr !=
ERROR_NO_MORE_ITEMS)
{
memIndex++;

}
SetupDiDestroyDriverInfoList(NewDeviceInfoSet, ref
DeviceInfoData, SPDIT_COMPATDRIVER);
}
deviceCounter++;
devInfoRetVal =
SetupDiEnumDeviceInfo(NewDeviceInfoSet, deviceCounter, ref
DeviceInfoData);
devInfoErr = Marshal.GetLastWin32Error();
}
SetupDiDestroyDeviceInfoList(NewDeviceInfoSet);
}
}
--- CODE END ---
 
W

Willy Denoyette [MVP]

Rymfax said:
Willy,

I made that change and I still get the 1784L error. I'm wondering if
the problem is not with SP_DRVINFO_DATA (cause I have written that
thing every possible way I can think of), but with some other
structure or DllImport I'm using further up the chain. I'm literally
at my whits end on this. I have very similar code in C++ that works
just fine. I'm posting a C# class that has everything I'm doing in
it. I would be VERY grateful if you could take a look at it and see
if you see a problem. As above, everything works fine until it gets
to SetupDiEnumDriverInfo.

Thanks a ton!


--- CODE START ----
class GroupExample
{
public const int CR_SUCCESS = (0x00000000);
public const int DIGCF_PRESENT = (0x00000002);
public const int DIGCF_ALLCLASSES = (0x00000004);

public const int ERROR_NO_MORE_ITEMS = 259;

public const int SPDIT_COMPATDRIVER = (0x00000002);
public const int SPDIT_CLASSDRIVER = (0x00000001);

[StructLayout(LayoutKind.Sequential, CharSet =
CharSet.Unicode)]
public struct SP_DEVINFO_DATA
{
public int cbSize;
public Guid ClassGuid;
public IntPtr DevInst;
public int Reserved;
}

[StructLayout(LayoutKind.Sequential, CharSet =
CharSet.Unicode)]
public struct SP_DRVINSTALL_PARAMS
{
public int cbSize;
public int Rank;
public int Flags;
public int PrivateData;
public int Reserved;
}
[StructLayout(LayoutKind.Sequential, CharSet =
CharSet.Unicode)]
public struct SP_DEVINSTALL_PARAMS
{
public int cbSize;
public int Flags;
public int FlagsEx;
public IntPtr HwndParent;
public IntPtr InstallMsgHandler;
public IntPtr InstallMsgHandlerContext;
public IntPtr FileQueue;
public ulong CallInstallReserved;
public int Reserved;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string DriverPath;

}

[StructLayout(LayoutKind.Sequential, CharSet =
CharSet.Unicode)]
public struct SP_DRVINFO_DATA
{
public int cbSize;
public int DriverType;
public ulong Reserved;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string Description;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string MfgName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string ProviderName;
public System.Runtime.InteropServices.ComTypes.FILETIME
DriverDate;
public ulong DriverVersion;
}

[DllImport("setupapi.dll", SetLastError = true, CharSet =
CharSet.Unicode)]
public static extern Boolean
SetupDiDestroyDeviceInfoList(IntPtr DeviceInfoSet);

[DllImport("setupapi.dll", SetLastError = true, CharSet =
CharSet.Unicode)]
public static extern IntPtr SetupDiGetClassDevs(ref Guid
ClassGuid, IntPtr Enumerator,
IntPtr hwndParent, int Flags);

[DllImport("setupapi.dll", SetLastError = true, CharSet =
CharSet.Unicode)]
public static extern bool SetupDiEnumDeviceInfo(IntPtr
DeviceInfoSet, int MemberIndex,
ref SP_DEVINFO_DATA DeviceInfoData);

[DllImport("cfgmgr32.dll", SetLastError = true, CharSet =
CharSet.Unicode)]
private static extern int CM_Get_DevNode_Status(ref ulong
status, ref ulong probNum,
IntPtr devInst, int Flag);

[DllImport("setupapi.dll", SetLastError = true, CharSet =
CharSet.Unicode)]
public static extern bool
SetupDiGetDeviceRegistryProperty(IntPtr DeviceInfoSet,
ref SP_DEVINFO_DATA DeviceInfoData, int Property, ref int
PropertyRegDataType,
StringBuilder PropertyBuffer, int PropertyBufferSize, ref
int RequiredSize);

[DllImport("setupapi.dll", SetLastError = true, CharSet =
CharSet.Unicode)]
public static extern bool SetupDiGetDeviceInstallParams(IntPtr
DeviceInfoSet,
ref SP_DEVINFO_DATA DeviceInfoData, ref
SP_DEVINSTALL_PARAMS DeviceInstallParams);

[DllImport("setupapi.dll", SetLastError = true, CharSet =
CharSet.Unicode)]
private static extern bool SetupDiDestroyDriverInfoList(IntPtr
DeviceInfoSet,
ref SP_DEVINFO_DATA DeviceInfoData, int DriverType);

[DllImport("setupapi.dll", SetLastError = true, CharSet =
CharSet.Unicode)]
private static extern bool SetupDiBuildDriverInfoList(IntPtr
DeviceInfoSet,
ref SP_DEVINFO_DATA DeviceInfoData, int DriverType);

[DllImport("setupapi.dll", SetLastError = true, CharSet =
CharSet.Unicode)]
private static extern bool SetupDiEnumDriverInfo(IntPtr
DeviceInfoSet,
ref SP_DEVINFO_DATA DeviceInfoData, int DriverType, int
MemberIndex,
ref SP_DRVINFO_DATA DriverInfoData);

public void RunExample()
{
Guid newG = Guid.Empty;
IntPtr NewDeviceInfoSet = SetupDiGetClassDevs(ref newG,
IntPtr.Zero, IntPtr.Zero,
DIGCF_ALLCLASSES);
SP_DEVINFO_DATA DeviceInfoData = new SP_DEVINFO_DATA();
DeviceInfoData.cbSize =
Marshal.SizeOf(typeof(SP_DEVINFO_DATA));
int deviceCounter = 0;
bool devInfoRetVal =
SetupDiEnumDeviceInfo(NewDeviceInfoSet, deviceCounter, ref
DeviceInfoData);
int devInfoErr = Marshal.GetLastWin32Error();
while (devInfoRetVal && devInfoErr != ERROR_NO_MORE_ITEMS
&& deviceCounter < 3) // < 3 is to keep the loop short for testing
{
ulong status = 0;
ulong problem = 0;
if (CM_Get_DevNode_Status(ref status, ref problem,
DeviceInfoData.DevInst, 0) == CR_SUCCESS)
{
StringBuilder sbDesc = new StringBuilder("");
int MAX_LEN = 512;
int propRegDataType = 0;
sbDesc.Capacity = MAX_LEN;
int reqSize = 0;
SetupDiGetDeviceRegistryProperty(NewDeviceInfoSet,
ref DeviceInfoData,
(int)Setup.SPDRPCodes.SPDRP_FRIENDLYNAME, ref
propRegDataType, sbDesc,
MAX_LEN, ref reqSize);
if (sbDesc.ToString() == "")
{

SetupDiGetDeviceRegistryProperty(NewDeviceInfoSet, ref DeviceInfoData,
(int)Setup.SPDRPCodes.SPDRP_DEVICEDESC,
ref propRegDataType, sbDesc,
MAX_LEN, ref reqSize);
}
if (sbDesc.ToString() == "")
sbDesc.Append("Unknown Description");
StringBuilder sbHWID = new StringBuilder("");
sbHWID.Capacity = MAX_LEN;
SetupDiGetDeviceRegistryProperty(NewDeviceInfoSet,
ref DeviceInfoData,
(int)Setup.SPDRPCodes.SPDRP_HARDWAREID, ref
propRegDataType, sbHWID,
MAX_LEN, ref reqSize);
ScanResults scanResult = new
ScanResults(sbHWID.ToString(), sbDesc.ToString());
Console.WriteLine("Device Detected: {0} - {1}",
sbDesc.ToString(), sbHWID.ToString());

SP_DEVINSTALL_PARAMS deviceInstallParams = new
SP_DEVINSTALL_PARAMS();
deviceInstallParams.cbSize =
Marshal.SizeOf(typeof(SP_DEVINSTALL_PARAMS));
SetupDiGetDeviceInstallParams(NewDeviceInfoSet,
ref DeviceInfoData,
ref deviceInstallParams);
deviceInstallParams.DriverPath = @"C:
\MyDriverPath";
if (!SetupDiBuildDriverInfoList(NewDeviceInfoSet,
ref DeviceInfoData, SPDIT_COMPATDRIVER))
{
int eCode = Marshal.GetLastWin32Error();
Console.WriteLine("\tError Building Driver
Info List. Code: {0}", eCode);
}
int memIndex = 0;
int drvErr = 0;
SP_DRVINFO_DATA drvData = new SP_DRVINFO_DATA();
drvData.cbSize =
Marshal.SizeOf(typeof(SP_DRVINFO_DATA));
bool enumResult =
SetupDiEnumDriverInfo(NewDeviceInfoSet, ref DeviceInfoData,
SPDIT_COMPATDRIVER,
memIndex, ref drvData);
if (!enumResult)
{
drvErr = Marshal.GetLastWin32Error();
Console.WriteLine("\tError Enumerating Driver
Info. Code: {0}", drvErr);
}
while (enumResult && drvErr !=
ERROR_NO_MORE_ITEMS)
{
memIndex++;

}
SetupDiDestroyDriverInfoList(NewDeviceInfoSet, ref
DeviceInfoData, SPDIT_COMPATDRIVER);
}
deviceCounter++;
devInfoRetVal =
SetupDiEnumDeviceInfo(NewDeviceInfoSet, deviceCounter, ref
DeviceInfoData);
devInfoErr = Marshal.GetLastWin32Error();
}
SetupDiDestroyDeviceInfoList(NewDeviceInfoSet);
}
}
--- CODE END ---

Your struct should look like this (partly):

[StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)] <-----1
public struct SP_DRVINFO_DATA
{
public int cbSize;
public int DriverType;
public IntPtr Reserved; <--------------2

1) You need to use the correct Packing (the same as the packing used by the C structure in
the setupapi.h).
2) Why did you change this into a ulong?

Note that I diddn't check the other structs!!!!



WIlly.
 
R

Rymfax

I made that change and I still get the 1784L error. I'm wondering if
the problem is not with SP_DRVINFO_DATA (cause I have written that
thing every possible way I can think of), but with some other
structure or DllImport I'm using further up the chain. I'm literally
at my whits end on this. I have very similar code in C++ that works
just fine. I'm posting a C# class that has everything I'm doing in
it. I would be VERY grateful if you could take a look at it and see
if you see a problem. As above, everything works fine until it gets
to SetupDiEnumDriverInfo.
Thanks a ton!
--- CODE START ----
class GroupExample
{
public const int CR_SUCCESS = (0x00000000);
public const int DIGCF_PRESENT = (0x00000002);
public const int DIGCF_ALLCLASSES = (0x00000004);
public const int ERROR_NO_MORE_ITEMS = 259;
public const int SPDIT_COMPATDRIVER = (0x00000002);
public const int SPDIT_CLASSDRIVER = (0x00000001);
[StructLayout(LayoutKind.Sequential, CharSet =
CharSet.Unicode)]
public struct SP_DEVINFO_DATA
{
public int cbSize;
public Guid ClassGuid;
public IntPtr DevInst;
public int Reserved;
}
[StructLayout(LayoutKind.Sequential, CharSet =
CharSet.Unicode)]
public struct SP_DRVINSTALL_PARAMS
{
public int cbSize;
public int Rank;
public int Flags;
public int PrivateData;
public int Reserved;
}
[StructLayout(LayoutKind.Sequential, CharSet =
CharSet.Unicode)]
public struct SP_DEVINSTALL_PARAMS
{
public int cbSize;
public int Flags;
public int FlagsEx;
public IntPtr HwndParent;
public IntPtr InstallMsgHandler;
public IntPtr InstallMsgHandlerContext;
public IntPtr FileQueue;
public ulong CallInstallReserved;
public int Reserved;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string DriverPath;

[StructLayout(LayoutKind.Sequential, CharSet =
CharSet.Unicode)]
public struct SP_DRVINFO_DATA
{
public int cbSize;
public int DriverType;
public ulong Reserved;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string Description;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string MfgName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string ProviderName;
public System.Runtime.InteropServices.ComTypes.FILETIME
DriverDate;
public ulong DriverVersion;
}
[DllImport("setupapi.dll", SetLastError = true, CharSet =
CharSet.Unicode)]
public static extern Boolean
SetupDiDestroyDeviceInfoList(IntPtr DeviceInfoSet);
[DllImport("setupapi.dll", SetLastError = true, CharSet =
CharSet.Unicode)]
public static extern IntPtr SetupDiGetClassDevs(ref Guid
ClassGuid, IntPtr Enumerator,
IntPtr hwndParent, int Flags);
[DllImport("setupapi.dll", SetLastError = true, CharSet =
CharSet.Unicode)]
public static extern bool SetupDiEnumDeviceInfo(IntPtr
DeviceInfoSet, int MemberIndex,
ref SP_DEVINFO_DATA DeviceInfoData);
[DllImport("cfgmgr32.dll", SetLastError = true, CharSet =
CharSet.Unicode)]
private static extern int CM_Get_DevNode_Status(ref ulong
status, ref ulong probNum,
IntPtr devInst, int Flag);
[DllImport("setupapi.dll", SetLastError = true, CharSet =
CharSet.Unicode)]
public static extern bool
SetupDiGetDeviceRegistryProperty(IntPtr DeviceInfoSet,
ref SP_DEVINFO_DATA DeviceInfoData, int Property, ref int
PropertyRegDataType,
StringBuilder PropertyBuffer, int PropertyBufferSize, ref
int RequiredSize);
[DllImport("setupapi.dll", SetLastError = true, CharSet =
CharSet.Unicode)]
public static extern bool SetupDiGetDeviceInstallParams(IntPtr
DeviceInfoSet,
ref SP_DEVINFO_DATA DeviceInfoData, ref
SP_DEVINSTALL_PARAMS DeviceInstallParams);
[DllImport("setupapi.dll", SetLastError = true, CharSet =
CharSet.Unicode)]
private static extern bool SetupDiDestroyDriverInfoList(IntPtr
DeviceInfoSet,
ref SP_DEVINFO_DATA DeviceInfoData, int DriverType);
[DllImport("setupapi.dll", SetLastError = true, CharSet =
CharSet.Unicode)]
private static extern bool SetupDiBuildDriverInfoList(IntPtr
DeviceInfoSet,
ref SP_DEVINFO_DATA DeviceInfoData, int DriverType);
[DllImport("setupapi.dll", SetLastError = true, CharSet =
CharSet.Unicode)]
private static extern bool SetupDiEnumDriverInfo(IntPtr
DeviceInfoSet,
ref SP_DEVINFO_DATA DeviceInfoData, int DriverType, int
MemberIndex,
ref SP_DRVINFO_DATA DriverInfoData);
public void RunExample()
{
Guid newG = Guid.Empty;
IntPtr NewDeviceInfoSet = SetupDiGetClassDevs(ref newG,
IntPtr.Zero, IntPtr.Zero,
DIGCF_ALLCLASSES);
SP_DEVINFO_DATA DeviceInfoData = new SP_DEVINFO_DATA();
DeviceInfoData.cbSize =
Marshal.SizeOf(typeof(SP_DEVINFO_DATA));
int deviceCounter = 0;
bool devInfoRetVal =
SetupDiEnumDeviceInfo(NewDeviceInfoSet, deviceCounter, ref
DeviceInfoData);
int devInfoErr = Marshal.GetLastWin32Error();
while (devInfoRetVal && devInfoErr != ERROR_NO_MORE_ITEMS
&& deviceCounter < 3) // < 3 is to keep the loop short for testing
{
ulong status = 0;
ulong problem = 0;
if (CM_Get_DevNode_Status(ref status, ref problem,
DeviceInfoData.DevInst, 0) == CR_SUCCESS)
{
StringBuilder sbDesc = new StringBuilder("");
int MAX_LEN = 512;
int propRegDataType = 0;
sbDesc.Capacity = MAX_LEN;
int reqSize = 0;
SetupDiGetDeviceRegistryProperty(NewDeviceInfoSet,
ref DeviceInfoData,
(int)Setup.SPDRPCodes.SPDRP_FRIENDLYNAME, ref
propRegDataType, sbDesc,
MAX_LEN, ref reqSize);
if (sbDesc.ToString() == "")
{
SetupDiGetDeviceRegistryProperty(NewDeviceInfoSet, ref DeviceInfoData,
(int)Setup.SPDRPCodes.SPDRP_DEVICEDESC,
ref propRegDataType, sbDesc,
MAX_LEN, ref reqSize);
}
if (sbDesc.ToString() == "")
sbDesc.Append("Unknown Description");
StringBuilder sbHWID = new StringBuilder("");
sbHWID.Capacity = MAX_LEN;
SetupDiGetDeviceRegistryProperty(NewDeviceInfoSet,
ref DeviceInfoData,
(int)Setup.SPDRPCodes.SPDRP_HARDWAREID, ref
propRegDataType, sbHWID,
MAX_LEN, ref reqSize);
ScanResults scanResult = new
ScanResults(sbHWID.ToString(), sbDesc.ToString());
Console.WriteLine("Device Detected: {0} - {1}",
sbDesc.ToString(), sbHWID.ToString());
SP_DEVINSTALL_PARAMS deviceInstallParams = new
SP_DEVINSTALL_PARAMS();
deviceInstallParams.cbSize =
Marshal.SizeOf(typeof(SP_DEVINSTALL_PARAMS));
SetupDiGetDeviceInstallParams(NewDeviceInfoSet,
ref DeviceInfoData,
ref deviceInstallParams);
deviceInstallParams.DriverPath = @"C:
\MyDriverPath";
if (!SetupDiBuildDriverInfoList(NewDeviceInfoSet,
ref DeviceInfoData, SPDIT_COMPATDRIVER))
{
int eCode = Marshal.GetLastWin32Error();
Console.WriteLine("\tError Building Driver
Info List. Code: {0}", eCode);
}
int memIndex = 0;
int drvErr = 0;
SP_DRVINFO_DATA drvData = new SP_DRVINFO_DATA();
drvData.cbSize =
Marshal.SizeOf(typeof(SP_DRVINFO_DATA));
bool enumResult =
SetupDiEnumDriverInfo(NewDeviceInfoSet, ref DeviceInfoData,
SPDIT_COMPATDRIVER,
memIndex, ref drvData);
if (!enumResult)
{
drvErr = Marshal.GetLastWin32Error();
Console.WriteLine("\tError Enumerating Driver
Info. Code: {0}", drvErr);
}
while (enumResult && drvErr !=
ERROR_NO_MORE_ITEMS)
{
memIndex++;
}
SetupDiDestroyDriverInfoList(NewDeviceInfoSet, ref
DeviceInfoData, SPDIT_COMPATDRIVER);
}
deviceCounter++;
devInfoRetVal =
SetupDiEnumDeviceInfo(NewDeviceInfoSet, deviceCounter, ref
DeviceInfoData);
devInfoErr = Marshal.GetLastWin32Error();
}
SetupDiDestroyDeviceInfoList(NewDeviceInfoSet);
}
}
--- CODE END ---

Your struct should look like this (partly):

[StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)] <-----1
public struct SP_DRVINFO_DATA
{
public int cbSize;
public int DriverType;
public IntPtr Reserved;
...

read more »- Hide quoted text -

- Show quoted text -

Willy, You are a GOD among men!!!!

Do you think you could explain to me what the Pack = 4 does and why I
need it for this structure but not any of my others?

Thanks! Would you like my first born? He's yours! :)
 
W

Willy Denoyette [MVP]

Your struct should look like this (partly):

[StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)] <-----1
public struct SP_DRVINFO_DATA
{
public int cbSize;
public int DriverType;
public IntPtr Reserved;
...

read more »- Hide quoted text -

- Show quoted text -

Willy, You are a GOD among men!!!!

Do you think you could explain to me what the Pack = 4 does and why I
need it for this structure but not any of my others?

The problem is with this:

public System.Runtime.InteropServices.ComTypes.FILETIME DriverDate;
public ulong DriverVersion;
}
DriverDate, being a long (8 bytes) will be aligned at its natural boundary with the default
packing (Pack = 0), that means that it will be stored at a address which is a multiple of 8.
However, if you look at the preceeding fields, DriverDate would not end on such an address,
so, the lay-out manager will pad the preceeding field with 4 bytes (the fixed char array),
and as such render the struct incompatible (both in length and some field addresses) with
what the function is expecting.
When setting the Packing to 4 (the same as used in the header file) , no such padding is
done and the struct length corresponds to what the function expects.


Thanks! Would you like my first born? He's yours! :)

Wow, but thanks, too much honor really ;-).

Willy.
 
R

Rymfax

Willy,

Would love your help one more time please! I'm now trying to get
SetupDiGetDriverInfoDetail to work. I'm getting the same 1784L
error. I was hoping you could take a look again. My struct/invoke/
code is below. The new snippet of code is just being run insde the
while loop of the previous code. Thanks! Oh, and FYI, I tried this
struct with and without the Pack=4.


[StructLayout(LayoutKind.Sequential, Pack=4, CharSet =
CharSet.Unicode)]
public struct SP_DRVINFO_DETAIL_DATA
{
public int cbSize;
public System.Runtime.InteropServices.ComTypes.FILETIME
InfDate;
public int CompatIDsOffset;
public int CompatIDsLength;
public ulong Reserved;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string SectionName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string InfFileName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string DrvDescription;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string HardwareID;
}

[DllImport("setupapi.dll", SetLastError = true, CharSet =
CharSet.Unicode)]
private static extern bool SetupDiGetDriverInfoDetail(IntPtr
DeviceInfoSet,
ref SP_DEVINFO_DATA DeviceInfoData, ref SP_DRVINFO_DATA
DriverInfoData,
ref SP_DRVINFO_DETAIL_DATA DriverInfoDetailData, int
DriverInfoDetailDataSize,
ref int RequiredSize);

// New Code Snipped

string infPath = "";
int drvRank = 0;
SP_DRVINSTALL_PARAMS drvParams = new
SP_DRVINSTALL_PARAMS();
drvParams.cbSize =
Marshal.SizeOf(typeof(SP_DRVINSTALL_PARAMS));
if (SetupDiGetDriverInstallParams(devInfoSet, ref
devInfoData, ref drvData, ref drvParams))
{
drvRank = drvParams.Rank;
}
int dataSize = 2048;
SP_DRVINFO_DETAIL_DATA drvInfDetail = new
SP_DRVINFO_DETAIL_DATA();
drvInfDetail.cbSize =
Marshal.SizeOf(typeof(SP_DRVINFO_DETAIL_DATA));
if (!SetupDiGetDriverInfoDetail(devInfoSet, ref
devInfoData, ref drvData, ref drvInfDetail,
dataSize, ref dataSize))
{
int didErr = Marshal.GetLastWin32Error();
infPath = "blah";
}
memIndex++;
enumResult = SetupDiEnumDriverInfo(devInfoSet, ref
devInfoData, SPDIT_COMPATDRIVER,
memIndex, ref drvData);
 
W

Willy Denoyette [MVP]

Rymfax said:
Willy,

Would love your help one more time please! I'm now trying to get
SetupDiGetDriverInfoDetail to work. I'm getting the same 1784L
error. I was hoping you could take a look again. My struct/invoke/
code is below. The new snippet of code is just being run insde the
while loop of the previous code. Thanks! Oh, and FYI, I tried this
struct with and without the Pack=4.


[StructLayout(LayoutKind.Sequential, Pack=4, CharSet =
CharSet.Unicode)]
public struct SP_DRVINFO_DETAIL_DATA
{
public int cbSize;
public System.Runtime.InteropServices.ComTypes.FILETIME
InfDate;
public int CompatIDsOffset;
public int CompatIDsLength;
public ulong Reserved;


public IntPtr Reserved;

Note, as I said previously, I didn't check the other structs for packing issues and the
like. You really have to check the header files before defining your interop stucts (or stay
with C++ :)).


Willy.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top