E
Eric Renken
Well I am working on trying to get some HID code to work on Windows XP,
Vista 32, and Vista 64. Working on XP and Vista 32 was easy as there are
some great resources on the web; however Vista 64 is a whole other problem.
The first problem was an easy one all the samples show this structure:
[StructLayout(LayoutKind.Sequential)]
public struct SP_DEVICE_INTERFACE_DATA
{
public int cbSize;
public System.Guid InterfaceClassGuid;
public int Flags;
public IntPtr Reserved;
}
For calling the this method, SetupDiEnumDeviceInterfaces, in the
SetupAPI.dll; however most exaple has Reserved as just an Int and on a 64
bit platform that doesn't give you the correct size for an IntPtr. So all
my following problems are related to Vista 64.
Now that I have gotten past that part I am having problems with this method,
SetupDiGetDeviceInterfaceDetail, in SetupAPI.dll. When I call I this method
I get this error from GetLastError: "An attempt was made to reference a
token that does not exist."
Here is what my declartions look like:
[DllImport("setupapi.dll", CharSet = CharSet.Auto)]
static public extern bool SetupDiGetDeviceInterfaceDetail(IntPtr
DeviceInfoSet, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData, IntPtr
DeviceInterfaceDetailData, int DeviceInterfaceDetailDataSize, ref int
RequiredSize, IntPtr DeviceInfoData);
[StructLayout(LayoutKind.Sequential)]
public struct SP_DEVICE_INTERFACE_DATA
{
public int cbSize;
public System.Guid InterfaceClassGuid;
public int Flags;
public IntPtr Reserved;
}
[StructLayout(LayoutKind.Sequential)]
public struct SP_DEVICE_INTERFACE_DETAIL_DATA
{
public int cbSize;
public string DevicePath;
}
The program makes 2 calls to SetupDiGetDeviceInterfaceDetail. The first
call it to get the size of the structure and the second returns a pointer to
the data. However on the frist run both picese return the same error that I
stated above. Here is what the first call looks like:
Success =
DeviceManagementApiDeclarations.SetupDiGetDeviceInterfaceDetail(
DeviceInfoSet,
ref MyDeviceInterfaceData,
IntPtr.Zero, 0, ref BufferSize, IntPtr.Zero);
Here is the deifinition of the caribales used:
Scuesses = bool
DeviceInforSet = IntPtr
BufferSize = int
After the API call this data is called:
// Store the structure's size.
//MyDeviceInterfaceDetailData.cbSize =
MyDeviceInterfaceDetailData.ToString().Length;
MyDeviceInterfaceDetailData.cbSize =
Marshal.SizeOf(MyDeviceInterfaceDetailData);
// Allocate memory for the MyDeviceInterfaceDetailData Structure using
the returned buffer size.
IntPtr DetailDataBuffer = Marshal.AllocHGlobal(BufferSize);
// Store cbSize in the first 4 bytes of the array
Marshal.WriteInt32(DetailDataBuffer, 4 +
Marshal.SystemDefaultCharSize);
Debug.WriteLine("cbsize = " + MyDeviceInterfaceDetailData.cbSize);
I am pretty sure I would need to change the 4 + to 8 + for 64 bit, but I am
not positive.
Then I call SetupDiGetDeviceInterfaceDetail again:
Success =
DeviceManagementApiDeclarations.SetupDiGetDeviceInterfaceDetail (
DeviceInfoSet,
ref MyDeviceInterfaceData,
DetailDataBuffer,
BufferSize,
ref BufferSize,
IntPtr.Zero);
After that call this code is run:
IntPtr pdevicePathName = IntPtr.Zero;
if ( Marshal.SizeOf( DeviceInfoSet ) == 4 )
pdevicePathName = new IntPtr(DetailDataBuffer.ToInt32() +
Marshal.SizeOf(DeviceInfoSet));
else
pdevicePathName = new IntPtr(DetailDataBuffer.ToInt64() +
Marshal.SizeOf(DeviceInfoSet));
// Get the String containing the devicePathName.
SingledevicePathName = Marshal.PtrToStringAuto(pdevicePathName);
devicePathName[MemberIndex] = SingledevicePathName;
I just added the code to increment these values based on the Size of IntPtr.
The next time this code runs for the next HID device I get this error: The
supplied user buffer is not valid for the requested operation.
Any help would be greatly appriciated.
Thanks,
Eric Renken
Vista 32, and Vista 64. Working on XP and Vista 32 was easy as there are
some great resources on the web; however Vista 64 is a whole other problem.
The first problem was an easy one all the samples show this structure:
[StructLayout(LayoutKind.Sequential)]
public struct SP_DEVICE_INTERFACE_DATA
{
public int cbSize;
public System.Guid InterfaceClassGuid;
public int Flags;
public IntPtr Reserved;
}
For calling the this method, SetupDiEnumDeviceInterfaces, in the
SetupAPI.dll; however most exaple has Reserved as just an Int and on a 64
bit platform that doesn't give you the correct size for an IntPtr. So all
my following problems are related to Vista 64.
Now that I have gotten past that part I am having problems with this method,
SetupDiGetDeviceInterfaceDetail, in SetupAPI.dll. When I call I this method
I get this error from GetLastError: "An attempt was made to reference a
token that does not exist."
Here is what my declartions look like:
[DllImport("setupapi.dll", CharSet = CharSet.Auto)]
static public extern bool SetupDiGetDeviceInterfaceDetail(IntPtr
DeviceInfoSet, ref SP_DEVICE_INTERFACE_DATA DeviceInterfaceData, IntPtr
DeviceInterfaceDetailData, int DeviceInterfaceDetailDataSize, ref int
RequiredSize, IntPtr DeviceInfoData);
[StructLayout(LayoutKind.Sequential)]
public struct SP_DEVICE_INTERFACE_DATA
{
public int cbSize;
public System.Guid InterfaceClassGuid;
public int Flags;
public IntPtr Reserved;
}
[StructLayout(LayoutKind.Sequential)]
public struct SP_DEVICE_INTERFACE_DETAIL_DATA
{
public int cbSize;
public string DevicePath;
}
The program makes 2 calls to SetupDiGetDeviceInterfaceDetail. The first
call it to get the size of the structure and the second returns a pointer to
the data. However on the frist run both picese return the same error that I
stated above. Here is what the first call looks like:
Success =
DeviceManagementApiDeclarations.SetupDiGetDeviceInterfaceDetail(
DeviceInfoSet,
ref MyDeviceInterfaceData,
IntPtr.Zero, 0, ref BufferSize, IntPtr.Zero);
Here is the deifinition of the caribales used:
Scuesses = bool
DeviceInforSet = IntPtr
BufferSize = int
After the API call this data is called:
// Store the structure's size.
//MyDeviceInterfaceDetailData.cbSize =
MyDeviceInterfaceDetailData.ToString().Length;
MyDeviceInterfaceDetailData.cbSize =
Marshal.SizeOf(MyDeviceInterfaceDetailData);
// Allocate memory for the MyDeviceInterfaceDetailData Structure using
the returned buffer size.
IntPtr DetailDataBuffer = Marshal.AllocHGlobal(BufferSize);
// Store cbSize in the first 4 bytes of the array
Marshal.WriteInt32(DetailDataBuffer, 4 +
Marshal.SystemDefaultCharSize);
Debug.WriteLine("cbsize = " + MyDeviceInterfaceDetailData.cbSize);
I am pretty sure I would need to change the 4 + to 8 + for 64 bit, but I am
not positive.
Then I call SetupDiGetDeviceInterfaceDetail again:
Success =
DeviceManagementApiDeclarations.SetupDiGetDeviceInterfaceDetail (
DeviceInfoSet,
ref MyDeviceInterfaceData,
DetailDataBuffer,
BufferSize,
ref BufferSize,
IntPtr.Zero);
After that call this code is run:
IntPtr pdevicePathName = IntPtr.Zero;
if ( Marshal.SizeOf( DeviceInfoSet ) == 4 )
pdevicePathName = new IntPtr(DetailDataBuffer.ToInt32() +
Marshal.SizeOf(DeviceInfoSet));
else
pdevicePathName = new IntPtr(DetailDataBuffer.ToInt64() +
Marshal.SizeOf(DeviceInfoSet));
// Get the String containing the devicePathName.
SingledevicePathName = Marshal.PtrToStringAuto(pdevicePathName);
devicePathName[MemberIndex] = SingledevicePathName;
I just added the code to increment these values based on the Size of IntPtr.
The next time this code runs for the next HID device I get this error: The
supplied user buffer is not valid for the requested operation.
Any help would be greatly appriciated.
Thanks,
Eric Renken