2023-05-15 23:32:26 +01:00
|
|
|
|
// Copyright (c) Microsoft Corporation
|
|
|
|
|
|
// The Microsoft Corporation licenses this file to you under the MIT license.
|
|
|
|
|
|
// See the LICENSE file in the project root for more information.
|
|
|
|
|
|
|
|
|
|
|
|
// <summary>
|
|
|
|
|
|
// Application entry and pre-process/initialization.
|
|
|
|
|
|
// </summary>
|
|
|
|
|
|
// <history>
|
|
|
|
|
|
// 2008 created by Truong Do (ductdo).
|
|
|
|
|
|
// 2009-... modified by Truong Do (TruongDo).
|
|
|
|
|
|
// 2023- Included in PowerToys.
|
|
|
|
|
|
// </history>
|
|
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.Diagnostics;
|
|
|
|
|
|
using System.Diagnostics.CodeAnalysis;
|
|
|
|
|
|
using System.Drawing.Printing;
|
|
|
|
|
|
using System.Globalization;
|
|
|
|
|
|
using System.IO;
|
|
|
|
|
|
using System.IO.Pipes;
|
|
|
|
|
|
using System.Linq;
|
|
|
|
|
|
using System.Security.Authentication.ExtendedProtection;
|
|
|
|
|
|
using System.Security.Principal;
|
|
|
|
|
|
using System.ServiceModel.Channels;
|
|
|
|
|
|
using System.ServiceProcess;
|
|
|
|
|
|
using System.Threading;
|
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
using System.Windows.Forms;
|
|
|
|
|
|
using System.Xml.Linq;
|
2024-09-16 16:09:43 -04:00
|
|
|
|
|
2023-05-15 23:32:26 +01:00
|
|
|
|
using ManagedCommon;
|
|
|
|
|
|
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
|
|
|
|
|
|
using Microsoft.PowerToys.Telemetry;
|
|
|
|
|
|
using Newtonsoft.Json;
|
|
|
|
|
|
using StreamJsonRpc;
|
|
|
|
|
|
|
2024-10-18 17:32:08 +01:00
|
|
|
|
using Logger = MouseWithoutBorders.Core.Logger;
|
2025-01-17 15:41:39 +00:00
|
|
|
|
using Thread = MouseWithoutBorders.Core.Thread;
|
2024-10-18 17:32:08 +01:00
|
|
|
|
|
2023-05-15 23:32:26 +01:00
|
|
|
|
[module: SuppressMessage("Microsoft.MSInternal", "CA904:DeclareTypesInMicrosoftOrSystemNamespace", Scope = "namespace", Target = "MouseWithoutBorders", Justification = "Dotnet port with style preservation")]
|
|
|
|
|
|
[module: SuppressMessage("Microsoft.Design", "CA1014:MarkAssembliesWithClsCompliant", Justification = "Dotnet port with style preservation")]
|
|
|
|
|
|
[module: SuppressMessage("Microsoft.Globalization", "CA1304:SpecifyCultureInfo", Scope = "member", Target = "MouseWithoutBorders.Program.#Main()", MessageId = "System.String.ToLower", Justification = "Dotnet port with style preservation")]
|
|
|
|
|
|
[module: SuppressMessage("Microsoft.Globalization", "CA1300:SpecifyMessageBoxOptions", Scope = "member", Target = "MouseWithoutBorders.Program.#Main()", Justification = "Dotnet port with style preservation")]
|
|
|
|
|
|
|
|
|
|
|
|
namespace MouseWithoutBorders.Class
|
|
|
|
|
|
{
|
|
|
|
|
|
internal static class Program
|
|
|
|
|
|
{
|
|
|
|
|
|
private static readonly string ServiceName = "PowerToys.MWB.Service";
|
|
|
|
|
|
|
|
|
|
|
|
private static readonly string ServiceModeArg = "UseService";
|
|
|
|
|
|
|
2023-07-11 21:14:47 +01:00
|
|
|
|
public static bool ShowServiceModeErrorTooltip;
|
|
|
|
|
|
|
2023-05-15 23:32:26 +01:00
|
|
|
|
[STAThread]
|
|
|
|
|
|
private static void Main()
|
|
|
|
|
|
{
|
|
|
|
|
|
ManagedCommon.Logger.InitializeLogger("\\MouseWithoutBorders\\Logs");
|
2024-10-18 17:32:08 +01:00
|
|
|
|
Logger.Log(Application.ProductName + " Started!");
|
2023-05-15 23:32:26 +01:00
|
|
|
|
|
2024-10-24 22:04:32 +02:00
|
|
|
|
ETWTrace etwTrace = new ETWTrace();
|
|
|
|
|
|
|
2023-05-15 23:32:26 +01:00
|
|
|
|
if (PowerToys.GPOWrapper.GPOWrapper.GetConfiguredMouseWithoutBordersEnabledValue() == PowerToys.GPOWrapper.GpoRuleConfigured.Disabled)
|
|
|
|
|
|
{
|
2024-10-18 17:32:08 +01:00
|
|
|
|
Logger.Log("Tried to start with a GPO policy setting the utility to always be disabled. Please contact your systems administrator.");
|
2023-05-15 23:32:26 +01:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Thread.CurrentThread.Name = Application.ProductName + " main thread";
|
|
|
|
|
|
Common.BinaryName = Path.GetFileNameWithoutExtension(Application.ExecutablePath);
|
|
|
|
|
|
|
|
|
|
|
|
WindowsIdentity currentUser = WindowsIdentity.GetCurrent();
|
|
|
|
|
|
SecurityIdentifier currentUserSID = currentUser.User;
|
|
|
|
|
|
SecurityIdentifier localSystemSID = new SecurityIdentifier(WellKnownSidType.LocalSystemSid, null);
|
|
|
|
|
|
|
|
|
|
|
|
bool runningAsSystem = currentUserSID.Equals(localSystemSID);
|
|
|
|
|
|
Common.RunWithNoAdminRight = !runningAsSystem;
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
string[] args = Environment.GetCommandLineArgs();
|
|
|
|
|
|
|
|
|
|
|
|
string firstArg = string.Empty;
|
|
|
|
|
|
if (args.Length > 1 && args[1] != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
firstArg = args[1].Trim();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
User = WindowsIdentity.GetCurrent().Name;
|
2024-10-18 17:32:08 +01:00
|
|
|
|
Logger.LogDebug("*** Started as " + User);
|
2023-05-15 23:32:26 +01:00
|
|
|
|
|
2024-10-18 17:32:08 +01:00
|
|
|
|
Logger.Log(Environment.CommandLine);
|
2023-05-15 23:32:26 +01:00
|
|
|
|
|
|
|
|
|
|
bool serviceMode = firstArg == ServiceModeArg;
|
|
|
|
|
|
|
|
|
|
|
|
// If we're started from the .dll module or from the service process, we should
|
|
|
|
|
|
// assume the service mode.
|
2023-05-31 15:50:48 +01:00
|
|
|
|
if (serviceMode && !runningAsSystem)
|
2023-05-15 23:32:26 +01:00
|
|
|
|
{
|
2023-05-31 15:50:48 +01:00
|
|
|
|
try
|
2023-05-15 23:32:26 +01:00
|
|
|
|
{
|
|
|
|
|
|
var sc = new ServiceController(ServiceName);
|
|
|
|
|
|
sc.Start();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2023-05-31 15:50:48 +01:00
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
2024-10-18 17:32:08 +01:00
|
|
|
|
Logger.Log("Couldn't start the service. Will try to continue as not a service.");
|
|
|
|
|
|
Logger.Log(ex);
|
2023-07-11 21:14:47 +01:00
|
|
|
|
ShowServiceModeErrorTooltip = true;
|
2023-05-31 15:50:48 +01:00
|
|
|
|
serviceMode = false;
|
|
|
|
|
|
Setting.Values.UseService = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-05-15 23:32:26 +01:00
|
|
|
|
|
2023-05-31 15:50:48 +01:00
|
|
|
|
if (serviceMode || runningAsSystem)
|
|
|
|
|
|
{
|
2023-05-15 23:32:26 +01:00
|
|
|
|
if (args.Length > 2)
|
|
|
|
|
|
{
|
|
|
|
|
|
Helper.UserLocalAppDataPath = args[2].Trim();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-10-24 22:04:32 +02:00
|
|
|
|
ShutdownWithPowerToys.WaitForPowerToysRunner(etwTrace);
|
2023-05-15 23:32:26 +01:00
|
|
|
|
|
|
|
|
|
|
if (firstArg != string.Empty)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (Common.CheckSecondInstance(Common.RunWithNoAdminRight))
|
|
|
|
|
|
{
|
2024-10-18 17:32:08 +01:00
|
|
|
|
Logger.Log("*** Second instance, exiting...");
|
2023-05-15 23:32:26 +01:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
string myDesktop = Common.GetMyDesktop();
|
|
|
|
|
|
|
|
|
|
|
|
if (firstArg.Equals("winlogon", StringComparison.OrdinalIgnoreCase))
|
|
|
|
|
|
{
|
|
|
|
|
|
// Executed by service, running on logon desktop
|
2024-10-18 17:32:08 +01:00
|
|
|
|
Logger.Log("*** Running on " + firstArg + " desktop");
|
2023-05-15 23:32:26 +01:00
|
|
|
|
Common.RunOnLogonDesktop = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (args[1].Trim().Equals("default", StringComparison.OrdinalIgnoreCase))
|
|
|
|
|
|
{
|
2024-10-18 17:32:08 +01:00
|
|
|
|
Logger.Log("*** Running on " + firstArg + " desktop");
|
2023-05-15 23:32:26 +01:00
|
|
|
|
}
|
|
|
|
|
|
else if (args[1].Equals(myDesktop, StringComparison.OrdinalIgnoreCase))
|
|
|
|
|
|
{
|
2024-10-18 17:32:08 +01:00
|
|
|
|
Logger.Log("*** Running on " + myDesktop);
|
2023-05-15 23:32:26 +01:00
|
|
|
|
if (myDesktop.Equals("Screen-saver", StringComparison.OrdinalIgnoreCase))
|
|
|
|
|
|
{
|
|
|
|
|
|
Common.RunOnScrSaverDesktop = true;
|
|
|
|
|
|
Setting.Values.LastX = Common.JUST_GOT_BACK_FROM_SCREEN_SAVER;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
if (Common.CheckSecondInstance(true))
|
|
|
|
|
|
{
|
2024-10-18 17:32:08 +01:00
|
|
|
|
Logger.Log("*** Second instance, exiting...");
|
2023-05-15 23:32:26 +01:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
PowerToysTelemetry.Log.WriteEvent(new MouseWithoutBorders.Telemetry.MouseWithoutBordersStartedEvent());
|
|
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
Common.CurrentProcess = Process.GetCurrentProcess();
|
|
|
|
|
|
Common.CurrentProcess.PriorityClass = ProcessPriorityClass.RealTime;
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
|
{
|
2024-10-18 17:32:08 +01:00
|
|
|
|
Logger.Log(e);
|
2023-05-15 23:32:26 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-10-18 17:32:08 +01:00
|
|
|
|
Logger.Log(Environment.OSVersion.ToString());
|
2023-05-15 23:32:26 +01:00
|
|
|
|
|
|
|
|
|
|
// Environment.OSVersion is unreliable from 6.2 and up, so just forcefully call the APIs and log the exception unsupported by Windows:
|
|
|
|
|
|
int setProcessDpiAwarenessResult = -1;
|
|
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
setProcessDpiAwarenessResult = NativeMethods.SetProcessDpiAwareness(2);
|
2024-10-18 17:32:08 +01:00
|
|
|
|
Logger.Log(string.Format(CultureInfo.InvariantCulture, "SetProcessDpiAwareness: {0}.", setProcessDpiAwarenessResult));
|
2023-05-15 23:32:26 +01:00
|
|
|
|
}
|
|
|
|
|
|
catch (DllNotFoundException)
|
|
|
|
|
|
{
|
2024-10-18 17:32:08 +01:00
|
|
|
|
Logger.Log("SetProcessDpiAwareness is unsupported in Windows 7 and lower.");
|
2023-05-15 23:32:26 +01:00
|
|
|
|
}
|
|
|
|
|
|
catch (EntryPointNotFoundException)
|
|
|
|
|
|
{
|
2024-10-18 17:32:08 +01:00
|
|
|
|
Logger.Log("SetProcessDpiAwareness is unsupported in Windows 7 and lower.");
|
2023-05-15 23:32:26 +01:00
|
|
|
|
}
|
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
|
{
|
2024-10-18 17:32:08 +01:00
|
|
|
|
Logger.Log(e);
|
2023-05-15 23:32:26 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
if (setProcessDpiAwarenessResult != 0)
|
|
|
|
|
|
{
|
2024-10-18 17:32:08 +01:00
|
|
|
|
Logger.Log(string.Format(CultureInfo.InvariantCulture, "SetProcessDPIAware: {0}.", NativeMethods.SetProcessDPIAware()));
|
2023-05-15 23:32:26 +01:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
|
{
|
2024-10-18 17:32:08 +01:00
|
|
|
|
Logger.Log(e);
|
2023-05-15 23:32:26 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
System.Threading.Thread mainUIThread = Thread.CurrentThread;
|
|
|
|
|
|
Common.UIThreadID = mainUIThread.ManagedThreadId;
|
|
|
|
|
|
Thread.UpdateThreads(mainUIThread);
|
|
|
|
|
|
|
|
|
|
|
|
StartInputCallbackThread();
|
|
|
|
|
|
if (!Common.RunOnLogonDesktop)
|
|
|
|
|
|
{
|
|
|
|
|
|
StartSettingSyncThread();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Application.EnableVisualStyles();
|
|
|
|
|
|
_ = Application.SetHighDpiMode(HighDpiMode.PerMonitorV2);
|
|
|
|
|
|
Application.SetCompatibleTextRenderingDefault(false);
|
|
|
|
|
|
|
|
|
|
|
|
Common.Init();
|
|
|
|
|
|
Common.WndProcCounter++;
|
|
|
|
|
|
|
|
|
|
|
|
var formScreen = new FrmScreen();
|
|
|
|
|
|
|
|
|
|
|
|
Application.Run(formScreen);
|
2024-10-24 22:04:32 +02:00
|
|
|
|
|
|
|
|
|
|
etwTrace?.Dispose();
|
2023-05-15 23:32:26 +01:00
|
|
|
|
}
|
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
|
{
|
2024-10-18 17:32:08 +01:00
|
|
|
|
Logger.Log(e);
|
2023-05-15 23:32:26 +01:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private interface ISettingsSyncHelper
|
|
|
|
|
|
{
|
|
|
|
|
|
[JsonObject(MemberSerialization.OptIn)]
|
|
|
|
|
|
public struct MachineSocketState
|
|
|
|
|
|
{
|
|
|
|
|
|
// Disable false-positive warning due to IPC
|
|
|
|
|
|
#pragma warning disable CS0649
|
|
|
|
|
|
[JsonProperty]
|
|
|
|
|
|
public string Name;
|
|
|
|
|
|
|
|
|
|
|
|
[JsonProperty]
|
|
|
|
|
|
public SocketStatus Status;
|
|
|
|
|
|
#pragma warning restore CS0649
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Shutdown();
|
|
|
|
|
|
|
|
|
|
|
|
void Reconnect();
|
|
|
|
|
|
|
|
|
|
|
|
void GenerateNewKey();
|
|
|
|
|
|
|
|
|
|
|
|
void ConnectToMachine(string machineName, string securityKey);
|
|
|
|
|
|
|
|
|
|
|
|
Task<MachineSocketState[]> RequestMachineSocketStateAsync();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private sealed class SettingsSyncHelper : ISettingsSyncHelper
|
|
|
|
|
|
{
|
|
|
|
|
|
public Task<ISettingsSyncHelper.MachineSocketState[]> RequestMachineSocketStateAsync()
|
|
|
|
|
|
{
|
|
|
|
|
|
var machineStates = new Dictionary<string, SocketStatus>();
|
|
|
|
|
|
if (Common.Sk == null || Common.Sk.TcpSockets == null)
|
|
|
|
|
|
{
|
|
|
|
|
|
return Task.FromResult(Array.Empty<ISettingsSyncHelper.MachineSocketState>());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var client in Common.Sk.TcpSockets
|
|
|
|
|
|
.Where(t => t != null && t.IsClient && !string.IsNullOrEmpty(t.MachineName)))
|
|
|
|
|
|
{
|
|
|
|
|
|
var exists = machineStates.TryGetValue(client.MachineName, out var existingStatus);
|
|
|
|
|
|
if (!exists || existingStatus == SocketStatus.NA)
|
|
|
|
|
|
{
|
|
|
|
|
|
machineStates[client.MachineName] = client.Status;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return Task.FromResult(machineStates.Select((state) => new ISettingsSyncHelper.MachineSocketState { Name = state.Key, Status = state.Value }).ToArray());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void ConnectToMachine(string pcName, string securityKey)
|
|
|
|
|
|
{
|
|
|
|
|
|
Setting.Values.PauseInstantSaving = true;
|
|
|
|
|
|
|
|
|
|
|
|
Common.ClearComputerMatrix();
|
|
|
|
|
|
Setting.Values.MyKey = securityKey;
|
|
|
|
|
|
Common.MyKey = securityKey;
|
|
|
|
|
|
Common.MagicNumber = Common.Get24BitHash(Common.MyKey);
|
|
|
|
|
|
Common.MachineMatrix = new string[Common.MAX_MACHINE] { pcName.Trim().ToUpper(CultureInfo.CurrentCulture), Common.MachineName.Trim(), string.Empty, string.Empty };
|
|
|
|
|
|
|
|
|
|
|
|
string[] machines = Common.MachineMatrix;
|
|
|
|
|
|
Common.MachinePool.Initialize(machines);
|
|
|
|
|
|
Common.UpdateMachinePoolStringSetting();
|
|
|
|
|
|
|
|
|
|
|
|
SocketStuff.InvalidKeyFound = false;
|
|
|
|
|
|
Common.ReopenSocketDueToReadError = true;
|
|
|
|
|
|
Common.ReopenSockets(true);
|
|
|
|
|
|
Common.SendMachineMatrix();
|
|
|
|
|
|
|
|
|
|
|
|
Setting.Values.PauseInstantSaving = false;
|
|
|
|
|
|
Setting.Values.SaveSettings();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void GenerateNewKey()
|
|
|
|
|
|
{
|
|
|
|
|
|
Setting.Values.PauseInstantSaving = true;
|
|
|
|
|
|
|
|
|
|
|
|
Setting.Values.EasyMouse = (int)EasyMouseOption.Enable;
|
|
|
|
|
|
Common.ClearComputerMatrix();
|
|
|
|
|
|
Setting.Values.MyKey = Common.MyKey = Common.CreateRandomKey();
|
|
|
|
|
|
Common.GeneratedKey = true;
|
|
|
|
|
|
|
|
|
|
|
|
Setting.Values.PauseInstantSaving = false;
|
|
|
|
|
|
Setting.Values.SaveSettings();
|
|
|
|
|
|
|
|
|
|
|
|
Reconnect();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void Reconnect()
|
|
|
|
|
|
{
|
|
|
|
|
|
SocketStuff.InvalidKeyFound = false;
|
|
|
|
|
|
Common.ReopenSocketDueToReadError = true;
|
|
|
|
|
|
Common.ReopenSockets(true);
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 10; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (Common.AtLeastOneSocketConnected())
|
|
|
|
|
|
{
|
|
|
|
|
|
Common.MMSleep(0.5);
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Common.MMSleep(0.2);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Common.SendMachineMatrix();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void Shutdown()
|
|
|
|
|
|
{
|
|
|
|
|
|
Process[] ps = Process.GetProcessesByName("PowerToys.MouseWithoutBorders");
|
|
|
|
|
|
Process me = Process.GetCurrentProcess();
|
|
|
|
|
|
|
|
|
|
|
|
foreach (Process p in ps)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (p.Id != me.Id)
|
|
|
|
|
|
{
|
|
|
|
|
|
p.Kill();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Common.MainForm.Quit(true, false);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
internal static void StartSettingSyncThread()
|
|
|
|
|
|
{
|
|
|
|
|
|
var serverTaskCancellationSource = new CancellationTokenSource();
|
|
|
|
|
|
CancellationToken cancellationToken = serverTaskCancellationSource.Token;
|
|
|
|
|
|
|
|
|
|
|
|
IpcChannel<SettingsSyncHelper>.StartIpcServer("MouseWithoutBorders/SettingsSync", cancellationToken);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
internal static void StartInputCallbackThread()
|
|
|
|
|
|
{
|
|
|
|
|
|
Thread inputCallback = new(new ThreadStart(InputCallbackThread), "InputCallback Thread");
|
|
|
|
|
|
inputCallback.SetApartmentState(ApartmentState.STA);
|
|
|
|
|
|
inputCallback.Priority = ThreadPriority.Highest;
|
|
|
|
|
|
inputCallback.Start();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private static void InputCallbackThread()
|
|
|
|
|
|
{
|
2025-01-23 03:14:49 +09:00
|
|
|
|
// SuppressFlow fixes an issue on service mode, where the helper process can't get enough permissions to be started again.
|
|
|
|
|
|
// More details can be found on: https://github.com/microsoft/PowerToys/pull/36892
|
|
|
|
|
|
using var asyncFlowControl = ExecutionContext.SuppressFlow();
|
|
|
|
|
|
|
2023-05-15 23:32:26 +01:00
|
|
|
|
Common.InputCallbackThreadID = Thread.CurrentThread.ManagedThreadId;
|
|
|
|
|
|
while (!Common.InitDone)
|
|
|
|
|
|
{
|
|
|
|
|
|
Thread.Sleep(100);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Application.Run(new FrmInputCallback());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
internal static void StartService()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (Common.RunWithNoAdminRight)
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
// Kill all but me
|
|
|
|
|
|
Process me = Process.GetCurrentProcess();
|
|
|
|
|
|
Process[] ps = Process.GetProcessesByName(Common.BinaryName);
|
|
|
|
|
|
foreach (Process pp in ps)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (pp.Id != me.Id)
|
|
|
|
|
|
{
|
2024-10-18 17:32:08 +01:00
|
|
|
|
Logger.Log(string.Format(CultureInfo.InvariantCulture, "Killing process {0}.", pp.Id));
|
2023-05-15 23:32:26 +01:00
|
|
|
|
pp.KillProcess();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
|
{
|
2024-10-18 17:32:08 +01:00
|
|
|
|
Logger.Log(e);
|
2023-05-15 23:32:26 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Common.StartMouseWithoutBordersService();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
internal static string User { get; set; }
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|