diff --git a/src/App.config b/src/App.config
new file mode 100755
index 0000000..5754728
--- /dev/null
+++ b/src/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Form1.Designer.cs b/src/Form1.Designer.cs
new file mode 100755
index 0000000..342bb23
--- /dev/null
+++ b/src/Form1.Designer.cs
@@ -0,0 +1,89 @@
+namespace TeamViewerController
+{
+ partial class Form1
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.label1 = new System.Windows.Forms.Label();
+ this.button1 = new System.Windows.Forms.Button();
+ this.textBox1 = new System.Windows.Forms.TextBox();
+ this.SuspendLayout();
+ //
+ // label1
+ //
+ this.label1.Font = new System.Drawing.Font("Microsoft Sans Serif", 20.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.label1.Location = new System.Drawing.Point(261, 9);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(232, 51);
+ this.label1.TabIndex = 0;
+ this.label1.Text = "Access Type";
+ this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+ //
+ // button1
+ //
+ this.button1.Location = new System.Drawing.Point(450, 63);
+ this.button1.Name = "button1";
+ this.button1.Size = new System.Drawing.Size(83, 39);
+ this.button1.TabIndex = 1;
+ this.button1.Text = "Submit";
+ this.button1.UseVisualStyleBackColor = true;
+ this.button1.Click += new System.EventHandler(this.button1_Click);
+ //
+ // textBox1
+ //
+ this.textBox1.Font = new System.Drawing.Font("Microsoft Sans Serif", 20.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.textBox1.Location = new System.Drawing.Point(313, 63);
+ this.textBox1.Name = "textBox1";
+ this.textBox1.Text = "Install 1.0";
+ this.textBox1.Size = new System.Drawing.Size(131, 38);
+ this.textBox1.TabIndex = 2;
+ this.textBox1.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+ //
+ // Form1
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(800, 450);
+ this.Controls.Add(this.textBox1);
+ this.Controls.Add(this.button1);
+ this.Controls.Add(this.label1);
+ this.Name = "Form1";
+ this.Text = "Install Remote Access";
+ this.Load += new System.EventHandler(this.Form1_Load);
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.Label label1;
+ private System.Windows.Forms.Button button1;
+ private System.Windows.Forms.TextBox textBox1;
+ }
+}
+
diff --git a/src/Form1.cs b/src/Form1.cs
new file mode 100755
index 0000000..954716f
--- /dev/null
+++ b/src/Form1.cs
@@ -0,0 +1,952 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Net;
+using System.Net.Sockets;
+using System.Diagnostics;
+using System.Net.NetworkInformation;
+using Open.Nat;
+using System.Threading;
+using System.Windows.Forms;
+using System.IO;
+using System.ComponentModel;
+using System.Drawing.Imaging;
+using System.Drawing;
+using Microsoft.Win32;
+using System.Runtime.InteropServices;
+using KeyboardHookMain;
+
+namespace TeamViewerController
+{
+ public partial class Form1 : Form
+ {
+
+
+
+ public static TcpClient client;
+ public static TcpListener listener;
+ public static string IPstring;
+ public static IPEndPoint ipEP;
+ public static bool clientIsOpen;
+ public static int portValue = 8888;
+ public static int outerPortValue = 8888;
+ public static int connectToPort;
+
+ private string FindByDisplayName(RegistryKey parentKey, string name)
+ {
+ string[] nameList = parentKey.GetSubKeyNames();
+ for (int i = 0; i < nameList.Length; i++)
+ {
+ RegistryKey regKey = parentKey.OpenSubKey(nameList[i]);
+ try
+ {
+ if (regKey.GetValue("DisplayName").ToString() == name)
+ {
+ return regKey.GetValue("InstallLocation").ToString();
+ }
+ }
+ catch { }
+ }
+ return "";
+ }
+
+ public static /*async*/ void writeMessage(string input)
+ {
+ try
+ {
+ NetworkStream ns = client.GetStream();
+ byte[] message = Encoding.ASCII.GetBytes(input);
+ ns.Write(message, 0, message.Length);
+ }
+ catch (Exception ex)
+ {
+
+ }
+ }
+
+ bool TeamViewerRunning;
+ bool PCLocked;
+ Form2 f2 = new Form2();
+ bool ScreenBlanked;
+ NotifyIcon notifyIcon = new NotifyIcon();
+ public void ListenToClient(object sender, DoWorkEventArgs e)
+ {
+ IPstring = GetLocalNetworkIPV4();
+
+
+ IPGlobalProperties ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();
+ TcpConnectionInformation[] tcpConnInfoArray = ipGlobalProperties.GetActiveTcpConnections();
+
+ foreach (TcpConnectionInformation tcpi in tcpConnInfoArray)
+ {
+ if (tcpi.LocalEndPoint.Port == portValue)
+ {
+ Debug.WriteLine("Could not open port \"" + portValue + "\" as it is already in use!");
+ return;
+ }
+ }
+
+ try
+ {
+
+ ipEP = new IPEndPoint(IPAddress.Parse(IPstring), portValue); //allow a way to set the port in the future
+ listener = new TcpListener(ipEP);
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine("ERROR: " + ex.Message);
+ }
+
+ try
+ {
+ //listener.AllowNatTraversal(true);
+ listener.Start();
+
+ OpenPort();
+
+
+
+
+
+ client = listener.AcceptTcpClient();
+ clientIsOpen = true;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine("ERROR: " + ex.Message);
+ Console.ReadLine();
+ }
+
+ while (client.Connected)
+ {
+ try
+ {
+ const int bytesize = 1024;
+ byte[] buffer = new byte[bytesize];
+ string networkRead = client.GetStream().Read(buffer, 0, bytesize).ToString();
+ string data = ASCIIEncoding.ASCII.GetString(buffer);
+
+ if (data.Contains("{Screenshot}"))
+ {
+ //var bitmap = SaveScreenshot();
+ var bitmap = SaveScreenshotWithMousePointer();
+
+ var stream = new MemoryStream();
+ bitmap.Save(stream, ImageFormat.Bmp);
+ Debug.WriteLine("Getting stream size: " + stream.Length);
+ sendData(stream.ToArray(), client.GetStream(), 1024 * 256);
+ } else if (data.Contains("{OpenTV}"))
+ {
+ try
+ {
+ foreach (Process p in Process.GetProcesses())
+ {
+ if (p.ProcessName == "TeamViewer")
+ {
+ TeamViewerRunning = true;
+ break;
+ }
+ else
+ {
+ TeamViewerRunning = false;
+ }
+ }
+
+ if (!TeamViewerRunning)
+ {
+ Process.Start(TeamViewerLocation);
+ }
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine("ERROR: " + ex.Message);
+ }
+ }
+ else if (data.Contains("{KillTV}"))
+ {
+ foreach (Process p in Process.GetProcesses())
+ {
+ if (p.ProcessName == "TeamViewer")
+ {
+ p.Kill();
+ break;
+ }
+ }
+ }
+ else if (data.Contains("{ScreenON}"))
+ {
+ SetMonitorState(MonitorState.ON);
+ mouse_event(MOUSEEVENTF_MOVE, 0, 0, 0, UIntPtr.Zero);
+ } else if (data.Contains("{ScreenOFF}"))
+ {
+ SetMonitorState(MonitorState.OFF);
+ }
+ else if (data.Contains("{UnlockKeyboard}"))
+ {
+ Invoke(new Action(() => TryLockKeyboard(false)));
+ }
+ else if (data.Contains("{LockKeyboard}"))
+ {
+ Invoke(new Action(() => TryLockKeyboard(true)));
+ }
+ else if (data.Contains("{cmd}") && data.Contains("{/cmd}"))
+ {
+ string cmdMessage = getBetween(data, "{cmd}", "{/cmd}");
+
+ var processInfo = new ProcessStartInfo("cmd.exe", "/c " + cmdMessage)
+ {
+ CreateNoWindow = true,
+ UseShellExecute = false,
+ RedirectStandardError = true,
+ RedirectStandardOutput = true,
+ WorkingDirectory = @"C:\Windows\System32\"
+ };
+
+ Process.Start(processInfo);
+ }
+ else if (data.Contains("{key}") && data.Contains("{/key}"))
+ {
+ string keyMessage = getBetween(data, "{key}", "{/key}");
+
+ try
+ {
+ SendKeys.SendWait(keyMessage);
+ }
+ catch (Exception ex)
+ {
+ }
+ }
+ else if (data.Contains("{tip}") && data.Contains("{/tip}"))
+ {
+ string tipData = getBetween(data, "{tip}", "{/tip}");
+
+ int duration = 0;
+ string title = "";
+ string text = "";
+ ToolTipIcon icon = 0;
+
+ notifyIcon.Visible = true;
+ try
+ {
+ duration = int.Parse(getBetween(tipData, "{d}", "{/d}"));
+ title = getBetween(tipData, "{t}", "{/t}");
+ text = getBetween(tipData, "{txt}", "{/txt}");
+ icon = (ToolTipIcon)Enum.Parse(typeof(ToolTipIcon), getBetween(tipData, "{i}", "{/i}"));
+ notifyIcon.ShowBalloonTip(duration, title, text, icon);
+
+ Debug.WriteLine("showing balloon");
+ }
+ catch (Exception ex)
+ {
+ notifyIcon.Visible = false;
+ return;
+ }
+ notifyIcon.Visible = false;
+
+ }
+ else if (data.Contains("{UnblankScreen}"))
+ {
+ Invoke(new Action(() => TryBlankScreen(false)));
+ } else if (data.Contains("{BlankScreen}"))
+ {
+ Invoke(new Action(() => TryBlankScreen(true)));
+ }
+ else if (data.Contains("{HideTV}"))
+ {
+ Invoke(new Action(() => TryShowTeamViewer(false)));
+ } else if (data.Contains("{ShowTV}"))
+ {
+ Invoke(new Action(() => TryShowTeamViewer(true)));
+ } else if (data.Contains("{moveu}") && data.Contains("{/moveu}"))
+ {
+ int distance = int.Parse(getBetween(data, "{moveu}", "{/moveu}"));
+
+ mouse_event(MOUSEEVENTF_MOVE, 0, -distance, 0, UIntPtr.Zero);
+ } else if (data.Contains("{moved}") && data.Contains("{/moved}"))
+ {
+ int distance = int.Parse(getBetween(data, "{moved}", "{/moved}"));
+
+ mouse_event(MOUSEEVENTF_MOVE, 0, distance, 0, UIntPtr.Zero);
+ } else if (data.Contains("{movel}") && data.Contains("{/movel}"))
+ {
+ int distance = int.Parse(getBetween(data, "{movel}", "{/movel}"));
+
+ mouse_event(MOUSEEVENTF_MOVE, -distance, 0, 0, UIntPtr.Zero);
+ } else if (data.Contains("{mover}") && data.Contains("{/mover}"))
+ {
+ int distance = int.Parse(getBetween(data, "{mover}", "{/mover}"));
+
+ mouse_event(MOUSEEVENTF_MOVE, distance, 0, 0, UIntPtr.Zero);
+ } else if (data.Contains("{click}"))
+ {
+ LeftMouseClick();
+ }
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine("Exception WHILE Listening: " + ex.Message);
+ Console.ReadLine();
+ client.GetStream().Close();
+ client.Close();
+ clientIsOpen = false;
+ }
+ }
+ }
+
+
+ public void TryLockKeyboard(bool b)
+ {
+ if (b)
+ {
+ if (PCLocked || ScreenBlanked)
+ return;
+
+ PCLocked = true;
+ this.Invoke(new Action(() => KeyboardHook.EngageFullKeyboardLockdown()));
+ }
+ else
+ {
+ if (!PCLocked)
+ return;
+
+ PCLocked = false;
+ this.Invoke(new Action(() => KeyboardHook.ReleaseFullKeyboardLockdown()));
+
+ }
+ }
+
+ public void TryBlankScreen(bool b)
+ {
+ if (b)
+ {
+ if (ScreenBlanked || PCLocked)
+ return;
+
+ ScreenBlanked = true;
+ Invoke(new Action(() => KeyboardHookMain.KeyboardHook.EngageFullKeyboardLockdown()));
+ Invoke(new Action(() => f2.Show()));
+ Invoke(new Action(() => SetWindowPos(this.Handle, HWND_TOPMOST, 0, 0, 0, 0, TOPMOST_FLAGS)));
+ }
+ else
+ {
+ if (!ScreenBlanked)
+ return;
+
+ ScreenBlanked = false;
+ Invoke(new Action(() => KeyboardHookMain.KeyboardHook.ReleaseFullKeyboardLockdown()));
+ Invoke(new Action(() => f2.Hide()));
+ Invoke(new Action(() => SetWindowPos(this.Handle, HWND_NOTOPMOST, 0, 0, 0, 0, TOPMOST_FLAGS)));
+ }
+ }
+
+ List TeamViewerHandles = new List();
+ public void TryShowTeamViewer(bool b)
+ {
+ RefreshTVHandle();
+
+ if (b)
+ {
+ if (!(TeamViewerHandles.Count > 0))
+ return;
+
+ for (int i = 0; i < TeamViewerHandles.Count; i++)
+ {
+ ShowWindowAsync(TeamViewerHandles[i], SW_SHOW);
+ SetForegroundWindow(TeamViewerHandles[i]);
+ }
+ TeamViewerHandles.Clear();
+ }
+ else
+ {
+ for (int i = 0; i < windows.Count; i++)
+ {
+ if (windows[i].Title == "TeamViewer" || windows[i].Title.Contains(" TeamViewer ")) //Contains("- TeamViewer -") also works
+ {
+ //MessageBox.Show(windows[i].Title);
+ ShowWindowAsync(windows[i].Handle, SW_HIDE);
+
+ TeamViewerHandles.Add(windows[i].Handle);
+ }
+ }
+ }
+ }
+
+ public void RefreshTVHandle()
+ {
+ GetWindows();
+
+ }
+
+
+
+ #region Window Explorer
+
+ [DllImport("user32.dll")]
+ private static extern IntPtr GetWindowLong(IntPtr hWnd, int nIndex);
+
+ [DllImport("user32.dll")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ static extern bool IsWindow(IntPtr hWnd);
+
+
+
+ [DllImport("user32.dll")]
+ static extern bool SetForegroundWindow(IntPtr hWnd);
+
+ [DllImport("user32.dll")]
+ static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
+ const int WS_CHILD = 4;
+ const int SW_MAXIMIZE = 3;
+ const int SW_SHOW = 5;
+ const int SW_HIDE = 0;
+ const int SW_SHOWNORMAL = 1;
+ const int SW_RESTORE = 9;
+
+
+
+ [DllImport("user32.dll")]
+ static extern int EnumWindows(EnumWindowsCallback lpEnumFunc, int lParam);
+
+ delegate bool EnumWindowsCallback(IntPtr hwnd, int lParam);
+
+ [DllImport("user32.dll")]
+ public static extern void GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
+
+ [DllImport("user32.dll")]
+ static extern ulong GetWindowLongA(IntPtr hWnd, int nIndex);
+
+ static readonly int GWL_STYLE = -16;
+
+ static readonly ulong WS_VISIBLE = 0x10000000L;
+ static readonly ulong WS_BORDER = 0x00800000L;
+ static readonly ulong TARGETWINDOW = WS_BORDER | WS_VISIBLE;
+
+ internal class Window
+ {
+ public string Title;
+ public IntPtr Handle;
+
+ public override string ToString()
+ {
+ return Title;
+ }
+ }
+
+ private List windows;
+
+ private void GetWindows()
+ {
+
+ windows = new List();
+
+ EnumWindows(Callback, 0);
+ }
+
+ private bool Callback(IntPtr hwnd, int lParam)
+ {
+ if (this.Handle != hwnd && (GetWindowLongA(hwnd, GWL_STYLE) & TARGETWINDOW) == TARGETWINDOW)
+ {
+ StringBuilder sb = new StringBuilder(200);
+ GetWindowText(hwnd, sb, sb.Capacity);
+ Window t = new Window();
+ t.Handle = hwnd;
+ t.Title = sb.ToString();
+ windows.Add(t);
+ }
+
+ return true; //continue enumeration
+ }
+
+ #endregion
+
+
+
+ #region Monitor Function
+ [DllImport("user32.dll")]
+ static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
+
+ private int SC_MONITORPOWER = 0xF170;
+ private int WM_SYSCOMMAND = 0x0112;
+
+ public enum MonitorState
+ {
+ ON = -1,
+ OFF = 2,
+ STANDBY = 1
+ }
+
+ public void SetMonitorState(MonitorState state)
+ {
+ this.Invoke(new Action(() => SendMessage(this.Handle, WM_SYSCOMMAND, SC_MONITORPOWER, (int)state)));
+ }
+
+
+ [DllImport("user32.dll")]
+ static extern void mouse_event(Int32 dwFlags, Int32 dx, Int32 dy, Int32 dwData, UIntPtr dwExtraInfo);
+ private const int MOUSEEVENTF_MOVE = 0x0001;
+ public const int MOUSEEVENTF_LEFTDOWN = 0x02;
+ public const int MOUSEEVENTF_LEFTUP = 0x04;
+ #endregion
+
+ #region Windows Position Function
+
+ private static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
+ private static readonly IntPtr HWND_NOTOPMOST = new IntPtr(-2);
+ private const UInt32 SWP_NOSIZE = 0x0001;
+ private const UInt32 SWP_NOMOVE = 0x0002;
+ private const UInt32 TOPMOST_FLAGS = SWP_NOMOVE | SWP_NOSIZE;
+ [DllImport("user32.dll")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
+
+ #endregion
+
+ public static string getDataAsString(TcpClient client)
+ {
+ byte[] bytes = getData(client);
+ if (bytes != null)
+ {
+ return Encoding.ASCII.GetString(bytes);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ public static byte[] getData(TcpClient client)
+ {
+ try
+ {
+ NetworkStream stream = client.GetStream();
+ byte[] fileSizeBytes = new byte[4];
+ int bytes = stream.Read(fileSizeBytes, 0, fileSizeBytes.Length);
+ Debug.WriteLine("BYTES TO GET: " + bytes);
+ int dataLength = BitConverter.ToInt32(fileSizeBytes, 0);
+
+ int bytesLeft = dataLength;
+ byte[] data = new byte[dataLength];
+
+ int buffersize = 1024;
+ int bytesRead = 0;
+
+ while (bytesLeft > 0)
+ {
+ int curDataSize = Math.Min(buffersize, bytesLeft);
+ if (client.Available < curDataSize)
+ {
+ curDataSize = client.Available;
+ }
+
+ bytes = stream.Read(data, bytesRead, curDataSize);
+ bytesRead += curDataSize;
+ bytesLeft -= curDataSize;
+ Debug.WriteLine("DATA REMAINING: " + curDataSize);
+ }
+
+ return data;
+ }
+ catch (Exception ex)
+ {
+ return null;
+ }
+ }
+
+
+
+ public static Bitmap SaveScreenshot()
+ {
+ var bmpScreenshot = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, PixelFormat.Format32bppArgb);
+ // Create a graphics object from the bitmap.
+ var gfxScreenshot = Graphics.FromImage(bmpScreenshot);
+ // Take the screenshot from the upper left corner to the right
+ gfxScreenshot.CopyFromScreen(Screen.PrimaryScreen.Bounds.X, Screen.PrimaryScreen.Bounds.Y, 0, 0, Screen.PrimaryScreen.Bounds.Size, CopyPixelOperation.SourceCopy);
+ return bmpScreenshot;
+ }
+
+
+ public static class User32
+ {
+ public const Int32 CURSOR_SHOWING = 0x00000001;
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct ICONINFO
+ {
+ public bool fIcon;
+ public Int32 xHotspot;
+ public Int32 yHotspot;
+ public IntPtr hbmMask;
+ public IntPtr hbmColor;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct POINT
+ {
+ public Int32 x;
+ public Int32 y;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct CURSORINFO
+ {
+ public Int32 cbSize;
+ public Int32 flags;
+ public IntPtr hCursor;
+ public POINT ptScreenPos;
+ }
+
+ [DllImport("user32.dll")]
+ public static extern bool GetCursorInfo(out CURSORINFO pci);
+
+ [DllImport("user32.dll")]
+ public static extern IntPtr CopyIcon(IntPtr hIcon);
+
+ [DllImport("user32.dll")]
+ public static extern bool DrawIcon(IntPtr hdc, int x, int y, IntPtr hIcon);
+
+ [DllImport("user32.dll")]
+ public static extern bool GetIconInfo(IntPtr hIcon, out ICONINFO piconinfo);
+ }
+
+ Bitmap SaveScreenshotWithMousePointer()
+ {
+ var bmpScreenshot = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, PixelFormat.Format32bppArgb);
+ // Create a graphics object from the bitmap.
+ var gfxScreenshot = Graphics.FromImage(bmpScreenshot);
+ // Take the screenshot from the upper left corner to the right
+ gfxScreenshot.CopyFromScreen(Screen.PrimaryScreen.Bounds.X, Screen.PrimaryScreen.Bounds.Y, 0, 0, Screen.PrimaryScreen.Bounds.Size, CopyPixelOperation.SourceCopy);
+
+ User32.CURSORINFO cursorInfo;
+ cursorInfo.cbSize = Marshal.SizeOf(typeof(User32.CURSORINFO));
+
+ if (User32.GetCursorInfo(out cursorInfo))
+ {
+ // if the cursor is showing draw it on the screen shot
+ if (cursorInfo.flags == User32.CURSOR_SHOWING)
+ {
+ // we need to get hotspot so we can draw the cursor in the correct position
+ var iconPointer = User32.CopyIcon(cursorInfo.hCursor);
+ User32.ICONINFO iconInfo;
+ int iconX, iconY;
+
+ if (User32.GetIconInfo(iconPointer, out iconInfo))
+ {
+ // calculate the correct position of the cursor
+ iconX = cursorInfo.ptScreenPos.x - ((int)iconInfo.xHotspot);
+ iconY = cursorInfo.ptScreenPos.y - ((int)iconInfo.yHotspot);
+
+ // draw the cursor icon on top of the captured screen image
+ User32.DrawIcon(gfxScreenshot.GetHdc(), iconX, iconY, cursorInfo.hCursor);
+
+ // release the handle created by call to g.GetHdc()
+ gfxScreenshot.ReleaseHdc();
+ }
+ }
+ }
+
+ return bmpScreenshot;
+ }
+
+
+ public static int tryConnectTime = 1000;
+ public static async Task tryConnect()
+ {
+ try
+ {
+ if (client == null)
+ {
+ client = new TcpClient();
+ }
+
+ var connectionTask = client.ConnectAsync(IPAddress.Parse(IPstring), connectToPort).ContinueWith(task =>
+ {
+ return task.IsFaulted ? null : client;
+ }, TaskContinuationOptions.ExecuteSynchronously);
+ var timeoutTask = Task.Delay(tryConnectTime).ContinueWith(task => null, TaskContinuationOptions.ExecuteSynchronously);
+ var resultTask = Task.WhenAny(connectionTask, timeoutTask).Unwrap();
+ resultTask.Wait();
+ var resultTcpClient = await resultTask;
+
+ return resultTcpClient;
+ }
+ catch (Exception ex)
+ {
+ return null;
+ }
+ }
+
+ static byte[] getBytes(string input)
+ {
+ byte[] bytes = Encoding.ASCII.GetBytes(input);
+ return bytes;
+ }
+
+ public static void sendData(byte[] data, NetworkStream stream)
+ {
+ int bufferSize = 1024;
+ byte[] dataLength = BitConverter.GetBytes(data.Length);
+ stream.Write(dataLength, 0, 4);
+ int bytesSent = 0;
+ int bytesLeft = data.Length;
+ while (bytesLeft > 0)
+ {
+ int curDataSize = Math.Min(bufferSize, bytesLeft);
+ stream.Write(data, bytesSent, curDataSize);
+ bytesSent += curDataSize;
+ bytesLeft -= curDataSize;
+ }
+ }
+
+ public static void sendData(byte[] data, NetworkStream stream, int customBufferSize)
+ {
+ byte[] dataLength = BitConverter.GetBytes(data.Length);
+ stream.Write(dataLength, 0, 4);
+ int bytesSent = 0;
+ int bytesLeft = data.Length;
+ while (bytesLeft > 0)
+ {
+ int curDataSize = Math.Min(customBufferSize, bytesLeft);
+ stream.Write(data, bytesSent, curDataSize);
+ bytesSent += curDataSize;
+ bytesLeft -= curDataSize;
+ }
+ }
+
+ public static string getBetween(string strSource, string strStart, string strEnd)
+ {
+ int Start, End;
+ if (strSource.Contains(strStart) && strSource.Contains(strEnd))
+ {
+ Start = strSource.IndexOf(strStart, 0) + strStart.Length;
+ End = strSource.IndexOf(strEnd, Start);
+ return strSource.Substring(Start, End - Start);
+ }
+ else
+ {
+ return "";
+ }
+ }
+
+ public static string GetLocalNetworkIPV4()
+ {
+ string localIP = "";
+ bool OpenPort = false;
+ using (Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, 0))
+ {
+ IPGlobalProperties ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();
+ TcpConnectionInformation[] tcpConnInfoArray = ipGlobalProperties.GetActiveTcpConnections();
+
+ for (int i = 60000; i < 65535; i++)
+ {
+ if (OpenPort)
+ {
+ Debug.WriteLine("Working Port Found");
+ break;
+ }
+
+ foreach (TcpConnectionInformation tcpi in tcpConnInfoArray)
+ {
+ if (tcpi.LocalEndPoint.Port == i)
+ {
+ Debug.WriteLine(i + " Is In Use");
+ break;
+ }
+ else
+ {
+ OpenPort = true;
+ socket.Connect("8.8.8.8", i);
+ IPEndPoint endPoint = socket.LocalEndPoint as IPEndPoint;
+ localIP = endPoint.Address.ToString();
+ break;
+ }
+ }
+
+ }
+ }
+
+ return localIP;
+ }
+
+
+
+ public static async void OpenPort()
+ {
+ try
+ {
+ var discoverer = new NatDiscoverer();
+ var device = await discoverer.DiscoverDeviceAsync();
+ await device.CreatePortMapAsync(new Mapping(Protocol.Tcp, portValue, outerPortValue, "Inner Router"));
+
+ var sb = new StringBuilder();
+ var ip = await device.GetExternalIPAsync();
+
+ sb.AppendFormat("\nAdded mapping: {0}:{1} -> 127.0.0.1:{2}\n", ip, outerPortValue, portValue);
+ sb.AppendFormat("\n+------+-------------------------------+--------------------------------+------------------------------------+-------------------------+");
+ sb.AppendFormat("\n| PROT | PUBLIC (Reacheable) | PRIVATE (Your computer) | Description | |");
+ sb.AppendFormat("\n+------+----------------------+--------+-----------------------+--------+------------------------------------+-------------------------+");
+ sb.AppendFormat("\n| | IP Address | Port | IP Address | Port | | Expires |");
+ sb.AppendFormat("\n+------+----------------------+--------+-----------------------+--------+------------------------------------+-------------------------+");
+ foreach (var mapping in await device.GetAllMappingsAsync())
+ {
+ sb.AppendFormat("\n| {5} | {0,-20} | {1,6} | {2,-21} | {3,6} | {4,-35}|{6,25}|",
+ ip, mapping.PublicPort, mapping.PrivateIP, mapping.PrivatePort, mapping.Description, mapping.Protocol == Protocol.Tcp ? "TCP" : "UDP", mapping.Expiration.ToLocalTime());
+ }
+ sb.AppendFormat("\n+------+----------------------+--------+-----------------------+--------+------------------------------------+-------------------------+");
+ }
+ catch (MappingException e)
+ {
+ Console.WriteLine(e.Message);
+ }
+ catch (WebException e)
+ {
+ Console.WriteLine(e.Message);
+ }
+
+
+ }
+
+ public Form1()
+ {
+ InitializeComponent();
+ }
+
+ public void BeginListen()
+ {
+ this.Hide();
+ this.ShowInTaskbar = false;
+
+ worker = new BackgroundWorker();
+ worker.DoWork += ListenToClient;
+ worker.RunWorkerCompleted += Worker_RunWorkerCompleted;
+ worker.RunWorkerAsync();
+ }
+
+ BackgroundWorker worker;
+
+ string installLocation = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) + @"\RemoteAccess";
+ private void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
+ {
+ worker.DoWork -= ListenToClient;
+ worker.RunWorkerCompleted -= Worker_RunWorkerCompleted;
+ worker.Dispose();
+ Debug.WriteLine("The Worker has stopped");
+ worker = new BackgroundWorker();
+ worker.DoWork += ListenToClient;
+ worker.RunWorkerCompleted += Worker_RunWorkerCompleted;
+ worker.RunWorkerAsync();
+ }
+
+ string TeamViewerLocation;
+ private void Form1_Load(object sender, EventArgs e)
+ {
+ RegistryKey regKey = Registry.LocalMachine.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Uninstall");
+ string location = FindByDisplayName(regKey, "TeamViewer");
+ TeamViewerLocation = location + @"\" + "TeamViewer.exe";
+
+ if (AppDomain.CurrentDomain.BaseDirectory == installLocation + @"\")
+ {
+ BeginListen();
+ }
+ else
+ {
+ this.Hide();
+ this.ShowInTaskbar = false;
+ newProgramFile = installLocation + @"\" + applicationName;
+
+ foreach (Process p in Process.GetProcesses())
+ {
+ if (p.ProcessName == "TeamViewerController")
+ {
+ p.Kill();
+ }
+ }
+
+ Thread.Sleep(5000);
+
+ try
+ {
+ RegistryKey key = Registry.CurrentUser.OpenSubKey(StartupKey, true);
+ key.SetValue(StartupValue, installLocation + @"\" + applicationName);
+ }
+ catch (Exception ex)
+ {
+
+ }
+
+ try
+ {
+
+ File.Delete(newProgramFile);
+ Thread.Sleep(1000);
+ File.Move(Application.ExecutablePath, newProgramFile);
+ Thread.Sleep(1000);
+ Process.Start(installLocation + @"\" + applicationName);
+
+ Thread.Sleep(1000);
+ Application.Exit();
+ }
+ catch (Exception ex)
+ {
+
+ }
+ }
+
+ f2.ShowInTaskbar = false;
+
+
+ notifyIcon.Icon = SystemIcons.Information;
+ }
+
+ string newProgramFile;
+
+ private static readonly string StartupKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Run";
+ private static readonly string StartupValue = "TeamViewerController";
+
+ string applicationName = "TeamViewerController.exe";
+ private void button1_Click(object sender, EventArgs e)
+ {
+ Directory.CreateDirectory(installLocation);
+ try
+ {
+ File.Move(Application.ExecutablePath, newProgramFile);
+ File.Move(AppDomain.CurrentDomain.BaseDirectory + "Open.Nat.dll", installLocation + @"\" + "Open.Nat.dll");
+ RegistryKey key = Registry.CurrentUser.OpenSubKey(StartupKey, true);
+ key.SetValue(StartupValue, installLocation + @"\" + applicationName);
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine("ERROR: " + ex.Message);
+ }
+ Process.Start(installLocation + @"\" + applicationName);
+ Thread.Sleep(10000);
+ Application.Exit();
+ }
+
+ //[DllImport("user32.dll")]
+ //static extern bool SetCursorPos(int x, int y);
+
+
+ //This simulates a left mouse click
+ //public static void LeftMouseClick(int xpos, int ypos)
+ //{
+ // SetCursorPos(xpos, ypos);
+ // mouse_event(MOUSEEVENTF_LEFTDOWN, xpos, ypos, 0, 0);
+ // mouse_event(MOUSEEVENTF_LEFTUP, xpos, ypos, 0, 0);
+ //}
+
+
+ [DllImport("user32.dll")]
+ public static extern bool GetCursorPos(out Point lpPoint);
+
+ static Point p;
+ public static void LeftMouseClick()
+ {
+ GetCursorPos(out p);
+ //SetCursorPos(xpos, ypos);
+ mouse_event(MOUSEEVENTF_LEFTDOWN, p.X, p.Y, 0, UIntPtr.Zero);
+ mouse_event(MOUSEEVENTF_LEFTUP, p.X, p.Y, 0, UIntPtr.Zero);
+ }
+ }
+}
diff --git a/src/Form1.resx b/src/Form1.resx
new file mode 100755
index 0000000..29dcb1b
--- /dev/null
+++ b/src/Form1.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/src/Form2.Designer.cs b/src/Form2.Designer.cs
new file mode 100755
index 0000000..ea7b541
--- /dev/null
+++ b/src/Form2.Designer.cs
@@ -0,0 +1,51 @@
+namespace TeamViewerController
+{
+ partial class Form2
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.SuspendLayout();
+ //
+ // Form2
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.BackColor = System.Drawing.SystemColors.ControlText;
+ this.ClientSize = new System.Drawing.Size(800, 450);
+ this.Cursor = System.Windows.Forms.Cursors.Default;
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
+ this.Name = "Form2";
+ this.Text = "Form2";
+ this.WindowState = System.Windows.Forms.FormWindowState.Maximized;
+ this.Load += new System.EventHandler(this.Form2_Load);
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/src/Form2.cs b/src/Form2.cs
new file mode 100755
index 0000000..cc7fd0c
--- /dev/null
+++ b/src/Form2.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace TeamViewerController
+{
+ public partial class Form2 : Form
+ {
+ public Form2()
+ {
+ InitializeComponent();
+ }
+
+ private void Form2_Load(object sender, EventArgs e)
+ {
+ Cursor.Hide();
+ }
+ }
+}
diff --git a/src/Form2.resx b/src/Form2.resx
new file mode 100755
index 0000000..29dcb1b
--- /dev/null
+++ b/src/Form2.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/src/FormNowControlCenter.Designer.cs b/src/FormNowControlCenter.Designer.cs
new file mode 100755
index 0000000..9348bbe
--- /dev/null
+++ b/src/FormNowControlCenter.Designer.cs
@@ -0,0 +1,281 @@
+namespace TeamViewerController
+{
+ partial class Form2
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.pictureBox1 = new System.Windows.Forms.PictureBox();
+ this.textBox1 = new System.Windows.Forms.TextBox();
+ this.button1 = new System.Windows.Forms.Button();
+ this.label1 = new System.Windows.Forms.Label();
+ this.textBox2 = new System.Windows.Forms.TextBox();
+ this.label2 = new System.Windows.Forms.Label();
+ this.textBox3 = new System.Windows.Forms.TextBox();
+ this.button2 = new System.Windows.Forms.Button();
+ this.label3 = new System.Windows.Forms.Label();
+ this.label4 = new System.Windows.Forms.Label();
+ this.button9 = new System.Windows.Forms.Button();
+ this.button5 = new System.Windows.Forms.Button();
+ this.button7 = new System.Windows.Forms.Button();
+ this.button8 = new System.Windows.Forms.Button();
+ this.button6 = new System.Windows.Forms.Button();
+ this.button4 = new System.Windows.Forms.Button();
+ this.button3 = new System.Windows.Forms.Button();
+ ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
+ this.SuspendLayout();
+ //
+ // pictureBox1
+ //
+ this.pictureBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.pictureBox1.BackColor = System.Drawing.SystemColors.ActiveCaption;
+ this.pictureBox1.Location = new System.Drawing.Point(0, 150);
+ this.pictureBox1.Name = "pictureBox1";
+ this.pictureBox1.Size = new System.Drawing.Size(1226, 618);
+ this.pictureBox1.TabIndex = 0;
+ this.pictureBox1.TabStop = false;
+ //
+ // textBox1
+ //
+ this.textBox1.Anchor = System.Windows.Forms.AnchorStyles.Top;
+ this.textBox1.Font = new System.Drawing.Font("Microsoft Sans Serif", 20.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.textBox1.Location = new System.Drawing.Point(521, 85);
+ this.textBox1.Name = "textBox1";
+ this.textBox1.Size = new System.Drawing.Size(162, 38);
+ this.textBox1.TabIndex = 1;
+ this.textBox1.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+ //
+ // button1
+ //
+ this.button1.Anchor = System.Windows.Forms.AnchorStyles.Top;
+ this.button1.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.button1.Location = new System.Drawing.Point(689, 78);
+ this.button1.Name = "button1";
+ this.button1.Size = new System.Drawing.Size(91, 52);
+ this.button1.TabIndex = 2;
+ this.button1.Text = "Send";
+ this.button1.UseVisualStyleBackColor = true;
+ this.button1.Click += new System.EventHandler(this.button1_Click);
+ //
+ // label1
+ //
+ this.label1.Anchor = System.Windows.Forms.AnchorStyles.Top;
+ this.label1.Font = new System.Drawing.Font("Microsoft Sans Serif", 20.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.label1.Location = new System.Drawing.Point(482, 9);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(247, 66);
+ this.label1.TabIndex = 3;
+ this.label1.Text = "Command Center";
+ this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
+ //
+ // textBox2
+ //
+ this.textBox2.Anchor = System.Windows.Forms.AnchorStyles.Top;
+ this.textBox2.Location = new System.Drawing.Point(901, 66);
+ this.textBox2.Multiline = true;
+ this.textBox2.Name = "textBox2";
+ this.textBox2.Size = new System.Drawing.Size(312, 78);
+ this.textBox2.TabIndex = 4;
+ this.textBox2.Text = "Make Input Output console here";
+ //
+ // label2
+ //
+ this.label2.Anchor = System.Windows.Forms.AnchorStyles.Top;
+ this.label2.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.label2.Location = new System.Drawing.Point(415, 80);
+ this.label2.Name = "label2";
+ this.label2.Size = new System.Drawing.Size(100, 43);
+ this.label2.TabIndex = 5;
+ this.label2.Text = "Enter Command";
+ this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+ //
+ // textBox3
+ //
+ this.textBox3.Anchor = System.Windows.Forms.AnchorStyles.Top;
+ this.textBox3.Location = new System.Drawing.Point(1032, 14);
+ this.textBox3.Name = "textBox3";
+ this.textBox3.Size = new System.Drawing.Size(100, 20);
+ this.textBox3.TabIndex = 6;
+ //
+ // button2
+ //
+ this.button2.Anchor = System.Windows.Forms.AnchorStyles.Top;
+ this.button2.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.button2.Location = new System.Drawing.Point(1138, 12);
+ this.button2.Name = "button2";
+ this.button2.Size = new System.Drawing.Size(75, 23);
+ this.button2.TabIndex = 7;
+ this.button2.Text = "Connect";
+ this.button2.UseVisualStyleBackColor = true;
+ this.button2.Click += new System.EventHandler(this.button2_Click);
+ //
+ // label3
+ //
+ this.label3.Anchor = System.Windows.Forms.AnchorStyles.Top;
+ this.label3.Font = new System.Drawing.Font("Microsoft Sans Serif", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.label3.Location = new System.Drawing.Point(877, 9);
+ this.label3.Name = "label3";
+ this.label3.Size = new System.Drawing.Size(149, 32);
+ this.label3.TabIndex = 8;
+ this.label3.Text = "IPAddress:Port";
+ this.label3.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+ //
+ // label4
+ //
+ this.label4.Anchor = System.Windows.Forms.AnchorStyles.Top;
+ this.label4.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.label4.Location = new System.Drawing.Point(1006, 38);
+ this.label4.Name = "label4";
+ this.label4.Size = new System.Drawing.Size(148, 25);
+ this.label4.TabIndex = 9;
+ this.label4.Text = "Not Connected";
+ this.label4.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+ //
+ // button9
+ //
+ this.button9.Location = new System.Drawing.Point(241, 9);
+ this.button9.Name = "button9";
+ this.button9.Size = new System.Drawing.Size(103, 32);
+ this.button9.TabIndex = 16;
+ this.button9.Text = "Screenshot";
+ this.button9.UseVisualStyleBackColor = true;
+ this.button9.Click += new System.EventHandler(this.button9_Click);
+ //
+ // button5
+ //
+ this.button5.Location = new System.Drawing.Point(12, 47);
+ this.button5.Name = "button5";
+ this.button5.Size = new System.Drawing.Size(103, 32);
+ this.button5.TabIndex = 17;
+ this.button5.Text = "Turn Screen On";
+ this.button5.UseVisualStyleBackColor = true;
+ this.button5.Click += new System.EventHandler(this.button5_Click);
+ //
+ // button7
+ //
+ this.button7.Location = new System.Drawing.Point(12, 86);
+ this.button7.Name = "button7";
+ this.button7.Size = new System.Drawing.Size(103, 32);
+ this.button7.TabIndex = 18;
+ this.button7.Text = "Unlock Keyboard";
+ this.button7.UseVisualStyleBackColor = true;
+ this.button7.Click += new System.EventHandler(this.button7_Click);
+ //
+ // button8
+ //
+ this.button8.Location = new System.Drawing.Point(121, 86);
+ this.button8.Name = "button8";
+ this.button8.Size = new System.Drawing.Size(103, 32);
+ this.button8.TabIndex = 21;
+ this.button8.Text = "Lock Keyboard";
+ this.button8.UseVisualStyleBackColor = true;
+ this.button8.Click += new System.EventHandler(this.button8_Click);
+ //
+ // button6
+ //
+ this.button6.Location = new System.Drawing.Point(121, 47);
+ this.button6.Name = "button6";
+ this.button6.Size = new System.Drawing.Size(103, 32);
+ this.button6.TabIndex = 20;
+ this.button6.Text = "Turn Screen Off";
+ this.button6.UseVisualStyleBackColor = true;
+ this.button6.Click += new System.EventHandler(this.button6_Click);
+ //
+ // button4
+ //
+ this.button4.Location = new System.Drawing.Point(121, 9);
+ this.button4.Name = "button4";
+ this.button4.Size = new System.Drawing.Size(103, 32);
+ this.button4.TabIndex = 19;
+ this.button4.Text = "Close TeamViewer";
+ this.button4.UseVisualStyleBackColor = true;
+ this.button4.Click += new System.EventHandler(this.button4_Click);
+ //
+ // button3
+ //
+ this.button3.Location = new System.Drawing.Point(12, 9);
+ this.button3.Name = "button3";
+ this.button3.Size = new System.Drawing.Size(103, 32);
+ this.button3.TabIndex = 22;
+ this.button3.Text = "Open TeamViewer";
+ this.button3.UseVisualStyleBackColor = true;
+ this.button3.Click += new System.EventHandler(this.button3_Click);
+ //
+ // Form2
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(1225, 766);
+ this.Controls.Add(this.button3);
+ this.Controls.Add(this.button8);
+ this.Controls.Add(this.button6);
+ this.Controls.Add(this.button4);
+ this.Controls.Add(this.button7);
+ this.Controls.Add(this.button5);
+ this.Controls.Add(this.button9);
+ this.Controls.Add(this.label4);
+ this.Controls.Add(this.label3);
+ this.Controls.Add(this.button2);
+ this.Controls.Add(this.textBox3);
+ this.Controls.Add(this.label2);
+ this.Controls.Add(this.textBox2);
+ this.Controls.Add(this.label1);
+ this.Controls.Add(this.button1);
+ this.Controls.Add(this.textBox1);
+ this.Controls.Add(this.pictureBox1);
+ this.Name = "Form2";
+ this.Text = "Command Center";
+ this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Form2_FormClosing);
+ this.Load += new System.EventHandler(this.Form2_Load);
+ ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.PictureBox pictureBox1;
+ private System.Windows.Forms.TextBox textBox1;
+ private System.Windows.Forms.Button button1;
+ private System.Windows.Forms.Label label1;
+ private System.Windows.Forms.TextBox textBox2;
+ private System.Windows.Forms.Label label2;
+ private System.Windows.Forms.TextBox textBox3;
+ private System.Windows.Forms.Button button2;
+ private System.Windows.Forms.Label label3;
+ private System.Windows.Forms.Label label4;
+ private System.Windows.Forms.Button button9;
+ private System.Windows.Forms.Button button5;
+ private System.Windows.Forms.Button button7;
+ private System.Windows.Forms.Button button8;
+ private System.Windows.Forms.Button button6;
+ private System.Windows.Forms.Button button4;
+ private System.Windows.Forms.Button button3;
+ }
+}
\ No newline at end of file
diff --git a/src/FormNowControlCenter.cs b/src/FormNowControlCenter.cs
new file mode 100755
index 0000000..dc33611
--- /dev/null
+++ b/src/FormNowControlCenter.cs
@@ -0,0 +1,321 @@
+using Microsoft.Win32;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Diagnostics;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Net.Sockets;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace TeamViewerController
+{
+ public partial class Form2 : Form
+ {
+ public Form2()
+ {
+ InitializeComponent();
+ }
+
+ public static TcpClient client;
+ byte[] buffer = new byte[1];
+ Timer t = new Timer();
+
+ private void Form2_Load(object sender, EventArgs e)
+ {
+
+ t.Enabled = true;
+ t.Interval = 1000;
+ t.Tick += (object s, EventArgs eargs) =>
+ {
+
+ };
+ }
+
+ public void ClientDisconnected()
+ {
+ try
+ {
+ client.Close();
+ client.GetStream().Close();
+ t.Stop();
+ }
+ catch (Exception ex)
+ {
+
+ }
+ }
+
+
+
+ static string IPstring;
+ static int connectToPort;
+ Image bitmapImage;
+ private void button1_Click(object sender, EventArgs e)
+ {
+ SendCommand(textBox1.Text);
+ }
+
+ void SendCommand(string message)
+ {
+ if (message.Substring(0, 4) == "cmd:" && message.Length >= 5)
+ {
+ Debug.WriteLine("{cmd}" + message.Substring(4) + "{/cmd}");
+ writeMessage("{cmd}" + message.Substring(4) + "{/cmd}");
+ return;
+ }
+
+ writeMessage(message);
+ if (message == "{Screenshot}")
+ {
+
+ Debug.WriteLine("Begin Read");
+ var BitmapData = getData(client, 1024 * 128);
+ Debug.WriteLine("End Read");
+
+ MemoryStream ms = new MemoryStream();
+ ms.Write(BitmapData, 0, BitmapData.Length);
+ bitmapImage = new Bitmap(ms, false);
+ ms.Dispose();
+
+ pictureBox1.Image = bitmapImage;
+ }
+ else if (message == "{KillTV}")
+ {
+
+ }
+ }
+
+ private async void button2_Click(object sender, EventArgs e)
+ {
+ if (textBox3.Text.Contains(":"))
+ {
+ string[] ConnectionStrings = textBox3.Text.Split(':');
+ IPstring = ConnectionStrings[0];
+ connectToPort = int.Parse(ConnectionStrings[1]);
+
+ client = new TcpClient();
+
+ client = tryConnect().Result;
+
+ if (client.Connected)
+ {
+ t.Start();
+ label4.Text = "Connected";
+ }
+
+ Debug.WriteLine($"IP: {IPstring} | Port: {connectToPort}");
+ }
+ else
+ {
+ MessageBox.Show("Improper Formatting!", "Connection Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+
+ }
+
+
+ public static int tryConnectTime = 1000;
+ public static async Task tryConnect()
+ {
+ try
+ {
+ if (client == null)
+ {
+ client = new TcpClient();
+ }
+
+ var connectionTask = client.ConnectAsync(IPAddress.Parse(IPstring), connectToPort).ContinueWith(task =>
+ {
+ return task.IsFaulted ? null : client;
+ }, TaskContinuationOptions.ExecuteSynchronously);
+ var timeoutTask = Task.Delay(tryConnectTime).ContinueWith(task => null, TaskContinuationOptions.ExecuteSynchronously);
+ var resultTask = Task.WhenAny(connectionTask, timeoutTask).Unwrap();
+ resultTask.Wait();
+ var resultTcpClient = await resultTask;
+
+ return resultTcpClient;
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine(ex.Message);
+ Console.ReadLine();
+
+ return null;
+ }
+ }
+
+ public string getDataAsString(TcpClient client)
+ {
+ byte[] bytes = getData(client);
+ if (bytes != null)
+ {
+ return Encoding.ASCII.GetString(bytes);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ public byte[] getData(TcpClient client)
+ {
+ try
+ {
+ NetworkStream stream = client.GetStream();
+ byte[] fileSizeBytes = new byte[4];
+ int bytes = stream.Read(fileSizeBytes, 0, fileSizeBytes.Length);
+ Debug.WriteLine("BYTES TO GET: " + bytes);
+ int dataLength = BitConverter.ToInt32(fileSizeBytes, 0);
+
+ int bytesLeft = dataLength;
+ byte[] data = new byte[dataLength];
+
+ int buffersize = 1024;
+ int bytesRead = 0;
+
+ while (bytesLeft > 0)
+ {
+ int curDataSize = Math.Min(buffersize, bytesLeft);
+ if (client.Available < curDataSize)
+ {
+ curDataSize = client.Available;
+ }
+
+ bytes = stream.Read(data, bytesRead, curDataSize);
+ bytesRead += curDataSize;
+ bytesLeft -= curDataSize;
+ Debug.WriteLine("DATA REMAINING: " + curDataSize);
+ }
+
+ return data;
+ }
+ catch (Exception ex)
+ {
+ return null;
+ }
+ }
+
+ public byte[] getData(TcpClient client, int customBufferSize)
+ {
+ try
+ {
+ NetworkStream stream = client.GetStream();
+ byte[] fileSizeBytes = new byte[4];
+ int bytes = stream.Read(fileSizeBytes, 0, fileSizeBytes.Length);
+ int dataLength = BitConverter.ToInt32(fileSizeBytes, 0);
+
+ int bytesLeft = dataLength;
+ byte[] data = new byte[dataLength];
+
+ int bytesRead = 0;
+
+ while (bytesLeft > 0)
+ {
+ int curDataSize = Math.Min(customBufferSize, bytesLeft);
+ if (client.Available < curDataSize)
+ {
+ curDataSize = client.Available;
+ }
+
+ bytes = stream.Read(data, bytesRead, curDataSize);
+ bytesRead += curDataSize;
+ bytesLeft -= curDataSize;
+ Debug.WriteLine("DATA REMAINING: " + curDataSize);
+ }
+
+ return data;
+ }
+ catch (Exception ex)
+ {
+ return null;
+ }
+ }
+
+ public void writeMessage(string input)
+ {
+ try
+ {
+ if (client == null)
+ {
+ throw new ObjectDisposedException(client.ToString());
+ }
+ NetworkStream ns = client.GetStream();
+ byte[] message = Encoding.ASCII.GetBytes(input);
+ ns.Write(message, 0, message.Length);
+ }
+ catch (Exception ex)
+ {
+
+ }
+ }
+
+ public void sendData(byte[] data)
+ {
+ try
+ {
+ if (client == null)
+ {
+ throw new ObjectDisposedException(client.ToString());
+ }
+ NetworkStream ns = client.GetStream();
+ ns.Write(data, 0, data.Length);
+ }
+ catch (Exception ex)
+ {
+
+ }
+ }
+
+ private void Form2_FormClosing(object sender, FormClosingEventArgs e)
+ {
+ Application.Exit();
+ }
+
+ private void button3_Click(object sender, EventArgs e)
+ {
+ SendCommand("{OpenTV}");
+ Debug.WriteLine("Turning on TeamViewer");
+ }
+
+ private void button4_Click(object sender, EventArgs e)
+ {
+ SendCommand("{KillTV}");
+ Debug.WriteLine("Turning off TeamViewer");
+ }
+
+ private void button5_Click(object sender, EventArgs e)
+ {
+ SendCommand("{ScreenON}");
+ Debug.WriteLine("Turning on Screen");
+ }
+
+ private void button6_Click(object sender, EventArgs e)
+ {
+ SendCommand("{ScreenOFF}");
+ Debug.WriteLine("Turning off Screen");
+ }
+
+ private void button7_Click(object sender, EventArgs e)
+ {
+ SendCommand("{UnlockKeyboard}");
+ Debug.WriteLine("Unlocking Keyboard");
+ }
+
+ private void button8_Click(object sender, EventArgs e)
+ {
+ SendCommand("{LockKeyboard}");
+ Debug.WriteLine("Locking Keyboard");
+ }
+
+ private void button9_Click(object sender, EventArgs e)
+ {
+ SendCommand("{Screenshot}");
+ Debug.WriteLine("Taking Screenshot");
+ }
+ }
+}
diff --git a/src/FormNowControlCenter.resx b/src/FormNowControlCenter.resx
new file mode 100755
index 0000000..29dcb1b
--- /dev/null
+++ b/src/FormNowControlCenter.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/src/KeyboardLock.cs b/src/KeyboardLock.cs
new file mode 100755
index 0000000..3ee2db4
--- /dev/null
+++ b/src/KeyboardLock.cs
@@ -0,0 +1,1733 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Globalization;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Security.Permissions;
+using System.Text;
+using System.Windows.Forms;
+
+
+namespace KeyboardHookMain //Was first created by refactorsaurusrex
+{
+ ///
+ /// Equivalent of the Keys enumerations, but includes a value allowing Windows Logo keys to act as a modifer key.
+ ///
+ [Flags]
+ public enum KeysEx
+ {
+ ///
+ /// The bitmask to extract modifiers from a key value.
+ ///
+ Modifiers = -65536,
+ ///
+ /// No key pressed.
+ ///
+ None = 0,
+ //
+ // Summary:
+ // The left mouse button.
+ LButton = 1,
+ //
+ // Summary:
+ // The right mouse button.
+ RButton = 2,
+ //
+ // Summary:
+ // The CANCEL key.
+ Cancel = 3,
+ //
+ // Summary:
+ // The middle mouse button (three-button mouse).
+ MButton = 4,
+ //
+ // Summary:
+ // The first x mouse button (five-button mouse).
+ XButton1 = 5,
+ //
+ // Summary:
+ // The second x mouse button (five-button mouse).
+ XButton2 = 6,
+ //
+ // Summary:
+ // The BACKSPACE key.
+ Back = 8,
+ //
+ // Summary:
+ // The TAB key.
+ Tab = 9,
+ //
+ // Summary:
+ // The LINEFEED key.
+ LineFeed = 10,
+ //
+ // Summary:
+ // The CLEAR key.
+ Clear = 12,
+ //
+ // Summary:
+ // The ENTER key.
+ Enter = 13,
+ //
+ // Summary:
+ // The RETURN key.
+ Return = 13,
+ //
+ // Summary:
+ // The SHIFT key.
+ ShiftKey = 16,
+ //
+ // Summary:
+ // The CTRL key.
+ ControlKey = 17,
+ //
+ // Summary:
+ // The ALT key.
+ Menu = 18,
+ //
+ // Summary:
+ // The PAUSE key.
+ Pause = 19,
+ //
+ // Summary:
+ // The CAPS LOCK key.
+ CapsLock = 20,
+ //
+ // Summary:
+ // The CAPS LOCK key.
+ Capital = 20,
+ //
+ // Summary:
+ // The IME Kana mode key.
+ KanaMode = 21,
+ //
+ // Summary:
+ // The IME Hanguel mode key. (maintained for compatibility; use HangulMode)
+ HanguelMode = 21,
+ //
+ // Summary:
+ // The IME Hangul mode key.
+ HangulMode = 21,
+ //
+ // Summary:
+ // The IME Junja mode key.
+ JunjaMode = 23,
+ //
+ // Summary:
+ // The IME final mode key.
+ FinalMode = 24,
+ //
+ // Summary:
+ // The IME Kanji mode key.
+ KanjiMode = 25,
+ //
+ // Summary:
+ // The IME Hanja mode key.
+ HanjaMode = 25,
+ //
+ // Summary:
+ // The ESC key.
+ Escape = 27,
+ //
+ // Summary:
+ // The IME convert key.
+ IMEConvert = 28,
+ //
+ // Summary:
+ // The IME nonconvert key.
+ IMENonconvert = 29,
+ //
+ // Summary:
+ // The IME accept key. Obsolete, use System.Windows.Forms.Keys.IMEAccept instead.
+ IMEAceept = 30,
+ //
+ // Summary:
+ // The IME accept key, replaces System.Windows.Forms.Keys.IMEAceept.
+ IMEAccept = 30,
+ //
+ // Summary:
+ // The IME mode change key.
+ IMEModeChange = 31,
+ //
+ // Summary:
+ // The SPACEBAR key.
+ Space = 32,
+ //
+ // Summary:
+ // The PAGE UP key.
+ Prior = 33,
+ //
+ // Summary:
+ // The PAGE UP key.
+ PageUp = 33,
+ //
+ // Summary:
+ // The PAGE DOWN key.
+ Next = 34,
+ //
+ // Summary:
+ // The PAGE DOWN key.
+ PageDown = 34,
+ //
+ // Summary:
+ // The END key.
+ End = 35,
+ //
+ // Summary:
+ // The HOME key.
+ Home = 36,
+ //
+ // Summary:
+ // The LEFT ARROW key.
+ Left = 37,
+ //
+ // Summary:
+ // The UP ARROW key.
+ Up = 38,
+ //
+ // Summary:
+ // The RIGHT ARROW key.
+ Right = 39,
+ //
+ // Summary:
+ // The DOWN ARROW key.
+ Down = 40,
+ //
+ // Summary:
+ // The SELECT key.
+ Select = 41,
+ //
+ // Summary:
+ // The PRINT key.
+ Print = 42,
+ //
+ // Summary:
+ // The EXECUTE key.
+ Execute = 43,
+ //
+ // Summary:
+ // The PRINT SCREEN key.
+ PrintScreen = 44,
+ //
+ // Summary:
+ // The PRINT SCREEN key.
+ Snapshot = 44,
+ //
+ // Summary:
+ // The INS key.
+ Insert = 45,
+ //
+ // Summary:
+ // The DEL key.
+ Delete = 46,
+ //
+ // Summary:
+ // The HELP key.
+ Help = 47,
+ //
+ // Summary:
+ // The 0 key.
+ D0 = 48,
+ //
+ // Summary:
+ // The 1 key.
+ D1 = 49,
+ //
+ // Summary:
+ // The 2 key.
+ D2 = 50,
+ //
+ // Summary:
+ // The 3 key.
+ D3 = 51,
+ //
+ // Summary:
+ // The 4 key.
+ D4 = 52,
+ //
+ // Summary:
+ // The 5 key.
+ D5 = 53,
+ //
+ // Summary:
+ // The 6 key.
+ D6 = 54,
+ //
+ // Summary:
+ // The 7 key.
+ D7 = 55,
+ //
+ // Summary:
+ // The 8 key.
+ D8 = 56,
+ //
+ // Summary:
+ // The 9 key.
+ D9 = 57,
+ //
+ // Summary:
+ // The A key.
+ A = 65,
+ //
+ // Summary:
+ // The B key.
+ B = 66,
+ //
+ // Summary:
+ // The C key.
+ C = 67,
+ //
+ // Summary:
+ // The D key.
+ D = 68,
+ //
+ // Summary:
+ // The E key.
+ E = 69,
+ //
+ // Summary:
+ // The F key.
+ F = 70,
+ //
+ // Summary:
+ // The G key.
+ G = 71,
+ //
+ // Summary:
+ // The H key.
+ H = 72,
+ //
+ // Summary:
+ // The I key.
+ I = 73,
+ //
+ // Summary:
+ // The J key.
+ J = 74,
+ //
+ // Summary:
+ // The K key.
+ K = 75,
+ //
+ // Summary:
+ // The L key.
+ L = 76,
+ //
+ // Summary:
+ // The M key.
+ M = 77,
+ //
+ // Summary:
+ // The N key.
+ N = 78,
+ //
+ // Summary:
+ // The O key.
+ O = 79,
+ //
+ // Summary:
+ // The P key.
+ P = 80,
+ //
+ // Summary:
+ // The Q key.
+ Q = 81,
+ //
+ // Summary:
+ // The R key.
+ R = 82,
+ //
+ // Summary:
+ // The S key.
+ S = 83,
+ //
+ // Summary:
+ // The T key.
+ T = 84,
+ //
+ // Summary:
+ // The U key.
+ U = 85,
+ //
+ // Summary:
+ // The V key.
+ V = 86,
+ //
+ // Summary:
+ // The W key.
+ W = 87,
+ //
+ // Summary:
+ // The X key.
+ X = 88,
+ //
+ // Summary:
+ // The Y key.
+ Y = 89,
+ //
+ // Summary:
+ // The Z key.
+ Z = 90,
+ //
+ // Summary:
+ // The left Windows logo key (Microsoft Natural Keyboard).
+ LWin = 91,
+ //
+ // Summary:
+ // The right Windows logo key (Microsoft Natural Keyboard).
+ RWin = 92,
+ //
+ // Summary:
+ // The application key (Microsoft Natural Keyboard).
+ Apps = 93,
+ //
+ // Summary:
+ // The computer sleep key.
+ Sleep = 95,
+ //
+ // Summary:
+ // The 0 key on the numeric keypad.
+ NumPad0 = 96,
+ //
+ // Summary:
+ // The 1 key on the numeric keypad.
+ NumPad1 = 97,
+ //
+ // Summary:
+ // The 2 key on the numeric keypad.
+ NumPad2 = 98,
+ //
+ // Summary:
+ // The 3 key on the numeric keypad.
+ NumPad3 = 99,
+ //
+ // Summary:
+ // The 4 key on the numeric keypad.
+ NumPad4 = 100,
+ //
+ // Summary:
+ // The 5 key on the numeric keypad.
+ NumPad5 = 101,
+ //
+ // Summary:
+ // The 6 key on the numeric keypad.
+ NumPad6 = 102,
+ //
+ // Summary:
+ // The 7 key on the numeric keypad.
+ NumPad7 = 103,
+ //
+ // Summary:
+ // The 8 key on the numeric keypad.
+ NumPad8 = 104,
+ //
+ // Summary:
+ // The 9 key on the numeric keypad.
+ NumPad9 = 105,
+ //
+ // Summary:
+ // The multiply key.
+ Multiply = 106,
+ //
+ // Summary:
+ // The add key.
+ Add = 107,
+ //
+ // Summary:
+ // The separator key.
+ Separator = 108,
+ //
+ // Summary:
+ // The subtract key.
+ Subtract = 109,
+ //
+ // Summary:
+ // The decimal key.
+ Decimal = 110,
+ //
+ // Summary:
+ // The divide key.
+ Divide = 111,
+ //
+ // Summary:
+ // The F1 key.
+ F1 = 112,
+ //
+ // Summary:
+ // The F2 key.
+ F2 = 113,
+ //
+ // Summary:
+ // The F3 key.
+ F3 = 114,
+ //
+ // Summary:
+ // The F4 key.
+ F4 = 115,
+ //
+ // Summary:
+ // The F5 key.
+ F5 = 116,
+ //
+ // Summary:
+ // The F6 key.
+ F6 = 117,
+ //
+ // Summary:
+ // The F7 key.
+ F7 = 118,
+ //
+ // Summary:
+ // The F8 key.
+ F8 = 119,
+ //
+ // Summary:
+ // The F9 key.
+ F9 = 120,
+ //
+ // Summary:
+ // The F10 key.
+ F10 = 121,
+ //
+ // Summary:
+ // The F11 key.
+ F11 = 122,
+ //
+ // Summary:
+ // The F12 key.
+ F12 = 123,
+ //
+ // Summary:
+ // The F13 key.
+ F13 = 124,
+ //
+ // Summary:
+ // The F14 key.
+ F14 = 125,
+ //
+ // Summary:
+ // The F15 key.
+ F15 = 126,
+ //
+ // Summary:
+ // The F16 key.
+ F16 = 127,
+ //
+ // Summary:
+ // The F17 key.
+ F17 = 128,
+ //
+ // Summary:
+ // The F18 key.
+ F18 = 129,
+ //
+ // Summary:
+ // The F19 key.
+ F19 = 130,
+ //
+ // Summary:
+ // The F20 key.
+ F20 = 131,
+ //
+ // Summary:
+ // The F21 key.
+ F21 = 132,
+ //
+ // Summary:
+ // The F22 key.
+ F22 = 133,
+ //
+ // Summary:
+ // The F23 key.
+ F23 = 134,
+ //
+ // Summary:
+ // The F24 key.
+ F24 = 135,
+ //
+ // Summary:
+ // The NUM LOCK key.
+ NumLock = 144,
+ //
+ // Summary:
+ // The SCROLL LOCK key.
+ Scroll = 145,
+ //
+ // Summary:
+ // The left SHIFT key.
+ LShiftKey = 160,
+ //
+ // Summary:
+ // The right SHIFT key.
+ RShiftKey = 161,
+ //
+ // Summary:
+ // The left CTRL key.
+ LControlKey = 162,
+ //
+ // Summary:
+ // The right CTRL key.
+ RControlKey = 163,
+ //
+ // Summary:
+ // The left ALT key.
+ LMenu = 164,
+ //
+ // Summary:
+ // The right ALT key.
+ RMenu = 165,
+ //
+ // Summary:
+ // The browser back key (Windows 2000 or later).
+ BrowserBack = 166,
+ //
+ // Summary:
+ // The browser forward key (Windows 2000 or later).
+ BrowserForward = 167,
+ //
+ // Summary:
+ // The browser refresh key (Windows 2000 or later).
+ BrowserRefresh = 168,
+ //
+ // Summary:
+ // The browser stop key (Windows 2000 or later).
+ BrowserStop = 169,
+ //
+ // Summary:
+ // The browser search key (Windows 2000 or later).
+ BrowserSearch = 170,
+ //
+ // Summary:
+ // The browser favorites key (Windows 2000 or later).
+ BrowserFavorites = 171,
+ //
+ // Summary:
+ // The browser home key (Windows 2000 or later).
+ BrowserHome = 172,
+ //
+ // Summary:
+ // The volume mute key (Windows 2000 or later).
+ VolumeMute = 173,
+ //
+ // Summary:
+ // The volume down key (Windows 2000 or later).
+ VolumeDown = 174,
+ //
+ // Summary:
+ // The volume up key (Windows 2000 or later).
+ VolumeUp = 175,
+ ///
+ /// The media next track key (Windows 2000 or later).
+ ///
+ MediaNextTrack = 176,
+ ///
+ /// The media previous track key (Windows 2000 or later).
+ ///
+ MediaPreviousTrack = 177,
+ ///
+ /// The media Stop key (Windows 2000 or later).
+ ///
+ MediaStop = 178,
+ ///
+ /// The media play pause key (Windows 2000 or later).
+ ///
+ MediaPlayPause = 179,
+ ///
+ /// The launch mail key (Windows 2000 or later).
+ ///
+ LaunchMail = 180,
+ ///
+ /// The select media key (Windows 2000 or later).
+ ///
+ SelectMedia = 181,
+ ///
+ /// The start application one key (Windows 2000 or later).
+ ///
+ LaunchApplication1 = 182,
+ ///
+ /// The start application two key (Windows 2000 or later).
+ ///
+ LaunchApplication2 = 183,
+ ///
+ /// The OEM 1 key.
+ ///
+ Oem1 = 186,
+ ///
+ /// The OEM Semicolon key on a US standard keyboard (Windows 2000 or later).
+ ///
+ OemSemicolon = 186,
+ ///
+ /// The OEM plus key on any country/region keyboard (Windows 2000 or later).
+ ///
+ Oemplus = 187,
+ ///
+ /// The OEM comma key on any country/region keyboard (Windows 2000 or later).
+ ///
+ Oemcomma = 188,
+ ///
+ /// The OEM minus key on any country/region keyboard (Windows 2000 or later).
+ ///
+ OemMinus = 189,
+ ///
+ /// The OEM period key on any country/region keyboard (Windows 2000 or later).
+ ///
+ OemPeriod = 190,
+ ///
+ /// The OEM question mark key on a US standard keyboard (Windows 2000 or later).
+ ///
+ OemQuestion = 191,
+ ///
+ /// The OEM 2 key.
+ ///
+ Oem2 = 191,
+ ///
+ /// The OEM tilde key on a US standard keyboard (Windows 2000 or later).
+ ///
+ Oemtilde = 192,
+ ///
+ /// The OEM 3 key.
+ ///
+ Oem3 = 192,
+ ///
+ /// The OEM 4 key.
+ ///
+ Oem4 = 219,
+ ///
+ /// The OEM open bracket key on a US standard keyboard (Windows 2000 or later).
+ ///
+ OemOpenBrackets = 219,
+ ///
+ /// The OEM pipe key on a US standard keyboard (Windows 2000 or later).
+ ///
+ OemPipe = 220,
+ ///
+ /// The OEM 5 key.
+ ///
+ Oem5 = 220,
+ ///
+ /// The OEM 6 key.
+ ///
+ Oem6 = 221,
+ ///
+ /// The OEM close bracket key on a US standard keyboard (Windows 2000 or later).
+ ///
+ OemCloseBrackets = 221,
+ ///
+ /// The OEM 7 key.
+ ///
+ Oem7 = 222,
+ ///
+ /// The OEM singled/double quote key on a US standard keyboard (Windows 2000
+ /// or later).
+ ///
+ OemQuotes = 222,
+ ///
+ /// The OEM 8 key.
+ ///
+ Oem8 = 223,
+ ///
+ /// The OEM 102 key.
+ ///
+ Oem102 = 226,
+ ///
+ /// The OEM angle bracket or backslash key on the RT 102 key keyboard (Windows
+ /// 2000 or later).
+ ///
+ OemBackslash = 226,
+ ///
+ /// The PROCESS KEY key.
+ ///
+ ProcessKey = 229,
+ ///
+ /// Used to pass Unicode characters as if they were keystrokes. The Packet key
+ /// value is the low word of a 32-bit virtual-key value used for non-keyboard
+ /// input methods.
+ ///
+ Packet = 231,
+ ///
+ /// The ATTN key.
+ ///
+ Attn = 246,
+ ///
+ /// The CRSEL key.
+ ///
+ Crsel = 247,
+ ///
+ /// The EXSEL key.
+ ///
+ Exsel = 248,
+ ///
+ /// The ERASE EOF key.
+ ///
+ EraseEof = 249,
+ ///
+ /// The PLAY key.
+ ///
+ Play = 250,
+ ///
+ /// The ZOOM key.
+ ///
+ Zoom = 251,
+ ///
+ /// A constant reserved for future use.
+ ///
+ NoName = 252,
+ ///
+ /// The PA1 key.
+ ///
+ Pa1 = 253,
+ ///
+ /// The CLEAR key.
+ ///
+ OemClear = 254,
+ ///
+ /// The bitmask to extract a key code from a key value.
+ ///
+ KeyCode = 65535,
+ ///
+ /// The SHIFT modifier key.
+ ///
+ Shift = 65536,
+ ///
+ /// The CTRL modifier key.
+ ///
+ Control = 131072,
+ ///
+ /// The ALT modifier key.
+ ///
+ Alt = 262144,
+ ///
+ /// The WINLOGO modifier key.
+ ///
+ WinLogo = 524288
+ }
+
+ public enum KeyState
+ {
+ ///
+ /// Indicates that the key is pressed down.
+ ///
+ Down,
+ ///
+ /// Indicates that the key has been released.
+ ///
+ Up
+ }
+
+ static class NativeMethods
+ {
+ internal delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ internal static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static extern bool UnhookWindowsHookEx(IntPtr hhk);
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ internal static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ internal static extern short GetKeyState(int nVirtKey);
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ internal static extern uint MapVirtualKey(uint uCode, uint uMapType);
+
+ internal static class KeyStateConstants
+ {
+ internal const int KEY_PRESSED = 0x8000;
+ internal const int WM_KEYDOWN = 0x0100;
+ internal const int WM_KEYUP = 0x0101;
+ internal const int WM_SYSKEYDOWN = 0x0104;
+ internal const int WM_SYSKEYUP = 0x0105;
+ internal const int WH_KEYBOARD_LL = 13;
+ }
+ }
+
+ public class KeyCombination : IEquatable
+ {
+ ///
+ /// The backing keys for this combination.
+ ///
+ KeysEx keyChain;
+
+ ///
+ /// Creates a new KeyCombination based on the provided archetype. The new combination is a deep copy
+ /// of the original.
+ ///
+ /// The combination to copy from.
+ /// A new KeyCombination object.
+ public static KeyCombination CopyFrom(KeyCombination combo)
+ {
+ return new KeyCombination(combo.Keys);
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The keys that constitute a keyboard combination.
+ public KeyCombination(Keys keys)
+ {
+ keyChain = keys.ToKeysEx();
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The keys that constitute a keyboard combination.
+ public KeyCombination(KeysEx keys)
+ {
+ keyChain = keys;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The keys that constitute a keyboard combination, express in the following
+ /// format: "Modifer + Modifier + Key".
+ public KeyCombination(string keys)
+ {
+ if (!string.IsNullOrEmpty(keys))
+ FromStringToKeys(keys);
+ }
+
+ ///
+ /// Returns true if the values of its operands are equal, otherwise false.
+ ///
+ public static bool operator ==(KeyCombination x, KeyCombination y)
+ {
+ if (ReferenceEquals(null, x))
+ return ReferenceEquals(null, y);
+
+ return x.Equals(y);
+ }
+
+ ///
+ /// returns false if its operands are equal, otherwise true.
+ ///
+ public static bool operator !=(KeyCombination x, KeyCombination y)
+ {
+ return !(x == y);
+ }
+
+ ///
+ /// Adds the specified keys to this combination. Note that a combination can only contain a single
+ /// non-modifier key. If one already exists, it will be overwritten.
+ ///
+ /// The keys to add.
+ public void Add(KeysEx keys)
+ {
+ KeysEx keyCode = keys & KeysEx.KeyCode;
+
+ if (keyCode != KeysEx.None)
+ keyChain = keyCode | keyChain & KeysEx.Modifiers;
+
+ KeysEx modifiers = keys & KeysEx.Modifiers;
+
+ if (modifiers != KeysEx.None)
+ keyChain = modifiers | keyChain & KeysEx.KeyCode | keyChain & KeysEx.Modifiers;
+ }
+
+ ///
+ /// Removes the specified key from this combination. Must be called once for each key to be removed.
+ ///
+ /// The key to remove.
+ public void Remove(KeysEx key)
+ {
+ if (Contains(key))
+ keyChain ^= key;
+
+ if (key == KeysEx.LWin || key == KeysEx.RWin)
+ {
+ if (Contains(KeysEx.WinLogo))
+ keyChain ^= KeysEx.WinLogo;
+ }
+ }
+
+ ///
+ /// Determines whether the specified key exists in this combination.
+ ///
+ /// The key.
+ /// True if the specified key exists; otherwise, false.
+ public bool Contains(KeysEx key)
+ {
+ switch (key)
+ {
+ case KeysEx.Control:
+ case KeysEx.Shift:
+ case KeysEx.Alt:
+ case KeysEx.WinLogo:
+ return (keyChain & KeysEx.Modifiers) == key;
+
+ default:
+ return (keyChain & KeysEx.KeyCode) == key;
+ }
+ }
+
+ ///
+ /// Gets the keys that constitute this combination.
+ ///
+ public KeysEx Keys
+ {
+ get { return keyChain; }
+ }
+
+ ///
+ /// Gets a value indicating whether this instance is empty.
+ ///
+ public bool IsEmpty
+ {
+ get { return Keys == KeysEx.None; }
+ }
+
+ ///
+ /// Gets the unmodified key for this combination.
+ ///
+ public KeysEx UnmodifiedKey
+ {
+ get { return keyChain & KeysEx.KeyCode; }
+ }
+
+ ///
+ /// Returns a that represents this instance.
+ ///
+ /// A that represents this instance.
+ public override string ToString()
+ {
+ return keyChain.ToFriendlyString();
+ }
+
+ ///
+ /// Gets a value indicating whether this combination is valid.
+ ///
+ /// A valid combination is one which can be used as a keyboard shortcut. Certain
+ /// keys such as Enter or CapsLock cannot be used for a shortcut. A combination also cannot
+ /// consist solely of modifier keys.
+ public bool IsValid
+ {
+ get
+ {
+ KeysEx keyCode = keyChain & KeysEx.KeyCode;
+ switch (keyCode)
+ {
+ case KeysEx.Enter:
+ case KeysEx.CapsLock:
+ case KeysEx.NumLock:
+ case KeysEx.Tab:
+ case KeysEx.None:
+ case KeysEx.ShiftKey:
+ case KeysEx.LShiftKey:
+ case KeysEx.RShiftKey:
+ case KeysEx.ControlKey:
+ case KeysEx.LControlKey:
+ case KeysEx.RControlKey:
+ case KeysEx.Menu:
+ case KeysEx.LMenu:
+ case KeysEx.RMenu:
+ case KeysEx.LWin:
+ case KeysEx.RWin:
+ return false;
+
+ case KeysEx.Delete:
+ if ((keyChain & KeysEx.Modifiers) == (KeysEx.Control | KeysEx.Alt))
+ return false;
+ break;
+ }
+
+ return true;
+ }
+ }
+
+ ///
+ /// Determines whether the specified is equal to this instance.
+ ///
+ /// The to compare with the current .
+ /// true if the specified is equal to this instance; otherwise, false.
+ public override bool Equals(object obj)
+ {
+ return Equals(obj as KeyCombination);
+ }
+
+ ///
+ /// Returns a hash code for this instance.
+ ///
+ /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ return 17 * 23 + ToString().GetHashCode();
+ }
+ }
+
+ ///
+ /// Indicates whether the current object is equal to another object of the same type.
+ ///
+ /// An object to compare with this object.
+ /// true if the current object is equal to the parameter; otherwise, false.
+ public bool Equals(KeyCombination other)
+ {
+ if (ReferenceEquals(null, other))
+ return false;
+
+ return ToString() == other.ToString();
+ }
+
+ ///
+ /// Froms the string to keys.
+ ///
+ /// The keys.
+ void FromStringToKeys(string keys)
+ {
+ IEnumerable segments = keys.Split(new[] { '+' });
+
+ foreach (string segment in segments)
+ {
+ string modifiedSegment = segment.ToLowerInvariant().Trim() == "ctrl" ? "Control" : segment;
+ keyChain |= EnumParser.Parse(modifiedSegment.Trim());
+ }
+ }
+ }
+
+ public static class EnumParser
+ {
+ ///
+ /// Converts the string representation of the name or numeric value of one or more enumerated constants to an equivalent enumerated object.
+ ///
+ /// The enum type.
+ /// A string containing the name or value to convert.
+ public static T Parse(string value) where T : struct
+ {
+ return (T)Enum.Parse(typeof(T), value);
+ }
+
+ ///
+ /// Converts the string representation of the name or numeric value of one or more enumerated constants to an equivalent enumerated object.
+ ///
+ /// The enum type.
+ /// A string containing the name or value to convert.
+ /// If true, ignore case; otherwise, regard case.
+ public static T Parse(string value, bool ignoreCase) where T : struct
+ {
+ return (T)Enum.Parse(typeof(T), value, ignoreCase);
+ }
+ }
+
+ public static class Extensions
+ {
+ ///
+ /// Converts the specified Keys to a KeysEx enumeration.
+ ///
+ /// The keys to convert.
+ public static KeysEx ToKeysEx(this Keys keys)
+ {
+ return EnumParser.Parse(keys.ToString());
+ }
+ }
+
+ public static class KeysExtensions
+ {
+ ///
+ /// Returns a friendly string representation of this KeysEx instance.
+ ///
+ /// The keys to convert to a friendly string.
+ public static string ToFriendlyString(this KeysEx keys)
+ {
+ var friendlyString = new StringBuilder();
+
+ if (IsWinLogoModified(keys))
+ friendlyString.Append("WinLogo + ");
+
+ if (IsControlModified(keys))
+ friendlyString.Append("Ctrl + ");
+
+ if (IsShiftModified(keys))
+ friendlyString.Append("Shift + ");
+
+ if (IsAltModified(keys))
+ friendlyString.Append("Alt + ");
+
+ string unmodifiedKey = UnmodifiedKey(keys);
+
+ if (string.IsNullOrEmpty(unmodifiedKey) && friendlyString.Length >= 3)
+ friendlyString.Remove(friendlyString.Length - 3, 3);
+ else
+ friendlyString.Append(unmodifiedKey);
+
+ return friendlyString.ToString();
+ }
+
+ ///
+ /// Returns KeyCode portion of this instance. That is, the key stripped of modifiers.
+ ///
+ /// The keys to remove modifier keys from.
+ static string UnmodifiedKey(KeysEx keys)
+ {
+ KeysEx keyCode = keys & KeysEx.KeyCode;
+
+ switch (keyCode)
+ {
+ case KeysEx.Menu:
+ case KeysEx.LMenu:
+ case KeysEx.RMenu:
+ case KeysEx.ShiftKey:
+ case KeysEx.LShiftKey:
+ case KeysEx.RShiftKey:
+ case KeysEx.ControlKey:
+ case KeysEx.LControlKey:
+ case KeysEx.RControlKey:
+ case KeysEx.LWin:
+ case KeysEx.RWin:
+ return string.Empty;
+ }
+
+ switch (keyCode)
+ {
+ case KeysEx.D0:
+ case KeysEx.D1:
+ case KeysEx.D2:
+ case KeysEx.D3:
+ case KeysEx.D4:
+ case KeysEx.D5:
+ case KeysEx.D6:
+ case KeysEx.D7:
+ case KeysEx.D8:
+ case KeysEx.D9:
+ return keyCode.ToString().Remove(0, 1);
+ }
+
+ if (keyCode.ToString().ToUpperInvariant().StartsWith("OEM"))
+ {
+ const uint convertToChar = 2;
+ uint keyLiteral = NativeMethods.MapVirtualKey((uint)keyCode, convertToChar);
+ return Convert.ToChar(keyLiteral).ToString(CultureInfo.InvariantCulture);
+ }
+
+ return keyCode.ToString();
+ }
+
+ ///
+ /// Determines whether the specified keys contains the WinLogo modifier, the LWin key, or the RWin key.
+ ///
+ /// The keys to check for logo key modifiers.
+ /// True if this instance contains a logo key modifier; otherwise, false.
+ static bool IsWinLogoModified(KeysEx keys)
+ {
+ if ((keys & KeysEx.WinLogo) == KeysEx.WinLogo)
+ return true;
+
+ KeysEx keyCode = keys & KeysEx.KeyCode;
+ switch (keyCode)
+ {
+ case KeysEx.LWin:
+ case KeysEx.RWin:
+ return true;
+ }
+
+ return false;
+ }
+
+ ///
+ /// Determines whether this enumeration contains the Alt modifier.
+ ///
+ /// The keys to check for the Alt modifier.
+ /// True if this enumeration contains the Alt modifier; otherwise false.
+ static bool IsAltModified(KeysEx keys)
+ {
+ if ((keys & KeysEx.Alt) == KeysEx.Alt)
+ return true;
+
+ KeysEx keyCode = keys & KeysEx.KeyCode;
+ switch (keyCode)
+ {
+ case KeysEx.Menu:
+ case KeysEx.LMenu:
+ case KeysEx.RMenu:
+ return true;
+ }
+
+ return false;
+ }
+
+ ///
+ /// Determines whether this enumeration contains the Shift modifier.
+ ///
+ /// The keys to check for the Shift modifier.
+ /// True if this enumeration contains the Shift modifier; otherwise false.
+ static bool IsShiftModified(KeysEx keys)
+ {
+ if ((keys & KeysEx.Shift) == KeysEx.Shift)
+ return true;
+
+ KeysEx keyCode = keys & KeysEx.KeyCode;
+ switch (keyCode)
+ {
+ case KeysEx.ShiftKey:
+ case KeysEx.LShiftKey:
+ case KeysEx.RShiftKey:
+ return true;
+ }
+
+ return false;
+ }
+
+ ///
+ /// Determines whether this enumeration contains the Control modifier.
+ ///
+ /// The keys to check for the Control modifier.
+ /// True if this enumeration contains the Control modifier; otherwise false.
+ static bool IsControlModified(KeysEx keys)
+ {
+ if ((keys & KeysEx.Control) == KeysEx.Control)
+ return true;
+
+ KeysEx keyCode = keys & KeysEx.KeyCode;
+ switch (keyCode)
+ {
+ case KeysEx.ControlKey:
+ case KeysEx.LControlKey:
+ case KeysEx.RControlKey:
+ return true;
+ }
+
+ return false;
+ }
+ }
+
+ public class KeyboardHook : IDisposable
+ {
+ const int keyUp = NativeMethods.KeyStateConstants.WM_KEYUP;
+ const int systemKeyUp = NativeMethods.KeyStateConstants.WM_SYSKEYUP;
+ const int keyDown = NativeMethods.KeyStateConstants.WM_KEYDOWN;
+ const int systemKeyDown = NativeMethods.KeyStateConstants.WM_SYSKEYDOWN;
+
+ static readonly HashSet currentHookKeys = new HashSet();
+ static readonly NativeMethods.LowLevelKeyboardProc lockdownHookCallBack = LockdownHookCallBack;
+ static bool isKeyboardLockedDown;
+ static IntPtr lockdownHookId;
+ static KeysEx lockedDownKeys;
+
+ IntPtr hookId;
+ bool isDisposed;
+ bool keyReleased;
+ readonly NativeMethods.LowLevelKeyboardProc hookCallback;
+
+ ///
+ /// Occurs when a key is pressed while keyboard lockdown is engaged.
+ ///
+ public static event EventHandler LockedDownKeyboardKeyPressed = delegate { };
+
+ ///
+ /// Engages a full keyboard lockdown, which disables all keyboard processing beyond the LockedDownKeyboardKeyPressed event.
+ ///
+ public static void EngageFullKeyboardLockdown()
+ {
+ lockdownHookId = NativeMethods.SetWindowsHookEx(
+ NativeMethods.KeyStateConstants.WH_KEYBOARD_LL,
+ lockdownHookCallBack,
+ IntPtr.Zero,
+ 0);
+
+ if (lockdownHookId == IntPtr.Zero)
+ throw new Win32Exception(Marshal.GetLastWin32Error());
+
+ isKeyboardLockedDown = true;
+ }
+
+ ///
+ /// Releases keyboard lockdown and allows keyboard processing as normal.
+ ///
+ public static void ReleaseFullKeyboardLockdown()
+ {
+ if (lockdownHookId != IntPtr.Zero)
+ {
+ NativeMethods.UnhookWindowsHookEx(lockdownHookId);
+ lockdownHookId = IntPtr.Zero;
+ }
+
+ isKeyboardLockedDown = false;
+ }
+
+ ///
+ /// Determines whether the specified key combination is already in use.
+ ///
+ /// The combination to check.
+ /// True if the key combination is already in use; otherwise, false.
+ public static bool IsKeyCombinationTaken(KeyCombination combination)
+ {
+ return currentHookKeys.Contains(combination);
+ }
+
+ ///
+ /// Raises the KeyboardLockDownKeyPressed event by invoking each subscribed delegate asynchronously.
+ ///
+ /// The keys that are pressed.
+ /// The state of the keys.
+ static void OnLockedDownKeyboardKeyPressed(KeysEx pressedKeys, KeyState state)
+ {
+ foreach (EventHandler pressedEvent in LockedDownKeyboardKeyPressed.GetInvocationList())
+ {
+ var args = new KeyboardLockDownKeyPressedEventArgs(pressedKeys, state);
+ AsyncCallback callback = ar => ((EventHandler)ar.AsyncState).EndInvoke(ar);
+ pressedEvent.BeginInvoke(null, args, callback, pressedEvent);
+ }
+ }
+
+ ///
+ /// Returns a value indicating whether a non-modifier key is currently pressed.
+ ///
+ /// The key to check. Key must not be a modifier bit mask.
+ /// True if the key is currently pressed; otherwise false.
+ /// Occurs if key is a modifier bit mask.
+ static bool IsKeyPressed(KeysEx key)
+ {
+ if ((key & KeysEx.Modifiers) == KeysEx.Modifiers)
+ {
+ throw new ArgumentException("Key cannot contain any modifiers.", "key");
+ }
+
+ const int keyPressed = NativeMethods.KeyStateConstants.KEY_PRESSED;
+ return (NativeMethods.GetKeyState((int)key) & keyPressed) == keyPressed;
+ }
+
+ ///
+ /// Callback handler for keyboard lockdowns.
+ ///
+ static IntPtr LockdownHookCallBack(int nCode, IntPtr wParam, IntPtr lParam)
+ {
+ int keyStateParam = (int)wParam;
+ KeysEx pressedKey = (KeysEx)Marshal.ReadInt32(lParam);
+
+ switch (pressedKey)
+ {
+ case KeysEx.LControlKey:
+ case KeysEx.RControlKey:
+ pressedKey = KeysEx.Control;
+ break;
+
+ case KeysEx.RMenu:
+ case KeysEx.LMenu:
+ pressedKey = KeysEx.Alt;
+ break;
+
+ case KeysEx.LShiftKey:
+ case KeysEx.RShiftKey:
+ pressedKey = KeysEx.Shift;
+ break;
+
+ case KeysEx.LWin:
+ case KeysEx.RWin:
+ pressedKey = KeysEx.WinLogo;
+ break;
+ }
+
+ KeyState keyState;
+ if (keyStateParam == keyUp || keyStateParam == systemKeyUp)
+ {
+ keyState = KeyState.Up;
+ lockedDownKeys ^= pressedKey;
+ }
+ else if (keyStateParam == keyDown || keyStateParam == systemKeyDown)
+ {
+ keyState = KeyState.Down;
+ lockedDownKeys |= pressedKey;
+ }
+ else
+ {
+ throw new ArgumentOutOfRangeException("wParam", "Invalid key state detected.");
+ }
+
+ OnLockedDownKeyboardKeyPressed(lockedDownKeys, keyState);
+ return new IntPtr(1);
+ }
+
+ ///
+ /// Initializes a new instance of the KeyboardHook class.
+ ///
+ public KeyboardHook()
+ {
+ hookCallback = HookCallBack;
+ Combination = new KeyCombination(KeysEx.None);
+ }
+
+ ///
+ /// Finalizes an instance of the KeyboardHook class.
+ ///
+ ~KeyboardHook()
+ {
+ Dispose(false);
+ }
+
+ ///
+ /// Occurs when the KeyboardHook's assigned key combination is pressed.
+ ///
+ public event EventHandler Pressed = delegate { };
+
+ ///
+ /// Gets the key combination for this hook.
+ ///
+ public KeyCombination Combination { get; private set; }
+
+ ///
+ /// Gets or sets a value indicating whether to allow normal processing of key strokes after
+ /// the hook has finished processing it.
+ ///
+ public bool AllowPassThrough { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether the KeyboardHook Pressed event is fired repeatedly for the duration
+ /// of the key press or only once per key press.
+ ///
+ public bool AutoRepeat { get; set; }
+
+ ///
+ /// Gets a value indicating whether the KeyboardHook is currently active.
+ ///
+ public bool IsEngaged
+ {
+ get { return hookId != IntPtr.Zero; }
+ }
+
+ ///
+ /// Removes the keys associated with this hook. This can only be performed when the hook is not active.
+ ///
+ /// Occurs if the hook is currently engaged.
+ public void RemoveKeys() //----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------Was only public void before
+ {
+ if (Combination.Keys == KeysEx.None)
+ return;
+
+ if (IsEngaged)
+ throw new InvalidOperationException("Cannot remove keys while hook is engaged.");
+
+ if (Combination != null && currentHookKeys.Contains(Combination))
+ currentHookKeys.Remove(Combination);
+
+ Combination = new KeyCombination(KeysEx.None);
+ }
+
+ ///
+ /// Associates the specified key combination with this hook. This can only be performed when the hook is not active.
+ ///
+ /// The key combination.
+ /// Occurs if this hook is currently engaged -OR- if the key combination is invalid
+ /// -OR- if the key combination is already in use by another hook.
+ public void SetKeys(KeyCombination combination)
+ {
+ if (Combination == combination)
+ return;
+
+ if (IsEngaged)
+ throw new InvalidOperationException("Cannot set keys while hook is engaged.");
+
+ if (!combination.IsValid)
+ throw new InvalidOperationException("Key combination is not valid.");
+
+ if (currentHookKeys.Contains(combination))
+ throw new InvalidOperationException(string.Format("The combination '{0}' is already in use.", combination));
+
+ if (Combination != null && currentHookKeys.Contains(Combination))
+ currentHookKeys.Remove(Combination);
+
+ currentHookKeys.Add(combination);
+ Combination = combination;
+ }
+
+ ///
+ /// Activates the KeyboardHook.
+ ///
+ /// Occurs if the KeyboardHook is empty OR if the KeyboardHook is already engaged.
+ /// Occurs if the KeyboardHook has been disposed.
+ [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
+ public void Engage()
+ {
+ if (isDisposed)
+ throw new ObjectDisposedException("KeyboardHook");
+
+ if (Combination == null)
+ throw new InvalidOperationException("Cannot engage hook when Combination is null.");
+
+ if (IsEngaged)
+ return;
+
+ hookId = NativeMethods.SetWindowsHookEx(
+ NativeMethods.KeyStateConstants.WH_KEYBOARD_LL,
+ hookCallback,
+ IntPtr.Zero,
+ 0);
+
+ if (hookId == IntPtr.Zero)
+ throw new Win32Exception(Marshal.GetLastWin32Error());
+ }
+
+ ///
+ /// Removes the KeyboardHook from the system.
+ ///
+ /// Disengage removes the hook from the system, but maintains all its data. Use Engage to re-install the hook. To
+ /// discard the hook and all its data, use Dispose. It is not necessary to call Disengage prior to Dispose.
+ public void Disengage()
+ {
+ if (hookId != IntPtr.Zero)
+ {
+ NativeMethods.UnhookWindowsHookEx(hookId);
+ hookId = IntPtr.Zero;
+ }
+ }
+
+ ///
+ /// Returns the string representation of the KeyboardHook.
+ ///
+ /// A string representing the KeyboardHook.
+ public override string ToString()
+ {
+ return Combination == null ? string.Empty : Combination.ToString();
+ }
+
+ ///
+ /// Disengages the KeyboardHook and releases all associated resources.
+ ///
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Disengages the KeyboardHook, releases all unmanaged resources, and optionally releases
+ /// all managed resources.
+ ///
+ /// True to release both managed and unmanaged resources; false to
+ /// release only unmanaged resources.
+ protected virtual void Dispose(bool isDisposing)
+ {
+ if (isDisposed)
+ return;
+
+ if (isDisposing)
+ {
+ // No managed resources to dispose.
+ }
+
+ Disengage();
+
+ if (Combination != null)
+ currentHookKeys.Remove(Combination);
+
+ isDisposed = true;
+ }
+
+ ///
+ /// Raises the Pressed event.
+ ///
+ /// The Pressed event is executed asynchronously.
+ protected virtual void OnPressed()
+ {
+ // Invoke these asychronously in case they're slow. (Testing revealed that Windows will reassert
+ // responsibility for the key stroke(s) if the hookcallback doesn't immediately return.)
+ foreach (EventHandler pressedEvent in Pressed.GetInvocationList())
+ pressedEvent.BeginInvoke(this, EventArgs.Empty, ar => ((EventHandler)ar.AsyncState).EndInvoke(ar), pressedEvent);
+ }
+
+ ///
+ /// Determines whether the specified key, combined with all currently pressed modifier keys, matches this hook's key combination.
+ ///
+ /// The unmodified key to combine with all currently pressed keyboard modifier keys.
+ /// True if unmodifiedKey matches Combination.UnmodifiedKey and all modifier keys contained in the
+ /// Combination property are currently pressed; otherwise, false.
+ protected bool CheckIsHookKeyCombination(KeysEx unmodifiedKey)
+ {
+ KeyCombination pressedKeyCombo = new KeyCombination(unmodifiedKey);
+
+ if (IsKeyPressed(KeysEx.ControlKey))
+ pressedKeyCombo.Add(KeysEx.Control);
+
+ if (IsKeyPressed(KeysEx.ShiftKey))
+ pressedKeyCombo.Add(KeysEx.Shift);
+
+ if (IsKeyPressed(KeysEx.LMenu) || IsKeyPressed(KeysEx.RMenu))
+ pressedKeyCombo.Add(KeysEx.Alt);
+
+ if ((IsKeyPressed(KeysEx.LWin) || IsKeyPressed(KeysEx.RWin)))
+ pressedKeyCombo.Add(KeysEx.WinLogo);
+
+ return Combination == pressedKeyCombo;
+ }
+
+ ///
+ /// The callback proceedure for the installed KeyboardHook.
+ ///
+ /// A code the KeyboardHook procedure uses to determine how to process the message.
+ /// The key state.
+ /// The key pressed.
+ /// A value indicating whether or not to process additional hooks in the current hook chain.
+ IntPtr HookCallBack(int nCode, IntPtr wParam, IntPtr lParam)
+ {
+ if (isKeyboardLockedDown)
+ return new IntPtr(1); // A non-zero return value blocks additional processing of key strokes.
+
+ // MSDN documentation indicates that nCodes less than 0 should always only invoke CallNextHookEx.
+ if (nCode < 0)
+ return NativeMethods.CallNextHookEx(hookId, nCode, wParam, lParam);
+
+ int keyStateParam = (int)wParam;
+ KeyState keyState;
+
+ if (keyStateParam == keyUp || keyStateParam == systemKeyUp)
+ keyState = KeyState.Up;
+ else if (keyStateParam == keyDown || keyStateParam == systemKeyDown)
+ keyState = KeyState.Down;
+ else
+ throw new ArgumentOutOfRangeException("wParam", "Invalid key state detected.");
+
+ var pressedKey = (KeysEx)Marshal.ReadInt32(lParam);
+
+ if (!CheckIsHookKeyCombination(pressedKey))
+ return NativeMethods.CallNextHookEx(hookId, nCode, wParam, lParam);
+
+ if (keyState == KeyState.Up)
+ {
+ keyReleased = true;
+ return NativeMethods.CallNextHookEx(hookId, nCode, wParam, lParam);
+ }
+
+ // If AutoRepeat is on, always process hook; otherwise, only process hook if they key has been released and re-pressed.
+ if (AutoRepeat || keyReleased)
+ {
+ keyReleased = false;
+ OnPressed();
+ }
+
+ if (AllowPassThrough)
+ return NativeMethods.CallNextHookEx(hookId, nCode, wParam, lParam);
+
+ return new IntPtr(1);
+ }
+ }
+
+ public class KeyboardLockDownKeyPressedEventArgs : EventArgs
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The keys that were pressed.
+ /// The state of the pressed keys.
+ ///
+ public KeyboardLockDownKeyPressedEventArgs(KeysEx keys, KeyState state)
+ {
+ Keys = keys;
+ State = state;
+ }
+
+ ///
+ /// Gets the keys that were pressed.
+ ///
+ public KeysEx Keys { get; private set; }
+
+ ///
+ /// Gets the state of the pressed keys.
+ ///
+ public KeyState State { get; private set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Program.cs b/src/Program.cs
new file mode 100755
index 0000000..03c795f
--- /dev/null
+++ b/src/Program.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace TeamViewerController
+{
+ static class Program
+ {
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ Application.EnableVisualStyles();
+ Application.SetCompatibleTextRenderingDefault(false);
+ Application.Run(new Form1());
+ }
+ }
+}
diff --git a/src/Properties/AssemblyInfo.cs b/src/Properties/AssemblyInfo.cs
new file mode 100755
index 0000000..e0136b0
--- /dev/null
+++ b/src/Properties/AssemblyInfo.cs
@@ -0,0 +1,38 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+//[assembly: AssemblyTitle("TeamViewerController")] //OLD ONE
+[assembly: AssemblyTitle("Jarlson Multiplayer")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+//[assembly: AssemblyProduct("TeamViewerController")] // OLD ONE
+[assembly: AssemblyProduct("Jarlson Multiplayer")]
+[assembly: AssemblyCopyright("Copyright © 2020")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("6a0d27e7-625d-452c-9f4f-941cd87b9bb3")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/src/Properties/Resources.Designer.cs b/src/Properties/Resources.Designer.cs
new file mode 100755
index 0000000..67074ec
--- /dev/null
+++ b/src/Properties/Resources.Designer.cs
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace TeamViewerController.Properties {
+ using System;
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("TeamViewerController.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/src/Properties/Resources.resx b/src/Properties/Resources.resx
new file mode 100755
index 0000000..ffecec8
--- /dev/null
+++ b/src/Properties/Resources.resx
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/src/Properties/Settings.Designer.cs b/src/Properties/Settings.Designer.cs
new file mode 100755
index 0000000..f7c06a1
--- /dev/null
+++ b/src/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace TeamViewerController.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.3.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default {
+ get {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/src/Properties/Settings.settings b/src/Properties/Settings.settings
new file mode 100755
index 0000000..abf36c5
--- /dev/null
+++ b/src/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/src/TeamViewerController.csproj b/src/TeamViewerController.csproj
new file mode 100755
index 0000000..64d93a7
--- /dev/null
+++ b/src/TeamViewerController.csproj
@@ -0,0 +1,125 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {6A0D27E7-625D-452C-9F4F-941CD87B9BB3}
+ WinExe
+ TeamViewerController
+ Jarlson Multiplayer
+ v4.7.2
+ 512
+ true
+ true
+ publish\
+ true
+ Disk
+ false
+ Foreground
+ 7
+ Days
+ false
+ false
+ true
+ 0
+ 1.0.0.%2a
+ false
+ false
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ packages\Open.NAT.2.1.0.0\lib\net45\Open.Nat.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Form
+
+
+ Form1.cs
+
+
+ Form
+
+
+ Form2.cs
+
+
+
+
+
+ Form1.cs
+
+
+ Form2.cs
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+ Designer
+
+
+ True
+ Resources.resx
+ True
+
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+ True
+ Settings.settings
+ True
+
+
+
+
+
+
+
+ False
+ Microsoft .NET Framework 4.7.2 %28x86 and x64%29
+ true
+
+
+ False
+ .NET Framework 3.5 SP1
+ false
+
+
+
+
\ No newline at end of file
diff --git a/src/TeamViewerController.sln b/src/TeamViewerController.sln
new file mode 100755
index 0000000..7f5a0ea
--- /dev/null
+++ b/src/TeamViewerController.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.29519.87
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TeamViewerController", "TeamViewerController.csproj", "{6A0D27E7-625D-452C-9F4F-941CD87B9BB3}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {6A0D27E7-625D-452C-9F4F-941CD87B9BB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6A0D27E7-625D-452C-9F4F-941CD87B9BB3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6A0D27E7-625D-452C-9F4F-941CD87B9BB3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6A0D27E7-625D-452C-9F4F-941CD87B9BB3}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {62DF8BC2-3224-46C0-BDB2-916511CE469D}
+ EndGlobalSection
+EndGlobal
diff --git a/src/packages.config b/src/packages.config
new file mode 100755
index 0000000..9185792
--- /dev/null
+++ b/src/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file