help: SetupDiEnumDeviceInterfaces call fails with error 1784.

I’m trying to port the test application(echoapp.cpp in KMDF\echo\exe) for WDF UMDF echo driver’s to C#, for the purpose of getting a basic GUI up for building other driver test application.

Although my c# code follows the steps of the c++ code in echoapp.cpp, I somehow can’t get pass this problem with SetupDiEnumDeviceInterfaces, error 1784, ERROR_INVALID_USER_BUFFER. I thought it might be the buffer size, but I manually checked it - it’s the same as the CPP code- 28.

SP_DEVICE_INTERFACE_DATA dia = new SP_DEVICE_INTERFACE_DATA();
dia.cbSize = (UInt32) Marshal.SizeOf(dia); //this should be 28; verified w/ Win32 code

I’m on Wndow XP SP2.

I hope someone can still help me out in this Christmas season… Is anyone still here??? :slight_smile:

Here’s my C# code:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace APP_CS
{
public partial class TEST : Form
{

public Guid GUID_DEVINTERFACE_ECHO;

[StructLayout(LayoutKind.Sequential)]
public class SP_DEVICE_INTERFACE_DATA
{
public UInt32 cbSize;
public Guid InterfaceClassGuid;
public UInt32 Flags;
public IntPtr Reserved;
};

[StructLayout(LayoutKind.Sequential)]
public class SP_DEVINFO_DATA
{
public uint cbSize;
public Guid ClassGuid;
public uint DevInst; // DEVINST handle
public IntPtr Reserved;
};

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct SP_DEVICE_INTERFACE_DETAIL_DATA
{
public UInt32 cbSize;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string DevicePath;
}

public UInt32 DIGCF_DEFAULT = 0x00000001; // only valid with DIGCF_DEVICEINTERFACE
public UInt32 DIGCF_PRESENT = 0x00000002;
public UInt32 DIGCF_ALLCLASSES = 0x00000004;
public UInt32 DIGCF_PROFILE = 0x00000008;
public UInt32 DIGCF_DEVICEINTERFACE = 0x00000010;
public const short INVALID_HANDLE_VALUE = -1;

[DllImport(@“setupapi.dll”, CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr SetupDiGetClassDevs(
ref Guid ClassGuid, [MarshalAs(UnmanagedType.LPTStr)] string Enumerator,
IntPtr hwndParent, UInt32 Flags);

[DllImport(@“setupapi.dll”, CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool SetupDiEnumDeviceInterfaces(
IntPtr lpDeviceInfoSet, IntPtr devInfo, ref Guid gClass,
Int32 nIndex, ref SP_DEVICE_INTERFACE_DATA oInterfaceData);

[DllImport(@“setupapi.dll”, CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool SetupDiDestroyDeviceInfoList(IntPtr hDevInfo);

[DllImport(@“setupapi.dll”, CharSet = CharSet.Auto, SetLastError = true)]
public static extern Boolean SetupDiGetDeviceInterfaceDetail(
IntPtr hDevInfo,
ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData,
IntPtr deviceInterfaceDetailData,
UInt32 deviceInterfaceDetailDataSize,
out UInt32 requiredSize,
IntPtr deviceInfoData
);

[DllImport(@“setupapi.dll”, SetLastError = true)]
public static extern Boolean SetupDiGetDeviceInterfaceDetail(
IntPtr hDevInfo,
ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData,
ref SP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailData,
UInt32 deviceInterfaceDetailDataSize,
out UInt32 requiredSize,
IntPtr deviceInfoData
);

[DllImport(“Kernel32.dll”, ExactSpelling = true, CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool CloseHandle(int hHandle);

// CreateFile is is Overloaded for having SecurityAttributes or not
[DllImport(“Kernel32.dll”, CharSet = CharSet.Auto, SetLastError = true)]
public static extern int CreateFile(String lpFileName,
int dwDesiredAccess, int dwShareMode, IntPtr lpSecurityAttributes,
int dwCreationDisposition, int dwFlagsAndAttributes,
int hTemplateFile);

[DllImport(“Kernel32.dll”, CharSet = CharSet.Auto, SetLastError = true)]
public static extern int CreateFile(String lpFileName, int
dwDesiredAccess, int dwShareMode, SECURITY_ATTRIBUTES
lpSecurityAttributes, int dwCreationDisposition, int
dwFlagsAndAttributes, int hTemplateFile);

// DeviceIoControl is Overloaded for byte or int data
[DllImport(“Kernel32.dll”, CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool DeviceIoControl(
int hDevice, int dwIoControlCode, byte InBuffer,
int nInBufferSize, byte OutBuffer, int nOutBufferSize,
ref int pBytesReturned, int pOverlapped);

[DllImport(“Kernel32.dll”, CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool DeviceIoControl(
int hDevice, int dwIoControlCode, int InBuffer,
int nInBufferSize, int OutBuffer, int nOutBufferSize,
ref int pBytesReturned, int pOverlapped);

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct SECURITY_ATTRIBUTES
{
public int nLength; // DWORD
public IntPtr lpSecurityDescriptor; // LPVOID
public int bInheritHandle; // BOOL
}

private Boolean initDone = false;
private string devicePath;

public TEST()
{
InitializeComponent();
GUID_DEVINTERFACE_ECHO=new Guid(0xcdc35b6e, 0xbe4, 0x4936, 0xbf, 0x5f, 0x55, 0x37, 0x38, 0xa, 0x7c, 0x1a);
}

private void BTNWRITE_Click(object sender, EventArgs e)
{
int i = 0;
UInt32 RequiredSize = 0, nSize;

if (!initDone)
{
status.Text = “Init start”;
IntPtr h = SetupDiGetClassDevs(ref GUID_DEVINTERFACE_ECHO,
null, IntPtr.Zero, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);

if (h.ToInt32() == INVALID_HANDLE_VALUE)
{
status.Text = “SetupDiGetClassDevs failed!”;
return;
}

// create a Device Interface Data structure
SP_DEVICE_INTERFACE_DATA dia = new SP_DEVICE_INTERFACE_DATA();
dia.cbSize = (UInt32) Marshal.SizeOf(dia); //this should be 28; verified by working Win32 program

// start the enumeration
bool Success = SetupDiEnumDeviceInterfaces(h, IntPtr.Zero,
ref GUID_DEVINTERFACE_ECHO, i, ref dia);

if (!Success)
{
int err = Marshal.GetLastWin32Error();
status.Text = “SetupDiEnumDeviceInterfaces failed.” + err;
SetupDiDestroyDeviceInfoList(h);
return;
}

//two step process to get interface detail; first the size; then the interface
if (!SetupDiGetDeviceInterfaceDetail(h, ref dia, IntPtr.Zero, 0, out RequiredSize, IntPtr.Zero))
{
status.Text = “1st SetupDiGetDeviceInterfaceDetail call failed.”;
return;
}

SP_DEVICE_INTERFACE_DETAIL_DATA didd = new SP_DEVICE_INTERFACE_DETAIL_DATA();
if (IntPtr.Size == 8)
didd.cbSize = 8;
else
didd.cbSize = 5;

nSize = RequiredSize;

Success = SetupDiGetDeviceInterfaceDetail(h, ref dia,
ref didd, nSize, out RequiredSize, IntPtr.Zero);

if (!Success)
{
status.Text = “2nd SetupDiGetDeviceInterfaceDetail call failed.”;
SetupDiDestroyDeviceInfoList(h);
return;
}

devicePath = didd.DevicePath;
status.Text = didd.DevicePath;

}
else
{
status.Text = “Init Done” + devicePath;
}
}
}
}

http://www.pinvoke.net/default.aspx/setupapi.SetupDiEnumDeviceInterfaces

pinvoke.net is a great way to find 26 different authoritative c#
implementations of most of the platform sdk.

On Dec 22, 2007 1:07 AM, wrote:

> I’m trying to port the test application(echoapp.cpp in KMDF\echo\exe) for
> WDF UMDF echo driver’s to C#, for the purpose of getting a basic GUI up for
> building other driver test application.
>
>
> Although my c# code follows the steps of the c++ code in echoapp.cpp, I
> somehow can’t get pass this problem with SetupDiEnumDeviceInterfaces, error
> 1784, ERROR_INVALID_USER_BUFFER. I thought it might be the buffer size, but
> I manually checked it - it’s the same as the CPP code- 28.
>
> SP_DEVICE_INTERFACE_DATA dia = new SP_DEVICE_INTERFACE_DATA();
> dia.cbSize = (UInt32) Marshal.SizeOf(dia); //this should be 28; verified
> w/ Win32 code
>
> I’m on Wndow XP SP2.
>
> I hope someone can still help me out in this Christmas season… Is anyone
> still here??? :slight_smile:
>
> Here’s my C# code:
>
> -------------------------------------------------------------------------------
> using System;
> using System.Collections.Generic;
> using System.ComponentModel;
> using System.Data;
> using System.Drawing;
> using System.Text;
> using System.Windows.Forms;
> using System.Runtime.InteropServices;
>
> namespace APP_CS
> {
> public partial class TEST : Form
> {
>
> public Guid GUID_DEVINTERFACE_ECHO;
>
> [StructLayout(LayoutKind.Sequential)]
> public class SP_DEVICE_INTERFACE_DATA
> {
> public UInt32 cbSize;
> public Guid InterfaceClassGuid;
> public UInt32 Flags;
> public IntPtr Reserved;
> };
>
> [StructLayout(LayoutKind.Sequential)]
> public class SP_DEVINFO_DATA
> {
> public uint cbSize;
> public Guid ClassGuid;
> public uint DevInst; // DEVINST handle
> public IntPtr Reserved;
> };
>
> [StructLayout(LayoutKind.Sequential, Pack = 1)]
> public struct SP_DEVICE_INTERFACE_DETAIL_DATA
> {
> public UInt32 cbSize;
> [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
> public string DevicePath;
> }
>
> public UInt32 DIGCF_DEFAULT = 0x00000001; // only valid with
> DIGCF_DEVICEINTERFACE
> public UInt32 DIGCF_PRESENT = 0x00000002;
> public UInt32 DIGCF_ALLCLASSES = 0x00000004;
> public UInt32 DIGCF_PROFILE = 0x00000008;
> public UInt32 DIGCF_DEVICEINTERFACE = 0x00000010;
> public const short INVALID_HANDLE_VALUE = -1;
>
>
> [DllImport(@“setupapi.dll”, CharSet = CharSet.Auto, SetLastError =
> true)]
> public static extern IntPtr SetupDiGetClassDevs(
> ref Guid ClassGuid, [MarshalAs(UnmanagedType.LPTStr)] string
> Enumerator,
> IntPtr hwndParent, UInt32 Flags);
>
> [DllImport(@“setupapi.dll”, CharSet = CharSet.Auto, SetLastError =
> true)]
> public static extern bool SetupDiEnumDeviceInterfaces(
> IntPtr lpDeviceInfoSet, IntPtr devInfo, ref Guid gClass,
> Int32 nIndex, ref SP_DEVICE_INTERFACE_DATA oInterfaceData);
>
> [DllImport(@“setupapi.dll”, CharSet = CharSet.Auto, SetLastError =
> true)]
> public static extern bool SetupDiDestroyDeviceInfoList(IntPtr
> hDevInfo);
>
> [DllImport(@“setupapi.dll”, CharSet = CharSet.Auto, SetLastError =
> true)]
> public static extern Boolean SetupDiGetDeviceInterfaceDetail(
> IntPtr hDevInfo,
> ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData,
> IntPtr deviceInterfaceDetailData,
> UInt32 deviceInterfaceDetailDataSize,
> out UInt32 requiredSize,
> IntPtr deviceInfoData
> );
>
> [DllImport(@“setupapi.dll”, SetLastError = true)]
> public static extern Boolean SetupDiGetDeviceInterfaceDetail(
> IntPtr hDevInfo,
> ref SP_DEVICE_INTERFACE_DATA deviceInterfaceData,
> ref SP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailData,
> UInt32 deviceInterfaceDetailDataSize,
> out UInt32 requiredSize,
> IntPtr deviceInfoData
> );
>
>
> [DllImport(“Kernel32.dll”, ExactSpelling = true, CharSet =
> CharSet.Auto, SetLastError = true)]
> public static extern bool CloseHandle(int hHandle);
>
> // CreateFile is is Overloaded for having SecurityAttributes or not
> [DllImport(“Kernel32.dll”, CharSet = CharSet.Auto, SetLastError =
> true)]
> public static extern int CreateFile(String lpFileName,
> int dwDesiredAccess, int dwShareMode, IntPtr lpSecurityAttributes,
> int dwCreationDisposition, int dwFlagsAndAttributes,
> int hTemplateFile);
>
> [DllImport(“Kernel32.dll”, CharSet = CharSet.Auto, SetLastError =
> true)]
> public static extern int CreateFile(String lpFileName, int
> dwDesiredAccess, int dwShareMode, SECURITY_ATTRIBUTES
> lpSecurityAttributes, int dwCreationDisposition, int
> dwFlagsAndAttributes, int hTemplateFile);
>
> // DeviceIoControl is Overloaded for byte or int data
> [DllImport(“Kernel32.dll”, CharSet = CharSet.Auto, SetLastError =
> true)]
> public static extern bool DeviceIoControl(
> int hDevice, int dwIoControlCode, byte InBuffer,
> int nInBufferSize, byte OutBuffer, int nOutBufferSize,
> ref int pBytesReturned, int pOverlapped);
>
> [DllImport(“Kernel32.dll”, CharSet = CharSet.Auto, SetLastError =
> true)]
> public static extern bool DeviceIoControl(
> int hDevice, int dwIoControlCode, int InBuffer,
> int nInBufferSize, int OutBuffer, int nOutBufferSize,
> ref int pBytesReturned, int pOverlapped);
>
>
> [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
> public struct SECURITY_ATTRIBUTES
> {
> public int nLength; // DWORD
> public IntPtr lpSecurityDescriptor; // LPVOID
> public int bInheritHandle; // BOOL
> }
>
> private Boolean initDone = false;
> private string devicePath;
>
> public TEST()
> {
> InitializeComponent();
> GUID_DEVINTERFACE_ECHO=new Guid(0xcdc35b6e, 0xbe4, 0x4936,
> 0xbf, 0x5f, 0x55, 0x37, 0x38, 0xa, 0x7c, 0x1a);
> }
>
> private void BTNWRITE_Click(object sender, EventArgs e)
> {
> int i = 0;
> UInt32 RequiredSize = 0, nSize;
>
> if (!initDone)
> {
> status.Text = “Init start”;
> IntPtr h = SetupDiGetClassDevs(ref GUID_DEVINTERFACE_ECHO,
> null, IntPtr.Zero, DIGCF_PRESENT |
> DIGCF_DEVICEINTERFACE);
>
> if (h.ToInt32() == INVALID_HANDLE_VALUE)
> {
> status.Text = “SetupDiGetClassDevs failed!”;
> return;
> }
>
> // create a Device Interface Data structure
> SP_DEVICE_INTERFACE_DATA dia = new
> SP_DEVICE_INTERFACE_DATA();
> dia.cbSize = (UInt32) Marshal.SizeOf(dia); //this should
> be 28; verified by working Win32 program
>
> // start the enumeration
> bool Success = SetupDiEnumDeviceInterfaces(h, IntPtr.Zero,
> ref GUID_DEVINTERFACE_ECHO, i, ref dia);
>
> if (!Success)
> {
> int err = Marshal.GetLastWin32Error();
> status.Text = “SetupDiEnumDeviceInterfaces failed.” +
> err;
> SetupDiDestroyDeviceInfoList(h);
> return;
> }
>
> //two step process to get interface detail; first the size;
> then the interface
> if (!SetupDiGetDeviceInterfaceDetail(h, ref dia,
> IntPtr.Zero, 0, out RequiredSize, IntPtr.Zero))
> {
> status.Text = “1st SetupDiGetDeviceInterfaceDetail call
> failed.”;
> return;
> }
>
> SP_DEVICE_INTERFACE_DETAIL_DATA didd = new
> SP_DEVICE_INTERFACE_DETAIL_DATA();
> if (IntPtr.Size == 8)
> didd.cbSize = 8;
> else
> didd.cbSize = 5;
>
> nSize = RequiredSize;
>
> Success = SetupDiGetDeviceInterfaceDetail(h, ref dia,
> ref didd, nSize, out RequiredSize, IntPtr.Zero);
>
>
> if (!Success)
> {
> status.Text = “2nd SetupDiGetDeviceInterfaceDetail call
> failed.”;
> SetupDiDestroyDeviceInfoList(h);
> return;
> }
>
> devicePath = didd.DevicePath;
> status.Text = didd.DevicePath;
>
>
> }
> else
> {
> status.Text = “Init Done” + devicePath;
> }
> }
> }
> }
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>


Mark Roddy

I did reference www.pinvoke.net. I have almost the identical code with their sample… still the problem persists.

I zipped the entire directory, include this GUI app, echo driver, and test program. If anyone care to try the problem, you can download the zip file here. You will need to install the echo driver first by following the echo.htm file. Again except the GUI, these are files from DDK/UMDF or KMDF folders.

http://www.box.net/shared/tk1ol9zk8k

All you have to do is to replace “class” by “struct” in

public /*class*/ struct SP_DEVICE_INTERFACE_DATA

I suggest that you also change all your data types to structs
and use explicit packing in all other cases.

I had this class => struct suspicion immediately.

Here’s what I did after your 2nd post:

  1. replaced

//GUID_DEVINTERFACE_ECHO=new Guid(0xcdc35b6e, 0xbe4, 0x4936, 0xbf, 0x5f, 0x55, 0x37, 0x38, 0xa, 0x7c, 0x1a);

by

GUID_DEVINTERFACE_ECHO=new Guid(0x884b96c3, 0x56ef, 0x11d1, 0xbc, 0x8c, 0x00, 0xa0, 0xc9, 0x14, 0x05, 0xdd);

which is a keyboard from ntddkbd.h (not to bother with echo device),
and SetupDiEnumDeviceInterfaces failed with the same error 1784 as expected, then I

  1. replaced class => struct for SP_DEVICE_INTERFACE_DATA only, and
    SetupDiEnumDeviceInterfaces succeeded.

Hope it helps.

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:bounce-309333-
xxxxx@lists.osr.com] On Behalf Of xxxxx@yahoo.com
Sent: Saturday, December 22, 2007 11:56 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] help: SetupDiEnumDeviceInterfaces call fails with
error 1784.

I did reference www.pinvoke.net. I have almost the identical code with
their sample… still the problem persists.

I zipped the entire directory, include this GUI app, echo driver, and
test program. If anyone care to try the problem, you can download the
zip file here. You will need to install the echo driver first by
following the echo.htm file. Again except the GUI, these are files from
DDK/UMDF or KMDF folders.

http://www.box.net/shared/tk1ol9zk8k


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

That is the problem. I did copy and paste for those definitions…
Thanks.

If you care about perf, stop using the Auto stuff for character sets and just stick with Unicode. Also, if you really want to get into the C# groove, use SafeHandles to wrap the dev info set handle (which you are leaking)

internal class SafeDevInfoHandle : SafeHandleZeroOrMinusOneIsInvalid
{
Internal SafeDevInfoHandle() : base(true) {}

Protected override bool ReleaseHandle() { return TEST.SetupDiDestroyDeviceInfoList(this.handle); }
}

partial class TEST {
[DllImport(@“setupapi.dll”, CharSet = CharSet.Auto, SetLastError = true)]
public static extern SafeDevInfoHandle SetupDiGetClassDevs( <– note the change in return value
ref Guid ClassGuid, [MarshalAs(UnmanagedType.LPTStr)] string Enumerator,
IntPtr hwndParent, UInt32 Flags);

[DllImport(@“setupapi.dll”, CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool SetupDiEnumDeviceInterfaces(
SafeDevInfoHandle lpDeviceInfoSet, IntPtr devInfo, ref Guid gClass, <== note the change of type for the first parameter
Int32 nIndex, ref SP_DEVICE_INTERFACE_DATA oInterfaceData);

[DllImport(“setupapi.dll”, ExactSpelling=true]
[return:MarshalAs(UnmanagedType.Bool)] <– you should marshal from a 1 byte Boolean from a 4 byte win32 BOOL
static extern Boolean SetupDiDestroyDeviceInfoList(IntPtr handle);
}

If you have not used safe handles before, they are great for managing win32 handles and scope. lots of good stuff come out of them. For instance, the compilers knows that you derived from SafeHandle and will allocate a SafeDevInfoHandle for you when pinvoking SetupDiGetClassDevs. The compiler also knows to extrace the underlying handle value from the SafeHandle when it is passed to pinvoke function and provides for much better typesafety than IntPtr. Even more importantly, SafeHandle keeps a ref count of all active pinvokes using the handle value and makes sure that the handle is not closed while any of pinvoke calls are still pending. Finally, b/c it implements IDisposable you can scope it with the using clause and the underlying win32 handle will be automatically released (via ReleaseHandle) at the end of the using scope

using (SafeDevInfoHandle h = TEST.SetDiGetClassDevs(…)) {

} // h is now released

Another bonus is the IsInvalid get_op(), so this
if (h.ToInt32() == INVALID_HANDLE_VALUE)
becomes the much friendlier
if (h.IsInvalid)

finally, it should be ref SECURITY_ATTRIBUTES for CreateFile since all structs are value types and you need to pass a pointer…but really, you are not going to ever initialize a SECURITY_ATTRIBUTES so just change it to IntPtr lpSecurityAttributes and then you can just pass IntPtr.Zero

your friendly managed code advisor :wink:
d

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@yahoo.com
Sent: Saturday, December 22, 2007 7:28 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] help: SetupDiEnumDeviceInterfaces call fails with error 1784.

That is the problem. I did copy and paste for those definitions…
Thanks.


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer