mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-09 20:57:22 +02:00
[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:
@@ -153,7 +153,7 @@ namespace MouseWithoutBorders
|
|||||||
|
|
||||||
string filePath = stringData;
|
string filePath = stringData;
|
||||||
|
|
||||||
_ = Common.ImpersonateLoggedOnUserAndDoSomething(() =>
|
_ = Launch.ImpersonateLoggedOnUserAndDoSomething(() =>
|
||||||
{
|
{
|
||||||
if (File.Exists(filePath) || Directory.Exists(filePath))
|
if (File.Exists(filePath) || Directory.Exists(filePath))
|
||||||
{
|
{
|
||||||
@@ -579,7 +579,7 @@ namespace MouseWithoutBorders
|
|||||||
{
|
{
|
||||||
if (postAct.Equals("desktop", StringComparison.OrdinalIgnoreCase))
|
if (postAct.Equals("desktop", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
_ = ImpersonateLoggedOnUserAndDoSomething(() =>
|
_ = Launch.ImpersonateLoggedOnUserAndDoSomething(() =>
|
||||||
{
|
{
|
||||||
savingFolder = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\MouseWithoutBorders\\";
|
savingFolder = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\MouseWithoutBorders\\";
|
||||||
|
|
||||||
@@ -696,7 +696,7 @@ namespace MouseWithoutBorders
|
|||||||
Path.GetFileName(fileName),
|
Path.GetFileName(fileName),
|
||||||
remoteMachine);
|
remoteMachine);
|
||||||
|
|
||||||
_ = ImpersonateLoggedOnUserAndDoSomething(() =>
|
_ = Launch.ImpersonateLoggedOnUserAndDoSomething(() =>
|
||||||
{
|
{
|
||||||
ProcessStartInfo startInfo = new();
|
ProcessStartInfo startInfo = new();
|
||||||
startInfo.UseShellExecute = true;
|
startInfo.UseShellExecute = true;
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -93,7 +93,7 @@ namespace MouseWithoutBorders
|
|||||||
|
|
||||||
internal static void Init()
|
internal static void Init()
|
||||||
{
|
{
|
||||||
_ = Common.GetUserName();
|
_ = Helper.GetUserName();
|
||||||
Common.GeneratedKey = true;
|
Common.GeneratedKey = true;
|
||||||
|
|
||||||
try
|
try
|
||||||
@@ -148,7 +148,7 @@ namespace MouseWithoutBorders
|
|||||||
|
|
||||||
private static void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e)
|
private static void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e)
|
||||||
{
|
{
|
||||||
Common.WndProcCounter++;
|
Helper.WndProcCounter++;
|
||||||
|
|
||||||
if (e.Mode is PowerModes.Resume or PowerModes.Suspend)
|
if (e.Mode is PowerModes.Resume or PowerModes.Suspend)
|
||||||
{
|
{
|
||||||
@@ -167,21 +167,21 @@ namespace MouseWithoutBorders
|
|||||||
watchDogThread.Start();
|
watchDogThread.Start();
|
||||||
*/
|
*/
|
||||||
|
|
||||||
helper = new Thread(new ThreadStart(HelperThread), "Helper Thread");
|
helper = new Thread(new ThreadStart(Helper.HelperThread), "Helper Thread");
|
||||||
helper.SetApartmentState(ApartmentState.STA);
|
helper.SetApartmentState(ApartmentState.STA);
|
||||||
helper.Start();
|
helper.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void AskHelperThreadsToExit(int waitTime)
|
private static void AskHelperThreadsToExit(int waitTime)
|
||||||
{
|
{
|
||||||
signalHelperToExit = true;
|
Helper.signalHelperToExit = true;
|
||||||
signalWatchDogToExit = true;
|
Helper.signalWatchDogToExit = true;
|
||||||
_ = EvSwitch.Set();
|
_ = EvSwitch.Set();
|
||||||
|
|
||||||
int c = 0;
|
int c = 0;
|
||||||
if (helper != null && c < waitTime)
|
if (helper != null && c < waitTime)
|
||||||
{
|
{
|
||||||
while (signalHelperToExit)
|
while (Helper.signalHelperToExit)
|
||||||
{
|
{
|
||||||
Thread.Sleep(1);
|
Thread.Sleep(1);
|
||||||
}
|
}
|
||||||
@@ -251,7 +251,7 @@ namespace MouseWithoutBorders
|
|||||||
private static void NetworkChange_NetworkAvailabilityChanged(object sender, NetworkAvailabilityEventArgs e)
|
private static void NetworkChange_NetworkAvailabilityChanged(object sender, NetworkAvailabilityEventArgs e)
|
||||||
{
|
{
|
||||||
Logger.LogDebug("NetworkAvailabilityEventArgs.IsAvailable: " + e.IsAvailable.ToString(CultureInfo.InvariantCulture));
|
Logger.LogDebug("NetworkAvailabilityEventArgs.IsAvailable: " + e.IsAvailable.ToString(CultureInfo.InvariantCulture));
|
||||||
Common.WndProcCounter++;
|
Helper.WndProcCounter++;
|
||||||
ScheduleReopenSocketsDueToNetworkChanges(!e.IsAvailable);
|
ScheduleReopenSocketsDueToNetworkChanges(!e.IsAvailable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -269,7 +269,7 @@ namespace MouseWithoutBorders
|
|||||||
if (!Common.RunWithNoAdminRight)
|
if (!Common.RunWithNoAdminRight)
|
||||||
{
|
{
|
||||||
Logger.LogDebug("*** Starting on active Desktop: " + desktopToRunMouseWithoutBordersOn);
|
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())
|
if (!IsMyDesktopActive() || Common.CurrentProcess.SessionId != NativeMethods.WTSGetActiveConsoleSessionId())
|
||||||
{
|
{
|
||||||
Common.RunDDHelper(true);
|
Helper.RunDDHelper(true);
|
||||||
int waitCount = 20;
|
int waitCount = 20;
|
||||||
|
|
||||||
while (NativeMethods.WTSGetActiveConsoleSessionId() == 0xFFFFFFFF && waitCount > 0)
|
while (NativeMethods.WTSGetActiveConsoleSessionId() == 0xFFFFFFFF && waitCount > 0)
|
||||||
|
|||||||
@@ -101,8 +101,10 @@ namespace MouseWithoutBorders
|
|||||||
private static bool runOnLogonDesktop;
|
private static bool runOnLogonDesktop;
|
||||||
private static bool runOnScrSaverDesktop;
|
private static bool runOnScrSaverDesktop;
|
||||||
|
|
||||||
private static int[] toggleIcons;
|
#pragma warning disable SA1307 // Accessible fields should begin with upper-case letter
|
||||||
private static int toggleIconsIndex;
|
internal static int[] toggleIcons;
|
||||||
|
internal static int toggleIconsIndex;
|
||||||
|
#pragma warning restore SA1307
|
||||||
internal const int TOGGLE_ICONS_SIZE = 4;
|
internal const int TOGGLE_ICONS_SIZE = 4;
|
||||||
internal const int ICON_ONE = 0;
|
internal const int ICON_ONE = 0;
|
||||||
internal const int ICON_ALL = 1;
|
internal const int ICON_ALL = 1;
|
||||||
@@ -114,7 +116,9 @@ namespace MouseWithoutBorders
|
|||||||
internal const int NETWORK_STREAM_BUF_SIZE = 1024 * 1024;
|
internal const int NETWORK_STREAM_BUF_SIZE = 1024 * 1024;
|
||||||
internal static readonly EventWaitHandle EvSwitch = new(false, EventResetMode.AutoReset);
|
internal static readonly EventWaitHandle EvSwitch = new(false, EventResetMode.AutoReset);
|
||||||
private static Point lastPos;
|
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 long lastReconnectByHotKeyTime;
|
||||||
private static int tcpPort;
|
private static int tcpPort;
|
||||||
private static bool secondOpenSocketTry;
|
private static bool secondOpenSocketTry;
|
||||||
@@ -543,7 +547,7 @@ namespace MouseWithoutBorders
|
|||||||
internal static void SendAwakeBeat()
|
internal static void SendAwakeBeat()
|
||||||
{
|
{
|
||||||
if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop && Common.IsMyDesktopActive() &&
|
if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop && Common.IsMyDesktopActive() &&
|
||||||
Setting.Values.BlockScreenSaver && lastRealInputEventCount != Common.RealInputEventCount)
|
Setting.Values.BlockScreenSaver && lastRealInputEventCount != Event.RealInputEventCount)
|
||||||
{
|
{
|
||||||
SendPackage(ID.ALL, PackageType.Awake);
|
SendPackage(ID.ALL, PackageType.Awake);
|
||||||
}
|
}
|
||||||
@@ -552,13 +556,13 @@ namespace MouseWithoutBorders
|
|||||||
SendHeartBeat();
|
SendHeartBeat();
|
||||||
}
|
}
|
||||||
|
|
||||||
lastInputEventCount = Common.InputEventCount;
|
lastInputEventCount = Event.InputEventCount;
|
||||||
lastRealInputEventCount = Common.RealInputEventCount;
|
lastRealInputEventCount = Event.RealInputEventCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void HumanBeingDetected()
|
internal static void HumanBeingDetected()
|
||||||
{
|
{
|
||||||
if (lastInputEventCount == Common.InputEventCount)
|
if (lastInputEventCount == Event.InputEventCount)
|
||||||
{
|
{
|
||||||
if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop && Common.IsMyDesktopActive())
|
if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop && Common.IsMyDesktopActive())
|
||||||
{
|
{
|
||||||
@@ -566,7 +570,7 @@ namespace MouseWithoutBorders
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lastInputEventCount = Common.InputEventCount;
|
lastInputEventCount = Event.InputEventCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void PokeMyself()
|
private static void PokeMyself()
|
||||||
@@ -581,7 +585,7 @@ namespace MouseWithoutBorders
|
|||||||
InputSimulation.MoveMouseRelative(-x, -y);
|
InputSimulation.MoveMouseRelative(-x, -y);
|
||||||
Thread.Sleep(50);
|
Thread.Sleep(50);
|
||||||
|
|
||||||
if (lastInputEventCount != Common.InputEventCount)
|
if (lastInputEventCount != Event.InputEventCount)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -590,8 +594,8 @@ namespace MouseWithoutBorders
|
|||||||
|
|
||||||
internal static void InitLastInputEventCount()
|
internal static void InitLastInputEventCount()
|
||||||
{
|
{
|
||||||
lastInputEventCount = Common.InputEventCount;
|
lastInputEventCount = Event.InputEventCount;
|
||||||
lastRealInputEventCount = Common.RealInputEventCount;
|
lastRealInputEventCount = Event.RealInputEventCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void SendHello()
|
internal static void SendHello()
|
||||||
@@ -665,7 +669,7 @@ namespace MouseWithoutBorders
|
|||||||
{
|
{
|
||||||
Common.DoSomethingInUIThread(() =>
|
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);
|
Common.MMSleep(0.2);
|
||||||
InputSimulation.SendKey(new KEYBDDATA() { wVk = (int)VK.SNAPSHOT });
|
InputSimulation.SendKey(new KEYBDDATA() { wVk = (int)VK.SNAPSHOT });
|
||||||
@@ -674,14 +678,14 @@ namespace MouseWithoutBorders
|
|||||||
Logger.LogDebug("PrepareScreenCapture: SNAPSHOT simulated.");
|
Logger.LogDebug("PrepareScreenCapture: SNAPSHOT simulated.");
|
||||||
|
|
||||||
_ = NativeMethods.MoveWindow(
|
_ = NativeMethods.MoveWindow(
|
||||||
(IntPtr)NativeMethods.FindWindow(null, Common.HELPER_FORM_TEXT),
|
(IntPtr)NativeMethods.FindWindow(null, Helper.HELPER_FORM_TEXT),
|
||||||
MachineStuff.DesktopBounds.Left,
|
MachineStuff.DesktopBounds.Left,
|
||||||
MachineStuff.DesktopBounds.Top,
|
MachineStuff.DesktopBounds.Top,
|
||||||
MachineStuff.DesktopBounds.Right - MachineStuff.DesktopBounds.Left,
|
MachineStuff.DesktopBounds.Right - MachineStuff.DesktopBounds.Left,
|
||||||
MachineStuff.DesktopBounds.Bottom - MachineStuff.DesktopBounds.Top,
|
MachineStuff.DesktopBounds.Bottom - MachineStuff.DesktopBounds.Top,
|
||||||
false);
|
false);
|
||||||
|
|
||||||
_ = Common.SendMessageToHelper(0x406, IntPtr.Zero, IntPtr.Zero, false);
|
_ = Helper.SendMessageToHelper(0x406, IntPtr.Zero, IntPtr.Zero, false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -698,7 +702,7 @@ namespace MouseWithoutBorders
|
|||||||
// {
|
// {
|
||||||
// Process.Start("explorer", "\"" + file + "\"");
|
// Process.Start("explorer", "\"" + file + "\"");
|
||||||
// });
|
// });
|
||||||
_ = CreateProcessInInputDesktopSession(
|
_ = Launch.CreateProcessInInputDesktopSession(
|
||||||
"\"" + Environment.ExpandEnvironmentVariables(@"%SystemRoot%\System32\Mspaint.exe") +
|
"\"" + Environment.ExpandEnvironmentVariables(@"%SystemRoot%\System32\Mspaint.exe") +
|
||||||
"\"",
|
"\"",
|
||||||
"\"" + file + "\"",
|
"\"" + file + "\"",
|
||||||
@@ -956,8 +960,8 @@ namespace MouseWithoutBorders
|
|||||||
{
|
{
|
||||||
// SwitchToMachine(MachineName.Trim());
|
// SwitchToMachine(MachineName.Trim());
|
||||||
MachineStuff.NewDesMachineID = DesMachineID = MachineID;
|
MachineStuff.NewDesMachineID = DesMachineID = MachineID;
|
||||||
MachineStuff.SwitchLocation.X = XY_BY_PIXEL + myLastX;
|
MachineStuff.SwitchLocation.X = Event.XY_BY_PIXEL + Event.myLastX;
|
||||||
MachineStuff.SwitchLocation.Y = XY_BY_PIXEL + myLastY;
|
MachineStuff.SwitchLocation.Y = Event.XY_BY_PIXEL + Event.myLastY;
|
||||||
MachineStuff.SwitchLocation.ResetCount();
|
MachineStuff.SwitchLocation.ResetCount();
|
||||||
EvSwitch.Set();
|
EvSwitch.Set();
|
||||||
}
|
}
|
||||||
@@ -1314,7 +1318,7 @@ namespace MouseWithoutBorders
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_ = ImpersonateLoggedOnUserAndDoSomething(() =>
|
_ = Launch.ImpersonateLoggedOnUserAndDoSomething(() =>
|
||||||
{
|
{
|
||||||
st = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + @"\" + Common.BinaryName;
|
st = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + @"\" + Common.BinaryName;
|
||||||
if (!Directory.Exists(st))
|
if (!Directory.Exists(st))
|
||||||
|
|||||||
@@ -206,7 +206,7 @@ namespace MouseWithoutBorders.Class
|
|||||||
{
|
{
|
||||||
int rv = 1, dx = 0, dy = 0;
|
int rv = 1, dx = 0, dy = 0;
|
||||||
bool local = false;
|
bool local = false;
|
||||||
Common.InputEventCount++;
|
Event.InputEventCount++;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -220,14 +220,14 @@ namespace MouseWithoutBorders.Class
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Common.RealInputEventCount++;
|
Event.RealInputEventCount++;
|
||||||
|
|
||||||
if (MachineStuff.NewDesMachineID == Common.MachineID || MachineStuff.NewDesMachineID == ID.ALL)
|
if (MachineStuff.NewDesMachineID == Common.MachineID || MachineStuff.NewDesMachineID == ID.ALL)
|
||||||
{
|
{
|
||||||
local = true;
|
local = true;
|
||||||
if (Common.MainFormVisible && !DragDrop.IsDropping)
|
if (Common.MainFormVisible && !DragDrop.IsDropping)
|
||||||
{
|
{
|
||||||
Common.MainFormDot();
|
Helper.MainFormDot();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -269,10 +269,10 @@ namespace MouseWithoutBorders.Class
|
|||||||
{
|
{
|
||||||
MachineStuff.SwitchLocation.Count--;
|
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.X = MachineStuff.SwitchLocation.X - Event.XY_BY_PIXEL;
|
||||||
hookCallbackMouseData.Y = MachineStuff.SwitchLocation.Y - Common.XY_BY_PIXEL;
|
hookCallbackMouseData.Y = MachineStuff.SwitchLocation.Y - Event.XY_BY_PIXEL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -308,8 +308,8 @@ namespace MouseWithoutBorders.Class
|
|||||||
hookCallbackMouseData.Y = MachineStuff.PrimaryScreenBounds.Bottom + 1;
|
hookCallbackMouseData.Y = MachineStuff.PrimaryScreenBounds.Bottom + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
dx += dx < 0 ? -Common.MOVE_MOUSE_RELATIVE : Common.MOVE_MOUSE_RELATIVE;
|
dx += dx < 0 ? -Event.MOVE_MOUSE_RELATIVE : Event.MOVE_MOUSE_RELATIVE;
|
||||||
dy += dy < 0 ? -Common.MOVE_MOUSE_RELATIVE : Common.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)
|
private int KeyboardHookProc(int nCode, int wParam, IntPtr lParam)
|
||||||
{
|
{
|
||||||
Common.InputEventCount++;
|
Event.InputEventCount++;
|
||||||
if (!RealData)
|
if (!RealData)
|
||||||
{
|
{
|
||||||
return NativeMethods.CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
|
return NativeMethods.CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
Common.RealInputEventCount++;
|
Event.RealInputEventCount++;
|
||||||
|
|
||||||
keyboardHookStruct = LParamToKeyboardHookStruct(lParam);
|
keyboardHookStruct = LParamToKeyboardHookStruct(lParam);
|
||||||
hookCallbackKeybdData.dwFlags = keyboardHookStruct.Flags;
|
hookCallbackKeybdData.dwFlags = keyboardHookStruct.Flags;
|
||||||
|
|||||||
@@ -223,7 +223,7 @@ namespace MouseWithoutBorders.Class
|
|||||||
|
|
||||||
if (Common.MainFormVisible && !DragDrop.IsDropping)
|
if (Common.MainFormVisible && !DragDrop.IsDropping)
|
||||||
{
|
{
|
||||||
Common.MainFormDot();
|
Helper.MainFormDot();
|
||||||
}
|
}
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ using Newtonsoft.Json;
|
|||||||
using StreamJsonRpc;
|
using StreamJsonRpc;
|
||||||
|
|
||||||
using Logger = MouseWithoutBorders.Core.Logger;
|
using Logger = MouseWithoutBorders.Core.Logger;
|
||||||
|
using SettingsHelper = Microsoft.PowerToys.Settings.UI.Library.Utilities.Helper;
|
||||||
using Thread = MouseWithoutBorders.Core.Thread;
|
using Thread = MouseWithoutBorders.Core.Thread;
|
||||||
|
|
||||||
[module: SuppressMessage("Microsoft.MSInternal", "CA904:DeclareTypesInMicrosoftOrSystemNamespace", Scope = "namespace", Target = "MouseWithoutBorders", Justification = "Dotnet port with style preservation")]
|
[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)
|
if (args.Length > 2)
|
||||||
{
|
{
|
||||||
Helper.UserLocalAppDataPath = args[2].Trim();
|
SettingsHelper.UserLocalAppDataPath = args[2].Trim();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -235,7 +236,7 @@ namespace MouseWithoutBorders.Class
|
|||||||
Application.SetCompatibleTextRenderingDefault(false);
|
Application.SetCompatibleTextRenderingDefault(false);
|
||||||
|
|
||||||
Common.Init();
|
Common.Init();
|
||||||
Common.WndProcCounter++;
|
Core.Helper.WndProcCounter++;
|
||||||
|
|
||||||
var formScreen = new FrmScreen();
|
var formScreen = new FrmScreen();
|
||||||
|
|
||||||
@@ -430,7 +431,7 @@ namespace MouseWithoutBorders.Class
|
|||||||
Logger.Log(e);
|
Logger.Log(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
Common.StartMouseWithoutBordersService();
|
Service.StartMouseWithoutBordersService();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static string User { get; set; }
|
internal static string User { get; set; }
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ using MouseWithoutBorders.Core;
|
|||||||
using Settings.UI.Library.Attributes;
|
using Settings.UI.Library.Attributes;
|
||||||
|
|
||||||
using Lock = System.Threading.Lock;
|
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.#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.#SaveSetting(System.String,System.Object)", Justification = "Dotnet port with style preservation")]
|
||||||
@@ -193,7 +194,7 @@ namespace MouseWithoutBorders.Class
|
|||||||
{
|
{
|
||||||
_settingsUtils = new SettingsUtils();
|
_settingsUtils = new SettingsUtils();
|
||||||
|
|
||||||
_watcher = Helper.GetFileWatcher("MouseWithoutBorders", "settings.json", () =>
|
_watcher = SettingsHelper.GetFileWatcher("MouseWithoutBorders", "settings.json", () =>
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1684,7 +1684,7 @@ namespace MouseWithoutBorders.Class
|
|||||||
{
|
{
|
||||||
string fileName = null;
|
string fileName = null;
|
||||||
|
|
||||||
if (!Common.ImpersonateLoggedOnUserAndDoSomething(() =>
|
if (!Launch.ImpersonateLoggedOnUserAndDoSomething(() =>
|
||||||
{
|
{
|
||||||
if (!File.Exists(Common.LastDragDropFile))
|
if (!File.Exists(Common.LastDragDropFile))
|
||||||
{
|
{
|
||||||
@@ -1873,7 +1873,7 @@ namespace MouseWithoutBorders.Class
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_ = Common.ImpersonateLoggedOnUserAndDoSomething(() => { r = SendFileEx(s, ecStream, fileName); });
|
_ = Launch.ImpersonateLoggedOnUserAndDoSomething(() => { r = SendFileEx(s, ecStream, fileName); });
|
||||||
}
|
}
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
@@ -2111,7 +2111,7 @@ namespace MouseWithoutBorders.Class
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = Common.CreateLowIntegrityProcess(
|
_ = Launch.CreateLowIntegrityProcess(
|
||||||
"\"" + Path.GetDirectoryName(Application.ExecutablePath) + "\\MouseWithoutBordersHelper.exe\"",
|
"\"" + Path.GetDirectoryName(Application.ExecutablePath) + "\\MouseWithoutBordersHelper.exe\"",
|
||||||
"InternalError" + " \"" + msg + "\"",
|
"InternalError" + " \"" + msg + "\"",
|
||||||
0,
|
0,
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ internal static class DragDrop
|
|||||||
{
|
{
|
||||||
if (!IsDropping)
|
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)
|
if (h.ToInt32() > 0)
|
||||||
{
|
{
|
||||||
_ = Interlocked.Exchange(ref dragDropStep05ExCalledByIpc, 0);
|
_ = Interlocked.Exchange(ref dragDropStep05ExCalledByIpc, 0);
|
||||||
@@ -189,7 +189,7 @@ internal static class DragDrop
|
|||||||
|
|
||||||
if (!IsDropping)
|
if (!IsDropping)
|
||||||
{
|
{
|
||||||
_ = Common.ImpersonateLoggedOnUserAndDoSomething(() =>
|
_ = Launch.ImpersonateLoggedOnUserAndDoSomething(() =>
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(dragFileName) && (File.Exists(dragFileName) || Directory.Exists(dragFileName)))
|
if (!string.IsNullOrEmpty(dragFileName) && (File.Exists(dragFileName) || Directory.Exists(dragFileName)))
|
||||||
{
|
{
|
||||||
|
|||||||
274
src/modules/MouseWithoutBorders/App/Core/Event.cs
Normal file
274
src/modules/MouseWithoutBorders/App/Core/Event.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
526
src/modules/MouseWithoutBorders/App/Core/Helper.cs
Normal file
526
src/modules/MouseWithoutBorders/App/Core/Helper.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
312
src/modules/MouseWithoutBorders/App/Core/Launch.cs
Normal file
312
src/modules/MouseWithoutBorders/App/Core/Launch.cs
Normal 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
|
||||||
|
}
|
||||||
@@ -138,7 +138,7 @@ internal static class Logger
|
|||||||
Common.PackageSent.ClipboardDragDrop,
|
Common.PackageSent.ClipboardDragDrop,
|
||||||
Common.PackageSent.ClipboardDragDropEnd,
|
Common.PackageSent.ClipboardDragDropEnd,
|
||||||
Common.PackageSent.ExplorerDragDrop,
|
Common.PackageSent.ExplorerDragDrop,
|
||||||
Common.inputEventCount,
|
Event.inputEventCount,
|
||||||
Common.PackageSent.Nil);
|
Common.PackageSent.Nil);
|
||||||
Log(log);
|
Log(log);
|
||||||
lastPackageSent = Common.PackageSent; // Copy data
|
lastPackageSent = Common.PackageSent; // Copy data
|
||||||
@@ -161,7 +161,7 @@ internal static class Logger
|
|||||||
Common.PackageReceived.ClipboardDragDrop,
|
Common.PackageReceived.ClipboardDragDrop,
|
||||||
Common.PackageReceived.ClipboardDragDropEnd,
|
Common.PackageReceived.ClipboardDragDropEnd,
|
||||||
Common.PackageReceived.ExplorerDragDrop,
|
Common.PackageReceived.ExplorerDragDrop,
|
||||||
Common.invalidPackageCount,
|
Event.invalidPackageCount,
|
||||||
Common.PackageReceived.Nil,
|
Common.PackageReceived.Nil,
|
||||||
Receiver.processedPackageCount,
|
Receiver.processedPackageCount,
|
||||||
Receiver.skippedPackageCount);
|
Receiver.skippedPackageCount);
|
||||||
@@ -197,15 +197,9 @@ internal static class Logger
|
|||||||
myThreads.Add(t);
|
myThreads.Add(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = Logger.PrivateDump(sb, AllLogs, "[Program logs]\r\n===============\r\n", 0, level, false);
|
Logger.DumpProgramLogs(sb, level);
|
||||||
_ = Logger.PrivateDump(sb, new Common(), "[Other Logs]\r\n===============\r\n", 0, level, false);
|
Logger.DumpOtherLogs(sb, level);
|
||||||
Logger.DumpType(sb, typeof(Logger), 0, level);
|
Logger.DumpStaticTypes(sb, 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);
|
|
||||||
|
|
||||||
log = string.Format(
|
log = string.Format(
|
||||||
CultureInfo.CurrentCulture,
|
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)
|
internal static bool PrivateDump(StringBuilder sb, object obj, string objName, int level, int maxLevel, bool stop)
|
||||||
{
|
{
|
||||||
Type t;
|
Type t;
|
||||||
|
|||||||
@@ -1018,8 +1018,8 @@ internal static class MachineStuff
|
|||||||
}
|
}
|
||||||
|
|
||||||
NewDesMachineID = Common.DesMachineID = id;
|
NewDesMachineID = Common.DesMachineID = id;
|
||||||
SwitchLocation.X = Common.XY_BY_PIXEL + primaryScreenBounds.Left + ((primaryScreenBounds.Right - primaryScreenBounds.Left) / 2);
|
SwitchLocation.X = Event.XY_BY_PIXEL + primaryScreenBounds.Left + ((primaryScreenBounds.Right - primaryScreenBounds.Left) / 2);
|
||||||
SwitchLocation.Y = Common.XY_BY_PIXEL + primaryScreenBounds.Top + ((primaryScreenBounds.Bottom - primaryScreenBounds.Top) / 2);
|
SwitchLocation.Y = Event.XY_BY_PIXEL + primaryScreenBounds.Top + ((primaryScreenBounds.Bottom - primaryScreenBounds.Top) / 2);
|
||||||
SwitchLocation.ResetCount();
|
SwitchLocation.ResetCount();
|
||||||
Common.UpdateMultipleModeIconAndMenu();
|
Common.UpdateMultipleModeIconAndMenu();
|
||||||
Common.HideMouseCursor(false);
|
Common.HideMouseCursor(false);
|
||||||
|
|||||||
@@ -41,12 +41,12 @@ internal static class Receiver
|
|||||||
{
|
{
|
||||||
if (package.Type == PackageType.Invalid)
|
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.ShowToolTip("Invalid packages received!", 1000, ToolTipIcon.Warning, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Common.InvalidPackageCount++;
|
Event.InvalidPackageCount++;
|
||||||
Logger.Log("Invalid packages received!");
|
Logger.Log("Invalid packages received!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -104,7 +104,7 @@ internal static class Receiver
|
|||||||
{
|
{
|
||||||
if ((package.Kd.dwFlags & (int)Common.LLKHF.UP) == (int)Common.LLKHF.UP)
|
if ((package.Kd.dwFlags & (int)Common.LLKHF.UP) == (int)Common.LLKHF.UP)
|
||||||
{
|
{
|
||||||
Common.ShowOneWayModeMessage();
|
Helper.ShowOneWayModeMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -133,7 +133,7 @@ internal static class Receiver
|
|||||||
{
|
{
|
||||||
if (package.Md.dwFlags is Common.WM_LBUTTONDOWN or Common.WM_RBUTTONDOWN)
|
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)
|
else if (package.Md.dwFlags is Common.WM_LBUTTONUP or Common.WM_RBUTTONUP)
|
||||||
@@ -144,13 +144,13 @@ internal static class Receiver
|
|||||||
return;
|
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)
|
if (package.Md.dwFlags == Common.WM_MOUSEMOVE)
|
||||||
{
|
{
|
||||||
InputSimulation.MoveMouseRelative(
|
InputSimulation.MoveMouseRelative(
|
||||||
package.Md.X < 0 ? package.Md.X + Common.MOVE_MOUSE_RELATIVE : package.Md.X - 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 + Common.MOVE_MOUSE_RELATIVE : package.Md.Y - Common.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);
|
_ = NativeMethods.GetCursorPos(ref lastXY);
|
||||||
|
|
||||||
Point p = MachineStuff.MoveToMyNeighbourIfNeeded(lastXY.X, lastXY.Y, Common.MachineID);
|
Point p = MachineStuff.MoveToMyNeighbourIfNeeded(lastXY.X, lastXY.Y, Common.MachineID);
|
||||||
@@ -195,9 +195,9 @@ internal static class Receiver
|
|||||||
case PackageType.NextMachine:
|
case PackageType.NextMachine:
|
||||||
Logger.LogDebug("PackageType.NextMachine received!");
|
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;
|
break;
|
||||||
@@ -383,7 +383,7 @@ internal static class Receiver
|
|||||||
case PackageType.HideMouse:
|
case PackageType.HideMouse:
|
||||||
Common.HasSwitchedMachineSinceLastCopy = true;
|
Common.HasSwitchedMachineSinceLastCopy = true;
|
||||||
Common.HideMouseCursor(true);
|
Common.HideMouseCursor(true);
|
||||||
Common.MainFormDotEx(false);
|
Helper.MainFormDotEx(false);
|
||||||
Common.ReleaseAllKeys();
|
Common.ReleaseAllKeys();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
159
src/modules/MouseWithoutBorders/App/Core/Service.cs
Normal file
159
src/modules/MouseWithoutBorders/App/Core/Service.cs
Normal 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}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -63,8 +63,8 @@ namespace MouseWithoutBorders
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
Common.Hook = new InputHook();
|
Common.Hook = new InputHook();
|
||||||
Common.Hook.MouseEvent += new InputHook.MouseEvHandler(Common.MouseEvent);
|
Common.Hook.MouseEvent += new InputHook.MouseEvHandler(Event.MouseEvent);
|
||||||
Common.Hook.KeyboardEvent += new InputHook.KeybdEvHandler(Common.KeybdEvent);
|
Common.Hook.KeyboardEvent += new InputHook.KeybdEvHandler(Event.KeybdEvent);
|
||||||
|
|
||||||
Logger.Log("(((((Keyboard/Mouse hooks installed/reinstalled!)))))");
|
Logger.Log("(((((Keyboard/Mouse hooks installed/reinstalled!)))))");
|
||||||
/* The hook is called in the context of the thread that installed it.
|
/* The hook is called in the context of the thread that installed it.
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ namespace MouseWithoutBorders
|
|||||||
|
|
||||||
internal void UpdateKeyTextBox()
|
internal void UpdateKeyTextBox()
|
||||||
{
|
{
|
||||||
_ = Common.GetUserName();
|
_ = Helper.GetUserName();
|
||||||
textBoxEnc.Text = Common.MyKey;
|
textBoxEnc.Text = Common.MyKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -787,7 +787,7 @@ namespace MouseWithoutBorders
|
|||||||
{
|
{
|
||||||
if (!Common.RunWithNoAdminRight)
|
if (!Common.RunWithNoAdminRight)
|
||||||
{
|
{
|
||||||
Common.ApplyCADSetting();
|
Helper.ApplyCADSetting();
|
||||||
ShowUpdateMessage();
|
ShowUpdateMessage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1163,7 +1163,7 @@ namespace MouseWithoutBorders
|
|||||||
|
|
||||||
private void LinkLabelMiniLog_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
private void LinkLabelMiniLog_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
||||||
{
|
{
|
||||||
string miniLog = Common.GetMiniLog(new[] { groupBoxOtherOptions.Controls, groupBoxShortcuts.Controls });
|
string miniLog = Helper.GetMiniLog(new[] { groupBoxOtherOptions.Controls, groupBoxShortcuts.Controls });
|
||||||
|
|
||||||
Clipboard.SetText(miniLog);
|
Clipboard.SetText(miniLog);
|
||||||
Common.ShowToolTip("Log has been placed in the clipboard.", 30000, ToolTipIcon.Info, false);
|
Common.ShowToolTip("Log has been placed in the clipboard.", 30000, ToolTipIcon.Info, false);
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ namespace MouseWithoutBorders
|
|||||||
NotifyIcon.BalloonTipTitle = Application.ProductName;
|
NotifyIcon.BalloonTipTitle = Application.ProductName;
|
||||||
menuGenDumpFile.Visible = true;
|
menuGenDumpFile.Visible = true;
|
||||||
|
|
||||||
Common.WndProcCounter++;
|
Helper.WndProcCounter++;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -101,7 +101,7 @@ namespace MouseWithoutBorders
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Common.StartServiceAndSendLogoffSignal();
|
Service.StartServiceAndSendLogoffSignal();
|
||||||
Quit(true, true);
|
Quit(true, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -119,7 +119,7 @@ namespace MouseWithoutBorders
|
|||||||
NotifyIcon.Dispose();
|
NotifyIcon.Dispose();
|
||||||
if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop)
|
if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop)
|
||||||
{
|
{
|
||||||
Common.RunDDHelper(true);
|
Helper.RunDDHelper(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Common.UnhookClipboard();
|
// Common.UnhookClipboard();
|
||||||
@@ -133,7 +133,7 @@ namespace MouseWithoutBorders
|
|||||||
|
|
||||||
Setting.Values.SwitchCount += Common.SwitchCount;
|
Setting.Values.SwitchCount += Common.SwitchCount;
|
||||||
Process me = Process.GetCurrentProcess();
|
Process me = Process.GetCurrentProcess();
|
||||||
Common.WndProcCounter++;
|
Helper.WndProcCounter++;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -142,13 +142,13 @@ namespace MouseWithoutBorders
|
|||||||
Common.Cleanup();
|
Common.Cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
Common.WndProcCounter++;
|
Helper.WndProcCounter++;
|
||||||
if (!Common.RunOnScrSaverDesktop)
|
if (!Common.RunOnScrSaverDesktop)
|
||||||
{
|
{
|
||||||
Common.ReleaseAllKeys();
|
Common.ReleaseAllKeys();
|
||||||
}
|
}
|
||||||
|
|
||||||
Common.RunDDHelper(true);
|
Helper.RunDDHelper(true);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@@ -285,7 +285,7 @@ namespace MouseWithoutBorders
|
|||||||
helperTimer.Interval = 100;
|
helperTimer.Interval = 100;
|
||||||
helperTimer.Tick += new EventHandler(HelperTimer_Tick);
|
helperTimer.Tick += new EventHandler(HelperTimer_Tick);
|
||||||
helperTimer.Start();
|
helperTimer.Start();
|
||||||
Common.WndProcCounter++;
|
Helper.WndProcCounter++;
|
||||||
|
|
||||||
if (Environment.OSVersion.Version.Major > 6 ||
|
if (Environment.OSVersion.Version.Major > 6 ||
|
||||||
(Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor >= 1))
|
(Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor >= 1))
|
||||||
@@ -307,7 +307,7 @@ namespace MouseWithoutBorders
|
|||||||
|
|
||||||
private void HelperTimer_Tick(object sender, EventArgs e)
|
private void HelperTimer_Tick(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
Common.WndProcCounter++;
|
Helper.WndProcCounter++;
|
||||||
|
|
||||||
if (busy)
|
if (busy)
|
||||||
{
|
{
|
||||||
@@ -338,7 +338,7 @@ namespace MouseWithoutBorders
|
|||||||
|
|
||||||
if (Common.MainFormVisible)
|
if (Common.MainFormVisible)
|
||||||
{
|
{
|
||||||
Common.MainFormDot();
|
Helper.MainFormDot();
|
||||||
}
|
}
|
||||||
|
|
||||||
InputSimulation.ResetSystemKeyFlags();
|
InputSimulation.ResetSystemKeyFlags();
|
||||||
@@ -357,7 +357,7 @@ namespace MouseWithoutBorders
|
|||||||
{
|
{
|
||||||
if (!Common.SecondOpenSocketTry)
|
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.
|
// 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.");
|
Logger.LogDebug("No active user.");
|
||||||
@@ -407,7 +407,7 @@ namespace MouseWithoutBorders
|
|||||||
// Common.ReHookClipboard();
|
// Common.ReHookClipboard();
|
||||||
}
|
}
|
||||||
|
|
||||||
Common.RunDDHelper();
|
Helper.RunDDHelper();
|
||||||
}
|
}
|
||||||
|
|
||||||
count = 0;
|
count = 0;
|
||||||
@@ -485,7 +485,7 @@ namespace MouseWithoutBorders
|
|||||||
// One more time after 1/3 minutes (Sometimes XP has explorer started late)
|
// One more time after 1/3 minutes (Sometimes XP has explorer started late)
|
||||||
if (count == 600 || count == 1800)
|
if (count == 600 || count == 1800)
|
||||||
{
|
{
|
||||||
Common.RunDDHelper();
|
Helper.RunDDHelper();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count == 600)
|
if (count == 600)
|
||||||
@@ -545,7 +545,7 @@ namespace MouseWithoutBorders
|
|||||||
|
|
||||||
if (Common.ToggleIcons != null)
|
if (Common.ToggleIcons != null)
|
||||||
{
|
{
|
||||||
Common.ToggleIcon();
|
Helper.ToggleIcon();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count % 20 == 0)
|
if (count % 20 == 0)
|
||||||
@@ -578,13 +578,13 @@ namespace MouseWithoutBorders
|
|||||||
}
|
}
|
||||||
else if ((count % 36005) == 0)
|
else if ((count % 36005) == 0)
|
||||||
{// One hour
|
{// One hour
|
||||||
Common.SaveSwitchCount();
|
Event.SaveSwitchCount();
|
||||||
|
|
||||||
int rv = 0;
|
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;
|
break;
|
||||||
|
|
||||||
case NativeMethods.WM_HIDE_DRAG_DROP:
|
case NativeMethods.WM_HIDE_DRAG_DROP:
|
||||||
Common.MainFormDot();
|
Helper.MainFormDot();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
this.Width = 1;
|
this.Width = 1;
|
||||||
@@ -795,14 +795,14 @@ namespace MouseWithoutBorders
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case NativeMethods.WM_HIDE_DD_HELPER:
|
case NativeMethods.WM_HIDE_DD_HELPER:
|
||||||
Common.MainForm3Pixels();
|
Helper.MainForm3Pixels();
|
||||||
Common.MMSleep(0.2);
|
Common.MMSleep(0.2);
|
||||||
if (m.WParam.ToInt32() == 1)
|
if (m.WParam.ToInt32() == 1)
|
||||||
{
|
{
|
||||||
InputSimulation.MouseUp(); // A file is being dragged
|
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)
|
if (h.ToInt32() > 0)
|
||||||
{
|
{
|
||||||
@@ -831,7 +831,7 @@ namespace MouseWithoutBorders
|
|||||||
|
|
||||||
case WM_QUERYENDSESSION:
|
case WM_QUERYENDSESSION:
|
||||||
Logger.LogDebug("WM_QUERYENDSESSION...");
|
Logger.LogDebug("WM_QUERYENDSESSION...");
|
||||||
Common.StartServiceAndSendLogoffSignal();
|
Service.StartServiceAndSendLogoffSignal();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_ENDSESSION:
|
case WM_ENDSESSION:
|
||||||
|
|||||||
@@ -99,6 +99,111 @@ LegalKeyDictionary = Concurrent.ConcurrentDictionary`2[System.String,System.Byte
|
|||||||
--_budget = ????????????
|
--_budget = ????????????
|
||||||
--_growLockArray = True
|
--_growLockArray = True
|
||||||
--_comparerIsDefaultForClasses = False
|
--_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
|
KeybdPackage = MouseWithoutBorders.DATA
|
||||||
--Type = 0
|
--Type = 0
|
||||||
--Id = 0
|
--Id = 0
|
||||||
@@ -144,113 +249,15 @@ actualLastPos = {X=0,Y=0}
|
|||||||
--Empty = {X=0,Y=0}
|
--Empty = {X=0,Y=0}
|
||||||
myLastX = 0
|
myLastX = 0
|
||||||
myLastY = 0
|
myLastY = 0
|
||||||
|
[Helper]
|
||||||
|
===============
|
||||||
signalHelperToExit = False
|
signalHelperToExit = False
|
||||||
signalWatchDogToExit = False
|
signalWatchDogToExit = False
|
||||||
WndProcCounter = 0
|
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
|
HELPER_FORM_TEXT = Mouse without Borders Helper
|
||||||
HelperProcessName = PowerToys.MouseWithoutBordersHelper
|
HelperProcessName = PowerToys.MouseWithoutBordersHelper
|
||||||
PACKAGE_SIZE = 32
|
[Launch]
|
||||||
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
|
|
||||||
[Logger]
|
[Logger]
|
||||||
===============
|
===============
|
||||||
AllLogsLock = Lock
|
AllLogsLock = Lock
|
||||||
@@ -319,13 +326,6 @@ MAX_LOG = 10000
|
|||||||
MaxLogExceptionPerHour = 1000
|
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}
|
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}
|
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]
|
[MachineStuff]
|
||||||
===============
|
===============
|
||||||
McMatrixLock = Lock
|
McMatrixLock = Lock
|
||||||
@@ -424,3 +424,11 @@ lastXY = {X=0,Y=0}
|
|||||||
--x = 0
|
--x = 0
|
||||||
--y = 0
|
--y = 0
|
||||||
--Empty = {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
|
||||||
|
|||||||
@@ -114,18 +114,11 @@ public static class LoggerTests
|
|||||||
using var streamReader = new StreamReader(stream);
|
using var streamReader = new StreamReader(stream);
|
||||||
var expected = streamReader.ReadToEnd();
|
var expected = streamReader.ReadToEnd();
|
||||||
|
|
||||||
// copied from DumpObjects in Common.Log.cs
|
// copied from DumpObjects in Logger.cs
|
||||||
var sb = new StringBuilder(1000000);
|
var sb = new StringBuilder(1000000);
|
||||||
_ = Logger.PrivateDump(sb, Logger.AllLogs, "[Program logs]\r\n===============\r\n", 0, settingsDumpObjectsLevel, false);
|
Logger.DumpProgramLogs(sb, settingsDumpObjectsLevel);
|
||||||
_ = Logger.PrivateDump(sb, new Common(), "[Other Logs]\r\n===============\r\n", 0, settingsDumpObjectsLevel, false);
|
Logger.DumpOtherLogs(sb, settingsDumpObjectsLevel);
|
||||||
sb.AppendLine("[Logger]\r\n===============");
|
Logger.DumpStaticTypes(sb, settingsDumpObjectsLevel);
|
||||||
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);
|
|
||||||
var actual = sb.ToString();
|
var actual = sb.ToString();
|
||||||
|
|
||||||
expected = NormalizeLog(expected);
|
expected = NormalizeLog(expected);
|
||||||
|
|||||||
Reference in New Issue
Block a user