none
SetupDiGetDeviceRegistryProperty RRS feed

  • Question

  • I have a C# application using P/Invoke to call several SetupApi.dll methods.  I'm not getting an error when I call SetupDiGetDeviceRegistryProperty(), but I'm not getting the desired result either.

    At first, I followed the example code on pinvoke.net (http://pinvoke.net/default.aspx/setupapi.SetupDiGetDeviceRegistryProperty), but I got an error at the line "string ControllerDeviceDesc = Marshal.PtrToStringAuto(ptrBuf)".  I think this is because the sample code defined ptrBuf as a byte[].  So I defined my ptBuf as IntPtr and now the following code runs:

    [...]IntPtr ptrBuffer = new IntPtr();UInt32 requiredSize;UInt32 regType = REG_SZ (which is defined as 1);string deviceName;if (SetupDiGetDeviceRegistryProperty(deviceInfoSet, ref devInfoData, SPDRP_DEVICEDESC, out regType, out ptrBuffer, BUFFER_SIZE, out requiredSize) {   deviceName = Marshal.PtrToStringAuto(ptrBuffer);   MessageBox.Show("Device Name = " + deviceName);} else{   MessageBox.Show(GetLastWin32Error());}[...]

    The code runs, but the message box only has "Device Name = ". 

    If you need additional details, please let me know.  But I'm quite perplexed!

    Thanks!

    Friday, April 16, 2010 4:54 PM

Answers

  • Remove the "out" modifier on ptrBuffer. The pointer itself is an input parameter (even though the buffer it points to recieves output), so you must allocate and initialize it to point to a big enough buffer.

     


    Mattias, C# MVP
    • Proposed as answer by Ter-ray-cy Thursday, April 22, 2010 3:03 AM
    • Marked as answer by eryang Friday, April 23, 2010 5:10 AM
    Monday, April 19, 2010 2:06 PM
    Moderator

All replies

  • Remove the "out" modifier on ptrBuffer. The pointer itself is an input parameter (even though the buffer it points to recieves output), so you must allocate and initialize it to point to a big enough buffer.

     


    Mattias, C# MVP
    • Proposed as answer by Ter-ray-cy Thursday, April 22, 2010 3:03 AM
    • Marked as answer by eryang Friday, April 23, 2010 5:10 AM
    Monday, April 19, 2010 2:06 PM
    Moderator
  • Thanks,

    I removed "out" just like you suggested.  When I ran the program, I now get the error "The supplied user buffer is not valid for the requested operation."

    BUFFER_SIZE is set to 1024.  I ran debugger and watched ptBuffer.  I noticed a size attribute is set to 8, but I don't know how to manually set it myself.  What did you mean "allocate and initialize it to point to a big enough buffer"?

    Monday, April 19, 2010 2:36 PM
  • I mean

    ptrBuffer = Marshal.AllocHGlobal(BUFFER_SIZE);

    SetupDiGetDeviceRegistryProperty(...)

    Marshal.FreeHGlobal(ptrBuffer);

    Add the required logic to re-alloc a larger buffer and make another call if the function returns a bigger required size in the requiredSize parameter.


    Mattias, C# MVP
    • Marked as answer by santapanda Monday, April 19, 2010 3:39 PM
    • Unmarked as answer by santapanda Wednesday, April 21, 2010 2:27 PM
    • Proposed as answer by Ter-ray-cy Thursday, April 22, 2010 3:03 AM
    • Marked as answer by eryang Friday, April 23, 2010 5:10 AM
    • Unmarked as answer by santapanda Friday, April 23, 2010 12:44 PM
    Monday, April 19, 2010 2:47 PM
    Moderator
  • You are awesome!  Thanks that worked!  I had to change the toString line to

    deviceName = Marshal.PtrToStringAnsi(ptrBuffer);

    instead of deviceName = Marshal.PtrToStringAuto(ptrBuffer);

    When I made your change and ran the original code, I got boxes as my device name. 

    I didn't add the logic to re-allocate a larger buffer, because I wasn't sure what to compare requiredSize to.  I know I should add it to help prevent errors in the future, but I wanted to confirm the code.

    Is it

    if (ptrBuffer < uintRequiredSize) 
    {
      ptBuffer = Marshal.AllocHGlobal(uintRequiredSize);
      bool success = SetupDiGetDeviceRegistryProperty(...);
    }
    
    if (success)
    {
      deviceName = Marshal.PtrToStringAnsi(ptrBuffer);
      ...
    }
    ....
    
    Thanks again!
    Monday, April 19, 2010 3:39 PM
  • Hi santapanda,

    It seems you have get the right answer about this issue, so I marked it.

    If you have any further question about this issue, please feel free to ummark it, and we will discuss it again.

    Thanks for your post! And have a nice day!


    Sincerely,
    Eric
    MSDN Subscriber Support in Forum
    If you have any feedback of our support, please contact msdnmg@microsoft.com.
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Friday, April 23, 2010 5:12 AM
  • I was waiting for a response to my last post, requesting confirmation about the logic for re-allocating the buffer size.  If you can, please respond to that, then I will mark the post as being answered fully.

    Thanks!

    Friday, April 23, 2010 12:45 PM

  • I am not able to get the success status while executing - SetupDiGetDeviceRegistryProperty :

    I am using it like this :
     
    IntPtr propertyBuffer= newIntPtr();
     
    UInt32 RequiredSize;
     
    UInt32propertyRegDataType;
     
    UInt32propertyBufferSize = 0;
     
    UInt32RequiredSize;
     
     
    SetupDiGetDeviceRegistryProperty has been defined like this :

    Native.SetupDiGetDeviceRegistryProperty
      (deviceInfoSet,
      IntPtr.Zero,
      0x00000022,//Property Type
     out propertyRegDataType,
     propertyBuffer,
     propertyBufferSize,
     out RequiredSize);
     
    [StructLayout(LayoutKind.Sequential)]
    public struct SP_DEVINFO_DATA
    {
    /// <summary>Size of the structure, in bytes.</summary>
    internal UInt32 cbSize;
    /// <summary>GUID of the device interface class.</summary>
    internal Guid ClassGuid;
    /// <summary>Handle to this device instance.</summary>
    internal UInt32 DevInst;
    /// <summary>Reserved; do not use.</summary>
    internal UInt32 Reserved;
    }
     
    Do I need to Initialize any parameter before sending.I  have already populated deviceInfoSet.

    I tried getting the deviceInfoData  before sending it as an argument in the SetupDiGetDeviceRegistryProperty like this :

     Native.SP_DEVINFO_DATA deviceInfoData = new Native.SP_DEVINFO_DATA();
    //  deviceInfoData.cbSize = Marshal.SizeOf(struct);
    deviceInfoData.cbSize = 28;//What will be this size?
    success = Native.SetupDiEnumDeviceInfo(deviceInfoSet, 4/*I know this is the correct index*/, ref deviceInfoData);


    SetupDiEnumDeviceInfo is defined like this :

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


     
    How to do the  parameters' intialization?I am running it in Windows 7.

    I dont know but  both functions gave me false?Is it due to the wrong deviceInfoData initialization  or there is something  else I need to do to access these functions .
     
    Rgds,

     

    • Edited by hcktester Wednesday, February 12, 2014 8:22 AM
    Wednesday, February 12, 2014 7:43 AM
  • HI,

    Kindly update on this, is this post closed ??

    Rgds



    • Edited by hcktester Tuesday, February 18, 2014 4:27 PM Seeking for Attention !
    Friday, February 14, 2014 2:12 AM
  • Hi.

    Your SP_DEVINFO_DATA struct definition is wrong. The Reserved field should be IntPtr, and not uint. With that the Marshal.SizeOf will also work for both 32 and 64 bit.

    Cheers,

    Zoltán

    Friday, July 25, 2014 9:03 PM