From: m on 13 Apr 2010 19:20 While setting the size like this is possible, I wouldn't recommend it. In C# this code will be handled by a compiler provided constructor, and will always set the value of the cbSize member to 32. Remember that in C# structures are a special kind of class with no properties or methods. The binary layout when passed to pInvoke is defined by the marshal as attributes applied to the members and the defaults applied by the framework. I never trust the defaults and always define the marshalling explicitly so I can use any compatible .NET data type and not worry about what the physical layout will be since it has been specifically defined (and .NET throws an exception if the conversion is invalid) All that being said, the easiest change you can make it to simply cast (explicit conversion) the value of Marshal.SizeOf(devInfoData) to uint. The compiler tells you that there is no implicit conversion, but there certainly is an explicit conversion. As a side note, I have never understood the rational behind the decision to use signed integers for sizes and indices in .NET when the quantities are, like size_t, inherently unsigned (and with array objects, a negative index is an exception). Fortunately, most of the time a foreach next loop is approprate so it rarely comes up "santapanda" <santapanda(a)discussions.microsoft.com> wrote in message news:E7CEB637-18BB-4E5E-891B-F299F9CDE12F(a)microsoft.com... > Hi, > > Interesting suggestion, but I'm not sure I understand 100%. Are you > saying > add the cast to: > > devInfoData.cbSize = (uint) Marshal.SizeOf(devInfoData) > > I had originally declared cbsize as an int, and that's what started the > errors. But after reading your suggestion, I wonder if I should > explicitly > set cbSize in my struct: > > [StructLayout(LayoutKind.Sequential)] > public struct SP_DEVINFO_DATA > { > public int cbSize = 32; > public System.Guid ClassGuid; > public int DevInst; > public int Reserved; > } > > Is that possible? > > > > "m" wrote: > >> IMHO, the better solution is to add an explicit conversion (cast) or to >> change the struct def'n to match the data type (of the same size) that >> you >> can provide. Constants are very useful, but can be annoying when the >> aren't >> ;) >> >> "santapanda" <santapanda(a)discussions.microsoft.com> wrote in message >> news:7B5E070D-8587-43E2-A57E-5C3468E7238B(a)microsoft.com... >> > Thank you, >> > >> > I changed the structure to the definition provided in pinvoke.net. >> > After >> > making that change the line >> > >> > devInfoData.cbSize = Marshal.SizeOf(devInfoData); >> > >> > produced a compilation error about implicit conversion from 'int' to >> > 'uint'. >> > So instead, I changed the line to read >> > >> > devInfoData.cbSize = 32; >> > >> > 32 is the size pinvoke.net states for 64bit structure; 28 bytes is for >> > 32-bit. >> > >> > Thanks again! >> > >> > "holycow" wrote: >> > >> >> Your definition of SP_DEVINFO_DATA differs from one given by >> >> pinvoke.net: >> >> http://pinvoke.net/default.aspx/Structures/SP_DEVINFO_DATA.html >> >> >> >> If your machine is 64 bit, this will matter. >> >> >> >> >> >> >> >> "santapanda" <santapanda(a)discussions.microsoft.com> wrote in message >> >> news:F889AC4D-6A3E-410C-9923-EF714631BA00(a)microsoft.com... >> >> > Hello, >> >> > >> >> > I have a C# application using P/Invoke on several SetupDIxxx >> >> > methods. I >> >> > am >> >> > attempting to pass an SP_DEVINFO_DATA object to the >> >> > SetupDiEnumDeviceInfo() >> >> > method. I have setup the SP_DEVINFO_DATA struct as follows: >> >> > >> >> > [StructLayout(LayoutKind.Sequential)] >> >> > public struct SP_DEVINFO_DATA >> >> > { >> >> > public int cbSize; >> >> > public System.Guid ClassGuid; >> >> > public int DevInst; >> >> > public int Reserved; >> >> > } >> >> > >> >> > Based on articles in the MSDN Library, and an example i found on >> >> > pinvoke.net, I know I'm supposed to set my object's cbsize to >> >> > sizeof(SP_DEVINFO_DATA). >> >> > >> >> > Here is my code: >> >> > ===================== >> >> > [...] >> >> > SP_DEVINFO_DATA devInfoData = new SP_DEVINFO_DATA(); >> >> > IntPtr deviceInfoSet = SetupDiGetClassDevs (ref guids[0], null, 0, >> >> > DIGCF_PRESENT | DIGCF_ALLCLASSES); >> >> > >> >> > if (deviceInfoSet != INVALID_HANDLE_VALUE) >> >> > { >> >> > int devIndex = 0; >> >> > devInfoData.cbSize = Marshal.SizeOf(devInfoData); >> >> > bool success = SetupDiEnumDeviceInfo(deviceInfoSet, devIndex, >> >> > out devInfoData); >> >> > [...] >> >> > } >> >> > ===================== >> >> > >> >> > When I run, I get the error: "The supplied user buffer is not valid >> >> > for >> >> > the >> >> > requested operation." The documentation from MSDN states this error >> >> > is >> >> > generated when "the cbSize member is not set correctly for an output >> >> > parameter". >> >> > >> >> > This is my first time using P/Invoke and working with Windows APIs. >> >> > So >> >> > please help me understand how to pass the correct cbSize value. >> >> > When I >> >> > ran >> >> > debugger, the cbSize is 0 when the object is going in, but when it >> >> > comes >> >> > out >> >> > the cbSize is 28. I tried setting cbSize prior to calling the >> >> > SetupDiEnumDeviceInfo method to various values like 28 and 1024, but >> >> > I >> >> > still >> >> > got the same error. >> >> > >> >> > Thanks! >> >> >> . >>
From: santapanda on 14 Apr 2010 16:12 Thanks M, Now I'm having the same issue with an SP_DEVINFO_LIST_DTAIL_DATA structure. My structure is defined as [StructLayout(LayoutKind.Sequential)] public struct SP_DEVINFO_LIST_DETAIL_DATA { public UInt32 cbSize; public System.Guid classGuid; public IntPtr remoteMachineHandle; public string RemoteMachineName; } The code has: SP_DEVINFO_LIST_DETAIL_DATA dList = new SP_DEVINFO_LIST_DETAIL_DATA(); dList.cbSize = (UInt32) Marshal.SizeOf(dList); When I call SetupDiGetDeviceInfoListDetail(deviceInfoSet, out dList), I'm getting the same error. This time, a run through debugger finds that cbSize is set to 40. I tried to apply the same logic I found on pinvoke for SP_DEVINFO_DATA, that on a 64-bit computer, the size is 4 + (32-bit). But setting 40, 44, 32, or 28 do not work. How do I figure out the correct size? I'm new to Marshalling unmanaged code, so I'm learning this by brute force; but I'm trying to understand what I'm doing rather than just mimicking what I'm being told/seen from other examples. Thanks in advance for your help! "m" wrote: > While setting the size like this is possible, I wouldn't recommend it. In > C# this code will be handled by a compiler provided constructor, and will > always set the value of the cbSize member to 32. Remember that in C# > structures are a special kind of class with no properties or methods. The > binary layout when passed to pInvoke is defined by the marshal as attributes > applied to the members and the defaults applied by the framework. I never > trust the defaults and always define the marshalling explicitly so I can use > any compatible .NET data type and not worry about what the physical layout > will be since it has been specifically defined (and .NET throws an exception > if the conversion is invalid) > > All that being said, the easiest change you can make it to simply cast > (explicit conversion) the value of Marshal.SizeOf(devInfoData) to uint. The > compiler tells you that there is no implicit conversion, but there certainly > is an explicit conversion. > > As a side note, I have never understood the rational behind the decision to > use signed integers for sizes and indices in .NET when the quantities are, > like size_t, inherently unsigned (and with array objects, a negative index > is an exception). Fortunately, most of the time a foreach next loop is > approprate so it rarely comes up > > "santapanda" <santapanda(a)discussions.microsoft.com> wrote in message > news:E7CEB637-18BB-4E5E-891B-F299F9CDE12F(a)microsoft.com... > > Hi, > > > > Interesting suggestion, but I'm not sure I understand 100%. Are you > > saying > > add the cast to: > > > > devInfoData.cbSize = (uint) Marshal.SizeOf(devInfoData) > > > > I had originally declared cbsize as an int, and that's what started the > > errors. But after reading your suggestion, I wonder if I should > > explicitly > > set cbSize in my struct: > > > > [StructLayout(LayoutKind.Sequential)] > > public struct SP_DEVINFO_DATA > > { > > public int cbSize = 32; > > public System.Guid ClassGuid; > > public int DevInst; > > public int Reserved; > > } > > > > Is that possible? > > > > > > > > "m" wrote: > > > >> IMHO, the better solution is to add an explicit conversion (cast) or to > >> change the struct def'n to match the data type (of the same size) that > >> you > >> can provide. Constants are very useful, but can be annoying when the > >> aren't > >> ;) > >> > >> "santapanda" <santapanda(a)discussions.microsoft.com> wrote in message > >> news:7B5E070D-8587-43E2-A57E-5C3468E7238B(a)microsoft.com... > >> > Thank you, > >> > > >> > I changed the structure to the definition provided in pinvoke.net. > >> > After > >> > making that change the line > >> > > >> > devInfoData.cbSize = Marshal.SizeOf(devInfoData); > >> > > >> > produced a compilation error about implicit conversion from 'int' to > >> > 'uint'. > >> > So instead, I changed the line to read > >> > > >> > devInfoData.cbSize = 32; > >> > > >> > 32 is the size pinvoke.net states for 64bit structure; 28 bytes is for > >> > 32-bit. > >> > > >> > Thanks again! > >> > > >> > "holycow" wrote: > >> > > >> >> Your definition of SP_DEVINFO_DATA differs from one given by > >> >> pinvoke.net: > >> >> http://pinvoke.net/default.aspx/Structures/SP_DEVINFO_DATA.html > >> >> > >> >> If your machine is 64 bit, this will matter. > >> >> > >> >> > >> >> > >> >> "santapanda" <santapanda(a)discussions.microsoft.com> wrote in message > >> >> news:F889AC4D-6A3E-410C-9923-EF714631BA00(a)microsoft.com... > >> >> > Hello, > >> >> > > >> >> > I have a C# application using P/Invoke on several SetupDIxxx > >> >> > methods. I > >> >> > am > >> >> > attempting to pass an SP_DEVINFO_DATA object to the > >> >> > SetupDiEnumDeviceInfo() > >> >> > method. I have setup the SP_DEVINFO_DATA struct as follows: > >> >> > > >> >> > [StructLayout(LayoutKind.Sequential)] > >> >> > public struct SP_DEVINFO_DATA > >> >> > { > >> >> > public int cbSize; > >> >> > public System.Guid ClassGuid; > >> >> > public int DevInst; > >> >> > public int Reserved; > >> >> > } > >> >> > > >> >> > Based on articles in the MSDN Library, and an example i found on > >> >> > pinvoke.net, I know I'm supposed to set my object's cbsize to > >> >> > sizeof(SP_DEVINFO_DATA). > >> >> > > >> >> > Here is my code: > >> >> > ===================== > >> >> > [...] > >> >> > SP_DEVINFO_DATA devInfoData = new SP_DEVINFO_DATA(); > >> >> > IntPtr deviceInfoSet = SetupDiGetClassDevs (ref guids[0], null, 0, > >> >> > DIGCF_PRESENT | DIGCF_ALLCLASSES); > >> >> > > >> >> > if (deviceInfoSet != INVALID_HANDLE_VALUE) > >> >> > { > >> >> > int devIndex = 0; > >> >> > devInfoData.cbSize = Marshal.SizeOf(devInfoData); > >> >> > bool success = SetupDiEnumDeviceInfo(deviceInfoSet, devIndex, > >> >> > out devInfoData); > >> >> > [...] > >> >> > } > >> >> > ===================== > >> >> > > >> >> > When I run, I get the error: "The supplied user buffer is not valid > >> >> > for > >> >> > the > >> >> > requested operation." The documentation from MSDN states this error > >> >> > is > >> >> > generated when "the cbSize member is not set correctly for an output > >> >> > parameter". > >> >> > > >> >> > This is my first time using P/Invoke and working with Windows APIs. > >> >> > So > >> >> > please help me understand how to pass the correct cbSize value. > >> >> > When I > >> >> > ran > >> >> > debugger, the cbSize is 0 when the object is going in, but when it > >> >> > comes > >> >> > out > >> >> > the cbSize is 28. I tried setting cbSize prior to calling the > >> >> > SetupDiEnumDeviceInfo method to various values like 28 and 1024, but > >> >> > I > >> >> > still > >> >> > got the same error. > >> >> > > >> >> > Thanks! > >> >> > >> . > >> > . >
From: m on 14 Apr 2010 22:39 try something like this: (Untested code) [StructLayout(LayoutKind.Sequential)] public struct SP_DEVINFO_LIST_DETAIL_DATA { [MarshalAs(UnmanagedType.U4)] public UInt32 cbSize; [MarshalAs(UnmanagedType.Struct)] public System.Guid classGuid; [MarshalAs(UnmanagedType.SysInt)] public IntPtr remoteMachineHandle; [MarshalAs(UnmanagedType.ByValArray, SizeConst = SP_MAX_MACHINENAME_LENGTH, ArraySubType = UnmanagedType.char)] public char[] RemoteMachineName; } I have never used this one before in pInvoke, so I have just cut-and-paste some def'ns that might work. "santapanda" <santapanda(a)discussions.microsoft.com> wrote in message news:63D60702-5930-47E2-B157-D8D8BBC3877E(a)microsoft.com... > Thanks M, > > Now I'm having the same issue with an SP_DEVINFO_LIST_DTAIL_DATA > structure. > > My structure is defined as > > [StructLayout(LayoutKind.Sequential)] > public struct SP_DEVINFO_LIST_DETAIL_DATA > { > public UInt32 cbSize; > public System.Guid classGuid; > public IntPtr remoteMachineHandle; > public string RemoteMachineName; > } > > The code has: > > SP_DEVINFO_LIST_DETAIL_DATA dList = new SP_DEVINFO_LIST_DETAIL_DATA(); > > dList.cbSize = (UInt32) Marshal.SizeOf(dList); > > When I call SetupDiGetDeviceInfoListDetail(deviceInfoSet, out dList), I'm > getting the same error. This time, a run through debugger finds that > cbSize > is set to 40. I tried to apply the same logic I found on pinvoke for > SP_DEVINFO_DATA, that on a 64-bit computer, the size is 4 + (32-bit). But > setting 40, 44, 32, or 28 do not work. > > How do I figure out the correct size? I'm new to Marshalling unmanaged > code, so I'm learning this by brute force; but I'm trying to understand > what > I'm doing rather than just mimicking what I'm being told/seen from other > examples. > > Thanks in advance for your help! > > > > "m" wrote: > >> While setting the size like this is possible, I wouldn't recommend it. >> In >> C# this code will be handled by a compiler provided constructor, and will >> always set the value of the cbSize member to 32. Remember that in C# >> structures are a special kind of class with no properties or methods. >> The >> binary layout when passed to pInvoke is defined by the marshal as >> attributes >> applied to the members and the defaults applied by the framework. I >> never >> trust the defaults and always define the marshalling explicitly so I can >> use >> any compatible .NET data type and not worry about what the physical >> layout >> will be since it has been specifically defined (and .NET throws an >> exception >> if the conversion is invalid) >> >> All that being said, the easiest change you can make it to simply cast >> (explicit conversion) the value of Marshal.SizeOf(devInfoData) to uint. >> The >> compiler tells you that there is no implicit conversion, but there >> certainly >> is an explicit conversion. >> >> As a side note, I have never understood the rational behind the decision >> to >> use signed integers for sizes and indices in .NET when the quantities >> are, >> like size_t, inherently unsigned (and with array objects, a negative >> index >> is an exception). Fortunately, most of the time a foreach next loop is >> approprate so it rarely comes up >> >> "santapanda" <santapanda(a)discussions.microsoft.com> wrote in message >> news:E7CEB637-18BB-4E5E-891B-F299F9CDE12F(a)microsoft.com... >> > Hi, >> > >> > Interesting suggestion, but I'm not sure I understand 100%. Are you >> > saying >> > add the cast to: >> > >> > devInfoData.cbSize = (uint) Marshal.SizeOf(devInfoData) >> > >> > I had originally declared cbsize as an int, and that's what started the >> > errors. But after reading your suggestion, I wonder if I should >> > explicitly >> > set cbSize in my struct: >> > >> > [StructLayout(LayoutKind.Sequential)] >> > public struct SP_DEVINFO_DATA >> > { >> > public int cbSize = 32; >> > public System.Guid ClassGuid; >> > public int DevInst; >> > public int Reserved; >> > } >> > >> > Is that possible? >> > >> > >> > >> > "m" wrote: >> > >> >> IMHO, the better solution is to add an explicit conversion (cast) or >> >> to >> >> change the struct def'n to match the data type (of the same size) that >> >> you >> >> can provide. Constants are very useful, but can be annoying when the >> >> aren't >> >> ;) >> >> >> >> "santapanda" <santapanda(a)discussions.microsoft.com> wrote in message >> >> news:7B5E070D-8587-43E2-A57E-5C3468E7238B(a)microsoft.com... >> >> > Thank you, >> >> > >> >> > I changed the structure to the definition provided in pinvoke.net. >> >> > After >> >> > making that change the line >> >> > >> >> > devInfoData.cbSize = Marshal.SizeOf(devInfoData); >> >> > >> >> > produced a compilation error about implicit conversion from 'int' to >> >> > 'uint'. >> >> > So instead, I changed the line to read >> >> > >> >> > devInfoData.cbSize = 32; >> >> > >> >> > 32 is the size pinvoke.net states for 64bit structure; 28 bytes is >> >> > for >> >> > 32-bit. >> >> > >> >> > Thanks again! >> >> > >> >> > "holycow" wrote: >> >> > >> >> >> Your definition of SP_DEVINFO_DATA differs from one given by >> >> >> pinvoke.net: >> >> >> http://pinvoke.net/default.aspx/Structures/SP_DEVINFO_DATA.html >> >> >> >> >> >> If your machine is 64 bit, this will matter. >> >> >> >> >> >> >> >> >> >> >> >> "santapanda" <santapanda(a)discussions.microsoft.com> wrote in >> >> >> message >> >> >> news:F889AC4D-6A3E-410C-9923-EF714631BA00(a)microsoft.com... >> >> >> > Hello, >> >> >> > >> >> >> > I have a C# application using P/Invoke on several SetupDIxxx >> >> >> > methods. I >> >> >> > am >> >> >> > attempting to pass an SP_DEVINFO_DATA object to the >> >> >> > SetupDiEnumDeviceInfo() >> >> >> > method. I have setup the SP_DEVINFO_DATA struct as follows: >> >> >> > >> >> >> > [StructLayout(LayoutKind.Sequential)] >> >> >> > public struct SP_DEVINFO_DATA >> >> >> > { >> >> >> > public int cbSize; >> >> >> > public System.Guid ClassGuid; >> >> >> > public int DevInst; >> >> >> > public int Reserved; >> >> >> > } >> >> >> > >> >> >> > Based on articles in the MSDN Library, and an example i found on >> >> >> > pinvoke.net, I know I'm supposed to set my object's cbsize to >> >> >> > sizeof(SP_DEVINFO_DATA). >> >> >> > >> >> >> > Here is my code: >> >> >> > ===================== >> >> >> > [...] >> >> >> > SP_DEVINFO_DATA devInfoData = new SP_DEVINFO_DATA(); >> >> >> > IntPtr deviceInfoSet = SetupDiGetClassDevs (ref guids[0], null, >> >> >> > 0, >> >> >> > DIGCF_PRESENT | DIGCF_ALLCLASSES); >> >> >> > >> >> >> > if (deviceInfoSet != INVALID_HANDLE_VALUE) >> >> >> > { >> >> >> > int devIndex = 0; >> >> >> > devInfoData.cbSize = Marshal.SizeOf(devInfoData); >> >> >> > bool success = SetupDiEnumDeviceInfo(deviceInfoSet, devIndex, >> >> >> > out devInfoData); >> >> >> > [...] >> >> >> > } >> >> >> > ===================== >> >> >> > >> >> >> > When I run, I get the error: "The supplied user buffer is not >> >> >> > valid >> >> >> > for >> >> >> > the >> >> >> > requested operation." The documentation from MSDN states this >> >> >> > error >> >> >> > is >> >> >> > generated when "the cbSize member is not set correctly for an >> >> >> > output >> >> >> > parameter". >> >> >> > >> >> >> > This is my first time using P/Invoke and working with Windows >> >> >> > APIs. >> >> >> > So >> >> >> > please help me understand how to pass the correct cbSize value. >> >> >> > When I >> >> >> > ran >> >> >> > debugger, the cbSize is 0 when the object is going in, but when >> >> >> > it >> >> >> > comes >> >> >> > out >> >> >> > the cbSize is 28. I tried setting cbSize prior to calling the >> >> >> > SetupDiEnumDeviceInfo method to various values like 28 and 1024, >> >> >> > but >> >> >> > I >> >> >> > still >> >> >> > got the same error. >> >> >> > >> >> >> > Thanks! >> >> >> >> >> . >> >> >> . >>
From: santapanda on 15 Apr 2010 10:15 Thanks m, But that didn't work. After getting the same error about the buffer size, I altered your suggestion to use UnmanagedType.U8 for cbSize, since I'm on a 64-bit machine. That generated a new error: Type 'SP_DEVINFO_LIST_DTAIL_DATA' cannot be marshaled as an unmanaged structure; no meaningful size or offset can be computed. I'm going to post a new thread just for SP_DEVINFO_LIST_DETAIL_DATA. Thanks for all of your help so far; you were extremely helpful. santapanda "m" wrote: > try something like this: > > (Untested code) > > [StructLayout(LayoutKind.Sequential)] > public struct SP_DEVINFO_LIST_DETAIL_DATA > { > [MarshalAs(UnmanagedType.U4)] > public UInt32 cbSize; > > [MarshalAs(UnmanagedType.Struct)] > public System.Guid classGuid; > > [MarshalAs(UnmanagedType.SysInt)] > public IntPtr remoteMachineHandle; > > [MarshalAs(UnmanagedType.ByValArray, SizeConst = SP_MAX_MACHINENAME_LENGTH, > ArraySubType = UnmanagedType.char)] > public char[] RemoteMachineName; > } > > I have never used this one before in pInvoke, so I have just cut-and-paste > some def'ns that might work. > > "santapanda" <santapanda(a)discussions.microsoft.com> wrote in message > news:63D60702-5930-47E2-B157-D8D8BBC3877E(a)microsoft.com... > > Thanks M, > > > > Now I'm having the same issue with an SP_DEVINFO_LIST_DTAIL_DATA > > structure. > > > > My structure is defined as > > > > [StructLayout(LayoutKind.Sequential)] > > public struct SP_DEVINFO_LIST_DETAIL_DATA > > { > > public UInt32 cbSize; > > public System.Guid classGuid; > > public IntPtr remoteMachineHandle; > > public string RemoteMachineName; > > } > > > > The code has: > > > > SP_DEVINFO_LIST_DETAIL_DATA dList = new SP_DEVINFO_LIST_DETAIL_DATA(); > > > > dList.cbSize = (UInt32) Marshal.SizeOf(dList); > > > > When I call SetupDiGetDeviceInfoListDetail(deviceInfoSet, out dList), I'm > > getting the same error. This time, a run through debugger finds that > > cbSize > > is set to 40. I tried to apply the same logic I found on pinvoke for > > SP_DEVINFO_DATA, that on a 64-bit computer, the size is 4 + (32-bit). But > > setting 40, 44, 32, or 28 do not work. > > > > How do I figure out the correct size? I'm new to Marshalling unmanaged > > code, so I'm learning this by brute force; but I'm trying to understand > > what > > I'm doing rather than just mimicking what I'm being told/seen from other > > examples. > > > > Thanks in advance for your help!
From: Maxim S. Shatskih on 15 Apr 2010 12:56 > Type 'SP_DEVINFO_LIST_DTAIL_DATA' cannot be marshaled as an unmanaged > structure; no meaningful size or offset can be computed. Design a higher-level API which will not use such structures, implement it in unmanaged DLL by calling SetupDiXxx, and pinvoke to it. -- Maxim S. Shatskih Windows DDK MVP maxim(a)storagecraft.com http://www.storagecraft.com
First
|
Prev
|
Next
|
Last
Pages: 1 2 3 4 Prev: Replacing USBSTOR.sys Next: Can DIFx be used to install NDIS protocol driver? |