[MWB] - refactoring "Common" classes (Part 4) (#37579)

* [MouseWithoutBorders] - moving Common.Event.cs -> Core\Event.cs - #35155

* [MouseWithoutBorders] - moving Common.Service.cs -> Core\Service.cs - #35155

* [MouseWithoutBorders] - moving Common.Launch.cs -> Core\Launch.cs - #35155

* [MouseWithoutBorders] - moving Common.Helper.cs -> Core\Helper.cs - #35155

* [MouseWithoutBorders] - refactoring and fixes for logger unit test - #35155

* [MouseWithoutBorders] - cleaning up changes - #35155

* [MouseWithoutBorders] - re-[Ignore]-ing test - #35155
This commit is contained in:
Michael Clayton
2025-03-17 22:05:36 +00:00
committed by GitHub
parent 0e62e2ddd4
commit c89280cd9e
26 changed files with 1520 additions and 1496 deletions

View File

@@ -153,7 +153,7 @@ namespace MouseWithoutBorders
string filePath = stringData;
_ = Common.ImpersonateLoggedOnUserAndDoSomething(() =>
_ = Launch.ImpersonateLoggedOnUserAndDoSomething(() =>
{
if (File.Exists(filePath) || Directory.Exists(filePath))
{
@@ -579,7 +579,7 @@ namespace MouseWithoutBorders
{
if (postAct.Equals("desktop", StringComparison.OrdinalIgnoreCase))
{
_ = ImpersonateLoggedOnUserAndDoSomething(() =>
_ = Launch.ImpersonateLoggedOnUserAndDoSomething(() =>
{
savingFolder = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\MouseWithoutBorders\\";
@@ -696,7 +696,7 @@ namespace MouseWithoutBorders
Path.GetFileName(fileName),
remoteMachine);
_ = ImpersonateLoggedOnUserAndDoSomething(() =>
_ = Launch.ImpersonateLoggedOnUserAndDoSomething(() =>
{
ProcessStartInfo startInfo = new();
startInfo.UseShellExecute = true;

View File

@@ -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;
// <summary>
// Keyboard/Mouse hook callback implementation.
// </summary>
// <history>
// 2008 created by Truong Do (ductdo).
// 2009-... modified by Truong Do (TruongDo).
// 2023- Included in PowerToys.
// </history>
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);
}
}
}
}

View File

@@ -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;
// <summary>
// Some other helper methods.
// </summary>
// <history>
// 2008 created by Truong Do (ductdo).
// 2009-... modified by Truong Do (TruongDo).
// 2023- Included in PowerToys.
// </history>
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<ControlCollection> 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);
}
}
}
}

View File

@@ -93,7 +93,7 @@ namespace MouseWithoutBorders
internal static void Init()
{
_ = Common.GetUserName();
_ = Helper.GetUserName();
Common.GeneratedKey = true;
try
@@ -148,7 +148,7 @@ namespace MouseWithoutBorders
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 @@ namespace MouseWithoutBorders
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 @@ namespace MouseWithoutBorders
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);
}

View File

@@ -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;
// <summary>
// Impersonation.
// </summary>
// <history>
// 2008 created by Truong Do (ductdo).
// 2009-... modified by Truong Do (TruongDo).
// 2023- Included in PowerToys.
// </history>
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
}
}

View File

@@ -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;
// <summary>
// Service control code.
// </summary>
// <history>
// 2008 created by Truong Do (ductdo).
// 2009-... modified by Truong Do (TruongDo).
// 2023- Included in PowerToys.
// </history>
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}");
}
}
}
}

View File

@@ -269,7 +269,7 @@ namespace MouseWithoutBorders
if (!Common.RunWithNoAdminRight)
{
Logger.LogDebug("*** Starting on active Desktop: " + desktopToRunMouseWithoutBordersOn);
StartMouseWithoutBordersService(desktopToRunMouseWithoutBordersOn);
Service.StartMouseWithoutBordersService(desktopToRunMouseWithoutBordersOn);
}
}
@@ -279,7 +279,7 @@ namespace MouseWithoutBorders
{
if (!IsMyDesktopActive() || Common.CurrentProcess.SessionId != NativeMethods.WTSGetActiveConsoleSessionId())
{
Common.RunDDHelper(true);
Helper.RunDDHelper(true);
int waitCount = 20;
while (NativeMethods.WTSGetActiveConsoleSessionId() == 0xFFFFFFFF && waitCount > 0)

View File

@@ -101,8 +101,10 @@ namespace MouseWithoutBorders
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 @@ namespace MouseWithoutBorders
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 @@ namespace MouseWithoutBorders
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 @@ namespace MouseWithoutBorders
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 @@ namespace MouseWithoutBorders
}
}
lastInputEventCount = Common.InputEventCount;
lastInputEventCount = Event.InputEventCount;
}
private static void PokeMyself()
@@ -581,7 +585,7 @@ namespace MouseWithoutBorders
InputSimulation.MoveMouseRelative(-x, -y);
Thread.Sleep(50);
if (lastInputEventCount != Common.InputEventCount)
if (lastInputEventCount != Event.InputEventCount)
{
break;
}
@@ -590,8 +594,8 @@ namespace MouseWithoutBorders
internal static void InitLastInputEventCount()
{
lastInputEventCount = Common.InputEventCount;
lastRealInputEventCount = Common.RealInputEventCount;
lastInputEventCount = Event.InputEventCount;
lastRealInputEventCount = Event.RealInputEventCount;
}
internal static void SendHello()
@@ -665,7 +669,7 @@ namespace MouseWithoutBorders
{
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 @@ namespace MouseWithoutBorders
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 @@ namespace MouseWithoutBorders
// {
// Process.Start("explorer", "\"" + file + "\"");
// });
_ = CreateProcessInInputDesktopSession(
_ = Launch.CreateProcessInInputDesktopSession(
"\"" + Environment.ExpandEnvironmentVariables(@"%SystemRoot%\System32\Mspaint.exe") +
"\"",
"\"" + file + "\"",
@@ -956,8 +960,8 @@ namespace MouseWithoutBorders
{
// 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 @@ namespace MouseWithoutBorders
}
else
{
_ = ImpersonateLoggedOnUserAndDoSomething(() =>
_ = Launch.ImpersonateLoggedOnUserAndDoSomething(() =>
{
st = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + @"\" + Common.BinaryName;
if (!Directory.Exists(st))

View File

@@ -206,7 +206,7 @@ namespace MouseWithoutBorders.Class
{
int rv = 1, dx = 0, dy = 0;
bool local = false;
Common.InputEventCount++;
Event.InputEventCount++;
try
{
@@ -220,14 +220,14 @@ namespace MouseWithoutBorders.Class
}
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 @@ namespace MouseWithoutBorders.Class
{
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 @@ namespace MouseWithoutBorders.Class
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 @@ namespace MouseWithoutBorders.Class
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;

View File

@@ -223,7 +223,7 @@ namespace MouseWithoutBorders.Class
if (Common.MainFormVisible && !DragDrop.IsDropping)
{
Common.MainFormDot();
Helper.MainFormDot();
}
return rv;

View File

@@ -36,6 +36,7 @@ using Newtonsoft.Json;
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 @@ namespace MouseWithoutBorders.Class
{
if (args.Length > 2)
{
Helper.UserLocalAppDataPath = args[2].Trim();
SettingsHelper.UserLocalAppDataPath = args[2].Trim();
}
}
@@ -235,7 +236,7 @@ namespace MouseWithoutBorders.Class
Application.SetCompatibleTextRenderingDefault(false);
Common.Init();
Common.WndProcCounter++;
Core.Helper.WndProcCounter++;
var formScreen = new FrmScreen();
@@ -430,7 +431,7 @@ namespace MouseWithoutBorders.Class
Logger.Log(e);
}
Common.StartMouseWithoutBordersService();
Service.StartMouseWithoutBordersService();
}
internal static string User { get; set; }

View File

@@ -33,6 +33,7 @@ using MouseWithoutBorders.Core;
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 @@ namespace MouseWithoutBorders.Class
{
_settingsUtils = new SettingsUtils();
_watcher = Helper.GetFileWatcher("MouseWithoutBorders", "settings.json", () =>
_watcher = SettingsHelper.GetFileWatcher("MouseWithoutBorders", "settings.json", () =>
{
try
{

View File

@@ -1684,7 +1684,7 @@ namespace MouseWithoutBorders.Class
{
string fileName = null;
if (!Common.ImpersonateLoggedOnUserAndDoSomething(() =>
if (!Launch.ImpersonateLoggedOnUserAndDoSomething(() =>
{
if (!File.Exists(Common.LastDragDropFile))
{
@@ -1873,7 +1873,7 @@ namespace MouseWithoutBorders.Class
}
else
{
_ = Common.ImpersonateLoggedOnUserAndDoSomething(() => { r = SendFileEx(s, ecStream, fileName); });
_ = Launch.ImpersonateLoggedOnUserAndDoSomething(() => { r = SendFileEx(s, ecStream, fileName); });
}
return r;
@@ -2111,7 +2111,7 @@ namespace MouseWithoutBorders.Class
}
}
_ = Common.CreateLowIntegrityProcess(
_ = Launch.CreateLowIntegrityProcess(
"\"" + Path.GetDirectoryName(Application.ExecutablePath) + "\\MouseWithoutBordersHelper.exe\"",
"InternalError" + " \"" + msg + "\"",
0,

View File

@@ -132,7 +132,7 @@ internal static class DragDrop
{
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 class DragDrop
if (!IsDropping)
{
_ = Common.ImpersonateLoggedOnUserAndDoSomething(() =>
_ = Launch.ImpersonateLoggedOnUserAndDoSomething(() =>
{
if (!string.IsNullOrEmpty(dragFileName) && (File.Exists(dragFileName) || Directory.Exists(dragFileName)))
{

View File

@@ -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;
// <summary>
// Keyboard/Mouse hook callback implementation.
// </summary>
// <history>
// 2008 created by Truong Do (ductdo).
// 2009-... modified by Truong Do (TruongDo).
// 2023- Included in PowerToys.
// </history>
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);
}
}
}

View File

@@ -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;
// <summary>
// Some other helper methods.
// </summary>
// <history>
// 2008 created by Truong Do (ductdo).
// 2009-... modified by Truong Do (TruongDo).
// 2023- Included in PowerToys.
// </history>
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<ControlCollection> 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);
}
}
}

View File

@@ -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;
// <summary>
// Impersonation.
// </summary>
// <history>
// 2008 created by Truong Do (ductdo).
// 2009-... modified by Truong Do (TruongDo).
// 2023- Included in PowerToys.
// </history>
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
}

View File

@@ -138,7 +138,7 @@ internal static class Logger
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 class Logger
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 class Logger
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 class Logger
}
}
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;

View File

@@ -1018,8 +1018,8 @@ internal static class MachineStuff
}
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);

View File

@@ -41,12 +41,12 @@ internal static class Receiver
{
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 class Receiver
{
if ((package.Kd.dwFlags & (int)Common.LLKHF.UP) == (int)Common.LLKHF.UP)
{
Common.ShowOneWayModeMessage();
Helper.ShowOneWayModeMessage();
}
return;
@@ -133,7 +133,7 @@ internal static class Receiver
{
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 class Receiver
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 class Receiver
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 class Receiver
case PackageType.HideMouse:
Common.HasSwitchedMachineSinceLastCopy = true;
Common.HideMouseCursor(true);
Common.MainFormDotEx(false);
Helper.MainFormDotEx(false);
Common.ReleaseAllKeys();
break;

View File

@@ -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")]
// <summary>
// Service control code.
// </summary>
// <history>
// 2008 created by Truong Do (ductdo).
// 2009-... modified by Truong Do (TruongDo).
// 2023- Included in PowerToys.
// </history>
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}");
}
}
}

View File

@@ -63,8 +63,8 @@ namespace MouseWithoutBorders
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.

View File

@@ -132,7 +132,7 @@ namespace MouseWithoutBorders
internal void UpdateKeyTextBox()
{
_ = Common.GetUserName();
_ = Helper.GetUserName();
textBoxEnc.Text = Common.MyKey;
}
@@ -787,7 +787,7 @@ namespace MouseWithoutBorders
{
if (!Common.RunWithNoAdminRight)
{
Common.ApplyCADSetting();
Helper.ApplyCADSetting();
ShowUpdateMessage();
}
}
@@ -1163,7 +1163,7 @@ namespace MouseWithoutBorders
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);

View File

@@ -78,7 +78,7 @@ namespace MouseWithoutBorders
NotifyIcon.BalloonTipTitle = Application.ProductName;
menuGenDumpFile.Visible = true;
Common.WndProcCounter++;
Helper.WndProcCounter++;
try
{
@@ -101,7 +101,7 @@ namespace MouseWithoutBorders
}
else
{
Common.StartServiceAndSendLogoffSignal();
Service.StartServiceAndSendLogoffSignal();
Quit(true, true);
}
}
@@ -119,7 +119,7 @@ namespace MouseWithoutBorders
NotifyIcon.Dispose();
if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop)
{
Common.RunDDHelper(true);
Helper.RunDDHelper(true);
}
// Common.UnhookClipboard();
@@ -133,7 +133,7 @@ namespace MouseWithoutBorders
Setting.Values.SwitchCount += Common.SwitchCount;
Process me = Process.GetCurrentProcess();
Common.WndProcCounter++;
Helper.WndProcCounter++;
try
{
@@ -142,13 +142,13 @@ namespace MouseWithoutBorders
Common.Cleanup();
}
Common.WndProcCounter++;
Helper.WndProcCounter++;
if (!Common.RunOnScrSaverDesktop)
{
Common.ReleaseAllKeys();
}
Common.RunDDHelper(true);
Helper.RunDDHelper(true);
}
catch (Exception e)
{
@@ -285,7 +285,7 @@ namespace MouseWithoutBorders
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 @@ namespace MouseWithoutBorders
private void HelperTimer_Tick(object sender, EventArgs e)
{
Common.WndProcCounter++;
Helper.WndProcCounter++;
if (busy)
{
@@ -338,7 +338,7 @@ namespace MouseWithoutBorders
if (Common.MainFormVisible)
{
Common.MainFormDot();
Helper.MainFormDot();
}
InputSimulation.ResetSystemKeyFlags();
@@ -357,7 +357,7 @@ namespace MouseWithoutBorders
{
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 @@ namespace MouseWithoutBorders
// Common.ReHookClipboard();
}
Common.RunDDHelper();
Helper.RunDDHelper();
}
count = 0;
@@ -485,7 +485,7 @@ namespace MouseWithoutBorders
// 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 @@ namespace MouseWithoutBorders
if (Common.ToggleIcons != null)
{
Common.ToggleIcon();
Helper.ToggleIcon();
}
if (count % 20 == 0)
@@ -578,13 +578,13 @@ namespace MouseWithoutBorders
}
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 @@ namespace MouseWithoutBorders
break;
case NativeMethods.WM_HIDE_DRAG_DROP:
Common.MainFormDot();
Helper.MainFormDot();
/*
this.Width = 1;
@@ -795,14 +795,14 @@ namespace MouseWithoutBorders
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 @@ namespace MouseWithoutBorders
case WM_QUERYENDSESSION:
Logger.LogDebug("WM_QUERYENDSESSION...");
Common.StartServiceAndSendLogoffSignal();
Service.StartServiceAndSendLogoffSignal();
break;
case WM_ENDSESSION:

View File

@@ -99,6 +99,111 @@ LegalKeyDictionary = Concurrent.ConcurrentDictionary`2[System.String,System.Byte
--_budget = ????????????
--_growLockArray = True
--_comparerIsDefaultForClasses = False
initDone = False
REOPEN_WHEN_WSAECONNRESET = -10054
REOPEN_WHEN_HOTKEY = -10055
PleaseReopenSocket = 0
ReopenSocketDueToReadError = False
<LastResumeSuspendTime>k__BackingField = ????????????
--_dateData = ????????????
--MinValue = 01/01/0001 00:00:00
--MaxValue = 31/12/9999 23:59:59
--UnixEpoch = 01/01/1970 00:00:00
lastReleaseAllKeysCall = 0
PackageSent = MouseWithoutBorders.PackageMonitor
--Keyboard = 0
--Mouse = 0
--Heartbeat = 0
--ByeBye = 0
--Hello = 0
--Matrix = 0
--ClipboardText = 0
--ClipboardImage = 0
--Clipboard = 0
--ClipboardDragDrop = 0
--ClipboardDragDropEnd = 0
--ClipboardAsk = 0
--ExplorerDragDrop = 0
--Nil = 0
PackageReceived = MouseWithoutBorders.PackageMonitor
--Keyboard = 0
--Mouse = 0
--Heartbeat = 0
--ByeBye = 0
--Hello = 0
--Matrix = 0
--ClipboardText = 0
--ClipboardImage = 0
--Clipboard = 0
--ClipboardDragDrop = 0
--ClipboardDragDropEnd = 0
--ClipboardAsk = 0
--ExplorerDragDrop = 0
--Nil = 0
PackageID = 0
SensitivePoints = Generic.List`1[Point]
--_items = Point[]
----System.Drawing.Point[] = Point[]: N/A
--_size = 0
--_version = 0
--s_emptyArray = Point[]
----System.Drawing.Point[] = Point[]: N/A
p = {X=0,Y=0}
--x = 0
--y = 0
--Empty = {X=0,Y=0}
<IpcChannelCreated>k__BackingField = False
BIG_CLIPBOARD_DATA_TIMEOUT = 30000
MAX_CLIPBOARD_DATA_SIZE_CAN_BE_SENT_INSTANTLY_TCP = 1048576
MAX_CLIPBOARD_FILE_SIZE_CAN_BE_SENT = 104857600
TEXT_HEADER_SIZE = 12
DATA_SIZE = 48
TEXT_TYPE_SEP = {4CFF57F7-BEDD-43d5-AE8F-27A61E886F2F}
TOGGLE_ICONS_SIZE = 4
ICON_ONE = 0
ICON_ALL = 1
ICON_SMALL_CLIPBOARD = 2
ICON_BIG_CLIPBOARD = 3
ICON_ERROR = 4
JUST_GOT_BACK_FROM_SCREEN_SAVER = 9999
NETWORK_STREAM_BUF_SIZE = 1048576
SymAlBlockSize = 16
PW_LENGTH = 16
PACKAGE_SIZE = 32
PACKAGE_SIZE_EX = 64
WP_PACKAGE_SIZE = 6
KEYEVENTF_KEYDOWN = 1
KEYEVENTF_KEYUP = 2
WH_MOUSE = 7
WH_KEYBOARD = 2
WH_MOUSE_LL = 14
WH_KEYBOARD_LL = 13
WM_MOUSEMOVE = 512
WM_LBUTTONDOWN = 513
WM_RBUTTONDOWN = 516
WM_MBUTTONDOWN = 519
WM_XBUTTONDOWN = 523
WM_LBUTTONUP = 514
WM_RBUTTONUP = 517
WM_MBUTTONUP = 520
WM_XBUTTONUP = 524
WM_LBUTTONDBLCLK = 515
WM_RBUTTONDBLCLK = 518
WM_MBUTTONDBLCLK = 521
WM_MOUSEWHEEL = 522
WM_KEYDOWN = 256
WM_KEYUP = 257
WM_SYSKEYDOWN = 260
WM_SYSKEYUP = 261
[DragDrop]
===============
isDragging = False
dragDropStep05ExCalledByIpc = 0
isDropping = False
dragMachine = NONE
<MouseDown>k__BackingField = False
[Event]
===============
KeybdPackage = MouseWithoutBorders.DATA
--Type = 0
--Id = 0
@@ -144,113 +249,15 @@ actualLastPos = {X=0,Y=0}
--Empty = {X=0,Y=0}
myLastX = 0
myLastY = 0
[Helper]
===============
signalHelperToExit = False
signalWatchDogToExit = False
WndProcCounter = 0
initDone = False
REOPEN_WHEN_WSAECONNRESET = -10054
REOPEN_WHEN_HOTKEY = -10055
PleaseReopenSocket = 0
ReopenSocketDueToReadError = False
<LastResumeSuspendTime>k__BackingField = ????????????
--_dateData = ????????????
--MinValue = 01/01/0001 00:00:00
--MaxValue = 31/12/9999 23:59:59
--UnixEpoch = 01/01/1970 00:00:00
lastReleaseAllKeysCall = 0
PackageSent = MouseWithoutBorders.PackageMonitor
--Keyboard = 0
--Mouse = 0
--Heartbeat = 0
--ByeBye = 0
--Hello = 0
--Matrix = 0
--ClipboardText = 0
--ClipboardImage = 0
--Clipboard = 0
--ClipboardDragDrop = 0
--ClipboardDragDropEnd = 0
--ClipboardAsk = 0
--ExplorerDragDrop = 0
--Nil = 0
PackageReceived = MouseWithoutBorders.PackageMonitor
--Keyboard = 0
--Mouse = 0
--Heartbeat = 0
--ByeBye = 0
--Hello = 0
--Matrix = 0
--ClipboardText = 0
--ClipboardImage = 0
--Clipboard = 0
--ClipboardDragDrop = 0
--ClipboardDragDropEnd = 0
--ClipboardAsk = 0
--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
--_size = 0
--_version = 0
--s_emptyArray = Point[]
----System.Drawing.Point[] = Point[]: N/A
p = {X=0,Y=0}
--x = 0
--y = 0
--Empty = {X=0,Y=0}
<IpcChannelCreated>k__BackingField = False
BIG_CLIPBOARD_DATA_TIMEOUT = 30000
MAX_CLIPBOARD_DATA_SIZE_CAN_BE_SENT_INSTANTLY_TCP = 1048576
MAX_CLIPBOARD_FILE_SIZE_CAN_BE_SENT = 104857600
TEXT_HEADER_SIZE = 12
DATA_SIZE = 48
TEXT_TYPE_SEP = {4CFF57F7-BEDD-43d5-AE8F-27A61E886F2F}
TOGGLE_ICONS_SIZE = 4
ICON_ONE = 0
ICON_ALL = 1
ICON_SMALL_CLIPBOARD = 2
ICON_BIG_CLIPBOARD = 3
ICON_ERROR = 4
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
KEYEVENTF_KEYDOWN = 1
KEYEVENTF_KEYUP = 2
WH_MOUSE = 7
WH_KEYBOARD = 2
WH_MOUSE_LL = 14
WH_KEYBOARD_LL = 13
WM_MOUSEMOVE = 512
WM_LBUTTONDOWN = 513
WM_RBUTTONDOWN = 516
WM_MBUTTONDOWN = 519
WM_XBUTTONDOWN = 523
WM_LBUTTONUP = 514
WM_RBUTTONUP = 517
WM_MBUTTONUP = 520
WM_XBUTTONUP = 524
WM_LBUTTONDBLCLK = 515
WM_RBUTTONDBLCLK = 518
WM_MBUTTONDBLCLK = 521
WM_MOUSEWHEEL = 522
WM_KEYDOWN = 256
WM_KEYUP = 257
WM_SYSKEYDOWN = 260
WM_SYSKEYUP = 261
[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
<MouseDown>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

View File

@@ -114,18 +114,11 @@ public static class LoggerTests
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);