private static IEnumerable <PartialScreenInfo> GetSetupApiData()
        {
            var screenInfos = new List <PartialScreenInfo>();
            var monitorGuid = NativeMethods.GUID_DEVINTERFACE_MONITOR;

            var devInfoSetHandle = IntPtr.Zero;

            try
            {
                devInfoSetHandle = NativeMethods.SetupDiGetClassDevs(
                    ref monitorGuid,
                    null,
                    IntPtr.Zero,
                    NativeMethods.DiGetClassFlags.DIGCF_PRESENT |
                    NativeMethods.DiGetClassFlags.DIGCF_DEVICEINTERFACE);
                if (devInfoSetHandle == IntPtr.Zero)
                {
                    throw new Win32Exception();
                }

                uint i = 0;
                while (true)
                {
                    var deviceInterfaceData = new NativeMethods.SP_DEVICE_INTERFACE_DATA();
                    deviceInterfaceData.cbSize = Marshal.SizeOf(deviceInterfaceData);

                    if (!NativeMethods.SetupDiEnumDeviceInterfaces(
                            devInfoSetHandle, IntPtr.Zero, ref monitorGuid, i, ref deviceInterfaceData))
                    {
                        if (Marshal.GetLastWin32Error() == NativeMethods.ERROR_NO_MORE_ITEMS)
                        {
                            break;
                        }

                        throw new Win32Exception();
                    }

                    var deviceInterfaceDetail = GetDeviceInterfaceDetail(devInfoSetHandle, ref deviceInterfaceData);
                    var screenInfo            = new PartialScreenInfo(
                        deviceInterfaceDetail.DevicePath,
                        GetDeviceInstanceId(deviceInterfaceDetail.DevinfoData.DevInst),
                        GetMonitorEDID(devInfoSetHandle, deviceInterfaceDetail.DevinfoData));

                    screenInfos.Add(screenInfo);

                    i++;
                }
            }
            finally
            {
                if (devInfoSetHandle != IntPtr.Zero)
                {
                    NativeMethods.SetupDiDestroyDeviceInfoList(devInfoSetHandle);
                }
            }

            return(screenInfos);
        }
        private static DeviceInterfaceDetail GetDeviceInterfaceDetail(IntPtr devInfoSetHandle, ref NativeMethods.SP_DEVICE_INTERFACE_DATA deviceInterfaceData)
        {
            var devinfoData = new NativeMethods.SP_DEVINFO_DATA();

            devinfoData.cbSize = Marshal.SizeOf(devinfoData);

            uint requiredSize;

            if (!NativeMethods.SetupDiGetDeviceInterfaceDetail(
                    devInfoSetHandle,
                    ref deviceInterfaceData,
                    IntPtr.Zero,
                    0,
                    out requiredSize,
                    ref devinfoData))
            {
                if (Marshal.GetLastWin32Error() != NativeMethods.ERROR_INSUFFICIENT_BUFFER)
                {
                    throw new Win32Exception();
                }
            }

            var deviceInterfaceDetailDataBuffer = Marshal.AllocHGlobal(
                Marshal.SizeOf(typeof(uint)) +
                Marshal.SystemDefaultCharSize +
                (int)requiredSize + Marshal.SystemDefaultCharSize);

            string devicePath;

            try
            {
                // Potential danger: Writing int to uint
                Marshal.WriteInt32(
                    deviceInterfaceDetailDataBuffer,
                    NativeMethods.SP_DEVICE_INTERFACE_DETAIL_DATA_SIZE);

                if (!NativeMethods.SetupDiGetDeviceInterfaceDetail(
                        devInfoSetHandle,
                        ref deviceInterfaceData,
                        deviceInterfaceDetailDataBuffer,
                        requiredSize,
                        out requiredSize,
                        ref devinfoData))
                {
                    throw new Win32Exception();
                }

                devicePath = Marshal.PtrToStringAuto(
                    new IntPtr(deviceInterfaceDetailDataBuffer.ToInt32() + 4),
                    ((int)requiredSize - 6) / 2);
            }
            finally
            {
                Marshal.FreeHGlobal(deviceInterfaceDetailDataBuffer);
            }

            return(new DeviceInterfaceDetail(devinfoData, devicePath));
        }
        private static IEnumerable<PartialScreenInfo> GetSetupApiData()
        {
            var screenInfos = new List<PartialScreenInfo>();
            var monitorGuid = NativeMethods.GUID_DEVINTERFACE_MONITOR;

            var devInfoSetHandle = IntPtr.Zero;
            try
            {
                devInfoSetHandle = NativeMethods.SetupDiGetClassDevs(
                    ref monitorGuid,
                    null,
                    IntPtr.Zero,
                    NativeMethods.DiGetClassFlags.DIGCF_PRESENT |
                        NativeMethods.DiGetClassFlags.DIGCF_DEVICEINTERFACE);
                if (devInfoSetHandle == IntPtr.Zero)
                {
                    throw new Win32Exception();
                }

                uint i = 0;
                while (true)
                {
                    var deviceInterfaceData = new NativeMethods.SP_DEVICE_INTERFACE_DATA();
                    deviceInterfaceData.cbSize = Marshal.SizeOf(deviceInterfaceData);

                    if (!NativeMethods.SetupDiEnumDeviceInterfaces(
                        devInfoSetHandle, IntPtr.Zero, ref monitorGuid, i, ref deviceInterfaceData))
                    {
                        if (Marshal.GetLastWin32Error() == NativeMethods.ERROR_NO_MORE_ITEMS)
                        {
                            break;
                        }

                        throw new Win32Exception();
                    }

                    var deviceInterfaceDetail = GetDeviceInterfaceDetail(devInfoSetHandle, ref deviceInterfaceData);
                    var screenInfo = new PartialScreenInfo(
                        deviceInterfaceDetail.DevicePath,
                        GetDeviceInstanceId(deviceInterfaceDetail.DevinfoData.DevInst),
                        GetMonitorEDID(devInfoSetHandle, deviceInterfaceDetail.DevinfoData));

                    screenInfos.Add(screenInfo);

                    i++;
                }
            }
            finally
            {
                if (devInfoSetHandle != IntPtr.Zero)
                {
                    NativeMethods.SetupDiDestroyDeviceInfoList(devInfoSetHandle);
                }
            }

            return screenInfos;
        }