using System.Runtime.InteropServices; using System.Text; namespace XFESystem.DriverOracle; internal sealed record PciDevice(string InstanceId, string[] HardwareIds, uint Bus, uint Device, uint Function); internal static class WindowsPci { [StructLayout(LayoutKind.Sequential)] private struct DeviceInfo { public uint Size; public Guid ClassGuid; public uint Instance; public nuint Reserved; } private static readonly Guid DisplayClass = new("4d36e968-e325-11ce-bfc1-08002be10318"); [DllImport("setupapi.dll", CharSet = CharSet.Unicode, SetLastError = true)] [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] private static extern nint SetupDiGetClassDevsW(ref Guid classGuid, string? enumerator, nint parent, uint flags); [DllImport("setupapi.dll", SetLastError = true)] [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool SetupDiEnumDeviceInfo(nint set, uint index, ref DeviceInfo data); [DllImport("setupapi.dll", SetLastError = true)] [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool SetupDiGetDeviceRegistryPropertyW(nint set, ref DeviceInfo data, uint property, out uint type, byte[] buffer, uint bytes, out uint needed); [DllImport("setupapi.dll", CharSet = CharSet.Unicode, SetLastError = true)] [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool SetupDiGetDeviceInstanceIdW(nint set, ref DeviceInfo data, StringBuilder identifier, uint capacity, out uint needed); [DllImport("setupapi.dll", SetLastError = true)] [DefaultDllImportSearchPaths(DllImportSearchPath.System32)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool SetupDiDestroyDeviceInfoList(nint set); public static PciDevice[] Exact5090() { Guid display = DisplayClass; nint set = SetupDiGetClassDevsW(ref display, null, 0, 2 /* DIGCF_PRESENT */); if (set == -1) throw new InvalidOperationException("Read-only display PCI enumeration failed: " + Marshal.GetLastWin32Error()); var devices = new List(); try { for (uint index = 0; ; index++) { var data = new DeviceInfo { Size = (uint)Marshal.SizeOf() }; if (!SetupDiEnumDeviceInfo(set, index, ref data)) { if (Marshal.GetLastWin32Error() == 259) break; throw new InvalidOperationException("Display enumeration failed: " + Marshal.GetLastWin32Error()); } byte[] hardware = Property(set, ref data, 1 /* SPDRP_HARDWAREID */, 7); string[] ids = Encoding.Unicode.GetString(hardware).Split('\0', StringSplitOptions.RemoveEmptyEntries); if (!ids.Any(id => id.StartsWith(@"PCI\VEN_10DE&DEV_2B85&", StringComparison.OrdinalIgnoreCase) || id.Equals(@"PCI\VEN_10DE&DEV_2B85", StringComparison.OrdinalIgnoreCase))) continue; uint bus = BitConverter.ToUInt32(Property(set, ref data, 0x15 /* SPDRP_BUSNUMBER */, 4)); uint address = BitConverter.ToUInt32(Property(set, ref data, 0x1C /* SPDRP_ADDRESS */, 4)); var instance = new StringBuilder(1024); if (!SetupDiGetDeviceInstanceIdW(set, ref data, instance, 1024, out _)) throw new InvalidOperationException("Cannot read the matched PCI instance."); devices.Add(new(instance.ToString(), ids, bus, address >> 16, address & 0xFFFF)); } } finally { if (!SetupDiDestroyDeviceInfoList(set)) throw new InvalidOperationException("Cannot release read-only PCI enumeration state."); } return devices.ToArray(); } private static byte[] Property(nint set, ref DeviceInfo data, uint property, uint expectedType) { byte[] buffer = new byte[4096]; if (!SetupDiGetDeviceRegistryPropertyW(set, ref data, property, out uint type, buffer, (uint)buffer.Length, out uint needed) || type != expectedType || needed > buffer.Length || needed == 0 || (expectedType == 4 && needed != 4)) throw new InvalidOperationException("Cannot read the bounded PCI identity property " + property + ": " + Marshal.GetLastWin32Error()); return buffer[..(int)needed]; } }