From dc2dd78faa9c8e9a86ada289ec64b47953e325e9 Mon Sep 17 00:00:00 2001 From: Dexrn ZacAttack Date: Mon, 13 Jan 2025 02:08:49 -0800 Subject: [PATCH] patching, also rewrite incoming (probably) --- App.xaml.cs | 8 +- Controls/AppTile.xaml.cs | 90 ++++++++++++- Localization/Locale.cs | 5 +- Pages/AppsListPage.xaml.cs | 4 +- README.md | 6 +- Settings/InstalledPackages.cs | 11 +- Settings/Settings.cs | 5 + Strings/en-US/Controls.resw | 126 ------------------ Strings/en-US/Errors.resw | 143 --------------------- Strings/en-US/Resources.resw | 48 +++++-- Utils/Logger.cs | 4 +- Utils/Packages.cs | 51 ++++---- Utils/WinDurangoPatcher.cs | 233 ++++++++++++++++++++++++++++++++++ WinDurango.csproj | 32 ++++- 14 files changed, 442 insertions(+), 324 deletions(-) delete mode 100644 Strings/en-US/Controls.resw delete mode 100644 Strings/en-US/Errors.resw create mode 100644 Utils/WinDurangoPatcher.cs diff --git a/App.xaml.cs b/App.xaml.cs index 365a7db..42c0b6e 100644 --- a/App.xaml.cs +++ b/App.xaml.cs @@ -4,6 +4,7 @@ using System.Diagnostics; using System.IO; using System.Reflection; using System.Threading.Tasks; +using System.Windows.Markup.Localizer; using Windows.Storage; using WinDurango.UI.Settings; using WinDurango.UI.Utils; @@ -14,7 +15,7 @@ namespace WinDurango.UI public partial class App : Application { // constants - public static readonly string DataDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "WinDurango"); + public static readonly string DataDir = Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "WinDurango"), "UI"); public static readonly string AppDir = AppContext.BaseDirectory; private static readonly FileVersionInfo Fvi = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location); // versioning @@ -39,9 +40,10 @@ namespace WinDurango.UI return (major, minor, patch); } - private async Task InitializeLocalizer() + private static async Task InitializeLocalizer() { string StringsFolderPath = Path.Combine(AppContext.BaseDirectory, "Strings"); + Logger.WriteDebug(AppContext.BaseDirectory); StorageFolder stringsFolder = await StorageFolder.GetFolderFromPathAsync(StringsFolderPath); ILocalizer localizer = await new LocalizerBuilder() @@ -51,6 +53,8 @@ namespace WinDurango.UI options.DefaultLanguage = "en-US"; }) .Build(); + // await localizer.SetLanguage(Settings.Settings.Language); + Logger.WriteDebug($"Using language {localizer.GetCurrentLanguage()}"); } private void App_UnhandledException(object sender, Microsoft.UI.Xaml.UnhandledExceptionEventArgs e) diff --git a/Controls/AppTile.xaml.cs b/Controls/AppTile.xaml.cs index 5d8567c..b9504cc 100644 --- a/Controls/AppTile.xaml.cs +++ b/Controls/AppTile.xaml.cs @@ -1,4 +1,5 @@ -using Microsoft.UI.Xaml; +using CommunityToolkit.WinUI; +using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Media.Imaging; using System; @@ -6,6 +7,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; +using System.Threading.Tasks; using Windows.ApplicationModel; using Windows.ApplicationModel.Core; using Windows.Foundation; @@ -24,12 +26,16 @@ namespace WinDurango.UI.Controls private string _Publisher; private string _Version; private Uri _Logo; + private ProgressDialog currentDialog = null; + // "Just Works" + // this needs to be fixed. + private bool shouldShowDone = true; private async void HandleUnregister(object sender, SplitButtonClickEventArgs e) { if ((bool)unregisterCheckbox.IsChecked) { - var confirmation = new Confirmation($"Are you sure you want to uninstall {_Name}?", "Uninstall?"); + var confirmation = new Confirmation(Localization.Locale.GetLocalizedText("Packages.UninstallConfirmation", _Name), "Uninstall?"); Dialog.BtnClicked answer = await confirmation.Show(); if (answer == Dialog.BtnClicked.Yes) { @@ -51,6 +57,58 @@ namespace WinDurango.UI.Controls _ = Process.Start(new ProcessStartInfo(_package.InstalledPath) { UseShellExecute = true }); } + private async Task StatusUpdateAsync(string status, int progress) + { + if (currentDialog == null) + { + currentDialog = new ProgressDialog("Working", "Patcher", false); + // shitty way of doing it + if (new ProgressDialog("Working", "Patcher", false) != null) + { + await App.MainWindow.DispatcherQueue.EnqueueAsync(async () => + { + await currentDialog.ShowAsync(); + }); + } else + { + Logger.WriteDebug("???"); + } + } else + { + currentDialog.Text = status; + currentDialog.Progress = progress; + if (progress == 100) + { + Logger.WriteDebug("100"); + currentDialog.Hide(); + currentDialog = null; + if (shouldShowDone) + await new NoticeDialog("Done!", "Patcher").Show(); + } + } + } + + private async void RepatchPackage(object sender, RoutedEventArgs args) + { + shouldShowDone = false; + await WinDurangoPatcher.UnpatchPackage(_package, StatusUpdateAsync); + shouldShowDone = true; + await WinDurangoPatcher.PatchPackage(_package, true, StatusUpdateAsync); + App.MainWindow.ReloadAppList(); + } + + private async void UnpatchPackage(object sender, RoutedEventArgs args) + { + await WinDurangoPatcher.UnpatchPackage(_package, StatusUpdateAsync); + App.MainWindow.ReloadAppList(); + } + + private async void PatchPackage(object sender, RoutedEventArgs args) + { + await WinDurangoPatcher.PatchPackage(_package, false, StatusUpdateAsync); + App.MainWindow.ReloadAppList(); + } + public AppTile(string familyName) { _familyName = familyName; @@ -68,6 +126,7 @@ namespace WinDurango.UI.Controls _Publisher = _package.PublisherDisplayName ?? _package.Id.PublisherId; _Version = $"{_package.Id.Version.Major.ToString() ?? "U"}.{_package.Id.Version.Minor.ToString() ?? "U"}.{_package.Id.Version.Build.ToString() ?? "U"}.{_package.Id.Version.Revision.ToString() ?? "U"}"; _Logo = _package.Logo; + string ss = Packages.GetSplashScreenPath(_package); IReadOnlyList appListEntries = null; try @@ -112,7 +171,32 @@ namespace WinDurango.UI.Controls } infoExpander.Header = _Name; - Flyout rcFlyout = new(); + MenuFlyout rcFlyout = new(); + + bool isPatched = InstalledPackages.GetInstalledPackage(_package.Id.FamilyName).Value.installedPackage.IsPatched; + + MenuFlyoutItem patchButton = new MenuFlyoutItem + { + Text = isPatched ? "Repatch" : "Patch", + Name = "patchButton" + }; + + if (isPatched) + { + patchButton.Click += RepatchPackage; + MenuFlyoutItem unpatchButton = new MenuFlyoutItem + { + Text = "Unpatch", + Name = "unpatchButton" + }; + unpatchButton.Click += UnpatchPackage; + rcFlyout.Items.Add(unpatchButton); + } else + { + patchButton.Click += PatchPackage; + } + + rcFlyout.Items.Add(patchButton); expanderVersion.Text = $"Publisher: {_Publisher}\nVersion {_Version}"; diff --git a/Localization/Locale.cs b/Localization/Locale.cs index 374ee70..8f15dd5 100644 --- a/Localization/Locale.cs +++ b/Localization/Locale.cs @@ -10,7 +10,10 @@ namespace WinDurango.UI.Localization { public static string GetLocalizedText(string name, params object[] args) { - return string.Format(name.GetLocalizedString(), args); + String translated = Localizer.Get().GetLocalizedString(name); + if (translated == "") + Logger.Write(LogLevel.Warning, $"String {name} not found in string resources."); + return string.Format(translated == "" ? $"LOCALIZATION ERROR: String {name} not found in string resources." : translated, args); } } } diff --git a/Pages/AppsListPage.xaml.cs b/Pages/AppsListPage.xaml.cs index 124c11b..a2453e7 100644 --- a/Pages/AppsListPage.xaml.cs +++ b/Pages/AppsListPage.xaml.cs @@ -132,13 +132,13 @@ namespace WinDurango.UI.Pages { // there is no AppxManifest inside. Logger.WriteError($"Could not find AppxManifest.xml in {folder.Path} and {mountFolder}"); - await new NoticeDialog(GetLocalizedText("ManifestNotFoundMulti", folder.Path, mountFolder), "Error").Show(); + await new NoticeDialog(GetLocalizedText("Packages.Error.ManifestNotFoundMulti", folder.Path, mountFolder), "Error").Show(); } } else { Logger.WriteError($"Could not find AppxManifest.xml in {folder.Path} and no Mount folder exists"); - await new NoticeDialog(GetLocalizedText("ManifestNotFoundNoMount", folder.Path), "Error").Show(); + await new NoticeDialog(GetLocalizedText("Packages.Error.ManifestNotFoundNoMount", folder.Path), "Error").Show(); } return; diff --git a/README.md b/README.md index 66cb1af..f77155b 100644 --- a/README.md +++ b/README.md @@ -3,14 +3,16 @@ [![View stargazers](https://img.shields.io/github/stars/WinDurango-project/WinDurango.UI)](https://github.com/WinDurango-project/WinDurango.UI/stargazers) GUI for WinDurango, which is planned to allow for easy installing/patching among other random stuff I decide lmfao +### NOTICE: A large amount of the codebase has to be rewritten as I was not a good C# dev when this was originally made (statics everywhere, messy fields, etc) +#### Additonally, the translation shit does NOT work at this moment, I cannot figure out why. + > [!NOTE] > This does nothing more than provide a GUI for easily registering and patching packages with WinDurango. -> Additionally, I don't know much about C#... so the code is probably very messy. # Roadmap ## Features - - [ ] Compiling the DLLs and patching automatically + - [X] Patching - [X] Allow for package removal from UI instead of just completely uninstalling. - [X] Installation options - [X] Scan for already installed EraOS/XUWP stuff diff --git a/Settings/InstalledPackages.cs b/Settings/InstalledPackages.cs index 94d4890..0da84f7 100644 --- a/Settings/InstalledPackages.cs +++ b/Settings/InstalledPackages.cs @@ -12,14 +12,17 @@ namespace WinDurango.UI.Settings { public string FullName { get; set; } public List SymlinkedDLLs { get; set; } + public List OriginalDLLs { get; set; } + public bool IsPatched { get; set; } } + // TODO: make this not static public abstract class InstalledPackages { public static void RemoveInstalledPackage(Package pkg) { - string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "WinDurango"); + string path = App.DataDir; if (!Directory.Exists(path)) { _ = Directory.CreateDirectory(path); @@ -127,7 +130,7 @@ namespace WinDurango.UI.Settings public static void AddInstalledPackage(Package package) { - string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "WinDurango"); + string path = App.DataDir; if (!Directory.Exists(path)) { _ = Directory.CreateDirectory(path); @@ -154,7 +157,9 @@ namespace WinDurango.UI.Settings installedPkgs[package.Id.FamilyName] = new InstalledPackage { FullName = package.Id.FullName, - SymlinkedDLLs = [] + SymlinkedDLLs = [], + OriginalDLLs = [], + IsPatched = false }; string updated = JsonSerializer.Serialize(installedPkgs, new JsonSerializerOptions { WriteIndented = true }); diff --git a/Settings/Settings.cs b/Settings/Settings.cs index 709f35b..aa75619 100644 --- a/Settings/Settings.cs +++ b/Settings/Settings.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics; using System.IO; using System.Reflection; using System.Text.Json; @@ -22,6 +23,10 @@ public class WdSettingsData public uint SaveVersion { get; set; } = App.VerPacked; public ThemeSetting Theme { get; set; } = ThemeSetting.Fluent; public bool DebugLoggingEnabled { get; set; } = false; + + public string Language { get; set; } = "en-US"; + + public string DownloadedWDVer { get; set; } } public class WdSettings diff --git a/Strings/en-US/Controls.resw b/Strings/en-US/Controls.resw deleted file mode 100644 index 02653d8..0000000 --- a/Strings/en-US/Controls.resw +++ /dev/null @@ -1,126 +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 - - - Enable debug logging - - - Disable debug logging - - \ No newline at end of file diff --git a/Strings/en-US/Errors.resw b/Strings/en-US/Errors.resw deleted file mode 100644 index ee3dda1..0000000 --- a/Strings/en-US/Errors.resw +++ /dev/null @@ -1,143 +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 - - - AppxManifest does not exist in {0} and there is no "Mount" folder. - for when AppxManifest.xml is not found and there is no Mount folder to look in - - - {0} was not found. - - - AppxManifest does not exist in {0} and {1} - for when it's not found in either the Mount folder or current chosen folder - - - {0} was not found. - - - {0} is already installed. - - - {0} failed to install: {1} - - - Failed to uninstall {0}: {1} - - \ No newline at end of file diff --git a/Strings/en-US/Resources.resw b/Strings/en-US/Resources.resw index e99f511..f61549f 100644 --- a/Strings/en-US/Resources.resw +++ b/Strings/en-US/Resources.resw @@ -117,28 +117,60 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + Reading manifest... - + Checking if {0} is already installed... - + Installing {0}... - + Getting app info... - + Updating app list... - + {0} was installed! :) - + Uninstalling {0}... - + {0} was uninstalled. + + {0} is already installed. + + + Failed to uninstall {0}: {1} + + + {0} was not found. + + + {0} failed to install: {1} + + + AppxManifest does not exist in {0} and there is no "Mount" folder. + for when AppxManifest.xml is not found and there is no Mount folder to look in + + + AppxManifest does not exist in {0} and {1} + for when it's not found in either the Mount folder or current chosen folder + + + {0} was not found. + + + Enable debug logging + + + Disable debug logging + + + Are you sure you want to uninstall {0}? + \ No newline at end of file diff --git a/Utils/Logger.cs b/Utils/Logger.cs index c34e965..0474f88 100644 --- a/Utils/Logger.cs +++ b/Utils/Logger.cs @@ -12,7 +12,7 @@ namespace WinDurango.UI.Utils public class Logger { public static readonly Logger Instance = new(); - private static readonly string logDir = Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "WinDurango"), "logs"); + private static readonly string logDir = Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "WinDurango\\UI"), "logs"); private static readonly string logFile = Path.Combine(logDir, $"WinDurangoUI_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.log"); private static readonly object @lock = new(); @@ -22,6 +22,7 @@ namespace WinDurango.UI.Utils Directory.CreateDirectory(logDir); } + public static void WriteLine(string str) => Instance.WriteLog(LogLevel.Info, str); public static void WriteDebug(string str) => Instance.WriteLog(LogLevel.Debug, str); public static void WriteError(string str) => Instance.WriteLog(LogLevel.Error, str); public static void WriteWarning(string str) => Instance.WriteLog(LogLevel.Warning, str); @@ -52,7 +53,6 @@ namespace WinDurango.UI.Utils string logEntry = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] [{level.ToString().ToUpper()}] {message}"; Debug.WriteLine(logEntry); - lock (@lock) { using StreamWriter writer = new(logFile, true); diff --git a/Utils/Packages.cs b/Utils/Packages.cs index e5d5b8d..9f3c056 100644 --- a/Utils/Packages.cs +++ b/Utils/Packages.cs @@ -66,7 +66,7 @@ namespace WinDurango.UI.Utils if (!Directory.Exists(mountDir)) { - await new NoticeDialog(GetLocalizedText($"mountNotFound", mountDir), "Error").Show(); + await new NoticeDialog(GetLocalizedText($"Error.mountNotFound", mountDir), "Error").Show(); return; } @@ -77,20 +77,21 @@ namespace WinDurango.UI.Utils var (familyName, installedPackage) = InstalledPackages.GetInstalledPackage(package).Value; - if (hasExvd) - { - foreach (string filePath in Directory.GetFiles(Path.Combine(exvdDir + "\\Windows\\System32"))) - { - string fileName = Path.GetFileName(filePath); + // DO NOT COPY THE DLLS FROM THIS + //if (hasExvd) + //{ + // foreach (string filePath in Directory.GetFiles(Path.Combine(exvdDir + "\\Windows\\System32"))) + // { + // string fileName = Path.GetFileName(filePath); - if (File.Exists(Path.Combine(mountDir, fileName))) - continue; + // if (File.Exists(Path.Combine(mountDir, fileName))) + // continue; - FileSystemInfo symlink = File.CreateSymbolicLink(Path.Combine(mountDir, fileName), filePath); - installedPackage.SymlinkedDLLs.Add(symlink.Name); - InstalledPackages.UpdateInstalledPackage(familyName, installedPackage); - } - } + // FileSystemInfo symlink = File.CreateSymbolicLink(Path.Combine(mountDir, fileName), filePath); + // installedPackage.SymlinkedDLLs.Add(symlink.Name); + // InstalledPackages.UpdateInstalledPackage(familyName, installedPackage); + // } + //} } public static string GetSplashScreenPath(Package pkg) @@ -145,19 +146,19 @@ namespace WinDurango.UI.Utils // TODO: strip UI if (!File.Exists(manifestPath)) { - await new NoticeDialog(GetLocalizedText("NotFound", manifestPath), "Error").Show(); + await new NoticeDialog(GetLocalizedText("Error.NotFound", manifestPath), "Error").Show(); return null; } Logger.WriteInformation($"Installing package \"{manifestPath}\"..."); - var status = new ProgressDialog($"Installing package...", "Installing", false); + var status = new ProgressDialog(GetLocalizedText("Packages.InstallingPackage", "Package..."), "Installing", false); _ = App.MainWindow.DispatcherQueue.TryEnqueue(async () => await status.ShowAsync()); PackageManager pm = new(); try { Logger.WriteInformation($"Reading manifest..."); - status.Text = "ReadingManifest".GetLocalizedString(); + status.Text = "Packages.ReadingManifest".GetLocalizedString(); string manifest; await using (var stream = File.OpenRead(manifestPath)) { @@ -181,24 +182,24 @@ namespace WinDurango.UI.Utils { status.Hide(); Logger.WriteError($"{pkgName} is already installed."); - await new NoticeDialog(GetLocalizedText("AlreadyInstalled", pkgName), "Error").Show(); + await new NoticeDialog(GetLocalizedText("Error.AlreadyInstalled", pkgName), "Error").Show(); return null; } status.Progress = 40.0; - status.Text = GetLocalizedText("InstallingPackage", pkgName); + status.Text = GetLocalizedText("Packages.InstallingPackage", pkgName); Logger.WriteInformation($"Registering..."); var deployment = await pm.RegisterPackageAsync(appxManifestUri, null, DeploymentOptions.DevelopmentMode); status.Progress = 60.0; - status.Text = "GettingAppInfo".GetLocalizedString(); + status.Text = "Packages.GettingAppInfo".GetLocalizedString(); var recentPkg = GetMostRecentlyInstalledPackage(); if (addInstalledPackage) { - status.Text = $"UpdatingAppList".GetLocalizedString(); + status.Text = $"Ui.UpdatingAppList".GetLocalizedString(); status.Progress = 80.0; InstalledPackages.AddInstalledPackage(recentPkg); status.Progress = 90.0; @@ -212,7 +213,7 @@ namespace WinDurango.UI.Utils status.Hide(); Logger.WriteInformation($"{recentPkg.Id.Name} was installed."); - await new NoticeDialog(GetLocalizedText("PackageInstalled", recentPkg.Id.Name)).Show(); + await new NoticeDialog(GetLocalizedText("Packages.PackageInstalled", recentPkg.Id.Name)).Show(); return recentPkg.Id.FamilyName; } catch (Exception e) @@ -221,7 +222,7 @@ namespace WinDurango.UI.Utils status.Hide(); Logger.WriteError($"{appxManifestUri} failed to install"); Logger.WriteException(e); - await new NoticeDialog(GetLocalizedText("PackageInstallFailedEx", appxManifestUri, e.Message), "Error").Show(); + await new NoticeDialog(GetLocalizedText("Packages.Error.PackageInstallFailedEx", appxManifestUri, e.Message), "Error").Show(); return null; } } @@ -229,7 +230,7 @@ namespace WinDurango.UI.Utils public static async Task RemovePackage(Package package) { Logger.WriteError($"Uninstalling {package.DisplayName}..."); - var status = new ProgressDialog(GetLocalizedText("UninstallingPackage", package.DisplayName), "Uninstalling", false); + var status = new ProgressDialog(GetLocalizedText("Packages.UninstallingPackage", package.DisplayName), "Uninstalling", false); _ = App.MainWindow.DispatcherQueue.TryEnqueue(async () => await status.ShowAsync()); PackageManager pm = new(); try @@ -241,7 +242,7 @@ namespace WinDurango.UI.Utils status.Progress = 100.0; status.Hide(); Logger.WriteInformation($"{package.DisplayName} was uninstalled."); - await new NoticeDialog(GetLocalizedText("PackageUninstalled", package.DisplayName)).Show(); + await new NoticeDialog(GetLocalizedText("Packages.PackageUninstalled", package.DisplayName)).Show(); App.MainWindow.ReloadAppList(); } catch (Exception ex) @@ -249,7 +250,7 @@ namespace WinDurango.UI.Utils status.Hide(); Logger.WriteError($"{package.DisplayName} failed to uninstall"); Logger.WriteException(ex); - await new NoticeDialog(GetLocalizedText("PackageUninstallFailedEx", package.DisplayName, ex.Message), "Error!").Show(); + await new NoticeDialog(GetLocalizedText("Packages.Error.PackageUninstallFailedEx", package.DisplayName, ex.Message), "Error!").Show(); } return; } diff --git a/Utils/WinDurangoPatcher.cs b/Utils/WinDurangoPatcher.cs new file mode 100644 index 0000000..a97ee97 --- /dev/null +++ b/Utils/WinDurangoPatcher.cs @@ -0,0 +1,233 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.IO.Compression; +using System.IO.Packaging; +using System.Linq; +using System.Net.Http; +using System.Runtime.InteropServices; +using System.Security.Policy; +using System.Text; +using System.Text.Json; +using System.Threading.Tasks; +using Windows.ApplicationModel; +using WinDurango.UI.Settings; +using static System.Runtime.InteropServices.JavaScript.JSType; + +namespace WinDurango.UI.Utils +{ + public class GitHubRelease + { + public string Name { get; set; } + public string DownloadLink { get; set; } + } + + public class WinDurangoPatcher + { + private static GitHubRelease wdRelease; + private static string patchDir = Path.Combine(App.DataDir, "WinDurangoCore"); + + public static async Task PatchPackage(Windows.ApplicationModel.Package package, bool forceRedownload, Func statusCallback) + { + Logger.WriteInformation($"Patching package {package.Id.FamilyName}"); + statusCallback($"Patching {package.Id.FamilyName}", 0); + string curDate = DateTime.UtcNow.ToString("yyyy-MM-dd_HH-mm-ss"); + var instPkg = InstalledPackages.GetInstalledPackage(package.Id.FamilyName); + + string installPath = package.InstalledPath; + + statusCallback($"Getting release", 10); + await GetOrReuseRelease(); // don't use the return value since wdRelease is set regardless + + + if (!Path.Exists(patchDir) || forceRedownload) + { + if (forceRedownload && Path.Exists(patchDir)) + Directory.Delete(patchDir, true); + + string zip = Path.Combine(App.DataDir, "WinDurangoCore.zip"); + + try + { + using (HttpClient client = new HttpClient(new HttpClientHandler { AllowAutoRedirect = true })) + { + statusCallback($"Downloading WinDurango release \"{wdRelease.Name}\"", 20); + Logger.WriteInformation($"Downloading WinDurango release \"{wdRelease.Name}\""); + using (HttpResponseMessage res = await client.GetAsync(wdRelease.DownloadLink, HttpCompletionOption.ResponseHeadersRead)) + { + res.EnsureSuccessStatusCode(); + + using (FileStream stream = new FileStream(zip, FileMode.Create, FileAccess.Write, FileShare.None)) + { + statusCallback($"Writing release zip", 30); + await res.Content.CopyToAsync(stream); + } + } + } + } + catch (Exception ex) + { + Logger.WriteException(ex); + return false; + } + + + try + { + Directory.CreateDirectory(patchDir); + Logger.WriteInformation($"Unzipping"); + statusCallback($"Unzipping", 40); + ZipFile.ExtractToDirectory(zip, patchDir); + } + catch (Exception ex) + { + Logger.WriteException(ex); + return false; + } + } + + statusCallback($"Patching", 50); + if (Path.Exists(patchDir)) + { + DirectoryInfo unzipped = new DirectoryInfo(patchDir); + + var unzippedFiles = unzipped.GetFiles("*.dll"); + float prog = (90 - 50) / (float)unzippedFiles.Length; + DirectoryInfo pkg = new DirectoryInfo(installPath); + + foreach (var file in unzippedFiles) + { + int progress = (int)Math.Round(50 + prog * Array.IndexOf(unzippedFiles, file)); + statusCallback($"Copying {file.Name}", progress); + var pkgFName = pkg.GetFiles("*.dll").FirstOrDefault(pkgFName => pkgFName.Name == file.Name); + if (pkgFName != null) + { + Logger.WriteInformation($"Backing up old {pkgFName.Name}"); + string DllBackup = Path.Combine(installPath, "WDDllBackup", curDate); + if (!Path.Exists(DllBackup)) + Directory.CreateDirectory(DllBackup); + + File.Move(pkgFName.FullName, Path.Combine(DllBackup, pkgFName.Name)); + if (!instPkg.Value.installedPackage.OriginalDLLs.Contains(Path.Combine(DllBackup, pkgFName.Name))) + instPkg.Value.installedPackage.OriginalDLLs.Add(Path.Combine(DllBackup, pkgFName.Name)); + } + + string symPath = Path.Combine(installPath, file.Name); + Logger.WriteInformation($"Added {file.Name}"); + File.Copy(file.FullName, Path.Combine(installPath, file.Name)); + if (!instPkg.Value.installedPackage.SymlinkedDLLs.Contains(symPath)) + instPkg.Value.installedPackage.SymlinkedDLLs.Add(symPath); + } + } else + { + Logger.WriteError("How did this happen???? patchDir should exist."); + return false; + } + + statusCallback($"Updating package list", 95); + instPkg.Value.installedPackage.IsPatched = true; + InstalledPackages.UpdateInstalledPackage(instPkg.Value.familyName, instPkg.Value.installedPackage); + statusCallback($"Done!", 100); + return true; + } + + public static async Task UnpatchPackage(Windows.ApplicationModel.Package package, Func statusCallback) + { + Logger.WriteInformation($"Unpatching package {package.Id.FamilyName}"); + statusCallback($"Unpatching {package.Id.FamilyName}", 0); + var instPkg = InstalledPackages.GetInstalledPackage(package.Id.FamilyName); + var dlls = instPkg.Value.installedPackage.SymlinkedDLLs.ToArray(); + var origDlls = instPkg.Value.installedPackage.OriginalDLLs.ToArray(); + + string installPath = package.InstalledPath; + + float delProg = (0 - 50) / (float)instPkg.Value.installedPackage.SymlinkedDLLs.Count; + foreach (var dll in dlls) + { + int progress = (int)Math.Round(50 + delProg * Array.IndexOf(instPkg.Value.installedPackage.SymlinkedDLLs.ToArray(), dll)); + statusCallback($"Removing {dll}", progress); + try + { + File.Delete(dll); + } catch + { + Logger.WriteError($"Failed to delete {dll}."); + } + if (instPkg.Value.installedPackage.SymlinkedDLLs.Contains(dll)) + instPkg.Value.installedPackage.SymlinkedDLLs.Remove(dll); + }; + + float repProg = (99 - 50) / (float)instPkg.Value.installedPackage.OriginalDLLs.Count; + foreach (var dll in origDlls) + { + int progress = (int)Math.Round(50 + delProg * Array.IndexOf(origDlls, dll)); + statusCallback($"Placing back original DLL \"{dll}\"", progress); + try + { + File.Copy(dll, Path.Combine(installPath, dll)); + } + catch + { + Logger.WriteError($"Failed to copy {dll}."); + } + if (instPkg.Value.installedPackage.OriginalDLLs.Contains(dll)) + instPkg.Value.installedPackage.OriginalDLLs.Remove(dll); + }; + + instPkg.Value.installedPackage.IsPatched = false; + + statusCallback($"Updating package list", 99); + InstalledPackages.UpdateInstalledPackage(instPkg.Value.familyName, instPkg.Value.installedPackage); + statusCallback($"Done!", 100); + return true; + } + + // don't wanna use all the api shits lol + public static async Task GetOrReuseRelease() + { + if (wdRelease.GetType() != typeof(GitHubRelease)) + await GetLatestRelease(); + + return wdRelease; + } + + public static async Task GetLatestRelease() + { + GitHubRelease release = new GitHubRelease(); + + string url = $"https://api.github.com/repos/WinDurango/WinDurango/releases"; + + System.Net.Http.HttpClient client = new System.Net.Http.HttpClient(); + client.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (compatible; GitHubAPI/1.0)"); + var response = await client.GetAsync(url); + response.EnsureSuccessStatusCode(); + + var json = await response.Content.ReadAsStringAsync(); + + JsonDocument document = JsonDocument.Parse(json); + var releases = document.RootElement.EnumerateArray(); + + if (!releases.MoveNext()) + throw new Exception("Couldn't find any releases?????"); + + JsonElement newestRelease = releases.Current; + + string name = newestRelease.GetProperty("name").GetString(); + + release.Name = name; + + var assets = newestRelease.GetProperty("assets").EnumerateArray(); + + if (!assets.MoveNext()) + throw new Exception("Couldn't find any assets?????"); + + string download = assets.Current.GetProperty("browser_download_url").GetString(); + + release.DownloadLink = download; + + wdRelease = release; + return release; + } + } +} diff --git a/WinDurango.csproj b/WinDurango.csproj index 8abc81d..ddb017f 100644 --- a/WinDurango.csproj +++ b/WinDurango.csproj @@ -32,7 +32,6 @@ - @@ -42,6 +41,31 @@ 10.0.26100.38 + True + + + + embedded + + + + embedded + + + + embedded + + + + embedded + + + + embedded + + + + embedded @@ -100,12 +124,6 @@ - - - - - -