diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.Clipboard.cs b/src/modules/MouseWithoutBorders/App/Class/Common.Clipboard.cs
index 91fdfad11b..7654b0452d 100644
--- a/src/modules/MouseWithoutBorders/App/Class/Common.Clipboard.cs
+++ b/src/modules/MouseWithoutBorders/App/Class/Common.Clipboard.cs
@@ -32,12 +32,17 @@ using MouseWithoutBorders.Core;
using MouseWithoutBorders.Exceptions;
using SystemClipboard = System.Windows.Forms.Clipboard;
+using Thread = MouseWithoutBorders.Core.Thread;
namespace MouseWithoutBorders
{
internal partial class Common
{
- private const uint BIG_CLIPBOARD_DATA_TIMEOUT = 30000;
+ internal static readonly char[] Comma = new char[] { ',' };
+ internal static readonly char[] Star = new char[] { '*' };
+ internal static readonly char[] NullSeparator = new char[] { '\0' };
+
+ internal const uint BIG_CLIPBOARD_DATA_TIMEOUT = 30000;
private const uint MAX_CLIPBOARD_DATA_SIZE_CAN_BE_SENT_INSTANTLY_TCP = 1024 * 1024; // 1MB
private const uint MAX_CLIPBOARD_FILE_SIZE_CAN_BE_SENT = 100 * 1024 * 1024; // 100MB
private const int TEXT_HEADER_SIZE = 12;
@@ -46,11 +51,9 @@ namespace MouseWithoutBorders
private static long lastClipboardEventTime;
private static string lastMachineWithClipboardData;
private static string lastDragDropFile;
- private static long clipboardCopiedTime;
-
- internal static readonly char[] Comma = new char[] { ',' };
- internal static readonly char[] Star = new char[] { '*' };
- internal static readonly char[] NullSeparator = new char[] { '\0' };
+#pragma warning disable SA1307 // Accessible fields should begin with upper-case letter
+ internal static long clipboardCopiedTime;
+#pragma warning restore SA1307
internal static ID LastIDWithClipboardData { get; set; }
@@ -332,7 +335,7 @@ namespace MouseWithoutBorders
break;
default:
- ProcessPackage(data, tcp);
+ Receiver.ProcessPackage(data, tcp);
if (++unexpectedCount > 100)
{
Logger.Log("ReceiveClipboardDataUsingTCP: unexpectedCount > 100!");
diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.DragDrop.cs b/src/modules/MouseWithoutBorders/App/Class/Common.DragDrop.cs
index f3ef0f1395..5426f93db0 100644
--- a/src/modules/MouseWithoutBorders/App/Class/Common.DragDrop.cs
+++ b/src/modules/MouseWithoutBorders/App/Class/Common.DragDrop.cs
@@ -22,6 +22,8 @@ using Microsoft.PowerToys.Telemetry;
using MouseWithoutBorders.Class;
using MouseWithoutBorders.Core;
+using Thread = MouseWithoutBorders.Core.Thread;
+
namespace MouseWithoutBorders
{
/* Common.DragDrop.cs
@@ -238,7 +240,7 @@ namespace MouseWithoutBorders
internal static void DragDropStep08(DATA package)
{
- GetNameOfMachineWithClipboardData(package);
+ Receiver.GetNameOfMachineWithClipboardData(package);
Logger.LogDebug("DragDropStep08: ClipboardDragDrop Received. machine with drag file was set");
}
diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.Event.cs b/src/modules/MouseWithoutBorders/App/Class/Common.Event.cs
index e50e87b8f9..fc581a3de2 100644
--- a/src/modules/MouseWithoutBorders/App/Class/Common.Event.cs
+++ b/src/modules/MouseWithoutBorders/App/Class/Common.Event.cs
@@ -21,6 +21,8 @@ using MouseWithoutBorders.Class;
using MouseWithoutBorders.Core;
using MouseWithoutBorders.Form;
+using Thread = MouseWithoutBorders.Core.Thread;
+
namespace MouseWithoutBorders
{
internal partial class Common
@@ -145,7 +147,7 @@ namespace MouseWithoutBorders
}
}
- private static bool IsSwitchingByMouseEnabled()
+ internal static bool IsSwitchingByMouseEnabled()
{
return (EasyMouseOption)Setting.Values.EasyMouse == EasyMouseOption.Enable || InputHook.EasyMouseKeyDown;
}
diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.InitAndCleanup.cs b/src/modules/MouseWithoutBorders/App/Class/Common.InitAndCleanup.cs
index da52a60db2..b733e17830 100644
--- a/src/modules/MouseWithoutBorders/App/Class/Common.InitAndCleanup.cs
+++ b/src/modules/MouseWithoutBorders/App/Class/Common.InitAndCleanup.cs
@@ -23,6 +23,8 @@ using MouseWithoutBorders.Core;
using MouseWithoutBorders.Form;
using Windows.UI.Input.Preview.Injection;
+using Thread = MouseWithoutBorders.Core.Thread;
+
namespace MouseWithoutBorders
{
internal partial class Common
diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.Log.cs b/src/modules/MouseWithoutBorders/App/Class/Common.Log.cs
deleted file mode 100644
index 773564fe7f..0000000000
--- a/src/modules/MouseWithoutBorders/App/Class/Common.Log.cs
+++ /dev/null
@@ -1,119 +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.Concurrent;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Globalization;
-using System.IO;
-using System.Linq;
-using System.Net;
-using System.Net.Sockets;
-using System.Reflection;
-using System.Text;
-using System.Threading;
-using System.Windows.Forms;
-
-//
-// Logging.
-//
-//
-// 2008 created by Truong Do (ductdo).
-// 2009-... modified by Truong Do (TruongDo).
-// 2023- Included in PowerToys.
-//
-using MouseWithoutBorders.Class;
-using MouseWithoutBorders.Core;
-using MouseWithoutBorders.Exceptions;
-
-namespace MouseWithoutBorders
-{
- public class Thread
- {
- private static readonly Lock ThreadsLock = new();
- private static List threads;
-
- private readonly System.Threading.Thread thread;
-
- internal Thread(ThreadStart callback, string name)
- {
- UpdateThreads(thread = new System.Threading.Thread(callback) { Name = name });
- }
-
- internal Thread(ParameterizedThreadStart callback, string name)
- {
- UpdateThreads(thread = new System.Threading.Thread(callback) { Name = name });
- }
-
- internal static void UpdateThreads(System.Threading.Thread thread)
- {
- lock (ThreadsLock)
- {
- bool found = false;
- List toBeRemovedThreads = new();
- threads ??= new List();
-
- foreach (System.Threading.Thread t in threads)
- {
- if (!t.IsAlive)
- {
- toBeRemovedThreads.Add(t);
- }
- else if (t.ManagedThreadId == thread.ManagedThreadId)
- {
- found = true;
- }
- }
-
- foreach (System.Threading.Thread t in toBeRemovedThreads)
- {
- _ = threads.Remove(t);
- }
-
- if (!found)
- {
- threads.Add(thread);
- }
- }
- }
-
- internal static string DumpThreadsStack()
- {
- string stack = "\r\nMANAGED THREADS: " + threads.Count.ToString(CultureInfo.InvariantCulture) + "\r\n";
- stack += Logger.GetStackTrace(new StackTrace());
- return stack;
- }
-
- internal void SetApartmentState(ApartmentState apartmentState)
- {
- thread.SetApartmentState(apartmentState);
- }
-
- internal void Start()
- {
- thread.Start();
- }
-
- internal void Start(object parameter)
- {
- thread.Start(parameter);
- }
-
- internal static void Sleep(int millisecondsTimeout)
- {
- System.Threading.Thread.Sleep(millisecondsTimeout);
- }
-
- internal static System.Threading.Thread CurrentThread => System.Threading.Thread.CurrentThread;
-
- internal ThreadPriority Priority
- {
- get => thread.Priority;
- set => thread.Priority = value;
- }
-
- internal System.Threading.ThreadState ThreadState => thread.ThreadState;
- }
-}
diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.MachineStuff.cs b/src/modules/MouseWithoutBorders/App/Class/Common.MachineStuff.cs
index 2072478f2d..cbf11ca16e 100644
--- a/src/modules/MouseWithoutBorders/App/Class/Common.MachineStuff.cs
+++ b/src/modules/MouseWithoutBorders/App/Class/Common.MachineStuff.cs
@@ -51,10 +51,14 @@ namespace MouseWithoutBorders
private const int SKIP_PIXELS = 1;
private const int JUMP_PIXELS = 2;
- private static ID desMachineID;
+#pragma warning disable SA1307 // Accessible fields should begin with upper-case letter
+ internal static ID desMachineID;
+#pragma warning restore SA1307
internal static string DesMachineName = string.Empty;
private static ID newDesMachineID;
- private static ID newDesMachineIdEx;
+#pragma warning disable SA1307 // Accessible fields should begin with upper-case letter
+ internal static ID newDesMachineIdEx;
+#pragma warning restore SA1307
private static ID dropMachineID;
private static long lastJump = Common.GetTick();
@@ -720,7 +724,7 @@ namespace MouseWithoutBorders
}
}
- private static string AddToMachinePool(DATA package)
+ internal static string AddToMachinePool(DATA package)
{
// Log("********** AddToMachinePool called: " + package.src.ToString(CultureInfo.InvariantCulture));
diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.Receiver.cs b/src/modules/MouseWithoutBorders/App/Class/Common.Receiver.cs
deleted file mode 100644
index 5b17801450..0000000000
--- a/src/modules/MouseWithoutBorders/App/Class/Common.Receiver.cs
+++ /dev/null
@@ -1,431 +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.CodeAnalysis;
-using System.Drawing;
-using System.Globalization;
-using System.IO;
-using System.Threading.Tasks;
-using System.Windows.Forms;
-
-//
-// Back-end thread for the socket.
-//
-//
-// 2008 created by Truong Do (ductdo).
-// 2009-... modified by Truong Do (TruongDo).
-// 2023- Included in PowerToys.
-//
-using MouseWithoutBorders.Class;
-using MouseWithoutBorders.Core;
-
-[module: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "MouseWithoutBorders.Common.#PreProcess(MouseWithoutBorders.DATA)", Justification = "Dotnet port with style preservation")]
-
-namespace MouseWithoutBorders
-{
- internal partial class Common
- {
- private static readonly uint QUEUE_SIZE = 50;
- private static readonly int[] RecentProcessedPackageIDs = new int[QUEUE_SIZE];
- private static int recentProcessedPackageIndex;
-#pragma warning disable SA1307 // Accessible fields should begin with upper-case letter
- internal static long processedPackageCount;
- internal static long skippedPackageCount;
-#pragma warning restore SA1307
-
- internal static long JustGotAKey { get; set; }
-
- private static bool PreProcess(DATA package)
- {
- if (package.Type == PackageType.Invalid)
- {
- if ((Common.InvalidPackageCount % 100) == 0)
- {
- ShowToolTip("Invalid packages received!", 1000, ToolTipIcon.Warning, false);
- }
-
- Common.InvalidPackageCount++;
- Logger.Log("Invalid packages received!");
- return false;
- }
- else if (package.Type == 0)
- {
- Logger.Log("Got an unknown package!");
- return false;
- }
- else if (package.Type is not PackageType.ClipboardText and not PackageType.ClipboardImage
-
- // BEGIN: These package types are sent by TcpSend which is single direction.
- and not PackageType.Handshake and not PackageType.HandshakeAck)
- {
- // END
- lock (RecentProcessedPackageIDs)
- {
- for (int i = 0; i < QUEUE_SIZE; i++)
- {
- if (RecentProcessedPackageIDs[i] == package.Id)
- {
- skippedPackageCount++;
- return false;
- }
- }
-
- processedPackageCount++;
- recentProcessedPackageIndex = (int)((recentProcessedPackageIndex + 1) % QUEUE_SIZE);
- RecentProcessedPackageIDs[recentProcessedPackageIndex] = package.Id;
- }
- }
-
- return true;
- }
-
- private static System.Drawing.Point lastXY;
-
- internal static void ProcessPackage(DATA package, TcpSk tcp)
- {
- if (!PreProcess(package))
- {
- return;
- }
-
- switch (package.Type)
- {
- case PackageType.Keyboard:
- PackageReceived.Keyboard++;
- if (package.Des == MachineID || package.Des == ID.ALL)
- {
- JustGotAKey = GetTick();
-
- // NOTE(@yuyoyuppe): disabled to drop elevation requirement
- bool nonElevated = Common.RunWithNoAdminRight && false;
- if (nonElevated && Setting.Values.OneWayControlMode)
- {
- if ((package.Kd.dwFlags & (int)Common.LLKHF.UP) == (int)Common.LLKHF.UP)
- {
- Common.ShowOneWayModeMessage();
- }
-
- return;
- }
-
- InputSimulation.SendKey(package.Kd);
- }
-
- break;
-
- case PackageType.Mouse:
- PackageReceived.Mouse++;
-
- if (package.Des == MachineID || package.Des == ID.ALL)
- {
- if (desMachineID != MachineID)
- {
- NewDesMachineID = DesMachineID = MachineID;
- }
-
- // NOTE(@yuyoyuppe): disabled to drop elevation requirement
- bool nonElevated = Common.RunWithNoAdminRight && false;
- if (nonElevated && Setting.Values.OneWayControlMode && package.Md.dwFlags != Common.WM_MOUSEMOVE)
- {
- if (!IsDropping)
- {
- if (package.Md.dwFlags is WM_LBUTTONDOWN or WM_RBUTTONDOWN)
- {
- Common.ShowOneWayModeMessage();
- }
- }
- else if (package.Md.dwFlags is WM_LBUTTONUP or WM_RBUTTONUP)
- {
- IsDropping = false;
- }
-
- return;
- }
-
- if (Math.Abs(package.Md.X) >= MOVE_MOUSE_RELATIVE && Math.Abs(package.Md.Y) >= MOVE_MOUSE_RELATIVE)
- {
- if (package.Md.dwFlags == Common.WM_MOUSEMOVE)
- {
- InputSimulation.MoveMouseRelative(
- package.Md.X < 0 ? package.Md.X + MOVE_MOUSE_RELATIVE : package.Md.X - MOVE_MOUSE_RELATIVE,
- package.Md.Y < 0 ? package.Md.Y + MOVE_MOUSE_RELATIVE : package.Md.Y - MOVE_MOUSE_RELATIVE);
- _ = NativeMethods.GetCursorPos(ref lastXY);
-
- Point p = MoveToMyNeighbourIfNeeded(lastXY.X, lastXY.Y, MachineID);
-
- if (!p.IsEmpty)
- {
- HasSwitchedMachineSinceLastCopy = true;
-
- Logger.LogDebug(string.Format(
- CultureInfo.CurrentCulture,
- "***** Controlled Machine: newDesMachineIdEx set = [{0}]. Mouse is now at ({1},{2})",
- newDesMachineIdEx,
- lastXY.X,
- lastXY.Y));
-
- SendNextMachine(package.Src, newDesMachineIdEx, p);
- }
- }
- else
- {
- _ = NativeMethods.GetCursorPos(ref lastXY);
- package.Md.X = lastXY.X * 65535 / screenWidth;
- package.Md.Y = lastXY.Y * 65535 / screenHeight;
- _ = InputSimulation.SendMouse(package.Md);
- }
- }
- else
- {
- _ = InputSimulation.SendMouse(package.Md);
- _ = NativeMethods.GetCursorPos(ref lastXY);
- }
-
- LastX = lastXY.X;
- LastY = lastXY.Y;
- CustomCursor.ShowFakeMouseCursor(LastX, LastY);
- }
-
- DragDropStep01(package.Md.dwFlags);
- DragDropStep09(package.Md.dwFlags);
- break;
-
- case PackageType.NextMachine:
- Logger.LogDebug("PackageType.NextMachine received!");
-
- if (IsSwitchingByMouseEnabled())
- {
- PrepareToSwitchToMachine((ID)package.Md.WheelDelta, new Point(package.Md.X, package.Md.Y));
- }
-
- break;
-
- case PackageType.ExplorerDragDrop:
- PackageReceived.ExplorerDragDrop++;
- DragDropStep03(package);
- break;
-
- case PackageType.Heartbeat:
- case PackageType.Heartbeat_ex:
- PackageReceived.Heartbeat++;
-
- Common.GeneratedKey = Common.GeneratedKey || package.Type == PackageType.Heartbeat_ex;
-
- if (Common.GeneratedKey)
- {
- Setting.Values.MyKey = Common.MyKey;
- SendPackage(ID.ALL, PackageType.Heartbeat_ex_l2);
- }
-
- string desMachine = Common.AddToMachinePool(package);
-
- if (Setting.Values.FirstRun && !string.IsNullOrEmpty(desMachine))
- {
- Common.UpdateSetupMachineMatrix(desMachine);
- Common.UpdateClientSockets("UpdateSetupMachineMatrix");
- }
-
- break;
-
- case PackageType.Heartbeat_ex_l2:
- Common.GeneratedKey = true;
- Setting.Values.MyKey = Common.MyKey;
- SendPackage(ID.ALL, PackageType.Heartbeat_ex_l3);
-
- break;
-
- case PackageType.Heartbeat_ex_l3:
- Common.GeneratedKey = true;
- Setting.Values.MyKey = Common.MyKey;
-
- break;
-
- case PackageType.Awake:
- PackageReceived.Heartbeat++;
- _ = Common.AddToMachinePool(package);
- Common.HumanBeingDetected();
- break;
-
- case PackageType.Hello:
- PackageReceived.Hello++;
- SendHeartBeat();
- string newMachine = Common.AddToMachinePool(package);
- if (Setting.Values.MachineMatrixString == null)
- {
- string tip = newMachine + " saying Hello!";
- tip += "\r\n Right Click to setup your machine Matrix";
- ShowToolTip(tip);
- }
-
- break;
-
- case PackageType.Hi:
- PackageReceived.Hello++;
- break;
-
- case PackageType.ByeBye:
- PackageReceived.ByeBye++;
- ProcessByeByeMessage(package);
- break;
-
- case PackageType.Clipboard:
- PackageReceived.Clipboard++;
- if (!RunOnLogonDesktop && !RunOnScrSaverDesktop)
- {
- clipboardCopiedTime = GetTick();
- GetNameOfMachineWithClipboardData(package);
- SignalBigClipboardData();
- }
-
- break;
-
- case PackageType.MachineSwitched:
- if (GetTick() - clipboardCopiedTime < BIG_CLIPBOARD_DATA_TIMEOUT && (package.Des == MachineID))
- {
- clipboardCopiedTime = 0;
- Common.GetRemoteClipboard("PackageType.MachineSwitched");
- }
-
- break;
-
- case PackageType.ClipboardCapture:
- PackageReceived.Clipboard++;
- if (!RunOnLogonDesktop && !RunOnScrSaverDesktop)
- {
- if (package.Des == MachineID || package.Des == ID.ALL)
- {
- GetNameOfMachineWithClipboardData(package);
- GetRemoteClipboard("mspaint," + LastMachineWithClipboardData);
- }
- }
-
- break;
-
- case PackageType.CaptureScreenCommand:
- PackageReceived.Clipboard++;
- if (package.Des == MachineID || package.Des == ID.ALL)
- {
- Common.SendImage(package.Src, Common.CaptureScreen());
- }
-
- break;
-
- case PackageType.ClipboardAsk:
- PackageReceived.ClipboardAsk++;
-
- if (package.Des == MachineID)
- {
- _ = Task.Run(() =>
- {
- try
- {
- System.Threading.Thread thread = Thread.CurrentThread;
- thread.Name = $"{nameof(PackageType.ClipboardAsk)}.{thread.ManagedThreadId}";
- Thread.UpdateThreads(thread);
-
- string remoteMachine = package.MachineName;
- System.Net.Sockets.TcpClient client = ConnectToRemoteClipboardSocket(remoteMachine);
- bool clientPushData = true;
-
- if (ShakeHand(ref remoteMachine, client.Client, out Stream enStream, out Stream deStream, ref clientPushData, ref package.PostAction))
- {
- SocketStuff.SendClipboardData(client.Client, enStream);
- }
- }
- catch (Exception e)
- {
- Logger.Log(e);
- }
- });
- }
-
- break;
-
- case PackageType.ClipboardDragDrop:
- PackageReceived.ClipboardDragDrop++;
- DragDropStep08(package);
- break;
-
- case PackageType.ClipboardDragDropOperation:
- PackageReceived.ClipboardDragDrop++;
- DragDropStep08_2(package);
- break;
-
- case PackageType.ClipboardDragDropEnd:
- PackageReceived.ClipboardDragDropEnd++;
- DragDropStep12();
- break;
-
- case PackageType.ClipboardText:
- case PackageType.ClipboardImage:
- clipboardCopiedTime = 0;
- if (package.Type == PackageType.ClipboardImage)
- {
- PackageReceived.ClipboardImage++;
- }
- else
- {
- PackageReceived.ClipboardText++;
- }
-
- if (tcp != null)
- {
- Common.ReceiveClipboardDataUsingTCP(
- package,
- package.Type == PackageType.ClipboardImage,
- tcp);
- }
-
- break;
-
- case PackageType.HideMouse:
- HasSwitchedMachineSinceLastCopy = true;
- HideMouseCursor(true);
- MainFormDotEx(false);
- ReleaseAllKeys();
- break;
-
- default:
- if ((package.Type & PackageType.Matrix) == PackageType.Matrix)
- {
- PackageReceived.Matrix++;
- UpdateMachineMatrix(package);
- break;
- }
- else
- {
- // We should never get to this point!
- Logger.Log("Invalid package received!");
- return;
- }
- }
- }
-
- private static void GetNameOfMachineWithClipboardData(DATA package)
- {
- LastIDWithClipboardData = package.Src;
- List matchingMachines = Common.MachinePool.TryFindMachineByID(LastIDWithClipboardData);
- if (matchingMachines.Count >= 1)
- {
- LastMachineWithClipboardData = matchingMachines[0].Name.Trim();
- }
-
- /*
- lastMachineWithClipboardData =
- Common.GetString(BitConverter.GetBytes(package.machineNameHead));
- lastMachineWithClipboardData +=
- Common.GetString(BitConverter.GetBytes(package.machineNameTail));
- lastMachineWithClipboardData = lastMachineWithClipboardData.Trim();
- * */
- }
-
- private static void SignalBigClipboardData()
- {
- Logger.LogDebug("SignalBigClipboardData");
- SetToggleIcon(new int[TOGGLE_ICONS_SIZE] { ICON_BIG_CLIPBOARD, -1, ICON_BIG_CLIPBOARD, -1 });
- }
- }
-}
diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.WinAPI.cs b/src/modules/MouseWithoutBorders/App/Class/Common.WinAPI.cs
index 722590ef81..006c5d862c 100644
--- a/src/modules/MouseWithoutBorders/App/Class/Common.WinAPI.cs
+++ b/src/modules/MouseWithoutBorders/App/Class/Common.WinAPI.cs
@@ -23,6 +23,8 @@ using System.Windows.Forms;
using MouseWithoutBorders.Class;
using MouseWithoutBorders.Core;
+using Thread = MouseWithoutBorders.Core.Thread;
+
namespace MouseWithoutBorders
{
// Desktops, and GetScreenConfig routines
diff --git a/src/modules/MouseWithoutBorders/App/Class/Common.cs b/src/modules/MouseWithoutBorders/App/Class/Common.cs
index f3cf4a86fd..1131893ec4 100644
--- a/src/modules/MouseWithoutBorders/App/Class/Common.cs
+++ b/src/modules/MouseWithoutBorders/App/Class/Common.cs
@@ -32,6 +32,8 @@ using MouseWithoutBorders.Class;
using MouseWithoutBorders.Core;
using MouseWithoutBorders.Exceptions;
+using Thread = MouseWithoutBorders.Core.Thread;
+
// Log is enough
[module: SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Scope = "member", Target = "MouseWithoutBorders.Common.#CheckClipboard()", Justification = "Dotnet port with style preservation")]
[module: SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Scope = "member", Target = "MouseWithoutBorders.Common.#CheckForDesktopSwitchEvent(System.Boolean)", Justification = "Dotnet port with style preservation")]
@@ -88,8 +90,10 @@ namespace MouseWithoutBorders
private static FrmInputCallback inputCallbackForm;
private static FrmAbout aboutForm;
private static Thread helper;
- private static int screenWidth;
- private static int screenHeight;
+#pragma warning disable SA1307 // Accessible fields should begin with upper-case letter
+ internal static int screenWidth;
+ internal static int screenHeight;
+#pragma warning restore SA1307
private static int lastX;
private static int lastY;
@@ -552,7 +556,7 @@ namespace MouseWithoutBorders
lastRealInputEventCount = Common.RealInputEventCount;
}
- private static void HumanBeingDetected()
+ internal static void HumanBeingDetected()
{
if (lastInputEventCount == Common.InputEventCount)
{
@@ -613,7 +617,7 @@ namespace MouseWithoutBorders
SendPackage(ID.ALL, PackageType.Clipboard);
}
- private static void ProcessByeByeMessage(DATA package)
+ internal static void ProcessByeByeMessage(DATA package)
{
if (package.Src == desMachineID)
{
diff --git a/src/modules/MouseWithoutBorders/App/Class/IClipboardHelper.cs b/src/modules/MouseWithoutBorders/App/Class/IClipboardHelper.cs
index ecaeef77db..9621c54bc4 100644
--- a/src/modules/MouseWithoutBorders/App/Class/IClipboardHelper.cs
+++ b/src/modules/MouseWithoutBorders/App/Class/IClipboardHelper.cs
@@ -27,6 +27,9 @@ using MouseWithoutBorders.Core;
#endif
using SystemClipboard = System.Windows.Forms.Clipboard;
+#if !MM_HELPER
+using Thread = MouseWithoutBorders.Core.Thread;
+#endif
namespace MouseWithoutBorders
{
diff --git a/src/modules/MouseWithoutBorders/App/Class/Program.cs b/src/modules/MouseWithoutBorders/App/Class/Program.cs
index ac33da9ae9..011b1cfdc9 100644
--- a/src/modules/MouseWithoutBorders/App/Class/Program.cs
+++ b/src/modules/MouseWithoutBorders/App/Class/Program.cs
@@ -35,6 +35,7 @@ using Newtonsoft.Json;
using StreamJsonRpc;
using Logger = MouseWithoutBorders.Core.Logger;
+using Thread = MouseWithoutBorders.Core.Thread;
[module: SuppressMessage("Microsoft.MSInternal", "CA904:DeclareTypesInMicrosoftOrSystemNamespace", Scope = "namespace", Target = "MouseWithoutBorders", Justification = "Dotnet port with style preservation")]
[module: SuppressMessage("Microsoft.Design", "CA1014:MarkAssembliesWithClsCompliant", Justification = "Dotnet port with style preservation")]
diff --git a/src/modules/MouseWithoutBorders/App/Class/Setting.cs b/src/modules/MouseWithoutBorders/App/Class/Setting.cs
index a49b98d4f7..23ca49309c 100644
--- a/src/modules/MouseWithoutBorders/App/Class/Setting.cs
+++ b/src/modules/MouseWithoutBorders/App/Class/Setting.cs
@@ -13,7 +13,6 @@ using System.IO.Abstractions;
using System.Linq;
using System.Security.Cryptography;
using System.Text.Json.Serialization;
-using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
@@ -33,6 +32,8 @@ using Microsoft.Win32;
using MouseWithoutBorders.Core;
using Settings.UI.Library.Attributes;
+using Lock = System.Threading.Lock;
+
[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")]
[module: SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Scope = "member", Target = "MouseWithoutBorders.Properties.Setting.Values.#LoadStringSetting(System.String,System.String)", Justification = "Dotnet port with style preservation")]
diff --git a/src/modules/MouseWithoutBorders/App/Class/SocketStuff.cs b/src/modules/MouseWithoutBorders/App/Class/SocketStuff.cs
index 6f354e4af1..31b047a837 100644
--- a/src/modules/MouseWithoutBorders/App/Class/SocketStuff.cs
+++ b/src/modules/MouseWithoutBorders/App/Class/SocketStuff.cs
@@ -29,6 +29,8 @@ using MouseWithoutBorders.Core;
//
using MouseWithoutBorders.Exceptions;
+using Thread = MouseWithoutBorders.Core.Thread;
+
[module: SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Scope = "member", Target = "MouseWithoutBorders.SocketStuff.#SendData(System.Byte[])", Justification = "Dotnet port with style preservation")]
[module: SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Scope = "member", Target = "MouseWithoutBorders.SocketStuff.#Close()", Justification = "Dotnet port with style preservation")]
[module: SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Scope = "member", Target = "MouseWithoutBorders.SocketStuff.#CreateSocket(System.Boolean)", Justification = "Dotnet port with style preservation")]
@@ -1524,7 +1526,7 @@ namespace MouseWithoutBorders.Class
}
else
{
- Common.ProcessPackage(package, currentTcp);
+ Receiver.ProcessPackage(package, currentTcp);
}
}
}
diff --git a/src/modules/MouseWithoutBorders/App/Class/TcpServer.cs b/src/modules/MouseWithoutBorders/App/Class/TcpServer.cs
index ffff1ce76b..f915ae94e0 100644
--- a/src/modules/MouseWithoutBorders/App/Class/TcpServer.cs
+++ b/src/modules/MouseWithoutBorders/App/Class/TcpServer.cs
@@ -23,6 +23,8 @@ using MouseWithoutBorders.Core;
//
using MouseWithoutBorders.Exceptions;
+using Thread = MouseWithoutBorders.Core.Thread;
+
[module: SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Scope = "member", Target = "MouseWithoutBorders.TcpServer.#Close()", Justification = "Dotnet port with style preservation")]
namespace MouseWithoutBorders.Class
diff --git a/src/modules/MouseWithoutBorders/App/Core/Logger.cs b/src/modules/MouseWithoutBorders/App/Core/Logger.cs
index c6e62139ba..c561d5ff42 100644
--- a/src/modules/MouseWithoutBorders/App/Core/Logger.cs
+++ b/src/modules/MouseWithoutBorders/App/Core/Logger.cs
@@ -15,6 +15,9 @@ using System.Text;
using System.Threading;
using System.Windows.Forms;
+using MouseWithoutBorders.Class;
+using MouseWithoutBorders.Exceptions;
+
//
// Logging.
//
@@ -23,9 +26,6 @@ using System.Windows.Forms;
// 2009-... modified by Truong Do (TruongDo).
// 2023- Included in PowerToys.
//
-using MouseWithoutBorders.Class;
-using MouseWithoutBorders.Exceptions;
-
namespace MouseWithoutBorders.Core;
internal static class Logger
@@ -163,8 +163,8 @@ internal static class Logger
Common.PackageReceived.ExplorerDragDrop,
Common.invalidPackageCount,
Common.PackageReceived.Nil,
- Common.processedPackageCount,
- Common.skippedPackageCount);
+ Receiver.processedPackageCount,
+ Receiver.skippedPackageCount);
Log(log);
lastPackageReceived = Common.PackageReceived;
}
@@ -201,6 +201,8 @@ internal static class Logger
_ = Logger.PrivateDump(sb, new Common(), "[Other Logs]\r\n===============\r\n", 0, level, false);
sb.AppendLine("[Logger]\r\n===============");
Logger.DumpType(sb, typeof(Logger), 0, level);
+ sb.AppendLine("[Receiver]\r\n===============");
+ Logger.DumpType(sb, typeof(Receiver), 0, level);
log = string.Format(
CultureInfo.CurrentCulture,
diff --git a/src/modules/MouseWithoutBorders/App/Core/Receiver.cs b/src/modules/MouseWithoutBorders/App/Core/Receiver.cs
new file mode 100644
index 0000000000..4ef8a8ccdc
--- /dev/null
+++ b/src/modules/MouseWithoutBorders/App/Core/Receiver.cs
@@ -0,0 +1,429 @@
+// 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.CodeAnalysis;
+using System.Drawing;
+using System.Globalization;
+using System.IO;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+using MouseWithoutBorders.Class;
+
+[module: SuppressMessage("Microsoft.Reliability", "CA2002:DoNotLockOnObjectsWithWeakIdentity", Scope = "member", Target = "MouseWithoutBorders.Common.#PreProcess(MouseWithoutBorders.DATA)", Justification = "Dotnet port with style preservation")]
+
+//
+// Back-end thread for the socket.
+//
+//
+// 2008 created by Truong Do (ductdo).
+// 2009-... modified by Truong Do (TruongDo).
+// 2023- Included in PowerToys.
+//
+namespace MouseWithoutBorders.Core;
+
+internal static class Receiver
+{
+ private static readonly uint QUEUE_SIZE = 50;
+ private static readonly int[] RecentProcessedPackageIDs = new int[QUEUE_SIZE];
+ private static int recentProcessedPackageIndex;
+#pragma warning disable SA1307 // Accessible fields should begin with upper-case letter
+ internal static long processedPackageCount;
+ internal static long skippedPackageCount;
+#pragma warning restore SA1307
+
+ private static long JustGotAKey { get; set; }
+
+ private static bool PreProcess(DATA package)
+ {
+ if (package.Type == PackageType.Invalid)
+ {
+ if ((Common.InvalidPackageCount % 100) == 0)
+ {
+ Common.ShowToolTip("Invalid packages received!", 1000, ToolTipIcon.Warning, false);
+ }
+
+ Common.InvalidPackageCount++;
+ Logger.Log("Invalid packages received!");
+ return false;
+ }
+ else if (package.Type == 0)
+ {
+ Logger.Log("Got an unknown package!");
+ return false;
+ }
+ else if (package.Type is not PackageType.ClipboardText and not PackageType.ClipboardImage
+
+ // BEGIN: These package types are sent by TcpSend which is single direction.
+ and not PackageType.Handshake and not PackageType.HandshakeAck)
+ {
+ // END
+ lock (RecentProcessedPackageIDs)
+ {
+ for (int i = 0; i < QUEUE_SIZE; i++)
+ {
+ if (RecentProcessedPackageIDs[i] == package.Id)
+ {
+ skippedPackageCount++;
+ return false;
+ }
+ }
+
+ processedPackageCount++;
+ recentProcessedPackageIndex = (int)((recentProcessedPackageIndex + 1) % QUEUE_SIZE);
+ RecentProcessedPackageIDs[recentProcessedPackageIndex] = package.Id;
+ }
+ }
+
+ return true;
+ }
+
+ private static System.Drawing.Point lastXY;
+
+ internal static void ProcessPackage(DATA package, TcpSk tcp)
+ {
+ if (!PreProcess(package))
+ {
+ return;
+ }
+
+ switch (package.Type)
+ {
+ case PackageType.Keyboard:
+ Common.PackageReceived.Keyboard++;
+ if (package.Des == Common.MachineID || package.Des == ID.ALL)
+ {
+ JustGotAKey = Common.GetTick();
+
+ // NOTE(@yuyoyuppe): disabled to drop elevation requirement
+ bool nonElevated = Common.RunWithNoAdminRight && false;
+ if (nonElevated && Setting.Values.OneWayControlMode)
+ {
+ if ((package.Kd.dwFlags & (int)Common.LLKHF.UP) == (int)Common.LLKHF.UP)
+ {
+ Common.ShowOneWayModeMessage();
+ }
+
+ return;
+ }
+
+ InputSimulation.SendKey(package.Kd);
+ }
+
+ break;
+
+ case PackageType.Mouse:
+ Common.PackageReceived.Mouse++;
+
+ if (package.Des == Common.MachineID || package.Des == ID.ALL)
+ {
+ if (Common.desMachineID != Common.MachineID)
+ {
+ Common.NewDesMachineID = Common.DesMachineID = Common.MachineID;
+ }
+
+ // NOTE(@yuyoyuppe): disabled to drop elevation requirement
+ bool nonElevated = Common.RunWithNoAdminRight && false;
+ if (nonElevated && Setting.Values.OneWayControlMode && package.Md.dwFlags != Common.WM_MOUSEMOVE)
+ {
+ if (!Common.IsDropping)
+ {
+ if (package.Md.dwFlags is Common.WM_LBUTTONDOWN or Common.WM_RBUTTONDOWN)
+ {
+ Common.ShowOneWayModeMessage();
+ }
+ }
+ else if (package.Md.dwFlags is Common.WM_LBUTTONUP or Common.WM_RBUTTONUP)
+ {
+ Common.IsDropping = false;
+ }
+
+ return;
+ }
+
+ if (Math.Abs(package.Md.X) >= Common.MOVE_MOUSE_RELATIVE && Math.Abs(package.Md.Y) >= Common.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);
+ _ = NativeMethods.GetCursorPos(ref lastXY);
+
+ Point p = Common.MoveToMyNeighbourIfNeeded(lastXY.X, lastXY.Y, Common.MachineID);
+
+ if (!p.IsEmpty)
+ {
+ Common.HasSwitchedMachineSinceLastCopy = true;
+
+ Logger.LogDebug(string.Format(
+ CultureInfo.CurrentCulture,
+ "***** Controlled Machine: newDesMachineIdEx set = [{0}]. Mouse is now at ({1},{2})",
+ Common.newDesMachineIdEx,
+ lastXY.X,
+ lastXY.Y));
+
+ Common.SendNextMachine(package.Src, Common.newDesMachineIdEx, p);
+ }
+ }
+ else
+ {
+ _ = NativeMethods.GetCursorPos(ref lastXY);
+ package.Md.X = lastXY.X * 65535 / Common.screenWidth;
+ package.Md.Y = lastXY.Y * 65535 / Common.screenHeight;
+ _ = InputSimulation.SendMouse(package.Md);
+ }
+ }
+ else
+ {
+ _ = InputSimulation.SendMouse(package.Md);
+ _ = NativeMethods.GetCursorPos(ref lastXY);
+ }
+
+ Common.LastX = lastXY.X;
+ Common.LastY = lastXY.Y;
+ CustomCursor.ShowFakeMouseCursor(Common.LastX, Common.LastY);
+ }
+
+ Common.DragDropStep01(package.Md.dwFlags);
+ Common.DragDropStep09(package.Md.dwFlags);
+ break;
+
+ case PackageType.NextMachine:
+ Logger.LogDebug("PackageType.NextMachine received!");
+
+ if (Common.IsSwitchingByMouseEnabled())
+ {
+ Common.PrepareToSwitchToMachine((ID)package.Md.WheelDelta, new Point(package.Md.X, package.Md.Y));
+ }
+
+ break;
+
+ case PackageType.ExplorerDragDrop:
+ Common.PackageReceived.ExplorerDragDrop++;
+ Common.DragDropStep03(package);
+ break;
+
+ case PackageType.Heartbeat:
+ case PackageType.Heartbeat_ex:
+ Common.PackageReceived.Heartbeat++;
+
+ Common.GeneratedKey = Common.GeneratedKey || package.Type == PackageType.Heartbeat_ex;
+
+ if (Common.GeneratedKey)
+ {
+ Setting.Values.MyKey = Common.MyKey;
+ Common.SendPackage(ID.ALL, PackageType.Heartbeat_ex_l2);
+ }
+
+ string desMachine = Common.AddToMachinePool(package);
+
+ if (Setting.Values.FirstRun && !string.IsNullOrEmpty(desMachine))
+ {
+ Common.UpdateSetupMachineMatrix(desMachine);
+ Common.UpdateClientSockets("UpdateSetupMachineMatrix");
+ }
+
+ break;
+
+ case PackageType.Heartbeat_ex_l2:
+ Common.GeneratedKey = true;
+ Setting.Values.MyKey = Common.MyKey;
+ Common.SendPackage(ID.ALL, PackageType.Heartbeat_ex_l3);
+
+ break;
+
+ case PackageType.Heartbeat_ex_l3:
+ Common.GeneratedKey = true;
+ Setting.Values.MyKey = Common.MyKey;
+
+ break;
+
+ case PackageType.Awake:
+ Common.PackageReceived.Heartbeat++;
+ _ = Common.AddToMachinePool(package);
+ Common.HumanBeingDetected();
+ break;
+
+ case PackageType.Hello:
+ Common.PackageReceived.Hello++;
+ Common.SendHeartBeat();
+ string newMachine = Common.AddToMachinePool(package);
+ if (Setting.Values.MachineMatrixString == null)
+ {
+ string tip = newMachine + " saying Hello!";
+ tip += "\r\n Right Click to setup your machine Matrix";
+ Common.ShowToolTip(tip);
+ }
+
+ break;
+
+ case PackageType.Hi:
+ Common.PackageReceived.Hello++;
+ break;
+
+ case PackageType.ByeBye:
+ Common.PackageReceived.ByeBye++;
+ Common.ProcessByeByeMessage(package);
+ break;
+
+ case PackageType.Clipboard:
+ Common.PackageReceived.Clipboard++;
+ if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop)
+ {
+ Common.clipboardCopiedTime = Common.GetTick();
+ GetNameOfMachineWithClipboardData(package);
+ SignalBigClipboardData();
+ }
+
+ break;
+
+ case PackageType.MachineSwitched:
+ if (Common.GetTick() - Common.clipboardCopiedTime < Common.BIG_CLIPBOARD_DATA_TIMEOUT && (package.Des == Common.MachineID))
+ {
+ Common.clipboardCopiedTime = 0;
+ Common.GetRemoteClipboard("PackageType.MachineSwitched");
+ }
+
+ break;
+
+ case PackageType.ClipboardCapture:
+ Common.PackageReceived.Clipboard++;
+ if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop)
+ {
+ if (package.Des == Common.MachineID || package.Des == ID.ALL)
+ {
+ GetNameOfMachineWithClipboardData(package);
+ Common.GetRemoteClipboard("mspaint," + Common.LastMachineWithClipboardData);
+ }
+ }
+
+ break;
+
+ case PackageType.CaptureScreenCommand:
+ Common.PackageReceived.Clipboard++;
+ if (package.Des == Common.MachineID || package.Des == ID.ALL)
+ {
+ Common.SendImage(package.Src, Common.CaptureScreen());
+ }
+
+ break;
+
+ case PackageType.ClipboardAsk:
+ Common.PackageReceived.ClipboardAsk++;
+
+ if (package.Des == Common.MachineID)
+ {
+ _ = Task.Run(() =>
+ {
+ try
+ {
+ System.Threading.Thread thread = Thread.CurrentThread;
+ thread.Name = $"{nameof(PackageType.ClipboardAsk)}.{thread.ManagedThreadId}";
+ Thread.UpdateThreads(thread);
+
+ string remoteMachine = package.MachineName;
+ System.Net.Sockets.TcpClient client = Common.ConnectToRemoteClipboardSocket(remoteMachine);
+ bool clientPushData = true;
+
+ if (Common.ShakeHand(ref remoteMachine, client.Client, out Stream enStream, out Stream deStream, ref clientPushData, ref package.PostAction))
+ {
+ SocketStuff.SendClipboardData(client.Client, enStream);
+ }
+ }
+ catch (Exception e)
+ {
+ Logger.Log(e);
+ }
+ });
+ }
+
+ break;
+
+ case PackageType.ClipboardDragDrop:
+ Common.PackageReceived.ClipboardDragDrop++;
+ Common.DragDropStep08(package);
+ break;
+
+ case PackageType.ClipboardDragDropOperation:
+ Common.PackageReceived.ClipboardDragDrop++;
+ Common.DragDropStep08_2(package);
+ break;
+
+ case PackageType.ClipboardDragDropEnd:
+ Common.PackageReceived.ClipboardDragDropEnd++;
+ Common.DragDropStep12();
+ break;
+
+ case PackageType.ClipboardText:
+ case PackageType.ClipboardImage:
+ Common.clipboardCopiedTime = 0;
+ if (package.Type == PackageType.ClipboardImage)
+ {
+ Common.PackageReceived.ClipboardImage++;
+ }
+ else
+ {
+ Common.PackageReceived.ClipboardText++;
+ }
+
+ if (tcp != null)
+ {
+ Common.ReceiveClipboardDataUsingTCP(
+ package,
+ package.Type == PackageType.ClipboardImage,
+ tcp);
+ }
+
+ break;
+
+ case PackageType.HideMouse:
+ Common.HasSwitchedMachineSinceLastCopy = true;
+ Common.HideMouseCursor(true);
+ Common.MainFormDotEx(false);
+ Common.ReleaseAllKeys();
+ break;
+
+ default:
+ if ((package.Type & PackageType.Matrix) == PackageType.Matrix)
+ {
+ Common.PackageReceived.Matrix++;
+ Common.UpdateMachineMatrix(package);
+ break;
+ }
+ else
+ {
+ // We should never get to this point!
+ Logger.Log("Invalid package received!");
+ return;
+ }
+ }
+ }
+
+ internal static void GetNameOfMachineWithClipboardData(DATA package)
+ {
+ Common.LastIDWithClipboardData = package.Src;
+ List matchingMachines = Common.MachinePool.TryFindMachineByID(Common.LastIDWithClipboardData);
+ if (matchingMachines.Count >= 1)
+ {
+ Common.LastMachineWithClipboardData = matchingMachines[0].Name.Trim();
+ }
+
+ /*
+ lastMachineWithClipboardData =
+ Common.GetString(BitConverter.GetBytes(package.machineNameHead));
+ lastMachineWithClipboardData +=
+ Common.GetString(BitConverter.GetBytes(package.machineNameTail));
+ lastMachineWithClipboardData = lastMachineWithClipboardData.Trim();
+ * */
+ }
+
+ private static void SignalBigClipboardData()
+ {
+ Logger.LogDebug("SignalBigClipboardData");
+ Common.SetToggleIcon(new int[Common.TOGGLE_ICONS_SIZE] { Common.ICON_BIG_CLIPBOARD, -1, Common.ICON_BIG_CLIPBOARD, -1 });
+ }
+}
diff --git a/src/modules/MouseWithoutBorders/App/Core/Thread.cs b/src/modules/MouseWithoutBorders/App/Core/Thread.cs
new file mode 100644
index 0000000000..1ce276e903
--- /dev/null
+++ b/src/modules/MouseWithoutBorders/App/Core/Thread.cs
@@ -0,0 +1,105 @@
+// 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.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.Threading;
+
+//
+// Logging.
+//
+//
+// 2008 created by Truong Do (ductdo).
+// 2009-... modified by Truong Do (TruongDo).
+// 2023- Included in PowerToys.
+//
+namespace MouseWithoutBorders.Core;
+
+internal sealed class Thread
+{
+ private static readonly Lock ThreadsLock = new();
+ private static List threads;
+
+ private readonly System.Threading.Thread thread;
+
+ internal Thread(ThreadStart callback, string name)
+ {
+ UpdateThreads(thread = new System.Threading.Thread(callback) { Name = name });
+ }
+
+ internal Thread(ParameterizedThreadStart callback, string name)
+ {
+ UpdateThreads(thread = new System.Threading.Thread(callback) { Name = name });
+ }
+
+ internal static void UpdateThreads(System.Threading.Thread thread)
+ {
+ lock (ThreadsLock)
+ {
+ bool found = false;
+ List toBeRemovedThreads = new();
+ threads ??= new List();
+
+ foreach (System.Threading.Thread t in threads)
+ {
+ if (!t.IsAlive)
+ {
+ toBeRemovedThreads.Add(t);
+ }
+ else if (t.ManagedThreadId == thread.ManagedThreadId)
+ {
+ found = true;
+ }
+ }
+
+ foreach (System.Threading.Thread t in toBeRemovedThreads)
+ {
+ _ = threads.Remove(t);
+ }
+
+ if (!found)
+ {
+ threads.Add(thread);
+ }
+ }
+ }
+
+ internal static string DumpThreadsStack()
+ {
+ string stack = "\r\nMANAGED THREADS: " + threads.Count.ToString(CultureInfo.InvariantCulture) + "\r\n";
+ stack += Logger.GetStackTrace(new StackTrace());
+ return stack;
+ }
+
+ internal void SetApartmentState(ApartmentState apartmentState)
+ {
+ thread.SetApartmentState(apartmentState);
+ }
+
+ internal void Start()
+ {
+ thread.Start();
+ }
+
+ internal void Start(object parameter)
+ {
+ thread.Start(parameter);
+ }
+
+ internal static void Sleep(int millisecondsTimeout)
+ {
+ System.Threading.Thread.Sleep(millisecondsTimeout);
+ }
+
+ internal static System.Threading.Thread CurrentThread => System.Threading.Thread.CurrentThread;
+
+ internal ThreadPriority Priority
+ {
+ get => thread.Priority;
+ set => thread.Priority = value;
+ }
+
+ internal System.Threading.ThreadState ThreadState => thread.ThreadState;
+}
diff --git a/src/modules/MouseWithoutBorders/MouseWithoutBorders.UnitTests/Core/Logger.PrivateDump.expected.txt b/src/modules/MouseWithoutBorders/MouseWithoutBorders.UnitTests/Core/Logger.PrivateDump.expected.txt
index 1a20c67b31..dddef136c4 100644
--- a/src/modules/MouseWithoutBorders/MouseWithoutBorders.UnitTests/Core/Logger.PrivateDump.expected.txt
+++ b/src/modules/MouseWithoutBorders/MouseWithoutBorders.UnitTests/Core/Logger.PrivateDump.expected.txt
@@ -4,20 +4,28 @@
[Other Logs]
===============
= MouseWithoutBorders.Common
-lastClipboardEventTime = 0
-clipboardCopiedTime = 0
Comma = System.Char[]
--System.Char[] = System.Char[]: N/A
Star = System.Char[]
--System.Char[] = System.Char[]: N/A
NullSeparator = System.Char[]
--System.Char[] = System.Char[]: N/A
+lastClipboardEventTime = 0
+clipboardCopiedTime = 0
k__BackingField = NONE
k__BackingField = 0
k__BackingField = False
lastClipboardObject =
k__BackingField = False
-ClipboardThreadOldLock = O
+ClipboardThreadOldLock = Lock
+--_owningThreadId = 0
+--_state = 0
+--_recursionCount = 0
+--_spinCount = 22
+--_waiterStartTimeMs = 0
+--s_contentionCount = 0
+--s_maxSpinCount = 22
+--s_minSpinCountForAdaptiveSpin = -100
screenWidth = 0
screenHeight = 0
lastX = 0
@@ -43,7 +51,15 @@ socketMutexBalance = 0
k__BackingField = False
k__BackingField = 0
k__BackingField = 0
-InputSimulationLock = O
+InputSimulationLock = Lock
+--_owningThreadId = 0
+--_state = 0
+--_recursionCount = 0
+--_spinCount = 22
+--_waiterStartTimeMs = 0
+--s_contentionCount = 0
+--s_maxSpinCount = 22
+--s_minSpinCountForAdaptiveSpin = -100
lastSendNextMachine = 0
lastInputEventCount = 0
lastRealInputEventCount = 0
@@ -85,15 +101,7 @@ LegalKeyDictionary = Concurrent.ConcurrentDictionary`2[System.String,System.Byte
------[5] = 0
------[6] = 0
------[7] = 0
-------[8] = 0
-------[9] = 0
-------[10] = 0
-------[11] = 0
-------[12] = 0
-------[13] = 0
-------[14] = 0
-------[15] = 0
---_budget = 2
+--_budget = ????????????
--_growLockArray = True
--_comparerIsDefaultForClasses = False
KeybdPackage = MouseWithoutBorders.DATA
@@ -155,7 +163,15 @@ ReopenSocketDueToReadError = False
--MaxValue = 31/12/9999 23:59:59
--UnixEpoch = 01/01/1970 00:00:00
lastReleaseAllKeysCall = 0
-McMatrixLock = O
+McMatrixLock = Lock
+--_owningThreadId = 0
+--_state = 0
+--_recursionCount = 0
+--_spinCount = 22
+--_waiterStartTimeMs = 0
+--s_contentionCount = 0
+--s_maxSpinCount = 22
+--s_minSpinCountForAdaptiveSpin = -100
desMachineID = NONE
DesMachineName =
newDesMachineID = NONE
@@ -207,66 +223,6 @@ PackageReceived = MouseWithoutBorders.PackageMonitor
--ExplorerDragDrop = 0
--Nil = 0
PackageID = 0
-QUEUE_SIZE = 50
-RecentProcessedPackageIDs = 32[]
---[0] = 0
---[1] = 0
---[2] = 0
---[3] = 0
---[4] = 0
---[5] = 0
---[6] = 0
---[7] = 0
---[8] = 0
---[9] = 0
---[10] = 0
---[11] = 0
---[12] = 0
---[13] = 0
---[14] = 0
---[15] = 0
---[16] = 0
---[17] = 0
---[18] = 0
---[19] = 0
---[20] = 0
---[21] = 0
---[22] = 0
---[23] = 0
---[24] = 0
---[25] = 0
---[26] = 0
---[27] = 0
---[28] = 0
---[29] = 0
---[30] = 0
---[31] = 0
---[32] = 0
---[33] = 0
---[34] = 0
---[35] = 0
---[36] = 0
---[37] = 0
---[38] = 0
---[39] = 0
---[40] = 0
---[41] = 0
---[42] = 0
---[43] = 0
---[44] = 0
---[45] = 0
---[46] = 0
---[47] = 0
---[48] = 0
---[49] = 0
-recentProcessedPackageIndex = 0
-processedPackageCount = 0
-skippedPackageCount = 0
-k__BackingField = 0
-lastXY = {X=0,Y=0}
---x = 0
---y = 0
---Empty = {X=0,Y=0}
shownErrMessage = False
lastStartServiceTime = ????????????
--_dateData = ????????????
@@ -334,9 +290,17 @@ WM_KEYDOWN = 256
WM_KEYUP = 257
WM_SYSKEYDOWN = 260
WM_SYSKEYUP = 261
-[Logger Logs]
+[Logger]
===============
-AllLogsLock = O
+AllLogsLock = Lock
+--_owningThreadId = 0
+--_state = 0
+--_recursionCount = 0
+--_spinCount = 22
+--_waiterStartTimeMs = 0
+--s_contentionCount = 0
+--s_maxSpinCount = 22
+--s_minSpinCountForAdaptiveSpin = -100
LogCounter = Concurrent.ConcurrentDictionary`2[System.String,32]
--_tables = Concurrent.ConcurrentDictionary`2+Tables[System.String,32]
----_comparer = Generic.NonRandomizedStringEqualityComparer+OrdinalComparer
@@ -354,15 +318,7 @@ LogCounter = Concurrent.ConcurrentDictionary`2[System.String,32]
------[5] = 0
------[6] = 0
------[7] = 0
-------[8] = 0
-------[9] = 0
-------[10] = 0
-------[11] = 0
-------[12] = 0
-------[13] = 0
-------[14] = 0
-------[15] = 0
---_budget = 2
+--_budget = ????????????
--_growLockArray = True
--_comparerIsDefaultForClasses = False
allLogsIndex = 0
@@ -402,3 +358,65 @@ 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}
+[Receiver]
+===============
+QUEUE_SIZE = 50
+RecentProcessedPackageIDs = 32[]
+--[0] = 0
+--[1] = 0
+--[2] = 0
+--[3] = 0
+--[4] = 0
+--[5] = 0
+--[6] = 0
+--[7] = 0
+--[8] = 0
+--[9] = 0
+--[10] = 0
+--[11] = 0
+--[12] = 0
+--[13] = 0
+--[14] = 0
+--[15] = 0
+--[16] = 0
+--[17] = 0
+--[18] = 0
+--[19] = 0
+--[20] = 0
+--[21] = 0
+--[22] = 0
+--[23] = 0
+--[24] = 0
+--[25] = 0
+--[26] = 0
+--[27] = 0
+--[28] = 0
+--[29] = 0
+--[30] = 0
+--[31] = 0
+--[32] = 0
+--[33] = 0
+--[34] = 0
+--[35] = 0
+--[36] = 0
+--[37] = 0
+--[38] = 0
+--[39] = 0
+--[40] = 0
+--[41] = 0
+--[42] = 0
+--[43] = 0
+--[44] = 0
+--[45] = 0
+--[46] = 0
+--[47] = 0
+--[48] = 0
+--[49] = 0
+recentProcessedPackageIndex = 0
+processedPackageCount = 0
+skippedPackageCount = 0
+k__BackingField = 0
+lastXY = {X=0,Y=0}
+--x = 0
+--y = 0
+--Empty = {X=0,Y=0}
diff --git a/src/modules/MouseWithoutBorders/MouseWithoutBorders.UnitTests/Core/LoggerTests.cs b/src/modules/MouseWithoutBorders/MouseWithoutBorders.UnitTests/Core/LoggerTests.cs
index be960b9a9b..a3d3a173f1 100644
--- a/src/modules/MouseWithoutBorders/MouseWithoutBorders.UnitTests/Core/LoggerTests.cs
+++ b/src/modules/MouseWithoutBorders/MouseWithoutBorders.UnitTests/Core/LoggerTests.cs
@@ -62,6 +62,7 @@ public static class LoggerTests
"lastJump = ",
"lastStartServiceTime = ",
"InitialIV = ",
+ "--_budget = ",
};
for (var i = 0; i < lines.Length; i++)
{
@@ -89,6 +90,10 @@ public static class LoggerTests
"------[13] = 0",
"------[14] = 0",
"------[15] = 0",
+ "------[16] = 0",
+ "------[17] = 0",
+ "------[18] = 0",
+ "------[19] = 0",
};
lines = lines.Where(line => !removeLines.Contains(line)).ToArray();
@@ -113,8 +118,10 @@ public static class LoggerTests
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 Logs]\r\n===============");
+ sb.AppendLine("[Logger]\r\n===============");
Logger.DumpType(sb, typeof(Logger), 0, settingsDumpObjectsLevel);
+ sb.AppendLine("[Receiver]\r\n===============");
+ Logger.DumpType(sb, typeof(Receiver), 0, settingsDumpObjectsLevel);
var actual = sb.ToString();
expected = NormalizeLog(expected);
@@ -146,8 +153,6 @@ public static class LoggerTests
message.AppendLine(CultureInfo.InvariantCulture, $"[{j}]: {expectedLines[j]}:");
}
- var x = new ConcurrentDictionary(-1, 16);
-
Assert.Fail(message.ToString());
}
}