diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.Clipboard.cs b/src/modules/MouseWithoutBorders/App/Class/Common.Clipboard.cs
index 9ab32388942a..51be48ec5a24 100644
--- a/src/modules/MouseWithoutBorders/App/Class/Common.Clipboard.cs
+++ b/src/modules/MouseWithoutBorders/App/Class/Common.Clipboard.cs
@@ -153,7 +153,7 @@ internal static bool CheckClipboardEx(ByteArrayOrString data, bool isFilePath)
string filePath = stringData;
- _ = Common.ImpersonateLoggedOnUserAndDoSomething(() =>
+ _ = Launch.ImpersonateLoggedOnUserAndDoSomething(() =>
{
if (File.Exists(filePath) || Directory.Exists(filePath))
{
@@ -579,7 +579,7 @@ internal static void ReceiveAndProcessClipboardData(string remoteMachine, Socket
{
if (postAct.Equals("desktop", StringComparison.OrdinalIgnoreCase))
{
- _ = ImpersonateLoggedOnUserAndDoSomething(() =>
+ _ = Launch.ImpersonateLoggedOnUserAndDoSomething(() =>
{
savingFolder = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\MouseWithoutBorders\\";
@@ -696,7 +696,7 @@ internal static void ReceiveAndProcessClipboardData(string remoteMachine, Socket
Path.GetFileName(fileName),
remoteMachine);
- _ = ImpersonateLoggedOnUserAndDoSomething(() =>
+ _ = Launch.ImpersonateLoggedOnUserAndDoSomething(() =>
{
ProcessStartInfo startInfo = new();
startInfo.UseShellExecute = true;
diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.Event.cs b/src/modules/MouseWithoutBorders/App/Class/Common.Event.cs
deleted file mode 100644
index 92122bcc8fd6..000000000000
--- a/src/modules/MouseWithoutBorders/App/Class/Common.Event.cs
+++ /dev/null
@@ -1,277 +0,0 @@
-// 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.
-
-using System;
-using System.Diagnostics.CodeAnalysis;
-using System.Drawing;
-using System.Globalization;
-using System.Threading;
-using System.Threading.Tasks;
-
-//
-// Keyboard/Mouse hook callback implementation.
-//
-//
-// 2008 created by Truong Do (ductdo).
-// 2009-... modified by Truong Do (TruongDo).
-// 2023- Included in PowerToys.
-//
-using MouseWithoutBorders.Class;
-using MouseWithoutBorders.Core;
-using MouseWithoutBorders.Form;
-
-using Thread = MouseWithoutBorders.Core.Thread;
-
-namespace MouseWithoutBorders
-{
- internal partial class Common
- {
- private static readonly DATA KeybdPackage = new();
- private static readonly DATA MousePackage = new();
-#pragma warning disable SA1307 // Accessible fields should begin with upper-case names
- internal static ulong inputEventCount;
- internal static ulong invalidPackageCount;
-#pragma warning restore SA1307
- internal static int MOVE_MOUSE_RELATIVE = 100000;
- internal static int XY_BY_PIXEL = 300000;
-
- static Common()
- {
- }
-
- internal static ulong InvalidPackageCount
- {
- get => Common.invalidPackageCount;
- set => Common.invalidPackageCount = value;
- }
-
- internal static ulong InputEventCount
- {
- get => Common.inputEventCount;
- set => Common.inputEventCount = value;
- }
-
- internal static ulong RealInputEventCount
- {
- get;
- set;
- }
-
- private static Point actualLastPos;
- private static int myLastX;
- private static int myLastY;
-
- [SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification = "Dotnet port with style preservation")]
- internal static void MouseEvent(MOUSEDATA e, int dx, int dy)
- {
- try
- {
- PaintCount = 0;
- bool switchByMouseEnabled = IsSwitchingByMouseEnabled();
-
- if (switchByMouseEnabled && Sk != null && (DesMachineID == MachineID || !Setting.Values.MoveMouseRelatively) && e.dwFlags == WM_MOUSEMOVE)
- {
- Point p = MachineStuff.MoveToMyNeighbourIfNeeded(e.X, e.Y, MachineStuff.desMachineID);
-
- if (!p.IsEmpty)
- {
- HasSwitchedMachineSinceLastCopy = true;
-
- Logger.LogDebug(string.Format(
- CultureInfo.CurrentCulture,
- "***** Host Machine: newDesMachineIdEx set = [{0}]. Mouse is now at ({1},{2})",
- MachineStuff.newDesMachineIdEx,
- e.X,
- e.Y));
-
- myLastX = e.X;
- myLastY = e.Y;
-
- PrepareToSwitchToMachine(MachineStuff.newDesMachineIdEx, p);
- }
- }
-
- if (MachineStuff.desMachineID != MachineID && MachineStuff.SwitchLocation.Count <= 0)
- {
- MousePackage.Des = MachineStuff.desMachineID;
- MousePackage.Type = PackageType.Mouse;
- MousePackage.Md.dwFlags = e.dwFlags;
- MousePackage.Md.WheelDelta = e.WheelDelta;
-
- // Relative move
- if (Setting.Values.MoveMouseRelatively && Math.Abs(dx) >= MOVE_MOUSE_RELATIVE && Math.Abs(dy) >= MOVE_MOUSE_RELATIVE)
- {
- MousePackage.Md.X = dx;
- MousePackage.Md.Y = dy;
- }
- else
- {
- MousePackage.Md.X = (e.X - MachineStuff.primaryScreenBounds.Left) * 65535 / screenWidth;
- MousePackage.Md.Y = (e.Y - MachineStuff.primaryScreenBounds.Top) * 65535 / screenHeight;
- }
-
- SkSend(MousePackage, null, false);
-
- if (MousePackage.Md.dwFlags is WM_LBUTTONUP or WM_RBUTTONUP)
- {
- Thread.Sleep(10);
- }
-
- NativeMethods.GetCursorPos(ref actualLastPos);
-
- if (actualLastPos != Common.LastPos)
- {
- Logger.LogDebug($"Mouse cursor has moved unexpectedly: Expected: {Common.LastPos}, actual: {actualLastPos}.");
- Common.LastPos = actualLastPos;
- }
- }
-
-#if SHOW_ON_WINLOGON_EX
- if (RunOnLogonDesktop && e.dwFlags == WM_RBUTTONUP &&
- desMachineID == machineID &&
- e.x > 2 && e.x < 100 && e.y > 2 && e.y < 20)
- {
- DoSomethingInUIThread(delegate()
- {
- MainForm.HideMenuWhenRunOnLogonDesktop();
- MainForm.MainMenu.Hide();
- MainForm.MainMenu.Show(e.x - 5, e.y - 3);
- });
- }
-#endif
- }
- catch (Exception ex)
- {
- Logger.Log(ex);
- }
- }
-
- internal static bool IsSwitchingByMouseEnabled()
- {
- return (EasyMouseOption)Setting.Values.EasyMouse == EasyMouseOption.Enable || InputHook.EasyMouseKeyDown;
- }
-
- internal static void PrepareToSwitchToMachine(ID newDesMachineID, Point desMachineXY)
- {
- Logger.LogDebug($"PrepareToSwitchToMachine: newDesMachineID = {newDesMachineID}, desMachineXY = {desMachineXY}");
-
- if (((GetTick() - MachineStuff.lastJump < 100) && (GetTick() - MachineStuff.lastJump > 0)) || MachineStuff.desMachineID == ID.ALL)
- {
- Logger.LogDebug("PrepareToSwitchToMachine: lastJump");
- return;
- }
-
- MachineStuff.lastJump = GetTick();
-
- string newDesMachineName = MachineStuff.NameFromID(newDesMachineID);
-
- if (!IsConnectedTo(newDesMachineID))
- {// Connection lost, cancel switching
- Logger.LogDebug("No active connection found for " + newDesMachineName);
-
- // ShowToolTip("No active connection found for [" + newDesMachineName + "]!", 500);
- }
- else
- {
- MachineStuff.newDesMachineID = newDesMachineID;
- MachineStuff.SwitchLocation.X = desMachineXY.X;
- MachineStuff.SwitchLocation.Y = desMachineXY.Y;
- MachineStuff.SwitchLocation.ResetCount();
- _ = EvSwitch.Set();
-
- // PostMessage(mainForm.Handle, WM_SWITCH, IntPtr.Zero, IntPtr.Zero);
- if (newDesMachineID != DragDrop.DragMachine)
- {
- if (!DragDrop.IsDragging && !DragDrop.IsDropping)
- {
- if (DragDrop.MouseDown && !RunOnLogonDesktop && !RunOnScrSaverDesktop)
- {
- DragDrop.DragDropStep02();
- }
- }
- else if (DragDrop.DragMachine != (ID)1)
- {
- DragDrop.ChangeDropMachine();
- }
- }
- else
- {
- DragDrop.DragDropStep11();
- }
-
- // Change des machine
- if (MachineStuff.desMachineID != newDesMachineID)
- {
- Logger.LogDebug("MouseEvent: Switching to new machine:" + newDesMachineName);
-
- // Ask current machine to hide the Mouse cursor
- if (newDesMachineID != ID.ALL && MachineStuff.desMachineID != MachineID)
- {
- SendPackage(MachineStuff.desMachineID, PackageType.HideMouse);
- }
-
- DesMachineID = newDesMachineID;
-
- if (MachineStuff.desMachineID == MachineID)
- {
- if (GetTick() - clipboardCopiedTime < BIG_CLIPBOARD_DATA_TIMEOUT)
- {
- clipboardCopiedTime = 0;
- Common.GetRemoteClipboard("PrepareToSwitchToMachine");
- }
- }
- else
- {
- // Ask the new active machine to get clipboard data (if the data is too big)
- SendPackage(MachineStuff.desMachineID, PackageType.MachineSwitched);
- }
-
- _ = Interlocked.Increment(ref switchCount);
- }
- }
- }
-
- internal static void SaveSwitchCount()
- {
- if (SwitchCount > 0)
- {
- _ = Task.Run(() =>
- {
- Setting.Values.SwitchCount += SwitchCount;
- _ = Interlocked.Exchange(ref switchCount, 0);
- });
- }
- }
-
- internal static void KeybdEvent(KEYBDDATA e)
- {
- try
- {
- PaintCount = 0;
- if (MachineStuff.desMachineID != MachineStuff.newDesMachineID)
- {
- Logger.LogDebug("KeybdEvent: Switching to new machine...");
- DesMachineID = MachineStuff.newDesMachineID;
- }
-
- if (MachineStuff.desMachineID != MachineID)
- {
- KeybdPackage.Des = MachineStuff.desMachineID;
- KeybdPackage.Type = PackageType.Keyboard;
- KeybdPackage.Kd = e;
- KeybdPackage.DateTime = GetTick();
- SkSend(KeybdPackage, null, false);
- if (KeybdPackage.Kd.dwFlags is WM_KEYUP or WM_SYSKEYUP)
- {
- Thread.Sleep(10);
- }
- }
- }
- catch (Exception ex)
- {
- Logger.Log(ex);
- }
- }
- }
-}
diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.Helper.cs b/src/modules/MouseWithoutBorders/App/Class/Common.Helper.cs
deleted file mode 100644
index b741f9525626..000000000000
--- a/src/modules/MouseWithoutBorders/App/Class/Common.Helper.cs
+++ /dev/null
@@ -1,526 +0,0 @@
-// 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.
-
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Drawing;
-using System.Globalization;
-using System.IO;
-using System.Linq;
-using System.Runtime.InteropServices;
-using System.Security.Principal;
-using System.Windows.Forms;
-
-//
-// Some other helper methods.
-//
-//
-// 2008 created by Truong Do (ductdo).
-// 2009-... modified by Truong Do (TruongDo).
-// 2023- Included in PowerToys.
-//
-using Microsoft.Win32;
-using MouseWithoutBorders.Class;
-using MouseWithoutBorders.Core;
-using static System.Windows.Forms.Control;
-
-namespace MouseWithoutBorders
-{
- internal partial class Common
- {
- internal const string HELPER_FORM_TEXT = "Mouse without Borders Helper";
- internal const string HelperProcessName = "PowerToys.MouseWithoutBordersHelper";
- private static bool signalHelperToExit;
- private static bool signalWatchDogToExit;
- internal static long WndProcCounter;
-
- private static void WatchDogThread()
- {
- long oldCounter = WndProcCounter;
-
- do
- {
- for (int i = 0; i < 10; i++)
- {
- Thread.Sleep(1000);
-
- if (signalWatchDogToExit)
- {
- break;
- }
- }
-
- while (BlockingUI)
- {
- Thread.Sleep(1000);
- }
-
- if (WndProcCounter == oldCounter)
- {
- Process p = Process.GetCurrentProcess();
- string procInfo = $"{p.PrivateMemorySize64 / 1024 / 1024}MB, {p.TotalProcessorTime}, {Environment.ProcessorCount}.";
- string threadStacks = $"{procInfo} {Thread.DumpThreadsStack()}";
- Logger.TelemetryLogTrace(threadStacks, SeverityLevel.Error);
- break;
- }
-
- oldCounter = WndProcCounter;
- }
- while (true);
- }
-
- private static void HelperThread()
- {
- // 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 = System.Threading.ExecutionContext.SuppressFlow();
-
- try
- {
- while (true)
- {
- _ = EvSwitch.WaitOne(); // Switching to another machine?
-
- if (signalHelperToExit)
- {
- break;
- }
-
- if (MachineStuff.NewDesMachineID != Common.MachineID && MachineStuff.NewDesMachineID != ID.ALL)
- {
- HideMouseCursor(false);
- Common.MainFormDotEx(true);
- }
- else
- {
- if (MachineStuff.SwitchLocation.Count > 0)
- {
- MachineStuff.SwitchLocation.Count--;
-
- // When we want to move mouse by pixels, we add 300k to x and y (search for XY_BY_PIXEL for other related code).
- Logger.LogDebug($"+++++ Moving mouse to {MachineStuff.SwitchLocation.X}, {MachineStuff.SwitchLocation.Y}");
-
- // MaxXY = 65535 so 100k is safe.
- if (MachineStuff.SwitchLocation.X > XY_BY_PIXEL - 100000 || MachineStuff.SwitchLocation.Y > XY_BY_PIXEL - 100000)
- {
- InputSimulation.MoveMouse(MachineStuff.SwitchLocation.X - XY_BY_PIXEL, MachineStuff.SwitchLocation.Y - XY_BY_PIXEL);
- }
- else
- {
- InputSimulation.MoveMouseEx(MachineStuff.SwitchLocation.X, MachineStuff.SwitchLocation.Y);
- }
-
- Common.MainFormDot();
- }
- }
-
- if (MachineStuff.NewDesMachineID == Common.MachineID)
- {
- ReleaseAllKeys();
- }
- }
- }
- catch (Exception e)
- {
- Logger.Log(e);
- }
-
- signalHelperToExit = false;
- Logger.LogDebug("^^^Helper Thread exiting...^^^");
- }
-
- internal static void MainFormDotEx(bool bCheckTS)
- {
- Logger.LogDebug("***** MainFormDotEx:");
-
- if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop)
- {
- int left = MachineStuff.PrimaryScreenBounds.Left + ((MachineStuff.PrimaryScreenBounds.Right - MachineStuff.PrimaryScreenBounds.Left) / 2) - 1;
- int top = Setting.Values.HideMouse ? 3 : MachineStuff.PrimaryScreenBounds.Top + ((MachineStuff.PrimaryScreenBounds.Bottom - MachineStuff.PrimaryScreenBounds.Top) / 2);
-
- Common.MainFormVisible = true;
-
- if (Setting.Values.HideMouse && Setting.Values.StealFocusWhenSwitchingMachine && Common.SendMessageToHelper(0x407, new IntPtr(left), new IntPtr(top), true) == 0)
- {
- try
- {
- /* When user just switches to the Logon desktop, user is actually on the "Windows Default Lock Screen" (LockApp).
- * If a click is sent to this during switch, it actually triggers a desktop switch on the local machine causing a reconnection affecting the machine switch.
- * We can detect and skip in this case.
- * */
- IntPtr foreGroundWindow = NativeMethods.GetForegroundWindow();
- string foreGroundWindowText = GetText(foreGroundWindow);
-
- bool mouseClick = true;
-
- if (foreGroundWindowText.Equals("Windows Default Lock Screen", StringComparison.OrdinalIgnoreCase))
- {
- mouseClick = false;
- }
-
- // Window title may be localized, check process name:
- if (mouseClick)
- {
- _ = NativeMethods.GetWindowThreadProcessId(foreGroundWindow, out uint pid);
-
- if (pid > 0)
- {
- string foreGroundWindowProcess = Process.GetProcessById((int)pid)?.ProcessName;
-
- if (foreGroundWindowProcess.Equals("LockApp", StringComparison.OrdinalIgnoreCase))
- {
- mouseClick = false;
- }
- }
- }
-
- if (mouseClick)
- {
- InputSimulation.MouseClickDotForm(left + 1, top + 1);
- }
- }
- catch (Exception e)
- {
- Logger.Log(e);
- }
- }
- }
-
- CustomCursor.ShowFakeMouseCursor(int.MinValue, int.MinValue);
- }
-
- internal static void MainForm3Pixels()
- {
- Logger.LogDebug("***** MainFormDotLarge:");
-
- DoSomethingInUIThread(
- () =>
- {
- MainForm.Left = MachineStuff.PrimaryScreenBounds.Left + ((MachineStuff.PrimaryScreenBounds.Right - MachineStuff.PrimaryScreenBounds.Left) / 2) - 2;
- MainForm.Top = Setting.Values.HideMouse ? 3 : MachineStuff.PrimaryScreenBounds.Top + ((MachineStuff.PrimaryScreenBounds.Bottom - MachineStuff.PrimaryScreenBounds.Top) / 2) - 1;
- MainForm.Width = 3;
- MainForm.Height = 3;
- MainForm.Opacity = 0.11D;
- MainForm.TopMost = true;
-
- if (Setting.Values.HideMouse)
- {
- MainForm.BackColor = Color.Black;
- MainForm.Show();
- Common.MainFormVisible = true;
- }
- else
- {
- MainForm.BackColor = Color.White;
- MainForm.Hide();
- Common.MainFormVisible = false;
- }
- },
- true);
-
- CustomCursor.ShowFakeMouseCursor(int.MinValue, int.MinValue);
- }
-
- internal static void MainFormDot()
- {
- DoSomethingInUIThread(
- () =>
- {
- _ = Common.SendMessageToHelper(0x408, IntPtr.Zero, IntPtr.Zero, false);
-
- MainForm.Left = MachineStuff.PrimaryScreenBounds.Left + ((MachineStuff.PrimaryScreenBounds.Right - MachineStuff.PrimaryScreenBounds.Left) / 2) - 1;
- MainForm.Top = Setting.Values.HideMouse ? 3 : MachineStuff.PrimaryScreenBounds.Top + ((MachineStuff.PrimaryScreenBounds.Bottom - MachineStuff.PrimaryScreenBounds.Top) / 2);
- MainForm.Width = 1;
- MainForm.Height = 1;
- MainForm.Opacity = 0.15;
- MainForm.Hide();
- Common.MainFormVisible = false;
- },
- true);
-
- CustomCursor.ShowFakeMouseCursor(int.MinValue, int.MinValue);
- }
-
- internal static void ToggleIcon()
- {
- try
- {
- if (toggleIconsIndex < TOGGLE_ICONS_SIZE)
- {
- Common.DoSomethingInUIThread(() => Common.MainForm.ChangeIcon(toggleIcons[toggleIconsIndex++]));
- }
- else
- {
- toggleIconsIndex = 0;
- toggleIcons = null;
- }
- }
- catch (Exception e)
- {
- Logger.Log(e);
- }
- }
-
- internal static void RunDDHelper(bool cleanUp = false)
- {
- if (Common.RunOnLogonDesktop || Common.RunOnScrSaverDesktop)
- {
- return;
- }
-
- if (cleanUp)
- {
- try
- {
- Process[] ps = Process.GetProcessesByName(HelperProcessName);
- foreach (Process p in ps)
- {
- p.KillProcess();
- }
- }
- catch (Exception e)
- {
- Logger.Log(e);
- _ = Common.SendMessageToHelper(SharedConst.QUIT_CMD, IntPtr.Zero, IntPtr.Zero);
- }
-
- return;
- }
-
- if (!Common.IsMyDesktopActive())
- {
- return;
- }
-
- if (!Common.IpcChannelCreated)
- {
- Logger.TelemetryLogTrace($"{nameof(Common.IpcChannelCreated)} = {Common.IpcChannelCreated}. {Logger.GetStackTrace(new StackTrace())}", SeverityLevel.Warning);
- return;
- }
-
- if (!MainForm.IsDisposed)
- {
- MainForm.NotifyIcon.Visible = false;
- MainForm.NotifyIcon.Visible = Setting.Values.ShowOriginalUI;
- }
-
- IntPtr h = (IntPtr)NativeMethods.FindWindow(null, Common.HELPER_FORM_TEXT);
-
- if (h.ToInt32() <= 0)
- {
- _ = Common.CreateProcessInInputDesktopSession(
- $"\"{Path.GetDirectoryName(Application.ExecutablePath)}\\{HelperProcessName}.exe\"",
- string.Empty,
- Common.GetInputDesktop(),
- 0);
-
- HasSwitchedMachineSinceLastCopy = true;
-
- // Common.CreateLowIntegrityProcess("\"" + Path.GetDirectoryName(Application.ExecutablePath) + "\\MouseWithoutBordersHelper.exe\"", string.Empty, 0, false, 0);
- var processes = Process.GetProcessesByName(HelperProcessName);
- if (processes?.Length == 0)
- {
- Logger.Log("Unable to start helper process.");
- Common.ShowToolTip("Error starting Mouse Without Borders Helper, clipboard sharing will not work!", 5000, ToolTipIcon.Error);
- }
- else
- {
- Logger.Log("Helper process started.");
- }
- }
- else
- {
- var processes = Process.GetProcessesByName(HelperProcessName);
- if (processes?.Length > 0)
- {
- Logger.Log("Helper process found running.");
- }
- else
- {
- Logger.Log("Invalid helper process found running.");
- Common.ShowToolTip("Error finding Mouse Without Borders Helper, clipboard sharing will not work!", 5000, ToolTipIcon.Error);
- }
- }
- }
-
- internal static int SendMessageToHelper(int msg, IntPtr wparam, IntPtr lparam, bool wait = true, bool log = true)
- {
- int h = NativeMethods.FindWindow(null, Common.HELPER_FORM_TEXT);
- int rv = -1;
-
- if (h > 0)
- {
- rv = wait
- ? (int)NativeMethods.SendMessage((IntPtr)h, msg, wparam, lparam)
- : NativeMethods.PostMessage((IntPtr)h, msg, wparam, lparam) ? 1 : 0;
- }
-
- if (log)
- {
- Logger.LogDebug($"SendMessageToHelper: HelperWindow={h}, Return={rv}, msg={msg}, w={wparam.ToInt32()}, l={lparam.ToInt32()}, Post={!wait}");
- }
-
- return rv;
- }
-
- internal static bool IsWindows8AndUp()
- {
- return (Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor >= 2)
- || Environment.OSVersion.Version.Major > 6;
- }
-
- internal static string GetMiniLog(IEnumerable optionControls)
- {
- string log = string.Empty;
-
- log += "=============================================================================================================================\r\n";
- log += $"{Application.ProductName} version {Application.ProductVersion}\r\n";
-
- log += $"{Setting.Values.Username}/{GetDebugInfo(MyKey)}\r\n";
- log += $"{MachineName}/{MachineID}/{DesMachineID}\r\n";
- log += $"Id: {Setting.Values.DeviceId}\r\n";
- log += $"Matrix: {string.Join(",", MachineStuff.MachineMatrix)}\r\n";
- log += $"McPool: {Setting.Values.MachinePoolString}\r\n";
-
- log += "\r\nOPTIONS:\r\n";
-
- foreach (ControlCollection controlCollection in optionControls)
- {
- foreach (object c in controlCollection)
- {
- if (c is CheckBox checkBox)
- {
- log += $"({(checkBox.Checked ? 1 : 0)}) {checkBox.Text}\r\n";
- continue;
- }
-
- if (c is RadioButton radioButton)
- {
- log += $"({(radioButton.Checked ? 1 : 0)}) {radioButton.Name}.[{radioButton.Text}]\r\n";
- continue;
- }
-
- if (c is ComboBox comboBox)
- {
- log += $"{comboBox.Name} = {comboBox.Text}\r\n";
- continue;
- }
- }
- }
-
- log += "\r\n";
-
- SocketStuff sk = Sk;
-
- if (sk?.TcpSockets != null)
- {
- foreach (TcpSk tcp in sk.TcpSockets)
- {
- log += $"{Common.MachineName}{(tcp.IsClient ? "=>" : "<=")}{tcp.MachineName}({tcp.MachineId}):{tcp.Status}\r\n";
- }
- }
-
- log += string.Format(CultureInfo.CurrentCulture, "Helper:{0}\r\n", SendMessageToHelper(0x400, IntPtr.Zero, IntPtr.Zero));
-
- log += Setting.Values.LastPersonalizeLogonScr + "\r\n";
- log += "Name2IP =\r\n" + Setting.Values.Name2IP + "\r\n";
-
- log += "Last 10 trace messages:\r\n";
-
- log += string.Join(Environment.NewLine, Logger.LogCounter.Select(item => $"({item.Value}): {item.Key}").Take(10));
-
- log += "\r\n=============================================================================================================================";
-
- return log;
- }
-
- internal static bool GetUserName()
- {
- if (string.IsNullOrEmpty(Setting.Values.Username) && !Common.RunOnLogonDesktop)
- {
- if (Program.User.Contains("system", StringComparison.CurrentCultureIgnoreCase))
- {
- _ = Common.ImpersonateLoggedOnUserAndDoSomething(() =>
- {
- // See: https://stackoverflow.com/questions/19487541/how-to-get-windows-user-name-from-sessionid
- static string GetUsernameBySessionId(int sessionId)
- {
- string username = "SYSTEM";
- if (NativeMethods.WTSQuerySessionInformation(IntPtr.Zero, sessionId, NativeMethods.WTSInfoClass.WTSUserName, out nint buffer, out int strLen) && strLen > 1)
- {
- username = Marshal.PtrToStringAnsi(buffer);
- NativeMethods.WTSFreeMemory(buffer);
-
- if (NativeMethods.WTSQuerySessionInformation(IntPtr.Zero, sessionId, NativeMethods.WTSInfoClass.WTSDomainName, out buffer, out strLen) && strLen > 1)
- {
- username = @$"{Marshal.PtrToStringAnsi(buffer)}\{username}";
- NativeMethods.WTSFreeMemory(buffer);
- }
- }
-
- return username;
- }
-
- // The most direct way to fetch the username is WindowsIdentity.GetCurrent(true).Name
- // but GetUserName can run within an ExecutionContext.SuppressFlow block, which creates issues
- // with WindowsIdentity.GetCurrent.
- // See: https://stackoverflow.com/questions/76998988/exception-when-using-executioncontext-suppressflow-in-net-7
- // So we use WTSQuerySessionInformation as a workaround.
- Setting.Values.Username = GetUsernameBySessionId(Process.GetCurrentProcess().SessionId);
- });
- }
- else
- {
- Setting.Values.Username = Program.User;
- }
-
- Logger.LogDebug("[Username] = " + Setting.Values.Username);
- }
-
- return !string.IsNullOrEmpty(Setting.Values.Username);
- }
-
- internal static void ShowOneWayModeMessage()
- {
- ToggleShowTopMostMessage(
- @"
-Due to Security Controls, a remote device cannot control a SAW device.
-Please use the keyboard and Mouse from the SAW device.
-(Press Esc to hide this message)
-",
- string.Empty,
- 10);
- }
-
- internal static void ApplyCADSetting()
- {
- try
- {
- if (Setting.Values.DisableCAD)
- {
- RegistryKey k = Registry.LocalMachine.CreateSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System");
- if (k != null)
- {
- k.SetValue("DisableCAD", 1, RegistryValueKind.DWord);
- k.Close();
- }
- }
- else
- {
- RegistryKey k = Registry.LocalMachine.CreateSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System");
- if (k != null)
- {
- k.SetValue("DisableCAD", 0, RegistryValueKind.DWord);
- k.Close();
- }
- }
- }
- catch (Exception e)
- {
- Logger.Log(e);
- }
- }
- }
-}
diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.InitAndCleanup.cs b/src/modules/MouseWithoutBorders/App/Class/Common.InitAndCleanup.cs
index 0b2b651060bb..44861926e9c9 100644
--- a/src/modules/MouseWithoutBorders/App/Class/Common.InitAndCleanup.cs
+++ b/src/modules/MouseWithoutBorders/App/Class/Common.InitAndCleanup.cs
@@ -93,7 +93,7 @@ internal static void SetupMachineNameAndID()
internal static void Init()
{
- _ = Common.GetUserName();
+ _ = Helper.GetUserName();
Common.GeneratedKey = true;
try
@@ -148,7 +148,7 @@ internal static void Init()
private static void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e)
{
- Common.WndProcCounter++;
+ Helper.WndProcCounter++;
if (e.Mode is PowerModes.Resume or PowerModes.Suspend)
{
@@ -167,21 +167,21 @@ private static void CreateHelperThreads()
watchDogThread.Start();
*/
- helper = new Thread(new ThreadStart(HelperThread), "Helper Thread");
+ helper = new Thread(new ThreadStart(Helper.HelperThread), "Helper Thread");
helper.SetApartmentState(ApartmentState.STA);
helper.Start();
}
private static void AskHelperThreadsToExit(int waitTime)
{
- signalHelperToExit = true;
- signalWatchDogToExit = true;
+ Helper.signalHelperToExit = true;
+ Helper.signalWatchDogToExit = true;
_ = EvSwitch.Set();
int c = 0;
if (helper != null && c < waitTime)
{
- while (signalHelperToExit)
+ while (Helper.signalHelperToExit)
{
Thread.Sleep(1);
}
@@ -251,7 +251,7 @@ internal static void ReleaseAllKeys()
private static void NetworkChange_NetworkAvailabilityChanged(object sender, NetworkAvailabilityEventArgs e)
{
Logger.LogDebug("NetworkAvailabilityEventArgs.IsAvailable: " + e.IsAvailable.ToString(CultureInfo.InvariantCulture));
- Common.WndProcCounter++;
+ Helper.WndProcCounter++;
ScheduleReopenSocketsDueToNetworkChanges(!e.IsAvailable);
}
diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.Launch.cs b/src/modules/MouseWithoutBorders/App/Class/Common.Launch.cs
deleted file mode 100644
index 76b811b8f8ef..000000000000
--- a/src/modules/MouseWithoutBorders/App/Class/Common.Launch.cs
+++ /dev/null
@@ -1,314 +0,0 @@
-// 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.
-
-using System;
-using System.ComponentModel;
-using System.Diagnostics;
-using System.Globalization;
-using System.Runtime.InteropServices;
-using System.Security.Principal;
-
-//
-// Impersonation.
-//
-//
-// 2008 created by Truong Do (ductdo).
-// 2009-... modified by Truong Do (TruongDo).
-// 2023- Included in PowerToys.
-//
-using MouseWithoutBorders.Class;
-using MouseWithoutBorders.Core;
-
-namespace MouseWithoutBorders
-{
- internal partial class Common
- {
- internal static bool RunElevated()
- {
- return WindowsIdentity.GetCurrent().Owner.IsWellKnown(WellKnownSidType.BuiltinAdministratorsSid);
- }
-
- internal static bool ImpersonateLoggedOnUserAndDoSomething(Action targetFunc)
- {
- if (Common.RunWithNoAdminRight)
- {
- targetFunc();
- return true;
- }
- else
- {
- // SuppressFlow fixes an issue on service mode, where WTSQueryUserToken runs successfully once and then fails
- // on subsequent calls. The reason appears to be an unknown issue with reverting the impersonation,
- // meaning that subsequent impersonation attempts run as the logged-on user and fail.
- // This is a workaround.
- using var asyncFlowControl = System.Threading.ExecutionContext.SuppressFlow();
-
- uint dwSessionId;
- IntPtr hUserToken = IntPtr.Zero, hUserTokenDup = IntPtr.Zero;
- try
- {
- dwSessionId = (uint)Process.GetCurrentProcess().SessionId;
- uint rv = NativeMethods.WTSQueryUserToken(dwSessionId, ref hUserToken);
- var lastError = rv == 0 ? Marshal.GetLastWin32Error() : 0;
-
- Logger.LogDebug($"{nameof(NativeMethods.WTSQueryUserToken)} returned {rv.ToString(CultureInfo.CurrentCulture)}");
-
- if (rv == 0)
- {
- Logger.Log($"{nameof(NativeMethods.WTSQueryUserToken)} failed with: {lastError}.");
- return false;
- }
-
- if (!NativeMethods.DuplicateToken(hUserToken, (int)NativeMethods.SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, ref hUserTokenDup))
- {
- Logger.TelemetryLogTrace($"{nameof(NativeMethods.DuplicateToken)} Failed! {Logger.GetStackTrace(new StackTrace())}", SeverityLevel.Warning);
- _ = NativeMethods.CloseHandle(hUserToken);
- _ = NativeMethods.CloseHandle(hUserTokenDup);
- return false;
- }
-
- if (NativeMethods.ImpersonateLoggedOnUser(hUserTokenDup))
- {
- targetFunc();
- _ = NativeMethods.RevertToSelf();
- _ = NativeMethods.CloseHandle(hUserToken);
- _ = NativeMethods.CloseHandle(hUserTokenDup);
- return true;
- }
- else
- {
- Logger.Log("ImpersonateLoggedOnUser Failed!");
- _ = NativeMethods.CloseHandle(hUserToken);
- _ = NativeMethods.CloseHandle(hUserTokenDup);
- return false;
- }
- }
- catch (Exception e)
- {
- Logger.Log(e);
- return false;
- }
- }
- }
-
- internal static int CreateProcessInInputDesktopSession(string commandLine, string arg, string desktop, short wShowWindow, bool lowIntegrity = false)
-
- // As user who runs explorer.exe
- {
- if (!Program.User.Contains("system", StringComparison.InvariantCultureIgnoreCase))
- {
- ProcessStartInfo s = new(commandLine, arg);
- s.WindowStyle = wShowWindow != 0 ? ProcessWindowStyle.Normal : ProcessWindowStyle.Hidden;
- Process p = Process.Start(s);
-
- return p == null ? 0 : p.Id;
- }
-
- string commandLineWithArg = commandLine + " " + arg;
- int lastError;
- int dwSessionId;
- IntPtr hUserToken = IntPtr.Zero, hUserTokenDup = IntPtr.Zero;
-
- Logger.LogDebug("CreateProcessInInputDesktopSession called, launching " + commandLineWithArg + " on " + desktop);
-
- try
- {
- dwSessionId = Process.GetCurrentProcess().SessionId;
-
- // Get the user token used by DuplicateTokenEx
- lastError = (int)NativeMethods.WTSQueryUserToken((uint)dwSessionId, ref hUserToken);
-
- NativeMethods.STARTUPINFO si = default;
- si.cb = Marshal.SizeOf(si);
- si.lpDesktop = "winsta0\\" + desktop;
- si.wShowWindow = wShowWindow;
-
- NativeMethods.SECURITY_ATTRIBUTES sa = default;
- sa.Length = Marshal.SizeOf(sa);
-
- if (!NativeMethods.DuplicateTokenEx(hUserToken, NativeMethods.MAXIMUM_ALLOWED, ref sa, (int)NativeMethods.SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, (int)NativeMethods.TOKEN_TYPE.TokenPrimary, ref hUserTokenDup))
- {
- lastError = Marshal.GetLastWin32Error();
- Logger.Log(string.Format(CultureInfo.CurrentCulture, "DuplicateTokenEx error: {0} Token does not have the privilege.", lastError));
- _ = NativeMethods.CloseHandle(hUserToken);
- return 0;
- }
-
- if (lowIntegrity)
- {
- NativeMethods.TOKEN_MANDATORY_LABEL tIL;
-
- // Low
- string sIntegritySid = "S-1-16-4096";
-
- bool rv = NativeMethods.ConvertStringSidToSid(sIntegritySid, out IntPtr pIntegritySid);
-
- if (!rv)
- {
- Logger.Log("ConvertStringSidToSid failed");
- _ = NativeMethods.CloseHandle(hUserToken);
- _ = NativeMethods.CloseHandle(hUserTokenDup);
- return 0;
- }
-
- tIL.Label.Attributes = NativeMethods.SE_GROUP_INTEGRITY;
- tIL.Label.Sid = pIntegritySid;
-
- rv = NativeMethods.SetTokenInformation(hUserTokenDup, NativeMethods.TOKEN_INFORMATION_CLASS.TokenIntegrityLevel, ref tIL, (uint)Marshal.SizeOf(tIL) + (uint)IntPtr.Size);
-
- if (!rv)
- {
- Logger.Log("SetTokenInformation failed");
- _ = NativeMethods.CloseHandle(hUserToken);
- _ = NativeMethods.CloseHandle(hUserTokenDup);
- return 0;
- }
- }
-
- uint dwCreationFlags = NativeMethods.NORMAL_PRIORITY_CLASS | NativeMethods.CREATE_NEW_CONSOLE;
- IntPtr pEnv = IntPtr.Zero;
-
- if (NativeMethods.CreateEnvironmentBlock(ref pEnv, hUserTokenDup, true))
- {
- dwCreationFlags |= NativeMethods.CREATE_UNICODE_ENVIRONMENT;
- }
- else
- {
- pEnv = IntPtr.Zero;
- }
-
- _ = NativeMethods.CreateProcessAsUser(
- hUserTokenDup, // client's access token
- null, // file to execute
- commandLineWithArg, // command line
- ref sa, // pointer to process SECURITY_ATTRIBUTES
- ref sa, // pointer to thread SECURITY_ATTRIBUTES
- false, // handles are not inheritable
- (int)dwCreationFlags, // creation flags
- pEnv, // pointer to new environment block
- null, // name of current directory
- ref si, // pointer to STARTUPINFO structure
- out NativeMethods.PROCESS_INFORMATION pi); // receives information about new process
-
- // GetLastError should be 0
- int iResultOfCreateProcessAsUser = Marshal.GetLastWin32Error();
- Logger.LogDebug("CreateProcessAsUser returned " + iResultOfCreateProcessAsUser.ToString(CultureInfo.CurrentCulture));
-
- // Close handles task
- _ = NativeMethods.CloseHandle(hUserToken);
- _ = NativeMethods.CloseHandle(hUserTokenDup);
-
- return (iResultOfCreateProcessAsUser == 0) ? (int)pi.dwProcessId : 0;
- }
- catch (Exception e)
- {
- Logger.Log(e);
- return 0;
- }
- }
-
-#if CUSTOMIZE_LOGON_SCREEN
- internal static bool CreateLowIntegrityProcess(string commandLine, string args, int wait, bool killIfTimedOut, long limitedMem, short wShowWindow = 0)
- {
- int processId = CreateProcessInInputDesktopSession(commandLine, args, "default", wShowWindow, true);
-
- if (processId <= 0)
- {
- return false;
- }
-
- if (wait > 0)
- {
- if (limitedMem > 0)
- {
- int sec = 0;
- while (true)
- {
- Process p;
-
- try
- {
- if ((p = Process.GetProcessById(processId)) == null)
- {
- Logger.Log("Process exited!");
- break;
- }
- }
- catch (ArgumentException)
- {
- Logger.Log("GetProcessById.ArgumentException");
- break;
- }
-
- if ((!p.HasExited && p.PrivateMemorySize64 > limitedMem) || (++sec > (wait / 1000)))
- {
- Logger.Log(string.Format(CultureInfo.CurrentCulture, "Process log (mem): {0}, {1}", sec, p.PrivateMemorySize64));
- return false;
- }
-
- Thread.Sleep(1000);
- }
- }
- else
- {
- Process p;
-
- if ((p = Process.GetProcessById(processId)) == null)
- {
- Logger.Log("Process exited!");
- }
- else if (NativeMethods.WaitForSingleObject(p.Handle, wait) != NativeMethods.WAIT_OBJECT_0 && killIfTimedOut)
- {
- Logger.Log("Process log (time).");
- TerminateProcessTree(p.Handle, (uint)processId, -1);
- return false;
- }
- }
- }
-
- return true;
- }
-
- internal static void TerminateProcessTree(IntPtr hProcess, uint processID, int exitCode)
- {
- if (processID > 0 && hProcess.ToInt32() > 0)
- {
- Process[] processes = Process.GetProcesses();
- int dwSessionId = Process.GetCurrentProcess().SessionId;
-
- foreach (Process p in processes)
- {
- if (p.SessionId == dwSessionId)
- {
- NativeMethods.PROCESS_BASIC_INFORMATION processBasicInformation = default;
-
- try
- {
- if (NativeMethods.NtQueryInformationProcess(p.Handle, 0, ref processBasicInformation, (uint)Marshal.SizeOf(processBasicInformation), out uint bytesWritten) >= 0)
- {// NT_SUCCESS(...)
- if (processBasicInformation.InheritedFromUniqueProcessId == processID)
- {
- TerminateProcessTree(p.Handle, processBasicInformation.UniqueProcessId, exitCode);
- }
- }
- }
- catch (InvalidOperationException e)
- {
- Logger.Log(e);
- continue;
- }
- catch (Win32Exception e)
- {
- Logger.Log(e);
- continue;
- }
- }
- }
-
- _ = NativeMethods.TerminateProcess(hProcess, (IntPtr)exitCode);
- }
- }
-#endif
- }
-}
diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.Service.cs b/src/modules/MouseWithoutBorders/App/Class/Common.Service.cs
deleted file mode 100644
index a5a71baf5cc8..000000000000
--- a/src/modules/MouseWithoutBorders/App/Class/Common.Service.cs
+++ /dev/null
@@ -1,161 +0,0 @@
-// 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.
-
-using System;
-using System.ComponentModel;
-using System.Diagnostics;
-using System.Diagnostics.CodeAnalysis;
-using System.Globalization;
-using System.Linq;
-using System.ServiceProcess;
-using System.Threading.Tasks;
-using System.Windows.Forms;
-
-//
-// Service control code.
-//
-//
-// 2008 created by Truong Do (ductdo).
-// 2009-... modified by Truong Do (TruongDo).
-// 2023- Included in PowerToys.
-//
-using MouseWithoutBorders.Class;
-using MouseWithoutBorders.Core;
-
-[module: SuppressMessage("Microsoft.Globalization", "CA1300:SpecifyMessageBoxOptions", Scope = "member", Target = "MouseWithoutBorders.Common.#StartMouseWithoutBordersService()", Justification = "Dotnet port with style preservation")]
-
-namespace MouseWithoutBorders
-{
- internal partial class Common
- {
- private static bool shownErrMessage;
- private static DateTime lastStartServiceTime = DateTime.UtcNow;
-
- internal static void StartMouseWithoutBordersService(string desktopToRunMouseWithoutBordersOn = null, string startTag1 = "byapp", string startTag2 = null)
- {
- // NOTE(@yuyoyuppe): the new flow assumes we run both mwb processes directly from the svc.
- if (Common.RunWithNoAdminRight || true)
- {
- return;
- }
-
- Logger.Log($"{nameof(StartMouseWithoutBordersService)}: {Logger.GetStackTrace(new StackTrace())}.");
-
- Task task = Task.Run(() =>
- {
- Process[] ps = Process.GetProcessesByName("MouseWithoutBordersSvc");
-
- if (ps.Length != 0)
- {
- if (DateTime.UtcNow - lastStartServiceTime < TimeSpan.FromSeconds(5))
- {
- Logger.Log($"{nameof(StartMouseWithoutBordersService)}: Aborted.");
- return;
- }
-
- foreach (Process pp in ps)
- {
- Logger.Log(string.Format(CultureInfo.InvariantCulture, "Killing process MouseWithoutBordersSvc {0}.", pp.Id));
- pp.KillProcess();
- }
- }
-
- lastStartServiceTime = DateTime.UtcNow;
- ServiceController service = new("MouseWithoutBordersSvc");
-
- try
- {
- Logger.Log("Starting " + service.ServiceName);
- }
- catch (Exception)
- {
- if (!shownErrMessage)
- {
- shownErrMessage = true;
- _ = MessageBox.Show(
- Application.ProductName + " is not installed yet, please run Setup.exe first!",
- Application.ProductName,
- MessageBoxButtons.OK,
- MessageBoxIcon.Error);
- }
-
- return;
- }
-
- try
- {
- int c = 0;
-
- while (service.Status != ServiceControllerStatus.Stopped && c++ < 5)
- {
- Thread.Sleep(1000);
- service = new ServiceController("MouseWithoutBordersSvc");
- }
-
- if (string.IsNullOrWhiteSpace(desktopToRunMouseWithoutBordersOn))
- {
- startTag2 ??= Process.GetCurrentProcess().SessionId.ToString(CultureInfo.InvariantCulture);
- service.Start(new string[] { startTag1, startTag2 });
- }
- else
- {
- service.Start(new string[] { desktopToRunMouseWithoutBordersOn });
- }
- }
- catch (Exception e)
- {
- Logger.Log(e);
-
- // ERROR_SERVICE_ALREADY_RUNNING
- if (!(shownErrMessage || ((e?.InnerException as Win32Exception)?.NativeErrorCode == 1056)))
- {
- shownErrMessage = true;
- _ = MessageBox.Show(
- "Cannot start service " + service.ServiceName + ": " + e.Message,
- Common.BinaryName,
- MessageBoxButtons.OK,
- MessageBoxIcon.Error);
- }
-
- return;
- }
- });
-
- // Wait for the task while not blocking the UI thread.
- do
- {
- MMSleep(1);
-
- if (task.IsCanceled || task.IsCompleted || task.IsFaulted)
- {
- break;
- }
- }
- while (true);
- }
-
- internal static void StartServiceAndSendLogoffSignal()
- {
- try
- {
- Process[] p = Process.GetProcessesByName("winlogon");
- Process me = Process.GetCurrentProcess();
- string myWinlogon = p?.FirstOrDefault(item => item.SessionId == me.SessionId)?.Id.ToString(CultureInfo.InvariantCulture) ?? null;
-
- if (string.IsNullOrWhiteSpace(myWinlogon))
- {
- StartMouseWithoutBordersService(null, "logoff");
- }
- else
- {
- StartMouseWithoutBordersService(null, "logoff", myWinlogon);
- }
- }
- catch (Exception e)
- {
- Logger.Log($"{nameof(StartServiceAndSendLogoffSignal)}: {e.Message}");
- }
- }
- }
-}
diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.WinAPI.cs b/src/modules/MouseWithoutBorders/App/Class/Common.WinAPI.cs
index f1190a7cc7b5..ed5610193073 100644
--- a/src/modules/MouseWithoutBorders/App/Class/Common.WinAPI.cs
+++ b/src/modules/MouseWithoutBorders/App/Class/Common.WinAPI.cs
@@ -269,7 +269,7 @@ internal static void StartMMService(string desktopToRunMouseWithoutBordersOn)
if (!Common.RunWithNoAdminRight)
{
Logger.LogDebug("*** Starting on active Desktop: " + desktopToRunMouseWithoutBordersOn);
- StartMouseWithoutBordersService(desktopToRunMouseWithoutBordersOn);
+ Service.StartMouseWithoutBordersService(desktopToRunMouseWithoutBordersOn);
}
}
@@ -279,7 +279,7 @@ internal static void CheckForDesktopSwitchEvent(bool cleanupIfExit)
{
if (!IsMyDesktopActive() || Common.CurrentProcess.SessionId != NativeMethods.WTSGetActiveConsoleSessionId())
{
- Common.RunDDHelper(true);
+ Helper.RunDDHelper(true);
int waitCount = 20;
while (NativeMethods.WTSGetActiveConsoleSessionId() == 0xFFFFFFFF && waitCount > 0)
diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.cs b/src/modules/MouseWithoutBorders/App/Class/Common.cs
index 40699b355b65..8d4ff7f326c3 100644
--- a/src/modules/MouseWithoutBorders/App/Class/Common.cs
+++ b/src/modules/MouseWithoutBorders/App/Class/Common.cs
@@ -101,8 +101,10 @@ internal Common()
private static bool runOnLogonDesktop;
private static bool runOnScrSaverDesktop;
- private static int[] toggleIcons;
- private static int toggleIconsIndex;
+#pragma warning disable SA1307 // Accessible fields should begin with upper-case letter
+ internal static int[] toggleIcons;
+ internal static int toggleIconsIndex;
+#pragma warning restore SA1307
internal const int TOGGLE_ICONS_SIZE = 4;
internal const int ICON_ONE = 0;
internal const int ICON_ALL = 1;
@@ -114,7 +116,9 @@ internal Common()
internal const int NETWORK_STREAM_BUF_SIZE = 1024 * 1024;
internal static readonly EventWaitHandle EvSwitch = new(false, EventResetMode.AutoReset);
private static Point lastPos;
- private static int switchCount;
+#pragma warning disable SA1307 // Accessible fields should begin with upper-case names
+ internal static int switchCount;
+#pragma warning restore SA1307
private static long lastReconnectByHotKeyTime;
private static int tcpPort;
private static bool secondOpenSocketTry;
@@ -543,7 +547,7 @@ internal static void SendNextMachine(ID hostMachine, ID nextMachine, Point reque
internal static void SendAwakeBeat()
{
if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop && Common.IsMyDesktopActive() &&
- Setting.Values.BlockScreenSaver && lastRealInputEventCount != Common.RealInputEventCount)
+ Setting.Values.BlockScreenSaver && lastRealInputEventCount != Event.RealInputEventCount)
{
SendPackage(ID.ALL, PackageType.Awake);
}
@@ -552,13 +556,13 @@ internal static void SendAwakeBeat()
SendHeartBeat();
}
- lastInputEventCount = Common.InputEventCount;
- lastRealInputEventCount = Common.RealInputEventCount;
+ lastInputEventCount = Event.InputEventCount;
+ lastRealInputEventCount = Event.RealInputEventCount;
}
internal static void HumanBeingDetected()
{
- if (lastInputEventCount == Common.InputEventCount)
+ if (lastInputEventCount == Event.InputEventCount)
{
if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop && Common.IsMyDesktopActive())
{
@@ -566,7 +570,7 @@ internal static void HumanBeingDetected()
}
}
- lastInputEventCount = Common.InputEventCount;
+ lastInputEventCount = Event.InputEventCount;
}
private static void PokeMyself()
@@ -581,7 +585,7 @@ private static void PokeMyself()
InputSimulation.MoveMouseRelative(-x, -y);
Thread.Sleep(50);
- if (lastInputEventCount != Common.InputEventCount)
+ if (lastInputEventCount != Event.InputEventCount)
{
break;
}
@@ -590,8 +594,8 @@ private static void PokeMyself()
internal static void InitLastInputEventCount()
{
- lastInputEventCount = Common.InputEventCount;
- lastRealInputEventCount = Common.RealInputEventCount;
+ lastInputEventCount = Event.InputEventCount;
+ lastRealInputEventCount = Event.RealInputEventCount;
}
internal static void SendHello()
@@ -665,7 +669,7 @@ internal static void PrepareScreenCapture()
{
Common.DoSomethingInUIThread(() =>
{
- if (!DragDrop.MouseDown && Common.SendMessageToHelper(0x401, IntPtr.Zero, IntPtr.Zero) > 0)
+ if (!DragDrop.MouseDown && Helper.SendMessageToHelper(0x401, IntPtr.Zero, IntPtr.Zero) > 0)
{
Common.MMSleep(0.2);
InputSimulation.SendKey(new KEYBDDATA() { wVk = (int)VK.SNAPSHOT });
@@ -674,14 +678,14 @@ internal static void PrepareScreenCapture()
Logger.LogDebug("PrepareScreenCapture: SNAPSHOT simulated.");
_ = NativeMethods.MoveWindow(
- (IntPtr)NativeMethods.FindWindow(null, Common.HELPER_FORM_TEXT),
+ (IntPtr)NativeMethods.FindWindow(null, Helper.HELPER_FORM_TEXT),
MachineStuff.DesktopBounds.Left,
MachineStuff.DesktopBounds.Top,
MachineStuff.DesktopBounds.Right - MachineStuff.DesktopBounds.Left,
MachineStuff.DesktopBounds.Bottom - MachineStuff.DesktopBounds.Top,
false);
- _ = Common.SendMessageToHelper(0x406, IntPtr.Zero, IntPtr.Zero, false);
+ _ = Helper.SendMessageToHelper(0x406, IntPtr.Zero, IntPtr.Zero, false);
}
else
{
@@ -698,7 +702,7 @@ internal static void OpenImage(string file)
// {
// Process.Start("explorer", "\"" + file + "\"");
// });
- _ = CreateProcessInInputDesktopSession(
+ _ = Launch.CreateProcessInInputDesktopSession(
"\"" + Environment.ExpandEnvironmentVariables(@"%SystemRoot%\System32\Mspaint.exe") +
"\"",
"\"" + file + "\"",
@@ -956,8 +960,8 @@ internal static void SkSend(DATA data, uint? exceptDes, bool includeHandShakingS
{
// SwitchToMachine(MachineName.Trim());
MachineStuff.NewDesMachineID = DesMachineID = MachineID;
- MachineStuff.SwitchLocation.X = XY_BY_PIXEL + myLastX;
- MachineStuff.SwitchLocation.Y = XY_BY_PIXEL + myLastY;
+ MachineStuff.SwitchLocation.X = Event.XY_BY_PIXEL + Event.myLastX;
+ MachineStuff.SwitchLocation.Y = Event.XY_BY_PIXEL + Event.myLastY;
MachineStuff.SwitchLocation.ResetCount();
EvSwitch.Set();
}
@@ -1314,7 +1318,7 @@ private static string GetMyStorageDir()
}
else
{
- _ = ImpersonateLoggedOnUserAndDoSomething(() =>
+ _ = Launch.ImpersonateLoggedOnUserAndDoSomething(() =>
{
st = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + @"\" + Common.BinaryName;
if (!Directory.Exists(st))
diff --git a/src/modules/MouseWithoutBorders/App/Class/InputHook.cs b/src/modules/MouseWithoutBorders/App/Class/InputHook.cs
index 9bd7b5c4bfe9..33cbe77e890a 100644
--- a/src/modules/MouseWithoutBorders/App/Class/InputHook.cs
+++ b/src/modules/MouseWithoutBorders/App/Class/InputHook.cs
@@ -206,7 +206,7 @@ private int MouseHookProc(int nCode, int wParam, IntPtr lParam)
{
int rv = 1, dx = 0, dy = 0;
bool local = false;
- Common.InputEventCount++;
+ Event.InputEventCount++;
try
{
@@ -220,14 +220,14 @@ private int MouseHookProc(int nCode, int wParam, IntPtr lParam)
}
else
{
- Common.RealInputEventCount++;
+ Event.RealInputEventCount++;
if (MachineStuff.NewDesMachineID == Common.MachineID || MachineStuff.NewDesMachineID == ID.ALL)
{
local = true;
if (Common.MainFormVisible && !DragDrop.IsDropping)
{
- Common.MainFormDot();
+ Helper.MainFormDot();
}
}
@@ -269,10 +269,10 @@ private int MouseHookProc(int nCode, int wParam, IntPtr lParam)
{
MachineStuff.SwitchLocation.Count--;
- if (MachineStuff.SwitchLocation.X > Common.XY_BY_PIXEL - 100000 || MachineStuff.SwitchLocation.Y > Common.XY_BY_PIXEL - 100000)
+ if (MachineStuff.SwitchLocation.X > Event.XY_BY_PIXEL - 100000 || MachineStuff.SwitchLocation.Y > Event.XY_BY_PIXEL - 100000)
{
- hookCallbackMouseData.X = MachineStuff.SwitchLocation.X - Common.XY_BY_PIXEL;
- hookCallbackMouseData.Y = MachineStuff.SwitchLocation.Y - Common.XY_BY_PIXEL;
+ hookCallbackMouseData.X = MachineStuff.SwitchLocation.X - Event.XY_BY_PIXEL;
+ hookCallbackMouseData.Y = MachineStuff.SwitchLocation.Y - Event.XY_BY_PIXEL;
}
else
{
@@ -308,8 +308,8 @@ private int MouseHookProc(int nCode, int wParam, IntPtr lParam)
hookCallbackMouseData.Y = MachineStuff.PrimaryScreenBounds.Bottom + 1;
}
- dx += dx < 0 ? -Common.MOVE_MOUSE_RELATIVE : Common.MOVE_MOUSE_RELATIVE;
- dy += dy < 0 ? -Common.MOVE_MOUSE_RELATIVE : Common.MOVE_MOUSE_RELATIVE;
+ dx += dx < 0 ? -Event.MOVE_MOUSE_RELATIVE : Event.MOVE_MOUSE_RELATIVE;
+ dy += dy < 0 ? -Event.MOVE_MOUSE_RELATIVE : Event.MOVE_MOUSE_RELATIVE;
}
}
@@ -336,13 +336,13 @@ private int MouseHookProc(int nCode, int wParam, IntPtr lParam)
private int KeyboardHookProc(int nCode, int wParam, IntPtr lParam)
{
- Common.InputEventCount++;
+ Event.InputEventCount++;
if (!RealData)
{
return NativeMethods.CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
}
- Common.RealInputEventCount++;
+ Event.RealInputEventCount++;
keyboardHookStruct = LParamToKeyboardHookStruct(lParam);
hookCallbackKeybdData.dwFlags = keyboardHookStruct.Flags;
diff --git a/src/modules/MouseWithoutBorders/App/Class/InputSimulation.cs b/src/modules/MouseWithoutBorders/App/Class/InputSimulation.cs
index 6641655ad43c..a991c7f64f91 100644
--- a/src/modules/MouseWithoutBorders/App/Class/InputSimulation.cs
+++ b/src/modules/MouseWithoutBorders/App/Class/InputSimulation.cs
@@ -223,7 +223,7 @@ internal static uint SendMouse(MOUSEDATA md)
if (Common.MainFormVisible && !DragDrop.IsDropping)
{
- Common.MainFormDot();
+ Helper.MainFormDot();
}
return rv;
diff --git a/src/modules/MouseWithoutBorders/App/Class/Program.cs b/src/modules/MouseWithoutBorders/App/Class/Program.cs
index 203f5f277dd1..2fd8357e2490 100644
--- a/src/modules/MouseWithoutBorders/App/Class/Program.cs
+++ b/src/modules/MouseWithoutBorders/App/Class/Program.cs
@@ -36,6 +36,7 @@
using StreamJsonRpc;
using Logger = MouseWithoutBorders.Core.Logger;
+using SettingsHelper = Microsoft.PowerToys.Settings.UI.Library.Utilities.Helper;
using Thread = MouseWithoutBorders.Core.Thread;
[module: SuppressMessage("Microsoft.MSInternal", "CA904:DeclareTypesInMicrosoftOrSystemNamespace", Scope = "namespace", Target = "MouseWithoutBorders", Justification = "Dotnet port with style preservation")]
@@ -128,7 +129,7 @@ private static void Main()
{
if (args.Length > 2)
{
- Helper.UserLocalAppDataPath = args[2].Trim();
+ SettingsHelper.UserLocalAppDataPath = args[2].Trim();
}
}
@@ -235,7 +236,7 @@ private static void Main()
Application.SetCompatibleTextRenderingDefault(false);
Common.Init();
- Common.WndProcCounter++;
+ Core.Helper.WndProcCounter++;
var formScreen = new FrmScreen();
@@ -430,7 +431,7 @@ internal static void StartService()
Logger.Log(e);
}
- Common.StartMouseWithoutBordersService();
+ Service.StartMouseWithoutBordersService();
}
internal static string User { get; set; }
diff --git a/src/modules/MouseWithoutBorders/App/Class/Setting.cs b/src/modules/MouseWithoutBorders/App/Class/Setting.cs
index 31d9a50049ad..72365fe4787b 100644
--- a/src/modules/MouseWithoutBorders/App/Class/Setting.cs
+++ b/src/modules/MouseWithoutBorders/App/Class/Setting.cs
@@ -33,6 +33,7 @@
using Settings.UI.Library.Attributes;
using Lock = System.Threading.Lock;
+using SettingsHelper = Microsoft.PowerToys.Settings.UI.Library.Utilities.Helper;
[module: SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Scope = "member", Target = "MouseWithoutBorders.Properties.Setting.Values.#LoadIntSetting(System.String,System.Int32)", Justification = "Dotnet port with style preservation")]
[module: SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Scope = "member", Target = "MouseWithoutBorders.Properties.Setting.Values.#SaveSetting(System.String,System.Object)", Justification = "Dotnet port with style preservation")]
@@ -193,7 +194,7 @@ internal Settings()
{
_settingsUtils = new SettingsUtils();
- _watcher = Helper.GetFileWatcher("MouseWithoutBorders", "settings.json", () =>
+ _watcher = SettingsHelper.GetFileWatcher("MouseWithoutBorders", "settings.json", () =>
{
try
{
diff --git a/src/modules/MouseWithoutBorders/App/Class/SocketStuff.cs b/src/modules/MouseWithoutBorders/App/Class/SocketStuff.cs
index 3f848edf769c..8796f61dfb92 100644
--- a/src/modules/MouseWithoutBorders/App/Class/SocketStuff.cs
+++ b/src/modules/MouseWithoutBorders/App/Class/SocketStuff.cs
@@ -1684,7 +1684,7 @@ internal static void SendClipboardData(Socket s, Stream ecStream)
{
string fileName = null;
- if (!Common.ImpersonateLoggedOnUserAndDoSomething(() =>
+ if (!Launch.ImpersonateLoggedOnUserAndDoSomething(() =>
{
if (!File.Exists(Common.LastDragDropFile))
{
@@ -1873,7 +1873,7 @@ private static bool SendFile(Socket s, Stream ecStream, string fileName)
}
else
{
- _ = Common.ImpersonateLoggedOnUserAndDoSomething(() => { r = SendFileEx(s, ecStream, fileName); });
+ _ = Launch.ImpersonateLoggedOnUserAndDoSomething(() => { r = SendFileEx(s, ecStream, fileName); });
}
return r;
@@ -2111,7 +2111,7 @@ private void PreventDoS(List sockets)
}
}
- _ = Common.CreateLowIntegrityProcess(
+ _ = Launch.CreateLowIntegrityProcess(
"\"" + Path.GetDirectoryName(Application.ExecutablePath) + "\\MouseWithoutBordersHelper.exe\"",
"InternalError" + " \"" + msg + "\"",
0,
diff --git a/src/modules/MouseWithoutBorders/App/Core/DragDrop.cs b/src/modules/MouseWithoutBorders/App/Core/DragDrop.cs
index bf52717dfb62..7fb32b50fba5 100644
--- a/src/modules/MouseWithoutBorders/App/Core/DragDrop.cs
+++ b/src/modules/MouseWithoutBorders/App/Core/DragDrop.cs
@@ -132,7 +132,7 @@ internal static void DragDropStep04()
{
if (!IsDropping)
{
- IntPtr h = (IntPtr)NativeMethods.FindWindow(null, Common.HELPER_FORM_TEXT);
+ IntPtr h = (IntPtr)NativeMethods.FindWindow(null, Helper.HELPER_FORM_TEXT);
if (h.ToInt32() > 0)
{
_ = Interlocked.Exchange(ref dragDropStep05ExCalledByIpc, 0);
@@ -189,7 +189,7 @@ internal static void DragDropStep05Ex(string dragFileName)
if (!IsDropping)
{
- _ = Common.ImpersonateLoggedOnUserAndDoSomething(() =>
+ _ = Launch.ImpersonateLoggedOnUserAndDoSomething(() =>
{
if (!string.IsNullOrEmpty(dragFileName) && (File.Exists(dragFileName) || Directory.Exists(dragFileName)))
{
diff --git a/src/modules/MouseWithoutBorders/App/Core/Event.cs b/src/modules/MouseWithoutBorders/App/Core/Event.cs
new file mode 100644
index 000000000000..7856a64d87f6
--- /dev/null
+++ b/src/modules/MouseWithoutBorders/App/Core/Event.cs
@@ -0,0 +1,274 @@
+// 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.
+
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Drawing;
+using System.Globalization;
+using System.Threading;
+using System.Threading.Tasks;
+
+using MouseWithoutBorders.Class;
+
+//
+// Keyboard/Mouse hook callback implementation.
+//
+//
+// 2008 created by Truong Do (ductdo).
+// 2009-... modified by Truong Do (TruongDo).
+// 2023- Included in PowerToys.
+//
+namespace MouseWithoutBorders.Core;
+
+internal static class Event
+{
+ private static readonly DATA KeybdPackage = new();
+ private static readonly DATA MousePackage = new();
+#pragma warning disable SA1307 // Accessible fields should begin with upper-case names
+ internal static ulong inputEventCount;
+ internal static ulong invalidPackageCount;
+#pragma warning restore SA1307
+ internal static int MOVE_MOUSE_RELATIVE = 100000;
+ internal static int XY_BY_PIXEL = 300000;
+
+ static Event()
+ {
+ }
+
+ internal static ulong InvalidPackageCount
+ {
+ get => Event.invalidPackageCount;
+ set => Event.invalidPackageCount = value;
+ }
+
+ internal static ulong InputEventCount
+ {
+ get => Event.inputEventCount;
+ set => Event.inputEventCount = value;
+ }
+
+ internal static ulong RealInputEventCount
+ {
+ get;
+ set;
+ }
+
+ private static Point actualLastPos;
+#pragma warning disable SA1307 // Accessible fields should begin with upper-case names
+ internal static int myLastX;
+ internal static int myLastY;
+#pragma warning restore SA1307
+
+ [SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification = "Dotnet port with style preservation")]
+ internal static void MouseEvent(MOUSEDATA e, int dx, int dy)
+ {
+ try
+ {
+ Common.PaintCount = 0;
+ bool switchByMouseEnabled = IsSwitchingByMouseEnabled();
+
+ if (switchByMouseEnabled && Common.Sk != null && (Common.DesMachineID == Common.MachineID || !Setting.Values.MoveMouseRelatively) && e.dwFlags == Common.WM_MOUSEMOVE)
+ {
+ Point p = MachineStuff.MoveToMyNeighbourIfNeeded(e.X, e.Y, MachineStuff.desMachineID);
+
+ if (!p.IsEmpty)
+ {
+ Common.HasSwitchedMachineSinceLastCopy = true;
+
+ Logger.LogDebug(string.Format(
+ CultureInfo.CurrentCulture,
+ "***** Host Machine: newDesMachineIdEx set = [{0}]. Mouse is now at ({1},{2})",
+ MachineStuff.newDesMachineIdEx,
+ e.X,
+ e.Y));
+
+ myLastX = e.X;
+ myLastY = e.Y;
+
+ PrepareToSwitchToMachine(MachineStuff.newDesMachineIdEx, p);
+ }
+ }
+
+ if (MachineStuff.desMachineID != Common.MachineID && MachineStuff.SwitchLocation.Count <= 0)
+ {
+ MousePackage.Des = MachineStuff.desMachineID;
+ MousePackage.Type = PackageType.Mouse;
+ MousePackage.Md.dwFlags = e.dwFlags;
+ MousePackage.Md.WheelDelta = e.WheelDelta;
+
+ // Relative move
+ if (Setting.Values.MoveMouseRelatively && Math.Abs(dx) >= MOVE_MOUSE_RELATIVE && Math.Abs(dy) >= MOVE_MOUSE_RELATIVE)
+ {
+ MousePackage.Md.X = dx;
+ MousePackage.Md.Y = dy;
+ }
+ else
+ {
+ MousePackage.Md.X = (e.X - MachineStuff.primaryScreenBounds.Left) * 65535 / Common.screenWidth;
+ MousePackage.Md.Y = (e.Y - MachineStuff.primaryScreenBounds.Top) * 65535 / Common.screenHeight;
+ }
+
+ Common.SkSend(MousePackage, null, false);
+
+ if (MousePackage.Md.dwFlags is Common.WM_LBUTTONUP or Common.WM_RBUTTONUP)
+ {
+ Thread.Sleep(10);
+ }
+
+ NativeMethods.GetCursorPos(ref actualLastPos);
+
+ if (actualLastPos != Common.LastPos)
+ {
+ Logger.LogDebug($"Mouse cursor has moved unexpectedly: Expected: {Common.LastPos}, actual: {actualLastPos}.");
+ Common.LastPos = actualLastPos;
+ }
+ }
+
+#if SHOW_ON_WINLOGON_EX
+ if (RunOnLogonDesktop && e.dwFlags == WM_RBUTTONUP &&
+ desMachineID == machineID &&
+ e.x > 2 && e.x < 100 && e.y > 2 && e.y < 20)
+ {
+ DoSomethingInUIThread(delegate()
+ {
+ MainForm.HideMenuWhenRunOnLogonDesktop();
+ MainForm.MainMenu.Hide();
+ MainForm.MainMenu.Show(e.x - 5, e.y - 3);
+ });
+ }
+#endif
+ }
+ catch (Exception ex)
+ {
+ Logger.Log(ex);
+ }
+ }
+
+ internal static bool IsSwitchingByMouseEnabled()
+ {
+ return (EasyMouseOption)Setting.Values.EasyMouse == EasyMouseOption.Enable || InputHook.EasyMouseKeyDown;
+ }
+
+ internal static void PrepareToSwitchToMachine(ID newDesMachineID, Point desMachineXY)
+ {
+ Logger.LogDebug($"PrepareToSwitchToMachine: newDesMachineID = {newDesMachineID}, desMachineXY = {desMachineXY}");
+
+ if (((Common.GetTick() - MachineStuff.lastJump < 100) && (Common.GetTick() - MachineStuff.lastJump > 0)) || MachineStuff.desMachineID == ID.ALL)
+ {
+ Logger.LogDebug("PrepareToSwitchToMachine: lastJump");
+ return;
+ }
+
+ MachineStuff.lastJump = Common.GetTick();
+
+ string newDesMachineName = MachineStuff.NameFromID(newDesMachineID);
+
+ if (!Common.IsConnectedTo(newDesMachineID))
+ {// Connection lost, cancel switching
+ Logger.LogDebug("No active connection found for " + newDesMachineName);
+
+ // ShowToolTip("No active connection found for [" + newDesMachineName + "]!", 500);
+ }
+ else
+ {
+ MachineStuff.newDesMachineID = newDesMachineID;
+ MachineStuff.SwitchLocation.X = desMachineXY.X;
+ MachineStuff.SwitchLocation.Y = desMachineXY.Y;
+ MachineStuff.SwitchLocation.ResetCount();
+ _ = Common.EvSwitch.Set();
+
+ // PostMessage(mainForm.Handle, WM_SWITCH, IntPtr.Zero, IntPtr.Zero);
+ if (newDesMachineID != DragDrop.DragMachine)
+ {
+ if (!DragDrop.IsDragging && !DragDrop.IsDropping)
+ {
+ if (DragDrop.MouseDown && !Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop)
+ {
+ DragDrop.DragDropStep02();
+ }
+ }
+ else if (DragDrop.DragMachine != (ID)1)
+ {
+ DragDrop.ChangeDropMachine();
+ }
+ }
+ else
+ {
+ DragDrop.DragDropStep11();
+ }
+
+ // Change des machine
+ if (MachineStuff.desMachineID != newDesMachineID)
+ {
+ Logger.LogDebug("MouseEvent: Switching to new machine:" + newDesMachineName);
+
+ // Ask current machine to hide the Mouse cursor
+ if (newDesMachineID != ID.ALL && MachineStuff.desMachineID != Common.MachineID)
+ {
+ Common.SendPackage(MachineStuff.desMachineID, PackageType.HideMouse);
+ }
+
+ Common.DesMachineID = newDesMachineID;
+
+ if (MachineStuff.desMachineID == Common.MachineID)
+ {
+ if (Common.GetTick() - Common.clipboardCopiedTime < Common.BIG_CLIPBOARD_DATA_TIMEOUT)
+ {
+ Common.clipboardCopiedTime = 0;
+ Common.GetRemoteClipboard("PrepareToSwitchToMachine");
+ }
+ }
+ else
+ {
+ // Ask the new active machine to get clipboard data (if the data is too big)
+ Common.SendPackage(MachineStuff.desMachineID, PackageType.MachineSwitched);
+ }
+
+ _ = Interlocked.Increment(ref Common.switchCount);
+ }
+ }
+ }
+
+ internal static void SaveSwitchCount()
+ {
+ if (Common.SwitchCount > 0)
+ {
+ _ = Task.Run(() =>
+ {
+ Setting.Values.SwitchCount += Common.SwitchCount;
+ _ = Interlocked.Exchange(ref Common.switchCount, 0);
+ });
+ }
+ }
+
+ internal static void KeybdEvent(KEYBDDATA e)
+ {
+ try
+ {
+ Common.PaintCount = 0;
+ if (MachineStuff.desMachineID != MachineStuff.newDesMachineID)
+ {
+ Logger.LogDebug("KeybdEvent: Switching to new machine...");
+ Common.DesMachineID = MachineStuff.newDesMachineID;
+ }
+
+ if (MachineStuff.desMachineID != Common.MachineID)
+ {
+ KeybdPackage.Des = MachineStuff.desMachineID;
+ KeybdPackage.Type = PackageType.Keyboard;
+ KeybdPackage.Kd = e;
+ KeybdPackage.DateTime = Common.GetTick();
+ Common.SkSend(KeybdPackage, null, false);
+ if (KeybdPackage.Kd.dwFlags is Common.WM_KEYUP or Common.WM_SYSKEYUP)
+ {
+ Thread.Sleep(10);
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ Logger.Log(ex);
+ }
+ }
+}
diff --git a/src/modules/MouseWithoutBorders/App/Core/Helper.cs b/src/modules/MouseWithoutBorders/App/Core/Helper.cs
new file mode 100644
index 000000000000..4122fbe31b48
--- /dev/null
+++ b/src/modules/MouseWithoutBorders/App/Core/Helper.cs
@@ -0,0 +1,526 @@
+// 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.
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Drawing;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Security.Principal;
+using System.Windows.Forms;
+
+using Microsoft.Win32;
+using MouseWithoutBorders.Class;
+using static System.Windows.Forms.Control;
+
+//
+// Some other helper methods.
+//
+//
+// 2008 created by Truong Do (ductdo).
+// 2009-... modified by Truong Do (TruongDo).
+// 2023- Included in PowerToys.
+//
+namespace MouseWithoutBorders.Core;
+
+internal static class Helper
+{
+ internal const string HELPER_FORM_TEXT = "Mouse without Borders Helper";
+ internal const string HelperProcessName = "PowerToys.MouseWithoutBordersHelper";
+#pragma warning disable SA1307 // Accessible fields should begin with upper-case letter
+ internal static bool signalHelperToExit;
+ internal static bool signalWatchDogToExit;
+#pragma warning restore SA1307
+ internal static long WndProcCounter;
+
+ private static void WatchDogThread()
+ {
+ long oldCounter = WndProcCounter;
+
+ do
+ {
+ for (int i = 0; i < 10; i++)
+ {
+ Thread.Sleep(1000);
+
+ if (signalWatchDogToExit)
+ {
+ break;
+ }
+ }
+
+ while (Common.BlockingUI)
+ {
+ Thread.Sleep(1000);
+ }
+
+ if (WndProcCounter == oldCounter)
+ {
+ Process p = Process.GetCurrentProcess();
+ string procInfo = $"{p.PrivateMemorySize64 / 1024 / 1024}MB, {p.TotalProcessorTime}, {Environment.ProcessorCount}.";
+ string threadStacks = $"{procInfo} {Thread.DumpThreadsStack()}";
+ Logger.TelemetryLogTrace(threadStacks, SeverityLevel.Error);
+ break;
+ }
+
+ oldCounter = WndProcCounter;
+ }
+ while (true);
+ }
+
+ internal static void HelperThread()
+ {
+ // 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 = System.Threading.ExecutionContext.SuppressFlow();
+
+ try
+ {
+ while (true)
+ {
+ _ = Common.EvSwitch.WaitOne(); // Switching to another machine?
+
+ if (signalHelperToExit)
+ {
+ break;
+ }
+
+ if (MachineStuff.NewDesMachineID != Common.MachineID && MachineStuff.NewDesMachineID != ID.ALL)
+ {
+ Common.HideMouseCursor(false);
+ Helper.MainFormDotEx(true);
+ }
+ else
+ {
+ if (MachineStuff.SwitchLocation.Count > 0)
+ {
+ MachineStuff.SwitchLocation.Count--;
+
+ // When we want to move mouse by pixels, we add 300k to x and y (search for XY_BY_PIXEL for other related code).
+ Logger.LogDebug($"+++++ Moving mouse to {MachineStuff.SwitchLocation.X}, {MachineStuff.SwitchLocation.Y}");
+
+ // MaxXY = 65535 so 100k is safe.
+ if (MachineStuff.SwitchLocation.X > Event.XY_BY_PIXEL - 100000 || MachineStuff.SwitchLocation.Y > Event.XY_BY_PIXEL - 100000)
+ {
+ InputSimulation.MoveMouse(MachineStuff.SwitchLocation.X - Event.XY_BY_PIXEL, MachineStuff.SwitchLocation.Y - Event.XY_BY_PIXEL);
+ }
+ else
+ {
+ InputSimulation.MoveMouseEx(MachineStuff.SwitchLocation.X, MachineStuff.SwitchLocation.Y);
+ }
+
+ Helper.MainFormDot();
+ }
+ }
+
+ if (MachineStuff.NewDesMachineID == Common.MachineID)
+ {
+ Common.ReleaseAllKeys();
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ Logger.Log(e);
+ }
+
+ signalHelperToExit = false;
+ Logger.LogDebug("^^^Helper Thread exiting...^^^");
+ }
+
+ internal static void MainFormDotEx(bool bCheckTS)
+ {
+ Logger.LogDebug("***** MainFormDotEx:");
+
+ if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop)
+ {
+ int left = MachineStuff.PrimaryScreenBounds.Left + ((MachineStuff.PrimaryScreenBounds.Right - MachineStuff.PrimaryScreenBounds.Left) / 2) - 1;
+ int top = Setting.Values.HideMouse ? 3 : MachineStuff.PrimaryScreenBounds.Top + ((MachineStuff.PrimaryScreenBounds.Bottom - MachineStuff.PrimaryScreenBounds.Top) / 2);
+
+ Common.MainFormVisible = true;
+
+ if (Setting.Values.HideMouse && Setting.Values.StealFocusWhenSwitchingMachine && Helper.SendMessageToHelper(0x407, new IntPtr(left), new IntPtr(top), true) == 0)
+ {
+ try
+ {
+ /* When user just switches to the Logon desktop, user is actually on the "Windows Default Lock Screen" (LockApp).
+ * If a click is sent to this during switch, it actually triggers a desktop switch on the local machine causing a reconnection affecting the machine switch.
+ * We can detect and skip in this case.
+ * */
+ IntPtr foreGroundWindow = NativeMethods.GetForegroundWindow();
+ string foreGroundWindowText = Common.GetText(foreGroundWindow);
+
+ bool mouseClick = true;
+
+ if (foreGroundWindowText.Equals("Windows Default Lock Screen", StringComparison.OrdinalIgnoreCase))
+ {
+ mouseClick = false;
+ }
+
+ // Window title may be localized, check process name:
+ if (mouseClick)
+ {
+ _ = NativeMethods.GetWindowThreadProcessId(foreGroundWindow, out uint pid);
+
+ if (pid > 0)
+ {
+ string foreGroundWindowProcess = Process.GetProcessById((int)pid)?.ProcessName;
+
+ if (foreGroundWindowProcess.Equals("LockApp", StringComparison.OrdinalIgnoreCase))
+ {
+ mouseClick = false;
+ }
+ }
+ }
+
+ if (mouseClick)
+ {
+ InputSimulation.MouseClickDotForm(left + 1, top + 1);
+ }
+ }
+ catch (Exception e)
+ {
+ Logger.Log(e);
+ }
+ }
+ }
+
+ CustomCursor.ShowFakeMouseCursor(int.MinValue, int.MinValue);
+ }
+
+ internal static void MainForm3Pixels()
+ {
+ Logger.LogDebug("***** MainFormDotLarge:");
+
+ Common.DoSomethingInUIThread(
+ () =>
+ {
+ Common.MainForm.Left = MachineStuff.PrimaryScreenBounds.Left + ((MachineStuff.PrimaryScreenBounds.Right - MachineStuff.PrimaryScreenBounds.Left) / 2) - 2;
+ Common.MainForm.Top = Setting.Values.HideMouse ? 3 : MachineStuff.PrimaryScreenBounds.Top + ((MachineStuff.PrimaryScreenBounds.Bottom - MachineStuff.PrimaryScreenBounds.Top) / 2) - 1;
+ Common.MainForm.Width = 3;
+ Common.MainForm.Height = 3;
+ Common.MainForm.Opacity = 0.11D;
+ Common.MainForm.TopMost = true;
+
+ if (Setting.Values.HideMouse)
+ {
+ Common.MainForm.BackColor = Color.Black;
+ Common.MainForm.Show();
+ Common.MainFormVisible = true;
+ }
+ else
+ {
+ Common.MainForm.BackColor = Color.White;
+ Common.MainForm.Hide();
+ Common.MainFormVisible = false;
+ }
+ },
+ true);
+
+ CustomCursor.ShowFakeMouseCursor(int.MinValue, int.MinValue);
+ }
+
+ internal static void MainFormDot()
+ {
+ Common.DoSomethingInUIThread(
+ () =>
+ {
+ _ = Helper.SendMessageToHelper(0x408, IntPtr.Zero, IntPtr.Zero, false);
+
+ Common.MainForm.Left = MachineStuff.PrimaryScreenBounds.Left + ((MachineStuff.PrimaryScreenBounds.Right - MachineStuff.PrimaryScreenBounds.Left) / 2) - 1;
+ Common.MainForm.Top = Setting.Values.HideMouse ? 3 : MachineStuff.PrimaryScreenBounds.Top + ((MachineStuff.PrimaryScreenBounds.Bottom - MachineStuff.PrimaryScreenBounds.Top) / 2);
+ Common.MainForm.Width = 1;
+ Common.MainForm.Height = 1;
+ Common.MainForm.Opacity = 0.15;
+ Common.MainForm.Hide();
+ Common.MainFormVisible = false;
+ },
+ true);
+
+ CustomCursor.ShowFakeMouseCursor(int.MinValue, int.MinValue);
+ }
+
+ internal static void ToggleIcon()
+ {
+ try
+ {
+ if (Common.toggleIconsIndex < Common.TOGGLE_ICONS_SIZE)
+ {
+ Common.DoSomethingInUIThread(() => Common.MainForm.ChangeIcon(Common.toggleIcons[Common.toggleIconsIndex++]));
+ }
+ else
+ {
+ Common.toggleIconsIndex = 0;
+ Common.toggleIcons = null;
+ }
+ }
+ catch (Exception e)
+ {
+ Logger.Log(e);
+ }
+ }
+
+ internal static void RunDDHelper(bool cleanUp = false)
+ {
+ if (Common.RunOnLogonDesktop || Common.RunOnScrSaverDesktop)
+ {
+ return;
+ }
+
+ if (cleanUp)
+ {
+ try
+ {
+ Process[] ps = Process.GetProcessesByName(HelperProcessName);
+ foreach (Process p in ps)
+ {
+ p.KillProcess();
+ }
+ }
+ catch (Exception e)
+ {
+ Logger.Log(e);
+ _ = Helper.SendMessageToHelper(SharedConst.QUIT_CMD, IntPtr.Zero, IntPtr.Zero);
+ }
+
+ return;
+ }
+
+ if (!Common.IsMyDesktopActive())
+ {
+ return;
+ }
+
+ if (!Common.IpcChannelCreated)
+ {
+ Logger.TelemetryLogTrace($"{nameof(Common.IpcChannelCreated)} = {Common.IpcChannelCreated}. {Logger.GetStackTrace(new StackTrace())}", SeverityLevel.Warning);
+ return;
+ }
+
+ if (!Common.MainForm.IsDisposed)
+ {
+ Common.MainForm.NotifyIcon.Visible = false;
+ Common.MainForm.NotifyIcon.Visible = Setting.Values.ShowOriginalUI;
+ }
+
+ IntPtr h = (IntPtr)NativeMethods.FindWindow(null, Helper.HELPER_FORM_TEXT);
+
+ if (h.ToInt32() <= 0)
+ {
+ _ = Launch.CreateProcessInInputDesktopSession(
+ $"\"{Path.GetDirectoryName(Application.ExecutablePath)}\\{HelperProcessName}.exe\"",
+ string.Empty,
+ Common.GetInputDesktop(),
+ 0);
+
+ Common.HasSwitchedMachineSinceLastCopy = true;
+
+ // Common.CreateLowIntegrityProcess("\"" + Path.GetDirectoryName(Application.ExecutablePath) + "\\MouseWithoutBordersHelper.exe\"", string.Empty, 0, false, 0);
+ var processes = Process.GetProcessesByName(HelperProcessName);
+ if (processes?.Length == 0)
+ {
+ Logger.Log("Unable to start helper process.");
+ Common.ShowToolTip("Error starting Mouse Without Borders Helper, clipboard sharing will not work!", 5000, ToolTipIcon.Error);
+ }
+ else
+ {
+ Logger.Log("Helper process started.");
+ }
+ }
+ else
+ {
+ var processes = Process.GetProcessesByName(HelperProcessName);
+ if (processes?.Length > 0)
+ {
+ Logger.Log("Helper process found running.");
+ }
+ else
+ {
+ Logger.Log("Invalid helper process found running.");
+ Common.ShowToolTip("Error finding Mouse Without Borders Helper, clipboard sharing will not work!", 5000, ToolTipIcon.Error);
+ }
+ }
+ }
+
+ internal static int SendMessageToHelper(int msg, IntPtr wparam, IntPtr lparam, bool wait = true, bool log = true)
+ {
+ int h = NativeMethods.FindWindow(null, Helper.HELPER_FORM_TEXT);
+ int rv = -1;
+
+ if (h > 0)
+ {
+ rv = wait
+ ? (int)NativeMethods.SendMessage((IntPtr)h, msg, wparam, lparam)
+ : NativeMethods.PostMessage((IntPtr)h, msg, wparam, lparam) ? 1 : 0;
+ }
+
+ if (log)
+ {
+ Logger.LogDebug($"SendMessageToHelper: HelperWindow={h}, Return={rv}, msg={msg}, w={wparam.ToInt32()}, l={lparam.ToInt32()}, Post={!wait}");
+ }
+
+ return rv;
+ }
+
+ internal static bool IsWindows8AndUp()
+ {
+ return (Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor >= 2)
+ || Environment.OSVersion.Version.Major > 6;
+ }
+
+ internal static string GetMiniLog(IEnumerable optionControls)
+ {
+ string log = string.Empty;
+
+ log += "=============================================================================================================================\r\n";
+ log += $"{Application.ProductName} version {Application.ProductVersion}\r\n";
+
+ log += $"{Setting.Values.Username}/{Common.GetDebugInfo(Common.MyKey)}\r\n";
+ log += $"{Common.MachineName}/{Common.MachineID}/{Common.DesMachineID}\r\n";
+ log += $"Id: {Setting.Values.DeviceId}\r\n";
+ log += $"Matrix: {string.Join(",", MachineStuff.MachineMatrix)}\r\n";
+ log += $"McPool: {Setting.Values.MachinePoolString}\r\n";
+
+ log += "\r\nOPTIONS:\r\n";
+
+ foreach (ControlCollection controlCollection in optionControls)
+ {
+ foreach (object c in controlCollection)
+ {
+ if (c is CheckBox checkBox)
+ {
+ log += $"({(checkBox.Checked ? 1 : 0)}) {checkBox.Text}\r\n";
+ continue;
+ }
+
+ if (c is RadioButton radioButton)
+ {
+ log += $"({(radioButton.Checked ? 1 : 0)}) {radioButton.Name}.[{radioButton.Text}]\r\n";
+ continue;
+ }
+
+ if (c is ComboBox comboBox)
+ {
+ log += $"{comboBox.Name} = {comboBox.Text}\r\n";
+ continue;
+ }
+ }
+ }
+
+ log += "\r\n";
+
+ SocketStuff sk = Common.Sk;
+
+ if (sk?.TcpSockets != null)
+ {
+ foreach (TcpSk tcp in sk.TcpSockets)
+ {
+ log += $"{Common.MachineName}{(tcp.IsClient ? "=>" : "<=")}{tcp.MachineName}({tcp.MachineId}):{tcp.Status}\r\n";
+ }
+ }
+
+ log += string.Format(CultureInfo.CurrentCulture, "Helper:{0}\r\n", SendMessageToHelper(0x400, IntPtr.Zero, IntPtr.Zero));
+
+ log += Setting.Values.LastPersonalizeLogonScr + "\r\n";
+ log += "Name2IP =\r\n" + Setting.Values.Name2IP + "\r\n";
+
+ log += "Last 10 trace messages:\r\n";
+
+ log += string.Join(Environment.NewLine, Logger.LogCounter.Select(item => $"({item.Value}): {item.Key}").Take(10));
+
+ log += "\r\n=============================================================================================================================";
+
+ return log;
+ }
+
+ internal static bool GetUserName()
+ {
+ if (string.IsNullOrEmpty(Setting.Values.Username) && !Common.RunOnLogonDesktop)
+ {
+ if (Program.User.Contains("system", StringComparison.CurrentCultureIgnoreCase))
+ {
+ _ = Launch.ImpersonateLoggedOnUserAndDoSomething(() =>
+ {
+ // See: https://stackoverflow.com/questions/19487541/how-to-get-windows-user-name-from-sessionid
+ static string GetUsernameBySessionId(int sessionId)
+ {
+ string username = "SYSTEM";
+ if (NativeMethods.WTSQuerySessionInformation(IntPtr.Zero, sessionId, NativeMethods.WTSInfoClass.WTSUserName, out nint buffer, out int strLen) && strLen > 1)
+ {
+ username = Marshal.PtrToStringAnsi(buffer);
+ NativeMethods.WTSFreeMemory(buffer);
+
+ if (NativeMethods.WTSQuerySessionInformation(IntPtr.Zero, sessionId, NativeMethods.WTSInfoClass.WTSDomainName, out buffer, out strLen) && strLen > 1)
+ {
+ username = @$"{Marshal.PtrToStringAnsi(buffer)}\{username}";
+ NativeMethods.WTSFreeMemory(buffer);
+ }
+ }
+
+ return username;
+ }
+
+ // The most direct way to fetch the username is WindowsIdentity.GetCurrent(true).Name
+ // but GetUserName can run within an ExecutionContext.SuppressFlow block, which creates issues
+ // with WindowsIdentity.GetCurrent.
+ // See: https://stackoverflow.com/questions/76998988/exception-when-using-executioncontext-suppressflow-in-net-7
+ // So we use WTSQuerySessionInformation as a workaround.
+ Setting.Values.Username = GetUsernameBySessionId(Process.GetCurrentProcess().SessionId);
+ });
+ }
+ else
+ {
+ Setting.Values.Username = Program.User;
+ }
+
+ Logger.LogDebug("[Username] = " + Setting.Values.Username);
+ }
+
+ return !string.IsNullOrEmpty(Setting.Values.Username);
+ }
+
+ internal static void ShowOneWayModeMessage()
+ {
+ Common.ToggleShowTopMostMessage(
+@"
+Due to Security Controls, a remote device cannot control a SAW device.
+Please use the keyboard and Mouse from the SAW device.
+(Press Esc to hide this message)
+",
+string.Empty,
+10);
+ }
+
+ internal static void ApplyCADSetting()
+ {
+ try
+ {
+ if (Setting.Values.DisableCAD)
+ {
+ RegistryKey k = Registry.LocalMachine.CreateSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System");
+ if (k != null)
+ {
+ k.SetValue("DisableCAD", 1, RegistryValueKind.DWord);
+ k.Close();
+ }
+ }
+ else
+ {
+ RegistryKey k = Registry.LocalMachine.CreateSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System");
+ if (k != null)
+ {
+ k.SetValue("DisableCAD", 0, RegistryValueKind.DWord);
+ k.Close();
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ Logger.Log(e);
+ }
+ }
+}
diff --git a/src/modules/MouseWithoutBorders/App/Core/Launch.cs b/src/modules/MouseWithoutBorders/App/Core/Launch.cs
new file mode 100644
index 000000000000..f4d9c62a7a52
--- /dev/null
+++ b/src/modules/MouseWithoutBorders/App/Core/Launch.cs
@@ -0,0 +1,312 @@
+// 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.
+
+using System;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Globalization;
+using System.Runtime.InteropServices;
+using System.Security.Principal;
+
+using MouseWithoutBorders.Class;
+
+//
+// Impersonation.
+//
+//
+// 2008 created by Truong Do (ductdo).
+// 2009-... modified by Truong Do (TruongDo).
+// 2023- Included in PowerToys.
+//
+namespace MouseWithoutBorders.Core;
+
+internal static class Launch
+{
+ private static bool RunElevated()
+ {
+ return WindowsIdentity.GetCurrent().Owner.IsWellKnown(WellKnownSidType.BuiltinAdministratorsSid);
+ }
+
+ internal static bool ImpersonateLoggedOnUserAndDoSomething(Action targetFunc)
+ {
+ if (Common.RunWithNoAdminRight)
+ {
+ targetFunc();
+ return true;
+ }
+ else
+ {
+ // SuppressFlow fixes an issue on service mode, where WTSQueryUserToken runs successfully once and then fails
+ // on subsequent calls. The reason appears to be an unknown issue with reverting the impersonation,
+ // meaning that subsequent impersonation attempts run as the logged-on user and fail.
+ // This is a workaround.
+ using var asyncFlowControl = System.Threading.ExecutionContext.SuppressFlow();
+
+ uint dwSessionId;
+ IntPtr hUserToken = IntPtr.Zero, hUserTokenDup = IntPtr.Zero;
+ try
+ {
+ dwSessionId = (uint)Process.GetCurrentProcess().SessionId;
+ uint rv = NativeMethods.WTSQueryUserToken(dwSessionId, ref hUserToken);
+ var lastError = rv == 0 ? Marshal.GetLastWin32Error() : 0;
+
+ Logger.LogDebug($"{nameof(NativeMethods.WTSQueryUserToken)} returned {rv.ToString(CultureInfo.CurrentCulture)}");
+
+ if (rv == 0)
+ {
+ Logger.Log($"{nameof(NativeMethods.WTSQueryUserToken)} failed with: {lastError}.");
+ return false;
+ }
+
+ if (!NativeMethods.DuplicateToken(hUserToken, (int)NativeMethods.SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, ref hUserTokenDup))
+ {
+ Logger.TelemetryLogTrace($"{nameof(NativeMethods.DuplicateToken)} Failed! {Logger.GetStackTrace(new StackTrace())}", SeverityLevel.Warning);
+ _ = NativeMethods.CloseHandle(hUserToken);
+ _ = NativeMethods.CloseHandle(hUserTokenDup);
+ return false;
+ }
+
+ if (NativeMethods.ImpersonateLoggedOnUser(hUserTokenDup))
+ {
+ targetFunc();
+ _ = NativeMethods.RevertToSelf();
+ _ = NativeMethods.CloseHandle(hUserToken);
+ _ = NativeMethods.CloseHandle(hUserTokenDup);
+ return true;
+ }
+ else
+ {
+ Logger.Log("ImpersonateLoggedOnUser Failed!");
+ _ = NativeMethods.CloseHandle(hUserToken);
+ _ = NativeMethods.CloseHandle(hUserTokenDup);
+ return false;
+ }
+ }
+ catch (Exception e)
+ {
+ Logger.Log(e);
+ return false;
+ }
+ }
+ }
+
+ internal static int CreateProcessInInputDesktopSession(string commandLine, string arg, string desktop, short wShowWindow, bool lowIntegrity = false)
+
+ // As user who runs explorer.exe
+ {
+ if (!Program.User.Contains("system", StringComparison.InvariantCultureIgnoreCase))
+ {
+ ProcessStartInfo s = new(commandLine, arg);
+ s.WindowStyle = wShowWindow != 0 ? ProcessWindowStyle.Normal : ProcessWindowStyle.Hidden;
+ Process p = Process.Start(s);
+
+ return p == null ? 0 : p.Id;
+ }
+
+ string commandLineWithArg = commandLine + " " + arg;
+ int lastError;
+ int dwSessionId;
+ IntPtr hUserToken = IntPtr.Zero, hUserTokenDup = IntPtr.Zero;
+
+ Logger.LogDebug("CreateProcessInInputDesktopSession called, launching " + commandLineWithArg + " on " + desktop);
+
+ try
+ {
+ dwSessionId = Process.GetCurrentProcess().SessionId;
+
+ // Get the user token used by DuplicateTokenEx
+ lastError = (int)NativeMethods.WTSQueryUserToken((uint)dwSessionId, ref hUserToken);
+
+ NativeMethods.STARTUPINFO si = default;
+ si.cb = Marshal.SizeOf(si);
+ si.lpDesktop = "winsta0\\" + desktop;
+ si.wShowWindow = wShowWindow;
+
+ NativeMethods.SECURITY_ATTRIBUTES sa = default;
+ sa.Length = Marshal.SizeOf(sa);
+
+ if (!NativeMethods.DuplicateTokenEx(hUserToken, NativeMethods.MAXIMUM_ALLOWED, ref sa, (int)NativeMethods.SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, (int)NativeMethods.TOKEN_TYPE.TokenPrimary, ref hUserTokenDup))
+ {
+ lastError = Marshal.GetLastWin32Error();
+ Logger.Log(string.Format(CultureInfo.CurrentCulture, "DuplicateTokenEx error: {0} Token does not have the privilege.", lastError));
+ _ = NativeMethods.CloseHandle(hUserToken);
+ return 0;
+ }
+
+ if (lowIntegrity)
+ {
+ NativeMethods.TOKEN_MANDATORY_LABEL tIL;
+
+ // Low
+ string sIntegritySid = "S-1-16-4096";
+
+ bool rv = NativeMethods.ConvertStringSidToSid(sIntegritySid, out IntPtr pIntegritySid);
+
+ if (!rv)
+ {
+ Logger.Log("ConvertStringSidToSid failed");
+ _ = NativeMethods.CloseHandle(hUserToken);
+ _ = NativeMethods.CloseHandle(hUserTokenDup);
+ return 0;
+ }
+
+ tIL.Label.Attributes = NativeMethods.SE_GROUP_INTEGRITY;
+ tIL.Label.Sid = pIntegritySid;
+
+ rv = NativeMethods.SetTokenInformation(hUserTokenDup, NativeMethods.TOKEN_INFORMATION_CLASS.TokenIntegrityLevel, ref tIL, (uint)Marshal.SizeOf(tIL) + (uint)IntPtr.Size);
+
+ if (!rv)
+ {
+ Logger.Log("SetTokenInformation failed");
+ _ = NativeMethods.CloseHandle(hUserToken);
+ _ = NativeMethods.CloseHandle(hUserTokenDup);
+ return 0;
+ }
+ }
+
+ uint dwCreationFlags = NativeMethods.NORMAL_PRIORITY_CLASS | NativeMethods.CREATE_NEW_CONSOLE;
+ IntPtr pEnv = IntPtr.Zero;
+
+ if (NativeMethods.CreateEnvironmentBlock(ref pEnv, hUserTokenDup, true))
+ {
+ dwCreationFlags |= NativeMethods.CREATE_UNICODE_ENVIRONMENT;
+ }
+ else
+ {
+ pEnv = IntPtr.Zero;
+ }
+
+ _ = NativeMethods.CreateProcessAsUser(
+ hUserTokenDup, // client's access token
+ null, // file to execute
+ commandLineWithArg, // command line
+ ref sa, // pointer to process SECURITY_ATTRIBUTES
+ ref sa, // pointer to thread SECURITY_ATTRIBUTES
+ false, // handles are not inheritable
+ (int)dwCreationFlags, // creation flags
+ pEnv, // pointer to new environment block
+ null, // name of current directory
+ ref si, // pointer to STARTUPINFO structure
+ out NativeMethods.PROCESS_INFORMATION pi); // receives information about new process
+
+ // GetLastError should be 0
+ int iResultOfCreateProcessAsUser = Marshal.GetLastWin32Error();
+ Logger.LogDebug("CreateProcessAsUser returned " + iResultOfCreateProcessAsUser.ToString(CultureInfo.CurrentCulture));
+
+ // Close handles task
+ _ = NativeMethods.CloseHandle(hUserToken);
+ _ = NativeMethods.CloseHandle(hUserTokenDup);
+
+ return (iResultOfCreateProcessAsUser == 0) ? (int)pi.dwProcessId : 0;
+ }
+ catch (Exception e)
+ {
+ Logger.Log(e);
+ return 0;
+ }
+ }
+
+#if CUSTOMIZE_LOGON_SCREEN
+ internal static bool CreateLowIntegrityProcess(string commandLine, string args, int wait, bool killIfTimedOut, long limitedMem, short wShowWindow = 0)
+ {
+ int processId = CreateProcessInInputDesktopSession(commandLine, args, "default", wShowWindow, true);
+
+ if (processId <= 0)
+ {
+ return false;
+ }
+
+ if (wait > 0)
+ {
+ if (limitedMem > 0)
+ {
+ int sec = 0;
+ while (true)
+ {
+ Process p;
+
+ try
+ {
+ if ((p = Process.GetProcessById(processId)) == null)
+ {
+ Logger.Log("Process exited!");
+ break;
+ }
+ }
+ catch (ArgumentException)
+ {
+ Logger.Log("GetProcessById.ArgumentException");
+ break;
+ }
+
+ if ((!p.HasExited && p.PrivateMemorySize64 > limitedMem) || (++sec > (wait / 1000)))
+ {
+ Logger.Log(string.Format(CultureInfo.CurrentCulture, "Process log (mem): {0}, {1}", sec, p.PrivateMemorySize64));
+ return false;
+ }
+
+ Thread.Sleep(1000);
+ }
+ }
+ else
+ {
+ Process p;
+
+ if ((p = Process.GetProcessById(processId)) == null)
+ {
+ Logger.Log("Process exited!");
+ }
+ else if (NativeMethods.WaitForSingleObject(p.Handle, wait) != NativeMethods.WAIT_OBJECT_0 && killIfTimedOut)
+ {
+ Logger.Log("Process log (time).");
+ TerminateProcessTree(p.Handle, (uint)processId, -1);
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ private static void TerminateProcessTree(IntPtr hProcess, uint processID, int exitCode)
+ {
+ if (processID > 0 && hProcess.ToInt32() > 0)
+ {
+ Process[] processes = Process.GetProcesses();
+ int dwSessionId = Process.GetCurrentProcess().SessionId;
+
+ foreach (Process p in processes)
+ {
+ if (p.SessionId == dwSessionId)
+ {
+ NativeMethods.PROCESS_BASIC_INFORMATION processBasicInformation = default;
+
+ try
+ {
+ if (NativeMethods.NtQueryInformationProcess(p.Handle, 0, ref processBasicInformation, (uint)Marshal.SizeOf(processBasicInformation), out uint bytesWritten) >= 0)
+ {// NT_SUCCESS(...)
+ if (processBasicInformation.InheritedFromUniqueProcessId == processID)
+ {
+ TerminateProcessTree(p.Handle, processBasicInformation.UniqueProcessId, exitCode);
+ }
+ }
+ }
+ catch (InvalidOperationException e)
+ {
+ Logger.Log(e);
+ continue;
+ }
+ catch (Win32Exception e)
+ {
+ Logger.Log(e);
+ continue;
+ }
+ }
+ }
+
+ _ = NativeMethods.TerminateProcess(hProcess, (IntPtr)exitCode);
+ }
+ }
+#endif
+}
diff --git a/src/modules/MouseWithoutBorders/App/Core/Logger.cs b/src/modules/MouseWithoutBorders/App/Core/Logger.cs
index 520f1671e3e5..fa59d422c930 100644
--- a/src/modules/MouseWithoutBorders/App/Core/Logger.cs
+++ b/src/modules/MouseWithoutBorders/App/Core/Logger.cs
@@ -138,7 +138,7 @@ internal static void LogAll()
Common.PackageSent.ClipboardDragDrop,
Common.PackageSent.ClipboardDragDropEnd,
Common.PackageSent.ExplorerDragDrop,
- Common.inputEventCount,
+ Event.inputEventCount,
Common.PackageSent.Nil);
Log(log);
lastPackageSent = Common.PackageSent; // Copy data
@@ -161,7 +161,7 @@ internal static void LogAll()
Common.PackageReceived.ClipboardDragDrop,
Common.PackageReceived.ClipboardDragDropEnd,
Common.PackageReceived.ExplorerDragDrop,
- Common.invalidPackageCount,
+ Event.invalidPackageCount,
Common.PackageReceived.Nil,
Receiver.processedPackageCount,
Receiver.skippedPackageCount);
@@ -197,15 +197,9 @@ internal static void DumpObjects(int level)
myThreads.Add(t);
}
- _ = Logger.PrivateDump(sb, AllLogs, "[Program logs]\r\n===============\r\n", 0, level, false);
- _ = Logger.PrivateDump(sb, new Common(), "[Other Logs]\r\n===============\r\n", 0, level, false);
- Logger.DumpType(sb, typeof(Logger), 0, level);
- sb.AppendLine("[DragDrop]\r\n===============");
- Logger.DumpType(sb, typeof(DragDrop), 0, level);
- sb.AppendLine("[MachineStuff]\r\n===============");
- Logger.DumpType(sb, typeof(MachineStuff), 0, level);
- sb.AppendLine("[Receiver]\r\n===============");
- Logger.DumpType(sb, typeof(Receiver), 0, level);
+ Logger.DumpProgramLogs(sb, level);
+ Logger.DumpOtherLogs(sb, level);
+ Logger.DumpStaticTypes(sb, level);
log = string.Format(
CultureInfo.CurrentCulture,
@@ -241,6 +235,36 @@ internal static void DumpObjects(int level)
}
}
+ internal static void DumpProgramLogs(StringBuilder sb, int level)
+ {
+ _ = Logger.PrivateDump(sb, AllLogs, "[Program logs]\r\n===============\r\n", 0, level, false);
+ }
+
+ internal static void DumpOtherLogs(StringBuilder sb, int level)
+ {
+ _ = Logger.PrivateDump(sb, new Common(), "[Other Logs]\r\n===============\r\n", 0, level, false);
+ }
+
+ internal static void DumpStaticTypes(StringBuilder sb, int level)
+ {
+ sb.AppendLine($"[{nameof(DragDrop)}]\r\n===============");
+ Logger.DumpType(sb, typeof(DragDrop), 0, level);
+ sb.AppendLine($"[{nameof(Event)}]\r\n===============");
+ Logger.DumpType(sb, typeof(Event), 0, level);
+ sb.AppendLine($"[{nameof(Helper)}]\r\n===============");
+ Logger.DumpType(sb, typeof(Helper), 0, level);
+ sb.AppendLine($"[{nameof(Launch)}]\r\n===============");
+ Logger.DumpType(sb, typeof(Launch), 0, level);
+ sb.AppendLine($"[{nameof(Logger)}]\r\n===============");
+ Logger.DumpType(sb, typeof(Logger), 0, level);
+ sb.AppendLine($"[{nameof(MachineStuff)}]\r\n===============");
+ Logger.DumpType(sb, typeof(MachineStuff), 0, level);
+ sb.AppendLine($"[{nameof(Receiver)}]\r\n===============");
+ Logger.DumpType(sb, typeof(Receiver), 0, level);
+ sb.AppendLine($"[{nameof(Service)}]\r\n===============");
+ Logger.DumpType(sb, typeof(Service), 0, level);
+ }
+
internal static bool PrivateDump(StringBuilder sb, object obj, string objName, int level, int maxLevel, bool stop)
{
Type t;
diff --git a/src/modules/MouseWithoutBorders/App/Core/MachineStuff.cs b/src/modules/MouseWithoutBorders/App/Core/MachineStuff.cs
index b835ce3420d6..144102629f6a 100644
--- a/src/modules/MouseWithoutBorders/App/Core/MachineStuff.cs
+++ b/src/modules/MouseWithoutBorders/App/Core/MachineStuff.cs
@@ -1018,8 +1018,8 @@ internal static void SwitchToMachine(string name)
}
NewDesMachineID = Common.DesMachineID = id;
- SwitchLocation.X = Common.XY_BY_PIXEL + primaryScreenBounds.Left + ((primaryScreenBounds.Right - primaryScreenBounds.Left) / 2);
- SwitchLocation.Y = Common.XY_BY_PIXEL + primaryScreenBounds.Top + ((primaryScreenBounds.Bottom - primaryScreenBounds.Top) / 2);
+ SwitchLocation.X = Event.XY_BY_PIXEL + primaryScreenBounds.Left + ((primaryScreenBounds.Right - primaryScreenBounds.Left) / 2);
+ SwitchLocation.Y = Event.XY_BY_PIXEL + primaryScreenBounds.Top + ((primaryScreenBounds.Bottom - primaryScreenBounds.Top) / 2);
SwitchLocation.ResetCount();
Common.UpdateMultipleModeIconAndMenu();
Common.HideMouseCursor(false);
diff --git a/src/modules/MouseWithoutBorders/App/Core/Receiver.cs b/src/modules/MouseWithoutBorders/App/Core/Receiver.cs
index 787c9a5a9ed6..303bec4ff0e3 100644
--- a/src/modules/MouseWithoutBorders/App/Core/Receiver.cs
+++ b/src/modules/MouseWithoutBorders/App/Core/Receiver.cs
@@ -41,12 +41,12 @@ private static bool PreProcess(DATA package)
{
if (package.Type == PackageType.Invalid)
{
- if ((Common.InvalidPackageCount % 100) == 0)
+ if ((Event.InvalidPackageCount % 100) == 0)
{
Common.ShowToolTip("Invalid packages received!", 1000, ToolTipIcon.Warning, false);
}
- Common.InvalidPackageCount++;
+ Event.InvalidPackageCount++;
Logger.Log("Invalid packages received!");
return false;
}
@@ -104,7 +104,7 @@ internal static void ProcessPackage(DATA package, TcpSk tcp)
{
if ((package.Kd.dwFlags & (int)Common.LLKHF.UP) == (int)Common.LLKHF.UP)
{
- Common.ShowOneWayModeMessage();
+ Helper.ShowOneWayModeMessage();
}
return;
@@ -133,7 +133,7 @@ internal static void ProcessPackage(DATA package, TcpSk tcp)
{
if (package.Md.dwFlags is Common.WM_LBUTTONDOWN or Common.WM_RBUTTONDOWN)
{
- Common.ShowOneWayModeMessage();
+ Helper.ShowOneWayModeMessage();
}
}
else if (package.Md.dwFlags is Common.WM_LBUTTONUP or Common.WM_RBUTTONUP)
@@ -144,13 +144,13 @@ internal static void ProcessPackage(DATA package, TcpSk tcp)
return;
}
- if (Math.Abs(package.Md.X) >= Common.MOVE_MOUSE_RELATIVE && Math.Abs(package.Md.Y) >= Common.MOVE_MOUSE_RELATIVE)
+ if (Math.Abs(package.Md.X) >= Event.MOVE_MOUSE_RELATIVE && Math.Abs(package.Md.Y) >= Event.MOVE_MOUSE_RELATIVE)
{
if (package.Md.dwFlags == Common.WM_MOUSEMOVE)
{
InputSimulation.MoveMouseRelative(
- package.Md.X < 0 ? package.Md.X + Common.MOVE_MOUSE_RELATIVE : package.Md.X - Common.MOVE_MOUSE_RELATIVE,
- package.Md.Y < 0 ? package.Md.Y + Common.MOVE_MOUSE_RELATIVE : package.Md.Y - Common.MOVE_MOUSE_RELATIVE);
+ package.Md.X < 0 ? package.Md.X + Event.MOVE_MOUSE_RELATIVE : package.Md.X - Event.MOVE_MOUSE_RELATIVE,
+ package.Md.Y < 0 ? package.Md.Y + Event.MOVE_MOUSE_RELATIVE : package.Md.Y - Event.MOVE_MOUSE_RELATIVE);
_ = NativeMethods.GetCursorPos(ref lastXY);
Point p = MachineStuff.MoveToMyNeighbourIfNeeded(lastXY.X, lastXY.Y, Common.MachineID);
@@ -195,9 +195,9 @@ internal static void ProcessPackage(DATA package, TcpSk tcp)
case PackageType.NextMachine:
Logger.LogDebug("PackageType.NextMachine received!");
- if (Common.IsSwitchingByMouseEnabled())
+ if (Event.IsSwitchingByMouseEnabled())
{
- Common.PrepareToSwitchToMachine((ID)package.Md.WheelDelta, new Point(package.Md.X, package.Md.Y));
+ Event.PrepareToSwitchToMachine((ID)package.Md.WheelDelta, new Point(package.Md.X, package.Md.Y));
}
break;
@@ -383,7 +383,7 @@ internal static void ProcessPackage(DATA package, TcpSk tcp)
case PackageType.HideMouse:
Common.HasSwitchedMachineSinceLastCopy = true;
Common.HideMouseCursor(true);
- Common.MainFormDotEx(false);
+ Helper.MainFormDotEx(false);
Common.ReleaseAllKeys();
break;
diff --git a/src/modules/MouseWithoutBorders/App/Core/Service.cs b/src/modules/MouseWithoutBorders/App/Core/Service.cs
new file mode 100644
index 000000000000..e8585220c87c
--- /dev/null
+++ b/src/modules/MouseWithoutBorders/App/Core/Service.cs
@@ -0,0 +1,159 @@
+// 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.
+
+using System;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
+using System.Linq;
+using System.ServiceProcess;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+using MouseWithoutBorders.Class;
+
+[module: SuppressMessage("Microsoft.Globalization", "CA1300:SpecifyMessageBoxOptions", Scope = "member", Target = "MouseWithoutBorders.Common.#StartMouseWithoutBordersService()", Justification = "Dotnet port with style preservation")]
+
+//
+// Service control code.
+//
+//
+// 2008 created by Truong Do (ductdo).
+// 2009-... modified by Truong Do (TruongDo).
+// 2023- Included in PowerToys.
+//
+namespace MouseWithoutBorders.Core;
+
+internal static class Service
+{
+ private static bool shownErrMessage;
+ private static DateTime lastStartServiceTime = DateTime.UtcNow;
+
+ internal static void StartMouseWithoutBordersService(string desktopToRunMouseWithoutBordersOn = null, string startTag1 = "byapp", string startTag2 = null)
+ {
+ // NOTE(@yuyoyuppe): the new flow assumes we run both mwb processes directly from the svc.
+ if (Common.RunWithNoAdminRight || true)
+ {
+ return;
+ }
+
+ Logger.Log($"{nameof(StartMouseWithoutBordersService)}: {Logger.GetStackTrace(new StackTrace())}.");
+
+ Task task = Task.Run(() =>
+ {
+ Process[] ps = Process.GetProcessesByName("MouseWithoutBordersSvc");
+
+ if (ps.Length != 0)
+ {
+ if (DateTime.UtcNow - lastStartServiceTime < TimeSpan.FromSeconds(5))
+ {
+ Logger.Log($"{nameof(StartMouseWithoutBordersService)}: Aborted.");
+ return;
+ }
+
+ foreach (Process pp in ps)
+ {
+ Logger.Log(string.Format(CultureInfo.InvariantCulture, "Killing process MouseWithoutBordersSvc {0}.", pp.Id));
+ pp.KillProcess();
+ }
+ }
+
+ lastStartServiceTime = DateTime.UtcNow;
+ ServiceController service = new("MouseWithoutBordersSvc");
+
+ try
+ {
+ Logger.Log("Starting " + service.ServiceName);
+ }
+ catch (Exception)
+ {
+ if (!shownErrMessage)
+ {
+ shownErrMessage = true;
+ _ = MessageBox.Show(
+ Application.ProductName + " is not installed yet, please run Setup.exe first!",
+ Application.ProductName,
+ MessageBoxButtons.OK,
+ MessageBoxIcon.Error);
+ }
+
+ return;
+ }
+
+ try
+ {
+ int c = 0;
+
+ while (service.Status != ServiceControllerStatus.Stopped && c++ < 5)
+ {
+ Thread.Sleep(1000);
+ service = new ServiceController("MouseWithoutBordersSvc");
+ }
+
+ if (string.IsNullOrWhiteSpace(desktopToRunMouseWithoutBordersOn))
+ {
+ startTag2 ??= Process.GetCurrentProcess().SessionId.ToString(CultureInfo.InvariantCulture);
+ service.Start(new string[] { startTag1, startTag2 });
+ }
+ else
+ {
+ service.Start(new string[] { desktopToRunMouseWithoutBordersOn });
+ }
+ }
+ catch (Exception e)
+ {
+ Logger.Log(e);
+
+ // ERROR_SERVICE_ALREADY_RUNNING
+ if (!(shownErrMessage || ((e?.InnerException as Win32Exception)?.NativeErrorCode == 1056)))
+ {
+ shownErrMessage = true;
+ _ = MessageBox.Show(
+ "Cannot start service " + service.ServiceName + ": " + e.Message,
+ Common.BinaryName,
+ MessageBoxButtons.OK,
+ MessageBoxIcon.Error);
+ }
+
+ return;
+ }
+ });
+
+ // Wait for the task while not blocking the UI thread.
+ do
+ {
+ Common.MMSleep(1);
+
+ if (task.IsCanceled || task.IsCompleted || task.IsFaulted)
+ {
+ break;
+ }
+ }
+ while (true);
+ }
+
+ internal static void StartServiceAndSendLogoffSignal()
+ {
+ try
+ {
+ Process[] p = Process.GetProcessesByName("winlogon");
+ Process me = Process.GetCurrentProcess();
+ string myWinlogon = p?.FirstOrDefault(item => item.SessionId == me.SessionId)?.Id.ToString(CultureInfo.InvariantCulture) ?? null;
+
+ if (string.IsNullOrWhiteSpace(myWinlogon))
+ {
+ StartMouseWithoutBordersService(null, "logoff");
+ }
+ else
+ {
+ StartMouseWithoutBordersService(null, "logoff", myWinlogon);
+ }
+ }
+ catch (Exception e)
+ {
+ Logger.Log($"{nameof(StartServiceAndSendLogoffSignal)}: {e.Message}");
+ }
+ }
+}
diff --git a/src/modules/MouseWithoutBorders/App/Form/frmInputCallback.cs b/src/modules/MouseWithoutBorders/App/Form/frmInputCallback.cs
index edd35035adbc..ad04cafdc0d8 100644
--- a/src/modules/MouseWithoutBorders/App/Form/frmInputCallback.cs
+++ b/src/modules/MouseWithoutBorders/App/Form/frmInputCallback.cs
@@ -63,8 +63,8 @@ internal void InstallKeyboardAndMouseHook()
try
{
Common.Hook = new InputHook();
- Common.Hook.MouseEvent += new InputHook.MouseEvHandler(Common.MouseEvent);
- Common.Hook.KeyboardEvent += new InputHook.KeybdEvHandler(Common.KeybdEvent);
+ Common.Hook.MouseEvent += new InputHook.MouseEvHandler(Event.MouseEvent);
+ Common.Hook.KeyboardEvent += new InputHook.KeybdEvHandler(Event.KeybdEvent);
Logger.Log("(((((Keyboard/Mouse hooks installed/reinstalled!)))))");
/* The hook is called in the context of the thread that installed it.
diff --git a/src/modules/MouseWithoutBorders/App/Form/frmMatrix.cs b/src/modules/MouseWithoutBorders/App/Form/frmMatrix.cs
index 8f23dba1a22c..ca095d814000 100644
--- a/src/modules/MouseWithoutBorders/App/Form/frmMatrix.cs
+++ b/src/modules/MouseWithoutBorders/App/Form/frmMatrix.cs
@@ -132,7 +132,7 @@ private void ButtonOK_Click(object sender, EventArgs e)
internal void UpdateKeyTextBox()
{
- _ = Common.GetUserName();
+ _ = Helper.GetUserName();
textBoxEnc.Text = Common.MyKey;
}
@@ -787,7 +787,7 @@ private void CheckBoxDisableCAD_CheckedChanged(object sender, EventArgs e)
{
if (!Common.RunWithNoAdminRight)
{
- Common.ApplyCADSetting();
+ Helper.ApplyCADSetting();
ShowUpdateMessage();
}
}
@@ -1163,7 +1163,7 @@ private void CheckBoxVKMap_CheckedChanged(object sender, EventArgs e)
private void LinkLabelMiniLog_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
- string miniLog = Common.GetMiniLog(new[] { groupBoxOtherOptions.Controls, groupBoxShortcuts.Controls });
+ string miniLog = Helper.GetMiniLog(new[] { groupBoxOtherOptions.Controls, groupBoxShortcuts.Controls });
Clipboard.SetText(miniLog);
Common.ShowToolTip("Log has been placed in the clipboard.", 30000, ToolTipIcon.Info, false);
diff --git a/src/modules/MouseWithoutBorders/App/Form/frmScreen.cs b/src/modules/MouseWithoutBorders/App/Form/frmScreen.cs
index 7963a7572121..b01a653f60e1 100644
--- a/src/modules/MouseWithoutBorders/App/Form/frmScreen.cs
+++ b/src/modules/MouseWithoutBorders/App/Form/frmScreen.cs
@@ -78,7 +78,7 @@ internal FrmScreen()
NotifyIcon.BalloonTipTitle = Application.ProductName;
menuGenDumpFile.Visible = true;
- Common.WndProcCounter++;
+ Helper.WndProcCounter++;
try
{
@@ -101,7 +101,7 @@ private void FrmScreen_FormClosing(object sender, FormClosingEventArgs e)
}
else
{
- Common.StartServiceAndSendLogoffSignal();
+ Service.StartServiceAndSendLogoffSignal();
Quit(true, true);
}
}
@@ -119,7 +119,7 @@ internal void Destroy()
NotifyIcon.Dispose();
if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop)
{
- Common.RunDDHelper(true);
+ Helper.RunDDHelper(true);
}
// Common.UnhookClipboard();
@@ -133,7 +133,7 @@ internal void Quit(bool cleanup, bool isFormClosing)
Setting.Values.SwitchCount += Common.SwitchCount;
Process me = Process.GetCurrentProcess();
- Common.WndProcCounter++;
+ Helper.WndProcCounter++;
try
{
@@ -142,13 +142,13 @@ internal void Quit(bool cleanup, bool isFormClosing)
Common.Cleanup();
}
- Common.WndProcCounter++;
+ Helper.WndProcCounter++;
if (!Common.RunOnScrSaverDesktop)
{
Common.ReleaseAllKeys();
}
- Common.RunDDHelper(true);
+ Helper.RunDDHelper(true);
}
catch (Exception e)
{
@@ -285,7 +285,7 @@ private void FrmScreen_Load(object sender, EventArgs e)
helperTimer.Interval = 100;
helperTimer.Tick += new EventHandler(HelperTimer_Tick);
helperTimer.Start();
- Common.WndProcCounter++;
+ Helper.WndProcCounter++;
if (Environment.OSVersion.Version.Major > 6 ||
(Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor >= 1))
@@ -307,7 +307,7 @@ private void FrmScreen_Load(object sender, EventArgs e)
private void HelperTimer_Tick(object sender, EventArgs e)
{
- Common.WndProcCounter++;
+ Helper.WndProcCounter++;
if (busy)
{
@@ -338,7 +338,7 @@ private void HelperTimer_Tick(object sender, EventArgs e)
if (Common.MainFormVisible)
{
- Common.MainFormDot();
+ Helper.MainFormDot();
}
InputSimulation.ResetSystemKeyFlags();
@@ -357,7 +357,7 @@ private void HelperTimer_Tick(object sender, EventArgs e)
{
if (!Common.SecondOpenSocketTry)
{
- if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop && !Common.GetUserName())
+ if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop && !Helper.GetUserName())
{
// While Windows 8 is hybrid-shutting down, user name would be empty (as returned from the .Net API), we should not do anything in this case.
Logger.LogDebug("No active user.");
@@ -407,7 +407,7 @@ private void HelperTimer_Tick(object sender, EventArgs e)
// Common.ReHookClipboard();
}
- Common.RunDDHelper();
+ Helper.RunDDHelper();
}
count = 0;
@@ -485,7 +485,7 @@ private void HelperTimer_Tick(object sender, EventArgs e)
// One more time after 1/3 minutes (Sometimes XP has explorer started late)
if (count == 600 || count == 1800)
{
- Common.RunDDHelper();
+ Helper.RunDDHelper();
}
if (count == 600)
@@ -545,7 +545,7 @@ private void HelperTimer_Tick(object sender, EventArgs e)
if (Common.ToggleIcons != null)
{
- Common.ToggleIcon();
+ Helper.ToggleIcon();
}
if (count % 20 == 0)
@@ -578,13 +578,13 @@ private void HelperTimer_Tick(object sender, EventArgs e)
}
else if ((count % 36005) == 0)
{// One hour
- Common.SaveSwitchCount();
+ Event.SaveSwitchCount();
int rv = 0;
- if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop && Common.IsMyDesktopActive() && (rv = Common.SendMessageToHelper(0x400, IntPtr.Zero, IntPtr.Zero)) <= 0)
+ if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop && Common.IsMyDesktopActive() && (rv = Helper.SendMessageToHelper(0x400, IntPtr.Zero, IntPtr.Zero)) <= 0)
{
- Logger.TelemetryLogTrace($"{Common.HELPER_FORM_TEXT} not found: {rv}", SeverityLevel.Warning);
+ Logger.TelemetryLogTrace($"{Helper.HELPER_FORM_TEXT} not found: {rv}", SeverityLevel.Warning);
}
}
}
@@ -776,7 +776,7 @@ protected override void WndProc(ref Message m)
break;
case NativeMethods.WM_HIDE_DRAG_DROP:
- Common.MainFormDot();
+ Helper.MainFormDot();
/*
this.Width = 1;
@@ -795,14 +795,14 @@ protected override void WndProc(ref Message m)
break;
case NativeMethods.WM_HIDE_DD_HELPER:
- Common.MainForm3Pixels();
+ Helper.MainForm3Pixels();
Common.MMSleep(0.2);
if (m.WParam.ToInt32() == 1)
{
InputSimulation.MouseUp(); // A file is being dragged
}
- IntPtr h = (IntPtr)NativeMethods.FindWindow(null, Common.HELPER_FORM_TEXT);
+ IntPtr h = (IntPtr)NativeMethods.FindWindow(null, Helper.HELPER_FORM_TEXT);
if (h.ToInt32() > 0)
{
@@ -831,7 +831,7 @@ protected override void WndProc(ref Message m)
case WM_QUERYENDSESSION:
Logger.LogDebug("WM_QUERYENDSESSION...");
- Common.StartServiceAndSendLogoffSignal();
+ Service.StartServiceAndSendLogoffSignal();
break;
case WM_ENDSESSION:
diff --git a/src/modules/MouseWithoutBorders/MouseWithoutBorders.UnitTests/Core/Logger.PrivateDump.expected.txt b/src/modules/MouseWithoutBorders/MouseWithoutBorders.UnitTests/Core/Logger.PrivateDump.expected.txt
index d4cc369a9fad..3c933bfff187 100644
--- a/src/modules/MouseWithoutBorders/MouseWithoutBorders.UnitTests/Core/Logger.PrivateDump.expected.txt
+++ b/src/modules/MouseWithoutBorders/MouseWithoutBorders.UnitTests/Core/Logger.PrivateDump.expected.txt
@@ -99,54 +99,6 @@ LegalKeyDictionary = Concurrent.ConcurrentDictionary`2[System.String,System.Byte
--_budget = ????????????
--_growLockArray = True
--_comparerIsDefaultForClasses = False
-KeybdPackage = MouseWithoutBorders.DATA
---Type = 0
---Id = 0
---Src = NONE
---Des = NONE
---DateTime = 0
---Kd = MouseWithoutBorders.KEYBDDATA
---Md = MouseWithoutBorders.MOUSEDATA
---Machine1 = NONE
---Machine2 = NONE
---Machine3 = NONE
---Machine4 = NONE
---PostAction = Other
---machineNameP1 = 0
---machineNameP2 = 0
---machineNameP3 = 0
---machineNameP4 = 0
-MousePackage = MouseWithoutBorders.DATA
---Type = 0
---Id = 0
---Src = NONE
---Des = NONE
---DateTime = 0
---Kd = MouseWithoutBorders.KEYBDDATA
---Md = MouseWithoutBorders.MOUSEDATA
---Machine1 = NONE
---Machine2 = NONE
---Machine3 = NONE
---Machine4 = NONE
---PostAction = Other
---machineNameP1 = 0
---machineNameP2 = 0
---machineNameP3 = 0
---machineNameP4 = 0
-inputEventCount = 0
-invalidPackageCount = 0
-MOVE_MOUSE_RELATIVE = 100000
-XY_BY_PIXEL = 300000
-k__BackingField = 0
-actualLastPos = {X=0,Y=0}
---x = 0
---y = 0
---Empty = {X=0,Y=0}
-myLastX = 0
-myLastY = 0
-signalHelperToExit = False
-signalWatchDogToExit = False
-WndProcCounter = 0
initDone = False
REOPEN_WHEN_WSAECONNRESET = -10054
REOPEN_WHEN_HOTKEY = -10055
@@ -189,12 +141,6 @@ PackageReceived = MouseWithoutBorders.PackageMonitor
--ExplorerDragDrop = 0
--Nil = 0
PackageID = 0
-shownErrMessage = False
-lastStartServiceTime = ????????????
---_dateData = ????????????
---MinValue = 01/01/0001 00:00:00
---MaxValue = 31/12/9999 23:59:59
---UnixEpoch = 01/01/1970 00:00:00
SensitivePoints = Generic.List`1[Point]
--_items = Point[]
----System.Drawing.Point[] = Point[]: N/A
@@ -223,8 +169,6 @@ JUST_GOT_BACK_FROM_SCREEN_SAVER = 9999
NETWORK_STREAM_BUF_SIZE = 1048576
SymAlBlockSize = 16
PW_LENGTH = 16
-HELPER_FORM_TEXT = Mouse without Borders Helper
-HelperProcessName = PowerToys.MouseWithoutBordersHelper
PACKAGE_SIZE = 32
PACKAGE_SIZE_EX = 64
WP_PACKAGE_SIZE = 6
@@ -251,6 +195,69 @@ WM_KEYDOWN = 256
WM_KEYUP = 257
WM_SYSKEYDOWN = 260
WM_SYSKEYUP = 261
+[DragDrop]
+===============
+isDragging = False
+dragDropStep05ExCalledByIpc = 0
+isDropping = False
+dragMachine = NONE
+k__BackingField = False
+[Event]
+===============
+KeybdPackage = MouseWithoutBorders.DATA
+--Type = 0
+--Id = 0
+--Src = NONE
+--Des = NONE
+--DateTime = 0
+--Kd = MouseWithoutBorders.KEYBDDATA
+--Md = MouseWithoutBorders.MOUSEDATA
+--Machine1 = NONE
+--Machine2 = NONE
+--Machine3 = NONE
+--Machine4 = NONE
+--PostAction = Other
+--machineNameP1 = 0
+--machineNameP2 = 0
+--machineNameP3 = 0
+--machineNameP4 = 0
+MousePackage = MouseWithoutBorders.DATA
+--Type = 0
+--Id = 0
+--Src = NONE
+--Des = NONE
+--DateTime = 0
+--Kd = MouseWithoutBorders.KEYBDDATA
+--Md = MouseWithoutBorders.MOUSEDATA
+--Machine1 = NONE
+--Machine2 = NONE
+--Machine3 = NONE
+--Machine4 = NONE
+--PostAction = Other
+--machineNameP1 = 0
+--machineNameP2 = 0
+--machineNameP3 = 0
+--machineNameP4 = 0
+inputEventCount = 0
+invalidPackageCount = 0
+MOVE_MOUSE_RELATIVE = 100000
+XY_BY_PIXEL = 300000
+k__BackingField = 0
+actualLastPos = {X=0,Y=0}
+--x = 0
+--y = 0
+--Empty = {X=0,Y=0}
+myLastX = 0
+myLastY = 0
+[Helper]
+===============
+signalHelperToExit = False
+signalWatchDogToExit = False
+WndProcCounter = 0
+HELPER_FORM_TEXT = Mouse without Borders Helper
+HelperProcessName = PowerToys.MouseWithoutBordersHelper
+[Launch]
+===============
[Logger]
===============
AllLogsLock = Lock
@@ -319,13 +326,6 @@ MAX_LOG = 10000
MaxLogExceptionPerHour = 1000
HeaderSENT = Be{0},Ke{1},Mo{2},He{3},Mx{4},Tx{5},Im{6},By{7},Cl{8},Dr{9},De{10},Ed{11},Ie{12},Ni{13}
HeaderRECEIVED = Be{0},Ke{1},Mo{2},He{3},Mx{4},Tx{5},Im{6},By{7},Cl{8},Dr{9},De{10},Ed{11},In{12},Ni{13},Pc{14}/{15}
-[DragDrop]
-===============
-isDragging = False
-dragDropStep05ExCalledByIpc = 0
-isDropping = False
-dragMachine = NONE
-k__BackingField = False
[MachineStuff]
===============
McMatrixLock = Lock
@@ -424,3 +424,11 @@ lastXY = {X=0,Y=0}
--x = 0
--y = 0
--Empty = {X=0,Y=0}
+[Service]
+===============
+shownErrMessage = False
+lastStartServiceTime = ????????????
+--_dateData = ????????????
+--MinValue = 01/01/0001 00:00:00
+--MaxValue = 31/12/9999 23:59:59
+--UnixEpoch = 01/01/1970 00:00:00
diff --git a/src/modules/MouseWithoutBorders/MouseWithoutBorders.UnitTests/Core/LoggerTests.cs b/src/modules/MouseWithoutBorders/MouseWithoutBorders.UnitTests/Core/LoggerTests.cs
index 2ef14453a00d..6d6b593e8acd 100644
--- a/src/modules/MouseWithoutBorders/MouseWithoutBorders.UnitTests/Core/LoggerTests.cs
+++ b/src/modules/MouseWithoutBorders/MouseWithoutBorders.UnitTests/Core/LoggerTests.cs
@@ -38,11 +38,13 @@ public void PrivateDumpShouldGenerateExpectedOutput()
*/
[TestMethod]
+ /*
[Ignore(
"This test relies on internal details of the dotnet platform and is sensitive to " +
"the specific version of dotnet being used. As a result it's likely to fail if the " +
"\"expected\" result was generated with a different version to the version used to " +
"run the test, so we're going to ignore it in the CI build process.")]
+ */
public void PrivateDumpShouldGenerateExpectedOutput()
{
static string NormalizeLog(string log)
@@ -114,18 +116,11 @@ static string NormalizeLog(string log)
using var streamReader = new StreamReader(stream);
var expected = streamReader.ReadToEnd();
- // copied from DumpObjects in Common.Log.cs
+ // copied from DumpObjects in Logger.cs
var sb = new StringBuilder(1000000);
- _ = Logger.PrivateDump(sb, Logger.AllLogs, "[Program logs]\r\n===============\r\n", 0, settingsDumpObjectsLevel, false);
- _ = Logger.PrivateDump(sb, new Common(), "[Other Logs]\r\n===============\r\n", 0, settingsDumpObjectsLevel, false);
- sb.AppendLine("[Logger]\r\n===============");
- Logger.DumpType(sb, typeof(Logger), 0, settingsDumpObjectsLevel);
- sb.AppendLine("[DragDrop]\r\n===============");
- Logger.DumpType(sb, typeof(DragDrop), 0, settingsDumpObjectsLevel);
- sb.AppendLine("[MachineStuff]\r\n===============");
- Logger.DumpType(sb, typeof(MachineStuff), 0, settingsDumpObjectsLevel);
- sb.AppendLine("[Receiver]\r\n===============");
- Logger.DumpType(sb, typeof(Receiver), 0, settingsDumpObjectsLevel);
+ Logger.DumpProgramLogs(sb, settingsDumpObjectsLevel);
+ Logger.DumpOtherLogs(sb, settingsDumpObjectsLevel);
+ Logger.DumpStaticTypes(sb, settingsDumpObjectsLevel);
var actual = sb.ToString();
expected = NormalizeLog(expected);