Prepare ms-private 0.0.1 release candidate
This commit is contained in:
1 parent
7aacc0b63f
commit
a515538438
75 files changed
+3957
-3484
No files matched your search
@@ -0,0 +1,86 @@
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Principal;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace MsPrivate.Launcher;
|
||||
|
||||
internal static class Program
|
||||
{
|
||||
private const string PayloadResource = "MsPrivate.Payload.zip";
|
||||
|
||||
[STAThread]
|
||||
private static int Main()
|
||||
{
|
||||
Application.SetHighDpiMode(HighDpiMode.PerMonitorV2);
|
||||
Application.EnableVisualStyles();
|
||||
using var mutex = new Mutex(initiallyOwned: true, @"Local\ms-private-launcher", out var ownsMutex);
|
||||
if (!ownsMutex)
|
||||
{
|
||||
MessageBox.Show("ms-private is already running.", "ms-private", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
return 2;
|
||||
}
|
||||
try
|
||||
{
|
||||
if (!OperatingSystem.IsWindows() || !Environment.Is64BitOperatingSystem) throw new PlatformNotSupportedException("ms-private requires 64-bit Windows.");
|
||||
using var identity = WindowsIdentity.GetCurrent();
|
||||
if (!new WindowsPrincipal(identity).IsInRole(WindowsBuiltInRole.Administrator)) throw new UnauthorizedAccessException("Administrator rights are required.");
|
||||
|
||||
var bytes = ReadPayload();
|
||||
var payloadHash = Convert.ToHexString(SHA256.HashData(bytes)).ToLowerInvariant();
|
||||
var version = Assembly.GetExecutingAssembly().GetName().Version ?? throw new InvalidDataException("The launcher version is missing.");
|
||||
var productVersion = $"{version.Major}.{version.Minor}.{version.Build}";
|
||||
var runtimeRoot = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "ms-private", "runtime");
|
||||
var runtimeName = productVersion + "-" + payloadHash[..12];
|
||||
var runtimeDirectory = Path.Combine(runtimeRoot, runtimeName);
|
||||
PayloadInstaller.EnsureInstalled(bytes, runtimeDirectory);
|
||||
RemoveOlderRuntimes(runtimeRoot, runtimeDirectory);
|
||||
|
||||
var entryPoint = Path.Combine(runtimeDirectory, "ms-private-GUI.ps1");
|
||||
var powershell = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "WindowsPowerShell", "v1.0", "powershell.exe");
|
||||
if (!File.Exists(powershell)) throw new FileNotFoundException("Windows PowerShell 5.1 was not found.", powershell);
|
||||
var start = new ProcessStartInfo
|
||||
{
|
||||
FileName = powershell,
|
||||
WorkingDirectory = runtimeDirectory,
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true
|
||||
};
|
||||
foreach (var argument in new[] { "-NoLogo", "-NoProfile", "-ExecutionPolicy", "RemoteSigned", "-File", entryPoint }) start.ArgumentList.Add(argument);
|
||||
using var process = Process.Start(start) ?? throw new InvalidOperationException("Windows PowerShell could not be started.");
|
||||
process.WaitForExit();
|
||||
if (process.ExitCode != 0) throw new InvalidOperationException($"The ms-private interface exited with code {process.ExitCode}.");
|
||||
return 0;
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
MessageBox.Show(exception.Message, "ms-private could not start", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
return 1;
|
||||
}
|
||||
finally
|
||||
{
|
||||
mutex.ReleaseMutex();
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] ReadPayload()
|
||||
{
|
||||
using var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(PayloadResource)
|
||||
?? throw new InvalidDataException("The embedded ms-private payload is missing.");
|
||||
using var memory = new MemoryStream();
|
||||
stream.CopyTo(memory);
|
||||
return memory.ToArray();
|
||||
}
|
||||
|
||||
private static void RemoveOlderRuntimes(string runtimeRoot, string currentDirectory)
|
||||
{
|
||||
if (!Directory.Exists(runtimeRoot) || PayloadInstaller.IsReparsePoint(runtimeRoot)) return;
|
||||
foreach (var directory in Directory.GetDirectories(runtimeRoot))
|
||||
{
|
||||
if (Path.GetFullPath(directory).Equals(Path.GetFullPath(currentDirectory), StringComparison.OrdinalIgnoreCase)) continue;
|
||||
if (PayloadInstaller.IsReparsePoint(directory)) continue;
|
||||
try { PayloadInstaller.DeleteOrdinaryDirectory(directory); } catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user