diff --git a/composer.json b/composer.json index 9838f5c..cc4c653 100644 --- a/composer.json +++ b/composer.json @@ -36,11 +36,12 @@ "require": { "php": ">=8.1", "ext-filter": "*", + "ext-json": "*", "amphp/amp": "^3", "amphp/byte-stream": "^2", "amphp/cache": "^2", "amphp/parser": "^1", - "amphp/windows-registry": "^1.0.1", + "amphp/process": "^2", "daverandom/libdns": "^2.0.2", "revolt/event-loop": "^1 || ^0.2" }, diff --git a/src/WindowsDnsConfigLoader.php b/src/WindowsDnsConfigLoader.php index efa3326..2302e38 100644 --- a/src/WindowsDnsConfigLoader.php +++ b/src/WindowsDnsConfigLoader.php @@ -4,19 +4,15 @@ use Amp\ForbidCloning; use Amp\ForbidSerialization; -use Amp\WindowsRegistry\KeyNotFoundException; -use Amp\WindowsRegistry\WindowsRegistry; +use Amp\Process\Process; +use function Amp\ByteStream\buffer; +use function Amp\ByteStream\splitLines; final class WindowsDnsConfigLoader implements DnsConfigLoader { use ForbidCloning; use ForbidSerialization; - private const NETWORK_CARDS_KEY = - 'HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards'; - private const TCPIP_PARAMETERS_KEY = - 'HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces'; - public function __construct( private readonly HostLoader $hostLoader = new HostLoader(), ) { @@ -24,69 +20,33 @@ public function __construct( public function loadConfig(): DnsConfig { - $keys = [ - "HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\NameServer", - "HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\DhcpNameServer", - ]; - - $nameserver = ""; - - while ($nameserver === "" && ($key = \array_shift($keys))) { - try { - $nameserver = WindowsRegistry::read($key); - } catch (KeyNotFoundException) { - // retry other possible locations - } + $powershell = Process::start([ + 'powershell', + '-Command', + 'Get-WmiObject -Class Win32_NetworkAdapterConfiguration | + Select-Object -ExpandProperty DNSServerSearchOrder', + ]); + + if ($powershell->join() !== 0) { + throw new DnsConfigException("Could not fetch DNS servers from WMI: " . buffer($powershell->getStderr())); } - if ($nameserver === "") { - foreach (self::findNetworkCardGuids() as $guid) { - foreach (["NameServer", "DhcpNameServer"] as $property) { - try { - $nameserver = WindowsRegistry::read(self::TCPIP_PARAMETERS_KEY . "\\$guid\\$property"); - - if ($nameserver !== "") { - break 2; - } - } catch (KeyNotFoundException) { - // retry other possible locations - } - } - } - } - - if ($nameserver === "") { - throw new DnsConfigException("Could not find a nameserver in the Windows Registry"); - } + $output = \iterator_to_array(splitLines($powershell->getStdout())); - $nameservers = []; - - // Comma is the delimiter for the NameServer key, but space is used for the DhcpNameServer key. - foreach (\explode(" ", \strtr($nameserver, ",", " ")) as $nameserver) { - $nameserver = \trim($nameserver); - $ip = \inet_pton($nameserver); - - if ($ip === false) { - continue; - } + $nameservers = \array_reduce($output, static function (array $nameservers, string $address): array { + $ip = \inet_pton($address); if (isset($ip[15])) { // IPv6 - $nameservers[] = "[" . $nameserver . "]:53"; - } else { // IPv4 - $nameservers[] = $nameserver . ":53"; + $nameservers[] = "[$address]:53"; + } elseif (isset($ip[3])) { // IPv4 + $nameservers[] = "$address:53"; } - } + + return $nameservers; + }, []); $hosts = $this->hostLoader->loadHosts(); return new DnsConfig($nameservers, $hosts); } - - private static function findNetworkCardGuids(): array - { - return \array_map( - static fn (string $key): string => WindowsRegistry::read("$key\\ServiceName"), - WindowsRegistry::listKeys(self::NETWORK_CARDS_KEY), - ); - } }