using System.ComponentModel; using System.Diagnostics; using System.Reflection; using Agent.Windows.Security; using Windows.Win32; using Windows.Win32.NetworkManagement.WindowsFilteringPlatform; namespace Agent.Windows.Diagnostics; public sealed record WindowsPlatformCheckResult( bool PlatformSupported, bool ApplicationProfileAvailable, bool BfeEngineOpen, bool HelperAvailable, bool HelperVersionCompatible, int? ErrorCode, string? ErrorOperation) { public bool Success => PlatformSupported && ApplicationProfileAvailable && BfeEngineOpen && HelperAvailable && HelperVersionCompatible; } public static class WindowsPlatformCheck { public static WindowsPlatformCheckResult Run(string helperPath) { bool platform = OperatingSystem.IsWindowsVersionAtLeast(10, 0, 26100); bool profile = false; bool bfe = false; bool helper = File.Exists(helperPath); bool version = false; try { _ = AppContainerProfile.DeriveFixed(); profile = true; using FwpmEngineClose0SafeHandle engine = OpenBfeReadOnly(); bfe = true; if (helper) { Version? current = Assembly.GetEntryAssembly()?.GetName().Version; string candidate = FileVersionInfo.GetVersionInfo(helperPath).FileVersion ?? ""; version = current is not null && HasSameReleaseIdentity(current, candidate); } return new(platform, profile, bfe, helper, version, null, null); } catch (Win32Exception ex) { return new(platform, profile, bfe, helper, version, ex.NativeErrorCode, ex.Message); } catch (Exception ex) when (ex is UnauthorizedAccessException or InvalidOperationException or IOException) { return new(platform, profile, bfe, helper, version, ex.HResult, ex.Message); } } internal static bool HasSameReleaseIdentity(Version current, string candidate) { if (!Version.TryParse(candidate, out Version? parsed)) return false; return current.Major == parsed.Major && current.Minor == parsed.Minor && current.Build == parsed.Build; } private static FwpmEngineClose0SafeHandle OpenBfeReadOnly() { uint result = PInvoke.FwpmEngineOpen0(10, null, null, out FwpmEngineClose0SafeHandle engine); if (result != 0) throw new Win32Exception(unchecked((int)result), $"FwpmEngineOpen0 failed with WFP/Win32 error 0x{result:X8}."); return engine; } }