From cdf421197196c3f27b89ef9ad3e7af408bacf5d5 Mon Sep 17 00:00:00 2001 From: Violet Hansen Date: Tue, 18 Feb 2025 13:33:51 +0200 Subject: [PATCH 1/2] AppControl Manager is now Native AOT and Fully Trimmed AppControl Manager is now Native AOT and Fully Trimmed --- .../Build AppControl Manager MSIX Package.yml | 2 +- AppControl Manager/AppControl Manager.csproj | 49 +- AppControl Manager/Main/BasePolicyCreator.cs | 11 +- AppControl Manager/MainWindow.xaml | 1 - AppControl Manager/MainWindow.xaml.cs | 4 + AppControl Manager/MyRoots.xml | 4 +- AppControl Manager/Others/DeviceGuardInfo.cs | 28 +- .../Others/FileCertificateInfoCol.cs | 2 +- AppControl Manager/Others/GlobalVars.cs | 6 + AppControl Manager/Others/MeasureTextWidth.cs | 67 + AppControl Manager/Others/ProcessStarter.cs | 35 +- .../Others/SnapBackGuarantee.cs | 22 +- .../Others/TaskSchedulerHelper.cs | 10 +- AppControl Manager/Package.appxmanifest | 2 +- .../AllowNewAppsEventLogsDataGrid.xaml | 365 +- .../AllowNewAppsEventLogsDataGrid.xaml.cs | 867 ++- .../AllowNewAppsLocalFilesDataGrid.xaml | 353 +- .../AllowNewAppsLocalFilesDataGrid.xaml.cs | 841 ++- .../AllowNewApps/AllowNewAppsStart.xaml.cs | 86 +- .../Pages/CreateDenyPolicy.xaml.cs | 57 +- ...eDenyPolicyFilesAndFoldersScanResults.xaml | 345 +- ...nyPolicyFilesAndFoldersScanResults.xaml.cs | 802 ++- AppControl Manager/Pages/CreatePolicy.xaml | 5 - AppControl Manager/Pages/CreatePolicy.xaml.cs | 17 +- .../Pages/CreateSupplementalPolicy.xaml | 1 - .../Pages/CreateSupplementalPolicy.xaml.cs | 69 +- ...entalPolicyFilesAndFoldersScanResults.xaml | 346 +- ...alPolicyFilesAndFoldersScanResults.xaml.cs | 784 ++- .../Pages/EventLogsPolicyCreation.xaml | 428 +- .../Pages/EventLogsPolicyCreation.xaml.cs | 895 ++- .../Pages/MDEAHPolicyCreation.xaml | 365 +- .../Pages/MDEAHPolicyCreation.xaml.cs | 889 ++- AppControl Manager/Pages/Settings.xaml | 19 +- AppControl Manager/Pages/Settings.xaml.cs | 68 - AppControl Manager/Pages/Simulation.xaml | 313 +- AppControl Manager/Pages/Simulation.xaml.cs | 656 +- .../Pages/StrictKernelPolicyScanResults.xaml | 351 +- .../StrictKernelPolicyScanResults.xaml.cs | 795 ++- .../ViewCurrentPolicies.xaml | 247 +- .../ViewCurrentPolicies.xaml.cs | 565 +- AppControl Manager/Pages/Update.xaml.cs | 66 +- .../Pages/ViewFileCertificates.xaml | 254 +- .../Pages/ViewFileCertificates.xaml.cs | 490 +- ...iversBlockListAutoUpdaterScheduledTask.ps1 | 12 + .../SnapBackGuaranteeScheduledTask.ps1 | 5 + .../SiPolicy/SiPolicyClassAutoGenerated.cs | 6010 ++++++++--------- .../Strings/en-US/Resources.resw | 255 +- AppControl Manager/app.manifest | 2 +- .../AppControl Manager/AppControl Manager.md | 3 +- 49 files changed, 10732 insertions(+), 7137 deletions(-) create mode 100644 AppControl Manager/Others/MeasureTextWidth.cs create mode 100644 AppControl Manager/Resources/DriversBlockListAutoUpdaterScheduledTask.ps1 create mode 100644 AppControl Manager/Resources/SnapBackGuaranteeScheduledTask.ps1 diff --git a/.github/workflows/Build AppControl Manager MSIX Package.yml b/.github/workflows/Build AppControl Manager MSIX Package.yml index e545c8e41..aa7463f6f 100644 --- a/.github/workflows/Build AppControl Manager MSIX Package.yml +++ b/.github/workflows/Build AppControl Manager MSIX Package.yml @@ -43,7 +43,7 @@ jobs: if ($LASTEXITCODE -ne 0) { throw [System.InvalidOperationException]::New('Failed to install .NET SDK') } Write-Host -Object "`nInstalling Visual Studio Build Tools" -ForegroundColor Magenta - $null = winget install --id Microsoft.VisualStudio.2022.BuildTools --exact --accept-package-agreements --accept-source-agreements --uninstall-previous --force --source winget --override '--force --wait --passive --add Microsoft.VisualStudio.Workload.ManagedDesktop --add Microsoft.VisualStudio.Workload.VCTools --add Microsoft.VisualStudio.Workload.MSBuildTools --add Microsoft.VisualStudio.Workload.UniversalBuildTools --add Microsoft.VisualStudio.ComponentGroup.WindowsAppSDK.Cs --add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 --add Microsoft.VisualStudio.Component.VC.v141.x86.x64 --add Microsoft.VisualStudio.Component.Windows11SDK.26100 --includeRecommended' + $null = winget install --id Microsoft.VisualStudio.2022.BuildTools --exact --accept-package-agreements --accept-source-agreements --uninstall-previous --force --source winget --override '--force --wait --passive --add Microsoft.VisualStudio.Workload.ManagedDesktop --add Microsoft.VisualStudio.Workload.VCTools --add Microsoft.VisualStudio.Workload.MSBuildTools --add Microsoft.VisualStudio.Workload.UniversalBuildTools --add Microsoft.VisualStudio.ComponentGroup.WindowsAppSDK.Cs --add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 --add Microsoft.VisualStudio.Component.VC.v141.x86.x64 --add Microsoft.VisualStudio.Component.Windows11SDK.26100 --includeRecommended --add Microsoft.VisualStudio.Component.VC.Tools.ARM64 --add Microsoft.VisualStudio.Component.UWP.VC.ARM64' if ($LASTEXITCODE -ne 0) { throw [System.InvalidOperationException]::New('Failed to install Visual Studio Build Tools') } Write-Host -Object "`nInstalling Visual C++ Redistributable" -ForegroundColor Magenta diff --git a/AppControl Manager/AppControl Manager.csproj b/AppControl Manager/AppControl Manager.csproj index 4f55b3776..2391e69fc 100644 --- a/AppControl Manager/AppControl Manager.csproj +++ b/AppControl Manager/AppControl Manager.csproj @@ -51,20 +51,6 @@ False True - - - - - - false - - disable A modern secure application that simplifies management of Application Control in Windows. https://github.com/HotCakeX/Harden-Windows-Security @@ -90,9 +76,9 @@ True AppControlManager - false + True send - 1.9.0.0 + 1.9.1.0 $(FileVersion) en-US LICENSE @@ -108,7 +94,19 @@ True all git - True + true + + + + True + full + false + false + false + false + false + false - @@ -244,8 +237,10 @@ + + @@ -259,12 +254,18 @@ Always + + Always + Always Always + + Always + Always diff --git a/AppControl Manager/Main/BasePolicyCreator.cs b/AppControl Manager/Main/BasePolicyCreator.cs index f7f8ec9cc..6fa3b8ff4 100644 --- a/AppControl Manager/Main/BasePolicyCreator.cs +++ b/AppControl Manager/Main/BasePolicyCreator.cs @@ -4,7 +4,6 @@ using System.IO; using System.IO.Compression; using System.Linq; -using System.Management; using System.Net.Http; using System.Text.Json; using System.Text.RegularExpressions; @@ -24,6 +23,8 @@ internal static void SetAutoUpdateDriverBlockRules() { Logger.Write("Creating scheduled task for fast weekly Microsoft recommended driver block list update"); + /* + // Initialize ManagementScope to interact with Task Scheduler's WMI namespace ManagementScope scope = new(@"root\Microsoft\Windows\TaskScheduler"); // Establish connection to the WMI namespace @@ -164,6 +165,14 @@ internal static void SetAutoUpdateDriverBlockRules() Logger.Write("Successfully created the Microsoft Recommended Driver Block Rules auto updater scheduled task."); + */ + + // TODO: use a Native AOT compatible way that doesn't rely on System.Management + + + // Execute the script using PowerShell + ProcessStarter.RunCommand("powershell.exe", $"-NoProfile -ExecutionPolicy Bypass -File \"{GlobalVars.DriversBlockListAutoUpdaterScheduledTaskScriptFilePath}\""); + } internal sealed class DriverBlockListInfo diff --git a/AppControl Manager/MainWindow.xaml b/AppControl Manager/MainWindow.xaml index 94b63132e..11295b365 100644 --- a/AppControl Manager/MainWindow.xaml +++ b/AppControl Manager/MainWindow.xaml @@ -8,7 +8,6 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:ui="using:CommunityToolkit.WinUI" xmlns:controls="using:CommunityToolkit.WinUI.Controls" - xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls" xmlns:animations="using:CommunityToolkit.WinUI.Animations" xmlns:AnimatedVisuals="using:Microsoft.UI.Xaml.Controls.AnimatedVisuals" mc:Ignorable="d" diff --git a/AppControl Manager/MainWindow.xaml.cs b/AppControl Manager/MainWindow.xaml.cs index 8cf0c2ebf..e8cbdd1e2 100644 --- a/AppControl Manager/MainWindow.xaml.cs +++ b/AppControl Manager/MainWindow.xaml.cs @@ -41,6 +41,8 @@ public sealed partial class MainWindow : Window private readonly AppWindow m_AppWindow; + internal readonly Frame AppFrame; + // Used for the BreadCrumBar's data to define valid navigational paths in the app internal sealed class PageTitleMap { @@ -246,6 +248,8 @@ public MainWindow() // Assign this instance to the static field _instance = this; + AppFrame = ContentFrame; + // Retrieve the window handle (HWND) of the main WinUI 3 window and store it in the global vars GlobalVars.hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this); diff --git a/AppControl Manager/MyRoots.xml b/AppControl Manager/MyRoots.xml index 76fe476bd..5f282702b 100644 --- a/AppControl Manager/MyRoots.xml +++ b/AppControl Manager/MyRoots.xml @@ -1,3 +1 @@ - - - \ No newline at end of file + \ No newline at end of file diff --git a/AppControl Manager/Others/DeviceGuardInfo.cs b/AppControl Manager/Others/DeviceGuardInfo.cs index 8c6d7a026..66757af87 100644 --- a/AppControl Manager/Others/DeviceGuardInfo.cs +++ b/AppControl Manager/Others/DeviceGuardInfo.cs @@ -1,6 +1,3 @@ -using System.Linq; -using System.Management; - namespace AppControlManager.Others; internal sealed class DeviceGuardStatus @@ -13,10 +10,10 @@ internal static class DeviceGuardInfo { // Define the WMI query to get the Win32_DeviceGuard class information - private const string query = "SELECT UsermodeCodeIntegrityPolicyEnforcementStatus, CodeIntegrityPolicyEnforcementStatus FROM Win32_DeviceGuard"; + // private const string query = "SELECT UsermodeCodeIntegrityPolicyEnforcementStatus, CodeIntegrityPolicyEnforcementStatus FROM Win32_DeviceGuard"; // Define the scope (namespace) for the query - private const string scope = @"\\.\root\Microsoft\Windows\DeviceGuard"; + // private const string scope = @"\\.\root\Microsoft\Windows\DeviceGuard"; /// @@ -25,6 +22,9 @@ internal static class DeviceGuardInfo /// internal static DeviceGuardStatus? GetDeviceGuardStatus() { + + /* + // Create a ManagementScope object for the WMI namespace ManagementScope managementScope = new(scope); @@ -49,6 +49,22 @@ internal static class DeviceGuardInfo } } - return new DeviceGuardStatus(); + */ + + + // TODO: Create a Native AOT compatible source generated COM code that won't rely on System.Management or PowerShell + + string UMscript = "(Get-CimInstance -Namespace \\\"root\\Microsoft\\Windows\\DeviceGuard\\\" -Query \\\"SELECT UsermodeCodeIntegrityPolicyEnforcementStatus FROM Win32_DeviceGuard\\\").UsermodeCodeIntegrityPolicyEnforcementStatus"; + string UMoutput = ProcessStarter.RunCommandWithOutput("powershell.exe", $"-NoProfile -Command \"{UMscript}\""); + + + string KMscript = "(Get-CimInstance -Namespace \\\"root\\Microsoft\\Windows\\DeviceGuard\\\" -Query \\\"SELECT CodeIntegrityPolicyEnforcementStatus FROM Win32_DeviceGuard\\\").CodeIntegrityPolicyEnforcementStatus"; + string KMoutput = ProcessStarter.RunCommandWithOutput("powershell.exe", $"-NoProfile -Command \"{KMscript}\""); + + return new DeviceGuardStatus() + { + UsermodeCodeIntegrityPolicyEnforcementStatus = uint.Parse(UMoutput), + CodeIntegrityPolicyEnforcementStatus = uint.Parse(KMoutput) + }; } } diff --git a/AppControl Manager/Others/FileCertificateInfoCol.cs b/AppControl Manager/Others/FileCertificateInfoCol.cs index b00f2fc4f..ee3cad5dd 100644 --- a/AppControl Manager/Others/FileCertificateInfoCol.cs +++ b/AppControl Manager/Others/FileCertificateInfoCol.cs @@ -3,7 +3,7 @@ namespace AppControlManager.Others; // a class that represents each certificate in a chain -// Used by the DataGrid in the View File Certificates page +// Used by the ListView in the View File Certificates page public sealed class FileCertificateInfoCol { public int SignerNumber { get; set; } diff --git a/AppControl Manager/Others/GlobalVars.cs b/AppControl Manager/Others/GlobalVars.cs index 1bef31db1..9b65d1bef 100644 --- a/AppControl Manager/Others/GlobalVars.cs +++ b/AppControl Manager/Others/GlobalVars.cs @@ -62,6 +62,12 @@ internal static class GlobalVars // Path to the empty policy file in app resources internal static readonly string EmptyPolicyPath = Path.Combine(AppContext.BaseDirectory, "Resources", "EmptyPolicy.xml"); + // Path to the PS Script that creates a scheduled task + internal static readonly string DriversBlockListAutoUpdaterScheduledTaskScriptFilePath = Path.Combine(AppContext.BaseDirectory, "Resources", "DriversBlockListAutoUpdaterScheduledTask.ps1"); + + // Path to the PS Script that creates a scheduled task for SnapBack guarantee in Allow New Apps page + internal static readonly string SnapBackGuaranteeScheduledTaskScriptFilePath = Path.Combine(AppContext.BaseDirectory, "Resources", "SnapBackGuaranteeScheduledTask.ps1"); + // Get the current OS version private static readonly Version CurrentOSVersion = Environment.OSVersion.Version; diff --git a/AppControl Manager/Others/MeasureTextWidth.cs b/AppControl Manager/Others/MeasureTextWidth.cs new file mode 100644 index 000000000..25df407f9 --- /dev/null +++ b/AppControl Manager/Others/MeasureTextWidth.cs @@ -0,0 +1,67 @@ +using System.Text; +using AppControlManager.IntelGathering; +using Microsoft.UI.Text; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Windows.Foundation; + +namespace AppControlManager.Others; + +internal static class ListViewUIHelpers +{ + // An offscreen TextBlock for measurement + private static readonly TextBlock tb = new() + { + // It's important to make sure this matches the header text style so column texts will be aligned properly + FontWeight = FontWeights.Bold, + Margin = new Thickness(10, 0, 2, 0), + TextWrapping = TextWrapping.NoWrap, + Padding = new Thickness(5), + }; + + // Padding to add to each column (in pixels) + private const double padding = 15; + + /// + /// Measures the width (in pixels) required to display the given text. + /// If text is empty or null, the padding will be the only width returned. + /// + internal static double MeasureTextWidth(string? text) + { + tb.Text = text; + + tb.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity)); + + return tb.DesiredSize.Width + padding; + } + + /// + /// Converts the properties of a FileIdentity row into a labeled, formatted string for copying to clipboard. + /// + /// The selected FileIdentity row from the ListView. + /// A formatted string of the row's properties with labels. + internal static string ConvertRowToText(FileIdentity row) + { + // Use StringBuilder to format each property with its label for easy reading + return new StringBuilder() + .AppendLine($"File Name: {row.FileName}") + .AppendLine($"Signature Status: {row.SignatureStatus}") + .AppendLine($"Original File Name: {row.OriginalFileName}") + .AppendLine($"Internal Name: {row.InternalName}") + .AppendLine($"File Description: {row.FileDescription}") + .AppendLine($"Product Name: {row.ProductName}") + .AppendLine($"File Version: {row.FileVersion}") + .AppendLine($"Package Family Name: {row.PackageFamilyName}") + .AppendLine($"SHA256 Hash: {row.SHA256Hash}") + .AppendLine($"SHA1 Hash: {row.SHA1Hash}") + .AppendLine($"Signing Scenario: {row.SISigningScenario}") + .AppendLine($"File Path: {row.FilePath}") + .AppendLine($"SHA1 Page Hash: {row.SHA1PageHash}") + .AppendLine($"SHA256 Page Hash: {row.SHA256PageHash}") + .AppendLine($"Has WHQL Signer: {row.HasWHQLSigner}") + .AppendLine($"File Publishers: {row.FilePublishersToDisplay}") + .AppendLine($"Is ECC Signed: {row.IsECCSigned}") + .AppendLine($"Opus Data: {row.Opus}") + .ToString(); + } +} diff --git a/AppControl Manager/Others/ProcessStarter.cs b/AppControl Manager/Others/ProcessStarter.cs index c0ba33f00..cacf2f676 100644 --- a/AppControl Manager/Others/ProcessStarter.cs +++ b/AppControl Manager/Others/ProcessStarter.cs @@ -50,10 +50,43 @@ internal static void RunCommand(string command, string? arguments = null) process.WaitForExit(); - if (process.ExitCode != 0) + if (process.ExitCode is not 0) + { + throw new InvalidOperationException($"Command '{command} {arguments}' failed with exit code {process.ExitCode}. Error: {error}"); + } + } + + /// + /// Executes an executable with arguments and returns the output + /// + /// + /// + /// Standard output of the executed command + /// + internal static string RunCommandWithOutput(string command, string? arguments = null) + { + ProcessStartInfo processInfo = new() + { + FileName = command, + Arguments = arguments ?? string.Empty, + RedirectStandardOutput = true, + RedirectStandardError = true, + UseShellExecute = false, + CreateNoWindow = true + }; + + using Process process = new() { StartInfo = processInfo }; + _ = process.Start(); + + string output = process.StandardOutput.ReadToEnd(); + string error = process.StandardError.ReadToEnd(); + process.WaitForExit(); + + if (process.ExitCode is not 0) { throw new InvalidOperationException($"Command '{command} {arguments}' failed with exit code {process.ExitCode}. Error: {error}"); } + return output; } } diff --git a/AppControl Manager/Others/SnapBackGuarantee.cs b/AppControl Manager/Others/SnapBackGuarantee.cs index b89d16697..d82984bc7 100644 --- a/AppControl Manager/Others/SnapBackGuarantee.cs +++ b/AppControl Manager/Others/SnapBackGuarantee.cs @@ -1,12 +1,10 @@ using System; using System.IO; -using System.Management; namespace AppControlManager.Others; internal static class SnapBackGuarantee { - private static readonly string savePath = Path.Combine(GlobalVars.UserConfigDir, "EnforcedModeSnapBack.cmd"); /// @@ -25,6 +23,8 @@ internal static void Create(string path) Logger.Write("Creating the scheduled task for Snap Back Guarantee"); + /* + // Initialize ManagementScope to interact with Task Scheduler's WMI namespace ManagementScope scope = new(@"root\Microsoft\Windows\TaskScheduler"); // Establish connection to the WMI namespace @@ -151,15 +151,21 @@ internal static void Create(string path) } #endregion + Logger.Write("Successfully created the Microsoft Recommended Driver Block Rules auto updater scheduled task."); + */ - // Saving the EnforcedModeSnapBack.cmd file to the UserConfig directory in Program Files - // It contains the instructions to revert the base policy to enforced mode + // TODO: use a Native AOT compatible way that doesn't rely on System.Management + // Execute the script using PowerShell + ProcessStarter.RunCommand("powershell.exe", $"-NoProfile -ExecutionPolicy Bypass -File \"{GlobalVars.SnapBackGuaranteeScheduledTaskScriptFilePath}\""); + // Saving the EnforcedModeSnapBack.cmd file to the UserConfig directory in Program Files + // It contains the instructions to revert the base policy to enforced mode + string contentToBeSaved = $@" REM Deploying the Enforced Mode SnapBack CI Policy CiTool --update-policy ""{path}"" -json @@ -171,22 +177,20 @@ REM Deleting this CMD file itself del ""%~f0"" "; - // Write to file (overwrite if exists) File.WriteAllText(savePath, contentToBeSaved); - // An alternative way to do this which is less reliable because RunOnce key can be deleted by 3rd party programs during installation etc. - } - /// /// Removes the SnapBack guarantee scheduled task and the related .bat file /// internal static void Remove() { - TaskSchedulerHelper.Delete("EnforcedModeSnapBack", @"\"); + string script = "schtasks.exe /Delete /TN EnforcedModeSnapBack /F"; + + ProcessStarter.RunCommand("powershell.exe", $"-NoProfile -ExecutionPolicy Bypass -Command \"{script}\""); if (Path.Exists(savePath)) { diff --git a/AppControl Manager/Others/TaskSchedulerHelper.cs b/AppControl Manager/Others/TaskSchedulerHelper.cs index cebda1414..02438be97 100644 --- a/AppControl Manager/Others/TaskSchedulerHelper.cs +++ b/AppControl Manager/Others/TaskSchedulerHelper.cs @@ -1,8 +1,8 @@ -using System; -using System.Linq; -using System.Management; +namespace AppControlManager.Others; -namespace AppControlManager.Others; +// TODO: Incompatible with Native AOT + +/* internal static class TaskSchedulerHelper { @@ -71,3 +71,5 @@ internal static void Delete(string taskName, string taskPath) } } } + +*/ diff --git a/AppControl Manager/Package.appxmanifest b/AppControl Manager/Package.appxmanifest index 83e2f1c11..97044a540 100644 --- a/AppControl Manager/Package.appxmanifest +++ b/AppControl Manager/Package.appxmanifest @@ -11,7 +11,7 @@ + Version="1.9.1.0" /> diff --git a/AppControl Manager/Pages/AllowNewApps/AllowNewAppsEventLogsDataGrid.xaml b/AppControl Manager/Pages/AllowNewApps/AllowNewAppsEventLogsDataGrid.xaml index 64d5f995b..a85144a5f 100644 --- a/AppControl Manager/Pages/AllowNewApps/AllowNewAppsEventLogsDataGrid.xaml +++ b/AppControl Manager/Pages/AllowNewApps/AllowNewAppsEventLogsDataGrid.xaml @@ -8,7 +8,10 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" xmlns:controls="using:CommunityToolkit.WinUI.Controls" - xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls"> + xmlns:intelgathering="using:AppControlManager.IntelGathering" + xmlns:interactivity="using:Microsoft.Xaml.Interactivity" + xmlns:behaviors="using:CommunityToolkit.WinUI.Behaviors" + x:Name="AllowNewAppsEventLogsDataGridXAML"> @@ -51,6 +54,43 @@ + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/AppControl Manager/Pages/AllowNewApps/AllowNewAppsEventLogsDataGrid.xaml.cs b/AppControl Manager/Pages/AllowNewApps/AllowNewAppsEventLogsDataGrid.xaml.cs index 214deb43e..2be0f04cc 100644 --- a/AppControl Manager/Pages/AllowNewApps/AllowNewAppsEventLogsDataGrid.xaml.cs +++ b/AppControl Manager/Pages/AllowNewApps/AllowNewAppsEventLogsDataGrid.xaml.cs @@ -1,22 +1,518 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Linq; using System.Text; using AppControlManager.IntelGathering; -using CommunityToolkit.WinUI.UI.Controls; +using AppControlManager.Others; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Navigation; using Windows.ApplicationModel.DataTransfer; +using WinRT; namespace AppControlManager.Pages; -public sealed partial class AllowNewAppsEventLogsDataGrid : Page +// Since the columns for data in the ItemTemplate use "Binding" instead of "x:Bind", we need to use [GeneratedBindableCustomProperty] for them to work properly +[GeneratedBindableCustomProperty] +public sealed partial class AllowNewAppsEventLogsDataGrid : Page, INotifyPropertyChanged { // A static instance of the AllowNewAppsEventLogsDataGrid class which will hold the single, shared instance of the page private static AllowNewAppsEventLogsDataGrid? _instance; + internal ListView UIListView { get; private set; } + + #region LISTVIEW IMPLEMENTATIONS + + public event PropertyChangedEventHandler? PropertyChanged; + private void OnPropertyChanged(string propertyName) => + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + + // Properties to hold each columns' width. + private GridLength _columnWidth1; + public GridLength ColumnWidth1 + { + get => _columnWidth1; + set { _columnWidth1 = value; OnPropertyChanged(nameof(ColumnWidth1)); } + } + + private GridLength _columnWidth2; + public GridLength ColumnWidth2 + { + get => _columnWidth2; + set { _columnWidth2 = value; OnPropertyChanged(nameof(ColumnWidth2)); } + } + + private GridLength _columnWidth3; + public GridLength ColumnWidth3 + { + get => _columnWidth3; + set { _columnWidth3 = value; OnPropertyChanged(nameof(ColumnWidth3)); } + } + + private GridLength _columnWidth4; + public GridLength ColumnWidth4 + { + get => _columnWidth4; + set { _columnWidth4 = value; OnPropertyChanged(nameof(ColumnWidth4)); } + } + + private GridLength _columnWidth5; + public GridLength ColumnWidth5 + { + get => _columnWidth5; + set { _columnWidth5 = value; OnPropertyChanged(nameof(ColumnWidth5)); } + } + + private GridLength _columnWidth6; + public GridLength ColumnWidth6 + { + get => _columnWidth6; + set { _columnWidth6 = value; OnPropertyChanged(nameof(ColumnWidth6)); } + } + + private GridLength _columnWidth7; + public GridLength ColumnWidth7 + { + get => _columnWidth7; + set { _columnWidth7 = value; OnPropertyChanged(nameof(ColumnWidth7)); } + } + + private GridLength _columnWidth8; + public GridLength ColumnWidth8 + { + get => _columnWidth8; + set { _columnWidth8 = value; OnPropertyChanged(nameof(ColumnWidth8)); } + } + + private GridLength _columnWidth9; + public GridLength ColumnWidth9 + { + get => _columnWidth9; + set { _columnWidth9 = value; OnPropertyChanged(nameof(ColumnWidth9)); } + } + + private GridLength _columnWidth10; + public GridLength ColumnWidth10 + { + get => _columnWidth10; + set { _columnWidth10 = value; OnPropertyChanged(nameof(ColumnWidth10)); } + } + + private GridLength _columnWidth11; + public GridLength ColumnWidth11 + { + get => _columnWidth11; + set { _columnWidth11 = value; OnPropertyChanged(nameof(ColumnWidth11)); } + } + + private GridLength _columnWidth12; + public GridLength ColumnWidth12 + { + get => _columnWidth12; + set { _columnWidth12 = value; OnPropertyChanged(nameof(ColumnWidth12)); } + } + + private GridLength _columnWidth13; + public GridLength ColumnWidth13 + { + get => _columnWidth13; + set { _columnWidth13 = value; OnPropertyChanged(nameof(ColumnWidth13)); } + } + + private GridLength _columnWidth14; + public GridLength ColumnWidth14 + { + get => _columnWidth14; + set { _columnWidth14 = value; OnPropertyChanged(nameof(ColumnWidth14)); } + } + + private GridLength _columnWidth15; + public GridLength ColumnWidth15 + { + get => _columnWidth15; + set { _columnWidth15 = value; OnPropertyChanged(nameof(ColumnWidth15)); } + } + + private GridLength _columnWidth16; + public GridLength ColumnWidth16 + { + get => _columnWidth16; + set { _columnWidth16 = value; OnPropertyChanged(nameof(ColumnWidth16)); } + } + + private GridLength _columnWidth17; + public GridLength ColumnWidth17 + { + get => _columnWidth17; + set { _columnWidth17 = value; OnPropertyChanged(nameof(ColumnWidth17)); } + } + + private GridLength _columnWidth18; + public GridLength ColumnWidth18 + { + get => _columnWidth18; + set { _columnWidth18 = value; OnPropertyChanged(nameof(ColumnWidth18)); } + } + + private GridLength _columnWidth19; + public GridLength ColumnWidth19 + { + get => _columnWidth19; + set { _columnWidth19 = value; OnPropertyChanged(nameof(ColumnWidth19)); } + } + + private GridLength _columnWidth20; + public GridLength ColumnWidth20 + { + get => _columnWidth20; + set { _columnWidth20 = value; OnPropertyChanged(nameof(ColumnWidth20)); } + } + + private GridLength _columnWidth21; + public GridLength ColumnWidth21 + { + get => _columnWidth21; + set { _columnWidth21 = value; OnPropertyChanged(nameof(ColumnWidth21)); } + } + + /// + /// Calculates the maximum required width for each column (including header text) + /// and assigns the value (with a little extra padding) to the corresponding property. + /// It should always run once ALL the data have been added to the ObservableCollection that is the ItemsSource of the ListView + /// And only after this method, the ItemsSource must be assigned to the ListView. + /// + internal void CalculateColumnWidths() + { + + // Measure header text widths first. + double maxWidth1 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("FileNameHeader/Text")); + double maxWidth2 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("TimeCreatedHeader/Text")); + double maxWidth3 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SignatureStatusHeader/Text")); + double maxWidth4 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("ActionHeader/Text")); + double maxWidth5 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("OriginalFileNameHeader/Text")); + double maxWidth6 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("InternalNameHeader/Text")); + double maxWidth7 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("FileDescriptionHeader/Text")); + double maxWidth8 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("ProductNameHeader/Text")); + double maxWidth9 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("FileVersionHeader/Text")); + double maxWidth10 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("PackageFamilyNameHeader/Text")); + double maxWidth11 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SHA256HashHeader/Text")); + double maxWidth12 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SHA1HashHeader/Text")); + double maxWidth13 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SigningScenarioHeader/Text")); + double maxWidth14 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("FilePathHeader/Text")); + double maxWidth15 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SHA1PageHashHeader/Text")); + double maxWidth16 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SHA256PageHashHeader/Text")); + double maxWidth17 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("HasWHQLSignerHeader/Text")); + double maxWidth18 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("FilePublishersHeader/Text")); + double maxWidth19 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("OpusDataHeader/Text")); + double maxWidth20 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("PolicyGUIDHeader/Text")); + double maxWidth21 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("PolicyNameHeader/Text")); + + // Iterate over all items to determine the widest string for each column. + foreach (FileIdentity item in AllowNewAppsStart.Instance.LocalFilesFileIdentities) + { + double w1 = ListViewUIHelpers.MeasureTextWidth(item.FileName); + if (w1 > maxWidth1) maxWidth1 = w1; + + double w2 = ListViewUIHelpers.MeasureTextWidth(item.TimeCreated.ToString()); + if (w2 > maxWidth2) maxWidth2 = w2; + + double w3 = ListViewUIHelpers.MeasureTextWidth(item.SignatureStatus.ToString()); + if (w3 > maxWidth3) maxWidth3 = w3; + + double w4 = ListViewUIHelpers.MeasureTextWidth(item.Action.ToString()); + if (w4 > maxWidth4) maxWidth4 = w4; + + double w5 = ListViewUIHelpers.MeasureTextWidth(item.OriginalFileName); + if (w5 > maxWidth5) maxWidth5 = w5; + + double w6 = ListViewUIHelpers.MeasureTextWidth(item.InternalName); + if (w6 > maxWidth6) maxWidth6 = w6; + + double w7 = ListViewUIHelpers.MeasureTextWidth(item.FileDescription); + if (w7 > maxWidth7) maxWidth7 = w7; + + double w8 = ListViewUIHelpers.MeasureTextWidth(item.ProductName); + if (w8 > maxWidth8) maxWidth8 = w8; + + double w9 = ListViewUIHelpers.MeasureTextWidth(item.FileVersion?.ToString()); + if (w9 > maxWidth9) maxWidth9 = w9; + + double w10 = ListViewUIHelpers.MeasureTextWidth(item.PackageFamilyName); + if (w10 > maxWidth10) maxWidth10 = w10; + + double w11 = ListViewUIHelpers.MeasureTextWidth(item.SHA256Hash); + if (w11 > maxWidth11) maxWidth11 = w11; + + double w12 = ListViewUIHelpers.MeasureTextWidth(item.SHA1Hash); + if (w12 > maxWidth12) maxWidth12 = w12; + + double w13 = ListViewUIHelpers.MeasureTextWidth(item.SISigningScenario.ToString()); + if (w13 > maxWidth13) maxWidth13 = w13; + + double w14 = ListViewUIHelpers.MeasureTextWidth(item.FilePath); + if (w14 > maxWidth14) maxWidth14 = w14; + + double w15 = ListViewUIHelpers.MeasureTextWidth(item.SHA1PageHash); + if (w15 > maxWidth15) maxWidth15 = w15; + + double w16 = ListViewUIHelpers.MeasureTextWidth(item.SHA256PageHash); + if (w16 > maxWidth16) maxWidth16 = w16; + + double w17 = ListViewUIHelpers.MeasureTextWidth(item.HasWHQLSigner.ToString()); + if (w17 > maxWidth17) maxWidth17 = w17; + + double w18 = ListViewUIHelpers.MeasureTextWidth(item.FilePublishersToDisplay); + if (w18 > maxWidth18) maxWidth18 = w18; + + double w19 = ListViewUIHelpers.MeasureTextWidth(item.Opus); + if (w19 > maxWidth19) maxWidth19 = w19; + + double w20 = ListViewUIHelpers.MeasureTextWidth(item.PolicyGUID.ToString()); + if (w20 > maxWidth20) maxWidth20 = w20; + + double w21 = ListViewUIHelpers.MeasureTextWidth(item.PolicyName); + if (w21 > maxWidth21) maxWidth21 = w21; + } + + // Set the column width properties. + ColumnWidth1 = new GridLength(maxWidth1); + ColumnWidth2 = new GridLength(maxWidth2); + ColumnWidth3 = new GridLength(maxWidth3); + ColumnWidth4 = new GridLength(maxWidth4); + ColumnWidth5 = new GridLength(maxWidth5); + ColumnWidth6 = new GridLength(maxWidth6); + ColumnWidth7 = new GridLength(maxWidth7); + ColumnWidth8 = new GridLength(maxWidth8); + ColumnWidth9 = new GridLength(maxWidth9); + ColumnWidth10 = new GridLength(maxWidth10); + ColumnWidth11 = new GridLength(maxWidth11); + ColumnWidth12 = new GridLength(maxWidth12); + ColumnWidth13 = new GridLength(maxWidth13); + ColumnWidth14 = new GridLength(maxWidth14); + ColumnWidth15 = new GridLength(maxWidth15); + ColumnWidth16 = new GridLength(maxWidth16); + ColumnWidth17 = new GridLength(maxWidth17); + ColumnWidth18 = new GridLength(maxWidth18); + ColumnWidth19 = new GridLength(maxWidth19); + ColumnWidth20 = new GridLength(maxWidth20); + ColumnWidth21 = new GridLength(maxWidth21); + } + + + /// + /// Copies the selected rows to the clipboard in a formatted manner, with each property labeled for clarity. + /// + /// The event sender. + /// The event arguments. + private void ListViewFlyoutMenuCopy_Click(object sender, RoutedEventArgs e) + { + // Check if there are selected items in the ListView + if (FileIdentitiesListView.SelectedItems.Count > 0) + { + // Initialize StringBuilder to store all selected rows' data with labels + StringBuilder dataBuilder = new(); + + // Loop through each selected item in the ListView + foreach (var selectedItem in FileIdentitiesListView.SelectedItems) + { + if (selectedItem is FileIdentity obj) + + // Append each row's formatted data to the StringBuilder + _ = dataBuilder.AppendLine(ListViewUIHelpers.ConvertRowToText(obj)); + + // Add a separator between rows for readability in multi-row copies + _ = dataBuilder.AppendLine(new string('-', 50)); + } + + // Create a DataPackage to hold the text data + DataPackage dataPackage = new(); + + // Set the formatted text as the content of the DataPackage + dataPackage.SetText(dataBuilder.ToString()); + + // Copy the DataPackage content to the clipboard + Clipboard.SetContent(dataPackage); + } + } + + + // Click event handlers for each property + private void CopyFileName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FileName); + private void CopySignatureStatus_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SignatureStatus.ToString()); + private void CopyOriginalFileName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.OriginalFileName); + private void CopyInternalName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.InternalName); + private void CopyFileDescription_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FileDescription); + private void CopyProductName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.ProductName); + private void CopyFileVersion_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FileVersion?.ToString()); + private void CopyPackageFamilyName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.PackageFamilyName); + private void CopySHA256Hash_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SHA256Hash); + private void CopySHA1Hash_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SHA1Hash); + private void CopySigningScenario_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SISigningScenario.ToString()); + private void CopyFilePath_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FilePath); + private void CopySHA1PageHash_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SHA1PageHash); + private void CopySHA256PageHash_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SHA256PageHash); + private void CopyHasWHQLSigner_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.HasWHQLSigner.ToString()); + private void CopyFilePublishers_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FilePublishersToDisplay); + private void CopyIsECCSigned_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.IsECCSigned.ToString()); + private void CopyOpusData_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.Opus); + + /// + /// Helper method to copy a specified property to clipboard without reflection + /// + /// Function that retrieves the desired property value as a string + private void CopyToClipboard(Func getProperty) + { + if (FileIdentitiesListView.SelectedItem is FileIdentity selectedItem) + { + string? propertyValue = getProperty(selectedItem); + if (propertyValue is not null) + { + DataPackage dataPackage = new(); + dataPackage.SetText(propertyValue); + Clipboard.SetContent(dataPackage); + } + } + } + + // Event handlers for each sort button + private void ColumnSortingButton_FileName_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.FileName); + } + private void ColumnSortingButton_SignatureStatus_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.SignatureStatus); + } + private void ColumnSortingButton_OriginalFileName_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.OriginalFileName); + } + private void ColumnSortingButton_InternalName_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.InternalName); + } + private void ColumnSortingButton_FileDescription_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.FileDescription); + } + private void ColumnSortingButton_ProductName_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.ProductName); + } + private void ColumnSortingButton_FileVersion_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.FileVersion); + } + private void ColumnSortingButton_PackageFamilyName_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.PackageFamilyName); + } + private void ColumnSortingButton_SHA256Hash_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.SHA256Hash); + } + private void ColumnSortingButton_SHA1Hash_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.SHA1Hash); + } + private void ColumnSortingButton_SigningScenario_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.SISigningScenario); + } + private void ColumnSortingButton_FilePath_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.FilePath); + } + private void ColumnSortingButton_SHA1PageHash_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.SHA1PageHash); + } + private void ColumnSortingButton_SHA256PageHash_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.SHA256PageHash); + } + private void ColumnSortingButton_HasWHQLSigner_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.HasWHQLSigner); + } + private void ColumnSortingButton_FilePublishers_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.FilePublishersToDisplay); + } + private void ColumnSortingButton_IsECCSigned_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.IsECCSigned); + } + private void ColumnSortingButton_OpusData_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.Opus); + } + + + /// + /// Performs data sorting + /// + /// + /// + private void SortColumn(Func keySelector) + { + // Determine if a search filter is active. + bool isSearchEmpty = string.IsNullOrWhiteSpace(SearchBox.Text); + // Use either the full list (AllowNewAppsStart.Instance.EventLogsAllFileIdentities) or the current display list. + var collectionToSort = isSearchEmpty ? AllowNewAppsStart.Instance.EventLogsAllFileIdentities : [.. AllowNewAppsStart.Instance.EventLogsFileIdentities]; + + if (SortingDirectionToggle.IsChecked) + { + // Sort in descending order. + AllowNewAppsStart.Instance.EventLogsFileIdentities = [.. collectionToSort.OrderByDescending(keySelector)]; + } + else + { + // Sort in ascending order. + AllowNewAppsStart.Instance.EventLogsFileIdentities = [.. collectionToSort.OrderBy(keySelector)]; + } + + // Refresh the ItemsSource so the UI updates. + FileIdentitiesListView.ItemsSource = AllowNewAppsStart.Instance.EventLogsFileIdentities; + } + + + /// + /// Converts the properties of a FileIdentity row into a labeled, formatted string for copying to clipboard. + /// + /// The selected FileIdentity row from the ListView. + /// A formatted string of the row's properties with labels. + private static string ConvertRowToText(FileIdentity row) + { + // Use StringBuilder to format each property with its label for easy reading + return new StringBuilder() + .AppendLine($"File Name: {row.FileName}") + .AppendLine($"Time Created: {row.TimeCreated}") + .AppendLine($"Signature Status: {row.SignatureStatus}") + .AppendLine($"Action: {row.Action}") + .AppendLine($"Original File Name: {row.OriginalFileName}") + .AppendLine($"Internal Name: {row.InternalName}") + .AppendLine($"File Description: {row.FileDescription}") + .AppendLine($"Product Name: {row.ProductName}") + .AppendLine($"File Version: {row.FileVersion}") + .AppendLine($"Package Family Name: {row.PackageFamilyName}") + .AppendLine($"SHA256 Hash: {row.SHA256Hash}") + .AppendLine($"SHA1 Hash: {row.SHA1Hash}") + .AppendLine($"SHA256 Flat Hash: {row.SHA256FlatHash}") + .AppendLine($"SHA1 Flat Hash: {row.SHA1FlatHash}") + .AppendLine($"Signing Scenario: {row.SISigningScenario}") + .AppendLine($"File Path: {row.FilePath}") + .AppendLine($"Computer Name: {row.ComputerName}") + .AppendLine($"Policy GUID: {row.PolicyGUID}") + .AppendLine($"Policy Name: {row.PolicyName}") + .AppendLine($"File Publishers: {row.FilePublishersToDisplay}") + .ToString(); + } + #endregion + + public AllowNewAppsEventLogsDataGrid() { this.InitializeComponent(); @@ -27,37 +523,35 @@ public AllowNewAppsEventLogsDataGrid() // Assign this instance to the static field _instance = this; + UIListView = FileIdentitiesListView; } // Public property to access the singleton instance from other classes // It's okay it's nullable, null check will happen before accessing it - public static AllowNewAppsEventLogsDataGrid? Instance => _instance; + public static AllowNewAppsEventLogsDataGrid Instance => _instance ?? throw new InvalidOperationException("AllowNewAppsEventLogsDataGrid is not initialized"); #region - - // Without the following steps, when the user begins data fetching process and then navigates away from this page - // Upon arrival at this page again, the DataGrid loses its virtualization, causing the UI to hang for extended periods of time - // But after nullifying DataGrid's ItemsSource when page is navigated from and reassigning it when page is navigated to, - // We tackle that problem. Data will sill be stored in the ObservableCollection when page is not in focus, - // But DataGrid's source will pick them up only when page is navigated to. protected override void OnNavigatedTo(NavigationEventArgs e) { base.OnNavigatedTo(e); - FileIdentitiesDataGrid.ItemsSource = AllowNewAppsStart.Instance.EventLogsFileIdentities; + FileIdentitiesListView.ItemsSource = AllowNewAppsStart.Instance.EventLogsFileIdentities; // Update the logs when user switches to this page UpdateTotalLogs(); - } - protected override void OnNavigatedFrom(NavigationEventArgs e) - { - base.OnNavigatedFrom(e); - FileIdentitiesDataGrid.ItemsSource = null; - } + // Assign the ItemsSource of the ListView only once + // We cannot do it after column width calculation because initialization is not guaranteed at that moment + if (AllowNewAppsStart.Instance.EventLogsDataProcessed) + { + CalculateColumnWidths(); - #endregion + FileIdentitiesListView.ItemsSource = AllowNewAppsStart.Instance.EventLogsFileIdentities; + AllowNewAppsStart.Instance.EventLogsDataProcessed = false; + } + } + #endregion /// /// Event handler for the SearchBox text change @@ -67,7 +561,6 @@ private void SearchBox_TextChanged(object sender, TextChangedEventArgs e) ApplyFilters(); } - /// /// Applies the date and search filters to the data grid /// @@ -109,20 +602,19 @@ private void ApplyFilters() AllowNewAppsStart.Instance.EventLogsFileIdentities.Clear(); // Populate the ObservableCollection with the filtered results - // This triggers the UI to update the DataGrid based on the filtered data + // This triggers the UI to update the ListView based on the filtered data foreach (FileIdentity result in filteredResults) { AllowNewAppsStart.Instance.EventLogsFileIdentities.Add(result); } - // Explicitly set the DataGrid's ItemsSource to ensure the data refreshes - FileIdentitiesDataGrid.ItemsSource = AllowNewAppsStart.Instance.EventLogsFileIdentities; + // Explicitly set the ListView's ItemsSource to ensure the data refreshes + FileIdentitiesListView.ItemsSource = AllowNewAppsStart.Instance.EventLogsFileIdentities; // Update any visual or text element showing the total logs count UpdateTotalLogs(); } - /// /// Event handler for the Clear Data button /// @@ -136,145 +628,8 @@ private void ClearDataButton_Click(object sender, RoutedEventArgs e) UpdateTotalLogs(true); } - - - // https://learn.microsoft.com/en-us/windows/communitytoolkit/controls/datagrid_guidance/group_sort_filter - // Column sorting logic for the entire DataGrid - private void FileIdentitiesDataGrid_Sorting(object sender, DataGridColumnEventArgs e) - { - // Sort the column based on its tag and current sort direction - if (string.Equals(e.Column.Tag?.ToString(), "FileName", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.FileName); - } - else if (string.Equals(e.Column.Tag?.ToString(), "TimeCreated", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.TimeCreated); - } - else if (string.Equals(e.Column.Tag?.ToString(), "SignatureStatus", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.SignatureStatus); - } - else if (string.Equals(e.Column.Tag?.ToString(), "Action", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.Action); - } - else if (string.Equals(e.Column.Tag?.ToString(), "OriginalFileName", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.OriginalFileName); - } - else if (string.Equals(e.Column.Tag?.ToString(), "InternalName", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.InternalName); - } - else if (string.Equals(e.Column.Tag?.ToString(), "FileDescription", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.FileDescription); - } - else if (string.Equals(e.Column.Tag?.ToString(), "ProductName", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.ProductName); - } - else if (string.Equals(e.Column.Tag?.ToString(), "FileVersion", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.FileVersion); - } - else if (string.Equals(e.Column.Tag?.ToString(), "PackageFamilyName", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.PackageFamilyName); - } - else if (string.Equals(e.Column.Tag?.ToString(), "SHA256Hash", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.SHA256Hash); - } - else if (string.Equals(e.Column.Tag?.ToString(), "SHA1Hash", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.SHA1Hash); - } - else if (string.Equals(e.Column.Tag?.ToString(), "SHA256FlatHash", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.SHA256FlatHash); - } - else if (string.Equals(e.Column.Tag?.ToString(), "SHA1FlatHash", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.SHA1FlatHash); - } - else if (string.Equals(e.Column.Tag?.ToString(), "SISigningScenario", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.SISigningScenario); - } - else if (string.Equals(e.Column.Tag?.ToString(), "FilePath", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.FilePath); - } - else if (string.Equals(e.Column.Tag?.ToString(), "ComputerName", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.ComputerName); - } - else if (string.Equals(e.Column.Tag?.ToString(), "PolicyGUID", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.PolicyGUID); - } - else if (string.Equals(e.Column.Tag?.ToString(), "PolicyName", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.PolicyName); - } - else if (string.Equals(e.Column.Tag?.ToString(), "FilePublishersToDisplay", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.FilePublishersToDisplay); - } - - - // Clear SortDirection for other columns - foreach (DataGridColumn column in FileIdentitiesDataGrid.Columns) - { - if (column != e.Column) - { - column.SortDirection = null; - } - } - } - - - /// - /// Helper method for sorting any column on the DataGird - /// - /// - /// - /// - private void SortColumn(DataGridColumnEventArgs e, Func keySelector) - { - // Check if the search box is empty or not - bool isSearchEmpty = string.IsNullOrWhiteSpace(SearchBox.Text); - - // Get the collection to sort based on the search box status - // Allowing us to sort only the items in the search results - List collectionToSort = isSearchEmpty ? AllowNewAppsStart.Instance.EventLogsAllFileIdentities : [.. AllowNewAppsStart.Instance.EventLogsFileIdentities]; - - // Perform the sorting based on the current SortDirection (ascending or descending) - if (e.Column.SortDirection is null || e.Column.SortDirection == DataGridSortDirection.Ascending) - { - // Descending: custom order depending on column type - AllowNewAppsStart.Instance.EventLogsFileIdentities = [.. collectionToSort.OrderByDescending(keySelector)]; - - // Set the column direction to Descending - e.Column.SortDirection = DataGridSortDirection.Descending; - } - else - { - // Ascending: custom order depending on column type - AllowNewAppsStart.Instance.EventLogsFileIdentities = [.. collectionToSort.OrderBy(keySelector)]; - e.Column.SortDirection = DataGridSortDirection.Ascending; - } - - // Update the ItemsSource of the DataGrid - // Required for sort + search to work properly, even though binding to the ObservableCollection already happens in XAML - FileIdentitiesDataGrid.ItemsSource = AllowNewAppsStart.Instance.EventLogsFileIdentities; - } - - /// - /// Selects all of the displayed rows on the DataGrid + /// Selects all of the displayed rows on the ListView /// /// /// @@ -283,29 +638,25 @@ private void SelectAll_Click(object sender, RoutedEventArgs e) _ = DispatcherQueue.TryEnqueue(() => { // Clear existing selections - FileIdentitiesDataGrid.SelectedItems.Clear(); + FileIdentitiesListView.SelectedItems.Clear(); foreach (FileIdentity fileIdentity in AllowNewAppsStart.Instance.EventLogsFileIdentities) { - _ = FileIdentitiesDataGrid.SelectedItems.Add(fileIdentity); // Select each item + FileIdentitiesListView.SelectedItems.Add(fileIdentity); // Select each item } - }); } - /// - /// De-selects all of the displayed rows on the DataGrid + /// De-selects all of the displayed rows on the ListView /// /// /// private void DeSelectAll_Click(object sender, RoutedEventArgs e) { - FileIdentitiesDataGrid.SelectedItems.Clear(); // Deselect all rows by clearing SelectedItems + FileIdentitiesListView.SelectedItems.Clear(); // Deselect all rows by clearing SelectedItems } - - /// /// Deletes the selected row from the results /// @@ -314,7 +665,7 @@ private void DeSelectAll_Click(object sender, RoutedEventArgs e) private void DataGridFlyoutMenuDelete_Click(object sender, RoutedEventArgs e) { // Collect the selected items to delete - List itemsToDelete = [.. FileIdentitiesDataGrid.SelectedItems.Cast()]; + List itemsToDelete = [.. FileIdentitiesListView.SelectedItems.Cast()]; // Remove each selected item from the FileIdentities collection foreach (FileIdentity item in itemsToDelete) @@ -326,180 +677,6 @@ private void DataGridFlyoutMenuDelete_Click(object sender, RoutedEventArgs e) UpdateTotalLogs(); } - - - /// - /// Copies the selected rows to the clipboard in a formatted manner, with each property labeled for clarity. - /// - /// The event sender. - /// The event arguments. - private void DataGridFlyoutMenuCopy_Click(object sender, RoutedEventArgs e) - { - // Check if there are selected items in the DataGrid - if (FileIdentitiesDataGrid.SelectedItems.Count > 0) - { - // Initialize StringBuilder to store all selected rows' data with labels - StringBuilder dataBuilder = new(); - - // Loop through each selected item in the DataGrid - foreach (FileIdentity selectedItem in FileIdentitiesDataGrid.SelectedItems) - { - // Append each row's formatted data to the StringBuilder - _ = dataBuilder.AppendLine(ConvertRowToText(selectedItem)); - - // Add a separator between rows for readability in multi-row copies - _ = dataBuilder.AppendLine(new string('-', 50)); - } - - // Create a DataPackage to hold the text data - DataPackage dataPackage = new(); - - // Set the formatted text as the content of the DataPackage - dataPackage.SetText(dataBuilder.ToString()); - - // Copy the DataPackage content to the clipboard - Clipboard.SetContent(dataPackage); - } - } - - /// - /// Converts the properties of a FileIdentity row into a labeled, formatted string for copying to clipboard. - /// - /// The selected FileIdentity row from the DataGrid. - /// A formatted string of the row's properties with labels. - private static string ConvertRowToText(FileIdentity row) - { - // Use StringBuilder to format each property with its label for easy reading - return new StringBuilder() - .AppendLine($"File Name: {row.FileName}") - .AppendLine($"Time Created: {row.TimeCreated}") - .AppendLine($"Signature Status: {row.SignatureStatus}") - .AppendLine($"Action: {row.Action}") - .AppendLine($"Original File Name: {row.OriginalFileName}") - .AppendLine($"Internal Name: {row.InternalName}") - .AppendLine($"File Description: {row.FileDescription}") - .AppendLine($"Product Name: {row.ProductName}") - .AppendLine($"File Version: {row.FileVersion}") - .AppendLine($"Package Family Name: {row.PackageFamilyName}") - .AppendLine($"SHA256 Hash: {row.SHA256Hash}") - .AppendLine($"SHA1 Hash: {row.SHA1Hash}") - .AppendLine($"SHA256 Flat Hash: {row.SHA256FlatHash}") - .AppendLine($"SHA1 Flat Hash: {row.SHA1FlatHash}") - .AppendLine($"Signing Scenario: {row.SISigningScenario}") - .AppendLine($"File Path: {row.FilePath}") - .AppendLine($"Computer Name: {row.ComputerName}") - .AppendLine($"Policy GUID: {row.PolicyGUID}") - .AppendLine($"Policy Name: {row.PolicyName}") - .AppendLine($"File Publishers: {row.FilePublishersToDisplay}") - .ToString(); - } - - - - /// - /// Event handler for the Copy Individual Items SubMenu. It will populate the submenu items in the flyout of the data grid. - /// - /// - /// - private void FileIdentitiesDataGrid_Loaded(object sender, RoutedEventArgs e) - { - // Ensure the CopyIndividualItemsSubMenu is available - if (CopyIndividualItemsSubMenu is null) - { - return; - } - - // Clear any existing items to avoid duplication if reloaded - CopyIndividualItemsSubMenu.Items.Clear(); - - // Create a dictionary to map headers to their specific click event methods - Dictionary copyActions = new() - { - { "File Name", CopyFileName_Click }, - { "Time Created", CopyTimeCreated_Click }, - { "Signature Status", CopySignatureStatus_Click }, - { "Action", CopyAction_Click }, - { "Original File Name", CopyOriginalFileName_Click }, - { "Internal Name", CopyInternalName_Click }, - { "File Description", CopyFileDescription_Click }, - { "Product Name", CopyProductName_Click }, - { "File Version", CopyFileVersion_Click }, - { "Package Family Name", CopyPackageFamilyName_Click }, - { "SHA256 Hash", CopySHA256Hash_Click }, - { "SHA1 Hash", CopySHA1Hash_Click }, - { "SHA256 Flat Hash", CopySHA256FlatHash_Click }, - { "SHA1 Flat Hash", CopySHA1FlatHash_Click }, - { "Signing Scenario", CopySigningScenario_Click }, - { "File Path", CopyFilePath_Click }, - { "Computer Name", CopyComputerName_Click }, - { "Policy GUID", CopyPolicyGUID_Click }, - { "Policy Name", CopyPolicyName_Click }, - { "File Publishers", CopyFilePublishersToDisplay_Click } - }; - - // Add menu items with specific click events for each column - foreach (DataGridColumn column in FileIdentitiesDataGrid.Columns) - { - string headerText = column.Header.ToString()!; - - if (copyActions.TryGetValue(headerText, out RoutedEventHandler? value)) - { - // Create a new MenuFlyout Item - MenuFlyoutItem menuItem = new() { Text = $"Copy {headerText}" }; - - // Set the click event for the menu item - menuItem.Click += value; - - // Add the menu item to the submenu - CopyIndividualItemsSubMenu.Items.Add(menuItem); - } - } - } - - // Click event handlers for each property - private void CopyFileName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FileName); - private void CopyTimeCreated_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.TimeCreated.ToString()); - private void CopySignatureStatus_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SignatureStatus.ToString()); - private void CopyAction_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.Action.ToString()); - private void CopyOriginalFileName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.OriginalFileName); - private void CopyInternalName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.InternalName); - private void CopyFileDescription_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FileDescription); - private void CopyProductName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.ProductName); - private void CopyFileVersion_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FileVersion?.ToString()); - private void CopyPackageFamilyName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.PackageFamilyName); - private void CopySHA256Hash_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SHA256Hash); - private void CopySHA1Hash_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SHA1Hash); - private void CopySHA256FlatHash_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SHA256FlatHash); - private void CopySHA1FlatHash_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SHA1FlatHash); - private void CopySigningScenario_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SISigningScenario.ToString()); - private void CopyFilePath_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FilePath); - private void CopyComputerName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.ComputerName); - private void CopyPolicyGUID_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.PolicyGUID.ToString()); - private void CopyPolicyName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.PolicyName); - private void CopyFilePublishersToDisplay_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FilePublishersToDisplay.ToString()); - - - - /// - /// Helper method to copy a specified property to clipboard without reflection - /// - /// Function that retrieves the desired property value as a string - private void CopyToClipboard(Func getProperty) - { - if (FileIdentitiesDataGrid.SelectedItem is FileIdentity selectedItem) - { - string? propertyValue = getProperty(selectedItem); - if (propertyValue is not null) - { - DataPackage dataPackage = new(); - dataPackage.SetText(propertyValue); - Clipboard.SetContent(dataPackage); - } - } - } - - - /// /// Updates the total logs count displayed on the UI /// @@ -511,7 +688,6 @@ internal void UpdateTotalLogs(bool? Zero = null) // Update the InfoBadge for the top menu AllowNewApps.Instance.UpdateEventLogsInfoBadge(0, 1); - } else { @@ -519,9 +695,6 @@ internal void UpdateTotalLogs(bool? Zero = null) // Update the InfoBadge for the top menu AllowNewApps.Instance.UpdateEventLogsInfoBadge(AllowNewAppsStart.Instance.EventLogsFileIdentities.Count, 1); - } } - - } diff --git a/AppControl Manager/Pages/AllowNewApps/AllowNewAppsLocalFilesDataGrid.xaml b/AppControl Manager/Pages/AllowNewApps/AllowNewAppsLocalFilesDataGrid.xaml index ea3f9b631..810edf021 100644 --- a/AppControl Manager/Pages/AllowNewApps/AllowNewAppsLocalFilesDataGrid.xaml +++ b/AppControl Manager/Pages/AllowNewApps/AllowNewAppsLocalFilesDataGrid.xaml @@ -8,7 +8,10 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" xmlns:controls="using:CommunityToolkit.WinUI.Controls" - xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls"> + xmlns:intelgathering="using:AppControlManager.IntelGathering" + xmlns:interactivity="using:Microsoft.Xaml.Interactivity" + xmlns:behaviors="using:CommunityToolkit.WinUI.Behaviors" + x:Name="AllowNewAppsLocalFilesDataGridXAML"> @@ -51,6 +54,43 @@ + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/AppControl Manager/Pages/AllowNewApps/AllowNewAppsLocalFilesDataGrid.xaml.cs b/AppControl Manager/Pages/AllowNewApps/AllowNewAppsLocalFilesDataGrid.xaml.cs index 0ab794f12..6e6bc97dd 100644 --- a/AppControl Manager/Pages/AllowNewApps/AllowNewAppsLocalFilesDataGrid.xaml.cs +++ b/AppControl Manager/Pages/AllowNewApps/AllowNewAppsLocalFilesDataGrid.xaml.cs @@ -1,22 +1,495 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Linq; using System.Text; using AppControlManager.IntelGathering; -using CommunityToolkit.WinUI.UI.Controls; +using AppControlManager.Others; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Navigation; using Windows.ApplicationModel.DataTransfer; +using WinRT; namespace AppControlManager.Pages; -public sealed partial class AllowNewAppsLocalFilesDataGrid : Page +// Since the columns for data in the ItemTemplate use "Binding" instead of "x:Bind", we need to use [GeneratedBindableCustomProperty] for them to work properly +[GeneratedBindableCustomProperty] +public sealed partial class AllowNewAppsLocalFilesDataGrid : Page, INotifyPropertyChanged { // A static instance of the AllowNewAppsLocalFilesDataGrid class which will hold the single, shared instance of the page private static AllowNewAppsLocalFilesDataGrid? _instance; + internal ListView UIListView { get; private set; } + + #region LISTVIEW IMPLEMENTATIONS + + public event PropertyChangedEventHandler? PropertyChanged; + private void OnPropertyChanged(string propertyName) => + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + + // Properties to hold each columns' width. + private GridLength _columnWidth1; + public GridLength ColumnWidth1 + { + get => _columnWidth1; + set { _columnWidth1 = value; OnPropertyChanged(nameof(ColumnWidth1)); } + } + + private GridLength _columnWidth2; + public GridLength ColumnWidth2 + { + get => _columnWidth2; + set { _columnWidth2 = value; OnPropertyChanged(nameof(ColumnWidth2)); } + } + + private GridLength _columnWidth3; + public GridLength ColumnWidth3 + { + get => _columnWidth3; + set { _columnWidth3 = value; OnPropertyChanged(nameof(ColumnWidth3)); } + } + + private GridLength _columnWidth4; + public GridLength ColumnWidth4 + { + get => _columnWidth4; + set { _columnWidth4 = value; OnPropertyChanged(nameof(ColumnWidth4)); } + } + + private GridLength _columnWidth5; + public GridLength ColumnWidth5 + { + get => _columnWidth5; + set { _columnWidth5 = value; OnPropertyChanged(nameof(ColumnWidth5)); } + } + + private GridLength _columnWidth6; + public GridLength ColumnWidth6 + { + get => _columnWidth6; + set { _columnWidth6 = value; OnPropertyChanged(nameof(ColumnWidth6)); } + } + + private GridLength _columnWidth7; + public GridLength ColumnWidth7 + { + get => _columnWidth7; + set { _columnWidth7 = value; OnPropertyChanged(nameof(ColumnWidth7)); } + } + + private GridLength _columnWidth8; + public GridLength ColumnWidth8 + { + get => _columnWidth8; + set { _columnWidth8 = value; OnPropertyChanged(nameof(ColumnWidth8)); } + } + + private GridLength _columnWidth9; + public GridLength ColumnWidth9 + { + get => _columnWidth9; + set { _columnWidth9 = value; OnPropertyChanged(nameof(ColumnWidth9)); } + } + + private GridLength _columnWidth10; + public GridLength ColumnWidth10 + { + get => _columnWidth10; + set { _columnWidth10 = value; OnPropertyChanged(nameof(ColumnWidth10)); } + } + + private GridLength _columnWidth11; + public GridLength ColumnWidth11 + { + get => _columnWidth11; + set { _columnWidth11 = value; OnPropertyChanged(nameof(ColumnWidth11)); } + } + + private GridLength _columnWidth12; + public GridLength ColumnWidth12 + { + get => _columnWidth12; + set { _columnWidth12 = value; OnPropertyChanged(nameof(ColumnWidth12)); } + } + + private GridLength _columnWidth13; + public GridLength ColumnWidth13 + { + get => _columnWidth13; + set { _columnWidth13 = value; OnPropertyChanged(nameof(ColumnWidth13)); } + } + + private GridLength _columnWidth14; + public GridLength ColumnWidth14 + { + get => _columnWidth14; + set { _columnWidth14 = value; OnPropertyChanged(nameof(ColumnWidth14)); } + } + + private GridLength _columnWidth15; + public GridLength ColumnWidth15 + { + get => _columnWidth15; + set { _columnWidth15 = value; OnPropertyChanged(nameof(ColumnWidth15)); } + } + + private GridLength _columnWidth16; + public GridLength ColumnWidth16 + { + get => _columnWidth16; + set { _columnWidth16 = value; OnPropertyChanged(nameof(ColumnWidth16)); } + } + + private GridLength _columnWidth17; + public GridLength ColumnWidth17 + { + get => _columnWidth17; + set { _columnWidth17 = value; OnPropertyChanged(nameof(ColumnWidth17)); } + } + + private GridLength _columnWidth18; + public GridLength ColumnWidth18 + { + get => _columnWidth18; + set { _columnWidth18 = value; OnPropertyChanged(nameof(ColumnWidth18)); } + } + + private GridLength _columnWidth19; + public GridLength ColumnWidth19 + { + get => _columnWidth19; + set { _columnWidth19 = value; OnPropertyChanged(nameof(ColumnWidth19)); } + } + + /// + /// Calculates the maximum required width for each column (including header text) + /// and assigns the value (with a little extra padding) to the corresponding property. + /// It should always run once ALL the data have been added to the ObservableCollection that is the ItemsSource of the ListView + /// And only after this method, the ItemsSource must be assigned to the ListView. + /// + internal void CalculateColumnWidths() + { + + // Measure header text widths first. + double maxWidth1 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("FileNameHeader/Text")); + double maxWidth2 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("TimeCreatedHeader/Text")); + double maxWidth3 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SignatureStatusHeader/Text")); + double maxWidth4 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("OriginalFileNameHeader/Text")); + double maxWidth5 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("InternalNameHeader/Text")); + double maxWidth6 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("FileDescriptionHeader/Text")); + double maxWidth7 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("ProductNameHeader/Text")); + double maxWidth8 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("FileVersionHeader/Text")); + double maxWidth9 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("PackageFamilyNameHeader/Text")); + double maxWidth10 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SHA256HashHeader/Text")); + double maxWidth11 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SHA1HashHeader/Text")); + double maxWidth12 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SigningScenarioHeader/Text")); + double maxWidth13 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("FilePathHeader/Text")); + double maxWidth14 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SHA1PageHashHeader/Text")); + double maxWidth15 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SHA256PageHashHeader/Text")); + double maxWidth16 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("HasWHQLSignerHeader/Text")); + double maxWidth17 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("FilePublishersHeader/Text")); + double maxWidth18 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("IsECCSignedHeader/Text")); + double maxWidth19 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("OpusDataHeader/Text")); + + // Iterate over all items to determine the widest string for each column. + foreach (FileIdentity item in AllowNewAppsStart.Instance.LocalFilesFileIdentities) + { + double w1 = ListViewUIHelpers.MeasureTextWidth(item.FileName); + if (w1 > maxWidth1) maxWidth1 = w1; + + double w2 = ListViewUIHelpers.MeasureTextWidth(item.TimeCreated.ToString()); + if (w2 > maxWidth2) maxWidth2 = w2; + + double w3 = ListViewUIHelpers.MeasureTextWidth(item.SignatureStatus.ToString()); + if (w3 > maxWidth3) maxWidth3 = w3; + + double w4 = ListViewUIHelpers.MeasureTextWidth(item.OriginalFileName); + if (w4 > maxWidth4) maxWidth4 = w4; + + double w5 = ListViewUIHelpers.MeasureTextWidth(item.InternalName); + if (w5 > maxWidth5) maxWidth5 = w5; + + double w6 = ListViewUIHelpers.MeasureTextWidth(item.FileDescription); + if (w6 > maxWidth6) maxWidth6 = w6; + + double w7 = ListViewUIHelpers.MeasureTextWidth(item.ProductName); + if (w7 > maxWidth7) maxWidth7 = w7; + + double w8 = ListViewUIHelpers.MeasureTextWidth(item.FileVersion?.ToString()); + if (w8 > maxWidth8) maxWidth8 = w8; + + double w9 = ListViewUIHelpers.MeasureTextWidth(item.PackageFamilyName); + if (w9 > maxWidth9) maxWidth9 = w9; + + double w10 = ListViewUIHelpers.MeasureTextWidth(item.SHA256Hash); + if (w10 > maxWidth10) maxWidth10 = w10; + + double w11 = ListViewUIHelpers.MeasureTextWidth(item.SHA1Hash); + if (w11 > maxWidth11) maxWidth11 = w11; + + double w12 = ListViewUIHelpers.MeasureTextWidth(item.SISigningScenario.ToString()); + if (w12 > maxWidth12) maxWidth12 = w12; + + double w13 = ListViewUIHelpers.MeasureTextWidth(item.FilePath); + if (w13 > maxWidth13) maxWidth13 = w13; + + double w14 = ListViewUIHelpers.MeasureTextWidth(item.SHA1PageHash); + if (w14 > maxWidth14) maxWidth14 = w14; + + double w15 = ListViewUIHelpers.MeasureTextWidth(item.SHA256PageHash); + if (w15 > maxWidth15) maxWidth15 = w15; + + double w16 = ListViewUIHelpers.MeasureTextWidth(item.HasWHQLSigner.ToString()); + if (w16 > maxWidth16) maxWidth16 = w16; + + double w17 = ListViewUIHelpers.MeasureTextWidth(item.FilePublishersToDisplay); + if (w17 > maxWidth17) maxWidth17 = w17; + + double w18 = ListViewUIHelpers.MeasureTextWidth(item.IsECCSigned.ToString()); + if (w18 > maxWidth18) maxWidth18 = w18; + + double w19 = ListViewUIHelpers.MeasureTextWidth(item.Opus); + if (w19 > maxWidth19) maxWidth19 = w19; + } + + // Set the column width properties. + ColumnWidth1 = new GridLength(maxWidth1); + ColumnWidth2 = new GridLength(maxWidth2); + ColumnWidth3 = new GridLength(maxWidth3); + ColumnWidth4 = new GridLength(maxWidth4); + ColumnWidth5 = new GridLength(maxWidth5); + ColumnWidth6 = new GridLength(maxWidth6); + ColumnWidth7 = new GridLength(maxWidth7); + ColumnWidth8 = new GridLength(maxWidth8); + ColumnWidth9 = new GridLength(maxWidth9); + ColumnWidth10 = new GridLength(maxWidth10); + ColumnWidth11 = new GridLength(maxWidth11); + ColumnWidth12 = new GridLength(maxWidth12); + ColumnWidth13 = new GridLength(maxWidth13); + ColumnWidth14 = new GridLength(maxWidth14); + ColumnWidth15 = new GridLength(maxWidth15); + ColumnWidth16 = new GridLength(maxWidth16); + ColumnWidth17 = new GridLength(maxWidth17); + ColumnWidth18 = new GridLength(maxWidth18); + ColumnWidth19 = new GridLength(maxWidth19); + } + + + + /// + /// Copies the selected rows to the clipboard in a formatted manner, with each property labeled for clarity. + /// + /// The event sender. + /// The event arguments. + private void ListViewFlyoutMenuCopy_Click(object sender, RoutedEventArgs e) + { + // Check if there are selected items in the ListView + if (FileIdentitiesListView.SelectedItems.Count > 0) + { + // Initialize StringBuilder to store all selected rows' data with labels + StringBuilder dataBuilder = new(); + + // Loop through each selected item in the ListView + foreach (var selectedItem in FileIdentitiesListView.SelectedItems) + { + + if (selectedItem is FileIdentity obj) + + // Append each row's formatted data to the StringBuilder + _ = dataBuilder.AppendLine(ListViewUIHelpers.ConvertRowToText(obj)); + + // Add a separator between rows for readability in multi-row copies + _ = dataBuilder.AppendLine(new string('-', 50)); + } + + // Create a DataPackage to hold the text data + DataPackage dataPackage = new(); + + // Set the formatted text as the content of the DataPackage + dataPackage.SetText(dataBuilder.ToString()); + + // Copy the DataPackage content to the clipboard + Clipboard.SetContent(dataPackage); + } + } + + + // Click event handlers for each property + private void CopyFileName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FileName); + private void CopySignatureStatus_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SignatureStatus.ToString()); + private void CopyOriginalFileName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.OriginalFileName); + private void CopyInternalName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.InternalName); + private void CopyFileDescription_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FileDescription); + private void CopyProductName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.ProductName); + private void CopyFileVersion_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FileVersion?.ToString()); + private void CopyPackageFamilyName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.PackageFamilyName); + private void CopySHA256Hash_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SHA256Hash); + private void CopySHA1Hash_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SHA1Hash); + private void CopySigningScenario_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SISigningScenario.ToString()); + private void CopyFilePath_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FilePath); + private void CopySHA1PageHash_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SHA1PageHash); + private void CopySHA256PageHash_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SHA256PageHash); + private void CopyHasWHQLSigner_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.HasWHQLSigner.ToString()); + private void CopyFilePublishers_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FilePublishersToDisplay); + private void CopyIsECCSigned_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.IsECCSigned.ToString()); + private void CopyOpusData_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.Opus); + + /// + /// Helper method to copy a specified property to clipboard without reflection + /// + /// Function that retrieves the desired property value as a string + private void CopyToClipboard(Func getProperty) + { + if (FileIdentitiesListView.SelectedItem is FileIdentity selectedItem) + { + string? propertyValue = getProperty(selectedItem); + if (propertyValue is not null) + { + DataPackage dataPackage = new(); + dataPackage.SetText(propertyValue); + Clipboard.SetContent(dataPackage); + } + } + } + + // Event handlers for each sort button + private void ColumnSortingButton_FileName_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.FileName); + } + private void ColumnSortingButton_SignatureStatus_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.SignatureStatus); + } + private void ColumnSortingButton_OriginalFileName_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.OriginalFileName); + } + private void ColumnSortingButton_InternalName_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.InternalName); + } + private void ColumnSortingButton_FileDescription_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.FileDescription); + } + private void ColumnSortingButton_ProductName_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.ProductName); + } + private void ColumnSortingButton_FileVersion_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.FileVersion); + } + private void ColumnSortingButton_PackageFamilyName_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.PackageFamilyName); + } + private void ColumnSortingButton_SHA256Hash_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.SHA256Hash); + } + private void ColumnSortingButton_SHA1Hash_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.SHA1Hash); + } + private void ColumnSortingButton_SigningScenario_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.SISigningScenario); + } + private void ColumnSortingButton_FilePath_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.FilePath); + } + private void ColumnSortingButton_SHA1PageHash_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.SHA1PageHash); + } + private void ColumnSortingButton_SHA256PageHash_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.SHA256PageHash); + } + private void ColumnSortingButton_HasWHQLSigner_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.HasWHQLSigner); + } + private void ColumnSortingButton_FilePublishers_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.FilePublishersToDisplay); + } + private void ColumnSortingButton_IsECCSigned_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.IsECCSigned); + } + private void ColumnSortingButton_OpusData_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.Opus); + } + + /// + /// Performs data sorting + /// + /// + /// + private void SortColumn(Func keySelector) + { + // Determine if a search filter is active. + bool isSearchEmpty = string.IsNullOrWhiteSpace(SearchBox.Text); + // Use either the full list (AllowNewAppsStart.Instance.LocalFilesAllFileIdentities) or the current display list. + var collectionToSort = isSearchEmpty ? AllowNewAppsStart.Instance.LocalFilesAllFileIdentities : [.. AllowNewAppsStart.Instance.LocalFilesFileIdentities]; + + if (SortingDirectionToggle.IsChecked) + { + // Sort in descending order. + AllowNewAppsStart.Instance.LocalFilesFileIdentities = [.. collectionToSort.OrderByDescending(keySelector)]; + } + else + { + // Sort in ascending order. + AllowNewAppsStart.Instance.LocalFilesFileIdentities = [.. collectionToSort.OrderBy(keySelector)]; + } + + // Refresh the ItemsSource so the UI updates. + FileIdentitiesListView.ItemsSource = AllowNewAppsStart.Instance.LocalFilesFileIdentities; + } + + + /// + /// Converts the properties of a FileIdentity row into a labeled, formatted string for copying to clipboard. + /// + /// The selected FileIdentity row from the ListView. + /// A formatted string of the row's properties with labels. + private static string ConvertRowToText(FileIdentity row) + { + // Use StringBuilder to format each property with its label for easy reading + return new StringBuilder() + .AppendLine($"File Name: {row.FileName}") + .AppendLine($"Time Created: {row.TimeCreated}") + .AppendLine($"Signature Status: {row.SignatureStatus}") + .AppendLine($"Action: {row.Action}") + .AppendLine($"Original File Name: {row.OriginalFileName}") + .AppendLine($"Internal Name: {row.InternalName}") + .AppendLine($"File Description: {row.FileDescription}") + .AppendLine($"Product Name: {row.ProductName}") + .AppendLine($"File Version: {row.FileVersion}") + .AppendLine($"Package Family Name: {row.PackageFamilyName}") + .AppendLine($"SHA256 Hash: {row.SHA256Hash}") + .AppendLine($"SHA1 Hash: {row.SHA1Hash}") + .AppendLine($"SHA256 Flat Hash: {row.SHA256FlatHash}") + .AppendLine($"SHA1 Flat Hash: {row.SHA1FlatHash}") + .AppendLine($"Signing Scenario: {row.SISigningScenario}") + .AppendLine($"File Path: {row.FilePath}") + .AppendLine($"Computer Name: {row.ComputerName}") + .AppendLine($"Policy GUID: {row.PolicyGUID}") + .AppendLine($"Policy Name: {row.PolicyName}") + .AppendLine($"File Publishers: {row.FilePublishersToDisplay}") + .ToString(); + } + + #endregion + public AllowNewAppsLocalFilesDataGrid() { this.InitializeComponent(); @@ -27,39 +500,35 @@ public AllowNewAppsLocalFilesDataGrid() // Assign this instance to the static field _instance = this; + UIListView = FileIdentitiesListView; } // Public property to access the singleton instance from other classes // It's okay it's nullable, null check will happen before accessing it - public static AllowNewAppsLocalFilesDataGrid? Instance => _instance; - + public static AllowNewAppsLocalFilesDataGrid Instance => _instance ?? throw new InvalidOperationException("AllowNewAppsLocalFilesDataGrid is not initialized"); #region - - // Without the following steps, when the user begins data fetching process and then navigates away from this page - // Upon arrival at this page again, the DataGrid loses its virtualization, causing the UI to hang for extended periods of time - // But after nullifying DataGrid's ItemsSource when page is navigated from and reassigning it when page is navigated to, - // We tackle that problem. Data will sill be stored in the ObservableCollection when page is not in focus, - // But DataGrid's source will pick them up only when page is navigated to. protected override void OnNavigatedTo(NavigationEventArgs e) { base.OnNavigatedTo(e); - FileIdentitiesDataGrid.ItemsSource = AllowNewAppsStart.Instance.LocalFilesFileIdentities; + FileIdentitiesListView.ItemsSource = AllowNewAppsStart.Instance.LocalFilesFileIdentities; // Update the logs when user switches to this page UpdateTotalLogs(); - } - protected override void OnNavigatedFrom(NavigationEventArgs e) - { - base.OnNavigatedFrom(e); - FileIdentitiesDataGrid.ItemsSource = null; - } + // Assign the ItemsSource of the ListView only once + // We cannot do it after column width calculation because initialization is not guaranteed at that moment + if (AllowNewAppsStart.Instance.EventLogsDataProcessed) + { + CalculateColumnWidths(); + FileIdentitiesListView.ItemsSource = AllowNewAppsStart.Instance.LocalFilesFileIdentities; + AllowNewAppsStart.Instance.EventLogsDataProcessed = false; + } + } #endregion - /// /// Event handler for the SearchBox text change /// @@ -68,7 +537,6 @@ private void SearchBox_TextChanged(object sender, TextChangedEventArgs e) ApplyFilters(); } - /// /// Applies the date and search filters to the data grid /// @@ -109,20 +577,19 @@ private void ApplyFilters() AllowNewAppsStart.Instance.LocalFilesFileIdentities.Clear(); // Populate the ObservableCollection with the filtered results - // This triggers the UI to update the DataGrid based on the filtered data + // This triggers the UI to update the ListView based on the filtered data foreach (FileIdentity result in filteredResults) { AllowNewAppsStart.Instance.LocalFilesFileIdentities.Add(result); } - // Explicitly set the DataGrid's ItemsSource to ensure the data refreshes - FileIdentitiesDataGrid.ItemsSource = AllowNewAppsStart.Instance.LocalFilesFileIdentities; + // Explicitly set the ListView's ItemsSource to ensure the data refreshes + FileIdentitiesListView.ItemsSource = AllowNewAppsStart.Instance.LocalFilesFileIdentities; // Update any visual or text element showing the total logs count UpdateTotalLogs(); } - /// /// Event handler for the Clear Data button /// @@ -136,144 +603,8 @@ private void ClearDataButton_Click(object sender, RoutedEventArgs e) UpdateTotalLogs(true); } - - - // https://learn.microsoft.com/en-us/windows/communitytoolkit/controls/datagrid_guidance/group_sort_filter - // Column sorting logic for the entire DataGrid - private void FileIdentitiesDataGrid_Sorting(object sender, DataGridColumnEventArgs e) - { - // Sort the column based on its tag and current sort direction - if (string.Equals(e.Column.Tag?.ToString(), "FileName", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.FileName); - } - else if (string.Equals(e.Column.Tag?.ToString(), "SignatureStatus", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.SignatureStatus); - } - else if (string.Equals(e.Column.Tag?.ToString(), "Action", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.Action); - } - else if (string.Equals(e.Column.Tag?.ToString(), "OriginalFileName", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.OriginalFileName); - } - else if (string.Equals(e.Column.Tag?.ToString(), "InternalName", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.InternalName); - } - else if (string.Equals(e.Column.Tag?.ToString(), "FileDescription", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.FileDescription); - } - else if (string.Equals(e.Column.Tag?.ToString(), "ProductName", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.ProductName); - } - else if (string.Equals(e.Column.Tag?.ToString(), "FileVersion", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.FileVersion); - } - else if (string.Equals(e.Column.Tag?.ToString(), "PackageFamilyName", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.PackageFamilyName); - } - else if (string.Equals(e.Column.Tag?.ToString(), "SHA256Hash", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.SHA256Hash); - } - else if (string.Equals(e.Column.Tag?.ToString(), "SHA1Hash", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.SHA1Hash); - } - else if (string.Equals(e.Column.Tag?.ToString(), "SHA256FlatHash", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.SHA256FlatHash); - } - else if (string.Equals(e.Column.Tag?.ToString(), "SHA1FlatHash", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.SHA1FlatHash); - } - else if (string.Equals(e.Column.Tag?.ToString(), "SISigningScenario", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.SISigningScenario); - } - else if (string.Equals(e.Column.Tag?.ToString(), "FilePath", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.FilePath); - } - else if (string.Equals(e.Column.Tag?.ToString(), "SHA1PageHash", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.SHA1PageHash); - } - else if (string.Equals(e.Column.Tag?.ToString(), "SHA256PageHash", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.SHA256PageHash); - } - else if (string.Equals(e.Column.Tag?.ToString(), "HasWHQLSigner", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.HasWHQLSigner); - } - else if (string.Equals(e.Column.Tag?.ToString(), "FilePublishersToDisplay", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.FilePublishersToDisplay); - } - else if (string.Equals(e.Column.Tag?.ToString(), "IsECCSigned", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.IsECCSigned); - } - - // Clear SortDirection for other columns - foreach (DataGridColumn column in FileIdentitiesDataGrid.Columns) - { - if (column != e.Column) - { - column.SortDirection = null; - } - } - } - - /// - /// Helper method for sorting any column on the DataGird - /// - /// - /// - /// - private void SortColumn(DataGridColumnEventArgs e, Func keySelector) - { - // Check if the search box is empty or not - bool isSearchEmpty = string.IsNullOrWhiteSpace(SearchBox.Text); - - // Get the collection to sort based on the search box status - // Allowing us to sort only the items in the search results - List collectionToSort = isSearchEmpty ? AllowNewAppsStart.Instance.LocalFilesAllFileIdentities : [.. AllowNewAppsStart.Instance.LocalFilesFileIdentities]; - - // Perform the sorting based on the current SortDirection (ascending or descending) - if (e.Column.SortDirection is null || e.Column.SortDirection == DataGridSortDirection.Ascending) - { - // Descending: custom order depending on column type - AllowNewAppsStart.Instance.LocalFilesFileIdentities = [.. collectionToSort.OrderByDescending(keySelector)]; - - // Set the column direction to Descending - e.Column.SortDirection = DataGridSortDirection.Descending; - } - else - { - // Ascending: custom order depending on column type - AllowNewAppsStart.Instance.LocalFilesFileIdentities = [.. collectionToSort.OrderBy(keySelector)]; - e.Column.SortDirection = DataGridSortDirection.Ascending; - } - - // Update the ItemsSource of the DataGrid - // Required for sort + search to work properly, even though binding to the ObservableCollection already happens in XAML - FileIdentitiesDataGrid.ItemsSource = AllowNewAppsStart.Instance.LocalFilesFileIdentities; - } - - - /// - /// Selects all of the displayed rows on the DataGrid + /// Selects all of the displayed rows on the ListView /// /// /// @@ -282,29 +613,26 @@ private void SelectAll_Click(object sender, RoutedEventArgs e) _ = DispatcherQueue.TryEnqueue(() => { // Clear existing selections - FileIdentitiesDataGrid.SelectedItems.Clear(); + FileIdentitiesListView.SelectedItems.Clear(); foreach (FileIdentity fileIdentity in AllowNewAppsStart.Instance.LocalFilesFileIdentities) { - _ = FileIdentitiesDataGrid.SelectedItems.Add(fileIdentity); // Select each item + FileIdentitiesListView.SelectedItems.Add(fileIdentity); // Select each item } }); } - /// - /// De-selects all of the displayed rows on the DataGrid + /// De-selects all of the displayed rows on the ListView /// /// /// private void DeSelectAll_Click(object sender, RoutedEventArgs e) { - FileIdentitiesDataGrid.SelectedItems.Clear(); // Deselect all rows by clearing SelectedItems + FileIdentitiesListView.SelectedItems.Clear(); // Deselect all rows by clearing SelectedItems } - - /// /// Deletes the selected row from the results /// @@ -313,7 +641,7 @@ private void DeSelectAll_Click(object sender, RoutedEventArgs e) private void DataGridFlyoutMenuDelete_Click(object sender, RoutedEventArgs e) { // Collect the selected items to delete - List itemsToDelete = [.. FileIdentitiesDataGrid.SelectedItems.Cast()]; + List itemsToDelete = [.. FileIdentitiesListView.SelectedItems.Cast()]; // Remove each selected item from the FileIdentities collection foreach (FileIdentity item in itemsToDelete) @@ -325,179 +653,6 @@ private void DataGridFlyoutMenuDelete_Click(object sender, RoutedEventArgs e) UpdateTotalLogs(); } - - - /// - /// Copies the selected rows to the clipboard in a formatted manner, with each property labeled for clarity. - /// - /// The event sender. - /// The event arguments. - private void DataGridFlyoutMenuCopy_Click(object sender, RoutedEventArgs e) - { - // Check if there are selected items in the DataGrid - if (FileIdentitiesDataGrid.SelectedItems.Count > 0) - { - // Initialize StringBuilder to store all selected rows' data with labels - StringBuilder dataBuilder = new(); - - // Loop through each selected item in the DataGrid - foreach (FileIdentity selectedItem in FileIdentitiesDataGrid.SelectedItems) - { - // Append each row's formatted data to the StringBuilder - _ = dataBuilder.AppendLine(ConvertRowToText(selectedItem)); - - // Add a separator between rows for readability in multi-row copies - _ = dataBuilder.AppendLine(new string('-', 50)); - } - - // Create a DataPackage to hold the text data - DataPackage dataPackage = new(); - - // Set the formatted text as the content of the DataPackage - dataPackage.SetText(dataBuilder.ToString()); - - // Copy the DataPackage content to the clipboard - Clipboard.SetContent(dataPackage); - } - } - - /// - /// Converts the properties of a FileIdentity row into a labeled, formatted string for copying to clipboard. - /// - /// The selected FileIdentity row from the DataGrid. - /// A formatted string of the row's properties with labels. - private static string ConvertRowToText(FileIdentity row) - { - // Use StringBuilder to format each property with its label for easy reading - return new StringBuilder() - .AppendLine($"File Name: {row.FileName}") - .AppendLine($"Signature Status: {row.SignatureStatus}") - .AppendLine($"Action: {row.Action}") - .AppendLine($"Original File Name: {row.OriginalFileName}") - .AppendLine($"Internal Name: {row.InternalName}") - .AppendLine($"File Description: {row.FileDescription}") - .AppendLine($"Product Name: {row.ProductName}") - .AppendLine($"File Version: {row.FileVersion}") - .AppendLine($"Package Family Name: {row.PackageFamilyName}") - .AppendLine($"SHA256 Hash: {row.SHA256Hash}") - .AppendLine($"SHA1 Hash: {row.SHA1Hash}") - .AppendLine($"SHA256 Flat Hash: {row.SHA256FlatHash}") - .AppendLine($"SHA1 Flat Hash: {row.SHA1FlatHash}") - .AppendLine($"Signing Scenario: {row.SISigningScenario}") - .AppendLine($"File Path: {row.FilePath}") - .AppendLine($"SHA1 Page Hash: {row.SHA1PageHash}") - .AppendLine($"SHA256 Page Hash: {row.SHA256PageHash}") - .AppendLine($"Has WHQL Signer: {row.HasWHQLSigner}") - .AppendLine($"File Publishers: {row.FilePublishersToDisplay}") - .AppendLine($"Is ECC Signed: {row.IsECCSigned}") - .ToString(); - } - - - - /// - /// Event handler for the Copy Individual Items SubMenu. It will populate the submenu items in the flyout of the data grid. - /// - /// - /// - private void FileIdentitiesDataGrid_Loaded(object sender, RoutedEventArgs e) - { - // Ensure the CopyIndividualItemsSubMenu is available - if (CopyIndividualItemsSubMenu is null) - { - return; - } - - // Clear any existing items to avoid duplication if reloaded - CopyIndividualItemsSubMenu.Items.Clear(); - - // Create a dictionary to map headers to their specific click event methods - Dictionary copyActions = new() - { - { "File Name", CopyFileName_Click }, - { "Signature Status", CopySignatureStatus_Click }, - { "Action", CopyAction_Click }, - { "Original File Name", CopyOriginalFileName_Click }, - { "Internal Name", CopyInternalName_Click }, - { "File Description", CopyFileDescription_Click }, - { "Product Name", CopyProductName_Click }, - { "File Version", CopyFileVersion_Click }, - { "Package Family Name", CopyPackageFamilyName_Click }, - { "SHA256 Hash", CopySHA256Hash_Click }, - { "SHA1 Hash", CopySHA1Hash_Click }, - { "SHA256 Flat Hash", CopySHA256FlatHash_Click }, - { "SHA1 Flat Hash", CopySHA1FlatHash_Click }, - { "Signing Scenario", CopySigningScenario_Click }, - { "File Path", CopyFilePath_Click }, - { "SHA1 Page Hash", CopySHA1PageHash_Click }, - { "SHA256 Page Hash", CopySHA256PageHash_Click }, - { "Has WHQL Signer", CopyHasWHQLSigner_Click }, - { "File Publishers", CopyFilePublishersToDisplay_Click }, - { "Is ECC Signed", CopyIsECCSigned_Click } - }; - - // Add menu items with specific click events for each column - foreach (DataGridColumn column in FileIdentitiesDataGrid.Columns) - { - string headerText = column.Header.ToString()!; - - if (copyActions.TryGetValue(headerText, out RoutedEventHandler? value)) - { - // Create a new MenuFlyout Item - MenuFlyoutItem menuItem = new() { Text = $"Copy {headerText}" }; - - // Set the click event for the menu item - menuItem.Click += value; - - // Add the menu item to the submenu - CopyIndividualItemsSubMenu.Items.Add(menuItem); - } - } - } - - // Click event handlers for each property - private void CopyFileName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FileName); - private void CopySignatureStatus_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SignatureStatus.ToString()); - private void CopyAction_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.Action.ToString()); - private void CopyOriginalFileName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.OriginalFileName); - private void CopyInternalName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.InternalName); - private void CopyFileDescription_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FileDescription); - private void CopyProductName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.ProductName); - private void CopyFileVersion_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FileVersion?.ToString()); - private void CopyPackageFamilyName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.PackageFamilyName); - private void CopySHA256Hash_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SHA256Hash); - private void CopySHA1Hash_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SHA1Hash); - private void CopySHA256FlatHash_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SHA256FlatHash); - private void CopySHA1FlatHash_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SHA1FlatHash); - private void CopySigningScenario_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SISigningScenario.ToString()); - private void CopyFilePath_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FilePath); - private void CopySHA1PageHash_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SHA1PageHash); - private void CopySHA256PageHash_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SHA256PageHash); - private void CopyHasWHQLSigner_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.HasWHQLSigner.ToString()); - private void CopyFilePublishersToDisplay_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FilePublishersToDisplay.ToString()); - private void CopyIsECCSigned_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.IsECCSigned.ToString()); - - - /// - /// Helper method to copy a specified property to clipboard without reflection - /// - /// Function that retrieves the desired property value as a string - private void CopyToClipboard(Func getProperty) - { - if (FileIdentitiesDataGrid.SelectedItem is FileIdentity selectedItem) - { - string? propertyValue = getProperty(selectedItem); - if (propertyValue is not null) - { - DataPackage dataPackage = new(); - dataPackage.SetText(propertyValue); - Clipboard.SetContent(dataPackage); - } - } - } - - - /// /// Updates the total logs count displayed on the UI /// @@ -517,9 +672,5 @@ internal void UpdateTotalLogs(bool? Zero = null) // Update the InfoBadge for the top menu AllowNewApps.Instance.UpdateLocalFilesInfoBadge(AllowNewAppsStart.Instance.LocalFilesFileIdentities.Count, 1); } - - } - - } diff --git a/AppControl Manager/Pages/AllowNewApps/AllowNewAppsStart.xaml.cs b/AppControl Manager/Pages/AllowNewApps/AllowNewAppsStart.xaml.cs index df58c10c4..14773dbb2 100644 --- a/AppControl Manager/Pages/AllowNewApps/AllowNewAppsStart.xaml.cs +++ b/AppControl Manager/Pages/AllowNewApps/AllowNewAppsStart.xaml.cs @@ -12,6 +12,7 @@ using AppControlManager.SiPolicy; using AppControlManager.SiPolicyIntel; using AppControlManager.XMLOps; +using CommunityToolkit.WinUI; using Microsoft.UI; using Microsoft.UI.Input; using Microsoft.UI.Xaml; @@ -25,6 +26,9 @@ namespace AppControlManager.Pages; public sealed partial class AllowNewAppsStart : Page, Sidebar.IAnimatedIconsManager { + internal bool EventLogsDataProcessed; + internal bool LocalFilesDataProcessed; + // The user selected XML base policy path internal string? selectedXMLFilePath; @@ -60,7 +64,7 @@ public sealed partial class AllowNewAppsStart : Page, Sidebar.IAnimatedIconsMana #region - // To store the FileIdentities displayed on the Local Files DataGrid + // To store the FileIdentities displayed on the Local Files ListView internal ObservableCollection LocalFilesFileIdentities { get; set; } // Store all outputs for searching, used as a temporary storage for filtering @@ -69,7 +73,7 @@ public sealed partial class AllowNewAppsStart : Page, Sidebar.IAnimatedIconsMana internal List LocalFilesAllFileIdentities; - // To store the FileIdentities displayed on the Event Logs DataGrid + // To store the FileIdentities displayed on the Event Logs ListView internal ObservableCollection EventLogsFileIdentities { get; set; } // Store all outputs for searching, used as a temporary storage for filtering @@ -127,7 +131,6 @@ public AllowNewAppsStart() LogSize = Convert.ToUInt64(currentLogSize); } - // Public property to access the singleton instance from other classes public static AllowNewAppsStart Instance => _instance ?? throw new InvalidOperationException("AllowNewAppsStart is not initialized."); @@ -384,11 +387,11 @@ await Task.Run(() => if (!_IsSignedPolicy) { // Create audit mode CIP - CiRuleOptions.Set(filePath: tempBasePolicyPath, rulesToAdd: [SiPolicy.OptionType.EnabledAuditMode]); + CiRuleOptions.Set(filePath: tempBasePolicyPath, rulesToAdd: [OptionType.EnabledAuditMode]); PolicyToCIPConverter.Convert(tempBasePolicyPath, AuditModeCIP); // Create Enforced mode CIP - CiRuleOptions.Set(filePath: tempBasePolicyPath, rulesToRemove: [SiPolicy.OptionType.EnabledAuditMode]); + CiRuleOptions.Set(filePath: tempBasePolicyPath, rulesToRemove: [OptionType.EnabledAuditMode]); PolicyToCIPConverter.Convert(tempBasePolicyPath, EnforcedModeCIP); } @@ -397,7 +400,7 @@ await Task.Run(() => { // Create audit mode CIP - CiRuleOptions.Set(filePath: tempBasePolicyPath, rulesToAdd: [SiPolicy.OptionType.EnabledAuditMode], rulesToRemove: [SiPolicy.OptionType.EnabledUnsignedSystemIntegrityPolicy]); + CiRuleOptions.Set(filePath: tempBasePolicyPath, rulesToAdd: [OptionType.EnabledAuditMode], rulesToRemove: [OptionType.EnabledUnsignedSystemIntegrityPolicy]); string CIPp7SignedFilePathAudit = Path.Combine(stagingArea.FullName, "BaseAudit.cip.p7"); @@ -410,10 +413,8 @@ await Task.Run(() => // Rename the .p7 signed file to .cip File.Move(CIPp7SignedFilePathAudit, AuditModeCIP, true); - - // Create Enforced mode CIP - CiRuleOptions.Set(filePath: tempBasePolicyPath, rulesToRemove: [SiPolicy.OptionType.EnabledAuditMode, SiPolicy.OptionType.EnabledUnsignedSystemIntegrityPolicy]); + CiRuleOptions.Set(filePath: tempBasePolicyPath, rulesToRemove: [OptionType.EnabledAuditMode, OptionType.EnabledUnsignedSystemIntegrityPolicy]); string CIPp7SignedFilePathEnforced = Path.Combine(stagingArea.FullName, "BaseAuditTemp.cip.p7"); @@ -430,7 +431,6 @@ await Task.Run(() => } - Logger.Write("Creating Enforced Mode SnapBack guarantee"); SnapBackGuarantee.Create(EnforcedModeCIP); @@ -443,7 +443,6 @@ await Task.Run(() => }); - DisableStep1(); EnableStep2(); DisableStep3(); @@ -497,13 +496,13 @@ private async void GoToStep3Button_Click(object sender, RoutedEventArgs e) // While the base policy is being deployed is audit mode, set the progress ring as indeterminate Step2ProgressRing.IsIndeterminate = true; - // Enable the DataGrid pages so user can select the logs + // Enable the ListView pages so user can select the logs AllowNewApps.Instance.EnableAllowNewAppsNavigationItem("LocalFiles"); AllowNewApps.Instance.EnableAllowNewAppsNavigationItem("EventLogs"); Step2InfoBar.IsOpen = true; - await Task.Run(() => + await Task.Run(async () => { // Deploy the base policy in enforced mode before proceeding with scans @@ -512,7 +511,6 @@ await Task.Run(() => throw new InvalidOperationException("Enforced mode CIP file could not be found"); } - _ = DispatcherQueue.TryEnqueue(() => { Step2InfoBar.Message = "Deploying the Enforced mode policy."; @@ -540,7 +538,6 @@ await Task.Run(() => Step2ProgressRing.IsIndeterminate = false; }); - DirectoryInfo[] selectedDirectories = []; // Convert user selected folder paths that are strings to DirectoryInfo objects @@ -564,7 +561,7 @@ await Task.Run(() => // Scan all of the detected files from the user selected directories HashSet LocalFilesResults = LocalFilesScan.Scan(DetectedFilesInSelectedDirectories, 2, null, Step2ProgressRing); - // Add the results of the directories scans to the DataGrid + // Add the results of the directories scans to the ListView foreach (FileIdentity item in LocalFilesResults) { _ = DispatcherQueue.TryEnqueue(() => @@ -574,6 +571,24 @@ await Task.Run(() => }); } + + await DispatcherQueue.EnqueueAsync(() => + { + // If the ListView page is loaded and user is on that page at this moment then calculate the column widths assign ItemsSource for ListView here + if (Equals(MainWindow.Instance.AppFrame.CurrentSourcePageType, typeof(AllowNewAppsLocalFilesDataGrid))) + { + LocalFilesDataProcessed = false; + + AllowNewAppsLocalFilesDataGrid.Instance.CalculateColumnWidths(); + AllowNewAppsLocalFilesDataGrid.Instance.UIListView.ItemsSource = LocalFilesFileIdentities; + } + else + { + // Set it to true so ListView will be updated once user navigated to the page + LocalFilesDataProcessed = true; + } + }); + } } }); @@ -610,12 +625,29 @@ await Task.Run(() => if (Output.Count > 0) { - // Add the event logs to the DataGrid + // Add the event logs to the ListView foreach (FileIdentity item in Output) { EventLogsFileIdentities.Add(item); EventLogsAllFileIdentities.Add(item); } + + await DispatcherQueue.EnqueueAsync(() => + { + // If the ListView page is loaded and user is on that page at this moment then calculate the column widths assign ItemsSource for ListView here + if (Equals(MainWindow.Instance.AppFrame.CurrentSourcePageType, typeof(AllowNewAppsEventLogsDataGrid))) + { + EventLogsDataProcessed = false; + + AllowNewAppsEventLogsDataGrid.Instance.CalculateColumnWidths(); + AllowNewAppsEventLogsDataGrid.Instance.UIListView.ItemsSource = EventLogsFileIdentities; + } + else + { + // Set it to true so ListView will be updated once user navigated to the page + EventLogsDataProcessed = true; + } + }); } // Update the total logs on that page once we add data to it from here @@ -626,7 +658,6 @@ await Task.Run(() => // Update the InfoBadge for the top menu AllowNewApps.Instance.UpdateEventLogsInfoBadge(EventLogsFileIdentities.Count, 1); - DisableStep1(); DisableStep2(); EnableStep3(); @@ -674,7 +705,7 @@ private async void ResetStepsButton_Click(object sender, RoutedEventArgs e) DisableStep2(); DisableStep3(); - // Clear the DataGrids and their respective search/filter-related lists + // Clear the ListViews and their respective search/filter-related lists LocalFilesFileIdentities.Clear(); LocalFilesAllFileIdentities.Clear(); EventLogsFileIdentities.Clear(); @@ -728,7 +759,6 @@ await Task.Run(() => SnapBackGuarantee.Remove(); }); - } finally { @@ -740,7 +770,6 @@ await Task.Run(() => } - private void ClearSelectedDirectoriesButton_Click(object sender, RoutedEventArgs e) { // Clear the text box on the UI @@ -757,14 +786,12 @@ private void DeployToggleButton_Checked(object sender, RoutedEventArgs e) } - private void DeployToggleButton_Unchecked(object sender, RoutedEventArgs e) { deployPolicy = false; } - private void ScanLevelComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (ScanLevelComboBox.SelectedItem is ComboBoxItem selectedItem) @@ -781,7 +808,6 @@ private void ScanLevelComboBox_SelectionChanged(object sender, SelectionChangedE private void BrowseForFoldersButton_Click(object sender, RoutedEventArgs e) { - List? selectedFolders = FileDialogHelper.ShowMultipleDirectoryPickerDialog(); if (selectedFolders is { Count: > 0 }) @@ -802,7 +828,6 @@ private void BrowseForFoldersButton_Click(object sender, RoutedEventArgs e) private void BrowseForXMLPolicyButton_Click(object sender, RoutedEventArgs e) { - string? selectedFile = FileDialogHelper.ShowFilePickerDialog(GlobalVars.XMLFilePickerFilter); if (!string.IsNullOrWhiteSpace(selectedFile)) @@ -821,7 +846,6 @@ private void BrowseForXMLPolicyButton_Click(object sender, RoutedEventArgs e) throw new InvalidOperationException($"Selected item '{selectedFile}' is not a valid XML file path"); } } - } @@ -895,7 +919,7 @@ private async void CreatePolicyButton_Click(object sender, RoutedEventArgs e) Step3InfoBar.Message = "Creating the policy using any available event logs or file scan results in other tabs."; - // Check if there are items for the local file scans DataGrid + // Check if there are items for the local file scans ListView if (LocalFilesFileIdentities.Count > 0) { // convert every selected item to FileIdentity and store it in the list @@ -905,7 +929,7 @@ private async void CreatePolicyButton_Click(object sender, RoutedEventArgs e) } } - // Check if there are selected items for the Event Logs scan DataGrid + // Check if there are selected items for the Event Logs scan ListView if (EventLogsFileIdentities.Count > 0) { // convert every selected item to FileIdentity and store it in the list @@ -915,7 +939,6 @@ private async void CreatePolicyButton_Click(object sender, RoutedEventArgs e) } } - // If there are no logs to create a Supplemental policy with if (fileIdentities.Count is 0) { @@ -924,7 +947,6 @@ private async void CreatePolicyButton_Click(object sender, RoutedEventArgs e) return; } - await Task.Run(() => { @@ -954,7 +976,7 @@ await Task.Run(() => } else { - CiRuleOptions.Set(filePath: EmptyPolicyPath, template: CiRuleOptions.PolicyTemplate.Supplemental, rulesToRemove: [SiPolicy.OptionType.EnabledUnsignedSystemIntegrityPolicy]); + CiRuleOptions.Set(filePath: EmptyPolicyPath, template: CiRuleOptions.PolicyTemplate.Supplemental, rulesToRemove: [OptionType.EnabledUnsignedSystemIntegrityPolicy]); } // Set policy version @@ -998,7 +1020,6 @@ await Task.Run(() => }); - Step3InfoBar.Severity = InfoBarSeverity.Success; Step3InfoBar.IsClosable = true; Step3InfoBar.Message = deployPolicy ? "Successfully created and deployed the policy." : "Successfully created the policy."; @@ -1014,7 +1035,6 @@ await Task.Run(() => } } - /// /// Event handler for the LogSize number box /// diff --git a/AppControl Manager/Pages/CreateDenyPolicy.xaml.cs b/AppControl Manager/Pages/CreateDenyPolicy.xaml.cs index 57bcae2ee..311cc5e71 100644 --- a/AppControl Manager/Pages/CreateDenyPolicy.xaml.cs +++ b/AppControl Manager/Pages/CreateDenyPolicy.xaml.cs @@ -8,6 +8,7 @@ using AppControlManager.Main; using AppControlManager.Others; using AppControlManager.XMLOps; +using CommunityToolkit.WinUI; using CommunityToolkit.WinUI.Controls; using Microsoft.UI.Input; using Microsoft.UI.Xaml; @@ -59,10 +60,11 @@ public CreateDenyPolicy() private bool usingWildCardFilePathRules; - // Used to store the scan results and as the source for the results DataGrids + // Used to store the scan results and as the source for the results ListViews internal ObservableCollection filesAndFoldersScanResults = []; internal List filesAndFoldersScanResultsList = []; + internal bool filesAndFoldersDataProcessed; private void FilesAndFoldersBrowseForFilesSettingsCard_Holding(object sender, HoldingRoutedEventArgs e) { @@ -163,7 +165,7 @@ private async void CreateFilesAndFoldersDenyPolicyButton_Click(object sender, Ro FilesAndFoldersInfoBar.Message = msg1; Logger.Write(msg1); - // Clear variables responsible for the DataGrid + // Clear variables responsible for the ListView filesAndFoldersScanResultsList.Clear(); filesAndFoldersScanResults.Clear(); @@ -171,7 +173,7 @@ private async void CreateFilesAndFoldersDenyPolicyButton_Click(object sender, Ro ScalabilityRadialGauge.IsEnabled = false; - await Task.Run(() => + await Task.Run(async () => { DirectoryInfo[] selectedDirectories = []; @@ -225,7 +227,7 @@ await Task.Run(() => // Scan all of the detected files from the user selected directories LocalFilesResults = LocalFilesScan.Scan(DetectedFilesInSelectedDirectories, (ushort)radialGaugeValue, FilesAndFoldersProgressBar, null); - // Add the results of the directories scans to the DataGrid + // Add the results of the directories scans to the ListView foreach (FileIdentity item in LocalFilesResults) { _ = DispatcherQueue.TryEnqueue(() => @@ -237,6 +239,23 @@ await Task.Run(() => } + await DispatcherQueue.EnqueueAsync(() => + { + // If the ListView page is loaded and user is on that page at this moment then calculate the column widths assign ItemsSource for ListView here + if (Equals(MainWindow.Instance.AppFrame.CurrentSourcePageType, typeof(CreateDenyPolicyFilesAndFoldersScanResults))) + { + filesAndFoldersDataProcessed = false; + + CreateDenyPolicyFilesAndFoldersScanResults.Instance.CalculateColumnWidths(); + CreateDenyPolicyFilesAndFoldersScanResults.Instance.UIListView.ItemsSource = filesAndFoldersScanResults; + } + else + { + // Set it to true so ListView will be updated once user navigated to the page + filesAndFoldersDataProcessed = true; + } + }); + string msg3 = GlobalVars.Rizz.GetString("ScanCompleted"); Logger.Write(msg3); @@ -245,8 +264,6 @@ await Task.Run(() => { FilesAndFoldersInfoBar.Message = msg3; }); - - } DirectoryInfo stagingArea = StagingArea.NewStagingArea("FilesAndFoldersDenyPolicy"); @@ -295,8 +312,6 @@ await Task.Run(() => CiToolHelper.UpdatePolicy(CIPPath); } - - }); } @@ -333,7 +348,6 @@ await Task.Run(() => } } - /// /// Deploy policy Toggle Button /// @@ -344,7 +358,6 @@ private void FilesAndFoldersPolicyDeployToggleButton_Click(object sender, Routed filesAndFoldersDeployButton = ((ToggleButton)sender).IsChecked ?? false; } - /// /// Browse for Files - Settings Card Click /// @@ -481,7 +494,6 @@ private void ScanLevelComboBox_SelectionChanged(object sender, SelectionChangedE } - // For Wildcard file path rules, only folder paths should be used if (filesAndFoldersScanLevel is ScanLevels.WildCardFolderPath) { @@ -573,11 +585,9 @@ internal async Task> GetAppsList() return apps; }); - } - /// /// Event handler for the Refresh button to get the apps list /// @@ -597,7 +607,6 @@ private async void PFNRefreshAppsListButton_Click(object sender, RoutedEventArgs } } - /// /// Event handler for the touch-initiated refresh action /// @@ -617,7 +626,6 @@ private async void PFNRefreshContainer_RefreshRequested(RefreshContainer sender, } } - // Since we have a ScrollView around the page, it captures the mouse Scroll Wheel events. // We have to disable its scrolling ability while pointer is inside of the ListView. // Scrolling via touch or dragging the ListView's scrollbar via mouse doesn't require this and they work either way. @@ -647,7 +655,6 @@ private void MainScrollView_PointerPressed(object sender, PointerRoutedEventArgs } - // To create a collection of grouped items, create a query that groups // an existing list, or returns a grouped collection from a database. // The following method is used to create the ItemsSource for our CollectionViewSource that is defined in XAML @@ -673,7 +680,6 @@ orderby g.Key } - /// /// Event handler to select all apps in the ListView /// @@ -704,7 +710,6 @@ private void PFNRemoveSelectionAppsListButton_Click(object sender, RoutedEventAr } - /// /// Event handler to display the selected apps count on the UI TextBlock /// @@ -717,7 +722,6 @@ private void PFNPackagedAppsListView_SelectionChanged(object sender, SelectionCh } - // Used to store the original Apps collection so when we filter the results and then remove the filters, // We can still have access to the original collection of apps private ObservableCollection? _originalContacts; @@ -785,7 +789,6 @@ private async void PFNSettingsCard_Expanded(object sender, EventArgs e) } - /// /// Main button's event handler - Create Deny policy based on PFNs /// @@ -818,8 +821,6 @@ private async void CreatePFNDenyPolicyButton_Click(object sender, RoutedEventArg return; } - - bool ErrorsOccurred = false; try @@ -839,8 +840,6 @@ private async void CreatePFNDenyPolicyButton_Click(object sender, RoutedEventArg // A list to store the selected PackagedAppView items List selectedAppsPFNs = []; - - // Loop through the selected items foreach (var selectedItem in PFNPackagedAppsListView.SelectedItems) { @@ -851,8 +850,6 @@ private async void CreatePFNDenyPolicyButton_Click(object sender, RoutedEventArg } } - - await Task.Run(() => { @@ -903,11 +900,7 @@ await Task.Run(() => CiToolHelper.UpdatePolicy(CIPPath); } - - }); - - } catch (Exception ex) @@ -921,7 +914,6 @@ await Task.Run(() => } finally { - if (!ErrorsOccurred) { PFNInfoBar.Severity = InfoBarSeverity.Success; @@ -934,10 +926,7 @@ await Task.Run(() => PFNInfoBar.IsClosable = true; } - - } #endregion - } diff --git a/AppControl Manager/Pages/CreateDenyPolicyFilesAndFoldersScanResults.xaml b/AppControl Manager/Pages/CreateDenyPolicyFilesAndFoldersScanResults.xaml index abb2968f3..346f4e35c 100644 --- a/AppControl Manager/Pages/CreateDenyPolicyFilesAndFoldersScanResults.xaml +++ b/AppControl Manager/Pages/CreateDenyPolicyFilesAndFoldersScanResults.xaml @@ -8,7 +8,10 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" xmlns:controls="using:CommunityToolkit.WinUI.Controls" - xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls"> + xmlns:intelgathering="using:AppControlManager.IntelGathering" + xmlns:interactivity="using:Microsoft.Xaml.Interactivity" + xmlns:behaviors="using:CommunityToolkit.WinUI.Behaviors" + x:Name="CreateDenyPolicyFilesAndFoldersScanResultsXAML"> @@ -62,6 +65,43 @@ + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/AppControl Manager/Pages/CreateDenyPolicyFilesAndFoldersScanResults.xaml.cs b/AppControl Manager/Pages/CreateDenyPolicyFilesAndFoldersScanResults.xaml.cs index a208be56e..a659ab005 100644 --- a/AppControl Manager/Pages/CreateDenyPolicyFilesAndFoldersScanResults.xaml.cs +++ b/AppControl Manager/Pages/CreateDenyPolicyFilesAndFoldersScanResults.xaml.cs @@ -1,287 +1,269 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Linq; using System.Text; using AppControlManager.IntelGathering; -using CommunityToolkit.WinUI.UI.Controls; +using AppControlManager.Others; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Navigation; using Windows.ApplicationModel.DataTransfer; +using WinRT; namespace AppControlManager.Pages; -public sealed partial class CreateDenyPolicyFilesAndFoldersScanResults : Page +// Since the columns for data in the ItemTemplate use "Binding" instead of "x:Bind", we need to use [GeneratedBindableCustomProperty] for them to work properly +[GeneratedBindableCustomProperty] +public sealed partial class CreateDenyPolicyFilesAndFoldersScanResults : Page, INotifyPropertyChanged { - public CreateDenyPolicyFilesAndFoldersScanResults() - { - this.InitializeComponent(); - // Make sure navigating to/from this page maintains its state - this.NavigationCacheMode = NavigationCacheMode.Enabled; - } + // A static instance of the CreateDenyPolicyFilesAndFoldersScanResults class which will hold the single, shared instance of the page + private static CreateDenyPolicyFilesAndFoldersScanResults? _instance; + internal ListView UIListView { get; private set; } - #region + #region LISTVIEW IMPLEMENTATIONS - // Without the following steps, when the user begins data fetching process and then navigates away from this page - // Upon arrival at this page again, the DataGrid loses its virtualization, causing the UI to hang for extended periods of time - // But after nullifying DataGrid's ItemsSource when page is navigated from and reassigning it when page is navigated to, - // We tackle that problem. Data will sill be stored in the ObservableCollection when page is not in focus, - // But DataGrid's source will pick them up only when page is navigated to. - protected override void OnNavigatedTo(NavigationEventArgs e) + public event PropertyChangedEventHandler? PropertyChanged; + private void OnPropertyChanged(string propertyName) => + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + + // Properties to hold each columns' width. + private GridLength _columnWidth1; + public GridLength ColumnWidth1 { - base.OnNavigatedTo(e); - FileIdentitiesDataGrid.ItemsSource = CreateDenyPolicy.Instance.filesAndFoldersScanResults; + get => _columnWidth1; + set { _columnWidth1 = value; OnPropertyChanged(nameof(ColumnWidth1)); } + } - // Update the logs when user switches to this page - UpdateTotalFiles(); + private GridLength _columnWidth2; + public GridLength ColumnWidth2 + { + get => _columnWidth2; + set { _columnWidth2 = value; OnPropertyChanged(nameof(ColumnWidth2)); } } - protected override void OnNavigatedFrom(NavigationEventArgs e) + private GridLength _columnWidth3; + public GridLength ColumnWidth3 { - base.OnNavigatedFrom(e); - FileIdentitiesDataGrid.ItemsSource = null; + get => _columnWidth3; + set { _columnWidth3 = value; OnPropertyChanged(nameof(ColumnWidth3)); } } - #endregion + private GridLength _columnWidth4; + public GridLength ColumnWidth4 + { + get => _columnWidth4; + set { _columnWidth4 = value; OnPropertyChanged(nameof(ColumnWidth4)); } + } + private GridLength _columnWidth5; + public GridLength ColumnWidth5 + { + get => _columnWidth5; + set { _columnWidth5 = value; OnPropertyChanged(nameof(ColumnWidth5)); } + } - /// - /// Event handler for the SearchBox text change - /// - private void SearchBox_TextChanged(object sender, TextChangedEventArgs e) + private GridLength _columnWidth6; + public GridLength ColumnWidth6 { - ApplyFilters(); + get => _columnWidth6; + set { _columnWidth6 = value; OnPropertyChanged(nameof(ColumnWidth6)); } } + private GridLength _columnWidth7; + public GridLength ColumnWidth7 + { + get => _columnWidth7; + set { _columnWidth7 = value; OnPropertyChanged(nameof(ColumnWidth7)); } + } - /// - /// Applies the date and search filters to the data grid - /// - private void ApplyFilters() + private GridLength _columnWidth8; + public GridLength ColumnWidth8 { + get => _columnWidth8; + set { _columnWidth8 = value; OnPropertyChanged(nameof(ColumnWidth8)); } + } - // Get the search term from the SearchBox, converting it to lowercase for case-insensitive searching - string searchTerm = SearchBox.Text.Trim().ToLowerInvariant(); + private GridLength _columnWidth9; + public GridLength ColumnWidth9 + { + get => _columnWidth9; + set { _columnWidth9 = value; OnPropertyChanged(nameof(ColumnWidth9)); } + } - // Start with all items from the complete list, 'AllFileIdentities' - // This list is used as the base set for filtering to preserve original data - IEnumerable filteredResults = CreateDenyPolicy.Instance.filesAndFoldersScanResultsList.AsEnumerable(); + private GridLength _columnWidth10; + public GridLength ColumnWidth10 + { + get => _columnWidth10; + set { _columnWidth10 = value; OnPropertyChanged(nameof(ColumnWidth10)); } + } - // Apply the search filter if there is a non-empty search term - if (!string.IsNullOrWhiteSpace(searchTerm)) - { + private GridLength _columnWidth11; + public GridLength ColumnWidth11 + { + get => _columnWidth11; + set { _columnWidth11 = value; OnPropertyChanged(nameof(ColumnWidth11)); } + } - // Filter results further to match the search term across multiple properties, case-insensitively - filteredResults = filteredResults.Where(output => - (output.FileName is not null && output.FileName.Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) || - (output.SignatureStatus.ToString().Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) || - (output.OriginalFileName is not null && output.OriginalFileName.Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) || - (output.InternalName is not null && output.InternalName.Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) || - (output.FileDescription is not null && output.FileDescription.Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) || - (output.ProductName is not null && output.ProductName.Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) || - (output.FileVersion is not null && output.FileVersion.ToString().Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) || - (output.PackageFamilyName is not null && output.PackageFamilyName.Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) || - (output.SHA1PageHash is not null && output.SHA1PageHash.Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) || - (output.FilePath is not null && output.FilePath.Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) || - (output.SHA256Hash is not null && output.SHA256Hash.Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) || - output.FilePublishersToDisplay.Contains(searchTerm, StringComparison.OrdinalIgnoreCase) || - output.Opus.Contains(searchTerm, StringComparison.OrdinalIgnoreCase) - ); - } + private GridLength _columnWidth12; + public GridLength ColumnWidth12 + { + get => _columnWidth12; + set { _columnWidth12 = value; OnPropertyChanged(nameof(ColumnWidth12)); } + } - // Clear the current contents of the ObservableCollection - CreateDenyPolicy.Instance.filesAndFoldersScanResults.Clear(); + private GridLength _columnWidth13; + public GridLength ColumnWidth13 + { + get => _columnWidth13; + set { _columnWidth13 = value; OnPropertyChanged(nameof(ColumnWidth13)); } + } - // Populate the ObservableCollection with the filtered results - // This triggers the UI to update the DataGrid based on the filtered data - foreach (FileIdentity result in filteredResults) - { - CreateDenyPolicy.Instance.filesAndFoldersScanResults.Add(result); - } + private GridLength _columnWidth14; + public GridLength ColumnWidth14 + { + get => _columnWidth14; + set { _columnWidth14 = value; OnPropertyChanged(nameof(ColumnWidth14)); } + } + + private GridLength _columnWidth15; + public GridLength ColumnWidth15 + { + get => _columnWidth15; + set { _columnWidth15 = value; OnPropertyChanged(nameof(ColumnWidth15)); } + } - // Explicitly set the DataGrid's ItemsSource to ensure the data refreshes - FileIdentitiesDataGrid.ItemsSource = CreateDenyPolicy.Instance.filesAndFoldersScanResults; + private GridLength _columnWidth16; + public GridLength ColumnWidth16 + { + get => _columnWidth16; + set { _columnWidth16 = value; OnPropertyChanged(nameof(ColumnWidth16)); } + } - // Update any visual or text element showing the total logs count - UpdateTotalFiles(); + private GridLength _columnWidth17; + public GridLength ColumnWidth17 + { + get => _columnWidth17; + set { _columnWidth17 = value; OnPropertyChanged(nameof(ColumnWidth17)); } } + private GridLength _columnWidth18; + public GridLength ColumnWidth18 + { + get => _columnWidth18; + set { _columnWidth18 = value; OnPropertyChanged(nameof(ColumnWidth18)); } + } /// - /// Event handler for the Clear Data button + /// Calculates the maximum required width for each column (including header text) + /// and assigns the value (with a little extra padding) to the corresponding property. + /// It should always run once ALL the data have been added to the ObservableCollection that is the ItemsSource of the ListView + /// And only after this method, the ItemsSource must be assigned to the ListView. /// - /// - /// - private void ClearDataButton_Click(object sender, RoutedEventArgs e) + internal void CalculateColumnWidths() { - CreateDenyPolicy.Instance.filesAndFoldersScanResults.Clear(); - CreateDenyPolicy.Instance.filesAndFoldersScanResultsList.Clear(); - UpdateTotalFiles(true); - } + // Measure header text widths first. + double maxWidth1 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("FileNameHeader/Text")); + double maxWidth2 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SignatureStatusHeader/Text")); + double maxWidth3 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("OriginalFileNameHeader/Text")); + double maxWidth4 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("InternalNameHeader/Text")); + double maxWidth5 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("FileDescriptionHeader/Text")); + double maxWidth6 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("ProductNameHeader/Text")); + double maxWidth7 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("FileVersionHeader/Text")); + double maxWidth8 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("PackageFamilyNameHeader/Text")); + double maxWidth9 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SHA256HashHeader/Text")); + double maxWidth10 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SHA1HashHeader/Text")); + double maxWidth11 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SigningScenarioHeader/Text")); + double maxWidth12 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("FilePathHeader/Text")); + double maxWidth13 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SHA1PageHashHeader/Text")); + double maxWidth14 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SHA256PageHashHeader/Text")); + double maxWidth15 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("HasWHQLSignerHeader/Text")); + double maxWidth16 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("FilePublishersHeader/Text")); + double maxWidth17 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("IsECCSignedHeader/Text")); + double maxWidth18 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("OpusDataHeader/Text")); + + // Iterate over all items to determine the widest string for each column. + foreach (FileIdentity item in CreateDenyPolicy.Instance.filesAndFoldersScanResults) + { + double w1 = ListViewUIHelpers.MeasureTextWidth(item.FileName); + if (w1 > maxWidth1) maxWidth1 = w1; + double w2 = ListViewUIHelpers.MeasureTextWidth(item.SignatureStatus.ToString()); + if (w2 > maxWidth2) maxWidth2 = w2; + double w3 = ListViewUIHelpers.MeasureTextWidth(item.OriginalFileName); + if (w3 > maxWidth3) maxWidth3 = w3; - // https://learn.microsoft.com/en-us/windows/communitytoolkit/controls/datagrid_guidance/group_sort_filter - // Column sorting logic for the entire DataGrid - private void FileIdentitiesDataGrid_Sorting(object sender, DataGridColumnEventArgs e) - { - // Sort the column based on its tag and current sort direction - if (string.Equals(e.Column.Tag?.ToString(), "FileName", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.FileName); - } - else if (string.Equals(e.Column.Tag?.ToString(), "SignatureStatus", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.SignatureStatus); - } - else if (string.Equals(e.Column.Tag?.ToString(), "OriginalFileName", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.OriginalFileName); - } - else if (string.Equals(e.Column.Tag?.ToString(), "InternalName", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.InternalName); - } - else if (string.Equals(e.Column.Tag?.ToString(), "FileDescription", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.FileDescription); - } - else if (string.Equals(e.Column.Tag?.ToString(), "ProductName", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.ProductName); - } - else if (string.Equals(e.Column.Tag?.ToString(), "FileVersion", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.FileVersion); - } - else if (string.Equals(e.Column.Tag?.ToString(), "PackageFamilyName", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.PackageFamilyName); - } - else if (string.Equals(e.Column.Tag?.ToString(), "SHA256Hash", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.SHA256Hash); - } - else if (string.Equals(e.Column.Tag?.ToString(), "SHA1Hash", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.SHA1Hash); - } - else if (string.Equals(e.Column.Tag?.ToString(), "SISigningScenario", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.SISigningScenario); - } - else if (string.Equals(e.Column.Tag?.ToString(), "FilePath", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.FilePath); - } - else if (string.Equals(e.Column.Tag?.ToString(), "SHA1PageHash", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.SHA1PageHash); - } - else if (string.Equals(e.Column.Tag?.ToString(), "SHA256PageHash", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.SHA256PageHash); - } - else if (string.Equals(e.Column.Tag?.ToString(), "HasWHQLSigner", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.HasWHQLSigner); - } - else if (string.Equals(e.Column.Tag?.ToString(), "FilePublishersToDisplay", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.FilePublishersToDisplay); - } - else if (string.Equals(e.Column.Tag?.ToString(), "IsECCSigned", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.IsECCSigned); - } - else if (string.Equals(e.Column.Tag?.ToString(), "Opus", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.Opus); - } + double w4 = ListViewUIHelpers.MeasureTextWidth(item.InternalName); + if (w4 > maxWidth4) maxWidth4 = w4; + double w5 = ListViewUIHelpers.MeasureTextWidth(item.FileDescription); + if (w5 > maxWidth5) maxWidth5 = w5; - // Clear SortDirection for other columns - foreach (DataGridColumn column in FileIdentitiesDataGrid.Columns) - { - if (column != e.Column) - { - column.SortDirection = null; - } - } - } + double w6 = ListViewUIHelpers.MeasureTextWidth(item.ProductName); + if (w6 > maxWidth6) maxWidth6 = w6; + double w7 = ListViewUIHelpers.MeasureTextWidth(item.FileVersion?.ToString()); + if (w7 > maxWidth7) maxWidth7 = w7; - /// - /// Helper method for sorting any column on the DataGird - /// - /// - /// - /// - private void SortColumn(DataGridColumnEventArgs e, Func keySelector) - { - // Check if the search box is empty or not - bool isSearchEmpty = string.IsNullOrWhiteSpace(SearchBox.Text); + double w8 = ListViewUIHelpers.MeasureTextWidth(item.PackageFamilyName); + if (w8 > maxWidth8) maxWidth8 = w8; - // Get the collection to sort based on the search box status - // Allowing us to sort only the items in the search results - List collectionToSort = isSearchEmpty ? CreateDenyPolicy.Instance.filesAndFoldersScanResultsList : [.. CreateDenyPolicy.Instance.filesAndFoldersScanResults]; + double w9 = ListViewUIHelpers.MeasureTextWidth(item.SHA256Hash); + if (w9 > maxWidth9) maxWidth9 = w9; - // Perform the sorting based on the current SortDirection (ascending or descending) - if (e.Column.SortDirection is null || e.Column.SortDirection == DataGridSortDirection.Ascending) - { - // Descending: custom order depending on column type - CreateDenyPolicy.Instance.filesAndFoldersScanResults = [.. collectionToSort.OrderByDescending(keySelector)]; + double w10 = ListViewUIHelpers.MeasureTextWidth(item.SHA1Hash); + if (w10 > maxWidth10) maxWidth10 = w10; - // Set the column direction to Descending - e.Column.SortDirection = DataGridSortDirection.Descending; - } - else - { - // Ascending: custom order depending on column type - CreateDenyPolicy.Instance.filesAndFoldersScanResults = [.. collectionToSort.OrderBy(keySelector)]; - e.Column.SortDirection = DataGridSortDirection.Ascending; - } + double w11 = ListViewUIHelpers.MeasureTextWidth(item.SISigningScenario.ToString()); + if (w11 > maxWidth11) maxWidth11 = w11; - // Update the ItemsSource of the DataGrid - // Required for sort + search to work properly, even though binding to the ObservableCollection already happens in XAML - FileIdentitiesDataGrid.ItemsSource = CreateDenyPolicy.Instance.filesAndFoldersScanResults; - } + double w12 = ListViewUIHelpers.MeasureTextWidth(item.FilePath); + if (w12 > maxWidth12) maxWidth12 = w12; + double w13 = ListViewUIHelpers.MeasureTextWidth(item.SHA1PageHash); + if (w13 > maxWidth13) maxWidth13 = w13; - /// - /// Selects all of the displayed rows on the DataGrid - /// - /// - /// - private void SelectAll_Click(object sender, RoutedEventArgs e) - { - _ = DispatcherQueue.TryEnqueue(() => - { - // Clear existing selections - FileIdentitiesDataGrid.SelectedItems.Clear(); + double w14 = ListViewUIHelpers.MeasureTextWidth(item.SHA256PageHash); + if (w14 > maxWidth14) maxWidth14 = w14; - foreach (FileIdentity fileIdentity in CreateDenyPolicy.Instance.filesAndFoldersScanResults) - { - _ = FileIdentitiesDataGrid.SelectedItems.Add(fileIdentity); // Select each item - } + double w15 = ListViewUIHelpers.MeasureTextWidth(item.HasWHQLSigner.ToString()); + if (w15 > maxWidth15) maxWidth15 = w15; - }); - } + double w16 = ListViewUIHelpers.MeasureTextWidth(item.FilePublishersToDisplay); + if (w16 > maxWidth16) maxWidth16 = w16; + double w17 = ListViewUIHelpers.MeasureTextWidth(item.IsECCSigned.ToString()); + if (w17 > maxWidth17) maxWidth17 = w17; - /// - /// De-selects all of the displayed rows on the DataGrid - /// - /// - /// - private void DeSelectAll_Click(object sender, RoutedEventArgs e) - { - FileIdentitiesDataGrid.SelectedItems.Clear(); // Deselect all rows by clearing SelectedItems - } + double w18 = ListViewUIHelpers.MeasureTextWidth(item.Opus); + if (w18 > maxWidth18) maxWidth18 = w18; + + } + // Set the column width properties. + ColumnWidth1 = new GridLength(maxWidth1); + ColumnWidth2 = new GridLength(maxWidth2); + ColumnWidth3 = new GridLength(maxWidth3); + ColumnWidth4 = new GridLength(maxWidth4); + ColumnWidth5 = new GridLength(maxWidth5); + ColumnWidth6 = new GridLength(maxWidth6); + ColumnWidth7 = new GridLength(maxWidth7); + ColumnWidth8 = new GridLength(maxWidth8); + ColumnWidth9 = new GridLength(maxWidth9); + ColumnWidth10 = new GridLength(maxWidth10); + ColumnWidth11 = new GridLength(maxWidth11); + ColumnWidth12 = new GridLength(maxWidth12); + ColumnWidth13 = new GridLength(maxWidth13); + ColumnWidth14 = new GridLength(maxWidth14); + ColumnWidth15 = new GridLength(maxWidth15); + ColumnWidth16 = new GridLength(maxWidth16); + ColumnWidth17 = new GridLength(maxWidth17); + ColumnWidth18 = new GridLength(maxWidth18); + } /// @@ -289,19 +271,22 @@ private void DeSelectAll_Click(object sender, RoutedEventArgs e) /// /// The event sender. /// The event arguments. - private void DataGridFlyoutMenuCopy_Click(object sender, RoutedEventArgs e) + private void ListViewFlyoutMenuCopy_Click(object sender, RoutedEventArgs e) { - // Check if there are selected items in the DataGrid - if (FileIdentitiesDataGrid.SelectedItems.Count > 0) + // Check if there are selected items in the ListView + if (FileIdentitiesListView.SelectedItems.Count > 0) { // Initialize StringBuilder to store all selected rows' data with labels StringBuilder dataBuilder = new(); - // Loop through each selected item in the DataGrid - foreach (FileIdentity selectedItem in FileIdentitiesDataGrid.SelectedItems) + // Loop through each selected item in the ListView + foreach (var selectedItem in FileIdentitiesListView.SelectedItems) { - // Append each row's formatted data to the StringBuilder - _ = dataBuilder.AppendLine(ConvertRowToText(selectedItem)); + + if (selectedItem is FileIdentity obj) + + // Append each row's formatted data to the StringBuilder + _ = dataBuilder.AppendLine(ListViewUIHelpers.ConvertRowToText(obj)); // Add a separator between rows for readability in multi-row copies _ = dataBuilder.AppendLine(new string('-', 50)); @@ -318,95 +303,6 @@ private void DataGridFlyoutMenuCopy_Click(object sender, RoutedEventArgs e) } } - /// - /// Converts the properties of a FileIdentity row into a labeled, formatted string for copying to clipboard. - /// - /// The selected FileIdentity row from the DataGrid. - /// A formatted string of the row's properties with labels. - private static string ConvertRowToText(FileIdentity row) - { - // Use StringBuilder to format each property with its label for easy reading - return new StringBuilder() - .AppendLine($"File Name: {row.FileName}") - .AppendLine($"Signature Status: {row.SignatureStatus}") - .AppendLine($"Original File Name: {row.OriginalFileName}") - .AppendLine($"Internal Name: {row.InternalName}") - .AppendLine($"File Description: {row.FileDescription}") - .AppendLine($"Product Name: {row.ProductName}") - .AppendLine($"File Version: {row.FileVersion}") - .AppendLine($"Package Family Name: {row.PackageFamilyName}") - .AppendLine($"SHA256 Hash: {row.SHA256Hash}") - .AppendLine($"SHA1 Hash: {row.SHA1Hash}") - .AppendLine($"Signing Scenario: {row.SISigningScenario}") - .AppendLine($"File Path: {row.FilePath}") - .AppendLine($"SHA1 Page Hash: {row.SHA1PageHash}") - .AppendLine($"SHA256 Page Hash: {row.SHA256PageHash}") - .AppendLine($"Has WHQL Signer: {row.HasWHQLSigner}") - .AppendLine($"File Publishers: {row.FilePublishersToDisplay}") - .AppendLine($"Is ECC Signed: {row.IsECCSigned}") - .AppendLine($"Opus Data: {row.Opus}") - .ToString(); - } - - - - /// - /// Event handler for the Copy Individual Items SubMenu. It will populate the submenu items in the flyout of the data grid. - /// - /// - /// - private void FileIdentitiesDataGrid_Loaded(object sender, RoutedEventArgs e) - { - // Ensure the CopyIndividualItemsSubMenu is available - if (CopyIndividualItemsSubMenu is null) - { - return; - } - - // Clear any existing items to avoid duplication if reloaded - CopyIndividualItemsSubMenu.Items.Clear(); - - // Create a dictionary to map headers to their specific click event methods - Dictionary copyActions = new() - { - { "File Name", CopyFileName_Click }, - { "Signature Status", CopySignatureStatus_Click }, - { "Original File Name", CopyOriginalFileName_Click }, - { "Internal Name", CopyInternalName_Click }, - { "File Description", CopyFileDescription_Click }, - { "Product Name", CopyProductName_Click }, - { "File Version", CopyFileVersion_Click }, - { "Package Family Name", CopyPackageFamilyName_Click }, - { "SHA256 Hash", CopySHA256Hash_Click }, - { "SHA1 Hash", CopySHA1Hash_Click }, - { "Signing Scenario", CopySigningScenario_Click }, - { "File Path", CopyFilePath_Click }, - { "SHA1 Page Hash", CopySHA1PageHash_Click }, - { "SHA256 Page Hash", CopySHA256PageHash_Click }, - { "Has WHQL Signer", CopyHasWHQLSigner_Click }, - { "File Publishers", CopyFilePublishersToDisplay_Click }, - { "Is ECC Signed", CopyIsECCSigned_Click }, - { "Opus Data", CopyOpus_Click } - }; - - // Add menu items with specific click events for each column - foreach (DataGridColumn column in FileIdentitiesDataGrid.Columns) - { - string headerText = column.Header.ToString()!; - - if (copyActions.TryGetValue(headerText, out RoutedEventHandler? value)) - { - // Create a new MenuFlyout Item - MenuFlyoutItem menuItem = new() { Text = $"Copy {headerText}" }; - - // Set the click event for the menu item - menuItem.Click += value; - - // Add the menu item to the submenu - CopyIndividualItemsSubMenu.Items.Add(menuItem); - } - } - } // Click event handlers for each property private void CopyFileName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FileName); @@ -424,10 +320,9 @@ private void FileIdentitiesDataGrid_Loaded(object sender, RoutedEventArgs e) private void CopySHA1PageHash_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SHA1PageHash); private void CopySHA256PageHash_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SHA256PageHash); private void CopyHasWHQLSigner_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.HasWHQLSigner.ToString()); - private void CopyFilePublishersToDisplay_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FilePublishersToDisplay); + private void CopyFilePublishers_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FilePublishersToDisplay); private void CopyIsECCSigned_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.IsECCSigned.ToString()); - private void CopyOpus_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.Opus); - + private void CopyOpusData_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.Opus); /// /// Helper method to copy a specified property to clipboard without reflection @@ -435,7 +330,7 @@ private void FileIdentitiesDataGrid_Loaded(object sender, RoutedEventArgs e) /// Function that retrieves the desired property value as a string private void CopyToClipboard(Func getProperty) { - if (FileIdentitiesDataGrid.SelectedItem is FileIdentity selectedItem) + if (FileIdentitiesListView.SelectedItem is FileIdentity selectedItem) { string? propertyValue = getProperty(selectedItem); if (propertyValue is not null) @@ -447,8 +342,271 @@ private void CopyToClipboard(Func getProperty) } } + // Event handlers for each sort button + private void ColumnSortingButton_FileName_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.FileName); + } + private void ColumnSortingButton_SignatureStatus_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.SignatureStatus); + } + private void ColumnSortingButton_OriginalFileName_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.OriginalFileName); + } + private void ColumnSortingButton_InternalName_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.InternalName); + } + private void ColumnSortingButton_FileDescription_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.FileDescription); + } + private void ColumnSortingButton_ProductName_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.ProductName); + } + private void ColumnSortingButton_FileVersion_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.FileVersion); + } + private void ColumnSortingButton_PackageFamilyName_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.PackageFamilyName); + } + private void ColumnSortingButton_SHA256Hash_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.SHA256Hash); + } + private void ColumnSortingButton_SHA1Hash_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.SHA1Hash); + } + + + private void ColumnSortingButton_SigningScenario_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.SISigningScenario); + } + + private void ColumnSortingButton_FilePath_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.FilePath); + } + + private void ColumnSortingButton_SHA1PageHash_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.SHA1PageHash); + } + + private void ColumnSortingButton_SHA256PageHash_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.SHA256PageHash); + } + + private void ColumnSortingButton_HasWHQLSigner_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.HasWHQLSigner); + } + + private void ColumnSortingButton_FilePublishers_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.FilePublishersToDisplay); + } + + private void ColumnSortingButton_IsECCSigned_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.IsECCSigned); + } + + private void ColumnSortingButton_OpusData_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.Opus); + } + + + /// + /// Performs data sorting + /// + /// + /// + private void SortColumn(Func keySelector) + { + // Determine if a search filter is active. + bool isSearchEmpty = string.IsNullOrWhiteSpace(SearchBox.Text); + // Use either the full list (CreateDenyPolicy.Instance.filesAndFoldersScanResultsList) or the current display list. + var collectionToSort = isSearchEmpty ? CreateDenyPolicy.Instance.filesAndFoldersScanResultsList : [.. CreateDenyPolicy.Instance.filesAndFoldersScanResults]; + + if (SortingDirectionToggle.IsChecked) + { + // Sort in descending order. + CreateDenyPolicy.Instance.filesAndFoldersScanResults = [.. collectionToSort.OrderByDescending(keySelector)]; + } + else + { + // Sort in ascending order. + CreateDenyPolicy.Instance.filesAndFoldersScanResults = [.. collectionToSort.OrderBy(keySelector)]; + } + + // Refresh the ItemsSource so the UI updates. + FileIdentitiesListView.ItemsSource = CreateDenyPolicy.Instance.filesAndFoldersScanResults; + } + + #endregion + + + + + + public CreateDenyPolicyFilesAndFoldersScanResults() + { + this.InitializeComponent(); + + // Make sure navigating to/from this page maintains its state + this.NavigationCacheMode = NavigationCacheMode.Enabled; + + // Assign this instance to the static field + _instance = this; + + UIListView = FileIdentitiesListView; + } + + + // Public property to access the singleton instance from other classes + public static CreateDenyPolicyFilesAndFoldersScanResults Instance => _instance ?? throw new InvalidOperationException("CreateDenyPolicyFilesAndFoldersScanResults page is not initialized"); + + + + #region + protected override void OnNavigatedTo(NavigationEventArgs e) + { + base.OnNavigatedTo(e); + + // Update the logs when user switches to this page + UpdateTotalFiles(); + + // Assign the ItemsSource of the ListView only once + // We cannot do it after column width calculation because initialization is not guaranteed at that moment + if (CreateDenyPolicy.Instance.filesAndFoldersDataProcessed) + { + CalculateColumnWidths(); + + FileIdentitiesListView.ItemsSource = CreateDenyPolicy.Instance.filesAndFoldersScanResults; + + CreateDenyPolicy.Instance.filesAndFoldersDataProcessed = false; + } + } + #endregion + + /// + /// Event handler for the SearchBox text change + /// + private void SearchBox_TextChanged(object sender, TextChangedEventArgs e) + { + ApplyFilters(); + } + + /// + /// Applies the date and search filters to the data grid + /// + private void ApplyFilters() + { + + // Get the search term from the SearchBox, converting it to lowercase for case-insensitive searching + string searchTerm = SearchBox.Text.Trim().ToLowerInvariant(); + + // Start with all items from the complete list, 'AllFileIdentities' + // This list is used as the base set for filtering to preserve original data + IEnumerable filteredResults = CreateDenyPolicy.Instance.filesAndFoldersScanResultsList.AsEnumerable(); + + // Apply the search filter if there is a non-empty search term + if (!string.IsNullOrWhiteSpace(searchTerm)) + { + + // Filter results further to match the search term across multiple properties, case-insensitively + filteredResults = filteredResults.Where(output => + (output.FileName is not null && output.FileName.Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) || + (output.SignatureStatus.ToString().Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) || + (output.OriginalFileName is not null && output.OriginalFileName.Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) || + (output.InternalName is not null && output.InternalName.Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) || + (output.FileDescription is not null && output.FileDescription.Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) || + (output.ProductName is not null && output.ProductName.Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) || + (output.FileVersion is not null && output.FileVersion.ToString().Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) || + (output.PackageFamilyName is not null && output.PackageFamilyName.Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) || + (output.SHA1PageHash is not null && output.SHA1PageHash.Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) || + (output.FilePath is not null && output.FilePath.Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) || + (output.SHA256Hash is not null && output.SHA256Hash.Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) || + output.FilePublishersToDisplay.Contains(searchTerm, StringComparison.OrdinalIgnoreCase) || + output.Opus.Contains(searchTerm, StringComparison.OrdinalIgnoreCase) + ); + } + + // Clear the current contents of the ObservableCollection + CreateDenyPolicy.Instance.filesAndFoldersScanResults.Clear(); + + // Populate the ObservableCollection with the filtered results + // This triggers the UI to update the ListView based on the filtered data + foreach (FileIdentity result in filteredResults) + { + CreateDenyPolicy.Instance.filesAndFoldersScanResults.Add(result); + } + + // Explicitly set the ListView's ItemsSource to ensure the data refreshes + FileIdentitiesListView.ItemsSource = CreateDenyPolicy.Instance.filesAndFoldersScanResults; + + // Update any visual or text element showing the total logs count + UpdateTotalFiles(); + } + + + /// + /// Event handler for the Clear Data button + /// + /// + /// + private void ClearDataButton_Click(object sender, RoutedEventArgs e) + { + CreateDenyPolicy.Instance.filesAndFoldersScanResults.Clear(); + CreateDenyPolicy.Instance.filesAndFoldersScanResultsList.Clear(); + + UpdateTotalFiles(true); + } + + + /// + /// Selects all of the displayed rows on the ListView + /// + /// + /// + private void SelectAll_Click(object sender, RoutedEventArgs e) + { + _ = DispatcherQueue.TryEnqueue(() => + { + // Clear existing selections + FileIdentitiesListView.SelectedItems.Clear(); + + foreach (FileIdentity fileIdentity in CreateDenyPolicy.Instance.filesAndFoldersScanResults) + { + FileIdentitiesListView.SelectedItems.Add(fileIdentity); // Select each item + } + + }); + } + + + /// + /// De-selects all of the displayed rows on the ListView + /// + /// + /// + private void DeSelectAll_Click(object sender, RoutedEventArgs e) + { + FileIdentitiesListView.SelectedItems.Clear(); // Deselect all rows by clearing SelectedItems + } + /// /// Updates the total logs count displayed on the UI /// @@ -462,9 +620,5 @@ internal void UpdateTotalFiles(bool? Zero = null) { TotalCountOfTheFilesTextBox.Text = $"Total files: {CreateDenyPolicy.Instance.filesAndFoldersScanResults.Count}"; } - - } - - } diff --git a/AppControl Manager/Pages/CreatePolicy.xaml b/AppControl Manager/Pages/CreatePolicy.xaml index 34b5db759..cef3a81a7 100644 --- a/AppControl Manager/Pages/CreatePolicy.xaml +++ b/AppControl Manager/Pages/CreatePolicy.xaml @@ -96,7 +96,6 @@ - - - - - @@ -211,7 +209,6 @@ private void DefaultWindowsAudit_Toggled(object sender, RoutedEventArgs e) #endregion - #region For Signed and Reputable Policy @@ -297,10 +294,8 @@ private void SignedAndReputableAudit_Toggled(object sender, RoutedEventArgs e) #endregion - #region For Microsoft Recommended Drivers Block Rules - /// /// Method to dynamically add a TextBlock with formatted content /// @@ -407,7 +402,6 @@ await Task.Run(() => } - /// /// Event handler for Auto Update button /// @@ -420,6 +414,8 @@ private async void RecommendedDriverBlockRulesScheduledAutoUpdate_Click(object s try { + RecommendedDriverBlockRulesScheduledAutoUpdate.IsEnabled = false; + RecommendedDriverBlockRulesInfoBar.IsClosable = false; RecommendedDriverBlockRulesInfoBar.IsOpen = true; RecommendedDriverBlockRulesInfoBar.Severity = InfoBarSeverity.Informational; @@ -434,7 +430,6 @@ private async void RecommendedDriverBlockRulesScheduledAutoUpdate_Click(object s } finally { - RecommendedDriverBlockRulesInfoBar.IsClosable = true; // Expand the settings card to make the InfoBar visible @@ -451,17 +446,15 @@ private async void RecommendedDriverBlockRulesScheduledAutoUpdate_Click(object s RecommendedDriverBlockRulesInfoBar.Message = GlobalVars.Rizz.GetString("AutoUpdateConfigured"); } + RecommendedDriverBlockRulesScheduledAutoUpdate.IsEnabled = true; } - } - #endregion #region For Microsoft Recommended User Mode Block Rules - /// /// Event handler for creating/deploying Microsoft recommended user-mode block rules policy /// @@ -492,14 +485,11 @@ await Task.Run(() => } } - #endregion - #region For Strict Kernel-mode policy - /// /// Event handler to prepare the system for Strict Kernel-mode policy /// @@ -562,7 +552,6 @@ private void StrictKernelModePolicyUseNoFlightRootsToggleSwitchSettingsCard_Clic } - private void StrictKernelModePolicyAuditSettingsCard_Click(object sender, RoutedEventArgs e) { StrictKernelModePolicyAudit.IsOn = !StrictKernelModePolicyAudit.IsOn; diff --git a/AppControl Manager/Pages/CreateSupplementalPolicy.xaml b/AppControl Manager/Pages/CreateSupplementalPolicy.xaml index d7f7da481..6d0c15966 100644 --- a/AppControl Manager/Pages/CreateSupplementalPolicy.xaml +++ b/AppControl Manager/Pages/CreateSupplementalPolicy.xaml @@ -9,7 +9,6 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:ui="using:CommunityToolkit.WinUI" xmlns:controls="using:CommunityToolkit.WinUI.Controls" - xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls" xmlns:win="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:animatedvisuals="using:AnimatedVisuals" mc:Ignorable="d"> diff --git a/AppControl Manager/Pages/CreateSupplementalPolicy.xaml.cs b/AppControl Manager/Pages/CreateSupplementalPolicy.xaml.cs index d70bcdf3a..ad71d1256 100644 --- a/AppControl Manager/Pages/CreateSupplementalPolicy.xaml.cs +++ b/AppControl Manager/Pages/CreateSupplementalPolicy.xaml.cs @@ -166,6 +166,8 @@ private void LightUp5(object sender, RoutedEventArgs e) #region Files and Folders scan + internal bool filesAndFoldersDataProcessed; + // Selected File Paths private readonly HashSet filesAndFoldersFilePaths = []; @@ -185,7 +187,7 @@ private void LightUp5(object sender, RoutedEventArgs e) private bool usingWildCardFilePathRules; - // Used to store the scan results and as the source for the results DataGrids + // Used to store the scan results and as the source for the results ListViews internal ObservableCollection filesAndFoldersScanResults = []; internal List filesAndFoldersScanResultsList = []; @@ -559,7 +561,7 @@ private async void CreateFilesAndFoldersSupplementalPolicyButton_Click(object se FilesAndFoldersInfoBar.Message = msg1; Logger.Write(msg1); - // Clear variables responsible for the DataGrid + // Clear variables responsible for the ListView filesAndFoldersScanResultsList.Clear(); filesAndFoldersScanResults.Clear(); @@ -567,7 +569,7 @@ private async void CreateFilesAndFoldersSupplementalPolicyButton_Click(object se ScalabilityRadialGauge.IsEnabled = false; - await Task.Run(() => + await Task.Run(async () => { DirectoryInfo[] selectedDirectories = []; @@ -577,11 +579,11 @@ await Task.Run(() => FileInfo[] selectedFiles = []; + HashSet LocalFilesResults = []; + // Convert user selected file paths that are strings to FileInfo objects selectedFiles = [.. filesAndFoldersFilePaths.Select(file => new FileInfo(file))]; - HashSet LocalFilesResults = []; - // Do the following steps only if Wildcard paths aren't going to be used because then only the selected folder paths are needed if (!usingWildCardFilePathRules) { @@ -619,18 +621,16 @@ await Task.Run(() => // Scan all of the detected files from the user selected directories LocalFilesResults = LocalFilesScan.Scan(DetectedFilesInSelectedDirectories, (ushort)radialGaugeValue, FilesAndFoldersProgressBar, null); - // Add the results of the directories scans to the DataGrid + // Add the results of the directories scans to the ListView foreach (FileIdentity item in LocalFilesResults) { _ = DispatcherQueue.TryEnqueue(() => { filesAndFoldersScanResults.Add(item); filesAndFoldersScanResultsList.Add(item); - }); } - string msg3 = "Scan completed, creating the Supplemental policy"; Logger.Write(msg3); @@ -642,6 +642,23 @@ await Task.Run(() => } + await DispatcherQueue.EnqueueAsync(() => + { + // If the ListView page is loaded and user is on that page at this moment then calculate the column widths assign ItemsSource for ListView here + if (Equals(MainWindow.Instance.AppFrame.CurrentSourcePageType, typeof(CreateSupplementalPolicyFilesAndFoldersScanResults))) + { + filesAndFoldersDataProcessed = false; + + CreateSupplementalPolicyFilesAndFoldersScanResults.Instance.CalculateColumnWidths(); + CreateSupplementalPolicyFilesAndFoldersScanResults.Instance.UIListView.ItemsSource = filesAndFoldersScanResults; + } + else + { + // Set it to true so ListView will be updated once user navigated to the page + filesAndFoldersDataProcessed = true; + } + }); + DirectoryInfo stagingArea = StagingArea.NewStagingArea("FilesAndFoldersSupplementalPolicy"); // Get the path to an empty policy file @@ -670,7 +687,6 @@ await Task.Run(() => // Copying the policy file to the User Config directory - outside of the temporary staging area File.Copy(EmptyPolicyPath, OutputPath, true); - // If user selected to deploy the policy if (filesAndFoldersDeployButton) { @@ -684,15 +700,12 @@ await Task.Run(() => FilesAndFoldersInfoBar.Message = msg4; }); - string CIPPath = Path.Combine(stagingArea.FullName, $"{supplementalPolicyID}.cip"); PolicyToCIPConverter.Convert(OutputPath, CIPPath); CiToolHelper.UpdatePolicy(CIPPath); } - - }); } @@ -1286,10 +1299,12 @@ private void ISGBrowseForBasePolicyButton_Flyout_Clear_Click(object sender, Rout #region Strict Kernel-Mode Supplemental Policy + internal bool StrictKernelModeDataProcessed; + // Path to the base policy for the Strict kernel-mode supplemental policy private string? StrictKernelModeBasePolicyPath; - // Used to store the scan results and as the source for the results DataGrids + // Used to store the scan results and as the source for the results ListViews internal ObservableCollection ScanResults = []; internal List ScanResultsList = []; @@ -1406,7 +1421,7 @@ private async void StrictKernelModePerformScans(bool OnlyAfterReboot) StrictKernelModeInfoBar.Message = "Scanning the system for events"; StrictKernelModeSection.IsExpanded = true; - // Clear variables responsible for the DataGrid + // Clear variables responsible for the ListView ScanResults.Clear(); ScanResultsList.Clear(); @@ -1439,7 +1454,7 @@ await Task.Run(() => { StrictKernelModeInfoBar.Message = $"{Output.Count} log(s) were generated during the Audit phase"; - // Add the event logs to the DataGrid + // Add the event logs to the ListView foreach (FileIdentity item in Output) { ScanResults.Add(item); @@ -1447,6 +1462,26 @@ await Task.Run(() => } DetectedKernelModeFilesDetailsSettingsCard.IsEnabled = true; + + + await DispatcherQueue.EnqueueAsync(() => + { + // If the ListView page is loaded and user is on that page at this moment then calculate the column widths assign ItemsSource for ListView here + if (Equals(MainWindow.Instance.AppFrame.CurrentSourcePageType, typeof(StrictKernelPolicyScanResults))) + { + StrictKernelModeDataProcessed = false; + + StrictKernelPolicyScanResults.Instance.CalculateColumnWidths(); + StrictKernelPolicyScanResults.Instance.UIListView.ItemsSource = ScanResults; + } + else + { + // Set it to true so ListView will be updated once user navigated to the page + StrictKernelModeDataProcessed = true; + } + }); + + } else { @@ -1724,7 +1759,7 @@ await Task.Run(() => // Scan all of the detected files from the user selected directories HashSet LocalFilesResults = LocalFilesScan.Scan(kernelModeDriversList, 2, null, null); - // Add the results to the DataGrid + // Add the results to the ListView // Only signed kernel-mode files foreach (FileIdentity item in LocalFilesResults.Where(fileIdentity => fileIdentity.SISigningScenario is 0 && fileIdentity.SignatureStatus is SignatureStatus.IsSigned)) { @@ -2178,7 +2213,7 @@ await Task.Run(() => string OutputPath = Path.Combine(GlobalVars.UserConfigDir, $"{PFNBasedSupplementalPolicyName}.xml"); // Instantiate the user selected Base policy - SiPolicy.SiPolicy policyObj = SiPolicy.Management.Initialize(PFNBasePolicyPath, null); + SiPolicy.SiPolicy policyObj = Management.Initialize(PFNBasePolicyPath, null); // Set the BasePolicyID of our new policy to the one from user selected policy string supplementalPolicyID = SetCiPolicyInfo.Set(EmptyPolicyPath, true, PFNBasedSupplementalPolicyName, policyObj.BasePolicyID, null); diff --git a/AppControl Manager/Pages/CreateSupplementalPolicyFilesAndFoldersScanResults.xaml b/AppControl Manager/Pages/CreateSupplementalPolicyFilesAndFoldersScanResults.xaml index aa926672f..548aa06e8 100644 --- a/AppControl Manager/Pages/CreateSupplementalPolicyFilesAndFoldersScanResults.xaml +++ b/AppControl Manager/Pages/CreateSupplementalPolicyFilesAndFoldersScanResults.xaml @@ -8,7 +8,10 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" xmlns:controls="using:CommunityToolkit.WinUI.Controls" - xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls"> + xmlns:intelgathering="using:AppControlManager.IntelGathering" + xmlns:interactivity="using:Microsoft.Xaml.Interactivity" + xmlns:behaviors="using:CommunityToolkit.WinUI.Behaviors" + x:Name="CreateSupplementalPolicyFilesAndFoldersScanResultsXAML"> @@ -62,6 +65,43 @@ + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/AppControl Manager/Pages/CreateSupplementalPolicyFilesAndFoldersScanResults.xaml.cs b/AppControl Manager/Pages/CreateSupplementalPolicyFilesAndFoldersScanResults.xaml.cs index ea451001a..03553f018 100644 --- a/AppControl Manager/Pages/CreateSupplementalPolicyFilesAndFoldersScanResults.xaml.cs +++ b/AppControl Manager/Pages/CreateSupplementalPolicyFilesAndFoldersScanResults.xaml.cs @@ -1,53 +1,504 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Linq; using System.Text; using AppControlManager.IntelGathering; -using CommunityToolkit.WinUI.UI.Controls; +using AppControlManager.Others; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Navigation; using Windows.ApplicationModel.DataTransfer; +using WinRT; namespace AppControlManager.Pages; - -public sealed partial class CreateSupplementalPolicyFilesAndFoldersScanResults : Page +// Since the columns for data in the ItemTemplate use "Binding" instead of "x:Bind", we need to use [GeneratedBindableCustomProperty] for them to work properly +[GeneratedBindableCustomProperty] +public sealed partial class CreateSupplementalPolicyFilesAndFoldersScanResults : Page, INotifyPropertyChanged { + // A static instance of the CreateSupplementalPolicy class which will hold the single, shared instance of the page + private static CreateSupplementalPolicyFilesAndFoldersScanResults? _instance; + + internal ListView UIListView { get; private set; } + + #region LISTVIEW IMPLEMENTATIONS + + public event PropertyChangedEventHandler? PropertyChanged; + private void OnPropertyChanged(string propertyName) => + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + + // Properties to hold each columns' width. + private GridLength _columnWidth1; + public GridLength ColumnWidth1 + { + get => _columnWidth1; + set { _columnWidth1 = value; OnPropertyChanged(nameof(ColumnWidth1)); } + } + + private GridLength _columnWidth2; + public GridLength ColumnWidth2 + { + get => _columnWidth2; + set { _columnWidth2 = value; OnPropertyChanged(nameof(ColumnWidth2)); } + } + + private GridLength _columnWidth3; + public GridLength ColumnWidth3 + { + get => _columnWidth3; + set { _columnWidth3 = value; OnPropertyChanged(nameof(ColumnWidth3)); } + } + + private GridLength _columnWidth4; + public GridLength ColumnWidth4 + { + get => _columnWidth4; + set { _columnWidth4 = value; OnPropertyChanged(nameof(ColumnWidth4)); } + } + + private GridLength _columnWidth5; + public GridLength ColumnWidth5 + { + get => _columnWidth5; + set { _columnWidth5 = value; OnPropertyChanged(nameof(ColumnWidth5)); } + } + + private GridLength _columnWidth6; + public GridLength ColumnWidth6 + { + get => _columnWidth6; + set { _columnWidth6 = value; OnPropertyChanged(nameof(ColumnWidth6)); } + } + + private GridLength _columnWidth7; + public GridLength ColumnWidth7 + { + get => _columnWidth7; + set { _columnWidth7 = value; OnPropertyChanged(nameof(ColumnWidth7)); } + } + + private GridLength _columnWidth8; + public GridLength ColumnWidth8 + { + get => _columnWidth8; + set { _columnWidth8 = value; OnPropertyChanged(nameof(ColumnWidth8)); } + } + + private GridLength _columnWidth9; + public GridLength ColumnWidth9 + { + get => _columnWidth9; + set { _columnWidth9 = value; OnPropertyChanged(nameof(ColumnWidth9)); } + } + + private GridLength _columnWidth10; + public GridLength ColumnWidth10 + { + get => _columnWidth10; + set { _columnWidth10 = value; OnPropertyChanged(nameof(ColumnWidth10)); } + } + + private GridLength _columnWidth11; + public GridLength ColumnWidth11 + { + get => _columnWidth11; + set { _columnWidth11 = value; OnPropertyChanged(nameof(ColumnWidth11)); } + } + + private GridLength _columnWidth12; + public GridLength ColumnWidth12 + { + get => _columnWidth12; + set { _columnWidth12 = value; OnPropertyChanged(nameof(ColumnWidth12)); } + } + + private GridLength _columnWidth13; + public GridLength ColumnWidth13 + { + get => _columnWidth13; + set { _columnWidth13 = value; OnPropertyChanged(nameof(ColumnWidth13)); } + } + + private GridLength _columnWidth14; + public GridLength ColumnWidth14 + { + get => _columnWidth14; + set { _columnWidth14 = value; OnPropertyChanged(nameof(ColumnWidth14)); } + } + + private GridLength _columnWidth15; + public GridLength ColumnWidth15 + { + get => _columnWidth15; + set { _columnWidth15 = value; OnPropertyChanged(nameof(ColumnWidth15)); } + } + + private GridLength _columnWidth16; + public GridLength ColumnWidth16 + { + get => _columnWidth16; + set { _columnWidth16 = value; OnPropertyChanged(nameof(ColumnWidth16)); } + } + + private GridLength _columnWidth17; + public GridLength ColumnWidth17 + { + get => _columnWidth17; + set { _columnWidth17 = value; OnPropertyChanged(nameof(ColumnWidth17)); } + } + + private GridLength _columnWidth18; + public GridLength ColumnWidth18 + { + get => _columnWidth18; + set { _columnWidth18 = value; OnPropertyChanged(nameof(ColumnWidth18)); } + } + + /// + /// Calculates the maximum required width for each column (including header text) + /// and assigns the value (with a little extra padding) to the corresponding property. + /// It should always run once ALL the data have been added to the ObservableCollection that is the ItemsSource of the ListView + /// And only after this method, the ItemsSource must be assigned to the ListView. + /// + internal void CalculateColumnWidths() + { + + // Measure header text widths first. + double maxWidth1 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("FileNameHeader/Text")); + double maxWidth2 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SignatureStatusHeader/Text")); + double maxWidth3 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("OriginalFileNameHeader/Text")); + double maxWidth4 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("InternalNameHeader/Text")); + double maxWidth5 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("FileDescriptionHeader/Text")); + double maxWidth6 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("ProductNameHeader/Text")); + double maxWidth7 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("FileVersionHeader/Text")); + double maxWidth8 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("PackageFamilyNameHeader/Text")); + double maxWidth9 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SHA256HashHeader/Text")); + double maxWidth10 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SHA1HashHeader/Text")); + double maxWidth11 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SigningScenarioHeader/Text")); + double maxWidth12 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("FilePathHeader/Text")); + double maxWidth13 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SHA1PageHashHeader/Text")); + double maxWidth14 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SHA256PageHashHeader/Text")); + double maxWidth15 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("HasWHQLSignerHeader/Text")); + double maxWidth16 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("FilePublishersHeader/Text")); + double maxWidth17 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("IsECCSignedHeader/Text")); + double maxWidth18 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("OpusDataHeader/Text")); + + // Iterate over all items to determine the widest string for each column. + foreach (FileIdentity item in CreateSupplementalPolicy.Instance.filesAndFoldersScanResults) + { + double w1 = ListViewUIHelpers.MeasureTextWidth(item.FileName); + if (w1 > maxWidth1) maxWidth1 = w1; + + double w2 = ListViewUIHelpers.MeasureTextWidth(item.SignatureStatus.ToString()); + if (w2 > maxWidth2) maxWidth2 = w2; + + double w3 = ListViewUIHelpers.MeasureTextWidth(item.OriginalFileName); + if (w3 > maxWidth3) maxWidth3 = w3; + + double w4 = ListViewUIHelpers.MeasureTextWidth(item.InternalName); + if (w4 > maxWidth4) maxWidth4 = w4; + + double w5 = ListViewUIHelpers.MeasureTextWidth(item.FileDescription); + if (w5 > maxWidth5) maxWidth5 = w5; + + double w6 = ListViewUIHelpers.MeasureTextWidth(item.ProductName); + if (w6 > maxWidth6) maxWidth6 = w6; + + double w7 = ListViewUIHelpers.MeasureTextWidth(item.FileVersion?.ToString()); + if (w7 > maxWidth7) maxWidth7 = w7; + + double w8 = ListViewUIHelpers.MeasureTextWidth(item.PackageFamilyName); + if (w8 > maxWidth8) maxWidth8 = w8; + + double w9 = ListViewUIHelpers.MeasureTextWidth(item.SHA256Hash); + if (w9 > maxWidth9) maxWidth9 = w9; + + double w10 = ListViewUIHelpers.MeasureTextWidth(item.SHA1Hash); + if (w10 > maxWidth10) maxWidth10 = w10; + + double w11 = ListViewUIHelpers.MeasureTextWidth(item.SISigningScenario.ToString()); + if (w11 > maxWidth11) maxWidth11 = w11; + + double w12 = ListViewUIHelpers.MeasureTextWidth(item.FilePath); + if (w12 > maxWidth12) maxWidth12 = w12; + + double w13 = ListViewUIHelpers.MeasureTextWidth(item.SHA1PageHash); + if (w13 > maxWidth13) maxWidth13 = w13; + + double w14 = ListViewUIHelpers.MeasureTextWidth(item.SHA256PageHash); + if (w14 > maxWidth14) maxWidth14 = w14; + + double w15 = ListViewUIHelpers.MeasureTextWidth(item.HasWHQLSigner.ToString()); + if (w15 > maxWidth15) maxWidth15 = w15; + + double w16 = ListViewUIHelpers.MeasureTextWidth(item.FilePublishersToDisplay); + if (w16 > maxWidth16) maxWidth16 = w16; + + double w17 = ListViewUIHelpers.MeasureTextWidth(item.IsECCSigned.ToString()); + if (w17 > maxWidth17) maxWidth17 = w17; + + double w18 = ListViewUIHelpers.MeasureTextWidth(item.Opus); + if (w18 > maxWidth18) maxWidth18 = w18; + + } + + // Set the column width properties. + ColumnWidth1 = new GridLength(maxWidth1); + ColumnWidth2 = new GridLength(maxWidth2); + ColumnWidth3 = new GridLength(maxWidth3); + ColumnWidth4 = new GridLength(maxWidth4); + ColumnWidth5 = new GridLength(maxWidth5); + ColumnWidth6 = new GridLength(maxWidth6); + ColumnWidth7 = new GridLength(maxWidth7); + ColumnWidth8 = new GridLength(maxWidth8); + ColumnWidth9 = new GridLength(maxWidth9); + ColumnWidth10 = new GridLength(maxWidth10); + ColumnWidth11 = new GridLength(maxWidth11); + ColumnWidth12 = new GridLength(maxWidth12); + ColumnWidth13 = new GridLength(maxWidth13); + ColumnWidth14 = new GridLength(maxWidth14); + ColumnWidth15 = new GridLength(maxWidth15); + ColumnWidth16 = new GridLength(maxWidth16); + ColumnWidth17 = new GridLength(maxWidth17); + ColumnWidth18 = new GridLength(maxWidth18); + } + + + + /// + /// Copies the selected rows to the clipboard in a formatted manner, with each property labeled for clarity. + /// + /// The event sender. + /// The event arguments. + private void ListViewFlyoutMenuCopy_Click(object sender, RoutedEventArgs e) + { + // Check if there are selected items in the ListView + if (FileIdentitiesListView.SelectedItems.Count > 0) + { + // Initialize StringBuilder to store all selected rows' data with labels + StringBuilder dataBuilder = new(); + + // Loop through each selected item in the ListView + foreach (var selectedItem in FileIdentitiesListView.SelectedItems) + { + + if (selectedItem is FileIdentity obj) + + // Append each row's formatted data to the StringBuilder + _ = dataBuilder.AppendLine(ListViewUIHelpers.ConvertRowToText(obj)); + + // Add a separator between rows for readability in multi-row copies + _ = dataBuilder.AppendLine(new string('-', 50)); + } + + // Create a DataPackage to hold the text data + DataPackage dataPackage = new(); + + // Set the formatted text as the content of the DataPackage + dataPackage.SetText(dataBuilder.ToString()); + + // Copy the DataPackage content to the clipboard + Clipboard.SetContent(dataPackage); + } + } + + + // Click event handlers for each property + private void CopyFileName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FileName); + private void CopySignatureStatus_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SignatureStatus.ToString()); + private void CopyOriginalFileName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.OriginalFileName); + private void CopyInternalName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.InternalName); + private void CopyFileDescription_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FileDescription); + private void CopyProductName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.ProductName); + private void CopyFileVersion_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FileVersion?.ToString()); + private void CopyPackageFamilyName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.PackageFamilyName); + private void CopySHA256Hash_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SHA256Hash); + private void CopySHA1Hash_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SHA1Hash); + private void CopySigningScenario_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SISigningScenario.ToString()); + private void CopyFilePath_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FilePath); + private void CopySHA1PageHash_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SHA1PageHash); + private void CopySHA256PageHash_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SHA256PageHash); + private void CopyHasWHQLSigner_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.HasWHQLSigner.ToString()); + private void CopyFilePublishers_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FilePublishersToDisplay); + private void CopyIsECCSigned_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.IsECCSigned.ToString()); + private void CopyOpusData_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.Opus); + + /// + /// Helper method to copy a specified property to clipboard without reflection + /// + /// Function that retrieves the desired property value as a string + private void CopyToClipboard(Func getProperty) + { + if (FileIdentitiesListView.SelectedItem is FileIdentity selectedItem) + { + string? propertyValue = getProperty(selectedItem); + if (propertyValue is not null) + { + DataPackage dataPackage = new(); + dataPackage.SetText(propertyValue); + Clipboard.SetContent(dataPackage); + } + } + } + + // Event handlers for each sort button + private void ColumnSortingButton_FileName_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.FileName); + } + private void ColumnSortingButton_SignatureStatus_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.SignatureStatus); + } + private void ColumnSortingButton_OriginalFileName_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.OriginalFileName); + } + private void ColumnSortingButton_InternalName_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.InternalName); + } + private void ColumnSortingButton_FileDescription_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.FileDescription); + } + private void ColumnSortingButton_ProductName_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.ProductName); + } + private void ColumnSortingButton_FileVersion_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.FileVersion); + } + private void ColumnSortingButton_PackageFamilyName_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.PackageFamilyName); + } + private void ColumnSortingButton_SHA256Hash_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.SHA256Hash); + } + private void ColumnSortingButton_SHA1Hash_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.SHA1Hash); + } + + + private void ColumnSortingButton_SigningScenario_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.SISigningScenario); + } + + private void ColumnSortingButton_FilePath_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.FilePath); + } + + private void ColumnSortingButton_SHA1PageHash_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.SHA1PageHash); + } + + private void ColumnSortingButton_SHA256PageHash_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.SHA256PageHash); + } + + private void ColumnSortingButton_HasWHQLSigner_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.HasWHQLSigner); + } + + private void ColumnSortingButton_FilePublishers_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.FilePublishersToDisplay); + } + + private void ColumnSortingButton_IsECCSigned_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.IsECCSigned); + } + + private void ColumnSortingButton_OpusData_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.Opus); + } + + + + + /// + /// Performs data sorting + /// + /// + /// + private void SortColumn(Func keySelector) + { + // Determine if a search filter is active. + bool isSearchEmpty = string.IsNullOrWhiteSpace(SearchBox.Text); + // Use either the full list (CreateSupplementalPolicy.Instance.filesAndFoldersScanResultsList) or the current display list. + var collectionToSort = isSearchEmpty ? CreateSupplementalPolicy.Instance.filesAndFoldersScanResultsList : [.. CreateSupplementalPolicy.Instance.filesAndFoldersScanResults]; + + if (SortingDirectionToggle.IsChecked) + { + // Sort in descending order. + CreateSupplementalPolicy.Instance.filesAndFoldersScanResults = [.. collectionToSort.OrderByDescending(keySelector)]; + } + else + { + // Sort in ascending order. + CreateSupplementalPolicy.Instance.filesAndFoldersScanResults = [.. collectionToSort.OrderBy(keySelector)]; + } + + // Refresh the ItemsSource so the UI updates. + FileIdentitiesListView.ItemsSource = CreateSupplementalPolicy.Instance.filesAndFoldersScanResults; + } + + #endregion + + + + + + + + + public CreateSupplementalPolicyFilesAndFoldersScanResults() { this.InitializeComponent(); // Make sure navigating to/from this page maintains its state this.NavigationCacheMode = NavigationCacheMode.Enabled; - } + // Assign this instance to the static field + _instance = this; + UIListView = FileIdentitiesListView; + } - #region + // Public property to access the singleton instance from other classes + public static CreateSupplementalPolicyFilesAndFoldersScanResults Instance => _instance ?? throw new InvalidOperationException("CreateSupplementalPolicyFilesAndFoldersScanResults page is not initialized"); - // Without the following steps, when the user begins data fetching process and then navigates away from this page - // Upon arrival at this page again, the DataGrid loses its virtualization, causing the UI to hang for extended periods of time - // But after nullifying DataGrid's ItemsSource when page is navigated from and reassigning it when page is navigated to, - // We tackle that problem. Data will sill be stored in the ObservableCollection when page is not in focus, - // But DataGrid's source will pick them up only when page is navigated to. protected override void OnNavigatedTo(NavigationEventArgs e) { base.OnNavigatedTo(e); - FileIdentitiesDataGrid.ItemsSource = CreateSupplementalPolicy.Instance.filesAndFoldersScanResults; // Update the logs when user switches to this page UpdateTotalFiles(); - } - protected override void OnNavigatedFrom(NavigationEventArgs e) - { - base.OnNavigatedFrom(e); - FileIdentitiesDataGrid.ItemsSource = null; - } + // Assign the ItemsSource of the ListView only once + // We cannot do it after column width calculation because initialization is not guaranteed at that moment + if (CreateSupplementalPolicy.Instance.filesAndFoldersDataProcessed) + { + CalculateColumnWidths(); - #endregion + FileIdentitiesListView.ItemsSource = CreateSupplementalPolicy.Instance.filesAndFoldersScanResults; + CreateSupplementalPolicy.Instance.filesAndFoldersDataProcessed = false; + } + } /// /// Event handler for the SearchBox text change @@ -97,14 +548,14 @@ private void ApplyFilters() CreateSupplementalPolicy.Instance.filesAndFoldersScanResults.Clear(); // Populate the ObservableCollection with the filtered results - // This triggers the UI to update the DataGrid based on the filtered data + // This triggers the UI to update the ListView based on the filtered data foreach (FileIdentity result in filteredResults) { CreateSupplementalPolicy.Instance.filesAndFoldersScanResults.Add(result); } - // Explicitly set the DataGrid's ItemsSource to ensure the data refreshes - FileIdentitiesDataGrid.ItemsSource = CreateSupplementalPolicy.Instance.filesAndFoldersScanResults; + // Explicitly set the ListView's ItemsSource to ensure the data refreshes + FileIdentitiesListView.ItemsSource = CreateSupplementalPolicy.Instance.filesAndFoldersScanResults; // Update any visual or text element showing the total logs count UpdateTotalFiles(); @@ -124,137 +575,8 @@ private void ClearDataButton_Click(object sender, RoutedEventArgs e) UpdateTotalFiles(true); } - - - // https://learn.microsoft.com/en-us/windows/communitytoolkit/controls/datagrid_guidance/group_sort_filter - // Column sorting logic for the entire DataGrid - private void FileIdentitiesDataGrid_Sorting(object sender, DataGridColumnEventArgs e) - { - // Sort the column based on its tag and current sort direction - if (string.Equals(e.Column.Tag?.ToString(), "FileName", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.FileName); - } - else if (string.Equals(e.Column.Tag?.ToString(), "SignatureStatus", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.SignatureStatus); - } - else if (string.Equals(e.Column.Tag?.ToString(), "OriginalFileName", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.OriginalFileName); - } - else if (string.Equals(e.Column.Tag?.ToString(), "InternalName", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.InternalName); - } - else if (string.Equals(e.Column.Tag?.ToString(), "FileDescription", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.FileDescription); - } - else if (string.Equals(e.Column.Tag?.ToString(), "ProductName", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.ProductName); - } - else if (string.Equals(e.Column.Tag?.ToString(), "FileVersion", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.FileVersion); - } - else if (string.Equals(e.Column.Tag?.ToString(), "PackageFamilyName", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.PackageFamilyName); - } - else if (string.Equals(e.Column.Tag?.ToString(), "SHA256Hash", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.SHA256Hash); - } - else if (string.Equals(e.Column.Tag?.ToString(), "SHA1Hash", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.SHA1Hash); - } - else if (string.Equals(e.Column.Tag?.ToString(), "SISigningScenario", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.SISigningScenario); - } - else if (string.Equals(e.Column.Tag?.ToString(), "FilePath", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.FilePath); - } - else if (string.Equals(e.Column.Tag?.ToString(), "SHA1PageHash", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.SHA1PageHash); - } - else if (string.Equals(e.Column.Tag?.ToString(), "SHA256PageHash", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.SHA256PageHash); - } - else if (string.Equals(e.Column.Tag?.ToString(), "HasWHQLSigner", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.HasWHQLSigner); - } - else if (string.Equals(e.Column.Tag?.ToString(), "FilePublishersToDisplay", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.FilePublishersToDisplay); - } - else if (string.Equals(e.Column.Tag?.ToString(), "IsECCSigned", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.IsECCSigned); - } - else if (string.Equals(e.Column.Tag?.ToString(), "Opus", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.Opus); - } - - - // Clear SortDirection for other columns - foreach (DataGridColumn column in FileIdentitiesDataGrid.Columns) - { - if (column != e.Column) - { - column.SortDirection = null; - } - } - } - - - /// - /// Helper method for sorting any column on the DataGird - /// - /// - /// - /// - private void SortColumn(DataGridColumnEventArgs e, Func keySelector) - { - // Check if the search box is empty or not - bool isSearchEmpty = string.IsNullOrWhiteSpace(SearchBox.Text); - - // Get the collection to sort based on the search box status - // Allowing us to sort only the items in the search results - List collectionToSort = isSearchEmpty ? CreateSupplementalPolicy.Instance.filesAndFoldersScanResultsList : [.. CreateSupplementalPolicy.Instance.filesAndFoldersScanResults]; - - // Perform the sorting based on the current SortDirection (ascending or descending) - if (e.Column.SortDirection is null || e.Column.SortDirection == DataGridSortDirection.Ascending) - { - // Descending: custom order depending on column type - CreateSupplementalPolicy.Instance.filesAndFoldersScanResults = [.. collectionToSort.OrderByDescending(keySelector)]; - - // Set the column direction to Descending - e.Column.SortDirection = DataGridSortDirection.Descending; - } - else - { - // Ascending: custom order depending on column type - CreateSupplementalPolicy.Instance.filesAndFoldersScanResults = [.. collectionToSort.OrderBy(keySelector)]; - e.Column.SortDirection = DataGridSortDirection.Ascending; - } - - // Update the ItemsSource of the DataGrid - // Required for sort + search to work properly, even though binding to the ObservableCollection already happens in XAML - FileIdentitiesDataGrid.ItemsSource = CreateSupplementalPolicy.Instance.filesAndFoldersScanResults; - } - - /// - /// Selects all of the displayed rows on the DataGrid + /// Selects all of the displayed rows on the ListView /// /// /// @@ -263,29 +585,25 @@ private void SelectAll_Click(object sender, RoutedEventArgs e) _ = DispatcherQueue.TryEnqueue(() => { // Clear existing selections - FileIdentitiesDataGrid.SelectedItems.Clear(); + FileIdentitiesListView.SelectedItems.Clear(); foreach (FileIdentity fileIdentity in CreateSupplementalPolicy.Instance.filesAndFoldersScanResults) { - _ = FileIdentitiesDataGrid.SelectedItems.Add(fileIdentity); // Select each item + FileIdentitiesListView.SelectedItems.Add(fileIdentity); // Select each item } - }); } - /// - /// De-selects all of the displayed rows on the DataGrid + /// De-selects all of the displayed rows on the ListView /// /// /// private void DeSelectAll_Click(object sender, RoutedEventArgs e) { - FileIdentitiesDataGrid.SelectedItems.Clear(); // Deselect all rows by clearing SelectedItems + FileIdentitiesListView.SelectedItems.Clear(); // Deselect all rows by clearing SelectedItems } - - /// /// Copies the selected rows to the clipboard in a formatted manner, with each property labeled for clarity. /// @@ -293,17 +611,20 @@ private void DeSelectAll_Click(object sender, RoutedEventArgs e) /// The event arguments. private void DataGridFlyoutMenuCopy_Click(object sender, RoutedEventArgs e) { - // Check if there are selected items in the DataGrid - if (FileIdentitiesDataGrid.SelectedItems.Count > 0) + // Check if there are selected items in the ListView + if (FileIdentitiesListView.SelectedItems.Count > 0) { // Initialize StringBuilder to store all selected rows' data with labels StringBuilder dataBuilder = new(); - // Loop through each selected item in the DataGrid - foreach (FileIdentity selectedItem in FileIdentitiesDataGrid.SelectedItems) + // Loop through each selected item in the ListView + foreach (var selectedItem in FileIdentitiesListView.SelectedItems) { - // Append each row's formatted data to the StringBuilder - _ = dataBuilder.AppendLine(ConvertRowToText(selectedItem)); + + if (selectedItem is FileIdentity item) + + // Append each row's formatted data to the StringBuilder + _ = dataBuilder.AppendLine(ListViewUIHelpers.ConvertRowToText(item)); // Add a separator between rows for readability in multi-row copies _ = dataBuilder.AppendLine(new string('-', 50)); @@ -320,137 +641,6 @@ private void DataGridFlyoutMenuCopy_Click(object sender, RoutedEventArgs e) } } - /// - /// Converts the properties of a FileIdentity row into a labeled, formatted string for copying to clipboard. - /// - /// The selected FileIdentity row from the DataGrid. - /// A formatted string of the row's properties with labels. - private static string ConvertRowToText(FileIdentity row) - { - // Use StringBuilder to format each property with its label for easy reading - return new StringBuilder() - .AppendLine($"File Name: {row.FileName}") - .AppendLine($"Signature Status: {row.SignatureStatus}") - .AppendLine($"Original File Name: {row.OriginalFileName}") - .AppendLine($"Internal Name: {row.InternalName}") - .AppendLine($"File Description: {row.FileDescription}") - .AppendLine($"Product Name: {row.ProductName}") - .AppendLine($"File Version: {row.FileVersion}") - .AppendLine($"Package Family Name: {row.PackageFamilyName}") - .AppendLine($"SHA256 Hash: {row.SHA256Hash}") - .AppendLine($"SHA1 Hash: {row.SHA1Hash}") - .AppendLine($"Signing Scenario: {row.SISigningScenario}") - .AppendLine($"File Path: {row.FilePath}") - .AppendLine($"SHA1 Page Hash: {row.SHA1PageHash}") - .AppendLine($"SHA256 Page Hash: {row.SHA256PageHash}") - .AppendLine($"Has WHQL Signer: {row.HasWHQLSigner}") - .AppendLine($"File Publishers: {row.FilePublishersToDisplay}") - .AppendLine($"Is ECC Signed: {row.IsECCSigned}") - .AppendLine($"Opus Data: {row.Opus}") - .ToString(); - } - - - - /// - /// Event handler for the Copy Individual Items SubMenu. It will populate the submenu items in the flyout of the data grid. - /// - /// - /// - private void FileIdentitiesDataGrid_Loaded(object sender, RoutedEventArgs e) - { - // Ensure the CopyIndividualItemsSubMenu is available - if (CopyIndividualItemsSubMenu is null) - { - return; - } - - // Clear any existing items to avoid duplication if reloaded - CopyIndividualItemsSubMenu.Items.Clear(); - - // Create a dictionary to map headers to their specific click event methods - Dictionary copyActions = new() - { - { "File Name", CopyFileName_Click }, - { "Signature Status", CopySignatureStatus_Click }, - { "Original File Name", CopyOriginalFileName_Click }, - { "Internal Name", CopyInternalName_Click }, - { "File Description", CopyFileDescription_Click }, - { "Product Name", CopyProductName_Click }, - { "File Version", CopyFileVersion_Click }, - { "Package Family Name", CopyPackageFamilyName_Click }, - { "SHA256 Hash", CopySHA256Hash_Click }, - { "SHA1 Hash", CopySHA1Hash_Click }, - { "Signing Scenario", CopySigningScenario_Click }, - { "File Path", CopyFilePath_Click }, - { "SHA1 Page Hash", CopySHA1PageHash_Click }, - { "SHA256 Page Hash", CopySHA256PageHash_Click }, - { "Has WHQL Signer", CopyHasWHQLSigner_Click }, - { "File Publishers", CopyFilePublishersToDisplay_Click }, - { "Is ECC Signed", CopyIsECCSigned_Click }, - { "Opus Data", CopyOpus_Click } - }; - - // Add menu items with specific click events for each column - foreach (DataGridColumn column in FileIdentitiesDataGrid.Columns) - { - string headerText = column.Header.ToString()!; - - if (copyActions.TryGetValue(headerText, out RoutedEventHandler? value)) - { - // Create a new MenuFlyout Item - MenuFlyoutItem menuItem = new() { Text = $"Copy {headerText}" }; - - // Set the click event for the menu item - menuItem.Click += value; - - // Add the menu item to the submenu - CopyIndividualItemsSubMenu.Items.Add(menuItem); - } - } - } - - // Click event handlers for each property - private void CopyFileName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FileName); - private void CopySignatureStatus_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SignatureStatus.ToString()); - private void CopyOriginalFileName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.OriginalFileName); - private void CopyInternalName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.InternalName); - private void CopyFileDescription_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FileDescription); - private void CopyProductName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.ProductName); - private void CopyFileVersion_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FileVersion?.ToString()); - private void CopyPackageFamilyName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.PackageFamilyName); - private void CopySHA256Hash_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SHA256Hash); - private void CopySHA1Hash_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SHA1Hash); - private void CopySigningScenario_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SISigningScenario.ToString()); - private void CopyFilePath_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FilePath); - private void CopySHA1PageHash_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SHA1PageHash); - private void CopySHA256PageHash_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SHA256PageHash); - private void CopyHasWHQLSigner_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.HasWHQLSigner.ToString()); - private void CopyFilePublishersToDisplay_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FilePublishersToDisplay); - private void CopyIsECCSigned_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.IsECCSigned.ToString()); - private void CopyOpus_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.Opus); - - - /// - /// Helper method to copy a specified property to clipboard without reflection - /// - /// Function that retrieves the desired property value as a string - private void CopyToClipboard(Func getProperty) - { - if (FileIdentitiesDataGrid.SelectedItem is FileIdentity selectedItem) - { - string? propertyValue = getProperty(selectedItem); - if (propertyValue is not null) - { - DataPackage dataPackage = new(); - dataPackage.SetText(propertyValue); - Clipboard.SetContent(dataPackage); - } - } - } - - - /// /// Updates the total logs count displayed on the UI /// @@ -464,7 +654,5 @@ internal void UpdateTotalFiles(bool? Zero = null) { TotalCountOfTheFilesTextBox.Text = $"Total files: {CreateSupplementalPolicy.Instance.filesAndFoldersScanResults.Count}"; } - - } } diff --git a/AppControl Manager/Pages/EventLogsPolicyCreation.xaml b/AppControl Manager/Pages/EventLogsPolicyCreation.xaml index e43027838..34f53fb79 100644 --- a/AppControl Manager/Pages/EventLogsPolicyCreation.xaml +++ b/AppControl Manager/Pages/EventLogsPolicyCreation.xaml @@ -8,15 +8,18 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:ui="using:CommunityToolkit.WinUI" xmlns:controls="using:CommunityToolkit.WinUI.Controls" - xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls" + xmlns:intelgathering="using:AppControlManager.IntelGathering" + xmlns:interactivity="using:Microsoft.Xaml.Interactivity" + xmlns:behaviors="using:CommunityToolkit.WinUI.Behaviors" + x:Name="EventLogsPolicyCreationXAML" xmlns:animations="using:CommunityToolkit.WinUI.Animations" mc:Ignorable="d"> @@ -130,21 +133,21 @@ + HorizontalAlignment="Stretch" + SelectedIndex="1" SelectionChanged="SegmentedControl_SelectionChanged"> + Tag="AddToPolicy" Width="160" Icon="{ui:FontIcon Glyph=}" /> + Tag="BasePolicyFile" Width="160" Icon="{ui:FontIcon Glyph=}"/> + Tag="BaseGUID" Width="130" Icon="{ui:FontIcon Glyph=}"/> + animations:Implicit.ShowAnimations="{StaticResource ShowTransitions}" + Style="{StaticResource PanelStyle}"> Browse for a XML policy file to add the logs to @@ -156,43 +159,36 @@ + animations:Implicit.ShowAnimations="{StaticResource ShowTransitions}" + Style="{StaticResource PanelStyle}"> Browse for a base - policy XML file that this Supplemental policy will belong to - + policy XML file that this Supplemental policy will belong to + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/AppControl Manager/Pages/EventLogsPolicyCreation.xaml.cs b/AppControl Manager/Pages/EventLogsPolicyCreation.xaml.cs index 4e9ed3d1d..8deafbe1e 100644 --- a/AppControl Manager/Pages/EventLogsPolicyCreation.xaml.cs +++ b/AppControl Manager/Pages/EventLogsPolicyCreation.xaml.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.ComponentModel; using System.IO; using System.Linq; using System.Text; @@ -9,21 +10,532 @@ using AppControlManager.Main; using AppControlManager.Others; using AppControlManager.XMLOps; -using CommunityToolkit.WinUI.UI.Controls; using Microsoft.UI.Input; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Input; using Microsoft.UI.Xaml.Navigation; using Windows.ApplicationModel.DataTransfer; +using WinRT; namespace AppControlManager.Pages; -public sealed partial class EventLogsPolicyCreation : Page +// Since the columns for data in the ItemTemplate use "Binding" instead of "x:Bind", we need to use [GeneratedBindableCustomProperty] for them to work properly +[GeneratedBindableCustomProperty] +public sealed partial class EventLogsPolicyCreation : Page, INotifyPropertyChanged { - // To store the FileIdentities displayed on the DataGrid - // Binding happens on the XAML but methods related to search update the ItemSource of the DataGrid from code behind otherwise there will not be an expected result + #region LISTVIEW IMPLEMENTATIONS + + public event PropertyChangedEventHandler? PropertyChanged; + private void OnPropertyChanged(string propertyName) => + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + + // Properties to hold each columns' width. + private GridLength _columnWidth1; + public GridLength ColumnWidth1 + { + get => _columnWidth1; + set { _columnWidth1 = value; OnPropertyChanged(nameof(ColumnWidth1)); } + } + + private GridLength _columnWidth2; + public GridLength ColumnWidth2 + { + get => _columnWidth2; + set { _columnWidth2 = value; OnPropertyChanged(nameof(ColumnWidth2)); } + } + + private GridLength _columnWidth3; + public GridLength ColumnWidth3 + { + get => _columnWidth3; + set { _columnWidth3 = value; OnPropertyChanged(nameof(ColumnWidth3)); } + } + + private GridLength _columnWidth4; + public GridLength ColumnWidth4 + { + get => _columnWidth4; + set { _columnWidth4 = value; OnPropertyChanged(nameof(ColumnWidth4)); } + } + + private GridLength _columnWidth5; + public GridLength ColumnWidth5 + { + get => _columnWidth5; + set { _columnWidth5 = value; OnPropertyChanged(nameof(ColumnWidth5)); } + } + + private GridLength _columnWidth6; + public GridLength ColumnWidth6 + { + get => _columnWidth6; + set { _columnWidth6 = value; OnPropertyChanged(nameof(ColumnWidth6)); } + } + + private GridLength _columnWidth7; + public GridLength ColumnWidth7 + { + get => _columnWidth7; + set { _columnWidth7 = value; OnPropertyChanged(nameof(ColumnWidth7)); } + } + + private GridLength _columnWidth8; + public GridLength ColumnWidth8 + { + get => _columnWidth8; + set { _columnWidth8 = value; OnPropertyChanged(nameof(ColumnWidth8)); } + } + + private GridLength _columnWidth9; + public GridLength ColumnWidth9 + { + get => _columnWidth9; + set { _columnWidth9 = value; OnPropertyChanged(nameof(ColumnWidth9)); } + } + + private GridLength _columnWidth10; + public GridLength ColumnWidth10 + { + get => _columnWidth10; + set { _columnWidth10 = value; OnPropertyChanged(nameof(ColumnWidth10)); } + } + + private GridLength _columnWidth11; + public GridLength ColumnWidth11 + { + get => _columnWidth11; + set { _columnWidth11 = value; OnPropertyChanged(nameof(ColumnWidth11)); } + } + + private GridLength _columnWidth12; + public GridLength ColumnWidth12 + { + get => _columnWidth12; + set { _columnWidth12 = value; OnPropertyChanged(nameof(ColumnWidth12)); } + } + + private GridLength _columnWidth13; + public GridLength ColumnWidth13 + { + get => _columnWidth13; + set { _columnWidth13 = value; OnPropertyChanged(nameof(ColumnWidth13)); } + } + + private GridLength _columnWidth14; + public GridLength ColumnWidth14 + { + get => _columnWidth14; + set { _columnWidth14 = value; OnPropertyChanged(nameof(ColumnWidth14)); } + } + + private GridLength _columnWidth15; + public GridLength ColumnWidth15 + { + get => _columnWidth15; + set { _columnWidth15 = value; OnPropertyChanged(nameof(ColumnWidth15)); } + } + + private GridLength _columnWidth16; + public GridLength ColumnWidth16 + { + get => _columnWidth16; + set { _columnWidth16 = value; OnPropertyChanged(nameof(ColumnWidth16)); } + } + + private GridLength _columnWidth17; + public GridLength ColumnWidth17 + { + get => _columnWidth17; + set { _columnWidth17 = value; OnPropertyChanged(nameof(ColumnWidth17)); } + } + + private GridLength _columnWidth18; + public GridLength ColumnWidth18 + { + get => _columnWidth18; + set { _columnWidth18 = value; OnPropertyChanged(nameof(ColumnWidth18)); } + } + + private GridLength _columnWidth19; + public GridLength ColumnWidth19 + { + get => _columnWidth19; + set { _columnWidth19 = value; OnPropertyChanged(nameof(ColumnWidth19)); } + } + + private GridLength _columnWidth20; + public GridLength ColumnWidth20 + { + get => _columnWidth20; + set { _columnWidth20 = value; OnPropertyChanged(nameof(ColumnWidth20)); } + } + + private GridLength _columnWidth21; + public GridLength ColumnWidth21 + { + get => _columnWidth21; + set { _columnWidth21 = value; OnPropertyChanged(nameof(ColumnWidth21)); } + } + + /// + /// Calculates the maximum required width for each column (including header text) + /// and assigns the value (with a little extra padding) to the corresponding property. + /// It should always run once ALL the data have been added to the ObservableCollection that is the ItemsSource of the ListView + /// And only after this method, the ItemsSource must be assigned to the ListView. + /// + internal void CalculateColumnWidths() + { + + // Measure header text widths first. + double maxWidth1 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("FileNameHeader/Text")); + double maxWidth2 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("TimeCreatedHeader/Text")); + double maxWidth3 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SignatureStatusHeader/Text")); + double maxWidth4 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("ActionHeader/Text")); + double maxWidth5 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("OriginalFileNameHeader/Text")); + double maxWidth6 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("InternalNameHeader/Text")); + double maxWidth7 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("FileDescriptionHeader/Text")); + double maxWidth8 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("ProductNameHeader/Text")); + double maxWidth9 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("FileVersionHeader/Text")); + double maxWidth10 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("PackageFamilyNameHeader/Text")); + double maxWidth11 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SHA256HashHeader/Text")); + double maxWidth12 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SHA1HashHeader/Text")); + double maxWidth13 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SigningScenarioHeader/Text")); + double maxWidth14 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("FilePathHeader/Text")); + double maxWidth15 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SHA1PageHashHeader/Text")); + double maxWidth16 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SHA256PageHashHeader/Text")); + double maxWidth17 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("HasWHQLSignerHeader/Text")); + double maxWidth18 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("FilePublishersHeader/Text")); + double maxWidth19 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("OpusDataHeader/Text")); + double maxWidth20 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("PolicyGUIDHeader/Text")); + double maxWidth21 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("PolicyNameHeader/Text")); + + // Iterate over all items to determine the widest string for each column. + foreach (FileIdentity item in FileIdentities) + { + double w1 = ListViewUIHelpers.MeasureTextWidth(item.FileName); + if (w1 > maxWidth1) maxWidth1 = w1; + + double w2 = ListViewUIHelpers.MeasureTextWidth(item.TimeCreated.ToString()); + if (w2 > maxWidth2) maxWidth2 = w2; + + double w3 = ListViewUIHelpers.MeasureTextWidth(item.SignatureStatus.ToString()); + if (w3 > maxWidth3) maxWidth3 = w3; + + double w4 = ListViewUIHelpers.MeasureTextWidth(item.Action.ToString()); + if (w4 > maxWidth4) maxWidth4 = w4; + + double w5 = ListViewUIHelpers.MeasureTextWidth(item.OriginalFileName); + if (w5 > maxWidth5) maxWidth5 = w5; + + double w6 = ListViewUIHelpers.MeasureTextWidth(item.InternalName); + if (w6 > maxWidth6) maxWidth6 = w6; + + double w7 = ListViewUIHelpers.MeasureTextWidth(item.FileDescription); + if (w7 > maxWidth7) maxWidth7 = w7; + + double w8 = ListViewUIHelpers.MeasureTextWidth(item.ProductName); + if (w8 > maxWidth8) maxWidth8 = w8; + + double w9 = ListViewUIHelpers.MeasureTextWidth(item.FileVersion?.ToString()); + if (w9 > maxWidth9) maxWidth9 = w9; + + double w10 = ListViewUIHelpers.MeasureTextWidth(item.PackageFamilyName); + if (w10 > maxWidth10) maxWidth10 = w10; + + double w11 = ListViewUIHelpers.MeasureTextWidth(item.SHA256Hash); + if (w11 > maxWidth11) maxWidth11 = w11; + + double w12 = ListViewUIHelpers.MeasureTextWidth(item.SHA1Hash); + if (w12 > maxWidth12) maxWidth12 = w12; + + double w13 = ListViewUIHelpers.MeasureTextWidth(item.SISigningScenario.ToString()); + if (w13 > maxWidth13) maxWidth13 = w13; + + double w14 = ListViewUIHelpers.MeasureTextWidth(item.FilePath); + if (w14 > maxWidth14) maxWidth14 = w14; + + double w15 = ListViewUIHelpers.MeasureTextWidth(item.SHA1PageHash); + if (w15 > maxWidth15) maxWidth15 = w15; + + double w16 = ListViewUIHelpers.MeasureTextWidth(item.SHA256PageHash); + if (w16 > maxWidth16) maxWidth16 = w16; + + double w17 = ListViewUIHelpers.MeasureTextWidth(item.HasWHQLSigner.ToString()); + if (w17 > maxWidth17) maxWidth17 = w17; + + double w18 = ListViewUIHelpers.MeasureTextWidth(item.FilePublishersToDisplay); + if (w18 > maxWidth18) maxWidth18 = w18; + + double w19 = ListViewUIHelpers.MeasureTextWidth(item.Opus); + if (w19 > maxWidth19) maxWidth19 = w19; + + double w20 = ListViewUIHelpers.MeasureTextWidth(item.PolicyGUID.ToString()); + if (w20 > maxWidth20) maxWidth20 = w20; + + double w21 = ListViewUIHelpers.MeasureTextWidth(item.PolicyName); + if (w21 > maxWidth21) maxWidth21 = w21; + } + + // Set the column width properties. + ColumnWidth1 = new GridLength(maxWidth1); + ColumnWidth2 = new GridLength(maxWidth2); + ColumnWidth3 = new GridLength(maxWidth3); + ColumnWidth4 = new GridLength(maxWidth4); + ColumnWidth5 = new GridLength(maxWidth5); + ColumnWidth6 = new GridLength(maxWidth6); + ColumnWidth7 = new GridLength(maxWidth7); + ColumnWidth8 = new GridLength(maxWidth8); + ColumnWidth9 = new GridLength(maxWidth9); + ColumnWidth10 = new GridLength(maxWidth10); + ColumnWidth11 = new GridLength(maxWidth11); + ColumnWidth12 = new GridLength(maxWidth12); + ColumnWidth13 = new GridLength(maxWidth13); + ColumnWidth14 = new GridLength(maxWidth14); + ColumnWidth15 = new GridLength(maxWidth15); + ColumnWidth16 = new GridLength(maxWidth16); + ColumnWidth17 = new GridLength(maxWidth17); + ColumnWidth18 = new GridLength(maxWidth18); + ColumnWidth19 = new GridLength(maxWidth19); + ColumnWidth20 = new GridLength(maxWidth20); + ColumnWidth21 = new GridLength(maxWidth21); + } + + + /// + /// Copies the selected rows to the clipboard in a formatted manner, with each property labeled for clarity. + /// + /// The event sender. + /// The event arguments. + private void ListViewFlyoutMenuCopy_Click(object sender, RoutedEventArgs e) + { + // Check if there are selected items in the ListView + if (FileIdentitiesListView.SelectedItems.Count > 0) + { + // Initialize StringBuilder to store all selected rows' data with labels + StringBuilder dataBuilder = new(); + + // Loop through each selected item in the ListView + foreach (var selectedItem in FileIdentitiesListView.SelectedItems) + { + if (selectedItem is FileIdentity obj) + + // Append each row's formatted data to the StringBuilder + _ = dataBuilder.AppendLine(ListViewUIHelpers.ConvertRowToText(obj)); + + // Add a separator between rows for readability in multi-row copies + _ = dataBuilder.AppendLine(new string('-', 50)); + } + + // Create a DataPackage to hold the text data + DataPackage dataPackage = new(); + + // Set the formatted text as the content of the DataPackage + dataPackage.SetText(dataBuilder.ToString()); + + // Copy the DataPackage content to the clipboard + Clipboard.SetContent(dataPackage); + } + } + + + // Click event handlers for each property + private void CopyFileName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FileName); + private void CopyTimeCreated_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.TimeCreated.ToString()); + private void CopySignatureStatus_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SignatureStatus.ToString()); + private void CopyAction_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.Action.ToString()); + private void CopyOriginalFileName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.OriginalFileName); + private void CopyInternalName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.InternalName); + private void CopyFileDescription_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FileDescription); + private void CopyProductName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.ProductName); + private void CopyFileVersion_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FileVersion?.ToString()); + private void CopyPackageFamilyName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.PackageFamilyName); + private void CopySHA256Hash_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SHA256Hash); + private void CopySHA1Hash_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SHA1Hash); + private void CopySigningScenario_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SISigningScenario.ToString()); + private void CopyFilePath_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FilePath); + private void CopySHA1PageHash_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SHA1PageHash); + private void CopySHA256PageHash_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SHA256PageHash); + private void CopyHasWHQLSigner_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.HasWHQLSigner.ToString()); + private void CopyFilePublishers_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FilePublishersToDisplay); + private void CopyOpusData_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.Opus); + private void CopyPolicyGUID_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.PolicyGUID.ToString()); + private void CopyPolicyName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.PolicyName); + + /// + /// Helper method to copy a specified property to clipboard without reflection + /// + /// Function that retrieves the desired property value as a string + private void CopyToClipboard(Func getProperty) + { + if (FileIdentitiesListView.SelectedItem is FileIdentity selectedItem) + { + string? propertyValue = getProperty(selectedItem); + if (propertyValue is not null) + { + DataPackage dataPackage = new(); + dataPackage.SetText(propertyValue); + Clipboard.SetContent(dataPackage); + } + } + } + + // Event handlers for each sort button + private void ColumnSortingButton_FileName_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.FileName); + } + + private void ColumnSortingButton_TimeCreated_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.TimeCreated); + } + + private void ColumnSortingButton_SignatureStatus_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.SignatureStatus); + } + + private void ColumnSortingButton_Action_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.Action); + } + + private void ColumnSortingButton_OriginalFileName_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.OriginalFileName); + } + private void ColumnSortingButton_InternalName_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.InternalName); + } + private void ColumnSortingButton_FileDescription_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.FileDescription); + } + private void ColumnSortingButton_ProductName_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.ProductName); + } + private void ColumnSortingButton_FileVersion_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.FileVersion); + } + private void ColumnSortingButton_PackageFamilyName_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.PackageFamilyName); + } + private void ColumnSortingButton_SHA256Hash_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.SHA256Hash); + } + private void ColumnSortingButton_SHA1Hash_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.SHA1Hash); + } + private void ColumnSortingButton_SigningScenario_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.SISigningScenario); + } + private void ColumnSortingButton_FilePath_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.FilePath); + } + private void ColumnSortingButton_SHA1PageHash_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.SHA1PageHash); + } + private void ColumnSortingButton_SHA256PageHash_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.SHA256PageHash); + } + private void ColumnSortingButton_HasWHQLSigner_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.HasWHQLSigner); + } + private void ColumnSortingButton_FilePublishers_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.FilePublishersToDisplay); + } + private void ColumnSortingButton_OpusData_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.Opus); + } + private void ColumnSortingButton_PolicyID_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.PolicyGUID); + } + private void ColumnSortingButton_PolicyName_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.PolicyName); + } + + /// + /// Performs data sorting + /// + /// + /// + private void SortColumn(Func keySelector) + { + // Determine if a search filter is active. + bool isSearchEmpty = string.IsNullOrWhiteSpace(SearchBox.Text); + // Use either the full list AllFileIdentities or the current display list. + var collectionToSort = isSearchEmpty ? AllFileIdentities : [.. FileIdentities]; + + if (SortingDirectionToggle.IsChecked) + { + // Sort in descending order. + FileIdentities = [.. collectionToSort.OrderByDescending(keySelector)]; + } + else + { + // Sort in ascending order. + FileIdentities = [.. collectionToSort.OrderBy(keySelector)]; + } + + // Refresh the ItemsSource so the UI updates. + FileIdentitiesListView.ItemsSource = FileIdentities; + } + + + /// + /// Converts the properties of a FileIdentity row into a labeled, formatted string for copying to clipboard. + /// + /// The selected FileIdentity row from the ListView. + /// A formatted string of the row's properties with labels. + private static string ConvertRowToText(FileIdentity row) + { + // Use StringBuilder to format each property with its label for easy reading + return new StringBuilder() + .AppendLine($"File Name: {row.FileName}") + .AppendLine($"Time Created: {row.TimeCreated}") + .AppendLine($"Signature Status: {row.SignatureStatus}") + .AppendLine($"Action: {row.Action}") + .AppendLine($"Original File Name: {row.OriginalFileName}") + .AppendLine($"Internal Name: {row.InternalName}") + .AppendLine($"File Description: {row.FileDescription}") + .AppendLine($"Product Name: {row.ProductName}") + .AppendLine($"File Version: {row.FileVersion}") + .AppendLine($"Package Family Name: {row.PackageFamilyName}") + .AppendLine($"SHA256 Hash: {row.SHA256Hash}") + .AppendLine($"SHA1 Hash: {row.SHA1Hash}") + .AppendLine($"SHA256 Flat Hash: {row.SHA256FlatHash}") + .AppendLine($"SHA1 Flat Hash: {row.SHA1FlatHash}") + .AppendLine($"Signing Scenario: {row.SISigningScenario}") + .AppendLine($"File Path: {row.FilePath}") + .AppendLine($"Computer Name: {row.ComputerName}") + .AppendLine($"Policy GUID: {row.PolicyGUID}") + .AppendLine($"Policy Name: {row.PolicyName}") + .AppendLine($"File Publishers: {row.FilePublishersToDisplay}") + .ToString(); + } + #endregion + + + + // To store the FileIdentities displayed on the ListView + // Binding happens on the XAML but methods related to search update the ItemSource of the ListView from code behind otherwise there will not be an expected result internal ObservableCollection FileIdentities { get; set; } // Store all outputs for searching, used as a temporary storage for filtering @@ -59,29 +571,6 @@ public EventLogsPolicyCreation() FilterByDateCalendarPicker.DateChanged += FilterByDateCalendarPicker_DateChanged; } - - #region - - // Without the following steps, when the user begins data fetching process and then navigates away from this page - // Upon arrival at this page again, the DataGrid loses its virtualization, causing the UI to hang for extended periods of time - // But after nullifying DataGrid's ItemsSource when page is navigated from and reassigning it when page is navigated to, - // We tackle that problem. Data will sill be stored in the ObservableCollection when page is not in focus, - // But DataGrid's source will pick them up only when page is navigated to. - protected override void OnNavigatedTo(NavigationEventArgs e) - { - base.OnNavigatedTo(e); - FileIdentitiesDataGrid.ItemsSource = FileIdentities; - } - - protected override void OnNavigatedFrom(NavigationEventArgs e) - { - base.OnNavigatedFrom(e); - FileIdentitiesDataGrid.ItemsSource = null; - } - - #endregion - - /// /// Event handler for the CalendarDatePicker date changed event /// @@ -150,21 +639,20 @@ private void ApplyFilters() FileIdentities.Clear(); // Populate the ObservableCollection with the filtered results - // This triggers the UI to update the DataGrid based on the filtered data + // This triggers the UI to update the ListView based on the filtered data foreach (FileIdentity result in filteredResults) { FileIdentities.Add(result); } - // Explicitly set the DataGrid's ItemsSource to ensure the data refreshes - FileIdentitiesDataGrid.ItemsSource = FileIdentities; + // Explicitly set the ListView's ItemsSource to ensure the data refreshes + FileIdentitiesListView.ItemsSource = FileIdentities; // Update any visual or text element showing the total logs count UpdateTotalLogs(); } - /// /// Event handler for the ScanLogs click /// @@ -182,7 +670,6 @@ private async void ScanLogs_Click(object sender, RoutedEventArgs e) ScanLogsProgressRing.IsActive = true; ScanLogsProgressRing.Visibility = Visibility.Visible; - // Disable the Policy creator button while scan is being performed CreatePolicyButton.IsEnabled = false; @@ -204,8 +691,10 @@ private async void ScanLogs_Click(object sender, RoutedEventArgs e) } UpdateTotalLogs(); - } + CalculateColumnWidths(); + FileIdentitiesListView.ItemsSource = FileIdentities; + } finally { // Enable the button again @@ -225,7 +714,6 @@ private async void ScanLogs_Click(object sender, RoutedEventArgs e) } - /// /// Event handler for the select Code Integrity EVTX file path button /// @@ -299,144 +787,8 @@ private void ClearDataButton_Click(object sender, RoutedEventArgs e) UpdateTotalLogs(true); } - - - // https://learn.microsoft.com/en-us/windows/communitytoolkit/controls/datagrid_guidance/group_sort_filter - // Column sorting logic for the entire DataGrid - private void FileIdentitiesDataGrid_Sorting(object sender, DataGridColumnEventArgs e) - { - // Sort the column based on its tag and current sort direction - if (string.Equals(e.Column.Tag?.ToString(), "FileName", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.FileName); - } - else if (string.Equals(e.Column.Tag?.ToString(), "TimeCreated", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.TimeCreated); - } - else if (string.Equals(e.Column.Tag?.ToString(), "SignatureStatus", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.SignatureStatus); - } - else if (string.Equals(e.Column.Tag?.ToString(), "Action", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.Action); - } - else if (string.Equals(e.Column.Tag?.ToString(), "OriginalFileName", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.OriginalFileName); - } - else if (string.Equals(e.Column.Tag?.ToString(), "InternalName", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.InternalName); - } - else if (string.Equals(e.Column.Tag?.ToString(), "FileDescription", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.FileDescription); - } - else if (string.Equals(e.Column.Tag?.ToString(), "ProductName", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.ProductName); - } - else if (string.Equals(e.Column.Tag?.ToString(), "FileVersion", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.FileVersion); - } - else if (string.Equals(e.Column.Tag?.ToString(), "PackageFamilyName", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.PackageFamilyName); - } - else if (string.Equals(e.Column.Tag?.ToString(), "SHA256Hash", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.SHA256Hash); - } - else if (string.Equals(e.Column.Tag?.ToString(), "SHA1Hash", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.SHA1Hash); - } - else if (string.Equals(e.Column.Tag?.ToString(), "SHA256FlatHash", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.SHA256FlatHash); - } - else if (string.Equals(e.Column.Tag?.ToString(), "SHA1FlatHash", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.SHA1FlatHash); - } - else if (string.Equals(e.Column.Tag?.ToString(), "SISigningScenario", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.SISigningScenario); - } - else if (string.Equals(e.Column.Tag?.ToString(), "FilePath", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.FilePath); - } - else if (string.Equals(e.Column.Tag?.ToString(), "ComputerName", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.ComputerName); - } - else if (string.Equals(e.Column.Tag?.ToString(), "PolicyGUID", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.PolicyGUID); - } - else if (string.Equals(e.Column.Tag?.ToString(), "PolicyName", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.PolicyName); - } - else if (string.Equals(e.Column.Tag?.ToString(), "FilePublishersToDisplay", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.FilePublishersToDisplay); - } - - // Clear SortDirection for other columns - foreach (DataGridColumn column in FileIdentitiesDataGrid.Columns) - { - if (column != e.Column) - { - column.SortDirection = null; - } - } - } - - /// - /// Helper method for sorting any column on the DataGird - /// - /// - /// - /// - private void SortColumn(DataGridColumnEventArgs e, Func keySelector) - { - // Check if the search box is empty or not - bool isSearchEmpty = string.IsNullOrWhiteSpace(SearchBox.Text); - - // Get the collection to sort based on the search box status - // Allowing us to sort only the items in the search results - List collectionToSort = isSearchEmpty ? AllFileIdentities : [.. FileIdentities]; - - // Perform the sorting based on the current SortDirection (ascending or descending) - if (e.Column.SortDirection is null || e.Column.SortDirection == DataGridSortDirection.Ascending) - { - // Descending: custom order depending on column type - FileIdentities = [.. collectionToSort.OrderByDescending(keySelector)]; - - // Set the column direction to Descending - e.Column.SortDirection = DataGridSortDirection.Descending; - } - else - { - // Ascending: custom order depending on column type - FileIdentities = [.. collectionToSort.OrderBy(keySelector)]; - e.Column.SortDirection = DataGridSortDirection.Ascending; - } - - // Update the ItemsSource of the DataGrid - // Required for sort + search to work properly, even though binding to the ObservableCollection already happens in XAML - FileIdentitiesDataGrid.ItemsSource = FileIdentities; - } - - - /// - /// Selects all of the displayed rows on the DataGrid + /// Selects all of the displayed rows on the ListView /// /// /// @@ -445,29 +797,26 @@ private void SelectAll_Click(object sender, RoutedEventArgs e) _ = DispatcherQueue.TryEnqueue(() => { // Clear existing selections - FileIdentitiesDataGrid.SelectedItems.Clear(); + FileIdentitiesListView.SelectedItems.Clear(); foreach (FileIdentity fileIdentity in FileIdentities) { - _ = FileIdentitiesDataGrid.SelectedItems.Add(fileIdentity); // Select each item + FileIdentitiesListView.SelectedItems.Add(fileIdentity); // Select each item } }); } - /// - /// De-selects all of the displayed rows on the DataGrid + /// De-selects all of the displayed rows on the ListView /// /// /// private void DeSelectAll_Click(object sender, RoutedEventArgs e) { - FileIdentitiesDataGrid.SelectedItems.Clear(); // Deselect all rows by clearing SelectedItems + FileIdentitiesListView.SelectedItems.Clear(); // Deselect all rows by clearing SelectedItems } - - /// /// Deletes the selected row from the results /// @@ -476,7 +825,7 @@ private void DeSelectAll_Click(object sender, RoutedEventArgs e) private void DataGridFlyoutMenuDelete_Click(object sender, RoutedEventArgs e) { // Collect the selected items to delete - List itemsToDelete = [.. FileIdentitiesDataGrid.SelectedItems.Cast()]; + List itemsToDelete = [.. FileIdentitiesListView.SelectedItems.Cast()]; // Remove each selected item from the FileIdentities collection foreach (FileIdentity item in itemsToDelete) @@ -488,179 +837,6 @@ private void DataGridFlyoutMenuDelete_Click(object sender, RoutedEventArgs e) UpdateTotalLogs(); } - - - /// - /// Copies the selected rows to the clipboard in a formatted manner, with each property labeled for clarity. - /// - /// The event sender. - /// The event arguments. - private void DataGridFlyoutMenuCopy_Click(object sender, RoutedEventArgs e) - { - // Check if there are selected items in the DataGrid - if (FileIdentitiesDataGrid.SelectedItems.Count > 0) - { - // Initialize StringBuilder to store all selected rows' data with labels - StringBuilder dataBuilder = new(); - - // Loop through each selected item in the DataGrid - foreach (FileIdentity selectedItem in FileIdentitiesDataGrid.SelectedItems) - { - // Append each row's formatted data to the StringBuilder - _ = dataBuilder.AppendLine(ConvertRowToText(selectedItem)); - - // Add a separator between rows for readability in multi-row copies - _ = dataBuilder.AppendLine(new string('-', 50)); - } - - // Create a DataPackage to hold the text data - DataPackage dataPackage = new(); - - // Set the formatted text as the content of the DataPackage - dataPackage.SetText(dataBuilder.ToString()); - - // Copy the DataPackage content to the clipboard - Clipboard.SetContent(dataPackage); - } - } - - /// - /// Converts the properties of a FileIdentity row into a labeled, formatted string for copying to clipboard. - /// - /// The selected FileIdentity row from the DataGrid. - /// A formatted string of the row's properties with labels. - private static string ConvertRowToText(FileIdentity row) - { - // Use StringBuilder to format each property with its label for easy reading - return new StringBuilder() - .AppendLine($"File Name: {row.FileName}") - .AppendLine($"Time Created: {row.TimeCreated}") - .AppendLine($"Signature Status: {row.SignatureStatus}") - .AppendLine($"Action: {row.Action}") - .AppendLine($"Original File Name: {row.OriginalFileName}") - .AppendLine($"Internal Name: {row.InternalName}") - .AppendLine($"File Description: {row.FileDescription}") - .AppendLine($"Product Name: {row.ProductName}") - .AppendLine($"File Version: {row.FileVersion}") - .AppendLine($"Package Family Name: {row.PackageFamilyName}") - .AppendLine($"SHA256 Hash: {row.SHA256Hash}") - .AppendLine($"SHA1 Hash: {row.SHA1Hash}") - .AppendLine($"SHA256 Flat Hash: {row.SHA256FlatHash}") - .AppendLine($"SHA1 Flat Hash: {row.SHA1FlatHash}") - .AppendLine($"Signing Scenario: {row.SISigningScenario}") - .AppendLine($"File Path: {row.FilePath}") - .AppendLine($"Computer Name: {row.ComputerName}") - .AppendLine($"Policy GUID: {row.PolicyGUID}") - .AppendLine($"Policy Name: {row.PolicyName}") - .AppendLine($"File Publishers: {row.FilePublishersToDisplay}") - .ToString(); - } - - - - /// - /// Event handler for the Copy Individual Items SubMenu. It will populate the submenu items in the flyout of the data grid. - /// - /// - /// - private void FileIdentitiesDataGrid_Loaded(object sender, RoutedEventArgs e) - { - // Ensure the CopyIndividualItemsSubMenu is available - if (CopyIndividualItemsSubMenu is null) - { - return; - } - - // Clear any existing items to avoid duplication if reloaded - CopyIndividualItemsSubMenu.Items.Clear(); - - // Create a dictionary to map headers to their specific click event methods - Dictionary copyActions = new() - { - { "File Name", CopyFileName_Click }, - { "Time Created", CopyTimeCreated_Click }, - { "Signature Status", CopySignatureStatus_Click }, - { "Action", CopyAction_Click }, - { "Original File Name", CopyOriginalFileName_Click }, - { "Internal Name", CopyInternalName_Click }, - { "File Description", CopyFileDescription_Click }, - { "Product Name", CopyProductName_Click }, - { "File Version", CopyFileVersion_Click }, - { "Package Family Name", CopyPackageFamilyName_Click }, - { "SHA256 Hash", CopySHA256Hash_Click }, - { "SHA1 Hash", CopySHA1Hash_Click }, - { "SHA256 Flat Hash", CopySHA256FlatHash_Click }, - { "SHA1 Flat Hash", CopySHA1FlatHash_Click }, - { "Signing Scenario", CopySigningScenario_Click }, - { "File Path", CopyFilePath_Click }, - { "Computer Name", CopyComputerName_Click }, - { "Policy GUID", CopyPolicyGUID_Click }, - { "Policy Name", CopyPolicyName_Click }, - { "File Publishers", CopyFilePublishersToDisplay_Click } - }; - - // Add menu items with specific click events for each column - foreach (DataGridColumn column in FileIdentitiesDataGrid.Columns) - { - string headerText = column.Header.ToString()!; - - if (copyActions.TryGetValue(headerText, out RoutedEventHandler? value)) - { - // Create a new MenuFlyout Item - MenuFlyoutItem menuItem = new() { Text = $"Copy {headerText}" }; - - // Set the click event for the menu item - menuItem.Click += value; - - // Add the menu item to the submenu - CopyIndividualItemsSubMenu.Items.Add(menuItem); - } - } - } - - // Click event handlers for each property - private void CopyFileName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FileName); - private void CopyTimeCreated_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.TimeCreated.ToString()); - private void CopySignatureStatus_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SignatureStatus.ToString()); - private void CopyAction_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.Action.ToString()); - private void CopyOriginalFileName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.OriginalFileName); - private void CopyInternalName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.InternalName); - private void CopyFileDescription_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FileDescription); - private void CopyProductName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.ProductName); - private void CopyFileVersion_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FileVersion?.ToString()); - private void CopyPackageFamilyName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.PackageFamilyName); - private void CopySHA256Hash_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SHA256Hash); - private void CopySHA1Hash_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SHA1Hash); - private void CopySHA256FlatHash_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SHA256FlatHash); - private void CopySHA1FlatHash_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SHA1FlatHash); - private void CopySigningScenario_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SISigningScenario.ToString()); - private void CopyFilePath_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FilePath); - private void CopyComputerName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.ComputerName); - private void CopyPolicyGUID_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.PolicyGUID.ToString()); - private void CopyPolicyName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.PolicyName); - private void CopyFilePublishersToDisplay_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FilePublishersToDisplay.ToString()); - - - /// - /// Helper method to copy a specified property to clipboard without reflection - /// - /// Function that retrieves the desired property value as a string - private void CopyToClipboard(Func getProperty) - { - if (FileIdentitiesDataGrid.SelectedItem is FileIdentity selectedItem) - { - string? propertyValue = getProperty(selectedItem); - if (propertyValue is not null) - { - DataPackage dataPackage = new(); - dataPackage.SetText(propertyValue); - Clipboard.SetContent(dataPackage); - } - } - } - - - /// /// Updates the total logs count displayed on the UI /// @@ -788,23 +964,24 @@ private async void CreatePolicyButton_Click(SplitButton sender, SplitButtonClick // All of the File Identities that will be used to put in the policy XML file List SelectedLogs = []; - // Check if there are selected items in the DataGrid - if (FileIdentitiesDataGrid.SelectedItems.Count > 0) + // Check if there are selected items in the ListView + if (FileIdentitiesListView.SelectedItems.Count > 0) { // convert every selected item to FileIdentity and store it in the list - foreach (FileIdentity item in FileIdentitiesDataGrid.SelectedItems) + foreach (var item in FileIdentitiesListView.SelectedItems) { - SelectedLogs.Add(item); + if (item is FileIdentity item1) + { + SelectedLogs.Add(item1); + } } } - - // If no item was selected from the DataGrid, use everything in the ObservableCollection + // If no item was selected from the ListView, use everything in the ObservableCollection else { SelectedLogs = [.. FileIdentities]; } - // If user selected to deploy the policy // Need to retrieve it while we're still at the UI thread bool DeployAtTheEnd = DeployPolicyToggle.IsChecked; diff --git a/AppControl Manager/Pages/MDEAHPolicyCreation.xaml b/AppControl Manager/Pages/MDEAHPolicyCreation.xaml index a5ac642a7..d92a3416c 100644 --- a/AppControl Manager/Pages/MDEAHPolicyCreation.xaml +++ b/AppControl Manager/Pages/MDEAHPolicyCreation.xaml @@ -8,7 +8,10 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:ui="using:CommunityToolkit.WinUI" xmlns:controls="using:CommunityToolkit.WinUI.Controls" - xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls" + xmlns:intelgathering="using:AppControlManager.IntelGathering" + xmlns:interactivity="using:Microsoft.Xaml.Interactivity" + xmlns:behaviors="using:CommunityToolkit.WinUI.Behaviors" + x:Name="MDEAHPolicyCreationXAML" xmlns:animations="using:CommunityToolkit.WinUI.Animations" mc:Ignorable="d"> @@ -336,6 +339,45 @@ Spacing="8"> + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/AppControl Manager/Pages/StrictKernelPolicyScanResults.xaml.cs b/AppControl Manager/Pages/StrictKernelPolicyScanResults.xaml.cs index 85173ded4..188d10e5d 100644 --- a/AppControl Manager/Pages/StrictKernelPolicyScanResults.xaml.cs +++ b/AppControl Manager/Pages/StrictKernelPolicyScanResults.xaml.cs @@ -1,286 +1,267 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Linq; using System.Text; using AppControlManager.IntelGathering; -using CommunityToolkit.WinUI.UI.Controls; +using AppControlManager.Others; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Navigation; using Windows.ApplicationModel.DataTransfer; +using WinRT; namespace AppControlManager.Pages; -public sealed partial class StrictKernelPolicyScanResults : Page +// Since the columns for data in the ItemTemplate use "Binding" instead of "x:Bind", we need to use [GeneratedBindableCustomProperty] for them to work properly +[GeneratedBindableCustomProperty] +public sealed partial class StrictKernelPolicyScanResults : Page, INotifyPropertyChanged { - public StrictKernelPolicyScanResults() - { - this.InitializeComponent(); - } + private static StrictKernelPolicyScanResults? _instance; + internal ListView UIListView { get; private set; } - #region + #region LISTVIEW IMPLEMENTATIONS - // Without the following steps, when the user begins data fetching process and then navigates away from this page - // Upon arrival at this page again, the DataGrid loses its virtualization, causing the UI to hang for extended periods of time - // But after nullifying DataGrid's ItemsSource when page is navigated from and reassigning it when page is navigated to, - // We tackle that problem. Data will sill be stored in the ObservableCollection when page is not in focus, - // But DataGrid's source will pick them up only when page is navigated to. - protected override void OnNavigatedTo(NavigationEventArgs e) + public event PropertyChangedEventHandler? PropertyChanged; + private void OnPropertyChanged(string propertyName) => + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + + // Properties to hold each columns' width. + private GridLength _columnWidth1; + public GridLength ColumnWidth1 { - base.OnNavigatedTo(e); + get => _columnWidth1; + set { _columnWidth1 = value; OnPropertyChanged(nameof(ColumnWidth1)); } + } - FileIdentitiesDataGrid.ItemsSource = CreateSupplementalPolicy.Instance.ScanResults; - // Update the logs when user switches to this page - UpdateTotalFiles(); + private GridLength _columnWidth2; + public GridLength ColumnWidth2 + { + get => _columnWidth2; + set { _columnWidth2 = value; OnPropertyChanged(nameof(ColumnWidth2)); } } - protected override void OnNavigatedFrom(NavigationEventArgs e) + private GridLength _columnWidth3; + public GridLength ColumnWidth3 { - base.OnNavigatedFrom(e); - FileIdentitiesDataGrid.ItemsSource = null; + get => _columnWidth3; + set { _columnWidth3 = value; OnPropertyChanged(nameof(ColumnWidth3)); } } - #endregion + private GridLength _columnWidth4; + public GridLength ColumnWidth4 + { + get => _columnWidth4; + set { _columnWidth4 = value; OnPropertyChanged(nameof(ColumnWidth4)); } + } + private GridLength _columnWidth5; + public GridLength ColumnWidth5 + { + get => _columnWidth5; + set { _columnWidth5 = value; OnPropertyChanged(nameof(ColumnWidth5)); } + } + private GridLength _columnWidth6; + public GridLength ColumnWidth6 + { + get => _columnWidth6; + set { _columnWidth6 = value; OnPropertyChanged(nameof(ColumnWidth6)); } + } - /// - /// Event handler for the SearchBox text change - /// - private void SearchBox_TextChanged(object sender, TextChangedEventArgs e) + private GridLength _columnWidth7; + public GridLength ColumnWidth7 { - ApplyFilters(); + get => _columnWidth7; + set { _columnWidth7 = value; OnPropertyChanged(nameof(ColumnWidth7)); } } + private GridLength _columnWidth8; + public GridLength ColumnWidth8 + { + get => _columnWidth8; + set { _columnWidth8 = value; OnPropertyChanged(nameof(ColumnWidth8)); } + } - /// - /// Applies the date and search filters to the data grid - /// - private void ApplyFilters() + private GridLength _columnWidth9; + public GridLength ColumnWidth9 { + get => _columnWidth9; + set { _columnWidth9 = value; OnPropertyChanged(nameof(ColumnWidth9)); } + } - // Get the search term from the SearchBox, converting it to lowercase for case-insensitive searching - string searchTerm = SearchBox.Text.Trim().ToLowerInvariant(); + private GridLength _columnWidth10; + public GridLength ColumnWidth10 + { + get => _columnWidth10; + set { _columnWidth10 = value; OnPropertyChanged(nameof(ColumnWidth10)); } + } - // Start with all items from the complete list, 'AllFileIdentities' - // This list is used as the base set for filtering to preserve original data - IEnumerable filteredResults = CreateSupplementalPolicy.Instance.ScanResultsList.AsEnumerable(); + private GridLength _columnWidth11; + public GridLength ColumnWidth11 + { + get => _columnWidth11; + set { _columnWidth11 = value; OnPropertyChanged(nameof(ColumnWidth11)); } + } - // Apply the search filter if there is a non-empty search term - if (!string.IsNullOrWhiteSpace(searchTerm)) - { + private GridLength _columnWidth12; + public GridLength ColumnWidth12 + { + get => _columnWidth12; + set { _columnWidth12 = value; OnPropertyChanged(nameof(ColumnWidth12)); } + } - // Filter results further to match the search term across multiple properties, case-insensitively - filteredResults = filteredResults.Where(output => - (output.FileName is not null && output.FileName.Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) || - (output.SignatureStatus.ToString().Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) || - (output.OriginalFileName is not null && output.OriginalFileName.Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) || - (output.InternalName is not null && output.InternalName.Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) || - (output.FileDescription is not null && output.FileDescription.Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) || - (output.ProductName is not null && output.ProductName.Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) || - (output.FileVersion is not null && output.FileVersion.ToString().Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) || - (output.PackageFamilyName is not null && output.PackageFamilyName.Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) || - (output.SHA1PageHash is not null && output.SHA1PageHash.Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) || - (output.FilePath is not null && output.FilePath.Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) || - (output.SHA256Hash is not null && output.SHA256Hash.Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) || - output.FilePublishersToDisplay.Contains(searchTerm, StringComparison.OrdinalIgnoreCase) || - output.Opus.Contains(searchTerm, StringComparison.OrdinalIgnoreCase) - ); - } + private GridLength _columnWidth13; + public GridLength ColumnWidth13 + { + get => _columnWidth13; + set { _columnWidth13 = value; OnPropertyChanged(nameof(ColumnWidth13)); } + } - // Clear the current contents of the ObservableCollection - CreateSupplementalPolicy.Instance.ScanResults.Clear(); + private GridLength _columnWidth14; + public GridLength ColumnWidth14 + { + get => _columnWidth14; + set { _columnWidth14 = value; OnPropertyChanged(nameof(ColumnWidth14)); } + } - // Populate the ObservableCollection with the filtered results - // This triggers the UI to update the DataGrid based on the filtered data - foreach (FileIdentity result in filteredResults) - { - CreateSupplementalPolicy.Instance.ScanResults.Add(result); - } + private GridLength _columnWidth15; + public GridLength ColumnWidth15 + { + get => _columnWidth15; + set { _columnWidth15 = value; OnPropertyChanged(nameof(ColumnWidth15)); } + } - // Explicitly set the DataGrid's ItemsSource to ensure the data refreshes - FileIdentitiesDataGrid.ItemsSource = CreateSupplementalPolicy.Instance.ScanResults; + private GridLength _columnWidth16; + public GridLength ColumnWidth16 + { + get => _columnWidth16; + set { _columnWidth16 = value; OnPropertyChanged(nameof(ColumnWidth16)); } + } - // Update any visual or text element showing the total logs count - UpdateTotalFiles(); + private GridLength _columnWidth17; + public GridLength ColumnWidth17 + { + get => _columnWidth17; + set { _columnWidth17 = value; OnPropertyChanged(nameof(ColumnWidth17)); } } + private GridLength _columnWidth18; + public GridLength ColumnWidth18 + { + get => _columnWidth18; + set { _columnWidth18 = value; OnPropertyChanged(nameof(ColumnWidth18)); } + } /// - /// Event handler for the Clear Data button + /// Calculates the maximum required width for each column (including header text) + /// and assigns the value (with a little extra padding) to the corresponding property. + /// It should always run once ALL the data have been added to the ObservableCollection that is the ItemsSource of the ListView + /// And only after this method, the ItemsSource must be assigned to the ListView. /// - /// - /// - private void ClearDataButton_Click(object sender, RoutedEventArgs e) + internal void CalculateColumnWidths() { - CreateSupplementalPolicy.Instance.ScanResults.Clear(); - CreateSupplementalPolicy.Instance.ScanResultsList.Clear(); - UpdateTotalFiles(true); - } + // Measure header text widths first. + double maxWidth1 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("FileNameHeader/Text")); + double maxWidth2 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SignatureStatusHeader/Text")); + double maxWidth3 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("OriginalFileNameHeader/Text")); + double maxWidth4 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("InternalNameHeader/Text")); + double maxWidth5 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("FileDescriptionHeader/Text")); + double maxWidth6 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("ProductNameHeader/Text")); + double maxWidth7 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("FileVersionHeader/Text")); + double maxWidth8 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("PackageFamilyNameHeader/Text")); + double maxWidth9 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SHA256HashHeader/Text")); + double maxWidth10 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SHA1HashHeader/Text")); + double maxWidth11 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SigningScenarioHeader/Text")); + double maxWidth12 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("FilePathHeader/Text")); + double maxWidth13 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SHA1PageHashHeader/Text")); + double maxWidth14 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SHA256PageHashHeader/Text")); + double maxWidth15 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("HasWHQLSignerHeader/Text")); + double maxWidth16 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("FilePublishersHeader/Text")); + double maxWidth17 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("IsECCSignedHeader/Text")); + double maxWidth18 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("OpusDataHeader/Text")); + // Iterate over all items to determine the widest string for each column. + foreach (FileIdentity item in CreateSupplementalPolicy.Instance.ScanResults) + { + double w1 = ListViewUIHelpers.MeasureTextWidth(item.FileName); + if (w1 > maxWidth1) maxWidth1 = w1; + double w2 = ListViewUIHelpers.MeasureTextWidth(item.SignatureStatus.ToString()); + if (w2 > maxWidth2) maxWidth2 = w2; - // https://learn.microsoft.com/en-us/windows/communitytoolkit/controls/datagrid_guidance/group_sort_filter - // Column sorting logic for the entire DataGrid - private void FileIdentitiesDataGrid_Sorting(object sender, DataGridColumnEventArgs e) - { - // Sort the column based on its tag and current sort direction - if (string.Equals(e.Column.Tag?.ToString(), "FileName", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.FileName); - } - else if (string.Equals(e.Column.Tag?.ToString(), "SignatureStatus", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.SignatureStatus); - } - else if (string.Equals(e.Column.Tag?.ToString(), "OriginalFileName", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.OriginalFileName); - } - else if (string.Equals(e.Column.Tag?.ToString(), "InternalName", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.InternalName); - } - else if (string.Equals(e.Column.Tag?.ToString(), "FileDescription", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.FileDescription); - } - else if (string.Equals(e.Column.Tag?.ToString(), "ProductName", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.ProductName); - } - else if (string.Equals(e.Column.Tag?.ToString(), "FileVersion", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.FileVersion); - } - else if (string.Equals(e.Column.Tag?.ToString(), "PackageFamilyName", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.PackageFamilyName); - } - else if (string.Equals(e.Column.Tag?.ToString(), "SHA256Hash", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.SHA256Hash); - } - else if (string.Equals(e.Column.Tag?.ToString(), "SHA1Hash", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.SHA1Hash); - } - else if (string.Equals(e.Column.Tag?.ToString(), "SISigningScenario", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.SISigningScenario); - } - else if (string.Equals(e.Column.Tag?.ToString(), "FilePath", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.FilePath); - } - else if (string.Equals(e.Column.Tag?.ToString(), "SHA1PageHash", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.SHA1PageHash); - } - else if (string.Equals(e.Column.Tag?.ToString(), "SHA256PageHash", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.SHA256PageHash); - } - else if (string.Equals(e.Column.Tag?.ToString(), "HasWHQLSigner", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.HasWHQLSigner); - } - else if (string.Equals(e.Column.Tag?.ToString(), "FilePublishersToDisplay", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.FilePublishersToDisplay); - } - else if (string.Equals(e.Column.Tag?.ToString(), "IsECCSigned", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.IsECCSigned); - } - else if (string.Equals(e.Column.Tag?.ToString(), "Opus", StringComparison.OrdinalIgnoreCase)) - { - SortColumn(e, output => output.Opus); - } + double w3 = ListViewUIHelpers.MeasureTextWidth(item.OriginalFileName); + if (w3 > maxWidth3) maxWidth3 = w3; + double w4 = ListViewUIHelpers.MeasureTextWidth(item.InternalName); + if (w4 > maxWidth4) maxWidth4 = w4; - // Clear SortDirection for other columns - foreach (DataGridColumn column in FileIdentitiesDataGrid.Columns) - { - if (column != e.Column) - { - column.SortDirection = null; - } - } - } + double w5 = ListViewUIHelpers.MeasureTextWidth(item.FileDescription); + if (w5 > maxWidth5) maxWidth5 = w5; + double w6 = ListViewUIHelpers.MeasureTextWidth(item.ProductName); + if (w6 > maxWidth6) maxWidth6 = w6; - /// - /// Helper method for sorting any column on the DataGird - /// - /// - /// - /// - private void SortColumn(DataGridColumnEventArgs e, Func keySelector) - { - // Check if the search box is empty or not - bool isSearchEmpty = string.IsNullOrWhiteSpace(SearchBox.Text); + double w7 = ListViewUIHelpers.MeasureTextWidth(item.FileVersion?.ToString()); + if (w7 > maxWidth7) maxWidth7 = w7; - // Get the collection to sort based on the search box status - // Allowing us to sort only the items in the search results - List collectionToSort = isSearchEmpty ? CreateSupplementalPolicy.Instance.ScanResultsList : [.. CreateSupplementalPolicy.Instance.ScanResults]; + double w8 = ListViewUIHelpers.MeasureTextWidth(item.PackageFamilyName); + if (w8 > maxWidth8) maxWidth8 = w8; - // Perform the sorting based on the current SortDirection (ascending or descending) - if (e.Column.SortDirection is null || e.Column.SortDirection == DataGridSortDirection.Ascending) - { - // Descending: custom order depending on column type - CreateSupplementalPolicy.Instance.ScanResults = [.. collectionToSort.OrderByDescending(keySelector)]; + double w9 = ListViewUIHelpers.MeasureTextWidth(item.SHA256Hash); + if (w9 > maxWidth9) maxWidth9 = w9; - // Set the column direction to Descending - e.Column.SortDirection = DataGridSortDirection.Descending; - } - else - { - // Ascending: custom order depending on column type - CreateSupplementalPolicy.Instance.ScanResults = [.. collectionToSort.OrderBy(keySelector)]; - e.Column.SortDirection = DataGridSortDirection.Ascending; - } + double w10 = ListViewUIHelpers.MeasureTextWidth(item.SHA1Hash); + if (w10 > maxWidth10) maxWidth10 = w10; - // Update the ItemsSource of the DataGrid - // Required for sort + search to work properly, even though binding to the ObservableCollection already happens in XAML - FileIdentitiesDataGrid.ItemsSource = CreateSupplementalPolicy.Instance.ScanResults; - } + double w11 = ListViewUIHelpers.MeasureTextWidth(item.SISigningScenario.ToString()); + if (w11 > maxWidth11) maxWidth11 = w11; + double w12 = ListViewUIHelpers.MeasureTextWidth(item.FilePath); + if (w12 > maxWidth12) maxWidth12 = w12; - /// - /// Selects all of the displayed rows on the DataGrid - /// - /// - /// - private void SelectAll_Click(object sender, RoutedEventArgs e) - { - _ = DispatcherQueue.TryEnqueue(() => - { - // Clear existing selections - FileIdentitiesDataGrid.SelectedItems.Clear(); + double w13 = ListViewUIHelpers.MeasureTextWidth(item.SHA1PageHash); + if (w13 > maxWidth13) maxWidth13 = w13; - foreach (FileIdentity fileIdentity in CreateSupplementalPolicy.Instance.ScanResults) - { - _ = FileIdentitiesDataGrid.SelectedItems.Add(fileIdentity); // Select each item - } + double w14 = ListViewUIHelpers.MeasureTextWidth(item.SHA256PageHash); + if (w14 > maxWidth14) maxWidth14 = w14; - }); - } + double w15 = ListViewUIHelpers.MeasureTextWidth(item.HasWHQLSigner.ToString()); + if (w15 > maxWidth15) maxWidth15 = w15; + double w16 = ListViewUIHelpers.MeasureTextWidth(item.FilePublishersToDisplay); + if (w16 > maxWidth16) maxWidth16 = w16; - /// - /// De-selects all of the displayed rows on the DataGrid - /// - /// - /// - private void DeSelectAll_Click(object sender, RoutedEventArgs e) - { - FileIdentitiesDataGrid.SelectedItems.Clear(); // Deselect all rows by clearing SelectedItems - } + double w17 = ListViewUIHelpers.MeasureTextWidth(item.IsECCSigned.ToString()); + if (w17 > maxWidth17) maxWidth17 = w17; + + double w18 = ListViewUIHelpers.MeasureTextWidth(item.Opus); + if (w18 > maxWidth18) maxWidth18 = w18; + } + // Set the column width properties. + ColumnWidth1 = new GridLength(maxWidth1); + ColumnWidth2 = new GridLength(maxWidth2); + ColumnWidth3 = new GridLength(maxWidth3); + ColumnWidth4 = new GridLength(maxWidth4); + ColumnWidth5 = new GridLength(maxWidth5); + ColumnWidth6 = new GridLength(maxWidth6); + ColumnWidth7 = new GridLength(maxWidth7); + ColumnWidth8 = new GridLength(maxWidth8); + ColumnWidth9 = new GridLength(maxWidth9); + ColumnWidth10 = new GridLength(maxWidth10); + ColumnWidth11 = new GridLength(maxWidth11); + ColumnWidth12 = new GridLength(maxWidth12); + ColumnWidth13 = new GridLength(maxWidth13); + ColumnWidth14 = new GridLength(maxWidth14); + ColumnWidth15 = new GridLength(maxWidth15); + ColumnWidth16 = new GridLength(maxWidth16); + ColumnWidth17 = new GridLength(maxWidth17); + ColumnWidth18 = new GridLength(maxWidth18); + } /// @@ -288,19 +269,21 @@ private void DeSelectAll_Click(object sender, RoutedEventArgs e) /// /// The event sender. /// The event arguments. - private void DataGridFlyoutMenuCopy_Click(object sender, RoutedEventArgs e) + private void ListViewFlyoutMenuCopy_Click(object sender, RoutedEventArgs e) { - // Check if there are selected items in the DataGrid - if (FileIdentitiesDataGrid.SelectedItems.Count > 0) + // Check if there are selected items in the ListView + if (FileIdentitiesListView.SelectedItems.Count > 0) { // Initialize StringBuilder to store all selected rows' data with labels StringBuilder dataBuilder = new(); - // Loop through each selected item in the DataGrid - foreach (FileIdentity selectedItem in FileIdentitiesDataGrid.SelectedItems) + // Loop through each selected item in the ListView + foreach (var selectedItem in FileIdentitiesListView.SelectedItems) { - // Append each row's formatted data to the StringBuilder - _ = dataBuilder.AppendLine(ConvertRowToText(selectedItem)); + if (selectedItem is FileIdentity obj) + + // Append each row's formatted data to the StringBuilder + _ = dataBuilder.AppendLine(ListViewUIHelpers.ConvertRowToText(obj)); // Add a separator between rows for readability in multi-row copies _ = dataBuilder.AppendLine(new string('-', 50)); @@ -317,95 +300,6 @@ private void DataGridFlyoutMenuCopy_Click(object sender, RoutedEventArgs e) } } - /// - /// Converts the properties of a FileIdentity row into a labeled, formatted string for copying to clipboard. - /// - /// The selected FileIdentity row from the DataGrid. - /// A formatted string of the row's properties with labels. - private static string ConvertRowToText(FileIdentity row) - { - // Use StringBuilder to format each property with its label for easy reading - return new StringBuilder() - .AppendLine($"File Name: {row.FileName}") - .AppendLine($"Signature Status: {row.SignatureStatus}") - .AppendLine($"Original File Name: {row.OriginalFileName}") - .AppendLine($"Internal Name: {row.InternalName}") - .AppendLine($"File Description: {row.FileDescription}") - .AppendLine($"Product Name: {row.ProductName}") - .AppendLine($"File Version: {row.FileVersion}") - .AppendLine($"Package Family Name: {row.PackageFamilyName}") - .AppendLine($"SHA256 Hash: {row.SHA256Hash}") - .AppendLine($"SHA1 Hash: {row.SHA1Hash}") - .AppendLine($"Signing Scenario: {row.SISigningScenario}") - .AppendLine($"File Path: {row.FilePath}") - .AppendLine($"SHA1 Page Hash: {row.SHA1PageHash}") - .AppendLine($"SHA256 Page Hash: {row.SHA256PageHash}") - .AppendLine($"Has WHQL Signer: {row.HasWHQLSigner}") - .AppendLine($"File Publishers: {row.FilePublishersToDisplay}") - .AppendLine($"Is ECC Signed: {row.IsECCSigned}") - .AppendLine($"Opus Data: {row.Opus}") - .ToString(); - } - - - - /// - /// Event handler for the Copy Individual Items SubMenu. It will populate the submenu items in the flyout of the data grid. - /// - /// - /// - private void FileIdentitiesDataGrid_Loaded(object sender, RoutedEventArgs e) - { - // Ensure the CopyIndividualItemsSubMenu is available - if (CopyIndividualItemsSubMenu is null) - { - return; - } - - // Clear any existing items to avoid duplication if reloaded - CopyIndividualItemsSubMenu.Items.Clear(); - - // Create a dictionary to map headers to their specific click event methods - Dictionary copyActions = new() - { - { "File Name", CopyFileName_Click }, - { "Signature Status", CopySignatureStatus_Click }, - { "Original File Name", CopyOriginalFileName_Click }, - { "Internal Name", CopyInternalName_Click }, - { "File Description", CopyFileDescription_Click }, - { "Product Name", CopyProductName_Click }, - { "File Version", CopyFileVersion_Click }, - { "Package Family Name", CopyPackageFamilyName_Click }, - { "SHA256 Hash", CopySHA256Hash_Click }, - { "SHA1 Hash", CopySHA1Hash_Click }, - { "Signing Scenario", CopySigningScenario_Click }, - { "File Path", CopyFilePath_Click }, - { "SHA1 Page Hash", CopySHA1PageHash_Click }, - { "SHA256 Page Hash", CopySHA256PageHash_Click }, - { "Has WHQL Signer", CopyHasWHQLSigner_Click }, - { "File Publishers", CopyFilePublishersToDisplay_Click }, - { "Is ECC Signed", CopyIsECCSigned_Click }, - { "Opus Data", CopyOpus_Click } - }; - - // Add menu items with specific click events for each column - foreach (DataGridColumn column in FileIdentitiesDataGrid.Columns) - { - string headerText = column.Header.ToString()!; - - if (copyActions.TryGetValue(headerText, out RoutedEventHandler? value)) - { - // Create a new MenuFlyout Item - MenuFlyoutItem menuItem = new() { Text = $"Copy {headerText}" }; - - // Set the click event for the menu item - menuItem.Click += value; - - // Add the menu item to the submenu - CopyIndividualItemsSubMenu.Items.Add(menuItem); - } - } - } // Click event handlers for each property private void CopyFileName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FileName); @@ -423,10 +317,9 @@ private void FileIdentitiesDataGrid_Loaded(object sender, RoutedEventArgs e) private void CopySHA1PageHash_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SHA1PageHash); private void CopySHA256PageHash_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SHA256PageHash); private void CopyHasWHQLSigner_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.HasWHQLSigner.ToString()); - private void CopyFilePublishersToDisplay_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FilePublishersToDisplay); + private void CopyFilePublishers_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FilePublishersToDisplay); private void CopyIsECCSigned_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.IsECCSigned.ToString()); - private void CopyOpus_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.Opus); - + private void CopyOpusData_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.Opus); /// /// Helper method to copy a specified property to clipboard without reflection @@ -434,7 +327,7 @@ private void FileIdentitiesDataGrid_Loaded(object sender, RoutedEventArgs e) /// Function that retrieves the desired property value as a string private void CopyToClipboard(Func getProperty) { - if (FileIdentitiesDataGrid.SelectedItem is FileIdentity selectedItem) + if (FileIdentitiesListView.SelectedItem is FileIdentity selectedItem) { string? propertyValue = getProperty(selectedItem); if (propertyValue is not null) @@ -446,8 +339,266 @@ private void CopyToClipboard(Func getProperty) } } + // Event handlers for each sort button + private void ColumnSortingButton_FileName_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.FileName); + } + private void ColumnSortingButton_SignatureStatus_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.SignatureStatus); + } + private void ColumnSortingButton_OriginalFileName_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.OriginalFileName); + } + private void ColumnSortingButton_InternalName_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.InternalName); + } + private void ColumnSortingButton_FileDescription_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.FileDescription); + } + private void ColumnSortingButton_ProductName_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.ProductName); + } + private void ColumnSortingButton_FileVersion_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.FileVersion); + } + private void ColumnSortingButton_PackageFamilyName_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.PackageFamilyName); + } + private void ColumnSortingButton_SHA256Hash_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.SHA256Hash); + } + private void ColumnSortingButton_SHA1Hash_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.SHA1Hash); + } + + + private void ColumnSortingButton_SigningScenario_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.SISigningScenario); + } + + private void ColumnSortingButton_FilePath_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.FilePath); + } + + private void ColumnSortingButton_SHA1PageHash_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.SHA1PageHash); + } + + private void ColumnSortingButton_SHA256PageHash_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.SHA256PageHash); + } + + private void ColumnSortingButton_HasWHQLSigner_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.HasWHQLSigner); + } + + private void ColumnSortingButton_FilePublishers_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.FilePublishersToDisplay); + } + + private void ColumnSortingButton_IsECCSigned_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.IsECCSigned); + } + + private void ColumnSortingButton_OpusData_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.Opus); + } + + + + + /// + /// Performs data sorting + /// + /// + /// + private void SortColumn(Func keySelector) + { + // Determine if a search filter is active. + bool isSearchEmpty = string.IsNullOrWhiteSpace(SearchBox.Text); + // Use either the full list (CreateSupplementalPolicy.Instance.ScanResultsList) or the current display list. + var collectionToSort = isSearchEmpty ? CreateSupplementalPolicy.Instance.ScanResultsList : [.. CreateSupplementalPolicy.Instance.ScanResults]; + + if (SortingDirectionToggle.IsChecked) + { + // Sort in descending order. + CreateSupplementalPolicy.Instance.ScanResults = [.. collectionToSort.OrderByDescending(keySelector)]; + } + else + { + // Sort in ascending order. + CreateSupplementalPolicy.Instance.ScanResults = [.. collectionToSort.OrderBy(keySelector)]; + } + + // Refresh the ItemsSource so the UI updates. + FileIdentitiesListView.ItemsSource = CreateSupplementalPolicy.Instance.ScanResults; + } + + #endregion + + + + + + public StrictKernelPolicyScanResults() + { + this.InitializeComponent(); + + UIListView = FileIdentitiesListView; + + // Assign this instance to the static field + _instance = this; + } + + // Public property to access the singleton instance from other classes + public static StrictKernelPolicyScanResults Instance => _instance ?? throw new InvalidOperationException("StrictKernelPolicyScanResults is not initialized."); + + + #region + protected override void OnNavigatedTo(NavigationEventArgs e) + { + base.OnNavigatedTo(e); + + // Update the logs when user switches to this page + UpdateTotalFiles(); + + // Assign the ItemsSource of the ListView only once + // We cannot do it after column width calculation because initialization is not guaranteed at that moment + if (CreateSupplementalPolicy.Instance.StrictKernelModeDataProcessed) + { + CalculateColumnWidths(); + + FileIdentitiesListView.ItemsSource = CreateSupplementalPolicy.Instance.ScanResults; + + CreateSupplementalPolicy.Instance.StrictKernelModeDataProcessed = false; + } + } + #endregion + + /// + /// Event handler for the SearchBox text change + /// + private void SearchBox_TextChanged(object sender, TextChangedEventArgs e) + { + ApplyFilters(); + } + /// + /// Applies the date and search filters to the data grid + /// + private void ApplyFilters() + { + + // Get the search term from the SearchBox, converting it to lowercase for case-insensitive searching + string searchTerm = SearchBox.Text.Trim().ToLowerInvariant(); + + // Start with all items from the complete list, 'AllFileIdentities' + // This list is used as the base set for filtering to preserve original data + IEnumerable filteredResults = CreateSupplementalPolicy.Instance.ScanResultsList.AsEnumerable(); + + // Apply the search filter if there is a non-empty search term + if (!string.IsNullOrWhiteSpace(searchTerm)) + { + + // Filter results further to match the search term across multiple properties, case-insensitively + filteredResults = filteredResults.Where(output => + (output.FileName is not null && output.FileName.Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) || + (output.SignatureStatus.ToString().Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) || + (output.OriginalFileName is not null && output.OriginalFileName.Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) || + (output.InternalName is not null && output.InternalName.Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) || + (output.FileDescription is not null && output.FileDescription.Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) || + (output.ProductName is not null && output.ProductName.Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) || + (output.FileVersion is not null && output.FileVersion.ToString().Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) || + (output.PackageFamilyName is not null && output.PackageFamilyName.Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) || + (output.SHA1PageHash is not null && output.SHA1PageHash.Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) || + (output.FilePath is not null && output.FilePath.Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) || + (output.SHA256Hash is not null && output.SHA256Hash.Contains(searchTerm, StringComparison.OrdinalIgnoreCase)) || + output.FilePublishersToDisplay.Contains(searchTerm, StringComparison.OrdinalIgnoreCase) || + output.Opus.Contains(searchTerm, StringComparison.OrdinalIgnoreCase) + ); + } + + // Clear the current contents of the ObservableCollection + CreateSupplementalPolicy.Instance.ScanResults.Clear(); + + // Populate the ObservableCollection with the filtered results + // This triggers the UI to update the ListView based on the filtered data + foreach (FileIdentity result in filteredResults) + { + CreateSupplementalPolicy.Instance.ScanResults.Add(result); + } + + // Explicitly set the ListView's ItemsSource to ensure the data refreshes + FileIdentitiesListView.ItemsSource = CreateSupplementalPolicy.Instance.ScanResults; + + // Update any visual or text element showing the total logs count + UpdateTotalFiles(); + } + + + /// + /// Event handler for the Clear Data button + /// + /// + /// + private void ClearDataButton_Click(object sender, RoutedEventArgs e) + { + CreateSupplementalPolicy.Instance.ScanResults.Clear(); + CreateSupplementalPolicy.Instance.ScanResultsList.Clear(); + + UpdateTotalFiles(true); + } + + + /// + /// Selects all of the displayed rows on the ListView + /// + /// + /// + private void SelectAll_Click(object sender, RoutedEventArgs e) + { + _ = DispatcherQueue.TryEnqueue(() => + { + // Clear existing selections + FileIdentitiesListView.SelectedItems.Clear(); + + foreach (FileIdentity fileIdentity in CreateSupplementalPolicy.Instance.ScanResults) + { + FileIdentitiesListView.SelectedItems.Add(fileIdentity); // Select each item + } + + }); + } + + /// + /// De-selects all of the displayed rows on the ListView + /// + /// + /// + private void DeSelectAll_Click(object sender, RoutedEventArgs e) + { + FileIdentitiesListView.SelectedItems.Clear(); // Deselect all rows by clearing SelectedItems + } + /// /// Updates the total logs count displayed on the UI /// @@ -461,11 +612,8 @@ internal void UpdateTotalFiles(bool? Zero = null) { TotalCountOfTheFilesTextBox.Text = $"Total files: {CreateSupplementalPolicy.Instance.ScanResults.Count}"; } - - } - /// /// Deletes the selected row from the results /// @@ -474,7 +622,7 @@ internal void UpdateTotalFiles(bool? Zero = null) private void DataGridFlyoutMenuDelete_Click(object sender, RoutedEventArgs e) { // Collect the selected items to delete - List itemsToDelete = [.. FileIdentitiesDataGrid.SelectedItems.Cast()]; + List itemsToDelete = [.. FileIdentitiesListView.SelectedItems.Cast()]; // Remove each selected item from the FileIdentities collection foreach (FileIdentity item in itemsToDelete) @@ -485,7 +633,4 @@ private void DataGridFlyoutMenuDelete_Click(object sender, RoutedEventArgs e) UpdateTotalFiles(); } - - - } diff --git a/AppControl Manager/Pages/SystemInformation/ViewCurrentPolicies.xaml b/AppControl Manager/Pages/SystemInformation/ViewCurrentPolicies.xaml index 1d3751bc5..13edf3199 100644 --- a/AppControl Manager/Pages/SystemInformation/ViewCurrentPolicies.xaml +++ b/AppControl Manager/Pages/SystemInformation/ViewCurrentPolicies.xaml @@ -2,7 +2,8 @@ x:Class="AppControlManager.Pages.ViewCurrentPolicies" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" - xmlns:local="using:AppControlManager.Pages" + xmlns:others="using:AppControlManager.Others" + x:Name="ViewCurrentPoliciesXAML" xmlns:customUI="using:AppControlManager.CustomUIElements" xmlns:AppControlManager="using:AppControlManager" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" @@ -10,7 +11,8 @@ xmlns:ui="using:CommunityToolkit.WinUI" xmlns:win="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:controls="using:CommunityToolkit.WinUI.Controls" - xmlns:tk7controls="using:CommunityToolkit.WinUI.UI.Controls" + xmlns:interactivity="using:Microsoft.Xaml.Interactivity" + xmlns:behaviors="using:CommunityToolkit.WinUI.Behaviors" xmlns:animatedvisuals="using:AnimatedVisuals" mc:Ignorable="d"> @@ -64,6 +66,34 @@ + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/AppControl Manager/Pages/ViewFileCertificates.xaml.cs b/AppControl Manager/Pages/ViewFileCertificates.xaml.cs index 61785004c..5e440ed67 100644 --- a/AppControl Manager/Pages/ViewFileCertificates.xaml.cs +++ b/AppControl Manager/Pages/ViewFileCertificates.xaml.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.ComponentModel; using System.IO; using System.Linq; using System.Security.Cryptography.Pkcs; @@ -14,11 +15,337 @@ using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Navigation; using Windows.ApplicationModel.DataTransfer; +using WinRT; namespace AppControlManager.Pages; -public sealed partial class ViewFileCertificates : Page +// Since the columns for data in the ItemTemplate use "Binding" instead of "x:Bind", we need to use [GeneratedBindableCustomProperty] for them to work properly +[GeneratedBindableCustomProperty] +public sealed partial class ViewFileCertificates : Page, INotifyPropertyChanged { + + #region LISTVIEW IMPLEMENTATIONS + + public event PropertyChangedEventHandler? PropertyChanged; + private void OnPropertyChanged(string propertyName) => + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + + // Properties to hold each columns' width. + private GridLength _columnWidth1; + public GridLength ColumnWidth1 + { + get => _columnWidth1; + set { _columnWidth1 = value; OnPropertyChanged(nameof(ColumnWidth1)); } + } + + private GridLength _columnWidth2; + public GridLength ColumnWidth2 + { + get => _columnWidth2; + set { _columnWidth2 = value; OnPropertyChanged(nameof(ColumnWidth2)); } + } + + private GridLength _columnWidth3; + public GridLength ColumnWidth3 + { + get => _columnWidth3; + set { _columnWidth3 = value; OnPropertyChanged(nameof(ColumnWidth3)); } + } + + private GridLength _columnWidth4; + public GridLength ColumnWidth4 + { + get => _columnWidth4; + set { _columnWidth4 = value; OnPropertyChanged(nameof(ColumnWidth4)); } + } + + private GridLength _columnWidth5; + public GridLength ColumnWidth5 + { + get => _columnWidth5; + set { _columnWidth5 = value; OnPropertyChanged(nameof(ColumnWidth5)); } + } + + private GridLength _columnWidth6; + public GridLength ColumnWidth6 + { + get => _columnWidth6; + set { _columnWidth6 = value; OnPropertyChanged(nameof(ColumnWidth6)); } + } + + private GridLength _columnWidth7; + public GridLength ColumnWidth7 + { + get => _columnWidth7; + set { _columnWidth7 = value; OnPropertyChanged(nameof(ColumnWidth7)); } + } + + private GridLength _columnWidth8; + public GridLength ColumnWidth8 + { + get => _columnWidth8; + set { _columnWidth8 = value; OnPropertyChanged(nameof(ColumnWidth8)); } + } + + private GridLength _columnWidth9; + public GridLength ColumnWidth9 + { + get => _columnWidth9; + set { _columnWidth9 = value; OnPropertyChanged(nameof(ColumnWidth9)); } + } + + private GridLength _columnWidth10; + public GridLength ColumnWidth10 + { + get => _columnWidth10; + set { _columnWidth10 = value; OnPropertyChanged(nameof(ColumnWidth10)); } + } + + private GridLength _columnWidth11; + public GridLength ColumnWidth11 + { + get => _columnWidth11; + set { _columnWidth11 = value; OnPropertyChanged(nameof(ColumnWidth11)); } + } + + /// + /// Calculates the maximum required width for each column (including header text) + /// and assigns the value (with a little extra padding) to the corresponding property. + /// + private void CalculateColumnWidths() + { + // Measure header text widths first. + double maxWidth1 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SignerNumberHeader/Text")); + double maxWidth2 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("TypeHeader/Text")); + double maxWidth3 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SubjectCommonNameHeader/Text")); + double maxWidth4 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("IssuerCommonNameHeader/Text")); + double maxWidth5 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("NotBeforeHeader/Text")); + double maxWidth6 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("NotAfterHeader/Text")); + double maxWidth7 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("HashingAlgorithmHeader/Text")); + double maxWidth8 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SerialNumberHeader/Text")); + double maxWidth9 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("ThumbprintHeader/Text")); + double maxWidth10 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("TBSHashHeader/Text")); + double maxWidth11 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("ExtensionOIDsHeader/Text")); + + // Iterate over all items to determine the widest string for each column. + foreach (FileCertificateInfoCol item in FileCertificates) + { + double w1 = ListViewUIHelpers.MeasureTextWidth(item.SignerNumber.ToString()); + if (w1 > maxWidth1) maxWidth1 = w1; + + double w2 = ListViewUIHelpers.MeasureTextWidth(item.Type.ToString()); + if (w2 > maxWidth2) maxWidth2 = w2; + + double w3 = ListViewUIHelpers.MeasureTextWidth(item.SubjectCN); + if (w3 > maxWidth3) maxWidth3 = w3; + + double w4 = ListViewUIHelpers.MeasureTextWidth(item.IssuerCN); + if (w4 > maxWidth4) maxWidth4 = w4; + + double w5 = ListViewUIHelpers.MeasureTextWidth(item.NotBefore.ToString()); + if (w5 > maxWidth5) maxWidth5 = w5; + + double w6 = ListViewUIHelpers.MeasureTextWidth(item.NotAfter.ToString()); + if (w6 > maxWidth6) maxWidth6 = w6; + + double w7 = ListViewUIHelpers.MeasureTextWidth(item.HashingAlgorithm); + if (w7 > maxWidth7) maxWidth7 = w7; + + double w8 = ListViewUIHelpers.MeasureTextWidth(item.SerialNumber); + if (w8 > maxWidth8) maxWidth8 = w8; + + double w9 = ListViewUIHelpers.MeasureTextWidth(item.Thumbprint); + if (w9 > maxWidth9) maxWidth9 = w9; + + double w10 = ListViewUIHelpers.MeasureTextWidth(item.TBSHash); + if (w10 > maxWidth10) maxWidth10 = w10; + + double w11 = ListViewUIHelpers.MeasureTextWidth(item.OIDs); + if (w11 > maxWidth11) maxWidth11 = w11; + } + + // Set the column width properties. + ColumnWidth1 = new GridLength(maxWidth1); + ColumnWidth2 = new GridLength(maxWidth2); + ColumnWidth3 = new GridLength(maxWidth3); + ColumnWidth4 = new GridLength(maxWidth4); + ColumnWidth5 = new GridLength(maxWidth5); + ColumnWidth6 = new GridLength(maxWidth6); + ColumnWidth7 = new GridLength(maxWidth7); + ColumnWidth8 = new GridLength(maxWidth8); + ColumnWidth9 = new GridLength(maxWidth9); + ColumnWidth10 = new GridLength(maxWidth10); + ColumnWidth11 = new GridLength(maxWidth11); + } + + /// + /// Converts the properties of a FileCertificateInfoCol row into a labeled, formatted string for copying to clipboard. + /// + /// The selected FileCertificateInfoCol row from the ListView. + /// A formatted string of the row's properties with labels. + private static string ConvertRowToText(FileCertificateInfoCol row) + { + // Use StringBuilder to format each property with its label for easy reading + return new StringBuilder() + .AppendLine(GlobalVars.Rizz.GetString("SignerNumberHeader/Text") + row.SignerNumber) + .AppendLine(GlobalVars.Rizz.GetString("TypeHeader/Text") + row.Type) + .AppendLine(GlobalVars.Rizz.GetString("SubjectCommonNameHeader/Text") + row.SubjectCN) + .AppendLine(GlobalVars.Rizz.GetString("IssuerCommonNameHeader/Text") + row.IssuerCN) + .AppendLine(GlobalVars.Rizz.GetString("NotBeforeHeader/Text") + row.NotBefore) + .AppendLine(GlobalVars.Rizz.GetString("NotAfterHeader/Text") + row.NotAfter) + .AppendLine(GlobalVars.Rizz.GetString("HashingAlgorithmHeader/Text") + row.HashingAlgorithm) + .AppendLine(GlobalVars.Rizz.GetString("SerialNumberHeader/Text") + row.SerialNumber) + .AppendLine(GlobalVars.Rizz.GetString("ThumbprintHeader/Text") + row.Thumbprint) + .AppendLine(GlobalVars.Rizz.GetString("TBSHashHeader/Text") + row.TBSHash) + .AppendLine(GlobalVars.Rizz.GetString("ExtensionOIDsHeader/Text") + row.OIDs) + .ToString(); + } + + + /// + /// Copies the selected rows to the clipboard in a formatted manner, with each property labeled for clarity. + /// + /// The event sender. + /// The event arguments. + private void ListViewFlyoutMenuCopy_Click(object sender, RoutedEventArgs e) + { + // Check if there are selected items in the ListView + if (FileCertificatesListView.SelectedItems.Count > 0) + { + // Initialize StringBuilder to store all selected rows' data with labels + StringBuilder dataBuilder = new(); + + // Loop through each selected item in the ListView + foreach (var selectedItem in FileCertificatesListView.SelectedItems) + { + + if (selectedItem is FileCertificateInfoCol obj) + + // Append each row's formatted data to the StringBuilder + _ = dataBuilder.AppendLine(ConvertRowToText(obj)); + + // Add a separator between rows for readability in multi-row copies + _ = dataBuilder.AppendLine(new string('-', 50)); + } + + // Create a DataPackage to hold the text data + DataPackage dataPackage = new(); + + // Set the formatted text as the content of the DataPackage + dataPackage.SetText(dataBuilder.ToString()); + + // Copy the DataPackage content to the clipboard + Clipboard.SetContent(dataPackage); + } + } + + // Click event handlers for each property + private void CopySignerNumber_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SignerNumber.ToString()); + private void CopyType_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.Type.ToString()); + private void CopySubjectCommonName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SubjectCN); + private void CopyIssuerCommonName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.IssuerCN); + private void CopyNotBefore_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.NotBefore.ToString()); + private void CopyNotAfter_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.NotAfter.ToString()); + private void CopyHashingAlgorithm_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.HashingAlgorithm); + private void CopySerialNumber_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SerialNumber); + private void CopyThumbprint_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.Thumbprint); + private void CopyTBSHash_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.TBSHash); + private void CopyExtensionOIDs_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.OIDs); + + /// + /// Helper method to copy a specified property to clipboard without reflection + /// + /// Function that retrieves the desired property value as a string + private void CopyToClipboard(Func getProperty) + { + if (FileCertificatesListView.SelectedItem is FileCertificateInfoCol selectedItem) + { + string? propertyValue = getProperty(selectedItem); + if (propertyValue is not null) + { + DataPackage dataPackage = new(); + dataPackage.SetText(propertyValue); + Clipboard.SetContent(dataPackage); + } + } + } + + // Event handlers for each sort button + private void ColumnSortingButton_SignerNumber_Click(object sender, RoutedEventArgs e) + { + SortColumn(policy => policy.SignerNumber); + } + private void ColumnSortingButton_Type_Click(object sender, RoutedEventArgs e) + { + SortColumn(policy => policy.Type); + } + private void ColumnSortingButton_SubjectCommonName_Click(object sender, RoutedEventArgs e) + { + SortColumn(policy => policy.SubjectCN); + } + private void ColumnSortingButton_IssuerCommonName_Click(object sender, RoutedEventArgs e) + { + SortColumn(policy => policy.IssuerCN); + } + private void ColumnSortingButton_NotBefore_Click(object sender, RoutedEventArgs e) + { + SortColumn(policy => policy.NotBefore); + } + private void ColumnSortingButton_NotAfter_Click(object sender, RoutedEventArgs e) + { + SortColumn(policy => policy.NotAfter); + } + private void ColumnSortingButton_HashingAlgorithm_Click(object sender, RoutedEventArgs e) + { + SortColumn(policy => policy.HashingAlgorithm); + } + private void ColumnSortingButton_SerialNumber_Click(object sender, RoutedEventArgs e) + { + SortColumn(policy => policy.SerialNumber); + } + private void ColumnSortingButton_Thumbprint_Click(object sender, RoutedEventArgs e) + { + SortColumn(policy => policy.Thumbprint); + } + private void ColumnSortingButton_TBSHash_Click(object sender, RoutedEventArgs e) + { + SortColumn(policy => policy.TBSHash); + } + private void ColumnSortingButton_ExtensionOIDs_Click(object sender, RoutedEventArgs e) + { + SortColumn(policy => policy.OIDs); + } + + /// + /// Performs data sorting + /// + /// + /// + private void SortColumn(Func keySelector) + { + // Determine if a search filter is active. + bool isSearchEmpty = string.IsNullOrWhiteSpace(SearchBox.Text); + // Use either the full list (FilteredCertificates) or the current display list. + var collectionToSort = isSearchEmpty ? FilteredCertificates : [.. FileCertificates]; + + if (SortingDirectionToggle.IsChecked) + { + // Sort in descending order. + FileCertificates = [.. collectionToSort.OrderByDescending(keySelector)]; + } + else + { + // Sort in ascending order. + FileCertificates = [.. collectionToSort.OrderBy(keySelector)]; + } + + // Refresh the ItemsSource so the UI updates. + FileCertificatesListView.ItemsSource = FileCertificates; + } + + #endregion + + public ViewFileCertificates() { this.InitializeComponent(); @@ -27,8 +354,8 @@ public ViewFileCertificates() this.NavigationCacheMode = NavigationCacheMode.Required; } - // Main collection assigned to the DataGrid - private readonly ObservableCollection FileCertificates = []; + // Main collection assigned to the ListView + private ObservableCollection FileCertificates = []; // Collection used during search private ObservableCollection FilteredCertificates = []; @@ -62,8 +389,6 @@ private void GatherSecurityCatalogs() } } - - /// /// Event handler for the Browse button /// @@ -96,9 +421,11 @@ private async void BrowseForFilesButton_Click(object sender, RoutedEventArgs e) // Initialize filtered collection with all certificates FilteredCertificates = [.. FileCertificates]; - FileCertificatesDataGrid.ItemsSource = FilteredCertificates; - } + CalculateColumnWidths(); + + FileCertificatesListView.ItemsSource = FilteredCertificates; + } } finally { @@ -107,7 +434,6 @@ private async void BrowseForFilesButton_Click(object sender, RoutedEventArgs e) } } - /// /// Event handler for the Settings Card click /// @@ -162,7 +488,10 @@ private async void BrowseForFilesSettingsCard_Click(object sender, RoutedEventAr // Initialize filtered collection with all certificates FilteredCertificates = [.. FileCertificates]; - FileCertificatesDataGrid.ItemsSource = FilteredCertificates; + + CalculateColumnWidths(); + + FileCertificatesListView.ItemsSource = FilteredCertificates; } } @@ -173,8 +502,6 @@ private async void BrowseForFilesSettingsCard_Click(object sender, RoutedEventAr } } - - /// /// Get the certificates of the .CIP files /// @@ -232,7 +559,6 @@ await Task.Run(() => } - /// /// Fetch for the .cer files /// @@ -272,7 +598,6 @@ await Task.Run(() => } - /// /// The main method that performs data collection task /// @@ -330,8 +655,6 @@ await Task.Run(() => } - - // Get full chains of all of the file's certificates List result = GetCertificateDetails.Get([.. signerDetails]); @@ -415,143 +738,8 @@ await Task.Run(() => }); return output; - - } - - - - /// - /// Copies the selected rows to the clipboard, formatting each property with its value. - /// - /// The event sender. - /// The event arguments. - private void DataGridFlyoutMenuCopy_Click(object sender, RoutedEventArgs e) - { - if (FileCertificatesDataGrid.SelectedItems.Count > 0) - { - StringBuilder dataBuilder = new(); - - foreach (FileCertificateInfoCol selectedItem in FileCertificatesDataGrid.SelectedItems) - { - _ = dataBuilder.AppendLine(ConvertRowToText(selectedItem)); - _ = dataBuilder.AppendLine(new string('-', 50)); - } - - DataPackage dataPackage = new(); - dataPackage.SetText(dataBuilder.ToString()); - Clipboard.SetContent(dataPackage); - } - } - - /// - /// Converts a row's properties and values into a formatted string for clipboard copy. - /// - /// The selected row from the DataGrid. - /// A formatted string of the row's properties and values. - private static string ConvertRowToText(FileCertificateInfoCol row) - { - return new StringBuilder() - .AppendLine($"Signer Number: {row.SignerNumber}") - .AppendLine($"Type: {row.Type}") - .AppendLine($"Subject Common Name: {row.SubjectCN}") - .AppendLine($"Issuer Common Name: {row.IssuerCN}") - .AppendLine($"Not Before: {row.NotBefore}") - .AppendLine($"Not After: {row.NotAfter}") - .AppendLine($"Hashing Algorithm: {row.HashingAlgorithm}") - .AppendLine($"Serial Number: {row.SerialNumber}") - .AppendLine($"Thumbprint: {row.Thumbprint}") - .AppendLine($"TBS Hash: {row.TBSHash}") - .AppendLine($"Extension OIDs: {row.OIDs}") - .ToString(); - } - - /// - /// Event handler for the Copy Individual Items SubMenu. Populates items in the flyout of the data grid. - /// - /// - /// - private void FileCertificatesDataGrid_Loaded(object sender, RoutedEventArgs e) - { - if (CopyIndividualItemsSubMenu is null) - { - return; - } - - CopyIndividualItemsSubMenu.Items.Clear(); - - Dictionary copyActions = new() - { - { "Signer Number", CopySignerNumber_Click }, - { "Type", CopyType_Click }, - { "Subject Common Name", CopySubjectCN_Click }, - { "Issuer Common Name", CopyIssuerCN_Click }, - { "Not Before", CopyNotBefore_Click }, - { "Not After", CopyNotAfter_Click }, - { "Hashing Algorithm", CopyHashingAlgorithm_Click }, - { "Serial Number", CopySerialNumber_Click }, - { "Thumbprint", CopyThumbprint_Click }, - { "TBS Hash", CopyTBSHash_Click }, - { "Extension OIDs", CopyOIDs_Click } - }; - - foreach (KeyValuePair action in copyActions) - { - MenuFlyoutItem menuItem = new() { Text = $"Copy {action.Key}" }; - menuItem.Click += action.Value; - CopyIndividualItemsSubMenu.Items.Add(menuItem); - } - } - - // Click event handlers for each property - private void CopySignerNumber_Click(object sender, RoutedEventArgs e) => CopyPropertyToClipboard("CertificateNumber"); - private void CopyType_Click(object sender, RoutedEventArgs e) => CopyPropertyToClipboard("Type"); - private void CopySubjectCN_Click(object sender, RoutedEventArgs e) => CopyPropertyToClipboard("SubjectCN"); - private void CopyIssuerCN_Click(object sender, RoutedEventArgs e) => CopyPropertyToClipboard("IssuerCN"); - private void CopyNotBefore_Click(object sender, RoutedEventArgs e) => CopyPropertyToClipboard("NotBefore"); - private void CopyNotAfter_Click(object sender, RoutedEventArgs e) => CopyPropertyToClipboard("NotAfter"); - private void CopyHashingAlgorithm_Click(object sender, RoutedEventArgs e) => CopyPropertyToClipboard("HashingAlgorithm"); - private void CopySerialNumber_Click(object sender, RoutedEventArgs e) => CopyPropertyToClipboard("SerialNumber"); - private void CopyThumbprint_Click(object sender, RoutedEventArgs e) => CopyPropertyToClipboard("Thumbprint"); - private void CopyTBSHash_Click(object sender, RoutedEventArgs e) => CopyPropertyToClipboard("TBSValue"); - private void CopyOIDs_Click(object sender, RoutedEventArgs e) => CopyPropertyToClipboard("OIDs"); - - /// - /// Helper method to copy a specified property value to the clipboard. - /// - /// - private void CopyPropertyToClipboard(string propertyName) - { - if (FileCertificatesDataGrid.SelectedItem is not FileCertificateInfoCol selectedItem) - { - return; - } - - string? propertyValue = propertyName switch - { - "CertificateNumber" => selectedItem.SignerNumber.ToString(), - "Type" => selectedItem.Type.ToString(), - "SubjectCN" => selectedItem.SubjectCN, - "IssuerCN" => selectedItem.IssuerCN, - "NotBefore" => selectedItem.NotBefore.ToString(), - "NotAfter" => selectedItem.NotAfter.ToString(), - "HashingAlgorithm" => selectedItem.HashingAlgorithm, - "SerialNumber" => selectedItem.SerialNumber, - "Thumbprint" => selectedItem.Thumbprint, - "TBSValue" => selectedItem.TBSHash, - "OIDs" => selectedItem.OIDs, - _ => null - }; - - if (!string.IsNullOrEmpty(propertyValue)) - { - DataPackage dataPackage = new(); - dataPackage.SetText(propertyValue); - Clipboard.SetContent(dataPackage); - } } - - /// /// Event handler for the search box /// @@ -583,7 +771,7 @@ private void SearchBox_TextChanged(object sender, TextChangedEventArgs e) )]; } - FileCertificatesDataGrid.ItemsSource = FilteredCertificates; + FileCertificatesListView.ItemsSource = FilteredCertificates; } diff --git a/AppControl Manager/Resources/DriversBlockListAutoUpdaterScheduledTask.ps1 b/AppControl Manager/Resources/DriversBlockListAutoUpdaterScheduledTask.ps1 new file mode 100644 index 000000000..123cf98e4 --- /dev/null +++ b/AppControl Manager/Resources/DriversBlockListAutoUpdaterScheduledTask.ps1 @@ -0,0 +1,12 @@ +$PowerShellCommand = @" +try { Invoke-WebRequest -Uri 'https://aka.ms/VulnerableDriverBlockList' -OutFile 'VulnerableDriverBlockList.zip' -ErrorAction Stop }catch { exit 1 } +Expand-Archive -Path '.\VulnerableDriverBlockList.zip' -DestinationPath 'VulnerableDriverBlockList' -Force +`$SiPolicy_EnforcedFile = Get-ChildItem -Recurse -File -Path '.\VulnerableDriverBlockList' -Filter 'SiPolicy_Enforced.p7b' | Select-Object -First 1 +Move-Item -Path `$SiPolicy_EnforcedFile.FullName -Destination (`$env:SystemDrive + '\Windows\System32\CodeIntegrity\SiPolicy.p7b') -Force +citool --refresh -json; Remove-Item -Path '.\VulnerableDriverBlockList' -Recurse -Force; Remove-Item -Path '.\VulnerableDriverBlockList.zip' -Force +"@ +$Action = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument "-NoProfile -WindowStyle Hidden -Command $PowerShellCommand" +$Trigger = New-ScheduledTaskTrigger -Once -At (Get-Date).AddHours(1) -RepetitionInterval (New-TimeSpan -Days 7) +$Principal = New-ScheduledTaskPrincipal -UserId 'S-1-5-18' -LogonType S4U -RunLevel Highest +$Settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -Compatibility Win8 -RunOnlyIfNetworkAvailable -ExecutionTimeLimit (New-TimeSpan -Minutes 3) -RestartCount 4 -RestartInterval (New-TimeSpan -Hours 6) +Register-ScheduledTask -TaskName 'MSFT Driver Block list update' -Description 'Microsoft Recommended Driver Block List update' -TaskPath '\MSFT Driver Block list update\' -Action $Action -Trigger $Trigger -Principal $Principal -Settings $Settings -Force \ No newline at end of file diff --git a/AppControl Manager/Resources/SnapBackGuaranteeScheduledTask.ps1 b/AppControl Manager/Resources/SnapBackGuaranteeScheduledTask.ps1 new file mode 100644 index 000000000..cfeab2c6a --- /dev/null +++ b/AppControl Manager/Resources/SnapBackGuaranteeScheduledTask.ps1 @@ -0,0 +1,5 @@ +$Action = New-ScheduledTaskAction -Execute 'cmd.exe' -Argument "/c `"C:\Program Files\WDACConfig\EnforcedModeSnapBack.cmd`"" +$Trigger = New-ScheduledTaskTrigger -AtLogOn +$Principal = New-ScheduledTaskPrincipal -UserId 'S-1-5-18' -LogonType S4U -RunLevel Highest +$Settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -Compatibility Win8 -Priority 0 -Hidden -RestartCount 2 -RestartInterval (New-TimeSpan -Minutes 3) +Register-ScheduledTask -TaskName 'EnforcedModeSnapBack' -Action $Action -Trigger $Trigger -Principal $Principal -Settings $Settings -Force \ No newline at end of file diff --git a/AppControl Manager/SiPolicy/SiPolicyClassAutoGenerated.cs b/AppControl Manager/SiPolicy/SiPolicyClassAutoGenerated.cs index 8124fd625..9bcbae556 100644 --- a/AppControl Manager/SiPolicy/SiPolicyClassAutoGenerated.cs +++ b/AppControl Manager/SiPolicy/SiPolicyClassAutoGenerated.cs @@ -13,3137 +13,2881 @@ // namespace AppControlManager.SiPolicy { - using System.Xml.Serialization; - - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:schemas-microsoft-com:sipolicy")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy", IsNullable = false)] - public partial class Macros - { - - private MacrosMacro[] macroField; - - /// - [System.Xml.Serialization.XmlElementAttribute("Macro")] - public MacrosMacro[] Macro - { - get - { - return this.macroField; - } - set - { - this.macroField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:schemas-microsoft-com:sipolicy")] - public partial class MacrosMacro - { - - private string idField; - - private string valueField; - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string Id - { - get - { - return this.idField; - } - set - { - this.idField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string Value - { - get - { - return this.valueField; - } - set - { - this.valueField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy")] - public partial class AppSetting - { - - private string[] valueField; - - private string nameField; - - /// - [System.Xml.Serialization.XmlElementAttribute("Value")] - public string[] Value - { - get - { - return this.valueField; - } - set - { - this.valueField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string Name - { - get - { - return this.nameField; - } - set - { - this.nameField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy")] - public partial class AppRoot - { - - private AppSetting[] settingField; - - private string manifestField; - - /// - [System.Xml.Serialization.XmlElementAttribute("Setting")] - public AppSetting[] Setting - { - get - { - return this.settingField; - } - set - { - this.settingField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "anyURI")] - public string Manifest - { - get - { - return this.manifestField; - } - set - { - this.manifestField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy")] - public partial class AppSettingRegion - { - - private AppRoot[] appField; - - /// - [System.Xml.Serialization.XmlElementAttribute("App")] - public AppRoot[] App - { - get - { - return this.appField; - } - set - { - this.appField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy")] - public partial class RuleType - { - - private OptionType itemField; - - /// - [System.Xml.Serialization.XmlElementAttribute("Option")] - public OptionType Item - { - get - { - return this.itemField; - } - set - { - this.itemField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy")] - public enum OptionType - { - - /// - [System.Xml.Serialization.XmlEnumAttribute("Enabled:UMCI")] - EnabledUMCI, - - /// - [System.Xml.Serialization.XmlEnumAttribute("Enabled:Boot Menu Protection")] - EnabledBootMenuProtection, - - /// - [System.Xml.Serialization.XmlEnumAttribute("Enabled:Intelligent Security Graph Authorization")] - EnabledIntelligentSecurityGraphAuthorization, - - /// - [System.Xml.Serialization.XmlEnumAttribute("Enabled:Invalidate EAs on Reboot")] - EnabledInvalidateEAsonReboot, - - /// - [System.Xml.Serialization.XmlEnumAttribute("Required:WHQL")] - RequiredWHQL, - - /// - [System.Xml.Serialization.XmlEnumAttribute("Enabled:Developer Mode Dynamic Code Trust")] - EnabledDeveloperModeDynamicCodeTrust, - - /// - [System.Xml.Serialization.XmlEnumAttribute("Enabled:Allow Supplemental Policies")] - EnabledAllowSupplementalPolicies, - - /// - [System.Xml.Serialization.XmlEnumAttribute("Disabled:Runtime FilePath Rule Protection")] - DisabledRuntimeFilePathRuleProtection, - - /// - [System.Xml.Serialization.XmlEnumAttribute("Enabled:Revoked Expired As Unsigned")] - EnabledRevokedExpiredAsUnsigned, - - /// - [System.Xml.Serialization.XmlEnumAttribute("Enabled:Audit Mode")] - EnabledAuditMode, - - /// - [System.Xml.Serialization.XmlEnumAttribute("Disabled:Flight Signing")] - DisabledFlightSigning, - - /// - [System.Xml.Serialization.XmlEnumAttribute("Enabled:Inherit Default Policy")] - EnabledInheritDefaultPolicy, - - /// - [System.Xml.Serialization.XmlEnumAttribute("Enabled:Unsigned System Integrity Policy")] - EnabledUnsignedSystemIntegrityPolicy, - - /// - [System.Xml.Serialization.XmlEnumAttribute("Enabled:Dynamic Code Security")] - EnabledDynamicCodeSecurity, - - /// - [System.Xml.Serialization.XmlEnumAttribute("Required:EV Signers")] - RequiredEVSigners, - - /// - [System.Xml.Serialization.XmlEnumAttribute("Enabled:Boot Audit On Failure")] - EnabledBootAuditOnFailure, - - /// - [System.Xml.Serialization.XmlEnumAttribute("Enabled:Advanced Boot Options Menu")] - EnabledAdvancedBootOptionsMenu, - - /// - [System.Xml.Serialization.XmlEnumAttribute("Disabled:Script Enforcement")] - DisabledScriptEnforcement, - - /// - [System.Xml.Serialization.XmlEnumAttribute("Required:Enforce Store Applications")] - RequiredEnforceStoreApplications, - - /// - [System.Xml.Serialization.XmlEnumAttribute("Enabled:Secure Setting Policy")] - EnabledSecureSettingPolicy, - - /// - [System.Xml.Serialization.XmlEnumAttribute("Enabled:Managed Installer")] - EnabledManagedInstaller, - - /// - [System.Xml.Serialization.XmlEnumAttribute("Enabled:Update Policy No Reboot")] - EnabledUpdatePolicyNoReboot, - - /// - [System.Xml.Serialization.XmlEnumAttribute("Enabled:Conditional Windows Lockdown Policy")] - EnabledConditionalWindowsLockdownPolicy, - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy")] - public partial class SettingValueType - { - - private object itemField; - - /// - [System.Xml.Serialization.XmlElementAttribute("Binary", typeof(byte[]), DataType = "hexBinary")] - [System.Xml.Serialization.XmlElementAttribute("Boolean", typeof(bool))] - [System.Xml.Serialization.XmlElementAttribute("DWord", typeof(uint))] - [System.Xml.Serialization.XmlElementAttribute("String", typeof(string))] - public object Item - { - get - { - return this.itemField; - } - set - { - this.itemField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:schemas-microsoft-com:sipolicy")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy", IsNullable = false)] - public partial class Setting - { - - private SettingValueType valueField; - - private string providerField; - - private string keyField; - - private string valueNameField; - - /// - public SettingValueType Value - { - get - { - return this.valueField; - } - set - { - this.valueField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string Provider - { - get - { - return this.providerField; - } - set - { - this.providerField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string Key - { - get - { - return this.keyField; - } - set - { - this.keyField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string ValueName - { - get - { - return this.valueNameField; - } - set - { - this.valueNameField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:schemas-microsoft-com:sipolicy")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy", IsNullable = false)] - public partial class Settings - { - - private Setting[] itemsField; - - /// - [System.Xml.Serialization.XmlElementAttribute("Setting")] - public Setting[] Items - { - get - { - return this.itemsField; - } - set - { - this.itemsField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:schemas-microsoft-com:sipolicy")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy", IsNullable = false)] - public partial class CertEKU - { - - private string idField; - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string ID - { - get - { - return this.idField; - } - set - { - this.idField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:schemas-microsoft-com:sipolicy")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy", IsNullable = false)] - public partial class CertOemID - { - - private string valueField; - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string Value - { - get - { - return this.valueField; - } - set - { - this.valueField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:schemas-microsoft-com:sipolicy")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy", IsNullable = false)] - public partial class CertPublisher - { - - private string valueField; - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string Value - { - get - { - return this.valueField; - } - set - { - this.valueField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:schemas-microsoft-com:sipolicy")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy", IsNullable = false)] - public partial class CertIssuer - { - - private string valueField; - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string Value - { - get - { - return this.valueField; - } - set - { - this.valueField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:schemas-microsoft-com:sipolicy")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy", IsNullable = false)] - public partial class CertRoot - { - - private CertEnumType typeField; - - private byte[] valueField; - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public CertEnumType Type - { - get - { - return this.typeField; - } - set - { - this.typeField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "hexBinary")] - public byte[] Value - { - get - { - return this.valueField; - } - set - { - this.valueField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy")] - public enum CertEnumType - { - - /// - TBS, - - /// - Wellknown, - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:schemas-microsoft-com:sipolicy")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy", IsNullable = false)] - public partial class ProductSigners - { - - private AllowedSigners allowedSignersField; - - private DeniedSigners deniedSignersField; - - private FileRulesRef fileRulesRefField; - - /// - public AllowedSigners AllowedSigners - { - get - { - return this.allowedSignersField; - } - set - { - this.allowedSignersField = value; - } - } - - /// - public DeniedSigners DeniedSigners - { - get - { - return this.deniedSignersField; - } - set - { - this.deniedSignersField = value; - } - } - - /// - public FileRulesRef FileRulesRef - { - get - { - return this.fileRulesRefField; - } - set - { - this.fileRulesRefField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:schemas-microsoft-com:sipolicy")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy", IsNullable = false)] - public partial class AllowedSigners - { - - private AllowedSigner[] allowedSignerField; - - private string workaroundField; - - /// - [System.Xml.Serialization.XmlElementAttribute("AllowedSigner")] - public AllowedSigner[] AllowedSigner - { - get - { - return this.allowedSignerField; - } - set - { - this.allowedSignerField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string Workaround - { - get - { - return this.workaroundField; - } - set - { - this.workaroundField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:schemas-microsoft-com:sipolicy")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy", IsNullable = false)] - public partial class AllowedSigner - { - - private ExceptDenyRule[] exceptDenyRuleField; - - private string signerIdField; - - /// - [System.Xml.Serialization.XmlElementAttribute("ExceptDenyRule")] - public ExceptDenyRule[] ExceptDenyRule - { - get - { - return this.exceptDenyRuleField; - } - set - { - this.exceptDenyRuleField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string SignerId - { - get - { - return this.signerIdField; - } - set - { - this.signerIdField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:schemas-microsoft-com:sipolicy")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy", IsNullable = false)] - public partial class ExceptDenyRule - { - - private string denyRuleIDField; - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string DenyRuleID - { - get - { - return this.denyRuleIDField; - } - set - { - this.denyRuleIDField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:schemas-microsoft-com:sipolicy")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy", IsNullable = false)] - public partial class DeniedSigners - { - - private DeniedSigner[] deniedSignerField; - - private string workaroundField; - - /// - [System.Xml.Serialization.XmlElementAttribute("DeniedSigner")] - public DeniedSigner[] DeniedSigner - { - get - { - return this.deniedSignerField; - } - set - { - this.deniedSignerField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string Workaround - { - get - { - return this.workaroundField; - } - set - { - this.workaroundField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:schemas-microsoft-com:sipolicy")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy", IsNullable = false)] - public partial class DeniedSigner - { - - private ExceptAllowRule[] exceptAllowRuleField; - - private string signerIdField; - - /// - [System.Xml.Serialization.XmlElementAttribute("ExceptAllowRule")] - public ExceptAllowRule[] ExceptAllowRule - { - get - { - return this.exceptAllowRuleField; - } - set - { - this.exceptAllowRuleField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string SignerId - { - get - { - return this.signerIdField; - } - set - { - this.signerIdField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:schemas-microsoft-com:sipolicy")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy", IsNullable = false)] - public partial class ExceptAllowRule - { - - private string allowRuleIDField; - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string AllowRuleID - { - get - { - return this.allowRuleIDField; - } - set - { - this.allowRuleIDField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:schemas-microsoft-com:sipolicy")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy", IsNullable = false)] - public partial class FileRulesRef - { - - private FileRuleRef[] fileRuleRefField; - - private string workaroundField; - - /// - [System.Xml.Serialization.XmlElementAttribute("FileRuleRef")] - public FileRuleRef[] FileRuleRef - { - get - { - return this.fileRuleRefField; - } - set - { - this.fileRuleRefField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string Workaround - { - get - { - return this.workaroundField; - } - set - { - this.workaroundField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:schemas-microsoft-com:sipolicy")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy", IsNullable = false)] - public partial class FileRuleRef - { - - private string ruleIDField; - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string RuleID - { - get - { - return this.ruleIDField; - } - set - { - this.ruleIDField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:schemas-microsoft-com:sipolicy")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy", IsNullable = false)] - public partial class TestSigners - { - - private AllowedSigners allowedSignersField; - - private DeniedSigners deniedSignersField; - - private FileRulesRef fileRulesRefField; - - /// - public AllowedSigners AllowedSigners - { - get - { - return this.allowedSignersField; - } - set - { - this.allowedSignersField = value; - } - } - - /// - public DeniedSigners DeniedSigners - { - get - { - return this.deniedSignersField; - } - set - { - this.deniedSignersField = value; - } - } - - /// - public FileRulesRef FileRulesRef - { - get - { - return this.fileRulesRefField; - } - set - { - this.fileRulesRefField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:schemas-microsoft-com:sipolicy")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy", IsNullable = false)] - public partial class TestSigningSigners - { - - private AllowedSigners allowedSignersField; - - private DeniedSigners deniedSignersField; - - private FileRulesRef fileRulesRefField; - - /// - public AllowedSigners AllowedSigners - { - get - { - return this.allowedSignersField; - } - set - { - this.allowedSignersField = value; - } - } - - /// - public DeniedSigners DeniedSigners - { - get - { - return this.deniedSignersField; - } - set - { - this.deniedSignersField = value; - } - } - - /// - public FileRulesRef FileRulesRef - { - get - { - return this.fileRulesRefField; - } - set - { - this.fileRulesRefField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:schemas-microsoft-com:sipolicy")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy", IsNullable = false)] - public partial class AppIDTag - { - - private string keyField; - - private string valueField; - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string Key - { - get - { - return this.keyField; - } - set - { - this.keyField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string Value - { - get - { - return this.valueField; - } - set - { - this.valueField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:schemas-microsoft-com:sipolicy")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy", IsNullable = false)] - public partial class AppIDTags - { - - private AppIDTag[] appIDTagField; - - private bool enforceDLLField; - - private bool enforceDLLFieldSpecified; - - /// - [System.Xml.Serialization.XmlElementAttribute("AppIDTag")] - public AppIDTag[] AppIDTag - { - get - { - return this.appIDTagField; - } - set - { - this.appIDTagField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public bool EnforceDLL - { - get - { - return this.enforceDLLField; - } - set - { - this.enforceDLLField = value; - } - } - - /// - [System.Xml.Serialization.XmlIgnoreAttribute()] - public bool EnforceDLLSpecified - { - get - { - return this.enforceDLLFieldSpecified; - } - set - { - this.enforceDLLFieldSpecified = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:schemas-microsoft-com:sipolicy")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy", IsNullable = false)] - public partial class FileAttribRef - { - - private string ruleIDField; - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string RuleID - { - get - { - return this.ruleIDField; - } - set - { - this.ruleIDField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:schemas-microsoft-com:sipolicy")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy", IsNullable = false)] - public partial class EKUs - { - - private EKU[] itemsField; - - /// - [System.Xml.Serialization.XmlElementAttribute("EKU")] - public EKU[] Items - { - get - { - return this.itemsField; - } - set - { - this.itemsField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:schemas-microsoft-com:sipolicy")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy", IsNullable = false)] - public partial class EKU - { - - private string idField; - - private byte[] valueField; - - private string friendlyNameField; - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string ID - { - get - { - return this.idField; - } - set - { - this.idField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "hexBinary")] - public byte[] Value - { - get - { - return this.valueField; - } - set - { - this.valueField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string FriendlyName - { - get - { - return this.friendlyNameField; - } - set - { - this.friendlyNameField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:schemas-microsoft-com:sipolicy")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy", IsNullable = false)] - public partial class FileRules - { - - private object[] itemsField; - - /// - [System.Xml.Serialization.XmlElementAttribute("Allow", typeof(Allow))] - [System.Xml.Serialization.XmlElementAttribute("Deny", typeof(Deny))] - [System.Xml.Serialization.XmlElementAttribute("FileAttrib", typeof(FileAttrib))] - [System.Xml.Serialization.XmlElementAttribute("FileRule", typeof(FileRule))] - public object[] Items - { - get - { - return this.itemsField; - } - set - { - this.itemsField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:schemas-microsoft-com:sipolicy")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy", IsNullable = false)] - public partial class Allow - { - - private string idField; - - private string friendlyNameField; - - private string fileNameField; - - private string internalNameField; - - private string fileDescriptionField; - - private string productNameField; - - private string packageFamilyNameField; - - private string packageVersionField; - - private string minimumFileVersionField; - - private string maximumFileVersionField; - - private byte[] hashField; - - private string appIDsField; - - private string filePathField; - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string ID - { - get - { - return this.idField; - } - set - { - this.idField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string FriendlyName - { - get - { - return this.friendlyNameField; - } - set - { - this.friendlyNameField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string FileName - { - get - { - return this.fileNameField; - } - set - { - this.fileNameField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string InternalName - { - get - { - return this.internalNameField; - } - set - { - this.internalNameField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string FileDescription - { - get - { - return this.fileDescriptionField; - } - set - { - this.fileDescriptionField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string ProductName - { - get - { - return this.productNameField; - } - set - { - this.productNameField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string PackageFamilyName - { - get - { - return this.packageFamilyNameField; - } - set - { - this.packageFamilyNameField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string PackageVersion - { - get - { - return this.packageVersionField; - } - set - { - this.packageVersionField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string MinimumFileVersion - { - get - { - return this.minimumFileVersionField; - } - set - { - this.minimumFileVersionField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string MaximumFileVersion - { - get - { - return this.maximumFileVersionField; - } - set - { - this.maximumFileVersionField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "hexBinary")] - public byte[] Hash - { - get - { - return this.hashField; - } - set - { - this.hashField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string AppIDs - { - get - { - return this.appIDsField; - } - set - { - this.appIDsField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string FilePath - { - get - { - return this.filePathField; - } - set - { - this.filePathField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:schemas-microsoft-com:sipolicy")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy", IsNullable = false)] - public partial class Deny - { - - private string idField; - - private string friendlyNameField; - - private string fileNameField; - - private string internalNameField; - - private string fileDescriptionField; - - private string productNameField; - - private string packageFamilyNameField; - - private string packageVersionField; - - private string minimumFileVersionField; - - private string maximumFileVersionField; - - private byte[] hashField; - - private string appIDsField; - - private string filePathField; - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string ID - { - get - { - return this.idField; - } - set - { - this.idField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string FriendlyName - { - get - { - return this.friendlyNameField; - } - set - { - this.friendlyNameField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string FileName - { - get - { - return this.fileNameField; - } - set - { - this.fileNameField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string InternalName - { - get - { - return this.internalNameField; - } - set - { - this.internalNameField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string FileDescription - { - get - { - return this.fileDescriptionField; - } - set - { - this.fileDescriptionField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string ProductName - { - get - { - return this.productNameField; - } - set - { - this.productNameField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string PackageFamilyName - { - get - { - return this.packageFamilyNameField; - } - set - { - this.packageFamilyNameField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string PackageVersion - { - get - { - return this.packageVersionField; - } - set - { - this.packageVersionField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string MinimumFileVersion - { - get - { - return this.minimumFileVersionField; - } - set - { - this.minimumFileVersionField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string MaximumFileVersion - { - get - { - return this.maximumFileVersionField; - } - set - { - this.maximumFileVersionField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "hexBinary")] - public byte[] Hash - { - get - { - return this.hashField; - } - set - { - this.hashField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string AppIDs - { - get - { - return this.appIDsField; - } - set - { - this.appIDsField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string FilePath - { - get - { - return this.filePathField; - } - set - { - this.filePathField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:schemas-microsoft-com:sipolicy")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy", IsNullable = false)] - public partial class FileAttrib - { - - private string idField; - - private string friendlyNameField; - - private string fileNameField; - - private string internalNameField; - - private string fileDescriptionField; - - private string productNameField; - - private string packageFamilyNameField; - - private string packageVersionField; - - private string minimumFileVersionField; - - private string maximumFileVersionField; - - private byte[] hashField; - - private string appIDsField; - - private string filePathField; - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string ID - { - get - { - return this.idField; - } - set - { - this.idField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string FriendlyName - { - get - { - return this.friendlyNameField; - } - set - { - this.friendlyNameField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string FileName - { - get - { - return this.fileNameField; - } - set - { - this.fileNameField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string InternalName - { - get - { - return this.internalNameField; - } - set - { - this.internalNameField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string FileDescription - { - get - { - return this.fileDescriptionField; - } - set - { - this.fileDescriptionField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string ProductName - { - get - { - return this.productNameField; - } - set - { - this.productNameField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string PackageFamilyName - { - get - { - return this.packageFamilyNameField; - } - set - { - this.packageFamilyNameField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string PackageVersion - { - get - { - return this.packageVersionField; - } - set - { - this.packageVersionField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string MinimumFileVersion - { - get - { - return this.minimumFileVersionField; - } - set - { - this.minimumFileVersionField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string MaximumFileVersion - { - get - { - return this.maximumFileVersionField; - } - set - { - this.maximumFileVersionField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "hexBinary")] - public byte[] Hash - { - get - { - return this.hashField; - } - set - { - this.hashField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string AppIDs - { - get - { - return this.appIDsField; - } - set - { - this.appIDsField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string FilePath - { - get - { - return this.filePathField; - } - set - { - this.filePathField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:schemas-microsoft-com:sipolicy")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy", IsNullable = false)] - public partial class FileRule - { - - private string idField; - - private string friendlyNameField; - - private string fileNameField; - - private string internalNameField; - - private string fileDescriptionField; - - private string productNameField; - - private string packageFamilyNameField; - - private string packageVersionField; - - private string minimumFileVersionField; - - private string maximumFileVersionField; - - private byte[] hashField; - - private string appIDsField; - - private string filePathField; - - private RuleTypeType typeField; - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string ID - { - get - { - return this.idField; - } - set - { - this.idField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string FriendlyName - { - get - { - return this.friendlyNameField; - } - set - { - this.friendlyNameField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string FileName - { - get - { - return this.fileNameField; - } - set - { - this.fileNameField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string InternalName - { - get - { - return this.internalNameField; - } - set - { - this.internalNameField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string FileDescription - { - get - { - return this.fileDescriptionField; - } - set - { - this.fileDescriptionField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string ProductName - { - get - { - return this.productNameField; - } - set - { - this.productNameField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string PackageFamilyName - { - get - { - return this.packageFamilyNameField; - } - set - { - this.packageFamilyNameField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string PackageVersion - { - get - { - return this.packageVersionField; - } - set - { - this.packageVersionField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string MinimumFileVersion - { - get - { - return this.minimumFileVersionField; - } - set - { - this.minimumFileVersionField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string MaximumFileVersion - { - get - { - return this.maximumFileVersionField; - } - set - { - this.maximumFileVersionField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "hexBinary")] - public byte[] Hash - { - get - { - return this.hashField; - } - set - { - this.hashField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string AppIDs - { - get - { - return this.appIDsField; - } - set - { - this.appIDsField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string FilePath - { - get - { - return this.filePathField; - } - set - { - this.filePathField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public RuleTypeType Type - { - get - { - return this.typeField; - } - set - { - this.typeField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy")] - public enum RuleTypeType - { - - /// - Match, - - /// - Exclude, - - /// - Attribute, - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:schemas-microsoft-com:sipolicy")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy", IsNullable = false)] - public partial class UpdatePolicySigner - { - - private string signerIdField; - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string SignerId - { - get - { - return this.signerIdField; - } - set - { - this.signerIdField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:schemas-microsoft-com:sipolicy")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy", IsNullable = false)] - public partial class UpdatePolicySigners - { - - private UpdatePolicySigner[] itemsField; - - /// - [System.Xml.Serialization.XmlElementAttribute("UpdatePolicySigner")] - public UpdatePolicySigner[] Items - { - get - { - return this.itemsField; - } - set - { - this.itemsField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:schemas-microsoft-com:sipolicy")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy", IsNullable = false)] - public partial class SupplementalPolicySigner - { - - private string signerIdField; - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string SignerId - { - get - { - return this.signerIdField; - } - set - { - this.signerIdField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:schemas-microsoft-com:sipolicy")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy", IsNullable = false)] - public partial class SupplementalPolicySigners - { - - private SupplementalPolicySigner[] itemsField; - - /// - [System.Xml.Serialization.XmlElementAttribute("SupplementalPolicySigner")] - public SupplementalPolicySigner[] Items - { - get - { - return this.itemsField; - } - set - { - this.itemsField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:schemas-microsoft-com:sipolicy")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy", IsNullable = false)] - public partial class CiSigner - { - - private string signerIdField; - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string SignerId - { - get - { - return this.signerIdField; - } - set - { - this.signerIdField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:schemas-microsoft-com:sipolicy")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy", IsNullable = false)] - public partial class CiSigners - { - - private CiSigner[] itemsField; - - /// - [System.Xml.Serialization.XmlElementAttribute("CiSigner")] - public CiSigner[] Items - { - get - { - return this.itemsField; - } - set - { - this.itemsField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:schemas-microsoft-com:sipolicy")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy", IsNullable = false)] - public partial class Signers - { - - private Signer[] itemsField; - - /// - [System.Xml.Serialization.XmlElementAttribute("Signer")] - public Signer[] Items - { - get - { - return this.itemsField; - } - set - { - this.itemsField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:schemas-microsoft-com:sipolicy")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy", IsNullable = false)] - public partial class Signer - { - - private CertRoot certRootField; - - private CertEKU[] certEKUField; - - private CertIssuer certIssuerField; - - private CertPublisher certPublisherField; - - private CertOemID certOemIDField; - - private FileAttribRef[] fileAttribRefField; - - private string nameField; - - private string idField; - - private System.DateTime signTimeAfterField; - - private bool signTimeAfterFieldSpecified; - - /// - public CertRoot CertRoot - { - get - { - return this.certRootField; - } - set - { - this.certRootField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("CertEKU")] - public CertEKU[] CertEKU - { - get - { - return this.certEKUField; - } - set - { - this.certEKUField = value; - } - } - - /// - public CertIssuer CertIssuer - { - get - { - return this.certIssuerField; - } - set - { - this.certIssuerField = value; - } - } - - /// - public CertPublisher CertPublisher - { - get - { - return this.certPublisherField; - } - set - { - this.certPublisherField = value; - } - } - - /// - public CertOemID CertOemID - { - get - { - return this.certOemIDField; - } - set - { - this.certOemIDField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("FileAttribRef")] - public FileAttribRef[] FileAttribRef - { - get - { - return this.fileAttribRefField; - } - set - { - this.fileAttribRefField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string Name - { - get - { - return this.nameField; - } - set - { - this.nameField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string ID - { - get - { - return this.idField; - } - set - { - this.idField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public System.DateTime SignTimeAfter - { - get - { - return this.signTimeAfterField; - } - set - { - this.signTimeAfterField = value; - } - } - - /// - [System.Xml.Serialization.XmlIgnoreAttribute()] - public bool SignTimeAfterSpecified - { - get - { - return this.signTimeAfterFieldSpecified; - } - set - { - this.signTimeAfterFieldSpecified = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:schemas-microsoft-com:sipolicy")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy", IsNullable = false)] - public partial class SigningScenarios - { - - private SigningScenario[] itemsField; - - /// - [System.Xml.Serialization.XmlElementAttribute("SigningScenario")] - public SigningScenario[] Items - { - get - { - return this.itemsField; - } - set - { - this.itemsField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:schemas-microsoft-com:sipolicy")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy", IsNullable = false)] - public partial class SigningScenario - { - - private ProductSigners productSignersField; - - private TestSigners testSignersField; - - private TestSigningSigners testSigningSignersField; - - private AppIDTags appIDTagsField; - - private string idField; - - private string friendlyNameField; - - private byte valueField; - - private string inheritedScenariosField; - - private ushort minimumHashAlgorithmField; - - private bool minimumHashAlgorithmFieldSpecified; - - /// - public ProductSigners ProductSigners - { - get - { - return this.productSignersField; - } - set - { - this.productSignersField = value; - } - } - - /// - public TestSigners TestSigners - { - get - { - return this.testSignersField; - } - set - { - this.testSignersField = value; - } - } - - /// - public TestSigningSigners TestSigningSigners - { - get - { - return this.testSigningSignersField; - } - set - { - this.testSigningSignersField = value; - } - } - - /// - public AppIDTags AppIDTags - { - get - { - return this.appIDTagsField; - } - set - { - this.appIDTagsField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string ID - { - get - { - return this.idField; - } - set - { - this.idField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string FriendlyName - { - get - { - return this.friendlyNameField; - } - set - { - this.friendlyNameField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public byte Value - { - get - { - return this.valueField; - } - set - { - this.valueField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string InheritedScenarios - { - get - { - return this.inheritedScenariosField; - } - set - { - this.inheritedScenariosField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public ushort MinimumHashAlgorithm - { - get - { - return this.minimumHashAlgorithmField; - } - set - { - this.minimumHashAlgorithmField = value; - } - } - - /// - [System.Xml.Serialization.XmlIgnoreAttribute()] - public bool MinimumHashAlgorithmSpecified - { - get - { - return this.minimumHashAlgorithmFieldSpecified; - } - set - { - this.minimumHashAlgorithmFieldSpecified = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:schemas-microsoft-com:sipolicy")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy", IsNullable = false)] - public partial class SiPolicy - { - - private string versionExField; - - private string policyTypeIDField; - - private string platformIDField; - - private string policyIDField; - - private string basePolicyIDField; - - private RuleType[] rulesField; - - private EKU[] eKUsField; - - private object[] fileRulesField; - - private Signer[] signersField; - - private SigningScenario[] signingScenariosField; - - private UpdatePolicySigner[] updatePolicySignersField; - - private CiSigner[] ciSignersField; - - private uint hvciOptionsField; - - private bool hvciOptionsFieldSpecified; - - private Setting[] settingsField; - - private MacrosMacro[] macrosField; - - private SupplementalPolicySigner[] supplementalPolicySignersField; - - private AppSettingRegion appSettingsField; - - private string friendlyNameField; - - private PolicyType policyTypeField; - - private bool policyTypeFieldSpecified; - - /// - public string VersionEx - { - get - { - return this.versionExField; - } - set - { - this.versionExField = value; - } - } - - /// - public string PolicyTypeID - { - get - { - return this.policyTypeIDField; - } - set - { - this.policyTypeIDField = value; - } - } - - /// - public string PlatformID - { - get - { - return this.platformIDField; - } - set - { - this.platformIDField = value; - } - } - - /// - public string PolicyID - { - get - { - return this.policyIDField; - } - set - { - this.policyIDField = value; - } - } - - /// - public string BasePolicyID - { - get - { - return this.basePolicyIDField; - } - set - { - this.basePolicyIDField = value; - } - } - - /// - [System.Xml.Serialization.XmlArrayItemAttribute("Rule", IsNullable = false)] - public RuleType[] Rules - { - get - { - return this.rulesField; - } - set - { - this.rulesField = value; - } - } - - /// - [System.Xml.Serialization.XmlArrayItemAttribute("EKU", IsNullable = false)] - public EKU[] EKUs - { - get - { - return this.eKUsField; - } - set - { - this.eKUsField = value; - } - } - - /// - [System.Xml.Serialization.XmlArrayItemAttribute("Allow", typeof(Allow), IsNullable = false)] - [System.Xml.Serialization.XmlArrayItemAttribute("Deny", typeof(Deny), IsNullable = false)] - [System.Xml.Serialization.XmlArrayItemAttribute("FileAttrib", typeof(FileAttrib), IsNullable = false)] - [System.Xml.Serialization.XmlArrayItemAttribute("FileRule", typeof(FileRule), IsNullable = false)] - public object[] FileRules - { - get - { - return this.fileRulesField; - } - set - { - this.fileRulesField = value; - } - } - - /// - [System.Xml.Serialization.XmlArrayItemAttribute("Signer", IsNullable = false)] - public Signer[] Signers - { - get - { - return this.signersField; - } - set - { - this.signersField = value; - } - } - - /// - [System.Xml.Serialization.XmlArrayItemAttribute("SigningScenario", IsNullable = false)] - public SigningScenario[] SigningScenarios - { - get - { - return this.signingScenariosField; - } - set - { - this.signingScenariosField = value; - } - } - - /// - [System.Xml.Serialization.XmlArrayItemAttribute("UpdatePolicySigner", IsNullable = false)] - public UpdatePolicySigner[] UpdatePolicySigners - { - get - { - return this.updatePolicySignersField; - } - set - { - this.updatePolicySignersField = value; - } - } - - /// - [System.Xml.Serialization.XmlArrayItemAttribute("CiSigner", IsNullable = false)] - public CiSigner[] CiSigners - { - get - { - return this.ciSignersField; - } - set - { - this.ciSignersField = value; - } - } - - /// - public uint HvciOptions - { - get - { - return this.hvciOptionsField; - } - set - { - this.hvciOptionsField = value; - } - } - - /// - [System.Xml.Serialization.XmlIgnoreAttribute()] - public bool HvciOptionsSpecified - { - get - { - return this.hvciOptionsFieldSpecified; - } - set - { - this.hvciOptionsFieldSpecified = value; - } - } - - /// - [System.Xml.Serialization.XmlArrayItemAttribute("Setting", IsNullable = false)] - public Setting[] Settings - { - get - { - return this.settingsField; - } - set - { - this.settingsField = value; - } - } - - /// - [System.Xml.Serialization.XmlArrayItemAttribute("Macro", IsNullable = false)] - public MacrosMacro[] Macros - { - get - { - return this.macrosField; - } - set - { - this.macrosField = value; - } - } - - /// - [System.Xml.Serialization.XmlArrayItemAttribute("SupplementalPolicySigner", IsNullable = false)] - public SupplementalPolicySigner[] SupplementalPolicySigners - { - get - { - return this.supplementalPolicySignersField; - } - set - { - this.supplementalPolicySignersField = value; - } - } - - /// - public AppSettingRegion AppSettings - { - get - { - return this.appSettingsField; - } - set - { - this.appSettingsField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string FriendlyName - { - get - { - return this.friendlyNameField; - } - set - { - this.friendlyNameField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public PolicyType PolicyType - { - get - { - return this.policyTypeField; - } - set - { - this.policyTypeField = value; - } - } - - /// - [System.Xml.Serialization.XmlIgnoreAttribute()] - public bool PolicyTypeSpecified - { - get - { - return this.policyTypeFieldSpecified; - } - set - { - this.policyTypeFieldSpecified = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.8.3928.0")] - [System.SerializableAttribute()] - [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy")] - public enum PolicyType - { - - /// - [System.Xml.Serialization.XmlEnumAttribute("Base Policy")] - BasePolicy, - - /// - [System.Xml.Serialization.XmlEnumAttribute("Supplemental Policy")] - SupplementalPolicy, - - /// - [System.Xml.Serialization.XmlEnumAttribute("AppID Tagging Policy")] - AppIDTaggingPolicy, - } + using System.Xml.Serialization; + + + + public partial class Macros + { + + private MacrosMacro[] macroField; + + /// + [System.Xml.Serialization.XmlElementAttribute("Macro")] + public MacrosMacro[] Macro + { + get + { + return this.macroField; + } + set + { + this.macroField = value; + } + } + } + + + [System.SerializableAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:schemas-microsoft-com:sipolicy")] + public partial class MacrosMacro + { + + private string idField; + + private string valueField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Id + { + get + { + return this.idField; + } + set + { + this.idField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Value + { + get + { + return this.valueField; + } + set + { + this.valueField = value; + } + } + } + + + [System.SerializableAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy")] + public partial class AppSetting + { + + private string[] valueField; + + private string nameField; + + /// + [System.Xml.Serialization.XmlElementAttribute("Value")] + public string[] Value + { + get + { + return this.valueField; + } + set + { + this.valueField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Name + { + get + { + return this.nameField; + } + set + { + this.nameField = value; + } + } + } + + + [System.SerializableAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy")] + public partial class AppRoot + { + + private AppSetting[] settingField; + + private string manifestField; + + /// + [System.Xml.Serialization.XmlElementAttribute("Setting")] + public AppSetting[] Setting + { + get + { + return this.settingField; + } + set + { + this.settingField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "anyURI")] + public string Manifest + { + get + { + return this.manifestField; + } + set + { + this.manifestField = value; + } + } + } + + + [System.SerializableAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy")] + public partial class AppSettingRegion + { + + private AppRoot[] appField; + + /// + [System.Xml.Serialization.XmlElementAttribute("App")] + public AppRoot[] App + { + get + { + return this.appField; + } + set + { + this.appField = value; + } + } + } + + + [System.SerializableAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy")] + public partial class RuleType + { + + private OptionType itemField; + + /// + [System.Xml.Serialization.XmlElementAttribute("Option")] + public OptionType Item + { + get + { + return this.itemField; + } + set + { + this.itemField = value; + } + } + } + + + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy")] + public enum OptionType + { + + /// + [System.Xml.Serialization.XmlEnumAttribute("Enabled:UMCI")] + EnabledUMCI, + + /// + [System.Xml.Serialization.XmlEnumAttribute("Enabled:Boot Menu Protection")] + EnabledBootMenuProtection, + + /// + [System.Xml.Serialization.XmlEnumAttribute("Enabled:Intelligent Security Graph Authorization")] + EnabledIntelligentSecurityGraphAuthorization, + + /// + [System.Xml.Serialization.XmlEnumAttribute("Enabled:Invalidate EAs on Reboot")] + EnabledInvalidateEAsonReboot, + + /// + [System.Xml.Serialization.XmlEnumAttribute("Required:WHQL")] + RequiredWHQL, + + /// + [System.Xml.Serialization.XmlEnumAttribute("Enabled:Developer Mode Dynamic Code Trust")] + EnabledDeveloperModeDynamicCodeTrust, + + /// + [System.Xml.Serialization.XmlEnumAttribute("Enabled:Allow Supplemental Policies")] + EnabledAllowSupplementalPolicies, + + /// + [System.Xml.Serialization.XmlEnumAttribute("Disabled:Runtime FilePath Rule Protection")] + DisabledRuntimeFilePathRuleProtection, + + /// + [System.Xml.Serialization.XmlEnumAttribute("Enabled:Revoked Expired As Unsigned")] + EnabledRevokedExpiredAsUnsigned, + + /// + [System.Xml.Serialization.XmlEnumAttribute("Enabled:Audit Mode")] + EnabledAuditMode, + + /// + [System.Xml.Serialization.XmlEnumAttribute("Disabled:Flight Signing")] + DisabledFlightSigning, + + /// + [System.Xml.Serialization.XmlEnumAttribute("Enabled:Inherit Default Policy")] + EnabledInheritDefaultPolicy, + + /// + [System.Xml.Serialization.XmlEnumAttribute("Enabled:Unsigned System Integrity Policy")] + EnabledUnsignedSystemIntegrityPolicy, + + /// + [System.Xml.Serialization.XmlEnumAttribute("Enabled:Dynamic Code Security")] + EnabledDynamicCodeSecurity, + + /// + [System.Xml.Serialization.XmlEnumAttribute("Required:EV Signers")] + RequiredEVSigners, + + /// + [System.Xml.Serialization.XmlEnumAttribute("Enabled:Boot Audit On Failure")] + EnabledBootAuditOnFailure, + + /// + [System.Xml.Serialization.XmlEnumAttribute("Enabled:Advanced Boot Options Menu")] + EnabledAdvancedBootOptionsMenu, + + /// + [System.Xml.Serialization.XmlEnumAttribute("Disabled:Script Enforcement")] + DisabledScriptEnforcement, + + /// + [System.Xml.Serialization.XmlEnumAttribute("Required:Enforce Store Applications")] + RequiredEnforceStoreApplications, + + /// + [System.Xml.Serialization.XmlEnumAttribute("Enabled:Secure Setting Policy")] + EnabledSecureSettingPolicy, + + /// + [System.Xml.Serialization.XmlEnumAttribute("Enabled:Managed Installer")] + EnabledManagedInstaller, + + /// + [System.Xml.Serialization.XmlEnumAttribute("Enabled:Update Policy No Reboot")] + EnabledUpdatePolicyNoReboot, + + /// + [System.Xml.Serialization.XmlEnumAttribute("Enabled:Conditional Windows Lockdown Policy")] + EnabledConditionalWindowsLockdownPolicy, + } + + + [System.SerializableAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy")] + public partial class SettingValueType + { + + private object itemField; + + /// + [System.Xml.Serialization.XmlElementAttribute("Binary", typeof(byte[]), DataType = "hexBinary")] + [System.Xml.Serialization.XmlElementAttribute("Boolean", typeof(bool))] + [System.Xml.Serialization.XmlElementAttribute("DWord", typeof(uint))] + [System.Xml.Serialization.XmlElementAttribute("String", typeof(string))] + public object Item + { + get + { + return this.itemField; + } + set + { + this.itemField = value; + } + } + } + + + public partial class Setting + { + + private SettingValueType valueField; + + private string providerField; + + private string keyField; + + private string valueNameField; + + /// + public SettingValueType Value + { + get + { + return this.valueField; + } + set + { + this.valueField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Provider + { + get + { + return this.providerField; + } + set + { + this.providerField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Key + { + get + { + return this.keyField; + } + set + { + this.keyField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string ValueName + { + get + { + return this.valueNameField; + } + set + { + this.valueNameField = value; + } + } + } + + + public partial class Settings + { + + private Setting[] itemsField; + + /// + [System.Xml.Serialization.XmlElementAttribute("Setting")] + public Setting[] Items + { + get + { + return this.itemsField; + } + set + { + this.itemsField = value; + } + } + } + + + public partial class CertEKU + { + + private string idField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string ID + { + get + { + return this.idField; + } + set + { + this.idField = value; + } + } + } + + + public partial class CertOemID + { + + private string valueField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Value + { + get + { + return this.valueField; + } + set + { + this.valueField = value; + } + } + } + + + public partial class CertPublisher + { + + private string valueField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Value + { + get + { + return this.valueField; + } + set + { + this.valueField = value; + } + } + } + + + public partial class CertIssuer + { + + private string valueField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Value + { + get + { + return this.valueField; + } + set + { + this.valueField = value; + } + } + } + + + public partial class CertRoot + { + + private CertEnumType typeField; + + private byte[] valueField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public CertEnumType Type + { + get + { + return this.typeField; + } + set + { + this.typeField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "hexBinary")] + public byte[] Value + { + get + { + return this.valueField; + } + set + { + this.valueField = value; + } + } + } + + + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy")] + public enum CertEnumType + { + + /// + TBS, + + /// + Wellknown, + } + + + public partial class ProductSigners + { + + private AllowedSigners allowedSignersField; + + private DeniedSigners deniedSignersField; + + private FileRulesRef fileRulesRefField; + + /// + public AllowedSigners AllowedSigners + { + get + { + return this.allowedSignersField; + } + set + { + this.allowedSignersField = value; + } + } + + /// + public DeniedSigners DeniedSigners + { + get + { + return this.deniedSignersField; + } + set + { + this.deniedSignersField = value; + } + } + + /// + public FileRulesRef FileRulesRef + { + get + { + return this.fileRulesRefField; + } + set + { + this.fileRulesRefField = value; + } + } + } + + + public partial class AllowedSigners + { + + private AllowedSigner[] allowedSignerField; + + private string workaroundField; + + /// + [System.Xml.Serialization.XmlElementAttribute("AllowedSigner")] + public AllowedSigner[] AllowedSigner + { + get + { + return this.allowedSignerField; + } + set + { + this.allowedSignerField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Workaround + { + get + { + return this.workaroundField; + } + set + { + this.workaroundField = value; + } + } + } + + + public partial class AllowedSigner + { + + private ExceptDenyRule[] exceptDenyRuleField; + + private string signerIdField; + + /// + [System.Xml.Serialization.XmlElementAttribute("ExceptDenyRule")] + public ExceptDenyRule[] ExceptDenyRule + { + get + { + return this.exceptDenyRuleField; + } + set + { + this.exceptDenyRuleField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string SignerId + { + get + { + return this.signerIdField; + } + set + { + this.signerIdField = value; + } + } + } + + + public partial class ExceptDenyRule + { + + private string denyRuleIDField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string DenyRuleID + { + get + { + return this.denyRuleIDField; + } + set + { + this.denyRuleIDField = value; + } + } + } + + + public partial class DeniedSigners + { + + private DeniedSigner[] deniedSignerField; + + private string workaroundField; + + /// + [System.Xml.Serialization.XmlElementAttribute("DeniedSigner")] + public DeniedSigner[] DeniedSigner + { + get + { + return this.deniedSignerField; + } + set + { + this.deniedSignerField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Workaround + { + get + { + return this.workaroundField; + } + set + { + this.workaroundField = value; + } + } + } + + + public partial class DeniedSigner + { + + private ExceptAllowRule[] exceptAllowRuleField; + + private string signerIdField; + + /// + [System.Xml.Serialization.XmlElementAttribute("ExceptAllowRule")] + public ExceptAllowRule[] ExceptAllowRule + { + get + { + return this.exceptAllowRuleField; + } + set + { + this.exceptAllowRuleField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string SignerId + { + get + { + return this.signerIdField; + } + set + { + this.signerIdField = value; + } + } + } + + + public partial class ExceptAllowRule + { + + private string allowRuleIDField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string AllowRuleID + { + get + { + return this.allowRuleIDField; + } + set + { + this.allowRuleIDField = value; + } + } + } + + + public partial class FileRulesRef + { + + private FileRuleRef[] fileRuleRefField; + + private string workaroundField; + + /// + [System.Xml.Serialization.XmlElementAttribute("FileRuleRef")] + public FileRuleRef[] FileRuleRef + { + get + { + return this.fileRuleRefField; + } + set + { + this.fileRuleRefField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Workaround + { + get + { + return this.workaroundField; + } + set + { + this.workaroundField = value; + } + } + } + + + public partial class FileRuleRef + { + + private string ruleIDField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string RuleID + { + get + { + return this.ruleIDField; + } + set + { + this.ruleIDField = value; + } + } + } + + + public partial class TestSigners + { + + private AllowedSigners allowedSignersField; + + private DeniedSigners deniedSignersField; + + private FileRulesRef fileRulesRefField; + + /// + public AllowedSigners AllowedSigners + { + get + { + return this.allowedSignersField; + } + set + { + this.allowedSignersField = value; + } + } + + /// + public DeniedSigners DeniedSigners + { + get + { + return this.deniedSignersField; + } + set + { + this.deniedSignersField = value; + } + } + + /// + public FileRulesRef FileRulesRef + { + get + { + return this.fileRulesRefField; + } + set + { + this.fileRulesRefField = value; + } + } + } + + + public partial class TestSigningSigners + { + + private AllowedSigners allowedSignersField; + + private DeniedSigners deniedSignersField; + + private FileRulesRef fileRulesRefField; + + /// + public AllowedSigners AllowedSigners + { + get + { + return this.allowedSignersField; + } + set + { + this.allowedSignersField = value; + } + } + + /// + public DeniedSigners DeniedSigners + { + get + { + return this.deniedSignersField; + } + set + { + this.deniedSignersField = value; + } + } + + /// + public FileRulesRef FileRulesRef + { + get + { + return this.fileRulesRefField; + } + set + { + this.fileRulesRefField = value; + } + } + } + + + public partial class AppIDTag + { + + private string keyField; + + private string valueField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Key + { + get + { + return this.keyField; + } + set + { + this.keyField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Value + { + get + { + return this.valueField; + } + set + { + this.valueField = value; + } + } + } + + + public partial class AppIDTags + { + + private AppIDTag[] appIDTagField; + + private bool enforceDLLField; + + private bool enforceDLLFieldSpecified; + + /// + [System.Xml.Serialization.XmlElementAttribute("AppIDTag")] + public AppIDTag[] AppIDTag + { + get + { + return this.appIDTagField; + } + set + { + this.appIDTagField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public bool EnforceDLL + { + get + { + return this.enforceDLLField; + } + set + { + this.enforceDLLField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool EnforceDLLSpecified + { + get + { + return this.enforceDLLFieldSpecified; + } + set + { + this.enforceDLLFieldSpecified = value; + } + } + } + + + public partial class FileAttribRef + { + + private string ruleIDField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string RuleID + { + get + { + return this.ruleIDField; + } + set + { + this.ruleIDField = value; + } + } + } + + + public partial class EKUs + { + + private EKU[] itemsField; + + /// + [System.Xml.Serialization.XmlElementAttribute("EKU")] + public EKU[] Items + { + get + { + return this.itemsField; + } + set + { + this.itemsField = value; + } + } + } + + + public partial class EKU + { + + private string idField; + + private byte[] valueField; + + private string friendlyNameField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string ID + { + get + { + return this.idField; + } + set + { + this.idField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "hexBinary")] + public byte[] Value + { + get + { + return this.valueField; + } + set + { + this.valueField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string FriendlyName + { + get + { + return this.friendlyNameField; + } + set + { + this.friendlyNameField = value; + } + } + } + + + public partial class FileRules + { + + private object[] itemsField; + + /// + [System.Xml.Serialization.XmlElementAttribute("Allow", typeof(Allow))] + [System.Xml.Serialization.XmlElementAttribute("Deny", typeof(Deny))] + [System.Xml.Serialization.XmlElementAttribute("FileAttrib", typeof(FileAttrib))] + [System.Xml.Serialization.XmlElementAttribute("FileRule", typeof(FileRule))] + public object[] Items + { + get + { + return this.itemsField; + } + set + { + this.itemsField = value; + } + } + } + + + public partial class Allow + { + + private string idField; + + private string friendlyNameField; + + private string fileNameField; + + private string internalNameField; + + private string fileDescriptionField; + + private string productNameField; + + private string packageFamilyNameField; + + private string packageVersionField; + + private string minimumFileVersionField; + + private string maximumFileVersionField; + + private byte[] hashField; + + private string appIDsField; + + private string filePathField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string ID + { + get + { + return this.idField; + } + set + { + this.idField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string FriendlyName + { + get + { + return this.friendlyNameField; + } + set + { + this.friendlyNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string FileName + { + get + { + return this.fileNameField; + } + set + { + this.fileNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string InternalName + { + get + { + return this.internalNameField; + } + set + { + this.internalNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string FileDescription + { + get + { + return this.fileDescriptionField; + } + set + { + this.fileDescriptionField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string ProductName + { + get + { + return this.productNameField; + } + set + { + this.productNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string PackageFamilyName + { + get + { + return this.packageFamilyNameField; + } + set + { + this.packageFamilyNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string PackageVersion + { + get + { + return this.packageVersionField; + } + set + { + this.packageVersionField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string MinimumFileVersion + { + get + { + return this.minimumFileVersionField; + } + set + { + this.minimumFileVersionField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string MaximumFileVersion + { + get + { + return this.maximumFileVersionField; + } + set + { + this.maximumFileVersionField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "hexBinary")] + public byte[] Hash + { + get + { + return this.hashField; + } + set + { + this.hashField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string AppIDs + { + get + { + return this.appIDsField; + } + set + { + this.appIDsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string FilePath + { + get + { + return this.filePathField; + } + set + { + this.filePathField = value; + } + } + } + + + public partial class Deny + { + + private string idField; + + private string friendlyNameField; + + private string fileNameField; + + private string internalNameField; + + private string fileDescriptionField; + + private string productNameField; + + private string packageFamilyNameField; + + private string packageVersionField; + + private string minimumFileVersionField; + + private string maximumFileVersionField; + + private byte[] hashField; + + private string appIDsField; + + private string filePathField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string ID + { + get + { + return this.idField; + } + set + { + this.idField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string FriendlyName + { + get + { + return this.friendlyNameField; + } + set + { + this.friendlyNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string FileName + { + get + { + return this.fileNameField; + } + set + { + this.fileNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string InternalName + { + get + { + return this.internalNameField; + } + set + { + this.internalNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string FileDescription + { + get + { + return this.fileDescriptionField; + } + set + { + this.fileDescriptionField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string ProductName + { + get + { + return this.productNameField; + } + set + { + this.productNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string PackageFamilyName + { + get + { + return this.packageFamilyNameField; + } + set + { + this.packageFamilyNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string PackageVersion + { + get + { + return this.packageVersionField; + } + set + { + this.packageVersionField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string MinimumFileVersion + { + get + { + return this.minimumFileVersionField; + } + set + { + this.minimumFileVersionField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string MaximumFileVersion + { + get + { + return this.maximumFileVersionField; + } + set + { + this.maximumFileVersionField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "hexBinary")] + public byte[] Hash + { + get + { + return this.hashField; + } + set + { + this.hashField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string AppIDs + { + get + { + return this.appIDsField; + } + set + { + this.appIDsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string FilePath + { + get + { + return this.filePathField; + } + set + { + this.filePathField = value; + } + } + } + + + public partial class FileAttrib + { + + private string idField; + + private string friendlyNameField; + + private string fileNameField; + + private string internalNameField; + + private string fileDescriptionField; + + private string productNameField; + + private string packageFamilyNameField; + + private string packageVersionField; + + private string minimumFileVersionField; + + private string maximumFileVersionField; + + private byte[] hashField; + + private string appIDsField; + + private string filePathField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string ID + { + get + { + return this.idField; + } + set + { + this.idField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string FriendlyName + { + get + { + return this.friendlyNameField; + } + set + { + this.friendlyNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string FileName + { + get + { + return this.fileNameField; + } + set + { + this.fileNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string InternalName + { + get + { + return this.internalNameField; + } + set + { + this.internalNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string FileDescription + { + get + { + return this.fileDescriptionField; + } + set + { + this.fileDescriptionField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string ProductName + { + get + { + return this.productNameField; + } + set + { + this.productNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string PackageFamilyName + { + get + { + return this.packageFamilyNameField; + } + set + { + this.packageFamilyNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string PackageVersion + { + get + { + return this.packageVersionField; + } + set + { + this.packageVersionField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string MinimumFileVersion + { + get + { + return this.minimumFileVersionField; + } + set + { + this.minimumFileVersionField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string MaximumFileVersion + { + get + { + return this.maximumFileVersionField; + } + set + { + this.maximumFileVersionField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "hexBinary")] + public byte[] Hash + { + get + { + return this.hashField; + } + set + { + this.hashField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string AppIDs + { + get + { + return this.appIDsField; + } + set + { + this.appIDsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string FilePath + { + get + { + return this.filePathField; + } + set + { + this.filePathField = value; + } + } + } + + + public partial class FileRule + { + + private string idField; + + private string friendlyNameField; + + private string fileNameField; + + private string internalNameField; + + private string fileDescriptionField; + + private string productNameField; + + private string packageFamilyNameField; + + private string packageVersionField; + + private string minimumFileVersionField; + + private string maximumFileVersionField; + + private byte[] hashField; + + private string appIDsField; + + private string filePathField; + + private RuleTypeType typeField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string ID + { + get + { + return this.idField; + } + set + { + this.idField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string FriendlyName + { + get + { + return this.friendlyNameField; + } + set + { + this.friendlyNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string FileName + { + get + { + return this.fileNameField; + } + set + { + this.fileNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string InternalName + { + get + { + return this.internalNameField; + } + set + { + this.internalNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string FileDescription + { + get + { + return this.fileDescriptionField; + } + set + { + this.fileDescriptionField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string ProductName + { + get + { + return this.productNameField; + } + set + { + this.productNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string PackageFamilyName + { + get + { + return this.packageFamilyNameField; + } + set + { + this.packageFamilyNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string PackageVersion + { + get + { + return this.packageVersionField; + } + set + { + this.packageVersionField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string MinimumFileVersion + { + get + { + return this.minimumFileVersionField; + } + set + { + this.minimumFileVersionField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string MaximumFileVersion + { + get + { + return this.maximumFileVersionField; + } + set + { + this.maximumFileVersionField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "hexBinary")] + public byte[] Hash + { + get + { + return this.hashField; + } + set + { + this.hashField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string AppIDs + { + get + { + return this.appIDsField; + } + set + { + this.appIDsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string FilePath + { + get + { + return this.filePathField; + } + set + { + this.filePathField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public RuleTypeType Type + { + get + { + return this.typeField; + } + set + { + this.typeField = value; + } + } + } + + + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy")] + public enum RuleTypeType + { + + /// + Match, + + /// + Exclude, + + /// + Attribute, + } + + + public partial class UpdatePolicySigner + { + + private string signerIdField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string SignerId + { + get + { + return this.signerIdField; + } + set + { + this.signerIdField = value; + } + } + } + + + public partial class UpdatePolicySigners + { + + private UpdatePolicySigner[] itemsField; + + /// + [System.Xml.Serialization.XmlElementAttribute("UpdatePolicySigner")] + public UpdatePolicySigner[] Items + { + get + { + return this.itemsField; + } + set + { + this.itemsField = value; + } + } + } + + + public partial class SupplementalPolicySigner + { + + private string signerIdField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string SignerId + { + get + { + return this.signerIdField; + } + set + { + this.signerIdField = value; + } + } + } + + + public partial class SupplementalPolicySigners + { + + private SupplementalPolicySigner[] itemsField; + + /// + [System.Xml.Serialization.XmlElementAttribute("SupplementalPolicySigner")] + public SupplementalPolicySigner[] Items + { + get + { + return this.itemsField; + } + set + { + this.itemsField = value; + } + } + } + + + public partial class CiSigner + { + + private string signerIdField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string SignerId + { + get + { + return this.signerIdField; + } + set + { + this.signerIdField = value; + } + } + } + + + public partial class CiSigners + { + + private CiSigner[] itemsField; + + /// + [System.Xml.Serialization.XmlElementAttribute("CiSigner")] + public CiSigner[] Items + { + get + { + return this.itemsField; + } + set + { + this.itemsField = value; + } + } + } + + + public partial class Signers + { + + private Signer[] itemsField; + + /// + [System.Xml.Serialization.XmlElementAttribute("Signer")] + public Signer[] Items + { + get + { + return this.itemsField; + } + set + { + this.itemsField = value; + } + } + } + + + public partial class Signer + { + + private CertRoot certRootField; + + private CertEKU[] certEKUField; + + private CertIssuer certIssuerField; + + private CertPublisher certPublisherField; + + private CertOemID certOemIDField; + + private FileAttribRef[] fileAttribRefField; + + private string nameField; + + private string idField; + + private System.DateTime signTimeAfterField; + + private bool signTimeAfterFieldSpecified; + + /// + public CertRoot CertRoot + { + get + { + return this.certRootField; + } + set + { + this.certRootField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("CertEKU")] + public CertEKU[] CertEKU + { + get + { + return this.certEKUField; + } + set + { + this.certEKUField = value; + } + } + + /// + public CertIssuer CertIssuer + { + get + { + return this.certIssuerField; + } + set + { + this.certIssuerField = value; + } + } + + /// + public CertPublisher CertPublisher + { + get + { + return this.certPublisherField; + } + set + { + this.certPublisherField = value; + } + } + + /// + public CertOemID CertOemID + { + get + { + return this.certOemIDField; + } + set + { + this.certOemIDField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("FileAttribRef")] + public FileAttribRef[] FileAttribRef + { + get + { + return this.fileAttribRefField; + } + set + { + this.fileAttribRefField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string Name + { + get + { + return this.nameField; + } + set + { + this.nameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string ID + { + get + { + return this.idField; + } + set + { + this.idField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public System.DateTime SignTimeAfter + { + get + { + return this.signTimeAfterField; + } + set + { + this.signTimeAfterField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool SignTimeAfterSpecified + { + get + { + return this.signTimeAfterFieldSpecified; + } + set + { + this.signTimeAfterFieldSpecified = value; + } + } + } + + + public partial class SigningScenarios + { + + private SigningScenario[] itemsField; + + /// + [System.Xml.Serialization.XmlElementAttribute("SigningScenario")] + public SigningScenario[] Items + { + get + { + return this.itemsField; + } + set + { + this.itemsField = value; + } + } + } + + + public partial class SigningScenario + { + + private ProductSigners productSignersField; + + private TestSigners testSignersField; + + private TestSigningSigners testSigningSignersField; + + private AppIDTags appIDTagsField; + + private string idField; + + private string friendlyNameField; + + private byte valueField; + + private string inheritedScenariosField; + + private ushort minimumHashAlgorithmField; + + private bool minimumHashAlgorithmFieldSpecified; + + /// + public ProductSigners ProductSigners + { + get + { + return this.productSignersField; + } + set + { + this.productSignersField = value; + } + } + + /// + public TestSigners TestSigners + { + get + { + return this.testSignersField; + } + set + { + this.testSignersField = value; + } + } + + /// + public TestSigningSigners TestSigningSigners + { + get + { + return this.testSigningSignersField; + } + set + { + this.testSigningSignersField = value; + } + } + + /// + public AppIDTags AppIDTags + { + get + { + return this.appIDTagsField; + } + set + { + this.appIDTagsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string ID + { + get + { + return this.idField; + } + set + { + this.idField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string FriendlyName + { + get + { + return this.friendlyNameField; + } + set + { + this.friendlyNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public byte Value + { + get + { + return this.valueField; + } + set + { + this.valueField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string InheritedScenarios + { + get + { + return this.inheritedScenariosField; + } + set + { + this.inheritedScenariosField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public ushort MinimumHashAlgorithm + { + get + { + return this.minimumHashAlgorithmField; + } + set + { + this.minimumHashAlgorithmField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool MinimumHashAlgorithmSpecified + { + get + { + return this.minimumHashAlgorithmFieldSpecified; + } + set + { + this.minimumHashAlgorithmFieldSpecified = value; + } + } + } + + + public partial class SiPolicy + { + + private string versionExField; + + private string policyTypeIDField; + + private string platformIDField; + + private string policyIDField; + + private string basePolicyIDField; + + private RuleType[] rulesField; + + private EKU[] eKUsField; + + private object[] fileRulesField; + + private Signer[] signersField; + + private SigningScenario[] signingScenariosField; + + private UpdatePolicySigner[] updatePolicySignersField; + + private CiSigner[] ciSignersField; + + private uint hvciOptionsField; + + private bool hvciOptionsFieldSpecified; + + private Setting[] settingsField; + + private MacrosMacro[] macrosField; + + private SupplementalPolicySigner[] supplementalPolicySignersField; + + private AppSettingRegion appSettingsField; + + private string friendlyNameField; + + private PolicyType policyTypeField; + + private bool policyTypeFieldSpecified; + + /// + public string VersionEx + { + get + { + return this.versionExField; + } + set + { + this.versionExField = value; + } + } + + /// + public string PolicyTypeID + { + get + { + return this.policyTypeIDField; + } + set + { + this.policyTypeIDField = value; + } + } + + /// + public string PlatformID + { + get + { + return this.platformIDField; + } + set + { + this.platformIDField = value; + } + } + + /// + public string PolicyID + { + get + { + return this.policyIDField; + } + set + { + this.policyIDField = value; + } + } + + /// + public string BasePolicyID + { + get + { + return this.basePolicyIDField; + } + set + { + this.basePolicyIDField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Rule", IsNullable = false)] + public RuleType[] Rules + { + get + { + return this.rulesField; + } + set + { + this.rulesField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("EKU", IsNullable = false)] + public EKU[] EKUs + { + get + { + return this.eKUsField; + } + set + { + this.eKUsField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Allow", typeof(Allow), IsNullable = false)] + [System.Xml.Serialization.XmlArrayItemAttribute("Deny", typeof(Deny), IsNullable = false)] + [System.Xml.Serialization.XmlArrayItemAttribute("FileAttrib", typeof(FileAttrib), IsNullable = false)] + [System.Xml.Serialization.XmlArrayItemAttribute("FileRule", typeof(FileRule), IsNullable = false)] + public object[] FileRules + { + get + { + return this.fileRulesField; + } + set + { + this.fileRulesField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Signer", IsNullable = false)] + public Signer[] Signers + { + get + { + return this.signersField; + } + set + { + this.signersField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("SigningScenario", IsNullable = false)] + public SigningScenario[] SigningScenarios + { + get + { + return this.signingScenariosField; + } + set + { + this.signingScenariosField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("UpdatePolicySigner", IsNullable = false)] + public UpdatePolicySigner[] UpdatePolicySigners + { + get + { + return this.updatePolicySignersField; + } + set + { + this.updatePolicySignersField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("CiSigner", IsNullable = false)] + public CiSigner[] CiSigners + { + get + { + return this.ciSignersField; + } + set + { + this.ciSignersField = value; + } + } + + /// + public uint HvciOptions + { + get + { + return this.hvciOptionsField; + } + set + { + this.hvciOptionsField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool HvciOptionsSpecified + { + get + { + return this.hvciOptionsFieldSpecified; + } + set + { + this.hvciOptionsFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Setting", IsNullable = false)] + public Setting[] Settings + { + get + { + return this.settingsField; + } + set + { + this.settingsField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("Macro", IsNullable = false)] + public MacrosMacro[] Macros + { + get + { + return this.macrosField; + } + set + { + this.macrosField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("SupplementalPolicySigner", IsNullable = false)] + public SupplementalPolicySigner[] SupplementalPolicySigners + { + get + { + return this.supplementalPolicySignersField; + } + set + { + this.supplementalPolicySignersField = value; + } + } + + /// + public AppSettingRegion AppSettings + { + get + { + return this.appSettingsField; + } + set + { + this.appSettingsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string FriendlyName + { + get + { + return this.friendlyNameField; + } + set + { + this.friendlyNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public PolicyType PolicyType + { + get + { + return this.policyTypeField; + } + set + { + this.policyTypeField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool PolicyTypeSpecified + { + get + { + return this.policyTypeFieldSpecified; + } + set + { + this.policyTypeFieldSpecified = value; + } + } + } + + + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:schemas-microsoft-com:sipolicy")] + public enum PolicyType + { + + /// + [System.Xml.Serialization.XmlEnumAttribute("Base Policy")] + BasePolicy, + + /// + [System.Xml.Serialization.XmlEnumAttribute("Supplemental Policy")] + SupplementalPolicy, + + /// + [System.Xml.Serialization.XmlEnumAttribute("AppID Tagging Policy")] + AppIDTaggingPolicy, + } } diff --git a/AppControl Manager/Strings/en-US/Resources.resw b/AppControl Manager/Strings/en-US/Resources.resw index f9029695a..dfbb9f74e 100644 --- a/AppControl Manager/Strings/en-US/Resources.resw +++ b/AppControl Manager/Strings/en-US/Resources.resw @@ -1,6 +1,5 @@  - - - + - + - - - - + + + + - - + + - - + + - - - - + + + + - + - + @@ -255,7 +254,7 @@ Deploy after Creation - Toggling this button means the policy will be deployed on the system after it's been created + Toggling this button means the policy will be deployed on the system after it's been created Create Supplemental Policy @@ -279,13 +278,13 @@ Create Deny policy by scanning files and folders - Create a Deny policy based on an app's Package Family Name (PFN) + Create a Deny policy based on an app's Package Family Name (PFN) Package Family Name - Create a Deny policy based on an app's Package Family Name (PFN) + Create a Deny policy based on an app's Package Family Name (PFN) Indicates that the created/deployed policy will have (Enabled:Audit Mode) policy rule option and will generate audit logs instead of blocking files. @@ -399,7 +398,7 @@ Deploy after Creation - Toggling this button means the policy will be deployed on the system after it's been created + Toggling this button means the policy will be deployed on the system after it's been created Search the data... @@ -519,7 +518,7 @@ Select the required info such as a deployed policy XML file and a name for the Supplemental policy that will be created - Now install your new app or run a pre-installed app that was being blocked. You can optionally browse for folders to scan such as the location where the app is installed. Once you're done, use the button below to go to Step 3. + Now install your new app or run a pre-installed app that was being blocked. You can optionally browse for folders to scan such as the location where the app is installed. Once you're done, use the button below to go to Step 3. Use the Event logs and local files tab to confirm or select the detected files in order to include them in the final Supplemental policy. @@ -591,7 +590,7 @@ Refresh - Fetches the latest certificate common names from the User's personal certificate store + Fetches the latest certificate common names from the User's personal certificate store Customize the App Background Style @@ -609,7 +608,7 @@ Icons Style - Pick a style for the main navigation's icons. + Pick a style for the main navigation's icons. Customize the Theme @@ -645,7 +644,7 @@ Darker Background - It will remove the extra light shadow from the background, giving an overall darker look to the AppControl Manager's appearance. + It will remove the extra light shadow from the background, giving an overall darker look to the AppControl Manager's appearance. User Configurations @@ -690,16 +689,16 @@ App Control policies restrict both kernel-mode and user-mode binaries. By default, only kernel-mode binaries are restricted. Enabling this rule option validates user mode executables and scripts. - This option isn't currently supported. + This option isn't currently supported. - By default, kernel drivers that aren't Windows Hardware Quality Labs (WHQL) signed are allowed to run. Enabling this rule requires that every driver is WHQL signed and removes legacy driver support. Kernel drivers built for Windows 10 should be WHQL certified. + By default, kernel drivers that aren't Windows Hardware Quality Labs (WHQL) signed are allowed to run. Enabling this rule requires that every driver is WHQL signed and removes legacy driver support. Kernel drivers built for Windows 10 should be WHQL certified. Instructs App Control to log information about applications, binaries, and scripts that would have been blocked, if the policy was enforced. You can use this option to identify the potential impact of your App Control policy, and use the audit events to refine the policy before enforcement. To enforce an App Control policy, delete this option. - If enabled, binaries from Windows Insider builds aren't trusted. This option is useful for organizations that only want to run released binaries, not prerelease Windows builds. + If enabled, binaries from Windows Insider builds aren't trusted. This option is useful for organizations that only want to run released binaries, not prerelease Windows builds. This option is reserved for future use and currently has no effect. @@ -708,7 +707,7 @@ Allows the policy to remain unsigned. When this option is removed, the policy must be signed and any supplemental policies must also be signed. The certificates that are trusted for future policy updates must be identified in the UpdatePolicySigners section. Certificates that are trusted for supplemental policies must be identified in the SupplementalPolicySigners section. - This option isn't currently supported. + This option isn't currently supported. The F8 preboot menu is disabled by default for all App Control policies. Setting this rule option allows the F8 menu to appear to physically present users. @@ -718,7 +717,7 @@ This option disables script enforcement options, covering PowerShell, Windows Based Script Host (wscript.exe), Windows Console Based Script Host (cscript.exe), HTA files run in Microsoft HTML Application Host (mshta.exe), and MSXML. Some script hosts may behave differently even when your policy is in audit mode. For more information on script enforcement, see Script enforcement with App Control. -NOTE: This option isn't supported on Windows Server 2016 or Windows 10 1607 LTSB and shouldn't be used on those operating systems. +NOTE: This option isn't supported on Windows Server 2016 or Windows 10 1607 LTSB and shouldn't be used on those operating systems. If this rule option is enabled, App Control policies also apply to Universal Windows applications. @@ -727,7 +726,7 @@ NOTE: This option isn't supported on Windows Server 2016 or Windows 10 1607 LTSB Use this option to automatically allow applications installed by a managed installer. For more information, see Authorize apps deployed with an App Control managed installer. - Use this option to automatically allow applications with "known good" reputation as defined by Microsoft's Intelligent Security Graph (ISG). + Use this option to automatically allow applications with "known good" reputation as defined by Microsoft's Intelligent Security Graph (ISG). When the Intelligent Security Graph option is used, App Control sets an extended file attribute that indicates that the file was authorized to run. This option causes App Control to periodically revalidate the reputation for files previously authorized by the ISG. @@ -747,10 +746,10 @@ NOTE: This option is only supported on Windows 10, version 1903 and later, or Wi Enables policy enforcement for .NET applications and dynamically loaded libraries. NOTE: This option is only supported on Windows 10, version 1803 and later, or Windows Server 2019 and later. -NOTE: This option is always enforced if any App Control UMCI policy enables it. There's no audit mode for .NET dynamic code security hardening. +NOTE: This option is always enforced if any App Control UMCI policy enables it. There's no audit mode for .NET dynamic code security hardening. - Use this option to treat binaries signed with revoked certificates, or expired certificates with the Lifetime Signing EKU on the signature, as "Unsigned binaries" for user-mode process/components, under enterprise signing scenarios. + Use this option to treat binaries signed with revoked certificates, or expired certificates with the Lifetime Signing EKU on the signature, as "Unsigned binaries" for user-mode process/components, under enterprise signing scenarios. Use this option to trust UWP apps that are debugged in Visual Studio or deployed through device portal when Developer Mode is enabled on the system. @@ -759,7 +758,7 @@ NOTE: This option is always enforced if any App Control UMCI policy enables it. It is currently undocumented. - It's used by the Smart App Control policy only. + It's used by the Smart App Control policy only. Configure Policy Rule Options @@ -912,10 +911,10 @@ NOTE: This option is always enforced if any App Control UMCI policy enables it. unsigned XML files. - Currently Deploying XML file: ' + Currently Deploying XML file: ' - The XML file ' + The XML file ' There was an error deploying the selected XML files @@ -945,7 +944,7 @@ NOTE: This option is always enforced if any App Control UMCI policy enables it. CIP binary files. - Currently Deploying CIP file: ' + Currently Deploying CIP file: ' Successfully deployed all of the selected CIP files @@ -996,7 +995,7 @@ NOTE: This option is always enforced if any App Control UMCI policy enables it. Success - Successfully generated the certificate with the selected details. The certificate's thumbprint is: ' + Successfully generated the certificate with the selected details. The certificate's thumbprint is: ' CreateDenyPolicy is not initialized. @@ -1044,7 +1043,7 @@ NOTE: This option is always enforced if any App Control UMCI policy enables it. An error occurred while creating the Deny policy - Successfully created a Deny policy named ' + Successfully created a Deny policy named ' Scalability: @@ -1080,7 +1079,7 @@ NOTE: This option is always enforced if any App Control UMCI policy enables it. WARNING - The policy ' + The policy ' must not be manually removed because you WILL NOT BE ABLE TO USE APPCONTROL MANAGER AGAIN. It is automatically removed when its corresponding base policy is removed from the system. Are you sure you still want to remove it manually? @@ -1092,42 +1091,42 @@ NOTE: This option is always enforced if any App Control UMCI policy enables it. No - Before you can safely remove the signed policy named ' + Before you can safely remove the signed policy named ' - with the ID ' + with the ID ' I Understand - + Policy ID - + Base Policy ID - + Friendly Name - + Version - + Is Authorized - + Is Enforced - + Is On Disk - + Is Signed Policy - + Is System Policy - + Policy Options @@ -1164,10 +1163,10 @@ NOTE: This option is always enforced if any App Control UMCI policy enables it. Policy Options: - System's last reboot was + System's last reboot was - Signed policy with the ID ' + Signed policy with the ID ' completed its 1st stage at @@ -1185,7 +1184,7 @@ NOTE: This option is always enforced if any App Control UMCI policy enables it. will be changed to the type - It will be re-deployed on the system with the same Policy ID and Base Policy ID. If it's currently in Audit Mode, it will be in Enforced Mode after this operation is completed. + It will be re-deployed on the system with the same Policy ID and Base Policy ID. If it's currently in Audit Mode, it will be in Enforced Mode after this operation is completed. Any existing Supplemental policy will continue to work. @@ -1223,4 +1222,148 @@ NOTE: This option is always enforced if any App Control UMCI policy enables it. Successfully created the Strict Kernel-mode policy + + File Name + + + Signature Status + + + Original File Name + + + InternalName + + + File Description + + + Product Name + + + File Version + + + Package Family Name + + + SHA256 Hash + + + SHA1 Hash + + + Signing Scenario + + + File Path + + + SHA1 Page Hash + + + SHA256 Page Hash + + + Has WHQL Signer + + + File Publishers + + + Is ECC Signed + + + Opus Data + + + Policy GUID + + + Policy Name + + + Time Created + + + Action + + + Path + + + Source + + + Is Authorized + + + Match Criteria + + + Specific File Name Level Match + + + Signer ID + + + Signer Name + + + Signer CertRoot + + + Signer Cert Publisher + + + Signer Scope + + + Cert Subject CN + + + Cert Issuer CN + + + Cert Not After + + + Cert TBS Value + + + File Path + + + Signer Number + + + Type + + + Subject Common Name + + + Issuer Common Name + + + Not Before + + + Not After + + + Hashing Algorithm + + + Serial Number + + + Thumbprint + + + TBS Hash + + + Extension OIDs + \ No newline at end of file diff --git a/AppControl Manager/app.manifest b/AppControl Manager/app.manifest index b6e53bfe1..e509ae84c 100644 --- a/AppControl Manager/app.manifest +++ b/AppControl Manager/app.manifest @@ -2,7 +2,7 @@ - + diff --git a/Wiki posts/AppControl Manager/AppControl Manager.md b/Wiki posts/AppControl Manager/AppControl Manager.md index 7bb489325..b192d91b7 100644 --- a/Wiki posts/AppControl Manager/AppControl Manager.md +++ b/Wiki posts/AppControl Manager/AppControl Manager.md @@ -177,7 +177,6 @@ Here is the complete list of all of the URLs the AppControl Manager application | https://raw.githubusercontent.com/HotCakeX/Harden-Windows-Security/refs/heads/main/AppControl%20Manager/version.txt | The latest available version of the AppControl Manager application. That text file is updated via automated GitHub action workflow that securely builds and uploads the MSIXBundle package to the GitHub releases. | | https://github.com/HotCakeX/Harden-Windows-Security/wiki/Introduction | The link that opens in the GitHub documentations page in the app via the built-in WebView 2 | | https://learn.microsoft.com/en-us/windows/security/application-security/application-control/app-control-for-business/appcontrol | The link that opens in the Microsoft documentations page in the app via the built-in WebView 2 | -| https://github.com/HotCakeX/Harden-Windows-Security/issues/415 | A link to one of the GitHub issues | | https://github.com/HotCakeX/Harden-Windows-Security/releases | During the update process, this link that is for the GitHub releases will be displayed on the update page as a quick way to read the release notes | | https://github.com/HotCakeX/Harden-Windows-Security/wiki/AppControl-Manager | Will be displayed on the Update page when a new version is available and being downloaded | | https://github.com/HotCakeX/Harden-Windows-Security/issues/new/choose | Link for the "Send Feedback" button at the bottom of the about section in settings | @@ -297,7 +296,7 @@ if ($LASTEXITCODE -ne 0) { throw [System.InvalidOperationException]::New('Failed # https://learn.microsoft.com/en-us/visualstudio/install/workload-component-id-vs-build-tools # https://learn.microsoft.com/en-us/visualstudio/install/use-command-line-parameters-to-install-visual-studio # https://learn.microsoft.com/en-us/visualstudio/install/workload-component-id-vs-community -winget install --id Microsoft.VisualStudio.2022.BuildTools --exact --accept-package-agreements --accept-source-agreements --uninstall-previous --force --source winget --override '--force --wait --passive --add Microsoft.VisualStudio.Workload.ManagedDesktop --add Microsoft.VisualStudio.Workload.VCTools --add Microsoft.VisualStudio.Workload.MSBuildTools --add Microsoft.VisualStudio.Workload.UniversalBuildTools --add Microsoft.VisualStudio.ComponentGroup.WindowsAppSDK.Cs --add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 --add Microsoft.VisualStudio.Component.VC.v141.x86.x64 --add Microsoft.VisualStudio.Component.Windows11SDK.26100 --includeRecommended' +winget install --id Microsoft.VisualStudio.2022.BuildTools --exact --accept-package-agreements --accept-source-agreements --uninstall-previous --force --source winget --override '--force --wait --passive --add Microsoft.VisualStudio.Workload.ManagedDesktop --add Microsoft.VisualStudio.Workload.VCTools --add Microsoft.VisualStudio.Workload.MSBuildTools --add Microsoft.VisualStudio.Workload.UniversalBuildTools --add Microsoft.VisualStudio.ComponentGroup.WindowsAppSDK.Cs --add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 --add Microsoft.VisualStudio.Component.VC.v141.x86.x64 --add Microsoft.VisualStudio.Component.Windows11SDK.26100 --includeRecommended --add Microsoft.VisualStudio.Component.VC.Tools.ARM64 --add Microsoft.VisualStudio.Component.UWP.VC.ARM64' if ($LASTEXITCODE -ne 0) { throw [System.InvalidOperationException]::New('Failed to install Visual Studio Build Tools') } From b55e956ea97bc1d12ecf0f794e3e804d6996959d Mon Sep 17 00:00:00 2001 From: Violet Hansen Date: Thu, 20 Feb 2025 21:03:45 +0200 Subject: [PATCH 2/2] Improved Native AOT and Trim compatibility Made multiple UI elements NAOT friendly Removed lots of empty lines Improved error info written to the log file when an error occurs Fixed columns in ListViews --- AppControl Manager/App.xaml | 3 - AppControl Manager/App.xaml.cs | 7 +- AppControl Manager/AppControl Manager.csproj | 16 +-- .../SigningDetailsDialog.xaml | 2 - .../SigningDetailsDialogForRemoval.xaml | 6 - .../SigningDetailsDialogForRemoval.xaml.cs | 2 - .../IntelGathering/GetEventLogsData.cs | 4 - .../GetMDEAdvancedHuntingLogsData.cs | 3 - .../InferCertificatePresence.cs | 1 - .../IntelGathering/KernelModeDrivers.cs | 1 - .../IntelGathering/LocalFilesScan.cs | 3 - .../Main/AppControlSimulation.cs | 1 - AppControl Manager/Main/BasePolicyCreator.cs | 5 - AppControl Manager/Main/UserConfiguration.cs | 6 - AppControl Manager/MainWindow.xaml.cs | 47 +++----- .../Others/CertificateCreator.cs | 9 -- AppControl Manager/Others/CiToolHelper.cs | 3 - AppControl Manager/Others/ErrorWriter.cs | 44 ++++++++ AppControl Manager/Others/FileDialogHelper.cs | 3 - AppControl Manager/Others/MicrosoftGraph.cs | 4 - AppControl Manager/Others/SignToolHelper.cs | 2 - .../Others/SnapBackGuarantee.cs | 2 +- AppControl Manager/Others/WinTrust.cs | 3 - .../Pages/AllowNewApps/AllowNewApps.xaml | 4 +- .../Pages/AllowNewApps/AllowNewApps.xaml.cs | 4 - .../AllowNewAppsEventLogsDataGrid.xaml | 64 +++++------ .../AllowNewAppsEventLogsDataGrid.xaml.cs | 28 +++-- .../AllowNewAppsLocalFilesDataGrid.xaml | 3 +- .../AllowNewAppsLocalFilesDataGrid.xaml.cs | 104 ++++++++---------- .../Pages/AllowNewApps/AllowNewAppsStart.xaml | 8 +- .../AllowNewApps/AllowNewAppsStart.xaml.cs | 37 +++---- .../Pages/BuildNewCertificate.xaml | 7 +- .../Pages/BuildNewCertificate.xaml.cs | 11 +- .../Pages/ConfigurePolicyRuleOptions.xaml | 10 +- .../Pages/ConfigurePolicyRuleOptions.xaml.cs | 19 +--- .../Pages/CreateDenyPolicy.xaml | 15 +-- .../Pages/CreateDenyPolicy.xaml.cs | 54 ++++----- ...eDenyPolicyFilesAndFoldersScanResults.xaml | 8 +- ...nyPolicyFilesAndFoldersScanResults.xaml.cs | 18 +-- AppControl Manager/Pages/CreatePolicy.xaml.cs | 2 - .../Pages/CreateSupplementalPolicy.xaml | 13 +-- .../Pages/CreateSupplementalPolicy.xaml.cs | 60 +++------- ...entalPolicyFilesAndFoldersScanResults.xaml | 2 +- ...alPolicyFilesAndFoldersScanResults.xaml.cs | 21 +--- AppControl Manager/Pages/Deployment.xaml | 1 - AppControl Manager/Pages/Deployment.xaml.cs | 8 -- .../Pages/EventLogsPolicyCreation.xaml | 12 +- .../Pages/EventLogsPolicyCreation.xaml.cs | 21 ++-- .../Pages/MDEAHPolicyCreation.xaml | 6 +- .../Pages/MDEAHPolicyCreation.xaml.cs | 27 ++--- .../Pages/MergePolicies.xaml.cs | 1 - AppControl Manager/Pages/Settings.xaml | 24 ++-- AppControl Manager/Pages/Settings.xaml.cs | 72 +++++------- AppControl Manager/Pages/Simulation.xaml | 2 +- AppControl Manager/Pages/Simulation.xaml.cs | 6 +- .../Pages/StrictKernelPolicyScanResults.xaml | 2 +- .../StrictKernelPolicyScanResults.xaml.cs | 19 +--- .../SystemInformation/CodeIntegrityInfo.xaml | 6 +- .../CodeIntegrityInfo.xaml.cs | 10 +- .../SystemInformation/SystemInformation.xaml | 7 +- .../SystemInformation.xaml.cs | 3 - .../ViewCurrentPolicies.xaml | 12 +- .../ViewCurrentPolicies.xaml.cs | 12 +- AppControl Manager/Pages/Update.xaml | 11 +- .../Pages/ValidatePolicy.xaml.cs | 4 - .../Pages/ViewFileCertificates.xaml | 2 +- .../Pages/ViewFileCertificates.xaml.cs | 2 +- .../SiPolicy/Merger.Aggregate.cs | 4 - AppControl Manager/SiPolicy/Merger.cs | 1 - .../SiPolicy/SiPolicyClassAutoGenerated.cs | 1 - .../SiPolicyIntel/AddSigningDetails.cs | 1 - .../FilePublisherSignerRuleComparer.cs | 1 - .../WHQLFilePublisherSignerRuleComparer.cs | 1 - .../Strings/en-US/Resources.resw | 9 -- AppControl Manager/XMLOps/NewFilePathRules.cs | 1 - .../XMLOps/NewHashLevelRules.cs | 1 - AppControl Manager/XMLOps/NewPFNLevelRules.cs | 1 - .../XMLOps/NewPublisherLevelRules.cs | 1 - AppControl Manager/XMLOps/SetCiPolicyInfo.cs | 1 - 79 files changed, 343 insertions(+), 619 deletions(-) create mode 100644 AppControl Manager/Others/ErrorWriter.cs diff --git a/AppControl Manager/App.xaml b/AppControl Manager/App.xaml index 72ad35c6d..a2cf86df1 100644 --- a/AppControl Manager/App.xaml +++ b/AppControl Manager/App.xaml @@ -51,7 +51,6 @@ - - - diff --git a/AppControl Manager/App.xaml.cs b/AppControl Manager/App.xaml.cs index 0b41e36d2..9f2a39423 100644 --- a/AppControl Manager/App.xaml.cs +++ b/AppControl Manager/App.xaml.cs @@ -79,7 +79,6 @@ public App() } - /// /// Event handler for when the sound setting is changed. /// @@ -101,7 +100,6 @@ private void OnSoundSettingChanged(object? sender, SoundSettingChangedEventArgs } - /// /// Invoked when the application is launched. /// @@ -135,15 +133,12 @@ protected override void OnLaunched(LaunchActivatedEventArgs args) /// private async void App_UnhandledException(object sender, Microsoft.UI.Xaml.UnhandledExceptionEventArgs e) { - Logger.Write($"Unhandled exception: {e.Exception.Message}"); + Logger.Write(ErrorWriter.FormatException(e.Exception)); // Prevent the app from crashing // With this set to false, the same error would keep writing to the log file forever. The exception keeps bubbling up since it's unhandled. e.Handled = true; - // Log the error to a file - Logger.Write(e.Exception.ToString()); - // Show error dialog to the user await ShowErrorDialogAsync(e.Exception); } diff --git a/AppControl Manager/AppControl Manager.csproj b/AppControl Manager/AppControl Manager.csproj index 2391e69fc..4f1d7acd1 100644 --- a/AppControl Manager/AppControl Manager.csproj +++ b/AppControl Manager/AppControl Manager.csproj @@ -1,5 +1,4 @@  - WinExe net9.0-windows10.0.26100.0 @@ -25,7 +24,6 @@ true enable - en-US @@ -48,8 +46,7 @@ true - False - True + True disable A modern secure application that simplifies management of Application Control in Windows. @@ -102,11 +99,12 @@ True full false + true false - false - false - false + true false + false + false - @@ -133,9 +130,8 @@ diff --git a/AppControl Manager/CustomUIElements/SigningDetailsDialog.xaml b/AppControl Manager/CustomUIElements/SigningDetailsDialog.xaml index 436a536e4..739aeab91 100644 --- a/AppControl Manager/CustomUIElements/SigningDetailsDialog.xaml +++ b/AppControl Manager/CustomUIElements/SigningDetailsDialog.xaml @@ -93,7 +93,6 @@ - @@ -144,5 +143,4 @@ - diff --git a/AppControl Manager/CustomUIElements/SigningDetailsDialogForRemoval.xaml b/AppControl Manager/CustomUIElements/SigningDetailsDialogForRemoval.xaml index 0c1830ec8..ceabfdb36 100644 --- a/AppControl Manager/CustomUIElements/SigningDetailsDialogForRemoval.xaml +++ b/AppControl Manager/CustomUIElements/SigningDetailsDialogForRemoval.xaml @@ -93,7 +93,6 @@ - @@ -110,11 +109,9 @@ - - @@ -131,7 +128,6 @@ - @@ -161,6 +157,4 @@ - - diff --git a/AppControl Manager/CustomUIElements/SigningDetailsDialogForRemoval.xaml.cs b/AppControl Manager/CustomUIElements/SigningDetailsDialogForRemoval.xaml.cs index a596462f7..60f46762a 100644 --- a/AppControl Manager/CustomUIElements/SigningDetailsDialogForRemoval.xaml.cs +++ b/AppControl Manager/CustomUIElements/SigningDetailsDialogForRemoval.xaml.cs @@ -498,6 +498,4 @@ private void XMLPolicyFileBrowseButton_Click(object sender, RoutedEventArgs e) } } - - } diff --git a/AppControl Manager/IntelGathering/GetEventLogsData.cs b/AppControl Manager/IntelGathering/GetEventLogsData.cs index 52e904c6c..3f28d2555 100644 --- a/AppControl Manager/IntelGathering/GetEventLogsData.cs +++ b/AppControl Manager/IntelGathering/GetEventLogsData.cs @@ -491,7 +491,6 @@ private static HashSet CodeIntegrityEventsRetriever(string? EvtxFi } - /// /// Retrieves the AppLocker events from the local and EVTX files /// @@ -897,7 +896,6 @@ private static HashSet AppLockerEventsRetriever(string? EvtxFilePa } - #region Helper methods to extract values /// @@ -928,7 +926,6 @@ private static HashSet AppLockerEventsRetriever(string? EvtxFilePa } - /// /// Only works for the node of the Event /// @@ -1049,7 +1046,6 @@ private static string ResolvePath(string path) #endregion - #region Async processing /// diff --git a/AppControl Manager/IntelGathering/GetMDEAdvancedHuntingLogsData.cs b/AppControl Manager/IntelGathering/GetMDEAdvancedHuntingLogsData.cs index e1bbaa2de..b33aa8d22 100644 --- a/AppControl Manager/IntelGathering/GetMDEAdvancedHuntingLogsData.cs +++ b/AppControl Manager/IntelGathering/GetMDEAdvancedHuntingLogsData.cs @@ -160,11 +160,9 @@ internal static HashSet Retrieve(List data // Add the entire event package to the output list _ = fileIdentities.Add(eventData); - } - // If the current group has Code Integrity Blocked log else if (possibleCodeIntegrityBlockEvent is not null) { @@ -488,7 +486,6 @@ internal static HashSet Retrieve(List data } - #region Helper methods to extract values /// diff --git a/AppControl Manager/IntelGathering/InferCertificatePresence.cs b/AppControl Manager/IntelGathering/InferCertificatePresence.cs index a058f66e3..e04fcf80e 100644 --- a/AppControl Manager/IntelGathering/InferCertificatePresence.cs +++ b/AppControl Manager/IntelGathering/InferCertificatePresence.cs @@ -79,7 +79,6 @@ internal static bool InferCertificatePresence(SiPolicy.SiPolicy policyObject, st } - /// /// Gets the path to a .cer certificate file and a certificate common name /// Makes sure the common name belongs to the certificate file diff --git a/AppControl Manager/IntelGathering/KernelModeDrivers.cs b/AppControl Manager/IntelGathering/KernelModeDrivers.cs index 377622987..5700307b5 100644 --- a/AppControl Manager/IntelGathering/KernelModeDrivers.cs +++ b/AppControl Manager/IntelGathering/KernelModeDrivers.cs @@ -50,7 +50,6 @@ private static IntPtr OpenFile(string path, out int error) } - internal static KernelUserVerdict CheckKernelUserModeStatus(string filePath) { diff --git a/AppControl Manager/IntelGathering/LocalFilesScan.cs b/AppControl Manager/IntelGathering/LocalFilesScan.cs index 0618e49b8..d4f0bf19a 100644 --- a/AppControl Manager/IntelGathering/LocalFilesScan.cs +++ b/AppControl Manager/IntelGathering/LocalFilesScan.cs @@ -49,7 +49,6 @@ internal static HashSet Scan(List files, ushort scalabil } - // Store the output of all of the parallel tasks in this ConcurrentDictionary temporaryOutput = []; @@ -103,7 +102,6 @@ internal static HashSet Scan(List files, ushort scalabil } - // To track whether ECC Signed signature has been detected or not // Once it's been set to true, it won't be changed to false anymore for the current file bool IsECCSigned = false; @@ -247,7 +245,6 @@ internal static HashSet Scan(List files, ushort scalabil } - // If the Leaf Certificate exists in the current package // Indicating that the current signer of the file is a normal certificate with Leaf/Intermediate(s)/Root if (package.LeafCertificate is not null) diff --git a/AppControl Manager/Main/AppControlSimulation.cs b/AppControl Manager/Main/AppControlSimulation.cs index 6de340df8..e416fdf55 100644 --- a/AppControl Manager/Main/AppControlSimulation.cs +++ b/AppControl Manager/Main/AppControlSimulation.cs @@ -40,7 +40,6 @@ internal static bool Invoke(List? filePaths, string xmlFilePath, bool no } - internal static void ExportToCsv(ConcurrentDictionary finalResults, string filePath) { // Create a list for CSV lines diff --git a/AppControl Manager/Main/BasePolicyCreator.cs b/AppControl Manager/Main/BasePolicyCreator.cs index 6fa3b8ff4..d166f94bc 100644 --- a/AppControl Manager/Main/BasePolicyCreator.cs +++ b/AppControl Manager/Main/BasePolicyCreator.cs @@ -378,7 +378,6 @@ internal static void GetDriversBlockRules(string StagingArea) } - /// /// Creates a base policy based on the AllowMicrosoft template /// @@ -465,7 +464,6 @@ internal static void BuildAllowMSFT(string StagingArea, bool IsAudit, ulong? Log } - /// /// Creates a base policy based on the DefaultWindows template /// @@ -553,7 +551,6 @@ internal static void BuildDefaultWindows(string StagingArea, bool IsAudit, ulong } - /// /// Gets the latest Microsoft Recommended block rules for User Mode files, removes the audit mode policy rule option and sets HVCI to strict /// It generates a XML file compliant with CI Policies Schema. @@ -641,7 +638,6 @@ internal static void GetBlockRules(string StagingArea, bool deploy) // Deploy the CIP file CiToolHelper.UpdatePolicy(tempPolicyCIPPath); - } File.Copy(tempPolicyPath, finalPolicyPath, true); @@ -649,7 +645,6 @@ internal static void GetBlockRules(string StagingArea, bool deploy) } - /// /// Creates SignedAndReputable App Control policy which is based on AllowMicrosoft template policy. /// It uses ISG to authorize files with good reputation. diff --git a/AppControl Manager/Main/UserConfiguration.cs b/AppControl Manager/Main/UserConfiguration.cs index b375a1cdd..b709a43bb 100644 --- a/AppControl Manager/Main/UserConfiguration.cs +++ b/AppControl Manager/Main/UserConfiguration.cs @@ -20,7 +20,6 @@ public partial class UserConfigurationContext : JsonSerializerContext } - // Represents an instance of the User configurations JSON settings file // Maintains the order of the properties when writing to the JSON file // Includes the methods for interacting with user configurations JSON file @@ -64,7 +63,6 @@ public sealed partial class UserConfiguration( public Dictionary? SignedPolicyStage1RemovalTimes { get; set; } = signedPolicyStage1RemovalTimes; - /// /// Sets user configuration settings to the JSON file /// By default all params are null, so use named parameters when calling this method for easy invocation @@ -130,7 +128,6 @@ internal static UserConfiguration Set( if (!string.IsNullOrWhiteSpace(SignedPolicyPath)) UserConfiguration.SignedPolicyPath = SignedPolicyPath; - if (!string.IsNullOrWhiteSpace(UnsignedPolicyPath)) { UserConfiguration.UnsignedPolicyPath = UnsignedPolicyPath; @@ -353,7 +350,6 @@ private static void WriteUserConfiguration(UserConfiguration userConfiguration) } - /// /// Adds a new key-value pair to the SignedPolicyStage1RemovalTimes dictionary. /// @@ -377,7 +373,6 @@ internal static void AddSignedPolicyStage1RemovalTime(string key, DateTime value } - /// /// Queries the SignedPolicyStage1RemovalTimes dictionary by key and returns the corresponding value. /// @@ -399,7 +394,6 @@ internal static void AddSignedPolicyStage1RemovalTime(string key, DateTime value } - /// /// Removes a key-value pair from the SignedPolicyStage1RemovalTimes dictionary by key. /// diff --git a/AppControl Manager/MainWindow.xaml.cs b/AppControl Manager/MainWindow.xaml.cs index e8cbdd1e2..cf74986c3 100644 --- a/AppControl Manager/MainWindow.xaml.cs +++ b/AppControl Manager/MainWindow.xaml.cs @@ -20,6 +20,7 @@ using Microsoft.UI.Xaml.Media.Animation; using Windows.ApplicationModel; using Windows.Graphics; +using WinRT; using Rect = Windows.Foundation.Rect; namespace AppControlManager; @@ -207,7 +208,6 @@ private void BreadcrumbBar_ItemClicked(BreadcrumbBar sender, BreadcrumbBarItemCl } - // Dictionary of all the main pages in the app, used by the search bar // Sub-pages should only be added if they don't rely on/access the the instance of any page that might not be initialized private static readonly Dictionary NavigationPageToItemContentMap = new() @@ -236,7 +236,6 @@ private void BreadcrumbBar_ItemClicked(BreadcrumbBar sender, BreadcrumbBarItemCl }; - // A static instance of the MainWindow class which will hold the single, shared instance of it private static MainWindow? _instance; @@ -369,7 +368,6 @@ static IEnumerable GetAllChildren(NavigationViewItem parent) this.Closed += MainWindow_Closed; - // Subscribing to the event that is fired when User Configuration changes for Unsigned policy path to that the Sidebar can be updated accordingly Events.UnsignedPolicyManager.UnsignedPolicyInUserConfigChanged += SidebarOnUnsignedPolicyChanged; } @@ -464,7 +462,6 @@ private static RectInt32 GetRect(Rect bounds, double scale) } - /* This will make keep the title bar text white even on light theme, making it unreadable @@ -501,11 +498,8 @@ private void MainWindow_Activated(object sender, WindowActivatedEventArgs args) /// private void MainWindow_Closed(object sender, WindowEventArgs args) { - // Get the AppWindow from the current Window - AppWindow appWindow = GetAppWindowForCurrentWindow(); - // Get the current size of the window - SizeInt32 size = appWindow.Size; + SizeInt32 size = m_AppWindow.Size; // Save to window width and height to the app settings AppSettingsCls.SaveSetting(AppSettingsCls.SettingKeys.MainWindowWidth, size.Width); @@ -531,16 +525,20 @@ private void MainWindow_Closed(object sender, WindowEventArgs args) /// /// Event handler to run at Window launch to restore its size to the one before closing /// - private static void RestoreWindowSize() + private void RestoreWindowSize() { - AppWindow appWindow = GetAppWindowForCurrentWindow(); - // If the window was last maximized then restore it to maximized if (AppSettingsCls.GetSetting(AppSettingsCls.SettingKeys.MainWindowIsMaximized)) { + + Logger.Write("Window was maximized when the app closed last time, setting it to maximized now"); + + // Using .As<>() instead of direct cast because in NAOT mode direct cast would throw error for invalid cast operation. This is a bug in CsWinRT + OverlappedPresenter presenter = m_AppWindow.Presenter.As(); + // Set the presenter to maximized - ((OverlappedPresenter)appWindow.Presenter).Maximize(); + presenter.Maximize(); } // Else set its size to its previous size before closing @@ -550,23 +548,25 @@ private static void RestoreWindowSize() int width = AppSettingsCls.GetSetting(AppSettingsCls.SettingKeys.MainWindowWidth); int height = AppSettingsCls.GetSetting(AppSettingsCls.SettingKeys.MainWindowHeight); + Logger.Write($"Setting the window size back to what it was when the app was closed. Height: {height} - Width: {width}"); + // If the previous window size was smaller than 200 pixels width/height then do not use it, let it use the natural window size if (width > 200 && height > 200) { // Apply to the current AppWindow - appWindow?.Resize(new SizeInt32(width, height)); + m_AppWindow?.Resize(new SizeInt32(width, height)); } } } - + /* + //This is already retrieved by m_AppWindow in the class, keeping it just in case private static AppWindow GetAppWindowForCurrentWindow() { WindowId windowId = Win32Interop.GetWindowIdFromWindow(GlobalVars.hWnd); return AppWindow.GetFromWindowId(windowId); } - - + */ /// /// Event handler for the global Icons Style change event @@ -579,7 +579,6 @@ private void OnIconsStylesChanged(object? sender, IconsStyleChangedEventArgs e) // Get the current theme ElementTheme currentTheme = RootGrid.ActualTheme; - // Set the Icons Style switch (e.NewIconsStyle) { @@ -1029,7 +1028,6 @@ private void OnIconsStylesChanged(object? sender, IconsStyleChangedEventArgs e) } - /// /// Event handler for the global NavigationView location change event /// @@ -1076,11 +1074,9 @@ private void OnNavigationViewLocationChanged(object? sender, NavigationViewLocat break; } } - } - /// /// Note: Keeping it transparent would probably not be good for accessibility. /// Changing it during runtime is not possible without trigger a theme change: Light/Dark. @@ -1114,7 +1110,6 @@ private void OnNavigationBackgroundChanged(object? sender, NavigationBackgroundC } - /// /// Event handler for the global BackgroundChanged event. When user selects a different background for the app, this will be triggered. /// @@ -1142,7 +1137,6 @@ private void OnBackgroundChanged(object? sender, BackgroundChangedEventArgs e) } - /// /// Event handler for the global AppThemeChanged event /// Also changes the AnimatedIcons based on the theme to maintain their accessibility @@ -1321,7 +1315,6 @@ private void SearchBox_SuggestionChosen(AutoSuggestBox sender, AutoSuggestBoxSug } - /// /// Main navigation event of the Nav View /// ItemInvoked event is much better than SelectionChanged because it allows click/tap on the same selected menu on main navigation @@ -1432,11 +1425,9 @@ internal void NavView_Navigate(Type? navPageType, NavigationTransitionInfo? tran MainNavigation.SelectedItem = allNavigationItems.First(x => string.Equals(x.Content.ToString(), info.Titles[0], StringComparison.OrdinalIgnoreCase)); } } - } - /// /// Event handler for the main Sidebar button click /// @@ -1563,7 +1554,6 @@ private void SidebarBasePolicyBrowseButton_Click(object sender, RoutedEventArgs } - /// /// Event handler to change visibility of the AnimatedIcons on the currently visible page in the frame /// It is called by the Sidebar's Browse/Clear buttons' event handlers @@ -1586,7 +1576,6 @@ private void AffectPagesAnimatedIconsVisibilities(bool on) } - /// /// This method is called via the methods responsible for Navigations. /// @@ -1649,7 +1638,6 @@ internal void AffectPagesAnimatedIconsVisibilities(Frame contentFrame) } - /// /// Event handler for the clear button in the sidebar for unsigned policy path /// @@ -1665,7 +1653,6 @@ private void SidebarBasePolicyClearButton_Click(object sender, RoutedEventArgs e } - /// /// Event handler for when the RootGrid of the window is loaded /// @@ -1684,7 +1671,6 @@ private void RootGrid_Loaded(object sender, RoutedEventArgs e) } - /// /// Event handler for when the event that changes unsigned policy path in user configurations is fired /// @@ -1713,7 +1699,6 @@ internal void AssignToSidebar(string unsignedPolicyPath) } - /// /// Event handler for sidebar settings cards for auto assignment /// diff --git a/AppControl Manager/Others/CertificateCreator.cs b/AppControl Manager/Others/CertificateCreator.cs index b648b76c6..539f1ad5b 100644 --- a/AppControl Manager/Others/CertificateCreator.cs +++ b/AppControl Manager/Others/CertificateCreator.cs @@ -60,12 +60,10 @@ internal static X509Certificate2 BuildAppControlCertificate(string CommonName, s CertificateCommonName: CommonName ); - return generatedCertificate; } - // Enum representing the applicable certificate stores internal enum CertificateStoreLocation { @@ -103,7 +101,6 @@ internal static X509Certificate2 GenerateSelfSignedCertificate( true)); - // Add subject key identifier // Its raw data which is a byte array will always start with 4, 20 // 4: This indicates the ASN.1 type is an OCTET STRING. @@ -115,7 +112,6 @@ internal static X509Certificate2 GenerateSelfSignedCertificate( new X509SubjectKeyIdentifierExtension(request.PublicKey, false)); - // Add enhanced key usage // Code Signing request.CertificateExtensions.Add( @@ -193,7 +189,6 @@ [new Oid("1.3.6.1.5.5.7.3.3")], } - /// /// Stores the certificate in one of the pre-defined certificate stores /// @@ -216,7 +211,6 @@ internal static void StoreCertificateInStore(X509Certificate2 cert, CertificateS cert = X509CertificateLoader.LoadCertificate(publicKeyData); } - using X509Store store = new(storeName, location); store.Open(OpenFlags.ReadWrite); store.Add(cert); @@ -224,7 +218,6 @@ internal static void StoreCertificateInStore(X509Certificate2 cert, CertificateS } - /// /// Searches through all the relevant certificate stores for any certificate with a given Subject Common Name /// And deletes all of the detected instances @@ -304,6 +297,4 @@ internal static List GetCertificatesFromPersonalStore(string s return matchingCertificates; } - - } diff --git a/AppControl Manager/Others/CiToolHelper.cs b/AppControl Manager/Others/CiToolHelper.cs index df77dc811..b08631301 100644 --- a/AppControl Manager/Others/CiToolHelper.cs +++ b/AppControl Manager/Others/CiToolHelper.cs @@ -208,7 +208,6 @@ internal static void RemovePolicy(string policyId) } - /// /// Removes multiple deployed App Control policy from the system /// @@ -260,7 +259,6 @@ internal static void RemovePolicy(List policyIds) } - /// /// Deploys a Code Integrity policy on the system by accepting the .CIP file path /// @@ -348,7 +346,6 @@ internal static void RefreshPolicy() } - // Extension methods for JsonElement to simplify retrieving properties with default values internal static class JsonElementExtensions { diff --git a/AppControl Manager/Others/ErrorWriter.cs b/AppControl Manager/Others/ErrorWriter.cs new file mode 100644 index 000000000..e1af2b283 --- /dev/null +++ b/AppControl Manager/Others/ErrorWriter.cs @@ -0,0 +1,44 @@ +using System; +using System.Text; + +namespace AppControlManager.Others; + +internal static class ErrorWriter +{ + /// + /// When an exception is raised by the app, writes the full details to the log file for review + /// + /// + /// + internal static string FormatException(Exception ex) + { + StringBuilder sb = new(); + + _ = sb.AppendLine("==== Unhandled Exception ===="); + _ = sb.AppendLine($"Message: {ex.Message}"); + _ = sb.AppendLine($"Type: {ex.GetType().FullName}"); + _ = sb.AppendLine($"Source: {ex.Source}"); + _ = sb.AppendLine("Stack Trace:"); + _ = sb.AppendLine(ex.StackTrace); + + // Log inner exceptions (if any) + Exception? inner = ex.InnerException; + int depth = 1; + while (inner is not null) + { + _ = sb.AppendLine(); + _ = sb.AppendLine($"-- Inner Exception {depth} --"); + _ = sb.AppendLine($"Message: {inner.Message}"); + _ = sb.AppendLine($"Type: {inner.GetType().FullName}"); + _ = sb.AppendLine($"Source: {inner.Source}"); + _ = sb.AppendLine("Stack Trace:"); + _ = sb.AppendLine(inner.StackTrace); + + inner = inner.InnerException; + depth++; + } + + _ = sb.AppendLine("=============================="); + return sb.ToString(); + } +} diff --git a/AppControl Manager/Others/FileDialogHelper.cs b/AppControl Manager/Others/FileDialogHelper.cs index 624845046..87eef7afc 100644 --- a/AppControl Manager/Others/FileDialogHelper.cs +++ b/AppControl Manager/Others/FileDialogHelper.cs @@ -156,7 +156,6 @@ out void* pDirectoryShellItem } - /// /// Opens a file picker dialog to select multiple files. /// @@ -305,7 +304,6 @@ out void* directoryShellItem } - /// /// Opens a folder picker dialog to select a single folder. /// @@ -401,7 +399,6 @@ out void* directoryShellItem } - /// /// Opens a folder picker dialog to select multiple folders. /// diff --git a/AppControl Manager/Others/MicrosoftGraph.cs b/AppControl Manager/Others/MicrosoftGraph.cs index f6853c799..d3d9b9274 100644 --- a/AppControl Manager/Others/MicrosoftGraph.cs +++ b/AppControl Manager/Others/MicrosoftGraph.cs @@ -306,7 +306,6 @@ internal static async Task SignOut(AuthenticationContext context) } - /// /// Grabs the path to a CIP file and upload it to Intune. /// @@ -349,7 +348,6 @@ internal static async Task UploadPolicyToIntune(string policyPath, string? group } - /// /// Assigns a group to the created Intune policy /// @@ -403,7 +401,6 @@ private static async Task AssignIntunePolicyToGroup(string policyId, string acce } - /// /// https://learn.microsoft.com/en-us/mem/intune/configuration/custom-settings-windows-10 /// @@ -480,7 +477,6 @@ private static async Task AssignIntunePolicyToGroup(string policyId, string acce } - /* private static async Task GetPoliciesAndAssignments(string accessToken) { diff --git a/AppControl Manager/Others/SignToolHelper.cs b/AppControl Manager/Others/SignToolHelper.cs index 16bcba28a..83eb7331a 100644 --- a/AppControl Manager/Others/SignToolHelper.cs +++ b/AppControl Manager/Others/SignToolHelper.cs @@ -164,7 +164,6 @@ private static bool Verify(string filePath) } - /// /// Returns the architecture of the current OS /// @@ -187,7 +186,6 @@ private static string GetArchitecture() } - /// /// Gets the path to SignTool.exe and verifies it to make sure it's valid /// If the SignTool.exe path is not provided by parameter, it will try to detect it automatically by checking if Windows SDK is installed diff --git a/AppControl Manager/Others/SnapBackGuarantee.cs b/AppControl Manager/Others/SnapBackGuarantee.cs index d82984bc7..644c28864 100644 --- a/AppControl Manager/Others/SnapBackGuarantee.cs +++ b/AppControl Manager/Others/SnapBackGuarantee.cs @@ -188,7 +188,7 @@ REM Deleting this CMD file itself /// internal static void Remove() { - string script = "schtasks.exe /Delete /TN EnforcedModeSnapBack /F"; + string script = "Get-ScheduledTask | Where-Object { $_.TaskName -eq 'EnforcedModeSnapBack' } | ForEach-Object { Unregister-ScheduledTask -TaskName $_.TaskName -Confirm:$false }"; ProcessStarter.RunCommand("powershell.exe", $"-NoProfile -ExecutionPolicy Bypass -Command \"{script}\""); diff --git a/AppControl Manager/Others/WinTrust.cs b/AppControl Manager/Others/WinTrust.cs index 3df11a4d8..63ca9022a 100644 --- a/AppControl Manager/Others/WinTrust.cs +++ b/AppControl Manager/Others/WinTrust.cs @@ -48,7 +48,6 @@ internal static partial bool CryptCATAdminCalcHashFromFileHandle3( #endregion - #region This section is related to the MeowParser class operations // P/Invoke declaration to import the 'CryptCATOpen' function from WinTrust.dll @@ -79,7 +78,6 @@ internal static partial IntPtr CryptCATEnumerateMember( #endregion - #region This section is related to the PageHashCalculator class // a method to compute the hash of the first page of a file using a native function from Wintrust.dll @@ -95,7 +93,6 @@ internal static partial int ComputeFirstPageHash( // the method signature #endregion - #region This section is related to the AllCertificatesGrabber class and its operations // Enum defining WinVerifyTrust results diff --git a/AppControl Manager/Pages/AllowNewApps/AllowNewApps.xaml b/AppControl Manager/Pages/AllowNewApps/AllowNewApps.xaml index 2f749e642..947c7b210 100644 --- a/AppControl Manager/Pages/AllowNewApps/AllowNewApps.xaml +++ b/AppControl Manager/Pages/AllowNewApps/AllowNewApps.xaml @@ -38,8 +38,8 @@ + Value="0" Opacity="0" + Style="{ThemeResource AttentionIconInfoBadgeStyle}"> diff --git a/AppControl Manager/Pages/AllowNewApps/AllowNewApps.xaml.cs b/AppControl Manager/Pages/AllowNewApps/AllowNewApps.xaml.cs index 6d0fc58ac..9956b2ea9 100644 --- a/AppControl Manager/Pages/AllowNewApps/AllowNewApps.xaml.cs +++ b/AppControl Manager/Pages/AllowNewApps/AllowNewApps.xaml.cs @@ -33,7 +33,6 @@ public AllowNewApps() } - #region Augmentation Interface @@ -100,7 +99,6 @@ private void LightUp1(object sender, RoutedEventArgs e) #endregion - // Public property to access the singleton instance from other classes public static AllowNewApps Instance => _instance ?? throw new InvalidOperationException("AllowNewApps is not initialized."); @@ -167,7 +165,6 @@ internal void EnableAllowNewAppsNavigationItem(string tag) } - /// /// Updates the value and opacity of the LocalFiles InfoBadge. /// @@ -190,5 +187,4 @@ public void UpdateEventLogsInfoBadge(int? value, double opacity) EventLogsCountInfoBadge.Opacity = opacity; } - } diff --git a/AppControl Manager/Pages/AllowNewApps/AllowNewAppsEventLogsDataGrid.xaml b/AppControl Manager/Pages/AllowNewApps/AllowNewAppsEventLogsDataGrid.xaml index a85144a5f..1e9c15555 100644 --- a/AppControl Manager/Pages/AllowNewApps/AllowNewAppsEventLogsDataGrid.xaml +++ b/AppControl Manager/Pages/AllowNewApps/AllowNewAppsEventLogsDataGrid.xaml @@ -10,7 +10,7 @@ xmlns:controls="using:CommunityToolkit.WinUI.Controls" xmlns:intelgathering="using:AppControlManager.IntelGathering" xmlns:interactivity="using:Microsoft.Xaml.Interactivity" - xmlns:behaviors="using:CommunityToolkit.WinUI.Behaviors" + xmlns:behaviors="using:CommunityToolkit.WinUI.Behaviors" x:Name="AllowNewAppsEventLogsDataGridXAML"> @@ -69,7 +69,9 @@ + + @@ -84,9 +86,9 @@ - - + + @@ -103,13 +105,13 @@ + Grid.Row="1" + SelectionMode="Extended" + ScrollViewer.HorizontalScrollMode="Enabled" + ScrollViewer.IsHorizontalRailEnabled="True" + ScrollViewer.HorizontalScrollBarVisibility="Visible" + ShowsScrollingPlaceholders="True" + ScrollViewer.VerticalScrollBarVisibility="Visible"> @@ -307,27 +309,27 @@ because in here the Data Context is set to FileIdentity so we cannot use x.Bind since a single FileIdentity item can't have the ColumnWidth properties of all of the columns And static properties wouldn't work since more than 1 ListViews might be assigning values to the static values at the same time --> - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + diff --git a/AppControl Manager/Pages/AllowNewApps/AllowNewAppsEventLogsDataGrid.xaml.cs b/AppControl Manager/Pages/AllowNewApps/AllowNewAppsEventLogsDataGrid.xaml.cs index 2be0f04cc..7b1692271 100644 --- a/AppControl Manager/Pages/AllowNewApps/AllowNewAppsEventLogsDataGrid.xaml.cs +++ b/AppControl Manager/Pages/AllowNewApps/AllowNewAppsEventLogsDataGrid.xaml.cs @@ -210,7 +210,7 @@ internal void CalculateColumnWidths() double maxWidth21 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("PolicyNameHeader/Text")); // Iterate over all items to determine the widest string for each column. - foreach (FileIdentity item in AllowNewAppsStart.Instance.LocalFilesFileIdentities) + foreach (FileIdentity item in AllowNewAppsStart.Instance.EventLogsFileIdentities) { double w1 = ListViewUIHelpers.MeasureTextWidth(item.FileName); if (w1 > maxWidth1) maxWidth1 = w1; @@ -381,10 +381,18 @@ private void ColumnSortingButton_FileName_Click(object sender, RoutedEventArgs e { SortColumn(fileIden => fileIden.FileName); } + private void ColumnSortingButton_TimeCreated_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.TimeCreated); + } private void ColumnSortingButton_SignatureStatus_Click(object sender, RoutedEventArgs e) { SortColumn(fileIden => fileIden.SignatureStatus); } + private void ColumnSortingButton_Action_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.Action); + } private void ColumnSortingButton_OriginalFileName_Click(object sender, RoutedEventArgs e) { SortColumn(fileIden => fileIden.OriginalFileName); @@ -441,15 +449,18 @@ private void ColumnSortingButton_FilePublishers_Click(object sender, RoutedEvent { SortColumn(fileIden => fileIden.FilePublishersToDisplay); } - private void ColumnSortingButton_IsECCSigned_Click(object sender, RoutedEventArgs e) - { - SortColumn(fileIden => fileIden.IsECCSigned); - } private void ColumnSortingButton_OpusData_Click(object sender, RoutedEventArgs e) { SortColumn(fileIden => fileIden.Opus); } - + private void ColumnSortingButton_PolicyGUID_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.PolicyGUID); + } + private void ColumnSortingButton_PolicyName_Click(object sender, RoutedEventArgs e) + { + SortColumn(fileIden => fileIden.PolicyName); + } /// /// Performs data sorting @@ -461,7 +472,7 @@ private void SortColumn(Func keySelector) // Determine if a search filter is active. bool isSearchEmpty = string.IsNullOrWhiteSpace(SearchBox.Text); // Use either the full list (AllowNewAppsStart.Instance.EventLogsAllFileIdentities) or the current display list. - var collectionToSort = isSearchEmpty ? AllowNewAppsStart.Instance.EventLogsAllFileIdentities : [.. AllowNewAppsStart.Instance.EventLogsFileIdentities]; + List collectionToSort = isSearchEmpty ? AllowNewAppsStart.Instance.EventLogsAllFileIdentities : [.. AllowNewAppsStart.Instance.EventLogsFileIdentities]; if (SortingDirectionToggle.IsChecked) { @@ -529,13 +540,12 @@ public AllowNewAppsEventLogsDataGrid() // Public property to access the singleton instance from other classes // It's okay it's nullable, null check will happen before accessing it - public static AllowNewAppsEventLogsDataGrid Instance => _instance ?? throw new InvalidOperationException("AllowNewAppsEventLogsDataGrid is not initialized"); + public static AllowNewAppsEventLogsDataGrid? Instance => _instance; #region protected override void OnNavigatedTo(NavigationEventArgs e) { base.OnNavigatedTo(e); - FileIdentitiesListView.ItemsSource = AllowNewAppsStart.Instance.EventLogsFileIdentities; // Update the logs when user switches to this page UpdateTotalLogs(); diff --git a/AppControl Manager/Pages/AllowNewApps/AllowNewAppsLocalFilesDataGrid.xaml b/AppControl Manager/Pages/AllowNewApps/AllowNewAppsLocalFilesDataGrid.xaml index 810edf021..1c73f5c48 100644 --- a/AppControl Manager/Pages/AllowNewApps/AllowNewAppsLocalFilesDataGrid.xaml +++ b/AppControl Manager/Pages/AllowNewApps/AllowNewAppsLocalFilesDataGrid.xaml @@ -10,7 +10,7 @@ xmlns:controls="using:CommunityToolkit.WinUI.Controls" xmlns:intelgathering="using:AppControlManager.IntelGathering" xmlns:interactivity="using:Microsoft.Xaml.Interactivity" - xmlns:behaviors="using:CommunityToolkit.WinUI.Behaviors" + xmlns:behaviors="using:CommunityToolkit.WinUI.Behaviors" x:Name="AllowNewAppsLocalFilesDataGridXAML"> @@ -102,7 +102,6 @@ - _columnWidth19; - set { _columnWidth19 = value; OnPropertyChanged(nameof(ColumnWidth19)); } - } - /// /// Calculates the maximum required width for each column (including header text) /// and assigns the value (with a little extra padding) to the corresponding property. @@ -174,24 +167,23 @@ internal void CalculateColumnWidths() // Measure header text widths first. double maxWidth1 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("FileNameHeader/Text")); - double maxWidth2 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("TimeCreatedHeader/Text")); - double maxWidth3 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SignatureStatusHeader/Text")); - double maxWidth4 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("OriginalFileNameHeader/Text")); - double maxWidth5 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("InternalNameHeader/Text")); - double maxWidth6 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("FileDescriptionHeader/Text")); - double maxWidth7 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("ProductNameHeader/Text")); - double maxWidth8 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("FileVersionHeader/Text")); - double maxWidth9 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("PackageFamilyNameHeader/Text")); - double maxWidth10 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SHA256HashHeader/Text")); - double maxWidth11 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SHA1HashHeader/Text")); - double maxWidth12 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SigningScenarioHeader/Text")); - double maxWidth13 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("FilePathHeader/Text")); - double maxWidth14 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SHA1PageHashHeader/Text")); - double maxWidth15 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SHA256PageHashHeader/Text")); - double maxWidth16 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("HasWHQLSignerHeader/Text")); - double maxWidth17 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("FilePublishersHeader/Text")); - double maxWidth18 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("IsECCSignedHeader/Text")); - double maxWidth19 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("OpusDataHeader/Text")); + double maxWidth2 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SignatureStatusHeader/Text")); + double maxWidth3 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("OriginalFileNameHeader/Text")); + double maxWidth4 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("InternalNameHeader/Text")); + double maxWidth5 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("FileDescriptionHeader/Text")); + double maxWidth6 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("ProductNameHeader/Text")); + double maxWidth7 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("FileVersionHeader/Text")); + double maxWidth8 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("PackageFamilyNameHeader/Text")); + double maxWidth9 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SHA256HashHeader/Text")); + double maxWidth10 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SHA1HashHeader/Text")); + double maxWidth11 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SigningScenarioHeader/Text")); + double maxWidth12 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("FilePathHeader/Text")); + double maxWidth13 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SHA1PageHashHeader/Text")); + double maxWidth14 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("SHA256PageHashHeader/Text")); + double maxWidth15 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("HasWHQLSignerHeader/Text")); + double maxWidth16 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("FilePublishersHeader/Text")); + double maxWidth17 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("IsECCSignedHeader/Text")); + double maxWidth18 = ListViewUIHelpers.MeasureTextWidth(GlobalVars.Rizz.GetString("OpusDataHeader/Text")); // Iterate over all items to determine the widest string for each column. foreach (FileIdentity item in AllowNewAppsStart.Instance.LocalFilesFileIdentities) @@ -199,59 +191,56 @@ internal void CalculateColumnWidths() double w1 = ListViewUIHelpers.MeasureTextWidth(item.FileName); if (w1 > maxWidth1) maxWidth1 = w1; - double w2 = ListViewUIHelpers.MeasureTextWidth(item.TimeCreated.ToString()); + double w2 = ListViewUIHelpers.MeasureTextWidth(item.SignatureStatus.ToString()); if (w2 > maxWidth2) maxWidth2 = w2; - double w3 = ListViewUIHelpers.MeasureTextWidth(item.SignatureStatus.ToString()); + double w3 = ListViewUIHelpers.MeasureTextWidth(item.OriginalFileName); if (w3 > maxWidth3) maxWidth3 = w3; - double w4 = ListViewUIHelpers.MeasureTextWidth(item.OriginalFileName); + double w4 = ListViewUIHelpers.MeasureTextWidth(item.InternalName); if (w4 > maxWidth4) maxWidth4 = w4; - double w5 = ListViewUIHelpers.MeasureTextWidth(item.InternalName); + double w5 = ListViewUIHelpers.MeasureTextWidth(item.FileDescription); if (w5 > maxWidth5) maxWidth5 = w5; - double w6 = ListViewUIHelpers.MeasureTextWidth(item.FileDescription); + double w6 = ListViewUIHelpers.MeasureTextWidth(item.ProductName); if (w6 > maxWidth6) maxWidth6 = w6; - double w7 = ListViewUIHelpers.MeasureTextWidth(item.ProductName); + double w7 = ListViewUIHelpers.MeasureTextWidth(item.FileVersion?.ToString()); if (w7 > maxWidth7) maxWidth7 = w7; - double w8 = ListViewUIHelpers.MeasureTextWidth(item.FileVersion?.ToString()); + double w8 = ListViewUIHelpers.MeasureTextWidth(item.PackageFamilyName); if (w8 > maxWidth8) maxWidth8 = w8; - double w9 = ListViewUIHelpers.MeasureTextWidth(item.PackageFamilyName); + double w9 = ListViewUIHelpers.MeasureTextWidth(item.SHA256Hash); if (w9 > maxWidth9) maxWidth9 = w9; - double w10 = ListViewUIHelpers.MeasureTextWidth(item.SHA256Hash); + double w10 = ListViewUIHelpers.MeasureTextWidth(item.SHA1Hash); if (w10 > maxWidth10) maxWidth10 = w10; - double w11 = ListViewUIHelpers.MeasureTextWidth(item.SHA1Hash); + double w11 = ListViewUIHelpers.MeasureTextWidth(item.SISigningScenario.ToString()); if (w11 > maxWidth11) maxWidth11 = w11; - double w12 = ListViewUIHelpers.MeasureTextWidth(item.SISigningScenario.ToString()); + double w12 = ListViewUIHelpers.MeasureTextWidth(item.FilePath); if (w12 > maxWidth12) maxWidth12 = w12; - double w13 = ListViewUIHelpers.MeasureTextWidth(item.FilePath); + double w13 = ListViewUIHelpers.MeasureTextWidth(item.SHA1PageHash); if (w13 > maxWidth13) maxWidth13 = w13; - double w14 = ListViewUIHelpers.MeasureTextWidth(item.SHA1PageHash); + double w14 = ListViewUIHelpers.MeasureTextWidth(item.SHA256PageHash); if (w14 > maxWidth14) maxWidth14 = w14; - double w15 = ListViewUIHelpers.MeasureTextWidth(item.SHA256PageHash); + double w15 = ListViewUIHelpers.MeasureTextWidth(item.HasWHQLSigner.ToString()); if (w15 > maxWidth15) maxWidth15 = w15; - double w16 = ListViewUIHelpers.MeasureTextWidth(item.HasWHQLSigner.ToString()); + double w16 = ListViewUIHelpers.MeasureTextWidth(item.FilePublishersToDisplay); if (w16 > maxWidth16) maxWidth16 = w16; - double w17 = ListViewUIHelpers.MeasureTextWidth(item.FilePublishersToDisplay); + double w17 = ListViewUIHelpers.MeasureTextWidth(item.IsECCSigned.ToString()); if (w17 > maxWidth17) maxWidth17 = w17; - double w18 = ListViewUIHelpers.MeasureTextWidth(item.IsECCSigned.ToString()); + double w18 = ListViewUIHelpers.MeasureTextWidth(item.Opus); if (w18 > maxWidth18) maxWidth18 = w18; - - double w19 = ListViewUIHelpers.MeasureTextWidth(item.Opus); - if (w19 > maxWidth19) maxWidth19 = w19; } // Set the column width properties. @@ -273,11 +262,9 @@ internal void CalculateColumnWidths() ColumnWidth16 = new GridLength(maxWidth16); ColumnWidth17 = new GridLength(maxWidth17); ColumnWidth18 = new GridLength(maxWidth18); - ColumnWidth19 = new GridLength(maxWidth19); } - /// /// Copies the selected rows to the clipboard in a formatted manner, with each property labeled for clarity. /// @@ -294,7 +281,6 @@ private void ListViewFlyoutMenuCopy_Click(object sender, RoutedEventArgs e) // Loop through each selected item in the ListView foreach (var selectedItem in FileIdentitiesListView.SelectedItems) { - if (selectedItem is FileIdentity obj) // Append each row's formatted data to the StringBuilder @@ -315,7 +301,6 @@ private void ListViewFlyoutMenuCopy_Click(object sender, RoutedEventArgs e) } } - // Click event handlers for each property private void CopyFileName_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.FileName); private void CopySignatureStatus_Click(object sender, RoutedEventArgs e) => CopyToClipboard((item) => item.SignatureStatus.ToString()); @@ -438,7 +423,7 @@ private void SortColumn(Func keySelector) // Determine if a search filter is active. bool isSearchEmpty = string.IsNullOrWhiteSpace(SearchBox.Text); // Use either the full list (AllowNewAppsStart.Instance.LocalFilesAllFileIdentities) or the current display list. - var collectionToSort = isSearchEmpty ? AllowNewAppsStart.Instance.LocalFilesAllFileIdentities : [.. AllowNewAppsStart.Instance.LocalFilesFileIdentities]; + List collectionToSort = isSearchEmpty ? AllowNewAppsStart.Instance.LocalFilesAllFileIdentities : [.. AllowNewAppsStart.Instance.LocalFilesFileIdentities]; if (SortingDirectionToggle.IsChecked) { @@ -466,9 +451,7 @@ private static string ConvertRowToText(FileIdentity row) // Use StringBuilder to format each property with its label for easy reading return new StringBuilder() .AppendLine($"File Name: {row.FileName}") - .AppendLine($"Time Created: {row.TimeCreated}") .AppendLine($"Signature Status: {row.SignatureStatus}") - .AppendLine($"Action: {row.Action}") .AppendLine($"Original File Name: {row.OriginalFileName}") .AppendLine($"Internal Name: {row.InternalName}") .AppendLine($"File Description: {row.FileDescription}") @@ -477,14 +460,14 @@ private static string ConvertRowToText(FileIdentity row) .AppendLine($"Package Family Name: {row.PackageFamilyName}") .AppendLine($"SHA256 Hash: {row.SHA256Hash}") .AppendLine($"SHA1 Hash: {row.SHA1Hash}") - .AppendLine($"SHA256 Flat Hash: {row.SHA256FlatHash}") - .AppendLine($"SHA1 Flat Hash: {row.SHA1FlatHash}") .AppendLine($"Signing Scenario: {row.SISigningScenario}") .AppendLine($"File Path: {row.FilePath}") - .AppendLine($"Computer Name: {row.ComputerName}") - .AppendLine($"Policy GUID: {row.PolicyGUID}") - .AppendLine($"Policy Name: {row.PolicyName}") + .AppendLine($"SHA1 Page Hash: {row.SHA1PageHash}") + .AppendLine($"SHA256 Page Hash: {row.SHA256PageHash}") + .AppendLine($"Has WHQL Signer: {row.HasWHQLSigner}") .AppendLine($"File Publishers: {row.FilePublishersToDisplay}") + .AppendLine($"Is ECC Signed: {row.IsECCSigned}") + .AppendLine($"Opus: {row.Opus}") .ToString(); } @@ -505,26 +488,25 @@ public AllowNewAppsLocalFilesDataGrid() // Public property to access the singleton instance from other classes // It's okay it's nullable, null check will happen before accessing it - public static AllowNewAppsLocalFilesDataGrid Instance => _instance ?? throw new InvalidOperationException("AllowNewAppsLocalFilesDataGrid is not initialized"); + public static AllowNewAppsLocalFilesDataGrid? Instance => _instance; #region protected override void OnNavigatedTo(NavigationEventArgs e) { base.OnNavigatedTo(e); - FileIdentitiesListView.ItemsSource = AllowNewAppsStart.Instance.LocalFilesFileIdentities; // Update the logs when user switches to this page UpdateTotalLogs(); // Assign the ItemsSource of the ListView only once // We cannot do it after column width calculation because initialization is not guaranteed at that moment - if (AllowNewAppsStart.Instance.EventLogsDataProcessed) + if (AllowNewAppsStart.Instance.LocalFilesDataProcessed) { CalculateColumnWidths(); FileIdentitiesListView.ItemsSource = AllowNewAppsStart.Instance.LocalFilesFileIdentities; - AllowNewAppsStart.Instance.EventLogsDataProcessed = false; + AllowNewAppsStart.Instance.LocalFilesDataProcessed = false; } } #endregion diff --git a/AppControl Manager/Pages/AllowNewApps/AllowNewAppsStart.xaml b/AppControl Manager/Pages/AllowNewApps/AllowNewAppsStart.xaml index ffb303d08..f32372216 100644 --- a/AppControl Manager/Pages/AllowNewApps/AllowNewAppsStart.xaml +++ b/AppControl Manager/Pages/AllowNewApps/AllowNewAppsStart.xaml @@ -193,9 +193,9 @@ - FilePublisher - Publisher - Hash + FilePublisher + Publisher + Hash @@ -34,7 +33,6 @@ private void KeySizeSettingsCard_Click(object sender, RoutedEventArgs e) KeySizeComboBox.IsDropDownOpen = !KeySizeComboBox.IsDropDownOpen; } - /// /// Method to ensure all the required fields are filled with content before the build button will be enabled /// @@ -50,8 +48,6 @@ private void CheckFieldContents() } } - - /// /// Event handler for the main build button /// @@ -72,7 +68,7 @@ private async void BuildCertificateButton_Click(object sender, RoutedEventArgs e generatedCertThumbPrint = null; - string keySize = ((ComboBoxItem)KeySizeComboBox.SelectedValue).Content.ToString()!; + string keySize = (string)KeySizeComboBox.SelectedItem; string commonName = CommonNameTextBox.Text; double validity = ValidityNumberBox.Value; string password = PFXEncryptionPasswordBox.Password; @@ -101,9 +97,7 @@ await Task.Run(() => generatedCertThumbPrint = generatedCert.Thumbprint; }); - } - catch { StatusInfoBar.Title = GlobalVars.Rizz.GetString("ErrorTitle"); @@ -139,8 +133,6 @@ await Task.Run(() => } } - - private void CommonNameTextBox_TextChanged(object sender, TextChangedEventArgs e) { CheckFieldContents(); @@ -151,7 +143,6 @@ private void PFXEncryptionPasswordBox_PasswordChanged(object sender, RoutedEvent CheckFieldContents(); } - private void CopyInfoBarToClipboardButton_Click(object sender, RoutedEventArgs e) { // Create a new data package diff --git a/AppControl Manager/Pages/ConfigurePolicyRuleOptions.xaml b/AppControl Manager/Pages/ConfigurePolicyRuleOptions.xaml index 956c64329..746c73e16 100644 --- a/AppControl Manager/Pages/ConfigurePolicyRuleOptions.xaml +++ b/AppControl Manager/Pages/ConfigurePolicyRuleOptions.xaml @@ -85,7 +85,7 @@ - FilePublisher - Publisher - Hash + FilePublisher + Publisher + Hash diff --git a/AppControl Manager/Pages/MDEAHPolicyCreation.xaml.cs b/AppControl Manager/Pages/MDEAHPolicyCreation.xaml.cs index 9da0d2d68..df0274009 100644 --- a/AppControl Manager/Pages/MDEAHPolicyCreation.xaml.cs +++ b/AppControl Manager/Pages/MDEAHPolicyCreation.xaml.cs @@ -465,7 +465,7 @@ private void SortColumn(Func keySelector) // Determine if a search filter is active. bool isSearchEmpty = string.IsNullOrWhiteSpace(SearchBox.Text); // Use either the full list AllFileIdentities or the current display list. - var collectionToSort = isSearchEmpty ? AllFileIdentities : [.. FileIdentities]; + List collectionToSort = isSearchEmpty ? AllFileIdentities : [.. FileIdentities]; if (SortingDirectionToggle.IsChecked) { @@ -517,10 +517,6 @@ private static string ConvertRowToText(FileIdentity row) #endregion - - - - #region For the toolbar menu's Selector Bar private SelectorBarItem _selectedItem; @@ -687,7 +683,6 @@ private void ApplyFilters() } - /// /// Event handler for the ScanLogs click /// @@ -771,7 +766,6 @@ await Task.Run(() => } - /// /// Event handler for the select Code Integrity EVTX file path button /// @@ -797,7 +791,6 @@ private void BrowseForLogs_Click(object sender, RoutedEventArgs e) } - /// /// Event handler for the Clear Data button /// @@ -1038,7 +1031,6 @@ await Task.Run(() => UpdateHvciOptions.Update(PolicyToAddLogsTo); - // If user selected to deploy the policy if (DeployAtTheEnd) { @@ -1077,7 +1069,6 @@ await Task.Run(() => // Copying the policy file to the User Config directory - outside of the temporary staging area File.Copy(EmptyPolicyPath, OutputPath, true); - // If user selected to deploy the policy if (DeployAtTheEnd) { @@ -1116,7 +1107,6 @@ await Task.Run(() => // Copying the policy file to the User Config directory - outside of the temporary staging area File.Copy(EmptyPolicyPath, OutputPath, true); - // If user selected to deploy the policy if (DeployAtTheEnd) { @@ -1165,15 +1155,13 @@ await Task.Run(() => /// private void ScanLevelComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { - if (ScanLevelComboBox.SelectedItem is ComboBoxItem selectedItem) - { - string selectedText = selectedItem.Content.ToString()!; + // Get the ComboBox that triggered the event + ComboBox comboBox = (ComboBox)sender; - if (!Enum.TryParse(selectedText, out scanLevel)) - { - throw new InvalidOperationException($"{selectedText} is not a valid Scan Level"); - } - } + // Get the selected item from the ComboBox + string selectedText = (string)comboBox.SelectedItem; + + scanLevel = Enum.Parse(selectedText); } private void BrowseForLogs_Holding(object sender, HoldingRoutedEventArgs e) @@ -1196,7 +1184,6 @@ private void BrowseForLogs_Flyout_Clear_Click(object sender, RoutedEventArgs e) } - /// /// Event handler for the Cancel Sign In button /// diff --git a/AppControl Manager/Pages/MergePolicies.xaml.cs b/AppControl Manager/Pages/MergePolicies.xaml.cs index 20e887422..fa6bd10a0 100644 --- a/AppControl Manager/Pages/MergePolicies.xaml.cs +++ b/AppControl Manager/Pages/MergePolicies.xaml.cs @@ -183,7 +183,6 @@ private void OtherPoliciesBrowseButton_Click(object sender, RoutedEventArgs e) } - private void OtherPoliciesSettingsCard_Click(object sender, RoutedEventArgs e) { diff --git a/AppControl Manager/Pages/Settings.xaml b/AppControl Manager/Pages/Settings.xaml index 647081cbe..eec15161a 100644 --- a/AppControl Manager/Pages/Settings.xaml +++ b/AppControl Manager/Pages/Settings.xaml @@ -109,7 +109,7 @@ - + @@ -118,33 +118,33 @@ - MicaAlt - Mica - Acrylic + MicaAlt + Mica + Acrylic - Use System Setting - Dark - Light + Use System Setting + Dark + Light - Animated - Windows Accent - Monochromatic + Animated + Windows Accent + Monochromatic - Left - Top + Left + Top diff --git a/AppControl Manager/Pages/Settings.xaml.cs b/AppControl Manager/Pages/Settings.xaml.cs index 27b3e1fc7..c7a831684 100644 --- a/AppControl Manager/Pages/Settings.xaml.cs +++ b/AppControl Manager/Pages/Settings.xaml.cs @@ -90,22 +90,18 @@ public Settings() private void IconsStyleComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { // Get the ComboBox that triggered the event - ComboBox? comboBox = sender as ComboBox; + ComboBox comboBox = (ComboBox)sender; // Get the selected item from the ComboBox - string? selectedIconsStyle = (comboBox?.SelectedItem as ComboBoxItem)?.Content.ToString(); + string selectedIconsStyle = (string)comboBox.SelectedItem; - if (selectedIconsStyle is not null) - { - // Raise the global BackgroundChanged event - IconsStyleManager.OnIconsStylesChanged(selectedIconsStyle); - } + // Raise the global BackgroundChanged event + IconsStyleManager.OnIconsStylesChanged(selectedIconsStyle); SaveSetting(SettingKeys.IconsStyle, selectedIconsStyle); } - /// /// Event handler for the Background ComboBox selection change event. /// @@ -114,22 +110,17 @@ private void IconsStyleComboBox_SelectionChanged(object sender, SelectionChanged private void BackgroundComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { // Get the ComboBox that triggered the event - ComboBox? comboBox = sender as ComboBox; + ComboBox comboBox = (ComboBox)sender; - // Get the selected item from the ComboBox - string? selectedBackdrop = (comboBox?.SelectedItem as ComboBoxItem)?.Content.ToString(); + // Get the selected item from the ComboBox (x:String) + string selectedBackdrop = (string)comboBox.SelectedItem; - if (selectedBackdrop is not null) - { - // Raise the global BackgroundChanged event - ThemeManager.OnBackgroundChanged(selectedBackdrop); - } + // Raise the global BackgroundChanged event + ThemeManager.OnBackgroundChanged(selectedBackdrop); SaveSetting(SettingKeys.BackDropBackground, selectedBackdrop); } - - /// /// Event handler for the NavigationViewLocation ComboBox selection change event. /// @@ -137,20 +128,20 @@ private void BackgroundComboBox_SelectionChanged(object sender, SelectionChanged /// private void NavigationViewLocationComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { - // Get the ComboBox that triggered the event - ComboBox? comboBox = sender as ComboBox; + ComboBox comboBox = (ComboBox)sender; - // Get the selected item from the ComboBox - string? selectedLocation = (comboBox?.SelectedItem as ComboBoxItem)?.Content?.ToString(); + // This won't work with Native AOT mode + // string? selectedLocation = (comboBox?.SelectedItem as ComboBoxItem)?.Content?.ToString(); - if (selectedLocation is not null) - { - // Raise the global OnNavigationViewLocationChanged event - NavigationViewLocationManager.OnNavigationViewLocationChanged(selectedLocation); - } - } + // This however works and uses WinRT method + // string? selectedLocation = (comboBox?.SelectedItem.As())?.Content?.ToString(); + // This method works too but it needs and not + string selectedLocation = (string)comboBox.SelectedItem; + // Raise the global OnNavigationViewLocationChanged event + NavigationViewLocationManager.OnNavigationViewLocationChanged(selectedLocation); + } /// /// Event handler for the Theme ComboBox selection change event. @@ -160,16 +151,13 @@ private void NavigationViewLocationComboBox_SelectionChanged(object sender, Sele private void ThemeComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { // Get the ComboBox that triggered the event - ComboBox? comboBox = sender as ComboBox; + ComboBox comboBox = (ComboBox)sender; // Get the selected item from the ComboBox - string? selectedTheme = (comboBox?.SelectedItem as ComboBoxItem)?.Content?.ToString(); + string selectedTheme = (string)comboBox.SelectedItem; - if (selectedTheme is not null) - { - // Raise the global BackgroundChanged event - AppThemeManager.OnAppThemeChanged(selectedTheme); - } + // Raise the global BackgroundChanged event + AppThemeManager.OnAppThemeChanged(selectedTheme); SaveSetting(SettingKeys.AppTheme, selectedTheme); } @@ -183,11 +171,10 @@ private void ThemeComboBox_SelectionChanged(object sender, SelectionChangedEvent private void NavigationViewBackground_Toggled(object sender, RoutedEventArgs e) { // Get the ToggleSwitch that triggered the event - ToggleSwitch? toggleSwitch = sender as ToggleSwitch; + ToggleSwitch toggleSwitch = (ToggleSwitch)sender; // Get the state of the ToggleSwitch - // Use false as a fallback if toggleSwitch is null - bool isBackgroundOn = toggleSwitch?.IsOn ?? false; + bool isBackgroundOn = toggleSwitch.IsOn; // Notify NavigationBackgroundManager when the toggle switch is changed NavigationBackgroundManager.OnNavigationBackgroundChanged(isBackgroundOn); @@ -196,7 +183,6 @@ private void NavigationViewBackground_Toggled(object sender, RoutedEventArgs e) } - /// /// Event handler for the Sound toggle switch change event. /// @@ -204,9 +190,11 @@ private void NavigationViewBackground_Toggled(object sender, RoutedEventArgs e) /// private void SoundToggleSwitch_Toggled(object sender, RoutedEventArgs e) { + // Get the ToggleSwitch that triggered the event + ToggleSwitch toggleSwitch = (ToggleSwitch)sender; + // Get the state of the toggle switch (on or off) - ToggleSwitch? toggleSwitch = sender as ToggleSwitch; - bool isSoundOn = toggleSwitch?.IsOn ?? false; + bool isSoundOn = toggleSwitch.IsOn; // Raise the event to notify the app of the sound setting change SoundManager.OnSoundSettingChanged(isSoundOn); @@ -352,11 +340,9 @@ private void BrowseButton_Click(object sender, RoutedEventArgs e) default: break; } - } - /// /// Event handler for AutoSuggestBox /// diff --git a/AppControl Manager/Pages/Simulation.xaml b/AppControl Manager/Pages/Simulation.xaml index 7390e02fb..22f5c26d5 100644 --- a/AppControl Manager/Pages/Simulation.xaml +++ b/AppControl Manager/Pages/Simulation.xaml @@ -11,7 +11,7 @@ xmlns:controls="using:CommunityToolkit.WinUI.Controls" xmlns:others="using:AppControlManager.Others" xmlns:interactivity="using:Microsoft.Xaml.Interactivity" - xmlns:behaviors="using:CommunityToolkit.WinUI.Behaviors" + xmlns:behaviors="using:CommunityToolkit.WinUI.Behaviors" x:Name="SimulationXAML" mc:Ignorable="d"> diff --git a/AppControl Manager/Pages/Simulation.xaml.cs b/AppControl Manager/Pages/Simulation.xaml.cs index 1afa6c398..52c9a2346 100644 --- a/AppControl Manager/Pages/Simulation.xaml.cs +++ b/AppControl Manager/Pages/Simulation.xaml.cs @@ -404,7 +404,7 @@ private void SortColumn(Func keySelector) // Determine if a search filter is active. bool isSearchEmpty = string.IsNullOrWhiteSpace(SearchBox.Text); // Use either the full list (AllSimulationOutputs) or the current display list. - var collectionToSort = isSearchEmpty ? AllSimulationOutputs : [.. SimulationOutputs]; + List collectionToSort = isSearchEmpty ? AllSimulationOutputs : [.. SimulationOutputs]; if (SortingDirectionToggle.IsChecked) { @@ -421,12 +421,8 @@ private void SortColumn(Func keySelector) SimOutputListView.ItemsSource = SimulationOutputs; } - - #endregion - - public ObservableCollection SimulationOutputs { get; set; } private readonly List AllSimulationOutputs; // Store all outputs for searching private List filePaths; // For selected file paths diff --git a/AppControl Manager/Pages/StrictKernelPolicyScanResults.xaml b/AppControl Manager/Pages/StrictKernelPolicyScanResults.xaml index 3a5f49138..2081106b5 100644 --- a/AppControl Manager/Pages/StrictKernelPolicyScanResults.xaml +++ b/AppControl Manager/Pages/StrictKernelPolicyScanResults.xaml @@ -10,7 +10,7 @@ xmlns:controls="using:CommunityToolkit.WinUI.Controls" xmlns:intelgathering="using:AppControlManager.IntelGathering" xmlns:interactivity="using:Microsoft.Xaml.Interactivity" - xmlns:behaviors="using:CommunityToolkit.WinUI.Behaviors" + xmlns:behaviors="using:CommunityToolkit.WinUI.Behaviors" x:Name="StrictKernelPolicyScanResultsXAML"> diff --git a/AppControl Manager/Pages/StrictKernelPolicyScanResults.xaml.cs b/AppControl Manager/Pages/StrictKernelPolicyScanResults.xaml.cs index 188d10e5d..001e53b8f 100644 --- a/AppControl Manager/Pages/StrictKernelPolicyScanResults.xaml.cs +++ b/AppControl Manager/Pages/StrictKernelPolicyScanResults.xaml.cs @@ -380,51 +380,39 @@ private void ColumnSortingButton_SHA1Hash_Click(object sender, RoutedEventArgs e { SortColumn(fileIden => fileIden.SHA1Hash); } - - private void ColumnSortingButton_SigningScenario_Click(object sender, RoutedEventArgs e) { SortColumn(fileIden => fileIden.SISigningScenario); } - private void ColumnSortingButton_FilePath_Click(object sender, RoutedEventArgs e) { SortColumn(fileIden => fileIden.FilePath); } - private void ColumnSortingButton_SHA1PageHash_Click(object sender, RoutedEventArgs e) { SortColumn(fileIden => fileIden.SHA1PageHash); } - private void ColumnSortingButton_SHA256PageHash_Click(object sender, RoutedEventArgs e) { SortColumn(fileIden => fileIden.SHA256PageHash); } - private void ColumnSortingButton_HasWHQLSigner_Click(object sender, RoutedEventArgs e) { SortColumn(fileIden => fileIden.HasWHQLSigner); } - private void ColumnSortingButton_FilePublishers_Click(object sender, RoutedEventArgs e) { SortColumn(fileIden => fileIden.FilePublishersToDisplay); } - private void ColumnSortingButton_IsECCSigned_Click(object sender, RoutedEventArgs e) { SortColumn(fileIden => fileIden.IsECCSigned); } - private void ColumnSortingButton_OpusData_Click(object sender, RoutedEventArgs e) { SortColumn(fileIden => fileIden.Opus); } - - - /// /// Performs data sorting /// @@ -435,7 +423,7 @@ private void SortColumn(Func keySelector) // Determine if a search filter is active. bool isSearchEmpty = string.IsNullOrWhiteSpace(SearchBox.Text); // Use either the full list (CreateSupplementalPolicy.Instance.ScanResultsList) or the current display list. - var collectionToSort = isSearchEmpty ? CreateSupplementalPolicy.Instance.ScanResultsList : [.. CreateSupplementalPolicy.Instance.ScanResults]; + List collectionToSort = isSearchEmpty ? CreateSupplementalPolicy.Instance.ScanResultsList : [.. CreateSupplementalPolicy.Instance.ScanResults]; if (SortingDirectionToggle.IsChecked) { @@ -454,10 +442,6 @@ private void SortColumn(Func keySelector) #endregion - - - - public StrictKernelPolicyScanResults() { this.InitializeComponent(); @@ -585,7 +569,6 @@ private void SelectAll_Click(object sender, RoutedEventArgs e) { FileIdentitiesListView.SelectedItems.Add(fileIdentity); // Select each item } - }); } diff --git a/AppControl Manager/Pages/SystemInformation/CodeIntegrityInfo.xaml b/AppControl Manager/Pages/SystemInformation/CodeIntegrityInfo.xaml index 98606d90d..a4637a3b7 100644 --- a/AppControl Manager/Pages/SystemInformation/CodeIntegrityInfo.xaml +++ b/AppControl Manager/Pages/SystemInformation/CodeIntegrityInfo.xaml @@ -64,9 +64,9 @@ + X1="0" Y1="0" + X2="500" Y2="0" + StrokeThickness="2" Grid.Row="2" Margin="0,10,0,10"/> diff --git a/AppControl Manager/Pages/SystemInformation/CodeIntegrityInfo.xaml.cs b/AppControl Manager/Pages/SystemInformation/CodeIntegrityInfo.xaml.cs index f12ef70a9..4dfb5c99e 100644 --- a/AppControl Manager/Pages/SystemInformation/CodeIntegrityInfo.xaml.cs +++ b/AppControl Manager/Pages/SystemInformation/CodeIntegrityInfo.xaml.cs @@ -1,3 +1,4 @@ +using System.Threading.Tasks; using AppControlManager.Others; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; @@ -14,7 +15,6 @@ public CodeIntegrityInfo() this.NavigationCacheMode = NavigationCacheMode.Enabled; } - /// /// Local method to convert numbers to their actual string values /// @@ -28,25 +28,23 @@ public CodeIntegrityInfo() _ => null }; - /// /// Event handler for the retrieve code integrity information button /// /// /// - private void RetrieveCodeIntegrityInfo_Click(object sender, RoutedEventArgs e) + private async void RetrieveCodeIntegrityInfo_Click(object sender, RoutedEventArgs e) { // Get the system code integrity information - CodeIntegrity.SystemCodeIntegrityInfo codeIntegrityInfoResult = CodeIntegrity.DetailsRetrieval.Get(); + CodeIntegrity.SystemCodeIntegrityInfo codeIntegrityInfoResult = await Task.Run(CodeIntegrity.DetailsRetrieval.Get); // Bind the CodeIntegrityDetails (List) to the ListView CodeIntegrityInfoListView.ItemsSource = codeIntegrityInfoResult.CodeIntegrityDetails; // Get the Application Control Status - DeviceGuardStatus? DGStatus = DeviceGuardInfo.GetDeviceGuardStatus(); + DeviceGuardStatus? DGStatus = await Task.Run(DeviceGuardInfo.GetDeviceGuardStatus); UMCI.Text = GetPolicyStatus(DGStatus?.UsermodeCodeIntegrityPolicyEnforcementStatus); KMCI.Text = GetPolicyStatus(DGStatus?.CodeIntegrityPolicyEnforcementStatus); - } } diff --git a/AppControl Manager/Pages/SystemInformation/SystemInformation.xaml b/AppControl Manager/Pages/SystemInformation/SystemInformation.xaml index 8fb57b1c5..6abbd3a70 100644 --- a/AppControl Manager/Pages/SystemInformation/SystemInformation.xaml +++ b/AppControl Manager/Pages/SystemInformation/SystemInformation.xaml @@ -24,7 +24,6 @@ View detailed information about the Deployed policies and Code Integrity on the system. - @@ -39,7 +38,6 @@ IsSettingsVisible="False" IsBackButtonVisible="Collapsed"> - @@ -52,11 +50,10 @@ - - + - + diff --git a/AppControl Manager/Pages/SystemInformation/SystemInformation.xaml.cs b/AppControl Manager/Pages/SystemInformation/SystemInformation.xaml.cs index f64ed4dda..df1f69df7 100644 --- a/AppControl Manager/Pages/SystemInformation/SystemInformation.xaml.cs +++ b/AppControl Manager/Pages/SystemInformation/SystemInformation.xaml.cs @@ -14,7 +14,6 @@ public SystemInformation() // Make sure navigating to/from this page maintains its state this.NavigationCacheMode = NavigationCacheMode.Enabled; - // Navigate to the CreatePolicy page when the window is loaded _ = ContentFrame.Navigate(typeof(ViewCurrentPolicies)); @@ -23,7 +22,6 @@ public SystemInformation() .First(item => string.Equals(item.Tag.ToString(), "ViewCurrentPolicies", StringComparison.OrdinalIgnoreCase)); } - // Event handler for the navigation menu private void NavigationView_SelectionChanged(NavigationView sender, NavigationViewSelectionChangedEventArgs args) { @@ -46,5 +44,4 @@ private void NavigationView_SelectionChanged(NavigationView sender, NavigationVi } } } - } diff --git a/AppControl Manager/Pages/SystemInformation/ViewCurrentPolicies.xaml b/AppControl Manager/Pages/SystemInformation/ViewCurrentPolicies.xaml index 13edf3199..3668be55d 100644 --- a/AppControl Manager/Pages/SystemInformation/ViewCurrentPolicies.xaml +++ b/AppControl Manager/Pages/SystemInformation/ViewCurrentPolicies.xaml @@ -12,7 +12,7 @@ xmlns:win="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:controls="using:CommunityToolkit.WinUI.Controls" xmlns:interactivity="using:Microsoft.Xaml.Interactivity" - xmlns:behaviors="using:CommunityToolkit.WinUI.Behaviors" + xmlns:behaviors="using:CommunityToolkit.WinUI.Behaviors" xmlns:animatedvisuals="using:AnimatedVisuals" mc:Ignorable="d"> @@ -119,11 +119,11 @@ - Default Windows - Allow Microsoft - Signed and Reputable - Strict Kernel-Mode - Strict Kernel-Mode (No Flight Roots) + Default Windows + Allow Microsoft + Signed and Reputable + Strict Kernel-Mode + Strict Kernel-Mode (No Flight Roots) diff --git a/AppControl Manager/Pages/SystemInformation/ViewCurrentPolicies.xaml.cs b/AppControl Manager/Pages/SystemInformation/ViewCurrentPolicies.xaml.cs index 9ab8c1738..631b1ec0c 100644 --- a/AppControl Manager/Pages/SystemInformation/ViewCurrentPolicies.xaml.cs +++ b/AppControl Manager/Pages/SystemInformation/ViewCurrentPolicies.xaml.cs @@ -191,7 +191,6 @@ private static string ConvertRowToText(CiPolicyInfo row) .ToString(); } - /// /// Copies the selected rows to the clipboard in a formatted manner, with each property labeled for clarity. /// @@ -300,7 +299,6 @@ private void ColumnSortingButton_PolicyRuleOptions_Click(object sender, RoutedEv SortColumn(policy => policy.PolicyOptionsDisplay); } - /// /// Performs data sorting /// @@ -311,7 +309,7 @@ private void SortColumn(Func keySelector) // Determine if a search filter is active. bool isSearchEmpty = string.IsNullOrWhiteSpace(SearchBox.Text); // Use either the full list (AllPoliciesOutput) or the current display list. - var collectionToSort = isSearchEmpty ? AllPoliciesOutput : [.. AllPolicies]; + List collectionToSort = isSearchEmpty ? AllPoliciesOutput : [.. AllPolicies]; if (SortingDirectionToggle.IsChecked) { @@ -355,7 +353,6 @@ public ViewCurrentPolicies() AllPoliciesOutput = []; } - /// /// Event handler for the RetrievePoliciesButton click /// @@ -366,16 +363,13 @@ private void RetrievePoliciesButton_Click(object sender, RoutedEventArgs e) RetrievePolicies(); } - /// /// Helper method to retrieve the policies from the system /// private async void RetrievePolicies() { - try { - // Disable the button to prevent multiple clicks while retrieving RetrievePoliciesButton.IsEnabled = false; @@ -432,7 +426,6 @@ private async void RetrievePolicies() // Update the UI once the task completes PoliciesCountTextBlock.Text = GlobalVars.Rizz.GetString("NumberOfPolicies") + policies.Count; - CalculateColumnWidths(); DeployedPolicies.ItemsSource = AllPolicies; @@ -444,7 +437,6 @@ private async void RetrievePolicies() } } - /// /// Event handler for the search box text change /// @@ -858,7 +850,7 @@ private async void SwapPolicyComboBox_SelectionChanged(object sender, SelectionC // Create colored runs Run accentPolicyName = new() { Text = selectedPolicy.FriendlyName, Foreground = violetBrush }; Run accentPolicyID = new() { Text = policyID, Foreground = violetBrush }; - Run accentPolicyType = new() { Text = ((ComboBoxItem)SwapPolicyComboBox.SelectedItem).Content.ToString(), Foreground = hotPinkBrush }; + Run accentPolicyType = new() { Text = (string)SwapPolicyComboBox.SelectedItem, Foreground = hotPinkBrush }; // Create bold text run Bold boldText = new(); diff --git a/AppControl Manager/Pages/Update.xaml b/AppControl Manager/Pages/Update.xaml index 6fc30bcfc..7e8cea48a 100644 --- a/AppControl Manager/Pages/Update.xaml +++ b/AppControl Manager/Pages/Update.xaml @@ -32,7 +32,6 @@ - @@ -77,7 +76,7 @@