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<PciDevice>();
try
{
for (uint index = 0; ; index++)
{
var data = new DeviceInfo { Size = (uint)Marshal.SizeOf<DeviceInfo>() };
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];
}
}
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<PciDevice>();
try
{
for (uint index = 0; ; index++)
{
var data = new DeviceInfo { Size = (uint)Marshal.SizeOf<DeviceInfo>() };
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];
}
}