From 313087052051d54576cb99048ce153b2719bff87 Mon Sep 17 00:00:00 2001 From: Lauren Ciha <64796985+lauren-ciha@users.noreply.github.com> Date: Fri, 13 Sep 2024 08:42:05 -0700 Subject: [PATCH 01/58] Update FileShare options to ReadWrite (#3850) --- extensions/CoreWidgetProvider/Widgets/SSHWalletWidget.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/extensions/CoreWidgetProvider/Widgets/SSHWalletWidget.cs b/extensions/CoreWidgetProvider/Widgets/SSHWalletWidget.cs index 2e78000dd..e8fa55641 100644 --- a/extensions/CoreWidgetProvider/Widgets/SSHWalletWidget.cs +++ b/extensions/CoreWidgetProvider/Widgets/SSHWalletWidget.cs @@ -208,6 +208,7 @@ private void HandleCheckPath(WidgetActionInvokedArgs args) var options = new FileStreamOptions() { Access = FileAccess.Read, + Share = FileShare.ReadWrite, }; using var reader = new StreamReader(ConfigFile, options); From 6f52ad28027204d3267f6eb4e91ff46cfb99e4e2 Mon Sep 17 00:00:00 2001 From: andreww-msft <30507740+andreww-msft@users.noreply.github.com> Date: Fri, 13 Sep 2024 10:25:38 -0700 Subject: [PATCH 02/58] Fix crash in SimpleTextInsights (#3853) --- ...rMissingFileProcessTerminationControl.xaml | 2 +- .../Helpers/InsightsHelper.cs | 39 ++++++++++++++----- .../Pages/WinLogsPage.xaml | 10 ++++- .../Strings/en-us/Resources.resw | 2 +- .../ViewModels/WinLogsPageViewModel.cs | 14 ++++--- 5 files changed, 50 insertions(+), 17 deletions(-) diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/InsightForMissingFileProcessTerminationControl.xaml b/tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/InsightForMissingFileProcessTerminationControl.xaml index df638eda5..cc5a62735 100644 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/InsightForMissingFileProcessTerminationControl.xaml +++ b/tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/InsightForMissingFileProcessTerminationControl.xaml @@ -14,7 +14,7 @@ - + diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/InsightsHelper.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/InsightsHelper.cs index 2c4cd23ed..4a998f6e9 100644 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/InsightsHelper.cs +++ b/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/InsightsHelper.cs @@ -5,7 +5,9 @@ using System.Collections.Generic; using System.ComponentModel; using System.Text.RegularExpressions; +using System.Threading.Tasks; using DevHome.DevDiagnostics.Models; +using Microsoft.UI.Dispatching; using Serilog; namespace DevHome.DevDiagnostics.Helpers; @@ -31,28 +33,47 @@ internal sealed partial class InsightsHelper [GeneratedRegex(@"0xc0000005", RegexOptions.IgnoreCase, "en-US")] private static partial Regex MemoryErrorRegex(); - private static readonly List RegexList = []; + private static readonly List _regexList = []; static InsightsHelper() { - RegexList.Add(new InsightRegex(InsightType.LockedFile, LockedFileErrorRegex())); - RegexList.Add(new InsightRegex(InsightType.Security, BufferOverflowErrorRegex())); - RegexList.Add(new InsightRegex(InsightType.MemoryViolation, MemoryErrorRegex())); + _regexList.Add(new InsightRegex(InsightType.LockedFile, LockedFileErrorRegex())); + _regexList.Add(new InsightRegex(InsightType.Security, BufferOverflowErrorRegex())); + _regexList.Add(new InsightRegex(InsightType.MemoryViolation, MemoryErrorRegex())); } - internal static Insight? FindPattern(string errorText) + internal static async Task FindPattern(string errorText, DispatcherQueue dispatcher) { SimpleTextInsight? newInsight = null; - foreach (var insightRegex in RegexList) + foreach (var insightRegex in _regexList) { var match = insightRegex.Regex.Match(errorText); if (match.Success) { - newInsight = new SimpleTextInsight + var tcs = new TaskCompletionSource(); + dispatcher.TryEnqueue(() => { - InsightType = insightRegex.InsightType, - }; + try + { + newInsight = new SimpleTextInsight + { + InsightType = insightRegex.InsightType, + }; + tcs.SetResult(true); + } + catch (Exception ex) + { + tcs.SetException(ex); + } + }); + + await tcs.Task; + + if (newInsight is null) + { + return null; + } // Once we flesh out our error database, we should have a more structured way to // handle different types of insights, rather than a switch statement. diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/WinLogsPage.xaml b/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/WinLogsPage.xaml index 49e93f1f4..00698560c 100644 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/WinLogsPage.xaml +++ b/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/WinLogsPage.xaml @@ -99,7 +99,15 @@ - + diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Strings/en-us/Resources.resw b/tools/DevDiagnostics/DevHome.DevDiagnostics/Strings/en-us/Resources.resw index a4a15b597..7249a1588 100644 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Strings/en-us/Resources.resw +++ b/tools/DevDiagnostics/DevHome.DevDiagnostics/Strings/en-us/Resources.resw @@ -1283,7 +1283,7 @@ Dump File creation time: {1} Title of an insight informing the user of a reason why a process exited - Process {0} (pid: {1,6}) exited with error code {2}. Enabling loader snaps and trying to launch the process again can help diagnose why the app exited. + Process {0} (pid: {1,6}) exited with error code {2}. To help diagnose this issue, enable loader snaps and try to launch the process again. {Locked="{0}, "{1,6}", "{2}"} Formatted string informing the user the process name {0}, the Process ID {1}, the exit code {2} of a process. diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/ViewModels/WinLogsPageViewModel.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/ViewModels/WinLogsPageViewModel.cs index d9e87a810..8ccdc9a60 100644 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/ViewModels/WinLogsPageViewModel.cs +++ b/tools/DevDiagnostics/DevHome.DevDiagnostics/ViewModels/WinLogsPageViewModel.cs @@ -173,13 +173,17 @@ private void WinLogsOutput_CollectionChanged(object? sender, NotifyCollectionCha private void FindPattern(string message) { - var newInsight = InsightsHelper.FindPattern(message); - if (newInsight is not null) + var newInsightTask = InsightsHelper.FindPattern(message, _dispatcher); + if (newInsightTask is not null) { - _dispatcher.TryEnqueue(() => + var newInsight = newInsightTask.Result; + if (newInsight is not null) { - _insightsService.AddInsight(newInsight); - }); + _dispatcher.TryEnqueue(() => + { + _insightsService.AddInsight(newInsight); + }); + } } } From f96f181c5c778d81e8d1e56edccd4f527717e7f5 Mon Sep 17 00:00:00 2001 From: Jason Holmes Date: Fri, 13 Sep 2024 10:54:50 -0700 Subject: [PATCH 03/58] Detect if the current process is elevated instead of whether the user is in the administrator group for showing the Dashboard (#3833) Co-authored-by: Jason Holmes <27746781+jaholme@users.noreply.github.com> --- common/Helpers/RuntimeHelper.cs | 33 +++++++++++++++++++ common/NativeMethods.txt | 6 +++- .../ViewModels/DashboardViewModel.cs | 4 +-- .../Views/DashboardView.xaml.cs | 4 +-- 4 files changed, 42 insertions(+), 5 deletions(-) diff --git a/common/Helpers/RuntimeHelper.cs b/common/Helpers/RuntimeHelper.cs index 1e81bd152..d08bb5dd8 100644 --- a/common/Helpers/RuntimeHelper.cs +++ b/common/Helpers/RuntimeHelper.cs @@ -2,9 +2,13 @@ // Licensed under the MIT License. using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using System.Security.Principal; using Windows.Win32; using Windows.Win32.Foundation; +using Windows.Win32.Security; +using static DevHome.Common.Helpers.RuntimeHelper; namespace DevHome.Common.Helpers; @@ -35,6 +39,35 @@ public static bool IsCurrentProcessRunningAsAdmin() return identity.Owner?.IsWellKnown(WellKnownSidType.BuiltinAdministratorsSid) ?? false; } + // Determine whether the current process is running elevated in a split token session + // will not return true if UAC is disabled and the user is running as administrator by default + public static unsafe bool IsCurrentProcessRunningElevated() + { + HANDLE tokenHandle; + if (!PInvoke.OpenProcessToken(PInvoke.GetCurrentProcess(), TOKEN_ACCESS_MASK.TOKEN_QUERY, &tokenHandle)) + { + throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error()); + } + + try + { + TOKEN_ELEVATION_TYPE elevationType; + uint elevationTypeSize = (uint)Unsafe.SizeOf(); + uint returnLength; + + if (!PInvoke.GetTokenInformation(tokenHandle, TOKEN_INFORMATION_CLASS.TokenElevationType, &elevationType, elevationTypeSize, &returnLength)) + { + throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error()); + } + + return elevationType == TOKEN_ELEVATION_TYPE.TokenElevationTypeFull; + } + finally + { + PInvoke.CloseHandle(tokenHandle); + } + } + public static void VerifyCurrentProcessRunningAsAdmin() { if (!IsCurrentProcessRunningAsAdmin()) diff --git a/common/NativeMethods.txt b/common/NativeMethods.txt index acddcf3da..342d73992 100644 --- a/common/NativeMethods.txt +++ b/common/NativeMethods.txt @@ -11,6 +11,9 @@ GetWindowLong WINDOW_EX_STYLE SHLoadIndirectString StrFormatByteSizeEx +OpenProcessToken +GetTokenInformation +GetCurrentProcess SFBS_FLAGS MAX_PATH GetDpiForWindow @@ -18,4 +21,5 @@ GetWindowRect GetMonitorInfo SetWindowPos MonitorFromWindow -E_INVALIDARG \ No newline at end of file +E_INVALIDARG +TOKEN_ELEVATION_TYPE \ No newline at end of file diff --git a/tools/Dashboard/DevHome.Dashboard/ViewModels/DashboardViewModel.cs b/tools/Dashboard/DevHome.Dashboard/ViewModels/DashboardViewModel.cs index 1525cfcdf..09e8bfa5e 100644 --- a/tools/Dashboard/DevHome.Dashboard/ViewModels/DashboardViewModel.cs +++ b/tools/Dashboard/DevHome.Dashboard/ViewModels/DashboardViewModel.cs @@ -46,8 +46,8 @@ public Visibility GetNoWidgetMessageVisibility(int widgetCount, bool isLoading) return (widgetCount == 0 && !isLoading && HasWidgetServiceInitialized) ? Visibility.Visible : Visibility.Collapsed; } - public bool IsRunningAsAdmin() + public bool IsRunningElevated() { - return RuntimeHelper.IsCurrentProcessRunningAsAdmin(); + return RuntimeHelper.IsCurrentProcessRunningElevated(); } } diff --git a/tools/Dashboard/DevHome.Dashboard/Views/DashboardView.xaml.cs b/tools/Dashboard/DevHome.Dashboard/Views/DashboardView.xaml.cs index f30eeb6c4..378e8968b 100644 --- a/tools/Dashboard/DevHome.Dashboard/Views/DashboardView.xaml.cs +++ b/tools/Dashboard/DevHome.Dashboard/Views/DashboardView.xaml.cs @@ -195,8 +195,8 @@ private void UnsubscribeFromWidgets() private async Task ValidateDashboardState() { - // Ensure we're not running as admin. Display an error and don't allow using the Dashboard if we are. - if (ViewModel.IsRunningAsAdmin()) + // Ensure we're not running elevated. Display an error and don't allow using the Dashboard if we are. + if (ViewModel.IsRunningElevated()) { _log.Error($"Dev Home is running as admin, can't show Dashboard"); RunningAsAdminMessageStackPanel.Visibility = Visibility.Visible; From 920edbf771d526136b79a4b3680212b72ef2f235 Mon Sep 17 00:00:00 2001 From: Jason Holmes Date: Fri, 13 Sep 2024 15:10:57 -0700 Subject: [PATCH 04/58] Disable Dev Diagnostics startup task by default (#3863) Co-authored-by: Jason Holmes <27746781+jaholme@users.noreply.github.com> --- src/Package-Can.appxmanifest | 2 +- src/Package-Dev.appxmanifest | 2 +- src/Package.appxmanifest | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Package-Can.appxmanifest b/src/Package-Can.appxmanifest index c36f7ff99..e9642d2e4 100644 --- a/src/Package-Can.appxmanifest +++ b/src/Package-Can.appxmanifest @@ -354,7 +354,7 @@ - + diff --git a/src/Package-Dev.appxmanifest b/src/Package-Dev.appxmanifest index e86f903cc..420f06455 100644 --- a/src/Package-Dev.appxmanifest +++ b/src/Package-Dev.appxmanifest @@ -354,7 +354,7 @@ - + diff --git a/src/Package.appxmanifest b/src/Package.appxmanifest index ed599df29..48f3b7fd4 100644 --- a/src/Package.appxmanifest +++ b/src/Package.appxmanifest @@ -354,7 +354,7 @@ - + From e06682b690d3a38b8dbde9290eb15125ed42f48f Mon Sep 17 00:00:00 2001 From: Scott Darnell <20483794+aeloros@users.noreply.github.com> Date: Mon, 16 Sep 2024 11:05:48 -0700 Subject: [PATCH 05/58] Enable the ability to toggle App Verifier in Image File Execution Options (IFEO) for the target app. (#3840) * merging latest No service, No Elevation! remove stale comment initial plug at a separate tool exe New tool app creation checkpoint. more telemetry more telemetry, and basic arg parsing per-targetapp instancing remove todo * remove unneeded files * cleanup for pr * pr feedback round 1 * pr feedback round 2 --- DevHome.sln | 20 ++ .../Helpers}/RegistryWatcher.cs | 308 ++++++++++-------- common/NativeMethods.txt | 3 +- .../Windows}/ThemeAwareWindow.cs | 14 +- .../src/DevSetupAgent/DevSetupAgent.csproj | 1 + .../src/DevSetupAgent/HostRegistryChannel.cs | 1 + .../src/DevSetupAgent/NativeMethods.txt | 3 +- src/DevHome.csproj | 1 + src/Package-Can.appxmanifest | 13 + src/Package-Dev.appxmanifest | 13 + src/Package.appxmanifest | 13 + src/Properties/launchsettings.json | 5 + .../DevHome.DevDiagnostics/App.config | 3 + .../Controls/ClipboardMonitorControl.xaml | 2 +- .../Helpers/HotKeyHelper.cs | 24 +- .../Helpers/ImageOptionsInternalTool.cs | 108 ++++++ .../Helpers/InternalToolsHelper.cs | 1 + .../Helpers/LoaderSnapAssistantTool.cs | 4 +- .../DevHome.DevDiagnostics/Helpers/Tool.cs | 7 +- .../DevHome.DevDiagnostics/NativeMethods.txt | 2 + .../Properties/Settings.Designer.cs | 12 + .../Properties/Settings.settings | 3 + .../Strings/en-us/Resources.resw | 12 + .../Views/BarWindow.xaml | 5 +- .../Views/BarWindow.xaml.cs | 8 +- .../Views/ClipboardMonitoringWindow.xaml | 5 +- .../Views/ClipboardMonitoringWindow.xaml.cs | 2 +- .../IfeoTool/Assets/LargeTile.scale-100.png | Bin 0 -> 7196 bytes .../IfeoTool/Assets/LargeTile.scale-125.png | Bin 0 -> 9350 bytes .../IfeoTool/Assets/LargeTile.scale-150.png | Bin 0 -> 11684 bytes .../IfeoTool/Assets/LargeTile.scale-200.png | Bin 0 -> 16871 bytes .../IfeoTool/Assets/LargeTile.scale-400.png | Bin 0 -> 44599 bytes .../IfeoTool/Assets/SmallTile.scale-100.png | Bin 0 -> 2042 bytes .../IfeoTool/Assets/SmallTile.scale-125.png | Bin 0 -> 2699 bytes .../IfeoTool/Assets/SmallTile.scale-150.png | Bin 0 -> 3304 bytes .../IfeoTool/Assets/SmallTile.scale-200.png | Bin 0 -> 4374 bytes .../IfeoTool/Assets/SmallTile.scale-400.png | Bin 0 -> 9600 bytes .../Assets/SplashScreen.scale-100.png | Bin 0 -> 7884 bytes .../Assets/SplashScreen.scale-125.png | Bin 0 -> 9858 bytes .../Assets/SplashScreen.scale-150.png | Bin 0 -> 12563 bytes .../Assets/SplashScreen.scale-200.png | Bin 0 -> 17965 bytes .../Assets/SplashScreen.scale-400.png | Bin 0 -> 49228 bytes .../Assets/Square150x150Logo.scale-100.png | Bin 0 -> 3362 bytes .../Assets/Square150x150Logo.scale-125.png | Bin 0 -> 4144 bytes .../Assets/Square150x150Logo.scale-150.png | Bin 0 -> 5160 bytes .../Assets/Square150x150Logo.scale-200.png | Bin 0 -> 7161 bytes .../Assets/Square150x150Logo.scale-400.png | Bin 0 -> 16077 bytes ...go.altform-lightunplated_targetsize-16.png | Bin 0 -> 716 bytes ...go.altform-lightunplated_targetsize-24.png | Bin 0 -> 1168 bytes ...o.altform-lightunplated_targetsize-256.png | Bin 0 -> 17717 bytes ...go.altform-lightunplated_targetsize-32.png | Bin 0 -> 1583 bytes ...go.altform-lightunplated_targetsize-48.png | Bin 0 -> 2583 bytes ...x44Logo.altform-unplated_targetsize-16.png | Bin 0 -> 716 bytes ...44Logo.altform-unplated_targetsize-256.png | Bin 0 -> 17717 bytes ...x44Logo.altform-unplated_targetsize-32.png | Bin 0 -> 1583 bytes ...x44Logo.altform-unplated_targetsize-48.png | Bin 0 -> 2583 bytes .../Assets/Square44x44Logo.scale-100.png | Bin 0 -> 1634 bytes .../Assets/Square44x44Logo.scale-125.png | Bin 0 -> 2287 bytes .../Assets/Square44x44Logo.scale-150.png | Bin 0 -> 2891 bytes .../Assets/Square44x44Logo.scale-200.png | Bin 0 -> 3832 bytes .../Assets/Square44x44Logo.scale-400.png | Bin 0 -> 7932 bytes .../Assets/Square44x44Logo.targetsize-16.png | Bin 0 -> 566 bytes .../Assets/Square44x44Logo.targetsize-24.png | Bin 0 -> 824 bytes ...x44Logo.targetsize-24_altform-unplated.png | Bin 0 -> 1168 bytes .../Assets/Square44x44Logo.targetsize-256.png | Bin 0 -> 12692 bytes .../Assets/Square44x44Logo.targetsize-32.png | Bin 0 -> 1206 bytes .../Assets/Square44x44Logo.targetsize-48.png | Bin 0 -> 1970 bytes .../IfeoTool/Assets/StoreLogo.scale-100.png | Bin 0 -> 2751 bytes .../IfeoTool/Assets/StoreLogo.scale-125.png | Bin 0 -> 3454 bytes .../IfeoTool/Assets/StoreLogo.scale-150.png | Bin 0 -> 4201 bytes .../IfeoTool/Assets/StoreLogo.scale-200.png | Bin 0 -> 5726 bytes .../IfeoTool/Assets/StoreLogo.scale-400.png | Bin 0 -> 12054 bytes .../Assets/Wide310x150Logo.scale-100.png | Bin 0 -> 3596 bytes .../Assets/Wide310x150Logo.scale-125.png | Bin 0 -> 4412 bytes .../Assets/Wide310x150Logo.scale-150.png | Bin 0 -> 5573 bytes .../Assets/Wide310x150Logo.scale-200.png | Bin 0 -> 7884 bytes .../Assets/Wide310x150Logo.scale-400.png | Bin 0 -> 17965 bytes .../IfeoTool/DevHome.IfeoTool.csproj | 41 +++ tools/Utilities/IfeoTool/IfeoToolApp.xaml | 17 + tools/Utilities/IfeoTool/IfeoToolApp.xaml.cs | 112 +++++++ tools/Utilities/IfeoTool/IfeoToolWindow.xaml | 37 +++ .../Utilities/IfeoTool/IfeoToolWindow.xaml.cs | 52 +++ .../IfeoTool/ImageFileExecutionOptions.cs | 199 +++++++++++ .../IfeoTool/ImageOptionsControlViewModel.cs | 99 ++++++ tools/Utilities/IfeoTool/NativeMethods.json | 4 + tools/Utilities/IfeoTool/NativeMethods.txt | 4 + tools/Utilities/IfeoTool/Program.cs | 91 ++++++ .../PublishProfiles/win-arm64.pubxml | 16 + .../Properties/PublishProfiles/win-x64.pubxml | 16 + .../Properties/PublishProfiles/win-x86.pubxml | 16 + .../IfeoTool/Properties/launchSettings.json | 7 + .../IfeoTool/Strings/en-us/Resources.resw | 129 ++++++++ .../Telemetry/IfeoToolAppLaunchEvent.cs | 25 ++ .../Telemetry/IfeoToolGlobalFlagsChanged.cs | 32 ++ .../IfeoTool/Telemetry/IfeoToolTraceEvent.cs | 25 ++ tools/Utilities/IfeoTool/app.manifest | 19 ++ .../IfeoTool/appsettings_ifeotool.json | 31 ++ 97 files changed, 1400 insertions(+), 165 deletions(-) rename {extensions/HyperVExtension/src/DevSetupAgent => common/Helpers}/RegistryWatcher.cs (66%) rename {tools/DevDiagnostics/DevHome.DevDiagnostics/Controls => common/Windows}/ThemeAwareWindow.cs (93%) create mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/ImageOptionsInternalTool.cs create mode 100644 tools/Utilities/IfeoTool/Assets/LargeTile.scale-100.png create mode 100644 tools/Utilities/IfeoTool/Assets/LargeTile.scale-125.png create mode 100644 tools/Utilities/IfeoTool/Assets/LargeTile.scale-150.png create mode 100644 tools/Utilities/IfeoTool/Assets/LargeTile.scale-200.png create mode 100644 tools/Utilities/IfeoTool/Assets/LargeTile.scale-400.png create mode 100644 tools/Utilities/IfeoTool/Assets/SmallTile.scale-100.png create mode 100644 tools/Utilities/IfeoTool/Assets/SmallTile.scale-125.png create mode 100644 tools/Utilities/IfeoTool/Assets/SmallTile.scale-150.png create mode 100644 tools/Utilities/IfeoTool/Assets/SmallTile.scale-200.png create mode 100644 tools/Utilities/IfeoTool/Assets/SmallTile.scale-400.png create mode 100644 tools/Utilities/IfeoTool/Assets/SplashScreen.scale-100.png create mode 100644 tools/Utilities/IfeoTool/Assets/SplashScreen.scale-125.png create mode 100644 tools/Utilities/IfeoTool/Assets/SplashScreen.scale-150.png create mode 100644 tools/Utilities/IfeoTool/Assets/SplashScreen.scale-200.png create mode 100644 tools/Utilities/IfeoTool/Assets/SplashScreen.scale-400.png create mode 100644 tools/Utilities/IfeoTool/Assets/Square150x150Logo.scale-100.png create mode 100644 tools/Utilities/IfeoTool/Assets/Square150x150Logo.scale-125.png create mode 100644 tools/Utilities/IfeoTool/Assets/Square150x150Logo.scale-150.png create mode 100644 tools/Utilities/IfeoTool/Assets/Square150x150Logo.scale-200.png create mode 100644 tools/Utilities/IfeoTool/Assets/Square150x150Logo.scale-400.png create mode 100644 tools/Utilities/IfeoTool/Assets/Square44x44Logo.altform-lightunplated_targetsize-16.png create mode 100644 tools/Utilities/IfeoTool/Assets/Square44x44Logo.altform-lightunplated_targetsize-24.png create mode 100644 tools/Utilities/IfeoTool/Assets/Square44x44Logo.altform-lightunplated_targetsize-256.png create mode 100644 tools/Utilities/IfeoTool/Assets/Square44x44Logo.altform-lightunplated_targetsize-32.png create mode 100644 tools/Utilities/IfeoTool/Assets/Square44x44Logo.altform-lightunplated_targetsize-48.png create mode 100644 tools/Utilities/IfeoTool/Assets/Square44x44Logo.altform-unplated_targetsize-16.png create mode 100644 tools/Utilities/IfeoTool/Assets/Square44x44Logo.altform-unplated_targetsize-256.png create mode 100644 tools/Utilities/IfeoTool/Assets/Square44x44Logo.altform-unplated_targetsize-32.png create mode 100644 tools/Utilities/IfeoTool/Assets/Square44x44Logo.altform-unplated_targetsize-48.png create mode 100644 tools/Utilities/IfeoTool/Assets/Square44x44Logo.scale-100.png create mode 100644 tools/Utilities/IfeoTool/Assets/Square44x44Logo.scale-125.png create mode 100644 tools/Utilities/IfeoTool/Assets/Square44x44Logo.scale-150.png create mode 100644 tools/Utilities/IfeoTool/Assets/Square44x44Logo.scale-200.png create mode 100644 tools/Utilities/IfeoTool/Assets/Square44x44Logo.scale-400.png create mode 100644 tools/Utilities/IfeoTool/Assets/Square44x44Logo.targetsize-16.png create mode 100644 tools/Utilities/IfeoTool/Assets/Square44x44Logo.targetsize-24.png create mode 100644 tools/Utilities/IfeoTool/Assets/Square44x44Logo.targetsize-24_altform-unplated.png create mode 100644 tools/Utilities/IfeoTool/Assets/Square44x44Logo.targetsize-256.png create mode 100644 tools/Utilities/IfeoTool/Assets/Square44x44Logo.targetsize-32.png create mode 100644 tools/Utilities/IfeoTool/Assets/Square44x44Logo.targetsize-48.png create mode 100644 tools/Utilities/IfeoTool/Assets/StoreLogo.scale-100.png create mode 100644 tools/Utilities/IfeoTool/Assets/StoreLogo.scale-125.png create mode 100644 tools/Utilities/IfeoTool/Assets/StoreLogo.scale-150.png create mode 100644 tools/Utilities/IfeoTool/Assets/StoreLogo.scale-200.png create mode 100644 tools/Utilities/IfeoTool/Assets/StoreLogo.scale-400.png create mode 100644 tools/Utilities/IfeoTool/Assets/Wide310x150Logo.scale-100.png create mode 100644 tools/Utilities/IfeoTool/Assets/Wide310x150Logo.scale-125.png create mode 100644 tools/Utilities/IfeoTool/Assets/Wide310x150Logo.scale-150.png create mode 100644 tools/Utilities/IfeoTool/Assets/Wide310x150Logo.scale-200.png create mode 100644 tools/Utilities/IfeoTool/Assets/Wide310x150Logo.scale-400.png create mode 100644 tools/Utilities/IfeoTool/DevHome.IfeoTool.csproj create mode 100644 tools/Utilities/IfeoTool/IfeoToolApp.xaml create mode 100644 tools/Utilities/IfeoTool/IfeoToolApp.xaml.cs create mode 100644 tools/Utilities/IfeoTool/IfeoToolWindow.xaml create mode 100644 tools/Utilities/IfeoTool/IfeoToolWindow.xaml.cs create mode 100644 tools/Utilities/IfeoTool/ImageFileExecutionOptions.cs create mode 100644 tools/Utilities/IfeoTool/ImageOptionsControlViewModel.cs create mode 100644 tools/Utilities/IfeoTool/NativeMethods.json create mode 100644 tools/Utilities/IfeoTool/NativeMethods.txt create mode 100644 tools/Utilities/IfeoTool/Program.cs create mode 100644 tools/Utilities/IfeoTool/Properties/PublishProfiles/win-arm64.pubxml create mode 100644 tools/Utilities/IfeoTool/Properties/PublishProfiles/win-x64.pubxml create mode 100644 tools/Utilities/IfeoTool/Properties/PublishProfiles/win-x86.pubxml create mode 100644 tools/Utilities/IfeoTool/Properties/launchSettings.json create mode 100644 tools/Utilities/IfeoTool/Strings/en-us/Resources.resw create mode 100644 tools/Utilities/IfeoTool/Telemetry/IfeoToolAppLaunchEvent.cs create mode 100644 tools/Utilities/IfeoTool/Telemetry/IfeoToolGlobalFlagsChanged.cs create mode 100644 tools/Utilities/IfeoTool/Telemetry/IfeoToolTraceEvent.cs create mode 100644 tools/Utilities/IfeoTool/app.manifest create mode 100644 tools/Utilities/IfeoTool/appsettings_ifeotool.json diff --git a/DevHome.sln b/DevHome.sln index 029065ab7..af3d4f781 100644 --- a/DevHome.sln +++ b/DevHome.sln @@ -201,6 +201,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "NTService", "NTService", "{ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Telemetry", "Telemetry", "{70D3F826-0057-4EAF-AA6D-09479075B056}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DevHome.IfeoTool", "tools\Utilities\IfeoTool\DevHome.IfeoTool.csproj", "{A9B2E87D-540F-4B4C-A4AA-EF3BDDC4171C}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EnableLocalCabCollection", "tools\DevDiagnostics\Utilities\EnableLocalCabCollection\EnableLocalCabCollection.csproj", "{A382B448-A1F3-4D87-A674-736D2987E613}" EndProject Global @@ -1353,6 +1354,24 @@ Global {82BD8133-F1D4-4383-BC4F-12EFAE1AFF91}.Release|x64.Build.0 = Release|x64 {82BD8133-F1D4-4383-BC4F-12EFAE1AFF91}.Release|x86.ActiveCfg = Release|x86 {82BD8133-F1D4-4383-BC4F-12EFAE1AFF91}.Release|x86.Build.0 = Release|x86 + {A9B2E87D-540F-4B4C-A4AA-EF3BDDC4171C}.Debug_FailFast|arm64.ActiveCfg = Debug_FailFast|arm64 + {A9B2E87D-540F-4B4C-A4AA-EF3BDDC4171C}.Debug_FailFast|arm64.Build.0 = Debug_FailFast|arm64 + {A9B2E87D-540F-4B4C-A4AA-EF3BDDC4171C}.Debug_FailFast|x64.ActiveCfg = Debug_FailFast|x64 + {A9B2E87D-540F-4B4C-A4AA-EF3BDDC4171C}.Debug_FailFast|x64.Build.0 = Debug_FailFast|x64 + {A9B2E87D-540F-4B4C-A4AA-EF3BDDC4171C}.Debug_FailFast|x86.ActiveCfg = Debug_FailFast|x86 + {A9B2E87D-540F-4B4C-A4AA-EF3BDDC4171C}.Debug_FailFast|x86.Build.0 = Debug_FailFast|x86 + {A9B2E87D-540F-4B4C-A4AA-EF3BDDC4171C}.Debug|arm64.ActiveCfg = Debug|arm64 + {A9B2E87D-540F-4B4C-A4AA-EF3BDDC4171C}.Debug|arm64.Build.0 = Debug|arm64 + {A9B2E87D-540F-4B4C-A4AA-EF3BDDC4171C}.Debug|x64.ActiveCfg = Debug|x64 + {A9B2E87D-540F-4B4C-A4AA-EF3BDDC4171C}.Debug|x64.Build.0 = Debug|x64 + {A9B2E87D-540F-4B4C-A4AA-EF3BDDC4171C}.Debug|x86.ActiveCfg = Debug|x86 + {A9B2E87D-540F-4B4C-A4AA-EF3BDDC4171C}.Debug|x86.Build.0 = Debug|x86 + {A9B2E87D-540F-4B4C-A4AA-EF3BDDC4171C}.Release|arm64.ActiveCfg = Release|arm64 + {A9B2E87D-540F-4B4C-A4AA-EF3BDDC4171C}.Release|arm64.Build.0 = Release|arm64 + {A9B2E87D-540F-4B4C-A4AA-EF3BDDC4171C}.Release|x64.ActiveCfg = Release|x64 + {A9B2E87D-540F-4B4C-A4AA-EF3BDDC4171C}.Release|x64.Build.0 = Release|x64 + {A9B2E87D-540F-4B4C-A4AA-EF3BDDC4171C}.Release|x86.ActiveCfg = Release|x86 + {A9B2E87D-540F-4B4C-A4AA-EF3BDDC4171C}.Release|x86.Build.0 = Release|x86 {A382B448-A1F3-4D87-A674-736D2987E613}.Debug_FailFast|arm64.ActiveCfg = Debug_FailFast|ARM64 {A382B448-A1F3-4D87-A674-736D2987E613}.Debug_FailFast|arm64.Build.0 = Debug_FailFast|ARM64 {A382B448-A1F3-4D87-A674-736D2987E613}.Debug_FailFast|x64.ActiveCfg = Debug_FailFast|x64 @@ -1451,6 +1470,7 @@ Global {024CB70C-3449-4204-9171-A25C6C25783D} = {7857275B-7970-4C26-B092-FF62EA890B1E} {567A82BE-7E9E-4D95-AF45-4EE8D57FE16D} = {A972EC5B-FC61-4964-A6FF-F9633EB75DFD} {82BD8133-F1D4-4383-BC4F-12EFAE1AFF91} = {567A82BE-7E9E-4D95-AF45-4EE8D57FE16D} + {A9B2E87D-540F-4B4C-A4AA-EF3BDDC4171C} = {FAB6FAA7-ADF4-4B65-9831-0C819915E6E1} {A382B448-A1F3-4D87-A674-736D2987E613} = {81AB1B86-AE3C-4E5B-8918-CA6CCED95266} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution diff --git a/extensions/HyperVExtension/src/DevSetupAgent/RegistryWatcher.cs b/common/Helpers/RegistryWatcher.cs similarity index 66% rename from extensions/HyperVExtension/src/DevSetupAgent/RegistryWatcher.cs rename to common/Helpers/RegistryWatcher.cs index 023f46ca2..93d63f44c 100644 --- a/extensions/HyperVExtension/src/DevSetupAgent/RegistryWatcher.cs +++ b/common/Helpers/RegistryWatcher.cs @@ -1,134 +1,174 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System.ComponentModel; -using System.Runtime.InteropServices; -using Microsoft.Win32; -using Serilog; -using Windows.Win32; -using Windows.Win32.Foundation; -using Windows.Win32.System.Registry; - -namespace HyperVExtension.DevSetupAgent; - -internal delegate void RegistryChangedEventHandler(); - -/// -/// Registry watcher class. -/// Utilizes RegNotifyChangeKeyValue Win32 API to watch for registry changes. -/// Calls RegistryChangedEventHandler delegate when registry change is detected. -/// -internal sealed class RegistryWatcher : IDisposable -{ - private readonly Serilog.ILogger _log = Log.ForContext("SourceContext", nameof(RegistryWatcher)); - - public event RegistryChangedEventHandler RegistryChanged; - - private readonly AutoResetEvent _waitEvent; - private readonly RegistryKey? _key; - private bool _started; - private bool _disposed; - - public RegistryWatcher(RegistryKey key, string keyPath, RegistryChangedEventHandler callback) - { - _waitEvent = new AutoResetEvent(true); - _key = key.CreateSubKey(keyPath); - if (_key == null) - { - _log.Error($"Cannot open {keyPath} registry key. Error: {Marshal.GetLastWin32Error()}"); - throw new Win32Exception(Marshal.GetLastWin32Error()); - } - - RegistryChanged += callback; - - _log.Information("Registry Watcher created."); - } - - public void Start() - { - lock (this) - { - if (!_started) - { - _started = true; - _waitEvent.Reset(); - Task.Run(() => - { - try - { - while (_started) - { - var notifyFilter = REG_NOTIFY_FILTER.REG_NOTIFY_CHANGE_LAST_SET | - REG_NOTIFY_FILTER.REG_NOTIFY_THREAD_AGNOSTIC; - var result = PInvoke.RegNotifyChangeKeyValue(_key!.Handle, true, notifyFilter, _waitEvent.SafeWaitHandle, true); - if (result != WIN32_ERROR.ERROR_SUCCESS) - { - throw new Win32Exception((int)result); - } - - _waitEvent.WaitOne(); - - if (_started) - { - try - { - RegistryChanged(); - } - catch (Exception ex) - { - _log.Error(ex, "RegistryChanged delegate failed."); - } - } - } - } - catch (Exception ex) - { - _log.Error(ex, "Registry Watcher thread failed."); - } - }); - _log.Information("Registry Watcher thread started."); - } - } - } - - public void Stop() - { - lock (this) - { - if (_started) - { - _started = false; - _waitEvent.Set(); - _log.Information("Registry Watcher thread stopped."); - } - } - } - - public void WaitForRegistryChange() - { - _log.Information("Waiting for registry change."); - _waitEvent.WaitOne(); - _log.Information("Registry change detected."); - RegistryChanged?.Invoke(); - } - - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - private void Dispose(bool disposing) - { - if (!_disposed) - { - if (disposing) - { - _key?.Dispose(); - _waitEvent.Dispose(); - } - - _disposed = true; - } - } -} +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.ComponentModel; +using System.IO; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Win32; +using Serilog; +using Windows.Win32; +using Windows.Win32.Foundation; +using Windows.Win32.System.Registry; + +namespace DevHome.Common; + +[Flags] +public enum RegistryNotifyFilterFlags +{ + SubKeyAddRemove = 0x1, + AttributesChange = 0x2, + ValueChanged = 0x4, + SecurityChanged = 0x8, +} + +public delegate void RegistryChangedEventHandler(); + +/// +/// Registry watcher class. +/// Utilizes RegNotifyChangeKeyValue Win32 API to watch for registry changes. +/// Calls RegistryChangedEventHandler delegate when registry change is detected. +/// +public sealed class RegistryWatcher : IDisposable +{ + private readonly Serilog.ILogger _log = Log.ForContext("SourceContext", nameof(RegistryWatcher)); + + public event RegistryChangedEventHandler RegistryChanged; + + private readonly AutoResetEvent _waitEvent; + private readonly RegistryKey? _key; + private readonly REG_NOTIFY_FILTER _notifyFilter; + private bool _started; + private bool _disposed; + + public RegistryWatcher(RegistryKey key, string keyPath, RegistryChangedEventHandler callback, RegistryNotifyFilterFlags filter = RegistryNotifyFilterFlags.ValueChanged) + { + _notifyFilter = TranslateFlags(filter); + _waitEvent = new AutoResetEvent(true); + + // TODO: Verify with the one other caller, that there wasn't a negative dependency around creating the key unintentionally or having write access. + _key = key.OpenSubKey(keyPath, false); + _key ??= key.CreateSubKey(keyPath); + if (_key == null) + { + _log.Error($"Cannot open {keyPath} registry key. Error: {Marshal.GetLastWin32Error()}"); + throw new Win32Exception(Marshal.GetLastWin32Error()); + } + + RegistryChanged += callback; + + _log.Information("Registry Watcher created."); + } + + private REG_NOTIFY_FILTER TranslateFlags(RegistryNotifyFilterFlags filter) + { + REG_NOTIFY_FILTER result = REG_NOTIFY_FILTER.REG_NOTIFY_THREAD_AGNOSTIC; + + if (filter.HasFlag(RegistryNotifyFilterFlags.SubKeyAddRemove)) + { + result |= REG_NOTIFY_FILTER.REG_NOTIFY_CHANGE_NAME; + } + else if (filter.HasFlag(RegistryNotifyFilterFlags.AttributesChange)) + { + result |= REG_NOTIFY_FILTER.REG_NOTIFY_CHANGE_ATTRIBUTES; + } + else if (filter.HasFlag(RegistryNotifyFilterFlags.ValueChanged)) + { + result |= REG_NOTIFY_FILTER.REG_NOTIFY_CHANGE_LAST_SET; + } + else if (filter.HasFlag(RegistryNotifyFilterFlags.SecurityChanged)) + { + result |= REG_NOTIFY_FILTER.REG_NOTIFY_CHANGE_SECURITY; + } + + return result; + } + + public void Start() + { + lock (this) + { + if (!_started) + { + _started = true; + _waitEvent.Reset(); + Task.Run(() => + { + try + { + while (_started) + { + var result = PInvoke.RegNotifyChangeKeyValue(_key!.Handle, true, _notifyFilter, _waitEvent.SafeWaitHandle, true); + if (result != WIN32_ERROR.ERROR_SUCCESS) + { + throw new Win32Exception((int)result); + } + + _waitEvent.WaitOne(); + + if (_started) + { + try + { + RegistryChanged(); + } + catch (Exception ex) + { + _log.Error(ex, "RegistryChanged delegate failed."); + } + } + } + } + catch (Exception ex) + { + _log.Error(ex, "Registry Watcher thread failed."); + } + }); + _log.Information("Registry Watcher thread started."); + } + } + } + + public void Stop() + { + lock (this) + { + if (_started) + { + _started = false; + _waitEvent.Set(); + _log.Information("Registry Watcher thread stopped."); + } + } + } + + public void WaitForRegistryChange() + { + _log.Information("Waiting for registry change."); + _waitEvent.WaitOne(); + _log.Information("Registry change detected."); + RegistryChanged?.Invoke(); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + private void Dispose(bool disposing) + { + if (!_disposed) + { + if (disposing) + { + _key?.Dispose(); + _waitEvent.Dispose(); + } + + _disposed = true; + } + } +} diff --git a/common/NativeMethods.txt b/common/NativeMethods.txt index 342d73992..2b9af6237 100644 --- a/common/NativeMethods.txt +++ b/common/NativeMethods.txt @@ -21,5 +21,6 @@ GetWindowRect GetMonitorInfo SetWindowPos MonitorFromWindow +RegNotifyChangeKeyValue E_INVALIDARG -TOKEN_ELEVATION_TYPE \ No newline at end of file +TOKEN_ELEVATION_TYPE diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/ThemeAwareWindow.cs b/common/Windows/ThemeAwareWindow.cs similarity index 93% rename from tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/ThemeAwareWindow.cs rename to common/Windows/ThemeAwareWindow.cs index 5880a64db..715d3056f 100644 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/ThemeAwareWindow.cs +++ b/common/Windows/ThemeAwareWindow.cs @@ -13,7 +13,7 @@ using Windows.UI.ViewManagement; using WinUIEx; -namespace DevHome.DevDiagnostics.Controls; +namespace DevHome.Common.Windows; /* This class encapsulates the theme-awareness logic, including support for custom chrome buttons. * The main BarWindow derives from ThemeAwareWindow. All internal tool windows and any other owned windows @@ -39,9 +39,9 @@ public class ThemeAwareWindow : WindowEx private List RelatedWindows { get; set; } = []; - internal List diff --git a/tools/SetupFlow/DevHome.SetupFlow/DevHome.SetupFlow.csproj b/tools/SetupFlow/DevHome.SetupFlow/DevHome.SetupFlow.csproj index a9559150c..adfc2ec10 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/DevHome.SetupFlow.csproj +++ b/tools/SetupFlow/DevHome.SetupFlow/DevHome.SetupFlow.csproj @@ -21,7 +21,6 @@ - Projection diff --git a/tools/SetupFlow/DevHome.SetupFlow/Models/CloneRepoTask.cs b/tools/SetupFlow/DevHome.SetupFlow/Models/CloneRepoTask.cs index 655c1f26b..b097920e1 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/Models/CloneRepoTask.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/Models/CloneRepoTask.cs @@ -13,7 +13,7 @@ using DevHome.Common.Services; using DevHome.Common.TelemetryEvents; using DevHome.Common.TelemetryEvents.SetupFlow; -using DevHome.RepositoryManagement.Services; +using DevHome.Database.Services; using DevHome.SetupFlow.Common.Helpers; using DevHome.SetupFlow.Services; using DevHome.SetupFlow.ViewModels; @@ -288,7 +288,7 @@ IAsyncOperation ISetupTask.Execute() // TODO: Is this the best place to add the repository to the database? // Maybe a "PostExecutionStep" would be nice. _host.GetService() - .AddRepository(RepositoryName, CloneLocation.FullName); + .MakeRepository(RepositoryName, CloneLocation.FullName, RepositoryToClone.RepoUri); } WasCloningSuccessful = true; diff --git a/tools/SetupFlow/DevHome.SetupFlow/Services/ConfigurationFileBuilder.cs b/tools/SetupFlow/DevHome.SetupFlow/Services/ConfigurationFileBuilder.cs index b72df561a..fbbbc864b 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/Services/ConfigurationFileBuilder.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/Services/ConfigurationFileBuilder.cs @@ -3,7 +3,10 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; +using System.Threading.Tasks; +using DevHome.Database.DatabaseModels.RepositoryManagement; using DevHome.SetupFlow.Common.Helpers; using DevHome.SetupFlow.Models; using DevHome.SetupFlow.Models.WingetConfigure; @@ -118,6 +121,38 @@ public string SerializeWingetFileObjectToString(WinGetConfigFile configFile) return configStringWithHeader; } + public string MakeConfigurationFileForRepoAndGit(Repository repository) + { + // WinGet configure uses the Id property to uniquely identify a resource and also to display the resource status in the UI. + // So we add a description to the Id to make it more readable in the UI. These do not need to be localized. + var id = $"{RepoNamePrefix}{repository.RepositoryName}{RepoNameSuffix}{Path.GetFullPath(repository.RepositoryClonePath)}"; + var gitDependsOnId = DscHelpers.GitWinGetPackageId; + + List resources = []; + + resources.Add(new WinGetConfigResource() + { + Resource = DscHelpers.GitCloneDscResource, + Id = id, + Directives = new() { AllowPrerelease = true, Description = $"Cloning: {repository.RepositoryName}" }, + DependsOn = [gitDependsOnId], + Settings = new GitDscSettings() { HttpsUrl = string.Empty, RootDirectory = Path.GetFullPath(repository.RepositoryClonePath) }, + }); + + resources.Add(CreateWinGetInstallForGitPreReq(ConfigurationFileKind.Normal)); + + var wingetConfigProperties = new WinGetConfigProperties(); + + // Merge the resources into the Resources property in the properties object + wingetConfigProperties.Resources = resources.ToArray(); + wingetConfigProperties.ConfigurationVersion = DscHelpers.WinGetConfigureVersion; + + // Create the new WinGetConfigFile object and serialize it to yaml + var configurationFile = new WinGetConfigFile() { Properties = wingetConfigProperties }; + + return SerializeWingetFileObjectToString(configurationFile); + } + /// /// Creates a list of WinGetConfigResource objects from the CloneRepoTask objects in the RepoConfigTaskGroup /// diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/MainPageViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/MainPageViewModel.cs index 829def6e0..918d3aae2 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/MainPageViewModel.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/MainPageViewModel.cs @@ -267,7 +267,7 @@ public void StartSetupForTargetEnvironmentWithTelemetry(string flowTitle, string /// Starts a setup flow that only includes repo config. /// [RelayCommand] - private void StartRepoConfig(string flowTitle) + public void StartRepoConfig(string flowTitle) { _log.Information("Starting flow for repo config"); StartSetupFlowForTaskGroups( diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SetupFlowViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SetupFlowViewModel.cs index 1e8c1937d..295b3138d 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SetupFlowViewModel.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SetupFlowViewModel.cs @@ -29,9 +29,10 @@ public partial class SetupFlowViewModel : ObservableObject private readonly MainPageViewModel _mainPageViewModel; private readonly PackageProvider _packageProvider; - private readonly string _creationFlowNavigationParameter = "StartCreationFlow"; private readonly string _configurationFlowNavigationParameter = "StartConfigurationFlow"; - private readonly string _quickstartNavigationParameter = "StartQuickstartPlayground"; + private readonly string _creationFlowNavigationParameter = "StartCreationFlow"; + + private readonly Dictionary> _navigationTargets = new(); public SetupFlowOrchestrator Orchestrator { get; } @@ -43,6 +44,10 @@ public SetupFlowViewModel( SetupFlowOrchestrator orchestrator, PackageProvider packageProvider) { + _navigationTargets.Add(_creationFlowNavigationParameter, StartCreationFlow); + _navigationTargets.Add("StartQuickstartPlayground", StartQuickStartFlow); + _navigationTargets.Add(KnownPageKeys.RepositoryConfiguration, StartRepositoryConfigurationFlow); + _host = host; _stringResource = stringResource; Orchestrator = orchestrator; @@ -135,14 +140,6 @@ public async Task StartFileActivationFlowAsync(StorageFile file) await _mainPageViewModel.StartConfigurationFileAsync(file); } - public void StartCreationFlow(string originPage) - { - Orchestrator.FlowPages = [_mainPageViewModel]; - - // This method is only called when the user clicks a button that redirects them to 'Create Environment' flow in the setup flow. - _mainPageViewModel.StartCreateEnvironmentWithTelemetry(string.Empty, _creationFlowNavigationParameter, originPage); - } - public void StartSetupFlow(string originPage, ComputeSystemReviewItem item) { Orchestrator.FlowPages = [_mainPageViewModel]; @@ -155,38 +152,43 @@ public void OnNavigatedTo(NavigationEventArgs args) { // The setup flow isn't set up to support using the navigation service to navigate to specific // pages. Instead we need to navigate to the main page and then start the creation flow template manually. - var parameter = args.Parameter?.ToString(); + var parameter = args.Parameter?.ToString() ?? string.Empty; - if ((!string.IsNullOrEmpty(parameter)) && - parameter.Contains(_creationFlowNavigationParameter, StringComparison.OrdinalIgnoreCase)) + if (string.IsNullOrEmpty(parameter)) { - // We expect that when navigating from anywhere in Dev Home to the create environment page - // that the arg.Parameter variable be semicolon delimited string with the first value being 'StartCreationFlow' - // and the second value being the page name that redirection came from for telemetry purposes. - var parameters = parameter.Split(';'); - Cancel(); - StartCreationFlow(originPage: parameters[1]); + _log.Information("args.Parameters is either null or empty. Not navigating"); + return; } - else if ((!string.IsNullOrEmpty(parameter)) && - parameter.Contains(_quickstartNavigationParameter, StringComparison.OrdinalIgnoreCase)) + + var didNavigate = false; + var actionPair = _navigationTargets.FirstOrDefault(x => parameter.Contains(x.Key, StringComparison.OrdinalIgnoreCase), default); + if (actionPair.Key != default) { - Cancel(); - Orchestrator.FlowPages = [_mainPageViewModel]; - var flowTitle = _stringResource.GetLocalized("MainPage_QuickstartPlayground/Header"); - _mainPageViewModel.StartQuickstart(flowTitle); + didNavigate = true; + actionPair.Value(parameter); } - else if (args.Parameter is object[] configObjs && configObjs.Length == 3) + else { - if (configObjs[0] is string configObj && configObj.Equals(_configurationFlowNavigationParameter, StringComparison.OrdinalIgnoreCase)) + if (args.Parameter is object[] configObjs && configObjs.Length == 3) { - // We expect that when navigating from anywhere in Dev Home to the create environment page - // that the arg.Parameter variable be an object array with the the first value being 'StartCreationFlow', - // the second value being the page name that redirection came from for telemetry purposes, and - // the third value being the ComputeSystemReviewItem to setup. - Cancel(); - StartSetupFlow(originPage: configObjs[1] as string, item: configObjs[2] as ComputeSystemReviewItem); + if (configObjs[0] is string configObj && configObj.Equals(_configurationFlowNavigationParameter, StringComparison.OrdinalIgnoreCase)) + { + didNavigate = true; + + // We expect that when navigating from anywhere in Dev Home to the create environment page + // that the arg.Parameter variable be an object array with the the first value being 'StartCreationFlow', + // the second value being the page name that redirection came from for telemetry purposes, and + // the third value being the ComputeSystemReviewItem to setup. + Cancel(); + StartSetupFlow(originPage: configObjs[1] as string, item: configObjs[2] as ComputeSystemReviewItem); + } } } + + if (!didNavigate) + { + _log.Warning($"Did not navigate with args {parameter}"); + } } public void StartAppManagementFlow(string query = null) @@ -194,4 +196,33 @@ public void StartAppManagementFlow(string query = null) Orchestrator.FlowPages = [_mainPageViewModel]; _mainPageViewModel.StartAppManagementFlow(query); } + + private void StartCreationFlow(string parameter) + { + // We expect that when navigating from anywhere in Dev Home to the create environment page + // that the arg.Parameter variable be semicolon delimited string with the first value being 'StartCreationFlow' + // and the second value being the page name that redirection came from for telemetry purposes. + var parameters = parameter.Split(';'); + Cancel(); + + Orchestrator.FlowPages = [_mainPageViewModel]; + + // This method is only called when the user clicks a button that redirects them to 'Create Environment' flow in the setup flow. + _mainPageViewModel.StartCreateEnvironmentWithTelemetry(string.Empty, _creationFlowNavigationParameter, parameters[1]); + } + + private void StartQuickStartFlow(string parameter) + { + Cancel(); + Orchestrator.FlowPages = [_mainPageViewModel]; + var flowTitle = _stringResource.GetLocalized("MainPage_QuickstartPlayground/Header"); + _mainPageViewModel.StartQuickstart(flowTitle); + } + + private void StartRepositoryConfigurationFlow(string parameter) + { + Cancel(); + Orchestrator.FlowPages = [_mainPageViewModel]; + _mainPageViewModel.StartRepoConfig(_stringResource.GetLocalized("ReposConfigPageTitle")); + } } From 9754d3f4505695f1af492a97232a931a377d47bf Mon Sep 17 00:00:00 2001 From: Branden Bonaby <105318831+bbonaby@users.noreply.github.com> Date: Fri, 20 Sep 2024 16:46:40 -0700 Subject: [PATCH 15/58] update summary page (#3837) --- src/App.xaml | 1 + src/DevHome.csproj | 4 ++++ src/Styles/HyperlinkButton.xaml | 20 +++++++++++++++++++ .../Views/Summary/SummaryNextSteps.xaml | 17 ++++++++-------- 4 files changed, 34 insertions(+), 8 deletions(-) create mode 100644 src/Styles/HyperlinkButton.xaml diff --git a/src/App.xaml b/src/App.xaml index d60987bf6..4f717c3bd 100644 --- a/src/App.xaml +++ b/src/App.xaml @@ -10,6 +10,7 @@ + diff --git a/src/DevHome.csproj b/src/DevHome.csproj index 2796c59df..222676547 100644 --- a/src/DevHome.csproj +++ b/src/DevHome.csproj @@ -61,6 +61,7 @@ + @@ -123,6 +124,9 @@ Always + + MSBuild:Compile + MSBuild:Compile diff --git a/src/Styles/HyperlinkButton.xaml b/src/Styles/HyperlinkButton.xaml new file mode 100644 index 000000000..99f0571be --- /dev/null +++ b/src/Styles/HyperlinkButton.xaml @@ -0,0 +1,20 @@ + + + + + diff --git a/tools/SetupFlow/DevHome.SetupFlow/Views/Summary/SummaryNextSteps.xaml b/tools/SetupFlow/DevHome.SetupFlow/Views/Summary/SummaryNextSteps.xaml index 4f6ccd335..1c042c60b 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/Views/Summary/SummaryNextSteps.xaml +++ b/tools/SetupFlow/DevHome.SetupFlow/Views/Summary/SummaryNextSteps.xaml @@ -48,9 +48,6 @@ Grid.Row="1" IsTabStop="false" XYFocusKeyboardNavigation="Enabled"> - - + + + + + + + + + + + + + + + + + + + + @@ -55,28 +106,25 @@ - - - - - diff --git a/tools/RepositoryManagement/DevHome.RepositoryManagement/Views/RepositoryManagementMainPageView.xaml.cs b/tools/RepositoryManagement/DevHome.RepositoryManagement/Views/RepositoryManagementMainPageView.xaml.cs index c1f20c584..f27d0fbd8 100644 --- a/tools/RepositoryManagement/DevHome.RepositoryManagement/Views/RepositoryManagementMainPageView.xaml.cs +++ b/tools/RepositoryManagement/DevHome.RepositoryManagement/Views/RepositoryManagementMainPageView.xaml.cs @@ -5,6 +5,8 @@ using DevHome.Common.Views; using DevHome.RepositoryManagement.ViewModels; using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using Microsoft.Windows.DevHome.SDK; namespace DevHome.RepositoryManagement.Views; diff --git a/tools/SetupFlow/DevHome.SetupFlow.Common/DevHome.SetupFlow.Common.csproj b/tools/SetupFlow/DevHome.SetupFlow.Common/DevHome.SetupFlow.Common.csproj index 1199e9bc6..3c42c58c8 100644 --- a/tools/SetupFlow/DevHome.SetupFlow.Common/DevHome.SetupFlow.Common.csproj +++ b/tools/SetupFlow/DevHome.SetupFlow.Common/DevHome.SetupFlow.Common.csproj @@ -15,6 +15,7 @@ all runtime; build; native; contentfiles; analyzers + diff --git a/tools/SetupFlow/DevHome.SetupFlow.Common/Helpers/DscHelpers.cs b/tools/SetupFlow/DevHome.SetupFlow.Common/Helpers/DscHelpers.cs index ed255d617..ac383c518 100644 --- a/tools/SetupFlow/DevHome.SetupFlow.Common/Helpers/DscHelpers.cs +++ b/tools/SetupFlow/DevHome.SetupFlow.Common/Helpers/DscHelpers.cs @@ -1,6 +1,10 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +using System; +using System.IO; +using System.Linq; + namespace DevHome.SetupFlow.Common.Helpers; /// @@ -30,5 +34,31 @@ public static class DscHelpers public const string ConfigurationFileYamlExtension = ".dsc.yaml"; - public const string ConfigurationFileWingetExtension = ".winget"; + public const string ConfigurationFileWingetExtension = ".winget"; + + /// + /// Enumerates all files inside the of a repository + /// and returns the most recently modified configuration file. + /// + /// The path to the root of a repository. + /// Path to the configuration file. String.Empty in all other cases. + public static string GetConfigurationFileIfExists(string repositoryRoot) + { + var configurationDirectory = Path.Join(repositoryRoot, ConfigurationFolderName); + if (Directory.Exists(configurationDirectory)) + { + var fileToUse = Directory.EnumerateFiles(configurationDirectory) + .Where(file => file.EndsWith(ConfigurationFileYamlExtension, StringComparison.OrdinalIgnoreCase) || + file.EndsWith(ConfigurationFileWingetExtension, StringComparison.OrdinalIgnoreCase)) + .OrderByDescending(configurationFile => File.GetLastWriteTime(configurationFile)) + .FirstOrDefault(); + + if (fileToUse != default) + { + return fileToUse; + } + } + + return string.Empty; + } } diff --git a/tools/SetupFlow/DevHome.SetupFlow/Models/CloneRepoTask.cs b/tools/SetupFlow/DevHome.SetupFlow/Models/CloneRepoTask.cs index b097920e1..e6c4a69f9 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/Models/CloneRepoTask.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/Models/CloneRepoTask.cs @@ -12,6 +12,7 @@ using DevHome.Common.Extensions; using DevHome.Common.Services; using DevHome.Common.TelemetryEvents; +using DevHome.Common.TelemetryEvents.RepositoryManagement; using DevHome.Common.TelemetryEvents.SetupFlow; using DevHome.Database.Services; using DevHome.SetupFlow.Common.Helpers; @@ -45,6 +46,8 @@ public partial class CloneRepoTask : ObservableObject, ISetupTask private readonly IRepositoryProvider _repositoryProvider; + private readonly RepositoryManagementDataAccessService _dataAccessService; + public DirectoryInfo CloneLocation => _cloneLocation; /// @@ -173,6 +176,7 @@ public CloneRepoTask( _activityId = activityId; _host = host; _summaryScreenInformation = new CloneRepoSummaryInformationViewModel(host.GetService(), stringResource); + _dataAccessService = _host.GetService(); } /// @@ -181,7 +185,14 @@ public CloneRepoTask( /// /// Repository will be placed here, at _cloneLocation.FullName /// The repository to clone - public CloneRepoTask(IRepositoryProvider repositoryProvider, DirectoryInfo cloneLocation, IRepository repositoryToClone, ISetupFlowStringResource stringResource, string providerName, Guid activityId, IHost host) + public CloneRepoTask( + IRepositoryProvider repositoryProvider, + DirectoryInfo cloneLocation, + IRepository repositoryToClone, + ISetupFlowStringResource stringResource, + string providerName, + Guid activityId, + IHost host) { _cloneLocation = cloneLocation; this.RepositoryToClone = repositoryToClone; @@ -193,6 +204,7 @@ public CloneRepoTask(IRepositoryProvider repositoryProvider, DirectoryInfo clone _activityId = activityId; _host = host; _summaryScreenInformation = new CloneRepoSummaryInformationViewModel(host.GetService(), stringResource); + _dataAccessService = _host.GetService(); } private void SetMessages(IStringResource stringResource) @@ -263,21 +275,12 @@ IAsyncOperation ISetupTask.Execute() } // Search for a configuration file. - var configurationDirectory = Path.Join(_cloneLocation.FullName, DscHelpers.ConfigurationFolderName); - if (Directory.Exists(configurationDirectory)) + var configurationFile = DscHelpers.GetConfigurationFileIfExists(_cloneLocation.FullName); + if (!configurationFile.Equals(string.Empty, StringComparison.OrdinalIgnoreCase)) { - var fileToUse = Directory.EnumerateFiles(configurationDirectory) - .Where(file => file.EndsWith(DscHelpers.ConfigurationFileYamlExtension, StringComparison.OrdinalIgnoreCase) || - file.EndsWith(DscHelpers.ConfigurationFileWingetExtension, StringComparison.OrdinalIgnoreCase)) - .OrderByDescending(configurationFile => File.GetLastWriteTime(configurationFile)) - .FirstOrDefault(); - - if (fileToUse != null) - { - _summaryScreenInformation.FilePathAndName = fileToUse; - _summaryScreenInformation.RepoName = RepositoryName; - _summaryScreenInformation.OwningAccount = RepositoryToClone.OwningAccountName ?? string.Empty; - } + _summaryScreenInformation.FilePathAndName = configurationFile; + _summaryScreenInformation.RepoName = RepositoryName; + _summaryScreenInformation.OwningAccount = RepositoryToClone.OwningAccountName ?? string.Empty; } var experimentationService = _host.GetService(); @@ -287,8 +290,7 @@ IAsyncOperation ISetupTask.Execute() { // TODO: Is this the best place to add the repository to the database? // Maybe a "PostExecutionStep" would be nice. - _host.GetService() - .MakeRepository(RepositoryName, CloneLocation.FullName, RepositoryToClone.RepoUri); + var repository = _dataAccessService.MakeRepository(RepositoryName, CloneLocation.FullName, _summaryScreenInformation.FilePathAndName, RepositoryToClone.RepoUri.ToString()); } WasCloningSuccessful = true; From 98d867c2fa6e75edd66d862cb5854470e150ad36 Mon Sep 17 00:00:00 2001 From: Huzaifa Danish Date: Thu, 3 Oct 2024 10:00:55 -0700 Subject: [PATCH 32/58] [Environments] Increased timeout for configuration (#3891) * Incresed timeout * Fixed sorting * Fixed pinning UI * Changed shimmer size * Revert "Fixed pinning UI" This reverts commit 8fc990864ae36038a2276af080360429638fc3ee. * Remove creep change * String comparison simplification * Simplified conditional check --------- Co-authored-by: Huzaifa Danish --- .../Environments/Styles/HorizontalCardStyles.xaml | 14 +++++++------- .../ViewModels/LandingPageViewModel.cs | 3 +-- .../Models/ConfigureTargetTask.cs | 4 ++-- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/common/Environments/Styles/HorizontalCardStyles.xaml b/common/Environments/Styles/HorizontalCardStyles.xaml index 7023eebdc..254211b36 100644 --- a/common/Environments/Styles/HorizontalCardStyles.xaml +++ b/common/Environments/Styles/HorizontalCardStyles.xaml @@ -239,12 +239,12 @@ - diff --git a/tools/Environments/DevHome.Environments/ViewModels/LandingPageViewModel.cs b/tools/Environments/DevHome.Environments/ViewModels/LandingPageViewModel.cs index 6972b7bb7..1dd0ba0b0 100644 --- a/tools/Environments/DevHome.Environments/ViewModels/LandingPageViewModel.cs +++ b/tools/Environments/DevHome.Environments/ViewModels/LandingPageViewModel.cs @@ -415,8 +415,7 @@ public void SearchHandler(string query) if (system is ComputeSystemViewModel computeSystemViewModel) { - var providerName = computeSystemViewModel.ProviderDisplayName; - if (providerName != _selectedProvider) + if (_selectedProvider.Length > 0 && computeSystemViewModel.ProviderDisplayName != _selectedProvider) { return false; } diff --git a/tools/SetupFlow/DevHome.SetupFlow/Models/ConfigureTargetTask.cs b/tools/SetupFlow/DevHome.SetupFlow/Models/ConfigureTargetTask.cs index 2de0a97be..4a00fd3cb 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/Models/ConfigureTargetTask.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/Models/ConfigureTargetTask.cs @@ -411,12 +411,12 @@ public IAsyncOperation Execute() applyConfigurationOperation.ConfigurationSetStateChanged += OnApplyConfigurationOperationChanged; applyConfigurationOperation.ActionRequired += OnActionRequired; - // We'll cancel the operation after 10 minutes. This is arbitrary for now and will need to be adjusted in the future. + // We'll cancel the operation after 30 minutes. This is arbitrary for now and will need to be adjusted in the future. // but we'll need to give the user the ability to cancel the operation in the UI as well. This is just a safety net. // More work is needed to give the user the ability to cancel the operation as the capability is not currently available. // in the UI of Dev Home's Loading page. var tokenSource = new CancellationTokenSource(); - tokenSource.CancelAfter(TimeSpan.FromMinutes(10)); + tokenSource.CancelAfter(TimeSpan.FromMinutes(30)); ApplyConfigurationAsyncOperation = applyConfigurationOperation.StartAsync(); var result = await ApplyConfigurationAsyncOperation.AsTask().WaitAsync(tokenSource.Token); From c6bbd93ac76879910f2f377739ca1af312624815 Mon Sep 17 00:00:00 2001 From: Benjamin Whelan <83029234+dainank@users.noreply.github.com> Date: Thu, 3 Oct 2024 19:03:53 +0200 Subject: [PATCH 33/58] Outdated links to filtered issues on the Contribution.md file (#3919) --- CONTRIBUTING.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 82f9d2c7e..31ea77677 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -101,7 +101,7 @@ If you don't have any additional info/context to add but would like to indicate If you're able & willing to help fix issues and/or implement features, we'd love your contribution! -The best place to start is the list of ["good first issue"](https://github.com/microsoft/devhome/issues?q=is%3Aopen+is%3Aissue+label%3A%22Help+Wanted%22++label%3A%22good+first+issue%22+)s. These are bugs or tasks that we on the team believe would be easier to implement for someone without any prior experience in the codebase. Once you're feeling more comfortable in the codebase, feel free to just use the ["Help Wanted"](https://github.com/microsoft/devhome/issues?q=is%3Aopen+is%3Aissue+label%3A%22Help+Wanted%22+) label, or just find an issue you're interested in and hop in! +The best place to start is the list of ["good first issue"](https://github.com/microsoft/devhome/issues?q=is%3Aopen+is%3Aissue+label%3A%22Help-Wanted%22++label%3A%22good-first-issue%22+)s. These are bugs or tasks that we on the team believe would be easier to implement for someone without any prior experience in the codebase. Once you're feeling more comfortable in the codebase, feel free to just use the ["Help Wanted"](https://github.com/microsoft/devhome/issues?q=is%3Aopen+is%3Aissue+label%3A%22Help-Wanted%22+) label, or just find an issue you're interested in and hop in! Generally, we categorize issues in the following way, which is largely derived from our old internal work tracking system: * ["Bugs"](https://github.com/microsoft/devhome/issues?q=is%3Aopen+is%3Aissue+label%3A%22Issue-Bug%22+) are parts of Dev Home that are not quite working the right way. There's code to already support some scenario, but it's not quite working right. Fixing these is generally a matter of debugging the broken functionality and fixing the wrong code. @@ -146,7 +146,7 @@ Team members will be happy to help review specs and guide them to completion. ### Help wanted -Once the team has approved an issue/spec, development can proceed. If no developers are immediately available, the spec can be parked ready for a developer to get started. Parked specs' issues will be labeled "Help Wanted". To find a list of development opportunities waiting for developer involvement, visit the Issues and filter on [the Help-Wanted label](https://github.com/microsoft/devhome/labels/Help%20Wanted). +Once the team has approved an issue/spec, development can proceed. If no developers are immediately available, the spec can be parked ready for a developer to get started. Parked specs' issues will be labeled "Help Wanted". To find a list of development opportunities waiting for developer involvement, visit the Issues and filter on [the Help-Wanted label](https://github.com/microsoft/devhome/labels/Help-Wanted). --- @@ -206,4 +206,4 @@ Once your code has been reviewed and approved by the requisite number of team me ## Thank you -Thank you in advance for your contribution! Now, [what's next on the list](https://github.com/microsoft/devhome/labels/Help%20Wanted)? 😜 +Thank you in advance for your contribution! Now, [what's next on the list](https://github.com/microsoft/devhome/labels/Help-Wanted)? 😜 From 70b3d8374616ee5f4aa8830bd16a34c72017e40b Mon Sep 17 00:00:00 2001 From: Branden Bonaby <105318831+bbonaby@users.noreply.github.com> Date: Thu, 3 Oct 2024 10:08:30 -0700 Subject: [PATCH 34/58] Fix multi user extension login for setup environment and create environment flows (#3907) * Fix multi user login for setup target and create environment flows * update based on comments. Removes Add/Remove event handlers and instead used the weak event listener --- .../DevHomeChoiceSetWithDynamicRefresh.cs | 26 +-- .../Assets/DarkHostConfig.json | 2 +- .../Assets/LightHostConfig.json | 2 +- .../CreationStateKindToVisibilityConverter.cs | 57 +++++++ .../Strings/en-us/Resources.resw | 8 + .../Utilities/DevDriveUtil.cs | 4 +- .../ComputeSystemCardViewModel.cs | 7 +- .../ComputeSystemsListViewModel.cs | 21 ++- .../EnvironmentCreationOptionsViewModel.cs | 156 ++++++++++++------ .../ViewModels/SetupTargetViewModel.cs | 82 ++++----- .../EnvironmentCreationOptionsView.xaml | 67 +++++++- 11 files changed, 304 insertions(+), 128 deletions(-) create mode 100644 tools/SetupFlow/DevHome.SetupFlow/Converters/CreationStateKindToVisibilityConverter.cs diff --git a/common/Renderers/DevHomeChoiceSetWithDynamicRefresh.cs b/common/Renderers/DevHomeChoiceSetWithDynamicRefresh.cs index f320e8480..e0b52398b 100644 --- a/common/Renderers/DevHomeChoiceSetWithDynamicRefresh.cs +++ b/common/Renderers/DevHomeChoiceSetWithDynamicRefresh.cs @@ -5,6 +5,7 @@ using System.Text.Json; using AdaptiveCards.ObjectModel.WinUI3; using AdaptiveCards.Rendering.WinUI3; +using CommunityToolkit.WinUI.Helpers; using DevHome.Common.DevHomeAdaptiveCards.CardModels; using DevHome.Common.DevHomeAdaptiveCards.InputValues; using Microsoft.UI.Xaml; @@ -85,9 +86,14 @@ private Grid SetupParentComboBoxForDynamicRefresh(AdaptiveChoiceSetInput choiceS comboBox.ItemsSource = listOfComboBoxItems; comboBox.SelectedIndex = int.TryParse(choiceSet.Value, out var selectedIndex) ? selectedIndex : UnSelectedIndex; - // Setup event handlers - comboBox.SelectionChanged += RefreshCardOnSelectionChanged; - comboBox.Unloaded += RemoveEventHandler; + // Setup selection changed weak event handler + var selectionChangedWeakRef = new WeakEventListener(comboBox) + { + OnEventAction = (instance, source, args) => RefreshCardOnSelectionChanged(instance, args), + OnDetachAction = (weakEventListener) => comboBox.SelectionChanged -= weakEventListener.OnEvent, + }; + + comboBox.SelectionChanged += selectionChangedWeakRef.OnEvent; // Use the choiceSets Id as the name of the combo box. comboBox.Name = choiceSet.Id; @@ -224,20 +230,6 @@ private void RefreshCardOnSelectionChanged(object sender, SelectionChangedEventA } } - private void RemoveEventHandler(object sender, object args) - { - if (sender is ComboBox parentComboBox) - { - parentComboBox.SelectionChanged -= RefreshCardOnSelectionChanged; - parentComboBox.Unloaded -= RemoveEventHandler; - _childChoiceSetDataForOnParentSelectionChanged.Remove(parentComboBox); - if (_choiceSetParentIdToChildIdMap.TryGetValue(parentComboBox.Name, out var childComboBoxId)) - { - _choiceSetIdToUIElementMap.Remove(childComboBoxId); - } - } - } - private void UpdateComboBoxWithDynamicData(ComboBox parentComboBox, ComboBox childComboBox) { _childChoiceSetDataForOnParentSelectionChanged.TryGetValue(parentComboBox, out var newDataForChildComboBox); diff --git a/settings/DevHome.Settings/Assets/DarkHostConfig.json b/settings/DevHome.Settings/Assets/DarkHostConfig.json index a3a18d106..a5c39a22f 100644 --- a/settings/DevHome.Settings/Assets/DarkHostConfig.json +++ b/settings/DevHome.Settings/Assets/DarkHostConfig.json @@ -4,7 +4,7 @@ "fontFamily": "'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif", "fontSizes": { "small": 12, - "default": 12, + "default": 14, "medium": 14, "large": 18, "extraLarge": 26 diff --git a/settings/DevHome.Settings/Assets/LightHostConfig.json b/settings/DevHome.Settings/Assets/LightHostConfig.json index 28841b433..5f01cdfe8 100644 --- a/settings/DevHome.Settings/Assets/LightHostConfig.json +++ b/settings/DevHome.Settings/Assets/LightHostConfig.json @@ -4,7 +4,7 @@ "fontFamily": "'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif", "fontSizes": { "small": 12, - "default": 12, + "default": 14, "medium": 14, "large": 18, "extraLarge": 26 diff --git a/tools/SetupFlow/DevHome.SetupFlow/Converters/CreationStateKindToVisibilityConverter.cs b/tools/SetupFlow/DevHome.SetupFlow/Converters/CreationStateKindToVisibilityConverter.cs new file mode 100644 index 000000000..c0d3bb52b --- /dev/null +++ b/tools/SetupFlow/DevHome.SetupFlow/Converters/CreationStateKindToVisibilityConverter.cs @@ -0,0 +1,57 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using DevHome.Common.Environments.Models; +using DevHome.SetupFlow.ViewModels.Environments; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Data; +using Microsoft.UI.Xaml.Media; + +namespace DevHome.SetupFlow.Converters; + +/// +/// Converts the state of the EnvironmentCreationOptions page to a visibility enum. +/// +public class CreationStateKindToVisibilityConverter : IValueConverter +{ + private const string ProgressRingGridName = "ProgressRingGrid"; + + private const string AdaptiveCardGridName = "AdaptiveCardGrid"; + + public object Convert(object value, Type targetType, object parameter, string language) + { + var parameterString = (string)parameter; + var creationStateKind = (CreationPageStateKind)value; + + if (parameterString.Equals(AdaptiveCardGridName, StringComparison.Ordinal)) + { + return creationStateKind switch + { + CreationPageStateKind.InitialPageAdaptiveCardLoaded => Visibility.Visible, + _ => Visibility.Collapsed, + }; + } + + if (parameterString.Equals(ProgressRingGridName, StringComparison.Ordinal)) + { + return creationStateKind switch + { + CreationPageStateKind.InitialPageAdaptiveCardLoading => Visibility.Visible, + CreationPageStateKind.OtherPageAdaptiveCardLoading => Visibility.Visible, + _ => Visibility.Collapsed, + }; + } + + return Visibility.Collapsed; + } + + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + throw new NotImplementedException(); + } +} diff --git a/tools/SetupFlow/DevHome.SetupFlow/Strings/en-us/Resources.resw b/tools/SetupFlow/DevHome.SetupFlow/Strings/en-us/Resources.resw index 1cf7dcdc5..c841bfdcf 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/Strings/en-us/Resources.resw +++ b/tools/SetupFlow/DevHome.SetupFlow/Strings/en-us/Resources.resw @@ -1820,6 +1820,10 @@ There was an error loading the data required to create {0} environments Locked={"{0}"} Error text display when we are unable to retrieve the creation data for a Dev Home provider. {0} is the name of the provider + + There was an error loading {0} environments for '{1}'. + Locked={"{0}", "{1}"} Error text to display when a Dev Home provider returns an error when returning environments for a specific user. {0} is the name of the provider and {1} is the users logon Id. + Environment Title for create environment review tab @@ -2035,4 +2039,8 @@ Please check your network settings and try again. Text displayed when there is no internet connection + + Select an account + Header text for combo box where the user can select an account + \ No newline at end of file diff --git a/tools/SetupFlow/DevHome.SetupFlow/Utilities/DevDriveUtil.cs b/tools/SetupFlow/DevHome.SetupFlow/Utilities/DevDriveUtil.cs index 474a5c1c5..da9265f68 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/Utilities/DevDriveUtil.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/Utilities/DevDriveUtil.cs @@ -6,11 +6,11 @@ using System.IO; using System.Linq; using System.Runtime.InteropServices; -using CommunityToolkit.Common; using Serilog; using Windows.Win32; using Windows.Win32.Foundation; using Windows.Win32.UI.Shell; +using static CommunityToolkit.Common.Converters; namespace DevHome.SetupFlow.Utilities; @@ -269,7 +269,7 @@ public static string ConvertBytesToString(ulong sizeInBytes) if (result != 0) { // fallback to using community toolkit which shows this unlocalized. In the form of 50 GB, 40 TB etc. - return Converters.ToFileSizeString((long)sizeInBytes); + return ToFileSizeString((long)sizeInBytes); } else { diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/Environments/ComputeSystemCardViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/Environments/ComputeSystemCardViewModel.cs index 82eaf9ba3..9784a8c87 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/Environments/ComputeSystemCardViewModel.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/Environments/ComputeSystemCardViewModel.cs @@ -72,7 +72,12 @@ public ComputeSystemCardViewModel(ComputeSystemCache computeSystem, IComputeSyst _dispatcherQueue = dispatcherQueue; _computeSystemManager = manager; ComputeSystemTitle = computeSystem.DisplayName.Value; - ComputeSystemAlternativeTitle = computeSystem.SupplementalDisplayName.Value; + + if (!string.IsNullOrEmpty(computeSystem.SupplementalDisplayName.Value)) + { + ComputeSystemAlternativeTitle = $"({computeSystem.SupplementalDisplayName.Value})"; + } + ComputeSystem = computeSystem; ComputeSystem.StateChanged += _computeSystemManager.OnComputeSystemStateChanged; _computeSystemManager.ComputeSystemStateChanged += OnComputeSystemStateChanged; diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/Environments/ComputeSystemsListViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/Environments/ComputeSystemsListViewModel.cs index 33d26bda4..4877db56c 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/Environments/ComputeSystemsListViewModel.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/Environments/ComputeSystemsListViewModel.cs @@ -48,8 +48,6 @@ public partial class ComputeSystemsListViewModel : ObservableObject public AdvancedCollectionView ComputeSystemCardAdvancedCollectionView { get; private set; } - public Dictionary DevIdToComputeSystemMap { get; set; } - public ComputeSystemProvider Provider { get; set; } public DeveloperIdWrapper CurrentDeveloperId { get; set; } @@ -101,21 +99,22 @@ public override string ToString() return AccessibilityName; } - public ComputeSystemsListViewModel(ComputeSystemsLoadedData loadedData) + public ComputeSystemsListViewModel( + ComputeSystemProviderDetails providerDetails, + KeyValuePair devIdComputeSystemPair) { - Provider = loadedData.ProviderDetails.ComputeSystemProvider; - DevIdToComputeSystemMap = loadedData.DevIdToComputeSystemMap; - - // Get the first developerId and compute system result. - var devIdToResultKeyValuePair = DevIdToComputeSystemMap.FirstOrDefault(); - CurrentResult = devIdToResultKeyValuePair.Value; - CurrentDeveloperId = devIdToResultKeyValuePair.Key; + Provider = providerDetails.ComputeSystemProvider; + CurrentResult = devIdComputeSystemPair.Value; + CurrentDeveloperId = devIdComputeSystemPair.Key; DisplayName = Provider.DisplayName; if ((CurrentResult != null) && (CurrentResult.ComputeSystems != null)) { - ComputeSystems = CurrentResult.ComputeSystems.Select(computeSystem => new ComputeSystemCache(computeSystem)).ToList(); + // Filter out compute systems that do not support configuration. + ComputeSystems = CurrentResult.ComputeSystems + .Where(computeSystem => computeSystem.SupportedOperations.HasFlag(ComputeSystemOperations.ApplyConfiguration)) + .Select(computeSystem => new ComputeSystemCache(computeSystem)).ToList(); } // Create a new AdvancedCollectionView for the ComputeSystemCards collection. diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/Environments/EnvironmentCreationOptionsViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/Environments/EnvironmentCreationOptionsViewModel.cs index 8091d1416..c0b8f6339 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/Environments/EnvironmentCreationOptionsViewModel.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/Environments/EnvironmentCreationOptionsViewModel.cs @@ -2,6 +2,8 @@ // Licensed under the MIT License. using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Linq; using System.Threading.Tasks; using AdaptiveCards.ObjectModel.WinUI3; @@ -19,11 +21,22 @@ using DevHome.SetupFlow.Models.Environments; using DevHome.SetupFlow.Services; using Microsoft.UI.Dispatching; +using Microsoft.UI.Xaml; using Microsoft.Windows.DevHome.SDK; using Serilog; namespace DevHome.SetupFlow.ViewModels.Environments; +public enum CreationPageStateKind +{ + AccountSelection, + InitialPageAdaptiveCardError, + InitialPageAdaptiveCardLoaded, + InitialPageAdaptiveCardLoading, + OtherPageAdaptiveCardLoading, + OtherPageAdaptiveCardLoaded, +} + /// /// View model for the Configure Environment page in the setup flow. This page will display an adaptive card that is provided by the selected /// compute system provider. The adaptive card will be display in the middle of the page and will contain compute system provider specific UI @@ -43,7 +56,7 @@ public partial class EnvironmentCreationOptionsViewModel : SetupPageViewModelBas private readonly SetupFlowViewModel _setupFlowViewModel; - private readonly IStringResource _stringResource; + private readonly IStringResource _stringResource; private ComputeSystemProviderDetails _curProviderDetails; @@ -59,17 +72,22 @@ public partial class EnvironmentCreationOptionsViewModel : SetupPageViewModelBas private AdaptiveInputs _userInputsFromAdaptiveCard; - private bool _isFirstTimeLoadingNewFlow; + [ObservableProperty] + private string _sessionErrorMessage; + [ObservableProperty] + private string _sessionErrorTitle; + + [NotifyPropertyChangedFor(nameof(DeveloperIdWrappers))] [NotifyCanExecuteChangedFor(nameof(GoToNextPageCommand))] [ObservableProperty] - private bool _isAdaptiveCardSessionLoaded; + private CreationPageStateKind _creationPageState; [ObservableProperty] - private string _sessionErrorMessage; + private ObservableCollection _developerIdWrappers = new(); [ObservableProperty] - private string _sessionErrorTitle; + private DeveloperIdWrapper _selectedDeveloperId; [ObservableProperty] private string _adaptiveCardLoadingMessage; @@ -105,7 +123,6 @@ public EnvironmentCreationOptionsViewModel( _elementRegistration.Set(DevHomeContentDialogContent.AdaptiveElementType, new DevHomeContentDialogContentParser()); _adaptiveCardRenderingService = renderingService; Orchestrator.CurrentSetupFlowKind = SetupFlowKind.CreateEnvironment; - _isFirstTimeLoadingNewFlow = true; } /// @@ -139,11 +156,13 @@ protected async override Task OnFirstNavigateToAsync() /// protected async override Task OnEachNavigateToAsync() { + ResetErrorUI(); + // Don't get a new adaptive card session if we went from review page back to // configure environment creation page. if (Orchestrator.IsNavigatingBackward) - { - ResetErrorUI(); + { + CreationPageState = CreationPageStateKind.InitialPageAdaptiveCardLoading; Orchestrator.AdaptiveCardFlowNavigator.GoToPreviousPage(); return; } @@ -153,21 +172,45 @@ protected async override Task OnEachNavigateToAsync() CanGoToNextPage = false; var curSelectedProviderId = _curProviderDetails?.ComputeSystemProvider?.Id ?? string.Empty; var upcomingSelectedProviderId = _upcomingProviderDetails?.ComputeSystemProvider?.Id; - _isFirstTimeLoadingNewFlow = true; // Selected compute system provider changed so we need to update the adaptive card in the UI // with a new adaptive card from the new provider. _curProviderDetails = _upcomingProviderDetails; - - IsAdaptiveCardSessionLoaded = false; + SelectedDeveloperId = new DeveloperIdWrapper(new EmptyDeveloperId()); AdaptiveCardLoadingMessage = StringResource.GetLocalized(StringResourceKey.EnvironmentCreationUILoadingMessage, _curProviderDetails.ComputeSystemProvider.DisplayName); + DeveloperIdWrappers.Clear(); + CreationPageState = CreationPageStateKind.AccountSelection; + + // The DeveloperId count will always be at least one for every provider. If there is only one, + // then the select account combo box will not be shown and the adaptive card for this provider will be shown. + if (_curProviderDetails.DeveloperIds.Count == 1) + { + PopulateAdaptiveCardSectionAsync(_curProviderDetails.DeveloperIds[0].DeveloperId); + return; + } + + // If execution ends here, the view will only show a combo box with a list of developerIds. + DeveloperIdWrappers = new(_curProviderDetails.DeveloperIds.OrderBy(wrapper => wrapper.LoginId)); + } + + [RelayCommand] + public void DeveloperIdSelected(DeveloperIdWrapper wrapper) + { + PopulateAdaptiveCardSectionAsync(wrapper.DeveloperId); + } + + private void PopulateAdaptiveCardSectionAsync(IDeveloperId developerId) + { + CreationPageState = CreationPageStateKind.InitialPageAdaptiveCardLoading; // Its possible that an extension could take a long time to load the adaptive card session. // So we run this on a background thread to prevent the UI from freezing. _ = Task.Run(() => { - var developerIdWrapper = _curProviderDetails.DeveloperIds.First(); - var result = _curProviderDetails.ComputeSystemProvider.CreateAdaptiveCardSessionForDeveloperId(developerIdWrapper.DeveloperId, ComputeSystemAdaptiveCardKind.CreateComputeSystem); + var result = _curProviderDetails.ComputeSystemProvider.CreateAdaptiveCardSessionForDeveloperId( + developerId, + ComputeSystemAdaptiveCardKind.CreateComputeSystem); + UpdateExtensionAdaptiveCard(result); }); } @@ -207,10 +250,11 @@ public void UpdateExtensionAdaptiveCard(ComputeSystemAdaptiveCardResult adaptive var result = _extensionAdaptiveCardSession.Initialize(_extensionAdaptiveCard); if (result.Status == ProviderOperationStatus.Failure) { - _log.Error(result.ExtendedError, $"Extension failed to generate adaptive card. DisplayMsg: {result.DisplayMessage}, DiagnosticMsg: {result.DiagnosticText}"); + _log.Error(result.ExtendedError, $"Extension failed to generate adaptive card. DisplayMessage: {result.DisplayMessage}, DiagnosticMessage: {result.DiagnosticText}"); SessionErrorTitle = _stringResource.GetLocalized("ErrorLoadingCreationUITitle", _curProviderDetails.ComputeSystemProvider.DisplayName); SessionErrorMessage = result.DisplayMessage; CanGoToNextPage = false; + CreationPageState = CreationPageStateKind.InitialPageAdaptiveCardError; } else { @@ -220,8 +264,10 @@ public void UpdateExtensionAdaptiveCard(ComputeSystemAdaptiveCardResult adaptive catch (Exception ex) { _log.Error(ex, $"Failed to get creation options adaptive card from provider {_curProviderDetails.ComputeSystemProvider.Id}."); - SessionErrorTitle = _stringResource.GetLocalized("ErrorLoadingCreationUITitle", _curProviderDetails.ComputeSystemProvider.DisplayName); + var displayName = _curProviderDetails.ComputeSystemProvider.DisplayName; + SessionErrorTitle = _stringResource.GetLocalized("ErrorLoadingCreationUIForDeveloperId", displayName, SelectedDeveloperId.LoginId); SessionErrorMessage = ex.Message; + CreationPageState = CreationPageStateKind.InitialPageAdaptiveCardError; } }); } @@ -239,17 +285,16 @@ public void OnAdaptiveCardUpdated(object sender, AdaptiveCard adaptiveCard) _renderedAdaptiveCard = _adaptiveCardRenderer.RenderAdaptiveCard(adaptiveCard); _renderedAdaptiveCard.Action += OnRenderedAdaptiveCardAction; _userInputsFromAdaptiveCard = _renderedAdaptiveCard.UserInputs; - - // Only send the adaptive card to the creation options view when the user moves - // from the extension selection page to the environment creation options page. - // All other times after that will happen when the user clicks the "Previous" - // button in the setup flow, in which case sending the adaptive card to the creation - // options view will be done in the OnRenderedAdaptiveCardAction method below. - if (_isFirstTimeLoadingNewFlow) + + if (ShouldAdaptiveCardAppearOnInitialPage()) + { + SendAdaptiveCardToCurrentView(); + CreationPageState = CreationPageStateKind.InitialPageAdaptiveCardLoaded; + CanGoToNextPage = true; + } + else { - SendAdaptiveCardToCurrentView(); - StopShowingLoadingUI(); - _isFirstTimeLoadingNewFlow = false; + CreationPageState = CreationPageStateKind.OtherPageAdaptiveCardLoaded; } }); } @@ -265,31 +310,38 @@ private void OnRenderedAdaptiveCardAction(object sender, AdaptiveActionEventArgs { _dispatcherQueue.TryEnqueue(async () => { - IsAdaptiveCardSessionLoaded = false; ResetErrorUI(); AdaptiveCardLoadingMessage = StringResource.GetLocalized(StringResourceKey.EnvironmentCreationUILoadingMessage, _curProviderDetails.ComputeSystemProvider.DisplayName); // Send the inputs and actions that the user entered back to the extension. var result = await _extensionAdaptiveCardSession.OnAction(args.Action.ToJson().Stringify(), args.Inputs.AsJson().Stringify()); - var actionFailed = result.Status == ProviderOperationStatus.Failure; - - if (actionFailed) - { - _log.Error(result.ExtendedError, $"Extension failed to generate adaptive card. DisplayMsg: {result.DisplayMessage}, DiagnosticMsg: {result.DiagnosticText}"); + var actionFailed = result.Status == ProviderOperationStatus.Failure; + + if (actionFailed) + { + _log.Error(result.ExtendedError, $"Extension failed to generate adaptive card. DisplayMsg: {result.DisplayMessage}, DiagnosticMsg: {result.DiagnosticText}"); SessionErrorMessage = result.DisplayMessage; - } - if (IsCurrentPage && !actionFailed) - { - // Move Setup flow forward if the adaptive card Id that was clicked was the next button. - if (Orchestrator.AdaptiveCardFlowNavigator.IsActionButtonIdNextButtonId(args.Action.Id)) + if (IsCurrentPage) { - await Orchestrator.GoToNextPage(); - } + // Make the current adaptive card in the session visible again since there was an error. + CreationPageState = CreationPageStateKind.InitialPageAdaptiveCardLoaded; + } + } + + if (IsCurrentPage && !actionFailed) + { + // Move Setup flow forward if the adaptive card Id that was clicked was the next button. + if (Orchestrator.AdaptiveCardFlowNavigator.IsActionButtonIdNextButtonId(args.Action.Id)) + { + await Orchestrator.GoToNextPage(); + } } - SendAdaptiveCardToCurrentView(SessionErrorMessage); - StopShowingLoadingUI(); + if (!ShouldAdaptiveCardAppearOnInitialPage()) + { + SendAdaptiveCardToCurrentView(SessionErrorMessage); + } }); } @@ -334,7 +386,8 @@ private void OnReviewPageViewRequest(EnvironmentCreationOptionsViewModel recipie { // Only send the adaptive card if the session has loaded. If the session hasn't loaded yet, we'll send an empty response. The review page should be sent the adaptive card // once the session has loaded in the OnAdaptiveCardUpdated method. - if (!IsAdaptiveCardSessionLoaded && Orchestrator?.CurrentPageViewModel is not SummaryViewModel) + var otherPageAdaptiveCardLoaded = CreationPageState == CreationPageStateKind.OtherPageAdaptiveCardLoaded; + if (!otherPageAdaptiveCardLoaded && Orchestrator?.CurrentPageViewModel is not SummaryViewModel) { return; } @@ -378,13 +431,12 @@ private async Task GetAdaptiveCardRenderer() public void GoToNextPage() { ResetErrorUI(); - Orchestrator.AdaptiveCardFlowNavigator.GoToNextPageWithValidation(_userInputsFromAdaptiveCard); - } + var validationSuccessful = Orchestrator.AdaptiveCardFlowNavigator.GoToNextPageWithValidation(_userInputsFromAdaptiveCard); - private void StopShowingLoadingUI() - { - CanGoToNextPage = true; - IsAdaptiveCardSessionLoaded = true; + if (validationSuccessful) + { + CreationPageState = CreationPageStateKind.OtherPageAdaptiveCardLoading; + } } private void ResetErrorUI() @@ -398,4 +450,14 @@ private void SendAdaptiveCardToCurrentView(string errorMessage = null) WeakReferenceMessenger.Default.Send(new NewAdaptiveCardAvailableMessage( new RenderedAdaptiveCardData(Orchestrator.CurrentPageViewModel, _renderedAdaptiveCard, errorMessage))); } + + private bool ShouldAdaptiveCardAppearOnInitialPage() + { + return CreationPageState switch + { + CreationPageStateKind.OtherPageAdaptiveCardLoaded => false, + CreationPageStateKind.OtherPageAdaptiveCardLoading => false, + _ => true, + }; + } } diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SetupTargetViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SetupTargetViewModel.cs index 41cbeb119..ed84d633b 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SetupTargetViewModel.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/SetupTargetViewModel.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using System; +using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Threading.Tasks; @@ -13,6 +14,7 @@ using DevHome.Common.Environments.Helpers; using DevHome.Common.Environments.Models; using DevHome.Common.Environments.Services; +using DevHome.Common.Models; using DevHome.Common.Services; using DevHome.SetupFlow.Models.Environments; using DevHome.SetupFlow.Services; @@ -395,63 +397,65 @@ public async Task UpdateListViewModelList(ComputeSystemsLoadedData data) { _notificationsHelper?.DisplayComputeSystemEnumerationErrors(data); - // Remove the mappings that failed to load. - // The errors are already handled by the notification helper. - foreach (var mapping in data.DevIdToComputeSystemMap.Where(kvp => - kvp.Value.Result.Status == ProviderOperationStatus.Failure)) + var computeSystemListViewModels = new List(); + var allComputeSystems = new List(); + foreach (var devIdToComputeSystemResultPair in data.DevIdToComputeSystemMap) { - data.DevIdToComputeSystemMap.Remove(mapping.Key); - } + // Remove the mappings that failed to load. + // The errors are already handled by the notification helper. + if (devIdToComputeSystemResultPair.Value.Result.Status == ProviderOperationStatus.Failure) + { + continue; + } + + var listViewModel = new ComputeSystemsListViewModel(data.ProviderDetails, devIdToComputeSystemResultPair); - var curListViewModel = new ComputeSystemsListViewModel(data); + if (listViewModel.ComputeSystems.Count > 0) + { + computeSystemListViewModels.Add(listViewModel); + allComputeSystems.AddRange(listViewModel.ComputeSystems); + } + } // Fetch data for all compute systems that support the ApplyConfiguration flag in parallel // on thread pool to avoid calling expensive OOP operations on the UI thread. - await Parallel.ForEachAsync(curListViewModel.ComputeSystems, async (computeSystem, token) => + await Parallel.ForEachAsync(allComputeSystems, async (computeSystem, token) => { - if (computeSystem.SupportedOperations.Value.HasFlag(ComputeSystemOperations.ApplyConfiguration)) - { - await computeSystem.FetchDataAsync(); - } + await computeSystem.FetchDataAsync(); }); await _dispatcherQueue.EnqueueAsync(async () => { - foreach (var computeSystem in curListViewModel.ComputeSystems) + foreach (var listViewModel in computeSystemListViewModels) { - // Remove any cards that don't support the ApplyConfiguration flag. - if (!computeSystem.SupportedOperations.Value.HasFlag(ComputeSystemOperations.ApplyConfiguration)) + foreach (var computeSystem in listViewModel.ComputeSystems) { - continue; + var packageFullName = data.ProviderDetails.ExtensionWrapper.PackageFullName; + var card = await _computeSystemViewModelFactory.CreateCardViewModelAsync( + ComputeSystemManagerObj, + computeSystem, + data.ProviderDetails.ComputeSystemProvider, + packageFullName, + _dispatcherQueue); + + // Don't show environments that aren't in a state to configure + if (!ShouldShowCard(card.CardState)) + { + _log.Information($"{computeSystem.DisplayName} not in valid state." + + $" Current state: {card.CardState}"); + continue; + } + + listViewModel.ComputeSystemCardCollection.Add(card); } - var packageFullName = data.ProviderDetails.ExtensionWrapper.PackageFullName; - var card = await _computeSystemViewModelFactory.CreateCardViewModelAsync( - ComputeSystemManagerObj, - computeSystem, - curListViewModel.Provider, - packageFullName, - _dispatcherQueue); - - // Don't show environments that aren't in a state to configure - if (!ShouldShowCard(card.CardState)) + if (listViewModel.ComputeSystemCardCollection.Count > 0) { - continue; + AddListViewModelToList(listViewModel); + listViewModel.CardSelectionChanged += OnListSelectionChanged; } - - curListViewModel.ComputeSystemCardCollection.Add(card); - curListViewModel.CardSelectionChanged += OnListSelectionChanged; - } - - // Don't add view model to list if it doesn't contain any cards. - if (curListViewModel.ComputeSystemCardCollection.Count == 0) - { - _log.Information($"The {data.ProviderDetails.ComputeSystemProvider.DisplayName} was found but does not contain environments that support configuration"); - UpdateProviderNames(curListViewModel); - return; } - AddListViewModelToList(curListViewModel); ShouldShowShimmerBelowList = true; }); } diff --git a/tools/SetupFlow/DevHome.SetupFlow/Views/Environments/EnvironmentCreationOptionsView.xaml b/tools/SetupFlow/DevHome.SetupFlow/Views/Environments/EnvironmentCreationOptionsView.xaml index 10a9dd6b4..c0fec3878 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/Views/Environments/EnvironmentCreationOptionsView.xaml +++ b/tools/SetupFlow/DevHome.SetupFlow/Views/Environments/EnvironmentCreationOptionsView.xaml @@ -9,12 +9,16 @@ xmlns:behaviors="using:CommunityToolkit.WinUI.Behaviors" xmlns:commonBehaviors="using:DevHome.Common.Behaviors" xmlns:setupFlowBehaviors="using:DevHome.SetupFlow.Behaviors" + xmlns:ic="using:Microsoft.Xaml.Interactions.Core" + xmlns:setupFlowConverters="using:DevHome.SetupFlow.Converters" Unloaded="ViewUnloaded" Loaded="ViewLoaded"> + + @@ -52,8 +56,9 @@ Margin="{ThemeResource ContentPageMargin}" Grid.Row="1"> - - + + + + HorizontalAlignment="Stretch"> + + + + + + + + + + + + + + + + + + + Padding="-15" + HorizontalAlignment="Left"> + Visibility="{x:Bind ViewModel.CreationPageState, Mode=OneWay, Converter={StaticResource CreationStateKindToVisibilityConverter}, ConverterParameter='ProgressRingGrid'}"> @@ -96,7 +145,7 @@ IsActive="True" Width="20" Height="20"/> - From 5b6c3622d17c6390543bcb6c4a0010e51f7422ea Mon Sep 17 00:00:00 2001 From: ssparach <128866445+ssparach@users.noreply.github.com> Date: Thu, 3 Oct 2024 10:19:28 -0700 Subject: [PATCH 35/58] [File Explorer Source Control Integration] Accessibility bug fixes (#3906) * accessibility bug fixes * address PR feedback --- .../Models/RepositoryInformation.cs | 12 ++++++++++-- .../ViewModels/FileExplorerViewModel.cs | 6 ++++-- .../Views/AddRepositoriesView.xaml | 11 ++++++++--- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/tools/Customization/DevHome.Customization/Models/RepositoryInformation.cs b/tools/Customization/DevHome.Customization/Models/RepositoryInformation.cs index a274836ad..37c34dca1 100644 --- a/tools/Customization/DevHome.Customization/Models/RepositoryInformation.cs +++ b/tools/Customization/DevHome.Customization/Models/RepositoryInformation.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System; using System.Linq; using System.Threading.Tasks; using DevHome.Common.Extensions; @@ -21,13 +20,22 @@ public class RepositoryInformation public string SourceControlProviderPackageDisplayName { get; } - public RepositoryInformation(string rootpath, string classId) + public string RepositoryPathMapping { get; } + + public int Position { get; } + + public int Size { get; } + + public RepositoryInformation(string rootpath, string classId, int position, int size) { RepositoryRootPath = rootpath; SourceControlProviderCLSID = classId; var extension = GetExtension(classId); SourceControlProviderDisplayName = GetExtensionDisplayName(extension); SourceControlProviderPackageDisplayName = GetExtensionPackageDisplayName(extension); + RepositoryPathMapping = string.Concat(RepositoryRootPath, " ", SourceControlProviderDisplayName); + Position = position; + Size = size; } private IExtensionWrapper? GetExtension(string classId) diff --git a/tools/Customization/DevHome.Customization/ViewModels/FileExplorerViewModel.cs b/tools/Customization/DevHome.Customization/ViewModels/FileExplorerViewModel.cs index 69c08da47..28bee5d87 100644 --- a/tools/Customization/DevHome.Customization/ViewModels/FileExplorerViewModel.cs +++ b/tools/Customization/DevHome.Customization/ViewModels/FileExplorerViewModel.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Linq; using System.Threading.Tasks; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; @@ -70,9 +71,10 @@ public void RefreshTrackedRepositories() { TrackedRepositories.Clear(); var repoCollection = RepoTracker.GetAllTrackedRepositories(); - foreach (KeyValuePair data in repoCollection) + for (int position = 0; position < repoCollection.Count; position++) { - TrackedRepositories.Add(new RepositoryInformation(data.Key, data.Value)); + var data = repoCollection.ElementAt(position); + TrackedRepositories.Add(new RepositoryInformation(data.Key, data.Value, position + 1, repoCollection.Count)); } } } diff --git a/tools/Customization/DevHome.Customization/Views/AddRepositoriesView.xaml b/tools/Customization/DevHome.Customization/Views/AddRepositoriesView.xaml index 77d93f310..6c22bf447 100644 --- a/tools/Customization/DevHome.Customization/Views/AddRepositoriesView.xaml +++ b/tools/Customization/DevHome.Customization/Views/AddRepositoriesView.xaml @@ -17,7 +17,7 @@ x:Uid="AddRepositoriesCard" Grid.Column="1"> - - - - - - - - diff --git a/src/Views/WhatsNewPage.xaml.cs b/src/Views/WhatsNewPage.xaml.cs deleted file mode 100644 index 7b66dab6d..000000000 --- a/src/Views/WhatsNewPage.xaml.cs +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using DevHome.Common.Contracts; -using DevHome.Common.Extensions; -using DevHome.Common.Helpers; -using DevHome.Common.Services; -using DevHome.Common.TelemetryEvents; -using DevHome.Common.TelemetryEvents.DeveloperId; -using DevHome.Common.Views; -using DevHome.Models; -using DevHome.SetupFlow.Utilities; -using DevHome.Telemetry; -using DevHome.ViewModels; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Windows.System; - -namespace DevHome.Views; - -public sealed partial class WhatsNewPage : ToolPage -{ - private readonly Uri _devDrivePageKeyUri = new("ms-settings:disksandvolumes"); - private readonly Uri _devDriveLearnMoreLinkUri = new("https://go.microsoft.com/fwlink/?linkid=2236041"); - private const string DevDriveLinkResourceKey = "WhatsNewPage_DevDriveCard/Link"; - - public WhatsNewViewModel ViewModel { get; } - - public WhatsNewPage() - { - ViewModel = Application.Current.GetService(); - InitializeComponent(); - } - - private async void OnLoaded(object sender, Microsoft.UI.Xaml.RoutedEventArgs e) - { - await Application.Current.GetService().SaveSettingAsync(WellKnownSettingsKeys.IsNotFirstRun, true); - - var whatsNewCards = FeaturesContainer.Resources - .Where((item) => item.Value.GetType() == typeof(WhatsNewCard)) - .Select(card => card.Value as WhatsNewCard) - .OrderBy(card => card?.Priority ?? 0); - - foreach (var card in whatsNewCards) - { - if (card is null) - { - continue; - } - - // When the Dev Drive feature is not enabled don't show the learn more uri link, but instead move the learn more text into the button content. - if (string.Equals(card.PageKey, _devDrivePageKeyUri.AbsoluteUri, StringComparison.OrdinalIgnoreCase)) - { - if (!DevDriveUtil.IsDevDriveFeatureEnabled) - { - card.ButtonText = Application.Current.GetService().GetLocalized(DevDriveLinkResourceKey); - card.ShouldShowLink = false; - } - } - else - { - card.ShouldShowIcon = false; - } - - ViewModel.AddCard(card); - } - - var whatsNewBigCards = BigFeaturesContainer.Resources - .Where((item) => item.Value.GetType() == typeof(WhatsNewCard)) - .Select(card => card.Value as WhatsNewCard) - .OrderBy(card => card?.Priority ?? 0); - - foreach (var card in whatsNewBigCards) - { - if (card is null) - { - continue; - } - - ViewModel.AddBigCard(card); - } - - ViewModel.NumberOfBigCards = whatsNewBigCards.Count(); - - MoveBigCardsIfNeeded(this.ActualWidth); - - TelemetryFactory.Get().Log( - "Page_Loaded_Event", - LogLevel.Critical, - new PageLoadedEvent(GetType().Name)); - } - - private async void Button_ClickAsync(object sender, RoutedEventArgs e) - { - var btn = sender as Button; - - if (btn?.DataContext is not string pageKey) - { - return; - } - - if (pageKey.Equals(_devDrivePageKeyUri.AbsoluteUri, StringComparison.OrdinalIgnoreCase)) - { - // Only launch the disks and volumes settings page when the Dev Drive feature is enabled. - // Otherwise redirect the user to the Dev Drive support page to learn more about the feature. - // Critical level approved by subhasan - TelemetryFactory.Get().Log( - "LaunchDisksAndVolumesSettingsPageTriggered", - LogLevel.Critical, - new DisksAndVolumesSettingsPageTriggeredEvent(source: "WhatsNewPageView")); - await Launcher.LaunchUriAsync(DevDriveUtil.IsDevDriveFeatureEnabled ? _devDrivePageKeyUri : _devDriveLearnMoreLinkUri); - } - else - { - if (pageKey.Equals(typeof(Settings.ViewModels.AccountsViewModel).FullName, StringComparison.OrdinalIgnoreCase)) - { - TelemetryFactory.Get().Log( - "EntryPoint_DevId_Event", - LogLevel.Critical, - new EntryPointEvent(EntryPointEvent.EntryPoint.WhatsNewPage)); - } - - var navigationService = Application.Current.GetService(); - navigationService.NavigateTo(pageKey!); - } - } - - public void OnSizeChanged(object sender, SizeChangedEventArgs args) - { - if (sender as Page == this) - { - MoveBigCardsIfNeeded(args.NewSize.Width); - } - } - - private void MoveBigCardsIfNeeded(double newWidth) - { - if (newWidth < 786) - { - ViewModel.SwitchToSmallerView(); - } - else - { - ViewModel.SwitchToLargerView(); - } - } -} diff --git a/test/TestingScenarios/DevHome.md b/test/TestingScenarios/DevHome.md index b45a7e3dd..0c4a4964f 100644 --- a/test/TestingScenarios/DevHome.md +++ b/test/TestingScenarios/DevHome.md @@ -5,8 +5,3 @@ Please manually verify these scenarios. This is required for all PRs that affec Please make sure to verify all these scenarios. 1. User can install Dev Home -1. On first launch from new installation, user is brought to the "Introducing Dev Home" page - -### Introducing Dev Home page -1. User can click all "learn more" links on the Introducing Dev Home page -1. User can resize the window and card sizes are responsive diff --git a/uitest/Common/DevHomeApplication.cs b/uitest/Common/DevHomeApplication.cs index 82c74a9fc..466e77ee6 100644 --- a/uitest/Common/DevHomeApplication.cs +++ b/uitest/Common/DevHomeApplication.cs @@ -34,8 +34,6 @@ public sealed class DevHomeApplication private WindowsElement MachineConfigurationNavigationItem => _devHomeSession.Driver.FindElementByAccessibilityId("DevHome.SetupFlow"); - private WindowsElement IntroducingDevHomeNavigationItem => _devHomeSession.Driver.FindElementByAccessibilityId("WhatsNew"); - private WindowsElement SettingsNavigationItem => _devHomeSession.Driver.FindElementByAccessibilityId("SettingsItem"); private WindowsElement ExtensionsNavigationItem => _devHomeSession.Driver.FindElementByAccessibilityId("Extensions"); @@ -83,13 +81,6 @@ public MachineConfigurationPage NavigateToMachineConfigurationPage() return new(_devHomeSession.Driver); } - public IntroducingDevHomePage NavigateToIntroducingDevHomePage() - { - Trace.WriteLine("Navigating to Introducing Dev Home"); - IntroducingDevHomeNavigationItem.Click(); - return new(_devHomeSession.Driver); - } - public SettingsPage NavigateToSettingsPage() { Trace.WriteLine("Navigating to Settings"); diff --git a/uitest/IntroducingTest.cs b/uitest/IntroducingTest.cs deleted file mode 100644 index 33ca2e846..000000000 --- a/uitest/IntroducingTest.cs +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using DevHome.UITest.Common; -using Microsoft.VisualStudio.TestTools.UnitTesting; - -namespace DevHome.Tests.UITest; - -[TestClass] -public class IntroducingTest : DevHomeTestBase -{ - [TestMethod] - public void GetStartedTest() - { - // Arrange - var introPage = Application.NavigateToIntroducingDevHomePage(); - - // Act - var machineConfigurationPage = introPage.ClickGetStarted(); - - // Assert - Assert.IsTrue(machineConfigurationPage.EndToEndSetupButton.Displayed); - } - - [TestMethod] - public void ExploreExtensionsTest() - { - // Arrange - var introPage = Application.NavigateToIntroducingDevHomePage(); - - // Act - var extensionsPage = introPage.ClickExploreExtensions(); - - // Assert - Assert.IsTrue(extensionsPage.GetUpdatesButton.Displayed); - } - - [TestMethod] - public void PinWidgetsTest() - { - // Arrange - var introPage = Application.NavigateToIntroducingDevHomePage(); - - // Act - var dashboardPage = introPage.ClickPinWidgets(); - - // Assert - Assert.IsTrue(dashboardPage.AddWidgetButton.Displayed); - } - - [TestMethod] - public void ConnectAccountsTest() - { - // Arrange - var introPage = Application.NavigateToIntroducingDevHomePage(); - - // Act - var accountsPage = introPage.ClickConnectAccounts(); - - // Assert - Assert.IsTrue(accountsPage.AddAccountsButton.Displayed); - } -} diff --git a/uitest/Pages/IntroducingDevHomePage.cs b/uitest/Pages/IntroducingDevHomePage.cs deleted file mode 100644 index a16e542c4..000000000 --- a/uitest/Pages/IntroducingDevHomePage.cs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System.Diagnostics; -using OpenQA.Selenium.Appium.Windows; - -namespace DevHome.UITest.Pages; - -public class IntroducingDevHomePage : ApplicationPage -{ - private WindowsElement GetStartedButton => Driver.FindElementByAccessibilityId("WhatsNewPage_GetStartedButton"); - - private WindowsElement ExploreExtensionsButton => Driver.FindElementByAccessibilityId("WhatsNewPage_ExtensionsButton"); - - private WindowsElement PinWidgetsButton => Driver.FindElementByAccessibilityId("WhatsNewPage_DevDashButton"); - - private WindowsElement ConnectAccountsButton => Driver.FindElementByAccessibilityId("WhatsNewPage_DevIdButton"); - - public IntroducingDevHomePage(WindowsDriver driver) - : base(driver) - { - } - - public MachineConfigurationPage ClickGetStarted() - { - Trace.WriteLine("Clicking Get Started"); - GetStartedButton.Click(); - return new MachineConfigurationPage(Driver); - } - - public ExtensionsPage ClickExploreExtensions() - { - Trace.WriteLine("Clicking Explore Extensions"); - ExploreExtensionsButton.Click(); - return new ExtensionsPage(Driver); - } - - public DashboardPage ClickPinWidgets() - { - Trace.WriteLine("Clicking Pin Widgets"); - PinWidgetsButton.Click(); - return new DashboardPage(Driver); - } - - public SettingsAccountsPage ClickConnectAccounts() - { - Trace.WriteLine("Clicking Connect Accounts"); - ConnectAccountsButton.Click(); - return new SettingsAccountsPage(Driver); - } -} From 45431310848858868d23ba4f0c028e103e26ae77 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Tue, 22 Oct 2024 12:14:06 -0700 Subject: [PATCH 45/58] Fix race condition when storing GitConfiguration to disk (#3949) --- .../FileExplorerGitIntegration/Models/GitConfiguration.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/GitExtension/FileExplorerGitIntegration/Models/GitConfiguration.cs b/extensions/GitExtension/FileExplorerGitIntegration/Models/GitConfiguration.cs index d656d0171..9489d7b1b 100644 --- a/extensions/GitExtension/FileExplorerGitIntegration/Models/GitConfiguration.cs +++ b/extensions/GitExtension/FileExplorerGitIntegration/Models/GitConfiguration.cs @@ -16,7 +16,7 @@ public class GitConfiguration : IDisposable private string GitExeInstallPath { get; set; } = string.Empty; - private readonly object _fileLock = new(); + private static readonly object _fileLock = new(); private readonly ILogger _log = Log.ForContext(); From be38a85539208612fa4b64d44a9d2e5201a61d53 Mon Sep 17 00:00:00 2001 From: Ryan Shepherd Date: Wed, 23 Oct 2024 13:23:24 -0700 Subject: [PATCH 46/58] Telemetry for detecting git (#3950) * Add telemetry to store where and which version of git.exe was detected * Strip trailing newline from git version --- .../GitExtension/GitDetectEvent.cs | 47 ++++++++++++++++ .../Models/GitDetect.cs | 53 ++++++++++++------- 2 files changed, 82 insertions(+), 18 deletions(-) create mode 100644 common/TelemetryEvents/GitExtension/GitDetectEvent.cs diff --git a/common/TelemetryEvents/GitExtension/GitDetectEvent.cs b/common/TelemetryEvents/GitExtension/GitDetectEvent.cs new file mode 100644 index 000000000..5372b3d9e --- /dev/null +++ b/common/TelemetryEvents/GitExtension/GitDetectEvent.cs @@ -0,0 +1,47 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Diagnostics.Tracing; +using DevHome.Telemetry; +using Microsoft.Diagnostics.Telemetry; +using Microsoft.Diagnostics.Telemetry.Internal; + +namespace DevHome.Common.TelemetryEvents.GitExtension; + +// How git.exe was located +public enum GitDetectStatus +{ + // git.exe was not found on the system + NotFound, + + // In the PATH environment variable + PathEnvironmentVariable, + + // Probed well-known registry keys to find a Git install location + RegistryProbe, + + // Probed well-known folders under Program Files [(x86)] + ProgramFiles, +} + +[EventData] +public class GitDetectEvent : EventBase +{ + public override PartA_PrivTags PartA_PrivTags => PrivTags.ProductAndServicePerformance; + + public string Status { get; } + + public string Version { get; } + + public GitDetectEvent(GitDetectStatus status, string version) + { + Status = status.ToString(); + Version = version; + } + + public override void ReplaceSensitiveStrings(Func replaceSensitiveStrings) + { + // This event so far has no sensitive strings + } +} diff --git a/extensions/GitExtension/FileExplorerGitIntegration/Models/GitDetect.cs b/extensions/GitExtension/FileExplorerGitIntegration/Models/GitDetect.cs index 28b1e0df5..5ba26c8c4 100644 --- a/extensions/GitExtension/FileExplorerGitIntegration/Models/GitDetect.cs +++ b/extensions/GitExtension/FileExplorerGitIntegration/Models/GitDetect.cs @@ -1,6 +1,9 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +using DevHome.Common.TelemetryEvents.GitExtension; +using DevHome.Common.TelemetryEvents.SourceControlIntegration; +using DevHome.Telemetry; using Microsoft.Win32; using Microsoft.Windows.DevHome.SDK; using Serilog; @@ -13,6 +16,12 @@ public class GitDetect private readonly ILogger _log = Log.ForContext(); + private struct DetectInfo + { + public bool Found; + public string Version; + } + public GitDetect() { GitConfiguration = new GitConfiguration(null); @@ -20,19 +29,21 @@ public GitDetect() public bool DetectGit() { - var gitExeFound = false; + var detect = new DetectInfo { Found = false, Version = string.Empty }; + var status = GitDetectStatus.NotFound; - if (!gitExeFound) + if (!detect.Found) { // Check if git.exe is present in PATH environment variable - gitExeFound = ValidateGitConfigurationPath("git.exe"); - if (gitExeFound) + detect = ValidateGitConfigurationPath("git.exe"); + if (detect.Found) { + status = GitDetectStatus.PathEnvironmentVariable; GitConfiguration.StoreGitExeInstallPath("git.exe"); } } - if (!gitExeFound) + if (!detect.Found) { // Check execution of git.exe by finding install location in registry keys string[] registryPaths = { "HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Git_is1", "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Git_is1" }; @@ -43,25 +54,31 @@ public bool DetectGit() if (!string.IsNullOrEmpty(gitPath)) { var paths = FindSubdirectories(gitPath); - gitExeFound = CheckForExeInPaths(paths); - if (gitExeFound) + detect = CheckForExeInPaths(paths); + if (detect.Found) { + status = GitDetectStatus.RegistryProbe; break; } } } } - if (!gitExeFound) + if (!detect.Found) { // Search for git.exe in common file paths var programFiles = Environment.GetEnvironmentVariable("ProgramFiles"); var programFilesX86 = Environment.GetEnvironmentVariable("ProgramFiles(x86)"); string[] possiblePaths = { $"{programFiles}\\Git\\bin", $"{programFilesX86}\\Git\\bin", $"{programFiles}\\Git\\cmd", $"{programFilesX86}\\Git\\cmd" }; - gitExeFound = CheckForExeInPaths(possiblePaths); + detect = CheckForExeInPaths(possiblePaths); + if (detect.Found) + { + status = GitDetectStatus.ProgramFiles; + } } - return gitExeFound; + TelemetryFactory.Get().Log("GitDetect_Event", LogLevel.Critical, new GitDetectEvent(status, detect.Version)); + return detect.Found; } private string[] FindSubdirectories(string installLocation) @@ -85,35 +102,35 @@ private string[] FindSubdirectories(string installLocation) } } - private bool CheckForExeInPaths(string[] possiblePaths) + private DetectInfo CheckForExeInPaths(string[] possiblePaths) { // Iterate through the possible paths to find the git.exe file foreach (var path in possiblePaths.Where(x => !string.IsNullOrEmpty(x))) { var gitPath = Path.Combine(path, "git.exe"); - var isValid = ValidateGitConfigurationPath(gitPath); + var detect = ValidateGitConfigurationPath(gitPath); // If the git.exe file is found, store the install path and log the information - if (isValid) + if (detect.Found) { GitConfiguration.StoreGitExeInstallPath(gitPath); _log.Information("Git Exe Install Path found"); - return true; + return detect; } } _log.Debug("Git.exe not found in paths examined"); - return false; + return new DetectInfo { Found = false, Version = string.Empty }; } - public bool ValidateGitConfigurationPath(string path) + private DetectInfo ValidateGitConfigurationPath(string path) { var result = GitExecute.ExecuteGitCommand(path, string.Empty, "--version"); if (result.Status == ProviderOperationStatus.Success && result.Output != null && result.Output.Contains("git version")) { - return true; + return new DetectInfo { Found = true, Version = result.Output.Replace("git version", string.Empty).TrimEnd() }; } - return false; + return new DetectInfo { Found = false, Version = string.Empty }; } } From cbca79d3508c5cf20efd6fe9334ccc105fc86abf Mon Sep 17 00:00:00 2001 From: Lauren Ciha <64796985+lauren-ciha@users.noreply.github.com> Date: Fri, 25 Oct 2024 10:21:49 -0700 Subject: [PATCH 47/58] Remove Device Restore (#3953) * Remove RestoreState.cs * Remove WinGetPackageRestoreDataSource and WinGetPackageRestoreDataSourceTest * Remove using from BaseSetupFlowTest.cs * Remove using from ServiceExtension * Remove using from PackageViewModel : * Remove strings * Updates (in progress) * Update GetIconByTheme * Split IconByTheme into GetLight/DarkThemeIcon() * Refactor GetLight/DarkThemeIcon() * Check _package.Icon, not packageIcon * Remove unnecessary usings from PackageViewModel.cs * Refactor GetIconByTheme() --- .../Models/RestoreState.cs | 21 -- .../BaseSetupFlowTest.cs | 7 - .../WinGetPackageRestoreDataSourceTest.cs | 231 ------------------ .../Extensions/ServiceExtensions.cs | 3 - .../Services/StringResourceKey.cs | 3 - .../WinGetPackageRestoreDataSource.cs | 175 ------------- .../Strings/en-us/Resources.resw | 16 -- .../ViewModels/PackageViewModel.cs | 21 +- 8 files changed, 6 insertions(+), 471 deletions(-) delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Models/RestoreState.cs delete mode 100644 tools/SetupFlow/DevHome.SetupFlow.UnitTest/ViewModels/WinGetPackageRestoreDataSourceTest.cs delete mode 100644 tools/SetupFlow/DevHome.SetupFlow/Services/WinGetPackageRestoreDataSource.cs diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/RestoreState.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/RestoreState.cs deleted file mode 100644 index 1e1206a6e..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/RestoreState.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using Microsoft.UI.Xaml.Controls; - -namespace DevHome.DevDiagnostics.Models; - -internal sealed class RestoreState -{ - internal double Left { get; set; } - - internal double Top { get; set; } - - internal double Width { get; set; } - - internal double Height { get; set; } - - internal Orientation BarOrientation { get; set; } - - internal bool IsLargePanelVisible { get; set; } -} diff --git a/tools/SetupFlow/DevHome.SetupFlow.UnitTest/BaseSetupFlowTest.cs b/tools/SetupFlow/DevHome.SetupFlow.UnitTest/BaseSetupFlowTest.cs index b88b11e91..5c68dfd5a 100644 --- a/tools/SetupFlow/DevHome.SetupFlow.UnitTest/BaseSetupFlowTest.cs +++ b/tools/SetupFlow/DevHome.SetupFlow.UnitTest/BaseSetupFlowTest.cs @@ -11,7 +11,6 @@ using DevHome.SetupFlow.ViewModels; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; -using Microsoft.Internal.Windows.DevHome.Helpers.Restore; using Moq; namespace DevHome.SetupFlow.UnitTest; @@ -26,8 +25,6 @@ public class BaseSetupFlowTest protected Mock ThemeSelectorService { get; private set; } - protected Mock RestoreInfo { get; private set; } - protected Mock StringResource { get; private set; } protected Mock LocalSettingsService { get; private set; } @@ -40,7 +37,6 @@ public void TestInitialize() { WindowsPackageManager = new Mock(); ThemeSelectorService = new Mock(); - RestoreInfo = new Mock(); StringResource = new Mock(); LocalSettingsService = new Mock(); TestHost = CreateTestHost(); @@ -76,11 +72,8 @@ private IHost CreateTestHost() // App-management services services.AddSingleton(WindowsPackageManager.Object); services.AddTransient(); - services.AddTransient(); - services.AddSingleton(RestoreInfo.Object); services.AddSingleton(); services.AddSingleton(); - services.AddSingleton(); services.AddSingleton(); services.AddSingleton(new Mock().Object); services.AddSingleton(new Mock().Object); diff --git a/tools/SetupFlow/DevHome.SetupFlow.UnitTest/ViewModels/WinGetPackageRestoreDataSourceTest.cs b/tools/SetupFlow/DevHome.SetupFlow.UnitTest/ViewModels/WinGetPackageRestoreDataSourceTest.cs deleted file mode 100644 index d690627ba..000000000 --- a/tools/SetupFlow/DevHome.SetupFlow.UnitTest/ViewModels/WinGetPackageRestoreDataSourceTest.cs +++ /dev/null @@ -1,231 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using DevHome.Common.Extensions; -using DevHome.Services.WindowsPackageManager.Contracts; -using DevHome.Services.WindowsPackageManager.Exceptions; -using DevHome.Services.WindowsPackageManager.Models; -using DevHome.SetupFlow.Services; -using DevHome.SetupFlow.UnitTest.Helpers; -using Microsoft.Internal.Windows.DevHome.Helpers.Restore; -using Microsoft.Management.Deployment; -using Moq; -using Windows.Storage.Streams; - -namespace DevHome.SetupFlow.UnitTest.ViewModels; - -[TestClass] -public class WinGetPackageRestoreDataSourceTest : BaseSetupFlowTest -{ - // Icon stream size - private const ulong EmptyIconStreamSize = 0; - private const ulong NonEmptyIconStreamSize = 1; - - [TestMethod] - public void LoadCatalogs_EmptyPackages_ReturnsNoCatalogs() - { - // Arrange - var expectedPackages = new List(); - var restoreApplicationInfoList = expectedPackages.Select(p => CreateRestoreApplicationInfo(p.Id).Object).ToList(); - WindowsPackageManager.Setup(wpm => wpm.GetPackagesAsync(It.IsAny>())).ReturnsAsync(expectedPackages); - ConfigureRestoreDeviceInfo(RestoreDeviceInfoStatus.Ok, restoreApplicationInfoList); - - // Act - var loadedPackages = LoadCatalogsFromRestoreDataSource(); - - // Assert - Assert.AreEqual(0, loadedPackages.Count); - WindowsPackageManager.Verify(wpm => wpm.GetPackagesAsync(It.IsAny>()), Times.Never()); - } - - [TestMethod] - public void LoadCatalogs_ExceptionThrownWhenGettingPackages_ReturnsNoCatalogs() - { - // Arrange - WindowsPackageManager!.Setup(wpm => wpm.GetPackagesAsync(It.IsAny>())).ThrowsAsync(new FindPackagesException(FindPackagesResultStatus.CatalogError)); - ConfigureRestoreDeviceInfo(RestoreDeviceInfoStatus.Ok, new List()); - - // Act - var loadedPackages = LoadCatalogsFromRestoreDataSource(); - - // Assert - Assert.AreEqual(0, loadedPackages.Count); - } - - [TestMethod] - [DataRow(RestoreDeviceInfoStatus.NotAvailable)] - [DataRow(RestoreDeviceInfoStatus.Error)] - public void LoadCatalogs_NonSuccessStatus_ReturnsNoCatalogs(RestoreDeviceInfoStatus status) - { - // Arrange - ConfigureRestoreDeviceInfo(status, new List()); - - // Act - var loadedPackages = LoadCatalogsFromRestoreDataSource(); - - // Assert - Assert.AreEqual(0, loadedPackages.Count); - } - - [TestMethod] - [DataRow("mock1", "mock2")] - [DataRow("mock2", "mock1")] - public void LoadCatalogs_OrderedPackages_ReturnsWinGetCatalogWithMatchingInputOrder(string packageId1, string packageId2) - { - // Arrange - var expectedPackages = new List - { - PackageHelper.CreatePackage(packageId1).Object, - PackageHelper.CreatePackage(packageId2).Object, - }; - var restoreApplicationInfoList = expectedPackages.Select(p => CreateRestoreApplicationInfo(p.Id).Object).ToList(); - WindowsPackageManager.Setup(wpm => wpm.GetPackagesAsync(It.IsAny>())).ReturnsAsync(expectedPackages); - ConfigureRestoreDeviceInfo(RestoreDeviceInfoStatus.Ok, restoreApplicationInfoList); - - // Act - var loadedPackages = LoadCatalogsFromRestoreDataSource(); - - // Assert - Assert.AreEqual(1, loadedPackages.Count); - Assert.AreEqual(expectedPackages.Count, loadedPackages[0].Packages.Count); - Assert.AreEqual(expectedPackages[0].Id, loadedPackages[0].Packages.ElementAt(0).Id); - Assert.IsNotNull(expectedPackages[0].LightThemeIcon); - Assert.IsNotNull(expectedPackages[0].DarkThemeIcon); - Assert.AreEqual(expectedPackages[1].Id, loadedPackages[0].Packages.ElementAt(1).Id); - Assert.IsNotNull(expectedPackages[1].LightThemeIcon); - Assert.IsNotNull(expectedPackages[1].DarkThemeIcon); - } - - [TestMethod] - public void LoadCatalogs_Success_ReturnsWinGetCatalogs() - { - // Arrange - var expectedPackages = new List - { - PackageHelper.CreatePackage("mock1").Object, - PackageHelper.CreatePackage("mock2").Object, - }; - var restoreApplicationInfoList = expectedPackages.Select(p => CreateRestoreApplicationInfo(p.Id).Object).ToList(); - WindowsPackageManager.Setup(wpm => wpm.GetPackagesAsync(It.IsAny>())).ReturnsAsync(expectedPackages); - ConfigureRestoreDeviceInfo(RestoreDeviceInfoStatus.Ok, restoreApplicationInfoList); - - // Act - var loadedPackages = LoadCatalogsFromRestoreDataSource(); - - // Assert - Assert.AreEqual(1, loadedPackages.Count); - Assert.AreEqual(expectedPackages.Count, loadedPackages[0].Packages.Count); - Assert.AreEqual(expectedPackages[0].Id, loadedPackages[0].Packages.ElementAt(0).Id); - Assert.IsNotNull(expectedPackages[0].LightThemeIcon); - Assert.IsNotNull(expectedPackages[0].DarkThemeIcon); - Assert.AreEqual(expectedPackages[1].Id, loadedPackages[0].Packages.ElementAt(1).Id); - Assert.IsNotNull(expectedPackages[1].LightThemeIcon); - Assert.IsNotNull(expectedPackages[1].DarkThemeIcon); - } - - [TestMethod] - public void LoadCatalogs_ExceptionThrownWhenGettingRestoreApplicationIcon_ReturnsNullForIcon() - { - var expectedPackages = new List - { - PackageHelper.CreatePackage("mock").Object, - }; - var restoreApplicationInfoList = expectedPackages.Select(p => - { - var restoreAppInfo = CreateRestoreApplicationInfo(p.Id); - - // Mock restore application icon not found by throwing an exception - restoreAppInfo - .Setup(appInfo => appInfo.GetIconAsync(It.IsAny())) - .Throws(new ArgumentOutOfRangeException()); - - return restoreAppInfo.Object; - }).ToList(); - WindowsPackageManager.Setup(wpm => wpm.GetPackagesAsync(It.IsAny>())).ReturnsAsync(expectedPackages); - ConfigureRestoreDeviceInfo(RestoreDeviceInfoStatus.Ok, restoreApplicationInfoList); - - // Act - var loadedPackages = LoadCatalogsFromRestoreDataSource(); - - // Assert - Assert.AreEqual(1, loadedPackages.Count); - Assert.AreEqual(expectedPackages.Count, loadedPackages[0].Packages.Count); - Assert.AreEqual(expectedPackages[0].Id, loadedPackages[0].Packages.ElementAt(0).Id); - Assert.IsNull(expectedPackages[0].LightThemeIcon); - Assert.IsNull(expectedPackages[0].DarkThemeIcon); - } - - [TestMethod] - public void LoadCatalogs_GettingRestoreApplicationIconWithEmptyStream_ReturnsNullForIcon() - { - var expectedPackages = new List - { - PackageHelper.CreatePackage("mock").Object, - }; - var restoreApplicationInfoList = expectedPackages.Select(p => CreateRestoreApplicationInfo(p.Id, EmptyIconStreamSize).Object).ToList(); - WindowsPackageManager.Setup(wpm => wpm.GetPackagesAsync(It.IsAny>())).ReturnsAsync(expectedPackages); - WindowsPackageManager.Setup(wpm => wpm.CreateWinGetCatalogPackageUri(It.IsAny())).Returns(new WinGetPackageUri("x-ms-winget://mock/mock")); - ConfigureRestoreDeviceInfo(RestoreDeviceInfoStatus.Ok, restoreApplicationInfoList); - - // Act - var loadedPackages = LoadCatalogsFromRestoreDataSource(); - - // Assert - Assert.AreEqual(1, loadedPackages.Count); - Assert.AreEqual(expectedPackages.Count, loadedPackages[0].Packages.Count); - Assert.AreEqual(expectedPackages[0].Id, loadedPackages[0].Packages.ElementAt(0).Id); - Assert.IsNull(expectedPackages[0].LightThemeIcon); - Assert.IsNull(expectedPackages[0].DarkThemeIcon); - } - - /// - /// Load catalogs from restore data source - /// - /// List of package catalogs - private IList LoadCatalogsFromRestoreDataSource() - { - var restoreDataSource = TestHost!.GetService(); - restoreDataSource.InitializeAsync().GetAwaiter().GetResult(); - return restoreDataSource.LoadCatalogsAsync().GetAwaiter().GetResult(); - } - - /// - /// Configure a restore device info including WinGet packages to restore - /// - /// Result status - /// Mock a list of application info to restore - private void ConfigureRestoreDeviceInfo(RestoreDeviceInfoStatus status, IList restoreApplicationInfoList) - { - // Mock restore device info - var deviceInfo = new Mock(); - deviceInfo.Setup(di => di.WinGetApplicationsInfo).Returns(restoreApplicationInfoList); - - // Mock restore device info result - var restoreDeviceInfoResult = new Mock(); - restoreDeviceInfoResult.Setup(result => result.Status).Returns(status); - restoreDeviceInfoResult.Setup(result => result.RestoreDeviceInfo).Returns(deviceInfo.Object); - RestoreInfo.Setup(restore => restore.GetRestoreDeviceInfoAsync()).Returns(Task.FromResult(restoreDeviceInfoResult.Object).AsAsyncOperation()); - } - - /// - /// Create an application info to restore - /// - /// Id of the package corresponding to the application to restore - /// Restore application info - private Mock CreateRestoreApplicationInfo(string packageId, ulong iconStreamSize = NonEmptyIconStreamSize) - { - var appInfo = new Mock(); - - // Mock id - appInfo.Setup(app => app.Id).Returns(packageId); - - // Mock icon - var mockIconStream = new Mock(); - mockIconStream.SetupGet(stream => stream.Size).Returns(iconStreamSize); - appInfo - .Setup(app => app.GetIconAsync(It.IsAny())) - .Returns(Task.FromResult(mockIconStream.Object).AsAsyncOperation()); - - return appInfo; - } -} diff --git a/tools/SetupFlow/DevHome.SetupFlow/Extensions/ServiceExtensions.cs b/tools/SetupFlow/DevHome.SetupFlow/Extensions/ServiceExtensions.cs index 85caef575..cbfbce278 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/Extensions/ServiceExtensions.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/Extensions/ServiceExtensions.cs @@ -12,7 +12,6 @@ using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Options; using Microsoft.Internal.Windows.DevHome.Helpers; -using Microsoft.Internal.Windows.DevHome.Helpers.Restore; namespace DevHome.SetupFlow.Extensions; @@ -58,13 +57,11 @@ private static IServiceCollection AddAppManagement(this IServiceCollection servi services.AddTransient(); // Services - services.AddSingleton(); services.AddSingleton(); services.AddTransient(); services.AddSingleton(); services.AddSingleton(); - services.AddSingleton(); services.AddSingleton(sp => { var dataSourcePath = sp.GetService>().Value.WinGetPackageJsonDataSourcePath; diff --git a/tools/SetupFlow/DevHome.SetupFlow/Services/StringResourceKey.cs b/tools/SetupFlow/DevHome.SetupFlow/Services/StringResourceKey.cs index 3f546d665..7a015f1a6 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/Services/StringResourceKey.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/Services/StringResourceKey.cs @@ -80,9 +80,6 @@ public static class StringResourceKey public static readonly string RemovedAllApplications = nameof(RemovedAllApplications); public static readonly string ResultCountPlural = nameof(ResultCountPlural); public static readonly string ResultCountSingular = nameof(ResultCountSingular); - public static readonly string RestorePackagesTitle = nameof(RestorePackagesTitle); - public static readonly string RestorePackagesDescription = nameof(RestorePackagesDescription); - public static readonly string RestorePackagesDescriptionWithDate = nameof(RestorePackagesDescriptionWithDate); public static readonly string Repository = nameof(Repository); public static readonly string ReviewNothingToSetUpToolTip = nameof(ReviewNothingToSetUpToolTip); public static readonly string SelectedPackagesCount = nameof(SelectedPackagesCount); diff --git a/tools/SetupFlow/DevHome.SetupFlow/Services/WinGetPackageRestoreDataSource.cs b/tools/SetupFlow/DevHome.SetupFlow/Services/WinGetPackageRestoreDataSource.cs deleted file mode 100644 index 530e9bfe3..000000000 --- a/tools/SetupFlow/DevHome.SetupFlow/Services/WinGetPackageRestoreDataSource.cs +++ /dev/null @@ -1,175 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Threading.Tasks; -using DevHome.Common.Extensions; -using DevHome.Services.WindowsPackageManager.Contracts; -using DevHome.Services.WindowsPackageManager.Models; -using DevHome.SetupFlow.Models; -using DevHome.Telemetry; -using Microsoft.Diagnostics.Telemetry.Internal; -using Microsoft.Internal.Windows.DevHome.Helpers.Restore; -using Serilog; -using Windows.Storage.Streams; - -namespace DevHome.SetupFlow.Services; - -public class WinGetPackageRestoreDataSource : WinGetPackageDataSource -{ - private readonly ILogger _log = Log.ForContext("SourceContext", nameof(WinGetPackageRestoreDataSource)); - private readonly IRestoreInfo _restoreInfo; - private readonly ISetupFlowStringResource _stringResource; - private IRestoreDeviceInfo _restoreDeviceInfo; - - public WinGetPackageRestoreDataSource( - ISetupFlowStringResource stringResource, - IWinGet winget, - IRestoreInfo restoreInfo) - : base(winget) - { - _stringResource = stringResource; - _restoreInfo = restoreInfo; - } - - /// - /// Gets the total number of package catalogs available in this data source - /// - /// - /// Each collection of packages from a restore device is compiled into a - /// catalog. At most show one catalog. - /// - public override int CatalogCount => _restoreDeviceInfo == null ? 0 : 1; - - /// - /// Gets the restore device information - /// - public async override Task InitializeAsync() - { - var restoreDeviceInfoResult = await _restoreInfo.GetRestoreDeviceInfoAsync(); - if (restoreDeviceInfoResult.Status == RestoreDeviceInfoStatus.Ok) - { - _restoreDeviceInfo = restoreDeviceInfoResult.RestoreDeviceInfo; - TelemetryFactory.Get().Log("AppInstall_RestoreApps_Found", LogLevel.Critical, new EmptyEvent(PartA_PrivTags.ProductAndServicePerformance)); - } - else - { - _log.Warning($"Restore data source skipped with status: {restoreDeviceInfoResult.Status}"); - } - } - - public async override Task> LoadCatalogsAsync() - { - var result = new List(); - if (_restoreDeviceInfo == null) - { - _log.Warning($"Load catalogs skipped because no restore device information was found"); - return result; - } - - try - { - _log.Information("Finding packages from restore data"); - var packages = await GetPackagesAsync(_restoreDeviceInfo.WinGetApplicationsInfo.Select(p => GetPackageUri(p)).ToList()); - foreach (var package in packages) - { - var packageUri = WinGet.CreatePackageUri(package); - _log.Information($"Obtaining icon information for restore package {package.Id}"); - var appInfo = _restoreDeviceInfo.WinGetApplicationsInfo.FirstOrDefault(p => packageUri == GetPackageUri(p)); - if (appInfo != null) - { - package.LightThemeIcon = await GetRestoreApplicationIconAsync(appInfo, RestoreApplicationIconTheme.Light); - package.DarkThemeIcon = await GetRestoreApplicationIconAsync(appInfo, RestoreApplicationIconTheme.Dark); - } - } - - if (packages.Any()) - { - result.Add(new PackageCatalog() - { - Name = _stringResource.GetLocalized(StringResourceKey.RestorePackagesTitle, _restoreDeviceInfo.DisplayName), - Description = GetDescription(), - Packages = packages.ToReadOnlyCollection(), - }); - } - else - { - _log.Information("No packages found from restore"); - } - } - catch (Exception e) - { - _log.Error(e, $"Error loading packages from winget restore catalog."); - } - - if (result.Count > 0) - { - TelemetryFactory.Get().Log("AppInstall_RestoreApps_Loaded", LogLevel.Critical, new EmptyEvent(PartA_PrivTags.ProductAndServicePerformance)); - } - - return result; - } - - /// - /// Get the icon for a restore application based on the provided theme - /// - /// Restore application - /// Target theme - /// Restore application icon stream, or null if no corresponding icon was found - private async Task GetRestoreApplicationIconAsync(IRestoreApplicationInfo appInfo, RestoreApplicationIconTheme theme) - { - try - { - // Load icon from restore app data - var iconTask = appInfo.GetIconAsync(theme); - - // Check if no icon is available - if (iconTask != null) - { - var icon = await iconTask; - - // Ensure stream is not empty to prevent rendering an empty image - if (icon.Size > 0) - { - return icon; - } - } - } - catch (Exception e) - { - _log.Error(e, $"Failed to get icon for restore package {appInfo.Id}"); - } - - _log.Warning($"No {theme} icon found for restore package {appInfo.Id}. A default one will be provided."); - return null; - } - - /// - /// Gets the restore catalog description - /// - /// Localized restore catalog description - private string GetDescription() - { - // Check if last modified time is not available - if (_restoreDeviceInfo.LastModifiedTime == DateTime.MinValue) - { - return _stringResource.GetLocalized(StringResourceKey.RestorePackagesDescription, _restoreDeviceInfo.DisplayName); - } - - return _stringResource.GetLocalized(StringResourceKey.RestorePackagesDescriptionWithDate, _restoreDeviceInfo.DisplayName, _restoreDeviceInfo.LastModifiedTime.ToString("d", CultureInfo.CurrentCulture)); - } - - /// - /// Gets the package URI for a restore application - /// - /// Application information - /// Package URI - /// All restored applications are from winget catalog - private WinGetPackageUri GetPackageUri(IRestoreApplicationInfo appInfo) - { - return WinGet.CreateWinGetCatalogPackageUri(appInfo.Id); - } -} diff --git a/tools/SetupFlow/DevHome.SetupFlow/Strings/en-us/Resources.resw b/tools/SetupFlow/DevHome.SetupFlow/Strings/en-us/Resources.resw index c841bfdcf..c915664c7 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/Strings/en-us/Resources.resw +++ b/tools/SetupFlow/DevHome.SetupFlow/Strings/en-us/Resources.resw @@ -601,18 +601,6 @@ {0} Results found for "{1}" {Locked="{0}", "{1}"} Label for a search result counter. {0} is replaced by the number of result items. {1} is replaced with the search term. - - On {0} - {Locked="{0}"} Header text of a section for restoring packages from another device. {0} is replaced by a device name. - - - These applications are from {0}. Select the ones to install. - {Locked="{0}"} Description text of a section for restoring packages from another device. {0} is replaced by a device name. - - - These applications are from {0} (last synced on {1}). Select the ones to install. - {Locked="{0}","{1}"} Description text of a section for restoring packages from another device. {0} is replaced by a device name. {1} is replaced by a date. - {0} packages {Locked="{0}"} Display the number of packages. {0} is replaced by the number of packages. @@ -661,10 +649,6 @@ Previous Label for a "go to previous page" button - - Restore - Label for restore button - Generate Configuration file Text for a generating configuration file button diff --git a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/PackageViewModel.cs b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/PackageViewModel.cs index 89af8dfb9..e8435c0ef 100644 --- a/tools/SetupFlow/DevHome.SetupFlow/ViewModels/PackageViewModel.cs +++ b/tools/SetupFlow/DevHome.SetupFlow/ViewModels/PackageViewModel.cs @@ -11,7 +11,7 @@ using DevHome.Services.WindowsPackageManager.Contracts; using DevHome.SetupFlow.Models; using DevHome.SetupFlow.Services; -using Microsoft.Internal.Windows.DevHome.Helpers.Restore; +using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Media.Imaging; using Windows.Storage.Streams; using Windows.System; @@ -86,8 +86,8 @@ public PackageViewModel( _orchestrator = orchestrator; // Lazy-initialize optional or expensive view model members - _packageDarkThemeIcon = new Lazy(() => GetIconByTheme(RestoreApplicationIconTheme.Dark)); - _packageLightThemeIcon = new Lazy(() => GetIconByTheme(RestoreApplicationIconTheme.Light)); + _packageDarkThemeIcon = new Lazy(() => GetIconByTheme()); + _packageLightThemeIcon = new Lazy(() => GetIconByTheme()); SelectedVersion = GetDefaultSelectedVersion(); InstallPackageTask = CreateInstallTask(); @@ -203,20 +203,11 @@ private void ToggleSelection() _screenReaderService.Announce(announcementText); } - /// - /// Gets the package icon based on the provided theme - /// - /// Package icon theme - /// Package icon - private BitmapImage GetIconByTheme(RestoreApplicationIconTheme theme) + private BitmapImage GetIconByTheme() { - return theme switch + return _themeSelector.GetActualTheme() switch { - // Get default dark theme icon if corresponding package icon was not found - RestoreApplicationIconTheme.Dark => - _package.DarkThemeIcon == null ? DefaultDarkPackageIconSource : CreateBitmapImage(_package.DarkThemeIcon), - - // Get default light theme icon if corresponding package icon was not found + ElementTheme.Dark => _package.DarkThemeIcon == null ? DefaultDarkPackageIconSource : CreateBitmapImage(_package.DarkThemeIcon), _ => _package.LightThemeIcon == null ? DefaultLightPackageIconSource : CreateBitmapImage(_package.LightThemeIcon), }; } From c3b1703d0474c494aa7ec43df1b29c0bb33e1281 Mon Sep 17 00:00:00 2001 From: Kristen Schau <47155823+krschau@users.noreply.github.com> Date: Mon, 28 Oct 2024 10:14:33 -0400 Subject: [PATCH 48/58] Remove Dev Diagnostics Experimental Feature (#3955) * Remove Dev Diagnostics * Remove IfeoTool * Remove NTService --- DevHome.sln | 224 - docs/architecture.md | 5 - .../DevHome.Service.IDL.vcxproj | 167 - .../DevHome.Service.Projection.csproj | 24 - .../BasicClassWinRTFactory`1.cs | 81 - service/DevHome.Service/ComHelpers.cs | 146 - .../DevHome.Service/DevHome.Service.csproj | 31 - service/DevHome.Service/DevHomeService.cs | 97 - service/DevHome.Service/NativeMethods.json | 4 - service/DevHome.Service/NativeMethods.txt | 18 - service/DevHome.Service/Program.cs | 20 - .../ServiceLifetimeController.cs | 59 - .../WindowsBackgroundService.cs | 70 - .../Devhome.Service.IDL/DevHome.Service.idl | 19 - .../Devhome.Service.IDL.vcxproj.filters | 22 - .../Strings/en-us/Resources.resw | 8 - src/DevHome.csproj | 10 - src/NavConfig.jsonc | 24 - src/Package-Can.appxmanifest | 41 - src/Package-Dev.appxmanifest | 41 - src/Package.appxmanifest | 30 - src/Program.cs | 2 +- src/Properties/launchsettings.json | 10 - tools/DevDiagnostics/DD.ico | Bin 151604 -> 0 bytes tools/DevDiagnostics/DD.png | Bin 20891 -> 0 bytes .../TestingScenarios/DevDiagnostics.md | 25 - .../DevHome.DevDiagnostics/App.config | 74 - .../Assets/LargeTile.scale-100.png | Bin 7196 -> 0 bytes .../Assets/LargeTile.scale-125.png | Bin 9350 -> 0 bytes .../Assets/LargeTile.scale-150.png | Bin 11684 -> 0 bytes .../Assets/LargeTile.scale-200.png | Bin 16871 -> 0 bytes .../Assets/LargeTile.scale-400.png | Bin 44599 -> 0 bytes .../Assets/SmallTile.scale-100.png | Bin 2042 -> 0 bytes .../Assets/SmallTile.scale-125.png | Bin 2699 -> 0 bytes .../Assets/SmallTile.scale-150.png | Bin 3304 -> 0 bytes .../Assets/SmallTile.scale-200.png | Bin 4374 -> 0 bytes .../Assets/SmallTile.scale-400.png | Bin 9600 -> 0 bytes .../Assets/SplashScreen.scale-100.png | Bin 7884 -> 0 bytes .../Assets/SplashScreen.scale-125.png | Bin 9858 -> 0 bytes .../Assets/SplashScreen.scale-150.png | Bin 12563 -> 0 bytes .../Assets/SplashScreen.scale-200.png | Bin 17965 -> 0 bytes .../Assets/SplashScreen.scale-400.png | Bin 49228 -> 0 bytes .../Assets/Square150x150Logo.scale-100.png | Bin 3362 -> 0 bytes .../Assets/Square150x150Logo.scale-125.png | Bin 4144 -> 0 bytes .../Assets/Square150x150Logo.scale-150.png | Bin 5160 -> 0 bytes .../Assets/Square150x150Logo.scale-200.png | Bin 7161 -> 0 bytes .../Assets/Square150x150Logo.scale-400.png | Bin 16077 -> 0 bytes ...go.altform-lightunplated_targetsize-16.png | Bin 716 -> 0 bytes ...go.altform-lightunplated_targetsize-24.png | Bin 1168 -> 0 bytes ...o.altform-lightunplated_targetsize-256.png | Bin 17717 -> 0 bytes ...go.altform-lightunplated_targetsize-32.png | Bin 1583 -> 0 bytes ...go.altform-lightunplated_targetsize-48.png | Bin 2583 -> 0 bytes ...x44Logo.altform-unplated_targetsize-16.png | Bin 716 -> 0 bytes ...44Logo.altform-unplated_targetsize-256.png | Bin 17717 -> 0 bytes ...x44Logo.altform-unplated_targetsize-32.png | Bin 1583 -> 0 bytes ...x44Logo.altform-unplated_targetsize-48.png | Bin 2583 -> 0 bytes .../Assets/Square44x44Logo.scale-100.png | Bin 1634 -> 0 bytes .../Assets/Square44x44Logo.scale-125.png | Bin 2287 -> 0 bytes .../Assets/Square44x44Logo.scale-150.png | Bin 2891 -> 0 bytes .../Assets/Square44x44Logo.scale-200.png | Bin 3832 -> 0 bytes .../Assets/Square44x44Logo.scale-400.png | Bin 7932 -> 0 bytes .../Assets/Square44x44Logo.targetsize-16.png | Bin 566 -> 0 bytes .../Assets/Square44x44Logo.targetsize-24.png | Bin 824 -> 0 bytes ...x44Logo.targetsize-24_altform-unplated.png | Bin 1168 -> 0 bytes .../Assets/Square44x44Logo.targetsize-256.png | Bin 12692 -> 0 bytes .../Assets/Square44x44Logo.targetsize-32.png | Bin 1206 -> 0 bytes .../Assets/Square44x44Logo.targetsize-48.png | Bin 1970 -> 0 bytes .../Assets/StoreLogo.scale-100.png | Bin 2751 -> 0 bytes .../Assets/StoreLogo.scale-125.png | Bin 3454 -> 0 bytes .../Assets/StoreLogo.scale-150.png | Bin 4201 -> 0 bytes .../Assets/StoreLogo.scale-200.png | Bin 5726 -> 0 bytes .../Assets/StoreLogo.scale-400.png | Bin 12054 -> 0 bytes .../Assets/Wide310x150Logo.scale-100.png | Bin 3596 -> 0 bytes .../Assets/Wide310x150Logo.scale-125.png | Bin 4412 -> 0 bytes .../Assets/Wide310x150Logo.scale-150.png | Bin 5573 -> 0 bytes .../Assets/Wide310x150Logo.scale-200.png | Bin 7884 -> 0 bytes .../Assets/Wide310x150Logo.scale-400.png | Bin 17965 -> 0 bytes .../Contracts/ViewModels/INavigationAware.cs | 12 - .../Controls/AddToolControl.xaml | 183 - .../Controls/AddToolControl.xaml.cs | 514 -- .../Controls/ClipboardMonitorControl.xaml | 44 - .../Controls/ClipboardMonitorControl.xaml.cs | 17 - .../Controls/DDSeparator.xaml | 31 - .../Controls/DDSeparator.xaml.cs | 38 - .../Controls/EditToolsControl.xaml | 55 - .../Controls/EditToolsControl.xaml.cs | 55 - .../Controls/ElevatedButtonControl.xaml | 19 - .../Controls/ElevatedButtonControl.xaml.cs | 55 - .../Controls/ExpandedViewControl.xaml | 102 - .../Controls/ExpandedViewControl.xaml.cs | 40 - .../Controls/ExternalToolsManagementButton.cs | 263 - ...rMissingFileProcessTerminationControl.xaml | 24 - ...ssingFileProcessTerminationControl.xaml.cs | 47 - .../Controls/InsightSimpleTextControl.xaml | 14 - .../Controls/InsightSimpleTextControl.xaml.cs | 29 - .../Controls/ProcessSelectionButton.cs | 68 - .../Controls/ProgressTextRing.xaml | 34 - .../Controls/ProgressTextRing.xaml.cs | 74 - .../DevHome.DevDiagnostics/DD.ico | Bin 151604 -> 0 bytes .../DevHome.DevDiagnostics/DDApp.xaml | 68 - .../DevHome.DevDiagnostics/DDApp.xaml.cs | 150 - .../DevHome.DevDiagnostics.csproj | 243 - .../Helpers/ClipboardMonitorInternalTool.cs | 71 - .../Helpers/CommonHelper.cs | 208 - .../Helpers/CommonInterop.cs | 21 - .../Helpers/CountToVisibilityConverter.cs | 22 - .../Helpers/DebugMonitor.cs | 153 - .../Helpers/ETWHelper.cs | 187 - .../Helpers/EnumStringConverter.cs | 35 - .../Helpers/ErrorLookupHelper.cs | 90 - .../Helpers/EventViewerHelper.cs | 82 - .../Helpers/ExpanderBehavior.cs | 39 - .../Helpers/ExternalTool.cs | 313 - .../Helpers/ExternalToolCollection.cs | 25 - .../Helpers/ExternalTool_v1.cs | 50 - .../Helpers/ExternalToolsHelper.cs | 300 - .../Helpers/HotKeyHelper.cs | 74 - .../Helpers/IApplicationActivationManager.cs | 39 - .../Helpers/ImageOptionsInternalTool.cs | 108 - .../Helpers/InsightsHelper.cs | 214 - .../Helpers/InternalToolsHelper.cs | 24 - .../Helpers/LoaderSnapAssistantTool.cs | 260 - .../Helpers/RestartManagerHelper.cs | 110 - .../Helpers/ServicingHelper.cs | 51 - .../Helpers/StandInDevHomeService.cs | 22 - .../DevHome.DevDiagnostics/Helpers/Tool.cs | 114 - .../Helpers/WERUtils.cs | 118 - .../Helpers/WinLogsHelper.cs | 269 - .../Helpers/WindowHelper.cs | 770 -- .../Helpers/WindowHooker`1.cs | 86 - .../DevHome.DevDiagnostics/Images/DD.ico | Bin 151604 -> 0 bytes .../Models/AppRuntimeInfo.cs | 133 - .../Models/ClipboardContents.cs | 26 - .../Models/ClipboardMonitor.cs | 187 - .../Models/FrameworkType.cs | 28 - .../DevHome.DevDiagnostics/Models/Insight.cs | 71 - .../Models/InstalledAppInfo.cs | 38 - .../DevHome.DevDiagnostics/Models/NavLink.cs | 30 - .../Models/PackageInfo.cs | 39 - .../Models/PerfCounters.cs | 230 - .../Models/ProcessModuleInfo.cs | 41 - .../DevHome.DevDiagnostics/Models/Setting.cs | 23 - .../Models/TargetAppData.cs | 170 - .../Models/ThemeName.cs | 23 - .../Models/WERAnalysis.cs | 114 - .../Models/WERAnalysisReport.cs | 79 - .../Models/WERAnalyzer.cs | 187 - .../Models/WERHelper.cs | 438 - .../Models/WERReport.cs | 46 - .../Models/WinLogsEntry.cs | 51 - .../DevHome.DevDiagnostics/NativeMethods.json | 4 - .../DevHome.DevDiagnostics/NativeMethods.txt | 121 - .../Pages/AboutPage.xaml | 47 - .../Pages/AboutPage.xaml.cs | 20 - .../Pages/AdditionalToolsPage.xaml | 46 - .../Pages/AdditionalToolsPage.xaml.cs | 25 - .../Pages/AdvancedSettingsPage.xaml | 67 - .../Pages/AdvancedSettingsPage.xaml.cs | 77 - .../Pages/AppDetailsPage.xaml | 168 - .../Pages/AppDetailsPage.xaml.cs | 28 - .../Pages/InsightsPage.xaml | 60 - .../Pages/InsightsPage.xaml.cs | 28 - .../Pages/ModulesPage.xaml | 78 - .../Pages/ModulesPage.xaml.cs | 34 - .../Pages/PreferencesPage.xaml | 45 - .../Pages/PreferencesPage.xaml.cs | 34 - .../Pages/ProcessListPage.xaml | 84 - .../Pages/ProcessListPage.xaml.cs | 29 - .../Pages/ResourceUsagePage.xaml | 61 - .../Pages/ResourceUsagePage.xaml.cs | 35 - .../Pages/SettingsPage.xaml | 43 - .../Pages/SettingsPage.xaml.cs | 18 - .../DevHome.DevDiagnostics/Pages/WERPage.xaml | 100 - .../Pages/WERPage.xaml.cs | 145 - .../Pages/WinLogsPage.xaml | 117 - .../Pages/WinLogsPage.xaml.cs | 39 - .../DevHome.DevDiagnostics/Program.cs | 251 - .../PublishProfiles/win-arm64.pubxml | 16 - .../Properties/PublishProfiles/win-x64.pubxml | 16 - .../Properties/PublishProfiles/win-x86.pubxml | 16 - .../Properties/Settings.Designer.cs | 256 - .../Properties/Settings.settings | 67 - .../Properties/launchSettings.json | 8 - .../Services/DDAppInfoService.cs | 28 - .../Services/DDInsightsService.cs | 70 - .../Services/DDNavigationService.cs | 166 - .../Services/DDPageService.cs | 73 - .../Strings/en-us/Resources.resw | 1325 --- .../Styles/CommandBarStyle.xaml | 838 -- .../Telemetry/FeatureState.cs | 66 - .../Telemetry/FocusStartEventData.cs | 16 - .../Telemetry/FocusStopEventData.cs | 16 - .../Telemetry/LogStateChangedEventData.cs | 30 - .../Telemetry/TelemetryReporter.cs | 171 - .../Telemetry/TimedStartEventBase.cs | 30 - .../Telemetry/TimedStopEventBase.cs | 30 - .../Telemetry/UsageEventData.cs | 21 - .../Telemetry/VisibilityStartEventData.cs | 16 - .../Telemetry/VisibilityStopEventData.cs | 16 - .../Telemetry/WindowEventGenerator.cs | 165 - .../ViewModels/AboutViewModel.cs | 41 - .../ViewModels/AdditionalToolsViewModel.cs | 26 - .../ViewModels/AdvancedSettingsViewModel.cs | 26 - .../ViewModels/AppDetailsPageViewModel.cs | 276 - .../ViewModels/BarWindowViewModel.cs | 271 - .../ClipboardMonitorControlViewModel.cs | 73 - .../ExpandedViewControlViewModel.cs | 266 - .../ViewModels/InsightsPageViewModel.cs | 21 - .../ViewModels/ModulesPageViewModel.cs | 109 - .../ViewModels/PreferencesViewModel.cs | 48 - .../ViewModels/ProcessListPageViewModel.cs | 192 - .../ViewModels/ResourceUsagePageViewModel.cs | 105 - .../ViewModels/SettingViewModel.cs | 35 - .../ViewModels/SettingsPageViewModel.cs | 68 - .../ViewModels/WERPageViewModel.cs | 287 - .../ViewModels/WinLogsPageViewModel.cs | 286 - .../Views/BarWindow.xaml | 221 - .../Views/BarWindow.xaml.cs | 644 -- .../Views/ClipboardMonitoringWindow.xaml | 42 - .../Views/ClipboardMonitoringWindow.xaml.cs | 22 - .../Views/PrimaryWindow.xaml | 13 - .../Views/PrimaryWindow.xaml.cs | 117 - .../DevHome.DevDiagnostics/app.manifest | 19 - .../appsettings_dd.json | 31 - .../DevHome.DevDiagnostics/errors.db | Bin 856064 -> 0 bytes .../DevHome.DevDiagnostics/errors.db.txt | 7434 ----------------- .../ErrorDBPopulateTool.csproj | 34 - .../ErrorDBPopulateTool.sln | 25 - .../ErrorDBPopulateTool/HRESULTS.txt | 5856 ------------- .../ErrorDBPopulateTool/NTStatus.txt | 3590 -------- .../ErrorDBPopulateTool/Program.cs | 91 - .../ErrorDBPopulateTool/Win32Errors.txt | 5408 ------------ .../ErrorDBPopulateTool/readme.md | 21 - .../TestTools/TestDumpAnalyzer/Program.cs | 35 - .../TestDumpAnalyzer/TestDumpAnalyzer.csproj | 10 - .../TestDumpAnalyzer/TestDumpAnalyzer.sln | 37 - .../TestLoadFailure/TestLoadFailure.cpp | 15 - .../TestLoadFailure/TestLoadFailure.sln | 31 - .../TestLoadFailure/TestLoadFailure.vcxproj | 146 - .../TestLoadFailure.vcxproj.filters | 22 - .../TestTools/TestServiceCaller/Program.cs | 43 - .../TestServiceCaller.csproj | 23 - .../EnableLoaderSnaps/EnableLoaderSnaps.cs | 52 - .../EnableLoaderSnaps.csproj | 13 - .../Utilities/EnableLoaderSnaps/app.manifest | 18 - .../EnableLocalCabCollection.cs | 28 - .../EnableLocalCabCollection.csproj | 16 - .../EnableLocalCabCollection/app.manifest | 17 - .../IfeoTool/Assets/LargeTile.scale-100.png | Bin 7196 -> 0 bytes .../IfeoTool/Assets/LargeTile.scale-125.png | Bin 9350 -> 0 bytes .../IfeoTool/Assets/LargeTile.scale-150.png | Bin 11684 -> 0 bytes .../IfeoTool/Assets/LargeTile.scale-200.png | Bin 16871 -> 0 bytes .../IfeoTool/Assets/LargeTile.scale-400.png | Bin 44599 -> 0 bytes .../IfeoTool/Assets/SmallTile.scale-100.png | Bin 2042 -> 0 bytes .../IfeoTool/Assets/SmallTile.scale-125.png | Bin 2699 -> 0 bytes .../IfeoTool/Assets/SmallTile.scale-150.png | Bin 3304 -> 0 bytes .../IfeoTool/Assets/SmallTile.scale-200.png | Bin 4374 -> 0 bytes .../IfeoTool/Assets/SmallTile.scale-400.png | Bin 9600 -> 0 bytes .../Assets/SplashScreen.scale-100.png | Bin 7884 -> 0 bytes .../Assets/SplashScreen.scale-125.png | Bin 9858 -> 0 bytes .../Assets/SplashScreen.scale-150.png | Bin 12563 -> 0 bytes .../Assets/SplashScreen.scale-200.png | Bin 17965 -> 0 bytes .../Assets/SplashScreen.scale-400.png | Bin 49228 -> 0 bytes .../Assets/Square150x150Logo.scale-100.png | Bin 3362 -> 0 bytes .../Assets/Square150x150Logo.scale-125.png | Bin 4144 -> 0 bytes .../Assets/Square150x150Logo.scale-150.png | Bin 5160 -> 0 bytes .../Assets/Square150x150Logo.scale-200.png | Bin 7161 -> 0 bytes .../Assets/Square150x150Logo.scale-400.png | Bin 16077 -> 0 bytes ...go.altform-lightunplated_targetsize-16.png | Bin 716 -> 0 bytes ...go.altform-lightunplated_targetsize-24.png | Bin 1168 -> 0 bytes ...o.altform-lightunplated_targetsize-256.png | Bin 17717 -> 0 bytes ...go.altform-lightunplated_targetsize-32.png | Bin 1583 -> 0 bytes ...go.altform-lightunplated_targetsize-48.png | Bin 2583 -> 0 bytes ...x44Logo.altform-unplated_targetsize-16.png | Bin 716 -> 0 bytes ...44Logo.altform-unplated_targetsize-256.png | Bin 17717 -> 0 bytes ...x44Logo.altform-unplated_targetsize-32.png | Bin 1583 -> 0 bytes ...x44Logo.altform-unplated_targetsize-48.png | Bin 2583 -> 0 bytes .../Assets/Square44x44Logo.scale-100.png | Bin 1634 -> 0 bytes .../Assets/Square44x44Logo.scale-125.png | Bin 2287 -> 0 bytes .../Assets/Square44x44Logo.scale-150.png | Bin 2891 -> 0 bytes .../Assets/Square44x44Logo.scale-200.png | Bin 3832 -> 0 bytes .../Assets/Square44x44Logo.scale-400.png | Bin 7932 -> 0 bytes .../Assets/Square44x44Logo.targetsize-16.png | Bin 566 -> 0 bytes .../Assets/Square44x44Logo.targetsize-24.png | Bin 824 -> 0 bytes ...x44Logo.targetsize-24_altform-unplated.png | Bin 1168 -> 0 bytes .../Assets/Square44x44Logo.targetsize-256.png | Bin 12692 -> 0 bytes .../Assets/Square44x44Logo.targetsize-32.png | Bin 1206 -> 0 bytes .../Assets/Square44x44Logo.targetsize-48.png | Bin 1970 -> 0 bytes .../IfeoTool/Assets/StoreLogo.scale-100.png | Bin 2751 -> 0 bytes .../IfeoTool/Assets/StoreLogo.scale-125.png | Bin 3454 -> 0 bytes .../IfeoTool/Assets/StoreLogo.scale-150.png | Bin 4201 -> 0 bytes .../IfeoTool/Assets/StoreLogo.scale-200.png | Bin 5726 -> 0 bytes .../IfeoTool/Assets/StoreLogo.scale-400.png | Bin 12054 -> 0 bytes .../Assets/Wide310x150Logo.scale-100.png | Bin 3596 -> 0 bytes .../Assets/Wide310x150Logo.scale-125.png | Bin 4412 -> 0 bytes .../Assets/Wide310x150Logo.scale-150.png | Bin 5573 -> 0 bytes .../Assets/Wide310x150Logo.scale-200.png | Bin 7884 -> 0 bytes .../Assets/Wide310x150Logo.scale-400.png | Bin 17965 -> 0 bytes .../IfeoTool/DevHome.IfeoTool.csproj | 41 - tools/Utilities/IfeoTool/IfeoToolApp.xaml | 17 - tools/Utilities/IfeoTool/IfeoToolApp.xaml.cs | 112 - tools/Utilities/IfeoTool/IfeoToolWindow.xaml | 37 - .../Utilities/IfeoTool/IfeoToolWindow.xaml.cs | 52 - .../IfeoTool/ImageFileExecutionOptions.cs | 199 - .../IfeoTool/ImageOptionsControlViewModel.cs | 99 - tools/Utilities/IfeoTool/NativeMethods.json | 4 - tools/Utilities/IfeoTool/NativeMethods.txt | 4 - tools/Utilities/IfeoTool/Program.cs | 91 - .../PublishProfiles/win-arm64.pubxml | 16 - .../Properties/PublishProfiles/win-x64.pubxml | 16 - .../Properties/PublishProfiles/win-x86.pubxml | 16 - .../IfeoTool/Properties/launchSettings.json | 7 - .../IfeoTool/Strings/en-us/Resources.resw | 129 - .../Telemetry/IfeoToolAppLaunchEvent.cs | 25 - .../Telemetry/IfeoToolGlobalFlagsChanged.cs | 32 - .../IfeoTool/Telemetry/IfeoToolTraceEvent.cs | 25 - tools/Utilities/IfeoTool/app.manifest | 19 - .../IfeoTool/appsettings_ifeotool.json | 31 - .../src/Strings/en-us/Resources.resw | 8 - .../ViewModels/UtilitiesMainPageViewModel.cs | 8 - uitest/UtilitiesTest.cs | 4 +- 321 files changed, 2 insertions(+), 41694 deletions(-) delete mode 100644 service/DevHome.Service.IDL/DevHome.Service.IDL.vcxproj delete mode 100644 service/DevHome.Service.Projection/DevHome.Service.Projection.csproj delete mode 100644 service/DevHome.Service/BasicClassWinRTFactory`1.cs delete mode 100644 service/DevHome.Service/ComHelpers.cs delete mode 100644 service/DevHome.Service/DevHome.Service.csproj delete mode 100644 service/DevHome.Service/DevHomeService.cs delete mode 100644 service/DevHome.Service/NativeMethods.json delete mode 100644 service/DevHome.Service/NativeMethods.txt delete mode 100644 service/DevHome.Service/Program.cs delete mode 100644 service/DevHome.Service/ServiceLifetimeController.cs delete mode 100644 service/DevHome.Service/WindowsBackgroundService.cs delete mode 100644 service/Devhome.Service.IDL/DevHome.Service.idl delete mode 100644 service/Devhome.Service.IDL/Devhome.Service.IDL.vcxproj.filters delete mode 100644 tools/DevDiagnostics/DD.ico delete mode 100644 tools/DevDiagnostics/DD.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics.UnitTest/TestingScenarios/DevDiagnostics.md delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/App.config delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/LargeTile.scale-100.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/LargeTile.scale-125.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/LargeTile.scale-150.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/LargeTile.scale-200.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/LargeTile.scale-400.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/SmallTile.scale-100.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/SmallTile.scale-125.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/SmallTile.scale-150.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/SmallTile.scale-200.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/SmallTile.scale-400.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/SplashScreen.scale-100.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/SplashScreen.scale-125.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/SplashScreen.scale-150.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/SplashScreen.scale-200.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/SplashScreen.scale-400.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Square150x150Logo.scale-100.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Square150x150Logo.scale-125.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Square150x150Logo.scale-150.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Square150x150Logo.scale-200.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Square150x150Logo.scale-400.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Square44x44Logo.altform-lightunplated_targetsize-16.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Square44x44Logo.altform-lightunplated_targetsize-24.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Square44x44Logo.altform-lightunplated_targetsize-256.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Square44x44Logo.altform-lightunplated_targetsize-32.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Square44x44Logo.altform-lightunplated_targetsize-48.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Square44x44Logo.altform-unplated_targetsize-16.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Square44x44Logo.altform-unplated_targetsize-256.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Square44x44Logo.altform-unplated_targetsize-32.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Square44x44Logo.altform-unplated_targetsize-48.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Square44x44Logo.scale-100.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Square44x44Logo.scale-125.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Square44x44Logo.scale-150.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Square44x44Logo.scale-200.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Square44x44Logo.scale-400.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Square44x44Logo.targetsize-16.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Square44x44Logo.targetsize-24.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Square44x44Logo.targetsize-24_altform-unplated.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Square44x44Logo.targetsize-256.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Square44x44Logo.targetsize-32.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Square44x44Logo.targetsize-48.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/StoreLogo.scale-100.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/StoreLogo.scale-125.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/StoreLogo.scale-150.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/StoreLogo.scale-200.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/StoreLogo.scale-400.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Wide310x150Logo.scale-100.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Wide310x150Logo.scale-125.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Wide310x150Logo.scale-150.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Wide310x150Logo.scale-200.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Wide310x150Logo.scale-400.png delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Contracts/ViewModels/INavigationAware.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/AddToolControl.xaml delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/AddToolControl.xaml.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/ClipboardMonitorControl.xaml delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/ClipboardMonitorControl.xaml.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/DDSeparator.xaml delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/DDSeparator.xaml.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/EditToolsControl.xaml delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/EditToolsControl.xaml.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/ElevatedButtonControl.xaml delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/ElevatedButtonControl.xaml.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/ExpandedViewControl.xaml delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/ExpandedViewControl.xaml.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/ExternalToolsManagementButton.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/InsightForMissingFileProcessTerminationControl.xaml delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/InsightForMissingFileProcessTerminationControl.xaml.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/InsightSimpleTextControl.xaml delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/InsightSimpleTextControl.xaml.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/ProcessSelectionButton.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/ProgressTextRing.xaml delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/ProgressTextRing.xaml.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/DD.ico delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/DDApp.xaml delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/DDApp.xaml.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/DevHome.DevDiagnostics.csproj delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/ClipboardMonitorInternalTool.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/CommonHelper.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/CommonInterop.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/CountToVisibilityConverter.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/DebugMonitor.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/ETWHelper.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/EnumStringConverter.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/ErrorLookupHelper.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/EventViewerHelper.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/ExpanderBehavior.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/ExternalTool.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/ExternalToolCollection.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/ExternalTool_v1.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/ExternalToolsHelper.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/HotKeyHelper.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/IApplicationActivationManager.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/ImageOptionsInternalTool.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/InsightsHelper.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/InternalToolsHelper.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/LoaderSnapAssistantTool.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/RestartManagerHelper.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/ServicingHelper.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/StandInDevHomeService.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/Tool.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/WERUtils.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/WinLogsHelper.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/WindowHelper.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/WindowHooker`1.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Images/DD.ico delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Models/AppRuntimeInfo.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Models/ClipboardContents.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Models/ClipboardMonitor.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Models/FrameworkType.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Models/Insight.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Models/InstalledAppInfo.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Models/NavLink.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Models/PackageInfo.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Models/PerfCounters.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Models/ProcessModuleInfo.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Models/Setting.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Models/TargetAppData.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Models/ThemeName.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Models/WERAnalysis.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Models/WERAnalysisReport.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Models/WERAnalyzer.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Models/WERHelper.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Models/WERReport.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Models/WinLogsEntry.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/NativeMethods.json delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/NativeMethods.txt delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/AboutPage.xaml delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/AboutPage.xaml.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/AdditionalToolsPage.xaml delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/AdditionalToolsPage.xaml.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/AdvancedSettingsPage.xaml delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/AdvancedSettingsPage.xaml.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/AppDetailsPage.xaml delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/AppDetailsPage.xaml.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/InsightsPage.xaml delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/InsightsPage.xaml.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/ModulesPage.xaml delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/ModulesPage.xaml.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/PreferencesPage.xaml delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/PreferencesPage.xaml.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/ProcessListPage.xaml delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/ProcessListPage.xaml.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/ResourceUsagePage.xaml delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/ResourceUsagePage.xaml.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/SettingsPage.xaml delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/SettingsPage.xaml.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/WERPage.xaml delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/WERPage.xaml.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/WinLogsPage.xaml delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/WinLogsPage.xaml.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Program.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Properties/PublishProfiles/win-arm64.pubxml delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Properties/PublishProfiles/win-x64.pubxml delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Properties/PublishProfiles/win-x86.pubxml delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Properties/Settings.Designer.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Properties/Settings.settings delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Properties/launchSettings.json delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Services/DDAppInfoService.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Services/DDInsightsService.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Services/DDNavigationService.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Services/DDPageService.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Strings/en-us/Resources.resw delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Styles/CommandBarStyle.xaml delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Telemetry/FeatureState.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Telemetry/FocusStartEventData.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Telemetry/FocusStopEventData.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Telemetry/LogStateChangedEventData.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Telemetry/TelemetryReporter.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Telemetry/TimedStartEventBase.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Telemetry/TimedStopEventBase.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Telemetry/UsageEventData.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Telemetry/VisibilityStartEventData.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Telemetry/VisibilityStopEventData.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Telemetry/WindowEventGenerator.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/ViewModels/AboutViewModel.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/ViewModels/AdditionalToolsViewModel.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/ViewModels/AdvancedSettingsViewModel.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/ViewModels/AppDetailsPageViewModel.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/ViewModels/BarWindowViewModel.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/ViewModels/ClipboardMonitorControlViewModel.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/ViewModels/ExpandedViewControlViewModel.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/ViewModels/InsightsPageViewModel.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/ViewModels/ModulesPageViewModel.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/ViewModels/PreferencesViewModel.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/ViewModels/ProcessListPageViewModel.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/ViewModels/ResourceUsagePageViewModel.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/ViewModels/SettingViewModel.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/ViewModels/SettingsPageViewModel.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/ViewModels/WERPageViewModel.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/ViewModels/WinLogsPageViewModel.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Views/BarWindow.xaml delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Views/BarWindow.xaml.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Views/ClipboardMonitoringWindow.xaml delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Views/ClipboardMonitoringWindow.xaml.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Views/PrimaryWindow.xaml delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/Views/PrimaryWindow.xaml.cs delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/app.manifest delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/appsettings_dd.json delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/errors.db delete mode 100644 tools/DevDiagnostics/DevHome.DevDiagnostics/errors.db.txt delete mode 100644 tools/DevDiagnostics/ErrorDBPopulateTool/ErrorDBPopulateTool.csproj delete mode 100644 tools/DevDiagnostics/ErrorDBPopulateTool/ErrorDBPopulateTool.sln delete mode 100644 tools/DevDiagnostics/ErrorDBPopulateTool/HRESULTS.txt delete mode 100644 tools/DevDiagnostics/ErrorDBPopulateTool/NTStatus.txt delete mode 100644 tools/DevDiagnostics/ErrorDBPopulateTool/Program.cs delete mode 100644 tools/DevDiagnostics/ErrorDBPopulateTool/Win32Errors.txt delete mode 100644 tools/DevDiagnostics/ErrorDBPopulateTool/readme.md delete mode 100644 tools/DevDiagnostics/TestTools/TestDumpAnalyzer/Program.cs delete mode 100644 tools/DevDiagnostics/TestTools/TestDumpAnalyzer/TestDumpAnalyzer.csproj delete mode 100644 tools/DevDiagnostics/TestTools/TestDumpAnalyzer/TestDumpAnalyzer.sln delete mode 100644 tools/DevDiagnostics/TestTools/TestLoadFailure/TestLoadFailure.cpp delete mode 100644 tools/DevDiagnostics/TestTools/TestLoadFailure/TestLoadFailure.sln delete mode 100644 tools/DevDiagnostics/TestTools/TestLoadFailure/TestLoadFailure.vcxproj delete mode 100644 tools/DevDiagnostics/TestTools/TestLoadFailure/TestLoadFailure.vcxproj.filters delete mode 100644 tools/DevDiagnostics/TestTools/TestServiceCaller/Program.cs delete mode 100644 tools/DevDiagnostics/TestTools/TestServiceCaller/TestServiceCaller.csproj delete mode 100644 tools/DevDiagnostics/Utilities/EnableLoaderSnaps/EnableLoaderSnaps.cs delete mode 100644 tools/DevDiagnostics/Utilities/EnableLoaderSnaps/EnableLoaderSnaps.csproj delete mode 100644 tools/DevDiagnostics/Utilities/EnableLoaderSnaps/app.manifest delete mode 100644 tools/DevDiagnostics/Utilities/EnableLocalCabCollection/EnableLocalCabCollection.cs delete mode 100644 tools/DevDiagnostics/Utilities/EnableLocalCabCollection/EnableLocalCabCollection.csproj delete mode 100644 tools/DevDiagnostics/Utilities/EnableLocalCabCollection/app.manifest delete mode 100644 tools/Utilities/IfeoTool/Assets/LargeTile.scale-100.png delete mode 100644 tools/Utilities/IfeoTool/Assets/LargeTile.scale-125.png delete mode 100644 tools/Utilities/IfeoTool/Assets/LargeTile.scale-150.png delete mode 100644 tools/Utilities/IfeoTool/Assets/LargeTile.scale-200.png delete mode 100644 tools/Utilities/IfeoTool/Assets/LargeTile.scale-400.png delete mode 100644 tools/Utilities/IfeoTool/Assets/SmallTile.scale-100.png delete mode 100644 tools/Utilities/IfeoTool/Assets/SmallTile.scale-125.png delete mode 100644 tools/Utilities/IfeoTool/Assets/SmallTile.scale-150.png delete mode 100644 tools/Utilities/IfeoTool/Assets/SmallTile.scale-200.png delete mode 100644 tools/Utilities/IfeoTool/Assets/SmallTile.scale-400.png delete mode 100644 tools/Utilities/IfeoTool/Assets/SplashScreen.scale-100.png delete mode 100644 tools/Utilities/IfeoTool/Assets/SplashScreen.scale-125.png delete mode 100644 tools/Utilities/IfeoTool/Assets/SplashScreen.scale-150.png delete mode 100644 tools/Utilities/IfeoTool/Assets/SplashScreen.scale-200.png delete mode 100644 tools/Utilities/IfeoTool/Assets/SplashScreen.scale-400.png delete mode 100644 tools/Utilities/IfeoTool/Assets/Square150x150Logo.scale-100.png delete mode 100644 tools/Utilities/IfeoTool/Assets/Square150x150Logo.scale-125.png delete mode 100644 tools/Utilities/IfeoTool/Assets/Square150x150Logo.scale-150.png delete mode 100644 tools/Utilities/IfeoTool/Assets/Square150x150Logo.scale-200.png delete mode 100644 tools/Utilities/IfeoTool/Assets/Square150x150Logo.scale-400.png delete mode 100644 tools/Utilities/IfeoTool/Assets/Square44x44Logo.altform-lightunplated_targetsize-16.png delete mode 100644 tools/Utilities/IfeoTool/Assets/Square44x44Logo.altform-lightunplated_targetsize-24.png delete mode 100644 tools/Utilities/IfeoTool/Assets/Square44x44Logo.altform-lightunplated_targetsize-256.png delete mode 100644 tools/Utilities/IfeoTool/Assets/Square44x44Logo.altform-lightunplated_targetsize-32.png delete mode 100644 tools/Utilities/IfeoTool/Assets/Square44x44Logo.altform-lightunplated_targetsize-48.png delete mode 100644 tools/Utilities/IfeoTool/Assets/Square44x44Logo.altform-unplated_targetsize-16.png delete mode 100644 tools/Utilities/IfeoTool/Assets/Square44x44Logo.altform-unplated_targetsize-256.png delete mode 100644 tools/Utilities/IfeoTool/Assets/Square44x44Logo.altform-unplated_targetsize-32.png delete mode 100644 tools/Utilities/IfeoTool/Assets/Square44x44Logo.altform-unplated_targetsize-48.png delete mode 100644 tools/Utilities/IfeoTool/Assets/Square44x44Logo.scale-100.png delete mode 100644 tools/Utilities/IfeoTool/Assets/Square44x44Logo.scale-125.png delete mode 100644 tools/Utilities/IfeoTool/Assets/Square44x44Logo.scale-150.png delete mode 100644 tools/Utilities/IfeoTool/Assets/Square44x44Logo.scale-200.png delete mode 100644 tools/Utilities/IfeoTool/Assets/Square44x44Logo.scale-400.png delete mode 100644 tools/Utilities/IfeoTool/Assets/Square44x44Logo.targetsize-16.png delete mode 100644 tools/Utilities/IfeoTool/Assets/Square44x44Logo.targetsize-24.png delete mode 100644 tools/Utilities/IfeoTool/Assets/Square44x44Logo.targetsize-24_altform-unplated.png delete mode 100644 tools/Utilities/IfeoTool/Assets/Square44x44Logo.targetsize-256.png delete mode 100644 tools/Utilities/IfeoTool/Assets/Square44x44Logo.targetsize-32.png delete mode 100644 tools/Utilities/IfeoTool/Assets/Square44x44Logo.targetsize-48.png delete mode 100644 tools/Utilities/IfeoTool/Assets/StoreLogo.scale-100.png delete mode 100644 tools/Utilities/IfeoTool/Assets/StoreLogo.scale-125.png delete mode 100644 tools/Utilities/IfeoTool/Assets/StoreLogo.scale-150.png delete mode 100644 tools/Utilities/IfeoTool/Assets/StoreLogo.scale-200.png delete mode 100644 tools/Utilities/IfeoTool/Assets/StoreLogo.scale-400.png delete mode 100644 tools/Utilities/IfeoTool/Assets/Wide310x150Logo.scale-100.png delete mode 100644 tools/Utilities/IfeoTool/Assets/Wide310x150Logo.scale-125.png delete mode 100644 tools/Utilities/IfeoTool/Assets/Wide310x150Logo.scale-150.png delete mode 100644 tools/Utilities/IfeoTool/Assets/Wide310x150Logo.scale-200.png delete mode 100644 tools/Utilities/IfeoTool/Assets/Wide310x150Logo.scale-400.png delete mode 100644 tools/Utilities/IfeoTool/DevHome.IfeoTool.csproj delete mode 100644 tools/Utilities/IfeoTool/IfeoToolApp.xaml delete mode 100644 tools/Utilities/IfeoTool/IfeoToolApp.xaml.cs delete mode 100644 tools/Utilities/IfeoTool/IfeoToolWindow.xaml delete mode 100644 tools/Utilities/IfeoTool/IfeoToolWindow.xaml.cs delete mode 100644 tools/Utilities/IfeoTool/ImageFileExecutionOptions.cs delete mode 100644 tools/Utilities/IfeoTool/ImageOptionsControlViewModel.cs delete mode 100644 tools/Utilities/IfeoTool/NativeMethods.json delete mode 100644 tools/Utilities/IfeoTool/NativeMethods.txt delete mode 100644 tools/Utilities/IfeoTool/Program.cs delete mode 100644 tools/Utilities/IfeoTool/Properties/PublishProfiles/win-arm64.pubxml delete mode 100644 tools/Utilities/IfeoTool/Properties/PublishProfiles/win-x64.pubxml delete mode 100644 tools/Utilities/IfeoTool/Properties/PublishProfiles/win-x86.pubxml delete mode 100644 tools/Utilities/IfeoTool/Properties/launchSettings.json delete mode 100644 tools/Utilities/IfeoTool/Strings/en-us/Resources.resw delete mode 100644 tools/Utilities/IfeoTool/Telemetry/IfeoToolAppLaunchEvent.cs delete mode 100644 tools/Utilities/IfeoTool/Telemetry/IfeoToolGlobalFlagsChanged.cs delete mode 100644 tools/Utilities/IfeoTool/Telemetry/IfeoToolTraceEvent.cs delete mode 100644 tools/Utilities/IfeoTool/app.manifest delete mode 100644 tools/Utilities/IfeoTool/appsettings_ifeotool.json diff --git a/DevHome.sln b/DevHome.sln index 07fe229aa..379a30a29 100644 --- a/DevHome.sln +++ b/DevHome.sln @@ -123,10 +123,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DevSetupAgent.Test", "exten EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HyperVExtension.HostGuestCommunication", "extensions\HyperVExtension\src\HyperVExtension.HostGuestCommunication\HyperVExtension.HostGuestCommunication.csproj", "{D759CD66-494C-4A00-8075-8B65A9891349}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DevHome.DevDiagnostics", "tools\DevDiagnostics\DevHome.DevDiagnostics\DevHome.DevDiagnostics.csproj", "{CAAC0CDF-9AB8-4F43-A3EB-38D785AF5725}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DevDiagnostics", "DevDiagnostics", "{DB3D0F2C-1A7F-44B4-B408-B21A56212985}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Customization", "Customization", "{623998FD-B0A6-4980-95D5-A5072301CA10}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DevHome.Customization", "tools\Customization\DevHome.Customization\DevHome.Customization.csproj", "{AF527EA4-6A24-4BD6-BC6E-A5863DC3489C}" @@ -174,37 +170,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DevHome.FileExplorerSourceC EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DevHome.FileExplorerSourceControlIntegrationUnitTest", "tools\Customization\DevHome.FileExplorerSourceControlIntegrationUnitTest\DevHome.FileExplorerSourceControlIntegrationUnitTest.csproj", "{A1FAE679-39D4-4278-A8E8-EA351F21A3E7}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DevHome.Service", "service\DevHome.Service\DevHome.Service.csproj", "{8A0AD1A7-29E1-47E1-9579-91F2B460518F}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DevHome.Service.Projection", "service\DevHome.Service.Projection\DevHome.Service.Projection.csproj", "{13F1F098-262B-432D-977C-F710E6826C5C}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DevHome.Service.IDL", "service\DevHome.Service.IDL\DevHome.Service.IDL.vcxproj", "{17E96025-8251-4D62-BFFB-C571F728B66B}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TestTools", "TestTools", "{7857275B-7970-4C26-B092-FF62EA890B1E}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestDumpAnalyzer", "tools\DevDiagnostics\TestTools\TestDumpAnalyzer\TestDumpAnalyzer.csproj", "{29963C5C-4CB6-4406-850A-99503CB87081}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Utilities", "Utilities", "{81AB1B86-AE3C-4E5B-8918-CA6CCED95266}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EnableLoaderSnaps", "tools\DevDiagnostics\Utilities\EnableLoaderSnaps\EnableLoaderSnaps.csproj", "{EB097CCA-D4B6-4C99-9EB8-161F26345562}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestLoadFailure", "tools\DevDiagnostics\TestTools\TestLoadFailure\TestLoadFailure.vcxproj", "{F196A38B-190C-4B00-813D-DC0B7AD24CB7}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestServiceCaller", "tools\DevDiagnostics\TestTools\TestServiceCaller\TestServiceCaller.csproj", "{024CB70C-3449-4204-9171-A25C6C25783D}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DevHome.Database", "database\DevHome.Database\DevHome.Database.csproj", "{01CADE81-7333-4E24-A39B-95B7E58D4503}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "RepositoryManagement", "RepositoryManagement", "{567A82BE-7E9E-4D95-AF45-4EE8D57FE16D}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DevHome.RepositoryManagement", "tools\RepositoryManagement\DevHome.RepositoryManagement\DevHome.RepositoryManagement.csproj", "{82BD8133-F1D4-4383-BC4F-12EFAE1AFF91}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "NTService", "NTService", "{E6BC5785-34E5-4A19-81A4-2CC8A37FD63F}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Telemetry", "Telemetry", "{70D3F826-0057-4EAF-AA6D-09479075B056}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DevHome.IfeoTool", "tools\Utilities\IfeoTool\DevHome.IfeoTool.csproj", "{A9B2E87D-540F-4B4C-A4AA-EF3BDDC4171C}" -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EnableLocalCabCollection", "tools\DevDiagnostics\Utilities\EnableLocalCabCollection\EnableLocalCabCollection.csproj", "{A382B448-A1F3-4D87-A674-736D2987E613}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug_FailFast|arm64 = Debug_FailFast|arm64 @@ -911,24 +884,6 @@ Global {D759CD66-494C-4A00-8075-8B65A9891349}.Release|x64.Build.0 = Release|x64 {D759CD66-494C-4A00-8075-8B65A9891349}.Release|x86.ActiveCfg = Release|x86 {D759CD66-494C-4A00-8075-8B65A9891349}.Release|x86.Build.0 = Release|x86 - {CAAC0CDF-9AB8-4F43-A3EB-38D785AF5725}.Debug_FailFast|arm64.ActiveCfg = Debug_FailFast|ARM64 - {CAAC0CDF-9AB8-4F43-A3EB-38D785AF5725}.Debug_FailFast|arm64.Build.0 = Debug_FailFast|ARM64 - {CAAC0CDF-9AB8-4F43-A3EB-38D785AF5725}.Debug_FailFast|x64.ActiveCfg = Debug_FailFast|x64 - {CAAC0CDF-9AB8-4F43-A3EB-38D785AF5725}.Debug_FailFast|x64.Build.0 = Debug_FailFast|x64 - {CAAC0CDF-9AB8-4F43-A3EB-38D785AF5725}.Debug_FailFast|x86.ActiveCfg = Debug_FailFast|x86 - {CAAC0CDF-9AB8-4F43-A3EB-38D785AF5725}.Debug_FailFast|x86.Build.0 = Debug_FailFast|x86 - {CAAC0CDF-9AB8-4F43-A3EB-38D785AF5725}.Debug|arm64.ActiveCfg = Debug|ARM64 - {CAAC0CDF-9AB8-4F43-A3EB-38D785AF5725}.Debug|arm64.Build.0 = Debug|ARM64 - {CAAC0CDF-9AB8-4F43-A3EB-38D785AF5725}.Debug|x64.ActiveCfg = Debug|x64 - {CAAC0CDF-9AB8-4F43-A3EB-38D785AF5725}.Debug|x64.Build.0 = Debug|x64 - {CAAC0CDF-9AB8-4F43-A3EB-38D785AF5725}.Debug|x86.ActiveCfg = Debug|x86 - {CAAC0CDF-9AB8-4F43-A3EB-38D785AF5725}.Debug|x86.Build.0 = Debug|x86 - {CAAC0CDF-9AB8-4F43-A3EB-38D785AF5725}.Release|arm64.ActiveCfg = Release|ARM64 - {CAAC0CDF-9AB8-4F43-A3EB-38D785AF5725}.Release|arm64.Build.0 = Release|ARM64 - {CAAC0CDF-9AB8-4F43-A3EB-38D785AF5725}.Release|x64.ActiveCfg = Release|x64 - {CAAC0CDF-9AB8-4F43-A3EB-38D785AF5725}.Release|x64.Build.0 = Release|x64 - {CAAC0CDF-9AB8-4F43-A3EB-38D785AF5725}.Release|x86.ActiveCfg = Release|x86 - {CAAC0CDF-9AB8-4F43-A3EB-38D785AF5725}.Release|x86.Build.0 = Release|x86 {AF527EA4-6A24-4BD6-BC6E-A5863DC3489C}.Debug_FailFast|arm64.ActiveCfg = Debug_FailFast|arm64 {AF527EA4-6A24-4BD6-BC6E-A5863DC3489C}.Debug_FailFast|arm64.Build.0 = Debug_FailFast|arm64 {AF527EA4-6A24-4BD6-BC6E-A5863DC3489C}.Debug_FailFast|x64.ActiveCfg = Debug_FailFast|x64 @@ -1193,132 +1148,6 @@ Global {A1FAE679-39D4-4278-A8E8-EA351F21A3E7}.Release|x64.Build.0 = Release|x64 {A1FAE679-39D4-4278-A8E8-EA351F21A3E7}.Release|x86.ActiveCfg = Release|x86 {A1FAE679-39D4-4278-A8E8-EA351F21A3E7}.Release|x86.Build.0 = Release|x86 - {8A0AD1A7-29E1-47E1-9579-91F2B460518F}.Debug_FailFast|arm64.ActiveCfg = Debug|ARM64 - {8A0AD1A7-29E1-47E1-9579-91F2B460518F}.Debug_FailFast|arm64.Build.0 = Debug|ARM64 - {8A0AD1A7-29E1-47E1-9579-91F2B460518F}.Debug_FailFast|x64.ActiveCfg = Debug|x64 - {8A0AD1A7-29E1-47E1-9579-91F2B460518F}.Debug_FailFast|x64.Build.0 = Debug|x64 - {8A0AD1A7-29E1-47E1-9579-91F2B460518F}.Debug_FailFast|x86.ActiveCfg = Debug|x86 - {8A0AD1A7-29E1-47E1-9579-91F2B460518F}.Debug_FailFast|x86.Build.0 = Debug|x86 - {8A0AD1A7-29E1-47E1-9579-91F2B460518F}.Debug|arm64.ActiveCfg = Debug|ARM64 - {8A0AD1A7-29E1-47E1-9579-91F2B460518F}.Debug|arm64.Build.0 = Debug|ARM64 - {8A0AD1A7-29E1-47E1-9579-91F2B460518F}.Debug|x64.ActiveCfg = Debug|x64 - {8A0AD1A7-29E1-47E1-9579-91F2B460518F}.Debug|x64.Build.0 = Debug|x64 - {8A0AD1A7-29E1-47E1-9579-91F2B460518F}.Debug|x86.ActiveCfg = Debug|x86 - {8A0AD1A7-29E1-47E1-9579-91F2B460518F}.Debug|x86.Build.0 = Debug|x86 - {8A0AD1A7-29E1-47E1-9579-91F2B460518F}.Release|arm64.ActiveCfg = Release|ARM64 - {8A0AD1A7-29E1-47E1-9579-91F2B460518F}.Release|arm64.Build.0 = Release|ARM64 - {8A0AD1A7-29E1-47E1-9579-91F2B460518F}.Release|x64.ActiveCfg = Release|x64 - {8A0AD1A7-29E1-47E1-9579-91F2B460518F}.Release|x64.Build.0 = Release|x64 - {8A0AD1A7-29E1-47E1-9579-91F2B460518F}.Release|x86.ActiveCfg = Release|x86 - {8A0AD1A7-29E1-47E1-9579-91F2B460518F}.Release|x86.Build.0 = Release|x86 - {13F1F098-262B-432D-977C-F710E6826C5C}.Debug_FailFast|arm64.ActiveCfg = Debug|ARM64 - {13F1F098-262B-432D-977C-F710E6826C5C}.Debug_FailFast|arm64.Build.0 = Debug|ARM64 - {13F1F098-262B-432D-977C-F710E6826C5C}.Debug_FailFast|x64.ActiveCfg = Debug|x64 - {13F1F098-262B-432D-977C-F710E6826C5C}.Debug_FailFast|x64.Build.0 = Debug|x64 - {13F1F098-262B-432D-977C-F710E6826C5C}.Debug_FailFast|x86.ActiveCfg = Debug|x86 - {13F1F098-262B-432D-977C-F710E6826C5C}.Debug_FailFast|x86.Build.0 = Debug|x86 - {13F1F098-262B-432D-977C-F710E6826C5C}.Debug|arm64.ActiveCfg = Debug|ARM64 - {13F1F098-262B-432D-977C-F710E6826C5C}.Debug|arm64.Build.0 = Debug|ARM64 - {13F1F098-262B-432D-977C-F710E6826C5C}.Debug|x64.ActiveCfg = Debug|x64 - {13F1F098-262B-432D-977C-F710E6826C5C}.Debug|x64.Build.0 = Debug|x64 - {13F1F098-262B-432D-977C-F710E6826C5C}.Debug|x86.ActiveCfg = Debug|x86 - {13F1F098-262B-432D-977C-F710E6826C5C}.Debug|x86.Build.0 = Debug|x86 - {13F1F098-262B-432D-977C-F710E6826C5C}.Release|arm64.ActiveCfg = Release|ARM64 - {13F1F098-262B-432D-977C-F710E6826C5C}.Release|arm64.Build.0 = Release|ARM64 - {13F1F098-262B-432D-977C-F710E6826C5C}.Release|x64.ActiveCfg = Release|x64 - {13F1F098-262B-432D-977C-F710E6826C5C}.Release|x64.Build.0 = Release|x64 - {13F1F098-262B-432D-977C-F710E6826C5C}.Release|x86.ActiveCfg = Release|x86 - {13F1F098-262B-432D-977C-F710E6826C5C}.Release|x86.Build.0 = Release|x86 - {17E96025-8251-4D62-BFFB-C571F728B66B}.Debug_FailFast|arm64.ActiveCfg = Debug|x64 - {17E96025-8251-4D62-BFFB-C571F728B66B}.Debug_FailFast|arm64.Build.0 = Debug|x64 - {17E96025-8251-4D62-BFFB-C571F728B66B}.Debug_FailFast|x64.ActiveCfg = Debug|x64 - {17E96025-8251-4D62-BFFB-C571F728B66B}.Debug_FailFast|x64.Build.0 = Debug|x64 - {17E96025-8251-4D62-BFFB-C571F728B66B}.Debug_FailFast|x86.ActiveCfg = Debug|Win32 - {17E96025-8251-4D62-BFFB-C571F728B66B}.Debug_FailFast|x86.Build.0 = Debug|Win32 - {17E96025-8251-4D62-BFFB-C571F728B66B}.Debug|arm64.ActiveCfg = Debug|x64 - {17E96025-8251-4D62-BFFB-C571F728B66B}.Debug|arm64.Build.0 = Debug|x64 - {17E96025-8251-4D62-BFFB-C571F728B66B}.Debug|x64.ActiveCfg = Debug|x64 - {17E96025-8251-4D62-BFFB-C571F728B66B}.Debug|x64.Build.0 = Debug|x64 - {17E96025-8251-4D62-BFFB-C571F728B66B}.Debug|x86.ActiveCfg = Debug|Win32 - {17E96025-8251-4D62-BFFB-C571F728B66B}.Debug|x86.Build.0 = Debug|Win32 - {17E96025-8251-4D62-BFFB-C571F728B66B}.Release|arm64.ActiveCfg = Release|x64 - {17E96025-8251-4D62-BFFB-C571F728B66B}.Release|arm64.Build.0 = Release|x64 - {17E96025-8251-4D62-BFFB-C571F728B66B}.Release|x64.ActiveCfg = Release|x64 - {17E96025-8251-4D62-BFFB-C571F728B66B}.Release|x64.Build.0 = Release|x64 - {17E96025-8251-4D62-BFFB-C571F728B66B}.Release|x86.ActiveCfg = Release|Win32 - {17E96025-8251-4D62-BFFB-C571F728B66B}.Release|x86.Build.0 = Release|Win32 - {29963C5C-4CB6-4406-850A-99503CB87081}.Debug_FailFast|arm64.ActiveCfg = Debug_FailFast|ARM64 - {29963C5C-4CB6-4406-850A-99503CB87081}.Debug_FailFast|arm64.Build.0 = Debug_FailFast|ARM64 - {29963C5C-4CB6-4406-850A-99503CB87081}.Debug_FailFast|x64.ActiveCfg = Debug_FailFast|x64 - {29963C5C-4CB6-4406-850A-99503CB87081}.Debug_FailFast|x64.Build.0 = Debug_FailFast|x64 - {29963C5C-4CB6-4406-850A-99503CB87081}.Debug_FailFast|x86.ActiveCfg = Debug_FailFast|x86 - {29963C5C-4CB6-4406-850A-99503CB87081}.Debug_FailFast|x86.Build.0 = Debug_FailFast|x86 - {29963C5C-4CB6-4406-850A-99503CB87081}.Debug|arm64.ActiveCfg = Debug|ARM64 - {29963C5C-4CB6-4406-850A-99503CB87081}.Debug|arm64.Build.0 = Debug|ARM64 - {29963C5C-4CB6-4406-850A-99503CB87081}.Debug|x64.ActiveCfg = Debug|x64 - {29963C5C-4CB6-4406-850A-99503CB87081}.Debug|x64.Build.0 = Debug|x64 - {29963C5C-4CB6-4406-850A-99503CB87081}.Debug|x86.ActiveCfg = Debug|x86 - {29963C5C-4CB6-4406-850A-99503CB87081}.Debug|x86.Build.0 = Debug|x86 - {29963C5C-4CB6-4406-850A-99503CB87081}.Release|arm64.ActiveCfg = Release|ARM64 - {29963C5C-4CB6-4406-850A-99503CB87081}.Release|arm64.Build.0 = Release|ARM64 - {29963C5C-4CB6-4406-850A-99503CB87081}.Release|x64.ActiveCfg = Release|x64 - {29963C5C-4CB6-4406-850A-99503CB87081}.Release|x64.Build.0 = Release|x64 - {29963C5C-4CB6-4406-850A-99503CB87081}.Release|x86.ActiveCfg = Release|x86 - {29963C5C-4CB6-4406-850A-99503CB87081}.Release|x86.Build.0 = Release|x86 - {EB097CCA-D4B6-4C99-9EB8-161F26345562}.Debug_FailFast|arm64.ActiveCfg = Debug_FailFast|ARM64 - {EB097CCA-D4B6-4C99-9EB8-161F26345562}.Debug_FailFast|arm64.Build.0 = Debug_FailFast|ARM64 - {EB097CCA-D4B6-4C99-9EB8-161F26345562}.Debug_FailFast|x64.ActiveCfg = Debug_FailFast|x64 - {EB097CCA-D4B6-4C99-9EB8-161F26345562}.Debug_FailFast|x64.Build.0 = Debug_FailFast|x64 - {EB097CCA-D4B6-4C99-9EB8-161F26345562}.Debug_FailFast|x86.ActiveCfg = Debug_FailFast|x86 - {EB097CCA-D4B6-4C99-9EB8-161F26345562}.Debug_FailFast|x86.Build.0 = Debug_FailFast|x86 - {EB097CCA-D4B6-4C99-9EB8-161F26345562}.Debug|arm64.ActiveCfg = Debug|ARM64 - {EB097CCA-D4B6-4C99-9EB8-161F26345562}.Debug|arm64.Build.0 = Debug|ARM64 - {EB097CCA-D4B6-4C99-9EB8-161F26345562}.Debug|x64.ActiveCfg = Debug|x64 - {EB097CCA-D4B6-4C99-9EB8-161F26345562}.Debug|x64.Build.0 = Debug|x64 - {EB097CCA-D4B6-4C99-9EB8-161F26345562}.Debug|x86.ActiveCfg = Debug|x86 - {EB097CCA-D4B6-4C99-9EB8-161F26345562}.Debug|x86.Build.0 = Debug|x86 - {EB097CCA-D4B6-4C99-9EB8-161F26345562}.Release|arm64.ActiveCfg = Release|ARM64 - {EB097CCA-D4B6-4C99-9EB8-161F26345562}.Release|arm64.Build.0 = Release|ARM64 - {EB097CCA-D4B6-4C99-9EB8-161F26345562}.Release|x64.ActiveCfg = Release|x64 - {EB097CCA-D4B6-4C99-9EB8-161F26345562}.Release|x64.Build.0 = Release|x64 - {EB097CCA-D4B6-4C99-9EB8-161F26345562}.Release|x86.ActiveCfg = Release|x86 - {EB097CCA-D4B6-4C99-9EB8-161F26345562}.Release|x86.Build.0 = Release|x86 - {F196A38B-190C-4B00-813D-DC0B7AD24CB7}.Debug_FailFast|arm64.ActiveCfg = Debug|x64 - {F196A38B-190C-4B00-813D-DC0B7AD24CB7}.Debug_FailFast|arm64.Build.0 = Debug|x64 - {F196A38B-190C-4B00-813D-DC0B7AD24CB7}.Debug_FailFast|x64.ActiveCfg = Debug|x64 - {F196A38B-190C-4B00-813D-DC0B7AD24CB7}.Debug_FailFast|x64.Build.0 = Debug|x64 - {F196A38B-190C-4B00-813D-DC0B7AD24CB7}.Debug_FailFast|x86.ActiveCfg = Debug|Win32 - {F196A38B-190C-4B00-813D-DC0B7AD24CB7}.Debug_FailFast|x86.Build.0 = Debug|Win32 - {F196A38B-190C-4B00-813D-DC0B7AD24CB7}.Debug|arm64.ActiveCfg = Debug|x64 - {F196A38B-190C-4B00-813D-DC0B7AD24CB7}.Debug|arm64.Build.0 = Debug|x64 - {F196A38B-190C-4B00-813D-DC0B7AD24CB7}.Debug|x64.ActiveCfg = Debug|x64 - {F196A38B-190C-4B00-813D-DC0B7AD24CB7}.Debug|x64.Build.0 = Debug|x64 - {F196A38B-190C-4B00-813D-DC0B7AD24CB7}.Debug|x86.ActiveCfg = Debug|Win32 - {F196A38B-190C-4B00-813D-DC0B7AD24CB7}.Debug|x86.Build.0 = Debug|Win32 - {F196A38B-190C-4B00-813D-DC0B7AD24CB7}.Release|arm64.ActiveCfg = Release|x64 - {F196A38B-190C-4B00-813D-DC0B7AD24CB7}.Release|arm64.Build.0 = Release|x64 - {F196A38B-190C-4B00-813D-DC0B7AD24CB7}.Release|x64.ActiveCfg = Release|x64 - {F196A38B-190C-4B00-813D-DC0B7AD24CB7}.Release|x64.Build.0 = Release|x64 - {F196A38B-190C-4B00-813D-DC0B7AD24CB7}.Release|x86.ActiveCfg = Release|Win32 - {F196A38B-190C-4B00-813D-DC0B7AD24CB7}.Release|x86.Build.0 = Release|Win32 - {024CB70C-3449-4204-9171-A25C6C25783D}.Debug_FailFast|arm64.ActiveCfg = Debug_FailFast|ARM64 - {024CB70C-3449-4204-9171-A25C6C25783D}.Debug_FailFast|arm64.Build.0 = Debug_FailFast|ARM64 - {024CB70C-3449-4204-9171-A25C6C25783D}.Debug_FailFast|x64.ActiveCfg = Debug_FailFast|x64 - {024CB70C-3449-4204-9171-A25C6C25783D}.Debug_FailFast|x64.Build.0 = Debug_FailFast|x64 - {024CB70C-3449-4204-9171-A25C6C25783D}.Debug_FailFast|x86.ActiveCfg = Debug_FailFast|x86 - {024CB70C-3449-4204-9171-A25C6C25783D}.Debug_FailFast|x86.Build.0 = Debug_FailFast|x86 - {024CB70C-3449-4204-9171-A25C6C25783D}.Debug|arm64.ActiveCfg = Debug|ARM64 - {024CB70C-3449-4204-9171-A25C6C25783D}.Debug|arm64.Build.0 = Debug|ARM64 - {024CB70C-3449-4204-9171-A25C6C25783D}.Debug|x64.ActiveCfg = Debug|x64 - {024CB70C-3449-4204-9171-A25C6C25783D}.Debug|x64.Build.0 = Debug|x64 - {024CB70C-3449-4204-9171-A25C6C25783D}.Debug|x86.ActiveCfg = Debug|x86 - {024CB70C-3449-4204-9171-A25C6C25783D}.Debug|x86.Build.0 = Debug|x86 - {024CB70C-3449-4204-9171-A25C6C25783D}.Release|arm64.ActiveCfg = Release|ARM64 - {024CB70C-3449-4204-9171-A25C6C25783D}.Release|arm64.Build.0 = Release|ARM64 - {024CB70C-3449-4204-9171-A25C6C25783D}.Release|x64.ActiveCfg = Release|x64 - {024CB70C-3449-4204-9171-A25C6C25783D}.Release|x64.Build.0 = Release|x64 - {024CB70C-3449-4204-9171-A25C6C25783D}.Release|x86.ActiveCfg = Release|x86 - {024CB70C-3449-4204-9171-A25C6C25783D}.Release|x86.Build.0 = Release|x86 {01CADE81-7333-4E24-A39B-95B7E58D4503}.Debug_FailFast|arm64.ActiveCfg = Debug_FailFast|arm64 {01CADE81-7333-4E24-A39B-95B7E58D4503}.Debug_FailFast|arm64.Build.0 = Debug_FailFast|arm64 {01CADE81-7333-4E24-A39B-95B7E58D4503}.Debug_FailFast|x64.ActiveCfg = Debug_FailFast|x64 @@ -1355,42 +1184,6 @@ Global {82BD8133-F1D4-4383-BC4F-12EFAE1AFF91}.Release|x64.Build.0 = Release|x64 {82BD8133-F1D4-4383-BC4F-12EFAE1AFF91}.Release|x86.ActiveCfg = Release|x86 {82BD8133-F1D4-4383-BC4F-12EFAE1AFF91}.Release|x86.Build.0 = Release|x86 - {A9B2E87D-540F-4B4C-A4AA-EF3BDDC4171C}.Debug_FailFast|arm64.ActiveCfg = Debug_FailFast|arm64 - {A9B2E87D-540F-4B4C-A4AA-EF3BDDC4171C}.Debug_FailFast|arm64.Build.0 = Debug_FailFast|arm64 - {A9B2E87D-540F-4B4C-A4AA-EF3BDDC4171C}.Debug_FailFast|x64.ActiveCfg = Debug_FailFast|x64 - {A9B2E87D-540F-4B4C-A4AA-EF3BDDC4171C}.Debug_FailFast|x64.Build.0 = Debug_FailFast|x64 - {A9B2E87D-540F-4B4C-A4AA-EF3BDDC4171C}.Debug_FailFast|x86.ActiveCfg = Debug_FailFast|x86 - {A9B2E87D-540F-4B4C-A4AA-EF3BDDC4171C}.Debug_FailFast|x86.Build.0 = Debug_FailFast|x86 - {A9B2E87D-540F-4B4C-A4AA-EF3BDDC4171C}.Debug|arm64.ActiveCfg = Debug|arm64 - {A9B2E87D-540F-4B4C-A4AA-EF3BDDC4171C}.Debug|arm64.Build.0 = Debug|arm64 - {A9B2E87D-540F-4B4C-A4AA-EF3BDDC4171C}.Debug|x64.ActiveCfg = Debug|x64 - {A9B2E87D-540F-4B4C-A4AA-EF3BDDC4171C}.Debug|x64.Build.0 = Debug|x64 - {A9B2E87D-540F-4B4C-A4AA-EF3BDDC4171C}.Debug|x86.ActiveCfg = Debug|x86 - {A9B2E87D-540F-4B4C-A4AA-EF3BDDC4171C}.Debug|x86.Build.0 = Debug|x86 - {A9B2E87D-540F-4B4C-A4AA-EF3BDDC4171C}.Release|arm64.ActiveCfg = Release|arm64 - {A9B2E87D-540F-4B4C-A4AA-EF3BDDC4171C}.Release|arm64.Build.0 = Release|arm64 - {A9B2E87D-540F-4B4C-A4AA-EF3BDDC4171C}.Release|x64.ActiveCfg = Release|x64 - {A9B2E87D-540F-4B4C-A4AA-EF3BDDC4171C}.Release|x64.Build.0 = Release|x64 - {A9B2E87D-540F-4B4C-A4AA-EF3BDDC4171C}.Release|x86.ActiveCfg = Release|x86 - {A9B2E87D-540F-4B4C-A4AA-EF3BDDC4171C}.Release|x86.Build.0 = Release|x86 - {A382B448-A1F3-4D87-A674-736D2987E613}.Debug_FailFast|arm64.ActiveCfg = Debug_FailFast|ARM64 - {A382B448-A1F3-4D87-A674-736D2987E613}.Debug_FailFast|arm64.Build.0 = Debug_FailFast|ARM64 - {A382B448-A1F3-4D87-A674-736D2987E613}.Debug_FailFast|x64.ActiveCfg = Debug_FailFast|x64 - {A382B448-A1F3-4D87-A674-736D2987E613}.Debug_FailFast|x64.Build.0 = Debug_FailFast|x64 - {A382B448-A1F3-4D87-A674-736D2987E613}.Debug_FailFast|x86.ActiveCfg = Debug_FailFast|x86 - {A382B448-A1F3-4D87-A674-736D2987E613}.Debug_FailFast|x86.Build.0 = Debug_FailFast|x86 - {A382B448-A1F3-4D87-A674-736D2987E613}.Debug|arm64.ActiveCfg = Debug|ARM64 - {A382B448-A1F3-4D87-A674-736D2987E613}.Debug|arm64.Build.0 = Debug|ARM64 - {A382B448-A1F3-4D87-A674-736D2987E613}.Debug|x64.ActiveCfg = Debug|x64 - {A382B448-A1F3-4D87-A674-736D2987E613}.Debug|x64.Build.0 = Debug|x64 - {A382B448-A1F3-4D87-A674-736D2987E613}.Debug|x86.ActiveCfg = Debug|x86 - {A382B448-A1F3-4D87-A674-736D2987E613}.Debug|x86.Build.0 = Debug|x86 - {A382B448-A1F3-4D87-A674-736D2987E613}.Release|arm64.ActiveCfg = Release|ARM64 - {A382B448-A1F3-4D87-A674-736D2987E613}.Release|arm64.Build.0 = Release|ARM64 - {A382B448-A1F3-4D87-A674-736D2987E613}.Release|x64.ActiveCfg = Release|x64 - {A382B448-A1F3-4D87-A674-736D2987E613}.Release|x64.Build.0 = Release|x64 - {A382B448-A1F3-4D87-A674-736D2987E613}.Release|x86.ActiveCfg = Release|x86 - {A382B448-A1F3-4D87-A674-736D2987E613}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1439,8 +1232,6 @@ Global {F4095FD3-6A3F-490B-966D-E63059612EE6} = {3E3791DF-070D-4ADE-96E8-93D6FBD53953} {0E05A442-BDC7-43D4-A000-F8C986826716} = {3E3791DF-070D-4ADE-96E8-93D6FBD53953} {D759CD66-494C-4A00-8075-8B65A9891349} = {81AACED5-CFB5-47A6-AFD6-4625AADCFFA3} - {CAAC0CDF-9AB8-4F43-A3EB-38D785AF5725} = {DB3D0F2C-1A7F-44B4-B408-B21A56212985} - {DB3D0F2C-1A7F-44B4-B408-B21A56212985} = {A972EC5B-FC61-4964-A6FF-F9633EB75DFD} {623998FD-B0A6-4980-95D5-A5072301CA10} = {A972EC5B-FC61-4964-A6FF-F9633EB75DFD} {AF527EA4-6A24-4BD6-BC6E-A5863DC3489C} = {623998FD-B0A6-4980-95D5-A5072301CA10} {FAB6FAA7-ADF4-4B65-9831-0C819915E6E1} = {A972EC5B-FC61-4964-A6FF-F9633EB75DFD} @@ -1460,29 +1251,14 @@ Global {8C1C7BF8-B27B-4F4D-97E5-A16E02C7860E} = {01AB3100-A939-41DD-A67F-1F8C275A307D} {83D12033-364A-45F2-8FCA-9BD8E8322D91} = {623998FD-B0A6-4980-95D5-A5072301CA10} {A1FAE679-39D4-4278-A8E8-EA351F21A3E7} = {623998FD-B0A6-4980-95D5-A5072301CA10} - {8A0AD1A7-29E1-47E1-9579-91F2B460518F} = {E6BC5785-34E5-4A19-81A4-2CC8A37FD63F} - {13F1F098-262B-432D-977C-F710E6826C5C} = {E6BC5785-34E5-4A19-81A4-2CC8A37FD63F} - {17E96025-8251-4D62-BFFB-C571F728B66B} = {E6BC5785-34E5-4A19-81A4-2CC8A37FD63F} - {7857275B-7970-4C26-B092-FF62EA890B1E} = {DB3D0F2C-1A7F-44B4-B408-B21A56212985} - {29963C5C-4CB6-4406-850A-99503CB87081} = {7857275B-7970-4C26-B092-FF62EA890B1E} - {81AB1B86-AE3C-4E5B-8918-CA6CCED95266} = {DB3D0F2C-1A7F-44B4-B408-B21A56212985} - {EB097CCA-D4B6-4C99-9EB8-161F26345562} = {81AB1B86-AE3C-4E5B-8918-CA6CCED95266} - {F196A38B-190C-4B00-813D-DC0B7AD24CB7} = {7857275B-7970-4C26-B092-FF62EA890B1E} - {024CB70C-3449-4204-9171-A25C6C25783D} = {7857275B-7970-4C26-B092-FF62EA890B1E} {567A82BE-7E9E-4D95-AF45-4EE8D57FE16D} = {A972EC5B-FC61-4964-A6FF-F9633EB75DFD} {82BD8133-F1D4-4383-BC4F-12EFAE1AFF91} = {567A82BE-7E9E-4D95-AF45-4EE8D57FE16D} - {A9B2E87D-540F-4B4C-A4AA-EF3BDDC4171C} = {FAB6FAA7-ADF4-4B65-9831-0C819915E6E1} - {A382B448-A1F3-4D87-A674-736D2987E613} = {81AB1B86-AE3C-4E5B-8918-CA6CCED95266} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {030B5641-B206-46BB-BF71-36FF009088FA} EndGlobalSection GlobalSection(SharedMSBuildProjectFiles) = preSolution - build\cppversion\version.vcxitems*{024cb70c-3449-4204-9171-a25c6c25783d}*SharedItemsImports = 5 build\cppversion\version.vcxitems*{092ac740-da01-4872-8e93-b9557dad6be5}*SharedItemsImports = 5 - build\cppversion\version.vcxitems*{13f1f098-262b-432d-977c-f710e6826c5c}*SharedItemsImports = 5 build\cppversion\version.vcxitems*{60e0fd98-5396-436d-bab7-187a853a5dc6}*SharedItemsImports = 5 - build\cppversion\version.vcxitems*{8a0ad1a7-29e1-47e1-9579-91f2b460518f}*SharedItemsImports = 5 - build\cppversion\version.vcxitems*{caac0cdf-9ab8-4f43-a3eb-38d785af5725}*SharedItemsImports = 5 EndGlobalSection EndGlobal diff --git a/docs/architecture.md b/docs/architecture.md index 70aafeaeb..1e00ef36a 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -34,7 +34,6 @@ graph TD; DevHome.Dashboard-->DevHome; DevHome.Experiments-->DevHome; DevHome.ExtensionLibrary-->DevHome; - DevHome.DevInsights-->DevHome.Service; DevHome.Settings-->DevHome; DevHome.SetupFlow-->DevHome; DevHome.RepositoryManagement-->DevHome @@ -70,10 +69,6 @@ Dev Home Common also provides telemetry functionality. This is a special component that acts similarly to a tool but isn't actually a tool. The Settings component, like other tools, consumes the Common project and is used by Dev Home Core. It manages user preferences across all tools and extensions. -## Service - -This is an NT service which runs as local system that provides functionality to various DevHome components. This functionality would typically require elevation and isn't transactional in nature. For items in DevHome that require elevation and are of a transactional nature, helper utilities are launched elevated instead. - ## Tools The tools are a set of functionalities that are integrated within Dev Home's codebase. They are designed to provide specific capabilities or features to Dev Home. They live as their own component but run in the same process as Dev Home and can communicate with each other and the core component through Dev Home's API. diff --git a/service/DevHome.Service.IDL/DevHome.Service.IDL.vcxproj b/service/DevHome.Service.IDL/DevHome.Service.IDL.vcxproj deleted file mode 100644 index 89cbbc02f..000000000 --- a/service/DevHome.Service.IDL/DevHome.Service.IDL.vcxproj +++ /dev/null @@ -1,167 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - - - - 17.0 - Win32Proj - {17e96025-8251-4d62-bffb-c571f728b66b} - DevHomeServiceIDL - 10.0 - - - - DynamicLibrary - true - v143 - Unicode - - - DynamicLibrary - false - v143 - true - Unicode - - - DynamicLibrary - true - v143 - Unicode - - - DynamicLibrary - false - v143 - true - Unicode - - - - - - - - - - - - - - - - - - - - - - Level3 - true - WIN32;_DEBUG;DEVHOMESERVICEIDL_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true - Use - pch.h - - - Windows - true - false - - - true - %(IntDir)%(Filename).winmd - $(WindowsSDK_MetadataFoundationPath);%(AdditionalMetadataDirectories) - $(ProjectDir)Generated Files - - - - - Level3 - true - true - true - WIN32;NDEBUG;DEVHOMESERVICEIDL_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true - Use - pch.h - - - Windows - true - true - true - false - - - true - %(IntDir)%(Filename).winmd - $(WindowsSDK_MetadataFoundationPath);%(AdditionalMetadataDirectories) - $(ProjectDir)Generated Files - - - - - Level3 - true - _DEBUG;DEVHOMESERVICEIDL_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true - - - Windows - true - false - - - true - %(IntDir)%(Filename).winmd - $(WindowsSDK_MetadataFoundationPath);%(AdditionalMetadataDirectories) - $(ProjectDir)Generated Files - - - - - Level3 - true - true - true - NDEBUG;DEVHOMESERVICEIDL_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true - - - Windows - true - true - true - false - - - true - %(IntDir)%(Filename).winmd - $(WindowsSDK_MetadataFoundationPath);%(AdditionalMetadataDirectories) - $(ProjectDir)Generated Files - - - - - - \ No newline at end of file diff --git a/service/DevHome.Service.Projection/DevHome.Service.Projection.csproj b/service/DevHome.Service.Projection/DevHome.Service.Projection.csproj deleted file mode 100644 index 89f7a75a9..000000000 --- a/service/DevHome.Service.Projection/DevHome.Service.Projection.csproj +++ /dev/null @@ -1,24 +0,0 @@ - - - - None - - - - - - - - - - - - - - - - DevHome.Service - $(SolutionDir)DevHome.Service.Projection\bin\$(Platform)\$(Configuration)\ - - - diff --git a/service/DevHome.Service/BasicClassWinRTFactory`1.cs b/service/DevHome.Service/BasicClassWinRTFactory`1.cs deleted file mode 100644 index 5953cc5f1..000000000 --- a/service/DevHome.Service/BasicClassWinRTFactory`1.cs +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System.Runtime.InteropServices; -using DevHome.Service; -using Windows.Win32.Foundation; -using WinRT; - -namespace COMRegistration; - -[ComVisible(true)] -public class BasicClassWinRTFactory : IClassFactory -where T : new() -{ - public BasicClassWinRTFactory() - { - } - - public int CreateInstance(IntPtr pUnkOuter, ref Guid riid, out IntPtr ppvObject) - { - ppvObject = IntPtr.Zero; - - if (pUnkOuter != IntPtr.Zero) - { - Marshal.ThrowExceptionForHR(HRESULT.CLASS_E_NOAGGREGATION); - } - - if (riid == typeof(T).GUID || riid == Guid.Parse(Guids.IUnknown)) - { - try - { - // Create the instance of the WinRT object - ppvObject = MarshalInspectable.FromManaged(new T()); - } - catch (Exception) - { - // We failed creating an object (possibly due to access denied). If we were just spun up - // to handle this (failed) activation, shut down our service. - if (ServiceLifetimeController.CanUnload()) - { - WindowsBackgroundService.Stop(); - } - - throw; - } - } - else - { - // The object that ppvObject points to does not support the - // interface identified by riid. - Marshal.ThrowExceptionForHR(HRESULT.E_NOINTERFACE); - } - - return 0; - } - - int IClassFactory.LockServer(bool fLock) - { - return 0; - } -} - -internal static class Guids -{ - public const string IClassFactory = "00000001-0000-0000-C000-000000000046"; - public const string IUnknown = "00000000-0000-0000-C000-000000000046"; -} - -// IClassFactory declaration -[ComImport] -[ComVisible(false)] -[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] -[Guid(Guids.IClassFactory)] -internal interface IClassFactory -{ - [PreserveSig] - int CreateInstance(IntPtr pUnkOuter, ref Guid riid, out IntPtr ppvObject); - - [PreserveSig] - int LockServer(bool fLock); -} diff --git a/service/DevHome.Service/ComHelpers.cs b/service/DevHome.Service/ComHelpers.cs deleted file mode 100644 index df58cb408..000000000 --- a/service/DevHome.Service/ComHelpers.cs +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System.Diagnostics; -using System.Runtime.InteropServices; -using System.Runtime.InteropServices.Marshalling; -using System.Security.Principal; -using Microsoft.Win32.SafeHandles; -using Windows.ApplicationModel; -using Windows.Win32; -using Windows.Win32.Foundation; -using Windows.Win32.Security; -using Windows.Win32.System.Com; -using Windows.Win32.System.Rpc; -using Windows.Win32.System.Threading; - -namespace DevHome.Service; - -internal sealed class ComHelpers -{ - [System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "Well-known constant")] - [System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1310:Field names should not contain underscore", Justification = "Well-known constant")] - [System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1306:Field names should begin with lower-case letter", Justification = "Well-known constant")] - private static readonly Guid CLSID_GlobalOptions = new("0000034B-0000-0000-C000-000000000046"); - - public static void EnableFastCOMRundown() - { - // We need to be careful creating the GlobalOptions object. We can't use the baked in CLR marshaller, as it calls CoInitializeSecurity under - // the covers... and we need to be able to set these options *before* we call CoInitializeSecurity. - CoCreateInstanceNoMarshal(CLSID_GlobalOptions, IntPtr.Zero, CLSCTX.CLSCTX_INPROC_SERVER | CLSCTX.CLSCTX_INPROC_HANDLER, typeof(IGlobalOptions).GUID, out IntPtr ptr).ThrowOnFailure(); - - ComWrappers cw = new StrategyBasedComWrappers(); - IGlobalOptions option2 = (IGlobalOptions)cw.GetOrCreateObjectForComInstance(ptr, CreateObjectFlags.None); - - // Enable fast COM rundown - option2.SetItem((uint)GLOBALOPT_PROPERTIES.COMGLB_RO_SETTINGS, (uint)GLOBALOPT_RO_FLAGS.COMGLB_FAST_RUNDOWN); - - // Don't allow exceptions to be handled by COM. Crash the service instead - option2.SetItem((uint)GLOBALOPT_PROPERTIES.COMGLB_EXCEPTION_HANDLING, (uint)GLOBALOPT_EH_VALUES.COMGLB_EXCEPTION_DONOT_HANDLE_ANY); - } - - public static void InitializeSecurity() - { - unsafe - { - PInvoke.CoInitializeSecurity((PSECURITY_DESCRIPTOR)null, -1, null, null, RPC_C_AUTHN_LEVEL.RPC_C_AUTHN_LEVEL_NONE, RPC_C_IMP_LEVEL.RPC_C_IMP_LEVEL_IMPERSONATE, null, EOLE_AUTHENTICATION_CAPABILITIES.EOAC_NONE, null); - } - } - - public static void VerifyCaller(Process caller) - { - VerifyCallerIsFromTheSamePackage(caller); - VerifyCallerIsInTheSameDirectory(caller); - } - - public static Process GetClientProcess() - { - unsafe - { - uint callerPid = 0; - RPC_STATUS rpcStatus = PInvoke.I_RpcBindingInqLocalClientPID(null, ref callerPid); - - // Unable to figure out our caller - if (rpcStatus != RPC_STATUS.RPC_S_OK) - { - throw new UnauthorizedAccessException(); - } - - return Process.GetProcessById((int)callerPid); - } - } - - public static void VerifyCallerIsInTheSameDirectory(Process callerProcess) - { - FileInfo callerFileInfo = new FileInfo(callerProcess.MainModule?.FileName ?? string.Empty); - FileInfo serverFileInfo = new FileInfo(Process.GetCurrentProcess().MainModule?.FileName ?? string.Empty); - - if (!callerFileInfo.Exists || !serverFileInfo.Exists) - { - throw new UnauthorizedAccessException(); - } - - if (callerFileInfo.DirectoryName != serverFileInfo.DirectoryName) - { - throw new UnauthorizedAccessException(); - } - - // Our caller is in the same directory that we are - } - - public static void VerifyCallerIsFromTheSamePackage(Process caller) - { - unsafe - { - string devHomeServicePackage = Package.Current.Id.FullName; - - SafeProcessHandle h = new(PInvoke.OpenProcess(PROCESS_ACCESS_RIGHTS.PROCESS_QUERY_LIMITED_INFORMATION, false, (uint)caller.Id), true); - - if (h.IsInvalid) - { - throw new UnauthorizedAccessException(); - } - - bool f = PInvoke.OpenProcessToken(h, TOKEN_ACCESS_MASK.TOKEN_QUERY, out SafeFileHandle token); - - if (!f || token.IsInvalid) - { - throw new UnauthorizedAccessException(); - } - - Span outputBuffer = new char[10000]; - uint packageFullNameLength = 10000; - - fixed (char* outBufferPointer = outputBuffer) - { - var callerPackageName = new PWSTR(outBufferPointer); - var res = PInvoke.GetPackageFullNameFromToken(token, ref packageFullNameLength, callerPackageName); - var callerPackageNameString = new string(callerPackageName); - - if (res != WIN32_ERROR.ERROR_SUCCESS || !devHomeServicePackage.Equals(callerPackageNameString, StringComparison.Ordinal)) - { - throw new UnauthorizedAccessException(); - } - } - - // We're running with the same package identity - } - } - - [DllImport("ole32.dll", EntryPoint = "CoCreateInstance")] - public static extern HRESULT CoCreateInstanceNoMarshal( - [In, MarshalAs(UnmanagedType.LPStruct)] Guid rclsid, - IntPtr pUnkOuter, - CLSCTX dwClsContext, - [In, MarshalAs(UnmanagedType.LPStruct)] Guid riid, - out IntPtr ppv); -} - -[Guid("0000015B-0000-0000-C000-000000000046")] -[GeneratedComInterface] -internal partial interface IGlobalOptions -{ - void SetItem(uint dwProperty, uint dwValue); - - void Query(uint dwProperty, out uint pdwValue); -} diff --git a/service/DevHome.Service/DevHome.Service.csproj b/service/DevHome.Service/DevHome.Service.csproj deleted file mode 100644 index f44057a8d..000000000 --- a/service/DevHome.Service/DevHome.Service.csproj +++ /dev/null @@ -1,31 +0,0 @@ - - - - enable - DevHome.Service - enable - WinExe - win-x86;win-x64;win-arm64 - $(SolutionDir)\src\Properties\PublishProfiles\win-$(Platform).pubxml - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - - - - - diff --git a/service/DevHome.Service/DevHomeService.cs b/service/DevHome.Service/DevHomeService.cs deleted file mode 100644 index ac6c4344b..000000000 --- a/service/DevHome.Service/DevHomeService.cs +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System.Diagnostics; -using System.Runtime.InteropServices; -using Microsoft.Diagnostics.Tracing.Parsers; -using Microsoft.Diagnostics.Tracing.Session; -using Windows.Win32.Foundation; - -namespace DevHome.Service.Runtime; - -[ComVisible(true)] -public class DevHomeService : IDevHomeService, IDisposable -{ - private readonly Process _owner; - - public event MissingFileProcessLaunchFailureHandler? MissingFileProcessLaunchFailure; - - private TraceEventSession? _etwSession; - - public DevHomeService() - { - Process myCaller = ComHelpers.GetClientProcess(); - ComHelpers.VerifyCaller(myCaller); - - _owner = myCaller; - _owner.EnableRaisingEvents = true; - - // Track our caller process - ServiceLifetimeController.ServiceStop += ServiceLifetimeController_ServiceStop; - ServiceLifetimeController.RegisterProcess(_owner); - - var crashDumpAnalyzerThread = new Thread(() => - { - KernelEventETWListener(); - }); - crashDumpAnalyzerThread.Name = "KernelEventETWListenerThread"; - crashDumpAnalyzerThread.Start(); - - _owner.Exited += Owner_Exited; - } - - private void ServiceLifetimeController_ServiceStop() - { - // Be sure to stop our ETW session when we exit. It's possible this gets called multiple times - // if we have multiple instances of our object... that's ok. - _etwSession?.Stop(); - } - - private void Owner_Exited(object? sender, EventArgs e) - { - // The owner of our object has exited. We'll stop listening to ETW events from this channel, but keep it open in case there are - // other listeners of the channel in this process. - _etwSession?.Source.StopProcessing(); - } - - private void KernelEventETWListener() - { - _etwSession = new TraceEventSession("DevHome.Service.KernelEventETWListenerSession"); - - // Enable the kernel provider to look for processes exiting with non-zero exit codes - _etwSession.EnableKernelProvider(KernelTraceEventParser.Keywords.Process); - - _etwSession.Source.Kernel.ProcessStop += data => - { - // Only return data for processes in session 0 or the caller's session (don't let one session spy on another session) - if (data.SessionID == 0 || data.SessionID == _owner.SessionId) - { - if (data.ExitStatus == NTSTATUS.STATUS_DLL_NOT_FOUND || data.ExitStatus == (int)WIN32_ERROR.ERROR_MOD_NOT_FOUND) - { - MissingFileProcessLaunchFailureInfo info = default(MissingFileProcessLaunchFailureInfo); - info.processName = data.ImageFileName; - info.pid = data.ProcessID; - info.exitCode = data.ExitStatus; - - try - { - MissingFileProcessLaunchFailure?.Invoke(info); - } - catch (Exception) - { - // We don't want to crash the process if the event handler throws an exception - } - } - } - }; - - _etwSession.Source.Process(); - } - - public void Dispose() - { - _etwSession?.Source.StopProcessing(); - _etwSession?.Dispose(); - GC.SuppressFinalize(this); - } -} diff --git a/service/DevHome.Service/NativeMethods.json b/service/DevHome.Service/NativeMethods.json deleted file mode 100644 index 7cd04b8f2..000000000 --- a/service/DevHome.Service/NativeMethods.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$schema": "https://aka.ms/CsWin32.schema.json", - "wideCharOnly": true -} diff --git a/service/DevHome.Service/NativeMethods.txt b/service/DevHome.Service/NativeMethods.txt deleted file mode 100644 index 210cef5c3..000000000 --- a/service/DevHome.Service/NativeMethods.txt +++ /dev/null @@ -1,18 +0,0 @@ -CoInitializeEx -CoInitializeSecurity -CoGetCallContext -CoRegisterClassObject -CoResumeClassObjects -GetPackageFullNameFromToken -I_RpcBindingInqLocalClientPID -OpenProcess -OpenProcessToken -CLASS_E_NOAGGREGATION -E_ACCESSDENIED -E_NOINTERFACE -GLOBALOPT_EH_VALUES -GLOBALOPT_PROPERTIES -GLOBALOPT_RO_FLAGS -STATUS_DLL_NOT_FOUND -WIN32_ERROR - diff --git a/service/DevHome.Service/Program.cs b/service/DevHome.Service/Program.cs deleted file mode 100644 index 258ef0a98..000000000 --- a/service/DevHome.Service/Program.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using DevHome.Service; -using DevHome.Service.Runtime; - -ComHelpers.EnableFastCOMRundown(); -ComHelpers.InitializeSecurity(); - -HostApplicationBuilder builder = Host.CreateApplicationBuilder(args); -builder.Services.AddWindowsService(options => -{ - options.ServiceName = "DevHome Service"; -}); - -builder.Services.AddSingleton(); -builder.Services.AddHostedService(); - -IHost host = builder.Build(); -host.Run(); diff --git a/service/DevHome.Service/ServiceLifetimeController.cs b/service/DevHome.Service/ServiceLifetimeController.cs deleted file mode 100644 index 05351be3e..000000000 --- a/service/DevHome.Service/ServiceLifetimeController.cs +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System.Diagnostics; -using System.Runtime.InteropServices; -using COMRegistration; -using DevHome.Service.Runtime; -using Windows.Win32; -using Windows.Win32.Foundation; -using Windows.Win32.System.Com; - -namespace DevHome.Service; - -internal delegate void ServiceStopEvent(); - -internal sealed class ServiceLifetimeController -{ - private static readonly List _processes = new(); - - internal static event ServiceStopEvent? ServiceStop; - - public static void RegisterProcess(Process p) - { - lock (_processes) - { - if (!_processes.Contains(p)) - { - _processes.Add(p); - p.EnableRaisingEvents = true; - p.Exited += ProcessExited; - } - } - } - - private static void ProcessExited(object? sender, EventArgs e) - { - Process? p = sender as Process; - Debug.Assert(p is not null, "What is this object?"); - - lock (_processes) - { - _processes.Remove(p); - if (_processes.Count == 0) - { - // It's ok to stop the service now - ServiceStop?.Invoke(); - WindowsBackgroundService.Stop(); - } - } - } - - public static bool CanUnload() - { - lock (_processes) - { - return _processes.Count == 0; - } - } -} diff --git a/service/DevHome.Service/WindowsBackgroundService.cs b/service/DevHome.Service/WindowsBackgroundService.cs deleted file mode 100644 index c4bd57cbf..000000000 --- a/service/DevHome.Service/WindowsBackgroundService.cs +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System.Runtime.InteropServices; -using COMRegistration; -using DevHome.Service.Runtime; -using Windows.Win32; -using Windows.Win32.Foundation; -using Windows.Win32.System.Com; - -namespace DevHome.Service; - -public sealed class WindowsBackgroundService() : BackgroundService -{ - private static readonly ManualResetEventSlim _stopEvent = new(false); - - public static void Stop() - { - _stopEvent.Set(); - } - - protected async override Task ExecuteAsync(CancellationToken stoppingToken) - { -#if CANARY_BUILD - RegisterClass(new Guid("0A920C6E-2569-44D1-A6E4-CE9FA44CD2A7")); -#elif STABLE_BUILD - RegisterClass(new Guid("E8D40232-20A1-4F3B-9C0C-AAA6538698C6")); -#else - RegisterClass(new Guid("1F98F450-C163-4A99-B257-E1E6CB3E1C57")); -#endif - - try - { - await Task.Run(() => _stopEvent.Wait(stoppingToken), stoppingToken); - - // If we end up here, it means that internally we decided to terminate the service because - // we no longer have any clients - Environment.Exit(0); - } - catch (OperationCanceledException) - { - // When the stopping token is canceled, for example, a call made from services.msc, - // we shouldn't exit with a non-zero exit code. In other words, this is expected... - } - catch (Exception) - { - // Terminates this process and returns an exit code to the operating system. - // This is required to avoid the 'BackgroundServiceExceptionBehavior', which - // performs one of two scenarios: - // 1. When set to "Ignore": will do nothing at all, errors cause zombie services. - // 2. When set to "StopHost": will cleanly stop the host, and log errors. - // - // In order for the Windows Service Management system to leverage configured - // recovery options, we need to terminate the process with a non-zero exit code. - Environment.Exit(1); - } - } - - private readonly List _registrationCookies = new(); - - public void RegisterClass(Guid clsid) - where T : new() - { - uint cookie; - - PInvoke.CoRegisterClassObject(clsid, new BasicClassWinRTFactory(), CLSCTX.CLSCTX_LOCAL_SERVER, REGCLS.REGCLS_MULTIPLEUSE | REGCLS.REGCLS_SUSPENDED, out cookie).ThrowOnFailure(); - _registrationCookies.Add(cookie); - PInvoke.CoResumeClassObjects().ThrowOnFailure(); - } -} diff --git a/service/Devhome.Service.IDL/DevHome.Service.idl b/service/Devhome.Service.IDL/DevHome.Service.idl deleted file mode 100644 index 8de1060a9..000000000 --- a/service/Devhome.Service.IDL/DevHome.Service.idl +++ /dev/null @@ -1,19 +0,0 @@ -import "inspectable.idl"; -import "windows.foundation.idl"; - -namespace DevHome.Service -{ - struct MissingFileProcessLaunchFailureInfo - { - String processName; - Int32 pid; - Int32 exitCode; - }; - - delegate void MissingFileProcessLaunchFailureHandler(MissingFileProcessLaunchFailureInfo failure); - - interface IDevHomeService - { - event MissingFileProcessLaunchFailureHandler MissingFileProcessLaunchFailure; - } -} \ No newline at end of file diff --git a/service/Devhome.Service.IDL/Devhome.Service.IDL.vcxproj.filters b/service/Devhome.Service.IDL/Devhome.Service.IDL.vcxproj.filters deleted file mode 100644 index ad878cbf1..000000000 --- a/service/Devhome.Service.IDL/Devhome.Service.IDL.vcxproj.filters +++ /dev/null @@ -1,22 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - - - Source Files - - - \ No newline at end of file diff --git a/settings/DevHome.Settings/Strings/en-us/Resources.resw b/settings/DevHome.Settings/Strings/en-us/Resources.resw index 919bd011d..d6611ad2b 100644 --- a/settings/DevHome.Settings/Strings/en-us/Resources.resw +++ b/settings/DevHome.Settings/Strings/en-us/Resources.resw @@ -553,14 +553,6 @@ Quiet background processes allows you to free up resources while developing Inline description of the Quiet background processes experimental feature on the 'Settings -> Experiments' page where you enable it. - - Dev Diagnostics - Name of experimental feature 'Dev Diagnostics' on the 'Settings -> Experiments' page where you enable it. - - - Dev Diagnostics is a utility to provide deeper insights into your applications - Inline description of the Dev Diagnostics experimental feature on the 'Settings -> Experiments' page where you enable it. - Quickstart Playground Locked="{Quickstart Playground}" Title text for the Quickstart Playground feature. diff --git a/src/DevHome.csproj b/src/DevHome.csproj index 369feb5ef..c692f658a 100644 --- a/src/DevHome.csproj +++ b/src/DevHome.csproj @@ -82,9 +82,6 @@ - - - @@ -92,7 +89,6 @@ - @@ -105,7 +101,6 @@ - @@ -176,11 +171,6 @@ - - - PreserveNewest - - diff --git a/src/NavConfig.jsonc b/src/NavConfig.jsonc index f83e7a23b..9526a6f03 100644 --- a/src/NavConfig.jsonc +++ b/src/NavConfig.jsonc @@ -131,30 +131,6 @@ "parameter": "StartQuickstartPlayground" } }, - { - "identity": "DevDiagnosticsExperiment", - "enabledByDefault": false, - "buildTypeOverrides": [ - { - "buildType": "dev", - "enabledByDefault": true, - "visible": true - }, - { - "buildType": "canary", - "enabledByDefault": true, - "visible": true - }, - { - "buildType": "stable", - "enabledByDefault": false, - "visible": true - } - ], - "openPage": { - "key": "DevHome.Utilities.ViewModels.UtilitiesMainPageViewModel" - } - }, { "identity": "RepositoryManagementExperiment", "enabledByDefault": false, diff --git a/src/Package-Can.appxmanifest b/src/Package-Can.appxmanifest index 70f084ee5..ebf1f989e 100644 --- a/src/Package-Can.appxmanifest +++ b/src/Package-Can.appxmanifest @@ -333,34 +333,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -402,19 +374,6 @@ - - - - - - - - - - - - - diff --git a/src/Package-Dev.appxmanifest b/src/Package-Dev.appxmanifest index 86de2ed19..79ec05ce6 100644 --- a/src/Package-Dev.appxmanifest +++ b/src/Package-Dev.appxmanifest @@ -333,34 +333,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -402,19 +374,6 @@ - - - - - - - - - - - - - diff --git a/src/Package.appxmanifest b/src/Package.appxmanifest index ae5e122fd..37ef64a0c 100644 --- a/src/Package.appxmanifest +++ b/src/Package.appxmanifest @@ -335,23 +335,6 @@ - - - - - - - - - - - - - - - - - @@ -391,19 +374,6 @@ - - - - - - - - - - - - - diff --git a/src/Program.cs b/src/Program.cs index 815f20c7e..2eb981d7a 100644 --- a/src/Program.cs +++ b/src/Program.cs @@ -70,7 +70,7 @@ private static async Task DecideRedirection() // Currently DevHome supports one set of command line arguments, most useful when debugging different apps within the Dev Home package. // // For example: - // --utilitylaunch DevHome.DevDiagnostics.Exe --utilityLaunchArgs "--application problemapp2" + // --utilitylaunch DevHome.MyUtility.Exe --utilityLaunchArgs "--application problemapp2" // // --utilityLaunch is the name of the utility to launch // --utilityLaunchArgs are the arguments to pass to the utility. This is optional, but be sure to include the quotes if you have spaces in the arguments. diff --git a/src/Properties/launchsettings.json b/src/Properties/launchsettings.json index d27fcc6a2..b4ad33268 100644 --- a/src/Properties/launchsettings.json +++ b/src/Properties/launchsettings.json @@ -7,16 +7,6 @@ }, "DevHome (Unpackaged)": { "commandName": "Project" - }, - "DevDiagnostics (Package)": { - "commandName": "MsixPackage", - "commandLineArgs": "--utilitylaunch DevHome.DevDiagnostics.Exe ", - "nativeDebugging": true - }, - "IfeoTool (Packaged)": { - "commandName": "MsixPackage", - "commandLineArgs": "--utilitylaunch DevHome.IfeoTool.Exe ", - "nativeDebugging": true } } } \ No newline at end of file diff --git a/tools/DevDiagnostics/DD.ico b/tools/DevDiagnostics/DD.ico deleted file mode 100644 index 84014e6192492a72f9e12192525186c61e6583a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 151604 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�~6B*a(XPzHHZQp>4%Y&7=Brt1+AX8f7emwi59**N?EUc3s`Yt=~V453imbkG0f6hWN;4!D} zdOwMg8h6NKNnMRg&vCrZ|Lf}ng*hH$;?4m|b&XJ{x~|6a|0|Eexv{QV;MCR45R_&v zDPMpo%o-PeNnKstoEbA_AgFU0U0>tk*VL4kl`W~Mt3d<=s_O*(g^R0em{wL&?#b)X zcbxgv)r-qZpp39Zjf?L%Kn_{%`Z{Pfv!)K|0Ih&s+Jupwi&l zG~G8U-={X8r=+2l=h_plJE2cZNniHgR6H4%I1;8W4f;luFhf~h=fynZ_XvFBF;D)~ z@;VLru;W~ojw@k?QRTTWQ}taYaZTmv>q_NMT=ri~xTZ8oTMbn_#$}$GF4NRd%~#_R zM@?f~rt>UU!Zx2K63-U0Y}7B;a#1vs=Ap~$a3A*7*|^?zoc`bA`mN)9;Q?G2?-dtD z!@q$1F97e0t;kO~4t9B?&y4d2!6PzxeF;vJKIvAJ@BzIZCXH zqa9GJcol6>Yy;O`8_=Ez1~B70dqy~AdU!t@D1`f9bJPwFA41cD0@DD_aS_~(EAyw% znTACnbJ%xg{>-^^XU?3%-YfIOzqxZ}&Ag7$IYgK{SEMq>nLcwC{zRUDqyLTfIs5+s D^9AZs diff --git a/tools/DevDiagnostics/DD.png b/tools/DevDiagnostics/DD.png deleted file mode 100644 index 50ab7fb27028f905e081a1466d18599ed13be550..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20891 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 - - - -

- - - - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - Default - - - True - - - False - - - True - - - - - DevHome.DevDiagnostics - DevEnv - - - - - 0 - - - True - - - 0 - - - True - - - True - - - - \ No newline at end of file diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/LargeTile.scale-100.png b/tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/LargeTile.scale-100.png deleted file mode 100644 index 7f7823934c8ff0d8fd6d990dd1b79a2ded23b775..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7196 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 diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/LargeTile.scale-150.png b/tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/LargeTile.scale-150.png deleted file mode 100644 index 03d2363b8847f56fba9980c210a65b72480f5617..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11684 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 diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/LargeTile.scale-400.png b/tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/LargeTile.scale-400.png deleted file mode 100644 index 78be0d717f232f86ec37149353ccc646eaf0ee0b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 44599 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 diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/SmallTile.scale-100.png b/tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/SmallTile.scale-100.png deleted file mode 100644 index 420b465f0bfe6bc64ab49a4da97f65ff73466596..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2042 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 diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/SmallTile.scale-150.png b/tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/SmallTile.scale-150.png deleted file mode 100644 index c03b608186f5d71fef554943e3493a818dfd67bf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3304 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 diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/SmallTile.scale-200.png b/tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/SmallTile.scale-200.png deleted file mode 100644 index 8ab3da0a8dcd6784d6e748eb312f7488b47b284d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4374 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 OgAA%`s?(t5`usofV^?1Q diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/SmallTile.scale-400.png b/tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/SmallTile.scale-400.png deleted file mode 100644 index 3e57fa8dfd5737cf55b23499b68eb8acab7a2bd9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9600 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 G4*efq<%`h( diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/SplashScreen.scale-100.png b/tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/SplashScreen.scale-100.png deleted file mode 100644 index da80d9b5b64a1f59c82c3566743bcf1eb5ef0fae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7884 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 diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/SplashScreen.scale-150.png b/tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/SplashScreen.scale-150.png deleted file mode 100644 index c6dcc19da13f80a3a5b3806bacf4aedcb3e5bd65..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12563 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 upke&KE5`r3SN*@sg;_07kb0k^Oji? diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/SplashScreen.scale-200.png b/tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/SplashScreen.scale-200.png deleted file mode 100644 index 8bfb4556579afde7f34ee882cca7adaf1ee9f3bf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17965 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 QYxDqYETHB!*WDld2c#iiiU0rr diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Square150x150Logo.scale-125.png b/tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Square150x150Logo.scale-125.png deleted file mode 100644 index fdd6dc63d67a508ce1aee5f6d098f2c1e575d3d3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4144 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 Ux6^*|0$?$@Z)s3*_wmdB12eq-L;wH) diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Square150x150Logo.scale-150.png b/tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Square150x150Logo.scale-150.png deleted file mode 100644 index ed17ab3a8fee84480a0ea9b2de2ac6ab049597d3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5160 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 z 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 Qfb>#UeD@ml$~5@@01B!jKL7v# diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Square44x44Logo.altform-lightunplated_targetsize-16.png b/tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Square44x44Logo.altform-lightunplated_targetsize-16.png deleted file mode 100644 index 60132fb3d51acfaa7f6699b34eefd2e425e0a010..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 716 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 JPDHLkV1h}lWK947 diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Square44x44Logo.scale-150.png b/tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Square44x44Logo.scale-150.png deleted file mode 100644 index 6daef9882407dfce96ad3abeba72e01c530b1220..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2891 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 Ef`)AXZvX%Q diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Square44x44Logo.targetsize-24.png b/tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Square44x44Logo.targetsize-24.png deleted file mode 100644 index 00b0c53247ec25c13f27abf67f81f8dccde0757e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 824 zcmV-81IPS{P)pH>PbXFRCt{2lv_wtK^TDlnK>7Cx7F>YArw7TK9o0-C@KhgvBU?> z9)cpMhoUej3R=6-c9EpVULq(646=vRq=zDse279NL<$QNCPHWebN-Yu=nM_wu|EPZ z4mBQv)>)LB9KhfllmY^4{W5Aw*u3?4B|CS10H4kqAVe1v1IEyVHFO_&Kw=IL#9XKo zwu^xRbn3_|-DrE^ZOs?(X(tS<&`ab9)j3wqivudWN;$mCaABu#od{MK&m~ZY&kW*l zUI2`Me9;L%C}VV36%`Rj2!18t6UX*IcL7dTvmS%Pg-iYT$!`I -p(GTuI=kCy-< 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 diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Square44x44Logo.targetsize-32.png b/tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Square44x44Logo.targetsize-32.png deleted file mode 100644 index 3ced4d93e8496255aaf0d0d07c84ad39d9cd56e7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1206 zcmV;n1WEgeP)pJXh}ptRCt{2mtAZWRTRh1xihmf+is!d!`fCs35oG5X(?zhEzxRy z&@_sqpfPHU$^#gEs3w$>CTQa~gv3{k+C(2PmJ~u0jFA`;6QQNiROO*!zi6Sdbi3Qm z&gVUzyHEk$mTs*d551e4n|toeJ-@lm~;>9bcV(s#bs9X&m- z0GXPg(PAQ5tm2{x6N>aQYj+pMdHLm?Yos30a2p`zO**4H*tT_k0l0fUm?*T{xK=p-lzz91#hU$i= z*5B$WOgw+<&)*5qA9TaRI$Vw?Qdh39_-r+@OMyZxGPOc*!^G$91CO=+1t1vnb&<#6 zlKc}{k1{KO9gg$c&*XeQ2NS{QGn;NYTpmadd~osyCw{6fi`|~N&cJ*~hrI`ra`{tP zA49q&8d@MJ{m zy`gO#YR3C&=E{`K!`s>RnigQDmXhfLU7BDA2@X}lP)7|1_Jb&eh^JYr_;fZCBEPEh z^Hl6Za-KWXU*A7(0FIXc!BsEm4Kl>oKI-mmkt+>VE!5{jnW--UbrPHzaTz+>4h`1t zpJ~6G0qihtMxmH%gv)O9VoNJ3R(9g2^`*^@$G94bHtDAJwU0b8bglhz2Jn67s2>bI zoAgIO)eH5xitL`nb^*xfw@Ev7WZ+?Mw)^D_(E7_dl}=exYA)^n`M+QR;NNV&13Vb< UfADpPfdBvi07*qoM6N<$g2P}$IsgCw diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Square44x44Logo.targetsize-48.png b/tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Square44x44Logo.targetsize-48.png deleted file mode 100644 index 9c040bd0ef5496a07c7faa50d51cc08e6ddd3fd7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1970 zcmV;j2Tk~iP)pMWJyFpRCt{2S!-+@)fGPH-kE*ao0qjDQ9}Z0d6Z`!rVk_@;RjHm zkSe4&jYx$6l~yeXgo-eb5G)c>5E38|B0{PHYJw6)ac}}@1VSPfQd`w=3IUQ(2sjQ6 zCOEctcXnoH?mazs)*BnM@$Qy&7Ld>CdUs~-%=x~1o_B1)cU-Jm1Nf#gPN3E@PN3E@ zPN3FOl0fr(eRaZu>m2{<*H8dx4LO0(hk&0E!Y3BO{+55?=VJl3n3NHd|C`jJOE#JXw&FGxi(z^=lpOkXgU|Bkpc84;$&B*yp~T%O?a$%w!iQ45}5 zF<<|5^&W9s^~gWyN`B?Kjxjy2!36`SQ9vz+|?y=(8V7J$JPhu>1Rp6i)@kEo&rd70*FZb!=L63 z?0RA^wynCHQrdrc<=v@e@5~ilz>Uc($vu;PY)x?syAd zZfj{rRhYYJF$qKHopzvBsGLaE>cF4p(ZqhBCpf^P1|0_A^1{0u&>%QfX;4sSH_UCG z=RawowO0b|=hN@=>Zc0NFhp9~d13|bRW$-xqI%oH-Lypv(y`$!CqRkN4#zaEApojsB@Lhh1Vq7zAfXj&O+hq zq58tdzhJiixOc8z%p`WN0K(NF{TdK3^@260AKfFaXqvriVaz^ldpegd9h!oJbCQde zcmZ9*t;g>e_yt)eVTvVZt%jJS9nBZ(#?|lOhvn!RyJn6MiT&hPKicVd!2riaj#od* zei1-R2Oi)V2kxAu*I^P`*wvbiYnj0$CO9zg7q-9^HM2lLxUGPNGdCrLH5kO{IA9!L?p?AZBT3*mj(UP{N=*TH^W?}Q5 zPuyPu$#XoF3N4jW>6`gd4G9C0}qaBtm)eRG}B)QlMc4rJ%nt?&I9gsfd8d?>Rl{f}9X`8h;?$z0$&1gCduUSsmY-`tZo%FLxK6FB2a- ze)ll~o%B>Xd_thJr&o;t=X3T;n=?hG)vwdn}BB1GjB-XrwB z+IIMcjVIGGtrJx5>~z)y39+jI#!5pghd}5uYJ$lMpg4tiI#aa7zuSLc<`nxJG1S7) z3Gg|U+NU70d^A0WF8p^qNM$D(OBEUqt|UdRRS^L%aKdTEtV;K>3#FDd&3@x&#x+b) z3ZZJ%(33fI#^lLo)oIFal1;{sF?c8VVz)dPbnHV|9Q+^fhlu6N`c z6EMJe>AACXLTj*F%m5TKBzKq+@&!t9w{KG9@Vyp$y&sVG*tSpCuL5W-+2=dde^Epx z>U`G6{Sv!su4lr;`jYKLNdmq~#iMd^2+6#H(A*Lb=XET+jxfK_j3J-J!Cq+7+6AjN zFTHA1@P(#L11-Z)hiUlYW>MNV?7OyP$}8;bMjWAhx&I!$Kv^FsV&{X!{hWf9o$(WR!G zmn`Y@5ZMpzpf!eGp!_iCN6KQ}K3;q*AED|>&@HP`T{~@4GJ^4!5pCO8Hzp>5tNM1g zbuB4c@G2%yt~~r2G;pOwrPW|Hb)YYj`ilFsa?8+KIA{l0G;>>{l-7D){qsDX;@lqt zpR!qYr`yZbTQvg4_=+DR{P}M$`;~B|qGm43wJBaq??E{Ea}{^7H_MuM4w} zPnnx`blrI1loNnV267@DZr*chz>rAzY3J=FXTGLf5O{Kt|uN>^#E*{ z2phaWIj?Ayx@UX$vX3j(TQvf%>J=z-0vT>T#hR8tfq_4m9YYr}DVXcIA#x;8?(0l) z{VShd|JMJjw|WHp{xnGSIIn2L3sT%a`QhF;FCiHcD0_Hxvmp+OxclCg{Y|Ai!xB<8 z0viwg+`OQ=uUgM5SHA!Mq4~DUIDuNrIDuNrcb>ri06Ia3%l793B>(^b07*qoM6N<$ Eg4sN_LI3~& diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/StoreLogo.scale-100.png b/tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/StoreLogo.scale-100.png deleted file mode 100644 index 9ed62f1cd4b0957cd8d5bc16e5c93a02bce8ae40..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2751 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 diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/StoreLogo.scale-150.png b/tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/StoreLogo.scale-150.png deleted file mode 100644 index 5eb33fef2bea3014375816cb15cfd649de404e35..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4201 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 diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/StoreLogo.scale-200.png b/tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/StoreLogo.scale-200.png deleted file mode 100644 index a5da4cb5ad4d48c49caff80a30570479a37828e6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5726 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 QE&u=k07*qoM6N<$g6n_*b^rhX diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/StoreLogo.scale-400.png b/tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/StoreLogo.scale-400.png deleted file mode 100644 index 40c96bb280665ce48a3eee00c08ff2183a690d1c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12054 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 VzAC_yC{z@js-T&anUh diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Wide310x150Logo.scale-100.png b/tools/DevDiagnostics/DevHome.DevDiagnostics/Assets/Wide310x150Logo.scale-100.png deleted file mode 100644 index 1090229375ef7718380dbb0b9bf91f50070d82da..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3596 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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/ElevatedButtonControl.xaml.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/ElevatedButtonControl.xaml.cs deleted file mode 100644 index 58cbbbc00..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/ElevatedButtonControl.xaml.cs +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices.WindowsRuntime; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Controls.Primitives; -using Microsoft.UI.Xaml.Data; -using Microsoft.UI.Xaml.Input; -using Microsoft.UI.Xaml.Media; -using Microsoft.UI.Xaml.Navigation; -using Windows.Foundation; -using Windows.Foundation.Collections; - -namespace DevHome.DevDiagnostics.Controls; - -public sealed partial class ElevatedButtonControl : UserControl, INotifyPropertyChanged -{ - public event PropertyChangedEventHandler? PropertyChanged; - - private System.Windows.Input.ICommand? _command; - - public System.Windows.Input.ICommand? Command - { - get => _command; - - set - { - _command = value; - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Command))); - } - } - - private string _text = string.Empty; - - public string Text - { - get => _text; - - set - { - _text = value; - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Text))); - } - } - - public ElevatedButtonControl() - { - this.InitializeComponent(); - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/ExpandedViewControl.xaml b/tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/ExpandedViewControl.xaml deleted file mode 100644 index d196aec83..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/ExpandedViewControl.xaml +++ /dev/null @@ -1,102 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/ExpandedViewControl.xaml.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/ExpandedViewControl.xaml.cs deleted file mode 100644 index f1f58f2f3..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/ExpandedViewControl.xaml.cs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using DevHome.DevDiagnostics.ViewModels; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Input; - -namespace DevHome.DevDiagnostics.Controls; - -public sealed partial class ExpandedViewControl : UserControl -{ - private readonly ExpandedViewControlViewModel _viewModel = new(); - - public ExpandedViewControl() - { - InitializeComponent(); - _viewModel.NavigationService.Frame = PageFrame; - } - - public Frame GetPageFrame() - { - return PageFrame; - } - - public void NavigateTo(Type viewModelType) - { - _viewModel.NavigateTo(viewModelType); - } - - public void NavigateToSettings(string viewModelType) - { - _viewModel.NavigateToSettings(viewModelType); - } - - private void GridSplitter_PointerPressed(object sender, PointerRoutedEventArgs e) - { - e.Handled = true; - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/ExternalToolsManagementButton.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/ExternalToolsManagementButton.cs deleted file mode 100644 index 460873e69..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/ExternalToolsManagementButton.cs +++ /dev/null @@ -1,263 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Collections.Specialized; -using System.ComponentModel; -using System.Diagnostics; -using System.Linq; -using DevHome.Common.Extensions; -using DevHome.DevDiagnostics.Helpers; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Media; - -namespace DevHome.DevDiagnostics.Controls; - -internal sealed class ExternalToolsManagementButton : AppBarButton -{ - private const string UnregisterButtonGlyph = "\uECC9"; - - private readonly Microsoft.UI.Dispatching.DispatcherQueue _dispatcher; - private readonly string _pinMenuItemText = CommonHelper.GetLocalizedString("PinMenuItemText"); - private readonly string _unpinMenuItemText = CommonHelper.GetLocalizedString("UnpinMenuItemRawText"); - private readonly string _unregisterMenuItemText = CommonHelper.GetLocalizedString("UnregisterMenuItemRawText"); - private readonly ExternalToolsHelper _externalTools; - - public event EventHandler? ExternalToolLaunchRequest; - - public ExternalToolsManagementButton() - { - _dispatcher = Microsoft.UI.Dispatching.DispatcherQueue.GetForCurrentThread(); - _externalTools = Application.Current.GetService(); - - InitializeExternalTools(); - } - - private void InitializeExternalTools() - { - if (_externalTools.AllExternalTools.Count > 0) - { - var flyout = new MenuFlyout(); - this.ContextFlyout = flyout; - - foreach (var tool in _externalTools.AllExternalTools) - { - AddExternalToolToContextMenu(flyout, tool); - tool.PropertyChanged += ExternalToolItem_PropertyChanged; - } - } - - // We have to cast to INotifyCollectionChanged explicitly because the CollectionChanged - // event in ReadOnlyObservableCollection is protected. - ((INotifyCollectionChanged)_externalTools.AllExternalTools).CollectionChanged += ExternalTools_CollectionChanged; - } - - private void ExternalTools_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) - { - _dispatcher.TryEnqueue(() => - { - if (e.Action == NotifyCollectionChangedAction.Add && e.NewItems is not null) - { - foreach (ExternalTool tool in e.NewItems) - { - // If this button doens't have a flyout, create one - if (this.ContextFlyout is not MenuFlyout flyout) - { - flyout = new MenuFlyout(); - this.ContextFlyout = flyout; - } - - AddExternalToolToContextMenu(flyout, tool); - - // Listen for tool changes - tool.PropertyChanged += ExternalToolItem_PropertyChanged; - } - } - else if (e.Action == NotifyCollectionChangedAction.Remove && e.OldItems is not null) - { - foreach (ExternalTool tool in e.OldItems) - { - tool.PropertyChanged -= ExternalToolItem_PropertyChanged; - - // If this button doens't have a flyout, create one - if (this.ContextFlyout is MenuFlyout flyout) - { - RemoveExternalToolFromContextMenu(flyout, tool); - - // If we've removed all the items from the flyout, remove the flyout - if (flyout.Items.Count == 0) - { - this.ContextFlyout = null; - } - } - } - } - }); - } - - private void AddExternalToolToContextMenu(MenuFlyout menuFlyout, ExternalTool tool) - { - menuFlyout.Items.Add(CreateContextMenuItemForTool(tool)); - } - - private void RemoveExternalToolFromContextMenu(MenuFlyout menuFlyout, ExternalTool tool) - { - foreach (var menuItem in menuFlyout.Items.Where(x => x.Tag == tool)) - { - tool.PropertyChanged -= ExternalToolItem_PropertyChanged; - menuFlyout.Items.Remove(menuItem); - break; - } - } - - // This creates a Menu Flyout item for an external tool. It also creates a sub-menu item for pinning/unpinning - // and unregistering the tool. - private MenuFlyoutItem CreateContextMenuItemForTool(ExternalTool tool) - { - var imageIcon = tool.GetIcon(); - - var menuItem = new MenuFlyoutItem - { - Text = tool.Name, - Tag = tool, - Icon = imageIcon, - }; - menuItem.Click += ExternalToolMenuItem_Click; - - var pinMenuSubItemItem = new MenuFlyoutItem - { - Text = _pinMenuItemText, - Icon = GetFontIcon(CommonHelper.PinGlyph), - Tag = tool, - }; - pinMenuSubItemItem.Click += ExternalToolPinUnpin_Click; - - var unPinMenuSubItemItem = new MenuFlyoutItem - { - Text = _unpinMenuItemText, - Icon = GetFontIcon(CommonHelper.UnpinGlyph), - Tag = tool, - }; - unPinMenuSubItemItem.Click += ExternalToolPinUnpin_Click; - - var unRegisterMenuSubItemItem = new MenuFlyoutItem - { - Text = _unregisterMenuItemText, - Icon = GetFontIcon(UnregisterButtonGlyph), - Tag = tool, - }; - unRegisterMenuSubItemItem.Click += UnregisterMenuItem_Click; - - var menuSubItemFlyout = new MenuFlyout(); - - menuSubItemFlyout.Items.Add(pinMenuSubItemItem); - menuSubItemFlyout.Items.Add(unPinMenuSubItemItem); - menuSubItemFlyout.Items.Add(unRegisterMenuSubItemItem); - - if (tool.IsPinned) - { - pinMenuSubItemItem.Visibility = Visibility.Collapsed; - } - else - { - unPinMenuSubItemItem.Visibility = Visibility.Collapsed; - } - - menuItem.ContextFlyout = menuSubItemFlyout; - - return menuItem; - } - - private void ExternalToolItem_PropertyChanged(object? sender, PropertyChangedEventArgs e) - { - if (sender is not ExternalTool tool) - { - Debug.Assert(false, "Why are we getting notified of a tool property change without a tool?"); - return; - } - - _dispatcher.TryEnqueue(() => - { - MenuFlyout? flyout = this.ContextFlyout as MenuFlyout; - Debug.Assert(flyout is not null, "Why does this button not have a menu flyout?. It should have been populated in CreateContextMenuItemForTool"); - - // Update the submenu item for this tool - foreach (MenuFlyoutItem menuItem in flyout.Items.Where(x => x.Tag == tool)) - { - // Update the name if it's changed - menuItem.Text = tool.Name; - - var imageIcon = tool.GetIcon(); - - menuItem.Icon = imageIcon; - - var menuSubItemFlyout = menuItem.ContextFlyout as MenuFlyout; - Debug.Assert(menuSubItemFlyout != null, "It's expected this menuItem has a sub flyout. See CreateContextMenuItemForTool"); - - var pinSubItemItem = menuSubItemFlyout.Items[0] as MenuFlyoutItem; - Debug.Assert(pinSubItemItem != null, "The subflyout should have 2 items. The first is to pin the tool. See CreateContextMenuItemForTool"); - - var unPinSubItemItem = menuSubItemFlyout.Items[1] as MenuFlyoutItem; - Debug.Assert(unPinSubItemItem != null, "The second flyout should be to unpin the tool. See CreateContextMenuItemForTool"); - - // Toggle the visibily of the pin and unpin menu items based on the pinned state of the tool - pinSubItemItem.Visibility = tool.IsPinned ? Visibility.Collapsed : Visibility.Visible; - unPinSubItemItem.Visibility = tool.IsPinned ? Visibility.Visible : Visibility.Collapsed; - break; - } - }); - } - - public void ExternalToolMenuItem_Click(object sender, RoutedEventArgs e) - { - if (sender is MenuFlyoutItem clickedMenuItem && clickedMenuItem.Tag is ExternalTool tool) - { - ExternalToolLaunchRequest?.Invoke(this, tool); - } - } - - private void ExternalToolPinUnpin_Click(object sender, RoutedEventArgs e) - { - ExternalTool tool = GetToolFromSender(sender); - tool.IsPinned = !tool.IsPinned; - HideFlyout(sender); - } - - public void UnregisterMenuItem_Click(object sender, RoutedEventArgs e) - { - ExternalTool tool = GetToolFromSender(sender); - tool.UnregisterTool(); - - HideFlyout(sender); - } - - private ExternalTool GetToolFromSender(object sender) - { - MenuFlyoutItem? clickedMenuItem = sender as MenuFlyoutItem; - Debug.Assert(clickedMenuItem != null, "Why is this null? This should be a MenuFlyoutItem"); - - ExternalTool? tool = clickedMenuItem.Tag as ExternalTool; - Debug.Assert(tool != null, "The menuflyout items should have external tools as their tag. See CreateContextMenuItemForTool"); - - return tool; - } - - private void HideFlyout(object sender) - { - this.ContextFlyout.Hide(); - } - - private FontIcon GetFontIcon(string s) - { - var fontFamily = (FontFamily)Application.Current.Resources["SymbolThemeFontFamily"]; - - var icon = new FontIcon - { - FontFamily = fontFamily, - Glyph = s, - }; - - return icon; - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/InsightForMissingFileProcessTerminationControl.xaml b/tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/InsightForMissingFileProcessTerminationControl.xaml deleted file mode 100644 index cc5a62735..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/InsightForMissingFileProcessTerminationControl.xaml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/InsightForMissingFileProcessTerminationControl.xaml.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/InsightForMissingFileProcessTerminationControl.xaml.cs deleted file mode 100644 index 06de27283..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/InsightForMissingFileProcessTerminationControl.xaml.cs +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -using System.ComponentModel; -using DevHome.DevDiagnostics.Helpers; -using Microsoft.UI.Xaml.Controls; - -namespace DevHome.DevDiagnostics.Controls; - -public sealed partial class InsightForMissingFileProcessTerminationControl : UserControl, INotifyPropertyChanged -{ - public event PropertyChangedEventHandler? PropertyChanged; - - public string ElevationButtonTextString { get; } = CommonHelper.GetLocalizedString("InsightsMissingFileEnableLoaderSnapsButtonLabel"); - - public string ElevationButtonToolTipString { get; } = CommonHelper.GetLocalizedString("InsightsMissingFileEnableLoaderSnapsButtonToolTip"); - - private string _text = string.Empty; - - public string Text - { - get => _text; - - set - { - _text = value; - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Text))); - } - } - - private System.Windows.Input.ICommand? _command; - - public System.Windows.Input.ICommand? Command - { - get => _command; - - set - { - _command = value; - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Command))); - } - } - - public InsightForMissingFileProcessTerminationControl() - { - this.InitializeComponent(); - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/InsightSimpleTextControl.xaml b/tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/InsightSimpleTextControl.xaml deleted file mode 100644 index 9a201b4d8..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/InsightSimpleTextControl.xaml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/InsightSimpleTextControl.xaml.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/InsightSimpleTextControl.xaml.cs deleted file mode 100644 index fd81e6598..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/InsightSimpleTextControl.xaml.cs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -using System.ComponentModel; -using Microsoft.UI.Xaml.Controls; - -namespace DevHome.DevDiagnostics.Controls; - -public sealed partial class InsightSimpleTextControl : UserControl, INotifyPropertyChanged -{ - private string _description = string.Empty; - - public event PropertyChangedEventHandler? PropertyChanged; - - public string Description - { - get => _description; - - set - { - _description = value; - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Description))); - } - } - - public InsightSimpleTextControl() - { - this.InitializeComponent(); - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/ProcessSelectionButton.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/ProcessSelectionButton.cs deleted file mode 100644 index 7b21082ae..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/ProcessSelectionButton.cs +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System.Diagnostics; -using DevHome.DevDiagnostics.Helpers; -using DevHome.DevDiagnostics.Models; -using Microsoft.UI.Input; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Input; - -namespace DevHome.DevDiagnostics.Controls; - -public class ProcessSelectionButton : AppBarButton -{ - public ProcessSelectionButton() - { - } - - protected override void OnPointerEntered(PointerRoutedEventArgs e) - { - base.OnPointerEntered(e); - - // When the mouse cursor is over the button, change to the default cursor. - ResetCursor(); - } - - protected override void OnPointerExited(PointerRoutedEventArgs e) - { - base.OnPointerExited(e); - - // When the mouse cursor leaves the button, change the cursor to the cross. - ChangeCursor(); - } - - protected override void OnPointerReleased(PointerRoutedEventArgs e) - { - base.OnPointerReleased(e); - - // Were we showing the select cursor? - if (ProtectedCursor == null) - { - return; - } - - Process? p; - Windows.Win32.Foundation.HWND hwnd; - - // Grab the window under the cursor and attach to that process. - WindowHelper.GetAppInfoUnderMouseCursor(out p, out hwnd); - if (p != null) - { - WindowHelper.TranslateUWPProcess(hwnd, ref p); - TargetAppData.Instance.SetNewAppData(p, hwnd); - } - - ResetCursor(); - } - - public void ChangeCursor() - { - ProtectedCursor = InputSystemCursor.Create(InputSystemCursorShape.Cross); - } - - public void ResetCursor() - { - ProtectedCursor = null; - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/ProgressTextRing.xaml b/tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/ProgressTextRing.xaml deleted file mode 100644 index 5d0c456db..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/ProgressTextRing.xaml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/ProgressTextRing.xaml.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/ProgressTextRing.xaml.cs deleted file mode 100644 index 067036e7d..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Controls/ProgressTextRing.xaml.cs +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System.ComponentModel; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; - -namespace DevHome.DevDiagnostics.Controls; - -public sealed partial class ProgressTextRing : UserControl, INotifyPropertyChanged -{ - public ProgressTextRing() - { - InitializeComponent(); - } - - public static readonly DependencyProperty IsActiveProperty = - DependencyProperty.Register(nameof(IsActive), typeof(bool), typeof(ProgressTextRing), new PropertyMetadata(false, OnIsActivePropertyChanged)); - - public bool IsActive - { - get => (bool)GetValue(IsActiveProperty); - set => SetValue(IsActiveProperty, value); - } - - private static void OnIsActivePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - var control = (ProgressTextRing)d; - control.OnPropertyChanged(nameof(TextBlockVisibility)); - } - - public static readonly DependencyProperty DiameterProperty = - DependencyProperty.Register(nameof(Diameter), typeof(double), typeof(ProgressTextRing), new PropertyMetadata(0.0, OnDiameterPropertyChanged)); - - public double Diameter - { - get => (double)GetValue(DiameterProperty); - set => SetValue(DiameterProperty, value); - } - - private static void OnDiameterPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - var control = (ProgressTextRing)d; - control.OnPropertyChanged(nameof(TextBlockFontSize)); - } - - public static readonly DependencyProperty ValueProperty = - DependencyProperty.Register(nameof(Value), typeof(double), typeof(ProgressTextRing), new PropertyMetadata(0.0, OnValuePropertyChanged)); - - public double Value - { - get => (double)GetValue(ValueProperty); - set => SetValue(ValueProperty, value); - } - - private static void OnValuePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - var control = (ProgressTextRing)d; - control.OnPropertyChanged(nameof(PercentageText)); - } - - private Visibility TextBlockVisibility => IsActive ? Visibility.Visible : Visibility.Collapsed; - - private double TextBlockFontSize => FontSize > 0 ? FontSize : Diameter / 3.6; - - public string PercentageText => $"{Value}%"; - - public event PropertyChangedEventHandler? PropertyChanged; - - private void OnPropertyChanged(string propertyName) - { - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/DD.ico b/tools/DevDiagnostics/DevHome.DevDiagnostics/DD.ico deleted file mode 100644 index 84014e6192492a72f9e12192525186c61e6583a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 151604 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�~6B*a(XPzHHZQp>4%Y&7=Brt1+AX8f7emwi59**N?EUc3s`Yt=~V453imbkG0f6hWN;4!D} zdOwMg8h6NKNnMRg&vCrZ|Lf}ng*hH$;?4m|b&XJ{x~|6a|0|Eexv{QV;MCR45R_&v zDPMpo%o-PeNnKstoEbA_AgFU0U0>tk*VL4kl`W~Mt3d<=s_O*(g^R0em{wL&?#b)X zcbxgv)r-qZpp39Zjf?L%Kn_{%`Z{Pfv!)K|0Ih&s+Jupwi&l zG~G8U-={X8r=+2l=h_plJE2cZNniHgR6H4%I1;8W4f;luFhf~h=fynZ_XvFBF;D)~ z@;VLru;W~ojw@k?QRTTWQ}taYaZTmv>q_NMT=ri~xTZ8oTMbn_#$}$GF4NRd%~#_R zM@?f~rt>UU!Zx2K63-U0Y}7B;a#1vs=Ap~$a3A*7*|^?zoc`bA`mN)9;Q?G2?-dtD z!@q$1F97e0t;kO~4t9B?&y4d2!6PzxeF;vJKIvAJ@BzIZCXH zqa9GJcol6>Yy;O`8_=Ez1~B70dqy~AdU!t@D1`f9bJPwFA41cD0@DD_aS_~(EAyw% znTACnbJ%xg{>-^^XU?3%-YfIOzqxZ}&Ag7$IYgK{SEMq>nLcwC{zRUDqyLTfIs5+s D^9AZs diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/DDApp.xaml b/tools/DevDiagnostics/DevHome.DevDiagnostics/DDApp.xaml deleted file mode 100644 index d8c6f41a9..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/DDApp.xaml +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - - - - - 0,0,0,4 - 0,8,0,8 - -12,0,0,0 - - 12 - 12,0 - XamlAutoFontFamily - 20 - - SemiBold - - - - diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/DDApp.xaml.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/DDApp.xaml.cs deleted file mode 100644 index 424ad44c9..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/DDApp.xaml.cs +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using DevHome.Common.Extensions; -using DevHome.Common.Services; -using DevHome.DevDiagnostics.Helpers; -using DevHome.DevDiagnostics.Models; -using DevHome.DevDiagnostics.Pages; -using DevHome.DevDiagnostics.Services; -using DevHome.DevDiagnostics.Telemetry; -using DevHome.DevDiagnostics.TelemetryEvents; -using DevHome.DevDiagnostics.ViewModels; -using DevHome.Service; -using DevHome.Telemetry; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using Microsoft.UI.Xaml; -using Windows.Storage; - -namespace DevHome.DevDiagnostics; - -public partial class App : Application, IApp -{ - // The .NET Generic Host provides dependency injection, configuration, logging, and other services. - // https://docs.microsoft.com/dotnet/core/extensions/generic-host - // https://docs.microsoft.com/dotnet/core/extensions/dependency-injection - // https://docs.microsoft.com/dotnet/core/extensions/configuration - // https://docs.microsoft.com/dotnet/core/extensions/logging - public IHost Host { get; } - - public T GetService() - where T : class => Host.GetService(); - - public Microsoft.UI.Dispatching.DispatcherQueue? UIDispatcher { get; } - - public App() - { - UnhandledException += App_UnhandledException; - - InitializeComponent(); - - UIDispatcher = Microsoft.UI.Dispatching.DispatcherQueue.GetForCurrentThread(); - - Host = Microsoft.Extensions.Hosting.Host.CreateDefaultBuilder() - .ConfigureServices((context, services) => - { - // Services - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(CommonHelper.GetDevHomeService()); - services.AddSingleton(); - - // Window - services.AddSingleton(); - - // Views and ViewModels - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - - // Settings sub-pages and viewmodels. - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - }).Build(); - - // Provide an explicit implementationInstance otherwise AddSingleton does not create a new instance immediately. - // It will lazily init when the first component requires it but the hotkey helper needs to be registered immediately. - Application.Current.GetService(); - - // And start up the listener for process load failures immediately - Application.Current.GetService(); - } - - private void App_UnhandledException(object sender, Microsoft.UI.Xaml.UnhandledExceptionEventArgs e) - { - // https://docs.microsoft.com/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.application.unhandledexception. - Serilog.Log.Fatal(e.Exception, $"Unhandled exception: {e.Message}"); - Serilog.Log.CloseAndFlush(); - - // We are very likely in a bad and unrecoverable state, so ensure we crash w/ the exception info. - Environment.FailFast(e.Message, e.Exception); - } - - internal static bool IsFeatureEnabled() - { - var isEnabled = false; - - ApplicationData.Current.LocalSettings.Values.TryGetValue($"ExperimentalFeature_DevDiagnosticsExperiment", out var isEnabledObj); - if (isEnabledObj is not null && isEnabledObj is string isEnabledValue) - { - isEnabled = isEnabledValue == "true"; - } - else - { -#if DEBUG - // Override on debug builds to be enabled by default - isEnabled = true; -#endif - } - - return isEnabled; - } - - internal static ITelemetry Logger => TelemetryFactory.Get(); - - internal static void LogTimeTaken(string eventName, uint timeTakenMilliseconds, Guid? relatedActivityId = null) => Logger.LogTimeTaken(eventName, timeTakenMilliseconds, relatedActivityId); - - internal static void LogCritical(string eventName, bool isError = false, Guid? relatedActivityId = null) => Logger.LogCritical(eventName, isError, relatedActivityId); - - internal static void Log(string eventName, LogLevel level, T data, Guid? relatedActivityId = null) - where T : EventBase - { - Logger.Log(eventName, level, data, relatedActivityId ?? null); - } - - internal static void LogError(string eventName, LogLevel level, T data, Guid? relatedActivityId = null) - where T : EventBase - { - Logger.LogError(eventName, level, data, relatedActivityId); - } - - internal static void Log(string eventName, LogLevel level, Guid? relatedActivityId = null) => Logger.Log(eventName, level, new UsageEventData(), relatedActivityId); -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/DevHome.DevDiagnostics.csproj b/tools/DevDiagnostics/DevHome.DevDiagnostics/DevHome.DevDiagnostics.csproj deleted file mode 100644 index ece671578..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/DevHome.DevDiagnostics.csproj +++ /dev/null @@ -1,243 +0,0 @@ - - - - WinExe - DevHome.DevDiagnostics - app.manifest - win-x86;win-x64;win-arm64 - Properties\PublishProfiles\win-$(Platform).pubxml - true - false - enable - 12.0 - DevHome.DevDiagnostics.Program - true - false - $(DefineConstants);DISABLE_XAML_GENERATED_MAIN - - - - 10.0.19041.0 - DD.ico - DD.ico - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - MSBuild:Compile - $(DefaultXamlRuntime) - - - - - - - - - - - PreserveNewest - - - PreserveNewest - - - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - - - - - - - - - - tlbimp - 0 - 1 - f935dc20-1cf0-11d0-adb9-00c04fd58a0b - 0 - false - true - - - - - - - - - - - - - - True - True - Settings.settings - - - - - MSBuild:Compile - - - MSBuild:Compile - - - MSBuild:Compile - - - MSBuild:Compile - - - MSBuild:Compile - - - MSBuild:Compile - - - MSBuild:Compile - - - MSBuild:Compile - - - MSBuild:Compile - - - MSBuild:Compile - - - MSBuild:Compile - - - Always - - - MSBuild:Compile - - - MSBuild:Compile - - - MSBuild:Compile - - - MSBuild:Compile - - - MSBuild:Compile - - - MSBuild:Compile - - - MSBuild:Compile - - - MSBuild:Compile - - - MSBuild:Compile - - - MSBuild:Compile - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - MSBuild:Compile - - - MSBuild:Compile - - - - - 7 - - - 7 - - - 7 - - - 7 - - - 7 - - - 7 - - - 7 - - - 7 - - - 7 - - diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/ClipboardMonitorInternalTool.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/ClipboardMonitorInternalTool.cs deleted file mode 100644 index 2488aca79..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/ClipboardMonitorInternalTool.cs +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using DevHome.Common.Extensions; -using DevHome.DevDiagnostics.Properties; -using DevHome.DevDiagnostics.Views; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Media; -using Windows.Graphics; - -namespace DevHome.DevDiagnostics.Helpers; - -public class ClipboardMonitorInternalTool : Tool -{ - private const string ClipboardButtonText = "\uf0e3"; // ClipboardList - private static readonly string _clipboardMonitorToolName = CommonHelper.GetLocalizedString("ClipboardMonitorName"); - - private ClipboardMonitoringWindow? _clipboardMonitoringWindow; - - public ClipboardMonitorInternalTool() - : base(_clipboardMonitorToolName, ToolType.Unknown, Settings.Default.IsClipboardMonitorToolPinned) - { - } - - public override IconElement GetIcon() - { - return new FontIcon - { - Glyph = ClipboardButtonText, - FontFamily = (FontFamily)Application.Current.Resources["SymbolThemeFontFamily"], - }; - } - - internal override void InvokeTool(ToolLaunchOptions options) - { - if (_clipboardMonitoringWindow is null || _clipboardMonitoringWindow.AppWindow is null) - { - _clipboardMonitoringWindow = new ClipboardMonitoringWindow(); - - // Add this window to the list of related windows for the BarWindow, - // so that we can ensure that any BarWindow theme changes are also propagated to this window. - var barWindow = Application.Current.GetService().DBarWindow; - barWindow?.AddRelatedWindow(_clipboardMonitoringWindow); - } - - if (options.ParentWindow is not null) - { - RectInt32 rect; - rect.X = options.ParentWindow.AppWindow.Position.X; - rect.Y = options.ParentWindow.AppWindow.Position.Y + 100; - rect.Width = options.ParentWindow.AppWindow.Size.Width; - rect.Height = _clipboardMonitoringWindow.AppWindow.Size.Height; - - _clipboardMonitoringWindow.AppWindow.MoveAndResize(rect); - } - - _clipboardMonitoringWindow.Activate(); - } - - protected override void OnIsPinnedChange(bool newValue) - { - Settings.Default.IsClipboardMonitorToolPinned = newValue; - Settings.Default.Save(); - } - - public override void UnregisterTool() - { - // Ignore this command for now until we have a way for the user to discover unregistered internal tools - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/CommonHelper.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/CommonHelper.cs deleted file mode 100644 index 75c46b0e5..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/CommonHelper.cs +++ /dev/null @@ -1,208 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.ComponentModel; -using System.Diagnostics; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Management; -using System.Runtime.InteropServices; -using DevHome.Common.Extensions; -using DevHome.Common.Services; -using DevHome.Service; -using Microsoft.UI.Xaml; -using Serilog; -using Windows.ApplicationModel; -using Windows.Wdk.System.Threading; -using Windows.Win32.Foundation; -using Windows.Win32.System.Threading; -using WinRT; -using PInvokeWdk = Windows.Wdk.PInvoke; - -namespace DevHome.DevDiagnostics.Helpers; - -internal sealed class CommonHelper -{ - public const string UnpinGlyph = "\uE77A"; - public const string PinGlyph = "\uE718"; - - private static readonly ILogger _log = Log.ForContext("SourceContext", nameof(CommonHelper)); - - internal static string GetLocalizedString(string stringName, params object[] args) - { - var stringResource = new StringResource(); - var localizedString = stringResource.GetLocalized(stringName, args); - Debug.Assert(!string.IsNullOrEmpty(localizedString), stringName + " is empty. Check if " + stringName + " is present in Resources.resw."); - return localizedString; - } - - internal static void RunAsAdmin(int pid, string pageName) - { - var startInfo = new ProcessStartInfo(); - startInfo.WindowStyle = ProcessWindowStyle.Hidden; - - var aliasSubDirectoryPath = $"Microsoft\\WindowsApps\\{Package.Current.Id.FamilyName}\\devhome.devdiagnostics.exe"; - var aliasPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), aliasSubDirectoryPath); - startInfo.FileName = aliasPath; - - // Pass pid and the page from where the admin request came from - startInfo.Arguments = $"--pid {pid} --expandWindow {pageName}"; - startInfo.UseShellExecute = true; - startInfo.Verb = "runas"; - - var process = new Process(); - process.StartInfo = startInfo; - - // Since a UAC prompt will be shown, we need to wait for the process to exit - // This can also be cancelled by the user which will result in an exception - try - { - process.Start(); - - // Close the primary window for this instance and exit - var primaryWindow = Application.Current.GetService(); - primaryWindow.Close(); - } - catch (Win32Exception ex) - { - _log.Error(ex, "Could not run Dev Diagnostics as admin"); - if (ex.NativeErrorCode == (int)WIN32_ERROR.ERROR_CANT_ACCESS_FILE) - { - var barWindow = Application.Current.GetService().DBarWindow; - barWindow?.ShowDialogToEnableAppExecutionAlias(); - } - else if (ex.NativeErrorCode == (int)WIN32_ERROR.ERROR_CANCELLED) - { - _log.Error(ex, "UAC to run Dev Diagnostics as admin was denied"); - } - } - } - - public static unsafe int GetParentProcessId(Process process) - { - var pbi = default(PROCESS_BASIC_INFORMATION); - int status = PInvokeWdk.NtQueryInformationProcess((HANDLE)process.Handle, PROCESSINFOCLASS.ProcessBasicInformation, &pbi, (uint)Marshal.SizeOf(pbi), null); - if (status != 0) - { - throw new InvalidOperationException("Failed to query process information."); - } - - return (int)pbi.InheritedFromUniqueProcessId; - } - - public static HWND? TryGetParentProcessHWND() - { - try - { - using var process = Process.GetCurrentProcess(); - var parentProcessId = GetParentProcessId(process); - if (parentProcessId != 0) - { - using var parentProcess = Process.GetProcessById(parentProcessId); - return new HWND(parentProcess.MainWindowHandle); - } - } - catch (Exception ex) - { - _log.Error(ex, "Failed to get parent process HWND"); - } - - return null; - } - - public static string GetCommandLine(Process process) - { - var activationArgs = string.Empty; - try - { - using var searcher = new ManagementObjectSearcher( - $"SELECT CommandLine FROM Win32_Process WHERE ProcessId = {process.Id}"); - if (searcher is null) - { - return activationArgs; - } - - using var objects = searcher.Get(); - if (objects is null) - { - return activationArgs; - } - - var obj = objects.Cast().FirstOrDefault(); - if (obj is not null) - { - activationArgs = obj["CommandLine"]?.ToString() ?? string.Empty; - } - } - catch (Exception ex) - { - _log.Error(ex, "Failed to get command line for process {ProcessId}", process.Id); - } - - return activationArgs; - } - - private static readonly Int32Converter _converter = new(); - - public static int? ParseStringToInt(string value) - { - int? valueAsInt; - - try - { - if (_converter.IsValid(value)) - { - // Int32Converter.ConvertFromString() does a pretty good job of parsing numbers, except when given a hex - // number that isn't prefixed with 0x. If it fails, try parsing it using int.Parse(). - valueAsInt = (int?)_converter.ConvertFromString(value); - } - else - { - valueAsInt = int.Parse(value, NumberStyles.HexNumber, CultureInfo.CurrentCulture); - } - } - catch - { - return null; - } - - return valueAsInt; - } - - public static int MulDiv(int number, int numerator, int denominator) - { - return (int)((((long)number * numerator) + (denominator >> 1)) / denominator); - } - - public static IDevHomeService GetDevHomeService() - { - try - { - var serverClass = new DevHomeServer(); - var serverPtr = Marshal.GetIUnknownForObject(serverClass); - var server = MarshalInterface.FromAbi(serverPtr); - return server; - } - catch (Exception ex) - { - _log.Error(ex, "Failed to get DevHomeService"); - - // We shouldn't treat our inability to connect to the NT service as fatal. We should still be able to run, with reduced functionality. - - // Return a "dummy" service that does nothing, so that we don't need to have multiple checks in the code to see if we have a service or not - return new StandInDevHomeService(); - } - } - - [ComImport] - #if CANARY_BUILD - [Guid("0A920C6E-2569-44D1-A6E4-CE9FA44CD2A7")] - #elif STABLE_BUILD - [Guid("E8D40232-20A1-4F3B-9C0C-AAA6538698C6")] - #else - [Guid("1F98F450-C163-4A99-B257-E1E6CB3E1C57")] - #endif - public class DevHomeServer; -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/CommonInterop.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/CommonInterop.cs deleted file mode 100644 index 1c961d3cb..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/CommonInterop.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System.Runtime.InteropServices; -using Windows.Win32.Foundation; -using Windows.Win32.UI.WindowsAndMessaging; - -namespace DevHome.DevDiagnostics.Helpers; - -internal sealed class CommonInterop -{ - // CSWin32 will not produce these methods for x86 so we need to define them here. - [DllImport("user32.dll", ExactSpelling = true, EntryPoint = "SetWindowLongPtrW", SetLastError = true)] - internal static extern nint SetWindowLongPtr64(HWND hWnd, WINDOW_LONG_PTR_INDEX nIndex, nint dwNewLong); - - [DllImport("user32.dll", ExactSpelling = true, EntryPoint = "GetWindowLongPtrW", SetLastError = true)] - internal static extern nint GetWindowLongPtr64(HWND hWnd, WINDOW_LONG_PTR_INDEX nIndex); - - [DllImport("user32.dll", ExactSpelling = true, EntryPoint = "GetClassLongPtrW", SetLastError = true)] - internal static extern nint GetClassLongPtr64(HWND hWnd, GET_CLASS_LONG_INDEX nIndex); -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/CountToVisibilityConverter.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/CountToVisibilityConverter.cs deleted file mode 100644 index 0b2d6757f..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/CountToVisibilityConverter.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Data; - -namespace DevHome.DevDiagnostics.Helpers; - -public class CountToVisibilityConverter : IValueConverter -{ - public object Convert(object value, Type targetType, object parameter, string language) - { - var count = (int)value; - return count > 0 ? Visibility.Collapsed : Visibility.Visible; - } - - public object ConvertBack(object value, Type targetType, object parameter, string language) - { - throw new NotImplementedException(); - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/DebugMonitor.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/DebugMonitor.cs deleted file mode 100644 index b8d5f8960..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/DebugMonitor.cs +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Diagnostics; -using System.IO; -using System.IO.MemoryMappedFiles; -using System.Text; -using System.Threading; -using DevHome.DevDiagnostics.Models; - -namespace DevHome.DevDiagnostics.Helpers; - -public sealed class DebugMonitor : IDisposable -{ - private readonly Process targetProcess; - private readonly ObservableCollection output; - private readonly EventWaitHandle stopEvent; - private readonly string errorMessageText = CommonHelper.GetLocalizedString("WinLogsAlreadyRunningErrorMessage"); - - private const string MutexName = "DevHome.PI.DebugMonitor.SingletonMutex"; - private const string StopEventName = "DebugMonitorStopEvent"; - private const string DBWinBufferReadyName = "DBWIN_BUFFER_READY"; - private const string DBWinDataReadyName = "DBWIN_DATA_READY"; - private const string DBWinBufferName = "DBWIN_BUFFER"; - - private static readonly List IgnoreLogList = []; - - public DebugMonitor(Process targetProcess, ObservableCollection output) - { - this.targetProcess = targetProcess; - this.targetProcess.Exited += TargetProcess_Exited; - this.output = output; - - stopEvent = new EventWaitHandle(false, EventResetMode.AutoReset, StopEventName); - } - - public void Start() - { - stopEvent.Reset(); - - // Don't initiate if debugger is attached. It makes debugging very slow. - if (Debugger.IsAttached) - { - return; - } - - // Check for multiple instances. It is possible to have multiple debug monitors listen on OutputDebugString, - // but the message would be randomly distributed among all running instances. - using var singletonMutex = new Mutex(false, MutexName, out var createdNew); - if (!createdNew) - { - throw new InvalidOperationException($"Failed to get the {MutexName} mutex."); - } - - bool isNewBufferReadyEvent; - using var bufferReadyEvent = new EventWaitHandle(false, EventResetMode.AutoReset, DBWinBufferReadyName, out isNewBufferReadyEvent); - bool isNewDataReadyEvent; - using var dataReadyEvent = new EventWaitHandle(false, EventResetMode.AutoReset, DBWinDataReadyName, out isNewDataReadyEvent); - - // Don't initiate if there is an existing OutputDebugString monitor running - if (!isNewBufferReadyEvent || !isNewDataReadyEvent) - { - WinLogsEntry entry = new(DateTime.Now, WinLogCategory.Error, errorMessageText, WinLogsHelper.DebugOutputLogsName); - output.Add(entry); - return; - } - - using var memoryMappedFile = MemoryMappedFile.CreateNew(DBWinBufferName, 4096); - while (true) - { - bufferReadyEvent.Set(); - var waitResult = WaitHandle.WaitAny(new[] { stopEvent, dataReadyEvent }); - - // Stop listenting to OutputDebugString if the debugger is attached. It makes debugging very slow. - if (Debugger.IsAttached) - { - break; - } - - // Stop event is triggered. - if (waitResult == 0) - { - break; - } - - if (waitResult == 1) - { - var timeGenerated = DateTime.Now; - - // The first DWORD of the shared memory buffer contains - // the process ID of the client that sent the debug string. - using var viewStream = memoryMappedFile.CreateViewStream(0, 0, MemoryMappedFileAccess.Read); - using BinaryReader binaryReader = new BinaryReader(viewStream); - var pid = binaryReader.ReadUInt32(); - - if (pid == targetProcess.Id) - { - // Get the message from the stream. - var stringBuilder = new StringBuilder(); - while (binaryReader.PeekChar() != '\0') - { - stringBuilder.Append(binaryReader.ReadChar()); - } - - var entryMessage = stringBuilder.ToString(); - - if (!string.IsNullOrWhiteSpace(entryMessage)) - { - var hasIgnoreLog = false; - foreach (var ignoreLog in IgnoreLogList) - { - if (entryMessage.Contains(ignoreLog)) - { - hasIgnoreLog = true; - } - } - - if (!hasIgnoreLog) - { - WinLogsEntry entry = new(timeGenerated, WinLogCategory.Debug, entryMessage, WinLogsHelper.DebugOutputLogsName); - output.Add(entry); - } - } - } - } - } - } - - public void Stop() - { - if (!stopEvent.SafeWaitHandle.IsClosed) - { - stopEvent.Set(); - } - } - - public void Dispose() - { - stopEvent.Close(); - stopEvent.Dispose(); - - GC.SuppressFinalize(this); - } - - private void TargetProcess_Exited(object? sender, EventArgs e) - { - Stop(); - Dispose(); - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/ETWHelper.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/ETWHelper.cs deleted file mode 100644 index 54166dc49..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/ETWHelper.cs +++ /dev/null @@ -1,187 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Diagnostics; -using System.Globalization; -using System.Linq; -using System.Security.Principal; -using DevHome.DevDiagnostics.Models; -using Microsoft.Diagnostics.Tracing; -using Microsoft.Diagnostics.Tracing.Session; -using Serilog; - -namespace DevHome.DevDiagnostics.Helpers; - -internal sealed class ETWHelper : IDisposable -{ - private static readonly ILogger _log = Log.ForContext("SourceContext", nameof(ETWHelper)); - private readonly Process _targetProcess; - private readonly ObservableCollection _output; - - private static readonly List _providerList = ["1AFF6089-E863-4D36-BDFD-3581F07440BE" /*COM Tracelog*/]; - private TraceEventSession? _session; - - // From: https://learn.microsoft.com/windows-server/identity/ad-ds/manage/understand-security-identifiers - private const string PerformanceLogUsersSid = "S-1-5-32-559"; - - public const string AddUserToPerformanceLogUsersSid = @" - Add-LocalGroupMember -Sid S-1-5-32-559 -Member ([System.Security.Principal.WindowsIdentity]::GetCurrent().Name) - # Check if the last command succeeded - if ($?) - { - # User added to the Performance Log Users group. - exit 0 - } - exit 1 - "; - - public ETWHelper(Process targetProcess, ObservableCollection output) - { - _targetProcess = targetProcess; - _targetProcess.Exited += TargetProcess_Exited; - _output = output; - } - - public void Start() - { - var isUserInPerformanceLogUsersGroup = IsUserInPerformanceLogUsersGroup(); - - if (!isUserInPerformanceLogUsersGroup) - { - isUserInPerformanceLogUsersGroup = TryAddUserToPerformanceLogUsersGroup(); - } - - if (isUserInPerformanceLogUsersGroup) - { - var sessionName = "DevHomePITrace" + Process.GetCurrentProcess().SessionId; - - // Stop and dispose any existing session - _session = TraceEventSession.GetActiveSession(sessionName); - if (_session is not null) - { - _session.Stop(); - _session.Dispose(); - } - - try - { - using (_session = new TraceEventSession(sessionName)) - { - // Filter the provider events based on processId - var providerOptions = new TraceEventProviderOptions { ProcessIDFilter = [_targetProcess.Id] }; - foreach (var provider in _providerList) - { - _session.EnableProvider(provider, TraceEventLevel.Always, options: providerOptions); - } - - _session.Source.Dynamic.All += EventsHandler; - _session.Source.UnhandledEvents += UnHandledEventsHandler; - _session.Source.Process(); - } - } - catch (Exception ex) - { - Stop(); - WinLogsEntry entry = new(DateTime.Now, WinLogCategory.Error, ex.Message, WinLogsHelper.EtwLogsName); - _output.Add(entry); - } - } - } - - public void Stop() - { - _session?.Stop(); - } - - public void Dispose() - { - _session?.Dispose(); - GC.SuppressFinalize(this); - } - - private void EventsHandler(TraceEvent traceEvent) - { - ETWEventHandler(traceEvent.ProcessID, traceEvent.TimeStamp, traceEvent.Level, traceEvent.ToString(CultureInfo.CurrentCulture)); - } - - private void UnHandledEventsHandler(TraceEvent traceEvent) - { - var errorMessage = CommonHelper.GetLocalizedString("UnhandledTraceEventErrorMessage", traceEvent.Dump()); - ETWEventHandler(traceEvent.ProcessID, traceEvent.TimeStamp, traceEvent.Level, errorMessage); - } - - private void ETWEventHandler(int processId, DateTime timeStamp, TraceEventLevel level, string message) - { - if (processId != _targetProcess.Id) - { - return; - } - - var category = WinLogsHelper.ConvertTraceEventLevelToWinLogCategory(level); - var entry = new WinLogsEntry(timeStamp, category, message, WinLogsHelper.EtwLogsName); - _output.Add(entry); - } - - private void TargetProcess_Exited(object? sender, EventArgs e) - { - Stop(); - Dispose(); - } - - public static bool IsUserInPerformanceLogUsersGroup() - { - WindowsIdentity processUserIdentity = WindowsIdentity.GetCurrent(); - var isPerformanceLogSidFound = processUserIdentity.Groups?.Any(sid => sid.Value == PerformanceLogUsersSid); - return isPerformanceLogSidFound ?? false; - } - - public static bool TryAddUserToPerformanceLogUsersGroup() - { - WindowsIdentity processUserIdentity = WindowsIdentity.GetCurrent(); - var userName = processUserIdentity.Name; - if (userName is null) - { - _log.Error("Unable to get the current user name"); - return false; - } - - var startInfo = new ProcessStartInfo(); - startInfo.WindowStyle = ProcessWindowStyle.Hidden; - startInfo.FileName = $"powershell.exe"; - - // Add the user to the Performance Log Users group - startInfo.Arguments = $"-ExecutionPolicy Bypass -Command \"{AddUserToPerformanceLogUsersSid}\""; - startInfo.UseShellExecute = true; - startInfo.Verb = "runas"; - - var process = new Process(); - process.StartInfo = startInfo; - - // Since a UAC prompt will be shown, we need to wait for the process to exit - // This can also be cancelled by the user which will result in an exception - try - { - process.Start(); - process.WaitForExit(); - - if (process.ExitCode == 0) - { - return true; - } - else - { - _log.Error("Unable to add the user to the Performance Log Users group"); - return false; - } - } - catch (Exception ex) - { - _log.Error(ex, "UAC to add the user to the Performance Log Users group was denied"); - } - - return false; - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/EnumStringConverter.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/EnumStringConverter.cs deleted file mode 100644 index 08825d09f..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/EnumStringConverter.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace DevHome.DevDiagnostics.Helpers; - -#pragma warning disable SA1649 // File name should match first type name -public class EnumStringConverter : JsonConverter -#pragma warning restore SA1649 // File name should match first type name - where TEnum : struct -{ - public override TEnum Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - if (reader.TokenType != JsonTokenType.String) - { - throw new JsonException(); - } - - var enumString = reader.GetString(); - if (Enum.TryParse(enumString, ignoreCase: true, out TEnum result)) - { - return result; - } - - throw new JsonException($"Unable to convert \"{enumString}\" to enum type {typeof(TEnum)}."); - } - - public override void Write(Utf8JsonWriter writer, TEnum value, JsonSerializerOptions options) - { - writer.WriteStringValue(value.ToString()); - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/ErrorLookupHelper.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/ErrorLookupHelper.cs deleted file mode 100644 index 9f1a240dc..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/ErrorLookupHelper.cs +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Reflection; -using Microsoft.Data.Sqlite; -using Serilog; - -namespace DevHome.DevDiagnostics.Helpers; - -internal sealed class ErrorLookupHelper -{ - private static readonly ILogger _log = Log.ForContext("SourceContext", nameof(ErrorLookupHelper)); - - private static SqliteConnectionStringBuilder? _dbConnectionString; - - private static SqliteConnectionStringBuilder DbConnectionString - { - get - { - if (_dbConnectionString == null) - { - _dbConnectionString = new SqliteConnectionStringBuilder(); - var path = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location); - var dbPath = Path.Combine(path ?? string.Empty, "errors.db"); - - _dbConnectionString.DataSource = dbPath; - _dbConnectionString.Mode = SqliteOpenMode.ReadOnly; - } - - return _dbConnectionString; - } - } - - public static AppError[]? LookupError(int error) - { - try - { - using SqliteConnection connection = new(DbConnectionString.ConnectionString); - connection.Open(); - AppError[]? errors = LookupErrors(connection, error); - connection.Close(); - return errors; - } - catch - { - _log.Error("Failed to look up errors: {AppError}", error.ToString(CultureInfo.CurrentCulture)); - } - - return null; - } - - private static AppError[]? LookupErrors(SqliteConnection connection, int hresult) - { - // Look up a solution for an error. - SqliteCommand errorCommand = connection.CreateCommand(); - errorCommand.CommandText = @"select Name, Help from tblErrors WHERE code=@code"; - - SqliteParameter errorParam = new("@code", hresult.ToString(CultureInfo.CurrentCulture)); - errorCommand.Parameters.Add(errorParam); - SqliteDataReader errorReader = errorCommand.ExecuteReader(); - IList errors = []; - - while (errorReader.Read()) - { - AppError error = new() - { - Code = hresult, - Name = errorReader.GetString(0), - Help = errorReader.GetString(1), - }; - errors.Add(error); - } - - errorReader.Close(); - return errors.ToArray(); - } -} - -public class AppError -{ - public int Code { get; set; } - - public string Name { get; set; } = string.Empty; - - public string Help { get; set; } = string.Empty; -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/EventViewerHelper.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/EventViewerHelper.cs deleted file mode 100644 index a086bff6c..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/EventViewerHelper.cs +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Collections.ObjectModel; -using System.Diagnostics; -using System.Diagnostics.Eventing.Reader; -using DevHome.DevDiagnostics.Models; - -namespace DevHome.DevDiagnostics.Helpers; - -internal sealed class EventViewerHelper : IDisposable -{ - private readonly Process targetProcess; - private readonly ObservableCollection output; - private readonly EventLogWatcher? eventLogWatcher; - - public EventViewerHelper(Process targetProcess, ObservableCollection output) - { - this.targetProcess = targetProcess; - this.targetProcess.Exited += TargetProcess_Exited; - this.output = output; - - try - { - // Subscribe for Application events matching the processName. - var filterQuery = "*[System[Provider[@Name=\"" + targetProcess.ProcessName + "\"]]]"; - EventLogQuery subscriptionQuery = new("Application", PathType.LogName, filterQuery); - eventLogWatcher = new EventLogWatcher(subscriptionQuery); - eventLogWatcher.EventRecordWritten += new EventHandler(EventLogEventRead); - } - catch (EventLogReadingException) - { - var message = CommonHelper.GetLocalizedString("UnableToStartEventViewerErrorMessage"); - WinLogsEntry entry = new(DateTime.Now, WinLogCategory.Error, message, WinLogsHelper.EventViewerName); - output.Add(entry); - } - } - - public void Start() - { - if (eventLogWatcher is not null) - { - eventLogWatcher.Enabled = true; - } - } - - public void Stop() - { - if (eventLogWatcher is not null) - { - eventLogWatcher.Enabled = false; - } - } - - public void Dispose() - { - if (eventLogWatcher is not null) - { - eventLogWatcher.Dispose(); - } - - GC.SuppressFinalize(this); - } - - public void EventLogEventRead(object? obj, EventRecordWrittenEventArgs eventArg) - { - if (eventArg.EventRecord != null) - { - WinLogCategory category = WinLogsHelper.ConvertStandardEventLevelToWinLogCategory(eventArg.EventRecord.Level); - var message = eventArg.EventRecord.FormatDescription(); - WinLogsEntry entry = new(eventArg.EventRecord.TimeCreated, category, message, WinLogsHelper.EventViewerName); - output.Add(entry); - } - } - - private void TargetProcess_Exited(object? sender, EventArgs e) - { - Stop(); - Dispose(); - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/ExpanderBehavior.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/ExpanderBehavior.cs deleted file mode 100644 index ce4e01881..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/ExpanderBehavior.cs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using DevHome.DevDiagnostics.Models; -using Microsoft.UI.Xaml.Controls; -using Microsoft.Xaml.Interactivity; - -namespace DevHome.DevDiagnostics.Helpers; - -public class ExpanderBehavior : Behavior -{ - protected override void OnAttached() - { - base.OnAttached(); - AssociatedObject.Expanding += AssociatedObject_Expanding; - AssociatedObject.Collapsed += OnCollapsed; - } - - private void AssociatedObject_Expanding(Expander sender, ExpanderExpandingEventArgs args) - { - if (AssociatedObject.DataContext is Insight insight && !insight.HasBeenRead) - { - insight.HasBeenRead = true; - insight.BadgeOpacity = 0; - } - } - - private void OnCollapsed(Expander sender, ExpanderCollapsedEventArgs args) - { - // Do nothing: once we've set HasBeenRead to true, we don't change it again. - } - - protected override void OnDetaching() - { - base.OnDetaching(); - AssociatedObject.Expanding -= AssociatedObject_Expanding; - AssociatedObject.Collapsed -= OnCollapsed; - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/ExternalTool.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/ExternalTool.cs deleted file mode 100644 index 2ad181d4d..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/ExternalTool.cs +++ /dev/null @@ -1,313 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Globalization; -using System.IO; -using System.Runtime.InteropServices; -using System.Text; -using System.Text.Json.Serialization; -using System.Text.RegularExpressions; -using System.Threading.Tasks; -using DevHome.Common.Extensions; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Serilog; -using Windows.System; -using Windows.Win32; -using Windows.Win32.Foundation; -using Windows.Win32.System.Com; -using Windows.Win32.UI.WindowsAndMessaging; -using static DevHome.DevDiagnostics.Helpers.WindowHelper; - -namespace DevHome.DevDiagnostics.Helpers; - -public enum ToolActivationType -{ - Protocol, - Msix, - Launch, -} - -public partial class ExternalTool : Tool -{ - private static readonly ILogger _log = Log.ForContext("SourceContext", nameof(ExternalTool)); - private readonly string _errorTitleText = CommonHelper.GetLocalizedString("ToolLaunchErrorTitle"); - - private readonly string _errorMessageText = CommonHelper.GetLocalizedString("ToolLaunchErrorMessage"); - - public string ID { get; private set; } - - public string Executable { get; private set; } - - [JsonConverter(typeof(EnumStringConverter))] - public ToolActivationType ActivationType { get; private set; } = ToolActivationType.Launch; - - public string Arguments { get; private set; } - - public string ExtraInfo { get; private set; } - - public string AppUserModelId { get; private set; } - - public string IconFilePath { get; private set; } - - public ExternalTool( - string name, - string executable, - ToolActivationType activationType, - string arguments = "", - string extraInfo = "", - string appUserModelId = "", - string iconFilePath = "", - ToolType type = ToolType.Unknown, - bool isPinned = false) - : base(name, type, isPinned) - { - Executable = executable; - ActivationType = activationType; - Arguments = arguments; - ExtraInfo = extraInfo; - AppUserModelId = appUserModelId; - IconFilePath = iconFilePath; - - ID = Guid.NewGuid().ToString(); - - if (!string.IsNullOrEmpty(executable)) - { - GetIcons(); - } - } - - private async void GetIcons() - { - try - { - if (!string.IsNullOrEmpty(IconFilePath)) - { - ToolIconSource = await GetSoftwareBitmapSourceFromImageFilePath(IconFilePath); - } - else - { - var softwareBitmap = GetSoftwareBitmapFromExecutable(Executable); - if (softwareBitmap is not null) - { - ToolIconSource = await GetSoftwareBitmapSourceFromSoftwareBitmapAsync(softwareBitmap); - } - } - } - catch (Exception ex) - { - _log.Error(ex, "Failed to get tool image"); - } - } - - public override IconElement GetIcon() - { - return new ImageIcon - { - Source = ToolIconSource, - }; - } - - internal async override void InvokeTool(ToolLaunchOptions options) - { - try - { - await InvokeToolInternal(options); - } - catch (Exception ex) - { - _log.Error(ex, "Tool launched failed"); - - var builder = new StringBuilder(); - builder.AppendLine(ex.Message); - if (ex.InnerException is not null) - { - builder.AppendLine(ex.InnerException.Message); - } - - var errorMessage = string.Format(CultureInfo.CurrentCulture, builder.ToString(), Executable); - PInvoke.MessageBox(HWND.Null, errorMessage, _errorTitleText, MESSAGEBOX_STYLE.MB_ICONERROR); - } - } - - internal void ValidateOptions(ToolLaunchOptions options) - { - // We can only get stdout if we're launching the process via CreateProcess. - if (options.RedirectStandardOut && ActivationType != ToolActivationType.Launch) - { - throw new InvalidOperationException("Can only redirect StandardOut with a CreateProcess launch"); - } - } - - private string CreateCommandLine(ToolLaunchOptions options) - { - var commandLineArgs = string.Empty; - if (!string.IsNullOrEmpty(Arguments)) - { - var argumentVariables = new Dictionary(); - if (options.TargetProcessId.HasValue) - { - argumentVariables.Add("pid", options.TargetProcessId.Value.ToString(CultureInfo.InvariantCulture)); - } - - if (options.TargetHWnd != HWND.Null) - { - argumentVariables.Add("hwnd", ((int)options.TargetHWnd).ToString(CultureInfo.InvariantCulture)); - } - - if (Type.HasFlag(ToolType.DumpAnalyzer) && options.CommandLineParams is not null) - { - argumentVariables.Add("crashDumpPath", options.CommandLineParams); - } - - commandLineArgs = ReplaceKnownVariables(Arguments, argumentVariables); - } - - return commandLineArgs; - } - - internal async Task InvokeToolInternal(ToolLaunchOptions options) - { - var process = default(Process); - - ValidateOptions(options); - - string commandLineArgs = CreateCommandLine(options); - - try - { - if (ActivationType == ToolActivationType.Protocol) - { - // Docs say this returns true if the default app for the URI scheme was launched; - // false otherwise. However, if there's no registered app for the protocol, it shows - // the "get an app from the store" dialog, and returns true. So we can't rely on the - // return value to know if the tool was actually launched. - var result = await Launcher.LaunchUriAsync(new Uri(commandLineArgs)); - if (result != true) - { - // We get here if the user supplied a valid registered protocol, but the app failed to launch. - var errorMessage = string.Format( - CultureInfo.InvariantCulture, _errorMessageText, commandLineArgs); - throw new InvalidOperationException(errorMessage); - } - - // Currently we can't get the process object of the launched app via LaunchUriAsync. If we - // ever do and want to populate ToolLaunchOptions.LaunchedProcess, we'll need to revisit the async behavior here, - // as when we return from this function (and our async operation is still ongoing) our callers currently expect to - // be able to read ToolLaunchOptions.LaunchedProcess immedately... there isn't an indication that they would need to - // do an await first. - } - else - { - if (ActivationType == ToolActivationType.Msix) - { - process = LaunchPackagedTool(AppUserModelId); - } - else - { - var finalExecutable = string.Empty; - var finalArguments = string.Empty; - - if (Path.GetExtension(Executable).Equals(".msc", StringComparison.OrdinalIgnoreCase)) - { - // Note: running most msc files requires elevation. - finalExecutable = "mmc.exe"; - finalArguments = $"{Executable} {commandLineArgs}"; - } - else if (Path.GetExtension(Executable).Equals(".ps1", StringComparison.OrdinalIgnoreCase)) - { - // Note: running powershell scripts might require setting the execution policy. - finalExecutable = "powershell.exe"; - finalArguments = $"{Executable} {commandLineArgs}"; - } - else - { - finalExecutable = Executable; - finalArguments = commandLineArgs; - } - - var startInfo = new ProcessStartInfo() - { - FileName = finalExecutable, - Arguments = finalArguments, - - // If we want to redirect standard out, we can't use shell execute - UseShellExecute = !options.RedirectStandardOut, - RedirectStandardOutput = options.RedirectStandardOut, - }; - process = Process.Start(startInfo); - } - } - } - catch (Exception ex) - { - // We compose a custom exception because an exception from executing some tools - // (powershell, mmc) will have lost the target tool information. - var errorMessage = string.Format(CultureInfo.InvariantCulture, _errorMessageText, Executable); - throw new InvalidOperationException(errorMessage, ex); - } - - options.LaunchedProcess = process; - return process; - } - - public static Process? LaunchPackagedTool(string appUserModelId) - { - var process = default(Process); - var clsid = CLSID.ApplicationActivationManager; - var iid = typeof(IApplicationActivationManager).GUID; - object obj; - - int hr = PInvoke.CoCreateInstance( - in clsid, null, CLSCTX.CLSCTX_LOCAL_SERVER, in iid, out obj); - - if (HResult.Succeeded(hr)) - { - var appActiveManager = (IApplicationActivationManager)obj; - uint processId; - hr = appActiveManager.ActivateApplication( - appUserModelId, string.Empty, ACTIVATEOPTIONS.None, out processId); - if (HResult.Succeeded(hr)) - { - process = Process.GetProcessById((int)processId); - } - } - else - { - Marshal.ThrowExceptionForHR(hr); - } - - return process; - } - - private string ReplaceKnownVariables(string input, Dictionary argumentValues) - { - // Process the input string to replace any instance of defined variables with "real" values. - // Eg, replace {pid} with 123, {hwnd} with 456. - var pattern = @"\{(\w+)\}"; - - var result = Regex.Replace(input, pattern, match => - { - var variable = match.Groups[1].Value; - - // Check if the variable exists in the dictionary; if so, replace it. - if (argumentValues.TryGetValue(variable, out var replacementValue)) - { - return replacementValue; - } - - // If the variable is not found, keep it as is. - return match.Value; - }); - - return result; - } - - public override void UnregisterTool() - { - Application.Current.GetService().RemoveExternalTool(this); - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/ExternalToolCollection.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/ExternalToolCollection.cs deleted file mode 100644 index b961edad5..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/ExternalToolCollection.cs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System.Collections.ObjectModel; - -namespace DevHome.DevDiagnostics.Helpers; - -public class ExternalToolCollection -{ - public int Version { get; set; } - - public ObservableCollection ExternalTools { get; set; } - - public ExternalToolCollection() - { - Version = ExternalToolsHelper.ToolsCollectionVersion; - ExternalTools = []; - } - - public ExternalToolCollection(int version, ObservableCollection tools) - { - Version = version; - ExternalTools = tools; - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/ExternalTool_v1.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/ExternalTool_v1.cs deleted file mode 100644 index 86a143df0..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/ExternalTool_v1.cs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Text.Json.Serialization; -using CommunityToolkit.Mvvm.ComponentModel; - -namespace DevHome.DevDiagnostics.Helpers; - -public enum ExternalToolArgType -{ - None, - ProcessId, - Hwnd, -} - -public partial class ExternalTool_v1 : ObservableObject -{ - public string ID { get; private set; } - - public string Name { get; private set; } - - public string Executable { get; private set; } - - [JsonConverter(typeof(EnumStringConverter))] - public ExternalToolArgType ArgType { get; private set; } = ExternalToolArgType.None; - - public string ArgPrefix { get; private set; } - - public string OtherArgs { get; private set; } - - public bool IsPinned { get; private set; } - - public ExternalTool_v1( - string name, - string executable, - ExternalToolArgType argtype, - string argprefix = "", - string otherArgs = "", - bool isPinned = false) - { - Name = name; - Executable = executable; - ArgType = argtype; - ArgPrefix = argprefix; - OtherArgs = otherArgs; - IsPinned = isPinned; - ID = Guid.NewGuid().ToString(); - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/ExternalToolsHelper.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/ExternalToolsHelper.cs deleted file mode 100644 index 53e500e9c..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/ExternalToolsHelper.cs +++ /dev/null @@ -1,300 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Collections.ObjectModel; -using System.Collections.Specialized; -using System.ComponentModel; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Text.Json; -using System.Text.Json.Serialization; -using DevHome.Common.Helpers; -using Serilog; -using Windows.Storage; - -namespace DevHome.DevDiagnostics.Helpers; - -internal sealed class ExternalToolsHelper -{ - private readonly JsonSerializerOptions _serializerOptions = new() { WriteIndented = true }; - private readonly string _toolInfoFileName; - - private static readonly ILogger _log = Log.ForContext("SourceContext", nameof(ExternalToolsHelper)); - - private readonly ObservableCollection _filteredExternalTools = []; - - private ObservableCollection _allExternalTools = []; - - // The ExternalTools menu shows all registered tools. - public ObservableCollection AllExternalTools - { - get => _allExternalTools; - set - { - // We're assigning the collection once, and this also covers the case where we reassign it again: - // we need to unsubscribe from the old collection's events, subscribe to the new collection's events, - // and initialize the filtered collection. - if (_allExternalTools != value) - { - if (_allExternalTools != null) - { - _allExternalTools.CollectionChanged -= AllExternalTools_CollectionChanged; - } - - _allExternalTools = value; - if (_allExternalTools != null) - { - _allExternalTools.CollectionChanged += AllExternalTools_CollectionChanged; - } - - // Synchronize the filtered collection with this unfiltered one. - SynchronizeAllFilteredItems(); - } - } - } - - // The bar shows only the pinned tools. - public ReadOnlyObservableCollection FilteredExternalTools { get; private set; } - - internal static int ToolsCollectionVersion { get; private set; } = 2; - - public ExternalToolsHelper() - { - string localFolder; - if (RuntimeHelper.IsMSIX) - { - localFolder = ApplicationData.Current.LocalFolder.Path; - } - else - { - localFolder = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location) ?? string.Empty; - } - - // The file should be in this location: - // %LocalAppData%\Packages\Microsoft.Windows.DevHome_8wekyb3d8bbwe\LocalState\externaltools.json - _toolInfoFileName = Path.Combine(localFolder, "externaltools.json"); - AllExternalTools = new(_allExternalTools); - FilteredExternalTools = new(_filteredExternalTools); - - Init(); - } - - private void Init() - { - _allExternalTools.Clear(); - if (File.Exists(_toolInfoFileName)) - { - var jsonData = File.ReadAllText(_toolInfoFileName); - try - { - var toolCollection = JsonSerializer.Deserialize(jsonData); - var existingData = toolCollection?.ExternalTools ?? []; - foreach (var toolItem in existingData) - { - _allExternalTools.Add(toolItem); - toolItem.PropertyChanged += ToolItem_PropertyChanged; - } - } - catch (Exception ex) - { - _log.Error(ex, $"Failed to parse {_toolInfoFileName}, attempting migration"); - MigrateOldTools(jsonData); - } - } - } - - private void MigrateOldTools(string jsonData) - { - try - { - var oldFormatData = JsonSerializer.Deserialize(jsonData) ?? []; - foreach (var oldTool in oldFormatData) - { - var arguments = string.Empty; - if (oldTool.ArgType == ExternalToolArgType.ProcessId) - { - arguments = $" {oldTool.ArgPrefix}{{pid}} {oldTool.OtherArgs}"; - } - else if (oldTool.ArgType == ExternalToolArgType.Hwnd) - { - arguments = $" {oldTool.ArgPrefix}{{hwnd}} {oldTool.OtherArgs}"; - } - else - { - arguments = oldTool.OtherArgs; - } - - var newTool = new ExternalTool( - oldTool.Name, - oldTool.Executable, - ToolActivationType.Launch, - arguments, - string.Empty, - string.Empty, - string.Empty, - ToolType.Unknown, - oldTool.IsPinned); - - _allExternalTools.Add(newTool); - newTool.PropertyChanged += ToolItem_PropertyChanged; - } - - // Write out the updated data with the new file format. - WriteToolsJsonFile(); - } - catch (Exception ex) - { - _log.Error(ex, "Failed to migrate old tools"); - } - } - - private void ToolItem_PropertyChanged(object? sender, PropertyChangedEventArgs e) - { - // The user can change the IsPinned property of a tool, to pin or unpin it on the bar. - if (sender is ExternalTool tool && string.Equals(e.PropertyName, nameof(ExternalTool.IsPinned), StringComparison.Ordinal)) - { - if (tool.IsPinned) - { - if (!_filteredExternalTools.Contains(tool)) - { - _filteredExternalTools.Add(tool); - } - } - else - { - _filteredExternalTools.Remove(tool); - } - } - - // Only update the JSON file if the property is not attributed [JsonIgnore]. - if (!IsJsonIgnoreProperty(e.PropertyName)) - { - WriteToolsJsonFile(); - } - } - - private bool IsJsonIgnoreProperty(string? propertyName) - { - if (string.IsNullOrEmpty(propertyName)) - { - return false; - } - - var property = typeof(T).GetProperty(propertyName); - if (property is not null) - { - var jsonIgnoreAttribute = property.GetCustomAttributes(typeof(JsonIgnoreAttribute), false).FirstOrDefault(); - return jsonIgnoreAttribute is not null; - } - - return false; - } - - public ExternalTool AddExternalTool(ExternalTool tool) - { - _allExternalTools.Add(tool); - WriteToolsJsonFile(); - return tool; - } - - public void RemoveExternalTool(ExternalTool tool) - { - if (_allExternalTools.Remove(tool)) - { - WriteToolsJsonFile(); - } - } - - private void WriteToolsJsonFile() - { - var toolCollection = new ExternalToolCollection(ToolsCollectionVersion, _allExternalTools); - var updatedJson = JsonSerializer.Serialize(toolCollection, _serializerOptions); - - try - { - File.WriteAllText(_toolInfoFileName, updatedJson); - } - catch (Exception ex) - { - _log.Error(ex, "WriteToolsJsonFile unable to write to file"); - } - } - - private void AllExternalTools_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) - { - // Whenever the "all tools" collection changes, we need to synchronize the filtered collection. - switch (e.Action) - { - case NotifyCollectionChangedAction.Add: - if (e.NewItems is not null) - { - foreach (ExternalTool newItem in e.NewItems) - { - if (newItem.IsPinned) - { - _filteredExternalTools.Add(newItem); - } - - newItem.PropertyChanged += ToolItem_PropertyChanged; - } - } - - break; - - case NotifyCollectionChangedAction.Remove: - if (e.OldItems is not null) - { - foreach (ExternalTool oldItem in e.OldItems) - { - oldItem.PropertyChanged -= ToolItem_PropertyChanged; - _filteredExternalTools.Remove(oldItem); - } - } - - break; - - case NotifyCollectionChangedAction.Replace: - if (e.OldItems is not null) - { - foreach (ExternalTool oldItem in e.OldItems) - { - oldItem.PropertyChanged -= ToolItem_PropertyChanged; - _filteredExternalTools.Remove(oldItem); - } - } - - if (e.NewItems is not null) - { - foreach (ExternalTool newItem in e.NewItems) - { - if (newItem.IsPinned) - { - _filteredExternalTools.Add(newItem); - } - - newItem.PropertyChanged += ToolItem_PropertyChanged; - } - } - - break; - - case NotifyCollectionChangedAction.Reset: - SynchronizeAllFilteredItems(); - break; - } - } - - private void SynchronizeAllFilteredItems() - { - _filteredExternalTools.Clear(); - foreach (var item in AllExternalTools) - { - if (item.IsPinned) - { - _filteredExternalTools.Add(item); - } - } - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/HotKeyHelper.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/HotKeyHelper.cs deleted file mode 100644 index 416ea0396..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/HotKeyHelper.cs +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using Microsoft.UI.Xaml; -using Windows.System; -using Windows.Win32; -using Windows.Win32.Foundation; -using Windows.Win32.UI.Input.KeyboardAndMouse; -using WinUIEx.Messaging; - -namespace DevHome.DevDiagnostics.Helpers; - -// Note: instead of making this class disposable, we're disposing the WindowMessageMonitor in -// UnregisterHotKey, and MainWindow calls this in its Closing event handler. -#pragma warning disable CA1001 // Types that own disposable fields should be disposable -public class HotKeyHelper// : IDisposable -#pragma warning restore CA1001 // Types that own disposable fields should be disposable -{ - internal ushort HotkeyID { get; private set; } - - private const string NoWindowHandleException = "Cannot get window handle: are you doing this too early?"; - private readonly HWND _windowHandle; - private readonly Action _onHotKeyPressed; - private readonly WindowMessageMonitor _windowMessageMonitor; - - public HotKeyHelper(Window handlerWindow, Action hotKeyHandler) - { - _onHotKeyPressed = hotKeyHandler; - - // Create a unique Id for this class in this instance. - var atomName = $"{Environment.CurrentManagedThreadId:X8}{GetType().FullName}"; - HotkeyID = PInvoke.GlobalAddAtom(atomName); - - // Set up the window message hook to listen for hot keys. - _windowHandle = (HWND)WinRT.Interop.WindowNative.GetWindowHandle(handlerWindow); - if (_windowHandle.IsNull) - { - throw new InvalidOperationException(NoWindowHandleException); - } - - _windowMessageMonitor = new WindowMessageMonitor(_windowHandle); - _windowMessageMonitor.WindowMessageReceived += OnWindowMessageReceived; - } - - private void OnWindowMessageReceived(object? sender, WindowMessageEventArgs e) - { - if (e.Message.MessageId == PInvoke.WM_HOTKEY) - { - var keyId = (int)e.Message.WParam; - if (keyId == HotkeyID) - { - _onHotKeyPressed?.Invoke((int)e.Message.LParam); - e.Handled = true; - } - } - } - - internal void RegisterHotKey(VirtualKey key, HOT_KEY_MODIFIERS modifiers) - { - PInvoke.RegisterHotKey(_windowHandle, HotkeyID, modifiers, (uint)key); - } - - internal void UnregisterHotKey() - { - if (HotkeyID != 0) - { - _ = PInvoke.UnregisterHotKey(_windowHandle, HotkeyID); - PInvoke.GlobalDeleteAtom(HotkeyID); - _windowMessageMonitor.Dispose(); - HotkeyID = 0; - } - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/IApplicationActivationManager.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/IApplicationActivationManager.cs deleted file mode 100644 index d971435d1..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/IApplicationActivationManager.cs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Runtime.InteropServices; - -namespace DevHome.DevDiagnostics.Helpers; - -[ComImport] -[Guid("2E941141-7F97-4756-BA1D-9DECDE894A3D")] -[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] -public interface IApplicationActivationManager -{ - int ActivateApplication( - [In] string appUserModelId, - [In] string arguments, - [In] ACTIVATEOPTIONS options, - [Out] out uint processId); -} - -public enum ACTIVATEOPTIONS -{ - None = 0x00000000, - DesignMode = 0x00000001, - NoErrorUI = 0x00000002, - NoSplashScreen = 0x00000004, -} - -public static class CLSID -{ - public static readonly Guid ApplicationActivationManager = new("45BA127D-10A8-46EA-8AB7-56EA9078943C"); -} - -public static class HResult -{ - public static bool Succeeded(int hr) => hr >= 0; - - public static bool Failed(int hr) => hr < 0; -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/ImageOptionsInternalTool.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/ImageOptionsInternalTool.cs deleted file mode 100644 index bb6de355a..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/ImageOptionsInternalTool.cs +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.ComponentModel; -using System.Diagnostics; -using System.IO; -using DevHome.DevDiagnostics.Models; -using DevHome.DevDiagnostics.Properties; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Media; -using Serilog; -using Windows.ApplicationModel; - -namespace DevHome.DevDiagnostics.Helpers; - -public class ImageOptionsInternalTool : Tool -{ - private const string ButtonText = "\ue9d5"; // Checklist icon - private static readonly string _toolName = CommonHelper.GetLocalizedString("ImageOptionsName"); - private static readonly ILogger _log = Log.ForContext("SourceContext", nameof(ExternalTool)); - - public ImageOptionsInternalTool() - : base(_toolName, ToolType.Unknown, Settings.Default.IsImageOptionsToolPinned, false) - { - TargetAppData.Instance.PropertyChanged += TargetApp_PropertyChanged; - } - - private void TargetApp_PropertyChanged(object? sender, PropertyChangedEventArgs e) - { - if (e.PropertyName != nameof(TargetAppData.Instance.TargetProcess)) - { - return; - } - - var process = TargetAppData.Instance.TargetProcess; - try - { - if (process is not null && process.MainModule is not null) - { - IsEnabled = true; - } - else - { - IsEnabled = false; - } - } - catch (Win32Exception ex) - { - if (ex.NativeErrorCode == (int)Windows.Win32.Foundation.WIN32_ERROR.ERROR_ACCESS_DENIED) - { - IsEnabled = false; - } - } - } - - public override IconElement GetIcon() - { - return new FontIcon - { - Glyph = ButtonText, - FontFamily = (FontFamily)Application.Current.Resources["SymbolThemeFontFamily"], - }; - } - - internal override void InvokeTool(ToolLaunchOptions options) - { - if (TargetAppData.Instance.TargetProcess == null || TargetAppData.Instance.TargetProcess.MainModule == null) - { - return; - } - - try - { - var fileInfo = new FileInfo(Environment.ProcessPath ?? string.Empty); - Directory.SetCurrentDirectory(fileInfo.DirectoryName ?? string.Empty); - - var aliasRoot = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), $"Microsoft\\WindowsApps\\{Package.Current.Id.FamilyName}"); - - var startInfo = new ProcessStartInfo() - { - FileName = Path.Combine(aliasRoot, "DevHome.IfeoTool.exe"), - Arguments = TargetAppData.Instance.TargetProcess.MainModule.ModuleName, - UseShellExecute = true, - WorkingDirectory = fileInfo.DirectoryName, - Verb = "runas", - }; - - var process = Process.Start(startInfo); - } - catch (Exception ex) - { - _log.Error(ex.Message); - } - } - - protected override void OnIsPinnedChange(bool newValue) - { - Settings.Default.IsImageOptionsToolPinned = newValue; - Settings.Default.Save(); - } - - public override void UnregisterTool() - { - // Ignore this command for now until we have a way for the user to discover unregistered internal tools - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/InsightsHelper.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/InsightsHelper.cs deleted file mode 100644 index 4a998f6e9..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/InsightsHelper.cs +++ /dev/null @@ -1,214 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Text.RegularExpressions; -using System.Threading.Tasks; -using DevHome.DevDiagnostics.Models; -using Microsoft.UI.Dispatching; -using Serilog; - -namespace DevHome.DevDiagnostics.Helpers; - -internal sealed partial class InsightsHelper -{ - private static readonly ILogger _log = Log.ForContext("SourceContext", nameof(InsightsHelper)); - - // TODO: Add more patterns for different insights. - // TODO: Insights patterns should be in a database of some kind. - // TODO: Pattern texts should be extracted from localized windows builds. - [GeneratedRegex( - @"The process cannot access the file '(.+?)' because it is being used by another process", - RegexOptions.IgnoreCase, "en-US")] - private static partial Regex LockedFileErrorRegex(); - - // TODO The following are examples of a simple pattern where we map error code to some help text. - // This is temporary: longer-term, we should update the errors.db - // to map the error code to a description, plus any existing documented solution options. - [GeneratedRegex(@"0xc0000409", RegexOptions.IgnoreCase, "en-US")] - private static partial Regex BufferOverflowErrorRegex(); - - [GeneratedRegex(@"0xc0000005", RegexOptions.IgnoreCase, "en-US")] - private static partial Regex MemoryErrorRegex(); - - private static readonly List _regexList = []; - - static InsightsHelper() - { - _regexList.Add(new InsightRegex(InsightType.LockedFile, LockedFileErrorRegex())); - _regexList.Add(new InsightRegex(InsightType.Security, BufferOverflowErrorRegex())); - _regexList.Add(new InsightRegex(InsightType.MemoryViolation, MemoryErrorRegex())); - } - - internal static async Task FindPattern(string errorText, DispatcherQueue dispatcher) - { - SimpleTextInsight? newInsight = null; - - foreach (var insightRegex in _regexList) - { - var match = insightRegex.Regex.Match(errorText); - if (match.Success) - { - var tcs = new TaskCompletionSource(); - dispatcher.TryEnqueue(() => - { - try - { - newInsight = new SimpleTextInsight - { - InsightType = insightRegex.InsightType, - }; - tcs.SetResult(true); - } - catch (Exception ex) - { - tcs.SetException(ex); - } - }); - - await tcs.Task; - - if (newInsight is null) - { - return null; - } - - // Once we flesh out our error database, we should have a more structured way to - // handle different types of insights, rather than a switch statement. - switch (insightRegex.InsightType) - { - case InsightType.LockedFile: - { - // Extract the file path from the matched group. - var pattern = string.Empty; - if (match.Groups != null && match.Groups.Count > 1) - { - pattern = match.Groups[1].Value; - } - - newInsight.Title = CommonHelper.GetLocalizedString("LockedFileInsightTitle"); - var processName = GetLockingProcess(pattern); - if (!string.IsNullOrEmpty(processName)) - { - newInsight.Description = - CommonHelper.GetLocalizedString("LockedFileInsightSpecificDescription", pattern, processName); - } - else - { - newInsight.Description = - CommonHelper.GetLocalizedString("LockedFileInsightUnknownDescription", pattern); - } - } - - break; - - case InsightType.Security: - { - var hexValue = match.Value; - var intConverter = new Int32Converter(); - var errorAsInt = (int?)intConverter.ConvertFromString(hexValue); - if (errorAsInt is not null) - { - var errors = ErrorLookupHelper.LookupError((int)errorAsInt); - if (errors is not null && errors.Length > 0) - { - var error = errors[0]; - { - newInsight.Description = - CommonHelper.GetLocalizedString("GenericInsightDescription", error.Name, error.Help); - } - } - } - - newInsight.Title = CommonHelper.GetLocalizedString("SecurityInsightTitle"); - } - - break; - - case InsightType.MemoryViolation: - { - var hexValue = match.Value; - var intConverter = new Int32Converter(); - var errorAsInt = (int?)intConverter.ConvertFromString(hexValue); - if (errorAsInt is not null) - { - var errors = ErrorLookupHelper.LookupError((int)errorAsInt); - if (errors is not null && errors.Length > 0) - { - var error = errors[0]; - { - if (IsPythonCtypesError(errorText, out var description)) - { - newInsight.Description = description; - } - else - { - newInsight.Description = - CommonHelper.GetLocalizedString("GenericInsightDescription", error.Name, error.Help); - } - } - } - } - - newInsight.Title = CommonHelper.GetLocalizedString("MemoryInsightTitle"); - } - - break; - - default: - break; - } - - break; - } - } - - return newInsight; - } - - // This is an example of an error that requires additional runtime processing to - // determine the locking process, so it cannot be handled in the error database alone. - private static string GetLockingProcess(string lockedFilePath) - { - var lockingProcess = string.Empty; - - try - { - // Determines if the specified file is locked by another process. - _ = RestartManagerHelper.GetLockingProcesses(lockedFilePath, out var processes); - if (processes != null && processes.Count > 0) - { - var process = processes[0]; - lockingProcess = process.ProcessName; - } - } - catch (Exception ex) - { - _log.Debug(ex, "Unable to determine if process is locked."); - } - - return lockingProcess; - } - - // We're special-casing Python ctypes errors here, just to exercise this type of issue - // pattern, but longer-term this should be handled by some data relationship in the errors.db. - private static bool IsPythonCtypesError(string errorText, out string description) - { - var result = false; - description = string.Empty; - var appPathPattern = @"Faulting application path: .*\\python\.exe"; - var modulePathPattern = @"Faulting module path: .*\\_ctypes\.pyd"; - var hasAppPath = Regex.IsMatch(errorText, appPathPattern); - var hasModulePath = Regex.IsMatch(errorText, modulePathPattern); - - if (hasAppPath && hasModulePath) - { - description = CommonHelper.GetLocalizedString("PythonCtypesDescription"); - result = true; - } - - return result; - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/InternalToolsHelper.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/InternalToolsHelper.cs deleted file mode 100644 index 219beaead..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/InternalToolsHelper.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System.Collections.Generic; -using System.Collections.ObjectModel; - -namespace DevHome.DevDiagnostics.Helpers; - -internal sealed class InternalToolsHelper -{ - private readonly List _allInternalTools; - - public ReadOnlyCollection AllInternalTools => _allInternalTools.AsReadOnly(); - - public InternalToolsHelper() - { - // All internal tools should be in this list - _allInternalTools = new List - { - new ClipboardMonitorInternalTool(), - new ImageOptionsInternalTool(), - }; - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/LoaderSnapAssistantTool.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/LoaderSnapAssistantTool.cs deleted file mode 100644 index 2420a192e..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/LoaderSnapAssistantTool.cs +++ /dev/null @@ -1,260 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Threading; -using CommunityToolkit.Mvvm.Input; -using DevHome.Common.Extensions; -using DevHome.DevDiagnostics.Controls; -using DevHome.DevDiagnostics.Models; -using DevHome.DevDiagnostics.Services; -using DevHome.DevDiagnostics.TelemetryEvents; -using DevHome.Service; -using DevHome.Telemetry; -using Microsoft.Diagnostics.Tracing; -using Microsoft.Diagnostics.Tracing.Session; -using Microsoft.UI.Xaml; -using Microsoft.Win32; -using Serilog; - -namespace DevHome.DevDiagnostics.Helpers; - -public class LoaderSnapAssistantTool -{ - private const string LoaderSnapsIdentifyNoLogsTelemetryName = "LoaderSnapsIdentifyNoLogs"; - private const string LoaderSnapsIdentifyLogsTelemetryName = "LoaderSnapsIdentifyLogs"; - - private const string WindowsImageETWProvider = "2cb15d1d-5fc1-11d2-abe1-00a0c911f518"; /*EP_Microsoft-Windows-ImageLoad*/ - private const uint LoaderSnapsFlag = 0x80; /* ETW_UMGL_LDR_SNAPS_FLAG */ - private const string LoaderSnapsETWOpCode = "Opcode(215)"; - private const string LoaderSnapsETWErrorLine = "LdrpProcessWork - ERROR: Unable to load"; - - private readonly DDInsightsService _insightsService; - private readonly IDevHomeService _devHomeService; - private readonly Microsoft.UI.Dispatching.DispatcherQueue _dispatcher; - - private struct LoaderSnapFailure - { - public int Pid { get; set; } - - public string? ErrorLog { get; set; } - - public string? ImageName { get; set; } - } - - private readonly Dictionary _loaderSnapFailures = new(); - - [Flags] - private enum TraceFlags - { - HeapTracing = 1, - CritSecTracing = 2, - LoaderSnaps = 4, - } - - public LoaderSnapAssistantTool() - { - _dispatcher = Microsoft.UI.Dispatching.DispatcherQueue.GetForCurrentThread(); - Debug.Assert(_dispatcher is not null, "Be sure to create this object on the UI thread"); - _insightsService = Application.Current.GetService(); - _devHomeService = Application.Current.GetService(); - Init(); - } - - private void Init() - { - var crashDumpAnalyzerThread = new Thread(LoaderSnapETWListener); - crashDumpAnalyzerThread.Name = "LoaderSnapAssistantThread"; - crashDumpAnalyzerThread.Start(); - - _devHomeService.MissingFileProcessLaunchFailure += info => - { - if (!IsLoaderSnapLoggingEnabledForImage(info.processName)) - { - App.Log(LoaderSnapsIdentifyNoLogsTelemetryName, LogLevel.Measure); - - _dispatcher.TryEnqueue(() => - { - var insight = new InsightPossibleLoaderIssue(); - insight.Title = CommonHelper.GetLocalizedString("InsightProcessExitMissingDependenciesTitle"); - insight.Text = string.Format(CultureInfo.CurrentCulture, CommonHelper.GetLocalizedString("InsightProcessExitMissingDependencies"), info.processName, info.pid, info.exitCode); - insight.ImageFileName = info.processName; - _insightsService.AddInsight(insight); - }); - } - else - { - lock (_loaderSnapFailures) - { - if (_loaderSnapFailures.TryGetValue(info.pid, out LoaderSnapFailure loadersnapError)) - { - // We had previously received information about this app's loader snap issue but were waiting for the image name. - // We can raise the notification now - _loaderSnapFailures.Remove(info.pid); - loadersnapError.ImageName = info.processName; - RaiseLoaderSnapInsight(loadersnapError); - } - else - { - // We haven't received the loader snap failure yet. Store the process name, and we'll raise the insight - // when we receive the loader snap logs - LoaderSnapFailure failure = default(LoaderSnapFailure); - failure.Pid = info.pid; - failure.ImageName = info.processName; - _loaderSnapFailures.Add(info.pid, failure); - } - } - } - }; - } - - private void LoaderSnapETWListener() - { - using TraceEventSession session = new TraceEventSession("LoaderSnapAssistantSession"); - session.StopOnDispose = true; - - // Enable the loader snaps provider - session.EnableProvider(WindowsImageETWProvider, TraceEventLevel.Error, LoaderSnapsFlag); - - // We don't care about a lot of the ETW data that is coming in, so we just hook up the All event and ignore it - session.Source.Dynamic.All += data => { }; - - // None of the loadersnap events are handled by the TraceEventParser, so we need to handle them ourselves - session.Source.UnhandledEvents += UnHandledEventsHandler; - session.Source.Process(); - } - - private void UnHandledEventsHandler(TraceEvent traceEvent) - { - if (traceEvent.EventName.Contains(LoaderSnapsETWOpCode)) - { - byte[] loaderSnapData = traceEvent.EventData(); - string s = System.Text.Encoding.Unicode.GetString(loaderSnapData.Skip(10).ToArray()); - - // The loader snap data has embedded nulls in its string. Get rid of the embedded nulls that signify newlines, and - // for the remaining ones, swap them out for colons - s = s.Replace("\n\0", string.Empty); - s = s.Replace("\0", ": "); - if (s.Contains(LoaderSnapsETWErrorLine)) - { - lock (_loaderSnapFailures) - { - if (_loaderSnapFailures.TryGetValue(traceEvent.ProcessID, out LoaderSnapFailure loadersnapError)) - { - // We had previously received information about this app's loader snap issue but were waiting for the image name. - // We can raise the notification now - _loaderSnapFailures.Remove(traceEvent.ProcessID); - loadersnapError.ErrorLog = s; - RaiseLoaderSnapInsight(loadersnapError); - } - else - { - // At this point, we don't have the faulting process's executable name. Wait until we get the callback - // from our service that tells of the process termination, and then we'll raise the insight. - LoaderSnapFailure failure = default(LoaderSnapFailure); - failure.Pid = traceEvent.ProcessID; - failure.ErrorLog = s; - _loaderSnapFailures.Add(traceEvent.ProcessID, failure); - } - } - } - } - } - - private void RaiseLoaderSnapInsight(LoaderSnapFailure failure) - { - App.Log(LoaderSnapsIdentifyLogsTelemetryName, LogLevel.Measure); - - _dispatcher.TryEnqueue(() => - { - var insight = new SimpleTextInsight(); - insight.Title = string.Format(CultureInfo.CurrentCulture, CommonHelper.GetLocalizedString("InsightProcessExitMissingDependenciesIdentifiedTitle"), failure.ImageName, failure.Pid); - Debug.Assert(!string.IsNullOrEmpty(failure.ErrorLog), "We should have an error log"); - insight.Description = failure.ErrorLog; - _insightsService.AddInsight(insight); - }); - } - - private bool IsLoaderSnapLoggingEnabledForImage(string imageFileName) - { - // Check if the following registry key exists - // Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\imageFileName - // TracingFlags = 0x4 - RegistryKey? key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\" + imageFileName, false); - - if (key is null) - { - return false; - } - - if (key.GetValue("TracingFlags") is not int tracingFlags) - { - return false; - } - - if (!((TraceFlags)tracingFlags).HasFlag(TraceFlags.LoaderSnaps)) - { - return false; - } - - return true; - } -} - -public class InsightPossibleLoaderIssue : Insight -{ - private const string LoaderSnapsEnableLogsTelemetryName = "LoaderSnapsEnableLogs"; - - private static readonly ILogger _log = Log.ForContext("SourceContext", nameof(ExternalTool)); - private readonly InsightForMissingFileProcessTerminationControl _mycontrol = new(); - private string _text = string.Empty; - - internal string Text - { - get => _text; - - set - { - _text = value; - _mycontrol.Text = value; - } - } - - internal string ImageFileName { get; set; } = string.Empty; - - internal InsightPossibleLoaderIssue() - { - _mycontrol.Command = new RelayCommand(ConfigureLoaderSnaps); - CustomControl = _mycontrol; - } - - public void ConfigureLoaderSnaps() - { - App.Log(LoaderSnapsEnableLogsTelemetryName, LogLevel.Measure); - - try - { - FileInfo fileInfo = new FileInfo(Environment.ProcessPath ?? string.Empty); - - var startInfo = new ProcessStartInfo() - { - FileName = "EnableLoaderSnaps.exe", - Arguments = ImageFileName, - UseShellExecute = true, - WorkingDirectory = fileInfo.DirectoryName, - Verb = "runas", - }; - - var process = Process.Start(startInfo); - } - catch (Exception ex) - { - _log.Error(ex.Message); - } - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/RestartManagerHelper.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/RestartManagerHelper.cs deleted file mode 100644 index ee0848d78..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/RestartManagerHelper.cs +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using Windows.Win32; -using Windows.Win32.Foundation; -using Windows.Win32.System.RestartManager; - -namespace DevHome.DevDiagnostics.Helpers; - -internal static class RestartManagerHelper -{ - // Find out what process(es) have a lock on the specified file. - internal static WIN32_ERROR GetLockingProcesses(string filePath, out List processes) - { - var key = Guid.NewGuid().ToString(); - processes = []; - - // Start a Restart Manager session. - var result = WIN32_ERROR.ERROR_SUCCESS; - uint handle; - unsafe - { - fixed (char* p = key) - { - PInvoke.RmStartSession(out handle, p); - } - } - - if (result != 0) - { - return result; - } - - try - { - uint pnProcInfo = 0; - var lpdwRebootReasons = (uint)RM_REBOOT_REASON.RmRebootReasonNone; - - unsafe - { - fixed (char* p = filePath) - { - var filePathStr = new PCWSTR(p); - var resources = new ReadOnlySpan(&filePathStr, 1); - var uniqueProcesses = default(Span); - var serviceNames = default(ReadOnlySpan); - - // Specify the given file as a resource to be managed by the Restart Manager. - result = PInvoke.RmRegisterResources(handle, resources, uniqueProcesses, serviceNames); - if (result != 0) - { - return result; - } - } - } - - // Note: there's a race here - the first call to RmGetList returns the count of processes, - // but when we call RmGetList again to get them this number might have changed. - unsafe - { - result = PInvoke.RmGetList(handle, out var pnProcInfoNeeded, ref pnProcInfo, null, out lpdwRebootReasons); - if (result == WIN32_ERROR.ERROR_MORE_DATA) - { - var processInfo = new RM_PROCESS_INFO[pnProcInfoNeeded]; - - fixed (RM_PROCESS_INFO* processArrayPtr = processInfo) - { - pnProcInfo = pnProcInfoNeeded; - - // Get the list of running processes that are using the given resource (file). - result = PInvoke.RmGetList(handle, out pnProcInfoNeeded, ref pnProcInfo, processArrayPtr, out lpdwRebootReasons); - if (result == 0) - { - // Enumerate all of the returned PIDS, get a Process for each one, and add it to the list. - processes = new List((int)pnProcInfo); - for (var i = 0; i < pnProcInfo; i++) - { - try - { - processes.Add(Process.GetProcessById((int)processInfo[i].Process.dwProcessId)); - } - catch (ArgumentException) - { - // The process might have died before we got to look at it. - } - } - } - else - { - return result; - } - } - } - else if (result != 0) - { - return result; - } - } - } - finally - { - _ = PInvoke.RmEndSession(handle); - } - - return 0; - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/ServicingHelper.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/ServicingHelper.cs deleted file mode 100644 index 8631521bf..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/ServicingHelper.cs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using Microsoft.UI.Xaml; -using Windows.Win32; -using Windows.Win32.Foundation; -using WinUIEx.Messaging; - -namespace DevHome.DevDiagnostics.Helpers; - -// Note: instead of making this class disposable, we're disposing the WindowMessageMonitor in -// UnregisterHotKey, and MainWindow calls this in its Closing event handler. -#pragma warning disable CA1001 // Types that own disposable fields should be disposable -public class ServicingHelper -#pragma warning restore CA1001 // Types that own disposable fields should be disposable -{ - private const string NoWindowHandleException = "Cannot get window handle: are you doing this too early?"; - private readonly HWND _windowHandle; - private readonly WindowMessageMonitor _windowMessageMonitor; - private readonly Action _onSessionEnd; - - public ServicingHelper(Window handlerWindow, Action handleSessionEnd) - { - _onSessionEnd = handleSessionEnd; - - // Set up the window message hook to listen for session end messages. - _windowHandle = (HWND)WinRT.Interop.WindowNative.GetWindowHandle(handlerWindow); - if (_windowHandle.IsNull) - { - throw new InvalidOperationException(NoWindowHandleException); - } - - _windowMessageMonitor = new WindowMessageMonitor(_windowHandle); - _windowMessageMonitor.WindowMessageReceived += OnWindowMessageReceived; - } - - private void OnWindowMessageReceived(object? sender, WindowMessageEventArgs e) - { - if (e.Message.MessageId == PInvoke.WM_ENDSESSION) - { - _onSessionEnd?.Invoke(); - e.Handled = true; - } - } - - internal void Unregister() - { - _windowMessageMonitor?.Dispose(); - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/StandInDevHomeService.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/StandInDevHomeService.cs deleted file mode 100644 index 181ac4a78..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/StandInDevHomeService.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -// This is the stand-in service that is used when DevHome's NT service is not available. It's basically a dummy object that can -// be used so the rest of DevHome can still function without the service. -using DevHome.Service; - -namespace DevHome.DevDiagnostics.Helpers; - -internal sealed class StandInDevHomeService : IDevHomeService -{ - // Let folks subscribe to this event, but it will never be raised. - public event MissingFileProcessLaunchFailureHandler? MissingFileProcessLaunchFailure - { - add { } - remove { } - } - - public StandInDevHomeService() - { - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/Tool.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/Tool.cs deleted file mode 100644 index 631666e4b..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/Tool.cs +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Diagnostics; -using System.Text.Json.Serialization; -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.Input; -using DevHome.Common.Extensions; -using DevHome.DevDiagnostics.Models; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Media; -using Windows.Win32.Foundation; - -namespace DevHome.DevDiagnostics.Helpers; - -public abstract partial class Tool : ObservableObject -{ - [ObservableProperty] - private bool _isPinned; - - [ObservableProperty] - [property: JsonIgnore] - private string _pinGlyph; - - [ObservableProperty] - [property: JsonIgnore] - private ImageSource? _toolIconSource; - - [ObservableProperty] - [property: JsonIgnore] - private bool _isEnabled; - - public string Name { get; private set; } - - [JsonConverter(typeof(EnumStringConverter))] - public ToolType Type { get; private set; } - - public Tool(string name, ToolType type, bool isPinned, bool isEnabled = true) - { - Name = name; - Type = type; - IsPinned = isPinned; - PinGlyph = IsPinned ? CommonHelper.UnpinGlyph : CommonHelper.PinGlyph; - IsEnabled = isEnabled; - } - - public abstract IconElement GetIcon(); - - partial void OnIsPinnedChanged(bool oldValue, bool newValue) - { - PinGlyph = newValue ? CommonHelper.UnpinGlyph : CommonHelper.PinGlyph; - OnIsPinnedChange(newValue); - } - - protected virtual void OnIsPinnedChange(bool newValue) - { - } - - [property: JsonIgnore] - [RelayCommand] - public void TogglePinnedState() - { - IsPinned = !IsPinned; - } - - public void Invoke(ToolLaunchOptions options) - { - InvokeTool(options); - } - - [property: JsonIgnore] - [RelayCommand] - public void Invoke() - { - ToolLaunchOptions options = new(); - options.TargetProcessId = TargetAppData.Instance.TargetProcess?.Id; - options.TargetHWnd = TargetAppData.Instance.HWnd; - - var barWindow = Application.Current.GetService().DBarWindow; - options.ParentWindow = barWindow; - - InvokeTool(options); - } - - internal virtual void InvokeTool(ToolLaunchOptions options) => throw new NotImplementedException(); - - [property: JsonIgnore] - [RelayCommand] - public abstract void UnregisterTool(); -} - -[Flags] -public enum ToolType -{ - Unknown = 0, - DumpAnalyzer = 1, -} - -public class ToolLaunchOptions -{ - public Window? ParentWindow { get; set; } - - public bool RedirectStandardOut { get; set; } /* = false; */ - - public string? CommandLineParams { get; set; } - - public int? TargetProcessId { get; set; } - - internal HWND TargetHWnd { get; set; } - - public Process? LaunchedProcess { get; set; } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/WERUtils.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/WERUtils.cs deleted file mode 100644 index a489c5ad3..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/WERUtils.cs +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System.Diagnostics; -using Microsoft.Win32; - -namespace DevHome.DevDiagnostics.Helpers; - -internal sealed class WERUtils -{ - internal const string LocalWERRegistryKey = "SOFTWARE\\Microsoft\\Windows\\Windows Error Reporting\\LocalDumps"; - - // Check to see if global local WER collection is enabled - // See https://learn.microsoft.com/windows/win32/wer/collecting-user-mode-dumps - // for more details - internal static bool IsGlobalCollectionEnabled() - { - var key = Registry.LocalMachine.OpenSubKey(LocalWERRegistryKey, false); - - return IsCollectionEnabledForKey(key); - } - - // See if local WER collection is enabled for a specific app - internal static bool IsCollectionEnabledForApp(string appName) - { - var key = Registry.LocalMachine.OpenSubKey(LocalWERRegistryKey, false); - - // If the local dump key doesn't exist, then app collection is disabled - if (key is null) - { - return false; - } - - var appKey = key.OpenSubKey(appName, false); - - // If the app key doesn't exist, per-app collection isn't enabled. Check the global setting - if (appKey is null) - { - return IsGlobalCollectionEnabled(); - } - - return IsCollectionEnabledForKey(appKey); - } - - internal static bool IsCollectionEnabledForKey(RegistryKey? key) - { - // If the key doesn't exist, then collection is disabled - if (key is null) - { - return false; - } - - // If the key exists, but dumpcount is set to 0, it's also disabled - if (key.GetValue("DumpCount") is int dumpCount && dumpCount == 0) - { - return false; - } - - // Collection is enabled enabled, but if we're not getting full memory dumps, so cabs may not be - // useful. In this case, report that collection is disabled. - var dumpType = key.GetValue("DumpType") as int?; - if (dumpType is null || dumpType != 2) - { - return false; - } - - // Otherwise it's enabled - return true; - } - - // This changes the registry keys necessary to allow local WER collection for a specific app - internal static void EnableCollectionForApp(string appname) - { - var globalKey = Registry.LocalMachine.OpenSubKey(LocalWERRegistryKey, true); - - if (globalKey is null) - { - // Need to create the key, and set the global dump collection count to 0 to prevent all apps from generating local dumps - globalKey = Registry.LocalMachine.CreateSubKey(LocalWERRegistryKey); - globalKey.SetValue("DumpCount", 0); - } - - Debug.Assert(globalKey is not null, "Global key is null"); - - var appKey = globalKey.CreateSubKey(appname); - Debug.Assert(appKey is not null, "App key is null"); - - // If dumpcount doesn't exist or is set to 0, set the default value to get cabs - if (appKey.GetValue("DumpCount") is not int dumpCount || dumpCount == 0) - { - appKey.SetValue("DumpCount", 10); - } - - // Make sure the cabs being collected are useful. Go for the full dumps instead of the mini dumps - appKey.SetValue("DumpType", 2); - return; - } - - // This changes the registry keys necessary to disable local WER collection for a specific app - internal static void DisableCollectionForApp(string appname) - { - var globalKey = Registry.LocalMachine.OpenSubKey(LocalWERRegistryKey, true); - - if (globalKey is null) - { - // Local collection isn't enabled - return; - } - - var appKey = globalKey.CreateSubKey(appname); - Debug.Assert(appKey is not null, "App key is null"); - - // Set the DumpCount value to 0 to disable collection - appKey.SetValue("DumpCount", 0); - - return; - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/WinLogsHelper.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/WinLogsHelper.cs deleted file mode 100644 index 8250cd4e9..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/WinLogsHelper.cs +++ /dev/null @@ -1,269 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Collections.ObjectModel; -using System.Collections.Specialized; -using System.Diagnostics; -using System.Diagnostics.Eventing.Reader; -using System.Threading; -using DevHome.Common.Extensions; -using DevHome.DevDiagnostics.Models; -using Microsoft.Diagnostics.Tracing; -using Microsoft.UI.Xaml; - -namespace DevHome.DevDiagnostics.Helpers; - -public class WinLogsHelper : IDisposable -{ - public const string EtwLogsName = "ETW Logs"; - public const string DebugOutputLogsName = "DebugOutput"; - public const string EventViewerName = "EventViewer"; - public const string WERName = "WER"; - - private readonly ETWHelper etwHelper; - private readonly DebugMonitor debugMonitor; - private readonly EventViewerHelper eventViewerHelper; - private readonly ObservableCollection output; - private readonly Process targetProcess; - private readonly WERHelper _werHelper; - - private Thread? etwThread; - private Thread? debugMonitorThread; - private Thread? eventViewerThread; - - public WinLogsHelper(Process targetProcess, ObservableCollection output) - { - this.targetProcess = targetProcess; - this.output = output; - - // Initialize ETW logs - etwHelper = new ETWHelper(targetProcess, output); - - // Initialize DebugMonitor - debugMonitor = new DebugMonitor(targetProcess, output); - - // Initialize EventViewer - eventViewerHelper = new EventViewerHelper(targetProcess, output); - - _werHelper = Application.Current.GetService(); - } - - public void Start(bool isEtwEnabled, bool isDebugOutputEnabled, bool isEventViewerEnabled, bool isWEREnabled) - { - if (isEtwEnabled) - { - StartETWLogsThread(); - } - - if (isDebugOutputEnabled) - { - StartDebugOutputsThread(); - } - - if (isEventViewerEnabled) - { - StartEventViewerThread(); - } - - if (isWEREnabled) - { - ((INotifyCollectionChanged)_werHelper.WERReports).CollectionChanged += WEREvents_CollectionChanged; - } - } - - public void Stop() - { - // Stop ETW logs - StopETWLogsThread(); - - // Stop Debug Outputs - StopDebugOutputsThread(); - - // Stop Event Viewer - StopEventViewerThread(); - - // Stop WER - ((INotifyCollectionChanged)_werHelper.WERReports).CollectionChanged -= WEREvents_CollectionChanged; - } - - public void Dispose() - { - etwHelper.Dispose(); - debugMonitor.Dispose(); - eventViewerHelper.Dispose(); - GC.SuppressFinalize(this); - } - - private void StartETWLogsThread() - { - // Stop and close existing thread if any - StopETWLogsThread(); - - // Start a new thread - etwThread = new Thread(() => - { - etwHelper.Start(); - }); - etwThread.Name = EtwLogsName + " Thread"; - etwThread.Start(); - } - - private void StopETWLogsThread() - { - etwHelper.Stop(); - - if (Thread.CurrentThread != etwThread) - { - etwThread?.Join(); - } - } - - private void StartDebugOutputsThread() - { - // Stop and close existing thread if any - StopDebugOutputsThread(); - - // Start a new thread - debugMonitorThread = new Thread(() => - { - // Start Debug Outputs - debugMonitor.Start(); - }); - debugMonitorThread.Name = DebugOutputLogsName + " Thread"; - debugMonitorThread.Start(); - } - - private void StopDebugOutputsThread() - { - debugMonitor.Stop(); - - if (Thread.CurrentThread != debugMonitorThread) - { - debugMonitorThread?.Join(); - } - } - - private void StartEventViewerThread() - { - // Stop and close existing thread if any - StopEventViewerThread(); - - // Start a new thread - eventViewerThread = new Thread(() => - { - // Start EventViewer logs - eventViewerHelper.Start(); - }); - eventViewerThread.Name = EventViewerName + " Thread"; - eventViewerThread.Start(); - } - - private void StopEventViewerThread() - { - eventViewerHelper.Stop(); - - if (Thread.CurrentThread != eventViewerThread) - { - eventViewerThread?.Join(); - } - } - - private void WEREvents_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) - { - if (e.Action == NotifyCollectionChangedAction.Add && e.NewItems != null) - { - foreach (WERReport report in e.NewItems) - { - var filePath = report.Executable ?? string.Empty; - - // Filter WER events based on the process we're targeting - if (filePath.Contains(targetProcess.ProcessName, StringComparison.OrdinalIgnoreCase)) - { - WinLogsEntry entry = new(report.TimeStamp, WinLogCategory.Error, report.Description, WinLogsHelper.WERName); - output.Add(entry); - } - } - } - } - - public void LogStateChanged(WinLogsTool logType, bool isEnabled) - { - if (isEnabled) - { - switch (logType) - { - case WinLogsTool.ETWLogs: - StartETWLogsThread(); - break; - case WinLogsTool.DebugOutput: - StartDebugOutputsThread(); - break; - case WinLogsTool.EventViewer: - StartEventViewerThread(); - break; - case WinLogsTool.WER: - ((INotifyCollectionChanged)_werHelper.WERReports).CollectionChanged += WEREvents_CollectionChanged; - break; - } - } - else - { - switch (logType) - { - case WinLogsTool.ETWLogs: - StopETWLogsThread(); - break; - case WinLogsTool.DebugOutput: - StopDebugOutputsThread(); - break; - case WinLogsTool.EventViewer: - StopEventViewerThread(); - break; - case WinLogsTool.WER: - ((INotifyCollectionChanged)_werHelper.WERReports).CollectionChanged -= WEREvents_CollectionChanged; - break; - } - } - } - - public static WinLogCategory ConvertTraceEventLevelToWinLogCategory(TraceEventLevel level) - { - var category = WinLogCategory.Information; - - switch (level) - { - case TraceEventLevel.Error: - case TraceEventLevel.Critical: - category = WinLogCategory.Error; - break; - case TraceEventLevel.Warning: - category = WinLogCategory.Warning; - break; - } - - return category; - } - - public static WinLogCategory ConvertStandardEventLevelToWinLogCategory(byte? level) - { - var category = WinLogCategory.Information; - - if (level.HasValue) - { - StandardEventLevel standardEventLevel = (StandardEventLevel)level.Value; - switch (standardEventLevel) - { - case StandardEventLevel.Error: - case StandardEventLevel.Critical: - category = WinLogCategory.Error; - break; - case StandardEventLevel.Warning: - category = WinLogCategory.Warning; - break; - } - } - - return category; - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/WindowHelper.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/WindowHelper.cs deleted file mode 100644 index 204a4a243..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/WindowHelper.cs +++ /dev/null @@ -1,770 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Collections.Specialized; -using System.Diagnostics; -using System.Drawing; -using System.IO; -using System.Runtime.InteropServices; -using System.Runtime.InteropServices.WindowsRuntime; -using System.Threading.Tasks; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Media; -using Microsoft.UI.Xaml.Media.Imaging; -using Microsoft.Win32.SafeHandles; -using Serilog; -using Windows.Devices.Display; -using Windows.Devices.Enumeration; -using Windows.Foundation; -using Windows.Graphics; -using Windows.Graphics.Imaging; -using Windows.Storage.Streams; -using Windows.Win32; -using Windows.Win32.Foundation; -using Windows.Win32.Graphics.Dwm; -using Windows.Win32.Graphics.Gdi; -using Windows.Win32.System.SystemInformation; -using Windows.Win32.System.Threading; -using Windows.Win32.UI.Accessibility; -using Windows.Win32.UI.Shell.Common; -using Windows.Win32.UI.WindowsAndMessaging; - -namespace DevHome.DevDiagnostics.Helpers; - -public class WindowHelper -{ - private static readonly ILogger _log = Log.ForContext("SourceContext", nameof(WindowHelper)); - - private static nint GetClassLongPtr(HWND hWnd, GET_CLASS_LONG_INDEX nIndex) - { - if (IntPtr.Size == 8) - { - return CommonInterop.GetClassLongPtr64(hWnd, nIndex); - } - else - { - return (nint)PInvoke.GetClassLong(hWnd, nIndex); - } - } - - private static nint SetWindowLongPtr(HWND hWnd, WINDOW_LONG_PTR_INDEX nIndex, nint newLong) - { - if (IntPtr.Size == 8) - { - return CommonInterop.SetWindowLongPtr64(hWnd, nIndex, newLong); - } - else - { - return (nint)PInvoke.SetWindowLong(hWnd, nIndex, (int)newLong); - } - } - - private static nint GetWindowLongPtr(HWND hWnd, WINDOW_LONG_PTR_INDEX nIndex) - { - if (IntPtr.Size == 8) - { - return CommonInterop.GetWindowLongPtr64(hWnd, nIndex); - } - else - { - return PInvoke.GetWindowLong(hWnd, nIndex); - } - } - - private static unsafe BOOL EnumProc(HWND hWnd, LPARAM data) - { -#pragma warning disable CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type - var enumData = (EnumWindowsData*)data.Value; -#pragma warning restore CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type - - // The caller should've set this, but we'll make sure here. - enumData->OutHwnd = HWND.Null; - - // Skip this one if the window doesn't include WS_VISIBLE, or if it's minimized. - if (!PInvoke.IsWindowVisible(hWnd)) - { - return true; - } - - if (PInvoke.IsIconic(hWnd)) - { - return true; - } - - // Skip toolwindows. - var extendedStyle = GetWindowLongPtr(hWnd, WINDOW_LONG_PTR_INDEX.GWL_EXSTYLE); - var isToolWindow = (extendedStyle & (long)WINDOW_EX_STYLE.WS_EX_TOOLWINDOW) - == (long)WINDOW_EX_STYLE.WS_EX_TOOLWINDOW; - if (isToolWindow) - { - return true; - } - - // Skip dialogs. - if (PInvoke.GetAncestor(hWnd, GET_ANCESTOR_FLAGS.GA_ROOTOWNER) != hWnd) - { - return true; - } - - PInvoke.GetWindowRect(hWnd, out var windowRect); - var screenBounds = GetMonitorRectForWindow(hWnd); - var isOnAnyScreen = - windowRect.left < screenBounds.right && windowRect.right > screenBounds.left && - windowRect.top < screenBounds.bottom && windowRect.bottom > screenBounds.top && - windowRect.right - windowRect.left > 1 && windowRect.bottom - windowRect.top > 1; - if (!isOnAnyScreen) - { - return true; - } - - unsafe - { - // Exclude system/shell windows. - var className = stackalloc char[256]; - var classNameLength = PInvoke.GetClassName(hWnd, className, 256); - if (classNameLength == 0) - { - return true; - } - - string classNameString = new(className, 0, classNameLength); - if (classNameString == "Progman" || classNameString == "Shell_TrayWnd" || - classNameString == "WorkerW" || classNameString == "SHELLDLL_DefView" || - classNameString == "IME") - { - return true; - } - - // Exclude cloaked windows. - var cloakedVal = 0; - var hRes = PInvoke.DwmGetWindowAttribute( - hWnd, DWMWINDOWATTRIBUTE.DWMWA_CLOAKED, &cloakedVal, sizeof(int)); - if (hRes != 0) - { - cloakedVal = 0; - } - - if (cloakedVal != 0) - { - return true; - } - - // Skip any windows that are on our exclusion list. - var excludedProcesses = enumData->ExcludedProcesses; - if (excludedProcesses != null && !IsAcceptableWindow(hWnd, excludedProcesses)) - { - return true; - } - } - - // Skip popups, unless they're for UWP apps or for dialog-based MFC apps. - var windowStyle = (WINDOW_STYLE)GetWindowLongPtr(hWnd, WINDOW_LONG_PTR_INDEX.GWL_STYLE); - var isPopup = (windowStyle & WINDOW_STYLE.WS_POPUP) == WINDOW_STYLE.WS_POPUP; - - // Dialog-based MFC apps will have WS_POPUP but also WS_OVERLAPPED. - var isOverlapped = (windowStyle & WINDOW_STYLE.WS_OVERLAPPED) == WINDOW_STYLE.WS_OVERLAPPED; - - if (isPopup) - { - var isUwpApp = IsProcessName(hWnd, "applicationframehost"); - if (isUwpApp) - { - // NOTE: We could use SHGetPropertyStoreForWindow + PKEY_AppUserModel_ID - // to get the appid for the app. - // Found a visible UWP window, stop enumerating. - enumData->OutHwnd = hWnd; - return false; - } - else if (isOverlapped) - { - // This is a top-level popup, most likely a dialog-based MFC app. - enumData->OutHwnd = hWnd; - return false; - } - - return true; - } - - // Found a window, stop enumerating. - enumData->OutHwnd = hWnd; - return false; - } - - private static Rectangle GetScreenBounds() - { - Rectangle rectangle = default; - - // Can't use async in EnumProc. - var deviceInfoOp = DeviceInformation.FindAllAsync(DisplayMonitor.GetDeviceSelector()); - deviceInfoOp.AsTask().Wait(); - var displayList = deviceInfoOp.GetResults(); - if (displayList == null || displayList.Count == 0) - { - return rectangle; - } - - var winSize = default(SizeInt32); - var displayOp = DisplayMonitor.FromInterfaceIdAsync(displayList[0].Id); - displayOp.AsTask().Wait(); - var monitorInfo = displayOp.GetResults(); - if (monitorInfo == null) - { - winSize.Width = 800; - winSize.Height = 1200; - } - else - { - winSize.Height = monitorInfo.NativeResolutionInRawPixels.Height; - winSize.Width = monitorInfo.NativeResolutionInRawPixels.Width; - } - - rectangle.Width = winSize.Width; - rectangle.Height = winSize.Height; - - return rectangle; - } - - public static RectInt32 GetRect(Rect bounds, double scale) - { - return new RectInt32( - _X: (int)Math.Round(bounds.X * scale), - _Y: (int)Math.Round(bounds.Y * scale), - _Width: (int)Math.Round(bounds.Width * scale), - _Height: (int)Math.Round(bounds.Height * scale)); - } - - internal static unsafe string GetWindowTitle(HWND hWnd) - { - var length = PInvoke.GetWindowTextLength(hWnd); - var windowText = stackalloc char[length]; - _ = PInvoke.GetWindowText(hWnd, windowText, length); - return new string(windowText); - } - - internal static IntPtr LoadDefaultAppIcon() - { - IntPtr icon = PInvoke.LoadIcon(HINSTANCE.Null, PInvoke.IDI_APPLICATION); - return icon; - } - - internal static Bitmap? GetAppIcon(HWND hWnd) - { - try - { - // Try getting the big icon first. - IntPtr hIcon = default; - hIcon = PInvoke.SendMessage(hWnd, PInvoke.WM_GETICON, PInvoke.ICON_BIG, IntPtr.Zero); - - // If that failed, try getting the small icon (or the system-provided default). - if (hIcon == IntPtr.Zero) - { - hIcon = PInvoke.SendMessage(hWnd, PInvoke.WM_GETICON, PInvoke.ICON_SMALL2, IntPtr.Zero); - if (hIcon == IntPtr.Zero) - { - hIcon = (nint)GetClassLongPtr(hWnd, GET_CLASS_LONG_INDEX.GCL_HICON); - } - } - - if (hIcon != IntPtr.Zero) - { - return new Bitmap(Icon.FromHandle(hIcon).ToBitmap(), 24, 24); - } - else - { - return null; - } - } - catch (Exception) - { - return null; - } - } - - public static async Task GetWinUI3BitmapSourceFromGdiBitmap(Bitmap bmp) - { - var softwareBitmap = GetSoftwareBitmapFromGdiBitmap(bmp); - var source = new SoftwareBitmapSource(); - await source.SetBitmapAsync(softwareBitmap); - return source; - } - - public static SoftwareBitmap? GetSoftwareBitmapFromExecutable(string executable) - { - SoftwareBitmap? softwareBitmap = null; - var toolIcon = Icon.ExtractAssociatedIcon(executable); - - // Fall back to Windows default app icon. - toolIcon ??= Icon.FromHandle(LoadDefaultAppIcon()); - - if (toolIcon is not null) - { - softwareBitmap = GetSoftwareBitmapFromGdiBitmap(toolIcon.ToBitmap()); - } - - return softwareBitmap; - } - - public static SoftwareBitmap GetSoftwareBitmapFromGdiBitmap(Bitmap bmp) - { - // Get pixels as an array of bytes. - var data = bmp.LockBits( - new Rectangle(0, 0, bmp.Width, bmp.Height), - System.Drawing.Imaging.ImageLockMode.ReadOnly, - bmp.PixelFormat); - var bytes = new byte[data.Stride * data.Height]; - Marshal.Copy(data.Scan0, bytes, 0, bytes.Length); - bmp.UnlockBits(data); - - // Get WinRT SoftwareBitmap. - var softwareBitmap = new SoftwareBitmap( - BitmapPixelFormat.Bgra8, - bmp.Width, - bmp.Height, - BitmapAlphaMode.Premultiplied); - softwareBitmap.CopyFromBuffer(bytes.AsBuffer()); - - return softwareBitmap; - } - - public static async Task GetSoftwareBitmapSourceFromSoftwareBitmapAsync(SoftwareBitmap softwareBitmap) - { - var softwareBitmapSource = new SoftwareBitmapSource(); - await softwareBitmapSource.SetBitmapAsync(softwareBitmap); - return softwareBitmapSource; - } - - internal static BitmapImage? GetBitmapImageFromFile(string filePath) - { - BitmapImage? bitmapImage = null; - try - { - // Creating a BitmapImage must be done on the UI thread. - bitmapImage = new BitmapImage(); - var icon = Icon.ExtractAssociatedIcon(filePath); - if (icon is not null) - { - using var bitmap = icon.ToBitmap(); - using var stream = new MemoryStream(); - bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Png); - - stream.Seek(0, SeekOrigin.Begin); - var randomAccessStream = new InMemoryRandomAccessStream(); - var outputStream = randomAccessStream.GetOutputStreamAt(0); - var writer = new DataWriter(outputStream); - writer.WriteBytes(stream.ToArray()); - writer.StoreAsync().GetResults(); - randomAccessStream.Seek(0); - - bitmapImage.SetSource(randomAccessStream); - } - } - catch (Exception ex) - { - _log.Error($"Error creating BitmapImage from filePath: {ex.Message}"); - } - - return bitmapImage; - } - - internal static async Task GetSoftwareBitmapSourceFromImageFilePath(string iconFilePath) - { - SoftwareBitmapSource? softwareBitmapSource = null; - - try - { - var fileStream = File.OpenRead(iconFilePath); - var decoder = await BitmapDecoder.CreateAsync(fileStream.AsRandomAccessStream()); - var softwareBitmap = await decoder.GetSoftwareBitmapAsync(); - - // SoftwareBitmapSource.SetBitmapAsync only supports SoftwareBitmap with - // bgra8 pixel format and pre-multiplied or no alpha. - if (softwareBitmap.BitmapPixelFormat != BitmapPixelFormat.Bgra8 - || softwareBitmap.BitmapAlphaMode == BitmapAlphaMode.Straight) - { - softwareBitmap = SoftwareBitmap.Convert( - softwareBitmap, BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied); - } - - softwareBitmapSource = new SoftwareBitmapSource(); - await softwareBitmapSource.SetBitmapAsync(softwareBitmap); - } - catch (Exception ex) - { - _log.Error($"Error creating SoftwareBitmapSource from file path: {ex.Message}"); - } - - return softwareBitmapSource; - } - - internal static unsafe uint GetProcessIdFromWindow(HWND hWnd) - { - uint processID = 0; - _ = PInvoke.GetWindowThreadProcessId(hWnd, &processID); - return processID; - } - - internal static void TranslateUWPProcess(HWND hWnd, ref Process process) - { - if (process.ProcessName.Equals("ApplicationFrameHost", StringComparison.OrdinalIgnoreCase)) - { - var processId = GetProcessIdFromUWPWindow(hWnd); - if (processId != 0) - { - process = Process.GetProcessById((int)processId); - } - } - } - - internal static unsafe uint GetProcessIdFromUWPWindow(HWND hWnd) - { - UWPProcessFinder processFinder = new(); - PInvoke.EnumChildWindows(hWnd, processFinder.EnumChildWindowsProc, IntPtr.Zero); - return processFinder.UWPProcessId; - } - - private sealed class UWPProcessFinder - { - public uint UWPProcessId { get; private set; } - - public unsafe BOOL EnumChildWindowsProc(HWND hWnd, LPARAM data) - { - var className = stackalloc char[256]; - var classNameLength = PInvoke.GetClassName(hWnd, className, 256); - if (classNameLength > 0) - { - string classNameString = new(className, 0, classNameLength); - if (classNameString.StartsWith("Windows.UI.Core.", StringComparison.OrdinalIgnoreCase)) - { - uint hWndProcessId = 0; - _ = PInvoke.GetWindowThreadProcessId(hWnd, &hWndProcessId); - UWPProcessId = hWndProcessId; - return false; - } - } - - return true; - } - } - - internal static HWINEVENTHOOK WatchWindowPositionEvents(WINEVENTPROC procDelegate, uint processID) - { - var eventHook = PInvoke.SetWinEventHook( - PInvoke.EVENT_OBJECT_DESTROY, - PInvoke.EVENT_OBJECT_LOCATIONCHANGE, - HMODULE.Null, - procDelegate, - processID, - 0, - PInvoke.WINEVENT_OUTOFCONTEXT | PInvoke.WINEVENT_SKIPOWNPROCESS); - return eventHook; - } - - internal static HWINEVENTHOOK WatchWindowForegroundEvents(WINEVENTPROC procDelegate) - { - var eventHook = PInvoke.SetWinEventHook( - PInvoke.EVENT_SYSTEM_FOREGROUND, - PInvoke.EVENT_SYSTEM_FOREGROUND, - HMODULE.Null, - procDelegate, - 0, - 0, - PInvoke.WINEVENT_OUTOFCONTEXT | PInvoke.WINEVENT_SKIPOWNPROCESS); - return eventHook; - } - - internal static HWINEVENTHOOK WatchWindowFocusEvents(WINEVENTPROC procDelegate, uint processID) - { - var eventHook = PInvoke.SetWinEventHook( - PInvoke.EVENT_OBJECT_FOCUS, - PInvoke.EVENT_OBJECT_FOCUS, - HMODULE.Null, - procDelegate, - processID, - 0, - PInvoke.WINEVENT_OUTOFCONTEXT | PInvoke.WINEVENT_SKIPOWNPROCESS); - return eventHook; - } - - internal sealed class EnumWindowsData - { - public HWND OutHwnd { get; set; } - - public StringCollection? ExcludedProcesses { get; set; } - - public EnumWindowsData() - { - OutHwnd = HWND.Null; - } - } - - internal static unsafe HWND FindVisibleForegroundWindow(StringCollection excludedProcesses) - { - EnumWindowsData data = new() { ExcludedProcesses = excludedProcesses }; -#pragma warning disable CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type - LPARAM lparamData = new((nint)(&data)); -#pragma warning restore CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type - PInvoke.EnumWindows(EnumProc, lparamData); - return data.OutHwnd; - } - - internal static bool IsAcceptableWindow(HWND hWnd, StringCollection excludedProcesses) - { - if (excludedProcesses != null && excludedProcesses.Count > 0) - { - foreach (var processName in excludedProcesses) - { - if (processName != null && IsProcessName(hWnd, processName)) - { - return false; - } - } - } - - return true; - } - - internal static unsafe bool IsProcessName(HWND hWnd, string name) - { - uint processId = 0; - _ = PInvoke.GetWindowThreadProcessId(hWnd, &processId); - var process = Process.GetProcessById((int)processId); - if (string.Equals(process.ProcessName, name, StringComparison.OrdinalIgnoreCase)) - { - return true; - } - - return false; - } - - internal static string GetProcessName(uint processId) - { - var process = Process.GetProcessById((int)processId); - return process.ProcessName; - } - - internal static void SetWindowExTransparent(HWND hwnd) - { - var extendedStyle = (WINDOW_EX_STYLE)PInvoke.GetWindowLong(hwnd, WINDOW_LONG_PTR_INDEX.GWL_EXSTYLE); - _ = PInvoke.SetWindowLong(hwnd, WINDOW_LONG_PTR_INDEX.GWL_EXSTYLE, (int)(extendedStyle | WINDOW_EX_STYLE.WS_EX_TRANSPARENT)); - } - - internal static void SetWindowExNotTransparent(HWND hwnd) - { - var extendedStyle = (WINDOW_EX_STYLE)PInvoke.GetWindowLong(hwnd, WINDOW_LONG_PTR_INDEX.GWL_EXSTYLE); - _ = PInvoke.SetWindowLong(hwnd, WINDOW_LONG_PTR_INDEX.GWL_EXSTYLE, (int)(extendedStyle & ~WINDOW_EX_STYLE.WS_EX_TRANSPARENT)); - } - - internal static T? FindParentControl(DependencyObject child) - where T : DependencyObject - { - var parentObject = VisualTreeHelper.GetParent(child); - if (parentObject == null) - { - return null; - } - - if (parentObject is T parent) - { - return parent; - } - else - { - return FindParentControl(parentObject); - } - } - - private static RECT GetWorkAreaRect() - { - RECT rect = default; - unsafe - { - PInvoke.SystemParametersInfo(SYSTEM_PARAMETERS_INFO_ACTION.SPI_GETWORKAREA, 0, &rect, 0); - } - - return rect; - } - - internal static RECT GetMonitorRectForWindow(HWND hWnd) - { - var monitor = PInvoke.MonitorFromWindow(hWnd, MONITOR_FROM_FLAGS.MONITOR_DEFAULTTONEAREST); - var monitorInfo = new MONITORINFO { cbSize = (uint)Marshal.SizeOf(typeof(MONITORINFO)) }; - PInvoke.GetMonitorInfo(monitor, ref monitorInfo); - var screenBounds = monitorInfo.rcMonitor; - return screenBounds; - } - - internal static double GetDpiScaleForWindow(HWND hWnd) - { - var monitor = PInvoke.MonitorFromWindow(hWnd, MONITOR_FROM_FLAGS.MONITOR_DEFAULTTONEAREST); - PInvoke.GetScaleFactorForMonitor(monitor, out DEVICE_SCALE_FACTOR scaleFactor).ThrowOnFailure(); - return (double)scaleFactor / 100; - } - - internal static void GetAppInfoUnderMouseCursor(out Process? process, out HWND hwnd) - { - process = null; - - // Grab the window under the cursor and attach to that process - PInvoke.GetCursorPos(out var pt); - hwnd = PInvoke.WindowFromPoint(pt); - - if (hwnd != HWND.Null) - { - // Walk up until we get the topmost parent window - HWND hwndParent = PInvoke.GetParent(hwnd); - - while (hwndParent != HWND.Null) - { - hwnd = hwndParent; - hwndParent = PInvoke.GetParent(hwnd); - } - - var processID = WindowHelper.GetProcessIdFromWindow(hwnd); - - if (processID != 0) - { - process = Process.GetProcessById((int)processID); - } - } - } - - // Only one ContentDialog can be shown at a time, so we have to keep track of the current one. - private static ContentDialog? ContentDialog { get; set; } - - internal static async void ShowTimedMessageDialog(FrameworkElement frameworkElement, string message, string closeButtonText) - { - if (ContentDialog is not null) - { - ContentDialog.Hide(); - ContentDialog = null; - } - - ContentDialog = new ContentDialog - { - XamlRoot = frameworkElement.XamlRoot, - RequestedTheme = frameworkElement.ActualTheme, - Content = message, - CloseButtonText = closeButtonText, - }; - - var timer = new DispatcherTimer - { - Interval = TimeSpan.FromSeconds(3), - }; - timer.Tick += (s, e) => - { - timer.Stop(); - if (ContentDialog is null) - { - return; - } - - ContentDialog.Hide(); - ContentDialog = null; - }; - - try - { - ContentDialog.Opened += (s, e) => timer.Start(); - ContentDialog.Closed += (s, e) => - { - timer.Stop(); - ContentDialog = null; - }; - await ContentDialog.ShowAsync(); - } - catch (Exception ex) - { - _log.Error(ex, "Error showing timed message dialog"); - } - } - - internal enum CpuArchitecture - { - X86, - X64, - ARM, - ARM64, - Unknown, - } - - internal static CpuArchitecture GetTargetArchitecture(IMAGE_FILE_MACHINE target) - { - return target switch - { - IMAGE_FILE_MACHINE.IMAGE_FILE_MACHINE_I386 => CpuArchitecture.X86, - IMAGE_FILE_MACHINE.IMAGE_FILE_MACHINE_AMD64 => CpuArchitecture.X64, - IMAGE_FILE_MACHINE.IMAGE_FILE_MACHINE_ARM => CpuArchitecture.ARM, - IMAGE_FILE_MACHINE.IMAGE_FILE_MACHINE_ARM64 => CpuArchitecture.ARM64, - _ => CpuArchitecture.Unknown, - }; - } - - internal static string GetAppArchitecture(SafeProcessHandle handle, string moduleName) - { - var cpuArchitecture = CommonHelper.GetLocalizedString("CpuArchitecture_Unknown"); - - try - { - unsafe - { - IMAGE_FILE_MACHINE processInfo; - IMAGE_FILE_MACHINE machineInfo; - var isWow64Result = PInvoke.IsWow64Process2(handle, out processInfo, &machineInfo); - if (isWow64Result) - { - var processArchitecture = GetTargetArchitecture(processInfo); - var machineArchitecture = GetTargetArchitecture(machineInfo); - - // "Unknown" means this is not a WOW64 process. - if (processArchitecture == CpuArchitecture.Unknown) - { - if (machineArchitecture == CpuArchitecture.X64) - { - // If this is an x64 machine and it's not a WOW64 process, it's an x64 process. - cpuArchitecture = CommonHelper.GetLocalizedString("CpuArchitecture_X64onX64"); - } - else - { - // If this is not an x64 machine, we need to get the process architecture from the process itself. - var processMachineInfo = default(PROCESS_MACHINE_INFORMATION); - var getProcInfoResult - = PInvoke.GetProcessInformation( - handle, - PROCESS_INFORMATION_CLASS.ProcessMachineTypeInfo, - &processMachineInfo, - (uint)Marshal.SizeOf()); - if (getProcInfoResult) - { - // Report the process architecture and the machine architecture. - processArchitecture = GetTargetArchitecture(processMachineInfo.ProcessMachine); - cpuArchitecture = CommonHelper.GetLocalizedString( - "CpuArchitecture_ProcessOnMachine", processArchitecture, machineArchitecture); - } - else - { - // If we can't get the process architecture, just report the machine architecture. - cpuArchitecture = CommonHelper.GetLocalizedString( - "CpuArchitecture_UnknownOnMachine", machineArchitecture); - } - } - } - else - { - // This is a WOW64 process, so report the process architecture and the machine architecture. - cpuArchitecture = CommonHelper.GetLocalizedString( - "CpuArchitecture_ProcessOnMachine", processArchitecture, machineArchitecture); - } - } - } - } - catch (Exception ex) - { - _log.Error(ex, "Error getting app architecture"); - } - - return cpuArchitecture; - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/WindowHooker`1.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/WindowHooker`1.cs deleted file mode 100644 index 0e44c2b8b..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Helpers/WindowHooker`1.cs +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Diagnostics; -using System.Globalization; -using System.Runtime.InteropServices; -using Serilog; -using Windows.Win32; -using Windows.Win32.Foundation; -using Windows.Win32.UI.WindowsAndMessaging; - -namespace DevHome.DevDiagnostics.Helpers; - -internal abstract class WindowHooker -{ - private static nint SetWindowLongPtr(HWND hWnd, WINDOW_LONG_PTR_INDEX nIndex, nint newLong) - { - if (IntPtr.Size == 8) - { - return CommonInterop.SetWindowLongPtr64(hWnd, nIndex, newLong); - } - else - { - return (nint)PInvoke.SetWindowLong(hWnd, nIndex, (int)newLong); - } - } - - protected static readonly ILogger Log = Serilog.Log.ForContext("SourceContext", nameof(T)); - - private readonly WNDPROC windowProcHook; - - private HWND listenerHwnd; - - private WNDPROC? originalWndProc; - - protected HWND ListenerHwnd { get => listenerHwnd; set => listenerHwnd = value; } - - internal WindowHooker() - { - windowProcHook = CustomWndProc; - } - - public virtual void Start(HWND listeningWindow) - { - if (ListenerHwnd != HWND.Null) - { - // No-OP if we're already running - Debug.Assert(ListenerHwnd == listeningWindow, "Why are we trying to start with a different hwnd?"); - return; - } - - ArgumentNullException.ThrowIfNull(listeningWindow, nameof(listeningWindow)); - - var wndproc = SetWindowLongPtr(listeningWindow, WINDOW_LONG_PTR_INDEX.GWL_WNDPROC, Marshal.GetFunctionPointerForDelegate(windowProcHook)); - if (wndproc == IntPtr.Zero) - { - Log.Error("SetWindowLongPtr failed: {GetLastError}", Marshal.GetLastWin32Error().ToString(CultureInfo.InvariantCulture)); - return; - } - - originalWndProc = Marshal.GetDelegateForFunctionPointer(wndproc); - ListenerHwnd = listeningWindow; - } - - public virtual void Stop() - { - if (ListenerHwnd != HWND.Null) - { - Debug.Assert(originalWndProc != null, "Where did the original wndproc go?"); - - var result = SetWindowLongPtr(ListenerHwnd, WINDOW_LONG_PTR_INDEX.GWL_WNDPROC, Marshal.GetFunctionPointerForDelegate(originalWndProc)); - if (result == IntPtr.Zero) - { - Log.Error("SetWindowLongPtr failed: {GetLastError}", Marshal.GetLastWin32Error().ToString(CultureInfo.InvariantCulture)); - } - - ListenerHwnd = HWND.Null; - } - } - - protected virtual LRESULT CustomWndProc(HWND hWnd, uint msg, WPARAM wParam, LPARAM lParam) - { - return PInvoke.CallWindowProc(originalWndProc, hWnd, msg, wParam, lParam); - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Images/DD.ico b/tools/DevDiagnostics/DevHome.DevDiagnostics/Images/DD.ico deleted file mode 100644 index 84014e6192492a72f9e12192525186c61e6583a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 151604 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�~6B*a(XPzHHZQp>4%Y&7=Brt1+AX8f7emwi59**N?EUc3s`Yt=~V453imbkG0f6hWN;4!D} zdOwMg8h6NKNnMRg&vCrZ|Lf}ng*hH$;?4m|b&XJ{x~|6a|0|Eexv{QV;MCR45R_&v zDPMpo%o-PeNnKstoEbA_AgFU0U0>tk*VL4kl`W~Mt3d<=s_O*(g^R0em{wL&?#b)X zcbxgv)r-qZpp39Zjf?L%Kn_{%`Z{Pfv!)K|0Ih&s+Jupwi&l zG~G8U-={X8r=+2l=h_plJE2cZNniHgR6H4%I1;8W4f;luFhf~h=fynZ_XvFBF;D)~ z@;VLru;W~ojw@k?QRTTWQ}taYaZTmv>q_NMT=ri~xTZ8oTMbn_#$}$GF4NRd%~#_R zM@?f~rt>UU!Zx2K63-U0Y}7B;a#1vs=Ap~$a3A*7*|^?zoc`bA`mN)9;Q?G2?-dtD z!@q$1F97e0t;kO~4t9B?&y4d2!6PzxeF;vJKIvAJ@BzIZCXH zqa9GJcol6>Yy;O`8_=Ez1~B70dqy~AdU!t@D1`f9bJPwFA41cD0@DD_aS_~(EAyw% znTACnbJ%xg{>-^^XU?3%-YfIOzqxZ}&Ag7$IYgK{SEMq>nLcwC{zRUDqyLTfIs5+s D^9AZs diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/AppRuntimeInfo.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/AppRuntimeInfo.cs deleted file mode 100644 index 3e701eec1..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/AppRuntimeInfo.cs +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Management; -using System.Text.RegularExpressions; -using CommunityToolkit.Mvvm.ComponentModel; -using DevHome.DevDiagnostics.Helpers; -using Microsoft.UI.Xaml; -using Serilog; - -namespace DevHome.DevDiagnostics.Models; - -public partial class AppRuntimeInfo : ObservableObject -{ - private static readonly ILogger _log = Log.ForContext("SourceContext", nameof(AppRuntimeInfo)); - - private readonly string _unknownText = CommonHelper.GetLocalizedString("UnknownText"); - - private const string UwpCommandLinePattern = @"^(.*) -ServerName:(.*?)\.AppX(.*?)\.mca$"; - - [GeneratedRegex(UwpCommandLinePattern)] - private static partial Regex UwpCommandLineRegex(); - - [ObservableProperty] - private int _processId = 0; - - [ObservableProperty] - private int _basePriority = 0; - - [ObservableProperty] - private int _priorityClass = 0; - - [ObservableProperty] - private string _mainModuleFileName = string.Empty; - - [ObservableProperty] - private string _cpuArchitecture = string.Empty; - - [ObservableProperty] - private bool _isPackaged = false; - - [ObservableProperty] - private bool _isRunningAsAdmin = false; - - [ObservableProperty] - private bool _isRunningAsSystem = false; - - [ObservableProperty] - private Visibility _visibility = Visibility.Visible; - - [ObservableProperty] - private string _activationArgs = string.Empty; - - [ObservableProperty] - private PackageInfo _packageInfo = new(); - - [ObservableProperty] - private string _identifiedFrameWorkTypes = string.Empty; - - private List FrameworkTypes { get; } = []; - - public AppRuntimeInfo() - { - FrameworkTypes.Add(new FrameworkType("Avalonia.Base.dll", "Avalonia")); - FrameworkTypes.Add(new FrameworkType("DXCore.dll", "DirectX")); - FrameworkTypes.Add(new FrameworkType("Microsoft.Maui.dll", "Maui")); - FrameworkTypes.Add(new FrameworkType("MFC", "MFC", false)); - FrameworkTypes.Add(new FrameworkType("Python.exe", "Python")); - FrameworkTypes.Add(new FrameworkType("Microsoft.Web.WebView2.Core.dll", "WebView2")); - FrameworkTypes.Add(new FrameworkType("Microsoft.Windows.SDK.NET.dll", "Windows App SDK")); - FrameworkTypes.Add(new FrameworkType("System.Windows.Forms.dll", "Windows Forms")); - FrameworkTypes.Add(new FrameworkType("Microsoft.UI.Xaml.dll", "WinUI 2")); - FrameworkTypes.Add(new FrameworkType("Microsoft.UI.Xaml.Controls.dll", "WinUI 3")); - FrameworkTypes.Add(new FrameworkType("PresentationFramework.dll", "WPF")); - } - - public void GetFrameworksAndCommandLine(Process process) - { - var identifiedFrameworks = new List(); - var modules = process.Modules; - foreach (ProcessModule module in modules) - { - foreach (var item in FrameworkTypes) - { - if (identifiedFrameworks.Contains(item.Name)) - { - continue; - } - - if (item.IsExactMatch) - { - if (module.ModuleName.Equals(item.Determinator, StringComparison.OrdinalIgnoreCase)) - { - identifiedFrameworks.Add(item.Name); - } - } - else - { - if (module.ModuleName.Contains(item.Determinator, StringComparison.OrdinalIgnoreCase)) - { - identifiedFrameworks.Add(item.Name); - } - } - } - } - - // Both WinUI2 and WinUI3 use Microsoft.UI.Xaml.dll, but only WinUI3 uses Microsoft.UI.Xaml.Controls.dll. - if (identifiedFrameworks.Contains("WinUI 3")) - { - identifiedFrameworks.Remove("WinUI 2"); - } - - IdentifiedFrameWorkTypes = string.Join(", ", identifiedFrameworks); - - /* The only reliable check for (most) UWP apps is if the command-line matches the known UWP pattern. - Examples: - "C:\Program Files\WindowsApps\Microsoft.WindowsAlarms_11.2406.47.0_x64__8wekyb3d8bbwe\Time.exe" -ServerName:App.AppXq8avk61zazpy808ab5ppkf6taqp47km6.mca - "C:\Program Files\WindowsApps\35455AndrewWhitechapel.uTaskManager_2309.21.1.0_x64__6rjrek5qak82t\uTaskManager.exe" -ServerName:uTaskManager.AppXjaq7n2ahxkbe1kpkhkxqhr5d0s2yr0pb.mca - "C:\Foo\TestApps\UwpAea\UwpAea\bin\x86\Debug\AppX\UwpAea.exe" -ServerName:Blueberry.Pie.AppXnzm9t7zr5rgagha6146e9rgzyahj42xx.mca - NOTE: does not handle the case of multi-instance UWP apps. - */ - ActivationArgs = CommonHelper.GetCommandLine(process); - if (UwpCommandLineRegex().IsMatch(ActivationArgs)) - { - IdentifiedFrameWorkTypes += ", UWP"; - ActivationArgs = _unknownText; - } - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/ClipboardContents.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/ClipboardContents.cs deleted file mode 100644 index 325c1dc29..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/ClipboardContents.cs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -namespace DevHome.DevDiagnostics.Models; - -public class ClipboardContents -{ - public string Raw { get; set; } = string.Empty; - - public string Hex { get; set; } = string.Empty; - - public string Dec { get; set; } = string.Empty; - - public string Code { get; set; } = string.Empty; - - public string Help { get; set; } = string.Empty; - - public void Clear() - { - Raw = string.Empty; - Hex = string.Empty; - Dec = string.Empty; - Code = string.Empty; - Help = string.Empty; - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/ClipboardMonitor.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/ClipboardMonitor.cs deleted file mode 100644 index 48d592556..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/ClipboardMonitor.cs +++ /dev/null @@ -1,187 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.ComponentModel; -using System.Globalization; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text.RegularExpressions; -using System.Threading; -using DevHome.Common.Extensions; -using DevHome.DevDiagnostics.Helpers; -using Microsoft.UI.Xaml; -using Windows.Win32; -using Windows.Win32.Foundation; - -namespace DevHome.DevDiagnostics.Models; - -internal sealed class ClipboardMonitor : WindowHooker, INotifyPropertyChanged -{ - public static readonly ClipboardMonitor Instance = new(); - - public ClipboardContents Contents { get; private set; } = new(); - - public event PropertyChangedEventHandler? PropertyChanged; - - internal ClipboardMonitor() - { - } - - private void ClipboardChanged() - { - SafeHandle? h = null; - ClipboardContents newContents = new(); - try - { - var clipboardText = string.Empty; - PInvoke.OpenClipboard(ListenerHwnd); - h = PInvoke.GetClipboardData_SafeHandle(13 /* CF_UNICODETEXT */); - if (!h.IsInvalid) - { - unsafe - { - var p = PInvoke.GlobalLock(h); - clipboardText = Marshal.PtrToStringUni((IntPtr)p) ?? string.Empty; - } - - if (clipboardText != string.Empty) - { - newContents = ParseClipboardContents(clipboardText); - } - } - } - finally - { - if (h is not null && !h.IsInvalid) - { - PInvoke.GlobalUnlock(h); - - // You're not suppose to close this handle. - h.SetHandleAsInvalid(); - } - - PInvoke.CloseClipboard(); - - Contents = newContents; - OnPropertyChanged(nameof(Contents)); - } - } - - /* TODO This pattern matches the following: - 100 - 0x100 - 0x80040005 - -2147221499 - -1 - 0xabc - abc - ffffffff - 1de - cab - bee - - ...but sequences like "cab", "bee", "fed" could be false positives. We need - more logic to exclude these. - */ - private static readonly Regex _findNumbersRegex = - new( - pattern: @"(?:0[xX][0-9A-Fa-f]+|-?\b(?:\d+|\d*\.\d+)\b|\b[0-9A-Fa-f]+\b)", - options: RegexOptions.Compiled | RegexOptions.IgnoreCase); - - private ClipboardContents ParseClipboardContents(string text) - { - ClipboardContents newContents = new(); - - // If this text contains a number, show it in different number bases. - var matches = _findNumbersRegex.Matches(text); - - foreach (var match in matches.Cast()) - { - var original = match.ToString(); - - // Assume the number is easily identifable as either base 10 or base 16... convert to int. - int? errorAsInt = CommonHelper.ParseStringToInt(original); - - if (errorAsInt is null) - { - // If this ConvertFromString() function fails due to a bad format, update the above regex to ensure - // the bad string isn't fed to this function. - Log.Warning("Failed to parse \" {original} \" to a number", original); - return newContents; - } - - newContents.Raw = original; - newContents.Hex = Convert.ToString((int)errorAsInt, 16); - newContents.Dec = Convert.ToString((int)errorAsInt, 10); - - var errors = ErrorLookupHelper.LookupError((int)errorAsInt); - if (errors is not null) - { - foreach (var error in errors) - { - // Seperate each error with a space. These errors aren't localized, so we may not need to worry - // about the space being in the wrong place. - if (newContents.Code != string.Empty) - { - newContents.Code += " "; - newContents.Help += " "; - } - - newContents.Code += error.Name; - newContents.Help += error.Help; - } - } - - break; - } - - return newContents; - } - - public void Start() - { - var primaryWindow = Application.Current.GetService(); - Start((HWND)primaryWindow.GetWindowHandle()); - } - - public override void Start(HWND hwndUsedForListening) - { - base.Start(hwndUsedForListening); - - var success = PInvoke.AddClipboardFormatListener(ListenerHwnd); - if (!success) - { - Log.Error("AddClipboardFormatListener failed: {GetLastError}", Marshal.GetLastWin32Error().ToString(CultureInfo.CurrentCulture)); - } - } - - public override void Stop() - { - if (ListenerHwnd != HWND.Null) - { - PInvoke.RemoveClipboardFormatListener(ListenerHwnd); - - base.Stop(); - } - } - - protected override LRESULT CustomWndProc(HWND hWnd, uint msg, WPARAM wParam, LPARAM lParam) - { - switch (msg) - { - case PInvoke.WM_CLIPBOARDUPDATE: - { - ThreadPool.QueueUserWorkItem((o) => ClipboardChanged()); - break; - } - } - - return base.CustomWndProc(hWnd, msg, wParam, lParam); - } - - private void OnPropertyChanged(string propertyName) - { - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/FrameworkType.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/FrameworkType.cs deleted file mode 100644 index 6f36a0438..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/FrameworkType.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using CommunityToolkit.Mvvm.ComponentModel; - -namespace DevHome.DevDiagnostics.Models; - -public partial class FrameworkType : ObservableObject -{ - internal bool IsExactMatch { get; private set; } = true; - - internal string Determinator - { - get; set; - } - - public string Name - { - get; set; - } - - public FrameworkType(string determinator, string name, bool isExactMatch = true) - { - Determinator = determinator; - Name = name; - IsExactMatch = isExactMatch; - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/Insight.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/Insight.cs deleted file mode 100644 index 200c5b3ca..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/Insight.cs +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System.Text.RegularExpressions; -using CommunityToolkit.Mvvm.ComponentModel; -using DevHome.DevDiagnostics.Controls; -using Microsoft.UI.Xaml; - -namespace DevHome.DevDiagnostics.Models; - -public enum InsightType -{ - Unknown, - LockedFile, - AccessDeniedFile, - AccessDeniedRegistry, - InvalidPath, - Security, - MemoryViolation, -} - -public abstract partial class Insight : ObservableObject -{ - public string Title { get; set; } = string.Empty; - - public InsightType InsightType { get; set; } = InsightType.Unknown; - - public UIElement? CustomControl { get; protected set; } - - [ObservableProperty] - private bool _hasBeenRead; - - // We show the badge by default, as HasBeenRead is false by default. - [ObservableProperty] - private double _badgeOpacity = 1; -} - -public class SimpleTextInsight : Insight -{ - private readonly InsightSimpleTextControl _mycontrol = new(); - private string _description = string.Empty; - - internal string Description - { - get => _description; - - set - { - _description = value; - _mycontrol.Description = value; - } - } - - internal SimpleTextInsight() - { - CustomControl = _mycontrol; - } -} - -internal sealed class InsightRegex -{ - internal InsightType InsightType { get; set; } - - internal Regex Regex { get; set; } - - internal InsightRegex(InsightType type, Regex regex) - { - Regex = regex; - InsightType = type; - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/InstalledAppInfo.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/InstalledAppInfo.cs deleted file mode 100644 index 102bdf2f1..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/InstalledAppInfo.cs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using Microsoft.UI.Xaml.Media.Imaging; -using Windows.ApplicationModel; - -namespace DevHome.DevDiagnostics.Models; - -public class InstalledAppInfo -{ - public string? Name { get; set; } - - public BitmapImage? Icon { get; set; } - - public string? ShortcutFilePath { get; set; } - - public string? TargetPath { get; set; } - - public string? AppUserModelId { get; set; } - - public Package? AppPackage { get; set; } - - public string? IconFilePath { get; set; } - - public bool IsMsix - { - get => AppUserModelId is not null; - - set - { - } - } - - public override string ToString() - { - return Name ?? base.ToString()!; - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/NavLink.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/NavLink.cs deleted file mode 100644 index 5065ccde6..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/NavLink.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; - -namespace DevHome.DevDiagnostics.Models; - -public class NavLink -{ - public string IconText { get; internal set; } - - public string ContentText { get; internal set; } - - public NavLink(string icon, string title) - { - IconText = icon; - ContentText = title; - } -} - -public class PageNavLink : NavLink -{ - public Type? PageViewModel { get; internal set; } - - public PageNavLink(string icon, string title, Type? pageViewModel) - : base(icon, title) - { - PageViewModel = pageViewModel; - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/PackageInfo.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/PackageInfo.cs deleted file mode 100644 index c9ccfd4da..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/PackageInfo.cs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using CommunityToolkit.Mvvm.ComponentModel; - -namespace DevHome.DevDiagnostics.Models; - -public partial class PackageInfo : ObservableObject -{ - [ObservableProperty] - private string _fullName = string.Empty; - - [ObservableProperty] - private string _version = string.Empty; - - [ObservableProperty] - private string _displayName = string.Empty; - - [ObservableProperty] - private string _installedDate = string.Empty; - - [ObservableProperty] - private string _installedPath = string.Empty; - - [ObservableProperty] - private string _publisher = string.Empty; - - [ObservableProperty] - private bool _isDevelopmentMode = false; - - [ObservableProperty] - private string _signatureKind = string.Empty; - - [ObservableProperty] - private string _status = string.Empty; - - [ObservableProperty] - private string _dependencies = string.Empty; -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/PerfCounters.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/PerfCounters.cs deleted file mode 100644 index 0aedc4065..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/PerfCounters.cs +++ /dev/null @@ -1,230 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics; -using System.Linq; -using System.Threading; -using CommunityToolkit.Mvvm.ComponentModel; -using Serilog; - -namespace DevHome.DevDiagnostics.Models; - -public partial class PerfCounters : ObservableObject, IDisposable -{ - private static readonly ILogger _log = Log.ForContext("SourceContext", nameof(PerfCounters)); - - public static readonly PerfCounters Instance = new(); - - private const string ProcessCategory = "Process"; - private const string ProcessorCategory = "Processor Information"; - private const string MemoryCategory = "Memory"; - private const string DiskCategory = "PhysicalDisk"; - - private const string CpuCounterName = "% Processor Time"; - private const string RamCounterName = "Working Set - Private"; - private const string SystemCpuCounterName = "% Processor Utility"; - private const string SystemRamCounterName = "Committed Bytes"; - private const string SystemDiskCounterName = "% Disk Time"; - - private const string ReadCounterName = "IO Read Bytes/sec"; - private const string WriteCounterName = "IO Write Bytes/sec"; - private const string GpuEngineName = "GPU Engine"; - private const string UtilizationPercentageName = "Utilization Percentage"; - - private Process? _targetProcess; - private PerformanceCounter? _cpuCounter; - private List? _gpuCounters; - private PerformanceCounter? _ramCounter; - private PerformanceCounter? _readCounter; - private PerformanceCounter? _writeCounter; - - private PerformanceCounter? _systemCpuCounter; - private PerformanceCounter? _systemRamCounter; - private PerformanceCounter? _systemDiskCounter; - - private Timer? _timer; - - [ObservableProperty] - private float _cpuUsage; - - [ObservableProperty] - private float _gpuUsage; - - [ObservableProperty] - private float _ramUsageInMB; - - [ObservableProperty] - private float _diskUsage; - - [ObservableProperty] - private float _networkUsage; - - [ObservableProperty] - private float _systemCpuUsage; - - [ObservableProperty] - private float _systemRamUsageInGB; - - [ObservableProperty] - private float _systemDiskUsage; - - public PerfCounters() - { - TargetAppData.Instance.PropertyChanged += TargetApp_PropertyChanged; - - ThreadPool.QueueUserWorkItem((o) => - { - _systemCpuCounter = new PerformanceCounter(ProcessorCategory, SystemCpuCounterName, "_Total", true); - _systemRamCounter = new PerformanceCounter(MemoryCategory, SystemRamCounterName, true); - _systemDiskCounter = new PerformanceCounter(DiskCategory, SystemDiskCounterName, "_Total", true); - UpdateTargetProcess(TargetAppData.Instance.TargetProcess); - }); - } - - private void TargetApp_PropertyChanged(object? sender, PropertyChangedEventArgs e) - { - if (e.PropertyName == nameof(TargetAppData.TargetProcess)) - { - ThreadPool.QueueUserWorkItem((o) => UpdateTargetProcess(TargetAppData.Instance.TargetProcess)); - } - else if (e.PropertyName == nameof(TargetAppData.HasExited)) - { - CloseTargetCounters(); - } - } - - private void UpdateTargetProcess(Process? process) - { - if (process == _targetProcess) - { - // Already tracking this process. - return; - } - - CloseTargetCounters(); - - _targetProcess = process; - if (_targetProcess == null) - { - return; - } - - var processName = _targetProcess.ProcessName; - _cpuCounter = new PerformanceCounter(ProcessCategory, CpuCounterName, processName, true); - _ramCounter = new PerformanceCounter(ProcessCategory, RamCounterName, processName, true); - _gpuCounters = GetGpuCounters(_targetProcess.Id); - _readCounter = new PerformanceCounter(ProcessCategory, ReadCounterName, processName, true); - _writeCounter = new PerformanceCounter(ProcessCategory, WriteCounterName, processName, true); - } - - public void Start() - { - Stop(); - _timer = new Timer(TimerCallback, null, TimeSpan.Zero, TimeSpan.FromSeconds(1)); - } - - public void Stop() - { - _timer?.Dispose(); - _timer = null; - } - - private void CloseTargetCounters() - { - _cpuCounter?.Close(); - _cpuCounter?.Dispose(); - _cpuCounter = null; - _ramCounter?.Close(); - _ramCounter?.Dispose(); - _ramCounter = null; - - foreach (var counter in _gpuCounters ?? Enumerable.Empty()) - { - counter.Close(); - counter.Dispose(); - } - - _gpuCounters?.Clear(); - - _readCounter?.Close(); - _readCounter?.Dispose(); - _readCounter = null; - _writeCounter?.Close(); - _writeCounter?.Dispose(); - _writeCounter = null; - } - - public static List GetGpuCounters(int pid) - { - var category = new PerformanceCounterCategory(GpuEngineName); - var counterNames = category.GetInstanceNames(); - var gpuCounters = counterNames - .Where(counterName => counterName.Contains($"pid_{pid}")) - .SelectMany(category.GetCounters) - .Where(counter => counter.CounterName.Equals(UtilizationPercentageName, StringComparison.Ordinal)) - .ToList(); - return gpuCounters; - } - - private void TimerCallback(object? state) - { - try - { - CpuUsage = _cpuCounter?.NextValue() / Environment.ProcessorCount ?? 0; - GpuUsage = GetGpuUsage(_gpuCounters); - - // Report app memory usage in MB - RamUsageInMB = _ramCounter?.NextValue() / (1024 * 1024) ?? 0; - - var readBytesPerSec = _readCounter?.NextValue() ?? 0; - var writeBytesPerSec = _writeCounter?.NextValue() ?? 0; - var totalDiskBytesPerSec = readBytesPerSec + writeBytesPerSec; - DiskUsage = totalDiskBytesPerSec / (1024 * 1024); - - SystemCpuUsage = _systemCpuCounter?.NextValue() ?? 0; - - // Report system memory usage in GB - SystemRamUsageInGB = _systemRamCounter?.NextValue() / (1024 * 1024 * 1024) ?? 0; - SystemDiskUsage = _systemDiskCounter?.NextValue() ?? 0; - } - catch (Exception ex) - { - _log.Debug(ex, "Failed to update counters."); - } - } - - public static float GetGpuUsage(List? gpuCounters) - { - float result = 0; - try - { - gpuCounters?.ForEach(x => x.NextValue()); - Thread.Sleep(500); - result = gpuCounters?.Sum(x => x.NextValue()) ?? 0; - } - catch (Exception ex) - { - _log.Debug(ex, "Failed to get Gpu usage."); - } - - return result; - } - - public void Dispose() - { - _cpuCounter?.Dispose(); - _ramCounter?.Dispose(); - _readCounter?.Dispose(); - _writeCounter?.Dispose(); - - foreach (var counter in _gpuCounters ?? Enumerable.Empty()) - { - counter.Dispose(); - } - - GC.SuppressFinalize(this); - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/ProcessModuleInfo.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/ProcessModuleInfo.cs deleted file mode 100644 index f3cff12e8..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/ProcessModuleInfo.cs +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System.Diagnostics; -using System.IO; - -namespace DevHome.DevDiagnostics.Models; - -public class ProcessModuleInfo -{ - public string ModuleName { get; } - - public string FileVersionInfo { get; } - - public string FileVersion { get; } - - public nint BaseAddress { get; } - - public nint EntryPointAddress { get; } - - public int ModuleMemorySize { get; } - - public ProcessModuleInfo(ProcessModule module) - { - ModuleName = module.ModuleName; - try - { - FileVersionInfo = module.FileVersionInfo.ToString(); - FileVersion = module.FileVersionInfo.FileVersion ?? string.Empty; - } - catch (FileNotFoundException) - { - FileVersionInfo = string.Empty; - FileVersion = string.Empty; - } - - BaseAddress = module.BaseAddress; - EntryPointAddress = module.EntryPointAddress; - ModuleMemorySize = module.ModuleMemorySize; - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/Setting.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/Setting.cs deleted file mode 100644 index 0eeed2d7c..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/Setting.cs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -namespace DevHome.DevDiagnostics.Models; - -public class Setting -{ - public string Path { get; } - - public string Header { get; } - - public string Description { get; } - - public string Glyph { get; } - - public Setting(string path, string header, string description, string glyph) - { - Path = path; - Header = header; - Description = description; - Glyph = glyph; - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/TargetAppData.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/TargetAppData.cs deleted file mode 100644 index a42ca6352..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/TargetAppData.cs +++ /dev/null @@ -1,170 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.ComponentModel; -using System.Diagnostics; -using System.Drawing; -using System.Security.Principal; -using CommunityToolkit.Mvvm.ComponentModel; -using Microsoft.UI.Xaml.Media.Imaging; -using Microsoft.Win32.SafeHandles; -using Windows.Win32; -using Windows.Win32.Foundation; -using static DevHome.DevDiagnostics.Helpers.WindowHelper; - -namespace DevHome.DevDiagnostics.Models; - -public partial class TargetAppData : ObservableObject -{ - public static readonly TargetAppData Instance = new(); - - public int ProcessId => TargetProcess?.Id ?? 0; - - public bool IsRunningAsSystem => TargetProcess?.SessionId == 0; - - public string Title { get; private set; } = string.Empty; - - public bool IsRunningAsAdmin - { - get - { - try - { - SafeFileHandle processToken; - var result = PInvoke.OpenProcessToken(TargetProcess?.SafeHandle, Windows.Win32.Security.TOKEN_ACCESS_MASK.TOKEN_QUERY, out processToken); - if (result != 0) - { - var identity = new WindowsIdentity(processToken.DangerousGetHandle()); - return identity?.Owner?.IsWellKnown(WellKnownSidType.BuiltinAdministratorsSid) ?? false; - } - - return false; - } - catch (Win32Exception ex) - { - if (ex.NativeErrorCode == (int)WIN32_ERROR.ERROR_ACCESS_DENIED) - { - return true; - } - - return false; - } - } - } - - [ObservableProperty] - private SoftwareBitmapSource? _icon; - - [ObservableProperty] - private string _appName = string.Empty; - - [ObservableProperty] - [NotifyPropertyChangedFor(nameof(ProcessId))] - private Process? _targetProcess; - - internal HWND HWnd { get; private set; } - - [ObservableProperty] - private bool _hasExited; - - private async void GetBitmap(Process process, HWND hWnd) - { - try - { - Bitmap? bitmap = null; - - if (hWnd != HWND.Null) - { - // First check if we can get an icon from the HWND - bitmap = GetAppIcon(hWnd); - } - - if (bitmap is null && process.MainWindowHandle != HWND.Null) - { - // If not, try and grab an icon from the process's main window - bitmap = GetAppIcon((HWND)process.MainWindowHandle); - } - - if (bitmap is null && process.MainModule is not null) - { - // Failing that, try and get the icon from the exe - bitmap = System.Drawing.Icon.ExtractAssociatedIcon(process.MainModule.FileName)?.ToBitmap(); - } - - // Failing that, grab the default app icon - bitmap ??= System.Drawing.Icon.FromHandle(LoadDefaultAppIcon()).ToBitmap(); - - if (bitmap is not null) - { - Icon = await GetWinUI3BitmapSourceFromGdiBitmap(bitmap); - } - else - { - Icon = null; - } - } - catch - { - Icon = null; - } - - return; - } - - private bool IsAppHost(string appName) - { - return string.Equals(appName, "ApplicationFrameHost", StringComparison.OrdinalIgnoreCase); - } - - internal void SetNewAppData(Process process, HWND hWnd) - { - TargetProcess = process; - HWnd = hWnd; - - // Reset hasExited, but don't trigger the property change event. -#pragma warning disable MVVMTK0034 // Direct field reference to [ObservableProperty] backing field - _hasExited = false; -#pragma warning restore MVVMTK0034 // Direct field reference to [ObservableProperty] backing field - try - { - // These can throw if we don't have permissions to monitor process state. - TargetProcess.EnableRaisingEvents = true; - TargetProcess.Exited += TargetProcess_Exited; - } - catch - { - } - - Title = GetWindowTitle(hWnd) ?? TargetProcess.MainWindowTitle; - - // Getting the icon will be async - GetBitmap(process, hWnd); - - AppName = IsAppHost(TargetProcess.ProcessName) ? Title : TargetProcess.ProcessName; - - OnPropertyChanged(nameof(AppName)); - OnPropertyChanged(nameof(TargetProcess)); - OnPropertyChanged(nameof(HWnd)); - } - - internal void ClearAppData() - { - Title = string.Empty; - AppName = string.Empty; - Icon = null; - TargetProcess?.Dispose(); - TargetProcess = null; - - OnPropertyChanged(nameof(AppName)); - OnPropertyChanged(nameof(TargetProcess)); - OnPropertyChanged(nameof(HWnd)); - OnPropertyChanged(nameof(Icon)); - } - - private void TargetProcess_Exited(object? sender, EventArgs e) - { - // Change the property, so that we trigger the property change event. - HasExited = true; - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/ThemeName.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/ThemeName.cs deleted file mode 100644 index 0ee4e8891..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/ThemeName.cs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System.Collections.Generic; -using Microsoft.UI.Xaml; - -namespace DevHome.DevDiagnostics.Models; - -public class ThemeName -{ - public string Name { get; set; } = string.Empty; - - public ElementTheme Theme { get; set; } - - public ThemeName(string name, ElementTheme theme) => (Name, Theme) = (name, theme); - - public static List Themes { get; private set; } = - [ - new ThemeName("Light", ElementTheme.Light), - new ThemeName("Dark", ElementTheme.Dark), - new ThemeName("Default", ElementTheme.Default) - ]; -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/WERAnalysis.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/WERAnalysis.cs deleted file mode 100644 index 95563c7f5..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/WERAnalysis.cs +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Diagnostics; -using System.IO; -using System.Text.RegularExpressions; -using DevHome.DevDiagnostics.Helpers; -using Serilog; - -namespace DevHome.DevDiagnostics.Models; - -// This class holds the WER analysis from a single dump analysis tool -public class WERAnalysis -{ - private static readonly ILogger _log = Log.ForContext("SourceContext", nameof(WERAnalysis)); - - public Tool AnalysisTool { get; private set; } - - public string? Analysis { get; private set; } - - public string? FailureBucket { get; private set; } - - private readonly string _crashDumpPath; - - public WERAnalysis(Tool analysisTool, string crashDumpPath) - { - AnalysisTool = analysisTool; - _crashDumpPath = crashDumpPath; - } - - public void Run() - { - // See if we have a cached analysis - var analysisFilePath = GetCachedResultsFileName(); - - if (File.Exists(analysisFilePath)) - { - Analysis = File.ReadAllText(analysisFilePath); - } - else - { - // Generate the analysis - ToolLaunchOptions options = new(); - options.CommandLineParams = _crashDumpPath; - options.RedirectStandardOut = true; - - AnalysisTool.Invoke(options); - - if (options.LaunchedProcess is not null) - { - string output = options.LaunchedProcess.StandardOutput.ReadToEnd(); - Analysis = output; - - try - { - // Cache these results - File.WriteAllText(analysisFilePath, output); - } - catch (Exception ex) - { - // If we can't write the file, we'll just ignore it. - // We'll just have to re-analyze the next time. - _log.Warning("Failed to cache analysis results - " + ex.ToString()); - } - } - } - - if (!string.IsNullOrEmpty(Analysis)) - { - ExternalTool? debuggerTool = AnalysisTool as ExternalTool; - - Debug.Assert(debuggerTool is not null, "We should only be running external tools on dumps"); - - // Apply the tool's regular expression to get the failure bucket - - // From MSDN - // When using System.Text.RegularExpressions to process untrusted input, pass a time -out value to prevent malicious - // users from causing a denial - of - service attack. A time-out value specifies how long a pattern - matching method - // should try to find a match before it times out. - // - // Only let the regex run for a max of 30 seconds... - Regex regex = new(debuggerTool.ExtraInfo, RegexOptions.Compiled, new TimeSpan(0, 0, 30)); - Match match = regex.Match(Analysis); - - if (match.Success) - { - FailureBucket = match.Groups[1].Value; - } - } - } - - private string GetCachedResultsFileName() - { - return _crashDumpPath + "." + AnalysisTool.Name + ".analysisresults"; - } - - public void RemoveCachedResults() - { - var analysisFilePath = GetCachedResultsFileName(); - - if (File.Exists(analysisFilePath)) - { - try - { - File.Delete(analysisFilePath); - } - catch (Exception ex) - { - _log.Warning("Failed to delete cache analysis results - " + ex.ToString()); - } - } - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/WERAnalysisReport.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/WERAnalysisReport.cs deleted file mode 100644 index cbe0e3420..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/WERAnalysisReport.cs +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Diagnostics; -using CommunityToolkit.Mvvm.ComponentModel; -using DevHome.Common.Extensions; -using DevHome.DevDiagnostics.Helpers; -using Microsoft.UI.Xaml; - -namespace DevHome.DevDiagnostics.Models; - -// This class contains a collection of all of the analysis reports generated by the -// different tools that are registered as crash analyzers -public partial class WERAnalysisReport : ObservableObject -{ - private readonly ExternalToolsHelper _externalTools; - private readonly Dictionary _toolAnalyses = new(); - - public WERReport Report { get; } - - // While we can have multiple failure buckets (1 from each tool), we have a "chosen" one here - // that we can bind to for the UI - [ObservableProperty] - private string _failureBucket = string.Empty; - - public ReadOnlyDictionary ToolAnalyses { get; private set; } - - public WERAnalysisReport(WERReport report) - { - Report = report; - ToolAnalyses = new(_toolAnalyses); - _externalTools = Application.Current.GetService(); - FailureBucket = report.FailureBucket; - } - - public void SetFailureBucketTool(Tool? tool) - { - if (tool is null) - { - // Resetting to the internal failure bucket - FailureBucket = Report.FailureBucket; - return; - } - - if (_toolAnalyses.TryGetValue(tool, out WERAnalysis? analysis)) - { - FailureBucket = string.IsNullOrEmpty(analysis.FailureBucket) ? string.Empty : analysis.FailureBucket; - } - else - { - FailureBucket = string.Empty; - } - } - - public void RunToolAnalysis(Tool tool) - { - Debug.Assert(tool.Type.HasFlag(ToolType.DumpAnalyzer), "We should only be running dump analyzers on dumps - Not " + tool.Type); - - WERAnalysis analysis = new(tool, Report.CrashDumpPath); - analysis.Run(); - if (analysis.Analysis is not null) - { - _toolAnalyses.Add(tool, analysis); - } - } - - public void RemoveToolAnalysis(Tool tool) - { - Debug.Assert(tool.Type.HasFlag(ToolType.DumpAnalyzer), "We should only be running dump analyzers on dumps - Not " + tool.Type); - - if (_toolAnalyses.TryGetValue(tool, out WERAnalysis? analysis)) - { - analysis.RemoveCachedResults(); - _toolAnalyses.Remove(tool); - } - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/WERAnalyzer.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/WERAnalyzer.cs deleted file mode 100644 index 2ecc36617..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/WERAnalyzer.cs +++ /dev/null @@ -1,187 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Collections.Specialized; -using System.Linq; -using System.Threading; -using DevHome.Common.Extensions; -using DevHome.DevDiagnostics.Helpers; -using Microsoft.UI.Xaml; - -namespace DevHome.DevDiagnostics.Models; - -// This class monitors for WER reports and runs analysis on them -public class WERAnalyzer : IDisposable -{ - private readonly WERHelper _werHelper; - private readonly ExternalToolsHelper _externalToolsHelper; - - private struct AnalysisRequest - { - public WERAnalysisReport Report; - public Tool Tool; - } - - private readonly BlockingCollection _analysisRequests = new(); - - private readonly ObservableCollection _werAnalysisReports = []; - - public ReadOnlyObservableCollection WERAnalysisReports { get; private set; } - - private readonly ObservableCollection _registeredAnalysisTools = []; - - public ReadOnlyObservableCollection RegisteredAnalysisTools { get; private set; } - - public WERAnalyzer() - { - WERAnalysisReports = new(_werAnalysisReports); - RegisteredAnalysisTools = new(_registeredAnalysisTools); - - _externalToolsHelper = Application.Current.GetService(); - - _werHelper = Application.Current.GetService(); - ((INotifyCollectionChanged)_werHelper.WERReports).CollectionChanged += WER_CollectionChanged; - - // Collect all of the tools used for dump analysis - foreach (Tool tool in _externalToolsHelper.AllExternalTools) - { - if (tool.Type.HasFlag(ToolType.DumpAnalyzer)) - { - _registeredAnalysisTools.Add(tool); - } - } - - ((INotifyCollectionChanged)_externalToolsHelper.AllExternalTools).CollectionChanged += AllExternalTools_CollectionChanged; - PopulateCurrentLogs(); - - // Create a dedicated thread to serially perform all of our crash dump analysis - var crashDumpAnalyzerThread = new Thread(() => - { - while (!_analysisRequests.IsCompleted) - { - if (_analysisRequests.TryTake(out AnalysisRequest request, Timeout.Infinite)) - { - request.Report.RunToolAnalysis(request.Tool); - } - } - }); - crashDumpAnalyzerThread.Name = "CrashDumpAnalyzerThread"; - crashDumpAnalyzerThread.Start(); - } - - private void AllExternalTools_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) - { - // If we have a new tool, we'll want to perform analysis on the crash dump - // with it. - if (e.Action == NotifyCollectionChangedAction.Add && e.NewItems is not null) - { - List newAnalysisTools = new(); - - foreach (Tool tool in e.NewItems) - { - if (tool.Type.HasFlag(ToolType.DumpAnalyzer)) - { - _registeredAnalysisTools.Add(tool); - newAnalysisTools.Add(tool); - } - } - - foreach (var report in _werAnalysisReports) - { - RunToolAnalysis(report, newAnalysisTools); - } - } - - // Or if we removed a tool, remove the analysis that it did. - else if (e.Action == NotifyCollectionChangedAction.Remove && e.OldItems is not null) - { - foreach (Tool tool in e.OldItems) - { - if (tool.Type.HasFlag(ToolType.DumpAnalyzer)) - { - _registeredAnalysisTools.Remove(tool); - - foreach (var report in _werAnalysisReports) - { - report.RemoveToolAnalysis(tool); - } - } - } - } - } - - private void WER_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) - { - if (e.Action == NotifyCollectionChangedAction.Add && e.NewItems != null) - { - ProcessDumpList(e.NewItems.Cast().ToList()); - } - } - - private void PopulateCurrentLogs() - { - ProcessDumpList(_werHelper.WERReports.ToList()); - } - - private void ProcessDumpList(List reports) - { - List reportsToAnalyze = new(); - - // First publish all of these reports to our listeners. Then we'll go back and perform - // analysis on them. - foreach (var report in reports) - { - var reportAnalysis = new WERAnalysisReport(report); - - _werAnalysisReports.Add(reportAnalysis); - reportsToAnalyze.Add(reportAnalysis); - - // When the crash dump path changes, we'll want to perform analysis on it. - report.PropertyChanged += (sender, e) => - { - if (e.PropertyName == nameof(WERReport.CrashDumpPath)) - { - RunToolAnalysis(reportAnalysis, RegisteredAnalysisTools.ToList()); - } - }; - } - - List tools = RegisteredAnalysisTools.ToList(); - foreach (var reportAnalysis in reportsToAnalyze) - { - RunToolAnalysis(reportAnalysis, tools); - } - } - - private void RunToolAnalysis(WERAnalysisReport report, List tools) - { - if (string.IsNullOrEmpty(report.Report.CrashDumpPath)) - { - // We need a crash dump to perform an analysis - return; - } - - foreach (Tool tool in tools) - { - AnalysisRequest request = new() - { - Report = report, - Tool = tool, - }; - - // Queue the request that will be processed on a separate thread - _analysisRequests.Add(request); - } - } - - public void Dispose() - { - _analysisRequests.CompleteAdding(); - _analysisRequests.Dispose(); - GC.SuppressFinalize(this); - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/WERHelper.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/WERHelper.cs deleted file mode 100644 index 57ac2f32d..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/WERHelper.cs +++ /dev/null @@ -1,438 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.ComponentModel; -using System.Diagnostics; -using System.Diagnostics.Eventing.Reader; -using System.Globalization; -using System.IO; -using System.Threading; -using DevHome.DevDiagnostics.Helpers; -using Microsoft.Win32; -using Serilog; - -namespace DevHome.DevDiagnostics.Models; - -/* - * This class is responsible for monitoring the system for WER reports. These reports are generated when an application crashes. - * Additionally it can be used to enable/disable local WER collection for a specific app. To learn more about local WER collection, - * check out https://learn.microsoft.com/windows/win32/wer/collecting-user-mode-dumps - * - * We learn about WER events from either events in the Application event log or from crash dump files on disk. - */ - -internal sealed class WERHelper : IDisposable -{ - private const string WERSubmissionQuery = "(*[System[Provider[@Name=\"Application Error\"]]] and *[System[EventID=1000]])"; - private const string WERReceiveQuery = "(*[System[Provider[@Name=\"Application Error\"]]] and *[System[EventID=1001]])"; - private const string DefaultDumpPath = "%LOCALAPPDATA%\\CrashDumps"; - - private static readonly ILogger _log = Log.ForContext("SourceContext", nameof(WERHelper)); - - private readonly Microsoft.UI.Dispatching.DispatcherQueue _dispatcher; - private readonly EventLogWatcher _eventLogWatcher; - private readonly List _filesystemWatchers = []; - private readonly ObservableCollection _werReports = []; - - private List _werLocations = []; - private bool _isRunning; - - public ReadOnlyObservableCollection WERReports { get; private set; } - - public WERHelper() - { - _dispatcher = Microsoft.UI.Dispatching.DispatcherQueue.GetForCurrentThread(); - - WERReports = new(_werReports); - - // Subscribe for Application events matching the processName. - EventLogQuery subscriptionQuery = new EventLogQuery("Application", PathType.LogName, WERSubmissionQuery); - _eventLogWatcher = new EventLogWatcher(subscriptionQuery); - _eventLogWatcher.EventRecordWritten += new EventHandler(EventLogEventRead); - } - - public void Start() - { - if (!_isRunning) - { - // We get WER events from both the EventLog and from crash dump files on disk. Spin off threads - // to look for existing crash dump files and existing event log events. - ThreadPool.QueueUserWorkItem((o) => - { - _werLocations = GetWERLocations(); - ReadLocalWERReports(); - EnableFileSystemWatchers(); - }); - - ThreadPool.QueueUserWorkItem((o) => - { - ReadWERReportsFromEventLog(); - }); - - _eventLogWatcher.Enabled = true; - - _isRunning = true; - } - } - - public void Stop() - { - if (_isRunning) - { - _eventLogWatcher.Enabled = false; - _isRunning = false; - DisableFileSystemWatchers(); - } - } - - public void Dispose() - { - _eventLogWatcher.Dispose(); - GC.SuppressFinalize(this); - } - - // Callback that fires when we have a new EventLog message - public void EventLogEventRead(object? obj, EventRecordWrittenEventArgs eventArg) - { - var eventRecord = eventArg.EventRecord; - if (eventRecord != null) - { - if (eventRecord.Id == 1000 && eventRecord.ProviderName.Equals("Application Error", StringComparison.OrdinalIgnoreCase)) - { - var filePath = eventRecord.Properties[10].Value.ToString() ?? string.Empty; - var timeGenerated = eventRecord.TimeCreated ?? DateTime.Now; - var moduleName = eventRecord.Properties[3].Value.ToString() ?? string.Empty; - var executable = eventRecord.Properties[0].Value.ToString() ?? string.Empty; - var eventGuid = eventRecord.Properties[12].Value.ToString() ?? string.Empty; - var description = eventRecord.FormatDescription(); - var pid = eventRecord.Properties[8].Value.ToString() ?? string.Empty; - - FindOrCreateWEREntryFromEventLog(filePath, timeGenerated, moduleName, executable, eventGuid, description, pid); - } - } - } - - private void ReadWERReportsFromEventLog() - { - var query = new EventLogQuery("Application", PathType.LogName, WERSubmissionQuery); - using var reader = new EventLogReader(query); - EventRecord? eventRecord; - while ((eventRecord = reader.ReadEvent()) is not null) - { - var filePath = eventRecord.Properties[10].Value.ToString() ?? string.Empty; - var timeGenerated = eventRecord.TimeCreated ?? DateTime.Now; - var moduleName = eventRecord.Properties[3].Value.ToString() ?? string.Empty; - var executable = eventRecord.Properties[0].Value.ToString() ?? string.Empty; - var eventGuid = eventRecord.Properties[12].Value.ToString() ?? string.Empty; - var description = eventRecord.FormatDescription(); - var pid = eventRecord.Properties[8].Value.ToString() ?? string.Empty; - - FindOrCreateWEREntryFromEventLog(filePath, timeGenerated, moduleName, executable, eventGuid, description, pid); - } - } - - private void FindOrCreateWEREntryFromEventLog(string filepath, DateTime timeGenerated, string moduleName, string executable, string eventGuid, string description, string processId) - { - int? pid = CommonHelper.ParseStringToInt(processId); - - // When adding/updating a report, we need to do it on the dispatcher thread - _dispatcher.TryEnqueue(() => - { - // Do we have an entry for this item already (created from the WER files on disk) - var werReport = FindMatchingReport(timeGenerated, executable, pid); - - var createdReport = false; - - if (werReport is null) - { - werReport = new WERReport(); - createdReport = true; - werReport.TimeStamp = timeGenerated; - werReport.Executable = executable; - werReport.Pid = pid ?? 0; - } - - // Populate the report - werReport.FilePath = filepath; - werReport.Module = moduleName; - werReport.EventGuid = eventGuid; - werReport.Description = description; - werReport.FailureBucket = GenerateFailureBucketFromEventLogDescription(description); - - // Don't add the report until it's fully populated so we have as much information as possible for our listeners - if (createdReport) - { - _werReports.Add(werReport); - } - }); - } - - private void FindOrCreateWEREntryFromLocalDumpFile(string crashDumpFile) - { - var timeGenerated = File.GetCreationTime(crashDumpFile); - FileInfo dumpFileInfo = new(crashDumpFile); - - Debug.Assert(dumpFileInfo.Exists, "Why doesn't this file exist?"); - - // Only look at .dmp files - if (dumpFileInfo.Extension != ".dmp") - { - return; - } - - // The crashdumpFilename has a format of - // executable.pid.dmp - // so it could be - // a.exe.40912.dmp - // but also - // a.b.exe.40912.dmp - // Parse the filename starting from the back - - // Find the last dot index - var dmpExtensionIndex = dumpFileInfo.Name.LastIndexOf('.'); - if (dmpExtensionIndex == -1) - { - _log.Information("Unexpected crash dump filename: " + dumpFileInfo.Name); - return; - } - - // Remove the .dmp. This should give us a string like a.b.exe.40912 - var filenameWithNoDmp = dumpFileInfo.Name.Substring(0, dmpExtensionIndex); - - // Find the PID - var pidIndex = filenameWithNoDmp.LastIndexOf('.'); - if (pidIndex == -1) - { - _log.Information("Unexpected crash dump filename: " + crashDumpFile); - return; - } - - var processID = filenameWithNoDmp.Substring(pidIndex + 1); - - // Now peel off the PID. This should give us a.b.exe - var executableFullPath = filenameWithNoDmp.Substring(0, pidIndex); - - FileInfo fileInfo = new(executableFullPath); - - string description = string.Empty; - - if (dumpFileInfo.Exists) - { - description = string.Format(CultureInfo.CurrentCulture, CommonHelper.GetLocalizedString("WERBasicInfo"), dumpFileInfo.Length, dumpFileInfo.CreationTime); - } - - var converter = new Int32Converter(); - var pid = (int?)converter.ConvertFromString(processID); - - _dispatcher.TryEnqueue(() => - { - // Do we have an entry for this item already (created from the event log entry) - var werReport = FindMatchingReport(timeGenerated, fileInfo.Name, pid); - - var createdReport = false; - - if (werReport is null) - { - werReport = new WERReport(); - createdReport = true; - werReport.TimeStamp = timeGenerated; - werReport.Executable = fileInfo.Name; - werReport.Pid = pid ?? 0; - werReport.Description = description; - } - - // Populate the report - werReport.CrashDumpPath = crashDumpFile; - - // Don't add the report until it's fully populated so we have as much information as possible for our listeners - if (createdReport) - { - _werReports.Add(werReport); - } - }); - - return; - } - - private WERReport? FindMatchingReport(DateTime timestamp, string executable, int? pid) - { - Debug.Assert(_dispatcher.HasThreadAccess, "This method should only be called on the dispatcher thread"); - Debug.Assert(timestamp.Kind == DateTimeKind.Local, "TimeGenerated should be in local time"); - var timestampIndex = timestamp.Ticks; - - // It's a match if the timestamp is within 2 minute of the event log entry - var ticksWindow = new TimeSpan(0, 2, 0).Ticks; - - WERReport? werReport = null; - - // See if we can find a matching entry in the list - foreach (var report in _werReports) - { - if (report.Executable.Equals(executable, StringComparison.OrdinalIgnoreCase) && report.Pid == pid) - { - // See if the timestamps are "close enough" - Debug.Assert(report.TimeStamp.Kind == DateTimeKind.Local, "TimeGenerated should be in local time"); - var ticksDiff = Math.Abs(report.TimeStamp.Ticks - timestampIndex); - - if (ticksDiff < ticksWindow) - { - werReport = report; - break; - } - } - } - - return werReport; - } - - private string GenerateFailureBucketFromEventLogDescription(string description) - { - /* The description can look like this - - Faulting application name: DevHome.Diagnostics.exe, version: 1.0.0.0, time stamp: 0x66470000 - Faulting module name: KERNELBASE.dll, version: 10.0.22621.3810, time stamp: 0x10210ca8 - Exception code: 0xe0434352 - Fault offset: 0x000000000005f20c - Faulting process id: 0x0xa078 - Faulting application start time: 0x0x1dad175bd05dea9 - Faulting application path: E:\devhome\src\bin\x64\Debug\net8.0-windows10.0.22621.0\AppX\DevHome.Diagnostics.exe - Faulting module path: C:\WINDOWS\System32\KERNELBASE.dll - Report Id: 7a4cd0a8-f65b-4f27-b250-cc5bd57e39d6 - Faulting package full name: Microsoft.Windows.DevHome.Dev_0.0.0.0_x64__8wekyb3d8bbwe - Faulting package-relative application ID: DevHome.Diagnostics - - Let's create a placeholder failure bucket based on the module name, offset, and exception code. In the above example, - we'll generate a bucket "KERNELBASE.dll+0x000000000005f20c 0xe0434352" - */ - - var lines = description.Split('\n', StringSplitOptions.RemoveEmptyEntries); - string? moduleName = null; - string? exceptionCode = null; - string? faultOffset = null; - - foreach (var line in lines) - { - if (line.Contains("Fault offset:")) - { - faultOffset = line.Substring(line.IndexOf(':') + 1).Trim(); - } - else if (line.Contains("Exception code:")) - { - exceptionCode = line.Substring(line.IndexOf(':') + 1).Trim(); - } - else if (line.Contains("Faulting module name:")) - { - var startIndex = line.IndexOf(':') + 1; - var endIndex = line.IndexOf(',') - 1; - - moduleName = line.Substring(startIndex, endIndex - startIndex + 1).Trim(); - } - } - - if (moduleName is not null && exceptionCode is not null && faultOffset is not null) - { - return $"{moduleName}+{faultOffset} {exceptionCode}"; - } - - return string.Empty; - } - - private void ReadLocalWERReports() - { - foreach (var dumpLocation in _werLocations) - { - try - { - // Enumerate all of the existing dump files in this location - foreach (var dumpFile in Directory.EnumerateFiles(dumpLocation, "*.dmp")) - { - FindOrCreateWEREntryFromLocalDumpFile(dumpFile); - } - } - catch - { - _log.Error("Error enumerating directory " + dumpLocation); - } - } - } - - // Generate a list of all of the locations on disk where local WER dumps are stored - private List GetWERLocations() - { - var list = new List(); - - var key = Registry.LocalMachine.OpenSubKey(WERUtils.LocalWERRegistryKey, false); - - if (key is not null) - { - var globaldumppath = GetDumpPath(key); - - Debug.Assert(globaldumppath is not null, "Global dump path is not set"); - list.Add(globaldumppath); - - var subKeys = key.GetSubKeyNames(); - foreach (var subkey in subKeys) - { - var dumpPath = GetDumpPath(key.OpenSubKey(subkey)); - - if (dumpPath is not null) - { - // If this item isn't in the list, add it. - if (!list.Contains(dumpPath)) - { - list.Add(dumpPath); - } - } - } - } - - return list; - } - - private string? GetDumpPath(RegistryKey? key) - { - if (key is not null) - { - if (key.GetValue("DumpFolder") is not string dumpFolder) - { - // If a dumppath isn't explicitly set, then use the system's default dump path - dumpFolder = DefaultDumpPath; - } - - return Environment.ExpandEnvironmentVariables(dumpFolder); - } - - return null; - } - - // Enable watchers to catch new WER dumps as they are generated - private void EnableFileSystemWatchers() - { - _filesystemWatchers.Clear(); - - foreach (var path in _werLocations) - { - // If this directory exists, monitor it for new files - if (Directory.Exists(path)) - { - var watcher = new FileSystemWatcher(path); - watcher.Created += (sender, e) => - { - _log.Information($"New dump file: {e.FullPath}"); - FindOrCreateWEREntryFromLocalDumpFile(e.FullPath); - }; - - watcher.EnableRaisingEvents = true; - _filesystemWatchers.Add(watcher); - } - } - } - - private void DisableFileSystemWatchers() - { - _filesystemWatchers.Clear(); - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/WERReport.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/WERReport.cs deleted file mode 100644 index f131e9e65..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/WERReport.cs +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.ComponentModel; -using System.Globalization; -using System.Runtime.CompilerServices; -using CommunityToolkit.Mvvm.ComponentModel; - -namespace DevHome.DevDiagnostics.Models; - -public partial class WERReport : ObservableObject -{ - [ObservableProperty] - private DateTime _timeStamp; - - public string TimeGenerated => TimeStamp.ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.CurrentCulture); - - [ObservableProperty] - private string _filePath = string.Empty; - - [ObservableProperty] - private string _module = string.Empty; - - [ObservableProperty] - private string _executable = string.Empty; - - [ObservableProperty] - private string _eventGuid = string.Empty; - - [ObservableProperty] - private string _description = string.Empty; - - [ObservableProperty] - private int _pid = 0; - - [ObservableProperty] - private string _crashDumpPath = string.Empty; - - [ObservableProperty] - private string _failureBucket = string.Empty; - - public WERReport() - { - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/WinLogsEntry.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/WinLogsEntry.cs deleted file mode 100644 index ac7473553..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Models/WinLogsEntry.cs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Globalization; -using DevHome.DevDiagnostics.Helpers; -using Microsoft.UI; -using Microsoft.UI.Xaml.Media; - -namespace DevHome.DevDiagnostics.Models; - -public class WinLogsEntry -{ - public WinLogsEntry(DateTime? time, WinLogCategory category, string message, string toolName) - { - TimeGenerated = time ?? DateTime.Now; - Category = category; - Message = message; - Tool = toolName; - SelectedText = message; - } - - public WinLogCategory Category { get; } - - public DateTime TimeGenerated { get; } - - public string TimeGeneratedString => TimeGenerated.ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.CurrentCulture); - - public string Tool { get; } - - public string Message { get; } - - public string SelectedText { get; set; } -} - -public enum WinLogCategory -{ - Information = 0, - Error, - Warning, - Debug, -} - -public enum WinLogsTool -{ - Unknown = 0, - ETWLogs, - DebugOutput, - EventViewer, - WER, -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/NativeMethods.json b/tools/DevDiagnostics/DevHome.DevDiagnostics/NativeMethods.json deleted file mode 100644 index 1175df48b..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/NativeMethods.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$schema": "https://aka.ms/CsWin32.schema.json", - "wideCharOnly": true -} \ No newline at end of file diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/NativeMethods.txt b/tools/DevDiagnostics/DevHome.DevDiagnostics/NativeMethods.txt deleted file mode 100644 index c0ddfcf60..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/NativeMethods.txt +++ /dev/null @@ -1,121 +0,0 @@ -AddClipboardFormatListener -CallWindowProc -CloseClipboard -CoCreateInstance -CombineRgn -CreateEllipticRgn -CreateRectRgn -CreateRoundRectRgn -DefSubclassProc -DwmGetWindowAttribute -DwmSetWindowAttribute -DwmSetWindowAttribute -EnumChildWindows -EnumThreadWindows -EnumWindows -GetAncestor -GetBinaryType -GetClassLong -GetClassName -GetClipboardData -GetCurrentPackageFullName -GetCursorPos -GetDesktopWindow -GetForegroundWindow -GetMonitorInfo -GetMonitorInfo -GetOpenFileName -GetParent -GetProcessInformation -GetScaleFactorForMonitor -GetTopWindow -GetWindowInfo -GetWindowLong -GetWindowRect -GetWindowText -GetWindowText -GetWindowTextLength -GetWindowTextLength -GetWindowThreadProcessId -GlobalAddAtom -GlobalDeleteAtom -GlobalLock -GlobalUnlock -IsIconic -IsImmersiveProcess -IsWindow -IsWindowArranged -IsWindowVisible -IsWow64Process2 -IsZoomed -LoadIcon -LoadImage -MessageBox -MonitorFromWindow -MoveWindow -NtQueryInformationProcess -OpenClipboard -OpenProcessToken -RegisterHotKey -RemoveClipboardFormatListener -RmRegisterResources -RmStartSession -RmGetList -RmEndSession -SendMessage -SetFocus -SetForegroundWindow -SetParent -SetWindowLong -SetWindowLong -SetWindowPos -SetWindowRgn -SetWindowSubclass -SetWinEventHook -ShowWindow -SystemParametersInfo -UnhookWinEvent -UnregisterHotKey -WaitForSingleObject -WindowFromPoint -CF_* -DEVICE_SCALE_FACTOR -DWMWA_* -DWMWINDOWATTRIBUTE -EVENT_* -EVENT_OBJECT_DESTROY -EVENT_OBJECT_LOCATIONCHANGE -EVENT_SYSTEM_FOREGROUND -GET_ANCESTOR_FLAGS -GET_CLASS_LONG_INDEX -HMONITOR -HWND_* -ICON_* -ICON_* -ICON_* -IDI_* -IMAGE_* -INVALID_HANDLE_VALUE -LR_* -MOD_* -// MONITOR_DEFAULTTONEAREST -PROCESS_BASIC_INFORMATION -PROCESS_INFORMATION_CLASS -PROCESS_MACHINE_INFORMATION -RM_APP_TYPE -RM_UNIQUE_PROCESS -RM_PROCESS_INFO -RM_REBOOT_REASON -SECTION_FLAGS -SUBCLASSPROC -SW_* -VIRTUAL_KEY -WIN32_ERROR -WINEVENT_* -WINEVENT_OUTOFCONTEXT -WINEVENT_SKIPOWNPROCESS -WINDOWPOS -WM_* -WS_* -GetProcessImageFileName -MAX_PATH diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/AboutPage.xaml b/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/AboutPage.xaml deleted file mode 100644 index bd87b1f75..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/AboutPage.xaml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/AboutPage.xaml.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/AboutPage.xaml.cs deleted file mode 100644 index 3db304a96..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/AboutPage.xaml.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using DevHome.Common.Extensions; -using DevHome.DevDiagnostics.ViewModels; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; - -namespace DevHome.DevDiagnostics.Pages; - -public sealed partial class AboutPage : Page -{ - public AboutViewModel ViewModel { get; } - - public AboutPage() - { - ViewModel = Application.Current.GetService(); - InitializeComponent(); - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/AdditionalToolsPage.xaml b/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/AdditionalToolsPage.xaml deleted file mode 100644 index ebf5b2360..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/AdditionalToolsPage.xaml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/AdditionalToolsPage.xaml.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/AdditionalToolsPage.xaml.cs deleted file mode 100644 index c951b01f7..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/AdditionalToolsPage.xaml.cs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using DevHome.Common.Extensions; -using DevHome.DevDiagnostics.ViewModels; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; - -namespace DevHome.DevDiagnostics.Pages; - -public sealed partial class AdditionalToolsPage : Page -{ - public AdditionalToolsViewModel ViewModel { get; } - - public AdditionalToolsPage() - { - ViewModel = Application.Current.GetService(); - InitializeComponent(); - } - - private void SettingsAddToolCard_Expanded(object sender, System.EventArgs e) - { - AddToolPanel.RefreshAppList(); - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/AdvancedSettingsPage.xaml b/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/AdvancedSettingsPage.xaml deleted file mode 100644 index aec0de71f..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/AdvancedSettingsPage.xaml +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/AppDetailsPage.xaml.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/AppDetailsPage.xaml.cs deleted file mode 100644 index b9f4943fc..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/AppDetailsPage.xaml.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using DevHome.Common.Extensions; -using DevHome.DevDiagnostics.Telemetry; -using DevHome.DevDiagnostics.ViewModels; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Navigation; - -namespace DevHome.DevDiagnostics.Pages; - -public partial class AppDetailsPage : Page -{ - private AppDetailsPageViewModel ViewModel { get; } - - public AppDetailsPage() - { - ViewModel = Application.Current.GetService(); - InitializeComponent(); - } - - protected override void OnNavigatedTo(NavigationEventArgs e) - { - base.OnNavigatedTo(e); - Application.Current.GetService().SwitchTo(Feature.AppDetails); - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/InsightsPage.xaml b/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/InsightsPage.xaml deleted file mode 100644 index e6e85ba97..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/InsightsPage.xaml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/InsightsPage.xaml.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/InsightsPage.xaml.cs deleted file mode 100644 index 238fd34e2..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/InsightsPage.xaml.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using DevHome.Common.Extensions; -using DevHome.DevDiagnostics.Telemetry; -using DevHome.DevDiagnostics.ViewModels; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Navigation; - -namespace DevHome.DevDiagnostics.Pages; - -public sealed partial class InsightsPage : Page -{ - private InsightsPageViewModel ViewModel { get; } - - public InsightsPage() - { - ViewModel = Application.Current.GetService(); - InitializeComponent(); - } - - protected override void OnNavigatedTo(NavigationEventArgs e) - { - base.OnNavigatedTo(e); - Application.Current.GetService().SwitchTo(Feature.Insights); - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/ModulesPage.xaml b/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/ModulesPage.xaml deleted file mode 100644 index 4a990a045..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/ModulesPage.xaml +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/ModulesPage.xaml.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/ModulesPage.xaml.cs deleted file mode 100644 index c2801b0e1..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/ModulesPage.xaml.cs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using DevHome.Common.Extensions; -using DevHome.DevDiagnostics.Telemetry; -using DevHome.DevDiagnostics.ViewModels; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Input; -using Microsoft.UI.Xaml.Navigation; - -namespace DevHome.DevDiagnostics.Pages; - -public sealed partial class ModulesPage : Page -{ - private ModulesPageViewModel ViewModel { get; } - - public ModulesPage() - { - ViewModel = Application.Current.GetService(); - InitializeComponent(); - } - - protected override void OnNavigatedTo(NavigationEventArgs e) - { - base.OnNavigatedTo(e); - Application.Current.GetService().SwitchTo(Feature.LoadedModule); - } - - private void GridSplitter_PointerPressed(object sender, PointerRoutedEventArgs e) - { - e.Handled = true; - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/PreferencesPage.xaml b/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/PreferencesPage.xaml deleted file mode 100644 index 17d178246..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/PreferencesPage.xaml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/PreferencesPage.xaml.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/PreferencesPage.xaml.cs deleted file mode 100644 index bb033b39b..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/PreferencesPage.xaml.cs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using DevHome.Common.Extensions; -using DevHome.DevDiagnostics.ViewModels; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; - -namespace DevHome.DevDiagnostics.Pages; - -public sealed partial class PreferencesPage : Page -{ - public PreferencesViewModel ViewModel { get; } - - public PreferencesPage() - { - ViewModel = Application.Current.GetService(); - InitializeComponent(); - } - - private void Page_Loaded(object sender, RoutedEventArgs e) - { - var selectedTheme = ViewModel.ElementTheme; - foreach (var item in ThemeSelectionComboBox.Items) - { - var comboItem = item as ComboBoxItem; - if (comboItem?.Tag is ElementTheme tag && tag == selectedTheme) - { - ThemeSelectionComboBox.SelectedValue = item; - break; - } - } - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/ProcessListPage.xaml b/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/ProcessListPage.xaml deleted file mode 100644 index a14b6212d..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/ProcessListPage.xaml +++ /dev/null @@ -1,84 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/ProcessListPage.xaml.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/ProcessListPage.xaml.cs deleted file mode 100644 index 00fdb2374..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/ProcessListPage.xaml.cs +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using DevHome.Common.Extensions; -using DevHome.DevDiagnostics.Telemetry; -using DevHome.DevDiagnostics.ViewModels; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Navigation; - -namespace DevHome.DevDiagnostics.Pages; - -public sealed partial class ProcessListPage : Page -{ - private ProcessListPageViewModel ViewModel { get; } - - public ProcessListPage() - { - ViewModel = Application.Current.GetService(); - InitializeComponent(); - } - - protected override void OnNavigatedTo(NavigationEventArgs e) - { - base.OnNavigatedTo(e); - ViewModel.ResetPage(); - Application.Current.GetService().SwitchTo(Feature.ProcessList); - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/ResourceUsagePage.xaml b/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/ResourceUsagePage.xaml deleted file mode 100644 index 0c9f0a184..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/ResourceUsagePage.xaml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/ResourceUsagePage.xaml.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/ResourceUsagePage.xaml.cs deleted file mode 100644 index dff5679f5..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/ResourceUsagePage.xaml.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using DevHome.Common.Extensions; -using DevHome.DevDiagnostics.Telemetry; -using DevHome.DevDiagnostics.ViewModels; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Navigation; - -namespace DevHome.DevDiagnostics.Pages; - -public sealed partial class ResourceUsagePage : Page, IDisposable -{ - private ResourceUsagePageViewModel ViewModel { get; } - - public ResourceUsagePage() - { - ViewModel = Application.Current.GetService(); - InitializeComponent(); - } - - protected override void OnNavigatedTo(NavigationEventArgs e) - { - base.OnNavigatedTo(e); - Application.Current.GetService().SwitchTo(Feature.ResourceUsage); - } - - public void Dispose() - { - ViewModel.Dispose(); - GC.SuppressFinalize(this); - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/SettingsPage.xaml b/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/SettingsPage.xaml deleted file mode 100644 index 8ca2a7707..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/SettingsPage.xaml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/SettingsPage.xaml.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/SettingsPage.xaml.cs deleted file mode 100644 index d333b94d6..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/SettingsPage.xaml.cs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using DevHome.DevDiagnostics.ViewModels; -using Microsoft.UI.Xaml.Controls; - -namespace DevHome.DevDiagnostics.Pages; - -public sealed partial class SettingsPage : Page -{ - public SettingsPageViewModel ViewModel { get; } - - public SettingsPage() - { - ViewModel = new SettingsPageViewModel(); - InitializeComponent(); - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/WERPage.xaml b/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/WERPage.xaml deleted file mode 100644 index 99db2a5dc..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/WERPage.xaml +++ /dev/null @@ -1,100 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/WERPage.xaml.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/WERPage.xaml.cs deleted file mode 100644 index 9e15a26c0..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/WERPage.xaml.cs +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Collections.Specialized; -using System.Diagnostics; -using System.Linq; -using CommunityToolkit.WinUI.UI.Controls; -using DevHome.Common.Extensions; -using DevHome.DevDiagnostics.Helpers; -using DevHome.DevDiagnostics.Models; -using DevHome.DevDiagnostics.Telemetry; -using DevHome.DevDiagnostics.ViewModels; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Navigation; - -namespace DevHome.DevDiagnostics.Pages; - -public sealed partial class WERPage : Page -{ - private readonly string _bucketUsingThisToolString = CommonHelper.GetLocalizedString("BucketUsingThisToolString"); - - private WERPageViewModel ViewModel { get; } - - public WERPage() - { - ViewModel = Application.Current.GetService(); - InitializeComponent(); - - // Populate selector items for each WER analyizer registered with the system - foreach (Tool tool in ViewModel.RegisteredAnalysisTools) - { - InfoSelector.Items.Add(CreateSelectorBarItemForDebugAnalyzer(tool)); - } - - ((INotifyCollectionChanged)ViewModel.RegisteredAnalysisTools).CollectionChanged += RegisteredAnalysisTools_CollectionChanged; - } - - private void RegisteredAnalysisTools_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) - { - // If we have a new tool, add a new selector item for it - if (e.Action == NotifyCollectionChangedAction.Add && e.NewItems is not null) - { - foreach (Tool tool in e.NewItems) - { - InfoSelector.Items.Add(CreateSelectorBarItemForDebugAnalyzer(tool)); - } - } - - // Or if we removed a tool, remove the selector item for it - else if (e.Action == NotifyCollectionChangedAction.Remove && e.OldItems is not null) - { - foreach (Tool tool in e.OldItems) - { - foreach (var item in InfoSelector.Items.Where(x => x.Tag == tool)) - { - InfoSelector.Items.Remove(item); - break; - } - } - } - } - - private SelectorBarItem CreateSelectorBarItemForDebugAnalyzer(Tool tool) - { - SelectorBarItem selectorBarItem = new() - { - Text = tool.Name, - Tag = tool, - }; - - MenuFlyout menuFlyout = new(); - MenuFlyoutItem item = new() - { - Text = _bucketUsingThisToolString, - Tag = tool, - }; - item.Click += (sender, e) => - { - ViewModel.SetBucketingTool(tool); - }; - menuFlyout.Items.Add(item); - - selectorBarItem.ContextFlyout = menuFlyout; - return selectorBarItem; - } - - protected override void OnNavigatedTo(NavigationEventArgs e) - { - base.OnNavigatedTo(e); - Application.Current.GetService().SwitchTo(Feature.WERReports); - } - - private void SelectorBar_SelectionChanged(SelectorBar sender, SelectorBarSelectionChangedEventArgs args) - { - UpdateInfoBox(); - } - - private void WERDataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e) - { - UpdateInfoBox(); - } - - private void UpdateInfoBox() - { - if (WERDataGrid.SelectedItem is null) - { - WERInfo.Text = string.Empty; - return; - } - - SelectorBarItem selectedItem = InfoSelector.SelectedItem; - int currentSelectedIndex = InfoSelector.Items.IndexOf(selectedItem); - WERAnalysisReport info = (WERAnalysisReport)WERDataGrid.SelectedItem; - - if (selectedItem is not null && selectedItem.Tag is Tool tool) - { - if (info.ToolAnalyses.TryGetValue(tool, out var analysis)) - { - WERInfo.Text = analysis.Analysis; - } - else - { - WERInfo.Text = CommonHelper.GetLocalizedString("WERAnalysisUnavailable"); - } - } - else - { - Debug.Assert(currentSelectedIndex == 0 || currentSelectedIndex == -1, "Expected only the first item would have a null tag"); - WERInfo.Text = info.Report.Description; - } - } - - private void HyperlinkButton_Click(object sender, RoutedEventArgs e) - { - HyperlinkButton? hyperlinkButton = sender as HyperlinkButton; - Debug.Assert(hyperlinkButton is not null, "Who called HyperlinkButton_Click that wasn't a hyperlink button?"); - - WERAnalysisReport? info = hyperlinkButton.Tag as WERAnalysisReport; - Debug.Assert(info is not null, "This object should have a Tag with a WERDisplayInfo"); - - ViewModel.OpenCab(info.Report.CrashDumpPath); - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/WinLogsPage.xaml b/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/WinLogsPage.xaml deleted file mode 100644 index 00698560c..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/WinLogsPage.xaml +++ /dev/null @@ -1,117 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/WinLogsPage.xaml.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/WinLogsPage.xaml.cs deleted file mode 100644 index 4229ee360..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Pages/WinLogsPage.xaml.cs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Collections.ObjectModel; -using System.Linq; -using DevHome.Common.Extensions; -using DevHome.DevDiagnostics.Models; -using DevHome.DevDiagnostics.Telemetry; -using DevHome.DevDiagnostics.ViewModels; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Navigation; - -namespace DevHome.DevDiagnostics.Pages; - -public partial class WinLogsPage : Page, IDisposable -{ - public WinLogsPageViewModel ViewModel { get; } - - public WinLogsPage() - { - ViewModel = Application.Current.GetService(); - InitializeComponent(); - DataContext = this; - } - - protected override void OnNavigatedTo(NavigationEventArgs e) - { - base.OnNavigatedTo(e); - Application.Current.GetService().SwitchTo(Feature.WinLogs); - } - - public void Dispose() - { - ViewModel.Dispose(); - GC.SuppressFinalize(this); - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Program.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Program.cs deleted file mode 100644 index f8bd1b44c..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Program.cs +++ /dev/null @@ -1,251 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Diagnostics; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Text.RegularExpressions; -using System.Threading; -using System.Threading.Tasks; -using DevHome.Common.Extensions; -using DevHome.Common.Helpers; -using DevHome.DevDiagnostics.Helpers; -using DevHome.DevDiagnostics.Models; -using DevHome.Service; -using Microsoft.Extensions.Configuration; -using Microsoft.UI.Dispatching; -using Microsoft.UI.Xaml; -using Microsoft.Windows.AppLifecycle; -using Serilog; -using Windows.ApplicationModel.Activation; -using WinRT; - -namespace DevHome.DevDiagnostics; - -public static class Program -{ - private static App? _app; - private static bool _firstActivation = true; - - [global::System.Runtime.InteropServices.DllImport("Microsoft.ui.xaml.dll")] - [global::System.Runtime.InteropServices.DefaultDllImportSearchPaths(global::System.Runtime.InteropServices.DllImportSearchPath.SafeDirectories)] - private static extern void XamlCheckProcessRequirements(); - - private const string MainInstanceKey = "mainInstance"; - - private const string ElevatedInstanceKey = "elevatedInstance"; - - [STAThread] - public static void Main(string[] args) - { - // Set up Logging - Environment.SetEnvironmentVariable("DEVHOME_LOGS_ROOT", Path.Join(Common.Logging.LogFolderRoot, "DevHome.DevDiagnostics")); - var configuration = new ConfigurationBuilder() - .AddJsonFile("appsettings_dd.json") - .Build(); - Log.Logger = new LoggerConfiguration() - .ReadFrom.Configuration(configuration) - .CreateLogger(); - - var stopEvent = new EventWaitHandle(false, EventResetMode.ManualReset, $"DevHomeDD-{Environment.ProcessId}"); - ThreadPool.QueueUserWorkItem((o) => - { - var waitResult = stopEvent.WaitOne(); - - _app?.UIDispatcher?.TryEnqueue(() => - { - var primaryWindow = Application.Current.GetService(); - primaryWindow.Close(); - }); - }); - - try - { - XamlCheckProcessRequirements(); - - WinRT.ComWrappersSupport.InitializeComWrappers(); - - var isRedirect = DecideRedirection().GetAwaiter().GetResult(); - - if (!isRedirect) - { - Log.Information("Starting application"); - Application.Start((p) => - { - var dispatcherQueue = DispatcherQueue.GetForCurrentThread(); - var context = new DispatcherQueueSynchronizationContext(dispatcherQueue); - SynchronizationContext.SetSynchronizationContext(context); - _app = new App(); - OnActivated(null, AppInstance.GetCurrent().GetActivatedEventArgs()); - }); - } - - stopEvent.Close(); - stopEvent.Dispose(); - } - catch (Exception ex) - { - Log.Fatal(ex, "Application start-up failed"); - } - finally - { - Log.CloseAndFlush(); - } - } - - private static async Task DecideRedirection() - { - var activatedEventArgs = AppInstance.GetCurrent().GetActivatedEventArgs(); - var isElevatedInstancePresent = false; - var isUnElevatedInstancePresent = false; - var instanceList = AppInstance.GetInstances(); - foreach (var appInstance in instanceList) - { - if (appInstance.Key.Equals(MainInstanceKey, StringComparison.OrdinalIgnoreCase)) - { - isUnElevatedInstancePresent = true; - } - else if (appInstance.Key.Equals(ElevatedInstanceKey, StringComparison.OrdinalIgnoreCase)) - { - isElevatedInstancePresent = true; - } - } - - AppInstance instance; - if (isElevatedInstancePresent) - { - // Redirect to the elevated instance if present. - instance = AppInstance.FindOrRegisterForKey(ElevatedInstanceKey); - } - else if (RuntimeHelper.IsCurrentProcessRunningAsAdmin()) - { - // Wait for unelevated instance to exit - while (isUnElevatedInstancePresent) - { - isUnElevatedInstancePresent = false; - instanceList = AppInstance.GetInstances(); - foreach (var appInstance in instanceList) - { - if (appInstance.Key.Equals(MainInstanceKey, StringComparison.OrdinalIgnoreCase)) - { - isUnElevatedInstancePresent = true; - var stopAppInstance = new EventWaitHandle(false, EventResetMode.ManualReset, $"DevHomeDD-{appInstance.ProcessId}"); - stopAppInstance.Set(); - } - } - } - - // Register the elevated instance key - instance = AppInstance.FindOrRegisterForKey(ElevatedInstanceKey); - } - else - { - instance = AppInstance.FindOrRegisterForKey(MainInstanceKey); - } - - var isRedirect = false; - if (instance.IsCurrent) - { - instance.Activated += OnActivated; - } - else - { - // Redirect the activation (and args) to the registered instance, and exit. - await instance.RedirectActivationToAsync(activatedEventArgs); - isRedirect = true; - } - - return isRedirect; - } - - private static void OnActivated(object? sender, Microsoft.Windows.AppLifecycle.AppActivationArguments e) - { - var wasFirstActivation = _firstActivation; - _firstActivation = false; - var commandLine = string.Empty; - if (e.Kind == Microsoft.Windows.AppLifecycle.ExtendedActivationKind.Launch) - { - commandLine = e.Data.As().Arguments; - } - else if (e.Kind == Microsoft.Windows.AppLifecycle.ExtendedActivationKind.StartupTask) - { - // Start the app in the background to handle the startup task and register the hotkey - if (wasFirstActivation && !App.IsFeatureEnabled()) - { - // Exit the process if PI Expermental feature is not enabled and its the first activation in the process - Log.Information("Experimental feature is not enabled. Exiting the process."); - Process.GetCurrentProcess().Kill(false); - } - - // Don't show the bar window for startup task activations. - return; - } - - // Convert commandLine into a string array. We just can't split based just on spaces, in case there are spaces inclosed in quotes - // i.e. --application "My App" - var commandLineArgs = Regex.Matches(commandLine, @"[\""].+?[\""]|[^ ]+").Select(m => m.Value).ToArray(); - - // TODO: This should be replaced with system.commandline Microsoft.Extensions.Configuration - // is not intended to be a general purpose commandline parser, but rather only supports /key=value or /key value pairs - var builder = new ConfigurationBuilder(); - builder.AddCommandLine(commandLineArgs); - var config = builder.Build(); - - Process? targetProcess = null; - var targetApp = config["application"]; - var targetPid = config["pid"]; - var pageToExpand = config["expandWindow"]; - - try - { - if (targetApp != null) - { - Debug.Assert(targetApp != string.Empty, "Why is appname empty?"); - - Process[] processes = Process.GetProcessesByName(targetApp); - if (processes.Length > 0) - { - targetProcess = processes[0]; - } - } - else if (targetPid != null) - { - var pid = int.Parse(targetPid, CultureInfo.CurrentCulture); - targetProcess = Process.GetProcessById(pid); - } - } - catch (Exception ex) - { - Log.Error(ex, "Failed to find target process {TargetApp} {TargetPid}", targetApp, targetPid); - } - - Debug.Assert(_app != null, "Why is _app null on a redirection?"); - - // Be sure to set the target app on the UI thread - _app?.UIDispatcher?.TryEnqueue(() => - { - if (targetProcess != null) - { - TargetAppData.Instance.SetNewAppData(targetProcess, Windows.Win32.Foundation.HWND.Null); - } - - // Show the bar window - var primaryWindow = Application.Current.GetService(); - primaryWindow.ShowBarWindow(); - - if (pageToExpand != null) - { - var barWindow = primaryWindow.DBarWindow; - Debug.Assert(barWindow is not null, "We show the bar window, so it cannot be null here"); - - var pageType = Type.GetType($"DevHome.DevDiagnostics.ViewModels.{pageToExpand}"); - if (pageType is not null) - { - barWindow.NavigateTo(pageType); - } - } - }); - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Properties/PublishProfiles/win-arm64.pubxml b/tools/DevDiagnostics/DevHome.DevDiagnostics/Properties/PublishProfiles/win-arm64.pubxml deleted file mode 100644 index 227cf8773..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Properties/PublishProfiles/win-arm64.pubxml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - FileSystem - arm64 - win-arm64 - true - False - False - True - True - - \ No newline at end of file diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Properties/PublishProfiles/win-x64.pubxml b/tools/DevDiagnostics/DevHome.DevDiagnostics/Properties/PublishProfiles/win-x64.pubxml deleted file mode 100644 index 19ae2a6b9..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Properties/PublishProfiles/win-x64.pubxml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - FileSystem - x64 - win-x64 - true - False - False - True - True - - \ No newline at end of file diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Properties/PublishProfiles/win-x86.pubxml b/tools/DevDiagnostics/DevHome.DevDiagnostics/Properties/PublishProfiles/win-x86.pubxml deleted file mode 100644 index dace1fa91..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Properties/PublishProfiles/win-x86.pubxml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - FileSystem - x86 - win-x86 - true - False - False - True - True - - \ No newline at end of file diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Properties/Settings.Designer.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Properties/Settings.Designer.cs deleted file mode 100644 index 8bed57117..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Properties/Settings.Designer.cs +++ /dev/null @@ -1,256 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace DevHome.DevDiagnostics.Properties { - - - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.11.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { - - private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default { - get { - return defaultInstance; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("False")] - public bool IsProcessFilterIncludeConHost { - get { - return ((bool)(this["IsProcessFilterIncludeConHost"])); - } - set { - this["IsProcessFilterIncludeConHost"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("False")] - public bool IsProcessFilterIncludeDllHost { - get { - return ((bool)(this["IsProcessFilterIncludeDllHost"])); - } - set { - this["IsProcessFilterIncludeDllHost"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("False")] - public bool IsProcessFilterIncludeSvcHost { - get { - return ((bool)(this["IsProcessFilterIncludeSvcHost"])); - } - set { - this["IsProcessFilterIncludeSvcHost"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("False")] - public bool IsProcessFilterIncludeEdge { - get { - return ((bool)(this["IsProcessFilterIncludeEdge"])); - } - set { - this["IsProcessFilterIncludeEdge"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("False")] - public bool IsProcessFilterIncludeWebview { - get { - return ((bool)(this["IsProcessFilterIncludeWebview"])); - } - set { - this["IsProcessFilterIncludeWebview"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("False")] - public bool IsProcessFilterIncludeRtb { - get { - return ((bool)(this["IsProcessFilterIncludeRtb"])); - } - set { - this["IsProcessFilterIncludeRtb"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("False")] - public bool IsProcessFilterIncludeWmi { - get { - return ((bool)(this["IsProcessFilterIncludeWmi"])); - } - set { - this["IsProcessFilterIncludeWmi"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("False")] - public bool IsProcessFilterIncludeWudf { - get { - return ((bool)(this["IsProcessFilterIncludeWudf"])); - } - set { - this["IsProcessFilterIncludeWudf"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("False")] - public bool IsProcessFilterIncludeBgTaskHost { - get { - return ((bool)(this["IsProcessFilterIncludeBgTaskHost"])); - } - set { - this["IsProcessFilterIncludeBgTaskHost"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("Default")] - public string CurrentTheme { - get { - return ((string)(this["CurrentTheme"])); - } - set { - this["CurrentTheme"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("True")] - public bool IsCpuUsageMonitoringEnabled { - get { - return ((bool)(this["IsCpuUsageMonitoringEnabled"])); - } - set { - this["IsCpuUsageMonitoringEnabled"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("False")] - public bool IsInsightsOnStartupEnabled { - get { - return ((bool)(this["IsInsightsOnStartupEnabled"])); - } - set { - this["IsInsightsOnStartupEnabled"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("True")] - public bool IsClipboardMonitoringEnabled { - get { - return ((bool)(this["IsClipboardMonitoringEnabled"])); - } - set { - this["IsClipboardMonitoringEnabled"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("\r\n\r\n DevHome.DevDiagnostics\r\n DevEnv\r\n")] - public global::System.Collections.Specialized.StringCollection ExcludedProcesses { - get { - return ((global::System.Collections.Specialized.StringCollection)(this["ExcludedProcesses"])); - } - set { - this["ExcludedProcesses"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("0")] - public double ExpandedWindowHeight { - get { - return ((double)(this["ExpandedWindowHeight"])); - } - set { - this["ExpandedWindowHeight"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("True")] - public bool ApplyAppFilteringToData { - get { - return ((bool)(this["ApplyAppFilteringToData"])); - } - set { - this["ApplyAppFilteringToData"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("0")] - public double WindowWidth { - get { - return ((double)(this["WindowWidth"])); - } - set { - this["WindowWidth"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("True")] - public bool IsClipboardMonitorToolPinned { - get { - return ((bool)(this["IsClipboardMonitorToolPinned"])); - } - set { - this["IsClipboardMonitorToolPinned"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("True")] - public bool IsImageOptionsToolPinned { - get { - return ((bool)(this["IsImageOptionsToolPinned"])); - } - set { - this["IsImageOptionsToolPinned"] = value; - } - } - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Properties/Settings.settings b/tools/DevDiagnostics/DevHome.DevDiagnostics/Properties/Settings.settings deleted file mode 100644 index b343d1786..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Properties/Settings.settings +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - False - - - Default - - - True - - - False - - - True - - - <?xml version="1.0" encoding="utf-16"?> -<ArrayOfString xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> - <string>DevHome.DevDiagnostics</string> - <string>DevEnv</string> -</ArrayOfString> - - - 0 - - - True - - - 0 - - - True - - - True - - - \ No newline at end of file diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Properties/launchSettings.json b/tools/DevDiagnostics/DevHome.DevDiagnostics/Properties/launchSettings.json deleted file mode 100644 index 6b879c187..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Properties/launchSettings.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "profiles": { - "DevHome.PI (Unpackaged)": { - "commandName": "Project", - "nativeDebugging": true - } - } -} \ No newline at end of file diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Services/DDAppInfoService.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Services/DDAppInfoService.cs deleted file mode 100644 index 1d8cbafed..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Services/DDAppInfoService.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.IO; -using System.Reflection; -using DevHome.Common.Helpers; -using Windows.ApplicationModel; - -namespace DevHome.DevDiagnostics.Services; - -public class DDAppInfoService -{ - public string IconPath { get; } = Path.Combine(AppContext.BaseDirectory, "Images/DD.ico"); - - public Version GetAppVersion() - { - if (RuntimeHelper.IsMSIX) - { - var packageVersion = Package.Current.Id.Version; - return new(packageVersion.Major, packageVersion.Minor, packageVersion.Build, packageVersion.Revision); - } - else - { - return Assembly.GetExecutingAssembly().GetName().Version!; - } - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Services/DDInsightsService.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Services/DDInsightsService.cs deleted file mode 100644 index 4787b951e..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Services/DDInsightsService.cs +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Collections.ObjectModel; -using System.ComponentModel; -using System.Diagnostics; -using System.Linq; -using CommunityToolkit.Mvvm.ComponentModel; -using DevHome.DevDiagnostics.Models; - -namespace DevHome.DevDiagnostics.Services; - -public partial class DDInsightsService : ObservableObject -{ - private Process? _targetProcess; - - [ObservableProperty] - private int _unreadCount; - - [ObservableProperty] - private ObservableCollection _insightsList; - - public DDInsightsService() - { - TargetAppData.Instance.PropertyChanged += TargetApp_PropertyChanged; - _insightsList = []; - - var process = TargetAppData.Instance.TargetProcess; - if (process is not null) - { - UpdateTargetProcess(process); - } - } - - public void UpdateTargetProcess(Process process) - { - if (_targetProcess != process) - { - _targetProcess = process; - InsightsList.Clear(); - UnreadCount = 0; - } - } - - private void TargetApp_PropertyChanged(object? sender, PropertyChangedEventArgs e) - { - if (e.PropertyName == nameof(TargetAppData.TargetProcess)) - { - if (TargetAppData.Instance.TargetProcess is not null) - { - UpdateTargetProcess(TargetAppData.Instance.TargetProcess); - } - } - } - - internal void AddInsight(Insight insight) - { - insight.PropertyChanged += (sender, e) => - { - if (e.PropertyName == nameof(Insight.HasBeenRead)) - { - UnreadCount = InsightsList.Count(insight => !insight.HasBeenRead); - } - }; - - UnreadCount++; - InsightsList.Add(insight); - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Services/DDNavigationService.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Services/DDNavigationService.cs deleted file mode 100644 index 1b8eeb151..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Services/DDNavigationService.cs +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System.Diagnostics.CodeAnalysis; -using DevHome.Common.Extensions; -using DevHome.Common.Services; -using DevHome.DevDiagnostics.Contracts.ViewModels; -using DevHome.DevDiagnostics.ViewModels; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Navigation; - -namespace DevHome.DevDiagnostics.Services; - -// Similar to DevHome.Services.NavigationService -internal sealed class DDNavigationService : INavigationService -{ - private readonly IPageService pageService; - private object? lastParameterUsed; - private Frame? frame; - private string? defaultPage; - - public object? LastParameterUsed => lastParameterUsed; - - public event NavigatedEventHandler? Navigated; - - public Frame? Frame - { - get - { - if (frame == null) - { - var barWindow = Application.Current.GetService().DBarWindow; - frame = barWindow?.GetFrame(); - if (frame is not null) - { - RegisterFrameEvents(); - } - } - - return frame; - } - - set - { - UnregisterFrameEvents(); - frame = value; - RegisterFrameEvents(); - } - } - - public string DefaultPage - { - get => defaultPage ?? typeof(AppDetailsPageViewModel).FullName ?? string.Empty; - set => defaultPage = value; - } - - [MemberNotNullWhen(true, nameof(Frame), nameof(frame))] - public bool CanGoBack => Frame != null && Frame.CanGoBack; - - [MemberNotNullWhen(true, nameof(Frame), nameof(frame))] - public bool CanGoForward => Frame != null && Frame.CanGoForward; - - public DDNavigationService(IPageService pageService) - { - this.pageService = pageService; - } - - private void RegisterFrameEvents() - { - if (frame != null) - { - frame.Navigated += OnNavigated; - } - } - - private void UnregisterFrameEvents() - { - if (frame != null) - { - frame.Navigated -= OnNavigated; - } - } - - public bool GoBack() - { - if (CanGoBack) - { - var vmBeforeNavigation = GetPageViewModel(frame); - frame.GoBack(); - if (vmBeforeNavigation is INavigationAware navigationAware) - { - navigationAware.OnNavigatedFrom(); - } - - return true; - } - - return false; - } - - public bool GoForward() - { - if (CanGoForward) - { - var vmBeforeNavigation = GetPageViewModel(frame); - frame.GoForward(); - if (vmBeforeNavigation is INavigationAware navigationAware) - { - navigationAware.OnNavigatedFrom(); - } - - return true; - } - - return false; - } - - public bool NavigateTo(string pageKey, object? parameter = null, bool clearNavigation = false) - { - var pageType = pageService.GetPageType(pageKey); - - if (frame != null && (frame.Content?.GetType() != pageType || (parameter != null && !parameter.Equals(lastParameterUsed)))) - { - frame.Tag = clearNavigation; - var vmBeforeNavigation = GetPageViewModel(frame); - var navigated = frame.Navigate(pageType, parameter); - if (navigated) - { - lastParameterUsed = parameter; - if (vmBeforeNavigation is INavigationAware navigationAware) - { - navigationAware.OnNavigatedFrom(); - } - } - - return navigated; - } - - return false; - } - - private void OnNavigated(object sender, NavigationEventArgs e) - { - if (sender is Frame frame) - { - var clearNavigation = (bool)frame.Tag; - if (clearNavigation) - { - frame.BackStack.Clear(); - } - - if (GetPageViewModel(frame) is INavigationAware navigationAware) - { - navigationAware.OnNavigatedTo(e.Parameter); - } - - Navigated?.Invoke(sender, e); - } - } - - public static object? GetPageViewModel(Frame frame) - { - return frame.Content?.GetType().GetProperty("_viewModel")?.GetValue(frame.Content, null); - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Services/DDPageService.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Services/DDPageService.cs deleted file mode 100644 index 04d4575fe..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Services/DDPageService.cs +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; -using System.Linq; -using CommunityToolkit.Mvvm.ComponentModel; -using DevHome.Common.Services; -using DevHome.DevDiagnostics.Pages; -using DevHome.DevDiagnostics.ViewModels; -using Microsoft.UI.Xaml.Controls; - -namespace DevHome.DevDiagnostics.Services; - -// Similar to DevHome.Services.PageService -internal sealed class DDPageService : IPageService -{ - private readonly Dictionary _pages = new(); - - public DDPageService() - { - Configure(); - Configure(); - Configure(); - Configure(); - Configure(); - Configure(); - Configure(); - Configure(); - - // Settings sub-_pages. - Configure(); - Configure(); - Configure(); - Configure(); - } - - public Type GetPageType(string key) - { - Type? pageType; - lock (_pages) - { - if (!_pages.TryGetValue(key, out pageType)) - { - throw new ArgumentException($"Page not found: {key}. Did you forget to call PageService.Configure?"); - } - } - - return pageType; - } - - public void Configure() - where T_VM : ObservableObject - where T_V : Page - { - lock (_pages) - { - var key = typeof(T_VM).FullName!; - if (_pages.ContainsKey(key)) - { - throw new ArgumentException($"The key {key} is already configured in PageService"); - } - - var type = typeof(T_V); - if (_pages.Any(p => p.Value == type)) - { - throw new ArgumentException($"This type is already configured with key {_pages.First(p => p.Value == type).Key}"); - } - - _pages.Add(key, type); - } - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Strings/en-us/Resources.resw b/tools/DevDiagnostics/DevHome.DevDiagnostics/Strings/en-us/Resources.resw deleted file mode 100644 index 71291b0a5..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Strings/en-us/Resources.resw +++ /dev/null @@ -1,1325 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Minimize - Tooltip for the minimize button in the BarWindow - - - Maximize - Tooltip for the maximize button in the BarWindow - - - Pin - A label for the menu item to pin a tool on the bar. - - - Unregister - The label for Unregister menu flyout for an icon in the toolbar. This will cause the program to no longer be registered with the bar. - - - Expand the large content panel - The tooltip for a button which expands the large content panel. - - - Settings - The tooltip for a button that takes the user to the settings for Dev Diagnostics. - - - External tools: add/remove, configure and launch - The tooltip for a button that takes the user to the external tools section of Dev Diagnostics. - - - Error - The title of an error message dialog when something goes wrong. - - - Failed to launch: {0} - {Locked="{0}"} Text for when there was an error launching an external tool. {0} is the name of an executable(.exe) file. - - - App details - The contents of a text block referring to details about an application. - - - ID - The contents of a text block referring to identity (ID) of an application. - - - Base priority - The contents of a text block referring to base CPU priority of an application. - - - Priority class - The contents of a text block referring to scheduling priority of an application. - - - Main module - This refers to the main module of an application like winword.exe or notepad.exe as an example. - - - CPU architecture - This refers to the CPU architecture of the target process and the host machine. - - - MSIX packaged - This refers to whether the application is using MSIX packaging technology. - - - Loaded modules - The contents of a text block referring to loaded application modules. - - - File Version Info - The contents of a text block referring to version of the module file loaded by an application. - - - Memory Size - The contents of a text block referring to size in memory of the module. - - - Filter... - The contents of a combo box that allows editing to filter out elements. - - - BgTaskHost - {Locked}The contents of a check box that refers to specific process names. - - - ConHost - {Locked}The contents of a check box that refers to specific process names. - - - DllHost - {Locked}The contents of a check box that refers to specific process names. - - - SvcHost - {Locked}The contents of a check box that refers to specific process names. - - - MsEdgeWebView2 - {Locked}The contents of a check box that refers to specific process names. - - - RuntimeBroker - {Locked}The contents of a check box that refers to specific process names. - - - WmiPrvSe - {Locked}The contents of a check box that refers to specific process names. - - - WudfHost - {Locked}The contents of a check box that refers to specific process names. - - - Refresh the process list - The contents of a button tool tip that will refresh the contents of the list. - - - PID - Process identifier. - - - Executable - The name of a process (winword.exe or notepad.exe for example). - - - Resource usage - The contents of a text block referring to process resource usage information. - - - Is responding - Refers to whether the application or process is responsive, or if it is stuck. - - - CPU usage - Refers to how much of the central processing unit (CPU) the process is utilizing. - - - GPU usage - Refers to how much of the graphical processing unit (GPU) the process is utilizing. - - - Memory usage - Refers to how much random access memory (RAM) the process is utilizing. - - - Disk usage - Refers to how much disk storage (hard drive/solid state drive) the process is utilizing. - - - Crash reports - The contents of a WER crash dumps. - - - Time generated - The time at which the WER report was generated. - - - Faulting executable - Refers to the process/application executable which caused the fault which generated the crash report - - - Info about the Windows Error Report - Refers to the WER diagnostic information about a process crash. - - - Windows logs - The contents of a text block referring to Windows logs. - - - Event Tracing for Windows (ETW) logs - Whether to enable Event Trace for Windows (ETW) logs in the log view output. - - - Debug output from the target app - Tooltip for whether to enable debug output (from OutputDebugString API) in the log view output. - - - Entries from the event log for the target app - Tooltip for whether to enable event viewer logs in the log view output. - - - Entries from the event log for the target app - Tooltip for whether the WER report logs are shown in the log view output. - - - Clear the list - Tooltip for a button that will clear the log list. - - - Time Generated - The time at which the log was generated. - - - Category - A header for what category the log entry belongs. - - - Tool - A header for what tool generated the log entry. - - - Message - The contents of a log entry. - - - Could not start OutputDebugString monitor since there is one already running. - An error message indicating that the resource is mutually exclusive due to an instance already running. - - - Tool Name - The name the user can assign to the tool they are adding. - - - Tool path - The name the user can assign to the tool they are adding. - - - Browse - A button to browse the filesystem. - - - Basic arguments - Refers to arguments that can be passed to a process when it is created - - - None - Refers to the type of data being shown - - - Prefix (if any) - Refers to arguments that can be passed to a process when it is created - - - OK - An affirmative value for a button - - - Cancel - Cancels the current operation the user is performing - - - Name - The name of a tool that could be edited. - - - Unregister - Text on a button for unregistering a tool. - - - Settings - The contents of a text block refering to settings. - - - Preferences - The contents of a text block refering to a user's settings preferences. - - - Theme selection - The contents of a text block refering to an application's color theme. - - - Light - Refers to a color theme or scheme - - - Dark - Refers to a color theme or scheme - - - Windows default - Refers to a color theme or scheme - - - Additional tools - Refers to tools the user has added. - - - Add a tool to the bar - Refers to tools a user could add to the bar UI. - - - Edit the configuration for registered tools - Refers to tools a user could edit that are already registered to the bar UI. - - - Monitor CPU usage for the target app - Refers tracing central processing unit (CPU) usage of the app the user has selected. - - - Show Insights on start-up - Refers showing insightful suggestions to the user about the app on startup. - - - Enable Clipboard monitoring - Refers monitoring the user's clipboard for error messages. - - - Processes to exclude when finding the foreground window. Enter the process names here, comma-separated. - Refers application process names for example notepad.exe, winword.exe etc, in a comma-separated list. - - - Save - Saves the data that the user has input. - - - About - A header for an about page. - - - App Info - The contents of a text block refering to the main window title. - - - File error - The contents of a text block refering to the main window title. - - - The Event Log lists several entries where the app has tried to open a file at 'C:\\Temp\\Scratch\\Foo.jpg'. That folder path exists, and you do have permission to access it, but the file specified does not exist in that path. However, I can see that there is a file with that name at a different folder path: 'C:\\Temp\\Foo.jpg' - perhaps this is the one you're looking for. - The contents of a text label. - - - See more - The contents of a text label. - - - Resource usage - The contents of a text label for computer resource usage (CPU/GPU/Disk/Network etc). - - - Over the last 24 hours, this app has exceeded 30% of CPU usage on 247 separate occasions. If the app is doing compute-intensive operations, this might be reasonable, but you should examine your code and your tests to ensure that this is within expected parameters. - The contents of a text label for computer resource usage (CPU/GPU/Disk/Network etc). - - - See more - The contents of a text label. - - - Hex - This refers to a short hand for hexadecimal number notation. - - - Dec - This refers to a short hand for decimal number notation. - - - Code - This refers to a short hand for an error code representation of the contents of the clipboard. - - - Is running as Admin - This refers to whether the application is running as admin - - - Is running as System - This refers to whether the application is running as System - - - Go to the key insights - The tooltip for a button that takes the user to the key insights page - - - Process list - The contents of a text block referring to Process list. - - - {0} (terminated) - {Locked="{0}"} Text indicating that the process has terminated. {0} is the process name. - - - Insights - The contents of a text block referring to Insights. - - - Help - Description of the error code - - - PID: {0} - {Locked="{0}"} Showing a process identifier. {0} is an integer - - - {0:0.0}% CPU usage - {Locked="{0:0.0}"} Showing CPU utilization. {0} is a percentage 0-100 - - - {0:N2} MB Memory used - {Locked="{0:N2}"} Showing RAM utilization. MB stands for megabytes. {0} is a number. - - - {0:N0} MB/s Disk utilization - {Locked="{0:N0}"} Showing disk utilization. MB/s stands for megabytes per second. {0} is a number. - - - cpu: n/a % - Showing CPU utilization which is not available/applicable. - - - memory: n/a MB - Showing RAM utilization which is not available/applicable. MB stands for megabytes. - - - dsk: n/a MB/s - Showing disk utilization which is not available/applicable. MB/s stands for megabytes per second. - - - {0} CPU usage: {1:0.0}% - {Locked="{0},{1:0.0}"} A notification for CPU usage. {0} is the name of a process (notepad.exe for example). {1} is a percentage - - - GOT UNHANDLED EVENT: {0} - {Locked="{0}"} An error message when an unhandled trace event is encountered. {0} is a verbose version of the event - - - Could not start EventViewer - An error message when the program is unable to start the Windows Event Viewer - - - Locked file - Describes a computer file that is locked for exclusive access - - - The app is trying to access the file '{0}', but this is locked by '{1}'. To fix this, close '{1}' - {Locked="{0}", "{1}"} A description to help a user that is dealing with a file locked for exclusive access. {0} is a file name. {1} is the name of an executable(.exe) process. - - - The app is trying to access the file '{0}', but this is locked by an unknown process - {Locked="{0}"} A description to help a user that is dealing with a file locked for exclusive access. {0} is a file name. - - - Could not start WER crash dump monitoring - Refers to being unable to start monitoring the WER error logs. - - - Preferences - Refers to a user's settings preferences. - - - Additional tools - Refers to a additional executable tools the user can add to the product - - - Advanced settings - Refers to a additional more complex settings. - - - About - Refers to additional information about the product. - - - {0:0.0}% - {Locked="{0:0.0}"} Showing CPU utilization. {0} is a percentage 0-100 - - - {0:N0} MB/s - {Locked="{0:N0}"} Showing disk utilization. MB/s stands for megabytes per second. {0} is a number. - - - {0:0.0}% - {Locked="{0:0.0}"} Showing GPU utilization. {0} is a percentage 0-100 - - - {0:N2} MB - {Locked="{0:N2}"} Showing RAM utilization. MB stands for megabytes. {0} is a number. - - - CPU usage of the attached process. - Refers to the amount of CPU a process is using, shown in the bar. - - - Process ID of the attached process. - Refers to the app's PID in the bar - - - {0:0.0}% - {Locked="{0:0.0}"} Showing Disk utilization. {0} is a percentage 0-100 - - - CPU usage of the attached process. - Refers to the amount of CPU a process is using, shown in the bottom bar. - - - Disk usage of the attached process. - Refers to the amount of disk usage a process is using, shown in the bottom bar. - - - Memory usage of the attached process. - Refers to the amount of Memory a process is using, shown in the bottom bar. - - - Process ID of the attached process. - Refers to the app's PID in the bottom bar - - - {0:N2} GB - {Locked="{0:N2}"} Showing RAM utilization. GB stands for gigabytes. {0} is a number. - - - Amount of CPU used by the overall system. - Tooltip for the system CPU usage box in the bar - - - Amount of disk utilization by the overall system. - Tooltip for the system disk usage box in the bar - - - Amount of committed memory used by the overall system. - Tooltip for the system memory usage box in the bar - - - Dev Diagnostics - {Locked}The name of the Dev Diagnostics application - - - Dev Diagnostics - {Locked}The description of the Dev Diagnostics application - - - Hotkey for Dev Diagnostics - The description of the startup task for Dev Diagnostics. This shows up in task manager/Windows Settings > Startup Apps. - - - Is Python - This refers to whether the application is a Python app. - - - Memory violation - Describes an issue related to a memory access violation. - - - This is a Python app that is using the ctypes foreign function library. This provides C-compatible data types, and allows calling functions in DLLs, and using raw pointers. A memory access violation can result if the code misuses pointers. - Describes an issue with a specific Python memory access violation. - - - Security issue - Describes an issue related to security. - - - Failure Bucket ID - Refers to the module which caused the fault which generated the crash report - - - Error {0}: {1} - {Locked="{0}", "{1}"} A description to help a user that is dealing with non-specific error situation. {0} is the error name. {1} is the error description. - - - Frameworks detected - This refers to the set of application frameworks this application uses. - - - Base address - The contents of a text block referring to the base address of a loaded module. - - - Entrypoint address - The contents of a text block referring to the entrypoint address of a loaded module. - - - Pinned - Text to show when the switch is turned on, to pin the tool to the bar. - - - Not pinned - Text to show when the switch is turned off, to not pin the tool to the bar. - - - Unpin - A label for the menuitem to unpin a tool on the bar. - - - Unpin - Should be the same as UnpinMenuItem.Text - - - Unregister - Same as UnregisterMenuItem.Text - - - About - Header for the Settings item for product information and privacy statement. - - - Info, Privacy Statement - Sub-header for the Settings item for product information and privacy statement. - - - Additional tools - Header for the Settings item for configuring additional tools. - - - Add or edit tool configurations - Sub-header for the Settings item for configuring additional tools. - - - Advanced settings - Header for the Settings item for configuring advanced features. - - - Configure advanced features - Sub-header for the Settings item for configuring advanced features. - - - Preferences - Header for the Settings item for user preferences. - - - Themes - Sub-header for the Settings item for user preferences. - - - Settings - The title of the main Settings page. - - - Theme - Title for the theme settings sub-page item. - - - Dark - Refers to a color theme or scheme. - - - Windows default - Refers to a color theme or scheme. - - - Light - Refers to a color theme or scheme. - - - Dev Diagnostics - {Locked} This is the name of the product. - - - © Microsoft. All rights reserved. - This is the copyright notice for the product. - - - Related links - Header for a set of hyperlinks to information about the product. - - - Documentation - Label for the link to the documentation for the product. - - - https://go.microsoft.com/fwlink/?linkid=2275140 - Link to the documentation for the product. - - - Privacy Statement - Label for the link to the standard privacy policy statement. - - - https://go.microsoft.com/fwlink/?linkid=2234882 - Link to the standard privacy policy statement. - - - Source code - Label for the link to the source code for the product. - - - https://go.microsoft.com/fwlink/?linkid=2234396 - Link to the source code for the product. - - - Register an external tool with Dev Diagnostics - Header for the settings item to add a tool to the product. - - - Edit or unregister existing tools - Header for the setting item to edit or unregister tools from the product. - - - The starting priority for threads created within this process - Tooltip for the Base Priority field. - - - The CPU architecture of the target process - Tooltip for the CPU Architecture field. - - - The windowing or application frameworks used in this app - Tooltip for the Framework Types field. - - - The process ID of the target process - Tooltip for the PID field. - - - True if the target process is running under an Administrator account - Tooltip for the Running as Admin field. - - - True if the target process is running as a System process, based on its Session ID - Tooltip for the Running as System field. - - - The executable used to start the process - Tooltip for the Main Module field. - - - True if this process is packaged with MSIX - Tooltip for the MSIX Packaged field. - - - Threads with different priorities in the process run relative to the priority class of the process - Tooltip for the Priority Class field. - - - Close - Text used on the Close button on a message dialog. - - - External tool {0} registered - Message shown to the user when an external tool is registered. - - - Executable - The executable path of an external tool. - - - Invalid tool path or name - Text for the message to show to the user when the supplied path or name is not valid. - - - Select a process to investigate - Describes using a button in Dev Diagnostics' UX to investigate another process running on the system - - - Dev Diagnostics - {Locked} The product name - - - {0} process running on {1} machine - {Locked="{0}", "{1}"} Message text when the process is the specified CPU architecture running on the specified CPU machine. {0} is the process architecture, {1} is the machine architecture. - - - Unknown - Message text when the CPU architecture of the process is unknown. - - - Unknown process type running on {0} - {Locked="{0}"}. Message text when the process is unknown CPU architecture running on the specified CPU machine. {0} is the machine architecture. - - - X64 process running on X64 machine - Message text when the process is x64 CPU architecture running on an X64 CPU machine. - - - Go to Advanced app settings - Content Dialog button text which on click opens the Advanced App settings page in Windows Settings app. - - - Go to Windows Settings > Apps > Advanced app settings > App execution alias > Dev Diagnostics > Enable the toggle and try to launch Dev Insights as admin again. - Content Dialog content suggesting users steps to enable app execution alias from Windows Settings app - - - Enable App Execution Alias for Dev Diagnostics and try again - Content Dialog title to enable app execution alias for Dev Diagnostics - - - Detach from the currently targeted process - Used to describe what the DetachAppButton does - - - Detach - Menu Item that allows the user to detach from the current process - - - Dump file - Header text for the link to a WER dump - - - Activation - Header text for a group of radio buttons indicating the activation type - - - Refresh - Text for a button to refresh the list of apps - - - Icon - Column heading for the icon column in a datagrid - - - Name - Column heading for the name column in a datagrid - - - Provide the command-line or protocol arguments here. Use {pid}, {hwnd}, or {crashDumpPath} if you want Dev Diagnostics to substitute the target app's process ID or window handle. For example: - {Locked="{pid}", "{hwnd}", "{crashDumpPath}"} Description text for a section where the user can type in the arguments to be used for the app - - - Arguments - Header text for a section describing the arguments to be used for the app - - - Launch - Text for a radio button for the launch activation option - - - Protocol - Text for a radio button for the protocol option - - - Launch example: /something /process={pid} /another={hwnd} - Example launch activation argument string - - - Protocol example: myprotocol:///args?one=ABC&two={pid}&three={hwnd} - Example protocol argument string - - - The type of activation for this tool - Describes the section where the user can specify the type of tool activation to use. - - - Get a list of installed apps - Describes a button that will get a list of installed apps. - - - Pin this tool to the toolbar, as well as adding it to the menu - Describes a toggle switch for pinning a tool to the toolbar. - - - Launch this tool by its path or package identity - Describes a radio button that specifies how to launch the selected tool. - - - Launch this tool by its registered protocol - Describes a radio button that specifies how to launch the selected tool. - - - Browse the filesystem to find a tool - Describes a button for browsing the filesystem. - - - The name you want to use for this tool in the menu and toolbar - Describes a textbox where the user can enter a name for the tool. - - - Collapse the large content panel - The tooltip for a button which collapses the large content panel. - - - Name of the attached app - Refers to the app's name in the bar - - - Clipboard Monitor - A label for the Clipboard Monitor tool - - - Image Options - A label for the Image Options tool - - - See insights that Dev Diagnostics has identified - Tooltip that tells users what the Insights button will do - - - Insights - A text label for the Insights button - - - Processes - A text label for the Processes button - - - Manage Tools - Label for a button to allow users to manage external tools - - - All Files - Filter string to specify that the file dialog should include all files - - - Batch Files - Filter string to specify that the file dialog should include batch files - - - Command Files - Filter string to specify that the file dialog should include command files - - - Executables - Filter string to specify that the file dialog should include executable files - - - Management Console Files - Filter string to specify that the file dialog should include Management Console files - - - PowerShell Scripts - Filter string to specify that the file dialog should include PowerShell files - - - Local WER crash dump collection for app - Label for Windows Error reporting toggle switch - - - Enable capture of Windows Error Reporting dumps for offline analysis - Tooltip to enable local cab collection for Windows Error Reports - - - More - Label for a link that navigates the user to a location to learn more about WER local dumps - - - Change - The contents of a button to allow the user to trigger elevation to change WER settings - - - Dev Diagnostics needs to run as Admin in order to modify WER crash dump collection for an app. - Tooltip for a button that relaunches Dev Diagnostics as admin to change WER settings - - - Get Information - The contents of a button to allow the user to trigger elevation to get more information - - - Dev Diagnostics needs to run as Admin in order to get more data for an app. - Tooltip for a button that relaunches Dev Diagnostics as admin to get more data - - - Dump Info - Selector Pivot that shows information about a Dump File - - - Filter Data to Target App - Label on a toggle button that controls whether presented data is filtered to the selected app - - - Controls whether data presented is for the entire system or filtered to the selected app - Tooltip for the FilterDataToTargetApp toggle - - - Activation arguments - Label for the arguments passed in when activating the target app. - - - Any arguments provided to the app when it was activated - Tooltip for the arguments passed in when activating the target app. - - - Full name - Textblock showing the full name of the MSIX package for this app. - - - Package full name - Tooltip for the full name of the MSIX package for this app. - - - Version - Textblock showing the version of the MSIX package for this app. - - - Package version - Tooltip for the version of the MSIX package for this app. - - - Display name - Textblock showing the display name of the MSIX package for this app. - - - Display name for this package - Tooltip for the display name of the MSIX package for this app. - - - Installed date - Textblock showing the installed date of the MSIX package for this app. - - - Date this package was installed - Tooltip for the installed date of the MSIX package for this app. - - - Installed path - Textblock showing the installed path of the MSIX package for this app. - - - Filesystem path where this package is installed - Tooltip for the installed path of the MSIX package for this app. - - - Publisher - Textblock showing the publisher name of the MSIX package for this app. - - - Name of the package publisher - Tooltip for the full publisher of the MSIX package for this app. - - - Development mode - Textblock showing whether the MSIX package for this app was installed in development mode. - - - Was this package sideloaded in development mode - Tooltip for whether the MSIX package for this app was installed in development mode. - - - Signature kind - Textblock showing the signature kind of the MSIX package for this app. - - - The kind of signature used to sign this package, if any - Tooltip for the signature kind of the MSIX package for this app. - - - Status - Textblock showing the status of the MSIX package for this app. - - - Deployment status of this package - Tooltip for the status of the MSIX package for this app. - - - Dependencies - Textblock showing the list of dependencies for the MSIX package for this app. - - - Additional packages this app depends on - Tooltip for the list of dependencies for the MSIX package for this app. - - - (unknown) - Text used in messages to indicate that the value of this item is unknown. - - - No issues - A message indicating that there are no issues with the given item. - - - Tool Type - Button text allowing the user to select the type of tool - - - Set the type of the tool being added. - Tooltip for the button text allowing the user to select the type of tool - - - WER crash dump analyzer - Describes type of tool used to analyze WER dumps - - - Tool that will be used to analyze WER crash dumps generated on the system - Tooltip that describes what a WER Dump analyzer does - - - Dev Diagnostics Clipboard Monitor - Window title for the clipboard monitor tool - - - Dev Insights Image Options - Window title for the image options tool - - - Analysis unavailable. - Message shown when there isn't crash analysis available. - - - Dump File Size: {0} bytes -Dump File creation time: {1} - {Locked="{0}", "{1}"} Created string that contains basic information about a crash dump - - - Use this tool for WER crash dump bucketing - Context menu button used to select a tool that is using to bucket WER reports - - - Use this tool for WER crash dump bucketing - Context menu button used to select a tool that is using to bucket WER reports - - - Regular Expression for WER crash dump bucket - Label for a textbox that will contain the regular expression a tool uses to determine the bucketing string of a cab. - - - Application Verifier - Label for a checkbox that enables Application Verifier for the target app. - - - Process list - Name of the button that brings up the process list page - - - Insights - Name of the button that brings up the Insights page - - - Expand or Collapse - Name of the button expands or collapses the UI. - - - Page Navigation - Name of the nav list. - - - Detach from the currently targeted process - Description of the detach app button for narrator to read. - - - Run as administrator - Description of the button to run as administrator. - - - Resize navigation pane - Description of the control to change the size of the navigation pane - - - Refresh the process list - Narrator description for the button that refreshes the process list - - - Process list filter - Narrator description for the combobox that filters the process list - - - Modules - Narrator description for the Modules List ListView - - - Resize modules pane - Description of the control to change the size of the navigation pane - - - Run as administrator - Description of the button to run Dev Diagnostics as administrator - - - Run as administrator - Description of the control button to run Dev Diagnostics as administrator - - - Clear the list - Description of the button to clear the log output of the WinLogs page - - - Filter the list - Description of the button to filter the log output list - - - A list of all running processes. You can select an item from the list to target. You can also type a name in the search box to find that process. The drop-down contains a list of all items that are filtered out by default - you can select any of these to include them in the main list. Another way to select your target process is to bring its window to the foreground and then use the hotkey Windows+F12. - {Locked="Windows+F12"} Description of the Process list page. - - - Recent crash reports available on this machine. By default, this is filtered to your target app (if any). You can select any dump file in the list to open it in a dump analyzer tool of your choice. If you want to change your choice of dump analyzer tool, go to Windows Settings > Apps > Default apps > Set default for ".dmp" file type. - {Locked=".dmp"} Description of the Crash reports page. - - - As Dev Diagnostics gathers context data for your target app, it can analyze the data, and in some cases it can provide insights into the nature of the problem. If Dev Insights does identify insights, they will be listed here. (Note that this is a work in progress, and initially there are very few cases where Dev Insights can provide definitive analysis.) - Description of the Insights page. - - - A list of a wide range of resource usage and sensor items for both your target app (if any), and for the system as a whole. - Description of the Resource usage page. - - - All the modules (DLLs, etc) that have been loaded by your target process. - Description of the Loaded modules page. - - - As you exercise the features of your target app, this will generate log outputs in various forms. By default, this page tracks Event Tracing for Windows (ETW) logs, the system Event log, and Windows Error Reporting (WER) logs. You can also enable Debug Output tracking, althought this can produce a large amount of output, depending on the app. Dev Diagnostics analyzes log output and in some cases can generate insights. - Description of the Windows logs page. - - - Information about the current target app. - Description of the App details page. - - - (No insights found) - Placeholder text on the Insights page when the insights list is empty. - - - Process exited due to missing files - Title of an insight informing the user of a reason why a process exited - - - Process {0} (pid: {1,6}) exited with error code {2}. To help diagnose this issue, enable loader snaps and try to launch the process again. - {Locked="{0}, "{1,6}", "{2}"} Formatted string informing the user the process name {0}, the Process ID {1}, the exit code {2} of a process. - - - Process {0} (pid: {1,6}) exited due to missing files - {Locked="{0}, "{1,6}"} Formatted string informing the user the process name {0} and the Process ID {1} - - - Enable - Label on button that enables loader snaps - - - Launch an elevated executable to enable loader snaps for this executable. - Tooltip that describes what the enable button will do - - - Enable - Text for a button to allow a user to enable local dump collection - - - Disable - Text for a button to allow a user to disable local dump collection - - - Disable the capture of Windows Error Reporting dumps for offline analysis - Tooltip to disable local cab collection for Windows Error Reports - - \ No newline at end of file diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Styles/CommandBarStyle.xaml b/tools/DevDiagnostics/DevHome.DevDiagnostics/Styles/CommandBarStyle.xaml deleted file mode 100644 index 739bbfd9d..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Styles/CommandBarStyle.xaml +++ /dev/null @@ -1,838 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Telemetry/FeatureState.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Telemetry/FeatureState.cs deleted file mode 100644 index 3dfee458a..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Telemetry/FeatureState.cs +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; -using System.Linq; - -namespace DevHome.DevDiagnostics.Telemetry; - -// NOTE: The below flags can never be deleted. We should only rename features that were removed from the product. -// The enum can only take additions over time. -[Flags] -internal enum Feature -{ - None = 0x0, - AppDetails = 0x1, - ResourceUsage = 0x2, - LoadedModule = 0x4, - WERReports = 0x8, - WinLogs = 0x10, - ProcessList = 0x20, - Insights = 0x40, - InsightsAtStartup = 0x80, - MonitorCPU = 0x100, -} - -internal enum FeatureShareType -{ - Exclusive, - Shared, -} - -internal sealed class FeatureState -{ - internal static readonly Dictionary Features = new() - { - { Feature.AppDetails, FeatureShareType.Exclusive }, - { Feature.ResourceUsage, FeatureShareType.Exclusive }, - { Feature.LoadedModule, FeatureShareType.Exclusive }, - { Feature.WERReports, FeatureShareType.Exclusive }, - { Feature.WinLogs, FeatureShareType.Exclusive }, - { Feature.ProcessList, FeatureShareType.Exclusive }, - { Feature.Insights, FeatureShareType.Exclusive }, - { Feature.InsightsAtStartup, FeatureShareType.Shared }, - { Feature.MonitorCPU, FeatureShareType.Shared }, - }; - - internal static bool IsExclusive(Feature feature) - { - if (FeatureState.Features[feature] == FeatureShareType.Exclusive) - { - return true; - } - - return false; - } -} - -public static class EnumExtensions -{ - public static IEnumerable GetFlags(this T en) - where T : struct, Enum - { - return Enum.GetValues().Where(member => en.HasFlag(member)).ToArray(); - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Telemetry/FocusStartEventData.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Telemetry/FocusStartEventData.cs deleted file mode 100644 index 8ba40ee27..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Telemetry/FocusStartEventData.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Diagnostics.Tracing; - -namespace DevHome.DevDiagnostics.TelemetryEvents; - -[EventData] -public class FocusStartEventData : TimedStartEventBase -{ - internal FocusStartEventData(string featureName, DateTime featureStartTime) - : base(featureName, featureStartTime) - { - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Telemetry/FocusStopEventData.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Telemetry/FocusStopEventData.cs deleted file mode 100644 index ff52103cc..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Telemetry/FocusStopEventData.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Diagnostics.Tracing; - -namespace DevHome.DevDiagnostics.TelemetryEvents; - -[EventData] -public class FocusStopEventData : TimedStopEventBase -{ - internal FocusStopEventData(string featureName, DateTime featureStartTime) - : base(featureName, featureStartTime) - { - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Telemetry/LogStateChangedEventData.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Telemetry/LogStateChangedEventData.cs deleted file mode 100644 index ff367df17..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Telemetry/LogStateChangedEventData.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Diagnostics.Tracing; -using DevHome.Telemetry; -using Microsoft.Diagnostics.Telemetry; -using Microsoft.Diagnostics.Telemetry.Internal; - -namespace DevHome.DevDiagnostics.TelemetryEvents; - -[EventData] -public class LogStateChangedEventData : EventBase -{ - internal LogStateChangedEventData(string stateName, string stateValue) - { - StateName = stateName; - StateValue = stateValue; - } - - public override PartA_PrivTags PartA_PrivTags => PrivTags.ProductAndServiceUsage; - - public string StateName { get; private set; } - - public string StateValue { get; private set; } - - public override void ReplaceSensitiveStrings(Func replaceSensitiveStrings) - { - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Telemetry/TelemetryReporter.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Telemetry/TelemetryReporter.cs deleted file mode 100644 index e4a138266..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Telemetry/TelemetryReporter.cs +++ /dev/null @@ -1,171 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Threading; -using DevHome.Common.Extensions; -using DevHome.DevDiagnostics.TelemetryEvents; -using DevHome.Telemetry; -using Microsoft.UI.Xaml; -using Serilog; - -namespace DevHome.DevDiagnostics.Telemetry; - -internal sealed class TelemetryReporter : IDisposable -{ - private readonly FeatureState currentFeatureState = new(); - private WindowEventGenerator? eventGenerator; - private static readonly Mutex FeatureMutex = new(); - private static readonly ILogger Log = Serilog.Log.ForContext("SourceContext", nameof(TelemetryReporter)); - - private static Feature currentFeatureSet; - - internal static Feature CurrentFeatureSet => currentFeatureSet; - - public TelemetryReporter() - { - } - - internal static void SetWindow(Window win) - { - ArgumentNullException.ThrowIfNull(win, nameof(win)); - - // Make sure to apply all this to the already existing service object. - var rep = Application.Current.GetService(); - rep.eventGenerator = new WindowEventGenerator(win); - rep.eventGenerator.InteractiveUsageVisibilityEvent += rep.InteractiveUsageVisibilityEvent; - rep.eventGenerator.InteractiveUsageFocusEvent += rep.InteractiveUsageFocusEvent; - } - - public void SwitchTo(Feature requestedFeature) - { - if (FeatureMutex.WaitOne()) - { - if (FeatureState.IsExclusive(requestedFeature)) - { - var foundFirst = false; - - // Use a copy of the flags, since we'll be modifying them inside the loop. - var currentFeatureSetIterator = currentFeatureSet.GetFlags(); - foreach (var flag in currentFeatureSetIterator) - { - // Skip empty flag. - if (flag == Feature.None) - { - continue; - } - - if (foundFirst) - { - continue; - } - - // If the requested feature is exclusive and the current iteration feature is exclusive, - // remove it as we're about to add an exclusive. - if (FeatureState.IsExclusive(flag)) - { - // First fire any events to stop the previous features telemetry. - // Debug.Assert(eventGenerator != null, "eventGenerator is null"); - if (eventGenerator != null) - { - var eventArgs = new WindowEventGenerator.InteractiveUsageEventArgs(WindowEventGenerator.InteractiveUsageEventType.Stop); - if (eventGenerator.CurrentlyVisible) - { - InteractiveUsageVisibilityEvent(this, eventArgs); - } - - if (eventGenerator.CurrentlyFocused) - { - InteractiveUsageFocusEvent(this, eventArgs); - } - } - - // Remove existing exclusive features. - currentFeatureSet &= ~flag; - - Log.Debug("Removed an exclusive feature {0}.", flag); - Log.Debug("currentFeatureSet = {0}", currentFeatureSet.ToString()); - - // Leave a mark that we've encountered our first exclusive feature. There should only ever be one. - foundFirst = true; - } - } - } - - // Add the feature to the set. - currentFeatureSet |= requestedFeature; - Log.Debug("Added the exclusive feature {0}.", requestedFeature); - Log.Debug("currentFeatureSet = {0}", currentFeatureSet.ToString()); - } - - // TODO: Codepath probably should throw exception... (failed to acquire mutex...) - } - - public Feature CurrentExclusive - { - get - { - foreach (var flag in currentFeatureSet.GetFlags()) - { - // Skip empty flag. - if (flag == Feature.None) - { - continue; - } - - // Return the first exclusive. - if (FeatureState.IsExclusive(flag)) - { - return currentFeatureSet & flag; - } - } - - return Feature.None; - } - } - - private void InteractiveUsageVisibilityEvent(object? sender, WindowEventGenerator.InteractiveUsageEventArgs e) - { - var app = App.Current as DevHome.DevDiagnostics.App; - if (app != null) - { - var featureName = CurrentExclusive.ToString(); - - if (e.UsageType == WindowEventGenerator.InteractiveUsageEventType.Start) - { - App.Log("DevHome_DevDiagnostics_VisibilityStart", LogLevel.Measure, new VisibilityStartEventData(featureName, DateTime.Now)); - Log.Debug("Visibility Start!"); - } - else - { - App.Log("DevHome_DevDiagnostics_VisibilityStop", LogLevel.Measure, new VisibilityStopEventData(featureName, DateTime.Now)); - Log.Debug("Visibility Stop"); - } - } - } - - private void InteractiveUsageFocusEvent(object? sender, WindowEventGenerator.InteractiveUsageEventArgs e) - { - var app = App.Current as DevHome.DevDiagnostics.App; - if (app != null) - { - var featureName = CurrentExclusive.ToString(); - - if (e.UsageType == WindowEventGenerator.InteractiveUsageEventType.Start) - { - App.Log("DevHome_DevDiagnostics_FocusStart", LogLevel.Measure, new VisibilityStartEventData(featureName, DateTime.Now)); - Log.Debug("Focus Start!"); - } - else - { - App.Log("DevHome_DevDiagnostics_FocusStop", LogLevel.Measure, new VisibilityStopEventData(featureName, DateTime.Now)); - Log.Debug("Focus Stop"); - } - } - } - - public void Dispose() - { - eventGenerator?.Dispose(); - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Telemetry/TimedStartEventBase.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Telemetry/TimedStartEventBase.cs deleted file mode 100644 index cbc6576b0..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Telemetry/TimedStartEventBase.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Diagnostics.Tracing; -using DevHome.Telemetry; -using Microsoft.Diagnostics.Telemetry; -using Microsoft.Diagnostics.Telemetry.Internal; - -namespace DevHome.DevDiagnostics.TelemetryEvents; - -[EventData] -public class TimedStartEventBase : EventBase -{ - protected TimedStartEventBase(string featureName, DateTime featureStartTime) - { - Name = featureName; - StartTime = featureStartTime; - } - - protected string Name { get; private set; } - - protected DateTime StartTime { get; private set; } - - public override PartA_PrivTags PartA_PrivTags => PrivTags.ProductAndServiceUsage; - - public override void ReplaceSensitiveStrings(Func replaceSensitiveStrings) - { - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Telemetry/TimedStopEventBase.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Telemetry/TimedStopEventBase.cs deleted file mode 100644 index 3300365c9..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Telemetry/TimedStopEventBase.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Diagnostics.Tracing; -using DevHome.Telemetry; -using Microsoft.Diagnostics.Telemetry; -using Microsoft.Diagnostics.Telemetry.Internal; - -namespace DevHome.DevDiagnostics.TelemetryEvents; - -[EventData] -public class TimedStopEventBase : EventBase -{ - internal TimedStopEventBase(string featureName, DateTime featureStopTime) - { - Name = featureName; - StopTime = featureStopTime; - } - - public string Name { get; private set; } - - public DateTime StopTime { get; private set; } - - public override PartA_PrivTags PartA_PrivTags => PrivTags.ProductAndServiceUsage; - - public override void ReplaceSensitiveStrings(Func replaceSensitiveStrings) - { - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Telemetry/UsageEventData.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Telemetry/UsageEventData.cs deleted file mode 100644 index 8a39aedd7..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Telemetry/UsageEventData.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Diagnostics.Tracing; -using DevHome.Telemetry; -using Microsoft.Diagnostics.Telemetry; -using Microsoft.Diagnostics.Telemetry.Internal; - -namespace DevHome.DevDiagnostics.TelemetryEvents; - -// Used to produce basic single-line telemetry events based on a simple string. -[EventData] -public class UsageEventData : EventBase -{ - public override PartA_PrivTags PartA_PrivTags => PrivTags.ProductAndServiceUsage; - - public override void ReplaceSensitiveStrings(Func replaceSensitiveStrings) - { - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Telemetry/VisibilityStartEventData.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Telemetry/VisibilityStartEventData.cs deleted file mode 100644 index 08a71c6c6..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Telemetry/VisibilityStartEventData.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Diagnostics.Tracing; - -namespace DevHome.DevDiagnostics.TelemetryEvents; - -[EventData] -public class VisibilityStartEventData : TimedStartEventBase -{ - internal VisibilityStartEventData(string featureName, DateTime featureStartTime) - : base(featureName, featureStartTime) - { - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Telemetry/VisibilityStopEventData.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Telemetry/VisibilityStopEventData.cs deleted file mode 100644 index aedb9c60b..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Telemetry/VisibilityStopEventData.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Diagnostics.Tracing; - -namespace DevHome.DevDiagnostics.TelemetryEvents; - -[EventData] -public class VisibilityStopEventData : TimedStopEventBase -{ - internal VisibilityStopEventData(string featureName, DateTime featureStartTime) - : base(featureName, featureStartTime) - { - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Telemetry/WindowEventGenerator.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Telemetry/WindowEventGenerator.cs deleted file mode 100644 index 181909bc0..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Telemetry/WindowEventGenerator.cs +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Threading; -using DevHome.Common.Extensions; -using DevHome.DevDiagnostics.Helpers; -using Microsoft.UI.Xaml; -using Windows.Win32; -using Windows.Win32.Foundation; - -namespace DevHome.Telemetry; - -internal sealed class WindowEventGenerator : WindowHooker, IDisposable -{ - private readonly Window window; - private readonly Mutex visibilityMutex = new(); - private readonly Mutex focusMutex = new(); - private bool currentlyVisible; - private bool currentlyFocused; - - internal bool CurrentlyVisible => currentlyVisible; - - internal bool CurrentlyFocused => currentlyFocused; - - internal enum InteractiveUsageEventType - { - Start, - Stop, - } - - internal sealed class InteractiveUsageEventArgs : EventArgs - { - internal InteractiveUsageEventArgs(InteractiveUsageEventType usageType) - { - UsageType = usageType; - } - - public InteractiveUsageEventType UsageType { get; private set; } - } - - public event System.EventHandler? InteractiveUsageVisibilityEvent; - - public event System.EventHandler? InteractiveUsageFocusEvent; - - public WindowEventGenerator(Window window) - { - this.window = window; - Start(new HWND(window.GetWindowHandle())); - } - - private void FireInteractiveUsageVisibilityEvent(bool newValue) - { - InteractiveUsageEventArgs interactiveArgs; - var oldValue = false; - var triggerEvent = false; - { - if (visibilityMutex.WaitOne()) - { - oldValue = currentlyVisible; - - if (newValue != oldValue) - { - triggerEvent = true; - currentlyVisible = newValue; - } - } - } - - if (triggerEvent) - { - if (newValue) - { - interactiveArgs = new InteractiveUsageEventArgs(InteractiveUsageEventType.Start); - } - else - { - interactiveArgs = new InteractiveUsageEventArgs(InteractiveUsageEventType.Stop); - } - - var raiseEvent = InteractiveUsageVisibilityEvent; - if (raiseEvent != null) - { - raiseEvent(this, interactiveArgs); - } - } - } - - private void FireInteractiveUsageFocusEvent(bool newValue) - { - InteractiveUsageEventArgs interactiveArgs; - var oldValue = false; - var triggerEvent = false; - { - if (focusMutex.WaitOne()) - { - oldValue = currentlyFocused; - - if (newValue != oldValue) - { - triggerEvent = true; - currentlyFocused = newValue; - } - } - } - - if (triggerEvent) - { - if (newValue) - { - interactiveArgs = new InteractiveUsageEventArgs(InteractiveUsageEventType.Start); - } - else - { - interactiveArgs = new InteractiveUsageEventArgs(InteractiveUsageEventType.Stop); - } - - var raiseEvent = InteractiveUsageFocusEvent; - if (raiseEvent != null) - { - raiseEvent(this, interactiveArgs); - } - } - } - - protected override LRESULT CustomWndProc(HWND hWnd, uint msg, WPARAM wParam, LPARAM lParam) - { - switch (msg) - { - case PInvoke.WM_ACTIVATE: - { - if (wParam == 0) - { - FireInteractiveUsageVisibilityEvent(false); - } - else - { - FireInteractiveUsageVisibilityEvent(true); - } - - break; - } - - case PInvoke.WM_SETFOCUS: - { - FireInteractiveUsageFocusEvent(true); - break; - } - - case PInvoke.WM_KILLFOCUS: - { - FireInteractiveUsageFocusEvent(false); - break; - } - } - - return base.CustomWndProc(hWnd, msg, wParam, lParam); - } - - public void Dispose() - { - visibilityMutex.Dispose(); - focusMutex.Dispose(); - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/ViewModels/AboutViewModel.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/ViewModels/AboutViewModel.cs deleted file mode 100644 index 3ca4954bf..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/ViewModels/AboutViewModel.cs +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System.Collections.ObjectModel; -using CommunityToolkit.Mvvm.ComponentModel; -using DevHome.Common.Extensions; -using DevHome.Common.Models; -using DevHome.DevDiagnostics.Helpers; -using DevHome.DevDiagnostics.Services; -using Microsoft.UI.Xaml; -using Serilog; - -namespace DevHome.DevDiagnostics.ViewModels; - -public partial class AboutViewModel : ObservableObject -{ - private static readonly ILogger _log = Log.ForContext("SourceContext", nameof(AboutViewModel)); - - public ObservableCollection Breadcrumbs { get; } - - [ObservableProperty] - private string _versionDescription; - - public AboutViewModel() - { - _versionDescription = GetVersionDescription(); - - Breadcrumbs = new ObservableCollection - { - new(CommonHelper.GetLocalizedString("SettingsPageHeader"), typeof(SettingsPageViewModel).FullName!), - new(CommonHelper.GetLocalizedString("SettingsAboutHeader"), typeof(AboutViewModel).FullName!), - }; - } - - private static string GetVersionDescription() - { - var appInfoService = Application.Current.GetService(); - var version = appInfoService.GetAppVersion(); - return $"{version.Major}.{version.Minor}.{version.Build}.{version.Revision}"; - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/ViewModels/AdditionalToolsViewModel.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/ViewModels/AdditionalToolsViewModel.cs deleted file mode 100644 index 00486d6c0..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/ViewModels/AdditionalToolsViewModel.cs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System.Collections.ObjectModel; -using CommunityToolkit.Mvvm.ComponentModel; -using DevHome.Common.Models; -using DevHome.DevDiagnostics.Helpers; -using Serilog; - -namespace DevHome.DevDiagnostics.ViewModels; - -public partial class AdditionalToolsViewModel : ObservableObject -{ - private static readonly ILogger _log = Log.ForContext("SourceContext", nameof(AdditionalToolsViewModel)); - - public ObservableCollection Breadcrumbs { get; } - - public AdditionalToolsViewModel() - { - Breadcrumbs = new ObservableCollection - { - new(CommonHelper.GetLocalizedString("SettingsPageHeader"), typeof(SettingsPageViewModel).FullName!), - new(CommonHelper.GetLocalizedString("SettingsAdditionalToolsHeader"), typeof(AdditionalToolsViewModel).FullName!), - }; - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/ViewModels/AdvancedSettingsViewModel.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/ViewModels/AdvancedSettingsViewModel.cs deleted file mode 100644 index 476c26aea..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/ViewModels/AdvancedSettingsViewModel.cs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System.Collections.ObjectModel; -using CommunityToolkit.Mvvm.ComponentModel; -using DevHome.Common.Models; -using DevHome.DevDiagnostics.Helpers; -using Serilog; - -namespace DevHome.DevDiagnostics.ViewModels; - -public partial class AdvancedSettingsViewModel : ObservableObject -{ - private static readonly ILogger _log = Log.ForContext("SourceContext", nameof(AdvancedSettingsViewModel)); - - public ObservableCollection Breadcrumbs { get; } - - public AdvancedSettingsViewModel() - { - Breadcrumbs = new ObservableCollection - { - new(CommonHelper.GetLocalizedString("SettingsPageHeader"), typeof(SettingsPageViewModel).FullName!), - new(CommonHelper.GetLocalizedString("SettingsAdvancedSettingsHeader"), typeof(AdvancedSettingsViewModel).FullName!), - }; - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/ViewModels/AppDetailsPageViewModel.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/ViewModels/AppDetailsPageViewModel.cs deleted file mode 100644 index 627b674c1..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/ViewModels/AppDetailsPageViewModel.cs +++ /dev/null @@ -1,276 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics; -using System.Globalization; -using System.Linq; -using System.Text; -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.Input; -using DevHome.Common.Helpers; -using DevHome.DevDiagnostics.Helpers; -using DevHome.DevDiagnostics.Models; -using Microsoft.UI.Xaml; -using Serilog; -using Windows.ApplicationModel; -using Windows.System.Diagnostics; - -namespace DevHome.DevDiagnostics.ViewModels; - -public partial class AppDetailsPageViewModel : ObservableObject -{ - private static readonly ILogger _log = Log.ForContext("SourceContext", nameof(AppDetailsPageViewModel)); - - private readonly string _noIssuesText = CommonHelper.GetLocalizedString("NoIssuesText"); - - [ObservableProperty] - private AppRuntimeInfo _appInfo; - - [ObservableProperty] - private Visibility _runAsAdminVisibility = Visibility.Collapsed; - - [ObservableProperty] - private Visibility _processRunningParamsVisibility = Visibility.Collapsed; - - [ObservableProperty] - private Visibility _processPackageVisibility = Visibility.Collapsed; - - [ObservableProperty] - private Visibility _appSettingsVisibility = Visibility.Collapsed; - - private Process? _targetProcess; - - public AppDetailsPageViewModel() - { - TargetAppData.Instance.PropertyChanged += TargetApp_PropertyChanged; - AppInfo = new(); - - var process = TargetAppData.Instance.TargetProcess; - if (process is not null) - { - AppSettingsVisibility = Visibility.Visible; - UpdateTargetProcess(process); - } - else - { - AppSettingsVisibility = Visibility.Collapsed; - } - } - - public void UpdateTargetProcess(Process process) - { - if (_targetProcess != process) - { - _targetProcess = process; - RunAsAdminVisibility = Visibility.Collapsed; - AppInfo = new(); - - try - { - AppInfo.ProcessId = _targetProcess.Id; - - if (process.HasExited) - { - AppInfo.Visibility = Visibility.Collapsed; - ProcessRunningParamsVisibility = Visibility.Collapsed; - } - else - { - AppInfo.Visibility = Visibility.Visible; - ProcessRunningParamsVisibility = Visibility.Visible; - AppInfo.IsRunningAsSystem = TargetAppData.Instance.IsRunningAsSystem; - AppInfo.IsRunningAsAdmin = TargetAppData.Instance.IsRunningAsAdmin; - AppInfo.BasePriority = _targetProcess.BasePriority; - AppInfo.PriorityClass = (int)_targetProcess.PriorityClass; - - if (_targetProcess.MainModule != null) - { - AppInfo.MainModuleFileName = _targetProcess.MainModule.FileName; - var cpuArchitecture = WindowHelper.GetAppArchitecture( - _targetProcess.SafeHandle, _targetProcess.MainModule.FileName); - AppInfo.CpuArchitecture = cpuArchitecture; - } - - AppInfo.GetFrameworksAndCommandLine(_targetProcess); - var pdi = ProcessDiagnosticInfo.TryGetForProcessId((uint)(_targetProcess?.Id ?? 0)); - if (pdi is not null) - { - GetPackageInfo(pdi); - } - } - } - catch (Win32Exception ex) - { - // This can throw if the process is running elevated and we are not. - _log.Error(ex, "Unable to construct an AppInfo for target process."); - if (ex.NativeErrorCode == (int)Windows.Win32.Foundation.WIN32_ERROR.ERROR_ACCESS_DENIED) - { - // Hide properties that cannot be retrieved when the target app is elevated and PI is not. - AppInfo.Visibility = Visibility.Collapsed; - - // Only show the button when not running as admin. This is possible when the target app is a system app. - if (!RuntimeHelper.IsCurrentProcessRunningAsAdmin()) - { - RunAsAdminVisibility = Visibility.Visible; - } - } - } - catch (Exception e) - { - _log.Error(e, "Failed to update target process."); - } - } - } - - private void TargetApp_PropertyChanged(object? sender, PropertyChangedEventArgs e) - { - if (e.PropertyName == nameof(TargetAppData.TargetProcess)) - { - if (TargetAppData.Instance.TargetProcess is not null) - { - AppSettingsVisibility = Visibility.Visible; - UpdateTargetProcess(TargetAppData.Instance.TargetProcess); - } - else - { - AppSettingsVisibility = Visibility.Collapsed; - } - } - } - - [RelayCommand] - private void RunAsAdmin() - { - if (_targetProcess is not null) - { - CommonHelper.RunAsAdmin(_targetProcess.Id, nameof(AppDetailsPageViewModel)); - } - } - - [RelayCommand] - public void DetachFromProcess() - { - TargetAppData.Instance.ClearAppData(); - } - - private void GetPackageInfo(ProcessDiagnosticInfo pdi) - { - if (!pdi.IsPackaged) - { - ProcessPackageVisibility = Visibility.Collapsed; - return; - } - - AppInfo.IsPackaged = true; - ProcessPackageVisibility = Visibility.Visible; - - var package = pdi.GetAppDiagnosticInfos().FirstOrDefault()?.AppInfo.Package; - if (package is not null) - { - if (package.Id is not null) - { - AppInfo.PackageInfo.FullName = package.Id.FullName; - var version = package.Id.Version; - AppInfo.PackageInfo.Version = $"{version.Major}.{version.Minor}.{version.Build}.{version.Revision}"; - } - - AppInfo.PackageInfo.DisplayName = package.DisplayName; - AppInfo.PackageInfo.InstalledDate = package.InstalledDate.ToString(CultureInfo.CurrentCulture); - AppInfo.PackageInfo.InstalledPath = package.InstalledPath; - AppInfo.PackageInfo.Publisher = package.PublisherDisplayName; - AppInfo.PackageInfo.IsDevelopmentMode = package.IsDevelopmentMode; - AppInfo.PackageInfo.SignatureKind = $"{package.SignatureKind}"; - AppInfo.PackageInfo.Status = GetPackageStatus(package); - - List dependencies = []; - foreach (var dependency in package.Dependencies) - { - dependencies.Add(dependency.Id.FullName); - } - - AppInfo.PackageInfo.Dependencies = string.Join(", ", dependencies); - } - } - - private string GetPackageStatus(Package package) - { - // Convert the individual bool Status properties to a list of matching strings. - List trueProperties = []; - var status = package.Status; - - if (status.DataOffline) - { - trueProperties.Add(nameof(status.DataOffline)); - } - - if (status.DependencyIssue) - { - trueProperties.Add(nameof(status.DependencyIssue)); - } - - if (status.DeploymentInProgress) - { - trueProperties.Add(nameof(status.DeploymentInProgress)); - } - - if (status.Disabled) - { - trueProperties.Add(nameof(status.Disabled)); - } - - if (status.IsPartiallyStaged) - { - trueProperties.Add(nameof(status.IsPartiallyStaged)); - } - - if (status.LicenseIssue) - { - trueProperties.Add(nameof(status.LicenseIssue)); - } - - if (status.Modified) - { - trueProperties.Add(nameof(status.Modified)); - } - - if (status.NeedsRemediation) - { - trueProperties.Add(nameof(status.NeedsRemediation)); - } - - if (status.NotAvailable) - { - trueProperties.Add(nameof(status.NotAvailable)); - } - - if (status.PackageOffline) - { - trueProperties.Add(nameof(status.PackageOffline)); - } - - if (status.Servicing) - { - trueProperties.Add(nameof(status.Servicing)); - } - - if (status.Tampered) - { - trueProperties.Add(nameof(status.Tampered)); - } - - string combinedStatus; - if (trueProperties.Count > 0) - { - combinedStatus = string.Join(", ", trueProperties); - } - else - { - combinedStatus = _noIssuesText; - } - - return combinedStatus; - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/ViewModels/BarWindowViewModel.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/ViewModels/BarWindowViewModel.cs deleted file mode 100644 index a95cfef30..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/ViewModels/BarWindowViewModel.cs +++ /dev/null @@ -1,271 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System.Collections.ObjectModel; -using System.Collections.Specialized; -using System.ComponentModel; -using System.Diagnostics; -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.Input; -using DevHome.Common.Extensions; -using DevHome.DevDiagnostics.Helpers; -using DevHome.DevDiagnostics.Models; -using DevHome.DevDiagnostics.Services; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Microsoft.UI.Xaml.Media.Imaging; -using Serilog; -using Windows.Graphics; -using Windows.System; -using Windows.Win32.Foundation; - -namespace DevHome.DevDiagnostics.ViewModels; - -public partial class BarWindowViewModel : ObservableObject -{ - private static readonly ILogger _log = Log.ForContext("SourceContext", nameof(BarWindowViewModel)); - - private readonly string _errorTitleText = CommonHelper.GetLocalizedString("ToolLaunchErrorTitle"); - private readonly string _expandToolTip = CommonHelper.GetLocalizedString("SwitchToLargeLayoutToolTip"); - private readonly string _collapseToolTip = CommonHelper.GetLocalizedString("SwitchToSmallLayoutToolTip"); - - private readonly Microsoft.UI.Dispatching.DispatcherQueue _dispatcher; - private readonly ExternalToolsHelper _externalToolsHelper; - - private readonly ObservableCollection - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Views/BarWindow.xaml.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Views/BarWindow.xaml.cs deleted file mode 100644 index bd29dc400..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Views/BarWindow.xaml.cs +++ /dev/null @@ -1,644 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Collections.Specialized; -using System.ComponentModel; -using System.Diagnostics; -using System.Linq; -using System.Runtime.InteropServices; -using DevHome.Common.Extensions; -using DevHome.Common.Windows; -using DevHome.DevDiagnostics.Controls; -using DevHome.DevDiagnostics.Helpers; -using DevHome.DevDiagnostics.Models; -using DevHome.DevDiagnostics.Properties; -using DevHome.DevDiagnostics.ViewModels; -using Microsoft.UI.Input; -using Microsoft.UI.Windowing; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; -using Serilog; -using Windows.Foundation; -using Windows.UI.WindowManagement; -using Windows.Win32; -using Windows.Win32.Foundation; -using Windows.Win32.UI.Shell; -using Windows.Win32.UI.WindowsAndMessaging; -using WinRT.Interop; -using WinUIEx; -using static DevHome.DevDiagnostics.Helpers.CommonHelper; -using static DevHome.DevDiagnostics.Helpers.WindowHelper; - -namespace DevHome.DevDiagnostics; - -public partial class BarWindow : ThemeAwareWindow -{ - private enum PinOption - { - Pin, - UnPin, - } - - private const string ExpandButtonText = "\ue70d"; // ChevronDown - private const string CollapseButtonText = "\ue70e"; // ChevronUp - private const string ManageToolsButtonText = "\uec7a"; // DeveloperTools - private static readonly ILogger _log = Log.ForContext("SourceContext", nameof(BarWindow)); - - private readonly string _aliasDisabledDialogTitle = GetLocalizedString("AliasDisabledDialogTitle"); - private readonly string _aliasDisabledDialogContent = GetLocalizedString("AliasDisabledDialogContent"); - private readonly string _aliasDisabledDialogButtonText = GetLocalizedString("AliasDisabledDialogButtonText"); - private readonly string _pinMenuItemText = GetLocalizedString("PinMenuItemText"); - private readonly string _unpinMenuItemText = GetLocalizedString("UnpinMenuItemRawText"); - private readonly string _unregisterMenuItemText = GetLocalizedString("UnregisterMenuItemRawText"); - private readonly string _manageToolsMenuItemText = GetLocalizedString("ManageExternalToolsMenuText"); - - private readonly Settings _settings = Settings.Default; - private readonly BarWindowViewModel _viewModel; - private readonly ExternalToolsHelper _externalTools; - private readonly InternalToolsHelper _internalTools; - - // Constants that control window sizes - private const int WindowPositionOffsetY = 30; - private const int FloatingHorizontalBarHeight = 90; - - // Default size of the expanded view as a percentage of the screen size - private const float DefaultExpandedViewHeightofScreen = 0.9f; - - private float _previousCustomTitleBarOffset; - - internal HWND ThisHwnd { get; private set; } - - private readonly object _parentProcessHwndLock = new(); - - private HWND? _parentProcessHwnd; - - public BarWindow() - { - _viewModel = new BarWindowViewModel(); - _externalTools = Application.Current.GetService(); - _internalTools = Application.Current.GetService(); - Title = GetLocalizedString("DDDisplayName"); - - InitializeComponent(); - _viewModel.PropertyChanged += ViewModel_PropertyChanged; - - ExpandCollapseLayoutButtonText.Text = _viewModel.ShowingExpandedContent ? CollapseButtonText : ExpandButtonText; - CustomTitleBarButtons.Add(ExpandCollapseLayoutButton); - - // Initialize the parent process HWND in the constructor to avoid re-entrancy on the UI thread - GetParentProcessHWND(); - } - - private HWND? GetParentProcessHWND() - { - lock (_parentProcessHwndLock) - { - if (!_parentProcessHwnd.HasValue) - { - _parentProcessHwnd = TryGetParentProcessHWND(); - } - - return _parentProcessHwnd; - } - } - - private void ViewModel_PropertyChanged(object? sender, PropertyChangedEventArgs e) - { - if (e.PropertyName == nameof(BarWindowViewModel.ShowingExpandedContent)) - { - if (_viewModel.ShowingExpandedContent) - { - ExpandLargeContentPanel(); - ExpandCollapseLayoutButtonText.Text = CollapseButtonText; - } - else - { - CollapseLargeContentPanel(); - ExpandCollapseLayoutButtonText.Text = ExpandButtonText; - } - } - } - - private void MainPanel_Loaded(object sender, RoutedEventArgs e) - { - ThisHwnd = (HWND)WindowNative.GetWindowHandle(this); - - _settings.PropertyChanged += Settings_PropertyChanged; - - if (_settings.IsClipboardMonitoringEnabled) - { - ClipboardMonitor.Instance.Start(); - } - - if (_settings.IsCpuUsageMonitoringEnabled) - { - PerfCounters.Instance.Start(); - } - - // Apply the user's chosen theme setting. - ThemeName t = ThemeName.Themes.First(t => t.Name == _settings.CurrentTheme); - SetRequestedTheme(t.Theme); - - SetDefaultPosition(); - SetRegionsForTitleBar(); - - PopulateCommandBar(); - ((INotifyCollectionChanged)Application.Current.GetService().AllExternalTools).CollectionChanged += AllExternalTools_CollectionChanged; - - // Now that the position is set correctly show the window - this.Show(); - HookWndProc(); - } - - public void PopulateCommandBar() - { - AddManageToolsOptionToCommandBar(); - - foreach (ExternalTool tool in _externalTools.AllExternalTools) - { - AddToolToCommandBar(tool); - } - - foreach (Tool tool in _internalTools.AllInternalTools) - { - AddToolToCommandBar(tool); - } - } - - private AppBarButton CreateAppBarButton(Tool tool, PinOption pinOption) - { - AppBarButton button = new AppBarButton - { - Label = tool.Name, - Tag = tool, - }; - - button.Icon = tool.GetIcon(); - button.Command = tool.InvokeCommand; - button.IsEnabled = tool.IsEnabled; - button.CommandParameter = this; - button.ContextFlyout = CreateMenuFlyout(tool, pinOption); - - ToolTipService.SetToolTip(button, tool.Name); - - return button; - } - - private MenuFlyout CreateMenuFlyout(Tool tool, PinOption pinOption) - { - MenuFlyout menu = new MenuFlyout(); - menu.Items.Add(CreatePinMenuItem(tool, pinOption)); - menu.Items.Add(CreateUnregisterMenuItem(tool)); - - return menu; - } - - private void AddToolToCommandBar(Tool tool) - { - // We create 2 copies of the button, one for the primary commands list and one for the secondary commands list. - // We're not allowed to put the same button in both lists. - AppBarButton primaryCommandButton = CreateAppBarButton(tool, PinOption.UnPin); // The primary button should always have the unpin option - AppBarButton secondaryCommandButton = CreateAppBarButton(tool, tool.IsPinned ? PinOption.UnPin : PinOption.Pin); // The secondary button is dynamic - - // If a tool is pinned, we'll add it to the primary commands list. - if (tool.IsPinned) - { - ToolsCommandBar.PrimaryCommands.Add(primaryCommandButton); - } - - // We'll always add all tools to the secondary commands list. - ToolsCommandBar.SecondaryCommands.Add(secondaryCommandButton); - - tool.PropertyChanged += (sender, args) => - { - if (args.PropertyName == nameof(Tool.ToolIconSource)) - { - // An ImageIcon can only be set once, so we can't share it with both buttons - primaryCommandButton.Icon = tool.GetIcon(); - secondaryCommandButton.Icon = tool.GetIcon(); - } - else if (args.PropertyName == nameof(Tool.IsPinned)) - { - // If a tool is pinned, we'll add it to the primary commands list, otherwise the secondary commands list - secondaryCommandButton.ContextFlyout = CreateMenuFlyout(tool, tool.IsPinned ? PinOption.UnPin : PinOption.Pin); - - if (tool.IsPinned) - { - ToolsCommandBar.PrimaryCommands.Add(primaryCommandButton); - } - else - { - ToolsCommandBar.PrimaryCommands.Remove(primaryCommandButton); - } - } - else if (args.PropertyName == nameof(Tool.IsEnabled)) - { - primaryCommandButton.IsEnabled = tool.IsEnabled; - secondaryCommandButton.IsEnabled = tool.IsEnabled; - } - }; - } - - private void AddManageToolsOptionToCommandBar() - { - // Put in the "manage tools" button - AppBarButton manageToolsButton = new AppBarButton - { - Label = _manageToolsMenuItemText, - Icon = new FontIcon() { Glyph = ManageToolsButtonText }, - Command = _viewModel.ManageExternalToolsButtonCommand, - }; - - // This should be at the top of the secondary command list - ToolsCommandBar.SecondaryCommands.Insert(0, manageToolsButton); - ToolsCommandBar.SecondaryCommands.Insert(1, new AppBarSeparator()); - } - - private MenuFlyoutItem CreatePinMenuItem(Tool tool, PinOption pinOption) - { - MenuFlyoutItem item = new MenuFlyoutItem - { - Text = pinOption == PinOption.Pin ? _pinMenuItemText : _unpinMenuItemText, - Command = tool.TogglePinnedStateCommand, - Icon = new FontIcon() { Glyph = tool.PinGlyph }, - }; - - return item; - } - - private MenuFlyoutItem CreateUnregisterMenuItem(Tool tool) - { - MenuFlyoutItem unRegister = new MenuFlyoutItem - { - Text = _unregisterMenuItemText, - Command = tool.UnregisterToolCommand, - Icon = new FontIcon() { Glyph = "\uECC9" }, - }; - - return unRegister; - } - - private void AllExternalTools_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) - { - switch (e.Action) - { - case NotifyCollectionChangedAction.Add: - { - if (e.NewItems is not null) - { - foreach (ExternalTool newItem in e.NewItems) - { - AddToolToCommandBar(newItem); - } - } - - break; - } - - case NotifyCollectionChangedAction.Remove: - { - Debug.Assert(e.OldItems is not null, "Why is old items null"); - foreach (ExternalTool oldItem in e.OldItems) - { - if (oldItem.IsPinned) - { - // Find this item in the command bar - AppBarButton? pinnedButton = ToolsCommandBar.PrimaryCommands.OfType().FirstOrDefault(b => b.Tag == oldItem); - if (pinnedButton is not null) - { - ToolsCommandBar.PrimaryCommands.Remove(pinnedButton); - } - else - { - Debug.Assert(false, "Could not find button for tool"); - } - } - - AppBarButton? button = ToolsCommandBar.SecondaryCommands.OfType().FirstOrDefault(b => b.Tag == oldItem); - if (button is not null) - { - ToolsCommandBar.SecondaryCommands.Remove(button); - } - else - { - Debug.Assert(false, "Could not find button for tool"); - } - } - - break; - } - } - } - - public void TitlebarLayoutUpdate() - { - if (AppWindow is null) - { - return; - } - - if (_previousCustomTitleBarOffset != ChromeButtonPanel.ActualOffset.X) - { - // If the offset has changed, we need to update the regions for the title bar - SetRegionsForTitleBar(); - _previousCustomTitleBarOffset = ChromeButtonPanel.ActualOffset.X; - } - } - - public void SetRegionsForTitleBar() - { - var scaleAdjustment = MainPanel.XamlRoot.RasterizationScale; - - RightPaddingColumn.Width = new GridLength(AppWindow.TitleBar.RightInset / scaleAdjustment); - LeftPaddingColumn.Width = new GridLength(AppWindow.TitleBar.LeftInset / scaleAdjustment); - - var transform = ChromeButtonPanel.TransformToVisual(null); - var bounds = transform.TransformBounds(new Rect(0, 0, ChromeButtonPanel.ActualWidth, ChromeButtonPanel.ActualHeight)); - var chromeButtonsRect = GetRect(bounds, scaleAdjustment); - var rectArray = new Windows.Graphics.RectInt32[] { chromeButtonsRect }; - - var nonClientInputSrc = InputNonClientPointerSource.GetForWindowId(AppWindow.Id); - nonClientInputSrc.SetRegionRects(NonClientRegionKind.Passthrough, rectArray); - } - - private void SetDefaultPosition() - { - // First set our default size before setting out position - SetDefaultWidthAndHeight(); - - // If attached to an app it should show up on the monitor that the app is on - // Be sure to grab the DPI for that monitor - var dpiScale = GetDpiScaleForWindow(_viewModel.ApplicationHwnd ?? GetParentProcessHWND() ?? ThisHwnd); - - RECT monitorRect = GetMonitorRectForWindow(_viewModel.ApplicationHwnd ?? GetParentProcessHWND() ?? ThisHwnd); - var screenWidth = monitorRect.right - monitorRect.left; - this.Move( - (int)((screenWidth - (Width * dpiScale)) / 2) + monitorRect.left, - (int)WindowPositionOffsetY + monitorRect.top); - } - - internal void SetDefaultWidthAndHeight() - { - // Get the saved settings for the ExpandedView size. On first run, this will be - // the default 0,0, so we'll set the size proportional to the monitor size. - // Subsequently, it will be whatever size the user sets. - RECT monitorRect = GetMonitorRectForWindow(_viewModel.ApplicationHwnd ?? GetParentProcessHWND() ?? ThisHwnd); - var dpiScale = GetDpiScaleForWindow(_viewModel.ApplicationHwnd ?? GetParentProcessHWND() ?? ThisHwnd); - - var settingWidth = Settings.Default.WindowWidth; - if (settingWidth == 0) - { - settingWidth = monitorRect.Width * 2 / (3 * dpiScale); - Settings.Default.WindowWidth = settingWidth; - } - - var settingHeight = Settings.Default.ExpandedWindowHeight; - if (settingHeight == 0) - { - settingHeight = monitorRect.Height * 3 / (4 * dpiScale); - Settings.Default.ExpandedWindowHeight = settingHeight; - } - - // Set the default window width - Width = Settings.Default.WindowWidth; - - // And set the default window height - if (LargeContentPanel is not null && - LargeContentPanel.Visibility == Visibility.Visible && - this.WindowState != WindowState.Maximized) - { - Height = Settings.Default.ExpandedWindowHeight; - } - else - { - Height = FloatingHorizontalBarHeight; - } - } - - internal void UpdatePositionFromHwnd(HWND hwnd) - { - RECT rect; - PInvoke.GetWindowRect(hwnd, out rect); - this.Move(rect.left, rect.top); - } - - private void WindowEx_Closed(object sender, WindowEventArgs args) - { - ClipboardMonitor.Instance.Stop(); - - // Save window size if we're not maximized - if (this.WindowState != WindowState.Maximized) - { - if (LargeContentPanel is not null && - LargeContentPanel.Visibility == Visibility.Visible) - { - Settings.Default.ExpandedWindowHeight = Height; - } - - Settings.Default.WindowWidth = Width; - Settings.Default.Save(); - } - - TargetAppData.Instance.ClearAppData(); - PerfCounters.Instance.Stop(); - - var primaryWindow = Application.Current.GetService(); - primaryWindow.ClearBarWindow(); - - // Unsubscribe from the activation handler - Activated -= Window_Activated; - } - - private void Settings_PropertyChanged(object? sender, PropertyChangedEventArgs e) - { - if (e.PropertyName == nameof(Settings.IsClipboardMonitoringEnabled)) - { - if (_settings.IsClipboardMonitoringEnabled) - { - ClipboardMonitor.Instance.Start(); - } - else - { - ClipboardMonitor.Instance.Stop(); - } - } - else if (string.Equals(e.PropertyName, nameof(Settings.IsCpuUsageMonitoringEnabled), StringComparison.Ordinal)) - { - if (_settings.IsCpuUsageMonitoringEnabled) - { - PerfCounters.Instance.Start(); - } - else - { - PerfCounters.Instance.Stop(); - } - } - } - - private void ExpandLargeContentPanel() - { - // We're expanding. - // Switch the bar to horizontal before we adjust the size. - LargeContentPanel.Visibility = Visibility.Visible; - - var monitorRect = GetMonitorRectForWindow(ThisHwnd); - var dpiScale = GetDpiScaleForWindow(ThisHwnd); - - // If we're maximized, we need to set the height to the monitor height - if (WindowState == WindowState.Maximized) - { - Height = monitorRect.Height / dpiScale; - } - else - { - // Expand the window but keep the x,y coordinates of top-left most corner of the window the same so it doesn't - // jump around the screen. - var availableHeight = monitorRect.Height - Math.Abs(AppWindow.Position.Y - monitorRect.top); - var targetHeight = (int)((double)availableHeight / dpiScale * DefaultExpandedViewHeightofScreen); - - // Set the height to the smaller of either the cached height or the computed size - Height = Math.Min(targetHeight, Settings.Default.ExpandedWindowHeight); - } - } - - private void CollapseLargeContentPanel() - { - // Make sure we cache the state before switching to collapsed bar. - if (Height > FloatingHorizontalBarHeight) - { - Settings.Default.ExpandedWindowHeight = Height; - } - - LargeContentPanel.Visibility = Visibility.Collapsed; - this.Height = FloatingHorizontalBarHeight; - this.MinHeight = FloatingHorizontalBarHeight; - } - - internal void NavigateTo(Type viewModelType) - { - _viewModel.ShowingExpandedContent = true; - ExpandedViewControl.NavigateTo(viewModelType); - } - - internal void NavigateToPiSettings(string settingsPage) - { - _viewModel.ShowingExpandedContent = true; - ExpandedViewControl.NavigateToSettings(settingsPage); - } - - internal Frame GetFrame() - { - return ExpandedViewControl.GetPageFrame(); - } - - private void WindowEx_WindowStateChanged(object sender, WindowState e) - { - if (e.Equals(WindowState.Normal)) - { - // If, as part of being restored, we were in an expanded state, then make our window bigger (don't go back to collapsed mode) - if (_viewModel.ShowingExpandedContent && Height == FloatingHorizontalBarHeight) - { - Height = Settings.Default.ExpandedWindowHeight; - } - } - else if (e.Equals(WindowState.Maximized)) - { - // If we're being maximized, expand our content - _viewModel.ShowingExpandedContent = true; - } - } - - private SUBCLASSPROC? _wndProc; - - private void HookWndProc() - { - _wndProc = new SUBCLASSPROC(NewWindowProc); - PInvoke.SetWindowSubclass(ThisHwnd, _wndProc, 456, 0); - } - - private bool _isSnapped; - private bool _transitionFromSnapped; - - private LRESULT NewWindowProc(HWND hWnd, uint msg, WPARAM wParam, LPARAM lParam, nuint uldSubclass, nuint dwRefData) - { - switch (msg) - { - case PInvoke.WM_WINDOWPOSCHANGING: - { - WINDOWPOS wndPos = Marshal.PtrToStructure(lParam); - - // We only care about this message if it's triggering a resize - if (wndPos.flags.HasFlag(SET_WINDOW_POS_FLAGS.SWP_NOSIZE)) - { - break; - } - - int floatingBarHeight = CommonHelper.MulDiv(FloatingHorizontalBarHeight, (int)this.GetDpiForWindow(), 96); - - if (PInvoke.IsWindowArranged(hWnd)) - { - _isSnapped = true; - } - else - { - if (_isSnapped) - { - _transitionFromSnapped = true; - _isSnapped = false; - } - } - - if (wndPos.cy > floatingBarHeight && !_viewModel.ShowingExpandedContent) - { - // We're trying to make our window bigger than the floating bar height and we're in collapsed mode. - if (!_isSnapped) - { - // Enforce our height limit if we're not being snapped - wndPos.cy = CommonHelper.MulDiv(FloatingHorizontalBarHeight, (int)this.GetDpiForWindow(), 96); - Marshal.StructureToPtr(wndPos, lParam, true); - _log.Information("WM_WINDOWPOSCHANGING: Enforcing height limit " + _isSnapped + " " + _transitionFromSnapped); - } - else - { - // In the snapped case, let the system make our window bigger, and we'll show the expanded content - _viewModel.ShowingExpandedContent = true; - _log.Information("WM_WINDOWPOSCHANGING: Enabling expanded content due to large window size"); - } - } - else if (wndPos.cy <= floatingBarHeight && _viewModel.ShowingExpandedContent && _transitionFromSnapped) - { - // We're transitioning from snapped to unsnapped and our window is the size of the floating bar, but we're - // trying to show expanded content. We need to expand our window to show the expanded content. - wndPos.cy = CommonHelper.MulDiv((int)Settings.Default.ExpandedWindowHeight, (int)this.GetDpiForWindow(), 96); - Marshal.StructureToPtr(wndPos, lParam, true); - _log.Information("WM_WINDOWPOSCHANGING: Expanding window size for expanded content " + _isSnapped); - } - else - { - // We'll say we're done transitioning from snapped once our size is "valid" for our current state - _transitionFromSnapped = false; - } - - break; - } - } - - return PInvoke.DefSubclassProc(hWnd, msg, wParam, lParam); - } - - public void ShowDialogToEnableAppExecutionAlias() - { - _ = this.ShowMessageDialogAsync(dialog => - { - dialog.Title = _aliasDisabledDialogTitle; - dialog.Content = new TextBlock() - { - Text = _aliasDisabledDialogContent, - TextWrapping = TextWrapping.WrapWholeWords, - }; - dialog.PrimaryButtonText = _aliasDisabledDialogButtonText; - dialog.PrimaryButtonCommand = _viewModel.LaunchAdvancedAppsPageInWindowsSettingsCommand; - }); - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Views/ClipboardMonitoringWindow.xaml b/tools/DevDiagnostics/DevHome.DevDiagnostics/Views/ClipboardMonitoringWindow.xaml deleted file mode 100644 index 5c6bcfc90..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Views/ClipboardMonitoringWindow.xaml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Views/ClipboardMonitoringWindow.xaml.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Views/ClipboardMonitoringWindow.xaml.cs deleted file mode 100644 index d9e69c735..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Views/ClipboardMonitoringWindow.xaml.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using DevHome.Common.Extensions; -using DevHome.Common.Windows; -using Microsoft.UI.Xaml; - -namespace DevHome.DevDiagnostics.Views; - -public sealed partial class ClipboardMonitoringWindow : ThemeAwareWindow -{ - public ClipboardMonitoringWindow() - { - InitializeComponent(); - } - - private void ThemeAwareWindow_Closed(object sender, WindowEventArgs args) - { - var barWindow = Application.Current.GetService().DBarWindow; - barWindow?.RemoveRelatedWindow(this); - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Views/PrimaryWindow.xaml b/tools/DevDiagnostics/DevHome.DevDiagnostics/Views/PrimaryWindow.xaml deleted file mode 100644 index 56b12fa92..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Views/PrimaryWindow.xaml +++ /dev/null @@ -1,13 +0,0 @@ - - - - diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/Views/PrimaryWindow.xaml.cs b/tools/DevDiagnostics/DevHome.DevDiagnostics/Views/PrimaryWindow.xaml.cs deleted file mode 100644 index 40e5a2f15..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/Views/PrimaryWindow.xaml.cs +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Diagnostics; -using DevHome.Common.Extensions; -using DevHome.DevDiagnostics.Helpers; -using DevHome.DevDiagnostics.Models; -using DevHome.DevDiagnostics.Properties; -using DevHome.DevDiagnostics.Views; -using DevHome.Telemetry; -using Microsoft.UI.Xaml; -using Windows.System; -using Windows.Win32; -using Windows.Win32.UI.Input.KeyboardAndMouse; -using Windows.Win32.UI.WindowsAndMessaging; -using WinUIEx; -using static DevHome.DevDiagnostics.Helpers.WindowHelper; - -namespace DevHome.DevDiagnostics; - -public sealed partial class PrimaryWindow : WindowEx -{ - private const VirtualKey HotKey = VirtualKey.F12; - - private const HOT_KEY_MODIFIERS KeyModifier = HOT_KEY_MODIFIERS.MOD_WIN; - - private readonly WERHelper _werHelper; - - private HotKeyHelper? _hotKeyHelper; - - private ServicingHelper? _servicingHelper; - - public BarWindow? DBarWindow { get; private set; } - - public PrimaryWindow() - { - InitializeComponent(); - _werHelper = Application.Current.GetService(); - _werHelper.Start(); - } - - public void ShowBarWindow() - { - if (DBarWindow == null) - { - DBarWindow = new(); - } - else - { - PInvoke.ShowWindow(DBarWindow.ThisHwnd, SHOW_WINDOW_CMD.SW_RESTORE); - - // Activate is unreliable so use SetForegroundWindow - PInvoke.SetForegroundWindow(DBarWindow.ThisHwnd); - } - } - - public void ClearBarWindow() - { - DBarWindow = null; - } - - private void Window_Loaded(object sender, RoutedEventArgs e) - { - App.Log("DevHome_DevDiagnostics_MainWindows_Loaded", LogLevel.Measure); - _servicingHelper = new(this, HandleSessionEnd); - _hotKeyHelper = new(this, HandleHotKey); - _hotKeyHelper.RegisterHotKey(HotKey, KeyModifier); - } - - private void WindowEx_Closed(object sender, WindowEventArgs args) - { - DBarWindow?.Close(); - _hotKeyHelper?.UnregisterHotKey(); - _servicingHelper?.Unregister(); - } - - public void HandleSessionEnd() - { - App.Log("DevHome_DevDiagnostics_SessionEnd", LogLevel.Info); - DBarWindow?.Close(); - Process.GetCurrentProcess().Kill(); - } - - public void HandleHotKey(int keyId) - { - var hWnd = FindVisibleForegroundWindow(Settings.Default.ExcludedProcesses); - - if (hWnd != IntPtr.Zero) - { - Process? process = null; - - try - { - var processId = GetProcessIdFromWindow(hWnd); - if (processId != 0) - { - process = Process.GetProcessById((int)processId); - } - } - catch - { - } - - if (process == null) - { - // Process must have died before we had a chance to grab it's process object. - return; - } - - TranslateUWPProcess(hWnd, ref process); - TargetAppData.Instance.SetNewAppData(process, hWnd); - } - - ShowBarWindow(); - } -} diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/app.manifest b/tools/DevDiagnostics/DevHome.DevDiagnostics/app.manifest deleted file mode 100644 index 2be00b102..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/app.manifest +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - PerMonitorV2 - - - \ No newline at end of file diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/appsettings_dd.json b/tools/DevDiagnostics/DevHome.DevDiagnostics/appsettings_dd.json deleted file mode 100644 index b631d1840..000000000 --- a/tools/DevDiagnostics/DevHome.DevDiagnostics/appsettings_dd.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "Serilog": { - "Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File", "Serilog.Sinks.Debug" ], - "MinimumLevel": "Debug", - "WriteTo": [ - { - "Name": "Console", - "Args": { - "outputTemplate": "[{Timestamp:yyyy/MM/dd HH:mm:ss.fff} {Level:u3}] ({SourceContext}) {Message:lj}{NewLine}{Exception}", - "restrictedToMinimumLevel": "Debug" - } - }, - { - "Name": "File", - "Args": { - "path": "%DEVHOME_LOGS_ROOT%\\devhomedd.dhlog", - "outputTemplate": "[{Timestamp:yyyy/MM/dd HH:mm:ss.fff} {Level:u3}] ({SourceContext}) {Message:lj}{NewLine}{Exception}", - "restrictedToMinimumLevel": "Information", - "rollingInterval": "Day" - } - }, - { - "Name": "Debug" - } - ], - "Enrich": [ "FromLogContext" ], - "Properties": { - "SourceContext": "DevHomeDD" - } - } -} \ No newline at end of file diff --git a/tools/DevDiagnostics/DevHome.DevDiagnostics/errors.db b/tools/DevDiagnostics/DevHome.DevDiagnostics/errors.db deleted file mode 100644 index ff79df92a6bd1b66fd7d2ae5a112674d9057b817..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 856064 zcmeFad3;;fc_vH{7u*04k`*tqV;iy}OR~hP&9WlPvIGJk1(O6QfRserG7ORs35x`1 zf|SJAj(q`UYxaF#oy5()IBVA=O`4?3RGzkzug$bG(>86|W}0-HBwdp4dERr*#RWyl zcGAxLBmI(ViM;1M=bq(Vo_9I9ql2Y|V)RsHezvd>-P5wB#pi1|9F4ZLwD|Dp--oa$l z{qdG?R}_CHDwD-%G?gAn_9wI3)z8v}S^R7yd16HW;7D<1PW@nO0Dbh70y*SjC-KHL3Z_v!9pcfNb9JJ&tb z-QOMSKG40ldq?-y?v35ocVFGTwmaAz2>&$vp?8Mf z9C~f&<)Iga9t|yps-fA?RHzWTCo~$$gi@h+=wN7HXjf=kXjACM(E8B2P&m{c@&*4j z_|L)b2md0-26DxZ#?EtD6k(L%X`pUg)m zrVHhXVsxProvBn#M@y&ho297w9bd0TXA7qR^(@Z2uTK@LwllFk;NMff-a79;5sQ!H zbNO6mD4EV=lOr+gBlNW}Uno}#6APtE8C_PR)y0X4Vzqi|ab{*IS{Sd)FBB*3=#k3V z;+f+7b_}mnjpBa=Y{ts`WT{-h@4ZB}V_=i`b$M}i9OJH>iWbW=r7GW=FIFpy^PnC* zTbwT%;?c_D!hC6JdLcSqoG2_-F{J6@638#kOh)nb7}4AuhN0f?nJ+FBO65{{Dq1bh zVv0%=Rr~n1fPb44w$8WekHjHLWYU9U{J`1b!gOU)W>|e(aS~(k^yMABOu>AyFxgWn z&n($zZwdG}IXUZmizXb)jiuwUa+!TH66@=H&bD`(5mrQ(9^T(dRck2`0rb*hap+NLKWMgipibgEYBAw4f*J-%<8E^X@>izx=@&3u%o?&g^6iw zqA9HR+4|ugaQJO2v*p)2-f701#t-H>Q zj9V%{l1=r4E9LTivD9EPajBv4Q?cKpRWnmqfzs4eaUL6^#GiAdZr65lv*q8Hx7Kx- z{*uR%=@HXm@=URemkoi*ip=D6;S7#ZaUnXtSdK1~W^okG-5l_zoL$zsc0*?*mK(^Y zGx=k&!BoP~%Oy(-JaBkK<;%Hj<%-+G_Nbng;yKJW_o3T&0h@ZVR8_Nww`B8TF|(U2 z|A9qoU0YMfBgyPgDh*~Yb2U?_s=?yGxLxx+Vo7K9DH~ssU*U+%+m7#f0e{RHu+{~d zsHQVGZb zcW6KVCd+^DkhRX=MDR!~hgBLOLD2Iq$^y>{2W?Mn2>ACo8?1G$O-&Q290h4(H_HCv zM{r-@^EuUx(a1(|Swm?7-^?S6&o#?x?~hvky(w#*uc;plEuBjDyTii=O)SpOV`qYi zqAT(%d+0{XzYE)-rMW3smGCK`fzfJ@~w7093}IGW-?`k>>;s7>wd>h9-S{{AJ)_g6y$U~WU1 zbZQ`(jSZ4>k7bknsT|HnGBH#smrmm}VqOX}r_g;e?6SI7OCU4`LM&sb;Bbj_IIoLO(zYlA(IHArU*1I@! z%D(Gr%O5{!`Mwm-q>m-DBfEBDn!v1vv&kITUu-0mNskJr=G0GA%2?oqXl5{(8^Ih7 z@rSA0LS?=%RkRCNK?!iyTfXd}y*8I3fiki$!|f1oCx|Kb@ufA5RKc>b3! zZo%_+zwij2zw?C?c>eYmdhz_NFYLkdn_svZ&u@I5?|=RC{OxakelMP1`}{gQzxp}; z{5L+A#q%qlyB*Ijf9?i6zw|jgT7Lbr_u=_#pSAJ))z4mm=dXNb8qZ(;3@QK8XZ(16 z@ySzoe&NX^o}Yhm1D>CIvJ=nGewuH7=F=%WpZqjO_~}n~;rXdg74iJ!rw-xyiBIw8 zAOBPbo*(<<19*P)lYIXppXAR!{K>U=e&`eD@chM3+>hrIpXkT)gP+)r=LbF!!t?zf zC$+~v&hLHS$8W;(y&tDb@I4 z`PPqc-rn*Ne(9S(!co2HBT+ox_~94e`GybQi|6YIEv>he{mC@ulU6vo-co*jOQ;raU9Q=J#ibJFMZ-hJYVue0M8eHa1zfKeUM{Y z{@@xs>mT4()IM-4p3VojUXQ(h3C~C0&-HrY`w!sx$osi24?oVIKlFGG&lfz-bzFLU zJ)Y;@H;3oh_uYl(nfG0f=i+-8@LYH=XRP{OzBB)x5}psfhu<>y?nm*gyqoWr-+e8f zv+p{M=ghnA#PjsK_+1aY^L{)_@8q0Jzq1?9sdwb@JoS$KcoyHmkx#yT9?yxl58^rg z_KkQJ-p2X7|7{#${%xG4``$+1>&drreeZoMckDfH-G%4fZ@m)FvA1wtPQ0an=kd41 z@jUhx{(SV!oRg6^bM|s?rpq_`rU^WczG(>0;WzEXGxH{nD*eV8Jcr)MZy9{!&3F#H zu@%p|-awkEHypw9$Q!ta``^Gl-1mCUO!DsHEm!>DYdJG_yp}ujz-u|e+h6lSJomq58qepyhSc`GhI4h>YqsLK_cakbZ+-Pc zcJ$PRK zGM?7wzLb0Nx|eb`u6-%@>iU=P{9f}Cw!Qi#{I08Bd<<9Wr4 zvUsk2(Pli?EOV|R%iLYv%lx8no$DT|^ZW+uq|;U7{CC!(cy>5E#qAC$v^kug04K&e zhKJwg{;*sAuqE=b$ce}m-JkECgmwL{a4H-PeHV7`3q!r3aPa>NzBRZI+}-u#t`Bsb z?&|3LmChG+9`D@T@uQA+bnI&XllE7&=i2_J?UQZ!z_$Z0352cRv_}2EVUbg=)+y4p) z`p>feCl>6(R{)g)a4;W_0Yn9gLHtYpE*RwKaDtFYj+p&K0eBp?rGT3Y(Z#t*LL>IZ zwU&R!M$7l0OCe?`&{HR^?1O78f9jy+n=>y_Nd)DQIFZiW=SnMn4jsV4(D8lVv?+RM}ZE?%j;%Ua7bFO15 zDop`a!7VXUm?+w}b>Y+ER!b|891L(M7SG2AQ^V>rh6)p<@{V=qWgExXSPi%n{U|FJb#dx4@k=3(!uyctrKL+9%s+E(QFp0o{$; z0T4vxta|9B;O}uF{#L)H32=BMlhpt_us(6GX?$DxO6fKt2#EQeSuBdDlqR5_E7u2S zC;XOw>uG;$tD+1yXm$($qu7fpUyfF%#RmzGBi6PwJ6oLO9K$V`YYq4}I$?jSPm$>z z%)|#SNn?DbGI2V(2zTX-@`G@z$RRz0nHA9bsE@{@&)?djh-%zdIWHE=lg0TNBCTrS zsTpD#iTNtj80$V)!CUIrYLkimzoq4&mdLj5FL%GN`>ODN3lD~V5_%%EBlugv9bND4 z%5;9X^WILYf0F>o_-@SMBtU!rdmWw);jb|G*>RH9uLkzxZG>mR-@+#7wa;-=J=M z%@?8Xbmiz#9Sg7dw)BurD*r(5=vcmYG@H)DvwCDC2Ml3+aULEIdUdOIbgZ(d+@(O~ z!2o9G^iCLGT=KpcJv$Bm)e>IjF2+0v5dkfPh2SRzxWX1EOOl_!-Y3=n@^oa2buT0CH<5f^Z39umra_$a-fvGAHx ztB!K@@%?sbg_x92pLo*mr0p2fa zgHXfgMi=lq`&b5Iwi;e@|4M?xvFu1Hc2Sy`;Dr*Pr;E`|r{Pe=K=UqL*Ta@h(7)C^ z&gueOY_p;V7;Rg;pK8eI-!(Hx#Qt&F{a&kgQjC@r@~H`%*R z*@JyhKxe~2#jr-QnA>=EY#2g1pUm`eQwhF0F~2kiscM|F^rmBj(T$BDlS%p)$%5=+ zGT`6uTo(?0Q@$#Z?9aw16!J$$5t%U}-tmSCen{!A1P0$)fsv#>-7a zA6$g=-*41E~_+04^ylZ#lBnNMXZ3RYO?Ullgf9~n#~WCLy<~oAPaWc#-`MHDHSeQ}h2o!(G zL=5=-6oShZVO}*>e0C8k0_9zCo+?gb`uNQh)^r9#nBkv{41*Z5kKGyY?{$2g{*9_5 zxX=f4vAj46PS8<+4tPu|QT!OX8BPrps|5yJz&~A?pvp(jH39~Nt?6Idg9l;VEOz=g zD6-jPI@zBAuZ9uF`PU?54$P>*MvGI>UcD6gEez+m=?>@swa!j|RMAVNzYGMc zf*EFP0oDkeV67%?CwzOrzr(>KUa2TTjgAef5I26Q3Q|+5uAB}Nzyea`;=pT7HR*X!Y7S7f)8dLLdnmf18>|-Z~I{jCePO$6n#rjA-<4&OGHdBrkrVz7v(T^Lw z4O+@lN6Wf6f?{aBA4#Q?X=s?hLi#eJ=@nYaEF?&YfgXe^xI4J-Pl@rvPIyEpW9-4b z6jB{6R|r|q0w-ncbha-RPePqmL5O_6!3lvBfVBWqFfpp`hH~0(rOJ8SI=@Cc_XcC+ z_qog{G@zka8mdf|Q)C>3u8>t?&maI;VeEeyr3s*ggxsRy|B70MY5Bah5rf%?(zWm0 z1I{yMo$oT^;HeoL%V)#{mF?Z+-emurA`{GeYInfD%h_a|@6-fxkhO!!Vc_htxmW#w z2FFE6Adb;Yv1bm1$>{`e(CCE6t!l@10mzxK&Uff;VzkH574#DsiifX@1k>?dSVM@3 zDU70OPw(VVw_4}h4UNIUpDTD-M;+^JQ+9)iZ6~`U;6GS<&^q6yyYhIIl@phXD`*46 zg;A$wfdoE7-?Cx~2;5dd+r}SE{7|^lsmjbu1rbu(qpa94jZpQzf=<|fRYzgVSS}SM zF82SXmN&H^!hcuyZ+4#we?L4Q`lrxh=#JnIgD(kg==ylq^E)5!ob32Y$Jve>+rQpk zZeQQ_k+$0cj|U>wpIE!k1NzL&N95TyPC{^TDDSUa4n!+-Ns%Se{N zf0@yde5NnY&}z={vC7QiY%xd73|4vCjUz8aY1tDXP4%S^x(3a|oLow9nD9!KwVlWd z80wq9wZ)grW}%Y;VqiR4LbqztSM=F;P3ZS8;Wd}KV?YTC;)9LKFdE-&_K~Ru~j{vI7564E1C|w2-(fvt))c~}h zfI=Zx=qJ@P%oq*SG=OV2;#wrN1WqITzo7$&CbSTRVM+}EpF~F0Fl3LFCWq6+@v7YQ zbA^Rz+u3tA;4jo7H*XwVF*ayg5(u0`q&oB$u0WpHGq_A+9HJmGP=f)1%x5Cm7?7Ey#s{mFTH*@9IuRU{)2a;S3 z0p=u~V3?QQ5?XGdFU0OoAvXMA6~Z@jqd9?ngCqG=20K+LR6ORXjBw$`d6Sa{gAk|A z-Y^dtcVl=*SQ#!7+{1$(Ps-UVBM)KcgRpH5g?DtyE6GeQn?ztO@5QS|_Txz?Dj1}aJ zC|?-}l|D1(L+t2?#N#42U=cf+$eUPgiKa~+BvO}T(Dh_%qm7r06x3FIrX+^*m z)V@840}rfd{!n$a+8}JCVa5qx!L$jYt}uX^S<7Ep3~#QueG>X)@IJX&d?0^31y1MU z$I!cwa3a5;LTDlG5g>tc#IE)*A--ZYOfl9Y$9_!t>DfP*`NkgMG$;h zA)U5!MUn1|vGBV4gg`oWEY&ZE%Vn18+k{c;gc`B-p(G>MVU~U%1s#dz=rv}_g)^lo zrGU^JhWw+l38y5`10<*+-DW~-e%`Lc@RAWM*zx;u{&L~9x0&vG;h?}VA%Zj-hwYogc7)c4 z-E4#wrUw9*Fh`lvs*Q|0|E^Sc?OqQN-MSad7IF{bBnxpuy{aK8H`tHdNAa;Qytd1< z6xW}qf@$h6`Pi{oiky9jP0LhBKtSbqa++Nm+-UdajPjR-`S}8zK;#~}z(pngYEgNcR|p_AHpAV)wPJErWKb^sZWfaxUE98T=cyrvmE_?kpv9l3k5t%X39e)DBfB4ap#}|$ zgneL=4Jrt!GKJuS8T-DwEq}fgUfZ^MuLN@Pu~9e<`+w?{=;{U(c5_xm?ce;;uUlacC$ekYz{R?v4dxO6ltOl>``a;*?&aZUd(;4Xat&XGZ z-)sLw`-6x9_)^nkNa9XlKGwd>V=ad}0p2BHIi?UZ0Kkn=G6>9SB)%aPoKSe_1(06A(743J z{th`?EGyOz0v!zkLkJDPngJ{WVg~i8A7-dU=^F?eegH5b9gn{}tAWz%6u?O$?5qv>~3H~mfj3*iq zERbE!O&DJi@3hkNa}iS5eqig<9(JsmH00(6q}nRFJ_X3YtRtWbPNFPqyff-V1J;es zy2p^Qg3eW(2icrxQ{^IeeL;mJxKc>4@rK;SA*C75BwtsfuunKQT2_Dc@XgP=eTDHV zx?mo$X<{rx*M@UkD@BFL0^%d)8%i)@)i8~iOfWTYzruV8p(Rd-b3?#7?!-WR{|e&6 z;N0YzBbf~1>|ioNXsZGP$PFeBi<&+#Y8Ao)Ji_GBi!gzD0Ii^6APxFlO$suhY`)I% z&cM)|v1gp?1J;<+j-l*ZF%(3cBrq00XH%>TbdNsZlqAlfmrWx&U)fli<;Pfi@bTV;hmDe8P6pxyG`#mCylQz3{4L zP~8EGni+EyaQHdDCXHMfr!uKXM9>tTSXV@Ab=M76IE#Hi zivy|46kq_bENkmShr_2p}j!+kLHT=L{vBJ z+1@ytl~bp%b1}vN=Q$7qm>}Pq^@q{wABIbGw3n!{Ap*y*5J3l4;iRFdNdxxges3= zev|g?$h^1q450Pvn_J5{zesa!#oFV}nt-*}xf-osE3G+4qY~hmC$lhfWhUG+R~Q$L zD-2~!6fr_!8`yCxo9waAI1zSo=y14YPC6M(4M8&ZLJvEhN{k$d5h>3xj-)V&suc+6 zgFu2%1)DPtTamLw*svXN=tKpaEu1UOF3v{Bafr{BCXFS+U61`TK3BD$?{s5o`q3{T zn-qP-{XB|&Zm|*Atx!j&Jd>*p^c)JqSi2rY)6!5JPMsk+X?ZDdkV{I91Xqbr(o;30 zmxVU7LF0k?puLJZt=f}Lh+d2hAj{w?9=hI98W-G4&vqIV5P@?vz6hIxU!iv3Zu=o8 z$O%uO8{z}0{6K1OkbpmrH?aL@*^>!vtc)W77tEQaEct<~$L@x1UtL19G7Ji*D`4$& z4xsmwjoumjoP!bhvv)6%8dYk&+y@u-n|C?`)@J8M^n0)LOCG{Q|13Y(#MrFd$h+-h zPDjAn>IBilJ&hiIrnOUHJZ8a;JM95$n-IQR6BZf$v+oK+dERLYSi58~2+QCM$l2>d z>5(KuSAM3Gr`#_p>`$zJedd&eszTWcSk@tM^p+FSr*KNM)kWza5CB)_-s zb}T5^kAU>?3rY7ujx&`XNg;GWDU+1;Bc%lh^@g1Abn2{qVZh2b_rQ1Cu6(z!zFluD z;`I<@0X-=$AzY-TB{MYyD02+#yr>UX`NzR?qkT{+Mg+yL(ymkclA_Y!r#dK=mL9yL zJ01axtnI>>{2bG<%-|>x2f_kSTNz0P8v=Nz#tOx;L(K!ig`EwSPv_3en<6L*6KD)Y z!*a+Wk&qLkz-egM)p$urxvev25wqBOrE|018!Y0U^m)D5mQYI z*!&Vb;&#^*?4qW4b5*aHYAMqv{{O8lzta-=KqQ44eJ}04GyIp~*M$?I-w8bwiUi+{ z9DuKOjdVWQd3DE^Iwsq{+x~|3O>IxM&9>bc_(9--z!vLIt+TNGf6sq^>mRhfv~{oV zyS{V2LEjZ1`G5US+{r=%IQf{br8PSo2PVLv7wrH^CgL#QWqKxb8WH{WTovtVp_7U3 zwtdb~P)UM{&qF1fyi2rYm&$yR)r7ELK}907iuP7#*s?b5d#vTBKTSffLeQITf=peY z!E@843D>jIn_b8U0$e z0~gapQn5dj^#;`rXyP_-EA7oh?-BtDc$IUN%8YYA#PL(${&oxs(;3E=&Nz3`MBIp> z+@dBvnWZr+aMeg^C<&Wl1e;K=wpP^@ccFtCC6S14oDw021<+6y6+lKUNOlFx=u-vw zunUQ#ju)FDmqK_2QWJq4ar3ikD`&O=?XeIiwiZu#BY0QLZ6idqHE(t(q@vpz z_HrCL!C8!9ql{rF2h@V$EwSiOX=1)ot(=0zjmKF|fDSCcVN)pxl#Fm-8T{Jb?(~AI zfa4v$NvLI$^kwD~@L)voaAQ2RCo}HEFo|4_4e~nI!OdjlS2l3H0yd$_SJHc@fh<;> z!#q-3K?Y}%&~GY%R7)Hw%vX+8;Z$`OopY(C$`iz^F&5!xVE7E>c&-Q7{=PH3jH_`VyYHyBf78KSyD6I;nM437Ym zfdhk+dx|io!WU->h$5y6wB#J5TDA>DuNR_Bf@9=3TqL7u6ZJ-083FbqQm+PI&-fFO znTwt>aD9zk;kfwt2qwv|g3n(;*X&aFE`u42ze2U)<7~eHAzMp4gPv5;g?d&7a zLWXd)XFd=tIubh(i)I(gF_#5u72gD(-!WO4g)EUTyYt>V+!?=<-&CcqVkzqRDL(Bs z!W}$DS4me$_TH5M$2O8{6fq3&weiQYZ?T;TsxnrE`#G_M^@JLjU~X^noCZs`fWp@3 zaVdQWMucjdMu5#ad(Bi{Dg7PKW`JpFjsQ`C@Ozd0q+DBQ>)B!0+mOHz4`;fyHcXSTL(}w*oslCt!;Fh zix0ufMdFfX7JbTTXnGUo=CU4a7qeS{y6?2C)C8!lX{I(58_r8L2LwX*p@4Ejf1NGN zMbEIL19qMS+0Y2}(j0YmSXQP8nvrIjqyu-yFk*lEmG?s2{hqdpAbOC*TVq~}2cru8 z%Ep&dE9!2hJ2VQ#PqrC!tXJ9FgmyebU(uXT~GwAk^ppK2|ubVuZ&;*~(@H<8D!L?eI0)@(MRB zk1kzM*c_tqk2%{g#S}!rX8MR_zMu~@g=(p=?Nwa7D`}r_ZXwt4fp}MgIIUAX_{LUn zEd=^p8KG(-G3+#zI5V*lUV@@Pxs(eA(Ner5QF;Z*3qhn9jr2%hfx zPS<4Tw>ux|ytd=h9aj5O?Wf!Rt?iv{y8}N8d@3**xWf9ZHDU$*pYd;M{bK95@85i% z^xfxM)AG9@_RRkbIOpJbd+;%z?@E3SefNWd+7Zl6NR?g!$r}g60f}|ZBvQlh zUaUp{{WrpqR#3}0i#zOF0CUVg=TuStT5X&`Jq~!w6dt zBh2Sp+f4BYEbt`u?=vB%yo2_HQ>C}-N(^s}BBs-Xn_R8NqpGBuv68fn!Nt&wUgumv zc$wIGalqOm&OAJH522HY>O?VNLEmTvH?do;H;;ynLKWw@w##65i^x)J7n15h0w`NS zw_DLwqES)jN;TPx*!nbTIi*JDm*VD>0keg9L}(a4e8D3gbze@tJKHmJxd zxlf`^;6XE9hTW@yFn*7W?>=WXV8y|%e7>$#C?Wl15XP=#!mXgC^I``fw28HavR+XT#8%PFn$Cty0~6KOHd`O!s`k7}&y zc6G4a_40Dut=wo_1lKH-@EaO7sA&LfY4QLg>Zm?x?=p08=qScG5TjFek%2dg=K#F| zQ7t-!fOWvR8iUm$(94Ts{p!*hlHvfc0Y!ap=E&F%QpLppkoghZ`ea`*t zrxX2X>1fz20;ORJfrG_h79)UcVsVDGd7Q_L$NG^ z6$d5ZjweY|k%O$(T916OtOqR+LE}4R5R=G8#JLcBuo`vuCBPNEH@Dg^bWR4We&-;@ zp{1v19M5Kf76lcx?dXp3hvEIhQ1Yw1-}>k#o*SiZ+0!C0>HOBAM5zXj<nY#g0tLWzAoR{#8XPQT zyY;@_G-$hAdoESqZRmQxbgcq_a$`Asrv$0-^Bea8>Zt|ikt{kO)$_cLYzs#M%@Rzf zEDKDlL~f#qe+2zKziCsW3aQ8wQ4?Z&lMB~s(xVatsz+az5|g!WtE~re!`Z*BsU1?DMn{n{ z?QUXI))M{l7xv9H#DMn@=-4X_v3rhSgAT$GFifwExsu6F))3^qAH2xv#mjx%jH z+vr0DkjP3Kx5FgTEGH0&yJQd65cjb_Er(0g&4v%hvcD(p&XwTxX7FsH=aJ`EKw) zDl4nx*G6q`owu}I9hvrHv*IQXgTxtYiL(Cwt37#NK)QWy<7btUj!845H!DG zkJS*2zRiiC(;n$mtAF_B4DV7=jAfM%MGo&Oj9j!bV>~+18iLT{HHwSvLR^>}?lVJh zfRv3=zClk%&7-?WAI22LERZ*I+mKh@kq{>${D<78cY+fkKm{HSY&-xiMi1tjx7yj1ul!6@D8VPN`|v*GwX6S26Mg+zmKv?!Qr_4JS{RVk1T)Wg;m7 zapn-wzW+3ctEeMI8EJ9xfs5}@EiT0W?9x4jB63B0u7+6ly$)do65)m-V@i?l9gL-s zX4B~0!`75ekC;by3ymWz3E4Ij%7|I-cXA-Df{*mZNMum+Yeaa7qEDfu?Xa`c$~y?* z*DO|Vzdcn|6F1CjI3;$6@@JvhtbpHBwRUW<2@qGYOolkdts?C% z7_>5ZZ<(!D7bdsL>-NJn zi}WdVHYob6CX<6!>MmC;a6L7 zIUIl$;hm_6sG>?;$Gn<0J61!q`ew?UsOp^|jj9?JC=)p&)}?P8W=OQcI7PJ4RR$E< z&emF)GeNF+qaxx46JatMu~+Wd_j)Sm|L&m$f$1;dvSeMm5td}l7qEJqM?v)lcW63t zEv?Gjuu>*^ST#Rh%pjnB`294YL6*$`lM~!?0x}yLyJ79~W%}&hx>NdeN(iPF8A9-M zt%dxGO4IdfP-Zv46_`y*{n-ZD26F608@8xdRk9ckm%;Qfy2Y}(hgoUpa2g_7ejgR4 z=c>+haFq!P(J>Qx^s-i>X-fbSzg7%FV>E1cUI=%=4p6&JQB%xYM=~j1!|6o$5O5XS z>2(m@K2W1(d9Awu{h15{H*oy|;zJPZ7$0CAWvqwG4vDG2R5Y+FcD?w81Stn~?aq@F zCl!f=AJXz*78ST)rEIP_ZtOn>%t3jEyM2{zOd=-bpk6jEq~707#6igWR);G4di51d zqot!rP7mXxOwdll$L-d}W%(|571bv-mRAD z;kIHgZfNxK&p+*v#FAbAx@qJ(}76@L&AG^G5%7=v+=>k7g+*zAss`@7F|r@LpF{_yKzInZ*;t{V^8}J+JCwIT>I9xe{cJ0+k4yYYr8J+2Z5IcdQmO# z_pOIBoyITLL^^>iqT5s_EPv84}bH05T!hhbMOsxP5>Y>N{Epxm$0TD0A zTOA!D1BZym{>4-QFhafN(gcel69_zwpjk$SLR_0EZ?H%hbN5619R$VWilSyOu4^D= zQs`Z;fM{p-u38?p!!9%&Rt;$|>S92WJ)A?**91cma zgRAH?fSn5bmy8OgL(-(*+6QVUVRa6mZB(_D`UIZFQk&pnt&_ETnSPAcH>lQ(^A~qt zOwEx}IZbaS9f8{mbqidHV)xhX!2+BHo$D2y<6ukbf|#cvBqfzRlw!5JF`@z}t=Hd^ zOse{PF{1!qIGSp)c-lkb_SzVtmbiH96bh`e+~S5u8quth zFlFzoA^B$)S4XaYL3A?K)wEr`NxX)vpM7I!B3He*Q-`ce$-iwV!qA+=Y;3r!-MO?= zwG0-Z^jPaVmU&AA!y!}I_~>8^H9(O@RGL>##z~Zj!QB|FA?36490i%X%#eWcF~EN?)tg0W zo21yAjO`b{J#Vm>DUG901`5*7GyWeWkkxY#BYDN+9ug`Xcw}gpldFgbP(~^UEr%~D zYA@iv5LwM=Z2$=i8$jZH=3_FFu#no3(Wm3K+Fe+*Bwl&1eg%&8OkXdd6MUu8?>*q+ z{1l4Evc%`s8nR{fY(>NO=!X1{TW5kFWa>x&6hrn)&*EdPFa13;4s}FQD8Fa|p-W}# z!V>HU2o5Y2wi&d4*Pf7oHXO)t;Le9@{TTBY$o-}!mlz#J4Ls;OsYGH?6)r;pMuHT) zWTyd36;Lc~37iDUEjtc@#Md;5912e04E3h^b5iX_IV}}P8olk-=s+*}MIH-6)d{NSKbTEmFXcNbQ>P|6S0UIfb%N^t%ECD$hTlGjS0rrWZKeodReQ?n1c5_zx zO!acAjHsj{*=n2&x4bO(M{f<;D7#LAl&wkWQX+$KBBDykcC(2D+xH+|Tlm&i`_3AY zQ1;|Nq(>8>wFe8N5A!)9$YHZU<&;tj)tlAcRzq6K-fbYTT@#26VGc(#qd8KF&5k1r zt^yYq!9%c!!#EbZ@b)(Swys`lK0T@G+laEPxXLZHL+Ake?6F&P6NN`%vvJZ#nl{?; z+MP^|^5gBT`fbgOkpP0-q4zU52~uNWqK>=&BA>?+Kv@L#jBqM+fwez~$l@3X zZ_$M1_KZGwL;0PwRuIs3JefGk>o9kfh(+YRJ(zZ~%?2*NwnHFk6j4oiV6)*H4R@;ztJV6SS>vJOi+3{mnl4Yt;91#3eOEm!CUDDl}l zhT=7uL&?gbJzb}P%*XnoiF)`MxgVqFXG+}~2wdn(-c!D*Kq=1CI zxwacU;iR>!F++=qi!UxIzvn`#Jg-v%zw5^RhN#~*6HKGWd0#dG%d8Y0z^RM*RW zT)61g8fvFe^tJ@_o7~*1i{70zlt&^h44(7RMJc ziW-GGA^at(g`j9NM(sw$Dg?(1a)e=Z-`euxmdJY}cXt1<`zzhA?C$HnI{ZiBmxu2R zuMd4Dba$vL_+)S-cvaUox=LN4&QElfJ2#*fz)1T)wZFLSM{W7Go;H8r1A!BPu=Qos z0ld$;&i|DEHU6W1tM$LNzNj_l`>F36z6qb*@_keSeDUf={?0mFgq!1!SuInEV_;a6 zbY!#UV3>c?d$Kse8-MIQbrgQu+K(oubQ6?Wq*dQ&lh8l$w7R1X*WI2BS{0>L;us?B zfLSM!%tbU!n}6zQzPo+}I!&Vaq%>E81b4EUmhKNcjmGP6uWds*oYis#q!T_bjra~^ z+`{t<&ZSP<#p+-i2-XB0s}-C=r3@;Tsv;nY-`Tg;*Wg@p2G^=SB(6pLcq86ki~~=H zz#gqfuEU=jEy@8H{lj0OhOpj(RtS zvL7@fil(t8kHZJ8IUVb*BSKKS)YEl%t9C7-MYn1p>Jh;)K(N$dFj{*O;1`Yp|E>^ z?)BAWxkrIh5}BLe1+{bB;KoSY`UzMRfl%k{JL+910&x<=f{GaTZYtiGM$S@c z;(*7Fru>4`BN}YqS%*L9zyO+espeeAd@r@cjJik0yPD(F(6vKJMF!jbb$EUD6+ocV zLjYTR2nE4`lz5w?3ct)DOMtVYf?ig=HxAd~;@QS&>Clu0k)xkT_4N&+Xdq`nwgx>q zDkxc{AQFDkpsKy44$scUeIU`UNQlR76uJARB&VTb@2#VZ(B>h$+NNGjqXH)!mM*MO zrUMSS%=}(ujKIl(gqS*N1oc$VE@0ZhotH*RMt>TyA$*%TkW{GDc=;1!i3{%Tv25yo z?86dhS%#L5{D)@KG!QpxS)3Iro~!XQ1Z~_^M+u;VTn4`)rEbUsxAr8wV>_>i+Hphw z7Ye6wuH@Rws(nu#E|wkemFxS9!9&uht*wwJ$O>+tA~YJg4OI@PfKP^Z@Y_AU7ZWI{ zD|_3U>n)bGfr})U90RdQ9P2X&RSh9}YNjxSlU;+KV{;5|$|c9BS1^bgY1v-$vi_%s z_c>SAP!4Fn1CYlbRLB*g-QgodZr~AAU;xk-ugon)hZVj?O;eQmKYQ#Am~U0z5gUv) z0e%JFvgCZZfzMb+lwu@eD^3(|2$A?mB`$@IC0*CPcy1cy99Y}X>8inNa>zM}fpw{Y z#gR2l`vTXY7(L`tV>1rX#IZzUgzow^qD##AT=5P1tVsn*`*aP?j~Fr${C<<$c7`ik zB_#_eW=sm`Uwmco#h|N7v+=%F*?wSaxK$y1kDb}io2 z(A_DO2v*~+#gL=u+rF;`CkR4D{eBHx@>@_!`Uo?l)eS%<1NUM*@^eTowulKsM!rrF z*U1rg)sUe$3h>>p@l5jbQ5Me`hF`65!6BX2@D26zPGTf@ui6<5S|lj;04r3tO9Sz2 zinJx*h3p?y`M8vvDJFNQ)f>yfOh;{y9Ii`G?%8d#B#Fxl%ssM71fCV(t1vkUmQjV3i=0JzO?>(|>an6s zeRgzM5~L<86EcM^J)ZbQIbZkIkeYZ92#(*U4;UhsA;xuxKWhZ%QaWh@^cefvAh)da;4lOL+3s8aKI`p5+Os# zD%|rR$m)|Mo+1<6kYfpJ8}Z}hv@B-;RF!-eYvg7paf#gTv5(iv0c#V|Tl_wKax#Mn ztiXlq3|yW22oUt-BFe<->{pZn#U&Qrm{>E?@fz|AsZjfU+HnBN7u%t$6Q_B`ovgjp zp1@nv$xXExsQR1GhxQ^+5fhbA$=fRQKKriPX}q+Em$bVeOL+*P*6^4>+khydqr|8m z(}?L6B}p!rpm@-!$2Fu0_HbSG(Z;&M-OQ^WIA=!NZ)`Yd&-BD2*=$0^Jfpg~TU`q!pLDvO%U-jE(}MSMw6>D?NpIEu(@P;{Uu@jRh_Q_2Jjml4|H_2zqQ?N`>VEdfqw|RJa9blJnOHK6EJV>_Wy(bT|fXn-3AVcqXAEFy%l8L})En;2CP<2wk_33i8PFY{Db0;n2$5?^zOPP~3lIa}?>8Dj zOh^J;f(2QiVj?m{x59oYDQnfX>+rPf+KZO|wb4?#qbgfmxS*@ub$VGizNc0+kPG9I zywB}|Mmy^X>`Cb1zVj;@(IJ|FRZf(K5DegsZpg!s22@%= znGk!t-pe5cFr=@o91?@p5RIo2AL14C0XH1Y&Qwlg8JKl*;}9<`(OR*tYD zU5CpCDb<$mt1J8H8!|<|h4KQNz^@5jKm>Sa>C6c2J#1Y(mo!p_cRfJ zCn^Ke1vv9$<-%6aufvzLm!IumbikF+s|KdLCM-08ap@c{X^Cy`tiy}ca}Z4*bDO4# z$@dZiXA2dx=xMU64#yGTWXm@vD29BZ`rGI*kWCm@f@N?+F3!OshxD7Qql^`6B3ix* z?(O98RKA-o&}YuAL6X6q1lC~5KB?A+Ac@B9gv!cCnheVYB2?DR?r>V`sA07i8K9Q0 zEdAsFvkb*tqnFaJ3ZP{cc`w?mes*0n3K*y>7y-Z&n5YFEna% zs)E%`<$)!bRp-oU70R3TV+zAd9bg8Z>+G(k>hgA?4i^`yCRn~1=?y9EQWR5{J}m3Y zTa{`dl3D5U3O9lTmC!1Cy1s`%%vR7jt(QpDA_+0!yh&&YxFJ9JSx%bX=lZl_f>6vV z=G=&`9+0lEWq|^q1`=bi#yqu^F42#kFKm>R+hApkS-!rDn_?}xD|x%4ZNWGSe4L7t z0}S^wb!Z=}?_|2WA3aQ~H9*-*B8oIwnqa<5&|l?CfR63p&^tkRs%cShLRn&m>+b2BGCS@2pfS3r8YzOc? z9Y6fDaUsYQM#3xLRBlZy73^Jgcry2pu@`{c2+PD>aB*DcA)aNO8bTnDY*RV)fOLpiiK2Dm2Ci+-R4s)Ptw=Dgk(HY)Kn&NQ!y zfeQ~|d{U>89V-iBcO9-ym>rgnsE?3A9a78>Aw*Ys;`^R}hMjeKJvmywCXHk}sb+E5 zZ%WvCn(V97`3c94k0nP{KPvDDoM+T^Sz%BJnfwkNYxS;9Lxq5 z!)ufpkpwyND?)i%q_{M0uRjkofXe%h8X6KNDgS8DP?iS?fcJSC!#}!%k{+0!8UT6M zinfAWvZ(?HvN3jKY4$K4iJ^5-=S%E@kI%-LxvY z4jWutANI-mjXX9%&|72Zr8BYqetfdT>Z;MWh^8AOF@?MA)is>aEm%UKX7B=xT~%`1 z3MbzU2tDEfX~kspCtwJQnxH~8FX~=9S-&3ffRCb?&(ll`5)6$cb8%V24dH84>jD`7cRzjwWWF+IE^MhSzm`J{gVxL{4qzab zh@it+SeTRuIyW}N7$O(*3{zqlYjIP3Jy47uba7gD5zDa>yunQhjDbV+;m-Os@UMY` zv^*g1(dbhsmU**bjA~2emipCj)j$(%DM^!&G5Wloth||M$*sbiSl>YsZgJ86ejFkL@3AA8-3!+pF642EG|MhYEp@ z`2WuTaO+Q7zu9`MwF`0nCtH5Jy8r+G!A}cy_<#1I_?@+`n+h-y1Z@xGaRL1RcY#r# z;5@TAYRb!4aXgc8lr3dX$#hkcGAe^dFf?X&QfYh1>KgOP`FVX9_ z1H`&6Bu4#JQg7!WUO`Z|)KC=@{e>M!96fL#43=y|oVb`~nJw`Jxx9iv)}A{2G>2eu zt?P7q%%=KzZ3*W{DY3YZbPAKghDv>SLH%sNI*P&sR_hwM?g_g9Nr$T3D6~3h%bTRI zKQf|8!aD;BddS1Y`B4T2AnQ-%tx`GBTfxnf;^?t^Oo0M70@kk7;mkQsw{C01bZ)kw z`nM7yh;~AiU#-bXnJ+CNlzE2!R`w4u?%Ar~VyH8Xq1jHb4j0d9rep&0RgD0HNcfvlQ9Op{!+MOHzRFNcR} zTQt_V?u!O#E-_#`YwK_dRh$DDPWaNp0fa2KRs3uN;)27s^Na>HQAbrwIc=>WcTCLF zg43_*w8>Xt@?F!`T@Kd?;@;z+_k?@=>~tL-rUL-5T7#w&62~!y51JR?B+?u+KqPJ* zHNmPYT*Zd(P<#SBg1P~&&9O^$IGtjsiDfjQ(>NH&ezTvfrV@R!HQNvtJ2f#^neYz|dw*&kZS$svJ zLHq$QcAS1yw@$P_m~s{J4Pb|@9fq=0{&hndV=LX^I9lHRCuum!pDkGCz(_dtzYasFLZMA;kt^;s2= z)7sYPQ~^5*eQ0uSh^o?v8sur3#3|!VGY}_mNzrm?4O~D87b>Z^*d}W3w~KYE=ENST z!)b*Qw^plV$Vg7TgeJ?niG_pJaifzt41A~*eknwepaE4_6*9nHc!2h?59It! zT@9hxYlCVKl8A^+P^9Ss01O&o6XAR6aA2j*g09cd<>|R;A9?M*)v~lHGN9!QeWxeE(($q-ZcUTADL##()jAqYf|FR!+jdnnvig zsTDb=r^S7BIJ|b@#$Lm1NG>FpJB`rS5BVk@sJ^6 zY#d546bIjrg}zGlLFJi2W%_9YmB}MJ>je$V{zzWM&oFus^!TgT!fKNF4NBbas^1Ul zF;M@ZmpX=?W1UR{|22)Mw~mZWq}f`&|08YqG7MvYr})0O6&WALi{u&1#mF24 z?`zLulY;FA%}v@j*N@`>apV1+P)KJ0TJ)t(0O^8^;jKmpyFXPrXFtDw3@gK<`oHyy zI_ARk;PQV#3h~36GEGypKx96ES;4??NQy9jkx{v43a$QD zS`8s=t~Y}SCzP|n|0#c@P;|2*;_4tWfJIaS!(#2OBjZv)tG^LaRQ*i0r8@={-+=Zg z^2Necx74$k8E&k<)}u!EfP_s0&6UQP`-4M?1WNIheAj&$c4rLe<;wSAfHL+OAk463 zjS;~4D`_Hb58AcNcA^WU4_+bc2RCq1;5E6)9#W(6o!Y;2YaN-C`=C<#{!)_@c*L!^ z&MXJFp1N=e`O0l|Bu#GS3H^>9xKewu{(Ae9Rn4khWZzUrZsbOo4ZgpSx0SFnmbemm zIP`=1(Equ-gzF3psFX1-1!!Ci&(^K=0W_eG>d({|a7iM9#Bm{e+)SR=F)oF|N)tf9 z?!p(d+5eJe#(k22p#`Hq+2~9;P9Vo8f$RVQD2o06yp|8PL{3M7-OJsb;U~gZ!0Uf5 zv?loeU^;kZ*ROS*?22@Ly7TVNwvN}gf3Lla`~N=O77ctYP(nukZvP+qXZ<@`@Amz~ zS7`YM5c*H~lUgRm2L$MRW(V)Cu6-?AQ?qOELcV#uhMfM*&3{2j~4kRd~%g_|6)ig>TALgJ7TjK530Jeq$f z)B(i>fw2uQy2+cS9*)W%^HqCn8RZFg5U@NSa>r)MQ9})GSo@~%w9Y-kw|gRrB~ne$ zgkqV+otRx~J4csMZ*W%)X2SWPOFWgMvq#lv7KWwFnJT=E480VWJu>A%fOC&eE#Vqs zwVnlDPevQa-2SGgh*d;nwh@017K8*QAP5aDj^tWd*u;X=h&T2tnSDXAXzhfODIpesv_E?*0-@Cf?q(0yUB-C4x-Q_HyZet)eKl-o7sBT3Ym!Oi#aL@W)&MU*M59d|9$9k3qy zUyUtTnwn-99FPDd$KA7|f=nczA4|Y3sE^Wiq-CBiV&|FoX3(52F3ziSFj<_COvNfH z5-ndtE3%3Kwp}>DAr``+ws+|PO3#fG{d13MZ24*q3U<=@z{)`ZNkHx86x{bxHsh4~ zVxT9g`i?tk?$pQ<5rKf`iyk`m+%n2P z?m@Le>wIg|fRvuM@+4irQN`k*m8`PM;p0FxF%=W-=|&E}nS{P&WR2~B26ohhGe+EK>{0R=b>fPdQ8dKTQnu@h7o;E*%iY_Vz4Z5`iMBIn*^eBkV3?Ibf%4F z;1|j!#e0;YzH$X@XX7$5(e~Gfc|XquNr~~g_a1QeE`lHzyrH8erG{W^S=!?Dq`@ZEMgM0!YcY`4}97Anu6t>Qb4S^~m?i_eT_5u)Ve6K1QzaR`ikb5NB zp!|uE^Go)~a+g$)vDRI0=(|8<8jgIq%uGgiVrWp*BkVj67FmXO-<3^rBZMkgu-pkW z1~9?8YYkb1^wKw%On{I(ViLt?H*Q(ZEq6dq<=U)w8!CT0M{_|t6bTgeCmR!3C=3%_ zJAy1^0hK~=&0WzhEw@u+-2}4N7_xdRNen;}UFv}HkrJ^??UAlkjFJKG67~qu0Un6Z zEKV^x(#eb}o4mN(MvZVI`nuZm#Yk!i&AUiPz~5FGw({o}n(#=*VoO;qyMH-=m7}-m zD$`Bl#_S6wtMO6Id_SBhheOU5v3|Zu9|>P3x>(_R}Xc28z!y z6jAzZba)t&6z&kzo?s;b`0!kFf&1S*t{ALbo2?HlF=$kWTb!G#$fkyf^qMHBUcmy# z!0{xv4TlID90#aJE*w;44XSp28R>+nM=_*zjUh>Fy!OuIJ;6@0;kCFmI2%4v`!Ky@ z!Rl*&rhRT1IfhB>x0Glh(pR{mvq~?ToC35wj0y| zQ)N0mVpLWaAG96+atmE907llWHGP{|mMk8GiA&;5T;b6uvWvR2 z!u+eTVvwuwAfBuvyD{|;2C-)4Ab0{AZbXl&4@M|iZw%ar_U1B0Oo3TfQ}Bk~F62Vy z7E49c|AEjyhh7yL4Ecgz2u^nWQ`awa{$=M>$6t0l+_91ebA<_&x{v=u<`mc8f>l`%yBUI_U~cQJd(n z$H0R1)x%QZ9E`zyZUg66DOlVtE^gx0!68XenT9w^W!_#`MhZfVzW%3-b_^LTzCdLe zGYLopu?f{})Lv=81uBC2;yt?D75X}Z8_+G%42CGEo-(Smc9#(IW!f5~zvuR6t@|lx zMG{K**Nb=P`9#fYq}uA_a*VS0I@kg)(i(g=iE;^Jx<@XvIEJ~QP|Oyv0vKJ^EXR;S zUSyZ4`aX2FV!Er-40~Yk97-xI+3DrOusF`5mu20H7Wjj?^h~upQpwU%#M(i4Hx<9t z*^zP!f~(m;zjLlxmOISB-pbbRx`J#ZUyv++5H?}@-ZGA6{Dyyl&XV@`2K7L(Q~<+ zIj82B$FoB+4oTC(Jg94AU{Oel6>~Ua%g9q;_~Us;Q;iQMvjeKgCYPzPwMlFO(K0YY zO!*?^yIokmgR6Z2L>}`J!O=ER(W{a%M_PHESa8;J36DFY(8qDqaT=Ml$FLuGR;J-| zwf8S0!(kg-4ClA%USnd#r~5f>6dxiS1%0jRg(x-Nm|aGm!vI1W&u`If0XqYIXYLAX z_vI5KapobHE2lO>jhni`MwwC&phphc6U(?|d>`(C zv(DeFhjb#AA35Px(&1crXUS_cn}Ryhhr!m!cX401rwy2G`!cdJj^c(M>-;9&4dZbj zIr1inU`3w{w_%KshmMQq@kCv;Z+&4eMq%<1JS3|2*=6Ky!~{Heo*v0XM&N1oAJX&4 zGAfGgf%bWRqwaVlHT?6`&Ld6J17n$05ON zZ}jx9CFax2K?6d=Tx)&z|7Y&a!|Xn@yUyD8MQYn^yWO_Si`tTH{UllKmesN>U)?IH zZcDYO7RzeKU0qU@q-rfyu97UvPItT9b(bQfpCmvaFyvtph9?8V!^1imk|8k35JCvF zVPL|rjA8Q3gq{!x5Fi5+=JP%8@_X;Ck}Y?$jQ{AirTaVYcHZ-z<$KNnz>wEFsh>k~ z(JfL3Gh2NRX=OvZS@xc7x9HLa`5}ju{`9R!{1m5X)*;`zFH;|1(QuPjK_-WIgQQms zOV?!Qsn>Vs+8zhVzl>+*$hy6&2>fkHY^1_+3NOV7J**ESWWt@FtI>VU_ z%ETR(JNnbx3^#Fhys%|6Ka48Ltv9k08+-BYV?TfEp>Upeb!)aSDz{DYMRnu!_^_4Z_Z6plT@@-#Ed{eBoE4t3M18;kr8 zoep$_QAzM#PXBj|Wy(y_h$~yaZ(}#%9lK-{QYDC78HRcnKDydSiX54 zpQM=J+BNFmCiO=w+;_q39P}?91~oFu-_dXn_=_zHzxLQ&-0Y~O`*DZ37`c3c6zN(e+UVd@dPy5uIG3cT zIZiPe-B5;#!n*f(y06Lrb}AY~liSTc)vrCAwJB;6909Pmknjk}x`HtubVhEc5*88oo}${R2ta7b8BnM7nXRLV*M5VBIT29 zPQ$Z~+5fwm&NU7GB>n&HANcu!ss4Z4|5y6o?LXDu+4qxuZ}jc#eWUl@o=W$>?tY{D zzOG;Dy4}^=`J4%BNXwsS`DF7Tq})I2&u!48``mln z&6u@+1~)|@_}paWqlfaqh=Jne9lZ+ zwQ|K>`K0TDBw;=ZTkn+%Q+-fuKB0Cu7ffxQ@n@N>w(T0t>>Al-_KI0af_NtI1>}Z` zTZT)c;m)06y-o3itA|(pwW5zXm4XpvpgIq&V=aE*nvyAYtf+CQI-zCHyj6<9`O_9P zmX74AhrFFzDGS5SxOD+)#gB{Ztbrugkkihe8)Z zz4PG@_xjiHf`9NozX9lU&n$FZmoZBA*^4q=PuXP$N@KK##lK27HWs{X{ef#KMp{=1 zhnY~0v{j;TI~QKMW67GWIRkJyc$s(eTWcRiQ>QiIM(P#*p=pJXhAir5+iWT--^hCg zgtbTu*tQQ`W3l?w&$%M)AxZbByVr=*hKx{ijramQE==_3?~qU z9^7x@jmW;XabD$JK)-!JFEY?>uX=P-Js@d2g(tGLMR;yV4teiSkTt$yTJjV)Ck`wh z939!)8}oWN(GEVK16e+SFO*Dc`RIYaLP0$i=HeB*`D~B;82*)Om{AP_ke8QlccAe$wc+)X~w?{%W6TuPdN%|jz;`5%>hKknHPFv)V;^vs* ziW^Edbt=FeG-W?2AN>bUIy@_&uve1F%y~WWBPOM>k}20IKRSJLsfAsNO6Jh~H46p_ znu4Z@{P~ic4-yHkHJZG2b+aMGxq!lM_xTP}@(tIK%LL{vg3Y^{Gqj1h8} zc(&fWLF4ni6rODRpfe{<1vB8r=XgErg`N+Jqp1r#7ha%5!J!A!l@Y6dzwNT5V*j0>AA%s&^~zNgH`WTpAIqtVUwfbMXQ655@; z_@Zx05!E<1&dTt^cKo0{pU>He+0%Fy1!JWE`*%7a!@+nx+_v+UIa^(gOddBuVbwv2 zMOkST5EifK)d%4A0Y%Mnk?8-OdB|z2(@weuCc5R2UMW_%du)a`%9})Ssh{4M6)aM( zacfS!kT`gaNAs;$u#?hEH2UR4>ed0r8Ml}{U8nJHVFPbr>+UmiFP%}>tc5k=#{OO! z@ar2h0su&DZ)upGdlaRI)s1xvw> zudmTTiYU1&o2n_9A7^9(wE9UB7v2xxU_K)59+!gKL;aIP#gqyIufOd3DMg>E& zy&J&S_Z)#v0P;d7Af?i&vwAeW?Cb^r_M_hRen_ zK+aRVvhDoXaJET4A{W^%5Mu?_0p(U7<8 z{eYQ`C+w6Q&GD`IInPhdO!SIQuz*tjAK9P+-ah2_`vKz0H4-HfWIZWNF-o0DCH)XO z%Ktyo^m9#vzc_enaB$#n5B#2iFANO!|KAt!wXgH|<7P z`)(&{CN^gcQnVfCU6T|=dakOk4Z@1*RzXb^Kjr;XUMS1kRfODAA{Rh=M153Ik_vm! z%L_x8H1$SYcDO8u)+s*yO!}#7IIr*G1UxL!zBZ6`w%$?3g>?X3xVveWz9#u-WVmir zRY{2>>p@Ox1z72;#k}xyc&**#^5`6ijW@ZvyiLVv{P0Kuyo5_{u_HO%Y^;n^>yY;I zNzG%1nuQpPQ&#TSD)wpvR+laG8h8^*_OkH$V^GqU0EDIgP4-S1_tr_O33WF;VFcB7 zSOup6xljub+9z49YsQF#M7Ro2bc5_oIY*hH)GD)OLJd^cnlVO@&0NO}AjR7tq{s_B zx4_`YjJ#TYOxwDT(I407(`19GP^5dW%>YXFg5f?{vmg-$_4W* zU?byPAXkdChdt#XGJ_5?+G94_IV!o)L}p0%qlT9)d#3zoTie6pv?2Xg*O%wd05Ew9 zaCir^7t2(Cd47yvKdN6JC+O<;(3nK*1%rqW;#s=4-tpHls%bmNA%W~%H%#AT7UH0Hk;6TUwwboh0}!*}G9_IOpM%z? zMQgfrk}l7PF6*~v^_W=A0(cmdb9VL;0Y3S{L$qInsI{D(E|cSMcnLBOg(=NhlO$eH zz*NQ2I45iC6q(5>0twzlImnAyu}tL_ij#IXeM;o~?!qnbKHKegSWrC-*)`sNwV6^_ z?%8yspD$C_<$zB0!GsEy1DdQg9@aJ1F>(3D*}gj(i=nv7kxP8{K>cFsCa@A1RxA3j zX&fq3{^d{sa`)Gh^E0X6nsg$2%XDKwm*{T#q`u4YC z)%T>|iY>Q%8sFyZKzS$g)%rf6uN0wCTbA+S)Vax-VT|M$NFws;Yvw;)-eF0Q-Az07 zjrPz~fe9Dz2pWld>>nuuCx3Vk1MJX`sVy*8AOVx)CExjScNuK>V-gaB`hg30cv20T z$VeHu_frza18!g{EYNWDTq*5WyQRx#5X*AM+6$2FDue8P>>zadJsl252ikC$!{uH! zXP)2n>32GOA=Q!7gfvFy*Df2++R>TVmD>=VGVZR$widJFWsuoqO?Nl-1~QE2sAyF2 z+eZ?4rVI{ymkz2Y5J|bh?sObD+gk>F{nSx@-5q|da@DZ|<*;6#^?;+04TJ^Sw5j1TPkoXzXs$?v#su?j_~U! z>B1;cxMdHQ0W$A;lwY@pUsEZxAmVbsW{;HVPV&SP{C!*adtNgAH4o1vG6Nne0}_7X zVSdmWe!!mV2S^;qH+%9e;cs=Y`fKb*ecj~0ZVrDBlu&=o|7EXjd|g_7>$_b|_nW_l zdI`=ERfhv{3Cv!w1r@~UTLEPQRvbSbf0nz)vafG|j2!_U(be=xqYi4jFg<7J_BrJ{ z&mE^NNueMKoPUM@_KyAN0iC*ey|5<6^2PALH3Khw6M=Tn>4;t|@zU|CgX|L8NA)DNI2ST?Yw4o%|#744gM#ivQGgG)M_wI?w5Q#A>8)_#W@-uV-nfZ; zI>@JZq4-pyc#>Aex{{&JtQ(9Iy1~ZI^HW?(8l^av&Yp#E%wev%vF#?Etc~fe@${d8 z5Y8V@$b8Gmk5b)`xVm?6WuqHZG&=e^pEld4u6C8{^=sQ0yCRsY$YOvPVNPQBP4hm0 zqZ@C4e?0eYXVZ!eE)jDoSO~%Qrj|#`H!odAI;&u`LTaWnu3gCvZBU=+sWW_kHrj8r z7#T{7j>V>hhUD;kpDk`sfaoAqcRQP&b3^N;kGUU`Kki^LtgY=*kZM|pwT}1q)R`nh z3%5ymLFajMY4wJZh}9VD`r_5>%m$^1o60x`}wYaL>|Bsoj=$4y`4{Y{A|a*_J7d+!|lUu z|9e}lZC~p@ZT<1qb1na%<+0`;X!D{^J+Jk7+8M!H=;%P;e1n#e={&1K zSr5vwN7vAi=9146TT)xhL16>zuYSXjW`OZ93Gsem=4R`Um(R%Y`VcetY@ET&Nm7IW za9bLhKSCafygbqM#Y@Z7)HT?jq>f_v3L9%?o)zLVBqMn5jb&F83fOB*W?fU(8m93Q zZ9{?m;}&(kaQEN4nZzEJxk6`y_5SjtaP70q@}QgLEX~lzOVcV*7#y;$MjIZwXf21S zNfC90*#swsO_TsuZ?xLx3elYd2>4o90C`&t)#crBm|WTV3*`wx2T@jApK}x9e_c+{ znTb$?$+4}s+{0Yz#BIdTF-D9?>AuUZ;~AtnKHB@jU;3#YMmrl;`_X}icBTvM8CoTZpO2@-Pp=ZWPc>5bX>@~A)t_d|D=qf6!< zb#s)*C+$UKlW9nn!i%CyZstuk0^k>dL~JHo0I!tKrj-2xmP57pvWfCZo~y4i#*=Og zg^1^-PmLJ#?1B^`;60ATy@*Lz%}XzbC|tWj(<3Uql~1r6uR-x~N71ls_-sn!#nNQK zXQ0v+3ttZahzmWFwo=XmTv&#D)##Vc^_WACaUc|zUlDronD7&2*ECo0hXtoyi2%HLL+fm3)x7y0N>!fYW<`?9%*=|FhRwZ`Lh>=d?>jdA3EoM`JOV#LKADy z+3D!;vZgKY#!uRRO7NXiQek9fx9dzt^Tx7)-z8-0g(`QRCM1Wx4*4C9yhp=LE60lV zsOi;=dn`Kc96g+s&Gw1LYXVl2Daqx0Nh-m8P#$!Y{b^AK6F<8PH-^K4UVb=t9!5Lw zAjMbBGnbtylLqwsEyfs#o0IS<`;oG#P`$ZZ**{B-`=5QOOj?lg+Pho(9Z@d;@9G9% zAKu`6!(qk?q0rBz>t>J~ERz6q;28A#9DP6+WVJbHy7rsslU^H--tubmT>0~YE%ftQ zZ(J)lT?(?$wL2s$$JGR8joc*D@RpFgxH6XWB1)R96I^KaDy(F&e3H>dw^}6oZp@7tuk3Y`@lza(;3r7^c9pR3l0&` z_(dQcGMaqnJlk@&Yc3Y_EIlETKMY$b{_)#cDjy;SsO#C~Mh=mn8O1Mj3NAzunb99? z3@e#@F?%|jE0epU_8Q%^#7vjrYd4G9mX)}9$Xd$9T@WYQJua>Xlp##U%jD=hqX)FZ z4WLsY`0V0U3IjTuS|92}>*^SjM5E_Dy$ZOaX_+G5I*l)F#{4hBDR+Hp&UY`QrppJ- z_U~?ObL6bF+c+=0*;yiX+7jEQLjb4{<<#!e(*-q1Gm9$~SJ|oZb5Om)BwHO-*UlS2 zfhEV=wniljNT6O!jwNU*2$h@Hu|#?HRf+Bku%a7U*G6hp}6%HoBpYOb!rS2otnA7*k9hE zQ8|Ujyl$pLOBC`V6&i+ii~b&>D|_Kk#g8%#I$N?VU8j07@93&Frh*-{7b_T1F`ZQA zRd%dQzKV3%roEz4&qXMpF?xo0TXQ-2lu9!EpTF0mWztj*%ftPwD0sa*REqTR^ZZQY zd%crtK3skp5g{-4Ga}{GtLZrI z;1yNU=1N3f)nUp|iZ+e(cyY1s_Ad54?yCkzMb4Y~)$%Q<-}y&6+d5uuf2Zx2+K#pUnU-H~ z{)>G0|C4{#Zq7G$sF~IIaCXN7?{KdlZ zwcrv3(rG?m2#`C9yR7WsGT!>PDa-KN#=*81@>Nh!zPlT?1i z?G~49`m?i^i5dKSI;*gBuF848@pWmK9;K$VEiFOK3oKR%>Ak}To>@Fg$rNDh1>64p-gs3;XUcL)Bx5oQY&hfKnSf& z(O|rvf*VWnuX8md;z(Mw&d#|db{A2Qv}2lr8FH>*VS~rz<1Mb?Ds8`rm&;_WjJ!t- zzV*zuyr>g6aNCSI}|qf(1;_<`UMGT|k-$40I*^o`+dMf{7?yf4L+>6x|J(R`uH}17GByrCtJxBSs@J(zml0yQN}rLwwkAiX-Eqqi zn)i{n3r-!^HAi&V-zQfRdCRY}>GC2fi;UQko1fis=MYz`FGw0^CXxgjdO+I zru=B2Cn*0ewWD>^QAHM>BAPAO25LtXfkcmuw;Z_P)$#=kmUXwDbYG3lo+haq1cfiz zWWJy1qf2MyUYwN`R;5Sg=G7ZZICB-3P}aj5#vaKq2dD$p-Fm{&R?O=-Nwi#w>7oT# zkp9u&il)M}vm=#e?%-`D9QCW#dt&$Wv~^c@ffw4Vk_k!|byrz5Dq-3B%VqLlj@e}# zabqWsXXt`1F_!OQu2!X{iO=l_&MVhlhs7fGFp79^M%j{Sz#Fs{-4as!g?gQG3Yj>G`k%todlP<>RJpdOC>3aFJ9K_P^g^y7 zj!ZL*Y!OWKFP2G}IYKsdck6LCENWJ;z~)AT*wDUtH?&4D;6}cWjY?@~;R%`SVwnt> zW9B0&q{IupqzOqA&cfx#Hs3t2BV@4g*jgp_ReYr3D)?75Kg?{j{5tlQT&^$Y;{=P} z7x!WBLV(=Q-iFlv#NA=e#WJZa1@KU<#~i8Y(b*YE6s#2~8dlH-y}?P7waYhe2*T}* zKPeBF6tTi1PBKeL_V-JkN_^v;Hz+XWbpEb72M7D9>6t|@M{{^drN3tDg)+%4?$tT! z2>Tb?ikzkSo!(cS-r%U7M3L%IJYMms^F{BTogCj|Y3uQ`JkQz_cTQ{P8+Wt!JKG@a z>-D(HWy_(Fvj3u61EOoPV4b{2LZ5i})p{FF7F>8mXFor583WPszvakZG*0A)Oy8v~ zkQx`Z%Za;J%5)YuCeeGujT8$^MsK_cJn^4}@SHQ%ROPe@gb*R=?qutamC1RTAjh`5 z_4EFOXUJpa^%o9JAch8m&Q*j}DAAiM(PI>Xl)7C0=n<2aTZ>QU_R5W5#;?UyZn<>2 zmt51jkSf=YRG58~%II!A?B*EIIILH`4QVZX`!g=|yP*BXrRl_Y`%Qc5k@IG7bDwEezw7BXaH-g{h z>2pMb#sbV+YpUC^a7|$z^CGO>yq3Fv*u)?ZLU>TZ#^1f@CE{m@r8fz7nwyEaObZY# z{rz)pF77GM{nCk(D86>NpPKbuU*O@~?pno|3kcQ5vH-b4VoXXX+wA|{O+VE%c<;b# z{eQ6kg}z_td$IR_>HR&_{_pDf$)4e!ZtVXHUBBJ+ySnDO9_;)(or@j6-SKwEuJ&)W zf32OkOWU7myVm;eT7L#)|G#YcX3L|^f2?`3`5_4Yr~l{m$|v)AK>;Ulm3q+t8;YW^TbFRA|v^d#CtUae5D z`Wbl&hx)^q(#giAPmW`o;TTJ$ON`JmX~~l9|I$ky#4)dd6pP#ucD_P^>LYTK5A}uN zSYimBOY1EztyQNL0dl$?18>OFyaUfEU~XUJxgGf9xW@pw=Jh@ymmvq?6^%;X+PR+t^G z03_avsxj0Z24la*1buH@gMU}qZx0$5Q+(bQKG)N2@bL5ywo=L_DnOPGpj-^KhEJ7X<3b{6 zo7@J3dwEkQ9(mYfh;ukw!Xz!H>7uXk3AE;G64OM}g~$JS=*rpfG3aO_g>bosefc zqWq?^#z;YraT4ng2wKCS&n!~B^iBdU>OHx;oco^yKnzn;zp#Z$n;dDqOd-m6KLuS> z9ixgH8aV7DhWAoUhhuf;T}>H>+`e9ERiV2l7$!anl-#F_-R#WBw4g{T6l)@3TX7nN zL)5xS>hn5aeytIvuGr#Q_HqRz_))x^JK{^>o(Wsh7S6oE?&3$fWKWZm|5>pDT)Zd} zQSi$W6$EyIN(NDp2@V3eEJa2;m{DuBwLKLnL1&jp(xmA)>& zL+irfZiZoYxeV02D3fnTl+PqfmL|=i7_XMLYmpXNR}qv8dyU7oymeu}w7^^r;G0-l zF&;c$26t`YXJY?IDOM3nKK$hXZuG@abtNa&0iI}ncRPEd{I(W|HMS!PWVssDR$}Tq;cf(9Fya#51UEmjI5~p=$ zEggV&JAAj30lT#7HPzPF-Ee_jEEyB0@l=X7_rf|RW^(A5XK*x6l!QudlK{dEHf6T{ z`SKfVusPRXbE9B8yAV%eiflEpQ{_osA5(!7@4NG~NM?OZ|9YP0;H4r4%Eh|yWc0mf z>(7^0GbYx-)_;5P?52L9l{X#YR&FZcc1zN5Y0pz7bB=sDK? zKVtp=YS#~Ro#<*M$N$S6ze#?7rQ^kpw)UTE|7QCa+jq77rM7C@nYK^2{{7Y;Yn^O; zsOA4``Qt6Gv~A2?w4f7(8sDinS0ad?^47IO;? zio7V$i=yq*CyrMDg&q~1heXF(sq0JCIrJ3oh6p&&!?O_il!)lXP)@ZJ5hZQWl(=yl zCgmiazlOa>GB5M-+yQv-?~H zEazVF%O^$F8#YthlC0yD=PECf`=}4^(}&|$_qn+Bd>cLjglQk$8$X&kjt}Rt1E{6$;%uyoJn|!eM!tIppg_9?Torp~_+0P$&cYKOu@IRPgH# zBrNI`D+gppD=!eK)2essOB8Qx8?|1Xd!?jKfZH%e!v+9=v<=vy@8$SDjemN}%pOpy* z7I%NYK9#1cd>O-0eV8bjO?vWR$(Ux0S83_S;$CmiM&bk;rk=5&d+fZLuD(arRnK^pEo%U9j{YI1lsX18n^ zuKuPu(eZo*sNo(Q82h{Qz2Mz08Ewng6Ik=S_bv%7J6WNw^)uJ_u2bJ>TL8XIgQVN? zVg0c9TCMqaD9MyPUjZ8UgpR)>P$FM%3zfiVA$KqPYy~jj9_?|vzLTfmj#tCQ!tLR> zTzN*7Huv#eo4#{syYWfV@EVVY70ZR;>&Kw1$2u{-nUIMrm!X}99fgvGfy>$l>#E2Wce1)T5{kIxb$ znu32wq|D$DonqoHbd%ZVolMTdW&S2rNXcd^6yGVnfv4%&Kq+KmQ&YlxwAA5|CZAW6 zFhE$y)lXDxf%#!EUIvu~Z%~W?uodQy+OmAj$Gdb}k{mn=kid zU#~nN*;jz_o zE??wvqJ8wWik0?}w;Q)FVM}a4wzX~&#nBO8yzfJ&fW@hhfH>5$yc}lNM#foY}J>GCcag<^h5vCqY_*b9bzdxD28{Q%sLT}1HvgG}q`lU;}i>@g} zo&Y_#8=W|McB9u5_U0M73D&^e?AE0TFX`pVr{y2MpSe8VIG0l4`45|lG8X+VnYQeL z_=onMXL}0M#ZoEx0St$HeWJ`jw`^KR>uO_}PJ98~8&5GXtIdf1&?& z|G~ar@B1Tt^L>x@{&MdR^`7W$?)j@dzqe>i)UzOWjX){YKYMch$OPyB_QO zXPrOQ`A+9>$3N}((;a6zy4wE~6#@Qq+rzC(E&rnB&F25Pd5R(ai~Vz@@@9M6tR9V* z2P6$t+ryR9m>L-$Ig2@EG9pG~#7I7@vhAf`U8L-Sg7^uu#p|D~RPerz=nP-(&qw1F zi-p4Q7_4jdiHczmIGabFN#w=1AqNSWq_trE4d#RFH&sUOq44?Fl?ZJ~J;g${zPExS z_RM=b8M7}RQwq69t_jjPSC}e}Qa##Kj<7y1Nd!UG`Jf$;Hq^gLgU%7HL}^4E`jTC4p+^=Enxm?w!XiDFSq#KF2?Q7$K{RZnbgaKj4A2QIqdwog|IIf zrY3T{`_A{x>+aPhhEj@px|(i7#@1o`#6xYPSA~iafaMq!z#2 zmCTu9Fxnnm{WEu*uKvP6f$}m(sIMwzGa+mvNyUnU=uc>pU zv-sEhE4XJ>G`{=g&U{uO<}*iB`sB>0#!r@6caeiVB)4xJ`s->%Q5p*f8QDw)# z-4=ORzN$h_i`SJHbWMm)wYa;5jRE9?)T08OtGZwA$mbJ^8_iA&{{tK4OlX?4QbwW& ze(fgVNf0-VapvR8Bqh$F6@v1YO;;%MGN#41=Ys{!g~S2bxjFwbo!ad2F97yWDFn+PFRtMH2&J<3@Z*I(A@=QwcbmsPDxCcPn zff(@*A1P-peuaT_)sORXWsXnq&mYL+_c~w3!AmtAKM8IrGr*!!rqt`~ixpt(DkaBK0VF$xwCabB(Gw(zjDr>QVgW~!K@FsAIXZqA~Q{beYOHn zd+!K?)ZfBz2a`fE$#u+*SI)9|n1KiCZ=t+vQ>3TcQ1YcYhifB9%6U*rl~-8c6^KOt zmrd72+$8~0>Hpy#uwn%y^fCEDGx^Xg1Y^k2j}=oIuFSBk*PyajRK@@rz3TKDxO_XG z^0doF;JsPCsaMx6>{w+QE>UReS&?y}E#yS*+GCx0cy61x)bYxc4{kjp3cxGBgW%Rk zS2W$F5W^ z_GAOGkH5lFw8Red^w!$-TK?y zh~dgfR4sizq|f#0d?&kHtWYD$*znOv=Hu^);{T5}m6`?*5B$o&wf?`;_c!}4_YL&^ zsos}+{#wsc_wVU`tn1Hql{$aD^SO?n?kKhYWc$-?Z?^tc>l-cqzUA}HKid4MroZ0w zJNUe*>7^=Y`4N<$$);CF#sT;dq%^Bj*8;f5#FY7#q+7`@;yu$dhcW~x-?AbKRjNoI zLme9ZRIZ$vSvCVm5~Y#2(kWR~V8*2CX%Ygep064flsZ1eK&mS=qGb(!DS$|F|TqRmStcYbKD0fK`^wVPU}*j zQa@*I7zmGJDv>-4tY`g!DuDQt>%>Dw@5|>9Q;=dcVdsv{30W0>BBV~qwqhE3T=5&o zET)z^rn^fXe%tNj?y16_+(5_GIw6deW=ZY(Xt?XxyfvAvzf=WBUzFQ=^xk}K`ZtH< zNUC6@o2>o-erC>%f*G;2Y~28TXL#%}=f+GwvqMn@HurPq1&FlPE{6u{GWw$xE-f8~ zld~Y%8#@|yceQFz{XHz;o_qlTX%`nV!6rb+V8tn!FnI8{FIpFM6n#yejjD4|V6nS= zvh}v=fY=KAW%LvIsMF5$z|s;>BBb_-trjUskr#JM@`x;h%7+3VPv(fT@wMV|Xh=u=U(frlf+f_sVgBBg#nNLIaEw`WZ5L<3ZU0cMY&=3^1Sh_|sl+_>>ms`GJ zsN)pVNw(WDoFUada^K#=2{XDQAKf{qaMEiUIh<3w5Uvq+`PG}0E5hZGlyO&$*}C3o2|KjOgfKKId?7!{ZX=XJ$hw#bH<9VI0Kz zkk_qt^P4@fOy9>m$%f-w@2~c>x6K(FB~Hya8>Ug@`93#ylIq=c6SJDvi$lX4*9BY) zw}nW6afwFV~i<%xv zDJKFBy+m$A zf;cyp7VPQsoNRX~4xH91XI6sM*N<*)*}Gka$;@1OuVt@RJ9uN?VdjbJGoN{Jf~pgB zx9x8CX)Rl-lFc!_-U;o*y_wVY$l#ASjkpnU!`#NpA;&%C?G)B`sY=?$8Clb#iCa>A zYJ_Uq?%;#07Sn~3Pck*Pj24~P*&9`IH%bZyk0#DWz5a1L4|+*AE{=z}ZBQ4+)st>c zS@*c*7JlQ8v-Qbp3(x+0^9-7J6g6m2Km5f?$5ce$ip=l;onO2>fAylQcS5}3Ex1AB zI@m2du8PL5x_5LtffwEU$$N@d)}Ih+SQ@?vo_+b4gJPlhL=@cFm#fXH(n+e#XyUh= z9#g5*k6?=ApzQbf!B^(bFHsZj?hIm&Sj(KnxbJ@4?VsypmFFs710i#p0TcIUBTx*`6@=~*P)#_NENyYN?potk?eKStP=HVTgsOz->b9H@i*m^Dm-fOD7qZZycIbTlHI@MpW4%TxZ=%=So&tconPFjr@Ey@;Sg>$w6XuDXH zAI;<`6Fa?h>GF+Ri~8T>G4=RF%s%I<+kJYtK%*@@VoH3=hGtiAR=Jz8bs!{uylizI zqiI)S$}~+(j3MT4D$ka;oQff;9kG5-#Zq#X*@HyMj9iiz5=EQ#aYaBqTea?ZmcHP% zDgSn_gUjAxJQl4{V8jQLkakvC0r``hAECF~N}70{StUBBw-!HSPLM;H{y0-eMqLA& zKyJ@5?M13V&#}|QydFuAf`1|(S=i4VTasHIznA^Lx9OWrgFiC(%)p-;c(MN<_J3dh z6Metj_l>^$dw;%nzUS9^HhYeA|MTuY&^^)he|P=9uFrP9y6W=?R>5gO!^rJP!n81})?@xDHoUU-=Bwx`s>i0U`s+*VX|0n;R%~ zATB|-2;gQ{sxK?@xr>iGku1t2#ggSQ>gJjP>(1?JAWBJd{>Co; zi7LQ*Bh(%Vx!m6mClrG*fza71Q2XLdX4GaFNu7f?QRUF_xJf$>uU<&Q!K33*k6sYK zn{lJXx+rh!9aX9)kASu5ZE9_#txUO4I!MH&^Ccvrsa8Lx+!Xm+zfy`ntXBw2yU44*(&J(V}u%39<=C!m7ES5l!5$DlxTjVRcHgf4xooLuMFaKIHwRS z1+Dt?Rni5XFG2Z%F~rv-t*&+I%&(}{eACNVvRB9-)!ie+bMpdjBw}PPP;k0Ru7H}? zt=yk{JZZrp;D8`N@xdfjSPdMaMujR5kEaQFg;S59k#h!)SIHtcCUT!l$PMcb#|atp z`FTWvpr1GzQuQOWB|BLq!9YzER_;p(qEY9{yN5=qhk&YqnA+}Z&3Fu%AePxnRq7(| zB~rd}Z$inUsVtGjm<~KtG_gX2A&1=h`m<-N2bE2aDztJ>LP3bn6G$J9N-XBGjAGP# zX!qL93zvo9*5g6{i}{sjIox?L6!5!b(Bhu#%+%^mRmng&snzXFNT`Y_TVKN z+p(2go|T!~U(rn(kxxF$IL8&aQkXYjZkNTG9jlVRaP$;|^rwTUkb=#1dUniYiPE-W z4WByhI94T-;h0#zFQMSTkbwm4kUi#+m8l9)9fea>G8m44e_ZKJC|I}Di3w{%dqTtW zjh=E+F&&?n+UdEA_F#eizo+`F5H8J->q*GD2~8G;kDrrEJUDb$VA%7w@rq;ip^>6n z*i5PQ1Z(7fsYgg>zCU}hN(JO&cpz808>th{;6|u;@h$We@AY)#Lh0gczDiER>@7a; zNYOJuT2N#tV^bDhZ; zjFi!Rec=cz5YKs#Edy<3~Ad)KjrCV&Ab5?8!Q z;~{H%;%EaN;L15Svi-Yu(FexoudYxxe39x?h(U(Jnl4pIgedCzv?oJoYk+sD-L0)a z+z5hRJwV+k!U08DoU2miI*v{OkgC>zU9W^tu zZQ!lP!Wp9B67?=ut0XHFRHxv}kAzp3R56@|)U)6nCD)3|7TVFoe8^eWJm0WFdS?p+ zQG^*Y^a~q?vrg47a$OJ+NXEi3yIP_lr~Ig}z2G{~54 zu_bOVpEuQiAsed>0YF$|kRACTq>+|RA}6$>t-W-;2JH_ch;h?%ZsTDiCE>vO9tgGv zg08F0OaUwy1aB-|TinZqyS9=$7%sfZNTqBxbI-jVf3gt*u6gNyr8nXN7T(fM2&eBDOCaXa6pVvM_ zozT~&b1)KLiH__*NYbZ2_#^liR;!e-pJ4!yvUaNx2AA>C>+v|d|KoW6+nC~s* zOHVUbeVDGp2bY4U+Bx4MD`vN$)hPwV)_#NEx69HVFY$5s91I37=+(t zIb~g7G(KVMX>eevuGbCw@3j@~gl;l${j(|&GugV$$a&}}OaenZ!T)R>KH6%QgXN0C zc}WT)#tnL<3OL_juazb;~O3h$}v7q_@jd-2b%|8?f*6% z0PgGiGkv4I|G4+{p1R8+y6uRO`QF|*!FtsZ?t}` z<=ZXGEqj~4)%>;Q=OFZ-1`UbG)iRYc%GUGqH0xU!y18PeEO0ybHBUSc%EK2JyCsZm zy#?yd-CJ0+<|RvRYhIt2xio$vo2UY=JhlX_=0J-?GqXUqCr6%u&0gN5ExaR&U#wn` zi>(=wO@X8Bb1tl= zm9AGl3KP_v%B{nd4&|M#@2GxRW6v{o+-+%Qb>r(O0X+C^ zw(lvgd&RUUd{2^W3BT(|N=^N+f$!OAUPN)l#to?6`D81?{qx>YS$Z7*mR; z1y;twhjsHRK>hk&kP`qPB1@$k;)Rv=ENT1b6=I75xh3(kgG4Rxn)NsTenQqI0ES>| zCdN@nsM$1u_d&+q@Y33qpslgg4}hW;b>n#EErNzRc@3A5-Sg zo9AyVg9XMvfSU^^+Uw4V*5CXi4P$8#C0E?dIJcHCmIR=1)^SLuatVNO%du!@3$M2n$b{B!h6mqENp!ahY53u)6dp>s#H=wxW4pmZ?l1TkfZ@G6lu zCYej_DrlTdn2PrWtoK%_s(fJm8bmDe0g>2BfefrfztJl|t|623PEX`YEJf-Z@p3GB zAzA;LVy@M@JN*;m>q8X?&^F?;wG z^1^&QLeceBr(|2sGp=D%Ql5|_Wosu;@rLWMZ4EuRTG#}k!?*BfLO&^cI<+C;18s^l68C(-fHWv2eqZuN zOcH^GH^-JP(71;TrJ=L9Y?p7X4Nbzq&+R|3-_pR{#ay6PE;2*>Ci}|Ko=FFw<>RpFfO>bav9i?@h<|%Og>kwCYtvVs+=RN$|AShz3 zQEJkVDPF($3%)sha-QdJE?s4xRqHftww;0p9FTm(Nsp_ht;Ct3P|}muDQ`DMy!}4- z7Eavc7uW+Gbi!oY9=gAeZmse5uQyl6+S~T7zs__FsKRvUORpeD<5_cL0hfa6;Ki(a z@7)t4n^KbZngM2cz%DK=Ud8(x+`g$=Rt%3SQT5IqP%~S3}C$ zqNwDtN*@&@E!R1D!4SS_^VP+Iyr1@+LPBi%J!Ng1B-@APC@+U?oYA&0Y z6mzXgYvLyqeQGx32!nu{ZrCmpFlpMSZJT?9mBqrb2@_kttNLqMe{f6^W4uy5sj!CPzh=MFNXK5jyg~F=W6Boz4@18Vd zk?2jmdEgooPUWqMU)#2FNWs~*3}@@jPymNp&7+|J4ra$y6}f&}ei+MXnyVJ|aCJks zC#S1`cwXjeh9w#X*PoFpy!tv;R{!I}W8{ke?`nFxY4B@N#eLvIp zeDAk=f3WvZ&)@F(YWF|u{*msJT|eJ-rt^R8yxs9z9Y56ZT>CGyA8-4MZO2>xZ0lsp zziKJB^fmuv^GMU*gVbIA^Q9V9yeDqGJJ|AMFjRx)sl3xkntsQc-dZD46-812aHYNn z8Os)4La7AC%2nWh+2mkrUaEnRJ&EUau;qy`g0M`M*sU}fDcvL&8g_p2>di}b5|dZw zZyTUOd4^EaF~!ymGK9oZtBcpj6-Kv55K;$ar3Uu32v}gSnMmKZJ#DqYp8Avj(uWDC4|kC=d-t;+GR_g52N<3o-*BDu6ON6uRfJ zCN~r%V-2tP_&k{LOR^+ofoYAqXUB_cd$OxF>Whz|6b!aJ+BmTF0739tB-)Fo-2LxM zvncRRcPO`;wn>(;XAPhhs9^7oGBC!uT6 zFn+?YGEx@^(Iwf*&aMwK#UxL5zSag;e;wKn2io#6u-;t*lsYB{Sj(rwFvBBa=42%C!z-?QkZz9SsyttSKhhCN>030YlW}&~Ejh$( z&GF$9lfJ1frni~>)RkGy-l>6AJ+*$2xjb~oxd>MAid}&3Vk&He*QqfY9S|z}dJS0V zw2l6$Fgk|`UP!1e{=a@xxPs0H?d3Rx&~Oo$!gTTfj#c8~)fZVcE4Jq>V~1?LwFd0; zBwfn}TOLfN0Q*c3ShAW!PSEK7*Bx_%LxY%qsLqvW<`O{pb(6R-29I;)Wm7Zti&cQA zBPQ)0NM>PdJU2YW?oZ*zuwane0iiY>KRYYHY;#9mC@Q}bViCtV2rR+hve&ENPfy)u zwfBc{oEOc6Df~yS*6Gv6-?RJgi!h9qzfglU9u*zXI`NA9z5O zxoz%gJdsum?!q!14{(L_RH;sMXnhg70}0*XC^E%(jqI*B0JTz@36jukk{kRih|K_p zi#d4t)8g&}=Ts;6d_*Cet=>SCXxI9~T*9t7x#cgStBTV&t2=9cb5+UQ)fEzSXPI($pc^)OYUE^WeU!{QYTSlyutPMHO#W*XNMAn%v93VO){S^k z;0l6VbqW|-@xq)<^L@-&gzaY;cYJRgyNLt!5c+cUQu%qv7qUxLO7E1``;7H@`pb8ON2+(WWy|wIgm9jgBt}swX7$|I?F_iI=d*;IZaZ?T! zBeFl)!qF=AcI-6T8_9VFvc!?(H0%ZmmmXa0K^vT|UI8bx%*@&XDdkTNPtaOMhhgg% zp%};u+Z}I^!qg4yvQ(w9v*JX9Eiu?9iRv_oZ6&JHBN}98atrE2X8IPsRb5ih@+f1) zsNnFdyyQyfvS2#8vK@q(#*SHJj{Ej)-VF;MMfjGthW(K{pA+fNH@VbGCbQcO1HDtd ztPs@*L&ua?6ksXU8J|ecs$M900cnHzUpqa#&JD0u z11Ne9Ak1J3up5VjP~R2j+SBcMrBqO0ca#`tNeKlK1g38=4&u}~*-Z9XR~5Xh^Pow1 z`<5?-pun3;^Ft}nEn6R{Q9%0~ojnFyhQqMYXErx69ZM<3LgX4Y6il;#gMujDtg@i_ zlI6Kt@FYYm)TP9P7QRB69{A7ft%x`U`4!|w;I4;nTS0h+5S4Xcm%x$G4q@^GupBhpUdGM~{B|S%f!KHNos1y~A|gs)3U|M;hf|OX1G5 z0S<2EFSIv0T*)V`)B9HKARD$N?uThGc@QUVWwus(N|*QvhJJb5p$VB{Tuz+j5~s+^ z+(*mF=6M>tx7zkREyLZl)UsmQ*?M2?Ga6R9(XlYB#Bg$L3?@O}<$}LFX`IoG$(bhF zLwrrQk-#5yz0THlp&P6*o0r0DQ2kHfD>G!!#PMn31T%J%w>;@Vy5~9af-ZkAee|cUu`q>BtT4Um(7P z^`{u?^I@#X@ky@*Q-i_dH}CxFC>_u;H^WZWyQ8C?7SaW?6E*O@$Ide1;V@#TTcTFU zlVX&DFpn-1N*Jk?2pmhHFK^ZW`aVw-YOv*nKxrB`qAnUPYt!GS7je5O4uj{`>YKWU zXoT1d8p&>czGsN1C-sFaEUgKeZ>cOMaTjR^Xa!2xgauNEvg;y`H+iP(l znk$9eEh=q)o0Vz+hL6ticIWwPR5w9;xNoOEr+f zhviT{7-$9aW=2)|Lf>6Zz}j2pm(?|C%O+|M5|EHz;kiJ-Om63eHn~!771u#E7H(tJ zDENwG@s8%~Xzc-P>=G0Y1d0+Lo-@UrI;DE8i9HRhm#sfn1F(DMJ+avSK*1YVJR)<> zp%}LcHuDx$Pyp>*t)c?#M&LEIQ_X&GXJf435Ttrv>RuppgDuE=Au0tzB^d&`F6bT3 zVGR*&xL?IW_Jv9F773-t^P^URsm$aMR~Pmw1>&|{lKAZ4)i597meEMuYx|N&zI%0#G$h<)pnAirx4TA zVYsj?(CA(7kp)xAS_>9rb#y$;i`WUysV7(u4LH*B2aECvzG zfo9S!deKmADcxQucv6-^b z8f~zPdJdloG{cq@5$E0#%f*GkBKHQpqRufxIETVmXG|IYOd!T_0%e)Ok*juIL?J`M zt-X(Kb&WK2zDdSCxoB5(xWTS-nQwjyPLQx=W(rADTdYwaYs}7ISC|E7U_r`o5Fu8n zb>-TN-|Hl@Snr4OUPpgPWdHAJdbert#=x%*{6POd>A%|F-}jgL-s#)h`)j>l>wUWC z@AiCu&!@V7sk_{LU)PU!&2;{Y&XvxGI{s+Ki|xPG{yW=uwEcOq0RErWA86gv@;6$p zwLI4Re)Bh*4>kP*NZ!>yU#wAnwfN4vJDMJ!E*7TfRGsQ&b0qh9DxQ#x zCvDkxR&x%4CT@>T0qvtd8BQE5;!&~FLt%j2k;t)=;pvXt5>CBKCji`>YN}@*6b27E z!`RQ{aLpEK02d3yS9dghDv)*rQ-IhyShBnbOC#0@ z$dIKKM5Kv!0D;#r$#^w*xsdeN;g6x+e6we0YVpFN)C}LfOloS(KIZK=Y~n+V^ne>_ za&CHbc1DGAG)S)gioeWZFn@k|)gnN6#iWed!{vbHArNUs24W6p?TzeFTM++bATITg4u{lTQT;XU%XYjG-#}Y zwD2nuCeBOylHL%|648e9OPhC|w;_J6Y6`j@uh&XC`(DPr*NuGw-a0kTfp`;ADk`JK z)_(>RwWC?!(GZ>}7LdUPu{zES=dD0Q19fXj65Y{sPatn#A!nW@w0VVcAQD(~t3eXE zAPkjVsevdwipzCJ(O9cP@yo*8mhATHniPJHu$a#$G8~K0>N&@xh621H8;^PsvJbu?JKAue8OIn$S3P9?b9`?_&k4&0s6xLfsG~YZGc!6 zCZAahY`F~#X!C5jR?vhGK(8;*(-SmSn3@Una$)7420>tR((YEEOXh#1ld9V<@r%=) zvTHSp|0o}5M^kSYahjH9Qv6)&R9{^sA?Mxp7@*FRBOdp-Dk&6Dx6E-#XEX{PY_ilr z?kwoykJMEDM{jmd7*5I7^`FCw(CH3z z!p7%sUrs4`-g3T;+rCmes@T*nsC5Nu=r^-!Q&UpiEP6zqaL=h#Ve*d*vLA71&yFiJ z%tqMXv)}RYi8z_MpP*~druWD^BX+tGPt2Vyr~_)678oTUZ{3?$AeG>W<+Z6Sm>nO>nt3?z3 zro0h)$ci;;{2V?DwPr_6erT+6nl5a8?$X0f>j=R!6!s~edv|b0jG(%@NRrjT^czMQ z57wTNyu8jtPLJ%&_@I4HjnY1|n5M0f*6cX`NR>p9zX=VR6l1H9VtqB_VAb1?%g0m` z4*tRwE0dxY8@6?+ul4O3g@4Xiu<3NL>FPq1!{C$@@cs^>lncD7p{}5F)kMw1g(}yd zs6B^8`JO;Ar^4u#=QvuJ9X8qChG0lWQ6AzN`mxIj44?Uy zjYUm)!zTz{DLeO)I8E-@kDpk_Jz5O#<|pmjX!!W9x(IW&PDeBvrT`b zY4E=poEZ46fu9(-KG4N$xxNQ_|8Q>+AHZDCVE6CpeujR3i(Orv-`6?P z@&9)G@s4NP|7!bt?MK@FQQP;mAskzOvi058BQ5`-<;Pp5nt!wTcQ$_p!v9hJ`RXQk z=acJ4-rd>u04l5NqbH2^bZK~Es#Kz{9_qjh8BLOl@S%)$V?O%{jDU|vm=ED+@}8V) zL%aEQZ4Z{NX>AU$VM#2i`JlIXh?WX#*@aEj6D)HH{eNfMJ;^9B3~6o!t6@58rOV|` z5?!zIVAh0~sM`QnD8%d~S9R2DYS|Yzn+P!8W}HtX`inUmuV!?L0h>`ff#N_j}cYu{0g-BmQM2TQIY|R?rHNeqIwYNFK zvwYW^d{>xspefYT{PPBW3xwi(m>sO$#x6Vtt)7Gy>@ewp$hL8YL55$0GB93yi--3D zUv(#6F$1cA@l^V{dL`c|mnX8Jpk6vH+luKL7}}955bWBHpfp&$j9WKVdaSN$f1^zDsKcmvh||40kD*h)YYf)uP$~SpjSE9cDA)7gj^vme_K+PwpT68 z&E0O^U@NIDK2L6TIPtI5Ru$+dF+%f}5lrct9+9gc_eLgBZTu|~h}K2J?Z=u=;I?l{ zM5VYL#86#<6ZAcKP|%vGQX>rw_YV$?H|SFI8XDuW(-_a9u;4S6s+UN~5vhBVrEych zytaZB;?FU+*|58S#L^IGN7MD3o_Aab3?V6??f(!5h6Dqe>~dS%6Eb+O1v(=WhG~$q z$!~N%u6voHKLz$hqg}|}u7PDe$oB4Nx*Et7M_)-*0dx9(h@~k$4MiS&=}Jb|R^aE7 znd6EPD^l-WdSUP{)~>0fPCtWR34=Suiz#Ri?q+DGf^FG(yybvh3$h!&5@?ej;`*sa zd%9o%2s<+$7EA1BjQIdUa0#?L@T85=YVvvX=^af=fv!(_GQQBXlU+~NY?(}XnEv9; zRd!DHdE)m9CNX}GHFW_cBm*M$fVsOa=fep>5WEoE55^O1LkW_<2G|=`L=!<-Z?F%; zHM?B{4Xft3JDM(qac0LS0X>1Iwy`F`0XS>d!78n1-Qcp_#{HMy{Al$KO;MYX6>?khMGeWZWCbC>h-Mr^UM+De1E2p2RdUyw0%^9P8QX z8qGh8b5MRZP?l3rNu0?Dccxmu>)Cvb;!sB{yz@+;m;26Wtw()|VD9@W7*4gb+z36) z(Us-VjpPyQeb>pj2u*glMjz3GlJ8H4A%g$K3)$$`kqm{&VogwD1C(vr3vzEq)1L4# z8X7EZZOwQiH3vK`ZdM$qX++LI(9!1na3>9%NI9@hlxW(g9e64X!l4z4imH40&#D6|LV6efX=>bf?KNDa z3haF*`BIvujyUdHeWF|hB-Hb!*ET7^w1)uuj;37+#o>~@_#cm8gq{(UqHn1MrJf8# zO&gYm5{m*x1C;QP@aAzVod5`al_*p9o}`sOdf1QH}HYXwtI(pKkiu zroo>WoF)U{?+k1X9PR(V`u}kMm-_GN`-#2_z5k~7hkK9q{HvbB-G8Zj6%4?C+cnwM z)A@s)`#XNU<0m@iJ05QTyY16$f2-|Ft-sy+-?cv3^0!)MoBt`b03V0wf1ZE7XOq&) zC*MIUJ(Fmq2t^vv$s7q##-vW7d1!T8QX|ALEKx~_FtT%-&!Tj$L7r;nQO!SI056M+ zc80nm)QcD9-ara5gBQj%t3JBWsOgGd7SAwMMub_Xzg~8A6CC|n)7d8y;-^c;ZRVKa zub#t+$zNfLmGD5GUOK-jL_sod-Fk#?;`qQ$e@mTlq{gQaqik`L!p*PWVksgSyeL*5 z&E>pU9OyU?L78<`>lUeU!j{cb%x}wq%1mltO`YiNY+{pw(9^Tb;tSi%!Y@o5Z+uf|;0UXY z(Xg`DH$j@8lgUkPNMs1#tO)pDNf92!dem4;Ws8i*qm~d<0hXKu)t!{!hSDn_K zZKKHmal_`uM@EKSyIEs{Y2DFlRIWu$0k;rO+uS(~dlGk9e39&Q_SH>r=gREf*#;6W zUll%;hNL(u(SVCra+Irn1xb=$!h8KJmxpMusvuY;brQZW)2A|^Me2lgI{tdgCfM^+ zDDXSmP9ziHWKPqI&-|36=9$Z@FyuU6xuyoz#C7E3IoHbQ8kVlk``v;cAv$rK+6eE4 znk0qI$57x-GKXWy9Go|R*JyHL!q+6>n*eu;Wt3Nz*_VZ^unEfis5~4mB{cZDL{!9i z^Cr%JMR=1fo{0c=$c8r`HAQk~+lvVeIFx!eGv{I~Wrn4?pcRf&7ujTDQopa#R-H0E zn-qyIXevh%GR(rBSHZ@q{3;@T;KT(Co#0A5wn`R*zgFa#s`-Oyr+t>VizoWNdXG!6$8D-pYYHsPU!%_MH-rRghuI9bW@lY~A*s$rs zE9S1MZ!Z{k4x3Bey`1d#LdM&b&Iis`I19;P1LS&e!D)6F1b9h%^SNYPnM{-wu`}n| z21tiMKS_a{$cEV~o4~+NE<@${gbL>~qQ@Dv))O&{B_fxM)7P{cxZ5RF!lvYemo_Q+ zd76Z!&C8~j2oJJ1HQo0~wmPvQjG*_I{r_}9rf)qk;y62s&+)bENs28{((MV5*uFp#@F ziBMyMLLETQr|X9{0d^N@gSoS9@3sTy(X{+9Y*?*I>XpxD2rr|C_n;+i$DJm^Va3OD z>+Xulb5w^bNih@(gan@8kwjhPKagDeP=}x}Gv2uJMy2qFi*V ziJFoZIZ_5yJPlRK{mFJ|IoZ-C5O1YN?QGkV48XsJ+k}j_s~Q$jZ>f0iMSjhgy7|xI zl_u=ulMIe;0{AW{#&uT8|{Ol9(h$kqb!%G04dUj&Z?A5p$8$7dAV&nA)+26Jl(& zcHAvi{IT6;AKRowF3p5?wmp=5N=ZQT9SQ|DLUh4P2-|A&=_aqo)Fz4XBNFhRN+>X1 zknxVx@YSnRh8S90op$oZ^AAr)zS(}uve`}QiWOvqK9~@78I7^HSSjeMsnbQzsh5~Z zOvlN>1z-RFouANbb;EB){H@9X;$eV^<7<=$`hey-;q_N;dQ>+T=x9`5@4UEkaF zsm?z{*S}iFqwW6_G5?=$n`-^V*0t7$T7IeJMDwpS|3LGTO@FiLosVJi&upH-8pWLH zN~7JA1)?s)s5|lrjTO$pN0^}_MdHSmxj#?DWkIT<`rQdns#C`l1&4F{f|S;YO(5VC z=OCK~w>?20oeT7IT>>dd<)C(Wx4Ngev@oYyHRf+x$Y6UBSUWf_0~;_%r36)VTd#sKK)9OiJILV3=Z{Ob-QMd z*u>Z~sd*!thrCJlZTme-4&2!&dUoQ`pV|ZxK7tJCN`vCT#~QsgcIv?q!%GkvkjGlbpQl}6A#WtJ~X-ba-a%7LD%k%GV>3M>s)*=Ha(`PcZ4o?o=S zT4pCZ?-qO@2z?&8#pVYUt}aVEJ89%JJX0j4C(Xf_o|v5~juhR+b#-^Jy7R&Ve^WD=$)WlHt;pArt_q~;jZMJe1@T`;2P}R@gT}J&b0g!H>uH8T=)xl< z)Zz^{-CA7;&B|Zs1{fdsr|(RWadArU!&&{+J&taLvoJ;X=lxEZ+9D*%fk%2M!)KOMo&@dz~ zLCA`Rp3~6$QJYRaPbV=*YuVaoGB_@70v10e2Tq632}T@`eaRQ21F=@3?%e|4WvU8Lx+2Oj`8+xbGeZ_HccPt|Qs4O`zx{ zxdS?y!o(0kRvJl;XP!rw$UHnD9^oeq^0aY2NDV!gI0dYjd|tevapbwpW4co9s2ml@ z25&J4Q6ERO3Y%gt8#EY8ToBn#H!iQrafSCdmL6E3hyVw*_!g0Txxlm6H-W3q$qp+w z3}8wC&jg(t)!By;(@G7gU78EQ6{i{4dq6G;n!w^F2=yst7_@b(Z)o?^g0augv9c!x#U5{L|Bw>Lj8r-5wu z^@Qk{+N;vU8KjU=oC%;ZFMU%&~OE(k7U9 zXL`QdFt*2xF?e#`TTT3sqHKHlJU_Z-)Iw*JT_DEg&!9nova1SAzpc#&01CXZ^l`g@^ZQLY<$ zEjKt(QfOQVW95%TY9_=NOV6u<6{IoN#}%{nhc*wix6Q53F~ct=Gc+e@RDlzXOn)H( zn8YUYqi|6$jv_ee(z!+})xtA3>PT4pMt@{pU9*!djh5gDID8izIhRaN8<@||)g!vo zq+G5;J|`Da(_o<@Y0fi3Kc{mx>n2;jXA=be*>wd8Uu~Gh7IPsMV$AjYoPOY^0NxrZ zT9a$DVl*TBdwOr&$!jQ*)Ws@3qugOqrJKHd;T!YScDO{}&n^%xr z=yWVSMu~KEDAcQF{|_~ln+AW3=>HE59O?f*`fv1o(094_FZb^0`O%*HyML;CuKR(m zKi74!tF`lwb{_Be=N&8Uf1bSmi>*J{@?SOo8rl9&QT4z4G3@@WKb_tL*LmdTyN@;v zy4;-;D&6f$iBd|AO8UbNpidk{0Sj#`EXDkt_mfnT<*PjT+Fyf=Sc&}7Cg@JG$sTPQ z$f*{O51)yM05OBb15Tkl#3kADm}pUH#V>02LHxh=G&9c zw?0Ws(>>vMVJsFfFcr;o^E_4BU|FtgE&{_3?z6YHOg0`#ernD;r@SUDp191Kt0l@Z z(Q?*QKb}3XzU^X62M3eF%LxbV&IL9-Kn!GZK1^W4Z2in8sMfLfUT4wW`Jz>RL|xpc zED40*@kn7j_PW$~W`E!SV>D6^g*A=DL-MF~6c#7cZF3auPK>%k^fj3B^mVVMB)tVA zd2L31f<~ zZzbP&`P_XMhS{|)VD3R#(S5TDi&0_GA?!YJ6;l(ZkK+~nQTV`|ecFG4N0=$-+hgzD z$4oo(nQDp+I#UDFNoUuLToy;X8Dk_mM&+Toq&dEu73QxbtvP z5c$M#mDr~Kf8@P;e4S@@*SmGKWLcIolgnf#Gf^g!#7d&qmM?J}kH^{8%{#hU7duWS zqmeDyR(z2o+2eRJ>5M#ugSGcoIY23Gfdf4hXn_tbEj^_a3Wc7QQd*!boC7@_dI4Hm zpqFzv{Hf-*-#fj#CPMoRd#Koy6YndT#4k&sx8AqrBA}O4rWbeuSB}*3NXg zIHXRRRu3j`)0ka$5Q+93a5e2ctwb*swA10+%j4r1?QwhSohF8;V7jE)FawGrgAXd zKdj6}VrbrhVpB#jE~rRf)czAw6Urz`7ebSGcgn-h4!Eq`G>V3!*B&mOqNxbJ0?5|S}d>V}^!d5HW_VJu1 zri(=tfHc)FBW!;|>rb`jX3wKKc;*fvzqFcppzVnqnMum3sWz_%zWO}3guh17rrD*M zwrEpT=yRCf$(cK!0d}|qZ6PojKI0vtM@z+NZ+&Xs$|8Qs=eq|jl+S#Y8O^+bfqh4q zB7Fjy?hp_B1~KOkwB>z!3VTeC%^13*qy+aOXseGa$}#5y>7I;0yGp`{(a{^^1I$!t z90(lrCJWHu*ko|Nl9&34tJcdSXQm@e;B%%-9si+os1CX4EhuXCOD@Wb4G(N(wB=tTa$ZK{ z0zz_Dt;|w2lqI?Qfwsr;%#iMrqwe=Ry)<|HekW)Fa`&3yjXMNJzf0(8Ti&fYIyhX! zv&SrJOl9#C+HP%(?eys4g?UOnq<10ZTVpKo)fQ_Q&12UcVyCaH9bx3WJN6zU_s#89 znMLCCa_1ry$1>9N5atca%Xga}p89$a_ps`Z~cRa3WXc1s+>c%=h6O z-PqA7o44y^a$idDWHZc!GU}3USwsbxx-_(T75z}aa)1+aU&@u)d1qRuqsQu@-1w}A zl<3kpUen`Q4)Y`_(F7lGNe!%x=BQOkO;v>agMj(4*d4yIcf!naxt*ArLV}}m$U$0Y zC^jJl*v9buw>_Afjy%F+#S!`dYNLaP?3WLEXoCNRas7hG zSgwJU&5{dMnOXI4G45P0dles&i+A{h(U zN;N6*+5Fk1%c|SVEP{B@Y^dr7pXnY)bfdUV4zsOmyAzZDkot%vO0kHJ`&loW>Rscr zKqh(#p6kgo>${qppE$&X+MR~NZ0zHx1%`0LhV znUz`K>3pAEr`%`HK`3mirJ(WnlbXftT_>Dt&k=sy8h$)z-RL-S8!i5xP*`g6%BPWB zTc`NuLEIy|3oZVQ>}?d`Tv2S9+8DULh27^b&zpUOF2fdMb6D#j{UVhD5z6+OY0phm;;II0d%y4-oN_z{0)^&#zAh< zZvF;!x$Tuw-~h%?I)iusFRc>{wqN(4$%oQ$BUc5N*Oom%G!m2xyx^Mn+4+U!t@U>0 zO%?gNG5uQINMF_FtNG~Lu3gbc(@INksv15OVxCl@aH{9|ZbHROd8n0sE;6kW2erbV zUne%K=P*My#J!n0p{*%qo^{>&0MWd?zD>DuT42F{?`F+dae5@8H{1iyl)Ey&YIRv* zW!y~HQ%`?7{W0p56MwrKNKF-?g{nCR+?2Wsh8V)iNu| zUAn>79Ma#J+0c56dUhOPW=(NsXz=Vm1=r5 zz<%*6kF0G_vUXv;8KdCK53rI(Ux~%R3BuH7r@q5?rk52_9_H1rybfX-#3)v+zKF%G z1DKBSyxpg1YrV*FsqW7OdbiuYClJ}zWqN1+`)IMJ@xb6c`d-+XzIT8kyM5uHw){NA zh{-PUZ?Q(X)yy+ldtjZyH^p57IZh_MOWiNtlqgjp;hvd1R%N3KW@nc^E2u9(AXK@LRk zpr9#-?3(^{%O)ANz@JhxeG%I-8C`F%yx*sH1+XFx4q%auJ4X1#CdxIdj#Ef(53SR^ zbL?w}zw~rOKTgcTNbD^+PxQm^epfRml=}P*J4$ZTt?mJX;JT;b_iHF>Q;V@&kZ<)< z7j3)jr=e(+z(#Un?dJm9B%rTqR}kGv_q4K|NETV?wldLrK~@&es`31FglfPhxEI_2 zR)zBeiLV2(5n^09w)=HxNeollluy<7S{W!gQn6bvC?dXG%52_Tf)eIKAjV>70I$he z>WX|*3Qw`274*)0I19;HgDsc4$Cl2mEUU3ka`p}lNQa3RdA!hF10z`pKjQ?%&E)7A zq{_{C+FjdWhf5tmsp!_B90|F*JZcPVBZdejz_zbZh?@p^EE{Aq3N~6A4^2WdFm zn3=05^T&k3;lcNl25h-??V#SGxPw>#ADEUJcW5(uZ0#+E`A}{cp}75c?FKE{&=^v= zJ=stZK&*)u*#xM&=M>BzJyzgQJ}DprcT=PS@G;($3nbA|C~$(DBW8?$CZz39pYA9?k}g0|{Hkza7K1%v|6Sw-%?2cE58KY2Q#{XFYl9T;LtoxiY6J&4`wuTexUo9X@HqCnwRffSA4ddvmeNa zW*cDaI5EndWiIjsN+s30$kQtlRuacFC%N+f zpDU~vx_+wb8@i5kZQJ>$cAnq)q0S%bTwjXP|(Dv}QZ`$^W)-x@?*7D6Q{mp-~`IV+$ZklWAZu~BK0Q~)iD?|nSB4ppk zKd0A;0NsxpVt3(4rscDX<3mI{&WxX$8>RQ^2qyN~%gbj?n4lQqAj5J9Hm&4@{bh~$ zpS-+Y#8y5D;g_7SO0&SgsiJt=N=If267PW=ZZej~Pj$;`?_YlzlS!8UVJDI1NUQCg zBwY4&F!7N5u^AdVmMq!i)9Zv(9wx18ci}}RgG6RwxOFWod%`GTFI%F9SYcV+iyh8-?I`y7BP*D&nbgohZs@*4}~a3vtpjL#0WJ8R8G@jjN&M5uVUXO?Z!AjuUmi zDEjWuA~j+N7gq7FkS!)`Og62ig}?Ud0tOd|r^f3+U&QTqY5kMh#HX0g!P;eFTv=@S z>5Dv3tMjJDM9G?~xdGF7X>^N^NZ&b+_XGsMtq*tkZ<0^06MflphQSW_V6v4}hjeWI z5=Q_O%Eb*Vsnfu;;ryhz5Jrk0rFET1%bvAM5ZIsYo}PozqVJhDpV5RHbPEKFuL7sd zMNN6hvMw}|cwCH-{sEgp$2+ts8(w7xEabzn6H_y!xFw%iC+xD1w(7eJ`_hTX9JS!o zyG+LBknT_#(`ECu+6dwzkIhe3)?bv$@f-v6`2Z<`fk|d1UWR5z`5VAF5DIt$F}y-6 zu*`B#7e_*vHc?Cv?v6diSxiMhK9aS<`XM=p`Wbca=26vE;`ex5ocTfbwYop5gOSXx z6SRqF-d)%eH+JsyRB_T<5hx~5H%|*scT(^CP1AXAu7K}L1(iN%8g{V#R+EW!LOAz` zZsK&sdLcwMQVifAETzZP&nKqkUA9c1dwNIEFdKRD<$Da2e6opMY9 zr2xxp^Pi34&L@@`z#`=fum5I2F3H;PI-#09x34h&=d;1aXhB-Ei!8+6!6iu$pe1UR z-QeXy*%R@^PM;WObdG&ptW=?Jhi*tz-cI&@=(GI*L`IVxx6y#m?nx)JxQ}WtCc#in2uD zGz><{=x-RjoZlpO>!jM8o(lL|yb>b}# zqoVCD2uK4K6Eo`_7XGeE5F)Cn=E(6v=(qN(;?x*V7Bn^W3_^+M0KelNCgC1F<3j*n z=iq%F>S-_YVJ8%B4pY1=y(`zLi5@Y`T=&U00~yn+$xkr(rz2&@>=l)zupmvoR#1h! z9+q&Ozw?W+3iiuE$q?c_5B=Xnumo6PvJZ`cdOG$qkVyW9Cs3v2li_uW5SjnvDW8GY zW&}$tv2{F0ngQR26AiDDJ#d_d_RK^MFVf5F&jn@Z6SZq$n`dLf&<#tiv2eD)K6w%| z>(8QRyvuex=_Jr%2FEGHJUuwZj5HPgJd<`NA5bnRhDmWyYvpT4y?bz^hn+?lSL{`C zWW9&rcS-V(*Un5CRqh%oW*SQHv&c45)FT=iRewxFd&0jS80@EzG40Q%rVzo*X<;$- z=fGrAGC(~RY;z(A#_l`=75OG?`^_m-OC@*HB9)6$6~(yJX}FS1u0Jh(sR0^~hjmQY z9GHA*&&1}6z$W;0YlEX8j#Q%Eg^xNJZR|eb=-QqdojHgPc#87&XdK1`0w}NFT<+C>M9?W< z?zLYhBkNDXA)4@GK9U9*9H49b&k1e){H^FnMHHdT;ilR(1 zajmlAlb6;hr_(DN;=|bt92I2qBp3)kJ?X#9s1PlE_}#|n`}UrL`LagWy~&^Zt0AYY9X%i z+7LHZER9nNs6XE$>(twMLPQ@4>kUsG|F!96i@@qNsw9c~GEF3B5+#S$sk=knzukq0 z1GN*}NjfzR5V+Kh>a(zX1-r)b!*rvqQ3wv)>&e18^>&^!ZT}(vG-~;&{h@t9irhGV ze(Btj_RajH3jB>)y!mPJGs}=Dk7rK$);~gdK{>S^^ik-!L}aSR7WnB#_JAeKgPNRK z|FBNAg^xbyAIYX1EW+rj*?XM(9)yKhP&R9J8TAN95X{p9`H5<9@)KymZj{k^@^wgm zAd;S*!g-Z(TC@UJgc9pU?&b$Q+}G<#&pM4$pOJg?f%N0aB1L?#G?v+Dj>*hhzB2!R zpX&erK-ZgHAKUp8JF7cS>}>D+i=8j*_>VijW5;KA6gqyWW2Gb6{*SQ#A8-G$_BY#i zw0%e0^tRvGR^67g{%Y&@wcc(WX>D)$?v^VpFE;<@=D*my()>`<&o+H?)ANl#(|EJt z-!*(!!@0t5{I_)iD6Ov|PcD3E_sb14#|djAWZ-U%LeeJl?%oq~Sb#6Mh^1U5SJ$ax zeM}tH7TlkNmhgPhIFsHUxwLNfPA3Ks$HS#N9qY&}sBguxX9FrK`4X}N8EL005ee?z zs|G!A+|u#_9t*M?Xos}BEjUaEXi2H8Ru_i4qG71ahZmA0HK>FAt5Iaa8l*KG*JoJbxFCq z=g8?zF0Yf0a73Kb98YrAGjS<*pT%xyAKg;b1F|J2Bz@@OxK|e!fjGF7wR=XK#3c@T zn$f~RM>r=ND#buK>9kvqw!$j{99)0XnhWf14rh(?&^EW;>T?TyZJii+)xX+ZIOoSR zPI*d;G^Slizm(1N#WRT#P9%aYa&)*JvY=Q5u8Q@bRqDYiZ^1=WtU+j>b=rChg`!!f z&*SJ)s>T;AoAcfMV1KF22M9~LbqtS6{T{FpzK~9>}yVegAHH%4R)81TLy6`+a3 z3$O2mRI}4o#F&u1>qJ)f$|ip``z*T|;Xas5j-MP`Ct!Myu)Nd$$w09PQZs=tJ{@M5 zHWb6{q*hK>yKm-nRKylh(Z@`;Kb4W7Ps1$Af|-Oe$Jmdh)zuq|E4VRjr-j=&K?&se z5=prfZv-UZ+%29aqMe^3IbwHVHX~15mzQy%(gi)zWoVf3g6GB=A|65}Zdq6=F$34@ zl!!<5wBtYmPNJ&v;Tw!MlZ~f;lj6f8Wja=FhG7+Ki?;6iwJXyeqjE04Nw2QI273xG zrem^9ef>7<(S6bN&6|#;47F!&BcMp1Q6Xdrrl}n5@yS{81;Jzb?s|;ckqj7Gx=Qxr z0Oj5K@)Li3ols$?ezG3*z3-R$-aPfstP}OS-yo35jCzeWn?E*xx^pUQiu3EKh!DF@ zHM}Fq$#vp<_X{tiyr=fvby!_N`pM)3WE9gtXHBDst0%|$&yNAq=B(z!l7wNbkB)1bz zf;k6&2d*S(DDod@XO+r`^kFaj?+E}U7I(iS$jBzrQXbia^b-K3wB=W@OM@0MzE0Vz zLz3RFIE}~xxqdIvaPcrw#+P=Gir)B;c~Te(;bbsPOHOcn!V?82rqKA^FNL{LvsgXO)2*YtXB}me$AE|0Spm z#iioho*f;v`HG$=^#qw`yy!g}{Le$gH#p*aa(I1|nF(GUbXw9w`Yp^NR1h@~fGcd8 z6(qBVe06<9n&5su9`KI^Qr6rzO-5!J-M55n^(o+a{z~AnM99(W3u)nZHA$7bWxS+ptj?9 zwjCs2Qw4lhm<`L};I(s^&&QG?tlvg*eEkHkxKx{>f9}l#bS*q;C4MXxiKeu%icW?$ z%&<5*$Z&X|Uv?sXVeL>ffpANWGXfjef*IIaLr@TKeatDKA|j|Fd!$+`51`CJ-Aw-P zddfK5GyO-HY*JbuM9UNRe#*%y3M>?RPk*H&7KqgAUQYHqV9T6kZgG?A1MHB*^HHZI zelt&C&>2#XUY^xbAa35>h44k{X$GzAXSG5JKItTj%+KuD+C7J$3m@YK2}{k(RABl4 zdka4-`~P~^gFAn8=hy7)B?I8(j-S}^){c*L{9?y9cZ_WR>h`bOzQ6sK+NX3etl^!8 zK1lx$_~&97fUUUp$d`H=TLB2D#38X?&p690rq3;btYesj`)y#DissXnvgR)$vtr`_ zG$+Gl(6&SKjMS2jWF0hhoJavgE}A-pg3^*s*^rV4dL!LB8!H2`(T=;Pu{ot=$0)$M z7=Xv_<#UD#D4AFhPI~MqnxY^fz=3oOzDrJ)0of=N)YI6M(u)EjN?pSop&kAFQP^gx zk>;1qIGHFvM*iX(&}_Ub%}nV|ze|O9UU-_^N&3qmZAWIIC@9BIDrB>V#;3aJab6B4 zh-0}-mfg+;z#lSDrdai{X{Z!ZD&CLS`jt>Pa@4TTY(}9yv6g4(q9QMo*UG?b{qKCK zr$NxEHwBGb=F(gcxrrWg2SwrSDHOr73P~pBRTBA_`#DeshSMAy1fkXv2WT~gRiv{y z3Vz)}=5(3VnPaygBkZ)6j9wi#h#M(Nm=-AMl%scYKKLX;BG`#CIYq@YkW~_wljUDfA01yyeUAKL z4hvK<$kYZGJbL+h@_LyP(WLkFG$@fPkOJctsoC*Th#QR#LkavN{b z2xBUrEbh|XJPdvYnsh{Rc#fzyZK7T|W=`OD@f^*TsXa~e>z)RsojI8appA*4yEd-Z zG-{B6RWyUu^Nz{|S(J>FTVU5Y=n8F*>kAE*A?!|D?fS-M>FXwhM^Y&Q=ix~Y z+O}RHI){#d53>F zIa#uR@*3YvjKBh!RE8FgVDrFQGFMoj-a_2DkbHfej?4Y;LbAh2#_FzY5unl}p12_S z`D-8w?=zAD3v7*5Cswv&pnXd%usw+?`QrK)blgDtFK>79#y#NJlZcwr z?`rJu@oI8@-LfzM>0WO0A>*Ek(KmTCtw6`LZ!3Yd{GJ#bm!e@4%}A`7QP^}GFt*vHeNf5`d zg*MhlWc1CHzC->J)RjcHR3z(O0a3H`YHV1hE5JvdoN@3(K%h38Cy^i)#$F zPAWPqo=>`WRJ_9vlc9BTAO>-@yeva4N4{2i)|qYS)~EwhF7C_gw2oG^(#x{WAS4^q z&R}yQZ(V^d65jvs3x%$)?;6|rUv_@a&bN1dqVp@ApWX4>JO12`t2;j2@gr0LIKKVY zx8Ef8|C`$nwEg+EnQiOadhz^!ZEIi4Z{zp>eDlA;=fAh<3r!C+ersb-!!I{{q2cku zUn_j!y$t^&+?P%e-&Zrb$QK!^`$0x5^YdKS~hn-i9_OF!-uE zAkLhy2f^-#cH2>Z%k;I1S=l{FFNRS}x=#@vVTy_+q~vdueF%?7$K6ty66f+l>}}YV zjU7|txRgVboh6m|-s3|su8EsyO@ldQsrbCr@<*J*%s^qF;(5P~)#_u756+yPm>QYW zdL>ZrW2tua^#pVGuYzuq@ae6erR&U&_oD_~znHA;EtB#xc>77#)#77mEy{L5di9So zBL9!c$(a|scIDJgo>{X_%-xPv4nFO%tU!?FXu;>g*Q-f)D4*$P;ku#KW!1tVVktD& zIlM^0C<-~&A4XF8!{k_*TpHZOdmEa4#smFcx+gp{o0v$fS^K&qD`hI0D^Fl=LsM8Z zN2f^E;;7e1Q%R|!z%~LI&+!l`q-zy3DpYr8SEa0QsWrP0Gt*sXV3`8m(LP!0DwBFM zxHiwIjoHMfQ8nlwi_IJId0Z6=(QuJVTu!(x$VBRl6z0Z>D`~@%8%!Bpe479>V0~2# zs{JlGRQ?nfQunFBCln*0r6U*dc6niwS{<#-eKOGX@<$MfNr!U9TqnokgeNn6jtSk?Q3OHT;zc1X$o;gb@k!nrHSdxHVvw; zG3z}vWePNuNo6^F`*o;?@FGzcF+*e!a5M0`5syhIDBP;(h8WXT$jX5PDQxZyZy%Du zQrIS$3!!_r*cvWX0ai7;Z@-A?Dys)*+LN zbITmFiLlH}$W#!lAS$_K?H7_m(um`PNN{ro?n4Jwin zUiHgyQh8D7r8wP(A~Z>&`J9(x(bn0nqQn#JMk1Wa?X71OOr&I?Od5@0SB)P=?{W-V zE6sQ6KgdeDSthwfZ7q5lAK5wy{$!J(#GmL5wBofjrb!w+d-v;a zhFbV|H5o6H+H!P>fger>Hvf&~!I?7|7mm8F%8jEo%JR+PeIP?b_skuH=vFYidC-oP z_i#+Z5PT>lh)_Af)1n%zv*YSHrqJ7vQkW9FaWy#bi)9j5jseFuKA2L7mQ_3tU7AS2 z3p>Z$1#?{CsOg1TNN+?Q+?b@vEhgpUsMzlV zDaBaeBUc-WzsqD@ioCi!N((4?t+-X7=)%c-G9 zyU!`i-kHHM^95vzw`p^n^5T_i*9q8_LBeEJfx|T$84BPXM5qOY55+Gyc}(X!S$-P) z2#C5-D3Fg?155gr$G0+U4@LHtaf5PUs8&MGK1NoyMafHLQd*83gQj30rx`inJz=Tg z@+a_gPVlin9{+fnauWlyqp_TH*42YwbPKju6(@kk8mI$glth)I@|g;(aY|E@{YY|b z$c!WTBg@S4a-B5-C|B<}87zMsQGmyL%Ds?o%4T7xS%LcSciBswTrX4Q;mF!ShW&&OOEcZ6 zQ8Ee%QlFg!iw<}$uLJ;s#fYaULzeduYA$H&V>dP8dSbO1&pt{hI>w(}0KHC%W$HW} zJk6+2`lu988YHN9&g*W>Sc0!NJIJC;&Z>i^Yb`7k#esx_{wvVH3`f|A^U`r#bB8UwZmd5sv_4s7h983a`)!2^^fU)IO?t2~mJv8_F;aKfdbcsdfc{EYc_b9=u*2a5yj z0(anZOY@?E946tQI1kCkon)wEa-4v#fe3_%hca@}U`lsamn-OI6J;eB%t7vBPEK)< zcs%sz>s?Cm@qWS`mGw|#OJ-nJhKqluOmczp^ZN=Pb&_)J#>2{Es&_jrr>ZxIx)`}K z-@c+`tV}vV?@j1G7N$Hw=?ROBDu%GR)FT$2-8AOJO5>T@obC{!^G#x-Zb0uNIeH3^ z5@!*{|Guc*C@;xA*De3BlLN}E1L5k3f{!EhubaA_CM4>r)ue;**V6vv8`24;sTm9M z4-JZXpzazLACMn|7p3ngY0NU*Vx_Pg0JqFM?8u$BvSnuz!)SAM~&N88vKr z$TX8&sU}I7Tnzm6q_^u?g<=b1JjxCA1NeY z#gbzowXj{;-CHitD>QpQ1AV{;@+Mwec_5RyTZaMmfpU8PV7s(}Teu3?ok4z_Dt}gy z{_TwTfR88(%)*v7gD9?MQdAHI))mA^3~LtOTOo-s7v8&MwoF>Yp?9IX%jxR8RbW^3 ztV8a;Zo_@NSz((zglDi!?!=KZ(Cu=%kR6^a4ctwS)!%XLa*ezlLOE1^gZUMqvoocm zC{vf3UdowJN3SW8D#EKoDxWEn9MNZ6)|q|^_yioQb`jj{>^qY`R`;lA?+v98mB}N0 zRLbtvlF`3_T_tC;7rHFHp_>xdxA%F9|M_GHgOrpdvX?}f$?ddR5k;!n9OtRuw zqru+VLQgso8CIWn*A6+r9_*C6A5>I9t{q#}CY@5QSZ*fdPz z(+DIzRBb+@4aKPH!GKW=p9f0L8zEg19YP(tKyLjl&4%HUk!f*E6t_9W>A`*gs2cSO zi=W(iMPc9Vy*5@1xv4mx5WH`c$+p;U%+czEUD6$&n3x$Gwy5;*udI=3rdNR|vQvst zE@_03y*U)kWD?4fSVajU!vbTpuh0^AVlEIQz=TlmeqEzDM7aO1QC)F5`KWZ%v}tsz zCCD|`kYhJg`ZJ?Qja}(LCJqG=tSofz9y>mjI-Z$m@BB?1e96`Fly;yGnoTK9ewrgD zpisZf77m!mGpg0Xd~p|oT_$amPL)?Y<9T;!a+ESs*`B~0WMfcdr?1eMjt3=!U9}lo zM+?seAcCZ^j~i+OYJuP;q+^hV(^qJS6ope*be(Iif!o+$u`#N!7p8#EbdeBF;u!um z!(ztD6VQ}GTyUBmSHJarid|@hEh%R;Y8i4#IE=++QI={)d0Y(~<$HY~K<*SrHXC}b zpMbFO!BLYFgX1a$Y{-%K4jH9psH}sl^f^gufA)sT^1U+@Q=U$3?Kqi`nUg;ql6Z4H zh?2Drlxa~uytc@EcKLkt|Nk3iGO#p%;VR{RS9>9}X9BJ;8<=?S`=8ZtnGBKQY39`B zbBZs*G%aHlD490k^K!jjHqhjTph8v{!t)nJex>je5S9E;BU9 zs$WTy%Xw7cZ}}-f>Q$cARuX-BAy3>~r}|m#ht62nyWhkbfoDwvQ(Xx2|0jj76uQ2# z>y@4VdFR*de75tScV6D{TRXmKN7C`*9bfJk+WtG+e`x#q_L27g)cynQciLZS`kQl(?a8KHr{DG+4w=?|2G;=H9QRQ-@AVn zDpUeFvi8uI_F>zeR+PVN|GCjYf<;fv6{n_(XNYc}Us<6@uleF^kK+4h2(<6gM9aR?RWT~=TyF2u}khwwz}mtgAP{6 zC)hvF#~-WxcxbffnVjdTQjgGCQsQpd6FuIMO$x z!Lt*tQlx}S#T#EUi-Q$12Kw~%WB&EHF}Vi>$}$Y_p)PH-rsKAJTxuEsNK|?f1io8U3u)V!jFK=~q`5f_}0)ucK5?6P%LfwwTs37|= zHEn_9G%8X^)oRg_`z_#~d!~XS`GCa*Z$cT%rY!U9$a|)%R(CjUF`3fI7b=g+<9&<) z9}RmlF;ikdj~pMM0v4bWN1Kn{sL`E?bO$w&RUd5{H8Jr9=vL@m+hLw(*>P_#UAb`u zc~4Cib|Cp|g*=3jFEaXv!g3W*sgO9m^a_-j^8&1~!qC$9uvpU0}tT6LDdxLh3@SI+|8W1ist`ym?V8Mk7847;g zA9li{rJ+Haa{jCo4vb(7?e)+@?ZmmEH_3mrCTE_j$e&a&dPhLem|Vts{r2Sj8YE&#=o4fvh44;ZO_H$B3Bid${sGQ~2Y5`D3@opmg@$DP*A^IJVvAt_-(x1+;{8aRU{ zh5U_&S8qk(hSX<{gx?qhj^U6N}E-n+J}|u zHyeXEbr1$psYUJ~bf2t{c5qbc!Z!bAdiJ;pmrbb5jk6{_GK5**q&+DwD?lNAi zC}%**R+E2Nubj9)U7L4cu+oS))ebcJr#O-6x?{S1e$L@*9(1o~vzg9I6+-`yNa<+^ zbOdFP2vM_gT_B~)Z(8_pg*bl$O!v8QH#InlW`L^;<;Rl`E%Otj%Mni1Z3yn3w34I+ z6n>^m3x>l4F83AsoK*0bV2yiR7+jfFKQ|XI*C2;az?-#fDYQ|S+)dVGsZ9HYgWRjW z!d@RhDuhhLx&DEHQ|K^K7A*L)e_#)PplcRz_ketMtG$ZqKR`A7M#f35M@9JI>9P_9 z1hOPP6mDT{XE3GNTH!54n|>5`*>f4t^$fI;ltz035lU{9NfH=A*7X&7Ye*v?=J*3b zJ?oh3Ia2eNFVI}<`o$||uxtM^)di?ho5o<_1CA=}-jy<`0VVUGJ@4aAP7v&=1itBM zLQDrzchB(3GEJPXE%W-^iYhaz2mgA`J$Bbna)>HT?fcy1vUQG>KhKR4KJ%Op7ex9Q zJXK?J4xjsGOUtE>wNwT(4a1+tZ5^K(noiD^Z;83&pn5h>P8{HfkEH7sdItKS9?MWj z89#zFTM(*C<+t_7J;5M7J_w0rxafp;a4H5yP{?Ar*8vWAi&q$h+-9y3gqHetn}XvR zDRv@aIGarBGfZA7lQXdY5`zgi#F!L+5pEZKt@!T#YHszYqF{5kklF2QGCOg)D|`hf+5SYZWzPoFrt8?cc-FdY0*E|1u=fsYGM+`tu$5%S~w*T<4-DnU-H6^Z&)>uQp$AZfg4OrefniXFaqGT{s)Mv90x0I_QGH2itKgXt|V1{hU1FS zCwWgOn~Lc5CN`Wr*$T&O#I8CcP8KOkq7LIYF%%VLjwVxUfzC)_6B3JT@nBfYXsXYd zP*2g9l>3rv70XR{lC^c_Mnc=?G1;WZZr#CfL(z$>q}O%U9#!U$%}nf7Y__?DY);frpTVP$EV0K%pZ?Z;WF72(5gmS`p){&W5Ss znJP&ENYcjSoB%e0C7El8hc_n}MkmUJVkncPN>SHR?6AG=fT^xhZ!~By)IypaRA*3! zKP`4`w(_zW%m)hXb%zoJD~`*kShQSFd$w*Md??VKHIPqm6yNlLLR*e-VC5`wY%2wU zCrImjiDBa=6-m5tHM|O@LWL;rq`yL@z~R#jwJkRkHJ)Os{*d)I6~4~BaD{ElxXD`; z`gjbYyB#RB=E&r)y6NZ{v9veP7Gh}-;g-LN7u94!GFc(Xpft~rEx94(k_OtJq75ez zGn7BxOp$h#ORubd#lXu#oMAc*tBA$13C>9G-w=^Cps^HA0S546@e8sYprA zR9+(e?j{sM`??@nnaog;hDrUS^w;y^0~8yu+5-Vlue(~mnddG82QDD#4y!-eqgVom z-4dule)>z3C)~UuV@YgRn&dI=KDTsDwkPI=WhJ>f6C_>^uu6l+!|&xHPTsAMlTe~& z;J(6(bw-r-VF@Mq@iu83_dV{W?`-^q3Rw#i21^{;V*6wuXYNMiQO-1KM`E0EUBN<1 zV{{P1mSK>btdLVcH1fW}3qDF3u^w&SyP%g8MKr6i4r=*Qg$5gDwH=H*=c+~;tEnSO zV>I2Ci8*N}D+fSTg|;8?kGB}ld4w`GdIKgbS|P;N@e|w2&sJ!evB$V)zY`q?+r#-8 zLFvT+x=Y>F!=;M4^0Ko?@1Ur^u$F#TP2M_Gt&I49Yb2K|ME@T)oM)d8fhi!hH;wP% z{*>g@fZ4l8Fl`3kmcNgFL%T~OIM;(w5*{usM}bwG)8N}w@si(*hN+54mF)t6OPqf{ zk*xc$NCOa)L-hwv%neUX%vvS5fhF+v#oiN(moJlF-F?AKpnF_`FcI6hi&Qq9 zX|E5gCd&9gx2`%~NG&@c!8)Y)GSu7PcuA8tDkL4u>Y6|Q9;2kIyU!tf6>n6Y6Z^L_ zz;ix8ns6*Mf$lVv33ao36Nl@>EN2pPU${4*zuE#@r3pNZsv~!9F?qA{tn|*0LjT## z^iyo9C?i_|5u1iE9R!S2jN&*`YHxVlml}#)y}%F5g_rEB^bp%8_^-#ulF~VKO0Fa+ ziYr2i+}UTGbyXhDq*Ngxff9=QuzBr5hDd&kC-ist`l2#HP=0UNp#fQ0`A+RXgkQnK zFD&BbARA%7$^K`Yn4*_bHyV;ee`*0*l2ZJKrD+6&&HucvAiQ3ohsH6&K=xt$+AK{3 zTH~#Ze7cQsyX=M`js%qiFP#|AlQP{uTaWw9n7F#IiZ_9zgoASXKINlE+w(Lb*eA>~ z2`6`RQN?8MY+5e|@{)3&XJ0I-) z-p*%t{1M{+zuNJKJ9g9e??C&{ws*IETifH?esSAJTfeLIjnbPr@snl`cQD{eMeF?^Tq z-nGMB3Gt)V=lQ!B2#KUv-~wB(-)QOSaP98b5;C`!9F(}2co8XBkaSO46J-2RAz#32 z>L=GLZ%M2jVig~-RS5T`Wcz4(S>Omlrc4f4fd2A1l_I697h(VQ?@?E-aY3eu;pZr1 z#@d9`YWsX=lB9ACU;jZyeZWSI*TqV$m8=!~Q+*mV#=#6!6xe@;4|drH(Pe^Y94BbZ z{dM7Nw4ql+jm}z7I(fN5Fn^!OborS@hqfF@;(ebV|Km=n%S*}@mlcrKrR}W{z`sXR z-)SUblK=79=~}Qu{_53Rh=$Aj{v^Ne^xqS7qAq^Aa+$@HW`Zf_hD-<^o$i6rQQ}F6 zy?^EnzTOeO9wI?$P?l$UDh3Ya)(q-_<+HR(=2G%%g;@I|U*!9a@Vz&$9VDyoba8aV z+{q~=gK$w>*##bg3)oQ>I^akNr(v%#(ni1I-YfwUABOaHBkd^r1RaivTIaH6sn>Y6 ziBj}Sday#+{NW>f)t>)qh`jYJpPi>dZ2azUg&_IE{e0J!`)&$k7ok;}86C`qqalr? zme>twnwcJ{5DkB1kZ-r;zE%DFsfjb2K2`z!m1VDV;9r+21j6@S;_KGj*Mae}QPW+w zTc0vuFaQJJzg1a~p04G$7%^*)AP)8j>+~e*A7_>Y9OCA>#};wV$6I9`ymJ7T8TZNA z$~gs*bo^j@p~(&3<;cKUX<%V$nR{S@BzI*!2cz>Wa9Vd`AQ<;|bwsOkS zJ7x?3vB+~5WPXts@uV3xI!5NEE|`F&C@8(*i|2GEFII@%e{O=N z@(C!7Q;$2fFiU$-u-+Ums=OPGg-~TvmkX#UD2bw!bVU94(F` z`jI}d6qtH?S=7h^IWTrCb-?@dJT$2oxXBYo`2X-)4-*N@WU!4-WDHS7kAd;%%2!kQy+18`!M7kOQ22Tsfx#x)QxpH5=g10M{=o1GAe=QP;cN zuIQncPYY?0!+$KQNSyl~Ta@7w!A{TiY^FjdhNCw?y1qX*^%`qm(~S>qHmN#8a+w1E zCTkB=EW6+wgp(ZM`21THrYu@7R8z6wyQt)5cize|8QjVU_cfFH{PF1ui3LZ9y*W_m zy~~`m)=dMa3$=)d)I+vq9!MR!Hz+0dK;iiu`COMGl+;t!VO+ydm&0-gP_iwIE*my_ z!_y+|S~mAB)w_~cDr6UwW*OBpY{ooW|J3Y&IOLnlQ^<#){Mb37#?L^a|dElX+gCi zi7g9F)ib1E4TQBDyKC(gauWvEbTA*w&5A`%%uWe64rO~Vd!ye1wL#__udCc60NV?e zxqx-<9jG_W_PTLS_&dh8eafW^%c8KPkL0xqX$!}`$W%U>n@UutDL$!y(rg~$iRj+C zLdS&=0UizG_-gQ1YFhp23Ky?(FYXAY~bwX8s%DsgmV^>sWJ7Z zrg6SnA(?^xFb4`B$&nX910wxly1%(+#%y@5nk(crjI0ep{KGlo1~Sq{#5gj%6L;C3 z)R}diCQ?@^B8!USSY+hhxN9&l2b6`5rKht>tlk(d1}*W?+${3K!g#s<1x{sBjX&Et z*wD^WMR^IYL;XWJ>d}!iH8@7Hx83c?{h44-uW-=S%>VyF;TsEGKi>7tT^GB$cm5h3 z08j6Hr1PJ3erxB2&Zl?$iydFt@%fH_*zx=60r)H1znxfs|Iq$7+Q-`4+umt=V%zs@ z`{K4@>uQeh-~;gH^z^zH@y4ihVyi;Y^-3=!~CSCIiMkGmR{_ zp;ka6IaUQ<>wO(MA$ z{+cgiz286ko2H3lX9HBPS-1uDKWa_+^3`E-qsu7K5ig z%r0NfWVot?l0_&UtD)%ZY|{$`QT%?T{^Dq7#i}-3E>cRKxdNq686{L08T*daY^5QG zm09gP!S2ouhWAjF(K=Hl zm819$v|dbUWuYKP8L!ThDnC153^puV26x$=6iWBx=};%H#d2?O2Wo| zZT<_J2u1WeTdSc+Ol=d1!73>lhcuUiMj{Be8s$1860G|gR&tf&NR^C?=fp_|oQ`o2 z)}UVC6bMQSl5=ME069}7`>V8eFw}a#eN9kn%7W>~fdR90(4{Il6^GWIWYB%~nMG7g zSf97FO8RC%A~1^wp{4M7xT@irp&DCdfDE@vPFHs+UA{hlb#eK|DoHYH+pE?CLT9koNSh9LobIouiS;{?(a+u| zy$@F1ga;ySi@(O4@I`zwFtvH(t|NZqi*0XEMk6{{YDG)2N~efDn#&%WOME~SyB8l_ zUR$~UZxAqMXssd2Stw6(wMvQx*~<_~j0kbuwBh6BwoETH&dg8=FCA8h9&y^oD*{(- z%vpdE3u{>I92t$uZZd;}jSMNa$qUsT+ylX>y*8e>cWO|{SFwmX_RgjF@(^Q9>XqCl z$zrube)%rGd_F8UUoATxLCV541yyoe8LP#~BN85CWACuKRp#sl7_R1qS~6QD;bK_t*lwc{y#}cb7%1gz3z>kS&}0Sz zZ88AaCNePwB}AU7p(~+O!nCY2L0#`9O6{jn1YwE*qvYZa-|m3e(?)D|T=k!Z$7$eB zqg@wI(G{6VxYQBE9!kMcAX;dm(tR9V!}`f7RaQ64Zj=dD0aUBE2m*Qgd46;5Vz)xA zC!ILW>$`5uo?FwLiIni0IsE=Iab#u_rVl08*&J)SA@(I@Pq z*aw^qzY$D=T9Y(6UM0oD6yhiCi+;41@sT;>9MS{(k$CcKO&j2fqcshs!<-9sP8X9; zRmtyoN_xk~!>|Lh{bphNXc7b{r#F;Jr0aYgNL7a8wHqtfhzrBBTqVcjs4nUgMnJ)# z@~+IOgo;jgaG*c+5z5J^t+Knz5Ae~@z`=Yp-S)M~Nptr4rBq) z5;UV^*vIU%D1_syp7P!EYz`c16GewXR_JulqYZsDqjMLxcG!(Q z6|xh|b^f93llm_0@WtK=DF`;mBld-H*j)z^dzt;euW+Y;^?$1CqdR|L=Qr&vcK&o{ zwev8(%0Iv3^&KDR__>a+-~Qd(FKvIU{kz(i+n;Xxp|*{-*|sOQ{p_|sxNU0N1Fb*a z`ukdsw)`fY0G@09*UevPKGEFK^p}VTc)0OTG_Ex6Z}_!_Kicq8;WrrMUjLl0;%L~v z_QVf%cKmglyf#^oT2|UUcqn34iWkp7P{&g4v7#1^BD4c5X`B{YMeGRML-il5ei{XL znsL70#)&)@>MCZo7muwv);RFuMpjNU67#j*No2WIAvDNi9IKCd7v~gXXuQH zrnDwYt#ryffqY`qrrFivxn!maa9?~2+TUliBSGy6u)+*C(Gi}S&*D388D7@H*Hj#& zXGp2)ubu&U;|c8e-)fd#vIff8%Dr2}-4_1I>Z@oP*sev%=F9$9#i9b`4 zQdQFx(qwn_H1I|bpZ|LJJgt>GFv0iuvMxxSSXfRzS3RY$2K=lI-<%F*uAUg*P%FN> zi8k2%)IO^#bHmyJi%?FG=l0t?uG4;Z$3snp$q)>Yj8$h56gL_7>uucO(Gq0=%p~)N z!XmXVFPUd9V$HemtpL-;=Oh`Zf|U271~vR4qi6d1>~Tr|yR1OClCsskA<&Jbh3=>J zC$Cq*#rxJeq4NigPCqmxicyuvNA5u>ylP8iedF`Jq+Qwk>;2$PYHlnD<^M3^@nTps z$36*2p18%ga~8I}%O3o+P(9hw+-oMuKeeynieL&)pP^RCRoVgDsV=J2k!lrWl{n-X z637wmZ*B635+ z9nBO$!Z56_cDL>}9&=sKr~00_y!r&9l!UE4((eC}??-<|Xr}-D(0L`$`G-blb|9m} zzu)(Kiq#TYmJazReLe!248ToY^<$wrMl9quAI>HX4Ej{{1e+@};U}C%j4g7+Dt@1p z#|S`GO5jL!7?4AOX#ca#*FPSyhr1u)1#p$M2nbZJj@ zpt<=;>5)HXR7h4O-l#9C$^aUsI6bvbvSm?n>V+x^N{6Lq{XP4FCo5~kYfVA03E*JqHH@mHV)hf~HSC?`{Yf^)pa4p#~DV~pZ#PKKqjUk4rWDyT#%amg8`UFJ&;0Tukh&B}x%Og+@-g+?AV2 za-JG*AD1f)>NhWYFzPmw3}BP1fppZFMW{-;kEJPZMbh(c5Cd*SrA{w>UTzC%A7J$6 z{Z&f=;pFLW%uv*I-8^3;^h@YzVz)QP`p1d`>Y+ivp9%ukm>%*f)VTY#Q<{}W{jJ&x{gg!M(X(BRJ_b~<0u!*(OkI} z<0V*!gkxHz6y!zuKWJoy#gy0()tX-6o`=M*Ji!}R(|8J(PBEi>{!PsD80-4fK13Bc zKzk&u7gD;>FwYa*q>JrKPF4?~P@tk0&ZQsHhPHoXZ~ggXcuMWc@{<{??ho(aS)(~w z9F}t9X2fQVO$VPTx!2~&(3$r#BNQxmEA-@O66!{(dYoEXSX>SW zi1AZKHfPr(cSDhLX*hZ$&`I|tr>cF(`ga-Xvo@6ZT`jnEntGl*6#0=%)Q79&v227_ zK-mAt+eUL=1aHEJdyziE+VGpl$Z;vV@mO{EV#_hxCyq+#v zw_yaEPH!GaOUD*4BnnD6uLgJN+3NFBH$MWEu{;&mCNzWW!O;u+JUdCKx%=V}yYk0! zMqDG$hs}QN5|7{SGyDI^!tYc6zvt-w_gLpQbnf5r)g50T_y4y#Had=N|7k4$C)<;@ zueSZMwx_rK{I>sj+f?gUTihdYs*vHOw;$7k(MO3R z^I81a^A;PTkp~C`1A0&%YtlU=tbf6id!%s?pN`z))!^XJ<1TfdUOd}P3fwh1mQ^X{ zQd+|!(e=ODo`l?Dy#OIuk04H!b*{fR&IjoRh(mk}FaN(c9SWUEh+Q5&|=-9|LtKLrv4rUuFR-?i^;Qaw>v$#UouaA!>kwJ=V{3Wq2;c?iJ9lvf)#dXB9I)e#<5@d}+Xt)f!dYK?m?{5ho3f%8e(yOeWr?i} z12pN6@(hh83Bw|XGamNDH5qvV%Hx8Z3AV7!z%nY$VsG}hkwJ5xhNoW)ZhWbz(>PGk zc=-LW-*lB4IZp^`==xK(Z?flWT$)TF3>hbrkT{BHQ4n?iKyGF_CGT!gs=kAt<1_%& z&l=GoBBWI~83wX&aD`@(axjxKVx&DU#9k3LAb-Gbl22Cwb59dN(ecmg(>i{}lS>Ix zR+XI^qNa2#!a*r%!t6ZED`c*|QU&;x_R{fxI^W=q@1GkOyKhu)zMCJz<-+qmTLt|+ zi6-6Q(28szLYe3>Gx+KZw!55AN@z~oIuEFh%`ED;r`4(qb>?zZ*%9wg54R!c5q=BF zfhuTmFIHNI<1Z1t862?3ivN)r{W+fcn#!~{s`R=o%4ON%h>D7_myXZkx0Ilf;&A$| zp@c{>g*t{}?J+J+-XrM^u}Y%2S=!~*0Hs>E)?(Gl+hDYHI3SaaYhs@S6szP~r`!ai zKCci6nui+f@5LfvIv8Hh9g1i=sbslI_n0GV&oPc;HgR82LapwS2cdWpc4pLLud!P~ zjLnMh(&nadsgRCq?lA!884DB@RBS8zWR*m;BWRQzj?PREjD+^XoUm2+pQaf$`BX%y zVg$Q=m{pP)uhIbK5HDeeqcd5IgcmKDVK+lX5-!4gt`G*Ql+p-MG(7{s;WYf7bc5+d z7wK@2#(dISXvx9sRmH?x7%a|O(3IP4xk~Ss(%MHM;s}kjJg4FCO4_|Z(+h_kkd`o6 z16-JKx>9>vY43T3qqG6d6k1ufhpK0=x*Sk?hjQYvO=CX*b`DcL*NegWV21YVs06G@ zWJK^{q)MvTK}iXRa}Z;r+t?Cu7%a?fpI~?74 z5%iCa!x+YBsk4&`8Y3kOpmg~rSc8GglE_k4{6Rjqe9e*{2}n zaFmsBm<3mtI27ZkEQ)1!hM8?LMlLNbUQ_mES_fnP3M;e_ZH;1AN)`qqy%|Sx$V#Ft z)lf82=41wIh)07c^$2iX%?u#mC}1e~<7#jd1my&o3`9cq+@4jI+y`l(AU?vom|R zDpmZlDKKyOx180h$0Hb?~d#Sv2kbfCm4C*7PY zF2Ax@m*W>W2V=l-CQr>oj!<*pgQyRz*n4*V#tM9dh)7M6WbL6UeQ^%2NpJbVnn~a* zofzWQ8nZ+nLyBhw$05R~#_!NQOk9IvU~Z;v2}F`6^L{6`S|tVWkkXwy{-(`KsFJc1 zb;;4Ez#Le3ZW{cTTxkSuaXAG&HpyAg}`r+zMy2!r26 z7m@TgB6RJRW;~qY&TbvlOgFh${fzcqBmIDlBzLE~mcs&n&xTU||3?-7|6N_5>DsyT z`*yB%{!iHdV;#TV@!a-b#^?VtZGU^)U*2}4_20I>)AI8zrAH z`1XeW`;6v)|G2=~(;FYD01QJK5^ zanLvf&dy-o9G@x@GOVHQqJ7j<9MjFmo}{|=MeUjZ2~;PmK|v(~mLD{UumP8s&aTV@ zCch8#;QA1RJ69tJ%(a)5_0S0yy!5vz*|<<><} zchuEnt#5;Z`bTf~Lf++)$d3)#YZSepMQ(g-k;5AqH@`+DV_1SbdY8}lN&`)KMB;Si z##M7}5SY2L*sFZjc_60TqZqQ zWmephpxJt*{8D}0k%?xQY#L_o0*+D=rY>GyUcRJbMA#&2M>ifJ59&4&vdd+aM$_v) z4gL|*#K7Y3s;n|#421IC50o>;knP7}8GQw57Z~I;Md4HHD5}m;nd8??9mh;`^oJ}t zk>>BhDLYVba)U_mF^rZj53bSlC#i|)v?hz3k4XM=qH0lXq;U;-A_Fgj@Wv23C=FGR%;sSJH( z;{l9oLLa)mCqE*=`lim95h8Mvp?HQ~1xO-4?0{Wd>g3_sWMzZM`2A~w7QZ`BZG0k3 zzV>|K4mQvz2mk42=CbKa33K;A`X=zDY85QurA=<{+#qQFph4w-#YaWuA)NL9w?H}0 z1G+A_^WeK|NBZ#^Oeu**<|*&YSY6@&|7GVv|3)W{D_ree-x+rVS36PaC+cnmcf{%< z2tYGwj0uRtWUaJ8Q;3tdOVIhtMh6x9_{2n7iF@w!37!<5-N`dRGIdD@)MI6d1YpW~ zUcw$xTMwD6z{VlI4a6>IZ|g5Ca)KwpsznIR32v0`G2Ah#PPVBRk5SwDk%n>jB{{ay zfzbTm{6!!dJjBGS?iN7n%@CwTP&2{L{LU9D(UqW-%8&(o+8^e){y@&Y#krk z+bbabY9;)YD(8jV&P-a;!*5uRXc3jf$+d0U5gf!qzFl0I;vw(_rwwhZAHGI&t1c zf3yOpGppP|WsZ@x&uz4V{CxQ!)BJXu=Gf%^;NCMJ-c*Kr&QCWivPycLymT2(PVplo z9b$v0x$=6CYjBeqelll{FctJ!@mL)i9LKqf%W8uK3{CY;9xfDK8M{go;nC8RXtf&i zLTaaP@yE*Um45K&azrEcYy}IU7|?@I zA+f$v;`B~#kbF|qB>!w3da~uGCPs4<1%@c*iGvi)1@&;%P-U4}SCgBI^a zP4@p|g+EfD`rm)p`I*kEJ8pLT(~fty|I_VB`}emGwf&2>j%}T--_-I;Eq}V@!RGI4 z{&-WR>BYu>+<3j=R~pVYJj#dv9sXHs*r1AXaZT^eFWDNU{?C>|H?dS*jk;-w70coq zU_s-Sr?Bs=s!^u4Z>n;Xs)k}zEBwwK;(1z5UfCcF>c}~!@Qe8=OcMP#bAp<+U~dAM zd~fA}W6u%8I9ieRn!rU&p^yiZtQ9t>l3ZNFE7bK1d2**pgXB8K70qyeKeq%vmMsPL zjH`Jj7*wbDMQPv}8S##^?|y2vr&j4_E^GkP(`x)3NY+|6UQpm5-q)_5ubIQ(lpK(z zcEdWGxFu-2wx7}by*_^-={_}onW*&KAE9WYxduF1QsAZTPaeBTOjr2L(P#RSz0Vx` zRPyN!Vy;S{ie3LAKM(504x+39-{tp%Go*A@Y}S}5ZGiP292m@x^sJM!8wUiU%XR(L zJbkEQK{7x@x$(f@h4zRb%M9$~<)!{AA^+*gG|2$2cz zzZ;Iy1~Y{*d3A&Eu%ejA-T#`Doas}*8+tJfCeRMmof~Z#?XJeEXW==N0!(6Z`^Fww z%)~%;{j+!u6a9ERDfVbeqYSS85l_LXOTWnSKDYR4dOR^_iF?Ug>8*M3Sg=ID-Hh)$ zA~^(WhfTw;U)&%D?U3|Vk3$%z;vBI8b2I~0wX-RW!~qA6lBz6EbgE<{nSg`(HhNXZ z?ir|f0D^XFa&(sPLdsKWyWUg3NKvO%?xNy5@i5)E&`Ud|d|Z{)9+z69=il2x2oZ`Z zzk*-*{c;G7V%34j^UT{kI6!>{Sbg|MGFj<@0pm_C>+xYmpJSM|AMC=iht?RBl;!WNIA-qdkNinak z*Yw^D#~v=YiJfy+RLrLu;Axm>`5dnvl(-*4V)>D;Q;O-bg-^|^&Z=>uO8iIp72|q% z4XEogD>>ouADpPJvKb^aK_wt_iuDyw0i6qzuDd`*3)KMVo3f38f_4ks)&26Ik1z_> zg~~AzOymB5t(In}Zb1HI87zEaoc?C0+GSt^c zB}z4xFiOgMslB45-`6~KB>pbo=XAP?`;pj1s&bW|*mz1aZD*z)vXad-97&w%eT^4{ z2oI=ILZW!n6P1>3Rg|YInkEJH)-GM8gt~<*cqPc%AM=KNBD`T9x9r6H#g!G6x07lWXa%QEY{jy1chq&O*) z*mbF)?J*`gFo{%?JhId*@F0Rn{x@lKW6s`P-Jp^8u`dh!^*|ag?sp%atauW<)oj1U zj{tv$p74Savuij34=&5&|1VGw0%+b_R>O?ypd4Eqi%K#712jSFKY;{_50icquq1PY zZBEN0){+y4109zM2?sU9CTo{Bo7_spS*RKhfOV^e>yfrD>q4 zlPG{|jlB*3vf*~a?!u3}M~45sk%CWdkd{9N{N?Fn(99eRLK9x z$mJJy63H7IWaFR2M%nfJT|c*CA*03q!ICU>DxgVvTkn?z%StwXRitRIOBTF#dgC?P z{ov5v_1sH+{5KOeI=dNQA$T%=KIdeiAKy2Z{;x+VBJ+av)yu3l`ei2w^*X|lJ0U+~igi@$b zC^}05YyGPDTrp=(Q8i%@63?V0hD$@}m~$oFKsk1G2geb-`WSzKA@Q6wKl8IbwLy0N z2&mdFFL1-lPCDDroY*56;B%g17U!Z*0}7FJPbfn8#Y6LglV3ax)KBc7b;U~#Y>=kk z&zrRCshY_}0I+s}>3m+_m}YlTn|FPp=CfQy2=g#%U9(rSQV>|V*yXy6NxHb~eGSrt z9V0E@cI?TNdfY0D+Y2ypDckGxjgB-1HYgW6eT*4?d=m}L$(pw0?wM1PU9#!?*FLr} zslbbE5c+T=^jgUy3(%rXU%|=A6)QpWc~5mP4(p9cqYd z5|?NVqJ*emuvt!W1Y>MgDO*Sw>nq#Gsf`J|Jnt~SNAvR~#0nefvvfRrfDN73tA zQ`-oYD3j)^8|3{TS=$fQ59O)KZeV2F!dl95B0)1uUiyzpFRU(Ipd^(FDJ_7U>1r7$ z~7#sH$kSZfWT)L!^~ zfr=dNl_ES?TZWg)8vfd0hi{U(jZxV#I7@cz%#ZoX+#>+_93bj%h5Oj z*{@*VOH&c1ff{L=SM5N_>;@$Rl*hSidpbb8USr&SI9kgYXuz%;huh zu@%_gQmLhWfFBY?z6zjbLue~cr@{tY%zK(u01O)wh=-#&MlIb%ytdn!1n!8}ei@)K*zYm1TU zYBD*KBAAlN+TIPiz?NSb%+bWIJDBi zxJ>b^1W=Br?n7x8q=A)hXxhN3sot^a@EVwFLFRxo|}XwP6gT44_`r?6o=8^7Va$Dc;(k_3hEM zqs;T)r}Nb8iqn=Os4S$q^NSmWQgM?`@B$X~sPtO)QP>{E1%`{C^Nxy1^qSE{VS~CA zgKLWn{_oPkvxBlt(%VvZ0ySpRrVYw%ice*Toq`=r-UF9qA>J`RFv~ja*mzma6Gh(r z+jLS&Yp3ke`1D9=TxDtN&M0h2NR7qZP<<{-Ye;Wvje~iUMXnnPNOB4OHqX^6!HfxR z@nf==1<3wdI-O~>sWI@ndxX2j$*7gH7}=^GMQhEbv3Lbhrj4_LKLLKx*)^Oyf_*G7tzc0qfZN|@Y#*7{kzpcA^@QI*mca{6!L4D@o$jteK13u1Ia z6&;w1q+i|nY(^Kuv80v4Gm!Ac(ik}*mIxbugrDkinqjTk8}_Z+?!Qge9^Ck(oT|&r z@K@pt=g8+#ZAZ=R9{h2y>!aQ@nqd?y@AnQJ-#CKjSk9w=mCdSzg`=%1jicdV+$1*v z)J%G&imaVZC|aE?ZoH&>D4_LU=BZ5M_81>HL4j7)R$y1~dwTVj2;u1>sn>-1%n=o2 z=ZiDAk0 z4N3_dR2{utucgyqC!@)RTOwPrY_brUEoDm%OZE>w64DS$1=RSV2CNjPRWS?ufK0u1 zFX(s6T!rhD`1N{%1|YT&jSPh&cj=<61vhdn@Cn_ZH*RYWJbut6<= z5qT7My&9(DJswP-rxKA2I!|~W(lc%9x)OBVL73S(psAMKY}=wVU@jX)B8cdVO4#5A z>GLH;PVPFL4i(7H&P>kEOk+IYNxVz8Mt=2dKj=ho;@cuMxA>NUJf^N+1!|F3=SQ`O z&}Zs30TWTO>0Hf-N@EsN3`E(Z8YC>_-3=@7MXo+!V(s9CbYv#!W9(h9G zbR8Up4urE%E8}_b0+}S2H{O=?mhC>Bk|V&9D5m$w5=JMG|K9YKU>s;rgjl|$5r5)J zl9vP{HRz_;4LEz(RPA`Y7qev9C}G0DqS}-4Q;wUaOJZje24;zRp=z(4)$h=GM!bZl zCAR70j7?KY8y&f2Ab0>T2A%Fzly2?(1|ts6FsM^>j_4BlO>-c-Bn)fr` zzz^u@HO}`slMY#>D%-_whsk!!g%CVI61X^$Zd_An3IQrs*Cm!~lO(paXJl~DQsclJ zw7bUBg=U~2h%V88qhhbw>AL4qqou^itj!){dH~{Nbf_s=YuljS!J=VRW9gV-q>w^d z>_0gRa3nA%6L@vU51SXoMtEqvXp!gDg%?O{qI)LEp;IwCY;=P{2nPk3kES#6Sc;Rg zgR>?#?7QsB+EN@oA{*$6p)w+8b$708tVk5-PL2Fm?%q8x&hxAjm8Fp^OSWwJLX(P8 zHBHi_NxnEu9LG&vXEYi~6HA)0W@JT4Tt$*)NwK7nb&2EL%E*OMpq`6LOM42Gg?70X zN`cara)49r3th^+Tkb5dhXaShvb$WC<@|on^SZMJPZewekBLMxerg+l5WB+&toZ6NTTV%vcP9-@j}$qP7x2p1Ovbx+j^|ci>Ui zA6W+iz13SacRFQ~BGouFDcOkQ1GNQV>dV(atZ<6%nFBDdM81LgGM<{qric5<7cl@r zfqK1ArUL$r{qHsOM}n*EP6b#h@-$~sBI|{HVGi$!SGfCHo;>k4qw8MRwQqikpFo^X z^|}Yl!p(Deep;NHzRci9kjdsLa&kWSV%r~y?k0~CPLOE`*U)#up1cMk2Qrc$IORqQ zFBt@?6of*Zr4f|DwRNE$%_RHbU0u0|?nS}&`mQa)({={Ge{1OXS@@g+LU}Ym94C$7 z^Ke6>*FcAmhSh%HWT+wkVzc-Mhyb?q_Tv-?#Tjpm^dT!Ydkypmane{GcuS~Zb@r1i zp(oWZ-xohGUQ|N^;~^{JS=828H1QU3|N1XFmhr)3$BrKDeoX(rm$~*dX7B_$dN|Zk z-v}@q6UvN1&`%0f8`57N5dVDp;5%?c8x-oU5AUIC;6Zr!6q1PODBy;@SkZFp1`m zhMGt06z+P?67gwP{p~fw3aQ^p1qx=vYpBONN>O%is1+nV&~<@KJ}`s(dSWiW%on&D zf36zNBiGL1*mF2us3E&jGAwuwZ-;)Y)`uN4_mM9{_nd7TRz(SvF2>-w_{%ydwtV;n{I0S zP~#nl{D0yVGWfUO%u*3JniR2b2fooxop>%Ve#J8bvJsLYoXz#q6!j@%d~X4XUo3Lb z`CvqWfgJ(g6W(Z5=|!0-yif#^C42QA^!Tn&kD>A^ief_3^&ZU#h^W4q&gHmmbSQtf zg;nm)R1lvK-}TU;(h&7tvLA>B%uDG2dfs{wfSD6ac0KS7q3I8&dqzNXpw6hvU@sIV zQeUSs8Uot1CM!@b{NB_GD3b6zqf?_`<2x{HM2j|R%?kPjkVg2)4!kqeuMHna_BOOW zgdsH)sU!hBhINP}`6332sPF*sCQ?@_>g(L)eC}h&XuGBey z2ThlmXQf;Q9MN;&B*U4)-{2qwZtPBPq6ppzje>q{XejWdgt~(EaH(Uf;M1qdKw}(3D0c$u8mZ44SsbxzO^Mj09RQA;kMn%$lt_XsN=OvE) zQm94MZ*ytTutH%(0Fs3?gfrW?RGnL+&lLiiMcx6=3)IQgxk+CxsN2;#RVDj}4iE2% z;!UyG6I2ji4E3Ez>)W7Xz@rLcQ)PYd`_d;uy6a!aPeIcVl|vjUQU~5ETq%OuA$9dW zwEse=ee2AG^ilk1y_4x=P?h8{cFH!v>2j=nBR}L7d|C3xZ^moAdi zNR0$1=ed%0ar`&RtRp-raI6TO%Xsk+wAQy{(N^71C}pVwC387Oo5BmkpIM)k_?5O6 zq>DvxOsLafCEU1xo>I8}{qeyR$6+OwzY(&~{!3=mH_;`w65JC-RAy8F&82XEz3HT2 zcaWrnU5}WM6Oo}?6qMJZh-8WffRjWH`hjKFfn)N(k^y}`l1iTCswLDHYPlmss`#^m zA5)1ty-abxu?O=JOCFve`412d-E5hMT&4$?lR2HUFtu*qO=o%5;P!ZCUh2F`3?J_#hvLOHYu)Xxjx3l9glByKIDj^${9 zSk7s;iY6B?Y7yf&Uy=sK_b+$=IXGaf0D=rnO!6NH|74|5c(0X5Gth=pI~cpNKJXgE z%#%g%5cG4DQ*M;%LIXHVxKXj|e8)m>yy8VbX~AecA8Spzg{J93JED+#=Zat?5P;y@ zT=T=I!ZPhj&JTr z?)%UC-n{p7d#Bp}Yx_If_qV;Lt$WYs_Pn;WwEKUe(%)Q5SMz6@&%}N`Hq-P^P2bdX zqVdy>kL~)KUGLk~g(hCczd~mbK&&&&d_M34W}X?b=iLQ0!f$KUBor+15m6TV;)IXl z)-+gdK)3cYt2wD)yix={OTb|VzCSc3p{T$~OeE`?`SlW?osxtrK@tssWpT)G|E5v8 z60E}a%2QN6*9a-Mu$K~=4=sgs_1;CgBL11n#Su#V)u=iB)txy1XEtE;4 zrXw-BTt}h_!Yu$<67t2Ujiq%*sy54ez6gNQj7WE7*Vv*DUptET06LaqwAf%qePzSE zmv#CJJBz$@5!H;cqnO}_Lp$USER*?w)6Pk8xujnu8jIyGD^DlJpy;#0JMpGWrvsobx)qymuK4CyY>}?g z?+W$iCLlVv-)o?9tZ%OdE5{-YS~^-qPA84qdNfCLx8%JD>j z$p3E(HK!S`7PChM+n&Hk9c2qKFGQyHk)~V<9{3$WzGsW~W1t%pT^|e$R7s=lK;_67 zv{2+g>nc+L+`3|RjKr?v2_8bIbSb&U1QHhlL15kzYa6iq$i3x=Y7!~eK;PDep#eadFis3z51Y1d7(r(_ntxiRR z8(+>2dlljCcfDQ&>BvQSgTH0_UEAqOomd)Tq8QbkZB@VX#k*p$*>x=Qd!oCoUg2%d zHfnhnif@d?rn#k?+v{sP)AKvhz4n*%=^_X?X0D*S%JsSn?W2D@{kCP*tn1VFdHS8r z74L|}CfQkeTb*q=HFr0vI`_LOyrBsGjii9?N}U&R+-0fG8jI*7sEL zoPjHC-V?QC&J}Nu#m1R1TMP|U6-#}9$(IL3NFR4!3xZXSa>TM1Jk$Unz}ZUwD->qC zMqY36Hsl2pTXQYc{#deSAUT-PHYsszo(U^_20XZk1VIkNEd)A@F#;ss9co4f7{S%T z7L^~sQh1qJhtwsL(?QuUUtaYt6hV!VmFUnn*LFm7DP9@hI}eGXy&#$AqFMnk6INhF z%p&3jlf}L|c#dFTbD5N7&MUmO2$qX!d0@XO)RR?lR8mf$h$YKdBdtQVr0$7{biKP+ znlmhMhVVRKK_n%Kh*!I9JY8<~Cng11z6(`6_OCaDc z*+uOejAsWlF;94!fcG#}m!UOrvZ8c2>MAY;IM6KFs(J6_J42JxuxJHQ-?uOcvhs{P z#_BDyY897oi!TN%2gJ|kp>819ja1tiZ>jh;!q0EUxPQ@(Ta0hLhPV>YshL%CqhTvv zDr~sm!if2Mun2g_!w;jsUy%OT8Mu*gxT(0L;;iR}@7qgb90=fu%@)DMaApEO{CWAI z1yxA#6cmr`A4R5q7G!-1*e$$;3Y4%G1&a&8W4tuG&g_4?=w6|t_yj%pR5yQa>vj{S zP7(sE_%&BL(3J84d)-MG&J2Y`_ie0TEx01*-)K<04SsvxnIcFX#*wLW;Iq0w2m(vR zRk-dRlj`ufbRsSMXsQUCu{qPwx4h}0%}?hSyyfCJLkD-F(f=c&(Vp=P7$j@wh~Ga8 zmf$PPko(;i7A9w%LsCAlNv&qDNQDP^HoXp)=^`8ikvu$dIFVu!QS(PJl0NE&enMt| z!{%-+SYk>&!qFj8TT~v?CJh*hB-kwm)PY*bQady$Wx0E2P)B27)qAm+qqrfo_@`t7 zD6+^oNNp-`4dJNU=RWeix!@cxL0TXLL6Oi-GB8o+nd5oSs{T=t?;M-pwVx?w$puYN z=4Z73-jVoNUGAUYs_|-Ti#Bq`8!s;!YzUhWO#hig6#}sPi^UOg`|vvaq;!mI=ONfU zXVXYxjhw3KH_VR{=+dl01F_6EFnQf zKX0Hz<)anHI=6#0~)>97zJgC!f0Qp!9-wmMSXLsHUMbLQ6%KQ5h5zU9& zMwl=dT-mB0U(}=oW(2|g4 zNj)jduF_O&N*s5N{ZhNb`OBgM%F&&is*$?<**qL4Y8&Au5!`R$?217gwM zIiq+sR8kbWJjmLbCQ41Jq>L(I$EiwxaJG0Ny!_MrZS}Qc9wDj~Pmb&8%ag(2eW0faTEI*yRd5-d+ zTb{(`+n}z<25?grLCP{i=7$3x3ysMhaByK!Z8Fw4&%<@^CDaKSiQ8eEM2^gg_{f{M zwL`&sx(K$G(`3jy@WY`oT5f9y3(&#U%-kOeb!MS2 zZed{Kz^$}OPIkU~=t1S!)j34GwAq0U?`DX?4-RK>Z}B%8n;3%EE@MHnoVD82z=i>mk`h5?S0SwV^XVBKLLB#Wc4-GKn} z2c3G`!=U~D)eUP6`;T>8?Kr&e!+ZaA@B8;2Zr^CXwXLw{@AjN){iD`b?fz`bFSp#& zyc~O5)6XN}F} z2XKbmWp@`{Sjk6pN<9vB{G;uWp|4q>Oua>1D3h0D=O z7jVIK*FYgNScTvc=pQv#IkXNJi%3d-SeD%-$Dm8%NJcZ;?2+rSy;Xm*h?L~xbmDiq zTp4aMiWMT-3I0#SJ1+~7F&_yBQ4s5MMvw)#RXw_$v~xxT9)wFqnY#*n0g{MMN%ME= z?SbG1O-+bEH}cV&EP#FI*xJ=>g&x# zq$@vMpt}AA8GNQUZj}_l18gzq(0#K?wy8eKnOL(>lmv6)kT^75<0*lK3T0Z$QmKk= zLki%EDk7m-N+=!pJ$u%KOO*Ok?JY8lT)Xbh)5+#>%#I%lO z3A8NZTae~~-$rV*K*E1FJa31y?n9CK^f0QFiNjZZi#fUkVqWslJiS7)xJbk7KJ4`G zgc}v$JR}w)@jRsjf|#n>z0s>{&Z=Ei&0k>MGvE^FDrVuctrpZ2PQx->Ku%u%GFMK< z&sM}26KLkm-D5-XyIJQ-Qr*VlXORiCz*rC6vA^x+5ga`*F>tv9P$@^nUmttVbYoNy zPO@T~Jp!u3^6CUE9MKE>G>gt6a=K3xE}{3|a=k0m*j$^)dDpuxYPC8(Yn5g@x+m?$ zr};87hvqlkpioF8Th|>}Z%m*@5u!Vu)*WBl*B0j)M#cMe;5XcGj8MeU8Uej5jI_k* z9j{cNG##mYpn*H7#uL{^|Ap^^ts_~UD9*9aXFEptc{f6iOGg^a(JF`qypq@Z5upkm_o_P(-VvhUpbf&BE~^?m)E ztB5BnB}5=tGZRkRJOl}7e=*ikl8y=}GV$I^sv|5|&@D^X(Iw(#1|8T=k zv;Nn@n#vzXrcit>4ocBJ;CzC?t(&4^Qmm`KJ+Q)i9I2W_ab~ zR@r+D;3F_BeEdRxru#WTCm?D%X5au`sIrnsBPW3p5fdhk1_M67AZ3muz=xnRUaCv$ zD7P079H`b*>fpPHXS{P>&LAfa(Uq9!g&PIja*z)F*AdT7GH?N`$l`$$W!K6k&D;{% ziuuS;iG6`n(}( zy~42)viwpT(APROWs9@Qj>BaD)BEMm%Z!_kJ)xi6UKt7JuZ3itOVsj5lC()C8~r0t zYa+qkD`ZMY89cTD;CJV&+m4}lVkAwL_WG}+*#@jpa36dHGia(Nbw~V|d zWs#O0(U60oku&EJast+}LAg*OLuYn0W>VbPH-mlS7ZoE*$VN;RPGe3N+?;&*X6{%b zK2kTV8hOZM)&0I|v94SR{*uRzhaE|Zde}9kj>p0}hvm@!TRiOhOUQ$aGY-(HnR=X6 zd^88rFTugrt6m-e81Ta4mw~rkJVe5k&p;P0B0S+sf|oJ*{TZxm1i~2Pd?lnz9>0nx zWv6D{aY!r;ZMn{^1dOtLqt7vh7a6y=A?E5MJTMnNWX{p?I9@Yko-=GRzj39@<)&&L9v5Q&GPSvazn z*5OMUnF%7z_<@-deXMas6jKJ-YSqB&Z2t2l zFmU%1kk)C*u>HN4a}5)dWqMxLR?F!P(Z`su?_ddB++(CnCDfT{|1|S_?&Q*G}2vYB?%xApLeEx0B=E>qqNOK1crSq|xxyaGD zzN@XC5LhgN`8!4ESLZ{veHZ#PG1u$&Kvgst2%gdBEg}pICLr*CpWJvAI&^fB=upC4 zR&T9$%r%I+We2_k(MKR#UmAfwc_x%kLVyz_Z9k~8J^lKBuWlG@*nhF(BOR~acV*w9 zz3KL|ZGX|W(ROIhsn++l-n9E$Ti)Grck_2O566BSS^xJpzNc~Du6OM^f*)1=Dcy6;^r`rA6+;pTyQPdPlh94LH`%HjjhPGmX;6Yt5l2lc00N`Gsggl*#h$#kT;8HK3v z;1?Q7NGCc@Xjtb}*D11IM&l?seKwV-53{K=jF3RG(N9a{Z&M37Ca=&`x}72#eyz?8 z83VXyGbzEIj1Jjz%K%W017|=C)&(cQ5D$(T^dxExDsd42Cj&b+WC{rWi}w3?L;PPv zp2KJyhOIVnk=-$L-{I5w8&ra;IdeFCyzyb zeRfXboszt;%qo!vx@LDOQM#3u16S#5WtAv8CI;i9!-;_jWDcZ=U8L3)IXD|wqQ=Y7 z$j~Cn&G<`dlwBxNRtbw-Hd3#!L3~N7CE;i?Sc;m&DZ9lK@Pzh;J$2I`a?o`^n zs#VTeyNz2~Z(WGumuRIqT-af%0xXt+0pU!z>?9ANdHJ(!$~ts-sSTjJV^+DUwaBR! z4wsNvC8b|FUkV)5!E_dU&1$x71t;)v?Gl$Hgw<_>bx_k$o|QWHIK8XlrNbfu^d&`M zAag_LdmryGQhFVpF+xUObXQmohdAmHk3@)VtBOwMTwtyAT;SVsHoQV}3Dl#B0x;&C zFNB-b92|2sB2QZ=Y-bbM6x)P7T3lb6p9WM2mYS)yShe~zUJ$zx*O>RV5;#ClGC8*M zc^Su0a)@vxmhB`>a&J5r-{~N@2Wl5#%{O+J$o6@46g@oWW(pd(4EUG(QV2qbHnY<{ zA|}cmH`iGrB06ue?p%eZYK)UsWDsq6<#2*pB-*d`~-+-lbe%= z&JTRCcc_LhmcT#ydg8b{ugFS3L&g1!oVs&a8hii%h~XRQgLcFoulh9dhCN>b0cnCI zV>+J=?!;(@z*OwS^$D{?`pW(1{Z_lv_?>+H+`d2d3JSX+*dj{g9NjpA?k`LCM*63e zLyy-f8Z%$L7ItG*Ni(mNO-XY{z`Rt|Up7yb9+b#sg4_4iEO3pC<4z@{#6BS~M_@#K z6J3Oloiz&_PEXRk!M~VAG6F#oI`D?d3+uqq`acCa=b&2t>p+PV2~om~f-a~9aJ4`e zGICpP`HHtt0(okxK;3ms*FNBD&82e4L_zjY25dAr4Axgb#Q{b?&As$y%}p+ota52x zYOK3$QF22O^~R|(RRUe=8LIxPuD6jSN>qRtlTJtB(1KY8X8L3<&0MMrnoDJZ56*?5 z(_fp%L$8^LKC2eyMAB55(~9fGYNi42X8i;qhOD_k^xWAEQ!jnche^okdI>zG8kM@_ z`oq!Cs1)R8dK-D+>_(hx|AwMckCZ@x8W-JY*-hMBUPjT8yRf}rNaQN7gUM})Om4Wy zye)7>S}O;;k66;8*L`N)MAOy!F@MLt!S#(Jr`N*lV&t8kE`b~Mm>7%7hlzc#R?MTL zLzze!Y%VKmxZ#MXhRcJgtXS3pvo8x8^a`&j9irqogoD52R!WM>q6k&JK8%+gS8p0= z^TC72V-MjEUJ!WX7P?um2roO`(YT3N097o^pJhR4ppZrc1Tm-zGXI>0#GaX-xr|aW zC2*(SFVP7l+~hjo44W|AwuZEPSI9cQjn&}$8X+F!q2l*Z+yp+| zcnQ3!4{uNfQbJCSMF9drLbR2#XSPL_jAJp^DY2ji@)fG4S`v|vh4Tor;_%Rc89F>r zq4^;W4OS4MRZZu5`nIC*t0vJ|IzasiJXoDd?r9cO(R0@iHn>>`Y%aoNKruQDlL;|A z>Bic0^oNm?VEq598uAVMa~+@V=-l^#y&vBD0PO$2ZcFZ2ZT&*)x!toZspj{^ek%4* z(`e&6c71kN3}3$Se}&Ex80d5j9OaP9>r!sqx(<0`auX}~Jl-^1>2f&V{R2So?U~~ z^0g$WhxKm9TS{QUOE6ct^Zjo8U&fL90}ZNk%FQHVhVe+qYl*k>Qp3Fkwb!mwVW{*L zMt9F){NL)v4_rKnyup*2NYK^?pr)S4F-Ec#zVJMNqeGQW{ck-Q{!poMD>JAn_2yfl zFSzth(d$)t4rauIbWWinQ1JcskXKg%mEWnWw3OcGCS=qN;itHs6oViY2XNs<7}2}UtmI>F=zs^8z@7MgEVDtmeYCE8yZui5q8 zL$b*3xw?**L%z%!d31?gj1z<&1G4s9w=G;;sPwNO(Mk+~CEb%f{@~9h~neUcn-T%4i zHMmVuK!m4P#^bJ3NHxHx;o+;UP*^EF2$$wnkk)io-0A>GDL^e6H;6)HP}%o7icGj| z`|#0^E!+=P*=yKQ2tkJxmsP_6t;%dMWedouTHxhYY`L>BvEen2M2du}_2X*FI}C%2 zUC0IJK)vTm$LL3A#INiojoV3z8;Eun<`oozF+zTViyP6{AO^1{quDLgE=@CV`5OM+SS(aMD5!GN~%i%E3Xn4+UIAy2~j}lWA zz^DuA6^2V-m^>-SJ>}!#O)-YG&3}ygrN#4ZaR_Ab)sM%;L8Z1xb;uea_C6(iq8&LP zB4u$HsOZ+5W}cpa9;F^EaCMhJBzbHD959{N+)}4|vT2lV0E~u_9X=h;%)^=PY%rW! zfICbvO+}&kmljbg(Ep(HE^>R}%);XVTQ6!+b^_$TPy)APlH9PJ?{>o^uPt)=Qjg>6 znbQ%~563;VzUrXc4CLsH4CX~Hx}{-wyad|Fp^ZFxQi?Iz;*t1pmN#C!8SrZirE+kk zMfPS47juJg+R?piPvDMX0WFFT*L*bq$W+xULgTWn;QzZDCdu=x6av*DZ0FQ$zY4RZ z(!Goly#|w0Rx>Gkxa%V<)l^M zbx|*^z_wUWo95?yzP(y{M z`Y0E@wGvn`PZemCyvrR{qeBX70Z-EQ&W`_*avk&pK}H!8Y*X>s$b-V|rMqbiHKX5e zaQ%{)%&j#5J0?pzo0Aw3JqWHWj?Th`H+?Z=oUgh{;k97Q+R=T5q>#$GXsL6gbQgWp zykzh6M`|xwBAysXGFpf+n!Us^fR-uh0-k(*9C0|zy5oYu!|%Aol+05Xj0b@a}F(I~xy!AZm zzWWJ<+3C|z=(zvPQ+qOUMD70%H|&47Pj;mnK78Zm{|){UXA)#wC**zk5m`_g=&%k`edEY$983*I zUjzxgW1pk)mAOoinpzcFF9<-85m*ia_@f$#-unF|ux_1Va$V=g+(-q%A_a9B4BSHE zhaz<@h^wJGntEdO@hD3$r4OfZd)aG+2TCB~N^IPNA^or$lCiD>EJyW3NrYdcuDQ&+ zf|~=epk^k{XB26d&9}$50g#xv%s0qoRGce~AglEPPw=UX)aadoEnJFB@skN=@1!>Gn3wcBlqgVa-|m zx166`1PB3{6(+Lpw`X5a^@HCH!VA3J>nL5lAkA5GW{u@O;Y*lbol|JC_&3A8O%;l6 zpM2X}d-DokRRSs5kR0hBj9w?$FDQ}A+6wg!(aTw_=*#waDGjl36*+>P-(NMd{v_gW zsl@ij6F3>&L7&9-b_W6io(<5tG39>&5*p_{8aE(UgFfVd8a=hb9fv~V17%Q6?u{kz zm8Ikr`93#0;j&|r8R~$bShIo_b2vc|b77>Rje#L5f=|wibA^+U!tI=`d0~u7=ymtw z-LQ65xGf0AAP)e)#-fPQfYyO0vKRDbC$7?A@x9^E4kMd^(8_vy5&hb6xHa>FurQVc z9>V~Zk~*I|#hN^yry-VK5Q`PlwDv3%o>}<4#EBNw#dfCq=F%Y84L6t?^F86|QfP2P zs-o<)AHug5N$+2RTU*s_^u;+|0_|EqNhmu1eR%YP0GfdT3!eB41F$!?XMuyEYB-tyXO6a?TqNdvV02cwHvoMqPrjigg>7J? z1{g4cd6dDwN8X6G63Er!1tyq$I6P8}FhPw4|set_aP< zP&R97Y5NYMKngAOp8&El0?uIPKox}^2VnRvilZj@-Qb5loYwx-aLE{edri?V$mTxg zn9#xRO4`6ILTD7side{A)O*XJgbj%0z}z42k6W$_wajramlXO2QEHScb691dT;@Po zGJNEI=gfAVIhXtE2n8_W+R?tY1bVepff$SLbSJTPv=1Z_%&b9Jmcq)}hhLT<-ckZ7 z+i?N>xVkxdJgG7xnqYTkNNCuM*P3r!NN2MR#59LFZln}pM$y_B}QUIb;ik5=Xi(v-+|ESPRo7ZL^qsB*I55HYj%Rs?^^ROOTwrU>;^_sIyRnb` zqpK9pA=^R)Q#hc^Ep~C~P-w|Sl1`K^(41#bMG59P0b|bhV&%xli5$` z=oDoeP6|sWj9M^5=DDZRq*uoLJnE@8e({YxC9t|Au8v{wN>$In4~-7yQi(W9`PzWY z&Iiv8SX^IN1DqLvMruD~o~3pBSf+*h9>OX>{A*SN z*!IAbjCsfYhFpK}F@typ;%+C=2mtWU^C%Ky`!nvyKTu>krmrYqT@k%R+; zJW9f$r2}Mh0YEqSgDm8Y7XR4!CgXUrUwO#za>JdD^1HL{#uBzh{|PT^Ry`@mGUs+_ zam2b9gu+4zygc!%OhEgLyHP_!3L1Ant{WP30O(vTU0jUPnUf@^1KdT*9GT}gO`sv! zihbQk14Zg^3%Y|q61IdJi_|ICQ}}q_vbebV=3DM0K?h3VBqcNCC*6Fl7B!ga8HuCd z8&dA-&A3k9WaxR5XVt`xj9~F6UbtLBahp?;>Fnwt*n}~6Zt4vq`uP@NwmdUEe}VWR zw;VP7+p^PN>V=>->r0a8 zXfCkw1K??Rk`yBJ1b))3hfs)(W&qjkP3D}RlU-^#ko2J!qIL|2|Fp{P-c6%0Cm!p&Co$yekl$C>xF zNptRl4?6aq_rm{<^MM9nDzJ+Er&6E36>F>6A8To)@F~(n&XE$zBqa#!`h=SyqM0Me zVmM3ujB=BwG~1Im)+gx~J0zezF*2@t?8coX7D{>tF(a;0h0`GV;Cvhd318G+TNq5} z+K_qMs;@4VNPu2ly;pd18WxnZFJVNL43f(1? zib@Ey;73EVFvJgri@e^Z6In&JTrr*Mj2@!O=Qh?9DwxO2;Kw@xWQn?yBaHfm5^7AP zuD%M#^5brdW_4*GZV#syI-71uUxtFaGtJ!(F3LJpUGad4>1q7`!G`^%jz8(>+xN)c z`S$aMTG(6bQurW}235v%%=)U<+ zZk2c*As4bqRH;Xf7@(e~Q;~Gb;(@n59Pzm8GljqlN#amKe1SeCm{j(mN3_Z1F(~E^ zf8n{4ueqQb|B}}#W>BP=0KvbQH&9!oo{PU_063eRhQnZT%F>q@6ELKpS(i3iHqwzCr57A)Yrg@ zo73wH$YT_E`8rIQ8RUoA!xc#WccN)=9^^%M3C{D&w0i>d?sB$fmR3QxB^z#Am#;w; zn?__EJ=|@b_Nu@HymNIMMy6sCZZPW6o?V;fP{^$au&jx9cq>l*BkGx&OZt8i+L>vZ?+Y8h6VcmdU-w z|2U#7XG*jWcgkA#9hl9XxT}`F%ik!`CAd#Po0m2`)4?!y6Q>nzMqtMX(>me;`$Fr> z?E%w*@)@V(J@je4MgAnmCI$#SjE^L-jFB}&45$}_R9D+NGF1_N2cQPK?#H?ei$#u? zLk|yfT4}}2Yc_^7g9I%$$*WR4U<8YK2#oQ2irbAY+=(8E#b}ULrt0 zas(&hB!;03)RhfrK%|~BwcKD}x>o=23TI2}3=ut#q4{Ltn!<$4$>Hlnd~JpdMowiE z7u)<-wTTw8nc&xw!)SkPQ5>2*i8>2B8{BkJaB)a9Vj?!3Y;2W+;7eiw79#0(dd({w zEv+FRbmJIi_UrEK_K^2sBn4?+cWWbk^B57v<>d0#b}p`_k__q_tK!aBh?EQgAhdaf zO)C4wi4uyV484QcH)S%XCrjl-vKRc`%C-6Ub$QIG&q2#TQiCj-yM$P{03OrbMt>^S zh3@0>!|QZCNxFIkC8igHB9nn*y6U!2P560)0jL8ZwIlq4pgP5Jg=zJxj{#{~ZTYwomJ zX>vLl&Hi8|$yUeBf6rW)o30F%^e>c9+~kCiAN{K9(ef^Cn|LG?f8L2F;pq~}mn4Ov zKv~zh+{R-v5zk~G-nKrbM(~?EfdhhrsqUEWFzKjyK=Y*~7F?s1<0#ji@eKi*9vw+& zIf$)7@1dBsGrh%e&)B*T=r=tUvL#d$8QP$m%yFj6RaEgIchRN}hVMw#GhsJ(i@T>% z1qdni^6bflv)EdkuO=^Smv^Ob)^Tdr(sHgnaY2FSxOpiZzPZ*~!>!#x1x&l3tu=18JKDt(s-YY!@WJ|d zH&}#o(|t-BGESY=>XVeXD`3&$8%Rec=Dvvfm@6;{gasoE^ouEytQa)7%z|HGQ(_>82Bnf4%F!?V8xth_Bz+zd~mj z>>#NEWWd2jH#!_c9-UCOZSZ-lt0ILrPfN;JLz5qI8;l^f0q4TOGFU!FS=^=bf7#|i zXO--Q8=PTYx|EW`>Ct{L#{qs<7chc*HxE{NHv$n+@R?9K5q5qdCUZ&%Z>t+8#>EVs zRj_z0;xYhCxj%(ls`xc|^$gZ{JG3pfo)ec>w8nrbZiXX+ z<}wi;Ez(AVz2*nT(6)?PT4ma$-53)=>whT|J~*S@{A*fLIf>4sS1(oWM1ARg%=&-Y zy-=(UUe-8r*C&QYhkAr_;B0&_)tg!p#h`mgAZLk5Aa208KP-$!o>x8)iydQj)<4^} zQrVG&jd|JM@^4s-^E2LHd4DW+?<#)qPxc4mL`Oixs!!Gh z&EvJk@zof*9Cmyh?D1}Sr`bTSWDw%KPfqPb|0>*D-pk5-3`qQ~tb(7e)r)X9t}8Rj zwpIkq1LniJuqN`B+w5|t3!7KnECsItY>K%RaF;&^@exYofR6{CTRCMOX1E`G9eKTs z`V83u!`=V4jM$`JT6Yp?x{zp1-mDy?SvJ}kE2WF!z{fb~F=e(mbSHXF(YsVG7w?kz zHEnvUS4KI8lN)b9$A1&**d)#n7!iG9RFJMt8q{65S1U~A0XLQ$2BB$r+wf1ApG2Uh zHaf~EwU8EO!9SM~Q@i%rP2;$?eqoE~p}WKGwuFilg}xm(PoK@?;RWUw4d0Qkf~qKz zHHFq<(({Aie-xaRWDq5s6d|CmTR;~D^Qz`DYI-!4-ODQg3i67}J;DZ>!?VQz3b&R~ z=^?(s^r!#qRz%ezvx~^H$~oY&SzC$`PSKIhVNe{XrH%;4DYzi|CiuJQep;oE;676# zi3|{i5`%X;T1K6Ql#mMlnH#4G$VjLml^fqVFC^}f83;EJeRHT9#Db)e|AunSiaP=C zu#Xcr;VwVK1V@SQ;4GXfw=mE}YSlk=V-~jq>9a`YJ0S@Gk$x;|D}d>Nvp8%++O92@gWg!kIbQ>#`=efI$wrMd*@E)tD>0LB ztc>apajE|BN6`z(5Lcx14ILGS?iUDsu=?cxSL<5Hl~L&-D->3L=%yyX)(ij=qBP)% zaZG0bD=0B0lK#Z1uvzFviGVnvFl4YKCuTkAZE$y?{!>GqoC0%(h%9qyLbz4v)zmNK z;)JlPKDKop0tDWUXVFN$n;Z$oHLStWLEzqzHM0b2v@K|r&0-pQ^+2e zoNvh<{9l8k24OQNL7f(5behM@4aN-oeK$`^>=Zb8&YEgD+dr9zEpiU)%gDZj?ur~* z6l*xa5{I2%3^h*^;JVq7JPKR-9dH7oT+oz{=ksDmNNhl!;(&-V`E-K+-?gV<|FMn> z`(E7pYwds2_CYZJA8j4neXZqZTlP1=g{DoX{s4LQ{RvB>WZ^*O&%ulVMS~)UD z3>>RVON*j6FvYIAcDcNmSyec_LcWZ01!qXfa`54Z<#Nk3kr@DKS>(+zvQBIO9?#`@ zsdHszgwbp4CHLLAeoRH=zggzcN?nNxbL7OuvK# zh`qvU`F5&A05%?cvzxMc`sv5n9yAE*kD*;h0iAhN2bWh{S#RuI1Al@}M!5(j&0+Yt z{i1WzcWbAut0mM^0j0+NRVE@TWBB_l4CmJuqjIRKBA+AG9lc9s6k`}7+t0xhZr1+2 z0MFk@3Z+iBaT~zAW@rXox}w=*Y?s)4hEvTOFW*XWxeI+hH~=a*nY25x!-ZiNATMMOH?gf-H@!gAcmS{KaFp10$$P|9GAC3#mR< zK}S%Ra-phoD+t1)*a;Zv-ty~MC5Zz*<_2ugDY8g51jjUqN7f0|B zRhwnp5ffz;W)N!EgKch(KJNIQA<`DHWt|N0cKT#gEtfQah8!;4E8JB^?TUWZT|3wk zIls~2QQ`dL#I84Pg9o(u5bKxPHf%O}TY}p$Q@)9;uoRfhk;8>rnH*-0h3v$(2Ydy{ zX9cxL)C4dhs`eZuR4g;7V9zBOo6AUk*vA zY;={ivkW+tVVJ_{GU{&(Z6LyQFt*i1jZCTgriGr^Etf-I->73}4W&qKm+e0S{biK* zNXm4YBBx{MbGCKL#5^|)Ig}@S$7)chh#P%L-ZRDjXB#^HWZ%#2{ZRW~wl}o>QrrGL z54S$k+T8NLT85kRv0n%G|1UM2Z~Qhy|2G=`ydirXCqQ9;8FczXg>h{51zDY*)BU}u zSv!~pSTF$uNFOStnfzw1P^4gWI}Hm3rwN9bsd#NF-Ay9C2PqM>m<+Bg57~iGHyLaA zo&zA^6>chnA^$W>FC3iNa!9I|zmg+T^qvSz>?j@W>nk7%x!~0XUvC-w^ydl)MjxE6-=|~8-9ewWxUktVfr1(R zQ~e&QfkLdWQO2ul19F@`P549IGI@nW86@+Q-Ez>-gd$#t9&wx+d7|Vgt|Nh_mqKtvFvw)uK(8MsqFPT?Xg+39(!n`G=Dts$AO9m9tXH)4>upLOH+R@=*peV+}ROUq4A|`|NCY}jS0zBYG zCInq}qmG)>c)ZMq(4zd;UhIt1;+4e(uNOLSx|_|-Kv;^{}{IV!a7 z+!odg!7-wL<0gb(c&QBf_H!)kc(AW#6=?Xu{|#QFiAPb5Hfw^NsmR#13>%EstJAA7>;+j1C_4oXTKgKeIs-GbufW`O$sMsGOO|^J2CcN_NP}u3bSuh?f`hjAXe6 z5sXhNA=u0?;aN?qp-8`;t3sv>lJ`>^C@^r4#5+kAXw_eN;Nti5Gb z8|rN7Jr$vlwgkqFnT9XH;hzorHGKE(b<0@&=5lp75VwE4ydl3Wt^li_a8D#vv6}TbhzM#e5}jz-o&hT`KXaAZ(f|y*pUt_X$3dVN8~Ni8W$HiC|Fc#2!c0 zC$n&0Ja>}PjAzo6Wap37yQvyEgpxHrQC29(*WwlSltC~wT1aBDYBNCYB~DLdkfSva z2l{L%{#a^gbO@Zy3E`f_5!TEdmp;zkEF#7S9#Pzyi_aGrLs*7;0#<~|MNkMqlp)9{ z1Slp^_HE@SW3jP3hNAkt4#jzQOySz2z|y;!=WqRu9P>H`)J1l93tX-Ff*st7roIk zm~K*#6o(#{zG1Z3sMSO!K9U2cJOLny)9lVDTEJ7%=10HMzi)lOSB|zxT;&xy${@SR z7U2Ip^q914Ua+1~6tEbXaO-E>?`}4JYyQ>*rW3L_^&lB@I52(sI(Yy>=els93`Utt ztj%?3tlo$uc2o`4m0B@Igs2hLd}v5uynm<+ewdk!Lm1Op8B^4) zrZ(5Z^Uvg*LFBE}iBfPew&cH;=iY7H4Wxie0|rNRrhFD0NqB${-KVPwsyCYpV)7^u z5=3h@sUd9H7NDsk(z3yq%F$$O-X zDj@xU-X6Lq>W8l4lO4UAyGHGq3wOMHCKfx6H0DEhyC&?`u$aC5sW9%D-y0{_?lMYW z+(%#1p}YLwa?LYg!sW&H+u3h}P!vh?t5M zQQPEr83hfF7pM>1R?{Y4Ny)GZ%{0g=S$)#2wXG9Rl^;do7D5MyZuOhS1XKzpy6I zfBsd`_7;rV9lyXVGoCj8L;4N{iDUg7p~9~Twx#zCJ*SJN$WerjptqM{++;W;@i7UNcdVFM`hPoJ%dFf~J)4>}-3 zqKSG+Q>*jh0uwhi9UG|WQU(+MNhY%#^l5WPb*SW1AfhUAoJRNtnH?g+pF!_KM!*DC zYQu)LrLF{Y1)YT&-7_Mqsl7sNGHMJDg;ZUiEB9hqNfL1Inrw=g*uJt-N3#yOsl#|V zs}gX@@a`d_brun+uP%dG{|sxn9lR)g1!IO5bH-<4g3_Vh60tIkJFZ&HQe!gas6qVN zA!sO}_U|@E&c!1?E)=+X%V5zT75B;0x)#Kf^~GUkP)Qs~_G9Ogfd1h4PauP~-UwZM z#TefJTN)xwDb&VM;aKV;5DJy4W8VbKcpb56j>oZga1c%-sIrXMaL7l>px93rrm>{+ zHA|{{cO%g~a}r-hRPW(3c=Lxy-gI!TW?*o?IYLH?jaGZ!T2x&=>$Me zcB3H?S-Qz0ybSaKE_8_`380xr#h28ZbWt6Z_v2?+~*_z?o z@OE+-ML>2ucRC^SZaLhu3y~sAe#A-{wuUpkc^V1A$(Y^ zD4#jr1j>0A4PYi7;DbkzS(6~iwCDBNd*Fgrt8~V4!_zCRo90^h}*teMuJIy;SCs&noh1_r@uzo)bQzSn#M7eAD=BhYIQIY zPTBAn$a@Wau4({Yy8Kcsc4iEnjvApTiSw|^t5(CRbk!}WK8JbCYpy-&6qUh-I88I< za4y{D;3$JC0wN)o3Jr5X!3rx5SJduojboOnL>k8iFSkTO{V&TgupV4kIn1vlO}xs{ zZW2m+W91iOvG`>SDJw(5WJfbJ9U$)AcyHE!C->CvpHx8eXPK`4{ z2z?R7l7)_r^JtV^-q!`LlfWABMpAiz(86NzzsyE>7t3Jj%M#jhI1|-T)hVglDU73{p2kPW##NItp*nm7%%)+Bb{%;rf}>zW{p6Kh~N|W3s5NiXMo9pDnLJTF@T- z>%azu8|D-pPGGC1eKDz#*r_sD-V%j9X!-vNv>bh-CRt=#C*g7j^tJ)PMI4EOV%V0W7 zv24JhZ>eeq>5j?A)aZ(j^e6iOsSriI8_TwUs-)o&BMgNv%sktDK@U~X{?HFXE@v$=UMoXWJRocPnAJpmJ~ljrK)X?G-Rz-H7C2E%R#3*UCuy^;3itf{KCxA z?Ao07e3^t|g?lmla#a^pF2(ifZi$(K5L~lO#*>8|1?P+Z+aH5yfRk$sGHA{iK_w0r zXn*IuPzI4#nu^V#QdRH%;@NRTA9PI*fsqas!YtoC_HUT3?Ml60{s4IeyxB6iy3$0V z94c0I?-Ux_yYhS539D5bajS6fajm!*cA@EJMNjiYgyL;Fq{gj(o7G<{dzl@=lIQSS z%5E>-sL~ouqZpijdt2(hH|-YI+!Dqxxaa&-j=pY`+iSHkl;e$?|k8_6B;q_${A<8m`{E)gJ;=N~yvxK3U zLS8Z;8$Yg*M6^FM0=22gI5R6wQjgwc))Yl80aOkYSIT_Pk z>+h*QM8NXmsO0&TFoUt?y^-=$vDg!Q8x<>TVredLhXXUnm`o~{0=w7a7)v6rseT!l z!em4QzZzBq<+9gMzfcI7m@zX!+zkERimQ!^NxAslHmY_x$Azfp!gLc{X~QfdN2n_8 z7i(oc_2VrDuv`^0rj|^JXA>2v=18(IoYC&L3-G6l{r|d#a}E2;`q7iIrL+x$3f0LVX$OzbHXprKL_?~N==ePy*@#G`^Z%p zXJ1mF*zoH~LLb0=boXUOQV6%J3e1yh4NhMXQQsS6w5v~Pe0;0UiBkkZMa=!RS!vrvgy{>`9sGcs|3Q z+hPpT;0%g}oVUdk z+~r7gna$Ryw3a(z>x*eT!!8g`4wk`y5Np%_T`{ttYECKX%~rl97MsLtapY@dSiPVU zoG|>kN$?4RAc&Y0dFGwhfQLuCE}9VH4pNQh0u>4u1z?JA|%DuakU+ukj$r9_b%AKZAJq!m5|9ycz+} zOBl}!G9KXc6>76h?T32Z{FYCCg6LaDGP7=aKB=DOKvqj#=?jK7nGW=!sDq{p%BWA2)Q zE*I*vCC$I3T3UcrsraE-wHFiJ1M?`C%1vH5RWBcX| zGnB(Q5#+?c7!qlWjONiWqc>gpj}UK#noIrzO8+6mlKlgtSj1W^Ad-f?onJ&SYi|WK zxA!yK?8sNk&>+BB;dD?T;T)EK$)dc!CJqoiN*tk@ZO6#PqX6;C5~vHN{58E=Gv0Uw z47X-hJ=WBIti{4CdymAPxQNC5Lu5FtMSpcbM5ZJHcw~jVx zhjPhyR;};%$qHC$kJF8F z>+tsmDqw$&kHZ=H8EM^#PsD2Q&_j`iO2{sp%%nh>fvv#!31mGs4V6CVVJI|K4v?S( z%I4vp3^$e?7|l@~G?w|yv+&a7 zi^b(erOlxy+-)NjpdP`GjxLRB#ZBN+1uU$m#fSfiaG$|Af%Ko-;uM%Je0;ZiCw!N> zdB=606BQ7!Cg_Jc{Nv$1MIjRFN>T~k<}sHJRRF2~VF^VWkcIRGk)4o6O{Xe*D8qom zJp5zQgZks_%5f&{2Ye*Oa0T2-(v%s7HVxB4b~ly6n3-BeD0^ort+7~^SMo>0v(VkL zRqEMk_1%?e{0oyyv+M8)*yHccrdJrO zfDdzV<9@WJ5Z$^DipD&}l7cYGQ219rUr<+YVDMPU{c^Etf=KA7kq=-X;HNxIB9WwU zF#Q9#I@Qeu-g?_+NOwSmWz-xdugxUNA$f(i3TP?&3!|8i!hUN`j7G+G6t)eX9e-78 zhU#!vHh*=Y(#Z5xJc5VEWvlGs!jD2z0v?p?IE4C;Jyfy;7YwNhFCA{;_N`6g|8H%$ z)Uf~S_P2C=y5q{eKic~b?f=sLRQsW}kF-6y=kNCv_uSn2v#pm}yLNwe_m$nTmiM;Y z)cmgIuZevq*4gy&ruoLdYW!g18+Uzf*UYYthEJiP>;3Di^uZg7&_h>VriZ6pEIGB@ zD4f-Jf-Rw{CPX1vFL?}E&kw>wZ6?T$WGr?+l;^G`X$Yw;iFl?L(0?Q;`pURfgrTC! znNipiya>j|)m##jmzb;cs_U<7G0>)_myaPdk{*N4(Pm^X=RvGu#BLduXf8q5Q>w@lSVhA+`M#gp0TeN9-fRPmsI2I`o_`{gAN}+<58iG{j+^uK-STiU@-)bw9eM315W6 z(P{Jmz9WHEs1AJ5AKinQoY`Z%Bh&c>z9!JR=e)tnBftbA5ZR^pCEa0xQ1l5^+ZGEa zmtMp~Xmg*h0Jn3BPM$7>9ihEs+Ekx`K+KV6g+egAhr-v*gjr_bVo{(3tuGm5jXbBu z%*0^i8NbXkDqq4l#N8rFcz@-sNG;&GSI`j7J*or?qRpN8{*m-(1_vLm5b?m8Gq1`3 z1f(pf_eAAnEH*ximXuw?2ndEn49Wytm53~iST~zU2>+#%QNm;~;U`sXMb?UH+g<@5 zMWO(ezDubxbeWX3dUP1fCc@@rrwiYC;2zL#s{-1o`&FwMCOVXL0%S{z&}jVzibR3E zLBI2!uYjrIIN=~&%8n5nP0wg{{FNEUylkFt_+blaHqTYSKOqRnE_G&0ikM}4j`#ZR zCR63b+9p0X`)Yo32@ACj6E9I#EBzf3E`zgI5YX%G6GRADy3pM;c~_8XWFf@qv#iPkRXjpUnO!h^HwWh?ii*%#5Q>Wr>gISSitmPjf+0@AEE zTzM0cTHw{|Qr$7AiRy+jw8*9QFN%3f#1=Br%U4HpmHW_O9u3-@Ew_-edA>Sf7t`M! zO6<^jnx1aE&s(h=ZI0c;>UUkLhY?^g6dyT_VoV&};^fN3dxV7>E+5v_VSE~KL60AM~AL2paZdQ%mo-`_=~QI{edZLgqiscvhFK95Fp5*jQv z7OC=SSlmZ6#2>1HC`sVHD_J%|8G5GGgXXXXGIF;`@G{*469dQPh(_+?27S{XN5w@} zPcgVhi@>o#3%FNR`eQ)^Jw>`*d%n$+_jCox>!%ByXk3H!w()omPtyNZh3ki6a`Xw|${LQ(^#xbMAH%TW-ZFvFKnTMitdvYx6j?x-vx-vdwS+vq^lxQV z#o|KZe1#2sx~k}A;Z!LG;et{x4kVXCvhchWE?1Bmef%opUK-}7Q=K|EH0TKqG>zN4 zE^Kaq^$AZrTx=Jiha-GUm9zT}=qhV@Xl?f{%|L>zT(qCuOF#UbykKx0Xrcr*MX?&L0f~@OcgaOJEa; zdCVmz5u4A0Bwp1me1zLNqYxq1gLtZPJH$4xg~B1E{1(!ezXi&qYDjn(dq`f&b}s53MiI%@3u+ z%s?_XMGINTga2+}{^CscEpuyY%WuB-UcL8(z}$;S?eaYFVeo2u=NA@kk@)}Z4L{tl z|9emY;O{!VyQ6pC-|YL&ePjEY_WtPJrM-8yf3bbD{qeScYWt2o|GeiL_uSh0?X72a z|MBip%g0;Z)chUIZ;btHY^3RLo8H^>y2c-BylvM}p#w@{q|-fj1)s+xhpEfetX ztyKVzixV5zrO-xZj%DK6>{uG83My!WU=WjQ>+G*(ghe2j1zr*0ULjPQ8JgxpLBC#@ zxy%?ARg;GR__XQ29uhAEESEyR3VUP;LqeVhCnU5zj6mXJ$zI^B$-tuPWHro5AWoiz z0{l!Ka$b(Us)H=*#$|W(E0pHwIgfzbA^;&0i52Zxamx}h%~$5=NrCIJOTm%WJEk_7 z%-rx=8JXq6{ae{&^hK}aQ2_u~*Z7dTwZPmYlLb~Pv-BFko!q6`k{_SN;u{m5{aT|v z)yqfEx}7j7;q062#<%TvfF_XbVc^uSE9*Dlja4o{1wm-DOLZyPX5%ej2m@+CJlLQ( zqcyyVBTqk>H8*V7cGZ|26O|ccZc?dNMamdfnK)nkL0DA|Umkr*mnXSR)^q}joQPXY z!&jdcE9bdjbaolMBTAekGXT^OLx%-R&{brdC1LM@yyutm_wZEueK>!xQQ5G%oFQ&A zWZkkiQ<>(a+mHSX4wC)F2MNX6R*wRG!`94T1K^G)>4k#97pOqlsp232ey0aPb)_-1 zZyfufI66%e!HD8yU6`L;CqEpWc8nlm?A#`2y=Ytye+`AfO|Jy~?XLh%cd|eyn5rqM z;ml}GZ5ld|;IbN`xy(CZhr(u4N~EU_P3JRaSp$1NhbwQx z{iO3vm71V=Y~6Y)>!Poaalqk38JG5A1>`Y9O!nzg)dt(;t_SZ(z;@K2HEe1Ijy+QWKiUMO67V;pZzZjM0toY_x+H1ipbXPzDb8O=f z=B1E2^O(w-_GJJTpr}JZ^oJ9B^jz48AA|E~X4)ChHCxWNg5UVdT`umx&O^ z$OMPp+KLW3W!*akD;;Wr7;`4 zu)flaI!3uDfemyyiQ>uh5*1LfBzc>klSTr2NtYA#gE(;UGA2EDm<#0t3GMkpW47lJ z7s{X&&g+V_Vr2q@DUyYQrZ_#!j2zp*t(v4SkqsgaYzz@^K190p{Y3!R0~v+ng*K)sR#JgDpPR&A=AGtgYLd-Kr>Xje}0G(00M8O&v3Fq(ZF{J=5)zIU6A~Zs#zdZ6KbuaN0qxOo!*yF`IURbgSG zVovm=K);q_9(^)HlpRmLDveX~$d=%9#3jU2&%Z*%ni^}9-E*jMLE{!qS(Lx9UlxnL z+G|ghK38(%ZHH!aQZR^i|`o|i_9UfuA0*+Gr&NMn2-=RzZZCO!YnRKdt72OG&h_2Em@( z+>2Aq$kmU@sdjTX+cP3Y1yo+Ra<()Uhk8bwfu>uAAG*JIYnwpkB@1_J+!`V6r>dAfjdPS;)48rz+csb0@wc?=72c;OZJeuOGK})xMT|o+3OX*7WDw zbB{$5i;5We6H*pM?v z?cNv*z!|1a&f=_~-t|4q?(X`iv`18Mx^Dsq9A;W)MC!W#TTJ_-gHBv^jbdFbkD4|E8HsAsF3Jse8ybUqIvg-%T+6`yVj6(Iwz>PQf3irN*%DpJU zi6vQvBXB`3k+;4Hm|H^T{rxfosZBvQ?kn88b@IY{%el{Q?xI2Q22B0?q+bSDO?)5j zOs=&$Dn%yNbw&nYh8jc0A;YEz3Wo041WU|0X3=(iuUY2_*DTy_krfXKW=a@r;|{O|1?`$p)2N25K6CJ}#*;B0(2J~;k3N-(0FHEqXLTphUA z6hXT_r4d5DfjqUKbXvIb93DD-%<(@!o9h)?E8vEiBxh;YN2D*Sxb@o#?AF^3HxT}l zc_7K&xN(IL(c{qDRw)bvL)e|Up_Dju3+pvzF(C}c8Cp;QUtpT+t1y%gM-L@D1Pi4z ztyih0;ZbbSB)^1G25>&X2h;8P0v_lxo-;cBK4b=~7KIL4)qA;^F0f--4w{W>kM&oc zfmX$r^*bV(+8*57+KZrqNz}+F^KbR z(kyhWmo4=}YHf|u=3T6SBIbmcY#)?9?J~TA&#Z;auX3Qjbo1FDZs|Xai*IUw})Lf3KGXuPW7?HVY?Cc){kX)3zcO` zKgL|%FMYV9V4hMsH{8mG?I0uiO!H73OGmG40L^0_hR@wQo^Xr&-C z^fC2Nv=e}t>R1;vO_4?FsWv|R$101s(6oh>^~WLcbWrBebIfj4FPQZ$5PZQQ@>N6J zQGmE6{{KS5{vX``K*z6kys+<|_kDC<=iZ;%n?x4C$J^)HZ*Kefw$-*f_x$Xh`&z%y zT4=pv_wOJN;GUN6XvsGJ*XH*(=VE^zd#dTLo8}t-N8^jT{&m;4HoUN1AHc>p9MC&y3T`&@-whv{ouoqBM2UEFm-0_(bY0hnQbC)T1b%! zlhXK``tbKm3GaPKa>y%2btGipVZZSpEoxdk@?iPm$)1Hxb#XS@(ZC!Q(p~#DQPDB+ zAC8mAI#`s7@s#ky`Axt>pWv4Nfvk+R0nH^A<5hQGv{xVuWc$Nv29#0kIh+deCX3w~ zJ{#Wio2b`yMxxulAL<9?o&pwu_y7=#psSlFy;`L=msu1Sy4)SrKz$d+K7y6 zi=p0~FK1h7hR0CFPz{e8U6ltpv zTU^Oj1M~{JHc|2Flti+=AU#4+fcru%0gc1;ZlSu_LsYB$BjN*Zv>&8)A_(pzXAam$ zc@-WWU|Lma{XH3j?bkwQkg3L;2-P;ObH9R?2rr89x#jPXsE9Q?;41^7^|Uw`e%H=B zHxJ8+kfo3{ysYKn>0U7y$1f`MO(2kVxs(K3K; zGA<Bnt8jQl`OvF=dHy`!U>X#2Gpvj3Zxv>C2Xu5sihe!3a-?=O zu4!(rh<+iLVxOWz+lfEh@Nmy=0&Lk&)ZMRzhZ}D3`U9@&&pW$$D*z7+!~SY$q#}qW z29l}%0dTkvqBts77PL&WOOgp;V)nXcW~V|ID7X1~BwR6S^dBM`9!vGY{d>K3^(=&% zE$rL8g(nh8%U!<`(Xf)op(M}5o8_vxd@ar< zJyE|H(Ne-Fcz#>@_8K*ffjwbw2@Ni@2@)P@@)shSOw}~0kgvK;4sN~%O)~EK^ASz{ zzudiPU|h#_CfW@&_Jvw4$&xHk6bV2iFGW%mO;ME8Y&5|Z(P$725QHcS0s#<&h=s($ zMY1e6?D&+wwKsRCdt^&_L7+-ljObe#Ls!(cTQE^ z+ZWv=B+HCv_{SF6x9U{YsZ(eD&avdEIJtZ(&rhLgup~uPr10qKeTckLDE@MV;Uw9@ z>KcL6ii$(^uHI`-;+HB6r8mZ>%L=hd+m>7fqRpWZ5cP`{Mv^Py52SaYB1M;0?=dC! z_kOIxK*;?&ChEN22u(qm8b|Z)856U!quz-9L%;V1R_`|F{tMTc*I&bhinErn5+aWP zuF=Tj>oTZHqDqlRb15xV0WIiD6nT7R^=&4jPah0a19n6@@=jwm+)t zInhjpuv>B?QK+_G*~VR3z0I=wPgj_xoZa>N%8XZ)-SwmJ^#HpA!A8W~f4I)PT;26% zEn5rY{|`i#BAfQMe|vkp?IUe{t)FWhZ255W7n;APc~jGOHXUmG*2dO`Z*DkT|5;@G zf1++6_6xD`+Fz=julZ=rBhimV&qw|dpTChm?_M3IMF8hmXSXba+07Q}1Fpmr*pEj3 zv&kO1TWlt^^A8a=2$c^G7@0;NLiY10Sp;l%hiPCV>I;gXmX_Ggy(}+kc@>?o(lq`$ zyBq=is6Amip+CI@yWuFa0L+1b4a|bTbQ-KC@c{T4LE@ptPHU~9nDj%dNXJSdYqfK$ zn-u`9$$t3mt%-0lEg>irK1~5`hHLP{NgZ+1o(5>g$QU)hfo(HrJe!?c+_-4zH8?te zN}j<%RCIwMd^$pdCg2f5_(90G4lL-+yjDzn0A?Sms$@c0L@u^^oYUda=zP#khghpW zU7UJ13g71>IBF}o>HJy-Aw4tGGfcrSeR9&$y+brQcaHG*8=}%PNJwKVBMv#a0y2%k z?dA5Y4gl%k8e*88n;ji^mi;CB$TkeG;6UIEVbT)xe{*IC2icN9F&2bqN3i%VNOHMf zr}_fAz{uU={ZMvfDjY0y<`A2XI@wjEn(aouLuZGh8GZmjs~=TU%ct3ArAlO5_R=%C zXSJWG$xxy@A8_MZma;4shh_!9*`7YbTfq)RlgLEk)-XHVtITJ#lE@!bd4+=X?8+iG z488!QcOXX*9xdF(vRqg>f)$)E>imd6(L_}EL=4qDj zP!1p)yk)hI(wGc+e}x$w-fQxv@a4+tG0GOChIQWOs0km1=?TKszE$^fdi5DTeW;M_ zyw}Z3{7JjDrU1#Fz75Hl$H0^YZ0P2Bt0^QZUqcAJ^By;qU1AzFvWP*NX~Y3(?%V_{ zdR#b3Kx2lLy%ZEO2I|=B7>3ZZBnCtSe&TFg!ynpO*_Te{ul=k=$(NG*acULmdWTq+ z)p_?if-7)dQ0kKHEk0f4i!ri_%)Db1>vy@qeFhiw;~UIT<;Hn)t7vO>NOf2nB#8)en&6&;3_bI=5jRi|5C=aOH~s{y+jN`tg9_lOVNFk6RURdl) z0G6475B+<-F3vP?dN~w431}nrOx_nC-PlA!VM{#$vCV`3v&uxm%Z{xb?w4wW^<h-AFz75%TE?phH#8*v-~|M#||&gpg#8b)dSea zmqE&>%h$|ILR4rGEea*{NF3&IYX;yrqaWh>LA9U86s#$1;|aTk6Zh=f=fU9$D58Yi z(f=w_ltsNM0vvLeVP>!pcalI|&_aC-E|-TX<{%hK!KmS%H!Hd#LBoxtK}CHPV2D5~ltC9*Ay= zY@_v)Xo`>VRgV?P|b zz4l|ZFV_5B&G**4Gx{U={Qs0cxp%B0H|ZFYK{}sNX2XG&J?Ty^e9=#!CK7`?f)AY- zI8=$9v2Qh716)$OicF@b*u1GTq~1_Gl6)3eme4KhOA&O}D1++#%~W>ud<6+5zL z^&-3{NUHCI!(mAB$HPFoSh=us5H2I!0PpfD zGM5s}J?rdobn94dD4@#mMmf8i=sM~GAua%(M$k&f62uD{hN$OcWl)2>WYH>`T%|<^#KVofrckpS1|5+5 zY%AZt=u6<6oEzf1T>UEWKMskF@^m%g-a?|TQ1H#Ua}2s+~O*rLk9g6OtBh$P;Dr8VMDg*IbV;!aU2h zuL2`vzg(DuZaNfG5KQZ>HkCJY*vPs;|E_&3GgW9LZpW#C_bi)K2zDp(`D^844#B(9#fXrkk*XYkq~M&9|D zn1Sr?zsUW^qyrFX85vtIx`rTg5dzQ9tLWBagX4nG6U{pLv0dsYD{G9iRL zTAeVX+oVugax;m0+bYmTP785+s}pAfE;pC5=PhM>s#9iTGdGj6+gAZPG9r7nyE--%Dy7t=>e^uoZKkG3$Y05eI+ zuIzI2I~5`8%ygD4LCk-tLukiVpG9Pbc7!L?RM4nRpkgf5L%n(sCIus}M7Wv{E7pfr zM-iKjW3-)>Mmqwe6f~q@^I`fz*MGmb3NVsG%mwb;;Wj5I@}MYG(aP6J!1a1L0}d5* z@>f>@FA`@8MCW!lsRqiZml#&4GOcBdptBjrR>d-?LcuGmCuom61qvPxP~cjI@y$*t zB1V9htZm}Qo@qr&l=BVh(~SSWBl4q>P5aybV|!iOi)~%4lP$lF-hcms-hW$~eywRw z<2N;)YWP^g*7`rJ|6qMr-KXky#6Da5dhG)>AB+BCbSd(Ae0)>?^yY5^qoKN~^PJl- zhtI*D+zHgdiPH`qP?$-KLbBmCjZOMQTwv8(&fm)W$UxS#8%n$E@$_lv15-USlI$5= znV+ZIWLerxxHHx+qOOmgBB^T*GH0@;EzX8^H`IIf`}NZKThR36IA%R7vxe@SEAD_j z3Q&%r1)>%Lyau>SQ)pAY{^sOf&I67h``UJlI2BmO3B**#q(V|M8OpYXV5#C5GcGWf zfa_eT?ov5N0!$Oc@X&W2h_8y+OYf!lS7(-?ZY*?|js@Il;KK@RA0qvBB%mrPD65RZ zABp!9!(L^OJWP_hJ37S64v#n!IZ#4~OE85_b~`%IG8M38nPc9w`F2)NGrBkFR?oA8 zjd3K^3!&4~ue)yxx6ujHq=jH9#*Zmp4j!6pfL5gf8zy&u9-s*4MP^U9(bwrrL{Nq~ zgBD+MaqZJ_6NLD+j(jVa_%-GfoN)vWWFWdmS*Iz1_Dp}D_NUu$DubqquNO1H?hq!c z!g?*`5M59g4hkO-IM8iHq_Bn_^h!<>w+V-j zy7SF-vFRL>8D4NB*{<)*MIXrYgALHDtQSxj;5_R!p`Kpdq_-Eur7k%eAFB%Bgo*bI zNe{?^upYGP##djy31SlQjm|NjREgo@Za}Pw+pH%`PqE2PHt!izjsla4+icQ%ArG90 z1Y;YW&%5!&*nz=-&hxP9h*-^q`lStuJbQgE^2KpF4?u`s9@A+zLm<9Kx4QT?IfuEp zl!~I0u&`UDtPA;hy?FveAY-}nIXB)$T6?>J&Yqo_U|(i<#PR@#Py^+Z8*7~uAWRpW zW%Q2SL%crc|Hsudb!*4 zz=%*Q;-nj4-L50&>*gAScjlvZzelQ*Wg2YWL`E3SN03fS;dH{0mF-EVpva_=yOGEY zz;q7ivUB4AiKb>@U<;9+1N1gRA>sxEOq%CbU!`}e2?OIg8h5Y^4DTHq6657}**T$) z1My~?KFNnapvrnLtpY$IC637ML-bXR)-bo7=_#kl;To8K}ncBNi!L^D?WUqid-f=*X+Uf>4+Apc@5#@&vX9 zQt?FQ*iEwNa<{JnB0_J>aYu=L>NJX_;S!eL5i|Ox7@E1KR{bvx`!Cfe;Tb0F?<17v`91nq8m!h zftdmZT*On$zXfo`B0zo@O>E>6tW(j79dogc`!WJA-czf{H!k< z(DFcdHHzxvu$J+(Y0j%;q2=ycy}~Dy7qs7v!L;MC;ep;kwBsF1XR~o>xd7glOKD!_ ztR@h}r3`ss9OY?FLqH&(U_-Po90(0FH<*f{py9L_md_FYJoph*8}|*6K2|TogDMA< zcBGjDqHY^Jotd*t<1^q0L{?kE07E7(tQnn zC&g1(A*oe|NA1Jj%*rg|EczS+Ll^B*?J6^|LNwR zY2MlNHBH@(A8+h!`0a+v4foft);HF@9Q#~sqV^|h-(K_n=wC(OgAc##|K#4DNAd5J zm~iiNN3~9kps)ryF)X;`%~X=k=65oVekb_oD;#mzq2a@QslzVC%M>Bt+Re_KS!6v! zND@};-d-jn$Xa(Cw+W;QH?FxMPG{)UO{7iC`vtp1Yn z8BpiZhDnzPqq>ntOB7|%S?1Vv<|@$Emw`>@>rmHu=F!%0aRzBn;@r9(eRF`fBTO^u zLXhjnGT|zj8Wg|Q?l1B-7k_y|)N{2SVq;qj3 zjr}vIb8-+S0cd;~UMS)~h8?RGDMUW>PUas()+Ea5J71EKtzB%aMhn@5Wp0}15b zcpfF@nO88wB{zd{vr2{!BL>Fbir@o|$a?>c#R5M$);@>62GTLbI6PsMKp!;zP`=Uk z)7#A8#)_N87n97LFu90GYd{^wk--eJ69)kRSp7n%Tg6Iv(QPR>c!Hubs+Vpf_aWDk zzmL2{t#`QseN1@@(pQ}(TYc;E6#CKyN!t)PZTWji4nvqr703y1S9NmAw@8`%%@EX* ze>+tMnu&{52(tGN>gF4!XM#D`^7Il@7D9mz@9G-NZ2q2DY#OQAofjQ3xD>44IhlYk zATTHY^YHLsza&x)rqEbbg}Lv3nql|w{)ZIBpjDM9(vWvUAH&fGn zF#k5Tgk&DhY<1EMqYNf{v0ait-+xo}@%!?C2T*(Ae03__c?uKV%w4=Ie}_Hb7dJrP z%_OZW4;+H*H3my&9BFhbnhTbd*z#Z!|D8Ocv1)75!?`Glz8Xd5twWFtnYlA`RvDNz zIwBWmB-$@MSHSo7bNt_x`IRMcV!12`xPF44$oPnwK<}Rv{J*zHvXM>4+rO*r@7oTw zexT(qS|ZIKZ2G~b{f)ohc(vhk4d2t{{W8=8EX{smjrdnlbAc!~szcP%XPyPR|EvcYPxS_L2ru`1 zz85O~YbcxQ`~yda)wG~T;;BM(KS)ZsL&Z_xx(Cc6JUL5M!Fh;WA74rys1f%3{GJi+ zB-M+g{|WrXnX^zksMVP-;SD0j*6ac@Z6whI&Rw2CA~NgHSowc;1%2_WajIOCKC7DM8o&XmSB>TLIe7is#0x( zFu>BF?YN|%QOZK1YT4f#&Ky0SN3Cj_)@|O=ly)RQ&|Cce;H@^Y-Q`2rnlBc>&dkGN zN3rUhIG$H43~JpieaYT=PvD;m|bSOX0*P{ zqx3X+Z3Xjwom-f7^r9iy7jeC8sFRPQ5A|)jUiwr|;*Q5fs(_z?ZhT`KIX98t z2Q%l|6lVRJ3bUeTAKeHB)?};?y=%vYj>h}P`i}N#6i#Eu$|`#K&7mS~Q(fkZCVTYc z0FPFbJkcXFS*V0`6$RdNu!7*{LRgsOUW^8Jv)$$s#MR+2hyuc&yV$`&Hn7YG@&I~1 zodXOzEtRQnLH>$u75(OTqcacW>a-C3RgP#YbAuZW8S$^YzuWTwydD-( zztWNFlW6vr9HD8s|GMNd{(ny-6WLVSw5k1M+tt>OwBFxxfAjrK7aKp&@BtC(k zTK8jhJ+V*4o~Zra+WTtW8+~uIHu7+;Lz?PKnud}@i5mCB+0 z%km7ed~DzMGC;B$%eMph7tnI87t^kb zRJLJ&-Si)`Q3DPU3J?UWL95u=WN6-Gbi$>9KLG*0f`;Jp=bi52>`i&6yxhC;DCA1M z1}wX-UdJ+M(#l+7qF_S(5!2c}0{YetsK>#Wq;v_0B4%Qgm{p_5C*bHg%YTA7Z>(xX zqk|7uGNT~A2?<~nGlp1FXX${!-;RzSJfaPAb=f5ffdrr|NX!Ab@w;kMoK_4c7smLBmhCZusa zXEj;LSRS=)qWiU#JK_OtvsUV@5YKt#P!RHkQ|QxFrof%bvM$YpJfAS z_&K|LOamoJk|%GlBb5mdod+y4FdXvCGFxI6Ryk<@)JHT3R_{3MzP~G*XNeF$BlcAkxeN#)VQ>ZUu-FW*u8D zihmqV zJ(Fe{AYNp!CM{EDpO4Z$A{FONZ$a_}T zs_67Ba|~4SE(@#>9fiAxlTgCIA&7VDKXtHF7bURR4_h-U=7+K&wf(l)Iab_c7l-Z8IUuHi0Tvwg|y4T>e?`o~E%#oh-23BWZz#d6o z?no~H`KhA|-*y}5XOq|L8(wn4z`heFHkwnRrf}sf4hhbEZL?SbyA_HFKz0wXK~q;t z1zNKwq~NDAn*~ndtZgu8+O+W9_1O=$V+Ho3jceW>I!~@b0?&CjnL7?twClR{Z~hpl@vDn+7w>!GQCm4L^ZU5DZ{8He`ZFd z8>O*xy9kXCc?{SO@Sm((o>azE zh!?6d3d1Cj=>lh-gbcloGz*rN7>!h6CNjZfGU3QVMoi*OJwmZOaFmY;BEWxHM>b-{ zd}K{gI63P^qK_H?;sKLTjKa^R|6HyQ2771oz*yF_@IP{7m=L-nV3cLk*2(B>%DE|{ zxEKMf!Aq(D46oZXFhjV+|2HF;zv&x+0Pt(=qwS4t--n0kgRNUyey%0k{1?sN(fmZy zuQn|=bpZ$9k%oUjCxEBx|Fr&8-LKU>9s6i(TkT6Vzgn|D`aulw<@P7Hqfk>H%hj<} zPj{2-qPBa7Wtl}-n3YF3OKBFKVRh*c0B?}~1SjtaKvxDzPwi`4W_P;{Hv&SHMVlaC ztZ=H;PPgM3l=Y3DG+6io^XcWf3Q^D-W#UA4qtMHe;(twQX`#WOX5Zuxt(yvHZ9T(; z&+Y~xmHnMFz1lzSW^E?hL@!Khw<0gMBmb&9?)vJ-t;oLrn#WBwcmcm?R+=kZn{3{F}KoRVY38^UAWB>5CcpFWEQ>Dve!cFEW_mE_SqD$#R(e;x;5q&d* zsS{%0XOaBT_eDEa{TIG^jwLccP;&Vclli)S!qEX*GzxfAt3O-wD6>qnS66vJGnZHUG zOcL~bBtVb$wKnS7;l9k_;6r+5cHxY~mLYO5s%T88!JHbm)CN7bP6MlcKBx2O)17=3 zB>b2o!6+Wqv-_qu0Xkc*xfXB@8GX=Cu%qIrY?M!YrDE&b)5a*n5^REn zHO`RzHkn^wHXvQB-xr<{YVsJFft+s!u@K)7HuEwKHX96&$O8@p@osoK#eJwu;jA_< zo(I6~Atd>CeXpCvUV|)DIg_#O@4M{^>t6tGCJ#v4Y_0)=e9yW;u-_+BY4QI0Ak;Dj_T6r-G@Mr$USywTP_5mv+k#p# z#J{vE-N1EET|wcu;B`|DvhndeEeR*By)$`0(C(Kr|E}_>V5$seP6TVj>^$%>!xQHp zzzrvv$_sMrJy_3omQP~YiQ8qWzw9hNo8V~Wpl>)2!U;f&&9dOK>%(p$U$)>jq>hYI z<S@>Fqt@C=Yc3CFO5_^K?pIg!aP0(#K?O! z4@B8s;J3dL% zeG_K%@fGY2^#Bx3jJvX^v*6|PB9}M7vaW;bYQ@R?1e(iU#8hdwxU%Ps%iGE3yZYSNQo>fIPJ}|rP%Fl(#iwVM z5lJ{p5xeduV*fuBc|Njfw*6D>v+Xn<#{M$)&9N=De^>kOYLhj;QIm~+J~|QkV+>UG=am8~Tn|wL z^!{1aV!~7LL;`}lC)sbH4a*H|KO~7-tf6MU`_rk)zdJAjEhjt&h; z64&5Rc7P89Hi{Nry{sr@mTP-wZ7e-{rAHs`Ureb3U{ACm9X3cnr#bbjYoVtv6 z%Nr`7y!9Z$dfxvOvH;=*OqgTHt3ukt2-sJi5Bu2?GZ++Gm@B^w=9RJlbjZ*L(u&F} z1!<6s2$}c)%D9x+qhlt;EPV8o;8z2ZnvWCgV^fnbzJm3m-dwBAnLjJ#=i{@IVZgo7 zNSd;Yw_HH&>p?a~@&2E{)RpIa>)7l>0lksg!`k~Noz)h(LH`*XMIk;CsgN_+%QPz3 z*a*EKSDv9>MNb?D^O-_%It8V+4U0zLHB&%YYcHg-_m48L>G^}?QoJ@O3hy1$ERh6^ zFnXVjtBI$reO|~3x` zYB$+RHx#X-%u^ie!A0|PKO5M)SU`#AKDl83EwGKG#`Q`HeICFP)Qv?f-bmDq&6#T` zpp>(hWxn3u$fW7)VMe>fv_|TExh%)Og@k!1k^|+$65vGo21WU70hODH-2I^BuZ0o_ zaq)o>u>mQ|inl3m3ieH|q_3#xjSO%qlcTU%V#YD8M`;Bq4xkMv6f&Laa+-w(zZH7GPQ8ml4Z?`6imlbD@CJ$%DC_82GPr zLx=kaUJ4WC4K9ImrP-`(VjLa^yO=<>xLwML!tF5Pu42Z&G)tjx8;O8y1gh6%2xIv& znevCsJ9hyzYYQj7roKQkmvXdl8!vVgBmaer43KFQTlI_`#*-tJ@#W(pD^E-Cur~n5 zfbh`{F24EbZn&4bwE%?RgSiC^{^v5dx!C3Uc7SR>xo5>?Q=NmjN0%>dm6-&&uwqu? z>6~J51QC5;k}b0Kj|+rWGY6j<_=n)d)@5WCyj-{ijc;j*cz-4|sU$N}jEmI^XjNKk zPGd3%ETkR5p|6Im;uXUa1tQeS6op1oH%M)nczUq_km3Er2k|~D(<=C_c*^p*E#Wu7aNyEU;eueios4-_jt+<16#so}?v zH_Y%9kC8MOQoU56)x2dIv9?#(32#nsY-nhp!Rw4WY>w0{C|NLgww?x#hx?E9XGZ#+ zAd;1UU@?pQOSw+5eWd_6+uc--w?_6gKv%vY~c0f)^Ow!9`3r%&g%h&e5-uCdn1PGuf-%pr6 z0_1pH=Xih57+`fXgK{w45rvofd=v8MP!w%sZLsv%U*6$@9TAorEdK|NzA&xFTa zLR(3$#wjdZG*-x(P+z(`s1k3q&7z%3sBd|+-LRIiL8P~#lu~0|lp%VkBH8_|&oRKUNjY-_- zdqRxk0zy=+Oa*{NnejUghjJN1dbv%77-cuK@`u&*bF<;)Nke-KvG{s|arY;c1w=)i zfEhT?hFQ8Wasf+k6^i-{)0;sF-a>$rS0U+^LM# z1NyML>lO??FF~JDIOmPW(U|}LP~`g=|9@xuSG8|%`^~oJTW4E7*76N4spi$DqfL#C zpKAQ(#upklH+;6?yBj7N-ckRb>c67?aNS?lE!W*2`$%jmR$KdZwGY+&aP(iISq${0 z`;&X9fZU9^+{EkKZfVfh$M&zXiV+_EL4e{QalWSyMar4}o@_$p*?^jr$a`Brr2%g9 z-p9Uy*D)R-3qr4C0jw6zcq)6>Q`@2D&KK%^>ht(HpVzEML1xJgxLgFpiJp zjX7}Mwp;2e(+M(Dcz)2H`!EQ;8Fa#Dt=@gmi#iLFUG3#|7J$`oK6e?k)|Jyb0_0%U zMapvk?`8moL`AY=OoZX5MWjP`LdjjBbk}F23xjkkn7VFqrFa8lF7jY#A!$0B)+0*H z0{Wr@BS40nnc#n*%>7~km<|(g#lL$9bRpJXSM0@87M^LKzGN!DpJY`QZn;1-?fgiD^fFPG0PD^3L(#o8D{uE&d zELDO3zIuiq)lcFPuG#GL*o-Oc1Kf8!PkxIRHBD9?f`ibEe>+BPJ$Tlm?zFzo35MM&~xt z^d>AcQfUm<~x7qH*sXqj8|Lc7`?V)^y6_~NUoc1Z{C-82B`BD#!Eh+^^e9Aq;(7{)Kpcnoz49SoLw1G!65XlkQY-_wm3oH@2cgR0 zz25V?GNQcBaX8%opUqg5RYUpk!dRt@(rCP#1_Ulb6<)l6O7{c@`E3~l){^uwSWgcO zH&{*zbgjD61%VKl^d2vuo;`sAu|2;jV_0FQE&c3>sd+W@3GO3(T4XeQ{7&=nf3EN` ziHSpWm4B>8@WP_^L}5P+cX;sk{JMNBy_N+7gbd@HKH5#@{FL8jR-K0j3Xj3Z9LMMX zseJL`Jwyeh6v+e^F786sK!fgm_%?xWf3^JEvYFktR)N!rcN88)mIGWIdwxYehH5az zq737Q9)>etv^s4E?;R@a#m_0CJ|RDc1~Ha7;@q1Qc~1XltP51)&}sIuN64git+#+u z;NJIQgk7yNg6hS_!!bbQ5#Jq=6$hu7o5+sFZ9r|FbNiF0CC+eR1r9uG>sp~2bcvYI zKi?Sl7>fgy<740@lmw)+-3%PybG5@YZZHEg)^~CS=ix3oQjm0&N@a23k$sQSA z)qViLdT8IoP>QwBk0cYub3Z(PejZ+F#I6_sLRb@_6?G4KUSSs)k!#l!Q0t&KH-5c) zKDVs^eCzl%_~&l(uYH)#V+*3@k?|euIVIarf`B8Bd zHsCzY%@+W6z3;VMpi~ny-wGOoUaE>T^6r-X$c4@r8IVUa;B6DEbU1U|kNjFWY!@BI z<=z->qJ!TCV+3dN77D=JPSIbyOEWyB`fxaLRF#wfd?$%iW|b=iks=->mLxKOM@3HK zf4EJIIP!sUF?Tp%47{&*vH%qA-Ar`ZRU=}^)jJ-|3`m8j6)3**Ok|nbH6lF>9bK*< z^4!7&^tpJp@Gu@jxNvu=w+QYR;(gLtW3h?x*SBpk1|I-n z29Bl@S+Ip#4>m^{{K)28vRPT@|C9`7$ZK#Pwo0FS-Z5)U94VX!TOY^x#=5IC{y@J! z;E9>Zfqq;*@#+T#$|Va(l)8NFUJO;EhN2q^Bo6e$*9*kpOz-GeVt8;6w8BSWv~JZ& z!*eVz048{0THyXwvm-p8oMa$D!6NY>Y(y0W?#ppFFHlTOH5)&s+kb}*IoMh%R#}^% zI$m{ZG1wr~lR#$ah&6$9fj$-*eK#Y+a3(h);lmP@VNsD@YiqZ$a@#Z zFCZcyiUIwdyqqiWG<9_0gKmM&)w~}p)Ilhj`#OylG>H01My3jR{r~o)1RVH=LyMAbt z49g+qP{yX9vcqa7njs1HnXe`!3eN%kK92c}N88O8;AV5|p;N}~aB}tD0x(RHInr&s z&2AhfO2vBt)Q=}|Bu@KE`d^o6aZ3xcOk6h6a|zD*#5(;7Voc+ADogE1OXox(gb-!N z6P)Taz4S{0`N>yfLPhKIjn2=9bRgORYbKJSI%bp)28>Ysrwaj6IT|O zq1<}Cg_B5x&48@1$`fD=i-i(ka&U!zbZ1tUuENU>Sd(M$if-E+RyyPYQ-qCabE1S( z?RmI(dO#(`nP|VF>d#8r=-d=o9jO(_jm6z@8jm+oIKgwKa1KB3(BoB|)S3Db!JL|3 zSeZVjRfaI{WJq^2_>|d5piJ*eq-`VgHWQd$%bg@6MdP}YwT!%zoH7y3i!2;JK%iZn>UwS)injlvuMRLGs>gSLl zsf8lYdA0C?!Pj|A3C=UPlB&K7{Jkj>I>Ofx@tOew!j2&8Q%q!E6AdY~!na^co&?`L z(15f<_u7lS468c>J&$J+zF=-esVuWF$IQglr}Nb!Cy;L~0N`O1DInWA!j}%p&+rj6 zL=zOUo^*Und*@QRo2{6inwq5Aj@Lw!&)n^hkbg%PzUl^|IQ0d4iA< z@6AgEpgWvG<-oR%^|y0~$~Oxd5d#yhLE;O9-W6dsB+&7A6odf=vc~E`CC2B>kbBtR zm3inf2yC#a%*-5fuL7dsVgaZO8ecSOL^#IWgOHqLq`ZmvqKm?o#TTy@0F^L;jQ?%7 z7)fF0gfwF7R$OTpU}Q89XMjD22!%yoA)Y8vKe7H`FgR7I3*kRFV35=T*F!fX{xp0@ zlK=l;fzP0^x?H_7C(Dv!J*V?wV{!Hs&%O_e!nm^xMYTncI(WWOGKixRm@ZTD~ zs-eFA<@)>TK3ex|>>FbD)xJ>k(V7#{KZrgb`8)>sQv5ktL@LMv5zxaUwWTvOHBvs0iqiv%o^^-#J8It&t61mB67#BqV9Uz zmTjRq%KbsQli2`tukjG|ugsl+V1n?iw0{t61gn8|F)d<)1xU~$@EEgl6gi`&=%LCW z&X@AeVk4^jo2XQ7*%~4gIAJI{bexdsPcel+#F|O}fsYGs3F=&F&Sw?y#IM1iBY~b@ z`lLnhNgxUQ=OUQ&4V}STEl*jc=Z8<6bS)1@p8#xJpq}!G3%DltPqFnV{Njx z#*P5agZqL^8u72C0U|1;#qJq5<-W{$rTGdiLIdRxe#r8m=|f_z{f8rkK1pW4e%iK? zIBI1*_0sV7)@BRuC-yIpDu1e22T#KomhoU{86m-CD`U8){#CGtVjPxs8|}+IUW~@B=p00_x2Rn;wb zhXyw|&$jYD%rlfSzU^cXM+0KgFi*vwkz+3x06U^H-xZqKM2j{yv$_5^n%Vq}GoLBE z1j#dlC5Ii)f&D~hbhSp!>l>B^M%W_VPGF_3HzBv0}712UJEMUAgc?71ltLTLizeoec@7F zY+9~c*x_uPp0X%|Ly)GUO?h%aot#3ts60r|7tfe`lZpN;)3HK(A@DHb8$cEyUkQlN za~39ex&U~QIV8Vs2|J|AjtaH*sMYhd$@1D>g;jUu^qdZKqp*r#02`qb(0Lf3*3jrr&Bh z-T1eSU*EX5;cpwhwIN&oclFomZ>yWAi^M)y`@d?B)%;6MuBIXSebKJS>ydQiLh%t+ z3L`mtOQs61B{Bn}$WO9Rd(8LsiB+bs#ERgXShygWjBGl?d$WA?f~a|x{;49;rA{M# zeGA+`gRq`lK*8>h$Xgo--N1aB&K#cS)uIP8t~LkP;+AxknGD0*AipzJG!~15$87NS znj2ul&mlDjHs?~gn0U6h6A5M%6VHU^C-YmIdfi2^LbHlSstUVzxrjuiaWVB$;n7(e znvJK~4WYOEE=c9)5*eJP)Vd46;}Y{~2?9~1)A|GUUM?bG=@gw`TaJci?v1D6b{xdi z<fQxUe^wLH;!YUg+!EpVjPShU=?jQ^2m26#MBZl#DS?QgXgEXW6_Z<&tMZOV70x zyM(3h2f4`*xpws%A=}@V^~cM|#f@mU`?pv`;?oQxsap`TF5A5_a=D-WS_Y5>Jx((c+XqoFG!W?9CM)ip3V_yNid2h1rJkaEUdD$Uz$g1ofqE!?>%C zXpIpZDc0(*K%m6*S>3z{{P8L8d~plCOnfw+4ozrOLt}HVSCswdjQoFrMSwT5245&X zi1(Cs_EVwB9FL_=Ci{?BHVix`qSS~)bsF7;nJYkAM=};FxJ}xpm9UnNpDAvJOhHI= z%ac{609Zg~@Nhhf{tRwl4fLHEUm|n*A@jZ>phb=|JMB=F!3IdL$`F4vCDSi!u(ZXC z1QbbPxF@O%$0o%=KNQlE=@1K$^lT9jB4c!H9jr3OiBy(#{i?45PUhJFQ(v0V++(At zG8hpY{JG-&Q2S_;Jziz-fkAYF8yw9J4<3m_1eA|%BRa@WCv!=xBRKr|A{y8$vmFSH zZ!Td~X7lgihMDbR5uhW(@~XZwG@Bpcak;ZncC#+7<2z-IR9|u|bE$$40oMswB-vaG zc5r`aPW9TAYbidSl0mzhxGyz}5{z_l#l zoxe>}$hPbXk!D{)BPp~4W_I{6)BVd0sPZi`N5O7KO!N;~YT#RdsaynP__i%xXvTFR z+_4Suij9#3YPqk&DZyU_&L~m@p2~UDXl&cE^M+&v{C3z4|5gRZ_Ib5x1R(Hpx>Tr7w8)LU2g&Z%kt-yeAy|(RKTdehB%ip%VzvZ6h zZ)v`_>3xlV--8v-PVEXs2x@Tbh!h)@ zs{^A6N`MBwGzZ5UEgpl82xES0*ypE{Bk0SprtBh;`Q-l6a?u(-Q?nx3{Vs2Yo50Yp zcdfAqoP^`A^FC1?CcJnnEZT+lm})4{0c-JP&CSa&~YBPkI=nE-FCl$w8YOa37LLEdrR|; zodr@TZLd3vz+$+Vi(@asenj$QIz>a1jt%9#3gD3VnXii&_X4WJ&}2?=7R~dlIqYSf z2Cw2fp-UK2Wu+o>pvGc*5x@(t=AcGzU6;rQ!mOcXAZB^#0V^&DvvOmS*<-MWq^|RN zj44;8jKcCOV@m>o%cS+JI0{}dTS5du#RNewmninu#a_8~E65FdOU>O5QOwSu9|UWkB{1C{C1H5R7MwfP**>xA@j@W@AuzAkBDi6nTz7fV6aK|4FB=7_3`J z2PZNhh^bdXO{wtbmP1m4 zz)F6amL3I{Ze!SH^>f9?xp+kI9|{|h$kOZ)7UnJU=j|g8SY{^Q+8qc@C}}P0=9?%2 z;Uf!a_)yqVl(!$vO8TXOOS8*|csI)(1NI7=ZN~jdJ_6dV|S7HtIy9GY+fkd92iC)C7x6=`vbxp-1u#3X$Kwgp_a;(nrI;R${yEFJ;s zn;_m$4{8BOjJ38PK?rnjFM>@ z>5!2X;|}8P9vDQHqf|c{YMn8fjuhkY1rv;e-T(Fb8_sc04&>EfXD(xsF(GKCTi;#UewO4 zE!C3~WS%!LWl>p7!^UM%Qs2XS$9_Ku=kUgxJXI8Z8(abX3t6)*f9G>9emt@N-xfI= z+4Ow-C)#AHU&0 z&lgd3n?aO*>sN&~A)Sb8j&ntGH*LWB5@jMgK9DkoFp7-G)Ufk`J7ty%)yM%pl2$SnZ63NX{^}+BzGg_zS2< zXyqV$twAG?I_O^SksWrN-QI3`_R@(&wqp;nVi^X3=CIq|1B1+b?djq;oG5LtUByD) z7g`8NN~Ek01=&ETCnfV(ZZ-8N)T@TGfIl8e#(hPf9*VFpg-PS;6!O>Y`z?kP0xyfA zB&_AkRmc{n%NVBv_QJFZmz&LN-DBQ}9srhfByb~XvL{UGaLNY#5Tcar?e6G>r_jta zC=UjBc+&n&8g2k0kTG|ge+_ZXuH1q`!-LQ#MsauDV!V;!3t%=RC~p0ViW_M6%T&@R zJfVX;^1(#R-uMm-_>53vJPHitZCl@4ap)6?3O0q^La__o zn#}_V#w2YR71diy-b=;Pe7b;ZvGrQji6xZ*O_T%yg42qr%uCr)kwAUdwD~=_lb>*9G{7Bea6eg$n1a5s#g=sjn17sZnt@cdI zREhGTgVw&U9U0%G+uLhfi>Nui_!=UfTf=G6v=%M=6aDVy^<&;9QmA_2UP14xfixuh z)Pfp|NYI3D?%V==B7SH`oRgD!dD&Y5PY4beY%LEaPl3gUbk|G4G%OQZ>3((Y^0~z+ zSS$E<>D*ujSbCfRAXH=%TV!U*-w0k*q>#eR)6r%A*Lab{`6HI{sllFs)0BrPfOezG zlTAG+C16>Tp7FsrjT1$<|1^Abm839CH~5B?wJ>{et5=uGHB_(aBwcpFb(&B&H;Ee=gsN6e={zE(3ke;?U#ICj62Nylb0JPo~(;4 zUE7C~4QJ8wWTEGc9qoZ+JqlFUkvPgBtzDoAGwbg_!l(;VUEStB*y}K*sQetR>_9{2 z1ePp6Ifp8t%i^DFE_wLh0RI`s>V|XE)pU*Wh`qwus7%lYc z9ZmHfeG|(l7dVDbjfa(Y99QVvydnsdaj&?rc&w<1g?EC1#aY}ul?p`tI)_$DUT(OE zGWn5fr?7^%g@hv4AZL;VR(n4HY0-s){k6i<2+wR~*7#9ab zVW2x5xO~z%$6y!D1AZT#9fvWFOJ=;HP>VT+d0T>9>E(_ThapNtSqzsKaA5|O+dV3_ z7BA78&c-Q9f}@2vi?oCN#8K6Y^7Tb6Qc=&HWImZHzPR=-?&6?3Q6_!;V`Fs70#RGX zCoI=oYjKD&vkd1exdylog@Pcq=` z?IID~9p)4Vam1I^K)4E2NmW<7Fenbxg~meRftg7YtU}(bF&xl^RIcAX>#moT(q=H$ zrZEq44;BG%(0i>8s|r_FFbs3_NLDauC6(y<%0KsWz0`98&qfHezC$cszwT79$mnd~ zAZTx|$XE7TIu3!3aEi4kTf>zZ-20)UNq9I+p=+`q2;*#wReq@)!Uuf7TDOm6hJX+_ z%P6G97Qkz$UIoy^>_a6f{-Hi!#B1}qEtFyI6C z>l}0vvHv$mjz>0KX#WfVsduzqZdq%2d-H75w>SQB!}rt=)t#<;DE2q8pNUHA^-3Mn4<o-MW&L2_X*l7T zVdXths)Qw2!f=m0Dv6}5r%9rg zybdz8y|x%-uoS6_?#k7gGzt^NDaM)!3i4=h4m`O}} zrsglrKrPoiVbWvb`d+g5GEQXL6dc)w2*AIbh}lJGreZ;B%K>BJ1y?pyd^V*Y>|pDbRAMW0HW zcr#T`Byo>Qr)GCYL$?iFr|tmWHZM_J0eRylG(2F@92^dK`Av1VLTY)O=MTK+1BBdj`FI#l=|TR^r7#TUC{jY~!w#yKd0efWw zBf%CxVU3#c)`qiIAS^xkXFRq5pMcG3Fmlbmd)EevXbe90-h){7pM;i8e{TQ+4?BQV z_^}}%VK8_HfIMz&c4|3odVmoAY6$(ws7S*b01HCg87|j~E#iof#U5tnHyYK!!r-Ol z>MUG?HHod~*67h*M`Cbj2hrW}A|iPb?u))ePe<3#ks(;#c%)1TpEy747y-*l93y20 zKf)l|+S5{Czq&NDU=lV#mb!wyM|`(1{(p7H@I6J8D=tY=*B@8dQ_KD+tUKDTAhY5! zvR-0tt0luJ5F(uwSl0eqXkq_*Y))>pi1zLi*G9l_e^g;}f(*xPAA`MW+s3D>h8X0g zU0zr`4;fAGzS$xQeQ=hw!pLEAl)G_!W!kzrV%#x@{>`{c+&@=6d04Bn&}7jiZQIsA ztgyJ?f{@RK6rrKSQ69GpZOv+lN1GME@}HZSSQ?}0?BW|tR)d3&(!mEmD;t60vlWrJRW`0-LA7-{}qqykO;{Oiab14Dg7)VcXAMNelWm^?Xe;33D@C zBnIz?4X62GC9}NUMc_G)N5$y1~L4tzjr;NO`0>A^{Dy( zxL9w3o=}ow8Evw5@7e>!vs5vdNBY4KP0A*AC)3a|*yo3>qS&D-;GuTWp`b-+*nxV0 z2J7HTHQ_jRdth&?voljn05J{?Uu>8klDD)!BtS&%H|u$5-E%21DSEWId~L+0-9vFt z`Pb?fba5nx_!k%EcydOTi%Dpv26k#w5qQ=U;w1aPhPFse@at{Rx;>elnxDoSp*zBR z1_%uh7I(Gm;YIl4#$UD-%O zAyw@EJ&}(_Hhp5#`!`6V$1*Sz{UFVw72~7WvGIMw`jwJy_Zui*|1}c{oP^csZ8Z^XL&I`fwLfH_)-? zQSZspBeCeN(u>VvLx9e!Nb;QQ7VF zl|1-6E*pRV>79$bV-!n=HXEr;Qlx+>)eoe(X%15L!ni6T50-Y;MfYBNz!d!hY)qoZ zw4Dd~4L~+7v1zmdL4?Z$o5|&U(i>xpBP(W@ej{EQwp+lD{a~T{g`{l3BA3>Z%h)6P zt^z&BAQ1*8_0E)b)J6B@?l({ZS%kkB*Z0?LC@|JnXpuB4K&7z=?WrTnQl+O!^z?d4 z+u=NzN-8TmhX4&yo}%rRa5$C8T0;^kPjf~RPhFW1bXCy$u+VA>_uV+`Vy6R|@rEQQ_7oT?DN_RgX5F@`o#KM*qd(nNp!FdL~Bc-hvZpu`!BV!P#&$xbxWFI`~ zqv+zH7w+;n(v}cG!>tGN>fO*SokYDq61lzU(nCD9PE)83Z*6uUlR;nXfjE|B5qs&l z3OHOV4;vOCR@y3edR}P@uKFQU#4aQs2Y_RrU@!}5to%h$J;p(=;8{3tAH<1`m@;)9 z_FxjRV5Yxi9d*&&xjIvYZkdfGEu7z%@8A% zW*24SDdAkVqosFXX>%s!-(9stx@Y~B#g2&Sqc_iq2;^Y1k%%{1x*u{d*S237lXpVA zp|0S(8ZSf*fB=BD9#m;q?-d-2&zPA5Svjj9S=jFmJ@Kd{uRD}v) zMUy@>mT3)jUPmudlNM~S53)1?&5ph7G&u|Zq)Df8-cHVQKy@T7i+N0hX*L`1au-VX zfU90RWPFz7Xzq6(l9p`6m0=|3Ikg+bwR<$NXU-yf-g=gT|H`Xlgq3))FgcEB2_isa z(2hQHTe$ChC5(;6I)sjt-$@W3B4zM;mFqJAprwinAPUY zicI`?$JV`QN=v|d4JvKj?OiI}PJx}=taC|E1a+6dea!jnLvPN_gm$=k(We~$;|8%X z!2X<)fgKdEG&q)-w+}VXfHcTn&6aMfiyq8v?eUsH`#Ant;Vg?37hdI@L+h`y3Tn%M@qMVH5T5XV@cmpu@bml<>3mJrl>8+4fBPc z3OWq52}I2qgxHb66w~x+Z>%5b@*?urC^{+*w71j_(U>$yuSQ!RkQOm=gsQ}1DM;zz zDO_NK7EIrU8!=&^TZst`Er{a7g-w)A!dI5b1z=bA9N}$j#q^^l-H;>nWT3(rjtwlE zTx&*y0-?NwtC=pf)I~Sv8cZ5qHklMwFPojp9d-cuhMMO;L09^?h?_-rS}?X4FNQZ# zYUTynWRkxq{H+BZj7==92zS~ijjhnQyY|101unPD>TG*UO|j?$BX{Z1Ck7LemaI>G z*ThwzA5CCiCebnk_)v%e(@D|oJzZ+VIgh_hzalxt2Io1ON6$GQiQ6_kPZXN~F_2yj zvFP?gCcB7ROuo~QbKuov*H=_Sc~6zj&PwRT3t-Uwsv#I4~sI#qg(JalWsxGC*&s_oVdS5vlG z)1^~&HM?@#BgXGYsU(XrCa887a7UpwqCQ~ub{MU|Z6MW9!_NMqX;wT-uDvy4s(m;U z*Kos$_#-}el_t=&c$Z6~96KE`Wj+ugW)ZOKDy5~sZWXq)X&A<&Pn@T)1F3%Tv z55ZMkES;>Y*`7;8OkIu_6l9vdyk~%`tVs|-wKW$l4b|1e z!7iq9MYF%G+eXcbxGC+1{LwR$wV6a4{3V=!k_01KJY2$fD8va*aVr00l6+OA#ttK; zdi=5~{i$6UNY!kt=Fs^_PKA`#w(?G}?2|4aN~*29(S}b=QV#C#C~`Y!H^4sJy9W^t z2=>)fi=&h}O3@0M+C4yLA}kQ&t-V#G`d-r6Km0GE513MTfvzP9QrTFI`{! zu<6o8Rg||A?yyU0E1~3cY8JX|KPDe}mwsto@qNfh7tfM=Az{kSB3E3nKVfTt2-FQu zEPJO)Y5I9?f4O`B>r@m@PC@}B|CVaqgJ4s z7E9$sJN7d+p&Y0W=c3Amwm(tf~0 zJ+m+=n+IG3JpNSRpNU1|Ggowo1Pd(4j;QbL6F5)GY0PPjC||^1plJw+BANq!p+sW5 z6fBdAmvy|uP+v`#weUGOtvQ%IVTG}8pqwflt&1jd(MxvUG!~3_OX|qz7@BID3V^(TvbTdp`_@UYXa=G6Tlg zFH;tbICQy)#{MxciZwF9+FmJ+!4AzC8U{1RFx)_DKxFKN8Gwg7C#duk^m;(+6ZPXp#NUXnluBO_eB6Q!q^>DzMN3`JiRKq}C`h9ghSoGM{b2^-rwP;%=IAVjt1AqsF zC`u@fllAN&e8WbN&^_Fk;5woWVbu)pOM`OnaOog!$nj|%+ro1tnNmRo4F{~w9`P-N3jZMwhx!|nUqeyi>MZEdZ;+xmglCt7P; zexhZ$n_$c z#y%07i8a*zZ0$a{y=`fM^hB3=E>KPJ^8U0)r1jZr|E%bv3=$c13@D%!|;6p6eVA?f&rKK@sYDxSOKLLFJ-}CI0fM?vCl%g)>&jOIQQp3Ao$vnF@M5 zBq+fkLZNv?X0J-#6SWI*a^GkGrxJPx)^3GTn~3~pC7Yq?J;*qSqe-upWs+inOV~p` zgv$>rhaL+t>h-SO603=yiu{It%fP<`L~-4KXCN)V__hCBV6jtIP*Z0smr1X@9mm%; z#cKAw9Qkz}3HQMq0z2U%l5cq)6E9;#t7^ckTV_$S*n0qp4xY6)w$@%(a{$)suj!zu zPB;+{d0MS@=E{_uXD(R0uy8>P1+lp#lC9hCCD+otAQZuz|wp* z)IDM{eh@*h6B^kHn*j2?cda#6lgdVZMaKzzJa#gf?4juE#Vf(RyunCgYb|v(DR{3w zVTR&y;%nF7FP%BTIxP+*Ie+%P`4^)sYmf(K+ax~rXveX`-g9fsv6|jjBOliZ;;4fm zN&x5Jv6I@z9zA~}QpN38LErKYtu=uWvXTF2w^UU|4Bs;#mcR`*;Otr>5B-72FPi}} z1F968(y)qznY(NnmLM-5hP6OT;fle~qU9DQ*n57hAy#wj)yOaDJUydCm_bl$Fyj{` zT3C|n(HtJwDi~g3tsa*v8~MfZok+7$0+@?<=@l1aPLf1}wT`aUfy`{=V`da&7C}FT zVvjR>BL{||o?MIJXoe%dphM9-NS?F+M=*QME{+pbAE|_D=myT%i?7u})MO*C>j3;1 z2=GM1GLm-#>p8Sm1CgDK{CxSYa4eA+Op`KCu|Cx0opned!K?$~y+|WqJO7D)fXk-j)O#<=J3?CkioG8L8f2G26p;% z>7}}wBn09|%16NNO2Z3(RYo#TBB4flr^0lflJF;=>w@7WLNRGKLSzzk;D zL&u2gZ>_#=PZqudyxU0a#_L0?f`f8Ol(vZ8JOO8lHgWKFmoCR@HfJK=rxVy54`P{xmtr-$jz_**zmZ5b^9++c!-~-W0V-=?8IrV26TdKb0v6*66u9ZghxJ=z zxud3d5HAQ6IixrD*c3h@my9bG3hXUcM{JY<-A`Co%V51^+svvV*BEfJt|R{jN%#o^*uu)EN{hIAqmgg*KLo}){9XM+ z*^Hox!OzFQ*Wxsi0tnE`Fj$a#o+(|F4fqy+1Z)5zjDSs#_wN!`SWS4g~fM_9=7v zz&+)bml>_MG>>zbj(oF@X3k+SdBmo9!e2LYVTMRCR;#1>wm5ZGoZP~mqR8Q3=CHrL zk#EwGoGm$&I9$cd(!KGnmS*YoPDTEWektz9G8MecvAFm!gle~|r zdYiOIBLPsMX(y6UY!PFpAb~}Wjdlr_`D_62pb0c)(&Jy-5bea>T z7wc-CLdb0`wEFb$NqUM=`BXlLP2ZooGBttt=Rt8biZS3szA~Uae_B8_De7d|QJ~4f?Kv1nlA?`T zvD?dx4>cm0qhbR)oIzZB$x}kn<&jjchf(C|Py+}@ML~y|!KO47fgI@N?k-K&)$G4k z7b%!!nqZUZs!=6Y!B7hAGe3CbqD)*XY8l|9MBFJHh*iH0NFWm#SD*+z=cn;Ug!BF^ zF5me`UMZvG8MA^n6z}$Rbh#;bGDUf0qO!#Qy~wr5rmx-9*ZxS`@3y_z*3$aX*2&i9 zmgj&1IMTeM>7ScE-n7=#*K~j5pEnj8pJ}|i;nNM@)o`KV!TMi7M}V%nU#)nZc4Gqu9*v7=a6pGaFhZ~xkpkgBQZSm3+t(cz&U z_{8|((z%u8N%+64sp)@ta_tZn@k;dhz?c0Q`dZ-N7)%~Uh6G-0qC(*tsvpba=Mj5# zxoTDgU7R|@>CpDIg3+9T1Bi)7 z8B}&dJ{p||Orgr$#QFJ!%d=CHsv+|*6pN6H(`brO%MPyXhr!hw-Jvs>k$Eua@Y!$D z=FO;9b;TM?!u{E`$M|G)Mz`zd192Eg@XfLPXoeN^4C891!5~z`0flo&quw2PJvgHg z=I@pNt(}B4+kKhz4zKNl)^a-fu+HOj4T7&{hpbzTzCVNXU~5QdCYV?q26+^+d^*~p zgK&}Js1F3DO^3dYIXuxF|fW-W;KPOa^&t2vl!h?=}Uv>O#Z4qysEP(VI1fEUm_ z{JLLjP>8Ed^fU`1yyOk6?SaO*6n&eLXb&8fntt@kzhvu2FrHLiUaJNt)^)RD16y@qZ6}STXtRE0O0CGuT%Uk+*; zC2b-8z4Tf)#QMd^7j&!ux2?CX*6+XXp|Gs>=vvqRPu{zL$$6f4-MjD3=(IZ2O&r^? z9j}u(mSXF*6~$H*Sy4u_tJPS0(jF|!jG%zAi(M1)rjc3@ zlf80TAHr7qR^H7>`#OHT(6y|=3hV*@!WB95)T}XI(o!zcm3NhrJ(Z4M^X~|kYYUX} z1tfpr6z*PmCywI2j$bWwg1oPI4v%81d>Ao5HJ8@!S$PnS&vJLi=lsJI_@O9qmhr>~ zUBk^=rYxhP{?|3~(%W4_S9@tsFNr~@qeZ4qGJ|+1=1tLxeakB?Sc6$~R~bTjWiQmW z4I`6@k(}oSdK#Rd1-!6Vz7EQ71HM-iEta&Vfmg!UP_bAA=^q`8z** zjsHD+ZT>pZ>99iAXU;B&eXgZk;2e{mp)tl_1QiZ&lO>j>mOze}suakL^wi2bv?}F} zUkrlR(N#KvT-7c!=20M&9 zKlPFpIRIxwDDIUl*xm833JYKjgESkzCZ1aUTWpSzI)-7U;LNmV-4z%D$l+`0g_XCL zl9}rrKkuyzd5$Tw!@b698K(wTzroRTcoe+e$tbgzRT|7D<7m0+)G}_b1plb2!jti) z-N)I150jo=xd)GGw&Uk++mlzFf4wd^BB}+uuI=T!SMDw+CtiE8<7e~M2SMFbCf_Q~ zzX6|x=)^_mzPa1d@yE0amXKLmw@AS7pO#|9ds97Eno;;qryNyMT@RK zE3rUu4}_R=f6Xq-71C5Wn>{ao;K`od``@?s?Che2P+ulEwfo8U`@aig(1pRS7L})v z$z{CBaGe(B&o5eO*sDut!C~kqJ+g8a_V!@M&-ls=;ZzBfmpP}<3vU$!B>M_J7HWEK zPBwSX0Cm#_jT)EEue?o1a9_t~y@|}6^f*IqP)^^#M3_Cd*PfhlUY$$!_OuvwAk0G7 zX@f7B|NoATf7-F@n|96YdU)sOcK(H(AKvjRJO1*HGdu3vzIS`l{g=8AZ2P8dU0c6? zYtNP!wmiQ1cQ=3S=KD8&cli%WKil!PM!aEvYC-EKU|+5&d&NUrh~#+a?C)CG49Stq)k_Vgp2+8_ z^%~%<<3t+H5?+NBnhuYlV7V<(KtnJU63Pl%czq~K`kLy|zSEXbnCuK5Z|^JC@YaQ&VnxU43{Cx+aK zH^aRG3^9jbl|dM-QCxY+CRtUy2WHNPh7Xlgl9!cVx^i9by=4Yvy4C82KhVO)mr#QlZXpe2mLFRfT{Joz zV#J;r&zuVVnkgQ@m z{QoyEQO^o#8#+b-Kxkj0D!~%6_x|rbM)eP@kZ*Ei`7oY?)kVM_!Pn~>6<2`O8RK2~ zwX%})te9F94}S1Dvnm8AZ($LO6C6rX&a1ENHh5yXXJ~OeernvCu%c>1lmMX29wGo& zSzXr+o6LEiGg*=wS^(T@&zCPeu7_QRkkRFYGInHSFAV(-{&lnK^ zYG~f7_@e?)&TfTAq*gP&5-W`$$4sX^3+*)Jyt8M!*mfb8x{6C{(1hrVw=Pi^{5sHEq!H$T$TR%!Q|aO z=diDcPx?RQEx0j1yE9_$FBNq0xkP*bS0YYt)Nl4kZ26(_k zb>}HjHg(M~o>+3`Hf?-(J@vld_`HGb8J_P9S@Ufna%t@L0Cq5u zWOPV#vvIEz8W;bc^y!XW!#jU?=TkdoxBuAodiO7F`>ky|xBkVg`?mbVmgAfM?&f!G z`pQlBmg}YOEuHIHNPai@bh54U&y(5zr@y$4e?3|Gxa_U5WWbl1*DOLJS%md?Cc?A- zGC(j^r7)u{QY#96agVVoEOja~g)+IL_2H>otS{otVY6Ocxhc`!pPcYP3{H&8EH-m5 zFkf#g=BCbBT$-avoDRoOh_RjpM9dZIsG1|(bKRVOdl1a}kB1Jk6Yk-m`hnzWAAz=) zvPRqh5JF0PLGNO3b9+|*P)swbPMNO~a`Bi9yi{QCF zj^gL}TZAGCTc=@%-!ZGu4mW6E<>gYce<3;ULxV3rGIBa(i6Rg%hLP|X?gD4>>*tJ7 zOIHNAnIrKEzeE*BURk*=!>W?>dwUQ|`i?0-UDSJMMa)pGPF$HavU^VD3U_J^sIdNX z(sHsW*%Fo{$fpq5uFtK!#QwgvCpqT5*Vxm31*c=*((Qcl0;wE%*K1UI+H;I;)Uo1-9miOG%&4ws&}t?1ste_~^i>4i#LipwEaz+d)N^qKTqm zkmaiAIOGpEr}gT}qC!lQNv}6djLhk0BbA!$VxyOFGG;M4!b@+nuXto9zdKshP|AXh zB2P_A!HnE~*cMTk7fTLa30#NoSf@F6^~5c{_)} zTXHOW&F`~1bK!7@bcS?p8mSOBvDT!fr&LSx0znflKF^=%w5e*2Ghcim8g59x_$$))dWtH zgob)&^@>&h#J|HGyrgA)C^;1Fgc3e^-xYX=kI2vA}`KP|qN5(p}(pqbMxZZqSwWiXEH~ znO9koyL&9KtFCIdgFDBgj8|7+E!SRqS8~v2H+FicdYqtZ?Kw+?$b!eixPdb zFy?A0FtI2ouRAanqdElg72a6LhPj(sO_Zod`kV#**GW>q7XJ!yC1_uWBXVG^YRdG3 zv3i2#u+D-@(E>RwVU2d9t9YQ(`u!`Ar>o0d$p?JS1H=8`ZRC&R1)BODs8tP59GY1~ zOwyrr+$>uW#41J%ut;PcMuckJr$d;QO|W&zM|>XnA@ZAiZLL_Y4KPM$(hsj(ATO{# zIpD*~WUFIbo*D?Gn1#R{(K2Hw79XxZxN=@|>`tEaMgk94u91q1IinbhU?Zf=O#vcy z{F?C@=B%+Y59}k?Yv-b;>1tlH2%pR+!=eXoOTUh{Ec<<0A6}vM*}>%($u%)OpT%~4 zw18JJDw#XB@^Z4=T<=mph!%^jXRacgLF?vQc(ewEZ!gB%TUwkpHH`{{Z+LrhVzFc9APTbY((>`&hBQ;Lr5KrbZ)NogOgjZmX7pO`s9 zS{@N1Fg`;v5o3rRFQ#gYje3IDwHvy^Oj#E7($yZC#zBZ5;!bz3oRip}N%pTF!|<_V zdX+R=*sOm$(`wiYghX>fjTeJ-I%V2a8{py$Y=Akpw;{zw@5vc9$Ra7|w7z%ctaf>C zvTyxxlzO>lFtohUp@heNoeeN9RkVsdlDeBQ?vYYqJq%ls;8WM0#vo7AE}3+BVfZpj z3xSF_=mm@a-_!A_j$I==&+Pc-9Xq#w=k~|CN46c`dTZ+u`2O9SKeFi$Hht@+XE&A0 z-wMnBb6p>&qW`yd*7(X7`%nFYjXSB;w0tC)@wFT6>jz01Jv|xlZq>WEIl#&wpGV0F zBM5K<(-XDfDlaH+T^g=23>^;uM1_ zwn?6WMk?Za;ff;i>2%|*Dm3+$WIAm8h-G3al|fF9r0n~~Gw6yM`Xez^VSbH-WW*yK z6bmB@8Xy$crJJ{SH|K8K&Au-}H_KBE$`bT_a%*zd`!U=ZrNKiiJeJ3%jHrU&&00X* zr5mL)s;sZjrk*~qh8yO8_}<8vii#zOO4aNkr{7F)i*~!o>i~AF@Ri{_b2H}+%d)$O z=di#Y;gPX1Ao>1HMH;Phe$L5o?>WaAmGs;(yLwlUxs0tHjn9eS!Z7>)La=Z%krb#-d3mO-P7aT=<@$ zVf{W^UJv()u36X_J|m5lZ%o0G)VDWU<>wm|o9Mrld@Nj;p+XTZH-=z-4rg};)Mn{C zMw%rW0xrs^Yf}nzqnD9I!DMh38@n(mx%Q4>7*l!_Lo$2bTSiEzKqIcSNR8QR+fhKr z{4T6QskspPicz|7kkV5P>Qd~hZ%sbxGpS7U28RzPpt6Lh${c`7u2vZC1#(BAw2I@C zk&veB^TBiY;q<)hAK@ba9Y9Hyi{3c&cv5@wOwF~*xqwbD_M;er- zIB-4rNL=+$!mBb`15IVMbM^lcWwZ?|wV19KnTxFk@nTI5HM+sz=ac8XNlE}vvYXoy zVSF_z!{V_^GuN&VY{JZ;M7PD^!;82QCXj-!0e~pI?@VKxQU`V=&xHk5eFPC7j!sm0 z#6<0#U4k@<0dVcw)D36cB1oj2IhLcaQ?a8U04;>vrK$6{bm(gdk%jrR{zzjh_j~!F z`3B6< zU5iDnvZX%-yusN-S|k`+a-aA>F2?Go8mfWuT4(aC4;Q_KlK>-x2(UQ7HRZZW84e#C zGr0?ND|}R*m)Wiw8GI%USb8=%=vfaMnh$|n--nIOV)=lb=*vuP0X3{}u+-xG6(L=G z*9qNW+(!GC_(#=W)^GU+TN}t**iK|mGkyDY`b>kO8%J&?1kCLXPb*Us&keV=VtIu@ zw`cnt#v1RVE2emUZ06~q2E{fG3?{6T8rEfp^GS`maT>M4EBOG;k|gp;E%`94dViw~ zi-U6pvQa9k6!5Qnl*& z00S7wk!x#O!>E%415iUDjlgn(BcYh{d2QNgy&SV(bLnJ-mw;$kR~~OfV>5)^#xgUv zFoVBx4F}-)Mi++D@~wnT)H;mzjquQGWK%?P^i3m0^bCd<)c~gKY6I@(l3S}0$uGRO zh;pFg=oFYzD1^la6c!I0ir4W{qiQiU+iC#>7DgCI)JV$m@w>+?@hL*fX}zjw2Xyx3@Xvrz7u+t3V=56CC5Vcw z&#!zL@a1cdBtv02`;JbCJcs-}9^uQ0E0iV0@@99Bg76;dbfJPh{!&cCw7Zdy zGQYy-%ut#Zrx~|AOihQEXYtmx(j&7!2zsRy%+DJl98LagK}_g`wmfQbE`Bx~ZgUab z`?C+5v`OoauH4c--IKtK(f#LU==_KzfGh|Ot)bDG3u{Pfn7f~*=z{7}NNvbawoWdp zj^b{~oIN}bf=`8*5&|HLl)q+`B%vOgB@n_J%;4+-*1LfO(KV2qHUIy-@4w~%p`GI%pImDU=MV;RgQ^|tHUmN4&k5k(agYaE48VeXI#V7o_W8jlI%+M2xT zjlrCpICiX7HDh5!G(d!&bh*P-p+M_Z;{XXGM@FAEDcG{R9; zT0Z~rG__uTw8GB3&JU77>wyg?TT`J6rRJyg1C70uH3I&+)i!Mp;TeXY8i^{lbz3nN z#EA#$hzNyAu{a)>^0X&c{ib{~)h{K9z(o>dShJ-u87;uSaC=#Gxg-QxI8q05OJi-RPc0IZ2t?NCJ+PD>x zLTc-Y-kVWhg&g$3K;M;B2IO_C=d_-6i)*6`e_iH3>5r!6+^|ctScM%bg&VVgwxM5~ zEHii7zg7&`D%a9-Gt9UNC-Tu~IA-XVEU|@oUMwm&;8-is)Qahh$M~3)GAf{|kK%;# zF7C|S)$}8c_bR$oPF{)2V#JaVva=*XY4b2^+ibGPe7~_A#~`imZtS7` z<@=Kx-hMDvjyb1gY@n}i!nAhUWLOk90`r8ikW9{_b&pX)VTOW<|IcA!(me z_H=`6<;qlY-J5X!z#z{P)hO$&{HKwzB8^~B#1R46kq!_5Gc1{_3+X_ET;}SzV#?2$lQ5kwHQucQbRb#uc7x+Y+Ev?2=)p6J@|Bf~(JI_)T&5`{YQYRTZ?tbA z=ydjC*SMjW!Vp~q2&d0B-YJBloP@&RF?oMbZ@k;Xnn-;-J26k}o|zYcLmoY)h#_G~ zQZ}L>rPAjc56aTroV@5$FnmVfhXUHQp$UT~tRka_+2i6VlhR^P^3WX!WvzTZSaMPg zGgo;kyV0Z2(1qlxH!oN-BPhVL67qKJ*iE5;wa7m3j*2(1AYDS3SzQ(A3US%An!&5( zS{W~ZU2fN+%ZD4JWA}ZclFa*Zcj#u(Lj4wP$WL9{|kQ~1Hx^@((OPlFWk>L>0^uJ{7>acCwy zbWX)$NLNykH)Gd*3aoJ3O0g|i*VQzHWt{UZYvo^k54*v&|I5-aa>WNt~BnA1HYKr<{?h^qw_ z=GxkY&ou6(#>K7VQhPVYPbthUw?;=kZ#;ujIP9jsCE8{$EQJaSHc1mQ=~#pG`2Neu z3*PVqChmwVcX2XvEV{jQp$F`*RfXpGApEp!OCb2+p^CKrk;Xm5%UC&uk10d4kpH$V3XI9*{$`PU3jjW#@~Ykr}x&T~-E zT*2hxLnxXMPsq%PXdTRQJ3Rm;ZzStY&`Z{h?CwIOK)t5RPd7-%f8rCDl8gEL#4Mni zEl8r4>+=|gy2@uBhaqXN!ca=_5pzY;)5dZBY%Nq}+i8!QBf96>{AFJ~Swt3)qfudQ zm&uBoBGpw$^;OcUQ6MaUadOWIS5?J<*sHxossWv!0n6tv@ayBcWTu`S0IHv|6l)$M zZF__i)}K9qwsROt7$j3eMUzr?#72zy^0 zgeU$GO<$fNT(J21%N}qCI>wC0Lda*9UTIJO;Bftsa4109!vNaXgji!yrQF!5k>zw((#*&S|N*<-2Z=|vHlf{;iOAsb{vvP7kUoxUR2pMhjsY>??mj#A78!ba1e1;l|~& zk~tO+PM3E#24wBrm3*@|Z&eWNsWg>@PetrMK^<)fgBnJn(ia_W;p?if-kqIF=;P zb&hHo)A>;yuELGuVCh!R5YFO?SPzJZ^RqA8+Ii(Y2yA&ZOG%LUYss}(pdhoC@{67y zcWhhADYQl3IoIxWh5PA7u}pw#BKAteTLm9(C>FkaDeU6uw6~!gs|(4eeWeEbdTSNf z_LnN+p{Wpf%vV*ze|iNQ@N2i~1BZ2=CK{7ptSCpDAuum7o`VAW2zk2VPqt zNXb%OCh8`ewV+L=&LY5A3S_%H7W;@U5V#pE7h`F7DM0on1RC{g=_LELC6?eOiTg3* zp}pPUB6Nh;#+eOl8E;vpMSq&FHhISU7qZ}N46@Qz2tn^p>Zsc4cLmcl{? z6``u-bzXx#9{J}zN{2T4)sEg;?7{b4Q;(RlA{xgPO*ox|YSQ85q{%7~Eb#v0m_~Z| zxk|YPoq+gnWPQx;&ZA^)6_tSe^%d5~`3hzsZVbR(ZuE=Q^HB2t_yU}&oFM()%iQ(~ zGbc~w<_QmL8%8OmQMs-%nHrN0O0b2eg?Q_?n&edYguK^q-o2*XNP~2?CvGI)=-rI~ z_(kqst+!VX1*%LX#$b3GJks;?r%{ z8@5+J(x~DNFApbwF>g_L<>1JemnF=QKa(+74A?fo<_k-&%uLQFsLF^JDWKP}Kp=IE zw42tLqyg`4M1>X1^ggB9u@6|Pv{`HZrXujmrDYlX41V4irnshBKZcNz^UO= zla(<55s7;KAuEUQxD=yDD&`s$J*0Uc`Fj6Cr8-h`5(^vTq0_agsg>!M6r`Kh=n7W6 zIS&Rl8$-Z@UTSWSiFgCp(jyHj*&aHXtcKp=&}^^3gXuIMp*COPS&5i9i1b?Hh@`|L zNyD3vw-GOiW#^fcko?NwvRrGop)gV>s%y#-_R4ZtrwSg0Wwm^H+p@HNSK~v1dTu6v z)_Xl(BOL|^Tf`Uvi40v`hHq-X`N_RFdsc)Ag!XP-QD0QcDB}cg^P4#ohSNqU-G;s`C8=hDn)B#dv!chBeJ`H_isvM>-%1byf*#%VH#w4OAck{qZeU*&^p z$6QHXASO03q;Qy)EkLDho8x(ynb=fx#$PEdRuj`u!BUEFg>uQ>UQ98AEdpT$)9eU6Q*b7Xl2aG$XMK&6Ki5O z-k;|mdfypFZxu@%9nJ==kgxIrIMoN0WmQQ&I4r6_+5`!lxNFAG6;t0xcOc*CE4jlybx%Fcj=Mstjsc?`<4V-H;Q> zp9(9a>hhDuKef=jk?o#w%YB`-94=$j!CEMP7)uzJ*$BAUq(*|c$Q86&un`EC_brt( z_mV6!*}P%2{M|E+ZQV25qkYb6CY;uvZak@ZoJzhToFYeL3ehDOzlFsv7KuQC`vLGc zw_ruX?>x-M3gZfRCa123Z&n-H68!coNb`Dpm<+d}T^SE734f!xNQ9YgJRz}oXYwa~ zG9jiCZo3g!Z60n*=vHX=*IaD`PuL$%-w9c0t}NxOLa%(k45NFKFZXURM<>TB$9MpU zmu^CG_#5|Q+muCH6{&RX%|0$no!71t#2IhwCt&+(@(J(BA$|3imlDr*dIMm;E%nfU zFJM2d-`jYf7@{|l*TS}s;c1Q?OT#ImGFuV-SD!`uM97$!dFycmK;mxx%n4Yt2 zOyO%WH|mD&Kf2=4kUwCd|2!)vWP+#4|9^YORL8E5?EDiuF79~y_Rno!+5X)2w|D<~ z_iFdyZU1B2w{Lsj)=zEug)RH30&u3>)%Dktf0-QZ{Kk&&;7c&P6tyqKOoy#c}V4_5+*Uq8!fFDC4AWu1H6piuSc2H9LE$W{CMVaIT=B;k=- zR_hx`8b?l?oe>l!NK;QAL=$MTXx3h_ct&T=%^>-MTNl}0W^P)zKQn(3cJ_SUTEuNJjnDfcZZBECNY;h)nN1w5HbW8P6S@4711R@VVsA{WY>lqvdGD!Bs zC|vkV2K9PUt=v@w((Hyhkxqw9lF<~qf-}aHUmk0aLUxGSmOtVXIu;m~LVLw#Jq@jJ znvka0)W)#HJC=xBoLx9CA+Cgg%sPJ58jmQ>&^R69yX;*gDG%|b(!#kxT)cR+qC+gs zN9@Z}6%_zswQ}D)C>)(8LyC(^xY&A|ma};qH4}$Gfiz6$m}|9WgszP3fTEsb;lZl`sCuf=5Ggj| zpGMiR+t{ZF5M5_Zqv|VXe?^T$aJMr`S<|t-`XWE$g6?}#PJ}%x9-o#onM8sbHesv^ zD#1hz4Ksx(-8y}PEd?@*TAE|2q8FiG_kn47{X7wOKd|##jOIi^4 zZH}oD%2{2!0-d}Ve9uQ7;Gq2LDby{@SVZZ|co2~nR!p{~CAQ6Xv;M9Im2WG{cO>8E zqYY`yr+9H#Y5$dSA%EFq#M1w6gkc)^x5=D4_J zq3}AwiK}r|GN2UZD=>WKixQkCq9{ck9XdCRF7T`4pvkXI2M}75K^Jd zYE=JSqLz<47TJwS4>vvnCN-FRcd;>&8;1ubk8+MrWDRB9Z0TyCZoe$>*C;|t#rWjA z@&?FxUO$lR`=ih$b;Sz^cFzdck-sh^U+N6HZCAt^RFCks77dC@}2otGLm`B zsn5EPM}-jtaZPFrl|n1k|AQ*sRv-l1|?$ak46ZmzNLFPEfW(tEJJM&J2dh+n-2DG{b$ms~ zu5Z{ix$B{wKeqF}9iQ2;wEbtcU)%of?(gY-YU?j={VQ9a-|{150{r;qi<|G;^mUuw zTmILjKP*jko$b0W`4`DoCRKO#H@np&<$gL@tH1|r|;#1!2P(`qB=_Ts>xm`0o7}&Uo|a8 zKnUPsH5BSVrF~7_Nk4QZ`JM1hJ!lK0LAf7)l(p*cDPM808P=fKvLR_Gi+7|Kn&h7L z0nq)nH)Ks1Z&$6UFp}aYUROnqpCQ-oDvDjmlFA>^^$Pw6H)S5z5-LQjg%JFw-sTn* z#aQwm)^*fBp{y+Ryrv&nr>2>$tcbaFX@8R(&DvP<@7Fb>cdo>WI7R8sH`7vIlcdbP zvE;Ybwba{ZmV&nNO^m48EHkl_$#1S}$6}2&+5PL9G5E-;Mz}+r)^9e+j66-bzke6n z8O02RZ(@yDatf;0N-H{udb1kJCmst?Ff=(eo~&xixB~eCr*3amg)bu%C50p8d$aJRETy5qyBgI^6BqmbqpOt1fqdZ5<$ zGQH=P{E82O^48CI+&5-LjkD`HSd+K3bD2Lki){*_PYF&6+sXkikHcX)nEbrAUto}^ z=@{tb^HbMV`AK0l>fD}Ot|mX{-|*1Q*d+Jzgw%tp8yq}!SIgSWlQ_sEf&Wf zTUh5+O!w^0OyulSOlPL&FccYP8$he}--!`(tZ~C=i$CMz;%?~j#h^U8qp&gB$mn{T zzAeVoKiHu7?cRyxv))i_!6Tkw0&2i>^jWRqmzPg9sC8QfH2!J-`k)8`_Qo=i_?VBb zp;SjEL_tG4a1*VpY;fg3p+Ya9ryj)(S@{cMT`D?nK`TRe*kdosr^B2zAVyn8V$9D5 zQ#NKE{VoE&fgroqIu9~{^MbN+P}u{t=ccZj?~}FKPQWq7Fuy}HT@JL77%F2zK7*Vk ztnn~ou(>NsFjmx^)e}^58r(Er1Q?5qAnVV-|D0U@N`pGS)%xM&U--&av37WL(Sp($ zdtEDwZRnLLs#F&^3ehiyXS0_&1E(Xq_VfzLs*Pn6C^=W;cD*xw=f%d7I=?6R=iYf` z^k@x>!gwiJ@lAC;bq(~6x%v4g!wKBpe;7#kzQ&l=EI2f4y%EVaD8_}w4IZ1GXe{E% zpG$tqd-9_H;W(4d$*Y*5e1@PS(#fXGCF2%by&EN5>vVdm^mKZ*LA~3_qb2;QC21-I$$$Ugi#+)Ty0r(&@dxj06FM(*kOhd7!};OzUrNP`vh3eKz^0 z-plL6egKa8{`bazMj9`I#@tMPGHl&|!VRYZ-)G7EB`CmN@q4 zGCi%oyFr!NebgNIM|q>-?ob^^K~(8Z=4a&dn$L9Kn{{2wj8YGxT3i0z1 zpkSKtc*zDKbZ)V-D@+IrHa7JvHnI8t@9eB}>{{OWZ+Cw6&gzc;x#Mehl(v7v_TKLQ zhX4Pm?(S_rylrY*$JYAR&MlwbGP3#mHZN{|bkk=yy;T0r@>uD!rI$+&cYRCO(WH+? z{%`!V+|eXC|MF`OblvHDv|-^J*x%!)hDT4t(mwXlFLE`UL$t(VLVPX4dfwi zR>o@xxQQ}H6l6utUYrf)m0A9dP@vJ@sOZg&W~w!~qwB42W(|4^Z!iCGtbqbziW2GF zL%Z{l`Vk%9m-I}dl~Y&J&SmTBvw0Mu!ojAXnBVkDi7eN5#q0 zs!_xHD2UoDZyqXtw7PuqmReOv-oV=9T!gH#YlhRlFCA(=0;Dq2bw^w0UV(1o-eg10 zli3@et6bCI^G#C!_t$rIeTlay+G7T6$Oo22reywSDuc75mQ(HGQbTK`b<;Y~?>bN$t>9o|P;9~WZ{iYE=dp>R#yje-tv=W zyoZ#_LY6arfo-_{n@4@y?ep+90@T#>O!GaW^_9D}`}jG2N@Y2%MOq%?J3T@9wxRDDOUleVi+fuTI+4{ z@cNNcU0c1K$OarSyxV?;$OuHh@VH=G9NK_zqT6>g->DSi3td~hA;A(91;`2v>Yu#I zrRfH?T5u~aV@!%@kz*Hz#l!+8<{Yz~3Z}W}x2 z+FmkX4bqP^NlZUn-`tht9USYUe8n5LZxech=8reYN3Wde>I|*tsp6R+sd7pgkUmq8*x6nqP`%`+V}>ysH2V3eJCe_^36K?N^YW+9vU#g(6J#yfA;3qjZPC ztL$ z_OcKDGI3hJvq`1q3hylaf8MrPVFM1B#ZA_X&Dxuj5;w>!{*%+sWo|>sIKd8AUYMId z3(X4ym2!^(ojSjCjn5-t6knq`U@Xpo(<87{vfwp_J!PH8>W?M=#mAMIZz0N{Dq+-+ z2g&FU>cDe5vU4R?7F%Iy>U)(PZbJ}$htxAbkH47Ckm6MdUPuNpXIcFJcXzCI?Ao&P z2X-FW@t=2m$Br92KD7P6ZU6S|3)^emU(NT{& zv5)Ptu(`FGDfX~p>6bOBv@lpdRJzxj?(H)&WvH~wlLljxaqmQKfK42Rn|bJ#kHMrA z&tomv6xu+6?=>uG(BVdOss5WMb?@WV>qyUp)06s1e=23%KZ`%no#V95pSmD zLawMY+^T4EvwZgc(G1$OpGjd3rtpcFI3d$HkI4NYD74(YL!4QFbLJG}9XjYTl zMaBZo+X*pCI=h1HP(5A)y&s&w^MJ~RwnC;3^i@5!5lNnMheR2G)GOFE)?LH&LNxMo z4>e#b-AJ!CsiJVOzP~Hj6DRuQx=94m57hB>Ef>i+ox}BFhc4wrS-|?F|6y? zc60?(BO6z3IHv3KD9U5Qg+eP{=S}hM093|d#2~p;ZSX}%~JaDrn$>GGXTN+2A3?N(Q? zgt94ChqDJ$_lq)H-4luORZQNpoV*H&j(Kgk9~23xb2yg^)nveksKT&kzAG4WYD?Do=hKupsNe5JUb-nTfu3GY(vV;s*!nJGuhD zQEnN)MPJ{L7PwT#`6b>j;Z-qJy0L8FmztC@*jMlG3amyeHW5q` zwH;_vlD|P%W};ayQ|OrtOdC6e$S)FdYz~Wj)3>D{Hn}@i1k9kewEq6)A!XM*(G`f0 z6GOTs{X9~L59$oA!T_>WiGoU6$C4ZcFZcAs4qq&-KaeG%?KAG$H70zAc!1+Ud@ z7^ww*?LbCIdkGT{23LN`A8t}2VgH`4K)Q_9n;~em@QjNgW9bK*2Z2#*U4d4~(Kg0J z^ueNf2ena&4u(r#=YeHS$MrQo0B$kW6}XhKoAADZ7UnuQ8)i+|Xw^_5u%(4J8!kR% zP;DN-@ty1nq(p#RDy+p9K}JQLH@rxd@1|#Fu6k?@8-_@Ed;x^J^?~M-NRF|tz^@xS zRe{7n)%QND)KI`OXRqwF;COZr(|j^ zR3B=-A2!gLu0V`Keae`{OCAO@p7Ru?HF{LHSzhx6!C;6x65aP-?h3Rv8c;z>M>*EC z;l(7vUegBVFEoxR)h00@80VGb_Cs8gf8%lr85KAvm7`X?Q9IH;n(Us0l2e&tL41co z65M;wa>8R{`?z9sU5KxTi=7^C?&BoQbbZb{@2dplRyBnQdF0VAZNEJjW5;>Xt9Ei! z&;y}Vb$zkBZ7rU7zXtGhM^UKTBql`#XQ3^Xoci zI}ddHD2=|EKS!FkxX=?NIN5qGfn;ZnWA?69#Y)p=1%Ewi5FT`m$Ygoa9)W%Iu*`eSQoyldz?PjyotlTuk>uz zr5B9@@G>5ydb7%LG-Ws-=Vjw;K%9Jk1S!iK8k6cku^J)|B;Qpx+ zu_1jrR;0@?psaC?(>mCwAl>06#KFF5X~J8{6R5lZk2jk?TkXlH`FTN7TnCMtEP=gg z6#4fBO0501posjtJu@$W>aqy(8hPC&ooPar>#N^U0yVLX_Ub2cQ3!mETLcY!Yl`%H zL4qM@R){6GnOk0M!|GbbuTtrBUxEYKWsY=7GMU{_*3d?0r* zlLh2iU&)n-Li&P%kY?kCpX*S`JBwz2&}%mBf#x;7dbu?09doeAF*uQZ6#z&*2d#pI z={0yH7V)9Xa8|&IznJ+A76U`=@T;XEZ|*2gq+wfnxXcdYIA1+WcG4BAUBUPK!e|L) z5oNQoGhGNPrypuwWrc=IgWj_2sy8uGx3T2(rpKD|gh^&g1Kt3-uWe9QFWy)n({nCP zEE`urG}`Rbf#wxX_e|+2Z%8LmrDg2hivaD7%l3$fPi{J*`|P1HF87$~#|(;r_iFR9 z!bgLpL*8CQ2h}cO0g|ECtdOK;3YoXdf@N6fiN8kk8chrAr1UmPl6fE*;api5)s{UB z5EKKl*^yUEAB+=1!gyT>C+AlNIYGf|g5eQT%CmJTbmlNvQA>vxtuu+iiS70gIQj7d4(85@Od zVy_e6EXSBHlylgbp??_h+A=MvM})|re|J-*YnHc`4tR&XwPVNntSUl0H5)+N1<1v; zdcHjZ6Y|#!GJa&l#M{5FwBV&SVfTPjmD;@V3qZ) zV;y1l2(!_eJaRTUGwI?EdMciTMEr@UJ*qvf-=yc8RFkQ)7f*PfaY2UQK0;?1M_2Uq za*l)NXb`2{$F}2?XE~ZzNj?JTyUyF3Dt*~oH7_^yXn6f#>HXf3-TN3&jL&^(Zkf!d zZj^mFU~T6-jf3-`qfcD1|@wwsR0i* zV%u5GDJ|fddF41jdZc*{x9U`BU;D)1$x;`<`pDvmaV~K+-S$F=oh6vOP9sm*IkC;<`e?|Qt2^oI$8$tgvmhIxYZ2QFdK*UiQveECiNu_*Y7W-?W470 zswjMa#a^_u1B$89F3S{ZP(cYyJ_Su=ig0hZ7g8^K+j+Vto0E)vzO=W!BY(j5m_2A? zV-Mmq=A!$}2w8F}H+})5LA7uI0@AVOM^$pa^k{pVg;S`8)$9gGkTd7cwWu}MQq~zq zfC>#5^pAL}F{Es&!2_7<#IY(}7R2%CCS@7=ZkFELKCVDzt4`XFi?h|PXJL;_uIvqR z?_7~5Uu!OsaFVOel zRDp4AOc`0!g$ui7cC2wUbO!XBC@rF=d!>20oIGFOQF_?B@*R(zh+?5y4wyudZBbmF zxZb(lN%P9^%))f-N|?wHyZ9^y;Be_Z-e0^US|P7PU+h5ZFCAwB(M|!z>_?l_e;B+~ zdZ@jHU^uvdovea>uUk-!-`NKkfYFj^EfZvHknE&vgHC_vE(!xb5X_Tetq%t>at% z{g%}&k8J+7&App`deg@@?Jj?&e5t&n^y$)A*MI1m?fR1BN0W2O-JRdrd8Fg}XzX@> zPP8CC9=ufgDqnz5Y_xY6p&r5QkQt>3#A@h@ce3#!G)$`sCDRs$n$|m7@E>dSYU$6k zwHJ631Pqm83^1mJy?wjqNG>xchIX@PUZBiH5=RExIWC&fQqyZK=#CSJfIq!v2*NOG zm4VuGPB0njBPGS60Qs!KkV2p8eD4~dBgpNHtLntYbgI=OxwE76DerW!(qDP5HiR|C z?bNH?#0fO#yelGv;(lo9Gf%IeDt|mEJ{sDv7|Q zy;?^UfPPG)ukWS(a;0Zl?;x@N)zY7eO9U+}6i|-M3A}F~F}2|#x;fqxM;|Q(2}i59 zU?@oXbnAXp<5cM@y!}9aj!pLsj*MHlBOhlV#l&XAW%0(IY2Al=`fBMerhj_ zogS*%BV`(85JzVEWA$V7;X> zG*x74Ane(CMsqVtZ4J-5Aflj+(>;hWT)iz9c_z;B^KyhS=QWnX@X8nq>Dd+($NktV zpA35e+NMKeB~A-5xVhQ0*Hr1jV{u{#xQ3S>Y67^3#^$ohUv@az;>n#o^>XPGp%Z{O z=_{#1!^N}OR9HJ4HZyz{P3d{Lra&Gk^pT!x>6se_{#v$p6gMBP*6e!89Vo!Vobt7j zPR-|9z``P#kDF~$`h1J`UmmN!rL^q5L<fZXO z)vzUvOlK+|9Q$si-lRQ3RMCmVEZ@{MUJ-69_ZoJZOLnJB{LQ65;f;?W_b8S`V!(I> z4!E+_s-b?KadHeu;^NDBm83vx7x_w2YekeGJ=uCIsLQLRSG{>9znvQ8nUhJL`QC8& zOk5^G{!R#zJ5;p`GfbapL3BJ&?<{?pH#!WBgdE6N9(Ut*GjVCC-NuVC*ZNYOmd8pj zdBdvtP2rEzywEpvVvKXRQP?psRcv8MDY(S#l`(E-#TH6u$o>^>Uq}RANYA(KkRkGx z(o$IaK9#2i=#{&Qv+Ty2O~<(;_EJEwo7sUl8qU3QY`9~YH&)0+NpH5kL>(P2EpFVA zzhG0C-y5}PCdx}Qi}PG>g6LE1m^h2Y%fz-hY>{4RL7+Uys?K@ugB$`}GL&5Zkd%TZ zXd(Jo8IP}OBDQAp=g$ir$&Y!aB+OOU=QtKb%!rv1Vv@E>hgv(4#q*_0-XD1uV=9n^ z^;PMWvj!8CFor!Mg?^u!Ht!7OK#5-^4NGvEMLHd_{?q9eHHK>S?$Qh1qC{Wc(C|e6 zakHe^FwYbj;^2lybY<2tDA8h++$z!X5)Myf{zoBgLJ^V{0(Uw+*rI;WzTwiW_tG~! zm_-&x)}oU_WsC6WORa7N)DD*}`jBC!bw}8z@h9a)|e7X26Q^_R%N@$;7MO?ZB}o! z(sWyI6GJD4hED+sD-`m&z2%8Xt~-miS|QLM2vWsChg*x4yh$5dE1hc_f=ln}X+&Z# z)M`RBR$Ali%;I&CAatyXtx?)XjA%UoW4Zax326U}>@sD9aOhw?6AcQ2ARTW}NU3(Y zbhd2-dZbk`ip&5(jnjUV9s;uL*m|rd1Um|2g3{fhvJ#c2OHM0^pnr>aw&ecis+1T-6Hdq zsDf4hO83-vwWxXYSp8<{V?Ho5^o&zPDU}TeC2e0AST2j5suoP5@Kqg(Hyl_D@~FfX zL%OF$rK3H|cb5FnP4eE3f{>^4@E_Ml3NN@NcF@d&MY>p&40_(^Nw;xbP538Ck*yS; zP$>S6V}zK&dKK8u->d;<8ZCKs$r``V>Xc@Axb#t9uCUIEe_51}gAryP24~}1G8ri5 zj^4*a<|7Coy#z9y@4R0E2953P;m!2f7IlmsArN`SJA?n=y=b2U-ojQaQGmiRjhw5W zx!4MrIa@Id$S!9(*Q96>Z+@0O;!QJw_~5%jK(RtnzT`%Mu)7v*3f_I!lkZtiSD1SI znP!d2Z03`Q9F->Zi7LaT=fkQUpBV3zR4H`DX>*e!YXl8eY(xD2Jsqu%T|ctx>vlc8 z^LKZ)cJ}Y=-toOV?%qDP{qF9c>|W}=f7?IaR^3+K+S>Z=Eu&kuZ2s=e*ET=7>GwB% z^QMvVAC~`G8C0Y6?WHrN&0XJ;d}q?t`L&%Rop;dWAN9{d3(oXG0Q%4P{LE1bMu)o_Vm1gRd?4UMDRAXO~-$k)J>{ z{(WzwcVc9+cX+Tu1U5ulc#8CrgRipA=JkTW?IJJ*t4`u&39Tf%b}=7KTHo7(qCB?z zmeP-Thohv+T8syKi%emATgj5Mg<%w|OD#eq?cuIt6V1Y-75?hUb_gvQ>5Ce!E-;2v zG(Mdj;PV{`8T0SLyHhoTG0V zm~Xu#{_2R~)#@4C5RlK!?TA?vaTOB<&N>`x^#OD)m40Ny#^bqrqsC(tFos7)TD;O$ zxm^0;_Etx5-6@9A`$o-fkfD zk!$-#?Zu}At-!jQM@YGhFX)E1yvYb$;oWcrN8UnmE(b75EWWHQ@Ny&zBd<|>zdPT z2V0P6kIa_-j<*t`Dnij?Yq^yny;hX?1u+yGPy1W&YWH0#eP`RKRAt-zlU$I*0WvC2 zhF`m`^`RE;bsb*5RQlU-byWRk5|H2K8Xh3e+L@x1p)^S#3h4cmX-pJN6}>!nLk}1Q z+KYwVvSfv=Bi^8B1j1l-nbegZ1%7@>eDtRKC~E{Y%7P7F1DW3J9~Rd z-{BJqaf>X94kSK!6#9nQ2;%9^MI+kQMkhzCY>2$PWy0hNdn*-*<`C!-`;KZTz0l%` zEd`hVR@h_Dqn4tBiT6wvnvI!-(m?s#Lnm|>o@-@wZZnGXP)n5JQ>AauH$OLt^Q{lI z?z#;xxAqHG87zI;zn|H>ve;CHjOR-sX$?s~tu;q;W37I9o0+qLVCotpI8^pFf;Z0o+V2T?@-J9ujq6NRWx>Wjl zZ}4f#stn=(VPa5CBqVWZQZHaPz={UQS>%`%a3_CbG9%=K&!wkYk0T^+mR7yp5v(n@ zS}e=J!1#*8X1W;W|GMEs(9f%QYp)4CaBxf}D3&W3ksfP3hLSi_YPFA80xA#N25Mu# z8sp%@?Gdkucfn7#Qlhu#O3n6$e9}b^L-W6FgPxIS32H27eRqpeNhg=POAT)|CzK9C zy$6388K_h}!1TUceDNxZ&s5d<$*{IamPy3m7017`AmJmy3Ebcp`R-8K5WW%AgRF9} zsy6VHjDDQf-_fGp(jYGU${UUKf8|IKSr~teQn1qewOI(4oHHBYP>YgGCnif@w|0Co z-}BY%&4=fla62>`tPD!+y#`zU1#b}NHPj2PnP3Z>3_{c99LJc?9@No`r9Yp27wUD@ z>c|GON9V*)Aqn8!atSc-<#zE%Y_NF32@I4Y9QEBocgm%&^+xj-AF~(v?7133nmlc5 zUPAxO;vjbR%pgZ*WS;azoZY~fbPX7CU{AIlMt|Qb{W))0=xT;SX`m=Kd`F6a-3GG` zv@37ZgKLB#-&0EV+$eobwgiI}%AC*~LQMA6$R*%**M+ zEeaStvaj@KV`Cvk*B1i0y8piNPqipYROu^ywSO|`reKlebvJ_S4y%zVhY7`9aHH}oiiOj+;R2w9RI~{Inac#ahO+#6T@{ok-yZ4rOhr~ zj{AEqt#58oo%2L}xb#~-ZLwd9#oMwHYSxeeJP?CvDi&VBCG98e;cCyw{M_t09=$(? z>0AVlp?^LdY|WY&_*Ea590P;*3Z76d9Svz&dn)|ea%iN=(idAWl@EiN z{falJOukV)5i~UHl~XLHmW?G zU@BAivGi|3pF;zuCu@ofWc7~Lu558t#TQW?3U}22q)aA9yH;uufAM22c*-?^pU-(W z;U*O*f6lJ0>kFZb%$5@{os}lp=Co ze`jk7QM!D8=@;V6$J>3Kd_b`>hdm65sp95<#hSPyvOOucXvEcP9vw5a!6Y zCKyp`cITBA4CO=hzS6(S2U(dIKQ4zuO#U^v_8(!O&W2yYhGE&rRmI>x+Jdxv=v3)n zdf&kkY&W&?lNrsxH8c2d3zqWXlck^cM&e0{!CId|{4N(Rp6#fe8OO(3XS4`+lzz_J zP`)dVQ1ZfgfyWkwbc{c?S-EV9GyIuelyi8XAzVZkA8ma^p`Xsu&w3X)y@X*-oqz$N zJiqZ#uxLyXU8ksTf~1{d$*}B|u8lt_CyuV*3@( zr#Bs)H5T3mGW(_28xc9gKnkZK0Ao2Ip}KxGY> zq2+P8)$S!&n4oyZ=VmV}wbyOlP~?)aAOwTeS7_KdZN=dgy*N+i8gD_6eivK((>`3P ze2yCJFTaFs8=BvK-cQ8K!f)TGIM+l=H0Yb9f3a>6DtUf$JUKyvE0m-Qp5-^Ib_P*MxG)ar4<+x6W zL%YfPN3o6S<(3hs&y@bD55_FBKaPQHX;GK#2&?jwK9CUN`{P)YsTR-Y9fEuI|N2l0 z*VF+YknDi=7vz>5s;mGITW@BtfS+t9^TUj6;~Bfd*xUbPT^}I|MJM?^Ti>_+g19<-a(McrYIuK(+z^@Y2ZGsY?hDo6VUYVh-99te)MG-1!5 zz%!J?DU$~rkEMhKh)QImHF5}dGsb@Apa#5U`NArE#EDOq%Xh?H6lH=CERJBbHFz-f z8Mp%dRAJ}2pqKC!VDT9jMa@QOnUPA-z_HXw0D&;m+YOQk)Wq*bbGx;Jmyu=X?d_({OUQJ8~-9}sfF~tpXWJhrMMTS+&0{-n~f(kyb2NXz*6~3vSTN} z+A#yWm-*!ntk$Bcrza!HNiGCDBYl1qCMMDB@-A=EXpSc*hOw5EMHPq!uiI>-WWKmG zzsS?}G_FJ|d!o30$Le;~)O^0Y)0>Z{0sq(Eo~vp66nEA`h~tG-;rM|@L>&g%+LI=z z=nV2oY8Etw^CbJ6ow z>KXohyz2!NqOXPG6F9g^m(GG-;m2Mdh16y(E(oy(mwi-5u>KX^x(Yu}&#uDotkidv zxBCEUD)}PfuBWKDJy#Uu0WEXG)EC#>uC^N9d*fRvX3?dytMEEc)ZbF>4jaq;1Hp)s zB?RnMTuoAik@Z~UB~n{n<{cPYnL!$WONm;O^jQw~bh`ZRRk)mEpXe-a3p27hHftmR zf@O02^oV=1!AUZxDza1KSrrjJqH1e5v6vQ(_CZf_z1kkr4d3XI98(Mv*Vb^_2*Vb}L&doc>9AM$L0a!a86Uzp=zU?@Y^wcUO)V=i`<*mL zQ#Ik4Udy@3FIfz4v(PuJh$q|OFpE{3n47tBfmm&zmKf|ZwFkFAzvee5c4_CBcXVk94X z)WCjJyRxu!o?Gj;wNNs|;SIS}0cUhe-0Rpe4+$$J!q)e!LL_}+c~5zh_wh`x%5skJ zZ(kk3i7~fyM~Gv14GuFbWFxtUaW-xC(Q$R)3`2~Yar3E&6J827@R18Z0|5w~ z4jBlN8ib~};FXH)1J zq65Y>GYpCC7kA8*goOV8E+y72ZeVg!$9$89V$+R^Njp zImDnFFX6sopA_odSPjy&w?$>EC#FjO-TMy3RV@4@_l4yR7C<)c7y~m*EL3|+q1eC7 ztIGA0rQi34EJKs>5PhPAq1|wZz}=4X-;)!yz|AR!(16%bMsI-sN99{c>12C(&~%;x z#@QQ5Gv^U37t`4m4{c7cdB5i)BA3M;(XfcifS%xq3$3aHlG6DN&#Wi~A?)>t3olIFx z{AhUdDM$tl^u)|HWXQZ-;Kg~KWhrJ}Ni=%|*Pn|CLk~#m5=E+kXnjy*rYxRQ$`!?| z1D;oZqO~9kqEh;8AIb>ahfu{1x%7GWZe|xqntTq8ytmqO4jJpd2}Ux}Q+`FxP8bQW zad=*r<>U^n4Gp_i$@a>*n|#Uq|2-X_>e%)5yN>Prm7PmFetyT-?-<(t``f>+`}exP ztNX;Z&rpr^M%g4JAQ&DKi@x3twL!$FkC(yHq&FDGQ)7_&0h$|f%yfUBV)#OP?{&YR65+GG(Kf!?z6tW?O;s}T7f zTPVNZdqTbO3c97QDn5xE)@_QZZxI7gq?9ouHCYNT&ZwvO(qpTz_YO{#_j_ZJc@Pik zK(WTo2lc)w%A&~3%uej7)yD+qca}q0rpSwD`9`F&*0f~1mBstwDCJ6_#r*M;n6&o% zD(^80UfJhkjHgCVP%0;xD9)P3C%9YY#h59{^}y&tK3IfC#fx?4LjDN;C>yQ^7hY{Qy+g`p9w9ncH~#AJeVLlPb85zI!lH6xTVyBUVX3JjQ!=k-duJ< z3hR;c`~1OjQy5tjhC>>sNoK1U+j$&QRWIWQbCC1$49?*qvc>&B~RHY4OH zAmhZQF1#sYo`t9Z%0)`+_pI*G`FpkeXgDI&nZP!qawLd=Cx3jAh8^&)1?O!EEau*8 zqXi_#vy2%R=edwxTZLBmMEy|t5g(f;!hYey3J7)dl43_LI|GY7om_ob5X}AM_l9#( zfmBrK1q;)ywxV>v_5sK%Ft&6(;^EG1wgppm z7a(@*V%uDATQF*yh@>7to;*13)S2+{wEp<&Lr}1mpD6Ec>n-+Fz%lbC)^-@9C^!|b z*Qp&koyWW-A539ANW+s#j}94LPj)V1>*-Ug5GD7Il^^yIN0Q41E91?#qyFikRcaUQ z8!NxZziwYcP_M6R7gj2G$PPiJhgaXpw@;NHYVTZ}r}kZm8?vVNr&b?Cft@P9+rMvI zsf{|1Uyo}Wx_@?+=MyWp%J1^8M|BWYS4^NWZcrvBvNOR?@LRF9@D9XPiJce?d2p3N zL5DAu-|0HJ1cyX*fO4Tl#_fmv^lVP z7l-#!`R(53DB0_lm^xS+8x$ElkA0F9%e{DM)@X)v_+xW!pA=&X=?7PNSn*)3e2+I5 zt473TwZH9cNa-xOS&`Q7TBRh=!R5~K-Tw66aVh89a@Ftwg5NIALUD(p=y0|`E6k#h8-OqvvQ(A z2#P!7sq!9Bv~ZU1Nf0=KUOXcJImn&VXxz9@$5+1;C+OAko!-INFrg1(jlstl6Ug^@ zcp1{f=4pIvmBK;?@sQpc2aeIeCSpQSb4T8l**LjeRgQ?Cbxl7!qk_Pe+=&r&wo>xM zfTU}I|4;q@AKdi}_5aTA_?aDla>w57KehdI_h0G0bKAFV8{PWbTmRhjUjZlmPm%BuPkn8q+T8owP`f_6`cV4wEbgt7ZZ{Zlapr4O)9@elp0(=F z>SV8?GD7Z@X7AEi2R2L=ix_iE>7A`s>Fs3#~?XK~kp^tAtkev7={v5LWv&$cU2M2Rpv7#U}0aYc1&{TpQvFT9r(97i&%3 zScTkoq<*A)y4XWhwN|^#4o@MZlCd0=N~-J^@g|qfF7j|vba*b4S!>|0MLD#?IVO{B zQ+jn3F5lt$W94VP?~uTpTOfV8gP7Y0IxT`~P$z&h7?iUF+7&$}<5m&AY?`?I;Ut>b zq0b?t$FNjyluvn&ah`6Yi6KyFH?pD+A&WOB(YYOF5q@*4@%Trnl=*xa6Ho72M3XO6 zq@XCTnE+bIXz5vaSf!5EUC8w1Rj79T^(V>`-kMO%_7<~kX>X0DBx*SC7F2|a674ON zcq~)(x;s)^NWzUaad>}x| zQKrZ_3tFNwB@3}teMxb5M7aU`6A{A=9BE4(yzo0aXj<=_WbU%Gt%Y=cbx@-8;qu9R zHw`$hjbNV}B0?mnaC37AIp0saL9-Vw+7kk*?Xi36EW9x)xk%YB%*>tN%S-RvxtC`4 z5E5A((7ifS#*){{_xEAW)~W?-q@R*YOkK8%sFXU%fSYnng3ru(*D*5SL7%wH!|}cY zfgv4t0Shry(7~pF;&~yoY)z(5tez+(PgKjpJ`j5q+_I-NuA<=bs7oZDkR`nOG}htr zU1dhDDP-U5J&O3VmlVM-bMfFdtDX4bW@oY{g9R}EvuGt0FACY?*j{8Q5GAujn4Jxx zRfPp1al!|}i;M+PY6=FZi*kGEl~qdhRB`zReW)Qf=gn2jF}4~Di(uH84DVh+J8YapEZT)RzF8P-;g&%-`kF8QU=ZX4V9ecHu$W#gKOJ|^DM4Xrs8Wta!s*VpNB>au+=$k>bv@HFLeQ%nSDabp zfz3+&&T?(TwlmQfMlL6SldKiKPC;JcWyaCtu;#V{6ONq9Y(#0jdzA+(EA^=|@gqNi zJ_+#%m5-;go?5K2%Ai)l4YaJGJe;z7V65W#&1~TpKAe54RkXtL!)3@e8jiX9SQeH; zYL%h5B*%uUMFuJ}mw9Bkdiz!tbz_8V?e2T+zIBzx|9|e@1U$~Gycf5Y`DW4Pl!lN} zzz{-W5`T*0IEtb;%4jr_CR#?;NRbsMQM6fBY-wbT6x#_Vov>3%ftKC^p3P9&LR(79 zR-g-%oi6N!77DZldMUjvUFhv?OYiUZzUO?)NVY?7d7l6C_fr~sX3l%I_q_YU^9y*B zx7IuzOiXizj(DsW8J#OYgNM)e@o5~44CtDPY1VlL`kd{%8~Hc>Bepk!N4M=hjDf*K z1qm=H<-v>EjF>?&(YiSfYOzKZ(9VD#J^L9z8rs zsCvWOMQCKm`C8|g;W-CHP5qV|;fH>vv`1fH21G5P-qFaNI*lPu)K0B8lK7~+gVLt2 zd7=0P0yGvy|L@%O`du9_?f8-Q-)hgceWmTe)_-U%w0y7SJuQQY?0#8I3uAH}Y+aF`()pMH3r0N)bR{myse!pjgDyzpT&@fT;LmD=>7$jcNA7}hiz&PzBE((9191C(Pv zGm42WGW^F#&3Y08rDmMqOys3H7)swHt~qpqymM4Y1is|Y1fR2|t_rBH)C53>BQH@v z^n0)zvYsc{e1H1Ll<2^8evnn^Hx`@3tL+{rH39(-MqaEy?At+8%rVnyz@p9y(BESH zb)^OfmwO{GsvE^Qz28fDlG{tWaPNbW7wRvC^8s*<<=cVkxs z#o#ePwig5khnu$Oc<;VMc*QsblmbZ~5010psz#@jd98k8WZu+y#EcGSB1Ii%kjoC- z5y32k0FsTKe;%-7A@UOn#k^_6N@kHvJu$1{vi6j8t341Q@CMo5S%SeeVqe2(VcUNc zDBl}-% z=NN0nvZJhkzP1S7-gW+A9BOyukuVIzY~>)Yh35t@EMUADdEoq(todwsB+_H1>c$~= zYs-%6I*)drnD0z@ltGU0eCE8&e6#1#>T~q5$Y~vk6-xU*qa~4WndE~yWof~)w;G8V zqN&kH4Rg0a7)Q@8-OC`>`r&`=y4T_+9#8ZWh4#-PJU2zyAN z61aNhAcj!R7De>Y^C-J>sF;pyDfH2)$tl=pDczVfgwd_dEtn zuLi1X+7ON6sq=Z*9bT|EQc$QUADbS_rRy>Y2#X7+UsiJwQ~{#Z1j4w6foqHnOzVix zT+#f-P>#E;M9VruDrRDH_Ctw+7268B4I6Kbol#B%^GFO;(70}YKx)ecNlQW=-s;?$ zl~oiY+Ijx_&!bci+J;0nbkAUV^=>$9SkVRg7H#O*y&5pdjIEUI%j_Yuq&s+i6=K+l z$SDO6sdU)daCne3q6Dlg*qAZ2;53PBTWe(8eBm&&qPgk*Q;~IrB$e`vHHeU;pc%0k zMcY}aUYvy&1vYm61Z-1Vk-WF-K&Ytiq=h)g081hsLUTmpTv?O&Q6V}sJRu+uRmNZl zdWaoFuZpZGM7UW~6X;igT7jvF8L2|$MWUl-0)mhW`;5yHTMgnrumI;vpEa)DYX^dp zk+ZkIL^uix=o~m4S=ITx*h#pFyxT;T&jr&JIT%`oC2(N7I8_SK1K{=D<3n{%+3jhygKU&_tc$uBuEt~lgq z;vAP*N}U*S;ymi<94=lFdB{u;r^NAaKvlX4q_cn-hifDRt5!flx zQ?6Uh926p;^&{s5nhK5|TlTF8`rgE(VTl9rl7+rue@5TWWN~lgxK8e22?cx(@|n+Z)mtJhV|I*8uYDsk(d!RF!a@TaW|9?!u@6soYIubC=Jfu1^m%mt~zXXuFk9 z_*O4!E~C*^I>>l0PPAd;;G)WJTp6fBm4UD!S455J zXcfM;3^}DfCCE!z-a0RJdU_&@I;-Ld<$xb9im?9w{#`HI)$!4eGaWa!f2IBB+cWKr zr~`0s+mE$=q4jmGxz?*&Uf*(W%d->TPOKzuh<`i&v+>(ve;j)-`cKhHbkzB-^G;{o zxi#{~k>^G3inKJp5g7r0-}G41P~+b=zNK*qaRGe|G2{ch>@p^RJ4>*Db>$pmTa(6B z2zAI!!Sy@Vj}*^MT##Bb3tOOM&_fn)gz<&Q&gehrkaq&WsAEiM7QldJh7ACEhej5MOEf4we$?@7Td)sv=`a?v zN3vM~F@IWAepCq5sf}HqqC}X?ifabe87(YGbQ1T-9xX+-0~qiJD#b>Yfic}IkuXwZ zU$(-rsX#^xIAXQdP*g#T2H@y83~bLmTtaE<^a*FT!Tup+)v?JF|AX>oV@Qt6)wRhr ziGf&y)teqd?M?O5!pm~P?JL1db!f`zP?(n65Rz)NJR6TYK~#fOfRkE+n(W&U?7deoM{JDbmpxVxcbs(`Q7WROp2c@NZL7~4=w&QT-lITrGox&*CJfE1E+~3SAj8eKKv@*zlC93-og|f+!dV!wAW1`-MjJMFsf6;< zX)x?}ho@7kL&(q>92f{qIfkZ0Y|Mb$)7)>G_Jw6)UpAQ9y}5+)(FYGj-lfy{MZ$8K zd!ezKw*^X$Jg~WqO2{1<9FDv_d|oj3 zsmU&^GegBt108bMsTdmNxw~{Dl=Wof*A<8;>8MpWD$|R#G6|n9)N~|zt%~1`OHljT zOz8%)_ekVzI#>g0SO!BIosbl*&&dlCodOs_5eKPuuw|*bgO7ZCrIc=2P_~2$$_GzJ zeoaA-BW^<8mE@v>=KEC&G{!J6woa-ukJp_jp{{bz>Bz4tMCR|HVhLEwq^hO=C7>%M zWI&{gS4V!uUnkrjGf3DPg_fcXRC6KFMs7ja1d?N*pg@qKCG+wdI9WpC!!YK0tIh>? z7LVnJHQlk2WIyLzK!P1pdYYpNiPSa1U znu}buu?AW9G)nM!yvxm%kf|`Z8u_I<*iciLQ9LmVrC~6ggBA&toJTntC^K?|S;0VQ%Qy^;C{iqM&&mQyLEPt;o=HxZiTr|{e{6QNKO^=^Lz2vCi6;l1 zQU+u~6UNR=NTFGw4F(dj;@Km?U!asoy&guy9Yg6XR95QGATLmaE=YLDf#^v_-V{Dn zHQYiIvNlO8&3OJcSks>Y@ue&B#_-6&X?x9fC_Z^EseyEXJXAs=Lw7cE!R{A&CXKUZ zv!pW?2|N!_&^r6P5^@;Qh|a4ifFYQLbFf9Cw0nOB4d}*`v=}DE!cOBS>6C#eVGmEl zREyKYE0&ukSJ5IfaJ7Q5b(PQv86>`{vm@Izjou>mx;4)nC`iTB-Zb<&JbFSz%XkP9%i8hL|`XM?7R?2HL~V3CEOQE8&)U)`YQUEa z8QUeqcn^k3$PDP6jl5ogkMxQCKRX2lIEj+Z*>OB+uqn^oO>ZAge=*XDN(NvGz86EOuBW2O6O_8xZT!Z6TsXOgMe+mP6xotoS% zDjO2(*RdBo#-|3edBqIB2^*d8N=2N0W!$OovvL?C=bI|_ws{1q{LVmV{_0qPAiDFM=G0gIO; zMdGB6#m|Fi$U7Czt<82}8#6WBtZOx}3io&k`7sBId!1Q5NC-xLziKY|qHoOc$u}p!f4Lc?Q#v4vKfW?*4{T_(W%Qi*#7Tq%? zB$;H22ON{&V)4wI2qOChuVVUqN8rJP!H^53R&i zxrGwyK_4zY)A6!glvE%?b8rfZclepZ7X#ICi#nFYqtG#2>e=Jbz!xm%f==8e6+f!B?a>T;iWGvlSUY=0x(BPlU{G0N<9%trlXkUf-^K2)4_ zOhS#lhpCKR7oIFm&xBs8gFs%V+{PuJv$*Ia|BBjXJyzgRv1qjanu|A-kQFod_){Io zWWhtS=osX+q4TlV5W;fHzpQzm)a}26^_a=r;%W)WHQ5(j<-n1#({k&X?Gs;eJ!0Ga zUF=4GxV+Ze@a_`Qbq0$|j>#snxMG!F6g3@#^(_e!3!Dj~FbIaPFpwL<27^E?PWIAaP1*;xHk$X-P4)-fRr>Hcve6JWFKs-X?)odkOZDfWR=NUc|edG0roCc~Jj9ByB&rgan*aamz6oJa&6(be)Cr z4x2TOM`#^FjQy={?vPVxr)oJI|-7Hb1f*5C*vLkh~25d7$W?`4SofBmi( z@9KDR`>Wet(fThf?`*j{@tMR_{9od4kIx|P|C7=0N1x(+-g&WecjVt9?}(g+*8fk< zztjA9bAQwKn%>+rkKTV@XnaHCN@I7!e>VJf!)(KzU4H<8KhU348FA!;qt5#$##6I7 z71!gZHOrYTIDH?j{j1MD$8avlZ_u(pERSw?XAzFy~@`g{8ZG6PENtjQkxvq{9al@Vm#op#<4 z9x*zIJ2my(VQ7c!syZic)DG<~A;kQ^sPmh4adhs%y+!uT`S5W74@k>scofOh9W5cu zJiXxjh8^o2Ngx>kPWkO;qB^9+Y6TvDvV`#So+;<;3eO4?mspP#B!X)~@cH1J^Xm#j zR5%OB4`AocL=Bum0Yxmv7fI^ZG+aXP`JrX!ZQ(VAL799z0%Ky##i8|-7>z#c{F*}3 z)IQ%A%VmXNg%cjSONc`6$~eEOqwU-GoZ$gyw2H9RAml(X{;*K5g)ZS4}6v#*30^TA=~E#c9Di6>C&hd{ik zL5`WY9RPBBiQ(oc=a<7k*e49`T^>0Bz!^ZXP_8pDxW9y`^WJIam%@YjFY|gi82{Xk zqro+dln{cRT5x_*!I+`-Q5=^5#CPM1eBGrDxyLt$S7oRIS7c}baLH%Ps3^7~WRYG`pI^(=4ycBb~0eI$s?ZN_QT%0c<8a(rY zsI#fO*AvuCR97xJknYPOa}bkX+~Na>T%m840_yI`%^h3XGn!w7$~Xy0dQNJz+g^~& zt5%yG?}~$iBWUQd7D%X{dva=*n1J7ix&(NIhKp!d0h_gpkEQxO3T+}`bUB|#7{3TX z#Y_qD-!qS=oq`e6#jcGCV&bDu_Je^=W?*6@Vo~JSzEe+s0Lx@cH!-;qYhh4O@{CaK zMR43rlzwIjI57o6GfIN!qA;gcX+36SAhAM-P9z3Hn_lP1D^_Xp?Ik#VwerH&g;;ag zx=bj$B_!jrr6Z$KFBku@23`i6hMxlh%ro~pCRAOAiKYc752K8<8N}2&1~LE_)ou_` zNUFjJA{$_Y61v)@HCOj23#7-^dVqJh}`8-Dx?aTSbzy_ z#M{4AH~}vv4XGx50+u&~myg0e>&3RKDayCJS+id@(C}pej&M{be?<1FVkO_6A~mC~ zVFZMK7%iMmQznA2CiO$4{)t}r@e<<7)5WVC6V|S0YSmUdXW)wJj_(JU>hU{Ej4FR& z$}utQI+sm=fq7JdpmZ*Tjl;q2i++K(bQvEMa8bkMHi1{b9BFz0Oah8-tqa&iQx_4R zh{b$u*-H&Kzc4>A7z5kANid=_AmpJk@V9HQ7n#`Dir^3sL!?JELn^Kp*%`ilq-Rf~}IQi%?ZC8`qS;j^*5&%xgUD$a6JIn8lm!2)f0tyw?r zp3E`fK&O$6K(b=ciHymr_yBL;iAhb<>FWBE`!ZHwA8xUsguwn}an$ir2viwlpdLc1 zAjpq-AtbnU#@g(Y=I~xjCaFOIX^KKVx09D#|F96(#U*6*AP1gzNhl0AMJ6HJa2Jo2 zkOa{6f@eA=yTGu&Sz~>&CcqF5gA5w-O6qHcc<;I4S@bJ$ccKr`E0_otE>?YE?##Hd3>1jHxi#;OmG1!a zoOS+D!6D1bR4-%tAstgDV^nAX1`r)!6kwhz9t?Xgk)UF*k%VEmK+JvbDd!(NfNICe z&00SlL0KtP#b?c$)Rlpb5Sr;j1yy6=xI0*8%>AtMT@R*B`sq)OQo18ZVjB~Bj6`mO z+$}W_u!7yM&|T{X>-#ikrcCEvt$S{b% z8!02izw@;7H=GhRPRD22kZJ&}%#wSKp??m$itIB@e?dU-5rR{Z(Y3*3C8()9Mt?ED z_FG^WKI?qj1BdoH7lDVaIF|=FTSh#8XYr}d|MVdCXYQGWmp8k8fnaEQh1(Ve_9>wb zlqpOdUC3yUpuvkfR7NEKffLSO>jbu)tVrTXL=Y@W7g-We_4j$ZH{rN}-H(*nIpVbQ zEd|9zLK(ORE$E1W{tp9{f`D2iAGAwtTUl@UCiruvoo^~QFFnpKP3R8U@Aie62Xds0 z2>;|c=Nk$E2xZ@O@*X%^X_AC$u`Okf9LYl};EyOQ;j%q$s*I@qgR{X8KJn0zGjG8ITEvRv*yNnqA zWUuqJ;2>*j^9!x%NXz6^7tj3F<9IV}hG1bTvi_6gaB{-LLiCZvcMKw37sE7RHR9xPvn9VeZySP)8WG_y8r zn6<@?Q0>3q9x6Wv3(q)TwhPxgqqKtpDzyBRz@^@*P!!fc0Ao8Akx@5 z?v9tP=jA74QC^p{y*tYYcJIkLe`=RJiAGj~u-dZ=3U&-+_72PlxrW|x#~^q2makzt zaf|b%^!Oy`9nU&s$i#6OGq&v6TIGTd!sAc&OPDU!L3%(-5%b=acfP2w#ljB%kOXkx zV6ZVGNqYm09EZWQ`Ux@hvh&KLA_thUcG z3-{V5!GWeEl&Y_?Cht8+eQY;bMhtsu)cL%Wfa`+Ek>Nr zC@5ptgY-o#kXjT3WLc+YsWKu1e1g#Fw>E88G3xSxdTnmHj5zk>wDW0&4iz9pA+%on zgv@OUPnm3B>@_5Prpt(A@44Uklm~|nmM~4gS34MM!-n#k%Lr-*Is0RUW2~9MglA*U z!~*ErV%-_ALPW9m&N_djgOCg&5^7G|Vkk;KB4)Ae`OGYM3WBVVB>4#_gn;%#Ip+@* zR1g=D6>2;(b?0fL((L8mUPj#dp|tY{3Zs8&991?LK4;D6yfE)AVR~@)Ed-~rVK~Gz z6twRuHaVX(D}b3?E*eIA6vP6hsAnw%VA+8XN~lGkmp}j<6(bVo#JKMEml3=^m~}pG zx8}w33IQ|04_uq_8x#9b&-!jJBWN8~{f{Xa`@Bg5FAl=`GWyF1RzI-dd{hSmfephl z6!a2k9H6f5tz`tM9~g8#5?(_en<8=pa~m5-HkxMxLmUoSiAHd^&n+V&z4L(c;qbu8 zqi`%-huyw%8?GSdd_Y0t(H@zZwWTuQ|3kZSG1m|c@bdQzO-_#U<(&}$ z#MG|rF1JF28Fqfp12UOSp&pu*(l{T+m>z->z-L8B_s(()UTMzxT^%dx;DAIV&-TN^ zgef`NggnyfVDocL)S~;Gasu~ogY!Gv0E7o)t8uIn75Vjtlmsa+XeJhZ>+?PQ0C$aM zRxkyKMTYPCI8&HK|KGRkRl7Pq(DCw)Yui8Cex~i4ZR@SyYyCj$W@}T+M_NuI{{J(H zpH2+NzaRhY`18>T;9q0!j;*5);LDtEI{lG%M_`Iq~ZGw zA8a_$(7x-V0R02~xup!V`GHjQS$0#@s9`Q=v?up(v$GTvz-%QW9}k#T@rCF!br?!D z%#IHanhW!#VPkULXCf&V>cniw5-X%I@hC3|vIKFMJvB|5M^asJHu6~Q_Y!bnPt`L+ z(qAfa3I%OauSIvV46FEoVng&9{@(aE!7A>}1Rr|sZE#C`H}%2s7-N3AKp#?fc^O+D zjXvE%g?$~l%R;z75>X~@ZDC~{Duork0>0_#@-ZsD(WmLy;4`LV5a8;*=wC0r)uI7-^r;HVvUw(G ztCY#Zv*gj3GPW~&Sa>$^J8lFuf>@SA-Li}{?kq3hDRo7E%&eC0D1>(ST%>gm;qEBU zENr8 zy7OgZjSS+YJh^TzVRj*XXNS226`#l?NcP|)SJq7;0T7p)M0n5TCwZ`ZKPQPqf3$8A z2FqXU)clk1=(i_T0>wtm(P~(!!uioK1pXVfk_lo#kgdQeZ*p;P2f^-2xLM|A*IS7-Cmytp-T+Bs(L}8l3ag!5hy9rc;O&})$FXEq;Dy^_RK?A28B z??$GiU?hPsn>H4eOqe;Mf!AU@lQ76=VK%q;^fFQ+4i`^Huh7MeWwm^b*{Ckcbi&{+ z;SQIcm}0*nYTJG5T;^+c&lC+dr9 zi5xBFqr1Z^3^c@qiIHb_$z^)v{fDr`y=Al}Ir?~0)Kp2ahbVLyPpq1TGVfq$Fw_~@re&mr^iD_H^d78;oF2O;Gm#x*83rQA(%Qo- zsMs#)+;u1_OxNu#BQ>Nu7i|rLvH30XlsrBvo_;HdT5-3pJc&0s9Bm0hAn%0L#%6XC z5IHCf%7)Aa#o$Bb90E;J(S!oAgSVTDEQ~sX(H-RpsF>+!eCI`2cCC zS7nQ5GqTS*>7__i5 z7c2zg*77JMk4&_=4g}^7qlKhr1m=FAj9B}bQ_&_JXfM-rsJC}&e6lKy`p06g$X}1W zYTp4kT^??3%&tZobpmwwMVH@{mWkQU3LvAHT84^omtqIEm+ywsF&u4B$c8}Bg2q0= z+%}0MO1W7wN%7P+3tlUuiAAz_U38a@hL+-2A4BW}t&X&sZ=#sWIv4|n+75tB%E_GF%i{0I2G_mMjasD$PZNZ}i92uk@kGUvrkuUh&s(>w$ zQDK-5zBCHV&E-J|V!h7yb@58Xsc@OL>)|Dt@}sBA17uixo&N}oLX;DF^h&^bZYVQu z#Z{i3(ot=*0v36EWgWu37J?E948==NFrtbkBy#Lc#d2vqXh^Y{xll%|e7d;L`S&h3RLUvAx=$J^gYph^h)Osorj!w0SS@>o);@hd;MgU>4ms8vV4MDU(Kg^6nE>pP*Vkb4LYsP%zC; zg)d_~a|DH=X_?pP+x3+*THUTL^tRYgc?x14iwC2xQUG358h8wyX=9+t$S}&y_Gy(9 z6KV$8*sIWMj7Q^?4EE&K^XMx95flcOd98t>(PE}yxCHQ-FeMX_=@v&SS4A499?wR9 zS{Ffe8^RBbp={1E0J=R*EmTcMBjKL%L^d1S$!Ji{43aBFtN31_e@ZOMCiD;D3e4P~ zOIw>kOZPD_m(ws#n2;q;Ot25xJP`2{0tV%39{?z#n$PThPF0@FGrcnUO5KjUjDGYN z0X8a0mKs=IcMa~q)_yariH)q6X(%z&RvKHApsEJ!8C1NInM)OzgLB2E=uep=#Bs^I z7n^W1&l-^R^GGVhrRG_ypj&AUdwYe>1OLyZ=ef+rE<5391!m-~Q_-K)`K*68z|E;^ zYTSm$#;v9ZvL=>)AS7rQ&KAnz(2^Sf0=O&~L_(P-II^Lcso#UWls>Ku5zRTOLxzS=!-1Ctkjz0 znOzE?c)UYrr{Er_v{Eo>ioQ_ciNNhSuLIs^-?l}5f{10qF4YCCqym%%Wfztfm@Bxb z-U;`?N((a|S*O&1CACqr6?)a$8Qb$~#Rp(WuILB-`*HRHaof?T)Gh3I3tMA#p5 z2&m@5V0}bK2IHv$755!ro@{2Rc3%a_ZTps@&*ym^nH|rdf+I?BOtST|_{v3d4#Qw~ zSFQs?r2VFQq=L37sYj#d0zeR{n##bnHwJiAvl2E}YZn`}cB+czT8a)H$-HNHE)Rj3V ziX;Bpw7QuFzjT$6H@7zzJslXG)u5^0%N6o zjzau1qg#s9R*h9LjE;9+yBDU3U^Qd(1BM!&i#Q@9fzbsYHl9*K0@8_q>#z0raKknd)4Y(NaEDQl-C&Ys4Oj#zAongc6|GNtF=i~N@7k$Q z@_nrF*Rpz?n-!}2%FMz$8nxLkX1t1U^4$Dev%@`+Ohh%jv|JhKcwOhB>*oGU(dg+U zg6TE!awi}*8O&d35cRgUTg%AUgIUQ-Y0&^0rYVLOAgwt9bKhP@w%)ktWj$Y@v=!ro5k!JXEq!%cm(MqBaiqftuF2tT~#&5EWG(A}9 z9@6D#13nE9^KqWQRoXJm7{ZUer+f+&bufB8VH}y&bUoo7CO&=&@%K{x1UHD^2z9r? z>h4r|9X#-{=ylsh5G9IA3&r&KYuAA|Ht4BR}5!wdP-K&NlyO(<4ncHGZ@4 z*BciapVaWxhV=#q6a3(Rj#tnJxT|<=Y=KooW>d$O$5|Z|BH{p}SHiE(D;ydYN;Q?v zuu9PDKnaR~N6THVzyx{_Q_b6{Qn=flXX33(*O&j&OeZTSZ?eC5Aoifl)W5YphJvRP zOY`~sCU->WEZC;rdP@@hWT#D12bdmVa72v^Tp~(0A?uQyZbN{GaAu*n`zx@Hb|z!9 zGF#u=Vj4BrHaR6H(<1Nnly0;#09Jl3_JE8rD3u(~aD;ET!UudiYY^D|w{EbF+888I z<9xfjlBT&gcE4T2BqQ??j*^o5AXxpSg=g;xFI}WA^K7WgbG&JhGN3+Byt!hzXNRdwhAnfo!QtCS=X3in;tQ;SI|A2!6f== z{XrkC^fJb!BbJk~BXeuWtjesd*bCAS7aJ_KN0OdF<)tJTJV6XevMaM#pjLHiMea=% zDxLsna}4~%bj=5-DGS)s#IvxpgmAr0%xOb4u?4m?074?q z=bE#zL4i1ypUCG|xi&5fs{@|+qOl1}B^du9+h_&%_DXkitc&a{WOC?_d}Kl^-RD+r#X%p4r33;`7|+z>8z^F; zX=3zfopldYkTKJBIMydW&dJGzU$uVb-L)lr<|%Jh&=6y$_|(`TEEfupF(SkDpf#R7 z>AycckenJ3HO4+5pt&(C`<}I6N+}SBFJf`&*c?+DA;w8z^0|`*ly0pclP2@{Rk1rR zJulDfiO%Oc^N6t^U1Ix%N&>YUhh=CoTicnQeYUG5Xb}+$tPz6L3T)B9&|p>jt_qTJ zy3(;8Ib>WWPT0qjz_psgH3tLSN>}!SA+5%4my!DHvv_2ap=vmmR)@F|`6P*=@Q!5V zCUAl2Shv6#%NxoDYMEzK1GYUA#_HkW9u)51K;$cSWJ1&2`AR2ycI=Jarno}vA6;6# z1n-fQU<=uV@~BaVaWC?EQ0N}!797^nGEJKxz%I~#G}a|^81z>ZG9__Rafy$v$F ztFjM6?~mQ8dtBNK<8k0T0wR@cNV5?oX3k8ROloxY2$f+#f***Q8lIxE!PBTwPjU%!o6lBxINl6yvT_}s zU%f`NjmTnlStTN<+e7PSI%e%i*zJj$3&0@Im!ekX{6<&!6d7`@GE2U+TaE z_cl~PYEfrC`ln$asZnBN;7#kPLLRhOWJ=fvKuuPVVU#`<{k(!op_BJGahy2drDPDQ zFTSve_d1a~Bw_G?JVxLitsv!S@LcqB=7_u+yqAFMy%3c@F9ChB^5e4T&nk4-gOZ*n z<|2z;Md<;t^Irn&LglG6Azl&vO!!<)b7AR#!J{}WCFCLcqw$59Fti8uChC(QEC<@5 zZ{XO$hE4tdAp8Hlx8tQ96CJzTKiytxf2jQcVgP=&?dI0+w!WuzsO9S|kF?yJ_~*oh z#6sfP@$Vq}KO1k0eLnURv7zXqY1sk7-Ia5qr2ew<&HUOuu)VB5 z$ZufPhjF?4RP2`om;mU{(}165*CeVAAk?@QO9pK7O&hdB0&N1jwR(GBh4tE|V!!AE zRB<4<&x@=NqMIJl$;u-%a&*StEKqXLOcv*mB(@|A+_pnYDLne2kpkAV0K9|S2EZ|` zF{^{~z}`I8pG3c*H2gwmX}*cX-V|8$!p6$_CR8@j*2AhAltD5p1~|)ehBmmhCW_&v zfA})q9j(C5e6SFEqYrs3Pp!;q8|IR5#8!)hSm5{0&|n;qZ&^PZ$_p&ahn8a(e0X}i zDOf0=1#Kc_fhJX&;{d4cp!Fxdh`7H3V>4_nH6L1GTyoWoz^MRm{lJ2C`2sFySeLuc z#ws#KD-BHM`${+z?SzAc&J_R@mS+Gh?+BEAz-1*r z7|^i_EYiU3QV3{raWTBowH+1;#de2Pj#Xfg2Eg+>0`yk-!~xz`fpvP{;n*7lAZ%Xa zMpfa4J+;L*82SVf$}~*V`|`2Z+o41%5*-c|d=UzS_Zgr^J3{KKz!<%6DfT*nglCFJ zhG&vpBcz}dj@j41to&DGB5RPd0lb6_`d~ix^8zHP(U3kM46TD?3CfPpvK82(drrk( zBhZN8uuWlQAOvC$O5$>)t);RFs*I;SjWgBcQWM5gzwcCB=J%8HVy?LaIDdJblg|EH zZp_I2b^+R{03-@syL*Zav7ZheNow;XPDSWHH{pvK@>a=W**M9nn@USO&T3|LyDBTV zy202hgOG=*tSR<01fhH=)aj1{QekwQ;3rcNn)SZI$OVVGcC(M8x zY?bXTt;R#`cgcOAf}&_W#kSZh1S%dyPVWZGS?0^-k^m%NAJ;epz!k@{SQ>S&_Fy3& zOGPjquzRqAOtJ&%*iQymjg#y{ecj-8Eh+$aS$Y?{MV=UF)XVF}O~Sbeb5(Gtc_}aw z!TzphLJdN*Fprsr5?IWlEaqi(o3$IYJ5bc{YHf7_6F<3qE z?j4l}zz?TmXJk0>A4lq$;>4L8U>4?c{V`l2+fTi<3;72z0u!58ng5a8rt-^$!diSK3#dPH;1l8r(mYxQKKgaSg0l|Qi zgtnuxpvIs>BdumRZcB1>7b{4bI#_&0Y*PT;ou4;*0zIbP9|z%U2Yw2eDJ+49Zk#Q; zxrg#7Go>%zh9Bz7U#uYWX@BvWSV5*ayrM3`|I#GJY`W7ls}*D~bwRk?&@+XX;s0ej zY=j33q6F0MxUE|&$Uy2!#ZLLRARe6&$&V9UHdkQ~$_SJ0ofRY??VpLQ%Rt3OSO7^< zII0d+ES2|(jyqeK;(=Zr%h&HTyDqmTAi&~+doZt5-giAcwQt@dU-wqfw&ps_u;$Nz zO7<58jvcPB(tRM@g$73CYFN-7A{9X6kg{~cTx`{Ytv&-A^0mY2Aw`4ygUe{7;4Kv- zE$tnRofHVb+Z_O)uikv!u$wA}n;Wmq#7@Yt!#fOugCsoD{>nIp496bQA)fYRZb{M6 z$~^Kq3!pa0Lb~B-Y{lDO-LSfwsT*!aT6TO0nq;ny4Pf%gBlA3O-4Zp1y+n@MIGVt+5YCPSB_+CWuS*qTQX zDhcZn3w;|ES~MZiwAR2Gd{>wT8R2I-&>gPQ$8a|GcLG;^43;Z~v?>)HE%7yuN0M5G zkmF>9V@_Am*?WI69{XRq%=~~(WCaj!UReIM#jUQ>7h|o~ZYMGh1ou$26Zkn3`&$DT zdIf?iEnF+maIc0vkO67TrSySIRq0w-hT3fw|w4XP3$gg1l(@y{F>2^|V%1h42d%JVU1v3euUekS&9fd<(W`UA6E zg5YS4kg!LlnsIwJ6ULpZ!bi{vKKegpxN6#Zfja^4{ab*rvc5tu1oxNeI={gn&@lD!O%d0&l+| zK#YHy0L0&Ieb1)Q5q&ufm=E7MULViX6zQVl8ZNxPDm(=H=VE^)aE&Hw2{Vwyo{@R3 zCht#4I^{^wjK-^Q5Oh8k`%49~xMtb8le_kx(dHQ_iXH|7JxbROTKm-k=>m@!PPxh-NTTM>DZs^zVbf+ zUg_Bb8~k40YMN4~D2~X~hqjZ-jn^MVZxs%P12eHdkOlOMBQaBuxCFgZWB^E8@G8v}QM$6O z`|bDX&QwvItP`Oy9~T%o#FkGOH;zoZu_OT&AU{-KBy1BKfX*vc=N{HPl3;XGlbqN~ zDU!8I+=r_04RpZ^{V_cf17K<$Hban9$a1D!ymCH}Q&1I9U9l|*AUn6+3;3mSifz_% zupA`n9n8f(DsvgB9@EI0iHqBYaIL116BavGMZO*kd>@hVo-r<;Cz)Rp72mVUfuwBm zEsL!U|D~KlN>5iYv}1{PbBhP6$l&XGyeIbIdXPCf?71cnq95;NBjz_aRuItk9WdHhEI15(tJK-tZ+H;VA>LBE)Ik=6;b?xg2PpmOzS=o`+$HjSOME)er*WR6v8g-C6ZlJ6Gpfa zZxO~xzHlk%$}46V`&1PvZ$0N?zZZly?FVmgO_v5|N;m>wkSTUme*~l>6Z>6(o78*( zZ=V*?Y#u>yf45h!0B0DE{Z4S?6k-ZsU^EOz7G%c~mi-pwV>hNf8vAV-JO#@P=tpKv zyjtE?Jj|S5qA2b?PBAUx)pdXZ9gV%;15rQT(o7xBx1w)H$KP9Rk2Ky;yfXGa0U-0I z=3sjjBnzJ90zVbI;if%hvnjN;u%xK~3PK52ehjwR270;`d#}LGtuM*WjQ;B>n}TvJe#~IbGD)Mj;&wZ4@ z!8nk27Gl5YLxVQL@FKSONZ`;pGk4hAVb`3DaHrPqIqq$<8l7xbfhn z(Bw$ym&kP*BM-^NW0`n$R)RZNg&SqxaC}~1B&GNv`0QFi{~8e9tX3d52xW8`Z{%ov zPR3;so6NUmeD-`JAa83@`-YLe@;-by(7mmC46`1NYjnTmiU@h(lYmPP3ey~dC=uSj zwTjBiq>y&OQ&kjF++U2ukI2j--UhExMOhz#ZQ{R~U3qJWf+=zwuEH78eL6lZV8!>I zJ_FTvZF!LO_Yt|c%@2rN6G$2<0wmw_*}q*POv($ zwU*m>_#*HiD%p~M0BVROMu1K*n9;qn3dc$3(fDD3sGwAp=gIj$l-?u8no6c+6?dqv z?ATFkh-U>tzYQ_W34D=9%*&^lG-#V;2!J}{ai4x@qAsl9-du&(=RD9G9$_X73!YF?O&TbwLj<}-=FUh`{_=t?qpJxgt;MvkF zj`77p22w&erljfKRE3x1Ku>&FhJ!;9Yw=u|&4hnxv8HSHb4DYX!(c!!$o=uVLqkNw zR<(+Pns@<8xm9vx&aT$Iq3^cfKDP>I$i9Q|jD?ZKWwN6{-JD_-TdBh1aiDlZd{BN3 z0}7$%(6p#4+G4x_4J+ zu(^DEAUGAd6Xw|oMFA9osh@pdVasgyR^i-$h!Rf+p_#bc)T;73)AR>x+46dQU{$O* zjMWqWiFnduM))djLV({_o#v@r5$_KIPoX#3+7=uNOSV>mxpx!oVVyia?GXXcs&kfQ z6x{AA{T=@F31vqU5;Gz6Ck;9}2AmwIx36F9Lq~mbBFF1ApM+NDnZ-o{x z?!XX3vp$tkD8>x;K@LWdwF5`v8o6y`o;2K{5N|lU$-00IMIwPg42_7eg4PVu78UD< zzv8-?_(53%q{B@r?kTVGz#=lq*|JEFS@d{FQ7dZ*oN{li!c);X9KS`z;^~4+Y3`QM zwD_FtNAeg=E#!eJd=&?l<2TDdq$SK8%?aKl5!KR&r7E>K-7V z)Mc{dmPAcVChkBLz76c^Ic71CYWmKa>NT>Ki^8^QQ|#( zy6i);+v%#p!O=Mye|BI@PWoHQ)V2$X4irSNBYUfGbnHJGf0m3q%+!q_UsNv;xuF-S zR_|Qtt)e{I4Ri5l3WPCQuy~jOroINNnTF!yKDM14Ur`1^S|{`AmT%pcgkIWLjY2n(nlPhjp)YR{%RUqoQ*%#jxyMqT~DFRFt-TcrWuRBI^WZxTX5H_ zs5Ev%F&V!?;DCi4Q&XM18=kS31Q^4!F_->gIry~Y+jkx5j-V?*J*Jz8-O4ybP8_nUqDoTi@AV72o zm_AJsoMd=}rs;Arf(zvbssw1U*T@XUsEH*qI}d$z(A@2K71@4=iqD9*+w(}Sn>U}-+AgJ>JRuXrHdCR35@ZY>-l}u0uJhv1 z$EUugb12o%n~)_1^BXixl9Rw@dM8(YMZ86zQBI{!i|*(bgQ!*0RZzX;Cfv#DA@bRV zctT)vnVH1^At7oR{8;mad=*u-;}#cUF-HcyKE2$gnXa{)8M5 z_^}~y7ES7jtc^zmIw``%Q4|1q_E11k`>|YgvO@8Dd!lGjTS+`2n`K=mgR^#4SMK<9LJ+Xfg zP}8Wnx-`Jtz2u(L{5zfo6Zx#5>vmOd!OX+4@0oLvAUnNwSv`&(yr<(_$Da1TZGThyiT0~e z0pL{I?$&p=KGgc-EuU_Aaf_SycH*^(L-8-i&&IEg{bp<=`j63{i$2Zytn-M|j>>=e z$c@nY-_X1W&;MghLrw9<-)KDCctyj<8;T7#qXyvHFRk$Z0N>tOgEs+q{yEvSIJ5Bj zC)Q8)A%h;IR6H_N8PrXxj$mfjTTSy&4INPqOvOJd08-EybUbudsIiwHKT?Akzk4MeDMtd!|a#e-G6WPRdY+p{gCMNy(r#*0H5!jL}N#QN%$}YaG zbPXo`?%DXK1dccO*1^Es<+yqp?Lbi7zLk6dWBIoXPQ&Ba zI3NLXyZTT~$|~?fLaa^Uz3azPeTBUuBd7sn&!`3#?CFDD`^28>bEAFu8a!`tYjquR zz}!4UF*jFh$1Wa=tIHDBVSQHGWgK2bYRGD}@?~vfBqmbqli5L|;3Lr#cH!!`)Zi_^ z*{HJ;>Vmuz`q^?@lB>>NLBL=mLQp$vpSZo&N)Jq2{f>%zL`EN>1D+m(zC>@X#64Vt z;s3z7xH=uFq5um`d@$)E^m_?j)>-*7cnAnk2~@5zc<9CD-Bp7ppnEF*VZl6TzsqAx z%TJ#{W(Wd6w}V}itbM7ZrU9YuPz`>7{i|{H0qU|QmO!^u!Va%0c;#j-iasdevVdbGhU29p_K4`R9WVh3YW|U-6XZV(EXuvNhP=5>5Yaa)k=r=ikLwvhy_S;3og+^BGp>Z^olKi?y12=frEdez#hvdPh$0mwOvw55!Q<5?3adp zG6-QAY8o=w7FF=U0jk>LF4h{j>TBZ{bk$njf{$H{J^CwazZ3>3PlKhxFI|B^^NMPtL z!Z1KQu@SFEjlC)Nfhy|hkritK*jPRXHPAmN9+SU&gb)KR3U-=!bx&K-Cx#Njdo=yS z9|Eua^VDUb$zVExIU>CTbs9fW(B_~JABXCBh>weFPMC#DM}dOX(k4%E!3H~%RaDCB znu%*}m-Q%(uAsRcQj(J3@1~#y+=80Z@2S1CF|v{}HjJFcP8fnUt&2%2bTlM4`%@yT z>r|`&AY9ha7C({)Z${K3T;m@2F6|H9p(+v@yO-jc=mimSOkLnp$sC{0jxO+^7c$_L z9jczj>t2Ze4}INBo3P^N2`@mgAXDstfgUm`7fkNJt&$9ee6z#VhXHCO{&NCK227&e z@d?Pw5KQurmTd+SjmI(%uu>&9nh%Jxn>L!qy}P;vwdi#GwF0d_g(Znm%7@~mZkfPI zVA{p%E8bJxj5O{ocEo>H*9L7TN!x|o!ZuA6++BiCj1Z0lX&8Y5rVg}4GZ7DXGX>u8 z)$yMZz=kK`9xfK#Abw<4iPvIAyxHx?3q*i+#$;C53pQW}eKh_Wfe#5_YOa7cX*ko) zmud|YIFRj3YO;Dt?HVr)t{AtKTUt87=Yoq-9mIRmJXmBQ2p{onwlGuWHxOqeo=Ld) z)`60R_~QaKxv;P~!Vm>(1y4%U0}$A}S&P>mHxQH(bh2i;TdR5Od^ldTJD;!txLoBN zN~lXzuZhV8AfxlbZoLNWel`9RGEk{Ol0Q%SdNEK9rZ7>+LB&-1+ zX(_k#C%&6_N8-W6ljFY=e_s4Kv2Vs+6YGusRrKehN286-dFOECJCQd;9*A7i{K@9I zrvGSqebXI{f7bY-#?FRMG^{l|dDmM3T>l)Z!HzwAD6y(bK2`vo+f0GcZ!Xio*`Rvu-zteC-f z3d!|^ps8oAQu<+Y3`U#$IID9VU#smi!wXQkN|=!a~`6haB+90 z2IF`);67yGf(j=8dtlGkQltYI!!UM8Lw^7tYG)EfY)>VYEmS>e16!XPilET! zKplhE=CRRbyq7hN1hFqq&2q3rzzlw{_@u-!3sy;oca7HKyT|SkBpel^jeI2zdJzO5 zo$?yRrx^IsJz7JtyWV0`LfUIXnx z0h>wzq0Z{!$KP-pp^IgVHsl#hhEwz}0~QV#(z}-u8dZWh3`*rU)2y`zTrv|`&_Ot% z8KCGLM0vYnJfYDgf#VC~XNs>DG{Bg`Y>3q*kSDN7sKcO^9jFC;BaD#i(O&v7185+cz3i5j+*kP(27~hik}iORXj}U&bJqU>XS z!mH}7A@8j_m$=J9^`44Rj8xiJlDi{`n5x}?v)W4Zh9QKOr9iig=l+SE*I@0rpj&f^ zJ1t!E4uHLNuQ-4nA&Ow03T|_6b7N*Xai|_r_z4^MmnO>==IyoXg{t0B57SU&3v9CJkvrUSwEAuu4qEz z!~hfjCzeGKO`jlW)@_5NBvC3p?E7kx0e3}0k@p+YjEG5i(T=MR@4x+S4hj_9Qf- z4O@WSS7nicF$`U7CaW<~y|%J!9jk>E!1w@-SdM)bR6GF_f0{7yxcawESdAr0u%PFO z0$U==!dcD2+;*%8Q&uFfrn6Ba+;X`{#egaL&{!U_ACm1DJpCtnhU4hporS=bV(&`8 z0~8wey?i|!-CWQa>jgz%w7dYd^->_QyXTnoUn~5@C*^+4N&MBo-us7w^U& zd`iau@7q<_)$zfOGaa|Ke-r-y!M49{dtTdfT0ha6Z+&*lM_Z1y9EA73l(;E=A$}zG zvDhi({eLl9jXo58lJm=m`j1CG9(fTm|No--T=P{;A8Hyw*8jnV?>GEv!_2OK0_gfb z&#%FDmn$A@`Ir_qOl2q1wjbGeGBunWOiRH>sbJ|F1H?MW$VSMIrZS6Zi+}?~G8t~p zWb%1xk5{fio5b2K3iGu>b7StYmXGTEb&X!_63~$pvKGZG-)yrpKu+x^o~lj+#s@oJ z`b5h|cAUht79{jKn1FQxseVur^RP{z&@8dVbdMUVodUaGZu#(zFsG9fW7-+%5+LDt z+FC;+(-pc6;I)R4ucxQwLt%hpw)YKOz6KUVTMF(fP!{90JRkK`%kS&J+?4jPLcLP< zi$$}n!&A2NtZ!fpSxx-N9^1!&p+gMnp)!0(S zj+Wn5n0{qgHpw)wcX%5fP|wyZjbeFu-s80X^a2!87%`_GZTX#@7XCyUE_>5aTDRsO zF*^J8qmI>(Omy_ImfsFef(p0Vk9zhAO#=e0r5nUtc#(;^YREV`kZF0pPLu-=LR&WU z;=|oT&qyvVq8JPaKXBYC`YVOP77!;{L(WmxOw0R1BjqXeXH&^N!f*QX3*(47hqAIG zj6*eK9wi4`-fLlGv*;cQdB&%udS56|rS1T`2z}ENwI$G&e9LbIjtOnBO!w=HVi8tj zi1AKnG*mCHND;BEYnr!Ix_b^u<3d@oM3X)_({07*0goQQV&A#Pjga zOZztXC%M=j-+ThKB(*#q?ECzT z&zMd}$VtfIfEk80+ZGZ(6`E~ytFTk1_$od&2|k*Z&A81o#--;D*O-}fI`MJ^g-EJA zjF7n#TjFek5GIMiuyRgIC1UVGuM6Tsu;*hzB5j#4>&Y4tmC~mYFB51yQf5Dxjp2|* zvr$a7{Udpnk|JTZx`U0Q*jl?U(wHqyCDaWjRzLWrg2o(1*^DD1?;_BBqb4T|n|2^_ zm<9|dkr}haus+CdIBGTKZgW^72nC5zz4s?xBHJ`>L@HaNxNvphRZ#0woyK2=I2GJt zqK34oL&b%}iv?D{F63?;?SxlPg6s1urfpl!b|b&IR%pMoeT2=~icL4au{?*S*kX7< zo;Ctppu}9Cohs~gAF838T(bC##EWDxImD5#_e*VKi1fx=D|lhy0xglJCcmHnZXLRe zUia~2Yt3MaqypIAyLZ=)fTHFTFZAaEhH&SMyaD9EBxIew5Viy24b`UQMZCZVW*iJV z1GH3r2T*S99??lMWAL}658pbdWG^H3f1YYtGSufPf*CjO#5nBp&f5fOC!N!oy2| zjixYSFyzw2jp84@_0H~@f_oY=6}XdZ;F!m-K}(Q=1zK{}!lv$sVHdphy31+9)AoB{bU z4w&FW;w{n950KaB9bLdaPDmdXqV2LISsjTj3pV9l+6ZD4^k~F>fiDPgLoQTgVF_Z; zts8@dna(rH2mNL4eYG(Xk!WJm&gD1w(X*BZCB8L2S%YBy7Q7TNOO=Cj1OJc_Hhel! zu+Z^NbG8LwW=(f;`Evp}MO32P=RW#476rL`Ya`&C(}@iWJarcCcAyirE%tEF?W_TmXp*%G>E`xd`V{9Q&Kc*9$S0e>)V$f;*z_|^ z-Hm_O_%I^=f4|{O!*h0h0w6E*XY>L}EcLGJHXTx@M>Af-+KKdFW^5qKQ^3c-dPW@D z)U!Z&!o#3;8-Z}!g}Dtx>oKo(6ZNZe!q4we1s3s=%=8{K`v2Q@h{Gn*Vt zLPhp47aBWdYcEm`mJLdmlDLSa!+LvMzQgAT_eLhdqI>efk5X8;X7@urWc2nP#g&E@ zDks7QadeYY@d3HCIvx4%GDJ9hgp<(d6j1Ovc~7CEbn_RGu#qlayL%-toxOn2gx)a= zIr^{9IDg?s$cvt|`?x=&U~FhMe)9jYt>W5+D`3KS!L_@ab(a32)Htqi$SX-7xGlEG^VP!@JBWVWp*Xn`7NZA8i3K#@M_J4*z$ z%koGBQFdb!;ql!UP@*bzsN-vO^YI#Sxal#|s6974WvLd}_R<KARnw?aNM$_2*#L@ufa!P{07(o4l|2rL*)oYy!dNp`W9BBjine zi2UAt_(BV#*>33ga@_=$*ru}D1is(Mel~4`5Dgc>T>kXdPh$e;EdmM!Bo6{<5z9dS zLV~pSsU3e-H*t0xkp(<%k{NA%ZgS5^Th#)))5IV!JI-mzoI7y=NiTyZI{vh7Lc7!S z5#TD%68YRT&v??O2673R^aOETZ_r8=Mnfzb9`I5Te)j}}{3e!q<+ z859zlK6N1q$G}p@7wcf=hNdR_v(sZVrowVKND>0ClF7FT+yT(Yo;w~s7|1e-f;)2o zsV;}}9e+{>*B(FyrrJz$1ij3k=$esT#WyPFfNYn{a>p0yVDk|^0k|HM^xi#S_FX^` zt?rqQ&u@bXquoRrUI9tmPzHo8+dwhuuEY>25P1IuqvJF6;C+a;i+4SFu|&lvn3tQByY&fA?gDCg zb)D;Yv(j$(yM^l~M@F*K>HY~V8Y&X1_*$g`fTfN=bC?b`(V^GUTkFTn)E>i)E_eKb zftpSM>e#HjJe&`&L72K{HkGHxvnRPh%Q4mNsgt=&HDs=I7O(4glL8x<8X1}GgX3;$ zoNyS025+=FL4)-)eRBrvfhg~@a9oNxK?{*Fs<*G!lfo1W3x!<+OY(wg#3{wMQs0_H={DDWVIp0ww(o$JlkPp z`AilPHD2FTdKNCJR5CS0j1nh=+_T2g`Yc5b)s%;1@~Za@OhQOlfnooTbT8J0%7>R5 zN=~G$_TpP30(p8IvkXE50!)(X0j9avv>}EpdLZf zhMkPYSguH{nIM9R(Hsd))9^x!xt%6V!v>$H!yS8&}4Xtl&J=q#>c}vT5OGDxS>=m(0 z^q-^Wqq%6zd7qPau8n*$awf93`QyzmX-+qNuIcBR_BFo0ai!tI4F`99ao4LZV+N@E zI(-3_mClvj|Evd*NsnjYPbP^mVi3b7NRu*YzFHiymo{i*IBn^C?*-UbvW4CMq;OIr zX~ymW=O-p7GX01!;FASWWq1h8M`+Sb##nuZ$ zysw4b|ES>M=Q9GPFt&-zJ#d6e(F`^Bp!mY#%3Q$Uy-Jr2r4kZY%w}-M?q)5I$F53% zpf-pbsH9zz=oolML}Pj(+~S@KgRp%(e&z0eFvm95pBYS#Wv6nplQZLDN6-~WeJuY8 zsy)%Gz=MUDEqdn)Z3d?UMS|K(vo{I${||V`)uiDnQ{umPV%djNN~)Fh?nt z;cC-IQlJ$%v?)F^n}bkA(rjyh7^Qx3$DZm1NK_EuG+B%`Te%xA@!vgm0qGm5;+4Dq zPA3E>m_!3v7;4h9BT496RMUkK@WgPqSUs03O1dBtPFTG>A}N`&e*S$}UeWV^nR^%T zy3VUiSXWE3WLxQJsz_?;t)^*`Cf*@+Q`dDJ=lJMYK9Pqxd0$5muWwpCk}ZAo$5 zG;z05U?`VqX@@%nbS?&3O1ZTZ3X~4~0~F{0ncsC*S>f9cOAZdwg85OfzF}156<}2N9_Jvx|F-D%I*^ zKfMS~_=OErG8&2oy8psVvxfN#L7afHO5H|#17Xo%jyN*} zqlg{~M>ZZo2w<`MPt6RW22PBPj7SG&5mKHgo=Mn+kSFJvO+w;}7dXy?IvTGFuETzK zq_1}WiIS6c(3^=mxIS6rsYcq_J-{p>2H=rGC8EM&x9QpqYv1euOd=fj7@SjX7(ZF{ zIw1p+K@lWKp%8>|Rk~r}HA7}auF!3|aMz>Ev#vvwiS1mJxfH`w-G5kpN`8*= z?r%a$8PCvqYy-&^nVD|WS=-M_)CC^&RNm9!Td(YF?#l%{$DE!X@8Jz3TVzgjo9^2B zwQAl1ZOR#UtlJbT%+>0TQ4SAnpcv6Zi`}N9_DJsFL>ha~H*7>75VDqJ7X~n;?0xW7 z6eSN2^ymgsDbiQF|Cer-b&bdd&5Ru+Ur*Wv#O}Wj_ChrCe$b+}t_R`eBO9ntwC8HK z>9kD^1Md~Rtw6kq396bN=7IljuW% z**-f_@Bi#PN`IO4<~EQpabULFw9%HUT1!FS6eB>~J4(YdPAjv4{E2eO!W=2-rg17?x-Z!wuw6?B3IDT5{9UKA46% zOdb@LF*cTC#M}lFB=(-^{*1Dk{{X7+)I`=_Bkr;m;KGPn&&u8-Yqw2qAX#GXv)#X? zw3Jb0%Un-#nhKu>hUYVVhMPa)o!K(W$o8ksxBfmfDN8A|6Z@eG*J zdV|9!HqbO^U)0fUx|l1&#C*DR%ZQqZuRIdMixsPYcs}9ISe^FCjeA+QaiIIxbR)>( z+5GtAG`GO~(E}Imjn2Ngr;hQ#)dU4lWw`pj8i_}3vRrH%_mS?)xJV|&%24}`bN8~2mh#)wf z;&m509E9^5$k<3DNVe)JS%0yWB8eGlR2Ngcl|ZbMDzyJ!-Eg*H$M@{WZvW%$-?Tlo z?MJuGbbY$(V&~s=Zgh5U{p8lmTkq-kY{z$Y+|mBq?cds-Zu?@}ySIF5%gb6Tt$SO3 zxn;chhnwHh^p8!CH-5bFL}P113B>CB+q(gz`Tk7GI3P2~V}$2xWNZj7+KCBx4!M@O z^8g}3z%o&SLQHcA5sLxZJQKC1jKlHB)Y!ySp5Nj*AB~0KFRd+K##QC#$-|K%1M(19 zg~7wmvDbwS6qqQ?ri`ai=|deduRYEV0;YBxC&JYQ!;6j!3B5w@eRygEaBw8#r;OWC z@*FJD_;MYc#H5Wa=qz!yNZ>?Z0)+h}j9#{Z0u_6sYpL&2KB3$;3&_AG6?@w5tEay- zdrmDA@1V0Jp(~nwbU%q1MNSC#rZvFGNNrMB5Gdse@5vmnNh@L0w*d@!K3Yi`ho@aS zLnsI}P3E#N`(c)-#tFk5qI#8mPbAZT#Gqo@c7MdB&B+}zX#%TUfhGyW0;K|5Wk(^S zn;N|g%!J&cwKHew#}NF@@&;Oe?~eAQzC*XoiYfYrm`znO zzHWRDMig-9nd#K~bUMq6S<=D$l zkbYS$>P*$d9hrHuV{C{CtwLZ_F=}{r<1|OVJN2zPx??%L!W=!OBh&|F*ilH|UK}@7 zjB6O^EgNXp0U&JZTij4ci=doO%8D8iiPgF#s;Xc>c5XP6q7g1_%yY22Q{S8zEQ6;7 zt|z`%dWmj4n3hukB2%L}b*{c0FM4I`kvG`)|5c?S<4NxerY8#@vq_z}Pbgzq$@4{9+_7+Hzs*u#ArNHoZ#Q(vF>+^SHDIfzlQ zBviW(qm~Wi6J(>Y)VuY2@%3hbqnVsZXC~p`m+L^sr0Oifqu%yp*={;$T|m+P-P#3I zJ5=dq*_uL~@=jlPSpfaV{54jAJc7N$sdwot91_7iA6$T?jD4_8FKs=~LmQ7n>pGeG z&-%4vf3j1}5nC2a>P~vfhc~7PS4@3f9YS>v+7YWhYZwRs^$)G2zE(*kC5xj~wXxMy zJRaA{bD$Og@IO#UeNCM?`nzLyt9pXwMnu~;jzaQ9CsSXoWCpX)F$c4w89@6+sLD@k z)I6bBIbxmx7}vvN23Ig02Y5BA#Gw1c3QMEk8Q``15=P1t9BWIdch=13#;0g0%w3IH z!+M%eZy;M>IC?1cRY{t30UDh*c0Zt&DJ0e}j&`R)813w}^p9N>q1RlwE*pnue-X}Z z6nL#VZZq=2#DTb!Las1l5T*s_IuP(Vi|Z^H&GKIS4Pd(ZXn65qqi7m83Zu3SWErHR z>DyjoSz%nzAd~5#nV4Ozx)oZ}+JcX^w-K-4>g<`=qh+2^35n-;)A$WO>$ zxvjyjC_jc}(E4D&P`w}WD^g`tl*KCy(^=qk0)Am!ZGyo7Q;+aIHFy7?y5wc@@@CwC zx|z5WXUH8&bV!}t7-ofo=I$@*7?Rof{u08Moysz`|tzX>w;jQP90q`+o0CctgTKhZOU)T0OQ2l?l z?WOPoylqQc>nB>Tw!XUMS6Wt@-`@0-jlbS_t}$%*P#q`0m*7Xw6nh!l+?O&gGto)q zZI*|`$}etojimSTE2(xX99Q+v_%n`@o!BTGjFVn(EZzaG%%qI>%-V1=iSe`zp4fry z`>w6!!!t#I-m}r|DdQQ7y)42Zitvihyvn?Bg3tHTmF#M2PEOj>%NH#aUj~fl^KGdr zXPFCsK$$dN0);8mk?{$~Dfz`N%kD<}PGgh!Csh;X#^N_sKaEKScMitFql=TdhDjBl zs08Rk{`i)b;oBrsK6<1G6#mru?vw!!xf97w9vhn&o?+^}-RH@IRO3USgdUXY)g+%R zCcv&TCsVw)n$#hQNrYq3&m%x^w2Ri`5>&W}1d5TocpgomV>7M-S~&7yv|I$*zwmrd z%7BmT3KUOZ;9&qi$$H|>`@nJTDk zjVTdoKOh^Mm3m?cA}?&oCyFURbJkJ@>tq)!m&mGE`E3568kg}|@B&ypogL++g{H9> z&EJI+#h0L_z=@PCE~1V`yMa!Ji%Cv5f;sWnAU0cTym%YX>eDGxF~m*TaG9NTt(F-( zBs+1VXdWtdBN9HAGW9_mN!r+!UbRce3KUC9yg>(xK;aJ!r+!x7g}Q_kndug4%xOzz z?P7Sjh;GqG;LZ4%Dk^4$6i^ncxCs+#Ji-+yzB%uO+-5!$kocYTEg!iywz9+w3mhX;#YvKgPKT88ypY%ZiZeIuwJD|QlCkoxH)k=!`5 zN3adHE{vU0Ed3+KJJ1Ii#D8sZD@^QtsgEa#3Afij797W5k%;-Rlqrm1cgAXYHV<|V_5NDx1BaP~qGF!`aSlqqy!$;y(* zD4SniQrhg|9x4JPpF5H=MKBUnr;r;4v}(G_vuW=G$->1C|1gW%yuJuT{JsMzQwbwM zXtNt7H|b~*u=nZNlqrE>Kdjnyy04Gs2CJl#ksStJ=J40{9GbCV%PCU^qnfb6U&QZ~ zH8jlbYu<_JX!<-erh50kt){8!k>)b%AvGDD%4o|PAd7_BcM9Ci)tTE78`Lf z&!j$l1H#@ww2V_r)e0EnQyD4(+CF?F^&>T8<*g>`Y&un|$La*L8-TNC3#lKjPigbH zRn2I6<2fc~q<$z#M^W95pKB(iIB(^?SOP(Ej_D1+*R#W^A57BToT|`E(wN);a6Pw_ z`hg@3xxk6bYj1)vLcxZFgVUSJ>rB&X)oXA-+X2viAfNhBlB`Uv&ff94sM@$kHr@*J zGne}QBn5X>AaCRBY^O&S(<|}t29W7{(y0$B0jswgU$*!DIAznooS)oyn)-ih>ihIV zKzPLwR}g{b-A4=;#XNJsS+m9o;tQq@{|%z@M>fzwVgE|%13H2`Fi$)|+G*wX5vu2# zI=1l?o|LPp_ZynAXSE(#uZf7nybE=}CopipZ|ue~no5@BWDmmUO$6`tF+1GKYu7 zT_D5CO{Oxz%6#IXp+U^92fTM8TWoa1au0?K$2L&QEkBdGUPC{Z8!lt*5vub_GcoCNbz7C#cWBNxhA~u#9$$niTun1ijQs&4n7y{%B)6O zVj_(Hzr5ij@&BW!0I;y_W83<>{%hyocJAN$^Bw=t{#U5=_q}boEnnF3?$$4&%inD+ z-`@Pk&F7mw+xV-EQw{%u4{!7@>MK4>g!Yx5&cx2m9Ge(J#B;1*GpNK&q*GDK{KO1B zI#J^a1H#|tR>v0SV$!bGm<`UxGO=ui&7u}Lf$?~(2*hG;rDvO zz_=Q??FG#(d~0zx9ca6II+DwV_bQzSSbV~JA!BBj!m<>49s}`=e7hg+@GS}0d99@GK$8wX0nZqgow>k z1>Hf54JMc2mjIvxw|fB@U+`ziZ+9U*3^tgD#oJedql*hb5ukQb@uAkHnJC@UmfQ;iL70{# zM9GoxM}k2i$<|;pi}%#F6z62jw!_`Bh-@M}X4)u-zjBcLO+N~sE&}p79o^NlB{>j-{$#JggcsLK5;p6{hI5#RnM|-PzNc99z<0SZV>)1!Aso zQ5#}bfH^38>9}A!CAm;6zJPRnV~bmzLm0!|PQO<-_!Kzz3oGDuc|_D9?+#+M}OEIvRU$n`WO>Bp92l_-Itq~o?2?YE@iOk)>abfZ2cnQ)jL#}nLvHdw3MEb zT1QD8RUdN7?wB43o9RB7Vk;>NQ@6`*?TCK-%rj3{B-_ z02nR9NZ`lKL0>=?0z?7|HFqct3rJvLt43>8iky|q8{tp>wWwD>g;Cg?Ilp`g(r@h| z7EEvQW5rh^oVGrb@-TQpT@rlCl{r2zFcM$SRdT9iEOJInu3#n!jIL(0QoJ}~*lgS* zYEYJ?g^!JI8M*>e5>WgYe`5Qrc+eL<1YQJzNG?l1TW=}?@O$L>11ST%xBKWY?}hA< z7bgiFf2<$}9?>GajM7U>awZhKCKyCnQN25Bj!oo{y3S+En_olqPlU*-MYCD9WfwOI z3JV#OUzv}&u@uf>G+G4oxUfEzGAROf7u0N^4kY$v7TD^-wIJh#w>^xrv0Aia<7>jBZPr z6b8E>q-IWxXHX763QI#~ptcmDr`bW+0kdl$fGR6Sm$3Du^;*(c^t~=!!y!<%hu7~(nOp}uD8%R}G`-}-_Yf$@+mdq+cAzTZN&u(;z)#(up)9Fk_oYQ*7zvZp z`tQIZBOl{lJeY>R?$bPe5|gqQxM19)1gU7ah+_GL^|6%6rHD7p|2M8On4_2iRo zvngV4fIKglJk_R6CT+FySc$zk;y$qovn)4X%4BfF z7Nf~JZb|Od_RDcpMa$!r;ZYc!>CPew^A`YMHCY^%GICXs=P5z(9PrEXJZj+%%>bt= zj&@@fHKEAx_!YEwRb8zp7KWM=UMO6)Adb#v4X=7l9F9il;eW+K`n;bDo_5^$?tl!!cQ^E*IFr3Hys^ z0#JySQzp5@?qodO$=ZSmV2$pOi%uH7!f;7K@o{ij!(9YJtzKE6Wo&kna!}aUMj4H+ z84eX+4rkVhl*vo6lM^pn`XKVpli(!7FGWi+8f)x5jFo#wZ5-)Ps@i|?rQ!> z)4w#muW3u;9#r~!`;A-xH~ZaCk+nroJfRqkwU%Oz{*xX_JS6G7?PX5lt4bOlu!F{5Nt)tQW|6m>e2JUnz)C zR2!XH&-56Kj6EK!6y?T`zJ6wM3N0w$pS)r4mdEA&`%q_c<4?UlSVg-~)LgQ&i`P*} ziWeguVg9A(wFH^{h8I-JtndcZqiRqCQ1M<`9B2G*uE*eQ>MrNSti#qtvy&1~EQE(M zlwww)5t~$1bt&QFMIe#(MXfz|Cj}fHbv@p+Rj08H@p}Mlk&)#V{Diw8qSSei!srb} z)I^A%H3#B6GVyaA6&jz2Z z`O*s2(;-74S$^#@yx!q_@i8)HZ%>e%#VBhb(UJfy50)?nXz~!kV34_Fo=+*1f#HZ3 z;))(E=31LBfkk&F$8pArWb_k|41>&R?WRK6EldIL2e2^mge7cySSNhq-DPoAnF2|G zr>9?~3)tuaR7_SVus_5;LD2_iYwCreAaI(qM}M6dZ_2ly!?iv!;H!2MzuuZtxQ3s4R}m_vMfpz z&K9%qx2*N_Cr45<31tiHf)BwFB()ehkiJ(|;My)zUae4$vYx6idQ}mHQ_}0Hp1$NL zR)Qdr9x2h*xtY8tMp&VYf!tl$ED966n@lcItw*&yGa*%=tM9My1(=$yGcvq^;m=+W zy+}&d9WSEn%CR#&y*0BmZu?~MN8m*+qf8ew7R6)FlV#@VO#t zvYd!^_1ux9Z9z5l_Zg()(5>XggaNo;z?|F-cPh5MO7$5`6w~wo&-C=@4D7+Wr=A*% zsgFvv(!ShSRDBhtTHoM&jO$30jTiwd;~x-LKUiI&vHJ9T8Dq{Lx{mQ@DvHj~!HdA> zlyiZg)Pn@t>ruG#&h@-Z*JRBd)Oms&p3DK*JA*Uha_mllX`IZkN(uXZ1k4(QW{ln$ zQCks>ee+Si=l0}bIr3ss9-JyjO0T05FRr8vU~F$K0&FcSEFXKy4j-r1R<7Cvb$Nmf zPkZ(JV(}5acK7$ZG&vK^3d#eBGCIW7sWS#-*Q9KeytcxEH<$q&DE48F-KFqA5tV87 z7J5?25fMZ!ptG*nx%T4A-E)P`5Kl#C5Qvm)5rt@mj`X}FNdZb5G)S;mdK`kQ0QZZ% z@Ux~9ogA=Jxx*+`+}GMP7mfAYmZW6eb2wd=%K##M0!cZ@%%RhT+aZ1xTthi*CTh~u z6Y)W}TcVdp9YxemOQ_T+b!3k>vPAZYp6=wd#zqFM5gS(%xl8gS##xW7Y@rBv7HXTQ zh@bUhnas>Vq)A%&O5XJ9O0DC??WZ?)-92M5NGm?H`kReu@Hb!y zJ4vW81RVwiDUrzFjIRO_V`nD<#r}VF!%V}D5AVoq|IGHU*xtA8$F{9)>+Sm8uCM8O zpz}vN@7nqcTi3S^bbL+wKeu0N??CPU?k&02zi)kK>+4%S-ST8hTk|u`15H2Ibfu}W zvD`S)@JSH!{}zi^c@(K$0@WcWdl#Ygajk~UDtfRof$cf+TFuKukBgFa0ph21W%7jdNzN19|htgMj zKdlUr7(Z6!VDs@!ED3xJt->!joGzk3C0d*G8uyuoA!((u+un`0PDWF+OZE-gI>aH{ zbyC{ShATzDhceNFy~g`R+O(liF%3v$qa@sLh=k!l6U%Lm3>Z^Q;)#Bp}!Q7l_Yj@vRw@b*%I*TIFut#{%F4@X1 zRSpAEZxx-suze`c0oFCCDQ^4dH$IHS79%X^f#rL zyi`Q(j(ySYUXzJJ%2xB7U|jho2NR1ooBRrq15ne%O}C0`$mal|AkIy7?U~{Q3WAPa zlN91sgOP1j^&1XL#hwMW>84R9Gm{-<1m(6P#U(JsrCyV>!2tkSXS>CTY(70cu1`yR zx03RVr6Jj{)rh<~WSYUHgF+q@l_oDDMigce!SJ`j4l#;);`X?;JPa0w#1tU!&jI3i zsn;Y)#D=<+F}$szE0pO+nIbA`46hH}@rDBH3eO=3abspT3o*uq^L6A)fahDr6={?xSm1Du?gFU&Xc>TwrK8XNLj-?eJ{Vi4V2e=h7sL`SHn9NSeJ6(UTpsk}42(|UM>zr_u*2sy+ ziG>|_ll6jPQ>@L;BcERoHo*oYj*ZF_tVOijeCSNiHBaByx5A&tdi=qh(4xp(h-hAh z1#qZ%!e)WDU+Z~J>BJMur^cnUDyGhBD@KV(cyVIZ*jUwsaV$^rJz45`)=x1#A{xs< zRG5W?$cYi|Cj))_%rYeH*(Ivu@G7W($^cVj0KE=~-!GmygMB-P%5D0BVv``QRxwct z6zKni1qm;@rs2!3T`JDd27R#SZ91oe(AWqZ24_sqjE|xH%Jc+~&5%p*Ff0QtNu*LD zIZMtWCLVxRqm`}NPNwpHGm%@ z>=(VLZazl8jMkY0JR2Bauyd_2+W9Nzg zzq{dD!;Wh^Ua|e#x8J|52n4`qyH>gyIzQ0ai^~6pw!XCE6CICtY-#_&_KWS?+rGZ- zbz45O<$UX3wLaC_(DK%n9nBwYUTJ=5(^oY9QRCYi8$jxX{Clnh1WO@$xG&U|#KT#( zEHQ6}vxB_yxH?pv zbPXmpC5&EP>gO`A_5Py{Lydnt2Xq2o4a#r{B5@?D^qA*13m?|&; zXs-d$kJiC#m}b1JVhJ!^Ckzf<26TUgg%I^Kkl}5*tlFPc9@NAhrwaq8Ujo`?IGXDH z2R}dBQK-BFbrY!=hmBW|j~XdSjX=SDGB*gfgLjCNfM$@Gt)Q>W-}9(^+5-PNaVt*4 zsRoNAe4^BgJjG{v|K86f?y91xC)vq`1qd?c`5T@iL0)I!GH?Q3R1^P;A>CHPObJCK zhI74t=gB*lSbVAWG`uf}^RrE93MEvN*cG+*{;emYCu+abP4R-Jcv zwuHhF`=Wu~zwuNBhrXHdX@s!j|4oV_I_xnidee$ul-o`e4rl$tt}Q} z+-y{cPidfGI^kHYh1X9u9f4RVEQlNe{$)G};s=RcVl#`C63QWA-^uo-dI}nRGWqY#DB_I8C$= zjBVC}(k0vqD}l5Pme`%@3GrtHap^M%!aU{WCvycKmQQkHiA04DBCXqnN?p zhaJ1HYvJNq^zOS1mkXwpl(7&I?ziEA5(_kBd;ioAke5ov7UPeE3yy<+6 zAYL4vR>I>oxR4B#3wgDH8PnSAITo~4nlmnw03@V5%tub zUYOrUg6L5I;T9Mw$*B*PP~YLcOz$7~-LQ=VNJZZjo~rZm&X%^YXyxs_zwbYR z93QdrTb)JVHJ9&WPXH_`ZdS>wF}g&|p(|%Eid}fV)JmDz)BAgV49Ooh8VnSLnDf%9 z9)89co*Owk{}z~|(r2<-cTrZ;;i4U-7D}t>UXvQd^V8H^CJ|6)N{;C9CW*1F>a*$S zH~B8M14l|IBauDVYf_{9gmB#G5R?q0>9|%6^137F{&znpt`WJ*d(ULPmKi`pFiye^%Ou+k-)XodV`+N($$77jlqFZq{ZjRiJ4xL zu@oE7J~*zMS=FG48}Aot6+jl#72l8o4$$D51KP=?>uYw~+!0>0^2 z^@`2i&=S@$I$X4POp@+4WDq@9L{rEi=)fiuhXce6vbaPeE7`?WDW9<*8THT$3(IWe zWY)yN;UPo9qBY3WjuSC1_Wzv?M~VOc-t9fxp6~j{u1lTo>fE{Y6I)Mq{CdYD?VoHP zYx`{56I*_$_2*jiEgx-pxcM{9bItut>rI`Fvq1kJt!M6EDgn5&7`66&t9g{TXQE64 zuZXu^Lb7O^IeD02=G-C1wxmz1K%;mwTm?9lOMvSPMazBPsN=eZK@chk5W@*9{h@i;j3?(_evJ|VqK-d+ zbfgRC(3?Gh^8(xOWQ>jAw#rtQN1^qb?nkzS_FF?o`o2M@Wv(VwD(j^2bvdm5B$t$3 z1Y_^TN(n_Ujz#@_|3wMK_^l9c9gK_5s-#?JGMaH9lj?cPsy(n&W4o$(Ng*<(YN)L#0+Q}8-UHcM zv*Ba%hX-YC`tb0a(MJxYI3EyFHy@W8EaX4Z9!scYQCM&8JFw|e$qBw1qhDRk5%WN6 zmc|1`UbC?htg^&)#hkA7CX8E8CN(7&1mznJNJqmBv3@C0`^CgWvn_qy8} z2Jw-3dl)r{F_-8!xa7DR;;S)?WfMrO>x;^2oRY2q7DEZW;${$5*;~66_VLQ2Bs!|6 zpmqDyp+j2D&;+2NkTYn_tGgVG!{tr_P$RYFaSY}DEJ z2D3YOCs0^qatyL3c_co#LKx5N8C6m7zgL&%09Qp{e0 zZdD@Vt(9eJBt|DoC{HoAex>i>+VvnOABlZHnfVcGPv6;XVt=u$0FwN0YW`+x76w<$ zqzJ~MoRvn6*JWGF{H_Q9R@{pY)FaRzOE?V1Sb7-AeXzI@m$E;P4akR7>@Fy%QF95E zC$i8TURS$7iU+1$tMOd3n>7|COj7_k_-MxWLElbQkSPn}RjZ`@1*g$gLcNILXsmCy zPNP~<;k48G3sS_u6i%^GDfh`5T0zhUh24lvmzoT!NaUiqzSo)^$wR}; zF|{)Hcs29JK1AeE)Um4P8OBOt!SQ^;VA9-VYBTnnaW(=Jh?Sr~VW83g1>3Q{hiXsB z^1Z{+=Uhh1d4^rU?x0N>AlJ&@Z8u~h0u^79oUmzuQ4P57ECsxag}yJ_d`f9e*Z+5% zkSo5BDWN(9@Q!^C)=r0fY{J*d%I2bRdGbHC8jlnpSP0VNIqxwCx3C13SP*1hS69qF z^3{^ca)B*Lwz#swpe=8A!Xh%qV7XFfWbFT+Z`kow+rPNIciS&-d)Kysu5an;>#TGh z-g>>`pE^!;G_}vSeWC5KEx)v7to2V@54OC&<)P;9YHn*f-uR1+#~XgWp8fwH@Uy71 z1iZ=t+@g=_dGHKSg=M^O82>}jV3QQ`vzO1n&1YK7yLWZv!t6yL2<Uq|*ip^I-?{wLCZw+lGL{;Y21n8%(oVei+ z0@SW(Q@pG+$@7})`;nThlba0dd635i3mw@6DmX&_Of^ew^Q~M628=%;S4t?eaRgfS51Hv4KjdwH`!bBvhl!*f z&n!Np1vkkuukkD^egZ$2!zY5m2N^`0fHuk}J5@r>4WtA1{a|t@a54nl6DS-)0&uS=F$xAS7<^Qe=TY7#$A`ld*se@PAMB)ZfoXDIFfStdIIX)%sGYHI zy{GR7bXs&2AwTmNoSPa+PlIb!!{QLed^S-ujWERc01-Z?Fc{H}dY@uXOR-G#@KHTo z!>di41AM)FS4_;BQ68`&m3JJftBwhv(HPX^YkeO|?j4vJt_g9?QeZluCFPyi?A8fl z^f#`+UocVmW0Mb`DWRmsRJ5z_`*j$g_(ah+bfMQIZ@l0rh#==(^3pcJtR|j=MR`FO z8&i}^NdXDpT0&KfOtio6gJzN7&3Mxy*Jw8OIriJRsc=e{7vWlkqfxg{xBx=LyT`CE z##bfshN1|GS}Z#sy|RQd8QJyDzVFk~T|Oi8kg2neQ;4LU!!>y&S4=WQe3db=>VM5l zNBV2!(CtlL35*nV^aqcRx%Tf;F{pmix`dOGF7*v4#2<*=VWHmcrHq(Xj&J$oZLr%qB@s2p-vguPcXRpU<4Pt%M)d zHvoi3Z2#+Q2*fP0Xs|V`qfG>tU3T=E5-MEGtT*<3w;qa=jyVXkXE=UEAslR3oJ`dm zy^uEAe*A`FhpSwaoQjsRq4c#E46%Mp(000_Jr2P6Re*^B=HV%+SrtZimJadRS?jy5 zvsL{8efcJt8O5`LX&lQXm7Vf41X&ZlNlJ4oQRv&#*5MdjXGw)mWGHgYAcDY`0CjGr zd;k-aCEU2RucGtA$=b(IVx(#Y-1x+5Z?y3|$9POipu`q=Xo5qU@R(TY#4&5W524I%+~V)>v@> z>Mt(#NiWcTij`d7`*e}2GpcoB!_>Cg1P?bEn3F^++dYy}&4#BH(*p@|IXHx}*kmn} zcVz^T%5bk9uY{|mH?fvus_)x$CcAo>0QukB z_S}{~-g3G1S6koKdVkA5wS1tZ(EQ%!_NI3>^)^1y@J}G|@AGe}ghnCRm42HNH+h_a zw8Gd(mWe?|8VtG{%Tpj9P{1wI8;Le3)Gdvu@oM{%B~%N@Ma}&tuPsBu3J^Uq#Uv_f zZMJrdqC*Y#4;-X&LkvC+MpyIKo+%5w* zv^%D0*6@6z=D_~w{(h76#<@cpQ3xR)3yqitQ5Bf!(Xb>vU=NeLcp1sJ=NHZ}_-?Ec z+OtrRflkOQBT$GZ|0=(oohNI85oekI{7h+$v8r^x$u8r7Llf!o!?{esM%=k$FyvhE zfA6@)p)6?Wo58UH%HhmjJi9o@T|u#dpyo%l>=3n=(6D5GG}C{{+&>J@q&l{G8k1rO zX>Z24m02vZJ$g(7ubJVwD`$zhVWO)POLs0k$AlIhXM;kTf*D5pN-KEo*E9VW{alU- z#7pYD`NBhWd57`<>{DwtkyUY8*mS6iX2#}j_>3&ANu>RQ$Q{Tr*0=Bhx+UEI#tm3l z6-jK+PL6%Uqa{>KD4gkEt~+_F75NZ`kIveSlL$C?+G;CM?GgG8A1hr#!;b0x3v~(e zV$})pS(;uK)at$umQeBFp?&>}p4cRk)+Z*A;YYbF`FiH&Xmo$Hw2a|r`_K9>SR*43 z|BzKqiJJNp-IG`&oEVj`EF$jn|w1Punb z%u6JSk;0H>bLN-sHqOI*U{wW^wdDDgzN2$AK^OYxHyt%5@F_Ny!0+1Rqe|N2V!<(k zgmY-mR41Ud)oh9qh;N5%kZy+7kc7e)Mm;4IO~^%;`sX&Cmi&T(FF7fS>5Gb+yp;*z z;z~_w?2girJ0=y_P@IaA!JU`;XIh$e&-Fj)$$+QvTqBr`y<$jE zVp`%cr)j|IjIKh7H4egD=``{v7y9+y&!`SCR>;Db936x|F^xoh%5W##_;5g3mr`Q( zK~`xW&X!P4ARjgMzuC`;C~=4csY`}e-vDmXqA*ZOxG=u}Z{*W#( z1WZN!{U`kx#<8AH4`*kxM_~}tX2AcOn1-uK>es{l$@Fq@1W9)sm=4lLE9qu~CyREQ z^JW;y8J;Pj0>IvAp#KR!=rK((aEIk(c)bV4h|#+IVN{Zfv#V#3cz22;b@rd|BaLr5 z5+seH18$Xkri2Os56|>J?x|ar9vA!BucDeZj@?)_VZQVv@=vDwr#+R}+bqy3LzS1- zle7y^NMy+!|xG=h}gwg;7_&$Fsxdwo4$NeJUsAs1~?#oTa zFt4>&ORTsvCKLEnx-%O|Z=5<(9tDz4Q@{WaU7I@#R1KVvSE#ZJh>^vvODE}Ac((5+ zb+U&>#+c~CyiV#@xd+EY+IZy>H=SCYgbA!$T;4zT@|;E%Ixi0f6TGC;y<_X7J&N5I z3)tD=8c(DhA4Wr^C!hhZPxt+V&TA4l0PEq38=+Jn`0!XmFTR=15o^5n=CzD_K_-`i z+&tbcX0EcwJ*I7BHROVLFPsxsD|GU8h<_wY=VkUlA+8&nbotC06Kld~O9|BzPQVlY zFN3+_dP(bmTcM6}p+blmszV#=!?(O(Y$HDg1wokTQ zYumA9sr9|6{r{1c3H1M)X!?B9yPMLDf7N)t;S2cqh5dVL8JWuuN5eZ09h!jKe?luO z@tGu`gu+2~7tkJO=h?gmuf*e)(~zW1$uC@-%j~%P8eA<7kVW64HN09zg7dEE$j+=C z+*aVd;lSoq;}z#^Fb>ZbICj)nzMU(d-Z@x3_zW;0H=F=|Z*8}K+a&Vkm$Jyp&WxQx zVRB4kr$$-1;WYdKKypym4)bMna|gYHo?aSd;Sq~{q4ZF54fGx_qknt$*_~-i&py%E z0g!}m2HomzI7e<3rIP{LFd`&b>F2M8vt?u;=c3mBZ`YeQNzVdH!XW?#mj>t;h=|sg zR)He+*%l3eG6>K__%gieW{r2NE=9MMyE({0zxCw7lVD2*%#5U=HyAS$jO4T><3e)X z&CkzXb!HFW6smO~xD?KochI}Bv;SLl;iBmdN`YA8LgSWd zg{xo?9-M_BZzARelki?co?^Dvn-HEVBY$~M)Z1^;aO_YoWE@;yb-#-wt24;6Wh5%^ zk8=Irtm~N=9QVjl`4QKHpF)r?!NpHg?e5ol^Y-7mpO2TB#{5jbNtNLmkzj;So}}HP zHoRyOQ?3{@o%Qf}aXI!W)^L(3JV*5ev1gOoFjelP|L01-$%r9&JQ6524+#wn{ zS~BMDl_#FK8`>$PzroE>y9dkgcr*zHyD7d<$-=-Na!XhPISk;!Lnea++T@Lb%MtEu zahT#;P8$4XgLBMHgv1l?r-UUX<|%Nq2S8IDduBR(D23uG(!zz%^6ArI^osIU9NT(l zzsafL!pxl`GywIB>a5EvfmJI@EJZ-57|j+J(%qrs9V>`C8VN4Z8JP`=lUXVwX}b`m z`c1A5Cm5^BHv$7|#NmOecaNj1`va<;6g;E)a2{`ysB7w2#jV7ER#@c9NZ!sJ>wmAm zmfo1q(pPk~PADh^>&H>bGw(OWIai~*%WX6yI{V+F)Fc%~0i?>Bwg*(2a0!K2^Hy8N zFBxqg#A zBy4avJvhc9gRJ;+a9YdHYHuy_gz=$~%~;1!SeZUfrLX(GSb&!JNJKG?IgJQ>7z(qXS9NA^^A;t;`@T@3BI9_ z#7wMIq$rgJXY%ag>D96#?(aE$FbF4lS+x5L%U2*4;bgH?;Wa-GYw$9|e>@Rf3JrLe z%}$7;FuGbsK79W9hx)(Pufc4fJuof>vQZAi9tGxY26Rg>d~{y?OBkP*+gxf5%A4)1 z{yTFxmI=&0@oSAGz@oqdDt3|c4gpk%!be(SzdpUHXixpcKUZ$R0Y1OK|7$i~ygm&7 zch^pSa7F6$lHtIC&GOlI_;0+R8M4P!UX*(4slGw^2f|_$ zIpOtp+&ti1l*+*A63PRhMr6OOnM-v>C4UVavVz$~s3eMxvfE_0RNf~;d%lFq00*Mm z`)zev&^B>n{(oX%2;5OQCULsNPFvC#brqrye<&&-=AL}LX#d~Y@V15>x$WP$?c-ga z?+QClZvBCdf9|-@{;~F>ZJ%yC*Vee@JzMT-{gKwF^+3ySwX8P(YV%0bPc%K&_(634 z`xHKX(f`KFuR|5><)Bwjco2>GGU_6-Qrj!g+&aopF2*#OLBWPuuuE|7Q06`(@xp~N z5|f9b9l;%rW@ds&yFsMqF3D2Knni5~P9Z$0!~-N((O;8Ki10&AiDQh@)s&4K5r7-p-vz9-cv+ z*~Gp(%E&N&c)cxnS#n&2qGSaTXXbXXj0EHZ(XQb3nyHOqdZ-vJMoZoKS**hiCI{^XGlW}hVfM7y zA#_tOBNI3qoeW;;#&o-n$h`nt$Kv@8ltI`C)qQPzZw3Fkf{-TTn2=E7GvbAT`wZ{~ z=*Lw}`Q$>`!{L9}(`hOr;Wr(P1t~Y3iQHg*h?UJ)s>HHh?H*8p^=Zf+Z!a6NvUbWm zF5-KnjAyYDCLWlxQt0AoL`vb_enlBczeDSd!AsmM=;T0RDmvrc_14bc$QAx_3FTZM$W>9G?TALesCNc*se{k4Yd(h za7wo2;<6e7b$4ODjAY<+lnT1zW01T!pj~CJ+NC6q!fv)01U0)I9w?(*{lmwC9d4AV z(S*)fOCMVm!zYFhmC=y?o?NiqQLylix}OrB5uPg}ul7iETd>W2Qeb0=H2xKU3Es2PFO%NXAjw|O;1ox-WxIIDXN`< zVIEV37^{<<+f>l$#VDct(Aix(N@qRaDYc&&`o*1ge@pxq5b1H#paN?T{54M~_5 zd&ZvkCNZ$9hz}u3q)!)0yIS!WbEzZDhI+5O`OXO+&XtkTIuJk6GDG7xd!iO^GTxy5EHtI{(pfKXs$oosZf1n`x(~CJ!^21d0Iy zK)1p|R%@idFxSv2NwaJCDI)AzQ*L5BV*#f=FJZHDeW5EVl>6X4T3^_it6CAnJqml| zGE(z)d?I)B-?}I+RBUvrVt6ai?`d&PAQuku>vCrP%?A~hdm$*-AKZD^F6;mH3BAyR z*j>H@_Rsq6okMoU{~;&v0;f&;|DlH8Z`iT1tyHWJHN8?P-g@10FzrAI)1w2nU06s|9ATjw7;$W!M5LSE47_&3%30FmT%c|3O<5A zY<*wrn_GKZey8R6mVM2iYu;$i!BcR5O#JT+|;Jq&01uNv&@UeVhR`cH+vX zi33DyHpHaxJi|vQ%QPmuoiU#h+Xe))=3QsX>C$XqmBcXGUIsib7tI6)fX(p+*+5_% zermRJJe)g-PVnMACD8FL&sCH7Yvl5ccuViUz0TyH02JOU|8Nwmd zsab}BXM!cC=}wG6)y<<5&CEgIjWXQR%gb1tIX+97WX?)GQnqSH4zE*+e`Ve*byQLn zC6o>w;t0iH0UAJ_j+Oxn%v=djN(m7188X?SL-5(pNS8Zr`>!Ad22>j2y}*dkq~&4C zej`H4&>IkL$enPeMtG<^gHUrJ$U4FW0t4X#oP;rtI+B1aXcJ&ZTFMcC3j_Y8Y%1Nr z`SP1vn(`-tK}TpJ%h@8uv$m9~Bw`V|4#ttH-iz!9PutkBU$%^PJrB6FjYpIp7fOfmXO&wyEa-abs(nZ`L}PX3&q)V3YshM&F?Fp z0FvZDkal!o*a54L8r-blJUKN1^!uoUv*jqHrNre0MQ4Wx%jnUwcRF}9_BDbq+Db}! z+?^3K=*})nvMukCn^3sFJdG_X1P2@uv3ryo#$xU!XVl=-7+*qJrZd3G50;MupL`;C z#C?yvR~SvGb1*y#FAlleoH|rKx?K#X;)XHt@XQ5>k$LRIF_6gx`yCl{j6vO1c2?t_ zr*SlM@IT@Pikd63#@+ijm5<`<;owc~YedB3Uo$$i`R5Opr?3Z^V4wS33|u?17_Ie& zeM1>NZXV7Brm`9?6m3VW9f4J|aLKwd-UH`e!nPeQ7a(t^g1v6YG)kOhaO}1KJML#% zTqEwYU>5Bw=Wru!HTD31vJz&>6F~cB15?3_*ZSaN;z%=$#Qt9+=?QIQska(O5-W&= zax*x9Bk*)*15=|6RPgL@`{O=Jo;xqC5k@Gea$ZC0yUXL)i37pw-Eu~7!%Q+L`xoGT zxlo_IWZ^^^1s{ga1rNKgrbdsUk~fE?x}Kc?oUy%Vnx-f``36wBhsVNtkG(Lpc;U!u+AC z(^3>*FU}%7QXXPAgU9sYlS1jw!eS(6Bp36Y0q z%E;9(L~X$Xj%ds)ir&~#wj1@HUG-6AK<6(r0yOU7z#BOSWk5P0xJH+7zh+yS9y}S` z?*_6@TI~Jd(__Ut%M)o;GIt1r$e2DEyv9+Woe`I>FHfVIS%Du`8}cdjF$J~w9f>0IpQn?U8_Th4lhs=pH#C6!8ZxP zS2}|9ywwt<%S^E;HzByEybl5@9Sk^v5C~d!Q+|T}3O0F0AN<&3|34hD9?Bc*hmQsQ$q`h2NT{~934_Lcofy=x!HM$2taH61=us$W5feDLC$d@VnS=^1gl^g z6MN-_4^_}^Y44uEz^U!`HDAWRd8D!(V`c*bcaDF9QpD(x3XHnwe=;U@1D7=gd9=C` zUabINj6%kNK{10uEGBe}jq?CfETr>k={`WadKF9XQ6S8QqEQgFa4Pt+PBnjq2ZX;? zn+O!cE0r!r()R@h+>EiIw`GT5sKu+U7^T8%{II#J#!=gptjf6<^@D}2=~{3#BkMYQOciQLfP$wDsf`!k>zfx>YY6QO*kU59U~pu^JMd|(jG zpezsxd2*m=^Z2VQbj(l@5cqX?t^!={Fk+AfIE?S{V`t}6W6DFJ*Km>>RiM6F_AgmZ zArZ(i0c+5+f&5GbsNB6L0s{iZU_;qaRNl>4qowAu*E3);6|_;xjs@@4d&?#J)*&)| zm=avLA30{enN9`a(-mN4hoXmr_c$`f0y&taD$j}~=tLwN=#UN0#||gO1wB58AblmCgbnv_QWRGV_f}fv`8FtBEC30%aBIM=ghwGcB3KNu9I}YHl2u zQOJ=iE#yl6G~8clLek1`V4$m*9ZNlkE6@j)%|9s z9jK`>Lli)p)-u`?9f*zv2BL@&sqo-=hB(qon!F^p0Iku}M#V=jy3Ohli27lP;AXmsIYRp3{aAfK)a2Z+(YAV#re>U;KX zg|tDYsC^SxS7_jHQ_P#dSN)>8-qjzCODTh*P*oX)a`MqVLFA@P2Q*-13On+n<>6Lk zUqkby_U!e1z)A4lxucWIh^>S(3;07*^vHZ2o+z(Crt z^Kaq6?iCJ$0&7stauiXsRxx$8=m0XPE78xCQClV*^#)J5A<5Ku4aswByBYE}!8j*lcx1H_!*RE?_`#V3| z`8DVT`2MXkTe~|hw*PDUd)f!v{<-Y~i2C2POzT&+Zfp6mmf4mq%|F$A zwCOLKzP#!7#`iS78bn|8zo@J7M)K}l@Za1HL6v}%gx(K^kiyypjZbU04bv9=jmTjp zYTocKR0`b|qf?6M>vl)p%|uR$#q^v7lA2-KtHI?p6jlh|Qb7;DAzY>Z$4v*Ac0mnL z*BfVs0Zj8-n9(>>4GPxahBFVgcydDFwaOc~_FV9@Zm{$eixa-EwWrsfHk(mr5U$z? zIKCijPcK5tWeS_T6H661$I#(4_!&2Y_;Mw>ei#)i>aREL9&~dGdGy=em03m@20y4X znea^I_1xZ6@L%hXm!6)v#o_X^S8q7dd;74@x~yw zFoeo%izHn2>QTef6*S+=VnIJ$Zy16TV(WPU<5X{CI9S;Y)qgtpxEn|9SL((xou9UyG;m+2E%<8Q?|;hZE(BSFS#x34#@NjVvQ}4&z8bsT7Cu(<#)4xEvm> zJOpjwQebNBKq(!Z8lM>%Oe27qD~zKag4o^l$q%k6Fn1x~2TVzkTwa>w;dtfCpfa2b ze!|U}gjH&yZqCfm6u|ytE3OcH)O`%?fE`&4(ttV+qc&(-K8ltXfc&YtVekg#5oag{4a~!f z6{KAhASi#-k%QcxM8gv*9VAQLV>B~!7`9De?G!qA!tWcSt9G{N{tiY#3k^q3`_lr1 z?j1$W7x6nQ;hQT+!5Dic_=p?Py4kGTK{CK#hQ`X}+WI$i4XGLJbw^DH^QP#d6=Z0@ zmGxmifTWbslVyNoh)q(iyKmr3U|)c%>QRB>UAY%lUM~0%M?!o}pn$kJmC;xlrudsY zC2X)wRT!?I)7kKJ@WYM@l~C_T#ZJ4tGq1|&189Xkt!x$YLzP$KVitlQ+JssxrDGFf zHeq9=ayNv~V(^2Gl7WOx!mwdPWsIG3s1sSBJzgK$c}91~uP{AZA`-6w@+9~g{D7k; zCrUjT`2I6g4Gj3KG06bL1r)Jx+P{5~H-X?l^1*s83(X+w#`!UC+Mv%NGkS^40m^oBH#7uU} z=KLPQ-IA&^1zZ9c)OpRZ8UtOqjVr;u{OG=z*G?ZTg|eCGSHQms&Mu#48?uBiiq{H} zHq39NG61PM7ktpo&cZ9IGRIh4nR^Nw-o5t;n!EsEt`dk1_I-|=K`yaex`q|G(prDI zjg!XM|563{3VY!R|9~S_I6O5ewT3Jv$Qvw)xfn)^xq--ywWDG*7PVvEBeXIE_TN%L zvOxx#(EHt(^sSLec>QU)E5@)|09X%;zdBW%k(i%4cE>7r;vOvr-y0iC47G!3?gQM8 z6wZsSP!j;+U`k5L*+9C3uqkr*L(YiX`j4X@>ed&mZ+zT00FHoFNIH5UP5E7Gx!ca26jxmOK}uYt*kK|%4T#FMlm*` z_eq?iGQ05c3W}B;K;Gc{l0!_5BGgdGrcHH|+7XD#Tr+h$upmWxfGOChQ=h5@iT}T* z;lm9(uJ0Jy{sq|od$zrQ+wrcy>-yfVvt9Rgeya27&bzk0d24gW$2-z>`@qLYX5dC-i7o{pFgo~Ox z!C$#Ofjpj~BU+wM$#X`W32c?z7ra;1LSEaUn&ViVJ!jrE=2SAC$(tkPJ-KVz<8+q^ z8GBg_d^Owzqm?<_&Xd6x{G^CRHx5i2@cvYq#ZEuCF6#i!( zBoz(Povr`?KYb?n3rF{G4p00<<}i9GkV&DAj{y1`@5HN_?6k3sRQHY-4L%qx=FJsg z;0srRKX>VqPOULqOL4KuMjfaCOP|RFf9k2j=j~~;Z4wvZKbKU&nDm{h z05zXK7yOB%V8UN8)nTX{&J6+^3YM143V#92^`U}K3s=*as0>b|ttZ7g zlDJfBzR88PwuiYwF2E}4hEe>ig9*P}y|MsiSOpbD-pYF~O+3*nv@*$*-g|=onTD3HAUy$jMgPNpiyp54c~9fcWi!K+(()_Ty~n1q z?lf+~+&NC8PQJ-ZWsLjV82qjyXmw@Hb%Ol`0aS%5sJbkeqLsmTRg>NscukST0A%Lx zxB+Y&)ZIYFL7_4|&2SscMt?k>FuXd*Uq}~%-*#k%0L7XBtQ`$WeOlHT;14ceSb;fJ zm&(2h5*m=4^BG5lC8`gmS*On==b+HhDPU0QZPud|%E!z;mWdJ;5(pa-bnv=LKYLba!Ch}5qqAy&K?jnWl1S6nXyzu}16 ztwy{Ahlu@Evnrm7`7GY`S=d!%uw3jhsD-iswtPW>Gr@eGFd_1MSd~( zbTv^aQl&Pqdty{8tlDFRwYYo+eO-=L4vDw@*Xoj`m~uonon2kR`zy$_IFJi|HAz^g zsSA?qQD>quulevm1$h?xjs(9_?|aOPUvDxaL*Z}*ITlFj`tObc!}&4E>ydk&kP%qI zPaeMaWCht4G}=DpXvOGIg69S^>Rq81OI|H=i_H?9EociJ;aSsIf>C$ID`~h!t_HvC zMi8b^tD1}Tp=;xRcJESBCvmPTgpDhYYS{Rf98vMCD^c;RLqW+E4yzI@zI7K|GBW!# zJ8q$%mtGp{WwTxsNqL?1g{9T~(yjtxlBz7yUKiIY4}7 zgG9s?_YS!m>9yb&>JT>(W;5+uq3xXMCo69vN3{k&Ux%)V-rhRh+KBAY3KBXHMf*8N zp3G0g02vqWjWU0|9e-mmF@IrKdUbVIjy0KqkGKp}y+yJz{y)(0D-AmiY=1BM|NZ&4 zw{3e>*T=hNyV^T9Iv?En(X9&|U+j2iM}K>=^s|KnejyN+_ah4tZqm$<#6I-5N{38h^NC$g2Mx35$mjp2awrNM=% zukX?xaSn6a%N^h&Lx;cirQFOPit}+^`;x$BHh+3S^7!?tF@9#s=Qv4#T5i`-#dkVd z9=I*Bn8Mf;OMwH*1M`%LdU&lR311~ktZ~BC3v*|2-ivS58wSZJhOyokr?WfUlvy!F zG5-$FF601I)j73f1viVlclIckLBjQg>nH>bwzx)U=@l-0MBMA{Z~z+0OVMGgFe z5D_}_K~eF&PJU$;*?<&DIzL?`tTA|NsL^wd?is*S?$Z9G2@Itl&KHNHN21mPGJDQb zW1gjiA~JMEMf#jnjQ066oLbEoI8#%~C_d}Df97lzdSsa^Y@8q3pk@=&i`Sc2H1D2) z9f^Hr1jGhEHfL9OCD`?k=V_y2T!g99gq=u6Jyx!xBJqJ}_rUhVSWrsQxLdMpwXT9K zn*}>!vs2}5fbx1_9;hupxY&qr6rAJI^?g_g2d@(me{x`3Vo)fF?82>2+U6?+FijaY zT&@5epTS0TCFoeS6TAq>PW3%;SFYNcB`+8-B+gRc!is6crWpeRUb^R?Krak*CI&Qj zbOKo#=m3rU9f^p4SI9D6-#T(>`Bwt=&iD}-*_!5nR zu>xN_O66vwj)C^%Fe=F6m5$A>yofQ<6+qb2V*_o8Ay9pZi8q;Sy(3_0CXwf}D2~E? zU#VQ>c04q&B|(H{@FtnDo^`Mv^b~m9g5-4Jr?CI*-t*ekm@45Tm8UWD+(2t$&_qe% ziP&W`Iai#xsTLeHR{&ez7abdDNstf>rF$7_ZDfPc+AIYq1{1TVN=wWMQwO!y(}Jl4 zH2a=s2AUI-7(D2`IF?M(g_LkvOIK@e?}lp?;M#N1u7RcmRR%Kg0OH}B(W^!-ty-b+ zN=h}1dT9W5Hu}!l93iuq^A!Ny)6rc6jfrs?_a!^H!X%amm*h>@ScODqx~|%mGE%t0 zMV&MXcd3G=ufrIwp=P*R9QunLvnqf)U%9L)1OF#6W*(08STTphjrQ!GI5Znxavcp( zs116K7V$q)LF3kaYrz*2qnKneAS`Yw$0);0)m!VaTB%$lSKJr;Yl3K9hO+ElwW|pb1hjiaPsiY&5|m-N zs8vUzKuUX@#7(sCDh{5l09U^oHL(6ML7r?-*NJ}1<3McNfb>)aK>FRlrvF3D80!0Z zA@h&XU8*d$Ha!UN!`~ z0Y3i7dPnd#?t2svVF;1A1XHMFje^7Q0i%|+TYdC694aOc(ei0|IZ-*|MqPkK;^%m?i%R)+0Mtd z{@K=RTU$H6v*XeB??bJ>mMyPq&9!{2`8S)Jo1SZ2#YgzJ{$AK52EKWCE-*O$OvLnwA4czbc%ylV1 z)+YR^+4LyD%8h8s>biV{k`P<1q6lYj^oZ4 zrJD>ESM+t0SJYV;|AjRn;J^_7c}&B?9pUD%PK{6&6~I~{=D~rIyb5a+O@ywaK<<%f z|G;b9PK*y`JUEb%RuuafLfN)L8b`{z=jDZLud&ahFx`1%=*O4|X8?kVd<5&+ z*8|Ij&U=Pb z$Ug`u$qks?{NTkv*RWaaq5%`B_X-=w1Wnmqb%i6QXZS5Skszy=mlLN4{!9p}VaF1K00K8CbX$lQ3m2;Zn8w2orsP#RPHTKOT0jgDft#$EY*EW*{)SVMD}y0qpkjzM?)d_r zU0wqgh7SUJ?c%2*Tw~IKn!CVPB|C2O9xq`ualHqZWqoXTTYv~k{==#ytDLVU!nE%;plOJAA2Jdeb*3+KGc7*`5UH#G$$iAw`n z7ATVvnYd`~gYe|_m(ttVJTTy9l#C7|J|oJXEz{{hAvQ|x$BenD*$|vAknq%XU|9FV zJr_9o?4~2|0AN3XuHy|eZZ@pT4C9weeT(TA-YZ2}BkmRbTlfI4TnC8tNOa%8PB(}( z3ThIyI9yFKmX-ageo>aiasnjpkNb!yR3Vegd39?gJbNA3)`#J&eT5sDWeZ%%!T8er zn%t8=TWcgKniGR9h-1&;fpAi2%ZrAH19$qN5Eo+L1jR4`A=DyNaXZRvtFVFe(L>23 z_|W%(vIZYiZ1a<=;nUZ5kQ4R}yxh@0CKde9d5XR&iRp9q#`3$y#D}~qBe|;Hs=`^h zZpEU50=4UR(z#ar2MQtzr?0cx)iVSAZe*fAP-9QPWQ-6ZccwOvh4#O|=D|0982bRK z?u>+$>!^e^8_f;$IqD)9^}pa?l+Yvk-9p*};winPM`1K-S9&Nb@Qb}Mm~yRfO+Y)i z2+%0`lBtMr9E$)qEr-QwC7M90%X8hVEp%p?-evwTqu5rD?9 z2o-AP3*Bf=csZq`t+lAnUxm$Jla|bTOp{XcG}f+nQVQ)FxTD^X*pW?lfycji0nK+s z?hAuzqWUTR$Rv)(+D&1x{9~{giq3_nucLczF4{5BQ-9n^0M2u4kX^I;IX~tS_E_bg zl#+y)1Nat~#S8`If_sW;TSL*^125ZbAaQ=yj+2o$nF|5VKyec!C~o9<(J*bCiDP8z z7#VW(I!bO0%?;dMZ$xPSV zlyQyC(kkKj@b|!9H?BZlhZyR^8WLhq!G?JFI?8nA*Y6uhx#3LQ#{vW6ukOtP0ygrP zRH?xRRQ$~amFkyOy~uA$S9Ep|;K$Men(_ahhJ}Xh|GIs#>!V#~JAb@$a_i?%@$Z8j zsrKczw{H33mapHkujThzPBwpi)3c2qZM@X*XZZ6M_77$r61-<|7#X)axF(~_uHdV+7$^av{1uc3nF=t zdDna$x!-fqg98U^CNVTJb}&71E3+`Y2VeX&ve(h{Ff%ofc9XDAtqxyXmPD6iYm!)} zWc29u-PqIh`v)G4QIbd_!V_e=8DJ4vVVC;~SdfK&n+J|}QjyRm=x8IKxRnm{q`KWv z6Tb3y!IoW!_c$J-grXwoE2<2J)~nzT)v(Yo2w zS$5X{`+a`vz4s1~yzDaL$;BzPtxKDIC{j1Y;XJa zog*;dZk>yqEV~BS6oGXpMMu&O_L{sYsM&4q+H5tk{WVcf=vFB5g!IRYEUCcKoy*RA zp|b=WC1v2ERtnKMW+LD=Zm}p_ZmaNlG3F(q-F91-O<&sd{J|accpO6l%M*4}M5RO> z908r#Y%Qgk3K*7Jrc%K8utlYCt~FJ#1v_b#MW36HKjDQ-Phcs>6^W-SykbUy>rSiX z(KRIciunsQFujqxQpUSSPslOfP%vf1=s4Cz zDd#!~q<1k)%>Ib^60%$lDt9;=X7a?>*R~ev=Y#7E?hJ&vL+(v@qx3}ZbDQah8HZ3o zfLEYhBU&?@+yQ36$Wr9E-B#oHRo02xTWFrRrPxHtJE9V0`l?8ghjN7}b3`thx3q)y zl_UP`kv>aTd*k}y3QUf~QZvFSZHlH&&*9w$y7>xWOccvR#vEyHt>-?4VxYCnB#?T5j? z*4Ht^G<;ZF8+~n$+-N_7vH-N7zT7r8#QVjhA1QNId_g&C`OeoDP$NYwIQ*#J0#T+_ zy7fj|3gVdVU04)IzK%5T-Rn?aNcC=uGG#sg z?ww9HYMhHiOXdh|Wk}6Q9E(yTOS!byyr8(iu^@S~l!XWfFsddJQ`wJ2!xu3)`4_$! zdP!Gp0$B2E>MQd_cA%Kv3AlW&vt#Bi?)UZwt{MBe& zHN?SaFso6SyMXu$lHfwY6so%D2b$PE9C_5v!Kg6GBQZNL91}oi z-y{-x&`k(SU&k?TzP zfyIn*eg`c@N8o8VQf43|^^8rSyyBINV^FQN3)Pc&@@!upi;vfvSOsXCQtrEnrXzZ0OvQ zLu8ZzOjlyYSb)4=6vU}tD0i6rj4WDz22xvBx;NLl;b(-O3=WnyMkn=Rlw#fcD$q)W1Aq``h1|r$|BGI`7?jf;5 z28nSTso+C- zAF24xiq`LFeWc}QTb^zHO!HdPr<&f-_(P2kHGH~Zss5Ym6Lr5|_XBk+wV$i~+S-Hr zKMdsmzpDBAn%C}oqWV+SPgi}as=D%O<*PyBEC1iMooUAR+9UJ!cvSBwbsmHwSAV8| zkByM%L{zJ#UMBYyaaVW>q)RfjL3K+4zqIi)!JAf>*E_p&hR&nf$ebN`F#fV`X^x5E z951yZip8ty>7k3>4$5s~{$k{UrH!kfo`muYR5-!4mwFXC&lpkhe$vPowxqI+e1z9%RZnF6u67Rv{k>;|hoSrJFauERG@}O#*y83t2%OCjRk|{Uz!1v&RqPGOqJywlp$vj*?ZbW9J(|&GwkUF;(SVs7@A1<+D3YFC zj7*muG@!@A+3HTI3~?$vB&=VRK9Qvz)JfCn0iUgIf~oBhO}dDzJ`f`pEDo5aDUwVP zrZ&he3`_*k-qSR14@9QySg;|-hk#>?F43_#4Dev398U_OL^pTC)D@D04$kqKYo*fe z>lGCCfS0o?bY@PxQ1}Shb>0&@D0=QqN04Kx7a4SRl<_n;h9vf@_t*}~n~x4fa4}7* zP?oC0>z$e``P@Vg)Tc8$C}1Ahh@|YN zC`@AHX`)BG9{j(<54WlR(W|Tp{kM;*KM`$?qwY-tk$%)%A4i;a%r1(1&R43UmRyTw zl1}xZ??b|g%m!7pmYk>JL^?tT&4wrA;4u#BZ zo4a{U02$hogN=ePotv>9g#L1iL@?NKZxtZrwCY9rGtrS zNgiicBzOgFpkg{E6wTr?Ix>)L;B4j~E>1Gr;NHlvoeT&=9UdD(Bu%>yxut^r0+m!b zoM`yDNIWNrYhkoCnn*G|bQHb3bwvU~M0WDKcAkKza{EAJ$PR`S05aJTX}UB!7$0M_ z9Ah!GXiZV97`tb6Unoi{X$ya8Jp1?w0Vx%eQjOt?O<(KIe>p=`aUoiouh}_4NwgSw zqn$2XA)IcypK70pi*c8faL}5R)SttQK*_&zD`Gtet11X7B?LyF&bAyM{1;w!Q7I)BgaQ4N>fE@)q zg~yDP6t~pk<)NPr!{xh-vfFx=cF>40^HL;XM=Dv58~PQjCOixA-sru{?DPUr?Ro_9 zK7Ch8#wuRY9=o>NdQ|*>yrT6RTVL1mwwBj6zq|RKrjIwBZamiTiH7s_@2dM~?Wgzu zY|Rhtdw=zNs{XF(j*5S*$XAT-Zt73(tO85&rN|3*&XO!t%;p_`7amxgOQEh0_66X# z#-~q+?1>#zD2-(z&pXPH9kwVFMS$pv4hd^?R-!tsGc@T&1NY-avZ-+1_H8?;PMW)w zjNA-RMdx^2%p~+x!zqe06UbJzdSyV1af_A_{y-^#RmRpcOY|pduJ0xRw_~6qo21_8 zA{3?1!8-#>UfJs4_LAh#tyMkoe4-=OvbOQ9^FmL@SQq#%;42kH`Xz>FByC;ayO2az6AF=^ks}l9ME7ul{p6NlzH8n!#S71-X9cz3UTFWgn z5I2tT4X|(k(mxDgX$*3R{(&9Tbq#JeMy}h17Qq$-RvSvJ(UyyIdfLKmvVL){ zXr&leu4oooXDOYIQQ-8l?Dl!vwL2&i8@e?Xxn`%S`L(&8sukumkL63ADAHWnZIhYR z$W;J*sxll*p0b`+$tJcjO-HVsyIH&Z7P`VP;*oxgAPPwhv<+oqPRw#hL@6MI;)>jCiz6YKi95JB7q`|oS?q-{ z&*CZqbMix7PLARxp#Kius*PN=>kB#(%-Tvk0yIuoG$Kj>1L8r`2g5;PeTC8}z5GCEf;ZBF^DCq_#U(sHdGrdO&##t z5CnWthIIZM9+b}O6XnTCR6aST-}4LXy-oot%5cKBG6~UYR5yF%KM=JDNXM%r3pE#; zKTG%Zosng`8?b|jML9l=QhaFY(4n~>s$v`JJ<~MCuLoUKN;5VG3|N6>iO6HhSGU$! zi3i;Z>0OsMyk~cw0f_ST$Ynd2?p6brHDI>KMgz4EFanW{zKk0pE+V?wWGA60f&q!Y zLZvd`Z>|3a8QoPo=V_`ZBhT4EOqz?BG~&-5AC0Yw!^SZd949mwOVT)3cy#azT|<@< zVAvRg6Wa$z!MCV&S~ywRLw;aF8O zZo9inuAc7ZqAV?~*MM;;SE+X0;ZCpb%+O`o6S-(7C7aLo5C9?=l*!mD6H1Sy5W`h4 zQ8QjS<^O{_%*+aJH_YzfAv(*L_wA7dJ1BNyV0?@Z$hj6INRtLDTUc6zOVBu??7;`Q zym1_1xRASHL*oDURs4EI>t<_b%LiJXZ2rCG?dH3izOLzx#7Ov8BnXY22+^=rHK zf41h2YTjORFZ=*MU45kL2dkc{{CwrRE93a|U+jPLS=8wqhd}uEb}P*bPD65zOCYUO zT51zs-vgz1hSVF9@PRjBj0LiyI>&DA5q$6YgtULpLSjD(yneDA8l@;Y1lK_I&MyL>x-{@wP9Dp;F%_*h8Q3`)| z0UT{VZ7`|i9|Zj%htBDdAPcFf|MK)B24fW4qomOwZ&kwXeKL}p82Fj`byzqCZe z34|avwnS4D-##@Y8P<28-4sO}vw0s>FAiW(!ryM)UlFzcm*>8*r+l^L1XGe)h%xus4S!fs`2Qynu|8w+71 zvd`;NjDr@uSjCmr`r7MopMDFIuF*BlT7HgqA4m^K^FQJ~P7Ai<{vnff4c&ZpQbopi2 zA+SkM$*Nh8a;Q?jF3#wcg8=jm<75_!rA*|}^9ObSjXAS@GV=BAWSDNCaT!wywCR(6 zTZlUhplMj#Iu~GwL665a+5NWeU0Y7U>&kXLyw7C)B6Zf0&586Eb(KBz`9n7%$qz1C zp?()!iSFj0?ief#bH21FqNR zv}BpIzkKt!+%X6fAoPnP5o6OIgoUygl)?T*mi}_(ceF$LY zRO-ZF3M(9sDePA)#qbohs6aH@2wwQV;l*5?*Y{FxzM!9=?1hk1G_ScIn9zkKWLIcE zfhDbz74R!g7$wR)V{pX{^l_y4w*+BoHtgJ>sWlY&n$qbL8da+>r4fK`*(C;UaY`>l#Y1 z$mqPOoeg&VioC@Rf=og_c8ae(O5({1nB5bI#F7)>PO|`E9_A_#M34Dhk(VrC+!kV_ zDzAilmxU=3tWSQXm@f~?@QTn)KvS7{x0MBZ$ND+<|(>t_s|(xEc-yRrG$ zmR1pVwfDo?aw|yWSOU}GgS?31I7$5D?-6bURz7zZ8q~aZdgltPyy?h`c3_QPYJzZS zbh}lBCZ=5rc>yZypy-(Zh}6xYk;4v9M9=xL$eS#&k&x?9Ie1v{2p#@Wo`UJ&W9}JQ zpz-AB0E#Kh7@cf;)O$q1C7GYwls0inbn7oQ{@;5lTE|;H-_qXviRNdT-qF<3`0b4k zG(1=TU+TTO&Dsyu9^T)$@3;1~R_Cf8ulh{YTdH1H`8}1fiue5U82Wi&A0}Q)3w_%x~UaV}DnO3I7HZAfKp3kBP>lp0l582s? zf6U}y#YB=q>fKz9)v97CZ5In;I5NmDs2oxB!l+Cl$Z7SNa7fXRQKrH-C7jBYArs<6|h3P??%Tqhr(XA1QN&n6k*RfK^~~UMwCdRCJZ#egQfZ zjQ*fI;K~}<>`h7$E1sw}Y~tZw+PYA>>&CqV6&RTv+$n*x6|GRqTwaLa5d0M!;JCxv z9a(@oj=Z%wlCukv;uauz8rokPWV;O`9B17w#l7NrStk6UVVGUOVk&H4A}W z0eOtsqjXdX62*oADH?YRtAsM}+TbG;>>|CXkkYJcf?U(YI40yh>;|k_4+k3yN6WHD zuPv#rrv4ZE0^}#0Ek1*}!{CA<3s)fCD-+b_Q9pA8-0HG*$?dfzTtVP?TJa^;UkWbJg8BMoomoG0} zTo4>;Kbi%81hibJ$TmdA0$*69_ z-M_*b(7oc^-?=`h#vN-^D!fwE>;rFuec(|*2n;e9ns;Y`6glB9MZV9@Tu0xarvW{i zK^lWsJBbY|oxWz4x=1iIS$8|kA%y*+?ibi|%+WYUJ^#Ke;2zIoYTs+8Ha&zGnz@Ix zUT9EA)IAYL(;!YzyW;Hq5(z~2j+!|Qe{ob^Uszu5R$#VT2)j@8l1v&W9wHo@Yz+Z{ zW`E`Rk7fbh7(+tCd+Y>>;4M}TlxP4Hsbp-M@g0EcE>f4k4$%e_kI8HjS%uqace;je zyUV_@C7zj!TTE1t%Uk4FF+b$8Nd}zMyOssQ;{;5O@3GSsr>U62fV(4SOwGKadVbNe zx(RjyWss$kU^yJBe0~3wETA7Jki7lfy9|6PmQDiFm)KeHy#Wg_Brwume#kdx0R%Y& zIOccTAyqXPZjrHbjdWe|K(9{cShc232R5OR9et8GNuZ26t~kJUnO=*#&qmn zM|bq&(W}%BE{zgF#;Mdu`x%roi7io$)Ox1`5t)QSj9Ib&AE|hIMeDOIzuNM2^G`J& zZ2FC+?`^u&ba&%#H-1ZFPs3*$-rbOHxU2pT>I?PH)jv`Hs=Cht4dBgn19f-QezNxK zY9HJG`Tak#|N8!iYyPa}t^0m=-`n@yR{hcHvsFJ|b-Jpd^5-hwQW>rI4Gi!K{u|9s zA^vr~{cWsdQoHxm7}BX&6%We|e~BiOtf6BG)$>#-c*;mz9%aNZtq?H|j;1>yzNF{) znd~G8uC#wmd4lON!oQMYn4pvlir`aGd0@UA#IG&k!E71@e?#qW4G{*LM9=uClnVUI z5|RqwM(V0$&R~%F{D&caS#>F60&NuG8|vZqFQ>; zkGE&s=lsa{uHmvsjj8kY5md!JTQG~DaMbB zggn0?iwbJg=e0lUrf>@A(3D^>VA#bP3Z~-u#=XLKA={u6Ftp?Wh}lvodKwa>b_^t1kR7LYWsqa;l|mKs#Z^uBI8;?V##va1SVBQatm{BCcM5};-wtm?DkJ()!{ zc6_LPnxqhYoSee{!Rv%MfFK>wpo-@Lg96VF*$lGPB55DbqUieANc))piT<%kbc!tb zdVWoK%0cnGN|Ufp5I2NvI?Oa{@+vOG-J&4pI-Eso=h&fk?1lN> zoH8t1MBFB4j4V>2c_5wiWYMxYakPEB^qb^3O!|HVo6_d1` z@=4FtjK$!d`GS)b^Wf3!<5*j7d&K>IY7{0we#P3BKTJ$hK>l(wxiDcS4DqGt7IXZ!u`=a8j}K73CB!kt;vo%VFKzux`w z6dV}pr>Bqs68P;CSyYZ5oo>I6zZDb~5Y-9|s48Z|v^U6;z)_Qe*p0ZcC8mHBBpIaoZ9OFI&~{HB-80^#`h!hs{OXtYcf41DLH5d)Odxbz&dK7USed!)%uAzx0ZbKDiA1i%wS2cW7vqXywNR=*ObHY~K^bCv5#C!VSc z;Eg31FV*uy!BlngF0?lQzk?0ieI1bi4>JQ?DQEVd?aY|T_hrnCxqM1p{IX_tBYTjs zy%Uk2vJ+zk-dCiOSSozMyosC%sTv$fw=d$#tT{h!?b z&i$wNH`M%e&2z{Vc=x`weLdBmss7IDiK@S^+NnBO`HPil3{&CH=9qVWtM$PTyGPj% zhX|V`$`0{Nf}YB9j@|G%DX&Lqyq3@+G~0MZ%DPMpu%dUf^~~#nXoH zIb(*JjEl6AK|sVj>fOvC@jd3Bc<@6-D->(PB=c~QnEbqo|>eAIQd^KxO8(8+jN z+Fj%f$TIWw7IMgiKk487;0KDv<60BDk0p}oiy9}D+Xs7L?ZF=?8pbZ`ELJ5!_dRFp z)_4O;-0)JlY9admBBI6q4j$CrL_^XlnX97ge(+6>DD*u3L5Zuh)*zLrLJE(A%OUqy zSp&Mz^@$u3!Vk|p_(Bn_$@n;GSK{M`ph%m@EBN&08vM?3dn_1%H<_z|)ZKb8DdQ_M zivgkJC?plJuM+)fmJT7u>54$Xvbh?FYV<4GaFRBq|5bBYuQ!W)>XRoPyoY2(m4%AW zOtLZ7q9U4}jtSnBS`7cJB{LL$eDF1HMX|F3B7?;_W;?YidFefoeG!`I#DjOc zk??Z_wWxyNB7-u&Z#!7@H6SN+BB|%^&mxI;#2;$^8#g2lgqUCKh%uW)rdnDYWhAB* z2wqUJ^vOJMDs(g%J|a+H(&K{XC7h)srFf*eZmhNcwVQ_?7)~AwkO>16v~ zlFD=}HOgqL4sOyrBKytNXhzC(2ga$HuR9N=A06xmXWBm({CXU*8Xc&il9mYM+Gu~b zRPiC3;UIo$y{pHw*Tob07j8Y`UnqW=oJu)$u|JC*^vRL-KM#Cu<3(|#*&+2OHW_ni zKYA*prvRYDG5&aV3!9p3|1(Dhh9-(FV=$&k01pS)ysXvamvaC3p)MXdncai}9c%wn z_qnq5${e;f5Q>i*$}2K9Cq~-;q=W*|ZV?Dm-d%ddQp!Jo1C^v!$P7Cr`hL9e>^k1- zTKgY6QgP+685@Q`K+RIDP5we#p&>>oh7>Qlb3S;FW!cg_-u_39!GDSLX_|ImG^W&`lDaWxG9kRkA{1O4zWtbvR5w*P_qKxR)V19h7= z&EU(3$OLtr}|^%P`-6pw)~TU#u8`dIO0?Cy#7 z|LbVznJddBFeaD~-1+v_Jtw#BvnAh^z8$^nkoX$TE@96W+JDed;AIz93C|pTbOXw| z(v1`hYvkRxT#@sWBbdxy!h|ljf83E1QWA)yb6)QTX)0}=*>_6olGkKO^8Q(}=`8w- z4=uHS%#pRTgo{e;F>FFd78;`pJMTetBzqB5&$oZnQ8lW%rOu0I+)|E|@F61(0<&D$ zSC!7Rf5g$#4NP#4CZ>{biU}v-j!@4qKyQWsZsyf3$QHgLJC=7L3-F7W-`f5yj;xCF zK*czXD~%LAQgb@8%g@tUC)jCch~kk7^TPkN4MDuEEWjtm{Eqf_h6b?{*T{d+L>NRD z3O0qtsWg&e!AKoMrQ~esP$ieBWvz1uB3*Aj3&e;CzqTx-ymT3EIv)Q zf1~?!^b|eV_zYEG`f;CvIvShAbA~DJdbfyn#itH|c{Do<<@0d+zYWkK7%8yYrkzpBBD1PE@Gmpuc7-J|Va8~PraIgn%R zXLzyD%>fiE_J0Q&`nA5db*;6o<((~=mSfGo+58>N4>kQ-({|(g8eiY=Jq-`kf4qJY z7XRDo?yUW}+PBpn-Jjn-Q1j3kSlM0iMTK9Pe{vwfi>#Yy10CPv05XW}Y(nQ0g-WDQv5LJd2` zD=d9qypbH7m|ZV+Opw6ovGnBBC=_>uy?|~nkjIYaQags{h2JT;##yaGSRw|--1196 z0P)f}w4ZACn>)r0K{D?$)YSV8Fl~4b-~cq8Qb?3(HrlVw6)A=o@T zrkiJi4~wv(fdsxx2o20s!p%T`^WKnqXkXQR$2vy&t>|NFd&DkdWLxpiOb#x`F8@Hs z2!99Wfqf8fGK^cW41*P|BBzL&O3N=Na%|e6t7)ObUTQqW|BS=){LviThwZnjJBB%k zsBF;KgzK9D^bU*qR3y|S8%<^GN+KVDnpFR?a&O`qK4oXOH_Kx-*&vh{5*fAvQ8AEH@(HZPpdJ@5Y zw2otit5naUc9ee23}P|stH6|09!JlAAO}}s`*v5y8%e;(dR1V8Y4V#5W?*CHQ0~}A zL8%QqVZs^c9EadJ=zDt!fgd9AwEb+{EJ-!l?)KAfEGZWzeDgecf%NA3eSs_%FV0^EbN4X^#@Q5JeN7y3H z64lSxUloLu2VnX$dP6ys^F;j0j?ujK6eSvzQ`O*#Qt9B!L|BJ>-nw{k31tp=#TW2D zag9~h0WN?! z36UKt<2rFo7+EHVDjxEKgdrL`1rUY=TmS9yfJhnbktAPKQ`}g)xCtE&tb0}AQOP^f zJOVEL9Ey3`{i_}QvX==|d$IThQwdDi=KWn*Un2mJPDQ=EuyCatiWpfuO8l-dFskfJ zE*KuwBAbTGb4SFPVn$#b0z=`A=TP?3=~s8e^*p|GDWKhV-pSnS_f;KO>Nuq-?jinLJ+>G%5QBj*%f?}!puA}L-?TaL>@A(N&PQ}h$*UjNWx-e zS_Q7S%JzaFMCD1BU)ym~h8!3j)8*;7KZbI77*)44Gq5~P31V*LP^!`84|P02s^g9- z_r(7EBH#fq8I?-NL}uI?Y=vp31y`O5G3lpA0g7IO#hMCDKj<6sf;PO_94a(A@ET5V z+_7;S1((B7ol4;Dmp%&@IyHu*BzIt+OCnC*QVshG7h6@S;vj@ zU~5(*q>D{|#py8_v*BuEyf@`g@^IKscN~{pOpQ&B6^&Kq1YY4@q7Bx|Z|3tklr?nv z(;a;resm1VBlMYZGOR7-fg#SXTx6lQg^No@PctIsu1^WgP42%^2Mt=T$Q-4e+C4W%BtKt(_=iCO z|D8%A3!akQUo?iup%mf3t>%u$IGd65U^@8}=7MB1d6E!tq9K=xKu%K93F)xTC`X8d zxY={oe6B?Zw}E)P3U9%@Vo|?kgE?XSQ@%249Y)&-3@pz^_J(gAlF5#1#WQ%$!tzDD zeUv%y?e}s~Y~@1s1wVt*8JN3buOtbs=?qcRSl2zIfGqXKa;RiD0IE@SZ6^6haA(}F zNh|Oip+sQSh_yi;1T}x?4RV;?S`L*72mHZ~9#Yh1;ocM_f&T(6EmAdyN+ZQ+45D}i zXB8AQPv&mhSJk=D@hAsOj+(lnSeqs3R)crzfb3M|A;$EkbFF+mw|5*RjcK;4I7M3! zJ@(dCEg3yCN3BQ`F|ibc1Wn&P7*p-JmVH(CAL}?s!Xx6sGHNX7a5u%K^B&1H<9A~n z52{7Lvw}U-4;Huui^wh1MhIU7yN7vKb4a1T-yiFEJ--=luM;)JP!EXDCqhFGb8ro9_+p(HyYi?wjejhohW|^$WU^_&D(_=V2F`O)v=` z!q{+(^)*%Z`S*3aO6}rgs_Z4;G-ZYBTVi%%9vRJh(6uoggRMKauzX5i$T-z?#{Umh ztW~uBM(f8~ueByxaxK%%f7N`YxxMMVO$$x;H~v`TM&rJQpKEx&{`2+kuYa-bm+Ib9 zccAw7YCl}NT{~KP`~F|r|HA(Mn*UaFqo!xyuk5>ysQ>4xKT@5n`h}{+s(peJ@JWz2 z|2>;~rlzXbzpIN2nVlFzI^K91mj_vi>G4E7a5datia=LsaoB6JAACm!%$%9^Zq3l= zG*j}HbHMF9>L2d9GdKi5;6ej{&rzkY8OdnqbDgxl$l=cCp024npA zf~(<-IRMRe(I(0*M(&xr=(=F7WR2!N5wdbD<()C?;-Ia^)26t!R5(lBmTeb11XvneJ)~eV?A38BPSQRDi(7=1uUX00q?5 zfI@?%0NHeg?+f;=ahvaXAI{~_qVbS_XIH%?!Bu`)Pt;w5^EotL?D22!sGBNcI^v}D!0kRNI{4um4Vlh z>jY242y#1ac2%3tG|YAcL|Kd_M{WT_1rYs5$% zzZ0==siP32^QDLWPSIwR8->QGzJz{Cp@W=q@t3PA#+4fc47YU_mwF8SGi+ z`JK6bI!TW`^aW6~g%1*>#0(AcC`$X`nqOOI`i3H{DT>QU*262Yth&$B(YUgZLG7|w z29!H0wMmCCjc?i6LHHOhUrftbDH`6FkqvCG`VL2r8k9rF9{N0{%5Z{|*-1?>{OBlE z#}U%Ak9kX~ftSpo=;XkQ9dE(!0q!au_n7RnY=M*sgni*~OOS7i*DK&*_uia~(d;_k z@e+v5qD6cRkZQxo(Sd^3fAb@~O>@E1hCD%4Q ztx-Cyj^$9ba%iICMf@w7yxU4n!HLv4Kv*bMf?*wD@6Z_0-mb?#)bS>KtObSp-W&zb zj0vIkG-Pq+Z!u32#8it!h8vi7O1!h)U=BquhgLdX;Ak^Y6NiU2%R}Tx!+ppJ1WFNB zQJxL(LwG4=Csk|#j;6^B~2r+LX;O($-O)?Rm0N3k^_Zp3Sfp# z5F0zjA;oj3oH?55xXA%@G}Vk#%mYfOW1qB{2d0dInx3hS8^u)O0>nfza%J!W^<`1; zO929J${nK{=6uI>Qut@Ts;6@(-HE)|agC#oj(s`z)UV9-lAEq{Y>^nCV<1;j#kV`P zFn5gyfgkXH4zLy<&k;G^20|AegiUOlcEM8@P!3FWbc{H%J1+_l;qsTP4vEifAe{s* z{ZVrt zxL;5~bohmiW&9KPx%PlcNPy>U)25Y^z~bY%%ZkI7)B)qm^ZeK39)&Ao`_7Kb9Bw8J znvyjc7+gO>>vofE0wo6YY(#_`C-^$cH^nQXUL4pYlw*mz>Gxq=>%y$@@Nu1kK9*qW zq?bdLQY6_ijk$m?6K^32`N9vl2%BT6qz0TPkLOU3bpK+<8GZnV*KlHhb;sHVV8eil z0KSsGT$T)cFNekVGR4pP*;OM2HmR`&5$U@O-4hKnytW+bi0(hsG0ES-g`Y|Xey4sy z`@gedh5i59TYj|VQp+99KheC54gf#XwBB@Ii?blkJo&-=HR~X+&5VL*VQ}K=d0VRW-5QJ@@D1z6+Z)#rToZ| zq$>+x4zFke{^@)b3O%+nJ%19O0YrTqWu#_!CCtd-iXcKwZonKcWl(&JLRp|U#n%Gu zYK(8%&EHuGv>7h&Md)OBK6L{=8lZ@O7ETIY2bgI<@FBw?_|FQkvnP){{FBFe{y4l6 zn@2jTA^dq?T_WjV9_jbzPxky#_&c!|ktz>SO3Zp@TFXz2=_vA0R48pO4(E_@pHBDu zVVKfrVi5dW;Y}d%Q6U_tV-3C`a3ZV}WK{@rG>0_&_+rl=gvk+JCwWS;*v#>`-8FDN z&?X_N!2sb2y&|$2PJHC)pWN#C{StyG(kvnu0E6dd1#Gucs(x)wlJ`e?elJWH>o#@c zrxJt7Q4vSf&xtbzof&qALAC=7ApdwRgZz%I4Y~1`=7hAodhI)eE|zwTiZ= zz>gDvYmDcsoel}Ynj9dulm5t&-zuI7SW?MMRsf;#)tbne90~?zGDm(hcs7CUP`6Pf zRU+@1_o;Maa4``rkmL>FZ@3fQg&b-Lrd~YqnIK^@T;3&p$&1LkRfcZY1qgb`)pCPO z=1^oXJ$vLgLW7ts)U#*VgPyz_#UWUh%>7Ib)d!iGBflObi#)N>#PF>0^p#z~CUD%5 z>4QiB;}hlPdoG81goW87|Eq{FP|efhP^%2>GJ7tmTMWMMMSUuVa)p`MBmXl<9b3M~ zl-+jhG3&EA6fvYPANe0ay2aZ8J%Wy9fXFBmceJFy@xO z%ph*>Ll<6nU-5t!a;Tm-cm2q(>@uFd@UM8p07r9&aW1z?b))jgr-P%I)u2cN+Gp`O z?7alM0M(64Jl4Fd7|YeTS753&#@fJK@y8c{#%HozS?_VKgY}iH!hW9 zDahiH|5~2n%dWiaBN@-39t11@M0uinuUu0Mt$aK;FC>3HNYe4Daw{)oP{ofeotwkb zmyZ0G@+5azdMVZ77dDZ*fQeo{qR|t=x>LEemy!%E{$ege7>@h8?uLCU!DQRhU|dCd zU^~(;1&@W^K6oB&zCn?rZqI1dQtnwstvkA2Z3aU2Ei5$Pyd{dmup5^$S7>Um_S1$N zA+}!mSj#yy(md=R?Yhg2)z98fr30~qd}EHySA<2F=;jwS9PR(E%EpS;?{9so_0=t( zZ27j9v6kBApKkiGrp2bijbCW|SmUL}+Z%qq;a0<=_5Zv6o9c(^{-*9-b)&WagbaYW z+E?xWPy4s`kM6&t=2JCqL3hBPK;8dc)xT0bU-kEu-vzS&U;58)%^x9V#6q+!c=hR@ zNT<#q2$Y&Z8AktrEmdPC3Njdx5=pZoogPoZ!ZM9FC5FJz75cXfjf@`(ku+W<1O*Ab zA9o?Fm^HIHz3r#+K$?lY^`+?jq3<~*xHjnPbrV{YfCGR*k0GG9jbv7l?2&F_ZfJRF31HqPvV$&F$TTDDytJ~VTLkzB zqDyBGyjj6+&r z(Tl%f`tb%*CcM==s$b%Md-T3?mIhrQ`M>Re8~7`-?AJ(z#|6lxgHxY?rr z4nosN16HcJvbG1{>A#*3oSSDAu57>7ptF9M5-B zfJg5Rj{zsyxC{eN**Lv!>I2?1MuJtW6`KMKbTFU*W$*F)LDZ0)h`u^Z(p1C6$Hs<| zwu*HQA-*NX5~N~e-aD2@mCD%R=w0E@(_;gu@QVSvGKE&!NDoRQU!Ts&&9!wT+OzcN zaQ;E8rYriY@VC5mvzmbUOt&<6BHs>u<7D*C@Hb|<$FG}n`;9cX9pTTynttSa2FO%x(EP4fipUQNbk}7oe=W9(aJCpE>v3nAoD>>O;-=& z9nIf?g>*$L!k?M3Pow+@$#9xmv*#Y*kkk3w0cdfv=O4pg_1owGL_SSMSBs@J*?#mC zURvlrjRq8`l0eb|6+4ly-gb2!`1;9P$)3Lt)8!(drx0gf9~ZTTfJ@)VQ&T8MNl-?b zO3EaJ8$txsTFt>ip`nFGu*|mPIMlSD1Sb3&j8`m(nR|g>e(}*Oq;Fg0f@TInpbW(q z(|s}z;Qz6cJ%1P81al<9CYcpuPNj$_K}!;OWb=aXMd5S=jSeVHy(V z#{Gn|VjSJV=@->^ANp=6aZH$ucQ#)KQdfKaGE53K3V^%}!7n9rPW%6%imMeZ|IqT| zEiW~HWAnM@)}~K2y{qXAqW}K~_5arzA8YvAh97O%Xy~l}-TEJ_zh3u+x`%4tUwdZ% zU+wqz-&?a&6W#aw`@Ur#k{GM6Rd-hXc-2x>U8P_7IuI@QpWl&3!u-kYd!xExUivH` zgVeTNH{s$ySe})f63t{}HF0)QhnaLTJAEY53MG{XE=KHXbTB*so@L_fIKXiF zxs?H@pH6$w_{FAGv*Nb%V5<--m-0xuAHxZ;p)eYdxQr6R`sl63KTJqg2@<7{g$J*I zEwpn+rK&qt1+muk;AZ2!F^{Z!sNJy1ibo1s84$W-;_n0N=zWU0^C0yo?vnca7z${5ydE!C``=uPc{WNT@;e+YW+Wr*#w1 zrz1ahLdEOPBbk42ED9k}JQD&8AT^92a0*d~64a#m;aw3UfbC(F>6gr>VM$Cyq0AJM z>4$EkEKWQgv<+an7yb?t7Q0hhH=)8W~4gavwmxR3F*i{7J6eIIs4N?(I>++5wt&x$^{gw&yFA$10oKc zc`WIzRop+7hi>X5ll}1MjMr3U{MzWrFf|di@H)Wru3ZpFKgVq2r{iwVojw6ooveXi z55|EaX#Mz0b&06cei z;_SSXmF!*3kFd$;;ppSxQNS305|aeF9h@AP8oX-2b6E+p2n7nGo-5TiY#UwSXc0(+ zRP#r8caVXMl}lR}WVJq%N0GqPR`hsy$Y3@NyZWI|sBk6TeB*DR@}-hGL>(ir1{`2e z4_yk7H@j)ynkAJjyKM$>`DW@6E-5#aPZb zur3~NFpqW{BV*AcyHSwroY=4>6EI-uCCMx=t|7_r(uy~bN7X}mFnV}5N{P{UYG$0h zgDf$mXRY77BC3@mbS#f@2zV+V*^LlAO=v6flr>t!!z4cW6ZsgHb37W3U>N?%rcK8~Y#R4c%U?hb#AZWcg_kUVKfAvCiv`Oj^T zIz9O(Fy_(d!{M)tq@kD@S2rF2We5+5Yr~7?QE+hlWV9>%T|c@NW22Q9&Sn0@$en*ezAH^1*h&~Yh+-$MRUmJv$h=8I^u3J+2 zqUXPqKMED+Rx%n16F_G!MAFDe-3IHx98evgT^L0eYnM87s8uj5F0$#aa1t(+6&eUN#{Zaf;JZn=wtrm$yX$d_^DAZ^xYl;;q^d|K?h5!Hh ziV?>DPq+MX%T`NO^Shc~)%0CWHH~K){-WW%4FmNbtgotjq4qPi_wWCvnlIFh?fdw? zJE}LTezWSH%5SXfsrV2+HveVv$V?rCTKtP@J83YV9YHxO0lV2SBt3(s$Y&8zhKNVN zcRaI>D=1u~uPtfJbQD1$$@_-LSzJ-7_Yj}FwRm8jUy;AbsO?}>ClI+oq|kG8ko6FW z@?)UDO8Oo^8Np%U?NXK-1^;2`SOy;q@hf;qr9whv&PoQ|t@&G(dN`9uf@a5A!nsiK>??yc%lOzWjBrZ!D^Fk4PQYSlS?-o;B74 zs`Lzk9|DUwO(cUDC#B;3ycI>VC)oNgJ^xhx8f@$BSX8GgaUQODDa?(; z$SL4Z6A*XuIyOxMyjoK9f@(NB)N2YvIy?pV8I4zHf1CJ|2L1}VW6T638+;zVUpU8L zIbbClP$R72E*&@RSPv7781fFPBE7VNxWSfRo_||@i$=`lsLqfoUIlFT!DRneW%~AI z%1m+p+s2W7pX|p8-<#j02dp}(Q>=>TG&y|gpKVG~=f1pjLF!;-U`($qzrn(d+oL*H zt9W|Jujb^yOm8q<-&k~Z?;LZ*_?Y8e`E^#$T#xFWH^p;|52wGHv*gRNGou`U$d@58 zv5x#z^zz%TiTUvY%>R_4&1$su%r8^rzjtOe_bUNLZGv#+PQj<1thO zNN3|zLb2ZQF|?)>)~f?AmY+~bfiPkCM0!usdc#4YD~ z^Y!h<=znsPv6C=bh6cs%hvhavv?AHK^mq(-6BxnHfJ38VeL=J!0a8_PjV?J|t4Wvz z5|&uerPCEzQBOy=GMzP-LqT-k20SA`Lhgnm7Rg@7$LI!6?8|Jdc-Ia;;632qlSk(C zbqLF!Dl>g8FBw2582QUhAH%LJsiGvcaT4PKZ{KY}T36d;Q64)c zTKR&2`RF7Plce)^^3>F1@t#_V3eDGg`z-&k8>y6Yl(>l|r8iKVy`KM2{&G##ioX&4 zk8ThUNWng^(&$mSAoeTxikhs+rN&?srwfduEJlCCO?UD%%d1(Mn@X}#fp&)u zYs3_dQ~-ambUEA*#;P5LP}zZ+EB8VQi_?wsDAp^V=a7Ayx z0ZF~v+sLEWK>`lXA9nMaP65l>#^D&%<~fNb+k?0S(Vb7p?nt?yUz#s`kaHtK0wpLE@d^Afe^XxGV!N1Y6*t7taiPC%v z(ef_l(Fp;`?a?1}b6^mj3`ihCxN5gx1%JYX1hG@71>2l+LQCs$O83RPl1CQ(w0~Fh z<8B~?VVOIj*E@-*o;`mK8)PH;-cp(p8xQa%^pQf$DZe;e66){h1Jp->tj%X(wqK8a z%#CQdSIB~L?3E^tWf!~KPn&t<&ky;X(T|oPuDYkFR2wd&n7X|g7Zw&_b6TCr9xHIA z!Q$oWvgb;`pz@x|KLeBS#pp-es8)o9j?5ZGmep$pV!1qF?!|Ohj|}nu^Q@wae%KK= z>{SKK3CY7aC&OZ)^D(hP)j&iwi@|ut1;Y6MgBAIT)_>O;ZTZhF^UYs?{omd6%S~@W z_Ww^d_BZ@x!|kRrLo| z@2IM*{N~ELKLQJqjhm0vj*PR081KjJZ1q{h%L@+@#mBpv^O8!O8X z&`4xdUdloQ*$0WsHR-U|gFJP-QEqdMWj4W+j|4V^Q7y8LKq+#8sp;_ETI z%}Nn+ciZjV{w-gt_4Im|3$N!5zB~Fkcid{BdUPZ5b{Ss*TG-3135&8@I=1IG6z(JM zpNRfNcsNr{W5sv*0nPR*Wfq==iwM5xD@~W(b;TPb_!fLr`Utc~hDYN)aJGOP%E9Z= zKM&7kY8094z$c0Gs+XS!dRXxvEu*KD$fFIf$2U~K$2zhX7o>XBb!F0{^;OtRLl6e0>n28 zz>iLXN&fL})S>TA#&)5OOcZOGa5I8d0Wwd)r{PeLei#RzKr24m^gUfbhUUm(^pAEM z6lyhKA$A=$P`edai+@`I2+eZv&wH4c!kOefwH%W6a*Nh z4$VnBASJViUcfE(C9`)yP!*u`i+h4t${Sl3s8Ed;knK6R82y9rj9juoVr-!Nbf#R! z0ZanwLo}4VxdO1C<9=)O_ro-`8Al_aJVh`MI0xqx(ylaV(rJu{`FAU1Y;9i7G_>Ixu4O7(23>a;g_;BJ(VwcBfC<~Ym6g_l? zQ**}7Y=X0!m3bQl05lK6oczDxp+;bnC($sHBc;plkwv#J*%Pud!^Y@|UTq8Rr-ABX8ZcbTkKB(2z6#gL+OOVhp_PYS8~s0Fs)i5l`bx-+FRqd8(uEC; zMJHmp7t`0)e%MNK@Y&iKT|h?^8nZaJVS=dXdqC(kqnftiwx>Py)3}anc_=+3Bqo zfFC^s)%mx>BO0vcaUW8PK)t)SEXfvCpdaB7yife>#Z^!EdJJXwlV&FP_>s(dFf8?B`?aS28hZ$wz5 z^i~S!z&s7P@IS+YJ6SX9URwF#r`?MRDQ+dt`E&uDmcQHu@U{% z@cguxgpq)^kLz20ic}xrOy$*WJ9u0nU>V-#Efp&HGVYB2_b_pLVZoQdHp|l{Yu-aY zDhft=&lD<<#qdJ(SHeT-b-dh>ri?E_xFxI(vde(B<}K!5qKvsa`swfpkoCx5Ozoj* zBRf&2TsnS5+ScVD9v3n95wd+Y|7Hs2n&_v(BSDfLCEazY3 z$=nnDWOxX@7^r|>jJ~WL4Y*sP-Kib|yxADD= zbqzBOjrCt!|C+k@)V;p;1GQcIKf1rG=7Tl8`#!O+qUtZI-ct1lI{s}}9>C{ct^fRr z!b$FQviDVLBXDCZE49IJJ}i4U&SeV*3J$H*HFsAaNL42|7bdrcxJftQXI8I#x`4E+ zp%;4ZR5OV6pApuCOfeM(Na;+R7?i{LYl))tF*14q!px4y*JL$S$bd$j%x& z*L#OMX$lQCHAcBDifx%akxEUCi)+U@3I&=@ysjFAdR=vW@SZ9lYisa@-rF6)B3G2^ z1u1)Gy^f}JD_cY0PHKd|m5ekl;cjS8BV;EsyC$Z4Z&SplpsV<1kFxXbUR};gAwa2#1~Bo-K*8PY*bw#u6LB?l zFa@N;mq~k&6d2Xh4{jDtI`CWT`S7+I3ILN$-x}%FMX%7w=sMeV5h`Oua|G(2g8eML z5bOd4qgwMj#bqTXg4D1kW)@JHI zjBkub!Tzlf0VE&q%)9pXZ)JpCU@~|^w3&kE{=%zY8RwW7fI2W69Sr&%1iB) z@`hJQ;?s6I-n9af^k)5gdK&{{skXt$+YCo6RUjQyg!Mzu=DFA_Y&F|=~ zcZ&uPFAQ57_%0JTkS?oyxut;s&PO&^yDW7e+4{wc0ICJqv%}Wz|JfFmfFG#5S+P>ygpTAzeHciXZo=G-?4^1bmot{^8zQ zH?9flLH8X=qWp&;6WuXDpwumg4TghNbc{AD@&)lYGp%K#j_WFtI=pB!PcKvRwfXDM>%xTjRzvM)a37 zoW9*MzR5m?@ZLg!-fl6#0?<1JT{25oe3 zWcyOUv`wx<(L>dOrK`|YQ+3t9+N&$YgPh9J-Gf&$Zozh7ZWPO{xq-n5pyQ=vu&k1V z*{WH(Qw&47f#kdNs7P1N+mm%PM15f$4s%kMqHJhu%4?? zzlzc_7hg$_#a%TZmJ~TfE4>60P+4O0YalFh70}3i1Yw#ebrb&g?B|^7i`=C>47aEji zv{;@($X=K0hvs3Ls2ID%oNeh%m=f?NQfGn;^B6aIpKXNF?1J}F0d0{7{diOt_H#rr z#b|>OzZxlIvEki3g4$;Wj|4*`ON(%=oan@YT=lAZ!KOsj{f*M@QU!qWz*(f>0NezO zIMN9k<*jbxt}vMzs_u?#7u}Gj{hp{s3vgru-ZL=W(SAIz(On$I!UND|e!d$|3W?or z>Lqa`wY6qtU;6ki*u!&GI^Y907d9TC4e`M0+5^)6 z@BWIfuV}r}`T)@XUV;bUx0+X*BTc{4^rpstYn zw&Mg?L2GvDQ-!Q=C{pc*BO4LJ{Na6ePE>V|q}oF5gk<8me`g92ddWhxY;8)sPwyGr z1)_UD91IIyfsiMFH}(-~1VcX85~MFKTU5sRAGGbOE>yCujQ#B?F0VkH3YRM%CMhQ@+jMs4$QRoF>G> zVW!|w%|`|bKyWy5zAs-w3XDqS;bAtS{L0P8AGBT%?K&`V&tEM7w&BFBuD)DZQtXI= zkjDZXWwLY$?lDOR;gGduw9i^lO=?hxMTmXG0@=KoZJyYnt-EnU|?_P*nMe$A%mNq!5GP z-LXFc+o!l*Ae$kZKutyAjMP;0Wy`HNmKq$UlSjCYX--S=PoxL7C^J_8%7{)@GFxE0 z2&lQ^@c2KtC~S40iqa`fl?y0D+t7iQ3}b=y-J1nKQpEhDeLE#ngu;~=oRjJ@OUBh1vS^V67h??H zxpU(dudT9#$b`Gqi9pH3`(Iq>Uc1=6F^7E%+#%FAqG^h1J8cg~wprgK9x!(dHJ}%C9+TYYYC^{T$lD#-~n_pqh~NKI{pAJvJ}r5 zF;`spW()+8eFAKxJeVb4EyBxbitvQ0*n&*4HjrHbgpjy@Pv5)U zs76;RO09K+8nItwjVix{u8eiR2%H^C^9sXU;fsCW>BcgT2`Ng5$S^9(6)M;$k#>+N zEK}7<-&Wf*Y=k~XJX_`^*py=RHIXG~9tS+mMu=G|K?8KO09cWc^L^h@Iyt8yGcZ_u z1eTWaKjUSXr};twfFiIx`o7&!RLg`@cN|uJsE?wZu(nq9CRl%Y;O4kcFg6R^L8=7W z4yrRg0ga*)DQy4^n|Yz{+uY!88CXP&dtIFH?v`R5ZSJy`9nyQea2g;6Lw)aZqnHyF zo>{zCiaP|h=#2#+btGr{{(b4^<`Ryh3ayxmxn0tRH9%~wfL5x=h3dUmQKPvj4i!3X zSzLe|R{$GG1We_Pj0FmXsTkwY0_;TKtf3hy_qn)P=>4NUqqA+awDtN60R9+B_P*8) z2stidh;Ju_-brxaYw#_|KdH{gj4625t%ySMEYLq<*L&}AWNgMh5yDO-2W1Bk6*IFk zZWBoDxrGIdU1l(R45Jz^5DVm7?`s@gsdeVupr8r{fbqU@04a3V(*q8V7R;OY7wf7R zDF78@W~}#aN77K3O`_})lw)umj}MQ{uq2&S&9~;of?Y0LSzfy-1?NKrAcZ8)^}gEC z({4aj7Bet_?Nf9D(FGOFVJ<08#MUu;epBH|m`HwS?_G|b-Ae0UOyd#HqS%e)CX=Af z`kTN&+7qffTXFejx7B#+-yuv?O*?-;cPP}a@O&ixU)f&K`a`XemhWzPqWKq^C!4;| z^p2+c8$aFn^^I?6c($Rneyr{{>*i~JvUaVuet%*AY|TH_d}!b2_PwS0@2VfK`i81r zeE$FM|F&BSNH59U8a#ec9ok4dW_2t$VNZ`Dp=fYsRvOQy5&&M+jlh7ju|&(wwyzE7 zTIS#2oV~P)e4|AaClZRYEuNZuxD9dv*i5ur=G%tj{cQ&)2PT2zhP#B6K*Ddx>)(aO zhNpBc#cXLG@}`JaT<(gV)wLyEq{Y7+iO17zN4!UG@p+q`gdR-+p}F(G5c4aAJV+ zmP)Ki-g>=~Qp!a6#}?5-5TUDosdph*6CsN|>^<_ZUAEXzFS`dQ_C8(!-o?;%@9{Y| z-QX095>$ks@jt?>M3h_2o)Ug;Zey12*SXA<%moz@wEDkuN*9p`o+PX*c!`nedr6}K zo{5he$b`0okKE`V=xpO(iAD_e$zUYP+zLR_SoAxNUkFTp4478{OgxhuqxetH%6ifO z$V;L-z4&i}8*e8`)@SzGUMH=P={jK8UUSQtr4_Nb^a*%Z3ODFjZao=GcI%3 z*si@+SMI5qT~{7Jzpns4k0rQXN4>4TKYl2lbSK6q zrt>1?rI|FN@Xo~IZ29P2Kr6zdymgw+VefF@-nH%e@`eg*Fc&|rqoE^HNpPacVJ*~| zJR_FoEV6uHph@PzFi>-#eCnJeRm7qJbj}yhRc>zKxQ=p`P@7634|A}%>Y4VIdfb9` zgB;AoE%v}DM?YCWU%A1V<2tGd^K@(~6$e7f=+p>%f~A<@Bz;+NC6OBAPzaU2xBy2z zyCu@}j;+`q2KC5d=e*r!z)W|z)T9-b^Kf?5$0ux$=tp#Ni z?c~ngJg%daYA4iIvU&iOb*Swh9zKQmt4-%f#n~N2LA!*U$xMRA!-d8IRp$buv5Yf% zV+Hh>8(iqqLB`-Hfdk`>18pPI738zC(&s=NAaaVLe}4fm4)N{UJ{=nj(oDsrUR5b) z$_!@c4*)E5U$-4h#XH?7;0rnw3>8zD=3-|30#BA!j(El)z56Y1CoNvVj}n%Gvl9K!09W!aI0Gymw}R+?$h-@n0=AY0yxd0KdUqoWo8DK zz>O33ZYX;GlLeqFB(?|peoQf2hIO2k7u*+T+o=Qzh%&ns+ynw(*lS{JfNL0$u1>A- zY;E9tAcsVy2*^W6TkSG;!X{>1)J~`^WJ%C_#dbE(g0`*zO&41Xmma$8&D`w!QMUrU z5%5dGXwz{Uz?E5p(inhnui*wQ+hJ#fF(@$clG_Sqh(NX z4a0&#WnYq{MlN(4!SCivhXFSoE^2MUZV)iuSX{LzD1u(82O^k&pgaO*Z1r2T+Bit>!*l`N_y)K7bbUSV@9#F#7`@U zVvJS?)(U+KEvcj_mI6MI%qd;C;ax8PwP4ym(D!k-h^bM^zTq>-GKF1B7Y$^e8jH)o zw!p=w9;H?y%&cMLLUPazYBO(S0XXqMs)cfHtrP%UFy`Og_p!1gOUyJds!d;|=O8pJ zo&w^j`u1|e%8fT$07ya7uk8D%8_!&iWPh>i#=$4s#H8?LD6^tB7l2L>_Y-{|DII~V z$lg3dK6tH7$bs-VynN<2nt2rYi}dnwP0g=VXKVk?0-FCN{FOdkeb0*m5yJE1!&C)6 z0$G1U+&zIHg#qpj#D+y1M0?FmG>%A%Wro&1(2Oze2Fx^uC$Q&uhfGA}WSA|xAtAm% z_+!IM6lRe%p6vUO+ZMxz$}nlej!OA6?f=(ToUds4!ItXg4>ezJ`b<-zv4D<$*Bb7v z|Ka*Gb^lQJk-D38UA5m|+r9r}&1Y(!s%hTWUHvUpAF1lE?63HI#ryE_ZvPFx4<*+_ z=PK_&uwZfuDN6*`RtQN5>CDW+<24OH7?C4a$PE-S5R<;;oDJYBx#|S0q&kR4#C^Omzq+{3%2pOy*DXVP&;)|*r-rx8-6h=g8CXsA_ zEcW%y7u#S&BbNkDV&y$wfixnEhP5jn^Oj(->p;hZo`B~{3$pzZ&0hHj^d1q4GGS6I z@&=Iv-@Q_Hlm@}uDP8lXW9c@@X%7sC-y-0LJfYQj&eKx$mfv?bU&#HH&3gH0Zo!(p z7=R05O2Xg)x1M|f?PMml);2R6F9O*aL1#q22`GAa;LNkYGc&1qa74DJb#G+zNOna(eu=+VI^+OC4N z%nN7TBmsC2Bc{~vtr2Jg&QKZH-|fN{;R^LuQjhq5$a@p`I?wC86BoE3xHFDy%d%_> zicN{M#7_%N(KJnym%s&hO>Dx#MU)JKAV@+40Sb#q8kX$~sneuwx+P88ba9*Mp1ZJZ z(l)cSX_BU$Hq#|d(8jl!N+QHaR~j+HRtYDJv2D6yN%iF#N$AJk+*R1=;~KvJaxEE1opvhdTcmF# zymL?9!t3x>WW?g?Vg=>*MDw=;Io}VkxkV^z@a&E=&RLbp703rT%pUB zMwlkY$O27Be$cJ86->dI%ba`+EHjb)BU%~ljAzdH_9I}(em{Dnu)}9}Zghy6`qRTY zzG8FB+Jb?=CT4jzH;v6X~(wiY|XF?og_eJu@om;PPqa@J+7b&pB6%w!o%YL3zU#)!; z#D+Kb7q)p1<{wZy5X_w->gE3Itm^w*3hZuw4H7}67b}+5ZaFNc`=1&)5P$h6{v3S4 z;OFSjgaD~FQxZXG?ob{iA{-V4F>UQ4OeJ+B1C zlmgFKTue{J?X=u}p!r~Ow8ryJ2PX=h-Wm`~nWE2X?V6Qqo}9lqr=2nw8RSmpk6edj zu*L&V2UiLO|0XckxXB)w(F-$oV=r2P++3agZpHKLVu#Vuj9|gF`mXefk4_neZEwgoPOc3 z=IOzHSMfB=-rt@nVhk z%Gk)B&uzx9*vQ^j>+0UYn&o%%x&Jl>*4e$iZD9GE@hi1rM{9-R_Jikry(XqCCZGk& zBx$DnT_0Rs1KCPOYt#i8oICy_!SPG;@6J_#)muE`Oai;DeFd9{A^;im6hMROv)@N0 zfWeLZ$A4>RvouUNe`*wmt)+Dh@9o>n5hOhY^ro8<0(uZ1xyBAbsCs>A~hIxH5kj^R{j z^b>Qd!y)F@r`NJ3@vIbFzyUh|yg~1X4+Y^k?EDKmkM8(uJJxnQ zv;EI+f4S$c_k5-2bkF;?{p7aau&uv)ruZ|(Pj!83=U?so7Ml1~{%7O8wNG~!``)~H zs-q*?cN677aYS^l((vc{#N0J2*fzxbI{4_lug_zUW1r|zv-pDOfph)C2W5&YqQGH( z8k;=*E63_4k49h*0lyDV9MTu1+vXRadqJo)u=7nE?a&J@JZZmz0)!@|kpkzOtw@KN zBXni%^4c}ocf$15RqWEDGnnjn3c;Sk+QiK@XTgeIhl-@Zm&KBN?uA2_Ip*F!#^=G> z@$O=2;}O;+H9yVmlk}oE0q#t6{c=_<3-TZb5F{bZGP=*dyWca6ck3>C+q^@YgK7zI zDTRLH`pBZI9;tn*yLe*b2!o9Z94H3Z$^4SZ>C>f&@_I#U+B-fcw3=@j&|>Qx9Jm%3 zQiTd64+4V78!MQ|?yj)C*(4kb$eKxdhZJ|E$vYqsk#C(@=VmO^MA+bJQajdNtZY2W zz*GG`I(`-dn_9P%;nlF|alK~0ejaXvP7mU&cibS2vY3-w;zefcApXRO(D(H3_+FOI zqQ6DPN?L$C=Zs;0ryx3d z@5CC5C7!45j2q(!a|RM3(vbxsMk~rz5W_LcbU;K%!K&1#fd1%J9hBjCf40bEF18!KI<30c)^C6HNxkA&vaHRnYa$JlHbZcpeH%izx?zK-DJ!wt| z3W^=E$g-VHAt${vJe3UNh%BgEc0m|}oH+@I>^JT_bM&%|6eUj>K%?`KX}H*fBD=K1 za>Hf{A5r{lUN3sxP0F<+#o~$cKh#l-zQ_dSZ_4Q7(mCKx<@reaqVsX+=~g;*i6R*(2te02_CXZo~-;3#3wu zgObuvYnJt9XohCNaR@98!<(3x_C%Ob0QHiqHFD@FBv*JUzn#Ls4tJq0QE zwZZ{!#Y(5C!Vhei3fP$k3qtfU+aW_jR4xGG#jGcUVNWw`j|gxYuhc$X?3}(`c=Eoc z&mr@K#t&)#FTUeG0$!rY3s|whgY@j~nq{Py3s1x)pYWjA=ooDW^0LYTnP)RFH8g}! zvjuf$gyWR|Cx7SW_4@l(^3(HPPY%*yI|fz;!l%=#k-S^k`u2&Q$ z4#B0u$Goq22!M1yJ9^qgU25CpjzMHA&-A{!bQ!Gq34-*qg^#v1B0J@68WND&+SrBK zex9vcFMNwPMk8lrIgn$*{j$O&WnLfl_XI)|BdSZzWq`w7!-VS{tB)kr$7`g1U#zYb zqW0>C6i7J)Zqk{`*mPMzWf_2haTcUX$Su*EZHh|C=}dFs0^m!K^(G6ta(y1`mm80w zxl44);W`KL(G5zPz%Jq7QPDzp|FwlB%KoAILivIa^h&Ca)IO>(@p_@xS0I)tFjl=E zN9|0+uC=8cviMIH0f~n78)cgCBRb}XvCB|FPl6Yrh#hDVK!y^V0Mtygkn%8W^2HiC z=2O*Y3Xk~MqCnMiu&vo`s4I7tmc3BT^URk?&D>w@V1}a^E zvi|5x5w$*B`v?T)xx)Km17drG0CiAMIxI#VRC!6fg`8^gT5g&2S*TG$eX#oB!h5~7 zT%eo3>L$vPQIlhk|T*zrd?_Pu{^WzTo*{)t_$?fmeLneAWg`SG4-w|#r}_jV89M{K?Mm>3q5HwZdD4_w%J+&Ofi#&UF`$RX=))dWF8q=P!Kng%C}%SD&zz zQoAaK9gXm8_AC+|$s^z|M}>#*4)xXW6kw zy{~9|@DAGH=S#i`Q7yGOPDg7m7K=wqeEWm`Z4oI|m((*1a`l&PE!|qXrMlL={Lk}~ zwXyEvGt~lLjUrbbX}H(xW4cL0W=6l!JF4`mVD0Hgt zT%=1QJ_&`QG&>6x@uVpOooQ=Ba!Oc}xe1n!jjFZRQ_)=M1Ejv@$xLk+xTLy=kw#HE zMlzVVc4+kA!bp;2GC2in^wbQODi^Oc7mCQc)z34tLbVR?=;L@C3D=*Q6~rYY&-=z7~)dqgt?jV{(II&p$R zBG<`Ti?{{39{OL0wsckYP(+pqNOsXHK4M>81nIZ0TxfF-!yOHie|2Jsm1LXA%mT$CH z?k>K#F~!*S`q%>aIgE9~jSdNFRBR%fq3_K4Fqska2tW&{4$qTsM&uD&XVqcjganbzdv8VYq zk53wgom4+l>qirBRG3oAF2k9e9vbHGPfVO29oLy(S>Zfi>79fT-DhO3J7F4VdE7kW zOYsv-M6~H})d;RTb$XG&zU~VDp6MmyB_&J5FNQ7H>^F=Tm?FJDbTHF9!U(ZIgp?)K zPuBXni-Q}_F@wlgLvQHT8ZAyV(m;J6us~>Qp|>*HH#yYn^ap{ZI63z7XGU{iP$n&+ z*QA9b>4ef3uqMEn=a)zvaLxqzgZ$Q722Qr#FN_Wh#33NwLQP~$P_ktL>oPgGF;+Xx zeSGT%V~pJhZw*1K?mSD6B}~ledCo{sk=Dw))H$P zS#+$afpT$4rw7JIhY3~mot+xXE$=w~LEGxmzF^sRx471b7ATAEnymC{F0E_+-~0ks zPt{I=_?yUxM81&bZuL>@(4r{EEx8?p0@bKeBX?VjK^+xDMXrvd{)Ms%tku*AvUSSB zP+mok3xpb6^U|`G?*pMn02c@nvXP@3WqRn_&Qf;Zlj<|IlbXYm9FoW$^lNLBGs8_M zS_MWBe7b*INDQ6VoYdfQ0wk$+TDYPn`&`t>CP>~+W^inBvZ7k4eWtruHsur9hNl6V z`=-W~9`ChIMv)g4e>$Mgi@x@QTL{i%2PRqK=ngndVFkt>swTmMz;6Dp`j^^yTi z7>g<=l2bA<>~;TVX^fAX@>vPr$aIiGCQ0>b?F2&mP1(hf*of_p%nmt=K)wQ&c#m;? z$bx(mUQX)l9J2`QF~oK#F%{or%x+iUcVVL=?cGqaSpzHxbigh;Fg`|Vp5v{e%LQ;U z*J5;PTQv{gz#>JGS|rar1EGcRMG+BU5s{9$cIE#+(Q%_=->={I-o4+uw{y?;?5XVj z>D|@c@7ejscP{UIV#l{_|C8Ha==q7Bfo(swZF$>v5P_xcCyM{3_(zKi#izUeeb@JO zEp|QI`LmtBw)1e|FBe|v_(wFh`JdI=7l|WRpE>nN$0st&$#jTCXGh979+uRT3nJJG zd6x38zGx9#V}+MQzY*vhHSjwYvcTCWrk=moTn zu)nd2O)>_X)x7Fx>3f{qFGHlvzf!xcvG1VKbKdCG6d6R}(kXgV>eUZ|NM?hBIckBK z7)Y0Fv*ZQ&YDQG%CUM6w?2>`n>-eD4rwScALP&4e@H>%m5Nq@ZjpSdwpuJ6(zko`ZAwAiKZ4ws z`F#dy!Fyc+PMPJ)+w^6gMAvbR;l{qScjB_dh!rEuzN|A7htijPqPAQtK6#dwy7QCB znpnELimOH&@jDn=eaVU1Yb@e0Un}ZsX=Fh}c16L`5#&M(650`LI9|JDcu=9EtM&UK z`n}cHL*Sd}@KUi@9;J7S$`V{w1!5u`^nQ-QDUMd8t+@W6^VeaKu@xZzn><%rEEbms|uvCeA=t7Pi|zdfqC6 zXUa%n2}M0Ps4LgkLQx$Yk;UZM+Cs7T+_6&~o!{vVoiCjQP_!!gk_2vG=m^i;*83L8 zZ0!a#3&R$o*gRc%X?$vk0tE^dc_GcyGB?lfS^ZEc!zytrNCJZAvB>aP@T*P%*DcjO`TpiuPdc1XSye2rDw$D7i;sy;@}(| zJs&%=7~ynj3J7ER^u_71Q65;n7|<>0EMPqr(rI?IjBRyGv~()FX|DU9hvad+yEu!W z?dW*U8+Gd9*ywqMd=&unOudklm8N(3g5TnqQq><|=<3WgkVSa3P-Y14f8NG&*nHqX z5i&ricmF4n>h{{T?&4@wZtAmfRznC!L#tvuR3^g^bQA5f-}0P8C-W?40`?lHW&2g4 zC2pc+sUYZK;}a5(o0*CWPg?}iyIL$x++`%sY`GMz8E#+q60qKLIxWKG67M9YeL`s= z8-hGn&C*65^C>;qN)P0SZf!^06Mj5>7LS>np&U$!(Sq4x0-pbHcJ+G76}U&EwJSJL z8xsuRkPo1L97Jp!n3wDt-O7NqS}bIu;p6v8lF;7! z;#`?iGPuPF+!hO-fX!lUbqVYQWg-4*%(>T1;~33aFCh+r4U5B}4$vzyYIPac77*B& zoR8FI6>|`<^t4ZDpfWyuz9c5i7^Tq4{n2q&r&mZ=n>EZrPKsLcky7RMCba>m?r^#? zIuTx(3B-*ny_aHM6!+FY#hm7PsmJy_<&E7SZ~fi=!>}NvP+?S&tq~guXU3f7^RO{;UnWPvg5o|Lv&c5 zac#D=j02(1dl)b~D$JaNJPU9NcsjQLL=k+Kt56g%@Kbt8pte}WAEa2?EHln+XVP1t zfb{Ybfp7}v7)LHv5oAVT3hbQ6$2A_N3^2R6MrjIlhsXzxA!&~4r-t6%B3Ww~sm)C_kb*NZ zN8yIKJ9D$)nJv3FX^m{BD>!#hzf0+M>YJBAcy*!nQg`uU^%@;TGRgx`V`2^EUsmLJ zsdiEJj}By{x7dNqnZ9RAJiU{*cBRL4Bvb%4I?C@n`ny`YK)}U%jGULY9*0U30O-Q4 zzk%H@*UrNLwr(SfrLEgvf`G96{||Ls?%4O$eW&*P^WA@J_a}D!ja@JA{4rksySAga z{YyRny63m`9Nc!N`(Jhc?(U@c!^Lx5|G4W?=ie=SsqoDmKf)K^_Rr_)AJ94O{z?`w z=`UN@)NC`ti~!N={UJAH%*?RLO7G~^s}T+|+8Y+147AkJ^l;VE)vL)+{b7{TEbYgj zM{K{uJ(;%mr`AVNCEVe$8G!NDhLL^(%q0@_%VfU(euB5vCuuK69AcPFMGHunU^a@czI2Nc;>pH^`uo6{-g=GBVsKzkes9Zjdc%~q zTGx+zCtxVV2ld|Q?O#i|xH%G%W)gW)MzA&LCnnOch6mKt!615~MFH1@#vl%>I?4pU z);wT2i6)LV!?+=r`z{g~ele2K27@gDx7}n`NF);Q7zZeYmi}5-?`f}8Y`&G&NCquL z7fR$6ctxVZgC2cl3KA?Hsw`qu&ReOE-csLCpniwuqVH?w_5prrfSep-;Y&7t zA`IeN1)P}9+1dHfAOolt>knxJ7a2iB`h&_bzUTxX^cm!{faX5(@fDnn|3)+iO1X2n z0-DicW-5iBoru97HeJd;J8&60=~n%lB|!Hxj0nu;oK8xio}L{;pwy<)(%2>$}8w8uZ?7NmwF-i@T%tD&$zMX%h`;{=V=_hKsFrni{OVzmQ|?Ue8A zG*J8v%jKc3EU_n(mJZb?)ot}XvWZ4%GSb6UWZ4RrVmFtDuv0`w%(q@zz$CGZr-2zP zXu7bav#2lE7f8T=t;I|YGb}L?SO`za)CS(y)j*W2S=EuGdZ@lz*&~lJl7hQC8F|gi zPvTYN2Qs)O6K_oXopL15Ga944aQ>a=VwX|O1l>!Br<@{_h&Jdj0L8)tPhB^(oJd0@5LI;jzJV=bZdBG8|2^L6?!hPXJT{Te@Ue-}m#p2W&V~B{!U|jC0k+UP9d*C<~ z%sI;i}H>59vlgkBAS<>(NCYy44bo6}WLFB?A(ZS} z=jN}BjYvlu{YHhWlIqcVHz?Z1Lkw}KeTY$f^UP+TE5lKjlfb5zd9cJ4;=&AI9=$5*7Lo|ApmjMUit4VQ8jkU#=-x!V)OpNJe;0s^45M z%4DBr=x5u9?!#2^@ANIwU&`^a@|-gAqE_o&0tFvuP?1HN9xT=qqFuPfD8~MfA(f^L z#P!PRmWB~?0nM;NL+Ze3jm2_6z{wTWw^owR)jNyDv+ML4)qUElIx@dH93-@`b;O7t zd`?0D?ir-bwYk;g3-y9TA(uAgai={56s`q>@%L9fwIf~$CW1OPj0GhUG<m*=mcB9_*! zS%^8FF!juxA~2n^sQhFnXrLTNPHPAIR8sv42~x5l^zD^gC44s?EQBkJkQt>Vp)#x1 z$K{5ceIId>9aM*foS=tr$+`_+r2tiw1qaM$vf`xP!0f?f_|&5v|H3bc z0w=sfV$f-@1kqwvu*@H^UGI0nZ?Vbc-toYeV6FpVsSgC=Ot7eksVmrEdct?R1*yz< zHric)Yw<2<$>4PrF}1)UIO{E}J_5g~2^(Di%WDv~27PR+xu}Ol1fTTYU0S0>G`Sv2 zWc{6YMrJ5OvX?F|FWu=?E-&SBo>qw&X(4?JrJoj6!U1Cc*2ttot(d_;^(dS}b3-CY zh)<+1_9QRYz9bue$Egpd4xDJpTyKCM>FP-aBL+we3AGZB>^Ic3BH`OA?&4R(SpX}| zP{8R8bDoKrAMq_4A5L?)tb?Er%mEB}cbkRGwGT07ZnlA~6w4_8|64k~y<^|^?VH{E z|L$GiyL-CKeyu#?U>sBAGhDzeslYto_jr)w*41)09Sbf@XvHV zRQyEO2RnbT^HSlb3XgUCO&WQ(f6DbwVfUQ<%0sD%)i*Sy=P6iE1XpB_lPJfc&Msgv z>nce&a0}z~)@~((^bKgziy>qufzlY;)r|T9@iCpoi8N!nd{# z!R=&u!IZPZ-hA*-^fr{yh8YS)3-R5*W5VeKr$m_C>_&pU#xF9>0_S#>)$KtY5oq~Mce zHo;xDx)G6h22%2L;62e%3Iii`!^>G3Qho}Gcj#w6q-?Y&tC#ABMfJMN%EWk3+saIo z;eDA+lW$V}hI*Ffvl#yTb*xWrMZ%zdiKh2t{dtvQ*u(TZKlR*0I@n1oW=S%@5PT`$(3B@iR9A;x{ihNcF2 z1nOcaYt2&(lcPb|j4iBjUl{e6TtXaOqMF(Lie6AInEguqnPTz971~aNJi7V_c7i>` zi~A|iK`~^qLdcjeAxyaOh#EpVMAEL{?{jjZui~O`6|j~_I1f4^435+jI2{$*kC7ho zu?Ig(I$#M=$#r;Dxq$c2`K9_Hf;Q`XF9vO*j_FVNS)2G~$jB3X=#Z*Adkshx< zjW(O3@fg2Rz7TUhLoSe24tF$AQcC6lGiIL5PghUN>l7B?gHSz&U3#hh6f1d?Mq{i7 z7{H#9L#%JsFb0^*65-27;3?gF@1-FLjHKU-!W%`R$Bjnj)XX<11%C6 zc3{OS#W7W{CSw`=sro@^GywTN31gXTxM+Y|F*FVvsp?r85H^OjEY7}kjN5fKSeoM~1& za~Y!WqUj%lk!*bEMYF?OuTpevlF|AT#o}Q!Uq|%&M39S(u9w+b+Ook0Ns(K-FkaoE zoTZoy)b~Rio2SK?A*cu`CT4kZUDO2yK*#arL(yRUCjHsKL!U&kaW!d zi|eP-GW}bxpw4<+x=Q_{6#ST`k(k&gRJUa#*9VYx+OggN0l6Z@O8(hTG`Vy@H|yUb z`1T-;#XP?hYY2rkQ?R%Um5x_dGPoEQO+PS}Q>xH{JAqZ7FT$Bhr)1-J{c(j{j?!Vw zD+MP|TLBcXKdQ zqot)4l>XOI%@)g+lbT15tzGS!U?BUIUe?6!v6?aA{n+Eu@Wg2VQ>Xxg700rLiV^{` zWB|Ce{OW3C(}J}0vV2vEwV2xoXO_Z5RPPiTngUkq%ElQM$XZ!UVX1K3GpE)gH}YG> zlDt3E!gvkp$)$M6KwUHyN_LBJU?>S)e~eS~<}OAR^B9q|DheGz+4Xb8d9K=JF0>RvV z8k0xmUzi6rvu4BAgES~gCh4!^gf3_qKr&PRh_1 zTVSCqC*;v1qL`?d>@S`Yg(lm3pj_h75|I#e9}yJELjA)E6n&UJ-s>Wfw#8UuUu9A7 zH^l}j7^IPQ-Aivn9B7wgTXbXlYHOH%Gx>7;Lzf>h;FUgq34#T6~( z3Ph_cY$aSy+bEHjlL7}Lxf+9fo}x3=Rdel#%ehq3#bQSem5DfKLYPs zS|#R2dOJ$w!rLjwwuqgBv3sIvU<2nP=Zfl~f9x~n|9`Y&S@r)uw{P3tKd^U<9DrZ9 zXV300?D~OSAKCfiJ12Jh!j9juqkH?+p0D+MX4}th`$OAKb^m1dcNYIl@pAFut{?CE zT<6bp-snSH{Ow$8j-8Jj0^QD@EBxUs=1Nucit?_K7|pqi)HCIz*n6>x?d5v=NecRVGa6 zJdO=jbjZB10z4yp(e>LT4QHdnKT(06^m#N>0@QV{8>ir;z200kC%C8ua!h<-T!n3vS|=2;xe6Obd}gAejm2qYp3u|u8E9Dh__3nkJ_)YBZY zJ}=a-*I@vitUki9;!V^&FvChXztJ_MhEvI@Xr9(hYivW(y4tWHtc90D1iabr5Ps=^ zlf^o0p2OAW=qg^h^W)g+)1lV-`uSy<>!C_dm^7(>{KWI_=+q@-YiIszTN2f6$vXT( z9Wu{z)w6UMub&%ZvRSli2u8gYuDcpCnsb*WTCPGH(>Vtg^nJL@<+-~&jljKUkg{_S zFgNN@dIqZx(|NqJQN;P(b(ppF^u%-RyNfLX^6@$y2;iM2^<)!I(#nfeq||5=)foSN8F7q#qlF;+HIEIYTCS;Bsfu@y}rP+By_EiO3E}71GcFmnv=li7J z`A@7Bs^j507%5nGxc%DtFsK(Bp{;!?;SH^x0Z@UOto^ z)8Off&(~iRCjC(wh`f{2Wa8QLNu;n*-aKnV zpf+h$9g{0{YHggTK15$Tq8pX#iy!r!-Ml+5vXL$3gSt6Ur}oCtVS0(_ka0X8WT zi4>K+JS9VsTj7+4sNCeBE}D7^539-%!42fc-YFr;A$j;m7;hxYg!d>j#>KlDvJa@G zg6e*1$Ua&>E7MXN5Q#H#6(H+_{+?+G7v>K{&}+i0go#1^SeRS9wn}NICA>Z@Mu;2g zX8CXI;&C6-wTrvBd9yr7y29|jsZNoQlT~VTrc9f7zHFF%5I!eT1A8pWsCJ_?@1$7E zQ9nlse*XvVA6_7SB`?=0DRQjZ!;m6VM>4IV%6f{xG@SsXI0pgJFt8=6gDPR7MI&JZD2vS*ln)l)uG7>^SP}wiFw?> zE(4%>bMzahq<+ydRwE@oC?9MKuFfjFkyVux2ppx513hCDn)ORMhCJ-uOyu zF;OR&i6%oWjiI5)Fca~GSoXp~I2l=}IsJuPL3d9~Aqc|2Si`o;pN&-1L=cT{>5zLQ zxmv1I6=P}R(XTw(@y}iAhDh$2DNHG_OM`7atn0O9Gte3<&SJFvG9#CJCp;bkesl{1 z#$q98x)g;Db1@^~{@`v5ro`I9aMv~e_WX9G$eZj;ed46LuTEi%nQHkfk93^&N!S_T zMImKMksmuo(w3LX^>l#pBnV+vVw5~LPB{yjdkIf>K~d!>6t!;QVnxU4)3sP zDr<@#kescb!mYeUw+DUBn0k}BY12_^`sUX@owCi(o!#;JN$%hcT8riYRZgHzNp`Vn zcsV3yS-?-B@0N`-8!4RgOo)jGL9FjHfZl7wg`?8iG%g&fQfghciVe3H_wdgpQ}q+Y z;>AmJ5Vcd`7n7*OWkTQEFpDI2jPj1m5zP4_I_>e@7a4{@3uX^Yfta)KfL=R zyS`)B$9MkToqKkaxBtZUtJ^=>^EY~~_4I7}v)f+o{%75j#qTbj==#a7qn-bOmjG`T z{tNj4AM5yQH1zg=UTPFb0KJXoIqnC}3vwF`ZsOv|B+qbSuxgFHu(my{C=cBT*Jj)4 z0?WnZ%&T^Ue=>Qo(LoeTK2W4i<{Q^3v=<|(8H5=j1)6i;t(Q%lq4V`G7mFngI1(oF zZMvcGiyG}4b=V`7>M@%Bq_2hhg;CU$Cb6J-hZF;MGarVZ&4lV0tVKwnFbhaJGK!(_ z86=|ID3(n@{P0;2Kj|2*?(ERYO0 z2@>16^eGuR(lY~Kl7@!O;apo>TM>DH`W9;e8}7S);|jnEz9R31a_}874uy?5zRA`4 z9T{Nq$znEiv}WyDMkFvv(OaA-`0<<%6`M^TW<;CtQ!_wfiYQ~^34rtU+w8;&{lui_ z*iY)(W7=P!r|8~uC@!Z3|CMp$-hK#)r#5<0Jyw5R6azUbk(6sEGo~5K^iqshyX>Yv zZVqQVJCVZGbq_KSVPthYlu8;~f+hx#kp4jLN{uVw-+seUQPh}q;4+2fjgKUx=UuIv z#MgphZNMC(b35kM_te*Pt!Ef~;@3J|m{I84T8VNdp~D`2+_|a&ozD~hxLVQa zj^mEYsqQjJ|Nbw9%cyT9x9Y1($vDiIB40*VC4IVai{lVNem1w<;5c)6w!O?%-7Pby zbnh)}lzhIvqGW?Ex{L&xtZG9)W{qBroIW?aMb}qw`78tm+7sJMA6p6CgRN7^;;YsLl}X+L9UmVZFGZQiInz}MUNM7bQ(HjbEx43`a;;CZz;U%kQS+P>smgWDi((5vSGYw z*GaX%t{NR1!lxqF!}UqbtQoe7ivitMy+w1XqG^5~0a~IYR8_nhO`!XL4VO5Xshpkw z(;E+HA{Dc8qxCs&LoOLrK#o^$Fpo$t*~-;bba&#H!PVVXpO@U4W=N5f;)qp$d87gg zQVQ96{d0?CRElSi$Lq4y@kq1TKyghKd2f+jaF4BYPKeC9v8$T&c~(ENWa3cHRm$h5 z<Q4|i`B;q1#Fdm=`g5Z@@fHNLSsZ-_S z!~`uyR!`On_NE4!!k^1MsCT`M7EaWY%9NsPlu`Zui8?9H03%<6< zSDfk*vr>OQAjJd;s^|er=+=!X`J-RsqLn@P zLZc=^9(XL$kqyt@kKo~y`sbvbWi&_rjKx|BfnPL4w;Zxj?5T87op|sp{G@HIxWO16 z>5UHdx&%u8DPg3FJ#B7cKHIlcRapH0@s6)_?E8UzH+ci#Pw#zkZ`Yph+Vk<*sg9x^wT2@7VDu{Qqz6StI(ty6v&Fi^E-iyX$c0_0IPceqTXN{G$F; zKiq)-HE531%Wf;P9>Cnx@)_mf7D0iNqi3mdm3hD^JR06BCt2FiYTyDh?ZCMK)t3BS zu~k*kvV2Px!NA@qYh<5g9E;qy*mDA2R+BGzqXAv4Ts^^lU23=G$ElM+qTb;6X#P!h z8H6MVQP^ij>1); z@NSn_a9@AFuncf=TKb!8JjTUcW4hENq&L60fFiG#w8lQ;0?#*%Gg2Hu26YzaB)o!#jr~5&E@S=u0VFCIr`dArNhMy4m1ik zlstY6KS8hGq0(_zSTkdn0U`k#XPweOu#95RS@+6{DlJ`2s*g9|NeynuuQ~5ip<=TI z*$wARi`L|htORj9tuYuZn^LT|RBPM$H3jWSBH3?zc4?iSXu6T`hg}*t-KN={_`lqM zTy?Z6|M{Gcv7g*c1i9C}=QVrEA6VK(E>e`wHM#xkQh{5D=wx7p2z7TA?gt~8)k#-5R+(}!1*R~sJ` z_96>^(z`Lc$oh)nJl~OS{WBrHvt>_8*~vtHI<%y}0qg3x44?_`3r<`M$|D^F3yvLf zO266PSx06`jWj+$0D6gLtQwt_H<~Vs2tJa&4U<}Cq3QvovJeZ)RxB8+^tO`BHXc@F zY8NfWeBwM$i9r&f7{AC7WNfLtw@TM6eLgs1*cMkwbATgwM>BC_C>d|OAOBim+p%o+ zhP}vLeFu%xsE#{LDgHik_UPK1Hi!QQ0xkO6Zj2uTC~-MzgeF342LU#*gOrT|H|(Pcm+59cKj!Mn)DkDx=j%7N+52Q)lI}fyX z{%HuNd(BRjcT^(%q{#g(#ABWHLb>zIS3P?H!p&3L0J?vw{O}(?yP} z!}23&)Yq?bVjbxJUbZTeX1btD*ox zpaEz_B1&inFF>F<{hel=q|;zKLf|4bDw4Ae%AZtZ;Y8AdU3m;C1pwuLQK*8t_ZE;P z5|ITJqAjN$p|dH00UL0ecuNn{+^M)s-i+*q)0IIZPwVmsLL3sj-R@II73EfgYBadc z)A=zib*VwEl0((^(9KEjrfjQ8A{hUcT+p7BbjSN zQa_^&2c~b7i?^?XMA+v85W#09A-6ytHo6-yg8JSZWn$|-u_y&XfzFU?WyiguC++RY zG+oA!-DQpAAchc+=FR?d?_$9Mj;C_I@Iphfj2{jr4iq6E5@;~a5K)V3#o2ZMufS%$=Au9=YmbYt}uQrMHvHJ~pIimZOO zZN>2xrYy49U!Lg8p)UGn+waE65Fw(bQfKPccR6ULz6MmL=M>Gj)80X)zjX?fVcfbE z_)6Bw?Y34ZQ`p)HKiI03`NpSZODib(dRsHppQIl9B&G?$)Yb;cTRb$gMufyds=CC+J#3QsO4`BdtybBcVI>zD$COJVNwea;%I9`Kdc-R+=|tp>Z^jMMWXw4U^HBNRLgm@dIOD1_V%Ej7 zH%*w!+zcY53R{}`je>_(uprEXVC^#ylW3{PBK(%nadyt(+K~{gyT7`G7CH)|agj;9 z<~@!1OKR-K7`f!u6Pt$F?R~^&&@5UO-xRBMHeS%ZJWETryrn3gt5oFM5$qau8My{nOzuJ@68q@(PRSzP}Y)>@h7IlI6q0oTZf|T=bTe%#Gc4Ms-0%e?S193-YiQ+QQtfC^-{VMC(VLq-y|9)8rOHsO>k$Hc^u;EzN0|u76sM~p$MR;# zJf=hz=PDvjThCp1F-17~HZ+C>A47Ufb8CFwRO+(j^|DQ&&^?zoo>(s-tJ9LzSOhG$ zGiNIrKN-JkZ%PD20Bud36}z<5zd<9V_3U)V(=P@zS(^OjoWPEdqcDqnB#U<@sg@eg z>9kas%8htLDI_E9P0nAO)jOO?;6I44vB`uqtRRum*Q%Bq3Nz}*i-cU$5vMxeKJ2Rz zBrg6kLROR})MESsDH0!QJPV+_v4csx>XQhGd%wiv*GXmgF5=P=MXf5x6^JaUPB)&x zWPeje!hAfl_%np`hDm(ND;G|CM4&Ub=(f4aEX1YaGB{_2c$YCbn}u;aS~mB$9NGGsEjX!@zhBu+T_| zLrtoo)c9!;7hF*rn}Yp{sW>#5efk<1XrMts=qJ_Z8;5Y^HV)I_wbl;Fak8M-gFB1p zhuc?M_0wBgKnXBX6Z!MLRV-5&PPQB#TTZ>{7UR_?m7Hu)b>)b}##J9P&VVIBZZhJ~ zLyCn3yZp$qQ%-2gpKn{WwCPgrWM@sbE!|pUzpPp@MZ|ei1T&t1pu`C8i)EZ|EU2*f zU|(BzZafYZxyqN2Gwec}oaN@XqF6%dTslq=KWckFNRP84KKbi5?61k6&$5ja+ z)37eKlFv4%zA~tVdd2&(JP|h&Wdnm%z$PexDDy6>vE%Q%N^U25{{QWcy+6D6x9+X% z`M13Pm+by?yU*?V+q-`4u21d!Cp*`6cJ25rJI-wXciX>r`*_cP?)lR_i#-Rn{q(lq zwe7|3f6zVC_3_TX)Ooe@p~71o|DfY`$2ytp1F=#tI>sfp=ojXemkjk!#bHw2)qv>JXK3v2_Cb0YfbNn5ab}hW zcT#rLEOtKHM0NTX55;3huc3G@1C@@qiZ51G%9aJsKvs2l-AxzTs^*838;W9(XiCOD zcN;R$36XAoSL5I{FX@RbH!p+O0}@9{1mXiW_aRQf7P zI>ctg5umhB3-;?O7yB20g5^--D0>#E1qJ49mgKF&4Y)&51Js3KIuK}r6*&a zKrn&tmyfEoBF~crUD1mU+%fcu1`%y=lcfQ;#?lLCF~krPfy!Q^U zMw)W6-hl6Q*qr3w?%y=Bf@@=LQmkzuG4;Y8{8$mD`t~sDYJl&2BUkSj7hmuwUv) zCBqF$hxEThamwS0lpUJ2ry zVq1In?d6M&2@Zx@{Pxxs%e>J=I=9kmVJr1NVA@yUWGc})Fl!chV75Wcj`EAN`5U~= z()c)~GfxBI8O#}|0{JFO%gaD7)R$hQcvu>mU20IgqhdhdulJUs>YBDRIhh0x1iYg% z3x<8>KDB_|fg@mwbE!cIkI>_%j%k>zcbw4Uh{Tww{&7s<;BWQr)B&M)RSQ;!6RE=-Lyu^ps}z`SDK#O=jm6|_ z**@DC=3MG7|5|S}5{lF~HSs7jB)*%|k7L6vDbKNrSu)ZXqOn;T`yafqcnL#YBp#?e zT^>S8$NT2B5Ef?0%`@!J0Oic4TyIct<9M}?7JrSmNWqhl$sFR2H)8rP1M>+XK}m5; zNN`Z*k!%9%=bn_xny@c}W>Zh2&ms$Nwatgeto>keLhl=zJ+Q+*`86(0Hj|!)EL~c^&2wQ9WdV%i53DU!kEdc|*uzhZV%|^gu{>JS4rh zU`!*cQ;V{=2V@Ir-{kY?2l#;-?`u$OqV(o#H2a1(D^gqTIk4%r&>4%yL4<*;$2?@2 zUS8vQn;2TPGl~}k#(PB%hY2#o1xWkN0C)!mk&5_{xNQb>8CxccN)cLEyhdgC(eRds z3_H7;T#L(Q^xD@5vIQ_yPgC=Ply=j|+r3tjX=%BV#;z1QG>ldj4h4@98gG;OP}a}<)$n?h7RAim=;_}kXIFTtw#F#*7Wr_8A(LF(EPXZH zuHpO6hr>Z9wiFrQ0^o)p%S@=nmb6gQA0oK4NXyBa14?R+KAE;R&OHYuPVDU z7C8mMhiOki-8M2vrMaEvWO@9EHy2e$YzzBgjOv{M?DIx25>)Jk!z%`>VdxZX8EZlX z8k8FPVQOMqfQ?+UsEJV^;pT5T)dVXYf>-chUSlq?bAfAVh!-*#fUgo>hajc`b{kzHH~=G074{tFbGkmAg6v9Dr5k5I63mG3G; zjiF~>3IagP6{&OXK5Et^C|f1EXW9lNdFpGFs(YB;5BdPJax`)#$0_B*K?%V;m*i1o zMuSpgh@@mk4s>e-i-!>OiN+h8N9C0LY3~Gj3JW3cT3h1pQj9Gxu?&(}%v8F`YbPZq z8Y+vS@BgVSzF!(gHf-|!nPq{T=NlBnIC+=v|H=F=5MS&=qV(}pNzj?u3fgw0_bNUm z3C6&%R2~GqBa9}gb~U~rBAoatKj3Xw;8yXn@#xfKtT#JJOq|k%?JT~Q411m7{r>WS z<{sfS?H?g|TM8e5NZxfB^8IlTBj-vyZ-6t&ExiBvEX62@ zI?PiW%GVnEAeL^>Yf?0MhpQ+n<4?pjuTX9(cYE?-wAS`Ko|RrA3&yHRs$p1@e>~r0 z9=^>T;!T_6$a(b?#dpP;c^x^WtdT#~(j;4IH~ekKsIAqB3(cKttg((dDEIQsVW@pQ zgA@YUHqN;Q#U+j#L#yd6$1K@_sSzVX=#pgzFk`CfFc`S&*q>X$sxISbdbUzY^~nY$ zB@S&IWD1S^6r$M9dWf5Ey!0HLn_8msGXN%2Bs)f!TaN8YFaki`HlwL{J$zXp!B)r` zPcAm7OmR|hbUm(!pV=`TH2o}%zTJ0Jbs4fX##C$F$GHa8DtH>4#%uXikgzG8gQFq7 z5LUOrclZ*)NX*tT$Fyky1=>&a%Z*!@1M772ed!$d3u)FNcoMtP-o^qcxn9!l15qiJ zH&KsQKhapio!Zz>2Y)ozfhScf-;hfl9wcQp(G-^kiD7|!26cuU%HhG>&dOWF6k*@- zUJ@}7zk!aJng%gnDEnFtj6{<Ldq*yQO^c0onk#*If6 z3EGiq>b!Zx5@~z45VY8uTy+ZwC=0}AiTJ`%NIu`7aK=&V>JR6-GIHy*z!@$5yX)em z#sb!aHu(?bdNA=CvTv>UrTQ^QIr0`#^~c$S@XGp_mB6^QKkmPSep48uWZAQS&|9}) zr9FRAf;@L|m}djF*jy6}>?2xf@h)MBl|$hb24mam?H~U!_m31`-22qv(l>*FLOqL$ zB^UpJ+~iubi-*eRfL3zCDaXe}YlS{-zXGPd1z*9ek`QRHnD=I_M6Z->H+D`^-P@qN z#o4Nix!><2jOKe_9b~nFv;~=bOH)HRGN{i8m?(x||I8eYEG;ef9YHFqH0T5dnO>wP zDgEnogE|+-H{?+Kk3OPYFj5MaqV-mQd<4-wPJAU6uD2h$zU7WzG3tPh@o~#ajA-CeTGz$cq}|I#ehJ`P<bee8_pZ@V(epO4y66el4~2njNWJCC-Q!g&ZHtD?P-H z`ctng$xR@3TV4B|tf`m{nBqQ;-)YX66X^m#^09&&5{bXh$DL2SvoscsE}vcJOWyjF zr2wJZHi+zIs!)*y*|3=%7%~2T;hR+d|FwP3?cLbBea~;-Q`yt8dvMpk;{||E@BFTv zM|Zrn{hx0C()Qk-`E7r6+w;8qSLxnX{1NK^{l%`Qsr`SX@SQa9|C2w}j^@*fn8~~R zS>FH&_rUrVv)g!kNXC>>HUqYR@t^`zxp!=RQ`}Ze->ow?4JY@&%w=BV(mNbn#Fe>) ztB1(2Lbkp>2mkWJ&8N`s=2!hw9|PDex&D2ocLQ*p4FI4LdwDhngQX5UbJ$%Nt_
private bool IsFeaturePresent(ExperimentalFeature experimentalFeature) { - if (string.Equals(experimentalFeature.Id, "QuietBackgroundProcessesExperiment", StringComparison.OrdinalIgnoreCase)) - { - try - { - return QuietBackgroundProcessesSessionManager.IsFeaturePresent(); - } - catch (Exception) - { - return false; - } - } - if (string.Equals(experimentalFeature.Id, "FileExplorerSourceControlIntegration", StringComparison.OrdinalIgnoreCase)) { try diff --git a/src/DevHome.csproj b/src/DevHome.csproj index c692f658a..0d92f7249 100644 --- a/src/DevHome.csproj +++ b/src/DevHome.csproj @@ -89,10 +89,6 @@ - - - - @@ -134,30 +130,6 @@ true - - - <_DevHomeInternal_CppPlatform>$(Platform) - <_DevHomeInternal_CppPlatform Condition="'$(Platform)' == 'x86'">Win32 - $(DevHomeInternal_Win32RuntimePath)$(_DevHomeInternal_CppPlatform)\ - - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - diff --git a/src/NavConfig.jsonc b/src/NavConfig.jsonc index 8f7a441dc..22e5c4d86 100644 --- a/src/NavConfig.jsonc +++ b/src/NavConfig.jsonc @@ -55,31 +55,6 @@ ] }, "experimentalFeatures": [ - { - "identity": "QuietBackgroundProcessesExperiment", - "enabledByDefault": false, - "needsFeaturePresenceCheck": true, - "buildTypeOverrides": [ - { - "buildType": "dev", - "enabledByDefault": true, - "visible": true - }, - { - "buildType": "canary", - "enabledByDefault": true, - "visible": true - }, - { - "buildType": "stable", - "enabledByDefault": false, - "visible": true - } - ], - "openPage": { - "key": "DevHome.Customization.ViewModels.MainPageViewModel" - } - }, { "identity": "FileExplorerSourceControlIntegration", "enabledByDefault": false, @@ -125,10 +100,7 @@ "enabledByDefault": false, "visible": false } - ], - "openPage": { - "key": "DevHome.RepositoryManagement.ViewModels.RepositoryManagementMainPageView" - } + ] }, { "identity": "RepositoryManagementSourceControlSelector", diff --git a/src/Package-Can.appxmanifest b/src/Package-Can.appxmanifest index ebf1f989e..f397ca5c1 100644 --- a/src/Package-Can.appxmanifest +++ b/src/Package-Can.appxmanifest @@ -31,23 +31,6 @@ - - - - DevHome.QuietBackgroundProcesses.Server.exe - singleInstance - - - - - - - DevHome.QuietBackgroundProcesses.ElevatedServer.exe - singleInstance - - - - com.microsoft.devhome diff --git a/src/Package-Dev.appxmanifest b/src/Package-Dev.appxmanifest index 79ec05ce6..da54a1a28 100644 --- a/src/Package-Dev.appxmanifest +++ b/src/Package-Dev.appxmanifest @@ -31,23 +31,6 @@ - - - - DevHome.QuietBackgroundProcesses.Server.exe - singleInstance - - - - - - - DevHome.QuietBackgroundProcesses.ElevatedServer.exe - singleInstance - - - - com.microsoft.devhome diff --git a/src/Package.appxmanifest b/src/Package.appxmanifest index 37ef64a0c..f826b9d69 100644 --- a/src/Package.appxmanifest +++ b/src/Package.appxmanifest @@ -31,23 +31,6 @@ - - - - DevHome.QuietBackgroundProcesses.Server.exe - singleInstance - - - - - - - DevHome.QuietBackgroundProcesses.ElevatedServer.exe - singleInstance - - - - com.microsoft.devhome diff --git a/telemetry/DevHome.Telemetry.Native/DevHome.Telemetry.Native.targets b/telemetry/DevHome.Telemetry.Native/DevHome.Telemetry.Native.targets deleted file mode 100644 index 5a844cc25..000000000 --- a/telemetry/DevHome.Telemetry.Native/DevHome.Telemetry.Native.targets +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/telemetry/DevHome.Telemetry.Native/DevHome.Telemetry.Native.vcxproj b/telemetry/DevHome.Telemetry.Native/DevHome.Telemetry.Native.vcxproj deleted file mode 100644 index 3c1f4df14..000000000 --- a/telemetry/DevHome.Telemetry.Native/DevHome.Telemetry.Native.vcxproj +++ /dev/null @@ -1,193 +0,0 @@ - - - - C++ - - - - - - Debug_FailFast - Win32 - - - Debug_FailFast - x64 - - - Debug - Win32 - - - Release - Win32 - - - Debug - x64 - - - Release - x64 - - - - - - - - - - - 17.0 - Win32Proj - {8eb52f7d-d216-49ff-bf16-de06e4695950} - DevHomeTelemetryNative - 10.0 - $(CppOutDir) - - - - StaticLibrary - true - v143 - Unicode - - - StaticLibrary - true - v143 - Unicode - - - StaticLibrary - false - v143 - true - Unicode - - - StaticLibrary - true - v143 - Unicode - - - StaticLibrary - true - v143 - Unicode - - - StaticLibrary - false - v143 - true - Unicode - - - - - - - - - - - - - - - - - - - - - - - - - - - - Level3 - true - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - - - - - Level3 - true - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - - - - - Level3 - true - true - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - true - true - - - - - Level3 - true - _DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - - - - - Level3 - true - _DEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - - - - - Level3 - true - true - true - NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - true - - - Console - true - true - true - - - - \ No newline at end of file diff --git a/telemetry/DevHome.Telemetry.Native/inc/DevHomeTelemetryProvider.h b/telemetry/DevHome.Telemetry.Native/inc/DevHomeTelemetryProvider.h deleted file mode 100644 index 794b3f024..000000000 --- a/telemetry/DevHome.Telemetry.Native/inc/DevHomeTelemetryProvider.h +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#pragma once - -//#include -#include -#include - -#define __WIL_TRACELOGGING_CONFIG_H -#include - -#define DEFINE_CRITICAL_DATA_EVENT_PARAM10( \ - EventId, VarType1, varName1, VarType2, varName2, VarType3, varName3, VarType4, varName4, VarType5, varName5, VarType6, varName6, VarType7, varName7, VarType8, varName8, VarType9, varName9, VarType10, varName10) \ - DEFINE_TRACELOGGING_EVENT_PARAM10( \ - EventId, \ - VarType1, \ - varName1, \ - VarType2, \ - varName2, \ - VarType3, \ - varName3, \ - VarType4, \ - varName4, \ - VarType5, \ - varName5, \ - VarType6, \ - varName6, \ - VarType7, \ - varName7, \ - VarType8, \ - varName8, \ - VarType9, \ - varName9, \ - VarType10, \ - varName10, \ - TraceLoggingKeyword(MICROSOFT_KEYWORD_CRITICAL_DATA)) - -// [uuid(2e74ff65-bbda-5e80-4c0a-bd8320d4223b)] -class DevHomeTelemetryProvider : public wil::TraceLoggingProvider -{ - IMPLEMENT_TRACELOGGING_CLASS(DevHomeTelemetryProvider, "Microsoft.Windows.DevHome", (0x2e74ff65, 0xbbda, 0x5e80, 0x4c, 0x0a, 0xbd, 0x83, 0x20, 0xd4, 0x22, 0x3b)); - -public: - - // Activity for quiet session - BEGIN_COMPLIANT_CRITICAL_DATA_ACTIVITY_CLASS_WITH_LEVEL( - QuietBackgroundProcesses_ElevatedServer_Session, - PDT_ProductAndServicePerformance, - WINEVENT_LEVEL_LOG_ALWAYS); - - DEFINE_ACTIVITY_START(bool isPlacebo, uint64_t expectedDuration) - { - TraceLoggingClassWriteStart( - QuietBackgroundProcesses_ElevatedServer_Session, - TraceLoggingValue(isPlacebo, "isPlacebo"), - TraceLoggingValue(expectedDuration, "expectedDuration")); - } - DEFINE_ACTIVITY_STOP(bool manuallyStopped, uint64_t actualDuration) - { - TraceLoggingClassWriteStop( - QuietBackgroundProcesses_ElevatedServer_Session, - TraceLoggingValue(manuallyStopped, "manuallyStopped"), - TraceLoggingValue(actualDuration, "actualDuration")); - } - END_ACTIVITY_CLASS(); - - - // Activity for process metrics - BEGIN_COMPLIANT_CRITICAL_DATA_ACTIVITY_CLASS_WITH_LEVEL( - QuietBackgroundProcesses_PerformanceMetrics, - PDT_ProductAndServicePerformance, - WINEVENT_LEVEL_LOG_ALWAYS); - - DEFINE_ACTIVITY_START(uint32_t quietSessionVersion, uint64_t samplingPeriodInMs, uint64_t totalCpuUsageInMicroseconds) - { - TraceLoggingClassWriteStart(QuietBackgroundProcesses_PerformanceMetrics, - TraceLoggingValue(quietSessionVersion, "quietSessionVersion"), - TraceLoggingValue(samplingPeriodInMs, "samplingPeriodInMs"), - TraceLoggingValue(totalCpuUsageInMicroseconds, "totalCpuUsageInMicroseconds") - ); - } - - DEFINE_CRITICAL_DATA_EVENT_PARAM4( - QuietBackgroundProcesses_ComputerInfo, - DWORD, processorCount, - PCWSTR, processor, - PCWSTR, motherboard, - DWORD, ram); - - DEFINE_CRITICAL_DATA_EVENT_PARAM10( - QuietBackgroundProcesses_SessionCategoryMetrics, - int, numProcesses_unknown, - int, numProcesses_user, - int, numProcesses_system, - int, numProcesses_developer, - int, numProcesses_background, - int, totalCpuTimesByCategory_unknown, - int, totalCpuTimesByCategory_user, - int, totalCpuTimesByCategory_system, - int, totalCpuTimesByCategory_developer, - int, totalCpuTimesByCategory_background); - - DEFINE_CRITICAL_DATA_EVENT_PARAM10( - QuietBackgroundProcesses_ProcessInfo, - int, reason, - bool, isInSystem32, - PCWSTR, processName, - uint32_t, category, - PCWSTR, packageFullName, - int, sampleCount, - double, maxPercent, - uint32_t, samplesAboveThreshold, - double, sigma4Deviation, - int, totalCpuTimeInMicroseconds); - END_ACTIVITY_CLASS(); -}; diff --git a/telemetry/DevHome.Telemetry.Native/inc/MicrosoftTelemetry.h b/telemetry/DevHome.Telemetry.Native/inc/MicrosoftTelemetry.h deleted file mode 100644 index 3fd155032..000000000 --- a/telemetry/DevHome.Telemetry.Native/inc/MicrosoftTelemetry.h +++ /dev/null @@ -1,87 +0,0 @@ -/* ++ - -Copyright (c) Microsoft Corporation. All rights reserved. -Licensed under the MIT License. See LICENSE in the project root for license information. - -Module Name: - - TraceLoggingConfig.h - -Abstract: - - Macro definitions used by this project's TraceLogging ETW providers: - - - Configuration macros that select the ETW Provider Groups to be used by - this project. - - Constants for tags that are commonly used in Microsoft's - TraceLogging-based ETW. - - Different versions of this file use different definitions for the - TraceLoggingOption configuration macros. The definitions in this file are - empty. As a result, providers using this configuration file will not join - any ETW Provider Groups and will not be given any special treatment by - group-sensitive ETW listeners. - -Environment: - - User mode or kernel mode. - ---*/ - -#pragma once - -// Configuration macro for use in TRACELOGGING_DEFINE_PROVIDER. The definition -// in this file configures the provider as a normal (non-telemetry) provider. -#define TraceLoggingOptionMicrosoftTelemetry() \ - // Empty definition for TraceLoggingOptionMicrosoftTelemetry - -// Configuration macro for use in TRACELOGGING_DEFINE_PROVIDER. The definition -// in this file configures the provider as a normal (non-telemetry) provider. -#define TraceLoggingOptionWindowsCoreTelemetry() \ - // Empty definition for TraceLoggingOptionWindowsCoreTelemetry - -// Event privacy tags. Use the PDT macro values for the tag parameter, e.g.: -// TraceLoggingWrite(..., -// TelemetryPrivacyDataTag(PDT_BrowsingHistory | PDT_ProductAndServiceUsage), -// ...); -#define TelemetryPrivacyDataTag(tag) TraceLoggingUInt64((tag), "PartA_PrivTags") -#define PDT_BrowsingHistory 0x0000000000000002u -#define PDT_DeviceConnectivityAndConfiguration 0x0000000000000800u -#define PDT_InkingTypingAndSpeechUtterance 0x0000000000020000u -#define PDT_ProductAndServicePerformance 0x0000000001000000u -#define PDT_ProductAndServiceUsage 0x0000000002000000u -#define PDT_SoftwareSetupAndInventory 0x0000000080000000u - -// Event categories specified via keywords, e.g.: -// TraceLoggingWrite(..., -// TraceLoggingKeyword(MICROSOFT_KEYWORD_MEASURES), -// ...); -#define MICROSOFT_KEYWORD_CRITICAL_DATA 0x0000800000000000 // Bit 47 -#define MICROSOFT_KEYWORD_MEASURES 0x0000400000000000 // Bit 46 -#define MICROSOFT_KEYWORD_TELEMETRY 0x0000200000000000 // Bit 45 -#define MICROSOFT_KEYWORD_RESERVED_44 0x0000100000000000 // Bit 44 (reserved for future assignment) - -// Event categories specified via event tags, e.g.: -// TraceLoggingWrite(..., -// TraceLoggingEventTag(MICROSOFT_EVENTTAG_REALTIME_LATENCY), -// ...); -#define MICROSOFT_EVENTTAG_DROP_USER_IDS 0x00008000 -#define MICROSOFT_EVENTTAG_AGGREGATE 0x00010000 -#define MICROSOFT_EVENTTAG_DROP_PII_EXCEPT_IP 0x00020000 -#define MICROSOFT_EVENTTAG_COSTDEFERRED_LATENCY 0x00040000 -#define MICROSOFT_EVENTTAG_CORE_DATA 0x00080000 -#define MICROSOFT_EVENTTAG_INJECT_XTOKEN 0x00100000 -#define MICROSOFT_EVENTTAG_REALTIME_LATENCY 0x00200000 -#define MICROSOFT_EVENTTAG_NORMAL_LATENCY 0x00400000 -#define MICROSOFT_EVENTTAG_CRITICAL_PERSISTENCE 0x00800000 -#define MICROSOFT_EVENTTAG_NORMAL_PERSISTENCE 0x01000000 -#define MICROSOFT_EVENTTAG_DROP_PII 0x02000000 -#define MICROSOFT_EVENTTAG_HASH_PII 0x04000000 -#define MICROSOFT_EVENTTAG_MARK_PII 0x08000000 - -// Field categories specified via field tags, e.g.: -// TraceLoggingWrite(..., -// TraceLoggingString(szUser, "UserName", "User's name", MICROSOFT_FIELDTAG_HASH_PII), -// ...); -#define MICROSOFT_FIELDTAG_DROP_PII 0x04000000 -#define MICROSOFT_FIELDTAG_HASH_PII 0x08000000 diff --git a/telemetry/DevHome.Telemetry.Native/packages.config b/telemetry/DevHome.Telemetry.Native/packages.config deleted file mode 100644 index 6b8deb9c9..000000000 --- a/telemetry/DevHome.Telemetry.Native/packages.config +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/tools/Customization/DevHome.Customization/DevHome.Customization.csproj b/tools/Customization/DevHome.Customization/DevHome.Customization.csproj index 6e9bd9ccb..dec29dd8b 100644 --- a/tools/Customization/DevHome.Customization/DevHome.Customization.csproj +++ b/tools/Customization/DevHome.Customization/DevHome.Customization.csproj @@ -18,7 +18,6 @@ - diff --git a/tools/Customization/DevHome.Customization/Extensions/ServiceExtensions.cs b/tools/Customization/DevHome.Customization/Extensions/ServiceExtensions.cs index c5e53584c..071d76d6a 100644 --- a/tools/Customization/DevHome.Customization/Extensions/ServiceExtensions.cs +++ b/tools/Customization/DevHome.Customization/Extensions/ServiceExtensions.cs @@ -4,7 +4,6 @@ using DevHome.Customization.ViewModels; using DevHome.Customization.ViewModels.DevDriveInsights; using DevHome.Customization.Views; -using DevHome.QuietBackgroundProcesses.UI.ViewModels; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; @@ -25,9 +24,7 @@ public static IServiceCollection AddWindowsCustomization(this IServiceCollection ActivatorUtilities.CreateInstance(sp, cacheLocation, environmentVariable, exampleDevDriveLocation, existingDevDriveLetters, relatedEnvironmentVariablesToBeSet, relatedCacheDirectories)); services.AddSingleton(); - services.AddTransient(); - - services.AddTransient(); + services.AddTransient(); services.AddSingleton(); services.AddTransient(); diff --git a/tools/Customization/DevHome.Customization/Views/MainPageView.xaml b/tools/Customization/DevHome.Customization/Views/MainPageView.xaml index 1b8e3a709..530e6f750 100644 --- a/tools/Customization/DevHome.Customization/Views/MainPageView.xaml +++ b/tools/Customization/DevHome.Customization/Views/MainPageView.xaml @@ -7,8 +7,7 @@ xmlns:ui="using:CommunityToolkit.WinUI" xmlns:i="using:Microsoft.Xaml.Interactivity" xmlns:ic="using:Microsoft.Xaml.Interactions.Core" - xmlns:views="using:DevHome.Customization.Views" - xmlns:quietviews="using:DevHome.QuietBackgroundProcesses.UI.Views"> + xmlns:views="using:DevHome.Customization.Views"> @@ -61,9 +60,6 @@ - - - diff --git a/tools/Experiments/src/DevHome.Experiments.csproj b/tools/Experiments/src/DevHome.Experiments.csproj index 282fc7201..412896adc 100644 --- a/tools/Experiments/src/DevHome.Experiments.csproj +++ b/tools/Experiments/src/DevHome.Experiments.csproj @@ -12,7 +12,6 @@ - diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/Common.h b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/Common.h deleted file mode 100644 index e92ab65a1..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/Common.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#include - -// Get temporary path for performance data -inline std::filesystem::path GetTemporaryPerformanceDataPath() -{ - auto tempDirectory = std::filesystem::temp_directory_path(); - return std::filesystem::path(tempDirectory) / L"DevHome.QuietMode.PerformanceData.dat"; -} diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/DevHome.QuietBackgroundProcesses.Common.vcxproj b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/DevHome.QuietBackgroundProcesses.Common.vcxproj deleted file mode 100644 index bbdd8af81..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/DevHome.QuietBackgroundProcesses.Common.vcxproj +++ /dev/null @@ -1,219 +0,0 @@ - - - - C++ - - - - - Utlity - true - true - true - true - {4B370E2F-FB1D-4887-90BF-3B72517485CE} - DevHome.QuietBackgroundProcesses.Common - DevHome.QuietBackgroundProcesses - en-US - 14.0 - true - Windows Store - 10.0 - 10.0.22621.0 - 10.0.17134.0 - false - $(CppOutDir) - - - - - Debug_FailFast - ARM - - - Debug_FailFast - ARM64 - - - Debug_FailFast - Win32 - - - Debug_FailFast - x64 - - - Debug - ARM - - - Debug - ARM64 - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - ARM64 - - - Release - Win32 - - - Release - x64 - - - - StaticLibrary - v143 - v142 - v141 - v140 - Unicode - false - - - true - true - - - true - true - - - false - true - false - - - true - - - - - - - - - - - - - - - - NotUsing - - - - - Level4 - %(AdditionalOptions) /bigobj - _WINRT_DLL;WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) - - - Windows - false - - - - - - - stdcpp17 - %(AdditionalIncludeDirectories) - - - onecore.lib;%(AdditionalDependencies) - - - - - %(Filename).h - $(ProjectDir)$(GeneratedFilesDir)midl - $(ProjectDir)$(GeneratedFilesDir)winmd\%(Filename).winmd - - - - - _DEBUG;%(PreprocessorDefinitions) - Disabled - - - - - _DEBUG;%(PreprocessorDefinitions) - Disabled - - - - - NDEBUG;%(PreprocessorDefinitions) - - - true - true - - - - - - - - - - - - - - - - <_MdmergeInputs Include="@(Midl)" Condition="'%(Midl.ExcludedFromBuild)' != 'true'"> - %(Midl.MetadataFileName) - - - - - $(Platform)\$(Configuration)\Merged\ - -n:2 - -v - $(MdmergeParameters) -metadata_dir "$(WindowsSDK_MetadataFoundationPath)" - $(MdmergeParameters) @(MdmergeInputs->'-i "%(Identity)"', ' -') - $(MdmergeParameters) -o "$(MdmergeMergedDir.TrimEnd('\'))" -partial $(MdmergeMergeDepth) - - - $(MdmergeMergedDir)DevHome.QuietBackgroundProcesses.winmd - $(IntDir)$(MSBuildProjectFile).mdmerge.rsp - $(MdMergePath)mdmerge %40"$(MdmergeResponseFile)" - - - - - - - - - copy /Y "$(MdmergeMergedDir)DevHome.QuietBackgroundProcesses.winmd" "$(OutDir)." - - - - - - - - - - \ No newline at end of file diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/DevHome.QuietBackgroundProcesses.idl b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/DevHome.QuietBackgroundProcesses.idl deleted file mode 100644 index 1236b6e6c..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/DevHome.QuietBackgroundProcesses.idl +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -import "inspectable.idl"; -import "windows.foundation.idl"; - -namespace DevHome.QuietBackgroundProcesses -{ - // Performance Engine types - enum ProcessCategory - { - Unknown, - User, - System, - Developer, - Background, - }; - - [default_interface] - runtimeclass ProcessRow - { - UInt32 Pid { get; }; - String Name { get; }; - String ServiceName { get; }; - String PackageFullName { get; }; - String Aumid { get; }; - String Path { get; }; - ProcessCategory Category { get; }; - Windows.Foundation.DateTime CreateTime { get; }; - Windows.Foundation.DateTime ExitTime { get; }; - - UInt64 SampleCount { get; }; - Double PercentCumulative { get; }; - Double VarianceCumulative { get; }; - Double Sigma4Cumulative { get; }; - Double MaxPercent { get; }; - UInt32 SamplesAboveThreshold { get; }; - - UInt64 TotalCpuTimeInMicroseconds { get; }; - } - - [default_interface] - runtimeclass ProcessPerformanceTable - { - ProcessRow[] Rows { get; }; - } - - [default_interface] - runtimeclass PerformanceRecorderEngine - { - static ProcessPerformanceTable TryGetLastPerformanceRecording(); - - PerformanceRecorderEngine(); - void Start(Windows.Foundation.TimeSpan periodInMs); - ProcessPerformanceTable Stop(); - } - - // Quiet background process types - [default_interface] - runtimeclass QuietBackgroundProcessesSession - { - static QuietBackgroundProcessesSession GetSingleton(); - - Int64 Start(); - ProcessPerformanceTable Stop(); - Boolean IsActive { get; }; - Int64 TimeLeftInSeconds { get; }; - } - - [default_interface] - runtimeclass QuietBackgroundProcessesSessionManager { - QuietBackgroundProcessesSessionManager(); - static Boolean IsFeaturePresent(); - static QuietBackgroundProcessesSession GetSession(); - static QuietBackgroundProcessesSession TryGetSession(); - static Boolean HasLastPerformanceRecording(); - static ProcessPerformanceTable TryGetLastPerformanceRecording(); - } -} diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/PropertySheet.props b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/PropertySheet.props deleted file mode 100644 index e34141b01..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/PropertySheet.props +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/Utility.h b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/Utility.h deleted file mode 100644 index 9b42fa2fa..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Common/Utility.h +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#pragma once - -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -constexpr bool DEBUG_BUILD = -#if _DEBUG - true; -#else - false; -#endif - -template -struct wrl_module_object_ref -{ - struct details - { - static void wrl_decrement_object_count() - { - auto& module = T::GetModule(); - auto count = module.DecrementObjectCount(); - auto msg = std::wstring(L"WRL: DecrementObjectCount = ") + std::to_wstring(count) + std::wstring(L"\n"); - OutputDebugStringW(msg.c_str()); - } - }; - - using wrl_module_object_ref_releaser = wil::unique_call; - - wrl_module_object_ref() - { - auto& module = T::GetModule(); - auto count = module.IncrementObjectCount(); - auto msg = std::wstring(L"WRL: IncrementObjectCount = ") + std::to_wstring(count) + std::wstring(L"\n"); - OutputDebugStringW(msg.c_str()); - - m_moduleReference.activate(); - } - - wrl_module_object_ref(wrl_module_object_ref&& other) noexcept = default; - wrl_module_object_ref& operator=(wrl_module_object_ref&& other) noexcept = default; - - wrl_module_object_ref(const wrl_module_object_ref&) = delete; - wrl_module_object_ref& operator=(const wrl_module_object_ref&) = delete; - - void reset() - { - m_moduleReference.reset(); - } - -private: - - wrl_module_object_ref_releaser m_moduleReference{ false }; -}; - -using wrl_server_process_ref = wrl_module_object_ref>; - -inline std::optional try_get_registry_value_dword(HKEY key, _In_opt_ PCWSTR subKey, _In_opt_ PCWSTR value_name, ::wil::reg::key_access access = ::wil::reg::key_access::read) -{ - wil::unique_hkey hkey; - if (SUCCEEDED(wil::reg::open_unique_key_nothrow(key, subKey, hkey, access))) - { - if (auto keyvalue = wil::reg::try_get_value_dword(hkey.get(), value_name)) - { - return keyvalue.value(); - } - } - return std::nullopt; -} - -inline void WaitForDebuggerIfPresent() -{ - auto waitForDebugger = try_get_registry_value_dword(HKEY_LOCAL_MACHINE, LR"(Software\Microsoft\Windows\CurrentVersion\DevHome\QuietBackgroundProcesses)", L"WaitForDebugger"); - - if (waitForDebugger.value_or(0)) - { - while (!IsDebuggerPresent()) - { - Sleep(1000); - }; - DebugBreak(); - } -} - -inline bool IsTokenElevated(HANDLE token) -{ - auto mandatoryLabel = wil::get_token_information(token); - LONG levelRid = static_cast(mandatoryLabel->Label.Sid)->SubAuthority[0]; - return levelRid == SECURITY_MANDATORY_HIGH_RID; -} - -inline void SelfElevate(std::optional const& arguments) -{ - auto path = wil::GetModuleFileNameW(); - - SHELLEXECUTEINFO sei = { sizeof(sei) }; - sei.lpVerb = L"runas"; - sei.lpFile = path.get(); - sei.lpParameters = arguments.value().c_str(); - sei.hwnd = NULL; - sei.nShow = SW_NORMAL; - - THROW_LAST_ERROR_IF(!ShellExecuteEx(&sei)); -} - -inline std::wstring ParseServerNameArgument(std::wstring_view wargv) -{ - constexpr wchar_t serverNamePrefix[] = L"-ServerName:"; - if (_wcsnicmp(wargv.data(), serverNamePrefix, wcslen(serverNamePrefix)) != 0) - { - THROW_HR(E_UNEXPECTED); - } - return { wargv.data() + wcslen(serverNamePrefix) }; -} - -inline void SetComFastRundownAndNoEhHandle() -{ - // Enable fast rundown of COM stubs in this process to ensure that RPCSS bookkeeping is updated synchronously. - wil::com_ptr pGlobalOptions; - THROW_IF_FAILED(CoCreateInstance(CLSID_GlobalOptions, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pGlobalOptions))); - THROW_IF_FAILED(pGlobalOptions->Set(COMGLB_RO_SETTINGS, COMGLB_FAST_RUNDOWN)); - THROW_IF_FAILED(pGlobalOptions->Set(COMGLB_EXCEPTION_HANDLING, COMGLB_EXCEPTION_DONOT_HANDLE_ANY)); -} diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer.Projection/DevHome.QuietBackgroundProcesses.ElevatedServer.Projection.csproj b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer.Projection/DevHome.QuietBackgroundProcesses.ElevatedServer.Projection.csproj deleted file mode 100644 index b792576ee..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer.Projection/DevHome.QuietBackgroundProcesses.ElevatedServer.Projection.csproj +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - enable - enable - x86;x64;arm64 - win-x86;win-x64;win-arm64 - $(CppBaseOutDir)\DevHome.QuietBackgroundProcesses.Common\ - - - - 10.0.19041.0 - DevHome.QuietBackgroundProcesses - $(OutDir) - - - - $(OutDir) - - - - - - - - - - - - - - - - diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/DevHome.QuietBackgroundProcesses.ElevatedServer.vcxproj b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/DevHome.QuietBackgroundProcesses.ElevatedServer.vcxproj deleted file mode 100644 index 959d22e02..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/DevHome.QuietBackgroundProcesses.ElevatedServer.vcxproj +++ /dev/null @@ -1,216 +0,0 @@ - - - - C++ - - - - - - true - true - true - true - {75945141-03ac-4c40-a586-16d463a0ac1b} - DevHome.QuietBackgroundProcesses.ElevatedServer - DevHome.QuietBackgroundProcesses - en-US - 14.0 - true - Windows Store - 10.0 - 10.0.22621.0 - 10.0.17134.0 - false - true - $(CppOutDir) - - - - - Debug_FailFast - ARM - - - Debug_FailFast - ARM64 - - - Debug_FailFast - Win32 - - - Debug_FailFast - x64 - - - Debug - ARM - - - Debug - ARM64 - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - ARM64 - - - Release - Win32 - - - Release - x64 - - - - $(CppOutDir) - - - Application - v143 - v142 - v141 - v140 - Unicode - false - - - true - true - - - true - true - - - false - true - false - - - Spectre - - - - - - - - - - - - - - - - - Use - pch.h - $(IntDir)pch.pch - Level4 - %(AdditionalOptions) /bigobj - _WINRT_DLL;WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) - Guard - Spectre - - - Windows - false - - - - - - - stdcpp20 - $(SolutionDir)telemetry\DevHome.Telemetry.Native\inc;$(ProjectDir)..\DevHome.QuietBackgroundProcesses.Common\;$(ProjectDir)..\DevHome.QuietBackgroundProcesses.Common\$(GeneratedFilesDir)midl;$(ProjectDir)..\DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine\;%(AdditionalIncludeDirectories) - - - onecore.lib;%(AdditionalDependencies) - - - - - _DEBUG;%(PreprocessorDefinitions) - ProgramDatabase - Disabled - - - - - _DEBUG;%(PreprocessorDefinitions) - ProgramDatabase - Disabled - - - - - NDEBUG;%(PreprocessorDefinitions) - - - true - true - - - - - - - - - - - - - - Create - - - - - - - - - - - - - - {8eb52f7d-d216-49ff-bf16-de06e4695950} - - - {4b370e2f-fb1d-4887-90bf-3b72517485ce} - - - {af5a7fa0-e3e8-44c8-8830-31dd08f583e8} - - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - \ No newline at end of file diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/Helpers.cpp b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/Helpers.cpp deleted file mode 100644 index 0af73613a..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/Helpers.cpp +++ /dev/null @@ -1,223 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "DevHomeTelemetryProvider.h" -#include "PerformanceRecorderEngine.h" -#include "Helpers.h" - -void WritePerformanceDataToDisk(_In_ PCWSTR path, const std::span& data) -{ - std::ofstream file(path, std::ios::binary); - if (!file.is_open()) - { - // Handle error - return; - } - - for (const auto& item : data) - { - file.write(reinterpret_cast(&item), sizeof(ProcessPerformanceSummary)); - } - - file.close(); -} - -std::vector ReadPerformanceDataFromDisk(_In_ PCWSTR path) -{ - std::vector data; - - std::ifstream file(path, std::ios::binary); - THROW_WIN32_IF(ERROR_SHARING_VIOLATION, !file.is_open()); - - ProcessPerformanceSummary item; - while (file.read(reinterpret_cast(&item), sizeof(ProcessPerformanceSummary))) - { - data.push_back(item); - } - - file.close(); - return data; -} - -struct ComputerInformation -{ - DWORD processorCount; - std::wstring processor; - std::wstring motherboard; - DWORDLONG ramInMegabytes; -}; - -// Get computer information -ComputerInformation GetComputerInformation() -{ - ComputerInformation computerInfo; - - // Get processor information - SYSTEM_INFO systemInfo = { 0 }; - GetSystemInfo(&systemInfo); - computerInfo.processorCount = systemInfo.dwNumberOfProcessors; - - // Get processor make and model using win32 apis - wil::unique_hkey hKey; - if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0, KEY_READ, &hKey) == ERROR_SUCCESS) - { - wchar_t processorName[256] = { 0 }; - DWORD processorNameSize = sizeof(processorName); - if (RegQueryValueEx(hKey.get(), L"ProcessorNameString", nullptr, nullptr, reinterpret_cast(processorName), &processorNameSize) == ERROR_SUCCESS) - { - computerInfo.processor = processorName; - } - } - - // Get motherboard make and model using win32 apis - if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\BIOS", 0, KEY_READ, &hKey) == ERROR_SUCCESS) - { - wchar_t biosName[256] = { 0 }; - DWORD biosNameSize = sizeof(biosName); - if (RegQueryValueEx(hKey.get(), L"BaseBoardProduct", nullptr, nullptr, reinterpret_cast(biosName), &biosNameSize) == ERROR_SUCCESS) - { - computerInfo.motherboard = biosName; - } - } - - // Get ram amount using GlobalMemoryStatusEx - MEMORYSTATUSEX memoryStatus = { 0 }; - memoryStatus.dwLength = sizeof(memoryStatus); - if (GlobalMemoryStatusEx(&memoryStatus)) - { - computerInfo.ramInMegabytes = memoryStatus.ullTotalPhys / 1024 / 1024; - } - - return computerInfo; -} - -void UploadPerformanceDataTelemetry(std::chrono::milliseconds samplingPeriod, const std::span& data) -{ - using namespace std::chrono_literals; - - enum class UploadReason - { - None, - MaxPercent, - Sigma4, - StandardDeviation, - SearchIndexer, - }; - - constexpr auto c_quietSessionVersion = 1; - - // Calculate total cpu time usage for all processes - std::chrono::microseconds totalCpuUsageInMicroseconds = std::accumulate(data.begin(), data.end(), 0us, [](std::chrono::microseconds total, const ProcessPerformanceSummary& item) { - return total + std::chrono::microseconds(item.totalCpuTimeInMicroseconds); - }); - - // Begin metrics activity - auto activity = DevHomeTelemetryProvider::QuietBackgroundProcesses_PerformanceMetrics::Start( - c_quietSessionVersion, - samplingPeriod.count(), - totalCpuUsageInMicroseconds.count()); - - // Upload computer information - auto computerInformation = GetComputerInformation(); - activity.QuietBackgroundProcesses_ComputerInfo( - computerInformation.processorCount, - computerInformation.processor.c_str(), - computerInformation.motherboard.c_str(), - computerInformation.ramInMegabytes); - - // Calculate the totalCpuTimeInMicroseconds items aggregated by item.category - std::vector numProcesses(5); - std::vector totalCpuTimesByCategory(5); - for (const auto& item : data) - { - numProcesses[item.category]++; - totalCpuTimesByCategory[item.category] += item.totalCpuTimeInMicroseconds; - } - - // Upload category metrics - activity.QuietBackgroundProcesses_SessionCategoryMetrics( - numProcesses[0], - numProcesses[1], - numProcesses[2], - numProcesses[3], - numProcesses[4], - totalCpuTimesByCategory[0], - totalCpuTimesByCategory[1], - totalCpuTimesByCategory[2], - totalCpuTimesByCategory[3], - totalCpuTimesByCategory[4]); - - // Get system32 path - wchar_t system32Path[MAX_PATH]; - GetSystemDirectory(system32Path, ARRAYSIZE(system32Path)); - - // Choose process information to upload - for (const auto& item : data) - { - // Calculate variance & standard deviation - auto variance = item.varianceCumulative / item.sampleCount; - auto standardDeviation = std::sqrt(variance); - - // Calulate sigma4 variance & sigma4 deviation (it's like variance but to the power of 4 instead of 2). - // Note: This helps identify processes that have a high variance in cpu usage, which otherwise might be difficult - // to notice in a 2 hour time-window. - auto sigma4Variance = item.sigma4Cumulative / item.sampleCount; - auto sigma4Deviation = std::sqrt(std::sqrt(sigma4Variance)); - - UploadReason reason{}; - if (item.maxPercent >= 20.0) - { - reason = UploadReason::MaxPercent; - } - else if (sigma4Deviation >= 4.0) - { - reason = UploadReason::Sigma4; - } - else if (standardDeviation >= 1.0) - { - reason = UploadReason::StandardDeviation; - } - else if (wil::compare_string_ordinal(item.name, L"SearchIndexer.exe", true) == 0) - { - reason = UploadReason::SearchIndexer; - } - else - { - continue; - } - - // Report process name with service name in telemetry - auto processNameTelemetry = std::wstring(item.name); - if (item.serviceName) - { - processNameTelemetry += std::wstring{} + L" (" + item.serviceName + L")"; - } - - activity.QuietBackgroundProcesses_ProcessInfo( - reason, - wil::compare_string_ordinal(item.path, system32Path, true) == 0, - processNameTelemetry.c_str(), - item.category, - item.packageFullName, - - item.sampleCount, - item.maxPercent, - item.samplesAboveThreshold, - sigma4Deviation, - item.totalCpuTimeInMicroseconds); - } - - activity.Stop(); -} diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/Helpers.h b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/Helpers.h deleted file mode 100644 index 1c6f2dbbd..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/Helpers.h +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#pragma once - -#include -#include - -#include -#include - -#include "DevHome.QuietBackgroundProcesses.h" -#include "PerformanceRecorderEngine.h" - -struct com_ptr_deleter -{ - template - void operator()(_Pre_opt_valid_ _Frees_ptr_opt_ T p) const - { - if (p) - { - p.reset(); - } - } -}; - -template -using unique_comptr_array = wil::unique_any_array_ptr, ArrayDeleter, com_ptr_deleter>; - -template -unique_comptr_array make_unique_comptr_array(size_t numOfElements) -{ - auto list = unique_comptr_array(reinterpret_cast*>(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, numOfElements * sizeof(wil::com_ptr_nothrow))), numOfElements); - THROW_IF_NULL_ALLOC(list.get()); - return list; -} - -// Create a performance recorder engine -wil::com_ptr MakePerformanceRecorderEngine(); - -// Read/write the performance data to/from disk -void WritePerformanceDataToDisk(_In_ PCWSTR path, const std::span& data); -std::vector ReadPerformanceDataFromDisk(_In_ PCWSTR path); - -// Upload the performance data to the telemetry service -void UploadPerformanceDataTelemetry(std::chrono::milliseconds samplingPeriod, const std::span& data); diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/PerformanceRecorderEngineWinrt.cpp b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/PerformanceRecorderEngineWinrt.cpp deleted file mode 100644 index c7e971cb5..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/PerformanceRecorderEngineWinrt.cpp +++ /dev/null @@ -1,364 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include "Common.h" -#include "TimedQuietSession.h" -#include "DevHome.QuietBackgroundProcesses.h" -#include "PerformanceRecorderEngine.h" -#include "Helpers.h" - - -namespace ABI::DevHome::QuietBackgroundProcesses -{ - class ProcessRow : - public Microsoft::WRL::RuntimeClass< - Microsoft::WRL::RuntimeClassFlags, - IProcessRow, - Microsoft::WRL::FtmBase> - { - InspectableClass(RuntimeClass_DevHome_QuietBackgroundProcesses_ProcessRow, BaseTrust); - - public: - STDMETHODIMP RuntimeClassInitialize(ProcessPerformanceSummary summary) noexcept - { - m_summary = summary; - return S_OK; - } - - STDMETHODIMP get_Pid(unsigned int* value) noexcept override - try - { - *value = m_summary.pid; - return S_OK; - } - CATCH_RETURN() - - STDMETHODIMP get_Name(HSTRING* value) noexcept override - try - { - Microsoft::WRL::Wrappers::HString str; - str.Set(m_summary.name); - *value = str.Detach(); - return S_OK; - } - CATCH_RETURN() - - STDMETHODIMP get_ServiceName(HSTRING* value) noexcept override - try - { - Microsoft::WRL::Wrappers::HString str; - str.Set(m_summary.serviceName); - *value = str.Detach(); - return S_OK; - } - CATCH_RETURN() - - STDMETHODIMP get_PackageFullName(HSTRING* value) noexcept override - try - { - Microsoft::WRL::Wrappers::HString str; - str.Set(m_summary.packageFullName); - *value = str.Detach(); - return S_OK; - } - CATCH_RETURN() - - STDMETHODIMP get_Aumid(HSTRING* value) noexcept override - try - { - Microsoft::WRL::Wrappers::HString str; - str.Set(m_summary.aumid); - *value = str.Detach(); - return S_OK; - } - CATCH_RETURN() - - STDMETHODIMP get_Path(HSTRING* value) noexcept override - try - { - Microsoft::WRL::Wrappers::HString str; - str.Set(m_summary.path); - *value = str.Detach(); - return S_OK; - } - CATCH_RETURN() - - STDMETHODIMP get_Category(ABI::DevHome::QuietBackgroundProcesses::ProcessCategory* value) noexcept override - try - { - *value = static_cast(m_summary.category); - return S_OK; - } - CATCH_RETURN() - - STDMETHODIMP get_CreateTime(struct ABI::Windows::Foundation::DateTime* value) noexcept override - try - { - INT64 time = m_summary.createTime.dwLowDateTime + ((UINT64)m_summary.createTime.dwHighDateTime << 32); - *value = ABI::Windows::Foundation::DateTime{ time }; - return S_OK; - } - CATCH_RETURN() - - STDMETHODIMP get_ExitTime(struct ABI::Windows::Foundation::DateTime* value) noexcept override - try - { - INT64 time = m_summary.exitTime.dwLowDateTime + ((UINT64)m_summary.exitTime.dwHighDateTime << 32); - *value = ABI::Windows::Foundation::DateTime{ time }; - return S_OK; - } - CATCH_RETURN() - - STDMETHODIMP get_SampleCount(unsigned __int64* value) noexcept override - try - { - *value = m_summary.sampleCount; - return S_OK; - } - CATCH_RETURN() - - STDMETHODIMP get_PercentCumulative(double* value) noexcept override - try - { - *value = m_summary.percentCumulative; - return S_OK; - } - CATCH_RETURN() - - STDMETHODIMP get_VarianceCumulative(double* value) noexcept override - try - { - *value = m_summary.varianceCumulative; - return S_OK; - } - CATCH_RETURN() - - STDMETHODIMP get_Sigma4Cumulative(double* value) noexcept override - try - { - *value = m_summary.sigma4Cumulative; - return S_OK; - } - CATCH_RETURN() - - STDMETHODIMP get_MaxPercent(double* value) noexcept override - try - { - *value = m_summary.maxPercent; - return S_OK; - } - CATCH_RETURN() - - STDMETHODIMP get_SamplesAboveThreshold(unsigned __int32* value) noexcept override - try - { - *value = m_summary.samplesAboveThreshold; - return S_OK; - } - CATCH_RETURN() - - STDMETHODIMP get_TotalCpuTimeInMicroseconds(unsigned __int64* value) noexcept override - try - { - *value = m_summary.totalCpuTimeInMicroseconds; - return S_OK; - } - CATCH_RETURN() - - private: - ProcessPerformanceSummary m_summary; - }; -} - -namespace ABI::DevHome::QuietBackgroundProcesses -{ - class ProcessPerformanceTable : - public Microsoft::WRL::RuntimeClass< - Microsoft::WRL::RuntimeClassFlags, - IProcessPerformanceTable, - Microsoft::WRL::FtmBase> - { - InspectableClass(RuntimeClass_DevHome_QuietBackgroundProcesses_ProcessPerformanceTable, BaseTrust); - - public: - STDMETHODIMP RuntimeClassInitialize(unique_process_utilization_monitoring_thread context) noexcept - { - m_context = std::move(context); - return S_OK; - } - - STDMETHODIMP get_Rows(unsigned int* valueLength, ABI::DevHome::QuietBackgroundProcesses::IProcessRow*** value) noexcept override - try - { - std::span span; - wil::unique_cotaskmem_array_ptr summariesCoarray; - std::vector summariesVector; - - if (m_context) - { - // We have a live context, read performance data from it - THROW_IF_FAILED(GetMonitoringProcessUtilization(m_context.get(), nullptr, summariesCoarray.addressof(), summariesCoarray.size_address())); - - // Make span from cotaskmem_array - span = std::span{ summariesCoarray.get(), summariesCoarray.size() }; - } - else - { - // We don't have a live context. Let's try to read performance data from disk. - auto performanceDataFile = GetTemporaryPerformanceDataPath(); - THROW_HR_IF(E_FAIL, !std::filesystem::exists(performanceDataFile)); - - // Make span from vector - summariesVector = ReadPerformanceDataFromDisk(performanceDataFile.c_str()); - span = std::span{ summariesVector }; - } - - // Create IProcessRow entries - auto list = make_unique_comptr_array(span.size()); - for (uint32_t i = 0; i < span.size(); i++) - { - auto& summary = span[i]; - wil::com_ptr row; - THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize(&row, summary)); - list[i] = std::move(row); - } - *valueLength = static_cast(span.size()); - *value = (ABI::DevHome::QuietBackgroundProcesses::IProcessRow**)list.release(); - return S_OK; - } - CATCH_RETURN() - - private: - unique_process_utilization_monitoring_thread m_context; - }; -} - -namespace ABI::DevHome::QuietBackgroundProcesses -{ - class PerformanceRecorderEngine : - public Microsoft::WRL::RuntimeClass< - Microsoft::WRL::RuntimeClassFlags, - IPerformanceRecorderEngine, - Microsoft::WRL::FtmBase> - { - InspectableClass(RuntimeClass_DevHome_QuietBackgroundProcesses_PerformanceRecorderEngine, BaseTrust); - - public: - STDMETHODIMP RuntimeClassInitialize() noexcept - { - return S_OK; - } - - // IPerformanceRecorderEngine - STDMETHODIMP Start(ABI::Windows::Foundation::TimeSpan samplingPeriod) noexcept override - try - { - // Convert TimeSpan from 100ns to milliseconds - auto periodInMs = static_cast(samplingPeriod.Duration / 10000); - THROW_IF_FAILED(StartMonitoringProcessUtilization(periodInMs, &m_context)); - return S_OK; - } - CATCH_RETURN() - - STDMETHODIMP Stop(ABI::DevHome::QuietBackgroundProcesses::IProcessPerformanceTable** result) noexcept override - try - { - THROW_IF_FAILED(StopMonitoringProcessUtilization(m_context.get())); - - { - // Get the performance data from the monitoring engine - std::chrono::milliseconds samplingPeriod; - wil::unique_cotaskmem_array_ptr summaries; - THROW_IF_FAILED(GetMonitoringProcessUtilization(m_context.get(), &samplingPeriod, summaries.addressof(), summaries.size_address())); - std::span data(summaries.get(), summaries.size()); - - // Write the performance .csv data to disk (if Dev Home is closed, enables user to see the Analytic Summary later) - try - { - auto performanceDataFile = GetTemporaryPerformanceDataPath(); - WritePerformanceDataToDisk(performanceDataFile.c_str(), data); - } - CATCH_LOG(); - - // Upload the performance data telemetry - try - { - UploadPerformanceDataTelemetry(samplingPeriod, data); - } - CATCH_LOG(); - } - - if (result) - { - wil::com_ptr performanceTable; - THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize(&performanceTable, std::move(m_context))); - *result = performanceTable.detach(); - } - - // Destroy the performance engine instance - m_context.reset(); - - return S_OK; - } - CATCH_RETURN() - - private: - unique_process_utilization_monitoring_thread m_context; - }; - - class PerformanceRecorderEngineStatics WrlFinal : - public Microsoft::WRL::AgileActivationFactory< - Microsoft::WRL::Implements> - { - InspectableClassStatic(RuntimeClass_DevHome_QuietBackgroundProcesses_PerformanceRecorderEngine, BaseTrust); - - public: - STDMETHODIMP ActivateInstance(_COM_Outptr_ IInspectable**) noexcept - { - // Disallow activation - must use GetSingleton() - return E_NOTIMPL; - } - - // IPerformanceRecorderEngineStatics - STDMETHODIMP TryGetLastPerformanceRecording(_COM_Outptr_ ABI::DevHome::QuietBackgroundProcesses::IProcessPerformanceTable** result) noexcept override - try - { - // Reconstruct a perform table from disk (passing nullptr for context) - wil::com_ptr performanceTable; - THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize(&performanceTable, nullptr)); - *result = performanceTable.detach(); - - return S_OK; - } - CATCH_RETURN() - }; - - ActivatableClassWithFactory(PerformanceRecorderEngine, PerformanceRecorderEngineStatics); -} - -wil::com_ptr MakePerformanceRecorderEngine() -{ - using namespace ABI::DevHome::QuietBackgroundProcesses; - wil::com_ptr result; - THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize(&result)); - return result; -} diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/PropertySheet.props b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/PropertySheet.props deleted file mode 100644 index e34141b01..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/PropertySheet.props +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/QuietBackgroundProcessesSession.cpp b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/QuietBackgroundProcessesSession.cpp deleted file mode 100644 index 6179b9577..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/QuietBackgroundProcessesSession.cpp +++ /dev/null @@ -1,141 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#include - -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include "TimedQuietSession.h" - -#include "DevHome.QuietBackgroundProcesses.h" - -constexpr auto DEFAULT_QUIET_DURATION = std::chrono::hours(2); - -std::mutex g_mutex; -std::unique_ptr g_activeTimer; - -namespace ABI::DevHome::QuietBackgroundProcesses -{ - class QuietBackgroundProcessesSession : - public Microsoft::WRL::RuntimeClass< - Microsoft::WRL::RuntimeClassFlags, - IQuietBackgroundProcessesSession, - Microsoft::WRL::FtmBase> - { - InspectableClass(RuntimeClass_DevHome_QuietBackgroundProcesses_QuietBackgroundProcessesSession, BaseTrust); - - public: - STDMETHODIMP RuntimeClassInitialize() noexcept - { - return S_OK; - } - - // IQuietBackgroundProcessesSession - STDMETHODIMP Start(__int64* result) noexcept override try - { - auto lock = std::scoped_lock(g_mutex); - - // Stop and discard the previous timer - if (g_activeTimer) - { - g_activeTimer->Cancel(nullptr); - } - - std::chrono::seconds duration = DEFAULT_QUIET_DURATION; - if (auto durationOverride = try_get_registry_value_dword(HKEY_LOCAL_MACHINE, LR"(Software\Microsoft\Windows\CurrentVersion\DevHome\QuietBackgroundProcesses)", L"Duration")) - { - duration = std::chrono::seconds(durationOverride.value()); - } - - // Let's make the quiet window a placebo 5 percent of the time - bool placebo = (rand() % 100) < 5; - - // Start timer - g_activeTimer.reset(new TimedQuietSession(placebo, duration)); - - // Return duration for showing countdown - *result = g_activeTimer->TimeLeftInSeconds().count(); - return S_OK; - } - CATCH_RETURN() - - STDMETHODIMP Stop(ABI::DevHome::QuietBackgroundProcesses::IProcessPerformanceTable** result) noexcept override - try - { - auto lock = std::scoped_lock(g_mutex); - *result = nullptr; - - // Turn off quiet mode and cancel timer - if (g_activeTimer) - { - g_activeTimer->Cancel(result); - g_activeTimer.reset(); - } - - return S_OK; - } - CATCH_RETURN() - - STDMETHODIMP get_IsActive(::boolean* value) noexcept override try - { - auto lock = std::scoped_lock(g_mutex); - *value = false; - if (g_activeTimer) - { - *value = g_activeTimer->IsActive(); - } - return S_OK; - } - CATCH_RETURN() - - STDMETHODIMP get_TimeLeftInSeconds(__int64* value) noexcept override try - { - auto lock = std::scoped_lock(g_mutex); - *value = 0; - if (g_activeTimer) - { - *value = g_activeTimer->TimeLeftInSeconds().count(); - } - return S_OK; - } - CATCH_RETURN() - }; - - class QuietBackgroundProcessesSessionStatics WrlFinal : - public Microsoft::WRL::AgileActivationFactory< - Microsoft::WRL::Implements> - { - InspectableClassStatic(RuntimeClass_DevHome_QuietBackgroundProcesses_QuietBackgroundProcessesSession, BaseTrust); - - public: - STDMETHODIMP ActivateInstance(_COM_Outptr_ IInspectable**) noexcept - { - // Disallow activation - must use GetSingleton() - return E_NOTIMPL; - } - - // IQuietBackgroundProcessesSessionStatics - STDMETHODIMP GetSingleton(_COM_Outptr_ IQuietBackgroundProcessesSession** session) noexcept override try - { - // Instanced objects are the only feasible way to manage a COM singleton without keeping a strong - // handle to the server - which keeps it alive. (IWeakReference keeps a strong handle to the server!) - // An 'instance' can be thought of as a 'handle' to 'the singleton' backend. - THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize(session)); - return S_OK; - } - CATCH_RETURN() - }; - - ActivatableClassWithFactory(QuietBackgroundProcessesSession, QuietBackgroundProcessesSessionStatics); -} diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/QuietState.cpp b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/QuietState.cpp deleted file mode 100644 index b6a6fbf14..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/QuietState.cpp +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#include "pch.h" - -#include - -#include -#include "QuietState.h" - -namespace QuietState -{ - std::mutex g_mutex; - - void TurnOff() noexcept - { - auto lock = std::scoped_lock(g_mutex); - LOG_IF_FAILED(DisableQuietBackgroundProcesses()); - } - - unique_quietwindowclose_call TurnOn() - { - auto lock = std::scoped_lock(g_mutex); - THROW_IF_FAILED(EnableQuietBackgroundProcesses()); - return unique_quietwindowclose_call{}; - } -} diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/QuietState.h b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/QuietState.h deleted file mode 100644 index 92ac8855c..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/QuietState.h +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) Microsoft Corporation and Contributors -// Licensed under the MIT license. - -#pragma once - -#include - -namespace QuietState -{ - void TurnOff() noexcept; - - using unique_quietwindowclose_call = wil::unique_call; - - unique_quietwindowclose_call TurnOn(); -} - diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/TimedQuietSession.h b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/TimedQuietSession.h deleted file mode 100644 index 6ad27b697..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/TimedQuietSession.h +++ /dev/null @@ -1,199 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#pragma once - -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include "DevHomeTelemetryProvider.h" - -#include "DevHome.QuietBackgroundProcesses.h" - -#include "Timer.h" -#include "QuietState.h" -#include "Helpers.h" - -using ElevatedServerReference = wrl_server_process_ref; - -struct UnelevatedServerReference -{ - wil::com_ptr m_reference; - - UnelevatedServerReference() : - m_reference(wil::GetActivationFactory(RuntimeClass_DevHome_QuietBackgroundProcesses_QuietBackgroundProcessesSessionManager)) - { - } - - void reset() - { - m_reference.reset(); - } -}; - - -// TimedQuietSession is a 2 hour "Quiet background processes" timed window that disables quiet -// mode when the timer expires or when explicitly cancelled. It keeps also keeps the server alive. -// -// TimedQuietSession maintains, -// 1. quiet mode signal -// 2. session timer -// 3. handle to session (elevated) server -// 4. handle to manager (unelevated) server -// -// COM server lifetime & process interaction: -// -// Processes: -// DevHome (client) -> UnelevatedServer (manager) -> ElevatedServer (session) -// -// Manager (unelevated server): -// Role of manager is simply allow client to check if session (elevated server) is alive -// without risking launching a UAC prompt. It caches a com proxy interface to session. -// -// Session (elevated server): -// Role of session is to enable/disable quiet mode and keep a timer. -// -// Lifetime: -// - The manager and session keep each other alive. -// -// - The session (TimedQuietSession) runs in ElevatedServer and keeps this elevated server -// alive until timer expiration. -// -// - The session (TimedQuietSession) also keeps the manager (in unelevated server) alive until timer expiration; -// this is only because the manager caches a *strong* handle to the session (elevated server), -// and there is no way to invalidate the session (proxy handle) in the client if we tore down -// this session. (Using IWeakReference does hold a weak reference to the object, but also holds a strong -// reference against the hosting process's lifetime.) -// -// Teardown Sequence: -// When all session timers (elevated) expire, the manager (unelevated) reference is released -> COM triggers -// teardown in unelevated server (assuming DevHome is closed), releasing the cached *strong* reference -// to the session (elevated) -> COM triggers teardown in elevated server. -// -#pragma warning(push) -#pragma warning(disable : 4324) // Avoid WRL alignment warning -struct TimedQuietSession -{ - TimedQuietSession(bool isPlacebo, std::chrono::seconds seconds) - { - // Save activity for telemetry - auto activity = DevHomeTelemetryProvider::QuietBackgroundProcesses_ElevatedServer_Session::Start(isPlacebo, seconds.count()); - - m_intendedDurationInSeconds = seconds; - - m_timer = std::make_unique(seconds, [this]() { - auto lock = std::scoped_lock(m_mutex); - Deactivate(false); - }); - - // Turn on quiet mode - if (isPlacebo) - { - // Don't actaully turn on quiet mode - i.e. control group for quiet mode in telemetry - } - else - { - m_quietState = QuietState::TurnOn(); - } - - // Start performance recorder - ABI::Windows::Foundation::TimeSpan samplingPeriod; - samplingPeriod.Duration = 1000 * 10000; // 1 second - m_performanceRecorderEngine = MakePerformanceRecorderEngine(); - THROW_IF_FAILED(m_performanceRecorderEngine->Start(samplingPeriod)); - - m_activity = activity.TransferToMember(); - } - - TimedQuietSession(TimedQuietSession&& other) noexcept = default; - TimedQuietSession& operator=(TimedQuietSession&& other) noexcept = default; - - TimedQuietSession(const TimedQuietSession&) = delete; - TimedQuietSession& operator=(const TimedQuietSession&) = delete; - - std::chrono::seconds TimeLeftInSeconds() - { - auto lock = std::scoped_lock(m_mutex); - return m_timer->TimeLeftInSeconds(); - } - - bool IsActive() - { - auto lock = std::scoped_lock(m_mutex); - return (bool)m_quietState; - } - - void Cancel(ABI::DevHome::QuietBackgroundProcesses::IProcessPerformanceTable** result) - { - auto lock = std::scoped_lock(m_mutex); - - Deactivate(true, result); - m_timer->Cancel(); - - // Destruct timer on another thread because it's destructor is blocking - auto destructionThread = std::thread([timer = std::move(m_timer)]() { - // destruct timer here - }); - - destructionThread.detach(); - } - -private: - void Deactivate(bool manuallyStopped, ABI::DevHome::QuietBackgroundProcesses::IProcessPerformanceTable** result = nullptr) - { - if (m_deactivated) - { - return; - } - - // Continue activity on current thread - auto activity = m_activity.TransferToCurrentThread(); - - auto totalQuietWindowTime = m_intendedDurationInSeconds - m_timer->TimeLeftInSeconds(); - - // Turn off quiet mode - m_quietState.reset(); - - // Stop the performance recorder - if (m_performanceRecorderEngine) - { - LOG_IF_FAILED(m_performanceRecorderEngine->Stop(result)); - } - - // Disable performance recorder - m_performanceRecorderEngine.reset(); - - // Release lifetime handles to this elevated server and unelevated client server - m_unelevatedServer.reset(); - m_elevatedServer.reset(); - - // Only allow deactivation once - m_deactivated = true; - - // Stop activity - activity.Stop(manuallyStopped, totalQuietWindowTime.count()); - } - - UnelevatedServerReference m_unelevatedServer; // Manager server - ElevatedServerReference m_elevatedServer; // Session server (this server) - - bool m_deactivated{}; - QuietState::unique_quietwindowclose_call m_quietState{ false }; - std::unique_ptr m_timer; - wil::com_ptr m_performanceRecorderEngine; - std::mutex m_mutex; - - DevHomeTelemetryProvider::QuietBackgroundProcesses_ElevatedServer_Session m_activity; - std::chrono::seconds m_intendedDurationInSeconds{}; -}; -#pragma warning(pop) diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/Timer.h b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/Timer.h deleted file mode 100644 index e112b6513..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/Timer.h +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "Utility.h" - -#if _DEBUG || NDEBUG -#define TRACK_SECONDS_LEFT -#endif - -using namespace std::chrono_literals; - -class Timer -{ -public: - Timer(std::chrono::seconds seconds, std::function callback) : - m_callback(std::forward>(callback)), - m_startTime(std::chrono::steady_clock::now()), - m_duration(seconds), - m_timerThread(std::thread(&Timer::TimerThread, this)) - { - } - - Timer(Timer&& other) noexcept = default; - Timer& operator=(Timer&& other) noexcept = default; - - Timer(const Timer&) = delete; - Timer& operator=(const Timer&) = delete; - - ~Timer() - { - if (m_timerThread.joinable()) - { - m_timerThread.join(); - } - } - - void Cancel() - { - OutputDebugStringW(L"Timer: Cancelling\n"); - - auto lock = std::scoped_lock(m_mutex); - - // Disable the callback from being called... - m_cancelled = true; - - // ... wake up the timer thread. - m_cancelCondition.notify_one(); - } - - std::chrono::seconds TimeLeftInSeconds() - { - auto lock = std::scoped_lock(m_mutex); - if (m_cancelled) - { - return 0s; - } - - auto secondsLeft = CalculateSecondsLeft(); - return std::max(secondsLeft, 0s); - } - -private: - std::chrono::seconds CalculateSecondsLeft() - { - auto now = std::chrono::steady_clock::now(); - auto elapsed = std::chrono::duration_cast(now - m_startTime); - auto secondsLeft = m_duration - elapsed; -#ifdef TRACK_SECONDS_LEFT - m_secondsLeft = secondsLeft; -#endif - return secondsLeft; - } - - void TimerThread() - { - // Pause until timer expired or cancelled - { - auto lock = std::unique_lock(m_mutex); - - m_cancelCondition.wait_for(lock, m_duration, [this] { - return this->m_cancelled; - }); - } - - // Do the callback - if (!this->m_cancelled) - { - this->m_callback(); - } - - OutputDebugStringW(L"Timer: Finished\n"); - } - - std::chrono::steady_clock::time_point m_startTime{}; - std::chrono::seconds m_duration{}; - std::thread m_timerThread; - std::mutex m_mutex; - bool m_cancelled{}; - std::condition_variable m_cancelCondition; - std::function m_callback; - -#ifdef TRACK_SECONDS_LEFT - std::chrono::seconds m_secondsLeft = std::chrono::seconds::max(); -#endif -}; diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/main.cpp b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/main.cpp deleted file mode 100644 index 067085996..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/main.cpp +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "Utility.h" -#include "TimedQuietSession.h" -#include "QuietState.h" - -int __stdcall wWinMain(HINSTANCE, HINSTANCE, LPWSTR wargv, int wargc) try -{ - constexpr auto ELEVATED_SERVER_STARTED_EVENT_NAME = L"Global\\DevHome_QuietBackgroundProcesses_ElevatedServer_Started"; - - if (wargc < 1) - { - THROW_HR(E_INVALIDARG); - } - - // Parse the servername from the cmdline argument, e.g. "-ServerName:DevHome.QuietBackgroundProcesses.ElevatedServer" - auto serverName = ParseServerNameArgument(wargv); - - if (wil::compare_string_ordinal(serverName, L"DevHome.QuietBackgroundProcesses.ElevatedServer", true) != 0) - { - THROW_HR(E_INVALIDARG); - } - - // Let's self-elevate and terminate - if (!IsTokenElevated(GetCurrentProcessToken())) - { - wil::unique_event elevatedServerRunningEvent; - elevatedServerRunningEvent.create(wil::EventOptions::ManualReset, ELEVATED_SERVER_STARTED_EVENT_NAME); - - // Launch elevated instance - SelfElevate(wargv); - - // Wait for the *actual* elevated server instance to register its winrt classes with COM before shutting down - elevatedServerRunningEvent.wait(); - return 0; - } - - WaitForDebuggerIfPresent(); - - auto unique_rouninitialize_call = wil::RoInitialize(); - - // Enable fast rundown of COM stubs in this process to ensure that RPCSS bookkeeping is updated synchronously. - SetComFastRundownAndNoEhHandle(); - - // To be safe, force quiet mode off to begin the proceedings in case we leaked the machine state previously - QuietState::TurnOff(); - - std::mutex mutex; - bool comFinished{}; - std::condition_variable finishCondition; - -#pragma warning(push) -#pragma warning(disable : 4324) // Avoid WRL alignment warning - - // Register WRL callback when all objects are destroyed - auto& module = Microsoft::WRL::Module::Create([&] { - // The last instance object of the module is released - { - auto lock = std::unique_lock(mutex); - comFinished = true; - } - finishCondition.notify_one(); - }); - -#pragma warning(pop) - - // Register WinRT activatable classes - module.RegisterObjects(); - auto unique_wrl_registration_cookie = wil::scope_exit([&module]() { - module.UnregisterObjects(); - }); - - // Tell the unelevated server instance that we've registered our winrt classes with COM (so it can terminate) - wil::unique_event elevatedServerRunningEvent; - elevatedServerRunningEvent.open(ELEVATED_SERVER_STARTED_EVENT_NAME); - elevatedServerRunningEvent.SetEvent(); - - // Wait for all server references to release (implicitly also waiting for timers to finish via CoAddRefServerProcess) - auto lock = std::unique_lock(mutex); - - finishCondition.wait(lock, [&] { - return comFinished; - }); - - // Safety - QuietState::TurnOff(); - - return 0; -} -CATCH_RETURN() diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/packages.config b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/packages.config deleted file mode 100644 index 1e9a0103c..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/packages.config +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/pch.cpp b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/pch.cpp deleted file mode 100644 index d58e93e60..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/pch.cpp +++ /dev/null @@ -1,4 +0,0 @@ -// Copyright (c) Microsoft Corporation and Contributors -// Licensed under the MIT license. - -#include "pch.h" diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/pch.h b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/pch.h deleted file mode 100644 index 601ace8be..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.ElevatedServer/pch.h +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) Microsoft Corporation and Contributors -// Licensed under the MIT license. - -#pragma once - -#define NOMINMAX - -#include -#include -#include diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine.vcxproj b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine.vcxproj deleted file mode 100644 index c60233ad2..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine.vcxproj +++ /dev/null @@ -1,270 +0,0 @@ - - - - C++ - - - - - - Debug_FailFast - ARM64 - - - Debug_FailFast - Win32 - - - Debug_FailFast - x64 - - - Debug - ARM64 - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM64 - - - Release - Win32 - - - Release - x64 - - - - {af5a7fa0-e3e8-44c8-8830-31dd08f583e8} - DynamicLibrary - DevHome_QuietBackgroundProcesses_PerformanceRecorderEngine - en-US - 14.0 - false - Windows Store - 10.0.22621.0 - 10.0.17134.0 - 10.0 - $(CppOutDir) - - - - DynamicLibrary - true - v143 - Spectre - - - DynamicLibrary - true - v143 - Spectre - - - DynamicLibrary - true - v143 - Spectre - - - DynamicLibrary - true - v143 - Spectre - - - DynamicLibrary - true - v143 - Spectre - - - DynamicLibrary - true - v143 - Spectre - - - DynamicLibrary - false - true - v143 - Spectre - - - DynamicLibrary - false - true - v143 - Spectre - - - DynamicLibrary - false - true - v143 - true - Spectre - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - false - false - - - false - false - - - false - false - - - false - false - - - false - false - - - false - false - - - false - false - - - false - false - - - false - false - - - - Use - false - stdcpp20 - - - Console - false - false - onecore.lib;onecoreuap_apiset.lib;%(AdditionalDependencies) - - - - - _DEBUG;%(PreprocessorDefinitions) - Disabled - Guard - Guard - Guard - ProgramDatabase - ProgramDatabase - ProgramDatabase - - - - - _DEBUG;%(PreprocessorDefinitions) - Disabled - Guard - Guard - Guard - ProgramDatabase - ProgramDatabase - ProgramDatabase - - - - - NDEBUG;%(PreprocessorDefinitions) - Guard - Guard - Guard - - - true - true - - - - - - - - - - - Create - Create - Create - Create - Create - Create - Create - Create - Create - - - - - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - \ No newline at end of file diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine.vcxproj.filters b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine.vcxproj.filters deleted file mode 100644 index 2a68852d4..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine.vcxproj.filters +++ /dev/null @@ -1,30 +0,0 @@ - - - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms - - - {a4747e26-49cd-412b-b5ad-2d499887d0d5} - - - - - - - - - - - inc - - - - - - - - - - \ No newline at end of file diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/PerformanceRecorderEngine.cpp b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/PerformanceRecorderEngine.cpp deleted file mode 100644 index 33d8d949f..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/PerformanceRecorderEngine.cpp +++ /dev/null @@ -1,715 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#include "pch.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -#include "PerformanceRecorderEngine.h" -#include "ServiceInformation.h" - -// 2 percent is the threshold for a process to be considered as a high CPU consumer -#define CPU_TIME_ABOVE_THRESHOLD_STRIKE_VALUE 2.0f - -enum class ProcessCategory -{ - Unknown, - User, - System, - Developer, - Background, -}; - -struct ProcessPerformanceInfo -{ - // Process id - wil::unique_process_handle process; - ULONG pid{}; - - // Process info - std::wstring name; - std::optional serviceName; - std::wstring path; - std::optional packageFullName; - std::optional aumid; - ProcessCategory category{}; - FILETIME createTime{}; - FILETIME exitTime{}; - - // CPU times - FILETIME startUserTime{}; - FILETIME startKernelTime{}; - FILETIME previousUserTime{}; - FILETIME currentUserTime{}; - FILETIME previousKernelTime{}; - FILETIME currentKernelTime{}; - - // Sampling - uint64_t sampleCount{}; - double percentCumulative{}; - double varianceCumulative{}; - double sigma4Cumulative{}; - double maxPercent{}; - uint32_t samplesAboveThreshold{}; -}; - -// Process Categories -std::set c_user = { - L"chrome.exe", - L"OUTLOOK.exe", - L"EXCEL.exe", - L"explorer.exe", - L"WINWORD.exe", - L"POWERPOINT.exe", - L"OfficeClickToRun.exe", - L"Microsoft.SharePoint.exe", - L"msedge.exe", - L"msedgewebview2.exe", - L"ShellExperienceHost.exe", - L"StartMenuExperienceHost.exe", - L"smartscreen.exe", - L"sihost.exe", - L"SystemSettings.exe", - L"electron.exe", - L"CrmSandbox.exe", - L"ms-teams.exe", - L"TextInputHost.exe", - L"UserOOBEBroker.exe", - L"WebViewHost.exe", - L"Widgets.exe", - L"WidgetService.exe", - L"XboxGameBarWidgets.exe", - L"teams.exe" -}; -std::set c_system = { - L"System", - L"Registry", - L"Secure System", - L"audiodg.exe", - L"ctfmon.exe", - L"LogonUI.exe", - L"MpDefenderCoreService.exe", - L"MpDlpService.exe", - L"ShellHost.exe", - L"smss.exe", - L"spoolsv.exe", - L"wininit.exe", - L"lsass.exe" -}; -std::set c_developer = { - L"cmd.exe", - L"conhost.exe", - L"console.exe", - L"OpenConsole.exe", - L"powershell.exe", - L"cl.exe", - L"link.exe", - L"devenv.exe", - L"DevHome.exe", - L"DevHomeGitHubExtension.exe", - L"python.exe", - L"build.exe", - L"msbuild.exe", - L"windbg.exe", - L"windbgx.exe", - L"EngHost.exe", - L"DbgX.Shell.exe", - L"GVFS.Mount.exe", - L"GVFS.Service.exe", - L"GVFS.ServiceUI.exe", - L"vscode.exe", - L"code.exe", - L"cpptools.exe", - L"notepad.exe", - L"notepad++.exe", - L"Wex.Services.exe", - L"Taskmgr.exe", - L"wpa.exe", - L"wpr.exe", - L"CalculatorApp.exe", - L"npm.exe", - L"winget.exe", - L"chocolatey.exe", - L"pip.exe", - L"vshost.exe", - L"VSSVC.exe", - L"VBCSCompiler.exe", - L"vcpkgsrv.exe", - L"WindowsTerminal.exe", - L"WindowsPackageManagerServer.exe", - L"reSearch.exe" -}; -std::set c_vms = { - L"vmmem", - L"vmwp.exe", // actual process name for 'vmmem' - L"vmcompute.exe", - L"vmconnect.exe", - L"vmwp.exe", - L"vmms.exe" -}; -std::set c_background = { - L"services.exe", - L"svchost.exe", - L"SCNotification.exe", - L"SecurityHealthyService.exe", - L"DevHome.QuietBackgroundProcesses.Server.exe", - L"DevHome.QuietBackgroundProcesses.ElevatedServer.exe", - L"OneDrive.exe", - L"MsMpEng.exe", - L"MsSense.exe", - L"NdrSetup.exe", - L"NisSrv.exe", - L"RuntimeBroker.exe", - L"rundll32.exe", - L"SearchHost.exe", - L"SenseCE.exe", - L"SenseNdr.exe", - L"SenseNdrX.exe", - L"SenseTVM.exe", - L"SearchIndexer.exe", - L"taskhostw.exe", - L"winlogon.exe", -}; - -ProcessCategory GetCategory(DWORD pid, std::wstring_view processName) -{ - auto search = [&](std::wstring_view processName, const auto& list) - { - auto it = std::find_if(list.begin(), list.end(), [&](const auto& elem) - { - return wil::compare_string_ordinal(processName, elem, true) == 0; - }); - auto found = (it != list.end()); - return found; - }; - - if (pid == 4) - { - // PID 4 is the System process - return ProcessCategory::System; - } - if (search(processName.data(), c_user)) - { - return ProcessCategory::User; - } - if (search(processName.data(), c_system)) - { - return ProcessCategory::System; - } - if (search(processName.data(), c_developer)) - { - return ProcessCategory::Developer; - } - if (search(processName.data(), c_vms)) - { - return ProcessCategory::Developer; - } - if (search(processName.data(), c_background)) - { - return ProcessCategory::Background; - } - return ProcessCategory::Unknown; -} - -template -void copystr(wchar_t(&dst)[N], const std::optional& src) -{ - wcscpy_s(dst, N, src.value_or(L"").substr(0, N - 1).c_str()); -} - -template -wil::unique_cotaskmem_array_ptr make_unique_cotaskmem_array_ptr(size_t numOfElements) -{ - wil::unique_cotaskmem_array_ptr result; - T* ptr = reinterpret_cast(CoTaskMemAlloc(sizeof(T) * numOfElements)); - THROW_IF_NULL_ALLOC(ptr); - *result.addressof() = ptr; - *result.size_address() = numOfElements; - return result; -} - -std::chrono::file_clock::time_point FileTimeToTimePoint(const FILETIME& fileTime) -{ - ULARGE_INTEGER uli; - uli.LowPart = fileTime.dwLowDateTime; - uli.HighPart = fileTime.dwHighDateTime; - std::chrono::file_clock::duration d{ (static_cast(fileTime.dwHighDateTime) << 32) | fileTime.dwLowDateTime }; - std::chrono::file_clock::time_point tp{ d }; - return tp; -} - -std::string FiletimeToString(const FILETIME& ft) -{ - std::chrono::file_clock::duration d{ (static_cast(ft.dwHighDateTime) << 32) | ft.dwLowDateTime }; - std::chrono::file_clock::time_point tp{ d }; - return std::format("{:%Y-%m-%d %H:%M}\n", tp); -} - -std::chrono::microseconds CpuTimeDuration(FILETIME previous, FILETIME current) -{ - if (CompareFileTime(&previous, ¤t) >= 0) - { - return std::chrono::microseconds(0); - } - - auto filetimeDeltaIn100ns = FileTimeToTimePoint(current) - FileTimeToTimePoint(previous); - auto durationMicroseconds = std::chrono::duration_cast(filetimeDeltaIn100ns); - return durationMicroseconds; -} - -int GetVirtualNumCpus() -{ - SYSTEM_INFO sysInfo; - GetSystemInfo(&sysInfo); - return sysInfo.dwNumberOfProcessors; -} - -template -std::span GetPids(DWORD (&pidArray)[size]) -{ - DWORD needed; - THROW_IF_WIN32_BOOL_FALSE(EnumProcesses(pidArray, sizeof(pidArray), &needed)); - return { &pidArray[0], needed / sizeof(DWORD) }; -} - -std::optional TryGetPackageFullNameFromTokenHelper(HANDLE token) -{ - wchar_t packageFullName[PACKAGE_FULL_NAME_MAX_LENGTH + 1]{}; - uint32_t packageFullNameLength = ARRAYSIZE(packageFullName); - if (GetPackageFullNameFromToken(token, &packageFullNameLength, packageFullName)) - { - return std::nullopt; - } - return std::wstring { packageFullName }; -} - -std::optional TryGetAppUserModelIdFromTokenHelper(HANDLE token) -{ - wchar_t aumid[APPLICATION_USER_MODEL_ID_MAX_LENGTH]{}; - uint32_t aumidLength = ARRAYSIZE(aumid); - if (GetApplicationUserModelIdFromToken(token, &aumidLength, aumid) != ERROR_SUCCESS) - { - return std::nullopt; - } - return std::wstring { aumid }; -} - -std::optional TryGetProcessName(HANDLE processHandle) -{ - static wchar_t s_buffer[MAX_PATH * 2]; - if (GetModuleFileNameExW(processHandle, nullptr, s_buffer, _countof(s_buffer)) > 0) - { - return s_buffer; - } - return std::nullopt; -} - -ProcessPerformanceInfo MakeProcessPerformanceInfo(DWORD processId) -{ - auto process = wil::unique_process_handle{ OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, processId) }; - if (!process) - { - // We can't open csrss.exe, so we'll just skip processes we can't open - auto info = ProcessPerformanceInfo{}; - info.process = nullptr; - info.pid = processId; - LOG_LAST_ERROR_MSG("Failed to open process handle for PID: %d", processId); - } - - auto processPathString = TryGetProcessName(process.get()); - - auto path = std::filesystem::path(processPathString.value_or(L"")); - - FILETIME createTime{}; - FILETIME exitTime{}; - FILETIME kernelTime{}; - FILETIME userTime{}; - if (process) - { - THROW_IF_WIN32_BOOL_FALSE(GetProcessTimes(process.get(), &createTime, &exitTime, &kernelTime, &userTime)); - } - - std::optional packageFullName; - std::optional aumid; - wil::unique_handle processToken; - if (process) - { - if (OpenProcessToken(process.get(), TOKEN_QUERY, &processToken)) - { - packageFullName = TryGetPackageFullNameFromTokenHelper(processToken.get()); - aumid = TryGetAppUserModelIdFromTokenHelper(processToken.get()); - } - else - { - PCWSTR processPath = processPathString ? processPathString.value().c_str() : L""; - LOG_LAST_ERROR_MSG("Failed to open process token for PID: %d (%ls)", processId, processPath); - } - } - - auto info = ProcessPerformanceInfo{}; - info.process = std::move(process); - info.pid = processId; - info.name = path.filename().wstring(); - info.path = path.parent_path().wstring(); - info.packageFullName = packageFullName; - info.aumid = aumid; - info.category = GetCategory(info.pid, info.name); - info.createTime = createTime; - - // Start times - info.startUserTime = userTime; - info.startKernelTime = kernelTime; - - info.previousUserTime = userTime; - info.currentUserTime = userTime; - info.previousKernelTime = kernelTime; - info.currentKernelTime = kernelTime; - - return info; -} - -bool UpdateProcessPerformanceInfo(ProcessPerformanceInfo& info) -{ - FILETIME createTime, exitTime, kernelTime, userTime; - THROW_IF_WIN32_BOOL_FALSE(GetProcessTimes(info.process.get(), &createTime, &exitTime, &kernelTime, &userTime)); - - if (exitTime.dwHighDateTime != 0 || exitTime.dwLowDateTime != 0) - { - info.exitTime = exitTime; - return false; - } - - info.previousUserTime = info.currentUserTime; - info.currentUserTime = userTime; - info.previousKernelTime = info.currentKernelTime; - info.currentKernelTime = kernelTime; - return true; -} - -struct cancellation_mechanism -{ - std::atomic m_cancelled{}; - std::mutex m_mutex; - std::condition_variable m_cancelCondition; - - void cancel() - { - auto lock = std::scoped_lock(m_mutex); - m_cancelled = true; - m_cancelCondition.notify_all(); - } - - bool wait_for_cancel(std::chrono::milliseconds duration) - { - auto lock = std::unique_lock(m_mutex); - auto cancelHappened = m_cancelCondition.wait_for(lock, duration, [this] { - return m_cancelled.load(); - }); - return cancelHappened; - } -}; - -struct MonitorThread -{ - cancellation_mechanism m_cancellationMechanism; - std::thread m_thread; - std::mutex m_dataMutex; - - // Tracking all our process infos - std::map m_runningProcesses; - std::vector m_terminatedProcesses; - - // Info - std::chrono::milliseconds m_samplingPeriod; - - MonitorThread(std::chrono::milliseconds periodMs) - { - m_samplingPeriod = periodMs; - - if (periodMs.count() <= 0) - { - THROW_HR(E_INVALIDARG); - } - - m_thread = std::thread([this, periodMs]() { - try - { - auto numCpus = GetVirtualNumCpus(); - - auto serviceInformation = ServiceInformation::RunningServiceInformation(); - - while (true) - { - if (m_cancellationMechanism.m_cancelled) - { - break; - } - - // Check for new processes to track - DWORD pidArray[2048]; - auto pids = GetPids(pidArray); - - auto lock = std::scoped_lock(m_dataMutex); - for (auto& pid : pids) - { - // Ignore process "0" - the 'SYSTEM 'System' process - if (pid == 0) - { - continue; - } - - // Make a new entry - if (!m_runningProcesses.contains(pid)) - { - try - { - // Create new process info object - auto processInfo = MakeProcessPerformanceInfo(pid); - - // Add the service name if it's an svchost.exe process - processInfo.serviceName = serviceInformation.TryGetServiceName(processInfo.pid, processInfo.name); - - // Add process to running processes map - m_runningProcesses[pid] = std::move(processInfo); - } - CATCH_LOG(); - } - } - - // Update counts for each tracked process - for (auto it = m_runningProcesses.begin(); it != m_runningProcesses.end(); ) - { - auto pid = it->first; - - // Get entry - auto& info = it->second; - - if (!info.process) - { - // The process couldn't be opened, so we'll skip this entry - ++it; - continue; - } - - // Update entry - try - { - if (!UpdateProcessPerformanceInfo(info)) - { - // The process terminated - - // Destroy the process handle - info.process.reset(); - - // Move from the map to the terminated list - m_terminatedProcesses.push_back(std::move(info)); - it = m_runningProcesses.erase(it); - - // Remove from running services names - serviceInformation.ForgetService(pid); - continue; - } - } - catch (...) - { - ++it; - continue; - } - - // Collect cpuTime for process - auto cpuTime = CpuTimeDuration(info.previousUserTime, info.currentUserTime); - cpuTime += CpuTimeDuration(info.previousKernelTime, info.currentKernelTime); - - double percent = (double)cpuTime.count() / std::chrono::duration_cast(periodMs).count() / (double)numCpus * 100.0f; - double variance = (double)std::pow(percent, 2.0f); - double sigma4 = (double)std::pow(percent, 4.0f); - - info.sampleCount++; - info.percentCumulative += percent; - info.varianceCumulative += variance; - info.sigma4Cumulative += sigma4; - if (percent > info.maxPercent) - { - info.maxPercent = percent; - } - if (percent > CPU_TIME_ABOVE_THRESHOLD_STRIKE_VALUE) - { - info.samplesAboveThreshold++; - } - - ++it; - } - - // Wait for interval period or user cancellation - if (m_cancellationMechanism.wait_for_cancel(periodMs)) - { - // User cancelled - break; - } - } - } - CATCH_LOG(); - }); - } - - void Cancel() - { - m_cancellationMechanism.cancel(); - if (m_thread.joinable()) - { - m_thread.join(); - } - } - - std::chrono::milliseconds GetSamplingPeriod() - { - return m_samplingPeriod; - } - - std::vector GetProcessPerformanceSummaries() - { - auto lock = std::scoped_lock(m_dataMutex); - - std::vector summaries; - auto MakeSummary = [](const ProcessPerformanceInfo& info) - { - auto summary = ProcessPerformanceSummary{}; - auto totalUserTime = CpuTimeDuration(info.startUserTime, info.currentUserTime); - auto totalKernelTime = CpuTimeDuration(info.startKernelTime, info.currentKernelTime); - - // Process info - summary.pid = info.pid; - if (summary.pid == 4) - { - copystr(summary.name, L"[System]"); - } - else if (info.name.empty()) - { - copystr(summary.name, L"[unk]"); - } - else - { - copystr(summary.name, info.name); - } - copystr(summary.serviceName, info.serviceName); - copystr(summary.packageFullName, info.packageFullName); - copystr(summary.aumid, info.aumid); - copystr(summary.path, info.path); - summary.category = static_cast(info.category); - summary.createTime = info.createTime; - summary.exitTime = info.exitTime; - - // Sampling - summary.sampleCount = info.sampleCount; - summary.percentCumulative = info.percentCumulative; - summary.varianceCumulative = info.varianceCumulative; - summary.sigma4Cumulative = info.sigma4Cumulative; - summary.maxPercent = info.maxPercent; - summary.samplesAboveThreshold = info.samplesAboveThreshold; - - // Other - summary.totalCpuTimeInMicroseconds = totalUserTime.count() + totalKernelTime.count(); - - if (summary.sampleCount <= 0) - { - summary.sampleCount = 0; - } - return summary; - }; - - // Add summaries for running processes - for (auto const& [key, info] : m_runningProcesses) - { - summaries.push_back(MakeSummary(info)); - } - - // Add summaries for terminated processes - for (auto const& info : m_terminatedProcesses) - { - summaries.push_back(MakeSummary(info)); - } - return summaries; - } -}; - -// -// Exports -// - -extern "C" __declspec(dllexport) HRESULT StartMonitoringProcessUtilization(uint32_t periodInMs, void** context) noexcept -try -{ - auto periodMs = std::chrono::milliseconds(periodInMs); - auto monitorThread = std::make_unique(periodMs); - *context = static_cast(monitorThread.release()); - return S_OK; -} -CATCH_RETURN() - -extern "C" __declspec(dllexport) HRESULT StopMonitoringProcessUtilization(void* context) noexcept -try -{ - auto monitorThread = reinterpret_cast(context); - monitorThread->Cancel(); - return S_OK; -} -CATCH_RETURN() - -extern "C" __declspec(dllexport) HRESULT DeleteMonitoringProcessUtilization(void* context) noexcept -try -{ - if (!context) - { - return S_OK; - } - auto monitorThread = std::unique_ptr(reinterpret_cast(context)); - monitorThread->Cancel(); - monitorThread.reset(); - return S_OK; -} -CATCH_RETURN() - -extern "C" __declspec(dllexport) HRESULT GetMonitoringProcessUtilization(void* context, std::chrono::milliseconds* samplingPeriodInMs, ProcessPerformanceSummary** ppSummaries, size_t* summaryCount) noexcept -try -{ - auto monitorThread = reinterpret_cast(context); - auto summaries = monitorThread->GetProcessPerformanceSummaries(); - - if (samplingPeriodInMs) - { - *samplingPeriodInMs = monitorThread->GetSamplingPeriod(); - } - - // Alloc summaries block - auto ptrSummaries = make_unique_cotaskmem_array_ptr(summaries.size()); - auto i = 0; - for (auto const& summary : summaries) - { - auto& dst = ptrSummaries.get()[i++]; - dst = summary; - } - - *summaryCount = ptrSummaries.size(); - *ppSummaries = ptrSummaries.release(); - - return S_OK; -} -CATCH_RETURN() diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/PerformanceRecorderEngine.h b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/PerformanceRecorderEngine.h deleted file mode 100644 index 671c97344..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/PerformanceRecorderEngine.h +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#pragma once - -#include -#include - -struct ProcessPerformanceSummary -{ - // Process info - ULONG pid{}; - wchar_t name[64]{}; - wchar_t serviceName[64]{}; - wchar_t packageFullName[PACKAGE_FULL_NAME_MAX_LENGTH + 1]{}; - wchar_t aumid[APPLICATION_USER_MODEL_ID_MAX_LENGTH]{}; - wchar_t path[MAX_PATH * 2]{}; - uint32_t category{}; - FILETIME createTime{}; - FILETIME exitTime{}; - - // Sampling - uint64_t sampleCount{}; - double percentCumulative{}; - double varianceCumulative{}; - double sigma4Cumulative{}; - double maxPercent{}; - uint32_t samplesAboveThreshold{}; - - // Other - uint64_t totalCpuTimeInMicroseconds{}; -}; - -extern "C" __declspec(dllexport) HRESULT StartMonitoringProcessUtilization(uint32_t periodInMs, void** context) noexcept; -extern "C" __declspec(dllexport) HRESULT StopMonitoringProcessUtilization(void* context) noexcept; -extern "C" __declspec(dllexport) HRESULT GetMonitoringProcessUtilization(void* context, std::chrono::milliseconds* samplingPeriodInMs, ProcessPerformanceSummary** ppSummaries, size_t* summaryCount) noexcept; -extern "C" __declspec(dllexport) HRESULT DeleteMonitoringProcessUtilization(void* context) noexcept; - -using unique_process_utilization_monitoring_thread = wil::unique_any; diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/ServiceInformation.h b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/ServiceInformation.h deleted file mode 100644 index 4d7c379e5..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/ServiceInformation.h +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#pragma once - -#include -#include - -#include -#include -#include - -namespace ServiceInformation -{ - inline bool IsSvchost(std::wstring_view name) - { - return wil::compare_string_ordinal(name, L"svchost.exe", true) == 0; - } - - inline std::map GetRunningServiceNames() - { - SC_HANDLE m_hScmManager = OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE); - THROW_LAST_ERROR_IF(m_hScmManager == NULL); - - std::unique_ptr services{}; - ULONG servicesCount = 0; - ULONG servicesSize = 0; - - while (true) - { - // Get services - ULONG resumeIndex = 0; - if (EnumServicesStatusEx(m_hScmManager, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_STATE_ALL, (LPBYTE)services.get(), servicesSize, &servicesSize, &servicesCount, &resumeIndex, NULL)) - { - break; - } - - THROW_LAST_ERROR_IF(GetLastError() != ERROR_MORE_DATA); - - // Increase the buffer size and try again. - servicesSize *= 2; - services.reset(reinterpret_cast(new BYTE[servicesSize])); - THROW_IF_NULL_ALLOC(services); - ZeroMemory(services.get(), servicesSize); - } - - auto map = std::map(); - for (ULONG index = 0; index < servicesCount; index++) - { - map.emplace(services.get()[index].ServiceStatusProcess.dwProcessId, services.get()[index].lpServiceName); - } - return map; - } - - class RunningServiceInformation - { - public: - std::optional TryGetServiceName(DWORD pid, std::wstring_view name) noexcept try - { - // Check if we have the service name cached - auto it = m_runningServiceNames.find(pid); - if (it != m_runningServiceNames.end()) - { - return it->second; - } - - // If the process is svchost.. - if (IsSvchost(name)) - { - // Update cache.. - m_runningServiceNames = GetRunningServiceNames(); - - // ..and try again - auto it = m_runningServiceNames.find(pid); - if (it != m_runningServiceNames.end()) - { - return it->second; - } - } - - return std::nullopt; - } - catch (...) - { - return std::nullopt; - } - - void ForgetService(DWORD pid) - { - m_runningServiceNames.erase(pid); - } - - private: - std::map m_runningServiceNames; - }; -} diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/dllmain.cpp b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/dllmain.cpp deleted file mode 100644 index b503a9ba4..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/dllmain.cpp +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#include "pch.h" - -BOOL APIENTRY DllMain(HMODULE /* hModule */, DWORD ul_reason_for_call, LPVOID /* lpReserved */) -{ - switch (ul_reason_for_call) - { - case DLL_PROCESS_ATTACH: - case DLL_THREAD_ATTACH: - case DLL_THREAD_DETACH: - case DLL_PROCESS_DETACH: - break; - } - return TRUE; -} diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/packages.config b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/packages.config deleted file mode 100644 index 09be25d9e..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/pch.cpp b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/pch.cpp deleted file mode 100644 index 40e691ba7..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/pch.cpp +++ /dev/null @@ -1,4 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#include "pch.h" diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/pch.h b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/pch.h deleted file mode 100644 index f4b4e6937..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.PerformanceRecorderEngine/pch.h +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#pragma once - -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif - -#include diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/DevHome.QuietBackgroundProcesses.Server.vcxproj b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/DevHome.QuietBackgroundProcesses.Server.vcxproj deleted file mode 100644 index fdd8d25fa..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/DevHome.QuietBackgroundProcesses.Server.vcxproj +++ /dev/null @@ -1,253 +0,0 @@ - - - - C++ - - - - - - true - true - true - true - {80805B43-CE75-4C6E-92F8-F385C1039E53} - DevHome.QuietBackgroundProcesses.Server - DevHome.QuietBackgroundProcesses - en-US - 14.0 - true - Windows Store - 10.0 - 10.0.22621.0 - 10.0.17134.0 - false - $(CppOutDir) - - - - - Debug_FailFast - ARM - - - Debug_FailFast - ARM64 - - - Debug_FailFast - Win32 - - - Debug_FailFast - x64 - - - Debug - ARM - - - Debug - ARM64 - - - Debug - Win32 - - - Debug - x64 - - - Release - ARM - - - Release - ARM64 - - - Release - Win32 - - - Release - x64 - - - - Application - v143 - v142 - v141 - v140 - Unicode - false - - - true - true - - - true - true - - - false - true - false - - - true - Spectre - - - Spectre - - - Spectre - - - Spectre - - - Spectre - - - Spectre - - - Spectre - - - Spectre - - - Spectre - - - Spectre - - - Spectre - - - Spectre - - - - - - - - - - - - - - - - - Use - pch.h - $(IntDir)pch.pch - Level4 - %(AdditionalOptions) /bigobj - _WINRT_DLL;WIN32_LEAN_AND_MEAN;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) - $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) - - - Windows - false - - - - - - - stdcpp17 - C++ - $(ProjectDir)..\DevHome.QuietBackgroundProcesses.Common\;$(ProjectDir)..\DevHome.QuietBackgroundProcesses.Common\$(GeneratedFilesDir)midl;%(AdditionalIncludeDirectories) - - - onecore.lib;%(AdditionalDependencies) - - - %(Filename).h - $(ProjectDir)$(GeneratedFilesDir)midl - $(ProjectDir)$(GeneratedFilesDir)winmd\%(Filename).winmd - - - - - _DEBUG;%(PreprocessorDefinitions) - Disabled - Guard - Guard - Guard - Guard - ProgramDatabase - ProgramDatabase - ProgramDatabase - - - - - _DEBUG;%(PreprocessorDefinitions) - Disabled - Guard - Guard - Guard - Guard - ProgramDatabase - ProgramDatabase - ProgramDatabase - - - - - NDEBUG;%(PreprocessorDefinitions) - Guard - Guard - Guard - Guard - - - true - true - - - - - - - - - Create - - - - - - - - - - - - {4b370e2f-fb1d-4887-90bf-3b72517485ce} - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - \ No newline at end of file diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/PropertySheet.props b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/PropertySheet.props deleted file mode 100644 index e34141b01..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/PropertySheet.props +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/QuietBackgroundProcessesSessionManager.cpp b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/QuietBackgroundProcessesSessionManager.cpp deleted file mode 100644 index 3d74ecd23..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/QuietBackgroundProcessesSessionManager.cpp +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#include - -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include - -#include "DevHome.QuietBackgroundProcesses.h" - -namespace ABI::DevHome::QuietBackgroundProcesses -{ - class QuietBackgroundProcessesSessionManager : - public Microsoft::WRL::RuntimeClass< - Microsoft::WRL::RuntimeClassFlags, - IQuietBackgroundProcessesSessionManager, - Microsoft::WRL::FtmBase> - { - InspectableClass(RuntimeClass_DevHome_QuietBackgroundProcesses_QuietBackgroundProcessesSessionManager, BaseTrust); - - public: - STDMETHODIMP RuntimeClassInitialize() noexcept - { - return S_OK; - } - }; - - class QuietBackgroundProcessesSessionManagerStatics WrlFinal : - public Microsoft::WRL::AgileActivationFactory< - Microsoft::WRL::Implements> - { - InspectableClassStatic(RuntimeClass_DevHome_QuietBackgroundProcesses_QuietBackgroundProcessesSessionManager, BaseTrust); - - public: - // IActivationFactory method - STDMETHODIMP ActivateInstance(_Outptr_result_nullonfailure_ IInspectable** ppvObject) noexcept - try - { - THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize(ppvObject)); - return S_OK; - } - CATCH_RETURN() - - // IQuietBackgroundProcessesSessionManagerStatics - STDMETHODIMP IsFeaturePresent(_Out_ boolean* isPresent) noexcept override try - { - THROW_IF_FAILED(IsQuietBackgroundProcessesFeaturePresent((bool*)isPresent)); - return S_OK; - } - CATCH_RETURN(); - - STDMETHODIMP GetSession(_Outptr_result_nullonfailure_ IQuietBackgroundProcessesSession** session) noexcept override - try - { - auto lock = std::scoped_lock(m_mutex); - *session = nullptr; - - if (!m_sessionReference) - { - auto factory = wil::GetActivationFactory(RuntimeClass_DevHome_QuietBackgroundProcesses_QuietBackgroundProcessesSession); - THROW_IF_FAILED(factory->GetSingleton(&m_sessionReference)); - } - m_sessionReference.copy_to(session); - return S_OK; - } - CATCH_RETURN() - - STDMETHODIMP TryGetSession(_COM_Outptr_result_maybenull_ IQuietBackgroundProcessesSession** session) noexcept override try - { - auto lock = std::scoped_lock(m_mutex); - m_sessionReference.try_copy_to(session); - return S_OK; - } - CATCH_RETURN() - - STDMETHODIMP TryGetLastPerformanceRecording(_COM_Outptr_ ABI::DevHome::QuietBackgroundProcesses::IProcessPerformanceTable** result) noexcept override - try - { - auto factory = wil::GetActivationFactory(RuntimeClass_DevHome_QuietBackgroundProcesses_PerformanceRecorderEngine); - THROW_IF_FAILED(factory->TryGetLastPerformanceRecording(result)); - - return S_OK; - } - CATCH_RETURN() - - STDMETHODIMP HasLastPerformanceRecording(boolean* result) noexcept override - try - { - *result = std::filesystem::exists(GetTemporaryPerformanceDataPath()); - return S_OK; - } - CATCH_RETURN() - - private: - std::mutex m_mutex; - wil::com_ptr m_sessionReference; - }; - - ActivatableClassWithFactory(QuietBackgroundProcessesSessionManager, QuietBackgroundProcessesSessionManagerStatics); -} diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/main.cpp b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/main.cpp deleted file mode 100644 index 54ae2b766..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/main.cpp +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "Utility.h" - -int __stdcall wWinMain(HINSTANCE, HINSTANCE, LPWSTR wargv, int wargc) try -{ - WaitForDebuggerIfPresent(); - - if (wargc < 1) - { - THROW_HR(E_INVALIDARG); - } - - // Parse the servername from the cmdline argument, e.g. "-ServerName:DevHome.QuietBackgroundProcesses.Server" - auto serverName = ParseServerNameArgument(wargv); - - if (wil::compare_string_ordinal(serverName, L"DevHome.QuietBackgroundProcesses.Server", true) != 0) - { - THROW_HR(E_INVALIDARG); - } - - auto unique_rouninitialize_call = wil::RoInitialize(); - - // Enable fast rundown of COM stubs in this process to ensure that RPCSS bookkeeping is updated synchronously. - SetComFastRundownAndNoEhHandle(); - - std::mutex mutex; - bool comFinished{}; - std::condition_variable finishCondition; - -#pragma warning(push) -#pragma warning(disable: 4324) // Avoid WRL alignment warning - - // Register WRL callback when all objects are destroyed - auto& module = Microsoft::WRL::Module::Create([&] { - // The last instance object of the module is released - { - auto lock = std::unique_lock(mutex); - comFinished = true; - } - finishCondition.notify_one(); - }); - -#pragma warning(pop) - - // Register WinRT activatable classes - module.RegisterObjects(); - auto unique_wrl_registration_cookie = wil::scope_exit([&module]() { - module.UnregisterObjects(); - }); - - // Wait for all server references to release - auto lock = std::unique_lock(mutex); - - finishCondition.wait(lock, [&] { - return comFinished; - }); - - return 0; -} -CATCH_RETURN() diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/packages.config b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/packages.config deleted file mode 100644 index 47df16ce8..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/packages.config +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/pch.cpp b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/pch.cpp deleted file mode 100644 index 40e691ba7..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/pch.cpp +++ /dev/null @@ -1,4 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#include "pch.h" diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/pch.h b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/pch.h deleted file mode 100644 index 9d6cb8929..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.Server/pch.h +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -#pragma once - -#define NOMINMAX - -#include -#include -#include diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/DevHome.QuietBackgroundProcesses.UI.csproj b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/DevHome.QuietBackgroundProcesses.UI.csproj deleted file mode 100644 index 74f170c19..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/DevHome.QuietBackgroundProcesses.UI.csproj +++ /dev/null @@ -1,28 +0,0 @@ - - - - - DevHome.QuietBackgroundProcesses.UI - x86;x64;arm64 - win-x86;win-x64;win-arm64 - true - enable - - - - - - - - - - MSBuild:Compile - - - - - - $(DefaultXamlRuntime) - - - \ No newline at end of file diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/ProcessData.cs b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/ProcessData.cs deleted file mode 100644 index 01e898712..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/ProcessData.cs +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; - -namespace DevHome.QuietBackgroundProcesses.UI; - -public class ProcessData -{ - public enum ProcessCategory - { - Unknown, - User, - System, - Developer, - Background, - } - - public ProcessData() - { - Name = string.Empty; - ServiceName = string.Empty; - DisplayName = string.Empty; - PackageFullName = string.Empty; - Aumid = string.Empty; - Path = string.Empty; - } - - public long Pid { get; set; } - - public string Name { get; set; } - - public string ServiceName { get; set; } - - public string DisplayName { get; set; } - - public string PackageFullName { get; set; } - - public string Aumid { get; set; } - - public string Path { get; set; } - - public ProcessCategory Category { get; set; } - - public DateTimeOffset CreateTime { get; set; } - - public DateTimeOffset ExitTime { get; set; } - - public ulong Samples { get; set; } - - public double Percent { get; set; } - - public double StandardDeviation { get; set; } - - public double Sigma4Deviation { get; set; } - - public double MaxPercent { get; set; } - - public TimeSpan TimeAboveThreshold { get; set; } - - public double TimeAboveThresholdInMinutes { get; set; } - - public ulong TotalCpuTimeInMicroseconds { get; set; } -} diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/QuietBackgroundProcessesEvent.cs b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/QuietBackgroundProcessesEvent.cs deleted file mode 100644 index 6a2507b76..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/QuietBackgroundProcessesEvent.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Diagnostics.Tracing; -using DevHome.Telemetry; -using Microsoft.Diagnostics.Telemetry; -using Microsoft.Diagnostics.Telemetry.Internal; -using Windows.Foundation.Diagnostics; - -namespace DevHome.QuietBackgroundProcesses.UI; - -[EventData] -public class QuietBackgroundProcessesEvent : EventBase -{ - public override PartA_PrivTags PartA_PrivTags => PrivTags.ProductAndServiceUsage; - - public LoggingOpcode Opcode { get; } - - public QuietBackgroundProcessesEvent(LoggingOpcode opcode = LoggingOpcode.Info) - { - Opcode = opcode; - } - - public override void ReplaceSensitiveStrings(Func replaceSensitiveStrings) - { - } -} diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Strings/en-us/Resources.resw b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Strings/en-us/Resources.resw deleted file mode 100644 index 2532574fb..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Strings/en-us/Resources.resw +++ /dev/null @@ -1,195 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Quiet background processes - The name of the Quiet background processes page - - - Start session - Button that starts a quiet background session - - - End session - Button that stops a quiet background session - - - Last session length: - Length of the previously run quiet session - - - Enhance resource management while developing for a maximum of 2 hours - Description of the Quiet background processes feature - - - Quiet background processes - Inline title of the Quiet background processes feature - - - An analytic summary will be available after a session has completed. The summary will include an overview of process resource consumption. The analytic summary is not available while feature is active. - A description of the Quiet background processes time window - - - Link to docs - Link that launches documentation - - - Provide feedback - Link that launches feedback - - - Related links - Label for the doc links - - - Analytic summary - Button to open the analytic summary dialog - - - - - Analysis of process CPU utilization while the session was in use. Calculated amount of time that the process used CPU above the designated threshold. - Desciption of the analytic summary page - - - Sort by - Label for the combo box for sorting - - - Sort-by combo box - Accessible name for the "Sort by" dropdown combo box in the analytic summary - - - Process - Sortby dropdown option - - - Type - Sortby dropdown option - - - CPU above threshold - Sortby dropdown option - - - Search for a process - Label for analytic summary save report button - - - Analytic Summary - Title of the analytic summary page - - - Save report - Label for analytic summary save report button - - - Close - Label for analytic summary close button - - - - - Process - Table heading for Process column - - - Type - Table heading for Type column - - - CPU above threshold - Table heading for 'CPU time above threshold' column - - - The time that a process spent using the CPU at greater than 2% utilization. - Sortby dropdown option - - - min - Abbreviation for the word minutes - - - - - Feature not supported on this version of Windows - Indicates that this OS isn't new enough to support the feature - - - There was an error that prevented the session from starting - Something went wrong when running the session - - - There was an error when retrieving the active quiet session - Something went wrong when asking the server if a quiet session is ongoing - - - There was an error when getting the time remaning in the session - Something went wrong when asking the server for time remaining - - - Unable to cancel session - Something went wrong when cancelling the session - - - There was an error retrieving the analytic summary - Something went wrong getting the analytic summary - - \ No newline at end of file diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/ViewModels/AnalyticSummaryPopupViewModel.cs b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/ViewModels/AnalyticSummaryPopupViewModel.cs deleted file mode 100644 index b183ada4c..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/ViewModels/AnalyticSummaryPopupViewModel.cs +++ /dev/null @@ -1,210 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.Input; -using CommunityToolkit.WinUI.Collections; -using DevHome.Telemetry; -using Serilog; - -namespace DevHome.QuietBackgroundProcesses.UI.ViewModels; - -public partial class AnalyticSummaryPopupViewModel : ObservableObject -{ - // Enum for process category - public enum ProcessTableColumn - { - Process, - Type, - CPUAboveThreshold, - } - - private readonly ILogger _log = Log.ForContext("SourceContext", nameof(AnalyticSummaryPopupViewModel)); - private readonly List _processDatas = new(); - - public int SortComboBoxIndex { get; set; } - - public AdvancedCollectionView ProcessDatasAd { get; private set; } - - private ProcessData.ProcessCategory ConvertProcessType(DevHome.QuietBackgroundProcesses.ProcessCategory inputType) - { - return (ProcessData.ProcessCategory)inputType; - } - - public AnalyticSummaryPopupViewModel(QuietBackgroundProcesses.ProcessPerformanceTable? performanceTable) - { - TelemetryFactory.Get().Log("QuietBackgroundProcesses_AnalyticSummary_Open", LogLevel.Info, new QuietBackgroundProcessesEvent()); - - try - { - if (performanceTable != null) - { - var rows = performanceTable.Rows; - foreach (var row in rows) - { - if (row != null) - { - var sampleCount = row.SampleCount; - var sampleDuration = 1; - - var displayName = row.Name; - if (!string.IsNullOrEmpty(row.ServiceName)) - { - displayName += " (" + row.ServiceName + ")"; - } - - var entry = new ProcessData - { - Pid = row.Pid, - Name = row.Name, - ServiceName = row.ServiceName, - DisplayName = displayName, - PackageFullName = row.PackageFullName, - Aumid = row.Aumid, - Path = row.Path, - Category = ConvertProcessType(row.Category), - CreateTime = row.CreateTime, - ExitTime = row.ExitTime, - Samples = row.SampleCount, - Percent = row.PercentCumulative / sampleCount, - StandardDeviation = (float)Math.Sqrt(row.VarianceCumulative / sampleCount), - Sigma4Deviation = (float)Math.Sqrt(Math.Sqrt(row.Sigma4Cumulative / sampleCount)), - MaxPercent = row.MaxPercent, - TimeAboveThreshold = TimeSpan.FromSeconds(row.SamplesAboveThreshold * sampleDuration), - TotalCpuTimeInMicroseconds = row.TotalCpuTimeInMicroseconds, - }; - - entry.TimeAboveThresholdInMinutes = entry.TimeAboveThreshold.TotalMinutes; - _processDatas.Add(entry); - } - } - } - } - catch (Exception ex) - { - _log.Error("Error populating performance summary table", ex); - } - - ProcessDatasAd = new AdvancedCollectionView(_processDatas, true); - ProcessDatasAd.SortDescriptions.Add(new SortDescription("Pid", SortDirection.Descending)); - } - - private ProcessTableColumn GetProcessTableColumnFromString(string value) - { - if (string.Equals(value, "Process", StringComparison.Ordinal)) - { - return ProcessTableColumn.Process; - } - else if (string.Equals(value, "Type", StringComparison.Ordinal)) - { - return ProcessTableColumn.Type; - } - else if (string.Equals(value, "CPUAboveThreshold", StringComparison.Ordinal)) - { - return ProcessTableColumn.CPUAboveThreshold; - } - - throw new ArgumentException("Invalid value for ProcessTableColumn"); - } - - [RelayCommand] - public void FilterProcessesTextInputChanged(string filterExpression) - { - ProcessDatasAd.Filter = item => - { - try - { - if (item is DevHome.QuietBackgroundProcesses.UI.ProcessData process) - { - return - process.Name.Contains(filterExpression, StringComparison.OrdinalIgnoreCase) - || process.Category.ToString().Contains(filterExpression, StringComparison.OrdinalIgnoreCase) - || process.TimeAboveThreshold.Minutes.ToString(CultureInfo.InvariantCulture).Contains(filterExpression, StringComparison.OrdinalIgnoreCase); - } - - return false; - } - catch (Exception ex) - { - _log.Error("Filtering failed", ex); - } - - return true; - }; - - ProcessDatasAd.RefreshFilter(); - } - - [RelayCommand] - public void SortProcessesComboBoxChanged(string selectedValueString) - { - ProcessDatasAd.SortDescriptions.Clear(); - - var selectedValue = GetProcessTableColumnFromString(selectedValueString); - switch (selectedValue) - { - case ProcessTableColumn.Process: - ProcessDatasAd.SortDescriptions.Add(new SortDescription("Name", SortDirection.Ascending)); - break; - case ProcessTableColumn.Type: - ProcessDatasAd.SortDescriptions.Add(new SortDescription("Category", SortDirection.Descending)); - break; - case ProcessTableColumn.CPUAboveThreshold: - ProcessDatasAd.SortDescriptions.Add(new SortDescription("TimeAboveThreshold", SortDirection.Descending)); - break; - } - } - - public void SaveReport(string filePath) - { - TelemetryFactory.Get().Log("QuietBackgroundProcesses_AnalyticSummary_Save", LogLevel.Info, new QuietBackgroundProcessesEvent()); - - // Save the report to a .csv - using (StreamWriter writer = new StreamWriter(filePath)) - { - // Write the .csv header - writer.WriteLine("Pid," + - "Name," + - "Samples," + - "Percent," + - "StandardDeviation," + - "Sigma4Deviation," + - "MaxPercent," + - "TimeAboveThreshold," + - "TotalCpuTimeInMicroseconds," + - "ServiceName," + - "PackageFullName," + - "Aumid," + - "Path," + - "Category," + - "CreateTime," + - "ExitTime"); - - // Write each item from the list to the file - foreach (var data in this._processDatas) - { - var row = $"{data.Pid}," + - $"{data.Name}," + - $"{data.Samples}," + - $"{data.Percent}," + - $"{data.StandardDeviation}," + - $"{data.Sigma4Deviation}," + - $"{data.MaxPercent}," + - $"{data.TimeAboveThreshold}," + - $"{data.TotalCpuTimeInMicroseconds}," + - $"{data.ServiceName}," + - $"{data.PackageFullName}," + - $"{data.Aumid}," + - $"{data.Path}," + - $"{data.Category}," + - $"{data.CreateTime}," + - $"{data.ExitTime}"; - writer.WriteLine(row); - } - } - } -} diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/ViewModels/QuietBackgroundProcessesViewModel.cs b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/ViewModels/QuietBackgroundProcessesViewModel.cs deleted file mode 100644 index d570ee5cd..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/ViewModels/QuietBackgroundProcessesViewModel.cs +++ /dev/null @@ -1,342 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; -using System.Globalization; -using System.Threading.Tasks; -using CommunityToolkit.Mvvm.ComponentModel; -using CommunityToolkit.Mvvm.Input; -using CommunityToolkit.WinUI; -using DevHome.Common.Services; -using DevHome.Telemetry; -using Microsoft.UI.Dispatching; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Media; -using Serilog; -using Windows.Foundation.Diagnostics; - -namespace DevHome.QuietBackgroundProcesses.UI.ViewModels; - -public partial class QuietBackgroundProcessesViewModel : ObservableObject -{ - private readonly ILogger _log = Log.ForContext("SourceContext", nameof(QuietBackgroundProcessesViewModel)); - - private readonly IExperimentationService _experimentationService; - - private readonly TimeSpan _zero = new(0, 0, 0); - private readonly TimeSpan _oneSecond = new(0, 0, 1); - private readonly DispatcherQueue _dispatcherQueue; - private TimeSpan _sessionDuration; - private QuietBackgroundProcessesSession? _session; - private ProcessPerformanceTable? _table; - - [ObservableProperty] - private bool _isFeaturePresent; - - [ObservableProperty] - private bool _isAnalyticSummaryAvailable; - - [ObservableProperty] - private string _countdownTimer; - - [ObservableProperty] - private string _sessionStateText; - - [ObservableProperty] - private SolidColorBrush _sessionStateTextColor; - - [ObservableProperty] - private bool _quietButtonEnabled; - - [ObservableProperty] - private bool _quietButtonChecked; - - [ObservableProperty] - private string? _quietButtonText; - - private QuietBackgroundProcessesSession GetSession() - { - if (_session == null) - { - _session = QuietBackgroundProcessesSessionManager.GetSession(); - } - - return _session; - } - - private string GetString(string id) - { - var stringResource = new StringResource("DevHome.QuietBackgroundProcesses.UI.pri", "DevHome.QuietBackgroundProcesses.UI/Resources"); - return stringResource.GetLocalized(id); - } - - private string GetStatusString(string id) - { - return GetString("QuietBackgroundProcesses_Status_" + id); - } - - private void SetErrorString(string id) - { - QuietButtonEnabled = false; - SessionStateText = GetStatusString(id); - SessionStateTextColor = (SolidColorBrush)Application.Current.Resources["SystemFillColorCriticalBrush"]; - } - - public bool IsQuietBackgroundProcessesFeatureEnabled => _experimentationService.IsFeatureEnabled("QuietBackgroundProcessesExperiment"); - - public QuietBackgroundProcessesViewModel( - IExperimentationService experimentationService, - DispatcherQueue dispatcherQueue) - { - _experimentationService = experimentationService; - _dispatcherQueue = dispatcherQueue; - _countdownTimer = string.Empty; - _sessionStateText = GetString("QuietBackgroundProcesses_Description"); - - // Set the default text color since there's no way to acquire it from - // the theme in code (and we want to change it when an error happens). - _sessionStateTextColor = (SolidColorBrush)Application.Current.Resources["TextFillColorSecondaryBrush"]; - _dispatcherTimer = new DispatcherTimer(); - } - - public async Task LoadViewModelContentAsync() - { - await Task.Run(async () => - { - if (!IsQuietBackgroundProcessesFeatureEnabled) - { - return; - } - - var isFeaturePresent = false; - try - { - isFeaturePresent = QuietBackgroundProcessesSessionManager.IsFeaturePresent(); - } - catch (Exception ex) - { - _log.Error(ex, "COM error"); - } - - var isAvailable = false; - isAvailable = _table != null; - if (!isAvailable) - { - try - { - isAvailable = QuietBackgroundProcessesSessionManager.HasLastPerformanceRecording(); - } - catch (Exception ex) - { - _log.Error(ex, "COM error"); - } - } - - var running = false; - long? timeLeftInSeconds = null; - if (isFeaturePresent) - { - // Check if an existing quiet session is running. - // Note: GetIsActive() won't ever launch a UAC prompt, but GetTimeRemaining() will if no session is running - so be careful with call order - running = GetIsActive(); - if (running) - { - timeLeftInSeconds = GetTimeRemaining(); - } - } - - // Update the UI thread - await _dispatcherQueue.EnqueueAsync(() => - { - IsFeaturePresent = isFeaturePresent; - IsAnalyticSummaryAvailable = isAvailable; - if (IsFeaturePresent) - { - QuietButtonEnabled = true; - - // Resume countdown if there's an existing quiet window - SetQuietSessionRunningState(running, timeLeftInSeconds); - } - else - { - SetErrorString("FeatureNotSupported"); - QuietButtonText = GetString("QuietBackgroundProcesses_QuietButton_Start"); - } - }); - }); - } - - private void SetQuietSessionRunningState(bool running, long? timeLeftInSeconds = null) - { - if (running) - { - var seconds = timeLeftInSeconds ?? GetTimeRemaining(); - StartCountdownTimer(seconds); - QuietButtonText = GetString("QuietBackgroundProcesses_QuietButton_Stop"); - IsAnalyticSummaryAvailable = false; - } - else - { - _dispatcherTimer?.Stop(); - QuietButtonText = GetString("QuietBackgroundProcesses_QuietButton_Start"); - if (!IsAnalyticSummaryAvailable) - { - IsAnalyticSummaryAvailable = QuietBackgroundProcessesSessionManager.HasLastPerformanceRecording(); - } - } - - QuietButtonChecked = !running; - } - - [RelayCommand] - public void QuietButtonClicked() - { - if (QuietButtonChecked) - { - try - { - TelemetryFactory.Get().Log("QuietBackgroundProcesses_Session", LogLevel.Critical, new QuietBackgroundProcessesEvent(LoggingOpcode.Start)); - - // Launch the server, which then elevates itself, showing a UAC prompt - var timeLeftInSeconds = GetSession().Start(); - _sessionDuration = TimeSpan.FromSeconds(timeLeftInSeconds); - SetQuietSessionRunningState(true, timeLeftInSeconds); - } - catch (Exception ex) - { - TelemetryFactory.Get().Log("QuietBackgroundProcesses_SessionStartError", LogLevel.Critical, new QuietBackgroundProcessesEvent()); - - SetErrorString("SessionStartError"); - _log.Error(ex, "QuietBackgroundProcessesSession::Start failed"); - } - } - else - { - try - { - TelemetryFactory.Get().Log("QuietBackgroundProcesses_Session", LogLevel.Critical, new QuietBackgroundProcessesEvent(LoggingOpcode.Stop)); - - _table = GetSession().Stop(); - IsAnalyticSummaryAvailable = _table != null; - SetQuietSessionRunningState(false); - CountdownTimer = GetLastSessionLengthString(_sessionDuration - _secondsLeft); - } - catch (Exception ex) - { - TelemetryFactory.Get().Log("QuietBackgroundProcesses_SessionStopError", LogLevel.Critical, new QuietBackgroundProcessesEvent()); - - SetErrorString("UnableToCancelSession"); - _log.Error(ex, "QuietBackgroundProcessesSession::Stop failed"); - } - } - } - - private bool GetIsActive() - { - try - { - _session = QuietBackgroundProcessesSessionManager.TryGetSession(); - if (_session != null) - { - return _session.IsActive; - } - } - catch (Exception ex) - { - SetErrorString("UnableToFindActiveSession"); - _log.Error(ex, "QuietBackgroundProcessesSession::IsActive failed"); - } - - return false; - } - - private int GetTimeRemaining() - { - try - { - return (int)GetSession().TimeLeftInSeconds; - } - catch (Exception ex) - { - SetErrorString("UnableToGetTimeLeft"); - _log.Error(ex, "QuietBackgroundProcessesSession::TimeLeftInSeconds failed"); - return 0; - } - } - - private DispatcherTimer _dispatcherTimer; - private TimeSpan _secondsLeft; - - private void StartCountdownTimer(long timeLeftInSeconds) - { - if (timeLeftInSeconds <= 0) - { - return; - } - - _dispatcherTimer = new DispatcherTimer(); - _dispatcherTimer.Tick += DispatcherTimer_Tick; - _dispatcherTimer.Interval = new TimeSpan(0, 0, 1); - _secondsLeft = new TimeSpan(0, 0, (int)timeLeftInSeconds); - _dispatcherTimer.Start(); - - CountdownTimer = _secondsLeft.ToString(); - } - - private void DispatcherTimer_Tick(object? sender, object e) - { - // Subtract 1 second - _secondsLeft = _secondsLeft.Subtract(_oneSecond); - - // Every 2 minutes ask the server for the actual time remaining (to resolve any drift) - if (_secondsLeft.Seconds % 120 == 0) - { - _secondsLeft = new TimeSpan(0, 0, GetTimeRemaining()); - } - - var sessionEnded = false; - if (_secondsLeft.CompareTo(_zero) <= 0) - { - // The window should be closed, but let's confirm with the server - if (!GetSession().IsActive) - { - sessionEnded = true; - } - } - - if (sessionEnded) - { - SetQuietSessionRunningState(false); - var lastSessionLength = _sessionDuration - _secondsLeft; - _secondsLeft = _zero; - CountdownTimer = GetLastSessionLengthString(lastSessionLength); - } - else - { - CountdownTimer = _secondsLeft.ToString(); // CultureInfo.InvariantCulture - } - } - - private string GetLastSessionLengthString(TimeSpan lastSessionLength) - { - return GetString("QuietBackgroundProcesses_Time_LastSessionLength") + " " + lastSessionLength.ToString("g", CultureInfo.CurrentCulture); - } - - public ProcessPerformanceTable? GetProcessPerformanceTable() - { - if (_table == null) - { - try - { - _table = QuietBackgroundProcessesSessionManager.TryGetLastPerformanceRecording(); - } - catch (Exception ex) - { - SetErrorString("UnableToGetAnalyticSummary"); - _log.Error(ex, "QuietBackgroundProcessesSessionManager.TryGetLastPerformanceRecording failed"); - } - } - - return _table; - } -} diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/AnalyticSummaryPopup.xaml b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/AnalyticSummaryPopup.xaml deleted file mode 100644 index 292b01c34..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/AnalyticSummaryPopup.xaml +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - - 652 - 700 - 650 - 36 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/AnalyticSummaryPopup.xaml.cs b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/AnalyticSummaryPopup.xaml.cs deleted file mode 100644 index e42652f8b..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/AnalyticSummaryPopup.xaml.cs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using DevHome.Common.Extensions; -using DevHome.Common.Windows.FileDialog; -using DevHome.QuietBackgroundProcesses.UI.ViewModels; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; - -namespace DevHome.QuietBackgroundProcesses.UI.Views; - -public sealed partial class AnalyticSummaryPopup : ContentDialog -{ - private readonly Window _mainWindow; - - public AnalyticSummaryPopupViewModel ViewModel - { - get; - } - - public AnalyticSummaryPopup(QuietBackgroundProcesses.ProcessPerformanceTable? performanceTable) - { - _mainWindow = Application.Current.GetService(); - - ViewModel = new AnalyticSummaryPopupViewModel(performanceTable); - - this.Style = Application.Current.Resources["DefaultContentDialogStyle"] as Style; - this.DefaultButton = ContentDialogButton.Primary; - this.InitializeComponent(); - } - - private void SaveReportButtonClicked(ContentDialog sender, ContentDialogButtonClickEventArgs args) - { - using var fileDialog = new WindowSaveFileDialog(); - fileDialog.AddFileType("CSV files", ".csv"); - - var filePath = fileDialog.Show(_mainWindow); - if (filePath != null) - { - ViewModel.SaveReport(filePath); - } - } -} diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/ProcessPerformanceTableControl.xaml b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/ProcessPerformanceTableControl.xaml deleted file mode 100644 index 8ad3f2dcd..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/ProcessPerformanceTableControl.xaml +++ /dev/null @@ -1,111 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/ProcessPerformanceTableControl.xaml.cs b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/ProcessPerformanceTableControl.xaml.cs deleted file mode 100644 index 364220422..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/ProcessPerformanceTableControl.xaml.cs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System.Collections.ObjectModel; -using DevHome.QuietBackgroundProcesses.UI.ViewModels; -using Microsoft.UI.Xaml; -using Microsoft.UI.Xaml.Controls; - -namespace DevHome.QuietBackgroundProcesses.UI.Views; - -public sealed partial class ProcessPerformanceTableControl : UserControl -{ - public ObservableCollection ProcessDatas { get; set; } = new ObservableCollection(); - - public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register( - nameof(ItemsSource), - typeof(object), - typeof(AnalyticSummaryPopupViewModel), - new PropertyMetadata(default)); - - public object ItemsSource - { - get => (object)GetValue(ItemsSourceProperty); - set => SetValue(ItemsSourceProperty, value); - } - - public ProcessPerformanceTableControl() - { - this.InitializeComponent(); - } -} diff --git a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/QuietBackgroundProcessesView.xaml b/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/QuietBackgroundProcessesView.xaml deleted file mode 100644 index 4f875f45c..000000000 --- a/tools/QuietBackgroundProcesses/DevHome.QuietBackgroundProcesses.UI/Views/QuietBackgroundProcessesView.xaml +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -