Initial commit: QSafe Android 1.1.0 and Windows 1.0.4
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows.Interop;
|
||||
using QSafe.Core;
|
||||
|
||||
namespace QSafe.Desktop;
|
||||
|
||||
public partial class App : Application
|
||||
{
|
||||
private Mutex? single;
|
||||
private bool ownsMutex;
|
||||
protected override void OnStartup(StartupEventArgs e)
|
||||
{
|
||||
base.OnStartup(e);
|
||||
bool smoke = e.Args.Contains("--smoke-test");
|
||||
bool demo = smoke || e.Args.Contains("--demo");
|
||||
var path = demo ? Path.Combine(Path.GetTempPath(), "QSafe-Demo", Guid.NewGuid().ToString("N")) : Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Kusoft", "QSafe");
|
||||
single = new Mutex(false, "Local\\QSafe-" + Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(path)))[..20]);
|
||||
try { ownsMutex = single.WaitOne(0); } catch (AbandonedMutexException) { ownsMutex = true; }
|
||||
if (!ownsMutex) { MessageBox.Show("QSafe уже запущен. Откройте существующее окно.", "QSafe"); Shutdown(); return; }
|
||||
try
|
||||
{
|
||||
var store = new LocalStore(path);
|
||||
int connectionIndex = Array.IndexOf(e.Args, "--connection");
|
||||
if (!demo && connectionIndex >= 0)
|
||||
{
|
||||
if (connectionIndex + 1 >= e.Args.Length) throw new InvalidDataException("Укажите личный файл локального подключения.");
|
||||
store.Configure(Connection.Parse(LocalStore.ReadBounded(e.Args[connectionIndex + 1], 65536)));
|
||||
}
|
||||
if (!demo && e.Args.Contains("--configure-only")) { Shutdown(); return; }
|
||||
MainWindow = new MainWindow(store, demo); MainWindow.Show();
|
||||
if (smoke)
|
||||
{
|
||||
var timer = new System.Windows.Threading.DispatcherTimer { Interval = TimeSpan.FromSeconds(2) };
|
||||
timer.Tick += (_, _) => { timer.Stop(); MainWindow.Close(); }; timer.Start();
|
||||
}
|
||||
}
|
||||
catch { MessageBox.Show("Не удалось открыть локальное хранилище или защищённые настройки. Данные не изменены. Проверьте доступ к папке %LOCALAPPDATA%\\Kusoft\\QSafe.", "QSafe", MessageBoxButton.OK, MessageBoxImage.Error); Shutdown(1); }
|
||||
}
|
||||
protected override void OnExit(ExitEventArgs e)
|
||||
{
|
||||
if (ownsMutex) single?.ReleaseMutex(); single?.Dispose(); base.OnExit(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static class NativeWindow
|
||||
{
|
||||
[DllImport("dwmapi.dll")] private static extern int DwmSetWindowAttribute(IntPtr hwnd, int attribute, ref int value, int size);
|
||||
[DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool SetWindowDisplayAffinity(IntPtr hwnd, uint affinity);
|
||||
public static void Style(Window window)
|
||||
{
|
||||
window.SourceInitialized += (_, _) =>
|
||||
{
|
||||
var handle = new WindowInteropHelper(window).Handle; int dark = 1;
|
||||
DwmSetWindowAttribute(handle, 20, ref dark, sizeof(int));
|
||||
// Demo contains only synthetic credentials and can be captured for interface review.
|
||||
SetProtection(window, !(Application.Current.MainWindow is MainWindow main && main.IsDemo));
|
||||
};
|
||||
}
|
||||
public static void SetProtection(Window window, bool enabled)
|
||||
{
|
||||
var handle = new WindowInteropHelper(window).Handle;
|
||||
if (handle != IntPtr.Zero) SetWindowDisplayAffinity(handle, enabled ? 0x11u : 0u);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user