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.
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.
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! :)
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.
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++;
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.