title: SetupDiGetDeviceRegistryProperty fails with ERROR_INVALID_DATA
body: <p>I'm trying to get the display names as they appear in the "Screen Resolution" window (Win8.1 x64). </p>
  
  <p>First I tried <code>EnumDisplayDevices</code></p>
  
  <pre><code>var deviceInfo = new DISPLAY_DEVICEW();
  uint i = 0;
  while (true)
  {
      if (!NativeMethods.EnumDisplayDevices(null, i++, deviceInfo, 0))
      {
          break;
      }
      PrintDeviceInfo(deviceInfo);
  
      NativeMethods.EnumDisplayDevices(deviceInfo.DeviceName, 0, deviceInfo, EDD_GET_DEVICE_INTERFACE_NAME);
      PrintDeviceInfo(deviceInfo);
  }
  </code></pre>
  
  <p>The second call to <code>EnumDisplayDevices</code> (with <code>EDD_GET_DEVICE_INTERFACE_NAME</code>) indeed yielded the display name as it appears for my main display (in DISPLAY_DEVICEW.DeviceString). However for my HDMI-connected TV that field contains <em>Generic PnP Monitor</em>, instead of <em>SAMSUNG</em> as it appears in the "Screen Resolution" Window. Perhaps the fact that it's connected by HDMI is somehow related?</p>
  
  <p>I then tried the Setup API</p>
  
  <pre><code>var hdevinfo = NativeMethods.SetupDiGetClassDevs(ref GUID_DEVINTERFACE_MONITOR, null, IntPtr.Zero, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
  if (hdevinfo == INVALID_HANDLE_VALUE) return;
  var spDeviceInterfaceData = new SP_DEVICE_INTERFACE_DATA();
  uint memberIndex = 0;
  while (true)
  {
      bool success = NativeMethods.SetupDiEnumDeviceInterfaces(hdevinfo, null, ref GUID_DEVINTERFACE_MONITOR, memberIndex++, spDeviceInterfaceData);
      if (!success)
      {
          break;
      }
      PrintInterfaceData(spDeviceInterfaceData);
  
      uint requiredSize;
      var devInfoData = new SP_DEVINFO_DATA();
  
      NativeMethods.SetupDiGetDeviceInterfaceDetail(hdevinfo, spDeviceInterfaceData, IntPtr.Zero, 0, out requiredSize, devInfoData);
      PrintDevInfoData(devInfoData);
  
      var interfaceDetail = Marshal.AllocHGlobal((int)requiredSize);
      var cbSize = (Marshal.SizeOf(typeof(uint)) + Marshal.SystemDefaultCharSize);
      Marshal.WriteInt32(interfaceDetail, 0, cbSize);
      NativeMethods.SetupDiGetDeviceInterfaceDetail(hdevinfo, spDeviceInterfaceData, interfaceDetail, requiredSize, IntPtr.Zero, null);
      var dynamicType = GetDeviceInterfaceDetailDataType(requiredSize);
      var interfaceDetailStruct = Marshal.PtrToStructure(interfaceDetail, dynamicType);
      Marshal.FreeHGlobal(interfaceDetail);
      PrintInterfaceDetail(interfaceDetailStruct);
  
      uint propertyRegDataType;
      NativeMethods.SetupDiGetDeviceRegistryProperty(hdevinfo, devInfoData, SPDRP_FRIENDLYNAME, out propertyRegDataType, null, 0, out requiredSize);
      Console.WriteLine(Marshal.GetLastWin32Error());
  }
  </code></pre>
  
  <p>Looking at the returned values from the different methods, everything seems to work, but the last call to <code>SetupDiGetDeviceRegistryProperty</code> fails with <code>ERROR_INVALID_DATA</code> (that is, the method returns false and <code>GetLastWin32Error</code> yields <code>13</code>). According to the <a href="http://msdn.microsoft.com/en-us/library/windows/hardware/ff551967%28v=vs.85%29.aspx" rel="nofollow">docs</a>, this means that <em>the requested property does not exist for a device or if the property data is not valid</em>.</p>
  
  <p>I actually looped over all possible <code>SPDRP</code> values (0-24) and they all result in the same failure. Just to clarify, I expected the method to fail, but with <code>ERROR_INSUFFICIENT_BUFFER</code> and having <code>requiredSize</code> set (the latter simply retains its previous value, as the unmanaged code doesn't change it).</p>
  
  <p>Here's the signature for <code>SetupDiGetDeviceRegistryProperty</code> (all other methods work as expected):</p>
  
  <pre><code>[StructLayout(LayoutKind.Sequential)]
  public class SP_DEVINFO_DATA
  {
      public uint cbSize = (uint) Marshal.SizeOf(typeof (SP_DEVINFO_DATA));
      public Guid ClassGuid;
      public uint DevInst;
      public IntPtr Reserved;
  }
  [DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
  public static extern bool SetupDiGetDeviceRegistryProperty(
      IntPtr deviceInfoSet,
      SP_DEVINFO_DATA deviceInfoData, 
      uint property, 
      out uint propertyRegDataType, 
      byte[] propertyBuffer, 
      uint propertyBufferSize, 
      out uint requiredSize);
  </code></pre>