SetupDiGetDeviceRegistryProperty fails with ERROR_INVALID_DATA

自作多情 提交于 2019-12-12 01:47:13

问题


I'm trying to get the display names as they appear in the "Screen Resolution" window (Win8.1 x64).

First I tried EnumDisplayDevices

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);
}

The second call to EnumDisplayDevices (with EDD_GET_DEVICE_INTERFACE_NAME) 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 Generic PnP Monitor, instead of SAMSUNG as it appears in the "Screen Resolution" Window. Perhaps the fact that it's connected by HDMI is somehow related?

I then tried the Setup API

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());
}

Looking at the returned values from the different methods, everything seems to work, but the last call to SetupDiGetDeviceRegistryProperty fails with ERROR_INVALID_DATA (that is, the method returns false and GetLastWin32Error yields 13). According to the docs, this means that the requested property does not exist for a device or if the property data is not valid.

I actually looped over all possible SPDRP values (0-24) and they all result in the same failure. Just to clarify, I expected the method to fail, but with ERROR_INSUFFICIENT_BUFFER and having requiredSize set (the latter simply retains its previous value, as the unmanaged code doesn't change it).

Here's the signature for SetupDiGetDeviceRegistryProperty (all other methods work as expected):

[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);

回答1:


Looks like what I'm looking for is impossible:

There is not a supported way to figour out the IDs that you referred to programmatically. It was never a design goal to provide a way for applications to label monitors with the same IDs that the screen resolution control panel uses



来源:https://stackoverflow.com/questions/24356289/setupdigetdeviceregistryproperty-fails-with-error-invalid-data

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!