diff --git a/src/c#/GeneralUpdate.Drivelution/Windows/Implementation/WindowsGeneralDrivelution.cs b/src/c#/GeneralUpdate.Drivelution/Windows/Implementation/WindowsGeneralDrivelution.cs index bbcdc600..74102c16 100644 --- a/src/c#/GeneralUpdate.Drivelution/Windows/Implementation/WindowsGeneralDrivelution.cs +++ b/src/c#/GeneralUpdate.Drivelution/Windows/Implementation/WindowsGeneralDrivelution.cs @@ -2,331 +2,240 @@ using System.Runtime.Versioning; using GeneralUpdate.Common.Shared; using GeneralUpdate.Drivelution.Abstractions; +using GeneralUpdate.Drivelution.Abstractions.Configuration; using GeneralUpdate.Drivelution.Abstractions.Exceptions; using GeneralUpdate.Drivelution.Abstractions.Models; +using GeneralUpdate.Drivelution.Core.Pipeline; using GeneralUpdate.Drivelution.Core.Utilities; using GeneralUpdate.Drivelution.Windows.Helpers; namespace GeneralUpdate.Drivelution.Windows.Implementation; /// -/// Windows驱动更新器实现 -/// Windows driver updater implementation +/// Windows driver updater implementation. +/// Inherits the unified pipeline from and adds Windows-specific +/// permission checks, PnPUtil-based installation, and INF file parsing. /// [SupportedOSPlatform("windows")] -public class WindowsGeneralDrivelution : IGeneralDrivelution +public class WindowsGeneralDrivelution : BaseDriverUpdater { - private readonly IDriverValidator _validator; - private readonly IDriverBackup _backup; + /// + /// Initializes a new instance of the class. + /// + /// Driver validator. + /// Driver backup manager. + /// Configuration options (optional). + public WindowsGeneralDrivelution( + IDriverValidator validator, + IDriverBackup backup, + DrivelutionOptions? options = null) + : base(validator, backup, options) + { + } + + // ─── Pipeline overrides ──────────────────────────────────────────── - public WindowsGeneralDrivelution(IDriverValidator validator, IDriverBackup backup) + /// + protected override IEnumerable GetPipelineSteps(UpdateStrategy strategy) { - _validator = validator ?? throw new ArgumentNullException(nameof(validator)); - _backup = backup ?? throw new ArgumentNullException(nameof(backup)); + // Prepend Windows permission check before the default pipeline + yield return CreatePermissionCheckStep(); + + foreach (var step in base.GetPipelineSteps(strategy)) + yield return step; } /// - public async Task UpdateAsync( + protected override async Task InstallCoreAsync( DriverInfo driverInfo, UpdateStrategy strategy, - CancellationToken cancellationToken = default) + CancellationToken cancellationToken) { - var result = new UpdateResult - { - StartTime = DateTime.UtcNow, - Status = UpdateStatus.NotStarted - }; + GeneralTracer.Info($"Installing Windows driver via PnPUtil: {driverInfo.FilePath}"); + await InstallDriverUsingPnPUtilAsync(driverInfo.FilePath, cancellationToken); + } + /// + protected override async Task VerifyInstallationAsync( + DriverInfo driverInfo, + CancellationToken cancellationToken) + { try { - GeneralTracer.Info($"Starting driver update for: {driverInfo.Name} v{driverInfo.Version}"); - - result.StepLogs.Add($"[{DateTime.Now:HH:mm:ss}] Starting driver update"); + GeneralTracer.Info($"Verifying Windows driver installation for: {driverInfo.FilePath}"); - // Step 1: Permission check - GeneralTracer.Info("Checking permissions..."); - result.StepLogs.Add($"[{DateTime.Now:HH:mm:ss}] Checking permissions"); - - if (!WindowsPermissionHelper.IsAdministrator()) + var psi = new ProcessStartInfo { - throw new DriverPermissionException( - "Administrator privileges are required for driver updates. " + - "Please restart the application as administrator."); - } + FileName = "pnputil.exe", + Arguments = "/enum-drivers", + RedirectStandardOutput = true, + RedirectStandardError = true, + UseShellExecute = false, + CreateNoWindow = true + }; - // Step 2: Validation - result.Status = UpdateStatus.Validating; - result.StepLogs.Add($"[{DateTime.Now:HH:mm:ss}] Validating driver"); - - if (!await ValidateAsync(driverInfo, cancellationToken)) + using var process = Process.Start(psi); + if (process is null) { - throw new DriverValidationException( - "Driver validation failed. Please check the driver file and try again.", - "General"); + GeneralTracer.Warn("Failed to start PnPUtil for verification"); + return false; } - // Step 3: Backup (if required) - if (strategy.RequireBackup) - { - result.Status = UpdateStatus.BackingUp; - result.StepLogs.Add($"[{DateTime.Now:HH:mm:ss}] Creating backup"); - - var backupPath = GenerateBackupPath(driverInfo, strategy.BackupPath); - if (await BackupAsync(driverInfo, backupPath, cancellationToken)) - { - result.BackupPath = backupPath; - GeneralTracer.Info($"Backup created at: {backupPath}"); - } - } + var output = await process.StandardOutput.ReadToEndAsync(cancellationToken); + await process.WaitForExitAsync(cancellationToken); - // Step 4: Execute update - result.Status = UpdateStatus.Updating; - result.StepLogs.Add($"[{DateTime.Now:HH:mm:ss}] Installing driver"); - - await ExecuteDriverInstallationAsync(driverInfo, strategy, cancellationToken); - - // Step 5: Verify installation - result.Status = UpdateStatus.Verifying; - result.StepLogs.Add($"[{DateTime.Now:HH:mm:ss}] Verifying installation"); - - bool verified = await VerifyDriverInstallationAsync(driverInfo, cancellationToken); - if (!verified) - { - GeneralTracer.Warn("Driver installation verification failed"); - result.StepLogs.Add($"[{DateTime.Now:HH:mm:ss}] WARNING: Installation verification failed"); - } - GeneralTracer.Info("Driver installation verification completed"); + var driverFileName = Path.GetFileName(driverInfo.FilePath); + var driverName = Path.GetFileNameWithoutExtension(driverInfo.FilePath); - // Step 6: Handle restart if needed - if (RestartHelper.IsRestartRequired(strategy.RestartMode)) - { - result.StepLogs.Add($"[{DateTime.Now:HH:mm:ss}] System restart is required"); - GeneralTracer.Info("System restart is required for driver update"); - } + bool isInstalled = output.Contains(driverFileName, StringComparison.OrdinalIgnoreCase) + || output.Contains(driverName, StringComparison.OrdinalIgnoreCase); - result.Success = true; - result.Status = UpdateStatus.Succeeded; - result.Message = "Driver update completed successfully"; - result.StepLogs.Add($"[{DateTime.Now:HH:mm:ss}] Update completed successfully"); - - GeneralTracer.Info("Driver update completed successfully"); - } - catch (DriverPermissionException ex) - { - GeneralTracer.Error("Permission denied during driver update", ex); - result.Success = false; - result.Status = UpdateStatus.Failed; - result.Error = CreateErrorInfo(ex, ErrorType.PermissionDenied, false); - result.StepLogs.Add($"[{DateTime.Now:HH:mm:ss}] ERROR: {ex.Message}"); - } - catch (DriverValidationException ex) - { - GeneralTracer.Error("Validation failed during driver update", ex); - result.Success = false; - result.Status = UpdateStatus.Failed; - result.Error = CreateErrorInfo(ex, ErrorType.HashValidationFailed, false); - result.StepLogs.Add($"[{DateTime.Now:HH:mm:ss}] ERROR: {ex.Message}"); - } - catch (DriverInstallationException ex) - { - GeneralTracer.Error("Installation failed during driver update", ex); - result.Success = false; - result.Status = UpdateStatus.Failed; - result.Error = CreateErrorInfo(ex, ErrorType.InstallationFailed, ex.CanRetry); - result.StepLogs.Add($"[{DateTime.Now:HH:mm:ss}] ERROR: {ex.Message}"); - - // Attempt rollback if backup exists - if (!string.IsNullOrEmpty(result.BackupPath)) - { - result.StepLogs.Add($"[{DateTime.Now:HH:mm:ss}] Attempting rollback"); - if (await TryRollbackAsync(result.BackupPath, cancellationToken)) - { - result.RolledBack = true; - result.Status = UpdateStatus.RolledBack; - result.StepLogs.Add($"[{DateTime.Now:HH:mm:ss}] Rollback completed"); - } - } + GeneralTracer.Info($"Driver verification result: {isInstalled}"); + return isInstalled; } catch (Exception ex) { - GeneralTracer.Error("Unexpected error during driver update", ex); - result.Success = false; - result.Status = UpdateStatus.Failed; - result.Error = CreateErrorInfo(ex, ErrorType.Unknown, false); - result.StepLogs.Add($"[{DateTime.Now:HH:mm:ss}] ERROR: {ex.Message}"); - } - finally - { - result.EndTime = DateTime.UtcNow; - GeneralTracer.Info($"Driver update process ended. Duration: {result.DurationMs}ms, Success: {result.Success}"); + GeneralTracer.Warn($"Failed to verify driver installation - {ex.Message}"); + return true; // Non-fatal: don't block the update } - - return result; } + // ─── Rollback override ───────────────────────────────────────────── + /// - public async Task ValidateAsync(DriverInfo driverInfo, CancellationToken cancellationToken = default) + public override async Task RollbackAsync( + string backupPath, + CancellationToken cancellationToken = default) { - GeneralTracer.Info($"Validating driver: {driverInfo.Name}"); - try { - // Validate file exists - if (!File.Exists(driverInfo.FilePath)) + GeneralTracer.Info($"Rolling back Windows driver from backup: {backupPath}"); + + if (!Directory.Exists(backupPath)) { - GeneralTracer.Error($"Driver file not found: {driverInfo.FilePath}"); + GeneralTracer.Error($"Backup directory not found: {backupPath}"); return false; } - // Validate hash if provided and not skipped - if (!string.IsNullOrEmpty(driverInfo.Hash)) + var backupFiles = Directory.GetFiles(backupPath, "*.*", SearchOption.AllDirectories); + if (backupFiles.Length == 0) { - if (!await _validator.ValidateIntegrityAsync( - driverInfo.FilePath, - driverInfo.Hash, - driverInfo.HashAlgorithm, - cancellationToken)) - { - return false; - } + GeneralTracer.Warn($"No backup files found in: {backupPath}"); + return false; } - // Validate signature if publishers provided - if (driverInfo.TrustedPublishers.Any()) + GeneralTracer.Info($"Found {backupFiles.Length} backup files"); + + // Reinstall backed-up INF drivers via PnPUtil + foreach (var infFile in backupFiles.Where( + f => f.EndsWith(".inf", StringComparison.OrdinalIgnoreCase))) { - if (!await _validator.ValidateSignatureAsync( - driverInfo.FilePath, - driverInfo.TrustedPublishers, - cancellationToken)) + try { - return false; + GeneralTracer.Info($"Restoring driver from: {infFile}"); + await InstallDriverUsingPnPUtilAsync(infFile, cancellationToken); + } + catch (Exception ex) + { + GeneralTracer.Warn($"Failed to restore driver from {infFile}: {ex.Message}"); } - } - - // Validate compatibility - if (!await _validator.ValidateCompatibilityAsync(driverInfo, cancellationToken)) - { - return false; } return true; } catch (Exception ex) { - GeneralTracer.Error("Driver validation failed", ex); - return false; + GeneralTracer.Error("Windows driver rollback failed", ex); + throw new DriverRollbackException($"Failed to rollback driver: {ex.Message}", ex); } } + // ─── Driver discovery overrides ──────────────────────────────────── + /// - public async Task BackupAsync(DriverInfo driverInfo, string backupPath, CancellationToken cancellationToken = default) - { - try - { - return await _backup.BackupAsync(driverInfo.FilePath, backupPath, cancellationToken); - } - catch (Exception ex) - { - GeneralTracer.Error("Failed to backup driver", ex); - return false; - } - } + protected override string GetDefaultSearchPattern() => "*.inf"; /// - public async Task RollbackAsync(string backupPath, CancellationToken cancellationToken = default) + public override async Task> GetDriversFromDirectoryAsync( + string directoryPath, + string? searchPattern = null, + CancellationToken cancellationToken = default) { + var drivers = new List(); + try { - GeneralTracer.Info($"Rolling back driver from backup: {backupPath}"); - - // Implement rollback logic - // This involves: - // 1. Restoring from backup - // 2. Optionally reinstalling the old driver - - if (!Directory.Exists(backupPath)) - { - GeneralTracer.Error($"Backup directory not found: {backupPath}"); - return false; - } + GeneralTracer.Info($"Reading Windows drivers from directory: {directoryPath}"); - // Find the backed up driver files - var backupFiles = Directory.GetFiles(backupPath, "*.*", SearchOption.AllDirectories); - if (!backupFiles.Any()) + if (!Directory.Exists(directoryPath)) { - GeneralTracer.Warn($"No backup files found in: {backupPath}"); - return false; + GeneralTracer.Warn($"Directory not found: {directoryPath}"); + return drivers; } - GeneralTracer.Info($"Found {backupFiles.Length} backup files"); - - // For INF-based drivers, try to reinstall the backed up version - var infFiles = backupFiles.Where(f => f.EndsWith(".inf", StringComparison.OrdinalIgnoreCase)).ToArray(); - - if (infFiles.Any()) + var pattern = searchPattern ?? "*.inf"; + var files = Directory.GetFiles(directoryPath, pattern, SearchOption.AllDirectories); + + foreach (var filePath in files) { - foreach (var infFile in infFiles) + if (cancellationToken.IsCancellationRequested) + break; + + try { - try - { - GeneralTracer.Info($"Attempting to restore driver from: {infFile}"); - await InstallDriverUsingPnPUtilAsync(infFile, cancellationToken); - } - catch (Exception ex) - { - GeneralTracer.Warn($"Failed to restore driver from: {infFile} - {ex.Message}"); - } + var info = await ParseWindowsDriverFileAsync(filePath, cancellationToken); + if (info is not null) + drivers.Add(info); + } + catch (Exception ex) + { + GeneralTracer.Warn($"Failed to parse driver file: {filePath} - {ex.Message}"); } } - return true; + GeneralTracer.Info($"Loaded {drivers.Count} Windows driver(s) from directory"); } catch (Exception ex) { - GeneralTracer.Error("Failed to rollback driver", ex); - throw new DriverRollbackException($"Failed to rollback driver: {ex.Message}", ex); + GeneralTracer.Error($"Error reading drivers from directory: {directoryPath}", ex); } + + return drivers; } + // ─── Private helpers ──────────────────────────────────────────────── + /// - /// 执行驱动安装 - /// Executes driver installation + /// Creates a Windows admin-privilege check as the first pipeline step. /// - private async Task ExecuteDriverInstallationAsync( - DriverInfo driverInfo, - UpdateStrategy strategy, - CancellationToken cancellationToken) + private static IPipelineStep CreatePermissionCheckStep() { - GeneralTracer.Info($"Executing driver installation: {driverInfo.FilePath}"); + return new DelegateStep("CheckPermissions", + execute: (context, ct) => + { + context.Result.StepLogs.Add($"[{DateTime.Now:HH:mm:ss}] Checking Windows administrator privileges"); - try - { - // TODO: Implement actual driver installation using SetupDi APIs - // This is a placeholder that would use Windows Device Manager APIs: - // - SetupDiGetClassDevs - // - SetupDiEnumDeviceInfo - // - UpdateDriverForPlugAndPlayDevices - // - DiInstallDriver (for .inf files) - - // For demonstration, we'll use PnPUtil as a fallback - await InstallDriverUsingPnPUtilAsync(driverInfo.FilePath, cancellationToken); - } - catch (Exception ex) - { - GeneralTracer.Error("Driver installation failed", ex); - throw new DriverInstallationException($"Failed to install driver: {ex.Message}", ex); - } + if (!WindowsPermissionHelper.IsAdministrator()) + { + return Task.FromResult(PipelineResult.Fail( + "Administrator privileges are required for driver updates. " + + "Please restart the application as administrator.")); + } + + return Task.FromResult(PipelineResult.Ok()); + }); } /// - /// 使用PnPUtil安装驱动 - /// Installs driver using PnPUtil + /// Installs a driver using the Windows PnPUtil command-line tool. /// - private async Task InstallDriverUsingPnPUtilAsync(string driverPath, CancellationToken cancellationToken) + private static async Task InstallDriverUsingPnPUtilAsync( + string driverPath, + CancellationToken cancellationToken) { - GeneralTracer.Info($"Installing driver using PnPUtil: {driverPath}"); + GeneralTracer.Info($"PnPUtil installing: {driverPath}"); - var startInfo = new ProcessStartInfo + var psi = new ProcessStartInfo { FileName = "pnputil.exe", Arguments = $"/add-driver \"{driverPath}\" /install", @@ -336,257 +245,102 @@ private async Task InstallDriverUsingPnPUtilAsync(string driverPath, Cancellatio RedirectStandardError = true }; - using var process = new Process { StartInfo = startInfo }; - process.Start(); + using var process = Process.Start(psi) + ?? throw new DriverInstallationException("Failed to start PnPUtil process."); var output = await process.StandardOutput.ReadToEndAsync(cancellationToken); var error = await process.StandardError.ReadToEndAsync(cancellationToken); - await process.WaitForExitAsync(cancellationToken); GeneralTracer.Info($"PnPUtil output: {output}"); if (process.ExitCode != 0) { - GeneralTracer.Error($"PnPUtil failed with exit code {process.ExitCode}. Error: {error}"); + GeneralTracer.Error($"PnPUtil failed (exit {process.ExitCode}): {error}"); throw new DriverInstallationException( $"PnPUtil failed with exit code {process.ExitCode}: {error}"); } } /// - /// 验证驱动安装 - /// Verify driver installation + /// Parses a Windows driver file (INF) and extracts metadata, hash, and signature info. /// - private async Task VerifyDriverInstallationAsync(DriverInfo driverInfo, CancellationToken cancellationToken) + private async Task ParseWindowsDriverFileAsync( + string filePath, + CancellationToken cancellationToken) { try { - GeneralTracer.Info($"Verifying driver installation for: {driverInfo.FilePath}"); - - // Use PnPUtil to enumerate installed drivers and check if our driver is present - var processStartInfo = new ProcessStartInfo + var driverInfo = new DriverInfo { - FileName = "pnputil.exe", - Arguments = "/enum-drivers", - RedirectStandardOutput = true, - RedirectStandardError = true, - UseShellExecute = false, - CreateNoWindow = true + Name = Path.GetFileNameWithoutExtension(filePath), + FilePath = filePath, + TargetOS = "Windows", + Architecture = Environment.Is64BitOperatingSystem ? "x64" : "x86" }; - using var process = Process.Start(processStartInfo); - if (process == null) - { - GeneralTracer.Warn("Failed to start PnPUtil for verification"); - return false; - } - - string output = await process.StandardOutput.ReadToEndAsync(cancellationToken); - await process.WaitForExitAsync(cancellationToken); - - // Check if the driver file name appears in the output - string driverFileName = Path.GetFileName(driverInfo.FilePath); - bool isInstalled = output.Contains(driverFileName, StringComparison.OrdinalIgnoreCase) || - output.Contains(Path.GetFileNameWithoutExtension(driverInfo.FilePath), StringComparison.OrdinalIgnoreCase); - - GeneralTracer.Info($"Driver verification result: {isInstalled}"); - return isInstalled; - } - catch (Exception ex) - { - GeneralTracer.Warn($"Failed to verify driver installation - {ex.Message}"); - // Return true to not block the update if verification fails - return true; - } - } - - private string GenerateBackupPath(DriverInfo driverInfo, string baseBackupPath) - { - if (string.IsNullOrEmpty(baseBackupPath)) - { - baseBackupPath = "./DriverBackups"; - } - - var fileName = Path.GetFileName(driverInfo.FilePath); - return Path.Combine(baseBackupPath, fileName); - } - - private async Task TryRollbackAsync(string backupPath, CancellationToken cancellationToken) - { - try - { - return await RollbackAsync(backupPath, cancellationToken); - } - catch (Exception ex) - { - GeneralTracer.Error("Rollback failed", ex); - return false; - } - } - - private ErrorInfo CreateErrorInfo(Exception ex, ErrorType type, bool canRetry) - { - return new ErrorInfo - { - Code = ex is DrivelutionException dex ? dex.ErrorCode : "DR_UNKNOWN", - Type = type, - Message = ex.Message, - Details = ex.ToString(), - StackTrace = ex.StackTrace, - InnerException = ex.InnerException, - CanRetry = canRetry, - SuggestedResolution = GetSuggestedResolution(type) - }; - } - - private string GetSuggestedResolution(ErrorType type) - { - return type switch - { - ErrorType.PermissionDenied => "Run the application as administrator", - ErrorType.SignatureValidationFailed => "Ensure the driver is properly signed by a trusted publisher", - ErrorType.HashValidationFailed => "Re-download the driver file and verify its integrity", - ErrorType.CompatibilityValidationFailed => "Check if the driver is compatible with your system", - ErrorType.InstallationFailed => "Check Windows Event Viewer for more details", - _ => "Contact support for assistance" - }; - } - - /// - public async Task> GetDriversFromDirectoryAsync( - string directoryPath, - string? searchPattern = null, - CancellationToken cancellationToken = default) - { - var driverInfoList = new List(); - - try - { - GeneralTracer.Info($"Reading driver information from directory: {directoryPath}"); - - if (!Directory.Exists(directoryPath)) + // Parse INF metadata + if (filePath.EndsWith(".inf", StringComparison.OrdinalIgnoreCase)) { - GeneralTracer.Warn($"Directory not found: {directoryPath}"); - return driverInfoList; + await ParseInfFileAsync(filePath, driverInfo, cancellationToken); } - // Default to .inf files for Windows - var pattern = searchPattern ?? "*.inf"; - var driverFiles = Directory.GetFiles(directoryPath, pattern, SearchOption.AllDirectories); - - GeneralTracer.Info($"Found {driverFiles.Length} driver files matching pattern: {pattern}"); + // Compute file hash + driverInfo.Hash = await HashValidator.ComputeHashAsync(filePath, "SHA256", cancellationToken); + driverInfo.HashAlgorithm = "SHA256"; - foreach (var filePath in driverFiles) - { - if (cancellationToken.IsCancellationRequested) - break; + // Extract signature info + ExtractSignatureInfo(filePath, driverInfo); - try - { - var driverInfo = await ParseDriverFileAsync(filePath, cancellationToken); - if (driverInfo != null) - { - driverInfoList.Add(driverInfo); - GeneralTracer.Info($"Parsed driver: {driverInfo.Name} v{driverInfo.Version}"); - } - } - catch (Exception ex) - { - GeneralTracer.Warn($"Failed to parse driver file: {filePath} - {ex.Message}"); - } - } - - GeneralTracer.Info($"Successfully loaded {driverInfoList.Count} driver(s) from directory"); + return driverInfo; } catch (Exception ex) { - GeneralTracer.Error($"Error reading drivers from directory: {directoryPath}", ex); + GeneralTracer.Warn($"Failed to parse driver file: {filePath} - {ex.Message}"); + return null; } - - return driverInfoList; } /// - /// Parses driver file information + /// Extracts digital signature / publisher information from a signed Windows driver file. /// - private async Task ParseDriverFileAsync(string filePath, CancellationToken cancellationToken) + private static void ExtractSignatureInfo(string filePath, DriverInfo driverInfo) { + if (!WindowsSignatureHelper.IsFileSigned(filePath)) + return; + try { - var fileInfo = new FileInfo(filePath); - var fileName = Path.GetFileNameWithoutExtension(filePath); - - var driverInfo = new DriverInfo - { - Name = fileName, - FilePath = filePath, - TargetOS = "Windows", - Architecture = Environment.Is64BitOperatingSystem ? "x64" : "x86" - }; + using var cert2 = new System.Security.Cryptography.X509Certificates.X509Certificate2(filePath); + var subject = cert2.Subject; + var cnIndex = subject.IndexOf("CN=", StringComparison.Ordinal); - // For .inf files, try to parse version and other metadata - if (filePath.EndsWith(".inf", StringComparison.OrdinalIgnoreCase)) - { - await ParseInfFileAsync(filePath, driverInfo, cancellationToken); - } + if (cnIndex < 0) + return; - // Get file hash for integrity validation - driverInfo.Hash = await HashValidator.ComputeHashAsync(filePath, "SHA256", cancellationToken); - driverInfo.HashAlgorithm = "SHA256"; + var cnStart = cnIndex + 3; + var cnEnd = subject.IndexOf(',', cnStart); - // Get signature information if available - try - { - if (WindowsSignatureHelper.IsFileSigned(filePath)) - { - // Try to extract publisher from certificate - using var cert2 = new System.Security.Cryptography.X509Certificates.X509Certificate2(filePath); - var subject = cert2.Subject; - - // Extract CN (Common Name) from subject - var cnIndex = subject.IndexOf("CN="); - if (cnIndex >= 0) - { - var cnStart = cnIndex + 3; - var cnEnd = subject.IndexOf(',', cnStart); - - string publisher; - if (cnEnd > cnStart) - { - publisher = subject.Substring(cnStart, cnEnd - cnStart); - } - else - { - // No comma after CN, take the rest of the string - publisher = subject.Substring(cnStart); - } - - if (!string.IsNullOrEmpty(publisher)) - { - driverInfo.TrustedPublishers.Add(publisher); - } - } - } - } - catch (Exception ex) - { - GeneralTracer.Debug($"Could not get signature for file: {filePath} - {ex.Message}"); - } + var publisher = cnEnd > cnStart + ? subject[cnStart..cnEnd] + : subject[cnStart..]; - return driverInfo; + if (!string.IsNullOrEmpty(publisher)) + driverInfo.TrustedPublishers.Add(publisher); } catch (Exception ex) { - GeneralTracer.Warn($"Failed to parse driver file: {filePath} - {ex.Message}"); - return null; + GeneralTracer.Debug($"Could not extract signature for {filePath}: {ex.Message}"); } } /// - /// Parses INF file + /// Parses a Windows INF file to extract DriverVer, DriverDesc, and HardwareId. /// - private async Task ParseInfFileAsync(string infPath, DriverInfo driverInfo, CancellationToken cancellationToken) + private static async Task ParseInfFileAsync( + string infPath, + DriverInfo driverInfo, + CancellationToken cancellationToken) { try { @@ -595,55 +349,69 @@ private async Task ParseInfFileAsync(string infPath, DriverInfo driverInfo, Canc foreach (var line in lines) { - var trimmedLine = line.Trim(); + var trimmed = line.Trim(); - // Parse version - if (trimmedLine.StartsWith("DriverVer", StringComparison.OrdinalIgnoreCase)) + if (trimmed.StartsWith("DriverVer", StringComparison.OrdinalIgnoreCase)) { - var parts = trimmedLine.Split('='); + var parts = trimmed.Split('='); if (parts.Length > 1) { var verParts = parts[1].Split(','); if (verParts.Length > 1) - { driverInfo.Version = verParts[1].Trim(); - } - if (verParts.Length > 0 && DateTime.TryParse(verParts[0].Trim(), out var releaseDate)) - { + if (verParts.Length > 0 + && DateTime.TryParse(verParts[0].Trim(), out var releaseDate)) driverInfo.ReleaseDate = releaseDate; - } } } - // Parse description - else if (trimmedLine.StartsWith("DriverDesc", StringComparison.OrdinalIgnoreCase)) + else if (trimmed.StartsWith("DriverDesc", StringComparison.OrdinalIgnoreCase)) { - var parts = trimmedLine.Split('='); + var parts = trimmed.Split('='); if (parts.Length > 1) - { driverInfo.Description = parts[1].Trim().Trim('"', '%'); - } } - // Parse hardware ID - else if (trimmedLine.StartsWith("HardwareId", StringComparison.OrdinalIgnoreCase) || - trimmedLine.Contains("HW_ID", StringComparison.OrdinalIgnoreCase)) + else if (trimmed.StartsWith("HardwareId", StringComparison.OrdinalIgnoreCase) + || trimmed.Contains("HW_ID", StringComparison.OrdinalIgnoreCase)) { - var parts = trimmedLine.Split('='); + var parts = trimmed.Split('='); if (parts.Length > 1) - { driverInfo.HardwareId = parts[1].Trim().Trim('"'); - } } } - // If version is still empty, try to infer from filename or use default if (string.IsNullOrEmpty(driverInfo.Version)) - { driverInfo.Version = "1.0.0"; - } } catch (Exception ex) { GeneralTracer.Debug($"Could not parse INF file: {infPath} - {ex.Message}"); } } + + // ─── Nested type ────────────────────────────────────────────────── + + /// + /// A lightweight pipeline step backed by delegates. + /// + private sealed class DelegateStep : IPipelineStep + { + private readonly Func> _execute; + + public string StepName { get; } + + public DelegateStep( + string stepName, + Func> execute) + { + StepName = stepName; + _execute = execute; + } + + public bool ShouldExecute(PipelineContext context) => true; + + public Task ExecuteAsync( + PipelineContext context, + CancellationToken cancellationToken) + => _execute(context, cancellationToken); + } }