mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-05 02:36:19 +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;
|
||||
|
||||
_ = Common.ImpersonateLoggedOnUserAndDoSomething(() =>
|
||||
_ = Launch.ImpersonateLoggedOnUserAndDoSomething(() =>
|
||||
{
|
||||
if (File.Exists(filePath) || Directory.Exists(filePath))
|
||||
{
|
||||
@@ -579,7 +579,7 @@ namespace MouseWithoutBorders
|
||||
{
|
||||
if (postAct.Equals("desktop", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
_ = ImpersonateLoggedOnUserAndDoSomething(() =>
|
||||
_ = Launch.ImpersonateLoggedOnUserAndDoSomething(() =>
|
||||
{
|
||||
savingFolder = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\MouseWithoutBorders\\";
|
||||
|
||||
@@ -696,7 +696,7 @@ namespace MouseWithoutBorders
|
||||
Path.GetFileName(fileName),
|
||||
remoteMachine);
|
||||
|
||||
_ = ImpersonateLoggedOnUserAndDoSomething(() =>
|
||||
_ = Launch.ImpersonateLoggedOnUserAndDoSomething(() =>
|
||||
{
|
||||
ProcessStartInfo startInfo = new();
|
||||
startInfo.UseShellExecute = true;
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
_ = Common.GetUserName();
|
||||
_ = Helper.GetUserName();
|
||||
Common.GeneratedKey = true;
|
||||
|
||||
try
|
||||
@@ -148,7 +148,7 @@ namespace MouseWithoutBorders
|
||||
|
||||
private static void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e)
|
||||
{
|
||||
Common.WndProcCounter++;
|
||||
Helper.WndProcCounter++;
|
||||
|
||||
if (e.Mode is PowerModes.Resume or PowerModes.Suspend)
|
||||
{
|
||||
@@ -167,21 +167,21 @@ namespace MouseWithoutBorders
|
||||
watchDogThread.Start();
|
||||
*/
|
||||
|
||||
helper = new Thread(new ThreadStart(HelperThread), "Helper Thread");
|
||||
helper = new Thread(new ThreadStart(Helper.HelperThread), "Helper Thread");
|
||||
helper.SetApartmentState(ApartmentState.STA);
|
||||
helper.Start();
|
||||
}
|
||||
|
||||
private static void AskHelperThreadsToExit(int waitTime)
|
||||
{
|
||||
signalHelperToExit = true;
|
||||
signalWatchDogToExit = true;
|
||||
Helper.signalHelperToExit = true;
|
||||
Helper.signalWatchDogToExit = true;
|
||||
_ = EvSwitch.Set();
|
||||
|
||||
int c = 0;
|
||||
if (helper != null && c < waitTime)
|
||||
{
|
||||
while (signalHelperToExit)
|
||||
while (Helper.signalHelperToExit)
|
||||
{
|
||||
Thread.Sleep(1);
|
||||
}
|
||||
@@ -251,7 +251,7 @@ namespace MouseWithoutBorders
|
||||
private static void NetworkChange_NetworkAvailabilityChanged(object sender, NetworkAvailabilityEventArgs e)
|
||||
{
|
||||
Logger.LogDebug("NetworkAvailabilityEventArgs.IsAvailable: " + e.IsAvailable.ToString(CultureInfo.InvariantCulture));
|
||||
Common.WndProcCounter++;
|
||||
Helper.WndProcCounter++;
|
||||
ScheduleReopenSocketsDueToNetworkChanges(!e.IsAvailable);
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
Logger.LogDebug("*** Starting on active Desktop: " + desktopToRunMouseWithoutBordersOn);
|
||||
StartMouseWithoutBordersService(desktopToRunMouseWithoutBordersOn);
|
||||
Service.StartMouseWithoutBordersService(desktopToRunMouseWithoutBordersOn);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -279,7 +279,7 @@ namespace MouseWithoutBorders
|
||||
{
|
||||
if (!IsMyDesktopActive() || Common.CurrentProcess.SessionId != NativeMethods.WTSGetActiveConsoleSessionId())
|
||||
{
|
||||
Common.RunDDHelper(true);
|
||||
Helper.RunDDHelper(true);
|
||||
int waitCount = 20;
|
||||
|
||||
while (NativeMethods.WTSGetActiveConsoleSessionId() == 0xFFFFFFFF && waitCount > 0)
|
||||
|
||||
@@ -101,8 +101,10 @@ namespace MouseWithoutBorders
|
||||
private static bool runOnLogonDesktop;
|
||||
private static bool runOnScrSaverDesktop;
|
||||
|
||||
private static int[] toggleIcons;
|
||||
private static int toggleIconsIndex;
|
||||
#pragma warning disable SA1307 // Accessible fields should begin with upper-case letter
|
||||
internal static int[] toggleIcons;
|
||||
internal static int toggleIconsIndex;
|
||||
#pragma warning restore SA1307
|
||||
internal const int TOGGLE_ICONS_SIZE = 4;
|
||||
internal const int ICON_ONE = 0;
|
||||
internal const int ICON_ALL = 1;
|
||||
@@ -114,7 +116,9 @@ namespace MouseWithoutBorders
|
||||
internal const int NETWORK_STREAM_BUF_SIZE = 1024 * 1024;
|
||||
internal static readonly EventWaitHandle EvSwitch = new(false, EventResetMode.AutoReset);
|
||||
private static Point lastPos;
|
||||
private static int switchCount;
|
||||
#pragma warning disable SA1307 // Accessible fields should begin with upper-case names
|
||||
internal static int switchCount;
|
||||
#pragma warning restore SA1307
|
||||
private static long lastReconnectByHotKeyTime;
|
||||
private static int tcpPort;
|
||||
private static bool secondOpenSocketTry;
|
||||
@@ -543,7 +547,7 @@ namespace MouseWithoutBorders
|
||||
internal static void SendAwakeBeat()
|
||||
{
|
||||
if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop && Common.IsMyDesktopActive() &&
|
||||
Setting.Values.BlockScreenSaver && lastRealInputEventCount != Common.RealInputEventCount)
|
||||
Setting.Values.BlockScreenSaver && lastRealInputEventCount != Event.RealInputEventCount)
|
||||
{
|
||||
SendPackage(ID.ALL, PackageType.Awake);
|
||||
}
|
||||
@@ -552,13 +556,13 @@ namespace MouseWithoutBorders
|
||||
SendHeartBeat();
|
||||
}
|
||||
|
||||
lastInputEventCount = Common.InputEventCount;
|
||||
lastRealInputEventCount = Common.RealInputEventCount;
|
||||
lastInputEventCount = Event.InputEventCount;
|
||||
lastRealInputEventCount = Event.RealInputEventCount;
|
||||
}
|
||||
|
||||
internal static void HumanBeingDetected()
|
||||
{
|
||||
if (lastInputEventCount == Common.InputEventCount)
|
||||
if (lastInputEventCount == Event.InputEventCount)
|
||||
{
|
||||
if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop && Common.IsMyDesktopActive())
|
||||
{
|
||||
@@ -566,7 +570,7 @@ namespace MouseWithoutBorders
|
||||
}
|
||||
}
|
||||
|
||||
lastInputEventCount = Common.InputEventCount;
|
||||
lastInputEventCount = Event.InputEventCount;
|
||||
}
|
||||
|
||||
private static void PokeMyself()
|
||||
@@ -581,7 +585,7 @@ namespace MouseWithoutBorders
|
||||
InputSimulation.MoveMouseRelative(-x, -y);
|
||||
Thread.Sleep(50);
|
||||
|
||||
if (lastInputEventCount != Common.InputEventCount)
|
||||
if (lastInputEventCount != Event.InputEventCount)
|
||||
{
|
||||
break;
|
||||
}
|
||||
@@ -590,8 +594,8 @@ namespace MouseWithoutBorders
|
||||
|
||||
internal static void InitLastInputEventCount()
|
||||
{
|
||||
lastInputEventCount = Common.InputEventCount;
|
||||
lastRealInputEventCount = Common.RealInputEventCount;
|
||||
lastInputEventCount = Event.InputEventCount;
|
||||
lastRealInputEventCount = Event.RealInputEventCount;
|
||||
}
|
||||
|
||||
internal static void SendHello()
|
||||
@@ -665,7 +669,7 @@ namespace MouseWithoutBorders
|
||||
{
|
||||
Common.DoSomethingInUIThread(() =>
|
||||
{
|
||||
if (!DragDrop.MouseDown && Common.SendMessageToHelper(0x401, IntPtr.Zero, IntPtr.Zero) > 0)
|
||||
if (!DragDrop.MouseDown && Helper.SendMessageToHelper(0x401, IntPtr.Zero, IntPtr.Zero) > 0)
|
||||
{
|
||||
Common.MMSleep(0.2);
|
||||
InputSimulation.SendKey(new KEYBDDATA() { wVk = (int)VK.SNAPSHOT });
|
||||
@@ -674,14 +678,14 @@ namespace MouseWithoutBorders
|
||||
Logger.LogDebug("PrepareScreenCapture: SNAPSHOT simulated.");
|
||||
|
||||
_ = NativeMethods.MoveWindow(
|
||||
(IntPtr)NativeMethods.FindWindow(null, Common.HELPER_FORM_TEXT),
|
||||
(IntPtr)NativeMethods.FindWindow(null, Helper.HELPER_FORM_TEXT),
|
||||
MachineStuff.DesktopBounds.Left,
|
||||
MachineStuff.DesktopBounds.Top,
|
||||
MachineStuff.DesktopBounds.Right - MachineStuff.DesktopBounds.Left,
|
||||
MachineStuff.DesktopBounds.Bottom - MachineStuff.DesktopBounds.Top,
|
||||
false);
|
||||
|
||||
_ = Common.SendMessageToHelper(0x406, IntPtr.Zero, IntPtr.Zero, false);
|
||||
_ = Helper.SendMessageToHelper(0x406, IntPtr.Zero, IntPtr.Zero, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -698,7 +702,7 @@ namespace MouseWithoutBorders
|
||||
// {
|
||||
// Process.Start("explorer", "\"" + file + "\"");
|
||||
// });
|
||||
_ = CreateProcessInInputDesktopSession(
|
||||
_ = Launch.CreateProcessInInputDesktopSession(
|
||||
"\"" + Environment.ExpandEnvironmentVariables(@"%SystemRoot%\System32\Mspaint.exe") +
|
||||
"\"",
|
||||
"\"" + file + "\"",
|
||||
@@ -956,8 +960,8 @@ namespace MouseWithoutBorders
|
||||
{
|
||||
// SwitchToMachine(MachineName.Trim());
|
||||
MachineStuff.NewDesMachineID = DesMachineID = MachineID;
|
||||
MachineStuff.SwitchLocation.X = XY_BY_PIXEL + myLastX;
|
||||
MachineStuff.SwitchLocation.Y = XY_BY_PIXEL + myLastY;
|
||||
MachineStuff.SwitchLocation.X = Event.XY_BY_PIXEL + Event.myLastX;
|
||||
MachineStuff.SwitchLocation.Y = Event.XY_BY_PIXEL + Event.myLastY;
|
||||
MachineStuff.SwitchLocation.ResetCount();
|
||||
EvSwitch.Set();
|
||||
}
|
||||
@@ -1314,7 +1318,7 @@ namespace MouseWithoutBorders
|
||||
}
|
||||
else
|
||||
{
|
||||
_ = ImpersonateLoggedOnUserAndDoSomething(() =>
|
||||
_ = Launch.ImpersonateLoggedOnUserAndDoSomething(() =>
|
||||
{
|
||||
st = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + @"\" + Common.BinaryName;
|
||||
if (!Directory.Exists(st))
|
||||
|
||||
@@ -206,7 +206,7 @@ namespace MouseWithoutBorders.Class
|
||||
{
|
||||
int rv = 1, dx = 0, dy = 0;
|
||||
bool local = false;
|
||||
Common.InputEventCount++;
|
||||
Event.InputEventCount++;
|
||||
|
||||
try
|
||||
{
|
||||
@@ -220,14 +220,14 @@ namespace MouseWithoutBorders.Class
|
||||
}
|
||||
else
|
||||
{
|
||||
Common.RealInputEventCount++;
|
||||
Event.RealInputEventCount++;
|
||||
|
||||
if (MachineStuff.NewDesMachineID == Common.MachineID || MachineStuff.NewDesMachineID == ID.ALL)
|
||||
{
|
||||
local = true;
|
||||
if (Common.MainFormVisible && !DragDrop.IsDropping)
|
||||
{
|
||||
Common.MainFormDot();
|
||||
Helper.MainFormDot();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -269,10 +269,10 @@ namespace MouseWithoutBorders.Class
|
||||
{
|
||||
MachineStuff.SwitchLocation.Count--;
|
||||
|
||||
if (MachineStuff.SwitchLocation.X > Common.XY_BY_PIXEL - 100000 || MachineStuff.SwitchLocation.Y > Common.XY_BY_PIXEL - 100000)
|
||||
if (MachineStuff.SwitchLocation.X > Event.XY_BY_PIXEL - 100000 || MachineStuff.SwitchLocation.Y > Event.XY_BY_PIXEL - 100000)
|
||||
{
|
||||
hookCallbackMouseData.X = MachineStuff.SwitchLocation.X - Common.XY_BY_PIXEL;
|
||||
hookCallbackMouseData.Y = MachineStuff.SwitchLocation.Y - Common.XY_BY_PIXEL;
|
||||
hookCallbackMouseData.X = MachineStuff.SwitchLocation.X - Event.XY_BY_PIXEL;
|
||||
hookCallbackMouseData.Y = MachineStuff.SwitchLocation.Y - Event.XY_BY_PIXEL;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -308,8 +308,8 @@ namespace MouseWithoutBorders.Class
|
||||
hookCallbackMouseData.Y = MachineStuff.PrimaryScreenBounds.Bottom + 1;
|
||||
}
|
||||
|
||||
dx += dx < 0 ? -Common.MOVE_MOUSE_RELATIVE : Common.MOVE_MOUSE_RELATIVE;
|
||||
dy += dy < 0 ? -Common.MOVE_MOUSE_RELATIVE : Common.MOVE_MOUSE_RELATIVE;
|
||||
dx += dx < 0 ? -Event.MOVE_MOUSE_RELATIVE : Event.MOVE_MOUSE_RELATIVE;
|
||||
dy += dy < 0 ? -Event.MOVE_MOUSE_RELATIVE : Event.MOVE_MOUSE_RELATIVE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -336,13 +336,13 @@ namespace MouseWithoutBorders.Class
|
||||
|
||||
private int KeyboardHookProc(int nCode, int wParam, IntPtr lParam)
|
||||
{
|
||||
Common.InputEventCount++;
|
||||
Event.InputEventCount++;
|
||||
if (!RealData)
|
||||
{
|
||||
return NativeMethods.CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
|
||||
}
|
||||
|
||||
Common.RealInputEventCount++;
|
||||
Event.RealInputEventCount++;
|
||||
|
||||
keyboardHookStruct = LParamToKeyboardHookStruct(lParam);
|
||||
hookCallbackKeybdData.dwFlags = keyboardHookStruct.Flags;
|
||||
|
||||
@@ -223,7 +223,7 @@ namespace MouseWithoutBorders.Class
|
||||
|
||||
if (Common.MainFormVisible && !DragDrop.IsDropping)
|
||||
{
|
||||
Common.MainFormDot();
|
||||
Helper.MainFormDot();
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
||||
@@ -36,6 +36,7 @@ using Newtonsoft.Json;
|
||||
using StreamJsonRpc;
|
||||
|
||||
using Logger = MouseWithoutBorders.Core.Logger;
|
||||
using SettingsHelper = Microsoft.PowerToys.Settings.UI.Library.Utilities.Helper;
|
||||
using Thread = MouseWithoutBorders.Core.Thread;
|
||||
|
||||
[module: SuppressMessage("Microsoft.MSInternal", "CA904:DeclareTypesInMicrosoftOrSystemNamespace", Scope = "namespace", Target = "MouseWithoutBorders", Justification = "Dotnet port with style preservation")]
|
||||
@@ -128,7 +129,7 @@ namespace MouseWithoutBorders.Class
|
||||
{
|
||||
if (args.Length > 2)
|
||||
{
|
||||
Helper.UserLocalAppDataPath = args[2].Trim();
|
||||
SettingsHelper.UserLocalAppDataPath = args[2].Trim();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,7 +236,7 @@ namespace MouseWithoutBorders.Class
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
|
||||
Common.Init();
|
||||
Common.WndProcCounter++;
|
||||
Core.Helper.WndProcCounter++;
|
||||
|
||||
var formScreen = new FrmScreen();
|
||||
|
||||
@@ -430,7 +431,7 @@ namespace MouseWithoutBorders.Class
|
||||
Logger.Log(e);
|
||||
}
|
||||
|
||||
Common.StartMouseWithoutBordersService();
|
||||
Service.StartMouseWithoutBordersService();
|
||||
}
|
||||
|
||||
internal static string User { get; set; }
|
||||
|
||||
@@ -33,6 +33,7 @@ using MouseWithoutBorders.Core;
|
||||
using Settings.UI.Library.Attributes;
|
||||
|
||||
using Lock = System.Threading.Lock;
|
||||
using SettingsHelper = Microsoft.PowerToys.Settings.UI.Library.Utilities.Helper;
|
||||
|
||||
[module: SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Scope = "member", Target = "MouseWithoutBorders.Properties.Setting.Values.#LoadIntSetting(System.String,System.Int32)", Justification = "Dotnet port with style preservation")]
|
||||
[module: SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Scope = "member", Target = "MouseWithoutBorders.Properties.Setting.Values.#SaveSetting(System.String,System.Object)", Justification = "Dotnet port with style preservation")]
|
||||
@@ -193,7 +194,7 @@ namespace MouseWithoutBorders.Class
|
||||
{
|
||||
_settingsUtils = new SettingsUtils();
|
||||
|
||||
_watcher = Helper.GetFileWatcher("MouseWithoutBorders", "settings.json", () =>
|
||||
_watcher = SettingsHelper.GetFileWatcher("MouseWithoutBorders", "settings.json", () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
@@ -1684,7 +1684,7 @@ namespace MouseWithoutBorders.Class
|
||||
{
|
||||
string fileName = null;
|
||||
|
||||
if (!Common.ImpersonateLoggedOnUserAndDoSomething(() =>
|
||||
if (!Launch.ImpersonateLoggedOnUserAndDoSomething(() =>
|
||||
{
|
||||
if (!File.Exists(Common.LastDragDropFile))
|
||||
{
|
||||
@@ -1873,7 +1873,7 @@ namespace MouseWithoutBorders.Class
|
||||
}
|
||||
else
|
||||
{
|
||||
_ = Common.ImpersonateLoggedOnUserAndDoSomething(() => { r = SendFileEx(s, ecStream, fileName); });
|
||||
_ = Launch.ImpersonateLoggedOnUserAndDoSomething(() => { r = SendFileEx(s, ecStream, fileName); });
|
||||
}
|
||||
|
||||
return r;
|
||||
@@ -2111,7 +2111,7 @@ namespace MouseWithoutBorders.Class
|
||||
}
|
||||
}
|
||||
|
||||
_ = Common.CreateLowIntegrityProcess(
|
||||
_ = Launch.CreateLowIntegrityProcess(
|
||||
"\"" + Path.GetDirectoryName(Application.ExecutablePath) + "\\MouseWithoutBordersHelper.exe\"",
|
||||
"InternalError" + " \"" + msg + "\"",
|
||||
0,
|
||||
|
||||
@@ -132,7 +132,7 @@ internal static class DragDrop
|
||||
{
|
||||
if (!IsDropping)
|
||||
{
|
||||
IntPtr h = (IntPtr)NativeMethods.FindWindow(null, Common.HELPER_FORM_TEXT);
|
||||
IntPtr h = (IntPtr)NativeMethods.FindWindow(null, Helper.HELPER_FORM_TEXT);
|
||||
if (h.ToInt32() > 0)
|
||||
{
|
||||
_ = Interlocked.Exchange(ref dragDropStep05ExCalledByIpc, 0);
|
||||
@@ -189,7 +189,7 @@ internal static class DragDrop
|
||||
|
||||
if (!IsDropping)
|
||||
{
|
||||
_ = Common.ImpersonateLoggedOnUserAndDoSomething(() =>
|
||||
_ = Launch.ImpersonateLoggedOnUserAndDoSomething(() =>
|
||||
{
|
||||
if (!string.IsNullOrEmpty(dragFileName) && (File.Exists(dragFileName) || Directory.Exists(dragFileName)))
|
||||
{
|
||||
|
||||
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.ClipboardDragDropEnd,
|
||||
Common.PackageSent.ExplorerDragDrop,
|
||||
Common.inputEventCount,
|
||||
Event.inputEventCount,
|
||||
Common.PackageSent.Nil);
|
||||
Log(log);
|
||||
lastPackageSent = Common.PackageSent; // Copy data
|
||||
@@ -161,7 +161,7 @@ internal static class Logger
|
||||
Common.PackageReceived.ClipboardDragDrop,
|
||||
Common.PackageReceived.ClipboardDragDropEnd,
|
||||
Common.PackageReceived.ExplorerDragDrop,
|
||||
Common.invalidPackageCount,
|
||||
Event.invalidPackageCount,
|
||||
Common.PackageReceived.Nil,
|
||||
Receiver.processedPackageCount,
|
||||
Receiver.skippedPackageCount);
|
||||
@@ -197,15 +197,9 @@ internal static class Logger
|
||||
myThreads.Add(t);
|
||||
}
|
||||
|
||||
_ = Logger.PrivateDump(sb, AllLogs, "[Program logs]\r\n===============\r\n", 0, level, false);
|
||||
_ = Logger.PrivateDump(sb, new Common(), "[Other Logs]\r\n===============\r\n", 0, level, false);
|
||||
Logger.DumpType(sb, typeof(Logger), 0, level);
|
||||
sb.AppendLine("[DragDrop]\r\n===============");
|
||||
Logger.DumpType(sb, typeof(DragDrop), 0, level);
|
||||
sb.AppendLine("[MachineStuff]\r\n===============");
|
||||
Logger.DumpType(sb, typeof(MachineStuff), 0, level);
|
||||
sb.AppendLine("[Receiver]\r\n===============");
|
||||
Logger.DumpType(sb, typeof(Receiver), 0, level);
|
||||
Logger.DumpProgramLogs(sb, level);
|
||||
Logger.DumpOtherLogs(sb, level);
|
||||
Logger.DumpStaticTypes(sb, level);
|
||||
|
||||
log = string.Format(
|
||||
CultureInfo.CurrentCulture,
|
||||
@@ -241,6 +235,36 @@ internal static class Logger
|
||||
}
|
||||
}
|
||||
|
||||
internal static void DumpProgramLogs(StringBuilder sb, int level)
|
||||
{
|
||||
_ = Logger.PrivateDump(sb, AllLogs, "[Program logs]\r\n===============\r\n", 0, level, false);
|
||||
}
|
||||
|
||||
internal static void DumpOtherLogs(StringBuilder sb, int level)
|
||||
{
|
||||
_ = Logger.PrivateDump(sb, new Common(), "[Other Logs]\r\n===============\r\n", 0, level, false);
|
||||
}
|
||||
|
||||
internal static void DumpStaticTypes(StringBuilder sb, int level)
|
||||
{
|
||||
sb.AppendLine($"[{nameof(DragDrop)}]\r\n===============");
|
||||
Logger.DumpType(sb, typeof(DragDrop), 0, level);
|
||||
sb.AppendLine($"[{nameof(Event)}]\r\n===============");
|
||||
Logger.DumpType(sb, typeof(Event), 0, level);
|
||||
sb.AppendLine($"[{nameof(Helper)}]\r\n===============");
|
||||
Logger.DumpType(sb, typeof(Helper), 0, level);
|
||||
sb.AppendLine($"[{nameof(Launch)}]\r\n===============");
|
||||
Logger.DumpType(sb, typeof(Launch), 0, level);
|
||||
sb.AppendLine($"[{nameof(Logger)}]\r\n===============");
|
||||
Logger.DumpType(sb, typeof(Logger), 0, level);
|
||||
sb.AppendLine($"[{nameof(MachineStuff)}]\r\n===============");
|
||||
Logger.DumpType(sb, typeof(MachineStuff), 0, level);
|
||||
sb.AppendLine($"[{nameof(Receiver)}]\r\n===============");
|
||||
Logger.DumpType(sb, typeof(Receiver), 0, level);
|
||||
sb.AppendLine($"[{nameof(Service)}]\r\n===============");
|
||||
Logger.DumpType(sb, typeof(Service), 0, level);
|
||||
}
|
||||
|
||||
internal static bool PrivateDump(StringBuilder sb, object obj, string objName, int level, int maxLevel, bool stop)
|
||||
{
|
||||
Type t;
|
||||
|
||||
@@ -1018,8 +1018,8 @@ internal static class MachineStuff
|
||||
}
|
||||
|
||||
NewDesMachineID = Common.DesMachineID = id;
|
||||
SwitchLocation.X = Common.XY_BY_PIXEL + primaryScreenBounds.Left + ((primaryScreenBounds.Right - primaryScreenBounds.Left) / 2);
|
||||
SwitchLocation.Y = Common.XY_BY_PIXEL + primaryScreenBounds.Top + ((primaryScreenBounds.Bottom - primaryScreenBounds.Top) / 2);
|
||||
SwitchLocation.X = Event.XY_BY_PIXEL + primaryScreenBounds.Left + ((primaryScreenBounds.Right - primaryScreenBounds.Left) / 2);
|
||||
SwitchLocation.Y = Event.XY_BY_PIXEL + primaryScreenBounds.Top + ((primaryScreenBounds.Bottom - primaryScreenBounds.Top) / 2);
|
||||
SwitchLocation.ResetCount();
|
||||
Common.UpdateMultipleModeIconAndMenu();
|
||||
Common.HideMouseCursor(false);
|
||||
|
||||
@@ -41,12 +41,12 @@ internal static class Receiver
|
||||
{
|
||||
if (package.Type == PackageType.Invalid)
|
||||
{
|
||||
if ((Common.InvalidPackageCount % 100) == 0)
|
||||
if ((Event.InvalidPackageCount % 100) == 0)
|
||||
{
|
||||
Common.ShowToolTip("Invalid packages received!", 1000, ToolTipIcon.Warning, false);
|
||||
}
|
||||
|
||||
Common.InvalidPackageCount++;
|
||||
Event.InvalidPackageCount++;
|
||||
Logger.Log("Invalid packages received!");
|
||||
return false;
|
||||
}
|
||||
@@ -104,7 +104,7 @@ internal static class Receiver
|
||||
{
|
||||
if ((package.Kd.dwFlags & (int)Common.LLKHF.UP) == (int)Common.LLKHF.UP)
|
||||
{
|
||||
Common.ShowOneWayModeMessage();
|
||||
Helper.ShowOneWayModeMessage();
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -133,7 +133,7 @@ internal static class Receiver
|
||||
{
|
||||
if (package.Md.dwFlags is Common.WM_LBUTTONDOWN or Common.WM_RBUTTONDOWN)
|
||||
{
|
||||
Common.ShowOneWayModeMessage();
|
||||
Helper.ShowOneWayModeMessage();
|
||||
}
|
||||
}
|
||||
else if (package.Md.dwFlags is Common.WM_LBUTTONUP or Common.WM_RBUTTONUP)
|
||||
@@ -144,13 +144,13 @@ internal static class Receiver
|
||||
return;
|
||||
}
|
||||
|
||||
if (Math.Abs(package.Md.X) >= Common.MOVE_MOUSE_RELATIVE && Math.Abs(package.Md.Y) >= Common.MOVE_MOUSE_RELATIVE)
|
||||
if (Math.Abs(package.Md.X) >= Event.MOVE_MOUSE_RELATIVE && Math.Abs(package.Md.Y) >= Event.MOVE_MOUSE_RELATIVE)
|
||||
{
|
||||
if (package.Md.dwFlags == Common.WM_MOUSEMOVE)
|
||||
{
|
||||
InputSimulation.MoveMouseRelative(
|
||||
package.Md.X < 0 ? package.Md.X + Common.MOVE_MOUSE_RELATIVE : package.Md.X - Common.MOVE_MOUSE_RELATIVE,
|
||||
package.Md.Y < 0 ? package.Md.Y + Common.MOVE_MOUSE_RELATIVE : package.Md.Y - Common.MOVE_MOUSE_RELATIVE);
|
||||
package.Md.X < 0 ? package.Md.X + Event.MOVE_MOUSE_RELATIVE : package.Md.X - Event.MOVE_MOUSE_RELATIVE,
|
||||
package.Md.Y < 0 ? package.Md.Y + Event.MOVE_MOUSE_RELATIVE : package.Md.Y - Event.MOVE_MOUSE_RELATIVE);
|
||||
_ = NativeMethods.GetCursorPos(ref lastXY);
|
||||
|
||||
Point p = MachineStuff.MoveToMyNeighbourIfNeeded(lastXY.X, lastXY.Y, Common.MachineID);
|
||||
@@ -195,9 +195,9 @@ internal static class Receiver
|
||||
case PackageType.NextMachine:
|
||||
Logger.LogDebug("PackageType.NextMachine received!");
|
||||
|
||||
if (Common.IsSwitchingByMouseEnabled())
|
||||
if (Event.IsSwitchingByMouseEnabled())
|
||||
{
|
||||
Common.PrepareToSwitchToMachine((ID)package.Md.WheelDelta, new Point(package.Md.X, package.Md.Y));
|
||||
Event.PrepareToSwitchToMachine((ID)package.Md.WheelDelta, new Point(package.Md.X, package.Md.Y));
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -383,7 +383,7 @@ internal static class Receiver
|
||||
case PackageType.HideMouse:
|
||||
Common.HasSwitchedMachineSinceLastCopy = true;
|
||||
Common.HideMouseCursor(true);
|
||||
Common.MainFormDotEx(false);
|
||||
Helper.MainFormDotEx(false);
|
||||
Common.ReleaseAllKeys();
|
||||
break;
|
||||
|
||||
|
||||
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
|
||||
{
|
||||
Common.Hook = new InputHook();
|
||||
Common.Hook.MouseEvent += new InputHook.MouseEvHandler(Common.MouseEvent);
|
||||
Common.Hook.KeyboardEvent += new InputHook.KeybdEvHandler(Common.KeybdEvent);
|
||||
Common.Hook.MouseEvent += new InputHook.MouseEvHandler(Event.MouseEvent);
|
||||
Common.Hook.KeyboardEvent += new InputHook.KeybdEvHandler(Event.KeybdEvent);
|
||||
|
||||
Logger.Log("(((((Keyboard/Mouse hooks installed/reinstalled!)))))");
|
||||
/* The hook is called in the context of the thread that installed it.
|
||||
|
||||
@@ -132,7 +132,7 @@ namespace MouseWithoutBorders
|
||||
|
||||
internal void UpdateKeyTextBox()
|
||||
{
|
||||
_ = Common.GetUserName();
|
||||
_ = Helper.GetUserName();
|
||||
textBoxEnc.Text = Common.MyKey;
|
||||
}
|
||||
|
||||
@@ -787,7 +787,7 @@ namespace MouseWithoutBorders
|
||||
{
|
||||
if (!Common.RunWithNoAdminRight)
|
||||
{
|
||||
Common.ApplyCADSetting();
|
||||
Helper.ApplyCADSetting();
|
||||
ShowUpdateMessage();
|
||||
}
|
||||
}
|
||||
@@ -1163,7 +1163,7 @@ namespace MouseWithoutBorders
|
||||
|
||||
private void LinkLabelMiniLog_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
|
||||
{
|
||||
string miniLog = Common.GetMiniLog(new[] { groupBoxOtherOptions.Controls, groupBoxShortcuts.Controls });
|
||||
string miniLog = Helper.GetMiniLog(new[] { groupBoxOtherOptions.Controls, groupBoxShortcuts.Controls });
|
||||
|
||||
Clipboard.SetText(miniLog);
|
||||
Common.ShowToolTip("Log has been placed in the clipboard.", 30000, ToolTipIcon.Info, false);
|
||||
|
||||
@@ -78,7 +78,7 @@ namespace MouseWithoutBorders
|
||||
NotifyIcon.BalloonTipTitle = Application.ProductName;
|
||||
menuGenDumpFile.Visible = true;
|
||||
|
||||
Common.WndProcCounter++;
|
||||
Helper.WndProcCounter++;
|
||||
|
||||
try
|
||||
{
|
||||
@@ -101,7 +101,7 @@ namespace MouseWithoutBorders
|
||||
}
|
||||
else
|
||||
{
|
||||
Common.StartServiceAndSendLogoffSignal();
|
||||
Service.StartServiceAndSendLogoffSignal();
|
||||
Quit(true, true);
|
||||
}
|
||||
}
|
||||
@@ -119,7 +119,7 @@ namespace MouseWithoutBorders
|
||||
NotifyIcon.Dispose();
|
||||
if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop)
|
||||
{
|
||||
Common.RunDDHelper(true);
|
||||
Helper.RunDDHelper(true);
|
||||
}
|
||||
|
||||
// Common.UnhookClipboard();
|
||||
@@ -133,7 +133,7 @@ namespace MouseWithoutBorders
|
||||
|
||||
Setting.Values.SwitchCount += Common.SwitchCount;
|
||||
Process me = Process.GetCurrentProcess();
|
||||
Common.WndProcCounter++;
|
||||
Helper.WndProcCounter++;
|
||||
|
||||
try
|
||||
{
|
||||
@@ -142,13 +142,13 @@ namespace MouseWithoutBorders
|
||||
Common.Cleanup();
|
||||
}
|
||||
|
||||
Common.WndProcCounter++;
|
||||
Helper.WndProcCounter++;
|
||||
if (!Common.RunOnScrSaverDesktop)
|
||||
{
|
||||
Common.ReleaseAllKeys();
|
||||
}
|
||||
|
||||
Common.RunDDHelper(true);
|
||||
Helper.RunDDHelper(true);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -285,7 +285,7 @@ namespace MouseWithoutBorders
|
||||
helperTimer.Interval = 100;
|
||||
helperTimer.Tick += new EventHandler(HelperTimer_Tick);
|
||||
helperTimer.Start();
|
||||
Common.WndProcCounter++;
|
||||
Helper.WndProcCounter++;
|
||||
|
||||
if (Environment.OSVersion.Version.Major > 6 ||
|
||||
(Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor >= 1))
|
||||
@@ -307,7 +307,7 @@ namespace MouseWithoutBorders
|
||||
|
||||
private void HelperTimer_Tick(object sender, EventArgs e)
|
||||
{
|
||||
Common.WndProcCounter++;
|
||||
Helper.WndProcCounter++;
|
||||
|
||||
if (busy)
|
||||
{
|
||||
@@ -338,7 +338,7 @@ namespace MouseWithoutBorders
|
||||
|
||||
if (Common.MainFormVisible)
|
||||
{
|
||||
Common.MainFormDot();
|
||||
Helper.MainFormDot();
|
||||
}
|
||||
|
||||
InputSimulation.ResetSystemKeyFlags();
|
||||
@@ -357,7 +357,7 @@ namespace MouseWithoutBorders
|
||||
{
|
||||
if (!Common.SecondOpenSocketTry)
|
||||
{
|
||||
if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop && !Common.GetUserName())
|
||||
if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop && !Helper.GetUserName())
|
||||
{
|
||||
// While Windows 8 is hybrid-shutting down, user name would be empty (as returned from the .Net API), we should not do anything in this case.
|
||||
Logger.LogDebug("No active user.");
|
||||
@@ -407,7 +407,7 @@ namespace MouseWithoutBorders
|
||||
// Common.ReHookClipboard();
|
||||
}
|
||||
|
||||
Common.RunDDHelper();
|
||||
Helper.RunDDHelper();
|
||||
}
|
||||
|
||||
count = 0;
|
||||
@@ -485,7 +485,7 @@ namespace MouseWithoutBorders
|
||||
// One more time after 1/3 minutes (Sometimes XP has explorer started late)
|
||||
if (count == 600 || count == 1800)
|
||||
{
|
||||
Common.RunDDHelper();
|
||||
Helper.RunDDHelper();
|
||||
}
|
||||
|
||||
if (count == 600)
|
||||
@@ -545,7 +545,7 @@ namespace MouseWithoutBorders
|
||||
|
||||
if (Common.ToggleIcons != null)
|
||||
{
|
||||
Common.ToggleIcon();
|
||||
Helper.ToggleIcon();
|
||||
}
|
||||
|
||||
if (count % 20 == 0)
|
||||
@@ -578,13 +578,13 @@ namespace MouseWithoutBorders
|
||||
}
|
||||
else if ((count % 36005) == 0)
|
||||
{// One hour
|
||||
Common.SaveSwitchCount();
|
||||
Event.SaveSwitchCount();
|
||||
|
||||
int rv = 0;
|
||||
|
||||
if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop && Common.IsMyDesktopActive() && (rv = Common.SendMessageToHelper(0x400, IntPtr.Zero, IntPtr.Zero)) <= 0)
|
||||
if (!Common.RunOnLogonDesktop && !Common.RunOnScrSaverDesktop && Common.IsMyDesktopActive() && (rv = Helper.SendMessageToHelper(0x400, IntPtr.Zero, IntPtr.Zero)) <= 0)
|
||||
{
|
||||
Logger.TelemetryLogTrace($"{Common.HELPER_FORM_TEXT} not found: {rv}", SeverityLevel.Warning);
|
||||
Logger.TelemetryLogTrace($"{Helper.HELPER_FORM_TEXT} not found: {rv}", SeverityLevel.Warning);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -776,7 +776,7 @@ namespace MouseWithoutBorders
|
||||
break;
|
||||
|
||||
case NativeMethods.WM_HIDE_DRAG_DROP:
|
||||
Common.MainFormDot();
|
||||
Helper.MainFormDot();
|
||||
|
||||
/*
|
||||
this.Width = 1;
|
||||
@@ -795,14 +795,14 @@ namespace MouseWithoutBorders
|
||||
break;
|
||||
|
||||
case NativeMethods.WM_HIDE_DD_HELPER:
|
||||
Common.MainForm3Pixels();
|
||||
Helper.MainForm3Pixels();
|
||||
Common.MMSleep(0.2);
|
||||
if (m.WParam.ToInt32() == 1)
|
||||
{
|
||||
InputSimulation.MouseUp(); // A file is being dragged
|
||||
}
|
||||
|
||||
IntPtr h = (IntPtr)NativeMethods.FindWindow(null, Common.HELPER_FORM_TEXT);
|
||||
IntPtr h = (IntPtr)NativeMethods.FindWindow(null, Helper.HELPER_FORM_TEXT);
|
||||
|
||||
if (h.ToInt32() > 0)
|
||||
{
|
||||
@@ -831,7 +831,7 @@ namespace MouseWithoutBorders
|
||||
|
||||
case WM_QUERYENDSESSION:
|
||||
Logger.LogDebug("WM_QUERYENDSESSION...");
|
||||
Common.StartServiceAndSendLogoffSignal();
|
||||
Service.StartServiceAndSendLogoffSignal();
|
||||
break;
|
||||
|
||||
case WM_ENDSESSION:
|
||||
|
||||
@@ -99,6 +99,111 @@ LegalKeyDictionary = Concurrent.ConcurrentDictionary`2[System.String,System.Byte
|
||||
--_budget = ????????????
|
||||
--_growLockArray = True
|
||||
--_comparerIsDefaultForClasses = False
|
||||
initDone = False
|
||||
REOPEN_WHEN_WSAECONNRESET = -10054
|
||||
REOPEN_WHEN_HOTKEY = -10055
|
||||
PleaseReopenSocket = 0
|
||||
ReopenSocketDueToReadError = False
|
||||
<LastResumeSuspendTime>k__BackingField = ????????????
|
||||
--_dateData = ????????????
|
||||
--MinValue = 01/01/0001 00:00:00
|
||||
--MaxValue = 31/12/9999 23:59:59
|
||||
--UnixEpoch = 01/01/1970 00:00:00
|
||||
lastReleaseAllKeysCall = 0
|
||||
PackageSent = MouseWithoutBorders.PackageMonitor
|
||||
--Keyboard = 0
|
||||
--Mouse = 0
|
||||
--Heartbeat = 0
|
||||
--ByeBye = 0
|
||||
--Hello = 0
|
||||
--Matrix = 0
|
||||
--ClipboardText = 0
|
||||
--ClipboardImage = 0
|
||||
--Clipboard = 0
|
||||
--ClipboardDragDrop = 0
|
||||
--ClipboardDragDropEnd = 0
|
||||
--ClipboardAsk = 0
|
||||
--ExplorerDragDrop = 0
|
||||
--Nil = 0
|
||||
PackageReceived = MouseWithoutBorders.PackageMonitor
|
||||
--Keyboard = 0
|
||||
--Mouse = 0
|
||||
--Heartbeat = 0
|
||||
--ByeBye = 0
|
||||
--Hello = 0
|
||||
--Matrix = 0
|
||||
--ClipboardText = 0
|
||||
--ClipboardImage = 0
|
||||
--Clipboard = 0
|
||||
--ClipboardDragDrop = 0
|
||||
--ClipboardDragDropEnd = 0
|
||||
--ClipboardAsk = 0
|
||||
--ExplorerDragDrop = 0
|
||||
--Nil = 0
|
||||
PackageID = 0
|
||||
SensitivePoints = Generic.List`1[Point]
|
||||
--_items = Point[]
|
||||
----System.Drawing.Point[] = Point[]: N/A
|
||||
--_size = 0
|
||||
--_version = 0
|
||||
--s_emptyArray = Point[]
|
||||
----System.Drawing.Point[] = Point[]: N/A
|
||||
p = {X=0,Y=0}
|
||||
--x = 0
|
||||
--y = 0
|
||||
--Empty = {X=0,Y=0}
|
||||
<IpcChannelCreated>k__BackingField = False
|
||||
BIG_CLIPBOARD_DATA_TIMEOUT = 30000
|
||||
MAX_CLIPBOARD_DATA_SIZE_CAN_BE_SENT_INSTANTLY_TCP = 1048576
|
||||
MAX_CLIPBOARD_FILE_SIZE_CAN_BE_SENT = 104857600
|
||||
TEXT_HEADER_SIZE = 12
|
||||
DATA_SIZE = 48
|
||||
TEXT_TYPE_SEP = {4CFF57F7-BEDD-43d5-AE8F-27A61E886F2F}
|
||||
TOGGLE_ICONS_SIZE = 4
|
||||
ICON_ONE = 0
|
||||
ICON_ALL = 1
|
||||
ICON_SMALL_CLIPBOARD = 2
|
||||
ICON_BIG_CLIPBOARD = 3
|
||||
ICON_ERROR = 4
|
||||
JUST_GOT_BACK_FROM_SCREEN_SAVER = 9999
|
||||
NETWORK_STREAM_BUF_SIZE = 1048576
|
||||
SymAlBlockSize = 16
|
||||
PW_LENGTH = 16
|
||||
PACKAGE_SIZE = 32
|
||||
PACKAGE_SIZE_EX = 64
|
||||
WP_PACKAGE_SIZE = 6
|
||||
KEYEVENTF_KEYDOWN = 1
|
||||
KEYEVENTF_KEYUP = 2
|
||||
WH_MOUSE = 7
|
||||
WH_KEYBOARD = 2
|
||||
WH_MOUSE_LL = 14
|
||||
WH_KEYBOARD_LL = 13
|
||||
WM_MOUSEMOVE = 512
|
||||
WM_LBUTTONDOWN = 513
|
||||
WM_RBUTTONDOWN = 516
|
||||
WM_MBUTTONDOWN = 519
|
||||
WM_XBUTTONDOWN = 523
|
||||
WM_LBUTTONUP = 514
|
||||
WM_RBUTTONUP = 517
|
||||
WM_MBUTTONUP = 520
|
||||
WM_XBUTTONUP = 524
|
||||
WM_LBUTTONDBLCLK = 515
|
||||
WM_RBUTTONDBLCLK = 518
|
||||
WM_MBUTTONDBLCLK = 521
|
||||
WM_MOUSEWHEEL = 522
|
||||
WM_KEYDOWN = 256
|
||||
WM_KEYUP = 257
|
||||
WM_SYSKEYDOWN = 260
|
||||
WM_SYSKEYUP = 261
|
||||
[DragDrop]
|
||||
===============
|
||||
isDragging = False
|
||||
dragDropStep05ExCalledByIpc = 0
|
||||
isDropping = False
|
||||
dragMachine = NONE
|
||||
<MouseDown>k__BackingField = False
|
||||
[Event]
|
||||
===============
|
||||
KeybdPackage = MouseWithoutBorders.DATA
|
||||
--Type = 0
|
||||
--Id = 0
|
||||
@@ -144,113 +249,15 @@ actualLastPos = {X=0,Y=0}
|
||||
--Empty = {X=0,Y=0}
|
||||
myLastX = 0
|
||||
myLastY = 0
|
||||
[Helper]
|
||||
===============
|
||||
signalHelperToExit = False
|
||||
signalWatchDogToExit = False
|
||||
WndProcCounter = 0
|
||||
initDone = False
|
||||
REOPEN_WHEN_WSAECONNRESET = -10054
|
||||
REOPEN_WHEN_HOTKEY = -10055
|
||||
PleaseReopenSocket = 0
|
||||
ReopenSocketDueToReadError = False
|
||||
<LastResumeSuspendTime>k__BackingField = ????????????
|
||||
--_dateData = ????????????
|
||||
--MinValue = 01/01/0001 00:00:00
|
||||
--MaxValue = 31/12/9999 23:59:59
|
||||
--UnixEpoch = 01/01/1970 00:00:00
|
||||
lastReleaseAllKeysCall = 0
|
||||
PackageSent = MouseWithoutBorders.PackageMonitor
|
||||
--Keyboard = 0
|
||||
--Mouse = 0
|
||||
--Heartbeat = 0
|
||||
--ByeBye = 0
|
||||
--Hello = 0
|
||||
--Matrix = 0
|
||||
--ClipboardText = 0
|
||||
--ClipboardImage = 0
|
||||
--Clipboard = 0
|
||||
--ClipboardDragDrop = 0
|
||||
--ClipboardDragDropEnd = 0
|
||||
--ClipboardAsk = 0
|
||||
--ExplorerDragDrop = 0
|
||||
--Nil = 0
|
||||
PackageReceived = MouseWithoutBorders.PackageMonitor
|
||||
--Keyboard = 0
|
||||
--Mouse = 0
|
||||
--Heartbeat = 0
|
||||
--ByeBye = 0
|
||||
--Hello = 0
|
||||
--Matrix = 0
|
||||
--ClipboardText = 0
|
||||
--ClipboardImage = 0
|
||||
--Clipboard = 0
|
||||
--ClipboardDragDrop = 0
|
||||
--ClipboardDragDropEnd = 0
|
||||
--ClipboardAsk = 0
|
||||
--ExplorerDragDrop = 0
|
||||
--Nil = 0
|
||||
PackageID = 0
|
||||
shownErrMessage = False
|
||||
lastStartServiceTime = ????????????
|
||||
--_dateData = ????????????
|
||||
--MinValue = 01/01/0001 00:00:00
|
||||
--MaxValue = 31/12/9999 23:59:59
|
||||
--UnixEpoch = 01/01/1970 00:00:00
|
||||
SensitivePoints = Generic.List`1[Point]
|
||||
--_items = Point[]
|
||||
----System.Drawing.Point[] = Point[]: N/A
|
||||
--_size = 0
|
||||
--_version = 0
|
||||
--s_emptyArray = Point[]
|
||||
----System.Drawing.Point[] = Point[]: N/A
|
||||
p = {X=0,Y=0}
|
||||
--x = 0
|
||||
--y = 0
|
||||
--Empty = {X=0,Y=0}
|
||||
<IpcChannelCreated>k__BackingField = False
|
||||
BIG_CLIPBOARD_DATA_TIMEOUT = 30000
|
||||
MAX_CLIPBOARD_DATA_SIZE_CAN_BE_SENT_INSTANTLY_TCP = 1048576
|
||||
MAX_CLIPBOARD_FILE_SIZE_CAN_BE_SENT = 104857600
|
||||
TEXT_HEADER_SIZE = 12
|
||||
DATA_SIZE = 48
|
||||
TEXT_TYPE_SEP = {4CFF57F7-BEDD-43d5-AE8F-27A61E886F2F}
|
||||
TOGGLE_ICONS_SIZE = 4
|
||||
ICON_ONE = 0
|
||||
ICON_ALL = 1
|
||||
ICON_SMALL_CLIPBOARD = 2
|
||||
ICON_BIG_CLIPBOARD = 3
|
||||
ICON_ERROR = 4
|
||||
JUST_GOT_BACK_FROM_SCREEN_SAVER = 9999
|
||||
NETWORK_STREAM_BUF_SIZE = 1048576
|
||||
SymAlBlockSize = 16
|
||||
PW_LENGTH = 16
|
||||
HELPER_FORM_TEXT = Mouse without Borders Helper
|
||||
HelperProcessName = PowerToys.MouseWithoutBordersHelper
|
||||
PACKAGE_SIZE = 32
|
||||
PACKAGE_SIZE_EX = 64
|
||||
WP_PACKAGE_SIZE = 6
|
||||
KEYEVENTF_KEYDOWN = 1
|
||||
KEYEVENTF_KEYUP = 2
|
||||
WH_MOUSE = 7
|
||||
WH_KEYBOARD = 2
|
||||
WH_MOUSE_LL = 14
|
||||
WH_KEYBOARD_LL = 13
|
||||
WM_MOUSEMOVE = 512
|
||||
WM_LBUTTONDOWN = 513
|
||||
WM_RBUTTONDOWN = 516
|
||||
WM_MBUTTONDOWN = 519
|
||||
WM_XBUTTONDOWN = 523
|
||||
WM_LBUTTONUP = 514
|
||||
WM_RBUTTONUP = 517
|
||||
WM_MBUTTONUP = 520
|
||||
WM_XBUTTONUP = 524
|
||||
WM_LBUTTONDBLCLK = 515
|
||||
WM_RBUTTONDBLCLK = 518
|
||||
WM_MBUTTONDBLCLK = 521
|
||||
WM_MOUSEWHEEL = 522
|
||||
WM_KEYDOWN = 256
|
||||
WM_KEYUP = 257
|
||||
WM_SYSKEYDOWN = 260
|
||||
WM_SYSKEYUP = 261
|
||||
[Launch]
|
||||
===============
|
||||
[Logger]
|
||||
===============
|
||||
AllLogsLock = Lock
|
||||
@@ -319,13 +326,6 @@ MAX_LOG = 10000
|
||||
MaxLogExceptionPerHour = 1000
|
||||
HeaderSENT = Be{0},Ke{1},Mo{2},He{3},Mx{4},Tx{5},Im{6},By{7},Cl{8},Dr{9},De{10},Ed{11},Ie{12},Ni{13}
|
||||
HeaderRECEIVED = Be{0},Ke{1},Mo{2},He{3},Mx{4},Tx{5},Im{6},By{7},Cl{8},Dr{9},De{10},Ed{11},In{12},Ni{13},Pc{14}/{15}
|
||||
[DragDrop]
|
||||
===============
|
||||
isDragging = False
|
||||
dragDropStep05ExCalledByIpc = 0
|
||||
isDropping = False
|
||||
dragMachine = NONE
|
||||
<MouseDown>k__BackingField = False
|
||||
[MachineStuff]
|
||||
===============
|
||||
McMatrixLock = Lock
|
||||
@@ -424,3 +424,11 @@ lastXY = {X=0,Y=0}
|
||||
--x = 0
|
||||
--y = 0
|
||||
--Empty = {X=0,Y=0}
|
||||
[Service]
|
||||
===============
|
||||
shownErrMessage = False
|
||||
lastStartServiceTime = ????????????
|
||||
--_dateData = ????????????
|
||||
--MinValue = 01/01/0001 00:00:00
|
||||
--MaxValue = 31/12/9999 23:59:59
|
||||
--UnixEpoch = 01/01/1970 00:00:00
|
||||
|
||||
@@ -114,18 +114,11 @@ public static class LoggerTests
|
||||
using var streamReader = new StreamReader(stream);
|
||||
var expected = streamReader.ReadToEnd();
|
||||
|
||||
// copied from DumpObjects in Common.Log.cs
|
||||
// copied from DumpObjects in Logger.cs
|
||||
var sb = new StringBuilder(1000000);
|
||||
_ = Logger.PrivateDump(sb, Logger.AllLogs, "[Program logs]\r\n===============\r\n", 0, settingsDumpObjectsLevel, false);
|
||||
_ = Logger.PrivateDump(sb, new Common(), "[Other Logs]\r\n===============\r\n", 0, settingsDumpObjectsLevel, false);
|
||||
sb.AppendLine("[Logger]\r\n===============");
|
||||
Logger.DumpType(sb, typeof(Logger), 0, settingsDumpObjectsLevel);
|
||||
sb.AppendLine("[DragDrop]\r\n===============");
|
||||
Logger.DumpType(sb, typeof(DragDrop), 0, settingsDumpObjectsLevel);
|
||||
sb.AppendLine("[MachineStuff]\r\n===============");
|
||||
Logger.DumpType(sb, typeof(MachineStuff), 0, settingsDumpObjectsLevel);
|
||||
sb.AppendLine("[Receiver]\r\n===============");
|
||||
Logger.DumpType(sb, typeof(Receiver), 0, settingsDumpObjectsLevel);
|
||||
Logger.DumpProgramLogs(sb, settingsDumpObjectsLevel);
|
||||
Logger.DumpOtherLogs(sb, settingsDumpObjectsLevel);
|
||||
Logger.DumpStaticTypes(sb, settingsDumpObjectsLevel);
|
||||
var actual = sb.ToString();
|
||||
|
||||
expected = NormalizeLog(expected);
|
||||
|
||||
Reference in New Issue
Block a user